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