blob: e6c6db569befa798861dcecc1401baad8cc2c3e2 [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
Emily Bernierd0a1eb72015-03-24 16:35:39 -040070// F(GenericNamedPropertyEnumeratorCallback, ...)
71// F(GenericNamedPropertyGetterCallback, ...)
Ben Murdochb8a8cc12014-11-26 15:28:44 +000072
73#define FOR_EACH_CALLBACK_TABLE_MAPPING_0(F) \
Emily Bernierd0a1eb72015-03-24 16:35:39 -040074 F(IndexedPropertyEnumeratorCallback, v8::Array)
Ben Murdochb8a8cc12014-11-26 15:28:44 +000075
Emily Bernierd0a1eb72015-03-24 16:35:39 -040076#define FOR_EACH_CALLBACK_TABLE_MAPPING_1(F) \
77 F(AccessorNameGetterCallback, v8::Value, v8::Local<v8::Name>) \
78 F(GenericNamedPropertyQueryCallback, v8::Integer, v8::Local<v8::Name>) \
79 F(GenericNamedPropertyDeleterCallback, v8::Boolean, v8::Local<v8::Name>) \
80 F(IndexedPropertyGetterCallback, v8::Value, uint32_t) \
81 F(IndexedPropertyQueryCallback, v8::Integer, uint32_t) \
82 F(IndexedPropertyDeleterCallback, v8::Boolean, uint32_t)
Ben Murdochb8a8cc12014-11-26 15:28:44 +000083
Emily Bernierd0a1eb72015-03-24 16:35:39 -040084#define FOR_EACH_CALLBACK_TABLE_MAPPING_2(F) \
85 F(GenericNamedPropertySetterCallback, v8::Value, v8::Local<v8::Name>, \
86 v8::Local<v8::Value>) \
87 F(IndexedPropertySetterCallback, v8::Value, uint32_t, v8::Local<v8::Value>)
Ben Murdochb8a8cc12014-11-26 15:28:44 +000088
89#define FOR_EACH_CALLBACK_TABLE_MAPPING_2_VOID_RETURN(F) \
90 F(AccessorNameSetterCallback, \
91 void, \
92 v8::Local<v8::Name>, \
93 v8::Local<v8::Value>) \
94
95
Steve Block6ded16b2010-05-10 14:33:55 +010096// Custom arguments replicate a small segment of stack that can be
Steve Blocka7e24c12009-10-30 11:49:00 +000097// accessed through an Arguments object the same way the actual stack
98// can.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000099template<int kArrayLength>
100class CustomArgumentsBase : public Relocatable {
Steve Blocka7e24c12009-10-30 11:49:00 +0000101 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000102 virtual inline void IterateInstance(ObjectVisitor* v) {
103 v->VisitPointers(values_, values_ + kArrayLength);
Steve Blocka7e24c12009-10-30 11:49:00 +0000104 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000105 protected:
106 inline Object** begin() { return values_; }
107 explicit inline CustomArgumentsBase(Isolate* isolate)
108 : Relocatable(isolate) {}
109 Object* values_[kArrayLength];
Steve Blocka7e24c12009-10-30 11:49:00 +0000110};
111
Ben Murdoch8b112d22011-06-08 16:22:53 +0100112
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000113template<typename T>
114class CustomArguments : public CustomArgumentsBase<T::kArgsLength> {
115 public:
116 static const int kReturnValueOffset = T::kReturnValueIndex;
117
118 typedef CustomArgumentsBase<T::kArgsLength> Super;
119 ~CustomArguments() {
120 this->begin()[kReturnValueOffset] =
121 reinterpret_cast<Object*>(kHandleZapValue);
122 }
123
124 protected:
125 explicit inline CustomArguments(Isolate* isolate) : Super(isolate) {}
126
127 template<typename V>
128 v8::Handle<V> GetReturnValue(Isolate* isolate);
129
130 inline Isolate* isolate() {
131 return reinterpret_cast<Isolate*>(this->begin()[T::kIsolateIndex]);
132 }
133};
Ben Murdoch8b112d22011-06-08 16:22:53 +0100134
135
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000136class PropertyCallbackArguments
137 : public CustomArguments<PropertyCallbackInfo<Value> > {
138 public:
139 typedef PropertyCallbackInfo<Value> T;
140 typedef CustomArguments<T> Super;
141 static const int kArgsLength = T::kArgsLength;
142 static const int kThisIndex = T::kThisIndex;
143 static const int kHolderIndex = T::kHolderIndex;
144 static const int kDataIndex = T::kDataIndex;
145 static const int kReturnValueDefaultValueIndex =
146 T::kReturnValueDefaultValueIndex;
147 static const int kIsolateIndex = T::kIsolateIndex;
148
149 PropertyCallbackArguments(Isolate* isolate,
150 Object* data,
151 Object* self,
152 JSObject* holder)
153 : Super(isolate) {
154 Object** values = this->begin();
155 values[T::kThisIndex] = self;
156 values[T::kHolderIndex] = holder;
157 values[T::kDataIndex] = data;
158 values[T::kIsolateIndex] = reinterpret_cast<Object*>(isolate);
159 // Here the hole is set as default value.
160 // It cannot escape into js as it's remove in Call below.
161 values[T::kReturnValueDefaultValueIndex] =
162 isolate->heap()->the_hole_value();
163 values[T::kReturnValueIndex] = isolate->heap()->the_hole_value();
164 DCHECK(values[T::kHolderIndex]->IsHeapObject());
165 DCHECK(values[T::kIsolateIndex]->IsSmi());
166 }
167
168 /*
169 * The following Call functions wrap the calling of all callbacks to handle
170 * calling either the old or the new style callbacks depending on which one
171 * has been registered.
172 * For old callbacks which return an empty handle, the ReturnValue is checked
173 * and used if it's been set to anything inside the callback.
174 * New style callbacks always use the return value.
175 */
176#define WRITE_CALL_0(Function, ReturnValue) \
177 v8::Handle<ReturnValue> Call(Function f); \
178
179#define WRITE_CALL_1(Function, ReturnValue, Arg1) \
180 v8::Handle<ReturnValue> Call(Function f, Arg1 arg1); \
181
182#define WRITE_CALL_2(Function, ReturnValue, Arg1, Arg2) \
183 v8::Handle<ReturnValue> Call(Function f, Arg1 arg1, Arg2 arg2); \
184
185#define WRITE_CALL_2_VOID(Function, ReturnValue, Arg1, Arg2) \
186 void Call(Function f, Arg1 arg1, Arg2 arg2); \
187
188FOR_EACH_CALLBACK_TABLE_MAPPING_0(WRITE_CALL_0)
189FOR_EACH_CALLBACK_TABLE_MAPPING_1(WRITE_CALL_1)
190FOR_EACH_CALLBACK_TABLE_MAPPING_2(WRITE_CALL_2)
191FOR_EACH_CALLBACK_TABLE_MAPPING_2_VOID_RETURN(WRITE_CALL_2_VOID)
192
193#undef WRITE_CALL_0
194#undef WRITE_CALL_1
195#undef WRITE_CALL_2
196#undef WRITE_CALL_2_VOID
197};
Ben Murdoch8b112d22011-06-08 16:22:53 +0100198
199
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000200class FunctionCallbackArguments
201 : public CustomArguments<FunctionCallbackInfo<Value> > {
202 public:
203 typedef FunctionCallbackInfo<Value> T;
204 typedef CustomArguments<T> Super;
205 static const int kArgsLength = T::kArgsLength;
206 static const int kHolderIndex = T::kHolderIndex;
207 static const int kDataIndex = T::kDataIndex;
208 static const int kReturnValueDefaultValueIndex =
209 T::kReturnValueDefaultValueIndex;
210 static const int kIsolateIndex = T::kIsolateIndex;
211 static const int kCalleeIndex = T::kCalleeIndex;
212 static const int kContextSaveIndex = T::kContextSaveIndex;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100213
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000214 FunctionCallbackArguments(internal::Isolate* isolate,
215 internal::Object* data,
216 internal::JSFunction* callee,
217 internal::Object* holder,
218 internal::Object** argv,
219 int argc,
220 bool is_construct_call)
221 : Super(isolate),
222 argv_(argv),
223 argc_(argc),
224 is_construct_call_(is_construct_call) {
225 Object** values = begin();
226 values[T::kDataIndex] = data;
227 values[T::kCalleeIndex] = callee;
228 values[T::kHolderIndex] = holder;
229 values[T::kContextSaveIndex] = isolate->heap()->the_hole_value();
230 values[T::kIsolateIndex] = reinterpret_cast<internal::Object*>(isolate);
231 // Here the hole is set as default value.
232 // It cannot escape into js as it's remove in Call below.
233 values[T::kReturnValueDefaultValueIndex] =
234 isolate->heap()->the_hole_value();
235 values[T::kReturnValueIndex] = isolate->heap()->the_hole_value();
236 DCHECK(values[T::kCalleeIndex]->IsJSFunction());
237 DCHECK(values[T::kHolderIndex]->IsHeapObject());
238 DCHECK(values[T::kIsolateIndex]->IsSmi());
239 }
240
241 /*
242 * The following Call function wraps the calling of all callbacks to handle
243 * calling either the old or the new style callbacks depending on which one
244 * has been registered.
245 * For old callbacks which return an empty handle, the ReturnValue is checked
246 * and used if it's been set to anything inside the callback.
247 * New style callbacks always use the return value.
248 */
249 v8::Handle<v8::Value> Call(FunctionCallback f);
250
251 private:
252 internal::Object** argv_;
253 int argc_;
254 bool is_construct_call_;
255};
256
257
258double ClobberDoubleRegisters(double x1, double x2, double x3, double x4);
259
260
261#ifdef DEBUG
262#define CLOBBER_DOUBLE_REGISTERS() ClobberDoubleRegisters(1, 2, 3, 4);
263#else
264#define CLOBBER_DOUBLE_REGISTERS()
265#endif
266
267
268#define DECLARE_RUNTIME_FUNCTION(Name) \
269Object* Name(int args_length, Object** args_object, Isolate* isolate)
270
271#define RUNTIME_FUNCTION_RETURNS_TYPE(Type, Name) \
272static INLINE(Type __RT_impl_##Name(Arguments args, Isolate* isolate)); \
273Type Name(int args_length, Object** args_object, Isolate* isolate) { \
274 CLOBBER_DOUBLE_REGISTERS(); \
275 Arguments args(args_length, args_object); \
276 return __RT_impl_##Name(args, isolate); \
277} \
278static Type __RT_impl_##Name(Arguments args, Isolate* isolate)
279
280
281#define RUNTIME_FUNCTION(Name) RUNTIME_FUNCTION_RETURNS_TYPE(Object*, Name)
282#define RUNTIME_FUNCTION_RETURN_PAIR(Name) \
283 RUNTIME_FUNCTION_RETURNS_TYPE(ObjectPair, Name)
284
285#define RUNTIME_ARGUMENTS(isolate, args) \
286 args.length(), args.arguments(), isolate
Steve Blocka7e24c12009-10-30 11:49:00 +0000287
288} } // namespace v8::internal
289
290#endif // V8_ARGUMENTS_H_