LCOV - code coverage report
Current view: top level - src/ic - call-optimization.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 53 55 96.4 %
Date: 2019-04-17 Functions: 10 10 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      208760 : CallOptimization::CallOptimization(Isolate* isolate, Handle<Object> function) {
      12             :   constant_function_ = Handle<JSFunction>::null();
      13      208760 :   is_simple_api_call_ = false;
      14             :   expected_receiver_type_ = Handle<FunctionTemplateInfo>::null();
      15             :   api_call_info_ = Handle<CallHandlerInfo>::null();
      16      208760 :   if (function->IsJSFunction()) {
      17      203305 :     Initialize(isolate, Handle<JSFunction>::cast(function));
      18        5455 :   } else if (function->IsFunctionTemplateInfo()) {
      19        2291 :     Initialize(isolate, Handle<FunctionTemplateInfo>::cast(function));
      20             :   }
      21      208761 : }
      22             : 
      23        4112 : Context CallOptimization::GetAccessorContext(Map holder_map) const {
      24        4112 :   if (is_constant_call()) {
      25        3509 :     return constant_function_->context()->native_context();
      26             :   }
      27         603 :   JSFunction constructor = JSFunction::cast(holder_map->GetConstructor());
      28         603 :   return constructor->context()->native_context();
      29             : }
      30             : 
      31         172 : bool CallOptimization::IsCrossContextLazyAccessorPair(Context native_context,
      32             :                                                       Map holder_map) const {
      33             :   DCHECK(native_context->IsNativeContext());
      34         172 :   if (is_constant_call()) return false;
      35         344 :   return native_context != GetAccessorContext(holder_map);
      36             : }
      37             : 
      38        9792 : Handle<JSObject> CallOptimization::LookupHolderOfExpectedType(
      39             :     Handle<Map> object_map, HolderLookup* holder_lookup) const {
      40             :   DCHECK(is_simple_api_call());
      41        9792 :   if (!object_map->IsJSObjectMap()) {
      42           0 :     *holder_lookup = kHolderNotFound;
      43             :     return Handle<JSObject>::null();
      44             :   }
      45       29376 :   if (expected_receiver_type_.is_null() ||
      46       11458 :       expected_receiver_type_->IsTemplateFor(*object_map)) {
      47        9572 :     *holder_lookup = kHolderIsReceiver;
      48             :     return Handle<JSObject>::null();
      49             :   }
      50         220 :   if (object_map->has_hidden_prototype()) {
      51             :     JSObject raw_prototype = JSObject::cast(object_map->prototype());
      52             :     Handle<JSObject> prototype(raw_prototype, raw_prototype->GetIsolate());
      53             :     object_map = handle(prototype->map(), prototype->GetIsolate());
      54          31 :     if (expected_receiver_type_->IsTemplateFor(*object_map)) {
      55          31 :       *holder_lookup = kHolderFound;
      56          31 :       return prototype;
      57             :     }
      58             :   }
      59         189 :   *holder_lookup = kHolderNotFound;
      60             :   return Handle<JSObject>::null();
      61             : }
      62             : 
      63             : 
      64         407 : bool CallOptimization::IsCompatibleReceiver(Handle<Object> receiver,
      65             :                                             Handle<JSObject> holder) const {
      66             :   DCHECK(is_simple_api_call());
      67         407 :   if (!receiver->IsHeapObject()) return false;
      68             :   Handle<Map> map(HeapObject::cast(*receiver)->map(), holder->GetIsolate());
      69         407 :   return IsCompatibleReceiverMap(map, holder);
      70             : }
      71             : 
      72             : 
      73        4057 : bool CallOptimization::IsCompatibleReceiverMap(Handle<Map> map,
      74             :                                                Handle<JSObject> holder) const {
      75             :   HolderLookup holder_lookup;
      76        4057 :   Handle<JSObject> api_holder = LookupHolderOfExpectedType(map, &holder_lookup);
      77        4058 :   switch (holder_lookup) {
      78             :     case kHolderNotFound:
      79             :       return false;
      80             :     case kHolderIsReceiver:
      81        3942 :       return true;
      82             :     case kHolderFound:
      83          15 :       if (api_holder.is_identical_to(holder)) return true;
      84             :       // Check if holder is in prototype chain of api_holder.
      85             :       {
      86             :         JSObject object = *api_holder;
      87             :         while (true) {
      88             :           Object prototype = object->map()->prototype();
      89          10 :           if (!prototype->IsJSObject()) return false;
      90          10 :           if (prototype == *holder) return true;
      91             :           object = JSObject::cast(prototype);
      92             :         }
      93             :       }
      94             :       break;
      95             :   }
      96           0 :   UNREACHABLE();
      97             : }
      98             : 
      99        2291 : void CallOptimization::Initialize(
     100             :     Isolate* isolate, Handle<FunctionTemplateInfo> function_template_info) {
     101        2291 :   if (function_template_info->call_code()->IsUndefined(isolate)) return;
     102             :   api_call_info_ = handle(
     103        2291 :       CallHandlerInfo::cast(function_template_info->call_code()), isolate);
     104             : 
     105        2291 :   if (!function_template_info->signature()->IsUndefined(isolate)) {
     106             :     expected_receiver_type_ =
     107             :         handle(FunctionTemplateInfo::cast(function_template_info->signature()),
     108         571 :                isolate);
     109             :   }
     110        2291 :   is_simple_api_call_ = true;
     111             : }
     112             : 
     113      203304 : void CallOptimization::Initialize(Isolate* isolate,
     114             :                                   Handle<JSFunction> function) {
     115      406609 :   if (function.is_null() || !function->is_compiled()) return;
     116             : 
     117      194629 :   constant_function_ = function;
     118      194629 :   AnalyzePossibleApiFunction(isolate, function);
     119             : }
     120             : 
     121      194629 : void CallOptimization::AnalyzePossibleApiFunction(Isolate* isolate,
     122             :                                                   Handle<JSFunction> function) {
     123      194629 :   if (!function->shared()->IsApiFunction()) return;
     124             :   Handle<FunctionTemplateInfo> info(function->shared()->get_api_func_data(),
     125             :                                     isolate);
     126             : 
     127             :   // Require a C++ callback.
     128        3592 :   if (info->call_code()->IsUndefined(isolate)) return;
     129        3573 :   api_call_info_ = handle(CallHandlerInfo::cast(info->call_code()), isolate);
     130             : 
     131        3573 :   if (!info->signature()->IsUndefined(isolate)) {
     132             :     expected_receiver_type_ =
     133          83 :         handle(FunctionTemplateInfo::cast(info->signature()), isolate);
     134             :   }
     135             : 
     136        3573 :   is_simple_api_call_ = true;
     137             : }
     138             : }  // namespace internal
     139      121996 : }  // namespace v8

Generated by: LCOV version 1.10