Line data Source code
1 : // 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_INL_H_
6 : #define V8_API_ARGUMENTS_INL_H_
7 :
8 : #include "src/api-arguments.h"
9 :
10 : #include "src/api-inl.h"
11 : #include "src/debug/debug.h"
12 : #include "src/objects/api-callbacks.h"
13 : #include "src/objects/slots-inl.h"
14 : #include "src/tracing/trace-event.h"
15 : #include "src/vm-state-inl.h"
16 :
17 : namespace v8 {
18 : namespace internal {
19 :
20 : CustomArgumentsBase::CustomArgumentsBase(Isolate* isolate)
21 10190070 : : Relocatable(isolate) {}
22 :
23 : template <typename T>
24 0 : CustomArguments<T>::~CustomArguments() {
25 : slot_at(kReturnValueOffset).store(Object(kHandleZapValue));
26 5095032 : }
27 :
28 : template <typename T>
29 : template <typename V>
30 5094798 : Handle<V> CustomArguments<T>::GetReturnValue(Isolate* isolate) {
31 : // Check the ReturnValue.
32 : FullObjectSlot slot = slot_at(kReturnValueOffset);
33 : // Nothing was set, return empty handle as per previous behaviour.
34 5094809 : if ((*slot)->IsTheHole(isolate)) return Handle<V>();
35 2956311 : Handle<V> result = Handle<V>::cast(Handle<Object>(slot.location()));
36 : result->VerifyApiCallResultType();
37 2956310 : return result;
38 : }
39 :
40 0 : inline JSObject PropertyCallbackArguments::holder() {
41 0 : return JSObject::cast(*slot_at(T::kHolderIndex));
42 : }
43 :
44 : inline Object PropertyCallbackArguments::receiver() {
45 : return *slot_at(T::kThisIndex);
46 : }
47 :
48 0 : inline JSObject FunctionCallbackArguments::holder() {
49 0 : return JSObject::cast(*slot_at(T::kHolderIndex));
50 : }
51 :
52 : #define FOR_EACH_CALLBACK(F) \
53 : F(Query, query, Object, v8::Integer, interceptor) \
54 : F(Deleter, deleter, Object, v8::Boolean, Handle<Object>())
55 :
56 : #define DCHECK_NAME_COMPATIBLE(interceptor, name) \
57 : DCHECK(interceptor->is_named()); \
58 : DCHECK(!name->IsPrivate()); \
59 : DCHECK_IMPLIES(name->IsSymbol(), interceptor->can_intercept_symbols());
60 :
61 : #define PREPARE_CALLBACK_INFO(ISOLATE, F, RETURN_VALUE, API_RETURN_TYPE, \
62 : CALLBACK_INFO, RECEIVER, ACCESSOR_KIND) \
63 : if (ISOLATE->debug_execution_mode() == DebugInfo::kSideEffects && \
64 : !ISOLATE->debug()->PerformSideEffectCheckForCallback( \
65 : CALLBACK_INFO, RECEIVER, Debug::k##ACCESSOR_KIND)) { \
66 : return RETURN_VALUE(); \
67 : } \
68 : VMState<EXTERNAL> state(ISOLATE); \
69 : ExternalCallbackScope call_scope(ISOLATE, FUNCTION_ADDR(F)); \
70 : PropertyCallbackInfo<API_RETURN_TYPE> callback_info(values_);
71 :
72 : #define PREPARE_CALLBACK_INFO_FAIL_SIDE_EFFECT_CHECK(ISOLATE, F, RETURN_VALUE, \
73 : API_RETURN_TYPE) \
74 : if (ISOLATE->debug_execution_mode() == DebugInfo::kSideEffects) { \
75 : return RETURN_VALUE(); \
76 : } \
77 : VMState<EXTERNAL> state(ISOLATE); \
78 : ExternalCallbackScope call_scope(ISOLATE, FUNCTION_ADDR(F)); \
79 : PropertyCallbackInfo<API_RETURN_TYPE> callback_info(values_);
80 :
81 : #define CREATE_NAMED_CALLBACK(FUNCTION, TYPE, RETURN_TYPE, API_RETURN_TYPE, \
82 : INFO_FOR_SIDE_EFFECT) \
83 : Handle<RETURN_TYPE> PropertyCallbackArguments::CallNamed##FUNCTION( \
84 : Handle<InterceptorInfo> interceptor, Handle<Name> name) { \
85 : DCHECK_NAME_COMPATIBLE(interceptor, name); \
86 : Isolate* isolate = this->isolate(); \
87 : RuntimeCallTimerScope timer( \
88 : isolate, RuntimeCallCounterId::kNamed##FUNCTION##Callback); \
89 : Handle<Object> receiver_check_unsupported; \
90 : GenericNamedProperty##FUNCTION##Callback f = \
91 : ToCData<GenericNamedProperty##FUNCTION##Callback>( \
92 : interceptor->TYPE()); \
93 : PREPARE_CALLBACK_INFO(isolate, f, Handle<RETURN_TYPE>, API_RETURN_TYPE, \
94 : INFO_FOR_SIDE_EFFECT, receiver_check_unsupported, \
95 : NotAccessor); \
96 : LOG(isolate, \
97 : ApiNamedPropertyAccess("interceptor-named-" #TYPE, holder(), *name)); \
98 : f(v8::Utils::ToLocal(name), callback_info); \
99 : return GetReturnValue<RETURN_TYPE>(isolate); \
100 : }
101 :
102 1414 : FOR_EACH_CALLBACK(CREATE_NAMED_CALLBACK)
103 : #undef CREATE_NAMED_CALLBACK
104 :
105 : #define CREATE_INDEXED_CALLBACK(FUNCTION, TYPE, RETURN_TYPE, API_RETURN_TYPE, \
106 : INFO_FOR_SIDE_EFFECT) \
107 : Handle<RETURN_TYPE> PropertyCallbackArguments::CallIndexed##FUNCTION( \
108 : Handle<InterceptorInfo> interceptor, uint32_t index) { \
109 : DCHECK(!interceptor->is_named()); \
110 : Isolate* isolate = this->isolate(); \
111 : RuntimeCallTimerScope timer( \
112 : isolate, RuntimeCallCounterId::kIndexed##FUNCTION##Callback); \
113 : Handle<Object> receiver_check_unsupported; \
114 : IndexedProperty##FUNCTION##Callback f = \
115 : ToCData<IndexedProperty##FUNCTION##Callback>(interceptor->TYPE()); \
116 : PREPARE_CALLBACK_INFO(isolate, f, Handle<RETURN_TYPE>, API_RETURN_TYPE, \
117 : INFO_FOR_SIDE_EFFECT, receiver_check_unsupported, \
118 : NotAccessor); \
119 : LOG(isolate, ApiIndexedPropertyAccess("interceptor-indexed-" #TYPE, \
120 : holder(), index)); \
121 : f(index, callback_info); \
122 : return GetReturnValue<RETURN_TYPE>(isolate); \
123 : }
124 :
125 1688 : FOR_EACH_CALLBACK(CREATE_INDEXED_CALLBACK)
126 :
127 : #undef FOR_EACH_CALLBACK
128 : #undef CREATE_INDEXED_CALLBACK
129 :
130 2475051 : Handle<Object> FunctionCallbackArguments::Call(CallHandlerInfo handler) {
131 4950248 : Isolate* isolate = this->isolate();
132 2475051 : LOG(isolate, ApiObjectAccess("call", holder()));
133 2475051 : RuntimeCallTimerScope timer(isolate, RuntimeCallCounterId::kFunctionCallback);
134 : v8::FunctionCallback f =
135 2475057 : v8::ToCData<v8::FunctionCallback>(handler->callback());
136 : Handle<Object> receiver_check_unsupported;
137 7425174 : if (isolate->debug_execution_mode() == DebugInfo::kSideEffects &&
138 : !isolate->debug()->PerformSideEffectCheckForCallback(
139 : handle(handler, isolate), receiver_check_unsupported,
140 2475336 : Debug::kNotAccessor)) {
141 64 : return Handle<Object>();
142 : }
143 4949982 : VMState<EXTERNAL> state(isolate);
144 4949985 : ExternalCallbackScope call_scope(isolate, FUNCTION_ADDR(f));
145 2474989 : FunctionCallbackInfo<v8::Value> info(values_, argv_, argc_);
146 2474989 : f(info);
147 2474981 : return GetReturnValue<Object>(isolate);
148 : }
149 :
150 240 : Handle<JSObject> PropertyCallbackArguments::CallNamedEnumerator(
151 : Handle<InterceptorInfo> interceptor) {
152 : DCHECK(interceptor->is_named());
153 240 : LOG(isolate(), ApiObjectAccess("interceptor-named-enumerator", holder()));
154 : RuntimeCallTimerScope timer(isolate(),
155 240 : RuntimeCallCounterId::kNamedEnumeratorCallback);
156 480 : return CallPropertyEnumerator(interceptor);
157 : }
158 :
159 235 : Handle<JSObject> PropertyCallbackArguments::CallIndexedEnumerator(
160 : Handle<InterceptorInfo> interceptor) {
161 : DCHECK(!interceptor->is_named());
162 235 : LOG(isolate(), ApiObjectAccess("interceptor-indexed-enumerator", holder()));
163 : RuntimeCallTimerScope timer(isolate(),
164 235 : RuntimeCallCounterId::kIndexedEnumeratorCallback);
165 470 : return CallPropertyEnumerator(interceptor);
166 : }
167 :
168 255149 : Handle<Object> PropertyCallbackArguments::CallNamedGetter(
169 : Handle<InterceptorInfo> interceptor, Handle<Name> name) {
170 : DCHECK_NAME_COMPATIBLE(interceptor, name);
171 255149 : Isolate* isolate = this->isolate();
172 : RuntimeCallTimerScope timer(isolate,
173 255149 : RuntimeCallCounterId::kNamedGetterCallback);
174 255149 : LOG(isolate,
175 : ApiNamedPropertyAccess("interceptor-named-getter", holder(), *name));
176 : GenericNamedPropertyGetterCallback f =
177 255149 : ToCData<GenericNamedPropertyGetterCallback>(interceptor->getter());
178 510298 : return BasicCallNamedGetterCallback(f, name, interceptor);
179 : }
180 :
181 33 : Handle<Object> PropertyCallbackArguments::CallNamedDescriptor(
182 : Handle<InterceptorInfo> interceptor, Handle<Name> name) {
183 : DCHECK_NAME_COMPATIBLE(interceptor, name);
184 33 : Isolate* isolate = this->isolate();
185 : RuntimeCallTimerScope timer(isolate,
186 33 : RuntimeCallCounterId::kNamedDescriptorCallback);
187 33 : LOG(isolate,
188 : ApiNamedPropertyAccess("interceptor-named-descriptor", holder(), *name));
189 : GenericNamedPropertyDescriptorCallback f =
190 : ToCData<GenericNamedPropertyDescriptorCallback>(
191 33 : interceptor->descriptor());
192 66 : return BasicCallNamedGetterCallback(f, name, interceptor);
193 : }
194 :
195 897309 : Handle<Object> PropertyCallbackArguments::BasicCallNamedGetterCallback(
196 : GenericNamedPropertyGetterCallback f, Handle<Name> name,
197 : Handle<Object> info, Handle<Object> receiver) {
198 : DCHECK(!name->IsPrivate());
199 897526 : Isolate* isolate = this->isolate();
200 1794791 : PREPARE_CALLBACK_INFO(isolate, f, Handle<Object>, v8::Value, info, receiver,
201 : Getter);
202 897264 : f(v8::Utils::ToLocal(name), callback_info);
203 1794528 : return GetReturnValue<Object>(isolate);
204 : }
205 :
206 667166 : Handle<Object> PropertyCallbackArguments::CallNamedSetter(
207 : Handle<InterceptorInfo> interceptor, Handle<Name> name,
208 : Handle<Object> value) {
209 : DCHECK_NAME_COMPATIBLE(interceptor, name);
210 : GenericNamedPropertySetterCallback f =
211 667166 : ToCData<GenericNamedPropertySetterCallback>(interceptor->setter());
212 1334332 : Isolate* isolate = this->isolate();
213 : RuntimeCallTimerScope timer(isolate,
214 667166 : RuntimeCallCounterId::kNamedSetterCallback);
215 1334332 : PREPARE_CALLBACK_INFO_FAIL_SIDE_EFFECT_CHECK(isolate, f, Handle<Object>,
216 : v8::Value);
217 667166 : LOG(isolate,
218 : ApiNamedPropertyAccess("interceptor-named-set", holder(), *name));
219 667166 : f(v8::Utils::ToLocal(name), v8::Utils::ToLocal(value), callback_info);
220 667166 : return GetReturnValue<Object>(isolate);
221 : }
222 :
223 63 : Handle<Object> PropertyCallbackArguments::CallNamedDefiner(
224 : Handle<InterceptorInfo> interceptor, Handle<Name> name,
225 : const v8::PropertyDescriptor& desc) {
226 : DCHECK_NAME_COMPATIBLE(interceptor, name);
227 126 : Isolate* isolate = this->isolate();
228 : RuntimeCallTimerScope timer(isolate,
229 63 : RuntimeCallCounterId::kNamedDefinerCallback);
230 : GenericNamedPropertyDefinerCallback f =
231 63 : ToCData<GenericNamedPropertyDefinerCallback>(interceptor->definer());
232 126 : PREPARE_CALLBACK_INFO_FAIL_SIDE_EFFECT_CHECK(isolate, f, Handle<Object>,
233 : v8::Value);
234 63 : LOG(isolate,
235 : ApiNamedPropertyAccess("interceptor-named-define", holder(), *name));
236 63 : f(v8::Utils::ToLocal(name), desc, callback_info);
237 63 : return GetReturnValue<Object>(isolate);
238 : }
239 :
240 65669 : Handle<Object> PropertyCallbackArguments::CallIndexedSetter(
241 : Handle<InterceptorInfo> interceptor, uint32_t index, Handle<Object> value) {
242 : DCHECK(!interceptor->is_named());
243 131338 : Isolate* isolate = this->isolate();
244 : RuntimeCallTimerScope timer(isolate,
245 65669 : RuntimeCallCounterId::kIndexedSetterCallback);
246 : IndexedPropertySetterCallback f =
247 65669 : ToCData<IndexedPropertySetterCallback>(interceptor->setter());
248 131338 : PREPARE_CALLBACK_INFO_FAIL_SIDE_EFFECT_CHECK(isolate, f, Handle<Object>,
249 : v8::Value);
250 65669 : LOG(isolate,
251 : ApiIndexedPropertyAccess("interceptor-indexed-set", holder(), index));
252 65669 : f(index, v8::Utils::ToLocal(value), callback_info);
253 65669 : return GetReturnValue<Object>(isolate);
254 : }
255 :
256 24 : Handle<Object> PropertyCallbackArguments::CallIndexedDefiner(
257 : Handle<InterceptorInfo> interceptor, uint32_t index,
258 : const v8::PropertyDescriptor& desc) {
259 : DCHECK(!interceptor->is_named());
260 48 : Isolate* isolate = this->isolate();
261 : RuntimeCallTimerScope timer(isolate,
262 24 : RuntimeCallCounterId::kIndexedDefinerCallback);
263 : IndexedPropertyDefinerCallback f =
264 24 : ToCData<IndexedPropertyDefinerCallback>(interceptor->definer());
265 48 : PREPARE_CALLBACK_INFO_FAIL_SIDE_EFFECT_CHECK(isolate, f, Handle<Object>,
266 : v8::Value);
267 24 : LOG(isolate,
268 : ApiIndexedPropertyAccess("interceptor-indexed-define", holder(), index));
269 24 : f(index, desc, callback_info);
270 24 : return GetReturnValue<Object>(isolate);
271 : }
272 :
273 244791 : Handle<Object> PropertyCallbackArguments::CallIndexedGetter(
274 : Handle<InterceptorInfo> interceptor, uint32_t index) {
275 : DCHECK(!interceptor->is_named());
276 244791 : Isolate* isolate = this->isolate();
277 : RuntimeCallTimerScope timer(isolate,
278 244791 : RuntimeCallCounterId::kNamedGetterCallback);
279 244791 : LOG(isolate,
280 : ApiIndexedPropertyAccess("interceptor-indexed-getter", holder(), index));
281 : IndexedPropertyGetterCallback f =
282 244791 : ToCData<IndexedPropertyGetterCallback>(interceptor->getter());
283 489582 : return BasicCallIndexedGetterCallback(f, index, interceptor);
284 : }
285 :
286 12 : Handle<Object> PropertyCallbackArguments::CallIndexedDescriptor(
287 : Handle<InterceptorInfo> interceptor, uint32_t index) {
288 : DCHECK(!interceptor->is_named());
289 12 : Isolate* isolate = this->isolate();
290 : RuntimeCallTimerScope timer(isolate,
291 12 : RuntimeCallCounterId::kIndexedDescriptorCallback);
292 12 : LOG(isolate, ApiIndexedPropertyAccess("interceptor-indexed-descriptor",
293 : holder(), index));
294 : IndexedPropertyDescriptorCallback f =
295 12 : ToCData<IndexedPropertyDescriptorCallback>(interceptor->descriptor());
296 24 : return BasicCallIndexedGetterCallback(f, index, interceptor);
297 : }
298 :
299 244803 : Handle<Object> PropertyCallbackArguments::BasicCallIndexedGetterCallback(
300 : IndexedPropertyGetterCallback f, uint32_t index, Handle<Object> info) {
301 244803 : Isolate* isolate = this->isolate();
302 : Handle<Object> receiver_check_unsupported;
303 489606 : PREPARE_CALLBACK_INFO(isolate, f, Handle<Object>, v8::Value, info,
304 : receiver_check_unsupported, Getter);
305 244803 : f(index, callback_info);
306 489606 : return GetReturnValue<Object>(isolate);
307 : }
308 :
309 475 : Handle<JSObject> PropertyCallbackArguments::CallPropertyEnumerator(
310 : Handle<InterceptorInfo> interceptor) {
311 : // For now there is a single enumerator for indexed and named properties.
312 : IndexedPropertyEnumeratorCallback f =
313 475 : v8::ToCData<IndexedPropertyEnumeratorCallback>(interceptor->enumerator());
314 : // TODO(cbruni): assert same type for indexed and named callback.
315 487 : Isolate* isolate = this->isolate();
316 : Handle<Object> receiver_check_unsupported;
317 956 : PREPARE_CALLBACK_INFO(isolate, f, Handle<JSObject>, v8::Array, interceptor,
318 : receiver_check_unsupported, NotAccessor);
319 469 : f(callback_info);
320 938 : return GetReturnValue<JSObject>(isolate);
321 : }
322 :
323 : // -------------------------------------------------------------------------
324 : // Accessors
325 :
326 642126 : Handle<Object> PropertyCallbackArguments::CallAccessorGetter(
327 : Handle<AccessorInfo> info, Handle<Name> name) {
328 642127 : Isolate* isolate = this->isolate();
329 : RuntimeCallTimerScope timer(isolate,
330 642126 : RuntimeCallCounterId::kAccessorGetterCallback);
331 642127 : LOG(isolate, ApiNamedPropertyAccess("accessor-getter", holder(), *name));
332 : AccessorNameGetterCallback f =
333 642127 : ToCData<AccessorNameGetterCallback>(info->getter());
334 : return BasicCallNamedGetterCallback(f, name, info,
335 1284254 : handle(receiver(), isolate));
336 : }
337 :
338 743588 : Handle<Object> PropertyCallbackArguments::CallAccessorSetter(
339 : Handle<AccessorInfo> accessor_info, Handle<Name> name,
340 : Handle<Object> value) {
341 1487217 : Isolate* isolate = this->isolate();
342 : RuntimeCallTimerScope timer(isolate,
343 743588 : RuntimeCallCounterId::kAccessorSetterCallback);
344 : AccessorNameSetterCallback f =
345 743588 : ToCData<AccessorNameSetterCallback>(accessor_info->setter());
346 1487217 : PREPARE_CALLBACK_INFO(isolate, f, Handle<Object>, void, accessor_info,
347 : handle(receiver(), isolate), Setter);
348 743588 : LOG(isolate, ApiNamedPropertyAccess("accessor-setter", holder(), *name));
349 743588 : f(v8::Utils::ToLocal(name), v8::Utils::ToLocal(value), callback_info);
350 743588 : return GetReturnValue<Object>(isolate);
351 : }
352 :
353 : #undef PREPARE_CALLBACK_INFO
354 : #undef PREPARE_CALLBACK_INFO_FAIL_SIDE_EFFECT_CHECK
355 :
356 : } // namespace internal
357 : } // namespace v8
358 :
359 : #endif // V8_API_ARGUMENTS_INL_H_
|