blob: 9fb2da3bc5ccaa950427295aca54c6e6515e949f [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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.
Steve Blocka7e24c12009-10-30 11:49:00 +00004
5#ifndef V8_ARGUMENTS_H_
6#define V8_ARGUMENTS_H_
7
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008#include "src/allocation.h"
9#include "src/isolate.h"
Ben Murdoch257744e2011-11-30 15:57:28 +000010
Steve Blocka7e24c12009-10-30 11:49:00 +000011namespace 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// }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000025//
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.
Steve Blocka7e24c12009-10-30 11:49:00 +000028
29class Arguments BASE_EMBEDDED {
30 public:
31 Arguments(int length, Object** arguments)
32 : length_(length), arguments_(arguments) { }
33
34 Object*& operator[] (int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000035 DCHECK(0 <= index && index < length_);
36 return *(reinterpret_cast<Object**>(reinterpret_cast<intptr_t>(arguments_) -
37 index * kPointerSize));
Steve Blocka7e24c12009-10-30 11:49:00 +000038 }
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
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000048 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
Steve Blocka7e24c12009-10-30 11:49:00 +000056 // Get the total number of arguments including the receiver.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000057 int length() const { return static_cast<int>(length_); }
Steve Blocka7e24c12009-10-30 11:49:00 +000058
59 Object** arguments() { return arguments_; }
Ben Murdoch589d6972011-11-30 16:04:58 +000060
Steve Blocka7e24c12009-10-30 11:49:00 +000061 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000062 intptr_t length_;
Steve Blocka7e24c12009-10-30 11:49:00 +000063 Object** arguments_;
64};
65
66
Ben Murdochb8a8cc12014-11-26 15:28:44 +000067// 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
Steve Block6ded16b2010-05-10 14:33:55 +0100111// Custom arguments replicate a small segment of stack that can be
Steve Blocka7e24c12009-10-30 11:49:00 +0000112// accessed through an Arguments object the same way the actual stack
113// can.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000114template<int kArrayLength>
115class CustomArgumentsBase : public Relocatable {
Steve Blocka7e24c12009-10-30 11:49:00 +0000116 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000117 virtual inline void IterateInstance(ObjectVisitor* v) {
118 v->VisitPointers(values_, values_ + kArrayLength);
Steve Blocka7e24c12009-10-30 11:49:00 +0000119 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000120 protected:
121 inline Object** begin() { return values_; }
122 explicit inline CustomArgumentsBase(Isolate* isolate)
123 : Relocatable(isolate) {}
124 Object* values_[kArrayLength];
Steve Blocka7e24c12009-10-30 11:49:00 +0000125};
126
Ben Murdoch8b112d22011-06-08 16:22:53 +0100127
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000128template<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};
Ben Murdoch8b112d22011-06-08 16:22:53 +0100149
150
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000151class 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};
Ben Murdoch8b112d22011-06-08 16:22:53 +0100213
214
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000215class 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;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100228
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000229 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
Steve Blocka7e24c12009-10-30 11:49:00 +0000302
303} } // namespace v8::internal
304
305#endif // V8_ARGUMENTS_H_