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 |