blob: 45717b50a7bf6af607ac25a67023c167514166e3 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005#include "src/ic/call-optimization.h"
6
7
8namespace v8 {
9namespace internal {
10
11CallOptimization::CallOptimization(Handle<JSFunction> function) {
12 Initialize(function);
13}
14
15
16Handle<JSObject> CallOptimization::LookupHolderOfExpectedType(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017 Handle<Map> object_map, HolderLookup* holder_lookup,
18 int* holder_depth_in_prototype_chain) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019 DCHECK(is_simple_api_call());
20 if (!object_map->IsJSObjectMap()) {
21 *holder_lookup = kHolderNotFound;
22 return Handle<JSObject>::null();
23 }
24 if (expected_receiver_type_.is_null() ||
25 expected_receiver_type_->IsTemplateFor(*object_map)) {
26 *holder_lookup = kHolderIsReceiver;
27 return Handle<JSObject>::null();
28 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000029 for (int depth = 1; true; depth++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000030 if (!object_map->prototype()->IsJSObject()) break;
31 Handle<JSObject> prototype(JSObject::cast(object_map->prototype()));
32 if (!prototype->map()->is_hidden_prototype()) break;
33 object_map = handle(prototype->map());
34 if (expected_receiver_type_->IsTemplateFor(*object_map)) {
35 *holder_lookup = kHolderFound;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000036 if (holder_depth_in_prototype_chain != NULL) {
37 *holder_depth_in_prototype_chain = depth;
38 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000039 return prototype;
40 }
41 }
42 *holder_lookup = kHolderNotFound;
43 return Handle<JSObject>::null();
44}
45
46
47bool CallOptimization::IsCompatibleReceiver(Handle<Object> receiver,
48 Handle<JSObject> holder) const {
49 DCHECK(is_simple_api_call());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000050 if (!receiver->IsHeapObject()) return false;
51 Handle<Map> map(HeapObject::cast(*receiver)->map());
52 return IsCompatibleReceiverMap(map, holder);
53}
54
55
56bool CallOptimization::IsCompatibleReceiverMap(Handle<Map> map,
57 Handle<JSObject> holder) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000058 HolderLookup holder_lookup;
59 Handle<JSObject> api_holder = LookupHolderOfExpectedType(map, &holder_lookup);
60 switch (holder_lookup) {
61 case kHolderNotFound:
62 return false;
63 case kHolderIsReceiver:
64 return true;
65 case kHolderFound:
66 if (api_holder.is_identical_to(holder)) return true;
67 // Check if holder is in prototype chain of api_holder.
68 {
69 JSObject* object = *api_holder;
70 while (true) {
71 Object* prototype = object->map()->prototype();
72 if (!prototype->IsJSObject()) return false;
73 if (prototype == *holder) return true;
74 object = JSObject::cast(prototype);
75 }
76 }
77 break;
78 }
79 UNREACHABLE();
80 return false;
81}
82
83
84void CallOptimization::Initialize(Handle<JSFunction> function) {
85 constant_function_ = Handle<JSFunction>::null();
86 is_simple_api_call_ = false;
87 expected_receiver_type_ = Handle<FunctionTemplateInfo>::null();
88 api_call_info_ = Handle<CallHandlerInfo>::null();
89
90 if (function.is_null() || !function->is_compiled()) return;
91
92 constant_function_ = function;
93 AnalyzePossibleApiFunction(function);
94}
95
96
97void CallOptimization::AnalyzePossibleApiFunction(Handle<JSFunction> function) {
98 if (!function->shared()->IsApiFunction()) return;
99 Handle<FunctionTemplateInfo> info(function->shared()->get_api_func_data());
100
101 // Require a C++ callback.
102 if (info->call_code()->IsUndefined()) return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000103 api_call_info_ = handle(CallHandlerInfo::cast(info->call_code()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000104
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000105 if (!info->signature()->IsUndefined()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000106 expected_receiver_type_ =
107 handle(FunctionTemplateInfo::cast(info->signature()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000108 }
109
110 is_simple_api_call_ = true;
111}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000112} // namespace internal
113} // namespace v8