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