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/isolate.h" 10 11namespace v8 { 12namespace internal { 13 14// Arguments provides access to runtime call parameters. 15// 16// It uses the fact that the instance fields of Arguments 17// (length_, arguments_) are "overlayed" with the parameters 18// (no. of parameters, and the parameter pointer) passed so 19// that inside the C++ function, the parameters passed can 20// be accessed conveniently: 21// 22// Object* Runtime_function(Arguments args) { 23// ... use args[i] here ... 24// } 25// 26// Note that length_ (whose value is in the integer range) is defined 27// as intptr_t to provide endian-neutrality on 64-bit archs. 28 29class Arguments BASE_EMBEDDED { 30 public: 31 Arguments(int length, Object** arguments) 32 : length_(length), arguments_(arguments) { } 33 34 Object*& operator[] (int index) { 35 DCHECK(0 <= index && index < length_); 36 return *(reinterpret_cast<Object**>(reinterpret_cast<intptr_t>(arguments_) - 37 index * kPointerSize)); 38 } 39 40 template <class S> Handle<S> at(int index) { 41 Object** value = &((*this)[index]); 42 // This cast checks that the object we're accessing does indeed have the 43 // expected type. 44 S::cast(*value); 45 return Handle<S>(reinterpret_cast<S**>(value)); 46 } 47 48 int smi_at(int index) { 49 return Smi::cast((*this)[index])->value(); 50 } 51 52 double number_at(int index) { 53 return (*this)[index]->Number(); 54 } 55 56 // Get the total number of arguments including the receiver. 57 int length() const { return static_cast<int>(length_); } 58 59 Object** arguments() { return arguments_; } 60 61 private: 62 intptr_t length_; 63 Object** arguments_; 64}; 65 66 67// For each type of callback, we have a list of arguments 68// They are used to generate the Call() functions below 69// These aren't included in the list as they have duplicate signatures 70// F(NamedPropertyEnumeratorCallback, ...) 71 72#define FOR_EACH_CALLBACK_TABLE_MAPPING_0(F) \ 73 F(IndexedPropertyEnumeratorCallback, v8::Array) \ 74 75#define FOR_EACH_CALLBACK_TABLE_MAPPING_1(F) \ 76 F(NamedPropertyGetterCallback, v8::Value, v8::Local<v8::String>) \ 77 F(AccessorNameGetterCallback, v8::Value, v8::Local<v8::Name>) \ 78 F(NamedPropertyQueryCallback, \ 79 v8::Integer, \ 80 v8::Local<v8::String>) \ 81 F(NamedPropertyDeleterCallback, \ 82 v8::Boolean, \ 83 v8::Local<v8::String>) \ 84 F(IndexedPropertyGetterCallback, \ 85 v8::Value, \ 86 uint32_t) \ 87 F(IndexedPropertyQueryCallback, \ 88 v8::Integer, \ 89 uint32_t) \ 90 F(IndexedPropertyDeleterCallback, \ 91 v8::Boolean, \ 92 uint32_t) \ 93 94#define FOR_EACH_CALLBACK_TABLE_MAPPING_2(F) \ 95 F(NamedPropertySetterCallback, \ 96 v8::Value, \ 97 v8::Local<v8::String>, \ 98 v8::Local<v8::Value>) \ 99 F(IndexedPropertySetterCallback, \ 100 v8::Value, \ 101 uint32_t, \ 102 v8::Local<v8::Value>) \ 103 104#define FOR_EACH_CALLBACK_TABLE_MAPPING_2_VOID_RETURN(F) \ 105 F(AccessorNameSetterCallback, \ 106 void, \ 107 v8::Local<v8::Name>, \ 108 v8::Local<v8::Value>) \ 109 110 111// Custom arguments replicate a small segment of stack that can be 112// accessed through an Arguments object the same way the actual stack 113// can. 114template<int kArrayLength> 115class CustomArgumentsBase : public Relocatable { 116 public: 117 virtual inline void IterateInstance(ObjectVisitor* v) { 118 v->VisitPointers(values_, values_ + kArrayLength); 119 } 120 protected: 121 inline Object** begin() { return values_; } 122 explicit inline CustomArgumentsBase(Isolate* isolate) 123 : Relocatable(isolate) {} 124 Object* values_[kArrayLength]; 125}; 126 127 128template<typename T> 129class CustomArguments : public CustomArgumentsBase<T::kArgsLength> { 130 public: 131 static const int kReturnValueOffset = T::kReturnValueIndex; 132 133 typedef CustomArgumentsBase<T::kArgsLength> Super; 134 ~CustomArguments() { 135 this->begin()[kReturnValueOffset] = 136 reinterpret_cast<Object*>(kHandleZapValue); 137 } 138 139 protected: 140 explicit inline CustomArguments(Isolate* isolate) : Super(isolate) {} 141 142 template<typename V> 143 v8::Handle<V> GetReturnValue(Isolate* isolate); 144 145 inline Isolate* isolate() { 146 return reinterpret_cast<Isolate*>(this->begin()[T::kIsolateIndex]); 147 } 148}; 149 150 151class PropertyCallbackArguments 152 : public CustomArguments<PropertyCallbackInfo<Value> > { 153 public: 154 typedef PropertyCallbackInfo<Value> T; 155 typedef CustomArguments<T> Super; 156 static const int kArgsLength = T::kArgsLength; 157 static const int kThisIndex = T::kThisIndex; 158 static const int kHolderIndex = T::kHolderIndex; 159 static const int kDataIndex = T::kDataIndex; 160 static const int kReturnValueDefaultValueIndex = 161 T::kReturnValueDefaultValueIndex; 162 static const int kIsolateIndex = T::kIsolateIndex; 163 164 PropertyCallbackArguments(Isolate* isolate, 165 Object* data, 166 Object* self, 167 JSObject* holder) 168 : Super(isolate) { 169 Object** values = this->begin(); 170 values[T::kThisIndex] = self; 171 values[T::kHolderIndex] = holder; 172 values[T::kDataIndex] = data; 173 values[T::kIsolateIndex] = reinterpret_cast<Object*>(isolate); 174 // Here the hole is set as default value. 175 // It cannot escape into js as it's remove in Call below. 176 values[T::kReturnValueDefaultValueIndex] = 177 isolate->heap()->the_hole_value(); 178 values[T::kReturnValueIndex] = isolate->heap()->the_hole_value(); 179 DCHECK(values[T::kHolderIndex]->IsHeapObject()); 180 DCHECK(values[T::kIsolateIndex]->IsSmi()); 181 } 182 183 /* 184 * The following Call functions wrap the calling of all callbacks to handle 185 * calling either the old or the new style callbacks depending on which one 186 * has been registered. 187 * For old callbacks which return an empty handle, the ReturnValue is checked 188 * and used if it's been set to anything inside the callback. 189 * New style callbacks always use the return value. 190 */ 191#define WRITE_CALL_0(Function, ReturnValue) \ 192 v8::Handle<ReturnValue> Call(Function f); \ 193 194#define WRITE_CALL_1(Function, ReturnValue, Arg1) \ 195 v8::Handle<ReturnValue> Call(Function f, Arg1 arg1); \ 196 197#define WRITE_CALL_2(Function, ReturnValue, Arg1, Arg2) \ 198 v8::Handle<ReturnValue> Call(Function f, Arg1 arg1, Arg2 arg2); \ 199 200#define WRITE_CALL_2_VOID(Function, ReturnValue, Arg1, Arg2) \ 201 void Call(Function f, Arg1 arg1, Arg2 arg2); \ 202 203FOR_EACH_CALLBACK_TABLE_MAPPING_0(WRITE_CALL_0) 204FOR_EACH_CALLBACK_TABLE_MAPPING_1(WRITE_CALL_1) 205FOR_EACH_CALLBACK_TABLE_MAPPING_2(WRITE_CALL_2) 206FOR_EACH_CALLBACK_TABLE_MAPPING_2_VOID_RETURN(WRITE_CALL_2_VOID) 207 208#undef WRITE_CALL_0 209#undef WRITE_CALL_1 210#undef WRITE_CALL_2 211#undef WRITE_CALL_2_VOID 212}; 213 214 215class FunctionCallbackArguments 216 : public CustomArguments<FunctionCallbackInfo<Value> > { 217 public: 218 typedef FunctionCallbackInfo<Value> T; 219 typedef CustomArguments<T> Super; 220 static const int kArgsLength = T::kArgsLength; 221 static const int kHolderIndex = T::kHolderIndex; 222 static const int kDataIndex = T::kDataIndex; 223 static const int kReturnValueDefaultValueIndex = 224 T::kReturnValueDefaultValueIndex; 225 static const int kIsolateIndex = T::kIsolateIndex; 226 static const int kCalleeIndex = T::kCalleeIndex; 227 static const int kContextSaveIndex = T::kContextSaveIndex; 228 229 FunctionCallbackArguments(internal::Isolate* isolate, 230 internal::Object* data, 231 internal::JSFunction* callee, 232 internal::Object* holder, 233 internal::Object** argv, 234 int argc, 235 bool is_construct_call) 236 : Super(isolate), 237 argv_(argv), 238 argc_(argc), 239 is_construct_call_(is_construct_call) { 240 Object** values = begin(); 241 values[T::kDataIndex] = data; 242 values[T::kCalleeIndex] = callee; 243 values[T::kHolderIndex] = holder; 244 values[T::kContextSaveIndex] = isolate->heap()->the_hole_value(); 245 values[T::kIsolateIndex] = reinterpret_cast<internal::Object*>(isolate); 246 // Here the hole is set as default value. 247 // It cannot escape into js as it's remove in Call below. 248 values[T::kReturnValueDefaultValueIndex] = 249 isolate->heap()->the_hole_value(); 250 values[T::kReturnValueIndex] = isolate->heap()->the_hole_value(); 251 DCHECK(values[T::kCalleeIndex]->IsJSFunction()); 252 DCHECK(values[T::kHolderIndex]->IsHeapObject()); 253 DCHECK(values[T::kIsolateIndex]->IsSmi()); 254 } 255 256 /* 257 * The following Call function wraps the calling of all callbacks to handle 258 * calling either the old or the new style callbacks depending on which one 259 * has been registered. 260 * For old callbacks which return an empty handle, the ReturnValue is checked 261 * and used if it's been set to anything inside the callback. 262 * New style callbacks always use the return value. 263 */ 264 v8::Handle<v8::Value> Call(FunctionCallback f); 265 266 private: 267 internal::Object** argv_; 268 int argc_; 269 bool is_construct_call_; 270}; 271 272 273double ClobberDoubleRegisters(double x1, double x2, double x3, double x4); 274 275 276#ifdef DEBUG 277#define CLOBBER_DOUBLE_REGISTERS() ClobberDoubleRegisters(1, 2, 3, 4); 278#else 279#define CLOBBER_DOUBLE_REGISTERS() 280#endif 281 282 283#define DECLARE_RUNTIME_FUNCTION(Name) \ 284Object* Name(int args_length, Object** args_object, Isolate* isolate) 285 286#define RUNTIME_FUNCTION_RETURNS_TYPE(Type, Name) \ 287static INLINE(Type __RT_impl_##Name(Arguments args, Isolate* isolate)); \ 288Type Name(int args_length, Object** args_object, Isolate* isolate) { \ 289 CLOBBER_DOUBLE_REGISTERS(); \ 290 Arguments args(args_length, args_object); \ 291 return __RT_impl_##Name(args, isolate); \ 292} \ 293static Type __RT_impl_##Name(Arguments args, Isolate* isolate) 294 295 296#define RUNTIME_FUNCTION(Name) RUNTIME_FUNCTION_RETURNS_TYPE(Object*, Name) 297#define RUNTIME_FUNCTION_RETURN_PAIR(Name) \ 298 RUNTIME_FUNCTION_RETURNS_TYPE(ObjectPair, Name) 299 300#define RUNTIME_ARGUMENTS(isolate, args) \ 301 args.length(), args.arguments(), isolate 302 303} } // namespace v8::internal 304 305#endif // V8_ARGUMENTS_H_ 306