1 // Copyright 2012 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_ARGUMENTS_H_ 6 #define V8_ARGUMENTS_H_ 7 8 #include "src/allocation.h" 9 #include "src/objects-inl.h" 10 #include "src/tracing/trace-event.h" 11 12 namespace v8 { 13 namespace internal { 14 15 // Arguments provides access to runtime call parameters. 16 // 17 // It uses the fact that the instance fields of Arguments 18 // (length_, arguments_) are "overlayed" with the parameters 19 // (no. of parameters, and the parameter pointer) passed so 20 // that inside the C++ function, the parameters passed can 21 // be accessed conveniently: 22 // 23 // Object* Runtime_function(Arguments args) { 24 // ... use args[i] here ... 25 // } 26 // 27 // Note that length_ (whose value is in the integer range) is defined 28 // as intptr_t to provide endian-neutrality on 64-bit archs. 29 30 class Arguments BASE_EMBEDDED { 31 public: 32 Arguments(int length, Object** arguments) 33 : length_(length), arguments_(arguments) { 34 DCHECK_GE(length_, 0); 35 } 36 37 Object*& operator[] (int index) { 38 DCHECK_GE(index, 0); 39 DCHECK_LT(static_cast<uint32_t>(index), static_cast<uint32_t>(length_)); 40 return *(reinterpret_cast<Object**>(reinterpret_cast<intptr_t>(arguments_) - 41 index * kPointerSize)); 42 } 43 44 template <class S> Handle<S> at(int index) { 45 Object** value = &((*this)[index]); 46 // This cast checks that the object we're accessing does indeed have the 47 // expected type. 48 S::cast(*value); 49 return Handle<S>(reinterpret_cast<S**>(value)); 50 } 51 52 int smi_at(int index) { 53 return Smi::cast((*this)[index])->value(); 54 } 55 56 double number_at(int index) { 57 return (*this)[index]->Number(); 58 } 59 60 // Get the total number of arguments including the receiver. 61 int length() const { return static_cast<int>(length_); } 62 63 Object** arguments() { return arguments_; } 64 65 Object** lowest_address() { return &this->operator[](length() - 1); } 66 67 Object** highest_address() { return &this->operator[](0); } 68 69 private: 70 intptr_t length_; 71 Object** arguments_; 72 }; 73 74 double ClobberDoubleRegisters(double x1, double x2, double x3, double x4); 75 76 #ifdef DEBUG 77 #define CLOBBER_DOUBLE_REGISTERS() ClobberDoubleRegisters(1, 2, 3, 4); 78 #else 79 #define CLOBBER_DOUBLE_REGISTERS() 80 #endif 81 82 // TODO(cbruni): add global flag to check whether any tracing events have been 83 // enabled. 84 #define RUNTIME_FUNCTION_RETURNS_TYPE(Type, Name) \ 85 static INLINE(Type __RT_impl_##Name(Arguments args, Isolate* isolate)); \ 86 \ 87 V8_NOINLINE static Type Stats_##Name(int args_length, Object** args_object, \ 88 Isolate* isolate) { \ 89 RuntimeCallTimerScope timer(isolate, &RuntimeCallStats::Name); \ 90 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.runtime"), \ 91 "V8.Runtime_" #Name); \ 92 Arguments args(args_length, args_object); \ 93 return __RT_impl_##Name(args, isolate); \ 94 } \ 95 \ 96 Type Name(int args_length, Object** args_object, Isolate* isolate) { \ 97 DCHECK(isolate->context() == nullptr || isolate->context()->IsContext()); \ 98 CLOBBER_DOUBLE_REGISTERS(); \ 99 if (V8_UNLIKELY(FLAG_runtime_stats)) { \ 100 return Stats_##Name(args_length, args_object, isolate); \ 101 } \ 102 Arguments args(args_length, args_object); \ 103 return __RT_impl_##Name(args, isolate); \ 104 } \ 105 \ 106 static Type __RT_impl_##Name(Arguments args, Isolate* isolate) 107 108 #define RUNTIME_FUNCTION(Name) RUNTIME_FUNCTION_RETURNS_TYPE(Object*, Name) 109 #define RUNTIME_FUNCTION_RETURN_PAIR(Name) \ 110 RUNTIME_FUNCTION_RETURNS_TYPE(ObjectPair, Name) 111 #define RUNTIME_FUNCTION_RETURN_TRIPLE(Name) \ 112 RUNTIME_FUNCTION_RETURNS_TYPE(ObjectTriple, Name) 113 114 } // namespace internal 115 } // namespace v8 116 117 #endif // V8_ARGUMENTS_H_ 118