OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 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 | 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_ARGUMENTS_H_ |
6 #define V8_ARGUMENTS_H_ | 6 #define V8_ARGUMENTS_H_ |
7 | 7 |
8 #include "src/allocation.h" | 8 #include "src/allocation.h" |
9 #include "src/isolate.h" | 9 #include "src/objects-inl.h" |
10 #include "src/tracing/trace-event.h" | 10 #include "src/tracing/trace-event.h" |
11 | 11 |
12 namespace v8 { | 12 namespace v8 { |
13 namespace internal { | 13 namespace internal { |
14 | 14 |
15 // Arguments provides access to runtime call parameters. | 15 // Arguments provides access to runtime call parameters. |
16 // | 16 // |
17 // It uses the fact that the instance fields of Arguments | 17 // It uses the fact that the instance fields of Arguments |
18 // (length_, arguments_) are "overlayed" with the parameters | 18 // (length_, arguments_) are "overlayed" with the parameters |
19 // (no. of parameters, and the parameter pointer) passed so | 19 // (no. of parameters, and the parameter pointer) passed so |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
64 | 64 |
65 Object** lowest_address() { return &this->operator[](length() - 1); } | 65 Object** lowest_address() { return &this->operator[](length() - 1); } |
66 | 66 |
67 Object** highest_address() { return &this->operator[](0); } | 67 Object** highest_address() { return &this->operator[](0); } |
68 | 68 |
69 private: | 69 private: |
70 intptr_t length_; | 70 intptr_t length_; |
71 Object** arguments_; | 71 Object** arguments_; |
72 }; | 72 }; |
73 | 73 |
74 | |
75 // For each type of callback, we have a list of arguments | |
76 // They are used to generate the Call() functions below | |
77 // These aren't included in the list as they have duplicate signatures | |
78 // F(GenericNamedPropertyEnumeratorCallback, ...) | |
79 // F(GenericNamedPropertyGetterCallback, ...) | |
80 | |
81 #define FOR_EACH_CALLBACK_TABLE_MAPPING_0(F) \ | |
82 F(IndexedPropertyEnumeratorCallback, v8::Array) | |
83 | |
84 #define FOR_EACH_CALLBACK_TABLE_MAPPING_1(F) \ | |
85 F(AccessorNameGetterCallback, v8::Value, v8::Local<v8::Name>) \ | |
86 F(GenericNamedPropertyQueryCallback, v8::Integer, v8::Local<v8::Name>) \ | |
87 F(GenericNamedPropertyDeleterCallback, v8::Boolean, v8::Local<v8::Name>) \ | |
88 F(IndexedPropertyGetterCallback, v8::Value, uint32_t) \ | |
89 F(IndexedPropertyQueryCallback, v8::Integer, uint32_t) \ | |
90 F(IndexedPropertyDeleterCallback, v8::Boolean, uint32_t) | |
91 | |
92 #define FOR_EACH_CALLBACK_TABLE_MAPPING_2(F) \ | |
93 F(GenericNamedPropertySetterCallback, v8::Value, v8::Local<v8::Name>, \ | |
94 v8::Local<v8::Value>) \ | |
95 F(IndexedPropertySetterCallback, v8::Value, uint32_t, v8::Local<v8::Value>) | |
96 | |
97 #define FOR_EACH_CALLBACK_TABLE_MAPPING_2_VOID_RETURN(F) \ | |
98 F(AccessorNameSetterCallback, \ | |
99 void, \ | |
100 v8::Local<v8::Name>, \ | |
101 v8::Local<v8::Value>) \ | |
102 | |
103 | |
104 // Custom arguments replicate a small segment of stack that can be | |
105 // accessed through an Arguments object the same way the actual stack | |
106 // can. | |
107 template<int kArrayLength> | |
108 class CustomArgumentsBase : public Relocatable { | |
109 public: | |
110 virtual inline void IterateInstance(ObjectVisitor* v) { | |
111 v->VisitPointers(values_, values_ + kArrayLength); | |
112 } | |
113 protected: | |
114 inline Object** begin() { return values_; } | |
115 explicit inline CustomArgumentsBase(Isolate* isolate) | |
116 : Relocatable(isolate) {} | |
117 Object* values_[kArrayLength]; | |
118 }; | |
119 | |
120 | |
121 template<typename T> | |
122 class CustomArguments : public CustomArgumentsBase<T::kArgsLength> { | |
123 public: | |
124 static const int kReturnValueOffset = T::kReturnValueIndex; | |
125 | |
126 typedef CustomArgumentsBase<T::kArgsLength> Super; | |
127 ~CustomArguments() { | |
128 this->begin()[kReturnValueOffset] = | |
129 reinterpret_cast<Object*>(kHandleZapValue); | |
130 } | |
131 | |
132 protected: | |
133 explicit inline CustomArguments(Isolate* isolate) : Super(isolate) {} | |
134 | |
135 template <typename V> | |
136 v8::Local<V> GetReturnValue(Isolate* isolate); | |
137 | |
138 inline Isolate* isolate() { | |
139 return reinterpret_cast<Isolate*>(this->begin()[T::kIsolateIndex]); | |
140 } | |
141 }; | |
142 | |
143 | |
144 class PropertyCallbackArguments | |
145 : public CustomArguments<PropertyCallbackInfo<Value> > { | |
146 public: | |
147 typedef PropertyCallbackInfo<Value> T; | |
148 typedef CustomArguments<T> Super; | |
149 static const int kArgsLength = T::kArgsLength; | |
150 static const int kThisIndex = T::kThisIndex; | |
151 static const int kHolderIndex = T::kHolderIndex; | |
152 static const int kDataIndex = T::kDataIndex; | |
153 static const int kReturnValueDefaultValueIndex = | |
154 T::kReturnValueDefaultValueIndex; | |
155 static const int kIsolateIndex = T::kIsolateIndex; | |
156 static const int kShouldThrowOnErrorIndex = T::kShouldThrowOnErrorIndex; | |
157 | |
158 PropertyCallbackArguments(Isolate* isolate, Object* data, Object* self, | |
159 JSObject* holder, Object::ShouldThrow should_throw) | |
160 : Super(isolate) { | |
161 Object** values = this->begin(); | |
162 values[T::kThisIndex] = self; | |
163 values[T::kHolderIndex] = holder; | |
164 values[T::kDataIndex] = data; | |
165 values[T::kIsolateIndex] = reinterpret_cast<Object*>(isolate); | |
166 values[T::kShouldThrowOnErrorIndex] = | |
167 Smi::FromInt(should_throw == Object::THROW_ON_ERROR ? 1 : 0); | |
168 | |
169 // Here the hole is set as default value. | |
170 // It cannot escape into js as it's remove in Call below. | |
171 values[T::kReturnValueDefaultValueIndex] = | |
172 isolate->heap()->the_hole_value(); | |
173 values[T::kReturnValueIndex] = isolate->heap()->the_hole_value(); | |
174 DCHECK(values[T::kHolderIndex]->IsHeapObject()); | |
175 DCHECK(values[T::kIsolateIndex]->IsSmi()); | |
176 } | |
177 | |
178 /* | |
179 * 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 | |
181 * has been registered. | |
182 * 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. | |
184 * New style callbacks always use the return value. | |
185 */ | |
186 #define WRITE_CALL_0(Function, ReturnValue) \ | |
187 v8::Local<ReturnValue> Call(Function f); | |
188 | |
189 #define WRITE_CALL_1(Function, ReturnValue, Arg1) \ | |
190 v8::Local<ReturnValue> Call(Function f, Arg1 arg1); | |
191 | |
192 #define WRITE_CALL_2(Function, ReturnValue, Arg1, Arg2) \ | |
193 v8::Local<ReturnValue> Call(Function f, Arg1 arg1, Arg2 arg2); | |
194 | |
195 #define WRITE_CALL_2_VOID(Function, ReturnValue, Arg1, Arg2) \ | |
196 void Call(Function f, Arg1 arg1, Arg2 arg2); \ | |
197 | |
198 FOR_EACH_CALLBACK_TABLE_MAPPING_0(WRITE_CALL_0) | |
199 FOR_EACH_CALLBACK_TABLE_MAPPING_1(WRITE_CALL_1) | |
200 FOR_EACH_CALLBACK_TABLE_MAPPING_2(WRITE_CALL_2) | |
201 FOR_EACH_CALLBACK_TABLE_MAPPING_2_VOID_RETURN(WRITE_CALL_2_VOID) | |
202 | |
203 #undef WRITE_CALL_0 | |
204 #undef WRITE_CALL_1 | |
205 #undef WRITE_CALL_2 | |
206 #undef WRITE_CALL_2_VOID | |
207 }; | |
208 | |
209 | |
210 class FunctionCallbackArguments | |
211 : public CustomArguments<FunctionCallbackInfo<Value> > { | |
212 public: | |
213 typedef FunctionCallbackInfo<Value> T; | |
214 typedef CustomArguments<T> Super; | |
215 static const int kArgsLength = T::kArgsLength; | |
216 static const int kHolderIndex = T::kHolderIndex; | |
217 static const int kDataIndex = T::kDataIndex; | |
218 static const int kReturnValueDefaultValueIndex = | |
219 T::kReturnValueDefaultValueIndex; | |
220 static const int kIsolateIndex = T::kIsolateIndex; | |
221 static const int kCalleeIndex = T::kCalleeIndex; | |
222 static const int kContextSaveIndex = T::kContextSaveIndex; | |
223 | |
224 FunctionCallbackArguments(internal::Isolate* isolate, internal::Object* data, | |
225 internal::HeapObject* callee, | |
226 internal::Object* holder, internal::Object** argv, | |
227 int argc, bool is_construct_call) | |
228 : Super(isolate), | |
229 argv_(argv), | |
230 argc_(argc), | |
231 is_construct_call_(is_construct_call) { | |
232 Object** values = begin(); | |
233 values[T::kDataIndex] = data; | |
234 values[T::kCalleeIndex] = callee; | |
235 values[T::kHolderIndex] = holder; | |
236 values[T::kContextSaveIndex] = isolate->heap()->the_hole_value(); | |
237 values[T::kIsolateIndex] = reinterpret_cast<internal::Object*>(isolate); | |
238 // Here the hole is set as default value. | |
239 // It cannot escape into js as it's remove in Call below. | |
240 values[T::kReturnValueDefaultValueIndex] = | |
241 isolate->heap()->the_hole_value(); | |
242 values[T::kReturnValueIndex] = isolate->heap()->the_hole_value(); | |
243 DCHECK(values[T::kCalleeIndex]->IsJSFunction() || | |
244 values[T::kCalleeIndex]->IsFunctionTemplateInfo()); | |
245 DCHECK(values[T::kHolderIndex]->IsHeapObject()); | |
246 DCHECK(values[T::kIsolateIndex]->IsSmi()); | |
247 } | |
248 | |
249 /* | |
250 * The following Call function wraps the calling of all callbacks to handle | |
251 * calling either the old or the new style callbacks depending on which one | |
252 * has been registered. | |
253 * For old callbacks which return an empty handle, the ReturnValue is checked | |
254 * and used if it's been set to anything inside the callback. | |
255 * New style callbacks always use the return value. | |
256 */ | |
257 v8::Local<v8::Value> Call(FunctionCallback f); | |
258 | |
259 private: | |
260 internal::Object** argv_; | |
261 int argc_; | |
262 bool is_construct_call_; | |
263 }; | |
264 | |
265 | |
266 double ClobberDoubleRegisters(double x1, double x2, double x3, double x4); | 74 double ClobberDoubleRegisters(double x1, double x2, double x3, double x4); |
267 | 75 |
268 | |
269 #ifdef DEBUG | 76 #ifdef DEBUG |
270 #define CLOBBER_DOUBLE_REGISTERS() ClobberDoubleRegisters(1, 2, 3, 4); | 77 #define CLOBBER_DOUBLE_REGISTERS() ClobberDoubleRegisters(1, 2, 3, 4); |
271 #else | 78 #else |
272 #define CLOBBER_DOUBLE_REGISTERS() | 79 #define CLOBBER_DOUBLE_REGISTERS() |
273 #endif | 80 #endif |
274 | 81 |
275 #define RUNTIME_FUNCTION_RETURNS_TYPE(Type, Name) \ | 82 #define RUNTIME_FUNCTION_RETURNS_TYPE(Type, Name) \ |
276 static INLINE(Type __RT_impl_##Name(Arguments args, Isolate* isolate)); \ | 83 static INLINE(Type __RT_impl_##Name(Arguments args, Isolate* isolate)); \ |
277 Type Name(int args_length, Object** args_object, Isolate* isolate) { \ | 84 Type Name(int args_length, Object** args_object, Isolate* isolate) { \ |
278 CLOBBER_DOUBLE_REGISTERS(); \ | 85 CLOBBER_DOUBLE_REGISTERS(); \ |
(...skipping 14 matching lines...) Expand all Loading... |
293 #define RUNTIME_FUNCTION(Name) RUNTIME_FUNCTION_RETURNS_TYPE(Object*, Name) | 100 #define RUNTIME_FUNCTION(Name) RUNTIME_FUNCTION_RETURNS_TYPE(Object*, Name) |
294 #define RUNTIME_FUNCTION_RETURN_PAIR(Name) \ | 101 #define RUNTIME_FUNCTION_RETURN_PAIR(Name) \ |
295 RUNTIME_FUNCTION_RETURNS_TYPE(ObjectPair, Name) | 102 RUNTIME_FUNCTION_RETURNS_TYPE(ObjectPair, Name) |
296 #define RUNTIME_FUNCTION_RETURN_TRIPLE(Name) \ | 103 #define RUNTIME_FUNCTION_RETURN_TRIPLE(Name) \ |
297 RUNTIME_FUNCTION_RETURNS_TYPE(ObjectTriple, Name) | 104 RUNTIME_FUNCTION_RETURNS_TYPE(ObjectTriple, Name) |
298 | 105 |
299 } // namespace internal | 106 } // namespace internal |
300 } // namespace v8 | 107 } // namespace v8 |
301 | 108 |
302 #endif // V8_ARGUMENTS_H_ | 109 #endif // V8_ARGUMENTS_H_ |
OLD | NEW |