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 12namespace v8 { 13namespace 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 30class 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 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 53 int smi_at(int index) { 54 return Smi::cast((*this)[index])->value(); 55 } 56 57 double number_at(int index) { 58 return (*this)[index]->Number(); 59 } 60 61 // Get the total number of arguments including the receiver. 62 int length() const { return static_cast<int>(length_); } 63 64 Object** arguments() { return arguments_; } 65 66 Object** lowest_address() { return &this->operator[](length() - 1); } 67 68 Object** highest_address() { return &this->operator[](0); } 69 70 private: 71 intptr_t length_; 72 Object** arguments_; 73}; 74 75double 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