LCOV - code coverage report
Current view: top level - src/ic - call-optimization.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 49 50 98.0 %
Date: 2017-04-26 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      409222 : CallOptimization::CallOptimization(Handle<Object> function) {
      12             :   constant_function_ = Handle<JSFunction>::null();
      13      409222 :   is_simple_api_call_ = false;
      14             :   expected_receiver_type_ = Handle<FunctionTemplateInfo>::null();
      15             :   api_call_info_ = Handle<CallHandlerInfo>::null();
      16      409222 :   if (function->IsJSFunction()) {
      17      399889 :     Initialize(Handle<JSFunction>::cast(function));
      18        9333 :   } else if (function->IsFunctionTemplateInfo()) {
      19        9278 :     Initialize(Handle<FunctionTemplateInfo>::cast(function));
      20             :   }
      21      409222 : }
      22             : 
      23             : 
      24       21417 : Handle<JSObject> CallOptimization::LookupHolderOfExpectedType(
      25             :     Handle<Map> object_map, HolderLookup* holder_lookup,
      26             :     int* holder_depth_in_prototype_chain) const {
      27             :   DCHECK(is_simple_api_call());
      28       21417 :   if (!object_map->IsJSObjectMap()) {
      29           1 :     *holder_lookup = kHolderNotFound;
      30             :     return Handle<JSObject>::null();
      31             :   }
      32       21676 :   if (expected_receiver_type_.is_null() ||
      33         260 :       expected_receiver_type_->IsTemplateFor(*object_map)) {
      34       21358 :     *holder_lookup = kHolderIsReceiver;
      35             :     return Handle<JSObject>::null();
      36             :   }
      37           6 :   for (int depth = 1; true; depth++) {
      38          64 :     if (!object_map->has_hidden_prototype()) break;
      39             :     Handle<JSObject> prototype(JSObject::cast(object_map->prototype()));
      40             :     object_map = handle(prototype->map());
      41          46 :     if (expected_receiver_type_->IsTemplateFor(*object_map)) {
      42          40 :       *holder_lookup = kHolderFound;
      43          40 :       if (holder_depth_in_prototype_chain != NULL) {
      44          12 :         *holder_depth_in_prototype_chain = depth;
      45             :       }
      46          40 :       return prototype;
      47             :     }
      48           6 :   }
      49          18 :   *holder_lookup = kHolderNotFound;
      50             :   return Handle<JSObject>::null();
      51             : }
      52             : 
      53             : 
      54         117 : bool CallOptimization::IsCompatibleReceiver(Handle<Object> receiver,
      55             :                                             Handle<JSObject> holder) const {
      56             :   DCHECK(is_simple_api_call());
      57         117 :   if (!receiver->IsHeapObject()) return false;
      58             :   Handle<Map> map(HeapObject::cast(*receiver)->map());
      59         117 :   return IsCompatibleReceiverMap(map, holder);
      60             : }
      61             : 
      62             : 
      63         812 : bool CallOptimization::IsCompatibleReceiverMap(Handle<Map> map,
      64             :                                                Handle<JSObject> holder) const {
      65             :   HolderLookup holder_lookup;
      66         812 :   Handle<JSObject> api_holder = LookupHolderOfExpectedType(map, &holder_lookup);
      67         812 :   switch (holder_lookup) {
      68             :     case kHolderNotFound:
      69             :       return false;
      70             :     case kHolderIsReceiver:
      71         781 :       return true;
      72             :     case kHolderFound:
      73          18 :       if (api_holder.is_identical_to(holder)) return true;
      74             :       // Check if holder is in prototype chain of api_holder.
      75             :       {
      76             :         JSObject* object = *api_holder;
      77             :         while (true) {
      78             :           Object* prototype = object->map()->prototype();
      79          12 :           if (!prototype->IsJSObject()) return false;
      80          12 :           if (prototype == *holder) return true;
      81             :           object = JSObject::cast(prototype);
      82             :         }
      83             :       }
      84             :       break;
      85             :   }
      86           0 :   UNREACHABLE();
      87             :   return false;
      88             : }
      89             : 
      90        9278 : void CallOptimization::Initialize(
      91             :     Handle<FunctionTemplateInfo> function_template_info) {
      92             :   Isolate* isolate = function_template_info->GetIsolate();
      93       18556 :   if (function_template_info->call_code()->IsUndefined(isolate)) return;
      94             :   api_call_info_ =
      95        9276 :       handle(CallHandlerInfo::cast(function_template_info->call_code()));
      96             : 
      97        9276 :   if (!function_template_info->signature()->IsUndefined(isolate)) {
      98             :     expected_receiver_type_ =
      99         132 :         handle(FunctionTemplateInfo::cast(function_template_info->signature()));
     100             :   }
     101        9276 :   is_simple_api_call_ = true;
     102             : }
     103             : 
     104      399889 : void CallOptimization::Initialize(Handle<JSFunction> function) {
     105     1199667 :   if (function.is_null() || !function->is_compiled()) return;
     106             : 
     107      316819 :   constant_function_ = function;
     108      316819 :   AnalyzePossibleApiFunction(function);
     109             : }
     110             : 
     111             : 
     112      316819 : void CallOptimization::AnalyzePossibleApiFunction(Handle<JSFunction> function) {
     113      316819 :   if (!function->shared()->IsApiFunction()) return;
     114             :   Isolate* isolate = function->GetIsolate();
     115             :   Handle<FunctionTemplateInfo> info(function->shared()->get_api_func_data(),
     116             :                                     isolate);
     117             : 
     118             :   // Require a C++ callback.
     119       12182 :   if (info->call_code()->IsUndefined(isolate)) return;
     120       12150 :   api_call_info_ = handle(CallHandlerInfo::cast(info->call_code()), isolate);
     121             : 
     122       12150 :   if (!info->signature()->IsUndefined(isolate)) {
     123             :     expected_receiver_type_ =
     124         128 :         handle(FunctionTemplateInfo::cast(info->signature()), isolate);
     125             :   }
     126             : 
     127       12150 :   is_simple_api_call_ = true;
     128             : }
     129             : }  // namespace internal
     130             : }  // namespace v8

Generated by: LCOV version 1.10