blob: 3bfe34dc894c1828a3faa580c97c30b130034159 [file] [log] [blame]
Ben Murdochda12d292016-06-02 14:46:10 +01001// Copyright 2016 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.
4
5#ifndef V8_API_ARGUMENTS_H_
6#define V8_API_ARGUMENTS_H_
7
8#include "src/api.h"
9#include "src/isolate.h"
10#include "src/tracing/trace-event.h"
11#include "src/vm-state-inl.h"
12
13namespace v8 {
14namespace internal {
15
16// Custom arguments replicate a small segment of stack that can be
17// accessed through an Arguments object the same way the actual stack
18// can.
19template <int kArrayLength>
20class CustomArgumentsBase : public Relocatable {
21 public:
22 virtual inline void IterateInstance(ObjectVisitor* v) {
23 v->VisitPointers(values_, values_ + kArrayLength);
24 }
25
26 protected:
27 inline Object** begin() { return values_; }
28 explicit inline CustomArgumentsBase(Isolate* isolate)
29 : Relocatable(isolate) {}
30 Object* values_[kArrayLength];
31};
32
33template <typename T>
34class CustomArguments : public CustomArgumentsBase<T::kArgsLength> {
35 public:
36 static const int kReturnValueOffset = T::kReturnValueIndex;
37
38 typedef CustomArgumentsBase<T::kArgsLength> Super;
39 ~CustomArguments() {
40 this->begin()[kReturnValueOffset] =
41 reinterpret_cast<Object*>(kHandleZapValue);
42 }
43
44 protected:
45 explicit inline CustomArguments(Isolate* isolate) : Super(isolate) {}
46
47 template <typename V>
48 Handle<V> GetReturnValue(Isolate* isolate);
49
50 inline Isolate* isolate() {
51 return reinterpret_cast<Isolate*>(this->begin()[T::kIsolateIndex]);
52 }
53};
54
55template <typename T>
56template <typename V>
57Handle<V> CustomArguments<T>::GetReturnValue(Isolate* isolate) {
58 // Check the ReturnValue.
59 Object** handle = &this->begin()[kReturnValueOffset];
60 // Nothing was set, return empty handle as per previous behaviour.
61 if ((*handle)->IsTheHole()) return Handle<V>();
62 Handle<V> result = Handle<V>::cast(Handle<Object>(handle));
63 result->VerifyApiCallResultType();
64 return result;
65}
66
67class PropertyCallbackArguments
68 : public CustomArguments<PropertyCallbackInfo<Value> > {
69 public:
70 typedef PropertyCallbackInfo<Value> T;
71 typedef CustomArguments<T> Super;
72 static const int kArgsLength = T::kArgsLength;
73 static const int kThisIndex = T::kThisIndex;
74 static const int kHolderIndex = T::kHolderIndex;
75 static const int kDataIndex = T::kDataIndex;
76 static const int kReturnValueDefaultValueIndex =
77 T::kReturnValueDefaultValueIndex;
78 static const int kIsolateIndex = T::kIsolateIndex;
79 static const int kShouldThrowOnErrorIndex = T::kShouldThrowOnErrorIndex;
80
81 PropertyCallbackArguments(Isolate* isolate, Object* data, Object* self,
82 JSObject* holder, Object::ShouldThrow should_throw)
83 : Super(isolate) {
84 Object** values = this->begin();
85 values[T::kThisIndex] = self;
86 values[T::kHolderIndex] = holder;
87 values[T::kDataIndex] = data;
88 values[T::kIsolateIndex] = reinterpret_cast<Object*>(isolate);
89 values[T::kShouldThrowOnErrorIndex] =
90 Smi::FromInt(should_throw == Object::THROW_ON_ERROR ? 1 : 0);
91
92 // Here the hole is set as default value.
93 // It cannot escape into js as it's remove in Call below.
94 values[T::kReturnValueDefaultValueIndex] =
95 isolate->heap()->the_hole_value();
96 values[T::kReturnValueIndex] = isolate->heap()->the_hole_value();
97 DCHECK(values[T::kHolderIndex]->IsHeapObject());
98 DCHECK(values[T::kIsolateIndex]->IsSmi());
99 }
100
101/*
102 * The following Call functions wrap the calling of all callbacks to handle
103 * calling either the old or the new style callbacks depending on which one
104 * has been registered.
105 * For old callbacks which return an empty handle, the ReturnValue is checked
106 * and used if it's been set to anything inside the callback.
107 * New style callbacks always use the return value.
108 */
109 Handle<JSObject> Call(IndexedPropertyEnumeratorCallback f);
110
111#define FOR_EACH_CALLBACK_TABLE_MAPPING_1_NAME(F) \
112 F(AccessorNameGetterCallback, "get", v8::Value, Object) \
113 F(GenericNamedPropertyQueryCallback, "has", v8::Integer, Object) \
114 F(GenericNamedPropertyDeleterCallback, "delete", v8::Boolean, Object)
115
116#define WRITE_CALL_1_NAME(Function, type, ApiReturn, InternalReturn) \
117 Handle<InternalReturn> Call(Function f, Handle<Name> name) { \
118 Isolate* isolate = this->isolate(); \
119 VMState<EXTERNAL> state(isolate); \
120 ExternalCallbackScope call_scope(isolate, FUNCTION_ADDR(f)); \
121 PropertyCallbackInfo<ApiReturn> info(begin()); \
122 LOG(isolate, \
123 ApiNamedPropertyAccess("interceptor-named-" type, holder(), *name)); \
124 f(v8::Utils::ToLocal(name), info); \
125 return GetReturnValue<InternalReturn>(isolate); \
126 }
127
128 FOR_EACH_CALLBACK_TABLE_MAPPING_1_NAME(WRITE_CALL_1_NAME)
129
130#undef FOR_EACH_CALLBACK_TABLE_MAPPING_1_NAME
131#undef WRITE_CALL_1_NAME
132
133#define FOR_EACH_CALLBACK_TABLE_MAPPING_1_INDEX(F) \
134 F(IndexedPropertyGetterCallback, "get", v8::Value, Object) \
135 F(IndexedPropertyQueryCallback, "has", v8::Integer, Object) \
136 F(IndexedPropertyDeleterCallback, "delete", v8::Boolean, Object)
137
138#define WRITE_CALL_1_INDEX(Function, type, ApiReturn, InternalReturn) \
139 Handle<InternalReturn> Call(Function f, uint32_t index) { \
140 Isolate* isolate = this->isolate(); \
141 VMState<EXTERNAL> state(isolate); \
142 ExternalCallbackScope call_scope(isolate, FUNCTION_ADDR(f)); \
143 PropertyCallbackInfo<ApiReturn> info(begin()); \
144 LOG(isolate, ApiIndexedPropertyAccess("interceptor-indexed-" type, \
145 holder(), index)); \
146 f(index, info); \
147 return GetReturnValue<InternalReturn>(isolate); \
148 }
149
150 FOR_EACH_CALLBACK_TABLE_MAPPING_1_INDEX(WRITE_CALL_1_INDEX)
151
152#undef FOR_EACH_CALLBACK_TABLE_MAPPING_1_INDEX
153#undef WRITE_CALL_1_INDEX
154
155 Handle<Object> Call(GenericNamedPropertySetterCallback f, Handle<Name> name,
156 Handle<Object> value) {
157 Isolate* isolate = this->isolate();
158 VMState<EXTERNAL> state(isolate);
159 ExternalCallbackScope call_scope(isolate, FUNCTION_ADDR(f));
160 PropertyCallbackInfo<v8::Value> info(begin());
161 LOG(isolate,
162 ApiNamedPropertyAccess("interceptor-named-set", holder(), *name));
163 f(v8::Utils::ToLocal(name), v8::Utils::ToLocal(value), info);
164 return GetReturnValue<Object>(isolate);
165 }
166
167 Handle<Object> Call(IndexedPropertySetterCallback f, uint32_t index,
168 Handle<Object> value) {
169 Isolate* isolate = this->isolate();
170 VMState<EXTERNAL> state(isolate);
171 ExternalCallbackScope call_scope(isolate, FUNCTION_ADDR(f));
172 PropertyCallbackInfo<v8::Value> info(begin());
173 LOG(isolate,
174 ApiIndexedPropertyAccess("interceptor-indexed-set", holder(), index));
175 f(index, v8::Utils::ToLocal(value), info);
176 return GetReturnValue<Object>(isolate);
177 }
178
179 void Call(AccessorNameSetterCallback f, Handle<Name> name,
180 Handle<Object> value) {
181 Isolate* isolate = this->isolate();
182 VMState<EXTERNAL> state(isolate);
183 ExternalCallbackScope call_scope(isolate, FUNCTION_ADDR(f));
184 PropertyCallbackInfo<void> info(begin());
185 LOG(isolate,
186 ApiNamedPropertyAccess("interceptor-named-set", holder(), *name));
187 f(v8::Utils::ToLocal(name), v8::Utils::ToLocal(value), info);
188 }
189
190 private:
191 inline JSObject* holder() {
192 return JSObject::cast(this->begin()[T::kHolderIndex]);
193 }
194};
195
196class FunctionCallbackArguments
197 : public CustomArguments<FunctionCallbackInfo<Value> > {
198 public:
199 typedef FunctionCallbackInfo<Value> T;
200 typedef CustomArguments<T> Super;
201 static const int kArgsLength = T::kArgsLength;
202 static const int kHolderIndex = T::kHolderIndex;
203 static const int kDataIndex = T::kDataIndex;
204 static const int kReturnValueDefaultValueIndex =
205 T::kReturnValueDefaultValueIndex;
206 static const int kIsolateIndex = T::kIsolateIndex;
207 static const int kCalleeIndex = T::kCalleeIndex;
208 static const int kContextSaveIndex = T::kContextSaveIndex;
209
210 FunctionCallbackArguments(internal::Isolate* isolate, internal::Object* data,
211 internal::HeapObject* callee,
212 internal::Object* holder, internal::Object** argv,
213 int argc, bool is_construct_call)
214 : Super(isolate),
215 argv_(argv),
216 argc_(argc),
217 is_construct_call_(is_construct_call) {
218 Object** values = begin();
219 values[T::kDataIndex] = data;
220 values[T::kCalleeIndex] = callee;
221 values[T::kHolderIndex] = holder;
222 values[T::kContextSaveIndex] = isolate->heap()->the_hole_value();
223 values[T::kIsolateIndex] = reinterpret_cast<internal::Object*>(isolate);
224 // Here the hole is set as default value.
225 // It cannot escape into js as it's remove in Call below.
226 values[T::kReturnValueDefaultValueIndex] =
227 isolate->heap()->the_hole_value();
228 values[T::kReturnValueIndex] = isolate->heap()->the_hole_value();
229 DCHECK(values[T::kCalleeIndex]->IsJSFunction() ||
230 values[T::kCalleeIndex]->IsFunctionTemplateInfo());
231 DCHECK(values[T::kHolderIndex]->IsHeapObject());
232 DCHECK(values[T::kIsolateIndex]->IsSmi());
233 }
234
235 /*
236 * The following Call function wraps the calling of all callbacks to handle
237 * calling either the old or the new style callbacks depending on which one
238 * has been registered.
239 * For old callbacks which return an empty handle, the ReturnValue is checked
240 * and used if it's been set to anything inside the callback.
241 * New style callbacks always use the return value.
242 */
243 Handle<Object> Call(FunctionCallback f);
244
245 private:
246 internal::Object** argv_;
247 int argc_;
248 bool is_construct_call_;
249};
250
251} // namespace internal
252} // namespace v8
253
254#endif // V8_API_ARGUMENTS_H_