v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
templates-inl.h
Go to the documentation of this file.
1// Copyright 2018 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#ifndef V8_OBJECTS_TEMPLATES_INL_H_
6#define V8_OBJECTS_TEMPLATES_INL_H_
7
9// Include the non-inl header before the rest of the headers.
10
14#include "src/objects/oddball.h"
16
17// Has to be the last include (doesn't have include guards):
19
20namespace v8 {
21namespace internal {
22
23#include "torque-generated/src/objects/templates-tq-inl.inc"
24
26TQ_OBJECT_CONSTRUCTORS_IMPL(TemplateInfoWithProperties)
27TQ_OBJECT_CONSTRUCTORS_IMPL(FunctionTemplateInfo)
28TQ_OBJECT_CONSTRUCTORS_IMPL(ObjectTemplateInfo)
29TQ_OBJECT_CONSTRUCTORS_IMPL(FunctionTemplateRareData)
30TQ_OBJECT_CONSTRUCTORS_IMPL(DictionaryTemplateInfo)
31
32NEVER_READ_ONLY_SPACE_IMPL(DictionaryTemplateInfo)
33NEVER_READ_ONLY_SPACE_IMPL(ObjectTemplateInfo)
34
36 is_object_template_call_handler,
37 IsObjectTemplateCallHandlerBit::kShift)
39 HasSideEffectsBit::kShift)
41 UndetectableBit::kShift)
43 NeedsAccessCheckBit::kShift)
45 ReadOnlyPrototypeBit::kShift)
47 RemovePrototypeBit::kShift)
49 AcceptAnyReceiverBit::kShift)
50
51bool FunctionTemplateInfo::published() const {
52 return BooleanBit::get(relaxed_flag(), PublishedBit::kShift);
53}
54
55void FunctionTemplateInfo::set_published(bool value) {
56 DCHECK(value);
57 if (published()) return;
60 BooleanBit::set(relaxed_flag(), PublishedBit::kShift, value));
61}
62
65 allowed_receiver_instance_type_range_start,
66 FunctionTemplateInfo::AllowedReceiverInstanceTypeRangeStartBits)
70 FunctionTemplateInfo::AllowedReceiverInstanceTypeRangeEndBits)
71
73 FunctionTemplateInfo::kFlagOffset)
74
75int32_t FunctionTemplateInfo::relaxed_flag() const {
76 return flag(kRelaxedLoad);
77}
79 return set_flag(flags, kRelaxedStore);
80}
81
82Address FunctionTemplateInfo::callback(i::IsolateForSandbox isolate) const {
83 Address result = maybe_redirected_callback(isolate);
84 if (!USE_SIMULATOR_BOOL) return result;
85 if (result == kNullAddress) return kNullAddress;
87}
88
89void FunctionTemplateInfo::init_callback(i::IsolateForSandbox isolate,
90 Address initial_value) {
91 init_maybe_redirected_callback(isolate, initial_value);
94 }
95}
96
97void FunctionTemplateInfo::set_callback(i::IsolateForSandbox isolate,
98 Address value) {
99 set_maybe_redirected_callback(isolate, value);
100 if (USE_SIMULATOR_BOOL) {
102 }
103}
104
106 i::IsolateForSandbox isolate) {
108 Address value = maybe_redirected_callback(isolate);
109 if (value == kNullAddress) return;
110 value =
112 set_maybe_redirected_callback(isolate, value);
113}
114
116 i::IsolateForSandbox isolate) {
118 Address value = callback(isolate);
119 set_maybe_redirected_callback(isolate, value);
120}
121
123 FunctionTemplateInfo, maybe_redirected_callback, Address,
124 kMaybeRedirectedCallbackOffset, kFunctionTemplateInfoCallbackTag)
125
126template <class IsolateT>
127bool FunctionTemplateInfo::has_callback(IsolateT* isolate) const {
128 return !IsTheHole(callback_data(kAcquireLoad), isolate);
129}
130
131// static
134 Isolate* isolate,
135 DirectHandle<FunctionTemplateInfo> function_template_info) {
136 Tagged<HeapObject> extra =
137 function_template_info->rare_data(isolate, kAcquireLoad);
138 if (IsUndefined(extra, isolate)) {
139 return AllocateFunctionTemplateRareData(isolate, function_template_info);
140 } else {
141 return Cast<FunctionTemplateRareData>(extra);
142 }
143}
144
145#define RARE_ACCESSORS(Name, CamelName, Default, ...) \
146 DEF_GETTER(FunctionTemplateInfo, Get##CamelName, Tagged<__VA_ARGS__>) { \
147 Tagged<HeapObject> extra = rare_data(cage_base, kAcquireLoad); \
148 Tagged<Undefined> undefined = GetReadOnlyRoots().undefined_value(); \
149 return extra == undefined ? Default \
150 : Cast<FunctionTemplateRareData>(extra)->Name(); \
151 } \
152 inline void FunctionTemplateInfo::Set##CamelName( \
153 Isolate* isolate, \
154 DirectHandle<FunctionTemplateInfo> function_template_info, \
155 DirectHandle<__VA_ARGS__> Name) { \
156 Tagged<FunctionTemplateRareData> rare_data = \
157 EnsureFunctionTemplateRareData(isolate, function_template_info); \
158 rare_data->set_##Name(*Name); \
159 }
160
161RARE_ACCESSORS(prototype_template, PrototypeTemplate, undefined,
163RARE_ACCESSORS(prototype_provider_template, PrototypeProviderTemplate,
165RARE_ACCESSORS(parent_template, ParentTemplate, undefined,
167RARE_ACCESSORS(named_property_handler, NamedPropertyHandler, undefined,
169RARE_ACCESSORS(indexed_property_handler, IndexedPropertyHandler, undefined,
171RARE_ACCESSORS(instance_template, InstanceTemplate, undefined,
173RARE_ACCESSORS(instance_call_handler, InstanceCallHandler, undefined,
175RARE_ACCESSORS(access_check_info, AccessCheckInfo, undefined,
177RARE_ACCESSORS(c_function_overloads, CFunctionOverloads,
178 GetReadOnlyRoots().empty_fixed_array(), FixedArray)
179#undef RARE_ACCESSORS
180
181InstanceType FunctionTemplateInfo::GetInstanceType() const {
182 int type = instance_type();
185 return static_cast<InstanceType>(type);
186}
187
188void FunctionTemplateInfo::SetInstanceType(int api_instance_type) {
189 // Translate |api_instance_type| value from range
190 // [Internals::kFirstEmbedderJSApiObjectType,
191 // Internals::kLastEmbedderJSApiObjectType] to range
192 // [Internals::kFirstJSApiObjectType, Internals::kLastJSApiObjectType].
195 // kNoJSApiObjectType must correspond to JS_API_OBJECT_TYPE.
196 static_assert(kNoJSApiObjectType == 0);
197 static_assert(JS_API_OBJECT_TYPE == Internals::kFirstJSApiObjectType);
198 set_instance_type(static_cast<InstanceType>(
199 api_instance_type + Internals::kFirstJSApiObjectType));
200}
201
203 int api_instance_type_start, int api_instance_type_end) {
204 // Translate |api_instance_type_start| and |api_instance_type_end| values
205 // from range [Internals::kFirstEmbedderJSApiObjectType,
206 // Internals::kLastEmbedderJSApiObjectType] to range
207 // [Internals::kFirstJSApiObjectType, Internals::kLastJSApiObjectType].
208 DCHECK_LE(Internals::kFirstEmbedderJSApiObjectType, api_instance_type_start);
209 DCHECK_LE(api_instance_type_start, api_instance_type_end);
211 // kNoJSApiObjectType must correspond to JS_API_OBJECT_TYPE.
212 static_assert(kNoJSApiObjectType == 0);
213 static_assert(JS_API_OBJECT_TYPE == Internals::kFirstJSApiObjectType);
214 set_allowed_receiver_instance_type_range_start(static_cast<InstanceType>(
215 api_instance_type_start + Internals::kFirstJSApiObjectType));
216 set_allowed_receiver_instance_type_range_end(static_cast<InstanceType>(
217 api_instance_type_end + Internals::kFirstJSApiObjectType));
218}
219
220// Ensure that instance type fields in FunctionTemplateInfo are big enough
221// to fit the whole JSApiObject type range.
222static_assert(
223 FunctionTemplateInfo::AllowedReceiverInstanceTypeRangeStartBits::is_valid(
224 LAST_JS_API_OBJECT_TYPE));
225static_assert(
226 FunctionTemplateInfo::AllowedReceiverInstanceTypeRangeEndBits::is_valid(
227 LAST_JS_API_OBJECT_TYPE));
228
230 return IsSharedFunctionInfo(shared_function_info());
231}
232
234 Tagged<Object> maybe_shared = shared_function_info();
235 if (IsSharedFunctionInfo(maybe_shared)) {
237 return shared->BreakAtEntry(isolate);
238 }
239 return false;
240}
241
243 Tagged<Object> parent = GetParentTemplate();
244 return IsUndefined(parent, isolate) ? Tagged<FunctionTemplateInfo>{}
246}
247
249 Tagged<Object> maybe_ctor = constructor();
250 if (IsUndefined(maybe_ctor, isolate)) return ObjectTemplateInfo();
251 Tagged<FunctionTemplateInfo> constructor =
252 Cast<FunctionTemplateInfo>(maybe_ctor);
253 while (true) {
254 constructor = constructor->GetParent(isolate);
255 if (constructor.is_null()) return ObjectTemplateInfo();
256 Tagged<Object> maybe_obj = constructor->GetInstanceTemplate();
257 if (!IsUndefined(maybe_obj, isolate)) {
258 return Cast<ObjectTemplateInfo>(maybe_obj);
259 }
260 }
262}
263
264int ObjectTemplateInfo::embedder_field_count() const {
265 return EmbedderFieldCountBits::decode(data());
266}
267
268void ObjectTemplateInfo::set_embedder_field_count(int count) {
270 return set_data(EmbedderFieldCountBits::update(data(), count));
271}
272
273bool ObjectTemplateInfo::immutable_proto() const {
274 return IsImmutablePrototypeBit::decode(data());
275}
276
277void ObjectTemplateInfo::set_immutable_proto(bool immutable) {
278 return set_data(IsImmutablePrototypeBit::update(data(), immutable));
279}
280
281bool ObjectTemplateInfo::code_like() const {
282 return IsCodeKindBit::decode(data());
283}
284
285void ObjectTemplateInfo::set_code_like(bool is_code_like) {
286 return set_data(IsCodeKindBit::update(data(), is_code_like));
287}
288
290 return IsTemplateFor(object->map());
291}
292
294 if (GetIsolateFromHeapObject(*this, isolate)) return true;
295 Isolate* isolate_value = Isolate::TryGetCurrent();
296 if (isolate_value != nullptr) {
297 *isolate = isolate_value;
298 return true;
299 }
300 return false;
301}
302
305 CHECK(TryGetIsolate(&isolate));
306 return isolate;
307}
308
309bool TemplateInfo::is_cacheable() const {
310 return IsCacheableBit::decode(template_info_flags());
311}
312void TemplateInfo::set_is_cacheable(bool is_cacheable) {
313 set_template_info_flags(
314 IsCacheableBit::update(template_info_flags(), is_cacheable));
315}
316
317bool TemplateInfo::should_promote_to_read_only() const {
318 return ShouldPromoteToReadOnlyBit::decode(template_info_flags());
319}
320void TemplateInfo::set_should_promote_to_read_only(
321 bool should_promote_to_read_only) {
322 DCHECK(should_promote_to_read_only);
323 set_template_info_flags(ShouldPromoteToReadOnlyBit::update(
324 template_info_flags(), should_promote_to_read_only));
325}
326
327uint32_t TemplateInfo::serial_number() const {
328 return SerialNumberBits::decode(template_info_flags());
329}
330void TemplateInfo::set_serial_number(uint32_t value) {
331 set_template_info_flags(
332 SerialNumberBits::update(template_info_flags(), value));
333}
334
336 uint32_t serial_number = this->serial_number();
337 if (serial_number == kUninitializedSerialNumber) {
339 serial_number = isolate->heap()->GetNextTemplateSerialNumber();
340 set_serial_number(serial_number);
341 }
342 return serial_number;
343}
344
345uint32_t TemplateInfo::GetHash() const {
346 uint32_t hash = ComputeUnseededHash(serial_number());
347 // Make sure that the hash can be encoded in a Smi in order to make it
348 // compatible with Object::GetSimpleHash() and avoid surprises.
349 return hash & Smi::kMaxValue;
350}
351
352// static
355 DirectHandle<TemplateInfo> info, CachingMode caching_mode) {
356 DCHECK(info->is_cacheable());
357
358 uint32_t serial_number = info->serial_number();
359 if (serial_number == kUninitializedSerialNumber) {
360 return {};
361 }
362
363 if (serial_number < kFastTemplateInstantiationsCacheSize) {
364 Tagged<FixedArray> fast_cache =
365 native_context->fast_template_instantiations_cache();
366 Tagged<Object> object = fast_cache->get(serial_number);
367 if (IsTheHole(object, isolate)) {
368 return {};
369 }
370 return handle(object, isolate);
371 }
373 native_context->slow_template_instantiations_cache();
374 ReadOnlyRoots roots(isolate);
375 // Instead of detouring via Object::GetHash() load the hash directly.
376 uint32_t hash = info->GetHash();
377 InternalIndex entry = cache->FindEntry(isolate, roots, info, hash);
378 if (entry.is_found()) {
379 return handle(cache->ValueAt(entry), isolate);
380 }
381 return {};
382}
383
384// static
387 DirectHandle<TemplateInfo> info, CachingMode caching_mode,
388 DirectHandle<Object> object) {
389 DCHECK(info->is_cacheable());
390
391 uint32_t serial_number = info->EnsureHasSerialNumber(isolate);
392
393 if (serial_number < kFastTemplateInstantiationsCacheSize) {
394 Handle<FixedArray> fast_cache =
395 handle(native_context->fast_template_instantiations_cache(), isolate);
396 fast_cache->set(serial_number, *object);
397 return;
398 }
400 handle(native_context->slow_template_instantiations_cache(), isolate);
401 if (caching_mode == CachingMode::kUnlimited ||
402 (cache->NumberOfElements() < kMaxTemplateInstantiationsCacheSize)) {
403 ReadOnlyRoots roots(isolate);
404 // Instead of detouring via Object::GetHash() load the hash directly.
405 uint32_t hash = info->GetHash();
406 auto new_cache =
407 EphemeronHashTable::Put(isolate, cache, info, object, hash);
408 if (*new_cache != *cache) {
409 native_context->set_slow_template_instantiations_cache(*new_cache);
410 }
411 }
412}
413
414// static
417 DirectHandle<TemplateInfo> info, CachingMode caching_mode) {
418 int serial_number = info->serial_number();
419 if (serial_number == kUninitializedSerialNumber) return;
420
421 if (serial_number < kFastTemplateInstantiationsCacheSize) {
422 Tagged<FixedArray> fast_cache =
423 native_context->fast_template_instantiations_cache();
424 DCHECK(!IsUndefined(fast_cache->get(serial_number), isolate));
425 fast_cache->set(serial_number, ReadOnlyRoots{isolate}.the_hole_value(),
427 return;
428 }
430 handle(native_context->slow_template_instantiations_cache(), isolate);
431 // Instead of detouring via Object::GetHash() load the hash directly.
432 uint32_t hash = info->GetHash();
433 bool was_present = false;
434 auto new_cache =
435 EphemeronHashTable::Remove(isolate, cache, info, &was_present, hash);
436 DCHECK(was_present);
437 if (!new_cache.is_identical_to(cache)) {
438 native_context->set_slow_template_instantiations_cache(*new_cache);
439 }
440}
441
442} // namespace internal
443} // namespace v8
444
446
447#endif // V8_OBJECTS_TEMPLATES_INL_H_
union v8::internal::@341::BuiltinMetadata::KindSpecificData data
static Isolate * TryGetCurrent()
Definition api.cc:9954
static bool get(int value, int bit_position)
Definition objects.h:907
static int set(int value, int bit_position, bool v)
Definition objects.h:911
static Address Redirect(Address external_function, Type type=ExternalReference::BUILTIN_CALL)
static Address UnwrapRedirection(Address redirection_trampoline)
void SetAllowedReceiverInstanceTypeRange(int api_instance_type_start, int api_instance_type_end)
void SetInstanceType(int api_instance_type)
static Tagged< FunctionTemplateRareData > EnsureFunctionTemplateRareData(Isolate *isolate, DirectHandle< FunctionTemplateInfo > function_template_info)
bool BreakAtEntry(Isolate *isolate)
void set_relaxed_flag(int32_t flags)
void init_callback_redirection(i::IsolateForSandbox isolate)
bool has_callback(IsolateT *isolate) const
bool IsTemplateFor(Tagged< JSObject > object) const
void remove_callback_redirection(i::IsolateForSandbox isolate)
static Tagged< FunctionTemplateRareData > AllocateFunctionTemplateRareData(Isolate *isolate, DirectHandle< FunctionTemplateInfo > function_template_info)
Definition templates.cc:143
Tagged< FunctionTemplateInfo > GetParent(Isolate *isolate)
static V8_INLINE bool InReadOnlySpace(Tagged< HeapObject > object)
static const int kFirstEmbedderJSApiObjectType
static const int kLastJSApiObjectType
static const int kFirstJSApiObjectType
static const int kLastEmbedderJSApiObjectType
static const int kMaxEmbedderFields
Definition js-objects.h:965
NEVER_READ_ONLY_SPACE Tagged< ObjectTemplateInfo > GetParent(Isolate *isolate)
static constexpr int kMaxValue
Definition smi.h:101
static void CacheTemplateInstantiation(Isolate *isolate, DirectHandle< NativeContext > native_context, DirectHandle< TemplateInfo > info, CachingMode caching_mode, DirectHandle< Object > object)
static constexpr int kMaxTemplateInstantiationsCacheSize
Definition templates.h:38
Isolate * GetIsolateChecked() const
static void UncacheTemplateInstantiation(Isolate *isolate, DirectHandle< NativeContext > native_context, DirectHandle< TemplateInfo > info, CachingMode caching_mode)
bool TryGetIsolate(Isolate **isolate) const
static const int kUninitializedSerialNumber
Definition templates.h:41
static const int kFastTemplateInstantiationsCacheSize
Definition templates.h:33
uint32_t EnsureHasSerialNumber(Isolate *isolate)
static MaybeHandle< ReturnType > ProbeInstantiationsCache(Isolate *isolate, DirectHandle< NativeContext > native_context, DirectHandle< TemplateInfo > info, CachingMode caching_mode)
Definition templates.h:70
#define USE_SIMULATOR_BOOL
Definition globals.h:73
Isolate * isolate
TNode< Object > callback
ZoneVector< RpoNumber > & result
constexpr bool IsInRange(T value, U lower_limit, U higher_limit)
Definition bounds.h:20
V8_INLINE IndirectHandle< T > handle(Tagged< T > object, Isolate *isolate)
Definition handles-inl.h:72
HasSideEffectsBit::kShift NeedsAccessCheckBit::kShift remove_prototype
@ SKIP_WRITE_BARRIER
Definition objects.h:52
ReadOnlyRoots GetReadOnlyRoots()
Definition roots-inl.h:86
Tagged(T object) -> Tagged< T >
uint32_t ComputeUnseededHash(uint32_t key)
Definition utils.h:271
V8_INLINE bool GetIsolateFromHeapObject(Tagged< HeapObject > object, Isolate **isolate)
kInterpreterTrampolineOffset Tagged< HeapObject >
HasSideEffectsBit::kShift needs_access_check
typename detail::FlattenUnionHelper< Union<>, Ts... >::type UnionOf
Definition union.h:123
@ kFunctionTemplateInfoCallbackTag
static constexpr Address kNullAddress
Definition v8-internal.h:53
UnionOf< Undefined, FunctionTemplateInfo > NamedPropertyHandler
UnionOf< Undefined, FunctionTemplateInfo > UnionOf< Undefined, InterceptorInfo > InstanceTemplate
allowed_receiver_instance_type_range_end
!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
static constexpr RelaxedLoadTag kRelaxedLoad
Definition globals.h:2909
static constexpr RelaxedStoreTag kRelaxedStore
Definition globals.h:2911
static constexpr AcquireLoadTag kAcquireLoad
Definition globals.h:2908
#define BOOL_ACCESSORS(holder, field, name, offset)
#define TQ_OBJECT_CONSTRUCTORS_IMPL(Type)
#define EXTERNAL_POINTER_ACCESSORS_MAYBE_READ_ONLY_HOST(holder, name, type, offset, tag)
#define BIT_FIELD_ACCESSORS(holder, field, name, BitField)
#define RELAXED_UINT32_ACCESSORS(holder, name, offset)
#define NEVER_READ_ONLY_SPACE_IMPL(Type)
#define DCHECK_LE(v1, v2)
Definition logging.h:490
#define CHECK(condition)
Definition logging.h:124
#define DCHECK(condition)
Definition logging.h:482
#define RARE_ACCESSORS(Name, CamelName, Default,...)
wasm::ValueType type