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.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 44 template <class S = Object> at(int index)45 Handle<S> at(int index) { 46 Object** value = &((*this)[index]); 47 // This cast checks that the object we're accessing does indeed have the 48 // expected type. 49 S::cast(*value); 50 return Handle<S>(reinterpret_cast<S**>(value)); 51 } 52 smi_at(int index)53 int smi_at(int index) { 54 return Smi::cast((*this)[index])->value(); 55 } 56 number_at(int index)57 double number_at(int index) { 58 return (*this)[index]->Number(); 59 } 60 61 // Get the total number of arguments including the receiver. length()62 int length() const { return static_cast<int>(length_); } 63 arguments()64 Object** arguments() { return arguments_; } 65 lowest_address()66 Object** lowest_address() { return &this->operator[](length() - 1); } 67 highest_address()68 Object** highest_address() { return &this->operator[](0); } 69 70 private: 71 intptr_t length_; 72 Object** arguments_; 73 }; 74 75 double ClobberDoubleRegisters(double x1, double x2, double x3, double x4); 76 77 #ifdef DEBUG 78 #define CLOBBER_DOUBLE_REGISTERS() ClobberDoubleRegisters(1, 2, 3, 4); 79 #else 80 #define CLOBBER_DOUBLE_REGISTERS() 81 #endif 82 83 // TODO(cbruni): add global flag to check whether any tracing events have been 84 // enabled. 85 #define RUNTIME_FUNCTION_RETURNS_TYPE(Type, Name) \ 86 static INLINE(Type __RT_impl_##Name(Arguments args, Isolate* isolate)); \ 87 \ 88 V8_NOINLINE static Type Stats_##Name(int args_length, Object** args_object, \ 89 Isolate* isolate) { \ 90 RuntimeCallTimerScope timer(isolate, &RuntimeCallStats::Name); \ 91 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.runtime"), \ 92 "V8.Runtime_" #Name); \ 93 Arguments args(args_length, args_object); \ 94 return __RT_impl_##Name(args, isolate); \ 95 } \ 96 \ 97 Type Name(int args_length, Object** args_object, Isolate* isolate) { \ 98 DCHECK(isolate->context() == nullptr || isolate->context()->IsContext()); \ 99 CLOBBER_DOUBLE_REGISTERS(); \ 100 if (V8_UNLIKELY(FLAG_runtime_stats)) { \ 101 return Stats_##Name(args_length, args_object, isolate); \ 102 } \ 103 Arguments args(args_length, args_object); \ 104 return __RT_impl_##Name(args, isolate); \ 105 } \ 106 \ 107 static Type __RT_impl_##Name(Arguments args, Isolate* isolate) 108 109 #define RUNTIME_FUNCTION(Name) RUNTIME_FUNCTION_RETURNS_TYPE(Object*, Name) 110 #define RUNTIME_FUNCTION_RETURN_PAIR(Name) \ 111 RUNTIME_FUNCTION_RETURNS_TYPE(ObjectPair, Name) 112 #define RUNTIME_FUNCTION_RETURN_TRIPLE(Name) \ 113 RUNTIME_FUNCTION_RETURNS_TYPE(ObjectTriple, Name) 114 115 } // namespace internal 116 } // namespace v8 117 118 #endif // V8_ARGUMENTS_H_ 119