LCOV - code coverage report
Current view: top level - src/ic - call-optimization.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 44 46 95.7 %
Date: 2017-10-20 Functions: 7 7 100.0 %

          Line data    Source code
       1             : // Copyright 2014 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             : #include "src/ic/call-optimization.h"
       6             : #include "src/objects-inl.h"
       7             : 
       8             : namespace v8 {
       9             : namespace internal {
      10             : 
      11      374792 : CallOptimization::CallOptimization(Handle<Object> function) {
      12             :   constant_function_ = Handle<JSFunction>::null();
      13      374792 :   is_simple_api_call_ = false;
      14             :   expected_receiver_type_ = Handle<FunctionTemplateInfo>::null();
      15             :   api_call_info_ = Handle<CallHandlerInfo>::null();
      16      374792 :   if (function->IsJSFunction()) {
      17      360541 :     Initialize(Handle<JSFunction>::cast(function));
      18       14251 :   } else if (function->IsFunctionTemplateInfo()) {
      19       12116 :     Initialize(Handle<FunctionTemplateInfo>::cast(function));
      20             :   }
      21      374792 : }
      22             : 
      23       18906 : Handle<JSObject> CallOptimization::LookupHolderOfExpectedType(
      24             :     Handle<Map> object_map, HolderLookup* holder_lookup) const {
      25             :   DCHECK(is_simple_api_call());
      26       18906 :   if (!object_map->IsJSObjectMap()) {
      27           0 :     *holder_lookup = kHolderNotFound;
      28             :     return Handle<JSObject>::null();
      29             :   }
      30       19548 :   if (expected_receiver_type_.is_null() ||
      31         642 :       expected_receiver_type_->IsTemplateFor(*object_map)) {
      32       18690 :     *holder_lookup = kHolderIsReceiver;
      33             :     return Handle<JSObject>::null();
      34             :   }
      35         216 :   if (object_map->has_hidden_prototype()) {
      36             :     Handle<JSObject> prototype(JSObject::cast(object_map->prototype()));
      37             :     object_map = handle(prototype->map());
      38          35 :     if (expected_receiver_type_->IsTemplateFor(*object_map)) {
      39          32 :       *holder_lookup = kHolderFound;
      40          32 :       return prototype;
      41             :     }
      42             :   }
      43         184 :   *holder_lookup = kHolderNotFound;
      44             :   return Handle<JSObject>::null();
      45             : }
      46             : 
      47             : 
      48         322 : bool CallOptimization::IsCompatibleReceiver(Handle<Object> receiver,
      49             :                                             Handle<JSObject> holder) const {
      50             :   DCHECK(is_simple_api_call());
      51         322 :   if (!receiver->IsHeapObject()) return false;
      52             :   Handle<Map> map(HeapObject::cast(*receiver)->map());
      53         322 :   return IsCompatibleReceiverMap(map, holder);
      54             : }
      55             : 
      56             : 
      57        3903 : bool CallOptimization::IsCompatibleReceiverMap(Handle<Map> map,
      58             :                                                Handle<JSObject> holder) const {
      59             :   HolderLookup holder_lookup;
      60        3903 :   Handle<JSObject> api_holder = LookupHolderOfExpectedType(map, &holder_lookup);
      61        3903 :   switch (holder_lookup) {
      62             :     case kHolderNotFound:
      63             :       return false;
      64             :     case kHolderIsReceiver:
      65        3787 :       return true;
      66             :     case kHolderFound:
      67          15 :       if (api_holder.is_identical_to(holder)) return true;
      68             :       // Check if holder is in prototype chain of api_holder.
      69             :       {
      70             :         JSObject* object = *api_holder;
      71             :         while (true) {
      72             :           Object* prototype = object->map()->prototype();
      73          10 :           if (!prototype->IsJSObject()) return false;
      74          10 :           if (prototype == *holder) return true;
      75             :           object = JSObject::cast(prototype);
      76             :         }
      77             :       }
      78             :       break;
      79             :   }
      80           0 :   UNREACHABLE();
      81             : }
      82             : 
      83       12116 : void CallOptimization::Initialize(
      84             :     Handle<FunctionTemplateInfo> function_template_info) {
      85             :   Isolate* isolate = function_template_info->GetIsolate();
      86       24232 :   if (function_template_info->call_code()->IsUndefined(isolate)) return;
      87             :   api_call_info_ =
      88       12114 :       handle(CallHandlerInfo::cast(function_template_info->call_code()));
      89             : 
      90       12114 :   if (!function_template_info->signature()->IsUndefined(isolate)) {
      91             :     expected_receiver_type_ =
      92         529 :         handle(FunctionTemplateInfo::cast(function_template_info->signature()));
      93             :   }
      94       12114 :   is_simple_api_call_ = true;
      95             : }
      96             : 
      97      360541 : void CallOptimization::Initialize(Handle<JSFunction> function) {
      98     1081623 :   if (function.is_null() || !function->is_compiled()) return;
      99             : 
     100      349425 :   constant_function_ = function;
     101      349425 :   AnalyzePossibleApiFunction(function);
     102             : }
     103             : 
     104             : 
     105      349425 : void CallOptimization::AnalyzePossibleApiFunction(Handle<JSFunction> function) {
     106      349425 :   if (!function->shared()->IsApiFunction()) return;
     107             :   Isolate* isolate = function->GetIsolate();
     108             :   Handle<FunctionTemplateInfo> info(function->shared()->get_api_func_data(),
     109             :                                     isolate);
     110             : 
     111             :   // Require a C++ callback.
     112        6812 :   if (info->call_code()->IsUndefined(isolate)) return;
     113        6792 :   api_call_info_ = handle(CallHandlerInfo::cast(info->call_code()), isolate);
     114             : 
     115        6792 :   if (!info->signature()->IsUndefined(isolate)) {
     116             :     expected_receiver_type_ =
     117         113 :         handle(FunctionTemplateInfo::cast(info->signature()), isolate);
     118             :   }
     119             : 
     120        6792 :   is_simple_api_call_ = true;
     121             : }
     122             : }  // namespace internal
     123             : }  // namespace v8

Generated by: LCOV version 1.10