blob: d11a8cd61ee0b18659e2e66164f3c5de20675411 [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)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000032 : length_(length), arguments_(arguments) {
33 DCHECK_GE(length_, 0);
34 }
Steve Blocka7e24c12009-10-30 11:49:00 +000035
36 Object*& operator[] (int index) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000037 DCHECK_GE(index, 0);
38 DCHECK_LT(static_cast<uint32_t>(index), static_cast<uint32_t>(length_));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000039 return *(reinterpret_cast<Object**>(reinterpret_cast<intptr_t>(arguments_) -
40 index * kPointerSize));
Steve Blocka7e24c12009-10-30 11:49:00 +000041 }
42
43 template <class S> Handle<S> at(int index) {
44 Object** value = &((*this)[index]);
45 // This cast checks that the object we're accessing does indeed have the
46 // expected type.
47 S::cast(*value);
48 return Handle<S>(reinterpret_cast<S**>(value));
49 }
50
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000051 int smi_at(int index) {
52 return Smi::cast((*this)[index])->value();
53 }
54
55 double number_at(int index) {
56 return (*this)[index]->Number();
57 }
58
Steve Blocka7e24c12009-10-30 11:49:00 +000059 // Get the total number of arguments including the receiver.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000060 int length() const { return static_cast<int>(length_); }
Steve Blocka7e24c12009-10-30 11:49:00 +000061
62 Object** arguments() { return arguments_; }
Ben Murdoch589d6972011-11-30 16:04:58 +000063
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000064 Object** lowest_address() { return &this->operator[](length() - 1); }
65
66 Object** highest_address() { return &this->operator[](0); }
67
Steve Blocka7e24c12009-10-30 11:49:00 +000068 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000069 intptr_t length_;
Steve Blocka7e24c12009-10-30 11:49:00 +000070 Object** arguments_;
71};
72
73
Ben Murdochb8a8cc12014-11-26 15:28:44 +000074// For each type of callback, we have a list of arguments
75// They are used to generate the Call() functions below
76// These aren't included in the list as they have duplicate signatures
Emily Bernierd0a1eb72015-03-24 16:35:39 -040077// F(GenericNamedPropertyEnumeratorCallback, ...)
78// F(GenericNamedPropertyGetterCallback, ...)
Ben Murdochb8a8cc12014-11-26 15:28:44 +000079
80#define FOR_EACH_CALLBACK_TABLE_MAPPING_0(F) \
Emily Bernierd0a1eb72015-03-24 16:35:39 -040081 F(IndexedPropertyEnumeratorCallback, v8::Array)
Ben Murdochb8a8cc12014-11-26 15:28:44 +000082
Emily Bernierd0a1eb72015-03-24 16:35:39 -040083#define FOR_EACH_CALLBACK_TABLE_MAPPING_1(F) \
84 F(AccessorNameGetterCallback, v8::Value, v8::Local<v8::Name>) \
85 F(GenericNamedPropertyQueryCallback, v8::Integer, v8::Local<v8::Name>) \
86 F(GenericNamedPropertyDeleterCallback, v8::Boolean, v8::Local<v8::Name>) \
87 F(IndexedPropertyGetterCallback, v8::Value, uint32_t) \
88 F(IndexedPropertyQueryCallback, v8::Integer, uint32_t) \
89 F(IndexedPropertyDeleterCallback, v8::Boolean, uint32_t)
Ben Murdochb8a8cc12014-11-26 15:28:44 +000090
Emily Bernierd0a1eb72015-03-24 16:35:39 -040091#define FOR_EACH_CALLBACK_TABLE_MAPPING_2(F) \
92 F(GenericNamedPropertySetterCallback, v8::Value, v8::Local<v8::Name>, \
93 v8::Local<v8::Value>) \
94 F(IndexedPropertySetterCallback, v8::Value, uint32_t, v8::Local<v8::Value>)
Ben Murdochb8a8cc12014-11-26 15:28:44 +000095
96#define FOR_EACH_CALLBACK_TABLE_MAPPING_2_VOID_RETURN(F) \
97 F(AccessorNameSetterCallback, \
98 void, \
99 v8::Local<v8::Name>, \
100 v8::Local<v8::Value>) \
101
102
Steve Block6ded16b2010-05-10 14:33:55 +0100103// Custom arguments replicate a small segment of stack that can be
Steve Blocka7e24c12009-10-30 11:49:00 +0000104// accessed through an Arguments object the same way the actual stack
105// can.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000106template<int kArrayLength>
107class CustomArgumentsBase : public Relocatable {
Steve Blocka7e24c12009-10-30 11:49:00 +0000108 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000109 virtual inline void IterateInstance(ObjectVisitor* v) {
110 v->VisitPointers(values_, values_ + kArrayLength);
Steve Blocka7e24c12009-10-30 11:49:00 +0000111 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000112 protected:
113 inline Object** begin() { return values_; }
114 explicit inline CustomArgumentsBase(Isolate* isolate)
115 : Relocatable(isolate) {}
116 Object* values_[kArrayLength];
Steve Blocka7e24c12009-10-30 11:49:00 +0000117};
118
Ben Murdoch8b112d22011-06-08 16:22:53 +0100119
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000120template<typename T>
121class CustomArguments : public CustomArgumentsBase<T::kArgsLength> {
122 public:
123 static const int kReturnValueOffset = T::kReturnValueIndex;
124
125 typedef CustomArgumentsBase<T::kArgsLength> Super;
126 ~CustomArguments() {
127 this->begin()[kReturnValueOffset] =
128 reinterpret_cast<Object*>(kHandleZapValue);
129 }
130
131 protected:
132 explicit inline CustomArguments(Isolate* isolate) : Super(isolate) {}
133
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000134 template <typename V>
135 v8::Local<V> GetReturnValue(Isolate* isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000136
137 inline Isolate* isolate() {
138 return reinterpret_cast<Isolate*>(this->begin()[T::kIsolateIndex]);
139 }
140};
Ben Murdoch8b112d22011-06-08 16:22:53 +0100141
142
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000143class PropertyCallbackArguments
144 : public CustomArguments<PropertyCallbackInfo<Value> > {
145 public:
146 typedef PropertyCallbackInfo<Value> T;
147 typedef CustomArguments<T> Super;
148 static const int kArgsLength = T::kArgsLength;
149 static const int kThisIndex = T::kThisIndex;
150 static const int kHolderIndex = T::kHolderIndex;
151 static const int kDataIndex = T::kDataIndex;
152 static const int kReturnValueDefaultValueIndex =
153 T::kReturnValueDefaultValueIndex;
154 static const int kIsolateIndex = T::kIsolateIndex;
155
156 PropertyCallbackArguments(Isolate* isolate,
157 Object* data,
158 Object* self,
159 JSObject* holder)
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 // Here the hole is set as default value.
167 // It cannot escape into js as it's remove in Call below.
168 values[T::kReturnValueDefaultValueIndex] =
169 isolate->heap()->the_hole_value();
170 values[T::kReturnValueIndex] = isolate->heap()->the_hole_value();
171 DCHECK(values[T::kHolderIndex]->IsHeapObject());
172 DCHECK(values[T::kIsolateIndex]->IsSmi());
173 }
174
175 /*
176 * The following Call functions wrap the calling of all callbacks to handle
177 * calling either the old or the new style callbacks depending on which one
178 * has been registered.
179 * For old callbacks which return an empty handle, the ReturnValue is checked
180 * and used if it's been set to anything inside the callback.
181 * New style callbacks always use the return value.
182 */
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000183#define WRITE_CALL_0(Function, ReturnValue) \
184 v8::Local<ReturnValue> Call(Function f);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000185
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000186#define WRITE_CALL_1(Function, ReturnValue, Arg1) \
187 v8::Local<ReturnValue> Call(Function f, Arg1 arg1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000188
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000189#define WRITE_CALL_2(Function, ReturnValue, Arg1, Arg2) \
190 v8::Local<ReturnValue> Call(Function f, Arg1 arg1, Arg2 arg2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000191
192#define WRITE_CALL_2_VOID(Function, ReturnValue, Arg1, Arg2) \
193 void Call(Function f, Arg1 arg1, Arg2 arg2); \
194
195FOR_EACH_CALLBACK_TABLE_MAPPING_0(WRITE_CALL_0)
196FOR_EACH_CALLBACK_TABLE_MAPPING_1(WRITE_CALL_1)
197FOR_EACH_CALLBACK_TABLE_MAPPING_2(WRITE_CALL_2)
198FOR_EACH_CALLBACK_TABLE_MAPPING_2_VOID_RETURN(WRITE_CALL_2_VOID)
199
200#undef WRITE_CALL_0
201#undef WRITE_CALL_1
202#undef WRITE_CALL_2
203#undef WRITE_CALL_2_VOID
204};
Ben Murdoch8b112d22011-06-08 16:22:53 +0100205
206
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000207class FunctionCallbackArguments
208 : public CustomArguments<FunctionCallbackInfo<Value> > {
209 public:
210 typedef FunctionCallbackInfo<Value> T;
211 typedef CustomArguments<T> Super;
212 static const int kArgsLength = T::kArgsLength;
213 static const int kHolderIndex = T::kHolderIndex;
214 static const int kDataIndex = T::kDataIndex;
215 static const int kReturnValueDefaultValueIndex =
216 T::kReturnValueDefaultValueIndex;
217 static const int kIsolateIndex = T::kIsolateIndex;
218 static const int kCalleeIndex = T::kCalleeIndex;
219 static const int kContextSaveIndex = T::kContextSaveIndex;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100220
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000221 FunctionCallbackArguments(internal::Isolate* isolate,
222 internal::Object* data,
223 internal::JSFunction* callee,
224 internal::Object* holder,
225 internal::Object** argv,
226 int argc,
227 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 DCHECK(values[T::kHolderIndex]->IsHeapObject());
245 DCHECK(values[T::kIsolateIndex]->IsSmi());
246 }
247
248 /*
249 * The following Call function wraps the calling of all callbacks to handle
250 * calling either the old or the new style callbacks depending on which one
251 * has been registered.
252 * For old callbacks which return an empty handle, the ReturnValue is checked
253 * and used if it's been set to anything inside the callback.
254 * New style callbacks always use the return value.
255 */
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000256 v8::Local<v8::Value> Call(FunctionCallback f);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000257
258 private:
259 internal::Object** argv_;
260 int argc_;
261 bool is_construct_call_;
262};
263
264
265double ClobberDoubleRegisters(double x1, double x2, double x3, double x4);
266
267
268#ifdef DEBUG
269#define CLOBBER_DOUBLE_REGISTERS() ClobberDoubleRegisters(1, 2, 3, 4);
270#else
271#define CLOBBER_DOUBLE_REGISTERS()
272#endif
273
274
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000275#define RUNTIME_FUNCTION_RETURNS_TYPE(Type, Name) \
276static INLINE(Type __RT_impl_##Name(Arguments args, Isolate* isolate)); \
277Type Name(int args_length, Object** args_object, Isolate* isolate) { \
278 CLOBBER_DOUBLE_REGISTERS(); \
279 Arguments args(args_length, args_object); \
280 return __RT_impl_##Name(args, isolate); \
281} \
282static Type __RT_impl_##Name(Arguments args, Isolate* isolate)
283
284
285#define RUNTIME_FUNCTION(Name) RUNTIME_FUNCTION_RETURNS_TYPE(Object*, Name)
286#define RUNTIME_FUNCTION_RETURN_PAIR(Name) \
287 RUNTIME_FUNCTION_RETURNS_TYPE(ObjectPair, Name)
288
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000289} // namespace internal
290} // namespace v8
Steve Blocka7e24c12009-10-30 11:49:00 +0000291
292#endif // V8_ARGUMENTS_H_