V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
call-optimization.cc
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 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));
20  }
21 }
22 
23 Context CallOptimization::GetAccessorContext(Map holder_map) const {
24  if (is_constant_call()) {
25  return constant_function_->context()->native_context();
26  }
27  JSFunction* constructor = JSFunction::cast(holder_map->GetConstructor());
28  return constructor->context()->native_context();
29 }
30 
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);
36 }
37 
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();
44  }
45  if (expected_receiver_type_.is_null() ||
46  expected_receiver_type_->IsTemplateFor(*object_map)) {
47  *holder_lookup = kHolderIsReceiver;
48  return Handle<JSObject>::null();
49  }
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;
56  return prototype;
57  }
58  }
59  *holder_lookup = kHolderNotFound;
60  return Handle<JSObject>::null();
61 }
62 
63 
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);
70 }
71 
72 
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) {
78  case kHolderNotFound:
79  return false;
80  case kHolderIsReceiver:
81  return true;
82  case kHolderFound:
83  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  if (!prototype->IsJSObject()) return false;
90  if (prototype == *holder) return true;
91  object = JSObject::cast(prototype);
92  }
93  }
94  break;
95  }
96  UNREACHABLE();
97 }
98 
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);
104 
105  if (!function_template_info->signature()->IsUndefined(isolate)) {
106  expected_receiver_type_ =
107  handle(FunctionTemplateInfo::cast(function_template_info->signature()),
108  isolate);
109  }
110  is_simple_api_call_ = true;
111 }
112 
113 void CallOptimization::Initialize(Isolate* isolate,
114  Handle<JSFunction> function) {
115  if (function.is_null() || !function->is_compiled()) return;
116 
117  constant_function_ = function;
118  AnalyzePossibleApiFunction(isolate, function);
119 }
120 
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(),
125  isolate);
126 
127  // Require a C++ callback.
128  if (info->call_code()->IsUndefined(isolate)) return;
129  api_call_info_ = handle(CallHandlerInfo::cast(info->call_code()), isolate);
130 
131  if (!info->signature()->IsUndefined(isolate)) {
132  expected_receiver_type_ =
133  handle(FunctionTemplateInfo::cast(info->signature()), isolate);
134  }
135 
136  is_simple_api_call_ = true;
137 }
138 } // namespace internal
139 } // namespace v8
Definition: libplatform.h:13