LCOV - code coverage report
Current view: top level - src - api-arguments-inl.h (source / functions) Hit Total Coverage
Test: app.info Lines: 77 78 98.7 %
Date: 2019-04-18 Functions: 20 24 83.3 %

          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_

Generated by: LCOV version 1.10