v8  3.25.30(node0.11.13)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
arguments.h
Go to the documentation of this file.
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #ifndef V8_ARGUMENTS_H_
29 #define V8_ARGUMENTS_H_
30 
31 #include "allocation.h"
32 
33 namespace v8 {
34 namespace internal {
35 
36 // Arguments provides access to runtime call parameters.
37 //
38 // It uses the fact that the instance fields of Arguments
39 // (length_, arguments_) are "overlayed" with the parameters
40 // (no. of parameters, and the parameter pointer) passed so
41 // that inside the C++ function, the parameters passed can
42 // be accessed conveniently:
43 //
44 // Object* Runtime_function(Arguments args) {
45 // ... use args[i] here ...
46 // }
47 
48 class Arguments BASE_EMBEDDED {
49  public:
50  Arguments(int length, Object** arguments)
51  : length_(length), arguments_(arguments) { }
52 
53  Object*& operator[] (int index) {
54  ASSERT(0 <= index && index < length_);
55  return *(reinterpret_cast<Object**>(reinterpret_cast<intptr_t>(arguments_) -
56  index * kPointerSize));
57  }
58 
59  template <class S> Handle<S> at(int index) {
60  Object** value = &((*this)[index]);
61  // This cast checks that the object we're accessing does indeed have the
62  // expected type.
63  S::cast(*value);
64  return Handle<S>(reinterpret_cast<S**>(value));
65  }
66 
67  int smi_at(int index) {
68  return Smi::cast((*this)[index])->value();
69  }
70 
71  double number_at(int index) {
72  return (*this)[index]->Number();
73  }
74 
75  // Get the total number of arguments including the receiver.
76  int length() const { return length_; }
77 
78  Object** arguments() { return arguments_; }
79 
80  private:
81  int length_;
82  Object** arguments_;
83 };
84 
85 
86 // For each type of callback, we have a list of arguments
87 // They are used to generate the Call() functions below
88 // These aren't included in the list as they have duplicate signatures
89 // F(NamedPropertyEnumeratorCallback, ...)
90 // F(NamedPropertyGetterCallback, ...)
91 
92 #define FOR_EACH_CALLBACK_TABLE_MAPPING_0(F) \
93  F(IndexedPropertyEnumeratorCallback, v8::Array) \
94 
95 #define FOR_EACH_CALLBACK_TABLE_MAPPING_1(F) \
96  F(AccessorGetterCallback, v8::Value, v8::Local<v8::String>) \
97  F(NamedPropertyQueryCallback, \
98  v8::Integer, \
99  v8::Local<v8::String>) \
100  F(NamedPropertyDeleterCallback, \
101  v8::Boolean, \
102  v8::Local<v8::String>) \
103  F(IndexedPropertyGetterCallback, \
104  v8::Value, \
105  uint32_t) \
106  F(IndexedPropertyQueryCallback, \
107  v8::Integer, \
108  uint32_t) \
109  F(IndexedPropertyDeleterCallback, \
110  v8::Boolean, \
111  uint32_t) \
112 
113 #define FOR_EACH_CALLBACK_TABLE_MAPPING_2(F) \
114  F(NamedPropertySetterCallback, \
115  v8::Value, \
116  v8::Local<v8::String>, \
117  v8::Local<v8::Value>) \
118  F(IndexedPropertySetterCallback, \
119  v8::Value, \
120  uint32_t, \
121  v8::Local<v8::Value>) \
122 
123 #define FOR_EACH_CALLBACK_TABLE_MAPPING_2_VOID_RETURN(F) \
124  F(AccessorSetterCallback, \
125  void, \
126  v8::Local<v8::String>, \
127  v8::Local<v8::Value>) \
128 
129 
130 // Custom arguments replicate a small segment of stack that can be
131 // accessed through an Arguments object the same way the actual stack
132 // can.
133 template<int kArrayLength>
134 class CustomArgumentsBase : public Relocatable {
135  public:
136  virtual inline void IterateInstance(ObjectVisitor* v) {
137  v->VisitPointers(values_, values_ + kArrayLength);
138  }
139  protected:
140  inline Object** begin() { return values_; }
141  explicit inline CustomArgumentsBase(Isolate* isolate)
142  : Relocatable(isolate) {}
143  Object* values_[kArrayLength];
144 };
145 
146 
147 template<typename T>
148 class CustomArguments : public CustomArgumentsBase<T::kArgsLength> {
149  public:
150  static const int kReturnValueOffset = T::kReturnValueIndex;
151 
154  this->begin()[kReturnValueOffset] =
155  reinterpret_cast<Object*>(kHandleZapValue);
156  }
157 
158  protected:
159  explicit inline CustomArguments(Isolate* isolate) : Super(isolate) {}
160 
161  template<typename V>
163 
164  inline Isolate* isolate() {
165  return reinterpret_cast<Isolate*>(this->begin()[T::kIsolateIndex]);
166  }
167 };
168 
169 
171  : public CustomArguments<PropertyCallbackInfo<Value> > {
172  public:
175  static const int kArgsLength = T::kArgsLength;
176  static const int kThisIndex = T::kThisIndex;
177  static const int kHolderIndex = T::kHolderIndex;
178  static const int kDataIndex = T::kDataIndex;
179  static const int kReturnValueDefaultValueIndex =
181  static const int kIsolateIndex = T::kIsolateIndex;
182 
184  Object* data,
185  Object* self,
186  JSObject* holder)
187  : Super(isolate) {
188  Object** values = this->begin();
189  values[T::kThisIndex] = self;
190  values[T::kHolderIndex] = holder;
191  values[T::kDataIndex] = data;
192  values[T::kIsolateIndex] = reinterpret_cast<Object*>(isolate);
193  // Here the hole is set as default value.
194  // It cannot escape into js as it's remove in Call below.
196  isolate->heap()->the_hole_value();
197  values[T::kReturnValueIndex] = isolate->heap()->the_hole_value();
198  ASSERT(values[T::kHolderIndex]->IsHeapObject());
199  ASSERT(values[T::kIsolateIndex]->IsSmi());
200  }
201 
202  /*
203  * The following Call functions wrap the calling of all callbacks to handle
204  * calling either the old or the new style callbacks depending on which one
205  * has been registered.
206  * For old callbacks which return an empty handle, the ReturnValue is checked
207  * and used if it's been set to anything inside the callback.
208  * New style callbacks always use the return value.
209  */
210 #define WRITE_CALL_0(Function, ReturnValue) \
211  v8::Handle<ReturnValue> Call(Function f); \
212 
213 #define WRITE_CALL_1(Function, ReturnValue, Arg1) \
214  v8::Handle<ReturnValue> Call(Function f, Arg1 arg1); \
215 
216 #define WRITE_CALL_2(Function, ReturnValue, Arg1, Arg2) \
217  v8::Handle<ReturnValue> Call(Function f, Arg1 arg1, Arg2 arg2); \
218 
219 #define WRITE_CALL_2_VOID(Function, ReturnValue, Arg1, Arg2) \
220  void Call(Function f, Arg1 arg1, Arg2 arg2); \
221 
226 
227 #undef WRITE_CALL_0
228 #undef WRITE_CALL_1
229 #undef WRITE_CALL_2
230 #undef WRITE_CALL_2_VOID
231 };
232 
233 
235  : public CustomArguments<FunctionCallbackInfo<Value> > {
236  public:
239  static const int kArgsLength = T::kArgsLength;
240  static const int kHolderIndex = T::kHolderIndex;
241  static const int kDataIndex = T::kDataIndex;
242  static const int kReturnValueDefaultValueIndex =
244  static const int kIsolateIndex = T::kIsolateIndex;
245  static const int kCalleeIndex = T::kCalleeIndex;
247 
249  internal::Object* data,
250  internal::JSFunction* callee,
251  internal::Object* holder,
252  internal::Object** argv,
253  int argc,
254  bool is_construct_call)
255  : Super(isolate),
256  argv_(argv),
257  argc_(argc),
258  is_construct_call_(is_construct_call) {
259  Object** values = begin();
260  values[T::kDataIndex] = data;
261  values[T::kCalleeIndex] = callee;
262  values[T::kHolderIndex] = holder;
263  values[T::kContextSaveIndex] = isolate->heap()->the_hole_value();
264  values[T::kIsolateIndex] = reinterpret_cast<internal::Object*>(isolate);
265  // Here the hole is set as default value.
266  // It cannot escape into js as it's remove in Call below.
268  isolate->heap()->the_hole_value();
269  values[T::kReturnValueIndex] = isolate->heap()->the_hole_value();
270  ASSERT(values[T::kCalleeIndex]->IsJSFunction());
271  ASSERT(values[T::kHolderIndex]->IsHeapObject());
272  ASSERT(values[T::kIsolateIndex]->IsSmi());
273  }
274 
275  /*
276  * The following Call function wraps the calling of all callbacks to handle
277  * calling either the old or the new style callbacks depending on which one
278  * has been registered.
279  * For old callbacks which return an empty handle, the ReturnValue is checked
280  * and used if it's been set to anything inside the callback.
281  * New style callbacks always use the return value.
282  */
284 
285  private:
286  internal::Object** argv_;
287  int argc_;
288  bool is_construct_call_;
289 };
290 
291 
292 double ClobberDoubleRegisters(double x1, double x2, double x3, double x4);
293 
294 
295 #ifdef DEBUG
296 #define CLOBBER_DOUBLE_REGISTERS() ClobberDoubleRegisters(1, 2, 3, 4);
297 #else
298 #define CLOBBER_DOUBLE_REGISTERS()
299 #endif
300 
301 
302 #define DECLARE_RUNTIME_FUNCTION(Type, Name) \
303 Type Name(int args_length, Object** args_object, Isolate* isolate)
304 
305 #define RUNTIME_FUNCTION(Type, Name) \
306 static Type __RT_impl_##Name(Arguments args, Isolate* isolate); \
307 Type Name(int args_length, Object** args_object, Isolate* isolate) { \
308  CLOBBER_DOUBLE_REGISTERS(); \
309  Arguments args(args_length, args_object); \
310  return __RT_impl_##Name(args, isolate); \
311 } \
312 static Type __RT_impl_##Name(Arguments args, Isolate* isolate)
313 
314 #define RUNTIME_ARGUMENTS(isolate, args) \
315  args.length(), args.arguments(), isolate
316 
317 } } // namespace v8::internal
318 
319 #endif // V8_ARGUMENTS_H_
#define FOR_EACH_CALLBACK_TABLE_MAPPING_0(F)
Definition: arguments.h:92
#define FOR_EACH_CALLBACK_TABLE_MAPPING_2_VOID_RETURN(F)
Definition: arguments.h:123
FunctionCallbackArguments(internal::Isolate *isolate, internal::Object *data, internal::JSFunction *callee, internal::Object *holder, internal::Object **argv, int argc, bool is_construct_call)
Definition: arguments.h:248
static const int kReturnValueOffset
Definition: arguments.h:150
void(* FunctionCallback)(const FunctionCallbackInfo< Value > &info)
Definition: v8.h:2603
static const int kArgsLength
Definition: v8.h:2548
#define WRITE_CALL_0(Function, ReturnValue)
Definition: arguments.h:210
static const int kHolderIndex
Definition: v8.h:2553
int smi_at(int index)
Definition: arguments.h:67
CustomArguments(Isolate *isolate)
Definition: arguments.h:159
Handle< S > at(int index)
Definition: arguments.h:59
#define ASSERT(condition)
Definition: checks.h:329
#define WRITE_CALL_2_VOID(Function, ReturnValue, Arg1, Arg2)
Definition: arguments.h:219
static const int kArgsLength
Definition: v8.h:2585
v8::Handle< V > GetReturnValue(Isolate *isolate)
Definition: arguments.cc:39
static Smi * cast(Object *object)
PropertyCallbackArguments(Isolate *isolate, Object *data, Object *self, JSObject *holder)
Definition: arguments.h:183
static const int kDataIndex
Definition: v8.h:2557
FunctionCallbackInfo< Value > T
Definition: arguments.h:237
static const int kReturnValueDefaultValueIndex
Definition: v8.h:2555
static const int kReturnValueIndex
Definition: v8.h:2594
const int kPointerSize
Definition: globals.h:268
Arguments(int length, Object **arguments)
Definition: arguments.h:50
double ClobberDoubleRegisters(double x1, double x2, double x3, double x4)
Definition: arguments.cc:120
static const int kReturnValueDefaultValueIndex
Definition: v8.h:2593
static const int kReturnValueDefaultValueIndex
Definition: arguments.h:179
Definition: v8.h:123
static const int kIsolateIndex
Definition: v8.h:2554
static const int kReturnValueDefaultValueIndex
Definition: arguments.h:242
static const int kCalleeIndex
Definition: v8.h:2558
CustomArgumentsBase(Isolate *isolate)
Definition: arguments.h:141
#define WRITE_CALL_2(Function, ReturnValue, Arg1, Arg2)
Definition: arguments.h:216
static const int kIsolateIndex
Definition: v8.h:2592
CustomArgumentsBase< T::kArgsLength > Super
Definition: arguments.h:152
Object * values_[kArrayLength]
Definition: arguments.h:143
static const int kThisIndex
Definition: v8.h:2596
PropertyCallbackInfo< Value > T
Definition: arguments.h:173
v8::Handle< v8::Value > Call(FunctionCallback f)
Definition: arguments.cc:48
static const int kHolderIndex
Definition: v8.h:2591
double number_at(int index)
Definition: arguments.h:71
#define WRITE_CALL_1(Function, ReturnValue, Arg1)
Definition: arguments.h:213
#define FOR_EACH_CALLBACK_TABLE_MAPPING_1(F)
Definition: arguments.h:95
static const int kReturnValueIndex
Definition: v8.h:2556
static const int kContextSaveIndex
Definition: v8.h:2559
static const int kDataIndex
Definition: v8.h:2595
const Address kHandleZapValue
Definition: v8globals.h:83
virtual void IterateInstance(ObjectVisitor *v)
Definition: arguments.h:136
#define FOR_EACH_CALLBACK_TABLE_MAPPING_2(F)
Definition: arguments.h:113