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: Arguments(int length,Object ** arguments)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 at(int index)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 smi_at(int index)52 int smi_at(int index) { 53 return Smi::cast((*this)[index])->value(); 54 } 55 number_at(int index)56 double number_at(int index) { 57 return (*this)[index]->Number(); 58 } 59 60 // Get the total number of arguments including the receiver. length()61 int length() const { return static_cast<int>(length_); } 62 arguments()63 Object** arguments() { return arguments_; } 64 lowest_address()65 Object** lowest_address() { return &this->operator[](length() - 1); } 66 highest_address()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 CLOBBER_DOUBLE_REGISTERS(); \ 98 if (FLAG_runtime_call_stats) { \ 99 return Stats_##Name(args_length, args_object, isolate); \ 100 } \ 101 Arguments args(args_length, args_object); \ 102 return __RT_impl_##Name(args, isolate); \ 103 } \ 104 \ 105 static Type __RT_impl_##Name(Arguments args, Isolate* isolate) 106 107 #define RUNTIME_FUNCTION(Name) RUNTIME_FUNCTION_RETURNS_TYPE(Object*, Name) 108 #define RUNTIME_FUNCTION_RETURN_PAIR(Name) \ 109 RUNTIME_FUNCTION_RETURNS_TYPE(ObjectPair, Name) 110 #define RUNTIME_FUNCTION_RETURN_TRIPLE(Name) \ 111 RUNTIME_FUNCTION_RETURNS_TYPE(ObjectTriple, Name) 112 113 } // namespace internal 114 } // namespace v8 115 116 #endif // V8_ARGUMENTS_H_ 117