5 #include "src/ic/call-optimization.h" 6 #include "src/objects-inl.h" 11 CallOptimization::CallOptimization(Isolate* isolate, Handle<Object>
function) {
12 constant_function_ = Handle<JSFunction>::null();
13 is_simple_api_call_ =
false;
14 expected_receiver_type_ = Handle<FunctionTemplateInfo>::null();
15 api_call_info_ = Handle<CallHandlerInfo>::null();
16 if (function->IsJSFunction()) {
17 Initialize(isolate, Handle<JSFunction>::cast(
function));
18 }
else if (function->IsFunctionTemplateInfo()) {
19 Initialize(isolate, Handle<FunctionTemplateInfo>::cast(
function));
23 Context CallOptimization::GetAccessorContext(Map holder_map)
const {
24 if (is_constant_call()) {
25 return constant_function_->context()->native_context();
27 JSFunction* constructor = JSFunction::cast(holder_map->GetConstructor());
28 return constructor->context()->native_context();
31 bool CallOptimization::IsCrossContextLazyAccessorPair(Context native_context,
32 Map holder_map)
const {
33 DCHECK(native_context->IsNativeContext());
34 if (is_constant_call())
return false;
35 return native_context != GetAccessorContext(holder_map);
38 Handle<JSObject> CallOptimization::LookupHolderOfExpectedType(
39 Handle<Map> object_map, HolderLookup* holder_lookup)
const {
40 DCHECK(is_simple_api_call());
41 if (!object_map->IsJSObjectMap()) {
42 *holder_lookup = kHolderNotFound;
43 return Handle<JSObject>::null();
45 if (expected_receiver_type_.is_null() ||
46 expected_receiver_type_->IsTemplateFor(*object_map)) {
47 *holder_lookup = kHolderIsReceiver;
48 return Handle<JSObject>::null();
50 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 if (expected_receiver_type_->IsTemplateFor(*object_map)) {
55 *holder_lookup = kHolderFound;
59 *holder_lookup = kHolderNotFound;
60 return Handle<JSObject>::null();
64 bool CallOptimization::IsCompatibleReceiver(Handle<Object> receiver,
65 Handle<JSObject> holder)
const {
66 DCHECK(is_simple_api_call());
67 if (!receiver->IsHeapObject())
return false;
68 Handle<Map> map(HeapObject::cast(*receiver)->map(), holder->GetIsolate());
69 return IsCompatibleReceiverMap(map, holder);
73 bool CallOptimization::IsCompatibleReceiverMap(Handle<Map> map,
74 Handle<JSObject> holder)
const {
75 HolderLookup holder_lookup;
76 Handle<JSObject> api_holder = LookupHolderOfExpectedType(map, &holder_lookup);
77 switch (holder_lookup) {
80 case kHolderIsReceiver:
83 if (api_holder.is_identical_to(holder))
return true;
86 JSObject*
object = *api_holder;
88 Object* prototype =
object->map()->prototype();
89 if (!prototype->IsJSObject())
return false;
90 if (prototype == *holder)
return true;
91 object = JSObject::cast(prototype);
99 void CallOptimization::Initialize(
100 Isolate* isolate, Handle<FunctionTemplateInfo> function_template_info) {
101 if (function_template_info->call_code()->IsUndefined(isolate))
return;
102 api_call_info_ = handle(
103 CallHandlerInfo::cast(function_template_info->call_code()), isolate);
105 if (!function_template_info->signature()->IsUndefined(isolate)) {
106 expected_receiver_type_ =
107 handle(FunctionTemplateInfo::cast(function_template_info->signature()),
110 is_simple_api_call_ =
true;
113 void CallOptimization::Initialize(Isolate* isolate,
114 Handle<JSFunction>
function) {
115 if (
function.is_null() || !function->is_compiled())
return;
117 constant_function_ =
function;
118 AnalyzePossibleApiFunction(isolate,
function);
121 void CallOptimization::AnalyzePossibleApiFunction(Isolate* isolate,
122 Handle<JSFunction>
function) {
123 if (!function->shared()->IsApiFunction())
return;
124 Handle<FunctionTemplateInfo> info(function->shared()->get_api_func_data(),
128 if (info->call_code()->IsUndefined(isolate))
return;
129 api_call_info_ = handle(CallHandlerInfo::cast(info->call_code()), isolate);
131 if (!info->signature()->IsUndefined(isolate)) {
132 expected_receiver_type_ =
133 handle(FunctionTemplateInfo::cast(info->signature()), isolate);
136 is_simple_api_call_ =
true;