| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef V8_ARGUMENTS_H_ | 5 #ifndef V8_API_ARGUMENTS_H_ |
| 6 #define V8_ARGUMENTS_H_ | 6 #define V8_API_ARGUMENTS_H_ |
| 7 | 7 |
| 8 #include "src/allocation.h" | |
| 9 #include "src/isolate.h" | 8 #include "src/isolate.h" |
| 10 #include "src/tracing/trace-event.h" | 9 #include "src/tracing/trace-event.h" |
| 11 | 10 |
| 12 namespace v8 { | 11 namespace v8 { |
| 13 namespace internal { | 12 namespace internal { |
| 14 | 13 |
| 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> 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 | |
| 52 int smi_at(int index) { | |
| 53 return Smi::cast((*this)[index])->value(); | |
| 54 } | |
| 55 | |
| 56 double number_at(int index) { | |
| 57 return (*this)[index]->Number(); | |
| 58 } | |
| 59 | |
| 60 // Get the total number of arguments including the receiver. | |
| 61 int length() const { return static_cast<int>(length_); } | |
| 62 | |
| 63 Object** arguments() { return arguments_; } | |
| 64 | |
| 65 Object** lowest_address() { return &this->operator[](length() - 1); } | |
| 66 | |
| 67 Object** highest_address() { return &this->operator[](0); } | |
| 68 | |
| 69 private: | |
| 70 intptr_t length_; | |
| 71 Object** arguments_; | |
| 72 }; | |
| 73 | |
| 74 | |
| 75 // For each type of callback, we have a list of arguments | 14 // For each type of callback, we have a list of arguments |
| 76 // They are used to generate the Call() functions below | 15 // They are used to generate the Call() functions below |
| 77 // These aren't included in the list as they have duplicate signatures | 16 // These aren't included in the list as they have duplicate signatures |
| 78 // F(GenericNamedPropertyEnumeratorCallback, ...) | 17 // F(GenericNamedPropertyEnumeratorCallback, ...) |
| 79 // F(GenericNamedPropertyGetterCallback, ...) | 18 // F(GenericNamedPropertyGetterCallback, ...) |
| 80 | 19 |
| 81 #define FOR_EACH_CALLBACK_TABLE_MAPPING_0(F) \ | 20 #define FOR_EACH_CALLBACK_TABLE_MAPPING_0(F) \ |
| 82 F(IndexedPropertyEnumeratorCallback, v8::Array) | 21 F(IndexedPropertyEnumeratorCallback, v8::Array) |
| 83 | 22 |
| 84 #define FOR_EACH_CALLBACK_TABLE_MAPPING_1(F) \ | 23 #define FOR_EACH_CALLBACK_TABLE_MAPPING_1(F) \ |
| 85 F(AccessorNameGetterCallback, v8::Value, v8::Local<v8::Name>) \ | 24 F(AccessorNameGetterCallback, v8::Value, v8::Local<v8::Name>) \ |
| 86 F(GenericNamedPropertyQueryCallback, v8::Integer, v8::Local<v8::Name>) \ | 25 F(GenericNamedPropertyQueryCallback, v8::Integer, v8::Local<v8::Name>) \ |
| 87 F(GenericNamedPropertyDeleterCallback, v8::Boolean, v8::Local<v8::Name>) \ | 26 F(GenericNamedPropertyDeleterCallback, v8::Boolean, v8::Local<v8::Name>) \ |
| 88 F(IndexedPropertyGetterCallback, v8::Value, uint32_t) \ | 27 F(IndexedPropertyGetterCallback, v8::Value, uint32_t) \ |
| 89 F(IndexedPropertyQueryCallback, v8::Integer, uint32_t) \ | 28 F(IndexedPropertyQueryCallback, v8::Integer, uint32_t) \ |
| 90 F(IndexedPropertyDeleterCallback, v8::Boolean, uint32_t) | 29 F(IndexedPropertyDeleterCallback, v8::Boolean, uint32_t) |
| 91 | 30 |
| 92 #define FOR_EACH_CALLBACK_TABLE_MAPPING_2(F) \ | 31 #define FOR_EACH_CALLBACK_TABLE_MAPPING_2(F) \ |
| 93 F(GenericNamedPropertySetterCallback, v8::Value, v8::Local<v8::Name>, \ | 32 F(GenericNamedPropertySetterCallback, v8::Value, v8::Local<v8::Name>, \ |
| 94 v8::Local<v8::Value>) \ | 33 v8::Local<v8::Value>) \ |
| 95 F(IndexedPropertySetterCallback, v8::Value, uint32_t, v8::Local<v8::Value>) | 34 F(IndexedPropertySetterCallback, v8::Value, uint32_t, v8::Local<v8::Value>) |
| 96 | 35 |
| 97 #define FOR_EACH_CALLBACK_TABLE_MAPPING_2_VOID_RETURN(F) \ | 36 #define FOR_EACH_CALLBACK_TABLE_MAPPING_2_VOID_RETURN(F) \ |
| 98 F(AccessorNameSetterCallback, \ | 37 F(AccessorNameSetterCallback, void, v8::Local<v8::Name>, v8::Local<v8::Value>) |
| 99 void, \ | |
| 100 v8::Local<v8::Name>, \ | |
| 101 v8::Local<v8::Value>) \ | |
| 102 | |
| 103 | 38 |
| 104 // Custom arguments replicate a small segment of stack that can be | 39 // Custom arguments replicate a small segment of stack that can be |
| 105 // accessed through an Arguments object the same way the actual stack | 40 // accessed through an Arguments object the same way the actual stack |
| 106 // can. | 41 // can. |
| 107 template<int kArrayLength> | 42 template <int kArrayLength> |
| 108 class CustomArgumentsBase : public Relocatable { | 43 class CustomArgumentsBase : public Relocatable { |
| 109 public: | 44 public: |
| 110 virtual inline void IterateInstance(ObjectVisitor* v) { | 45 virtual inline void IterateInstance(ObjectVisitor* v) { |
| 111 v->VisitPointers(values_, values_ + kArrayLength); | 46 v->VisitPointers(values_, values_ + kArrayLength); |
| 112 } | 47 } |
| 48 |
| 113 protected: | 49 protected: |
| 114 inline Object** begin() { return values_; } | 50 inline Object** begin() { return values_; } |
| 115 explicit inline CustomArgumentsBase(Isolate* isolate) | 51 explicit inline CustomArgumentsBase(Isolate* isolate) |
| 116 : Relocatable(isolate) {} | 52 : Relocatable(isolate) {} |
| 117 Object* values_[kArrayLength]; | 53 Object* values_[kArrayLength]; |
| 118 }; | 54 }; |
| 119 | 55 |
| 120 | 56 template <typename T> |
| 121 template<typename T> | |
| 122 class CustomArguments : public CustomArgumentsBase<T::kArgsLength> { | 57 class CustomArguments : public CustomArgumentsBase<T::kArgsLength> { |
| 123 public: | 58 public: |
| 124 static const int kReturnValueOffset = T::kReturnValueIndex; | 59 static const int kReturnValueOffset = T::kReturnValueIndex; |
| 125 | 60 |
| 126 typedef CustomArgumentsBase<T::kArgsLength> Super; | 61 typedef CustomArgumentsBase<T::kArgsLength> Super; |
| 127 ~CustomArguments() { | 62 ~CustomArguments() { |
| 128 this->begin()[kReturnValueOffset] = | 63 this->begin()[kReturnValueOffset] = |
| 129 reinterpret_cast<Object*>(kHandleZapValue); | 64 reinterpret_cast<Object*>(kHandleZapValue); |
| 130 } | 65 } |
| 131 | 66 |
| 132 protected: | 67 protected: |
| 133 explicit inline CustomArguments(Isolate* isolate) : Super(isolate) {} | 68 explicit inline CustomArguments(Isolate* isolate) : Super(isolate) {} |
| 134 | 69 |
| 135 template <typename V> | 70 template <typename V> |
| 136 v8::Local<V> GetReturnValue(Isolate* isolate); | 71 v8::Local<V> GetReturnValue(Isolate* isolate); |
| 137 | 72 |
| 138 inline Isolate* isolate() { | 73 inline Isolate* isolate() { |
| 139 return reinterpret_cast<Isolate*>(this->begin()[T::kIsolateIndex]); | 74 return reinterpret_cast<Isolate*>(this->begin()[T::kIsolateIndex]); |
| 140 } | 75 } |
| 141 }; | 76 }; |
| 142 | 77 |
| 143 | |
| 144 class PropertyCallbackArguments | 78 class PropertyCallbackArguments |
| 145 : public CustomArguments<PropertyCallbackInfo<Value> > { | 79 : public CustomArguments<PropertyCallbackInfo<Value> > { |
| 146 public: | 80 public: |
| 147 typedef PropertyCallbackInfo<Value> T; | 81 typedef PropertyCallbackInfo<Value> T; |
| 148 typedef CustomArguments<T> Super; | 82 typedef CustomArguments<T> Super; |
| 149 static const int kArgsLength = T::kArgsLength; | 83 static const int kArgsLength = T::kArgsLength; |
| 150 static const int kThisIndex = T::kThisIndex; | 84 static const int kThisIndex = T::kThisIndex; |
| 151 static const int kHolderIndex = T::kHolderIndex; | 85 static const int kHolderIndex = T::kHolderIndex; |
| 152 static const int kDataIndex = T::kDataIndex; | 86 static const int kDataIndex = T::kDataIndex; |
| 153 static const int kReturnValueDefaultValueIndex = | 87 static const int kReturnValueDefaultValueIndex = |
| (...skipping 14 matching lines...) Expand all Loading... |
| 168 | 102 |
| 169 // Here the hole is set as default value. | 103 // Here the hole is set as default value. |
| 170 // It cannot escape into js as it's remove in Call below. | 104 // It cannot escape into js as it's remove in Call below. |
| 171 values[T::kReturnValueDefaultValueIndex] = | 105 values[T::kReturnValueDefaultValueIndex] = |
| 172 isolate->heap()->the_hole_value(); | 106 isolate->heap()->the_hole_value(); |
| 173 values[T::kReturnValueIndex] = isolate->heap()->the_hole_value(); | 107 values[T::kReturnValueIndex] = isolate->heap()->the_hole_value(); |
| 174 DCHECK(values[T::kHolderIndex]->IsHeapObject()); | 108 DCHECK(values[T::kHolderIndex]->IsHeapObject()); |
| 175 DCHECK(values[T::kIsolateIndex]->IsSmi()); | 109 DCHECK(values[T::kIsolateIndex]->IsSmi()); |
| 176 } | 110 } |
| 177 | 111 |
| 178 /* | 112 /* |
| 179 * The following Call functions wrap the calling of all callbacks to handle | 113 * The following Call functions wrap the calling of all callbacks to handle |
| 180 * calling either the old or the new style callbacks depending on which one | 114 * calling either the old or the new style callbacks depending on which one |
| 181 * has been registered. | 115 * has been registered. |
| 182 * For old callbacks which return an empty handle, the ReturnValue is checked | 116 * For old callbacks which return an empty handle, the ReturnValue is checked |
| 183 * and used if it's been set to anything inside the callback. | 117 * and used if it's been set to anything inside the callback. |
| 184 * New style callbacks always use the return value. | 118 * New style callbacks always use the return value. |
| 185 */ | 119 */ |
| 186 #define WRITE_CALL_0(Function, ReturnValue) \ | 120 #define WRITE_CALL_0(Function, ReturnValue) \ |
| 187 v8::Local<ReturnValue> Call(Function f); | 121 v8::Local<ReturnValue> Call(Function f); |
| 188 | 122 |
| 189 #define WRITE_CALL_1(Function, ReturnValue, Arg1) \ | 123 #define WRITE_CALL_1(Function, ReturnValue, Arg1) \ |
| 190 v8::Local<ReturnValue> Call(Function f, Arg1 arg1); | 124 v8::Local<ReturnValue> Call(Function f, Arg1 arg1); |
| 191 | 125 |
| 192 #define WRITE_CALL_2(Function, ReturnValue, Arg1, Arg2) \ | 126 #define WRITE_CALL_2(Function, ReturnValue, Arg1, Arg2) \ |
| 193 v8::Local<ReturnValue> Call(Function f, Arg1 arg1, Arg2 arg2); | 127 v8::Local<ReturnValue> Call(Function f, Arg1 arg1, Arg2 arg2); |
| 194 | 128 |
| 195 #define WRITE_CALL_2_VOID(Function, ReturnValue, Arg1, Arg2) \ | 129 #define WRITE_CALL_2_VOID(Function, ReturnValue, Arg1, Arg2) \ |
| 196 void Call(Function f, Arg1 arg1, Arg2 arg2); \ | 130 void Call(Function f, Arg1 arg1, Arg2 arg2); |
| 197 | 131 |
| 198 FOR_EACH_CALLBACK_TABLE_MAPPING_0(WRITE_CALL_0) | 132 FOR_EACH_CALLBACK_TABLE_MAPPING_0(WRITE_CALL_0) |
| 199 FOR_EACH_CALLBACK_TABLE_MAPPING_1(WRITE_CALL_1) | 133 FOR_EACH_CALLBACK_TABLE_MAPPING_1(WRITE_CALL_1) |
| 200 FOR_EACH_CALLBACK_TABLE_MAPPING_2(WRITE_CALL_2) | 134 FOR_EACH_CALLBACK_TABLE_MAPPING_2(WRITE_CALL_2) |
| 201 FOR_EACH_CALLBACK_TABLE_MAPPING_2_VOID_RETURN(WRITE_CALL_2_VOID) | 135 FOR_EACH_CALLBACK_TABLE_MAPPING_2_VOID_RETURN(WRITE_CALL_2_VOID) |
| 202 | 136 |
| 203 #undef WRITE_CALL_0 | 137 #undef WRITE_CALL_0 |
| 204 #undef WRITE_CALL_1 | 138 #undef WRITE_CALL_1 |
| 205 #undef WRITE_CALL_2 | 139 #undef WRITE_CALL_2 |
| 206 #undef WRITE_CALL_2_VOID | 140 #undef WRITE_CALL_2_VOID |
| 207 }; | 141 }; |
| 208 | 142 |
| 209 | |
| 210 class FunctionCallbackArguments | 143 class FunctionCallbackArguments |
| 211 : public CustomArguments<FunctionCallbackInfo<Value> > { | 144 : public CustomArguments<FunctionCallbackInfo<Value> > { |
| 212 public: | 145 public: |
| 213 typedef FunctionCallbackInfo<Value> T; | 146 typedef FunctionCallbackInfo<Value> T; |
| 214 typedef CustomArguments<T> Super; | 147 typedef CustomArguments<T> Super; |
| 215 static const int kArgsLength = T::kArgsLength; | 148 static const int kArgsLength = T::kArgsLength; |
| 216 static const int kHolderIndex = T::kHolderIndex; | 149 static const int kHolderIndex = T::kHolderIndex; |
| 217 static const int kDataIndex = T::kDataIndex; | 150 static const int kDataIndex = T::kDataIndex; |
| 218 static const int kReturnValueDefaultValueIndex = | 151 static const int kReturnValueDefaultValueIndex = |
| 219 T::kReturnValueDefaultValueIndex; | 152 T::kReturnValueDefaultValueIndex; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 255 * New style callbacks always use the return value. | 188 * New style callbacks always use the return value. |
| 256 */ | 189 */ |
| 257 v8::Local<v8::Value> Call(FunctionCallback f); | 190 v8::Local<v8::Value> Call(FunctionCallback f); |
| 258 | 191 |
| 259 private: | 192 private: |
| 260 internal::Object** argv_; | 193 internal::Object** argv_; |
| 261 int argc_; | 194 int argc_; |
| 262 bool is_construct_call_; | 195 bool is_construct_call_; |
| 263 }; | 196 }; |
| 264 | 197 |
| 265 | |
| 266 double ClobberDoubleRegisters(double x1, double x2, double x3, double x4); | |
| 267 | |
| 268 | |
| 269 #ifdef DEBUG | |
| 270 #define CLOBBER_DOUBLE_REGISTERS() ClobberDoubleRegisters(1, 2, 3, 4); | |
| 271 #else | |
| 272 #define CLOBBER_DOUBLE_REGISTERS() | |
| 273 #endif | |
| 274 | |
| 275 #define RUNTIME_FUNCTION_RETURNS_TYPE(Type, Name) \ | |
| 276 static INLINE(Type __RT_impl_##Name(Arguments args, Isolate* isolate)); \ | |
| 277 Type Name(int args_length, Object** args_object, Isolate* isolate) { \ | |
| 278 CLOBBER_DOUBLE_REGISTERS(); \ | |
| 279 Arguments args(args_length, args_object); \ | |
| 280 Type value; \ | |
| 281 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.runtime"), "V8." #Name); \ | |
| 282 if (FLAG_runtime_call_stats) { \ | |
| 283 RuntimeCallStats* stats = isolate->counters()->runtime_call_stats(); \ | |
| 284 RuntimeCallTimerScope timer(isolate, &stats->Name); \ | |
| 285 value = __RT_impl_##Name(args, isolate); \ | |
| 286 } else { \ | |
| 287 value = __RT_impl_##Name(args, isolate); \ | |
| 288 } \ | |
| 289 return value; \ | |
| 290 } \ | |
| 291 static Type __RT_impl_##Name(Arguments args, Isolate* isolate) | |
| 292 | |
| 293 #define RUNTIME_FUNCTION(Name) RUNTIME_FUNCTION_RETURNS_TYPE(Object*, Name) | |
| 294 #define RUNTIME_FUNCTION_RETURN_PAIR(Name) \ | |
| 295 RUNTIME_FUNCTION_RETURNS_TYPE(ObjectPair, Name) | |
| 296 #define RUNTIME_FUNCTION_RETURN_TRIPLE(Name) \ | |
| 297 RUNTIME_FUNCTION_RETURNS_TYPE(ObjectTriple, Name) | |
| 298 | |
| 299 } // namespace internal | 198 } // namespace internal |
| 300 } // namespace v8 | 199 } // namespace v8 |
| 301 | 200 |
| 302 #endif // V8_ARGUMENTS_H_ | 201 #endif // V8_API_ARGUMENTS_H_ |
| OLD | NEW |