v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
call-optimization.cc
Go to the documentation of this file.
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
6
7#include <optional>
8
10
11namespace v8 {
12namespace internal {
13
14template <class IsolateT>
16 if (IsJSFunction(*function)) {
17 Initialize(isolate, Cast<JSFunction>(function));
18 } else if (IsFunctionTemplateInfo(*function)) {
19 Initialize(isolate, Cast<FunctionTemplateInfo>(function));
20 }
21}
22
23// Instantiations.
25 Handle<Object> function);
27 Handle<Object> function);
28
29std::optional<Tagged<NativeContext>> CallOptimization::GetAccessorContext(
30 Tagged<Map> holder_map) const {
31 if (is_constant_call()) {
32 return constant_function_->native_context();
33 }
34 Tagged<Object> maybe_native_context =
35 holder_map->map()->native_context_or_null();
36 if (IsNull(maybe_native_context)) {
37 // The holder is a remote object which doesn't have a creation context.
38 return {};
39 }
40 DCHECK(IsNativeContext(maybe_native_context));
41 return Cast<NativeContext>(maybe_native_context);
42}
43
46 DCHECK(IsNativeContext(native_context));
47 if (is_constant_call()) return false;
48 std::optional<Tagged<NativeContext>> maybe_context =
49 GetAccessorContext(holder_map);
50 if (!maybe_context.has_value()) {
51 // The holder is a remote object which doesn't have a creation context.
52 return true;
53 }
54 return native_context != maybe_context.value();
55}
56
57template <class IsolateT>
59 IsolateT* isolate, DirectHandle<Map> object_map,
60 HolderLookup* holder_lookup) const {
62 if (!IsJSObjectMap(*object_map)) {
63 *holder_lookup = kHolderNotFound;
65 }
66 if (expected_receiver_type_.is_null() ||
67 expected_receiver_type_->IsTemplateFor(*object_map)) {
68 *holder_lookup = kHolderIsReceiver;
70 }
71 if (IsJSGlobalProxyMap(*object_map) && !IsNull(object_map->prototype())) {
72 Tagged<JSObject> raw_prototype = Cast<JSObject>(object_map->prototype());
73 Handle<JSObject> prototype(raw_prototype, isolate);
74 object_map = direct_handle(prototype->map(), isolate);
75 if (expected_receiver_type_->IsTemplateFor(*object_map)) {
76 *holder_lookup = kHolderFound;
77 return prototype;
78 }
79 }
80 *holder_lookup = kHolderNotFound;
82}
83
84// Instantiations.
86 Isolate* isolate, DirectHandle<Map> object_map,
87 HolderLookup* holder_lookup) const;
89 LocalIsolate* isolate, DirectHandle<Map> object_map,
90 HolderLookup* holder_lookup) const;
91
94 HolderLookup holder_lookup) const {
96 switch (holder_lookup) {
97 case kHolderNotFound:
98 return false;
100 return true;
101 case kHolderFound:
102 if (api_holder.is_identical_to(holder)) return true;
103 // Check if holder is in prototype chain of api_holder.
104 {
105 Tagged<JSObject> object = *api_holder;
106 while (true) {
107 Tagged<Object> prototype = object->map()->prototype();
108 if (!IsJSObject(prototype)) return false;
109 if (prototype == *holder) return true;
110 object = Cast<JSObject>(prototype);
111 }
112 }
113 }
114 UNREACHABLE();
115}
116
117template <class IsolateT>
119 IsolateT* isolate, Handle<FunctionTemplateInfo> function_template_info) {
120 if (!function_template_info->has_callback(isolate)) return;
121 api_call_info_ = function_template_info;
122
123 Tagged<HeapObject> signature = function_template_info->signature();
124 if (!IsUndefined(signature, isolate)) {
126 handle(Cast<FunctionTemplateInfo>(signature), isolate);
127 }
128 is_simple_api_call_ = true;
129 accept_any_receiver_ = function_template_info->accept_any_receiver();
130}
131
132template <class IsolateT>
133void CallOptimization::Initialize(IsolateT* isolate,
134 Handle<JSFunction> function) {
135 if (function.is_null() || !function->is_compiled(isolate)) return;
136
137 constant_function_ = function;
138 AnalyzePossibleApiFunction(isolate, function);
139}
140
141template <class IsolateT>
143 IsolateT* isolate, DirectHandle<JSFunction> function) {
144 if (!function->shared()->IsApiFunction()) return;
145 Handle<FunctionTemplateInfo> function_template_info(
146 function->shared()->api_func_data(), isolate);
147 Initialize(isolate, function_template_info);
148}
149} // namespace internal
150} // namespace v8
Handle< FunctionTemplateInfo > api_call_info_
std::optional< Tagged< NativeContext > > GetAccessorContext(Tagged< Map > holder_map) const
void Initialize(IsolateT *isolate, Handle< JSFunction > function)
Handle< FunctionTemplateInfo > expected_receiver_type_
bool IsCrossContextLazyAccessorPair(Tagged< NativeContext > native_context, Tagged< Map > holder_map) const
CallOptimization(IsolateT *isolate, Handle< Object > function)
bool IsCompatibleReceiverMap(DirectHandle< JSObject > api_holder, Handle< JSObject > holder, HolderLookup) const
Handle< JSFunction > constant_function_
Handle< JSObject > LookupHolderOfExpectedType(IsolateT *isolate, DirectHandle< Map > receiver_map, HolderLookup *holder_lookup) const
void AnalyzePossibleApiFunction(IsolateT *isolate, DirectHandle< JSFunction > function)
V8_INLINE bool is_identical_to(Handle< S > other) const
Definition handles.h:716
V8_INLINE IndirectHandle< T > handle(Tagged< T > object, Isolate *isolate)
Definition handles-inl.h:72
V8_INLINE DirectHandle< T > direct_handle(Tagged< T > object, Isolate *isolate)
kInstanceDescriptorsOffset kTransitionsOrPrototypeInfoOffset IsNull(value)||IsJSProxy(value)||IsWasmObject(value)||(IsJSObject(value) &&(HeapLayout
Definition map-inl.h:70
kInstanceDescriptorsOffset kTransitionsOrPrototypeInfoOffset prototype
Definition map-inl.h:69
!IsContextMap !IsContextMap native_context
Definition map-inl.h:877
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Definition casting.h:150
#define DCHECK(condition)
Definition logging.h:482