• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/v8.h"
6 
7 #include "src/ic/call-optimization.h"
8 
9 
10 namespace v8 {
11 namespace internal {
12 
CallOptimization(Handle<JSFunction> function)13 CallOptimization::CallOptimization(Handle<JSFunction> function) {
14   Initialize(function);
15 }
16 
17 
LookupHolderOfExpectedType(Handle<Map> object_map,HolderLookup * holder_lookup) const18 Handle<JSObject> CallOptimization::LookupHolderOfExpectedType(
19     Handle<Map> object_map, HolderLookup* holder_lookup) const {
20   DCHECK(is_simple_api_call());
21   if (!object_map->IsJSObjectMap()) {
22     *holder_lookup = kHolderNotFound;
23     return Handle<JSObject>::null();
24   }
25   if (expected_receiver_type_.is_null() ||
26       expected_receiver_type_->IsTemplateFor(*object_map)) {
27     *holder_lookup = kHolderIsReceiver;
28     return Handle<JSObject>::null();
29   }
30   while (true) {
31     if (!object_map->prototype()->IsJSObject()) break;
32     Handle<JSObject> prototype(JSObject::cast(object_map->prototype()));
33     if (!prototype->map()->is_hidden_prototype()) break;
34     object_map = handle(prototype->map());
35     if (expected_receiver_type_->IsTemplateFor(*object_map)) {
36       *holder_lookup = kHolderFound;
37       return prototype;
38     }
39   }
40   *holder_lookup = kHolderNotFound;
41   return Handle<JSObject>::null();
42 }
43 
44 
IsCompatibleReceiver(Handle<Object> receiver,Handle<JSObject> holder) const45 bool CallOptimization::IsCompatibleReceiver(Handle<Object> receiver,
46                                             Handle<JSObject> holder) const {
47   DCHECK(is_simple_api_call());
48   if (!receiver->IsJSObject()) return false;
49   Handle<Map> map(JSObject::cast(*receiver)->map());
50   HolderLookup holder_lookup;
51   Handle<JSObject> api_holder = LookupHolderOfExpectedType(map, &holder_lookup);
52   switch (holder_lookup) {
53     case kHolderNotFound:
54       return false;
55     case kHolderIsReceiver:
56       return true;
57     case kHolderFound:
58       if (api_holder.is_identical_to(holder)) return true;
59       // Check if holder is in prototype chain of api_holder.
60       {
61         JSObject* object = *api_holder;
62         while (true) {
63           Object* prototype = object->map()->prototype();
64           if (!prototype->IsJSObject()) return false;
65           if (prototype == *holder) return true;
66           object = JSObject::cast(prototype);
67         }
68       }
69       break;
70   }
71   UNREACHABLE();
72   return false;
73 }
74 
75 
Initialize(Handle<JSFunction> function)76 void CallOptimization::Initialize(Handle<JSFunction> function) {
77   constant_function_ = Handle<JSFunction>::null();
78   is_simple_api_call_ = false;
79   expected_receiver_type_ = Handle<FunctionTemplateInfo>::null();
80   api_call_info_ = Handle<CallHandlerInfo>::null();
81 
82   if (function.is_null() || !function->is_compiled()) return;
83 
84   constant_function_ = function;
85   AnalyzePossibleApiFunction(function);
86 }
87 
88 
AnalyzePossibleApiFunction(Handle<JSFunction> function)89 void CallOptimization::AnalyzePossibleApiFunction(Handle<JSFunction> function) {
90   if (!function->shared()->IsApiFunction()) return;
91   Handle<FunctionTemplateInfo> info(function->shared()->get_api_func_data());
92 
93   // Require a C++ callback.
94   if (info->call_code()->IsUndefined()) return;
95   api_call_info_ =
96       Handle<CallHandlerInfo>(CallHandlerInfo::cast(info->call_code()));
97 
98   // Accept signatures that either have no restrictions at all or
99   // only have restrictions on the receiver.
100   if (!info->signature()->IsUndefined()) {
101     Handle<SignatureInfo> signature =
102         Handle<SignatureInfo>(SignatureInfo::cast(info->signature()));
103     if (!signature->args()->IsUndefined()) return;
104     if (!signature->receiver()->IsUndefined()) {
105       expected_receiver_type_ = Handle<FunctionTemplateInfo>(
106           FunctionTemplateInfo::cast(signature->receiver()));
107     }
108   }
109 
110   is_simple_api_call_ = true;
111 }
112 }
113 }  // namespace v8::internal
114