11cb0ef41Sopenharmony_ci// Copyright 2014 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#include "src/ic/call-optimization.h"
61cb0ef41Sopenharmony_ci#include "src/objects/objects-inl.h"
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_cinamespace v8 {
91cb0ef41Sopenharmony_cinamespace internal {
101cb0ef41Sopenharmony_ci
111cb0ef41Sopenharmony_citemplate <class IsolateT>
121cb0ef41Sopenharmony_ciCallOptimization::CallOptimization(IsolateT* isolate, Handle<Object> function) {
131cb0ef41Sopenharmony_ci  if (function->IsJSFunction()) {
141cb0ef41Sopenharmony_ci    Initialize(isolate, Handle<JSFunction>::cast(function));
151cb0ef41Sopenharmony_ci  } else if (function->IsFunctionTemplateInfo()) {
161cb0ef41Sopenharmony_ci    Initialize(isolate, Handle<FunctionTemplateInfo>::cast(function));
171cb0ef41Sopenharmony_ci  }
181cb0ef41Sopenharmony_ci}
191cb0ef41Sopenharmony_ci
201cb0ef41Sopenharmony_ci// Instantiations.
211cb0ef41Sopenharmony_citemplate CallOptimization::CallOptimization(Isolate* isolate,
221cb0ef41Sopenharmony_ci                                            Handle<Object> function);
231cb0ef41Sopenharmony_citemplate CallOptimization::CallOptimization(LocalIsolate* isolate,
241cb0ef41Sopenharmony_ci                                            Handle<Object> function);
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_ciContext CallOptimization::GetAccessorContext(Map holder_map) const {
271cb0ef41Sopenharmony_ci  if (is_constant_call()) {
281cb0ef41Sopenharmony_ci    return constant_function_->native_context();
291cb0ef41Sopenharmony_ci  }
301cb0ef41Sopenharmony_ci  JSFunction constructor = JSFunction::cast(holder_map.GetConstructor());
311cb0ef41Sopenharmony_ci  return constructor.native_context();
321cb0ef41Sopenharmony_ci}
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_cibool CallOptimization::IsCrossContextLazyAccessorPair(Context native_context,
351cb0ef41Sopenharmony_ci                                                      Map holder_map) const {
361cb0ef41Sopenharmony_ci  DCHECK(native_context.IsNativeContext());
371cb0ef41Sopenharmony_ci  if (is_constant_call()) return false;
381cb0ef41Sopenharmony_ci  return native_context != GetAccessorContext(holder_map);
391cb0ef41Sopenharmony_ci}
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_citemplate <class IsolateT>
421cb0ef41Sopenharmony_ciHandle<JSObject> CallOptimization::LookupHolderOfExpectedType(
431cb0ef41Sopenharmony_ci    IsolateT* isolate, Handle<Map> object_map,
441cb0ef41Sopenharmony_ci    HolderLookup* holder_lookup) const {
451cb0ef41Sopenharmony_ci  DCHECK(is_simple_api_call());
461cb0ef41Sopenharmony_ci  if (!object_map->IsJSObjectMap()) {
471cb0ef41Sopenharmony_ci    *holder_lookup = kHolderNotFound;
481cb0ef41Sopenharmony_ci    return Handle<JSObject>::null();
491cb0ef41Sopenharmony_ci  }
501cb0ef41Sopenharmony_ci  if (expected_receiver_type_.is_null() ||
511cb0ef41Sopenharmony_ci      expected_receiver_type_->IsTemplateFor(*object_map)) {
521cb0ef41Sopenharmony_ci    *holder_lookup = kHolderIsReceiver;
531cb0ef41Sopenharmony_ci    return Handle<JSObject>::null();
541cb0ef41Sopenharmony_ci  }
551cb0ef41Sopenharmony_ci  if (object_map->IsJSGlobalProxyMap() && !object_map->prototype().IsNull()) {
561cb0ef41Sopenharmony_ci    JSObject raw_prototype = JSObject::cast(object_map->prototype());
571cb0ef41Sopenharmony_ci    Handle<JSObject> prototype(raw_prototype, isolate);
581cb0ef41Sopenharmony_ci    object_map = handle(prototype->map(), isolate);
591cb0ef41Sopenharmony_ci    if (expected_receiver_type_->IsTemplateFor(*object_map)) {
601cb0ef41Sopenharmony_ci      *holder_lookup = kHolderFound;
611cb0ef41Sopenharmony_ci      return prototype;
621cb0ef41Sopenharmony_ci    }
631cb0ef41Sopenharmony_ci  }
641cb0ef41Sopenharmony_ci  *holder_lookup = kHolderNotFound;
651cb0ef41Sopenharmony_ci  return Handle<JSObject>::null();
661cb0ef41Sopenharmony_ci}
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_ci// Instantiations.
691cb0ef41Sopenharmony_citemplate Handle<JSObject> CallOptimization::LookupHolderOfExpectedType(
701cb0ef41Sopenharmony_ci    Isolate* isolate, Handle<Map> object_map,
711cb0ef41Sopenharmony_ci    HolderLookup* holder_lookup) const;
721cb0ef41Sopenharmony_citemplate Handle<JSObject> CallOptimization::LookupHolderOfExpectedType(
731cb0ef41Sopenharmony_ci    LocalIsolate* isolate, Handle<Map> object_map,
741cb0ef41Sopenharmony_ci    HolderLookup* holder_lookup) const;
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_cibool CallOptimization::IsCompatibleReceiverMap(
771cb0ef41Sopenharmony_ci    Handle<JSObject> api_holder, Handle<JSObject> holder,
781cb0ef41Sopenharmony_ci    HolderLookup holder_lookup) const {
791cb0ef41Sopenharmony_ci  DCHECK(is_simple_api_call());
801cb0ef41Sopenharmony_ci  switch (holder_lookup) {
811cb0ef41Sopenharmony_ci    case kHolderNotFound:
821cb0ef41Sopenharmony_ci      return false;
831cb0ef41Sopenharmony_ci    case kHolderIsReceiver:
841cb0ef41Sopenharmony_ci      return true;
851cb0ef41Sopenharmony_ci    case kHolderFound:
861cb0ef41Sopenharmony_ci      if (api_holder.is_identical_to(holder)) return true;
871cb0ef41Sopenharmony_ci      // Check if holder is in prototype chain of api_holder.
881cb0ef41Sopenharmony_ci      {
891cb0ef41Sopenharmony_ci        JSObject object = *api_holder;
901cb0ef41Sopenharmony_ci        while (true) {
911cb0ef41Sopenharmony_ci          Object prototype = object.map().prototype();
921cb0ef41Sopenharmony_ci          if (!prototype.IsJSObject()) return false;
931cb0ef41Sopenharmony_ci          if (prototype == *holder) return true;
941cb0ef41Sopenharmony_ci          object = JSObject::cast(prototype);
951cb0ef41Sopenharmony_ci        }
961cb0ef41Sopenharmony_ci      }
971cb0ef41Sopenharmony_ci  }
981cb0ef41Sopenharmony_ci  UNREACHABLE();
991cb0ef41Sopenharmony_ci}
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_citemplate <class IsolateT>
1021cb0ef41Sopenharmony_civoid CallOptimization::Initialize(
1031cb0ef41Sopenharmony_ci    IsolateT* isolate, Handle<FunctionTemplateInfo> function_template_info) {
1041cb0ef41Sopenharmony_ci  HeapObject call_code = function_template_info->call_code(kAcquireLoad);
1051cb0ef41Sopenharmony_ci  if (call_code.IsUndefined(isolate)) return;
1061cb0ef41Sopenharmony_ci  api_call_info_ = handle(CallHandlerInfo::cast(call_code), isolate);
1071cb0ef41Sopenharmony_ci
1081cb0ef41Sopenharmony_ci  HeapObject signature = function_template_info->signature();
1091cb0ef41Sopenharmony_ci  if (!signature.IsUndefined(isolate)) {
1101cb0ef41Sopenharmony_ci    expected_receiver_type_ =
1111cb0ef41Sopenharmony_ci        handle(FunctionTemplateInfo::cast(signature), isolate);
1121cb0ef41Sopenharmony_ci  }
1131cb0ef41Sopenharmony_ci  is_simple_api_call_ = true;
1141cb0ef41Sopenharmony_ci  accept_any_receiver_ = function_template_info->accept_any_receiver();
1151cb0ef41Sopenharmony_ci}
1161cb0ef41Sopenharmony_ci
1171cb0ef41Sopenharmony_citemplate <class IsolateT>
1181cb0ef41Sopenharmony_civoid CallOptimization::Initialize(IsolateT* isolate,
1191cb0ef41Sopenharmony_ci                                  Handle<JSFunction> function) {
1201cb0ef41Sopenharmony_ci  if (function.is_null() || !function->is_compiled()) return;
1211cb0ef41Sopenharmony_ci
1221cb0ef41Sopenharmony_ci  constant_function_ = function;
1231cb0ef41Sopenharmony_ci  AnalyzePossibleApiFunction(isolate, function);
1241cb0ef41Sopenharmony_ci}
1251cb0ef41Sopenharmony_ci
1261cb0ef41Sopenharmony_citemplate <class IsolateT>
1271cb0ef41Sopenharmony_civoid CallOptimization::AnalyzePossibleApiFunction(IsolateT* isolate,
1281cb0ef41Sopenharmony_ci                                                  Handle<JSFunction> function) {
1291cb0ef41Sopenharmony_ci  if (!function->shared().IsApiFunction()) return;
1301cb0ef41Sopenharmony_ci  Handle<FunctionTemplateInfo> info(function->shared().get_api_func_data(),
1311cb0ef41Sopenharmony_ci                                    isolate);
1321cb0ef41Sopenharmony_ci
1331cb0ef41Sopenharmony_ci  // Require a C++ callback.
1341cb0ef41Sopenharmony_ci  HeapObject call_code = info->call_code(kAcquireLoad);
1351cb0ef41Sopenharmony_ci  if (call_code.IsUndefined(isolate)) return;
1361cb0ef41Sopenharmony_ci  api_call_info_ = handle(CallHandlerInfo::cast(call_code), isolate);
1371cb0ef41Sopenharmony_ci
1381cb0ef41Sopenharmony_ci  if (!info->signature().IsUndefined(isolate)) {
1391cb0ef41Sopenharmony_ci    expected_receiver_type_ =
1401cb0ef41Sopenharmony_ci        handle(FunctionTemplateInfo::cast(info->signature()), isolate);
1411cb0ef41Sopenharmony_ci  }
1421cb0ef41Sopenharmony_ci
1431cb0ef41Sopenharmony_ci  is_simple_api_call_ = true;
1441cb0ef41Sopenharmony_ci  accept_any_receiver_ = info->accept_any_receiver();
1451cb0ef41Sopenharmony_ci}
1461cb0ef41Sopenharmony_ci}  // namespace internal
1471cb0ef41Sopenharmony_ci}  // namespace v8
148