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