v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
lookup-inl.h
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
5#ifndef V8_OBJECTS_LOOKUP_INL_H_
6#define V8_OBJECTS_LOOKUP_INL_H_
7
9// Include the non-inl header before the rest of the headers.
10
11// Include other inline headers *after* including lookup.h, such that e.g. the
12// definition of LookupIterator is available (and this comment prevents
13// clang-format from merging that include into the following ones).
19#include "src/objects/map-inl.h"
22
23namespace v8 {
24namespace internal {
25
28 Configuration configuration)
29 : LookupIterator(isolate, receiver, name, kInvalidIndex, receiver,
30 configuration) {}
31
34 DirectHandle<JSAny> lookup_start_object,
35 Configuration configuration)
36 : LookupIterator(isolate, receiver, name, kInvalidIndex,
37 Cast<JSAny>(lookup_start_object), configuration) {}
38
40 size_t index, Configuration configuration)
41 : LookupIterator(isolate, receiver, DirectHandle<Name>(), index, receiver,
42 configuration) {
44}
45
47 size_t index,
48 DirectHandle<JSAny> lookup_start_object,
49 Configuration configuration)
50 : LookupIterator(isolate, receiver, DirectHandle<Name>(), index,
51 Cast<JSAny>(lookup_start_object), configuration) {
53}
54
56 const PropertyKey& key,
57 Configuration configuration)
58 : LookupIterator(isolate, receiver, key.name(), key.index(), receiver,
59 configuration) {}
60
62 const PropertyKey& key,
63 DirectHandle<JSAny> lookup_start_object,
64 Configuration configuration)
65 : LookupIterator(isolate, receiver, key.name(), key.index(),
66 Cast<JSAny>(lookup_start_object), configuration) {}
67
68// This private constructor is the central bottleneck that all the other
69// constructors use.
71 DirectHandle<Name> name, size_t index,
72 DirectHandle<JSAny> lookup_start_object,
73 Configuration configuration)
74 : configuration_(ComputeConfiguration(isolate, configuration, name)),
75 isolate_(isolate),
76 name_(name),
78 lookup_start_object_(lookup_start_object),
79 index_(index) {
80 if (IsElement()) {
81 // If we're not looking at a TypedArray, we will need the key represented
82 // as an internalized string.
84 !IsJSTypedArray(*lookup_start_object, isolate_)
85#if V8_ENABLE_WEBASSEMBLY
86 && !IsWasmArray(*lookup_start_object, isolate_)
87#endif // V8_ENABLE_WEBASSEMBLY
88 ) {
89 if (name_.is_null()) {
90 name_ = isolate->factory()->SizeToString(index_);
91 }
92 name_ = isolate->factory()->InternalizeName(name_);
93 } else if (!name_.is_null() && !IsInternalizedString(*name_)) {
94 // Maintain the invariant that if name_ is present, it is internalized.
96 }
98 } else {
99 DCHECK(!name_.is_null());
100 name_ = isolate->factory()->InternalizeName(name_);
101#ifdef DEBUG
102 // Assert that the name is not an index.
103 // If we're not looking at the prototype chain and the lookup start object
104 // is not a typed array, then this means "array index", otherwise we need to
105 // ensure the full generality so that typed arrays are handled correctly.
106 if (!check_prototype_chain() && !IsJSTypedArray(*lookup_start_object)) {
107 uint32_t array_index;
108 DCHECK(!name_->AsArrayIndex(&array_index));
109 } else {
110 size_t integer_index;
111 DCHECK(!name_->AsIntegerIndex(&integer_index));
112 }
113#endif // DEBUG
114 Start<false>();
115 }
116}
117
121 : configuration_(configuration),
122 isolate_(isolate),
123 name_(name),
125 lookup_start_object_(receiver),
126 index_(kInvalidIndex) {
127 // This is the only lookup configuration allowed by this constructor because
128 // it's special case allowing lookup of the private symbols on the prototype
129 // chain. Usually private symbols are limited to OWN_SKIP_INTERCEPTOR lookups.
130 DCHECK(*name_ == *isolate->factory()->error_stack_symbol() ||
131 *name_ == *isolate->factory()->error_message_symbol());
133 Start<false>();
134}
135
136PropertyKey::PropertyKey(Isolate* isolate, double index) {
137 DCHECK_EQ(index, static_cast<uint64_t>(index));
138#if V8_TARGET_ARCH_32_BIT
139 if (index <= JSObject::kMaxElementIndex) {
140 static_assert(JSObject::kMaxElementIndex <=
141 std::numeric_limits<size_t>::max());
142 index_ = static_cast<size_t>(index);
143 } else {
145 name_ = isolate->factory()->InternalizeString(
146 isolate->factory()->HeapNumberToString(
147 isolate->factory()->NewHeapNumber(index), index));
148 }
149#else
150 index_ = static_cast<size_t>(index);
151#endif
152}
153
154template <template <typename> typename HandleType>
155 requires(std::is_convertible_v<HandleType<Name>, DirectHandle<Name>>)
156PropertyKey::PropertyKey(Isolate* isolate, HandleType<Name> name, size_t index)
157 : name_(name), index_(index) {
159#if V8_TARGET_ARCH_32_BIT
162#endif
163#if DEBUG
164 if (index_ != LookupIterator::kInvalidIndex && !name_.is_null()) {
165 // If both valid index and name are given then the name is a string
166 // representation of the same index.
167 size_t integer_index;
168 CHECK(name_->AsIntegerIndex(&integer_index));
169 CHECK_EQ(index_, integer_index);
171 // If only name is given it must not be a string representing an integer
172 // index.
173 size_t integer_index;
174 CHECK(!name_->AsIntegerIndex(&integer_index));
175 }
176#endif
177}
178
179template <template <typename> typename HandleType>
180 requires(std::is_convertible_v<HandleType<Name>, DirectHandle<Name>>)
181PropertyKey::PropertyKey(Isolate* isolate, HandleType<Name> name) {
182 if (name->AsIntegerIndex(&index_)) {
183 name_ = name;
184 } else {
186 name_ = isolate->factory()->InternalizeName(name);
187 }
188}
189
190template <typename T, template <typename> typename HandleType>
191 requires(std::is_convertible_v<HandleType<T>, DirectHandle<T>>)
192PropertyKey::PropertyKey(Isolate* isolate, HandleType<T> valid_key) {
193 HandleType<Object> valid_obj = Cast<Object>(valid_key);
194 DCHECK(IsName(*valid_obj) || IsNumber(*valid_obj));
195 if (Object::ToIntegerIndex(*valid_obj, &index_)) return;
196 if (IsNumber(*valid_obj)) {
197 // Negative or out of range -> treat as named property.
198 valid_obj = isolate->factory()->NumberToString(valid_obj);
199 }
200 DCHECK(IsName(*valid_obj));
201 name_ = Cast<Name>(valid_obj);
202 if (!name_->AsIntegerIndex(&index_)) {
204 name_ = isolate->factory()->InternalizeName(name_);
205 }
206}
207
208template <typename T, template <typename> typename HandleType>
209 requires(std::is_convertible_v<HandleType<T>, DirectHandle<T>>)
210PropertyKey::PropertyKey(Isolate* isolate, HandleType<T> key, bool* success) {
212 *success = true;
213 return;
214 }
215 *success = Object::ToName(isolate, key).ToHandle(&name_);
216 if (!*success) {
217 DCHECK(isolate->has_exception());
219 return;
220 }
221 if (!name_->AsIntegerIndex(&index_)) {
222 // Make sure the name is internalized.
223 name_ = isolate->factory()->InternalizeName(name_);
224 // {AsIntegerIndex} may modify {index_} before deciding to fail.
226 }
227}
228
232
234 if (name_.is_null()) {
236 name_ = isolate->factory()->SizeToString(index_);
237 }
238 return name_;
239}
240
245
247 if (name_.is_null()) {
248 DCHECK(IsElement());
250 }
251 return name_;
252}
253
257
260 (index_ != kInvalidIndex &&
261 object->map()->has_any_typed_array_or_wasm_array_elements());
262}
263
265 return !IsElement() && name()->IsPrivateName();
266}
267
269 return !holder_->HasFastProperties(isolate_);
270}
271
276
281
282template <class T>
287
289 DCHECK(receiver.is_identical_to(GetStoreTarget<JSReceiver>()));
291 Tagged<Map> receiver_map = receiver->map(isolate_);
292 if (receiver_map->is_extensible()) {
293 return false;
294 }
295 // Extending with elements and non-private properties is not allowed.
296 if (IsElement() || !name_->IsPrivate()) {
297 return true;
298 }
299 // These JSObject types are wrappers around a set of primitive values
300 // and exist only for the purpose of passing the data across V8 Api.
301 // They are not supposed to be ever leaked to user JS code.
302 CHECK(!IsMaybeReadOnlyJSObjectMap(receiver_map));
303
304 // Shared objects have fixed layout. No properties may be added to them, not
305 // even private symbols.
306 if (IsAlwaysSharedSpaceJSObjectMap(receiver_map)) {
307 return true;
308 }
309 // Extending non-extensible objects with private fields is allowed.
310 DCHECK(!receiver_map->is_extensible());
311 DCHECK(name_->IsPrivate());
312 if (name_->IsPrivateName()) {
314 }
315 return false;
316}
317
320 return IsPropertyCell(*transition_, isolate_) ||
321 (transition_map()->is_dictionary_map() &&
322 !GetStoreTarget<JSReceiver>()->HasFastProperties(isolate_)) ||
323 IsMap(transition_map()->GetBackPointer(isolate_), isolate_);
324}
325
326// static
329 DirectHandle<Name> name) {
330 RCS_SCOPE(isolate, RuntimeCallCounterId::kUpdateProtector);
331 DCHECK(IsInternalizedString(*name) || IsSymbol(*name));
332
333 // This check must be kept in sync with
334 // CodeStubAssembler::CheckForAssociatedProtector!
335 ReadOnlyRoots roots(isolate);
336 bool maybe_protector = roots.IsNameForProtector(*name);
337
338#if DEBUG
339 bool debug_maybe_protector =
340 *name == roots.constructor_string() || *name == roots.next_string() ||
341 *name == roots.resolve_string() || *name == roots.then_string() ||
342 *name == roots.is_concat_spreadable_symbol() ||
343 *name == roots.iterator_symbol() || *name == roots.species_symbol() ||
344 *name == roots.match_all_symbol() || *name == roots.replace_symbol() ||
345 *name == roots.split_symbol() || *name == roots.to_primitive_symbol() ||
346 *name == roots.valueOf_string() || *name == roots.length_string();
347 DCHECK_EQ(maybe_protector, debug_maybe_protector);
348#endif // DEBUG
349
350 if (maybe_protector) {
351 InternalUpdateProtector(isolate, receiver, name);
352 }
353}
354
359
361 DCHECK(!holder_.is_null());
364 DCHECK(holder_->HasFastProperties(isolate_));
365 return number_;
366}
367
369 DCHECK(!holder_.is_null());
372 DCHECK(!holder_->HasFastProperties(isolate_));
373 return number_;
374}
375
376// static
378 Isolate* isolate, Configuration configuration, DirectHandle<Name> name) {
379 return (!name.is_null() && name->IsPrivate()) ? OWN_SKIP_INTERCEPTOR
380 : configuration;
381}
382
383// static
385 Isolate* isolate, DirectHandle<JSAny> lookup_start_object, size_t index,
386 Configuration configuration) {
387 if (IsJSReceiver(*lookup_start_object, isolate)) {
389 }
391 isolate, Cast<JSPrimitive>(lookup_start_object), index, configuration);
392}
393
394template <class T>
396 DCHECK(IsJSReceiver(*receiver_, isolate_));
397 if (IsJSGlobalProxy(*receiver_, isolate_)) {
398 Tagged<HeapObject> prototype =
399 Cast<JSGlobalProxy>(*receiver_)->map(isolate_)->prototype(isolate_);
400 if (IsJSGlobalObject(prototype, isolate_)) {
401 return direct_handle(Cast<JSGlobalObject>(prototype), isolate_);
402 }
403 }
404 return Cast<T>(receiver_);
405}
406
407template <bool is_element>
409 Tagged<JSObject> holder) const {
410 if (is_element && index_ <= JSObject::kMaxElementIndex) {
411 return holder->GetIndexedInterceptor(isolate_);
412 } else {
413 return holder->GetNamedInterceptor(isolate_);
414 }
415}
416
425
426} // namespace internal
427} // namespace v8
428
429#endif // V8_OBJECTS_LOOKUP_INL_H_
Isolate * isolate_
@ kExtendingNonExtensibleWithPrivate
Definition v8-isolate.h:626
Handle< String > SizeToString(size_t value, bool check_cache=true)
Definition factory.cc:3935
void CountUsage(v8::Isolate::UseCounterFeature feature)
Definition isolate.cc:7028
static constexpr uint32_t kMaxElementIndex
Definition js-objects.h:924
DirectHandle< UnionOf< Map, PropertyCell > > transition_
Definition lookup.h:372
uint32_t array_index() const
Definition lookup.h:161
LookupIterator(Isolate *isolate, DirectHandle< JSAny > receiver, DirectHandle< Name > name, Configuration configuration=DEFAULT)
Definition lookup-inl.h:26
DirectHandle< InterceptorInfo > GetInterceptor() const
Definition lookup-inl.h:417
Isolate * isolate() const
Definition lookup.h:155
static Configuration ComputeConfiguration(Isolate *isolate, Configuration configuration, DirectHandle< Name > name)
Definition lookup-inl.h:377
InternalIndex dictionary_entry() const
Definition lookup-inl.h:368
DirectHandle< T > GetStoreTarget() const
Definition lookup-inl.h:395
DirectHandle< Name > name_
Definition lookup.h:371
DirectHandle< JSReceiver > holder_
Definition lookup.h:374
Isolate *const isolate_
Definition lookup.h:370
static void InternalUpdateProtector(Isolate *isolate, DirectHandle< JSAny > receiver, DirectHandle< Name > name)
Definition lookup.cc:200
static MaybeDirectHandle< JSReceiver > GetRootForNonJSReceiver(Isolate *isolate, DirectHandle< JSPrimitive > lookup_start_object, size_t index, Configuration configuration)
Definition lookup.cc:146
DirectHandle< PropertyCell > transition_cell() const
Definition lookup-inl.h:277
const DirectHandle< JSAny > receiver_
Definition lookup.h:373
PropertyKey GetKey() const
Definition lookup-inl.h:254
static const size_t kInvalidIndex
Definition lookup.h:279
DirectHandle< T > GetHolder() const
Definition lookup-inl.h:283
DirectHandle< JSAny > lookup_start_object() const
Definition lookup.h:198
V8_EXPORT_PRIVATE void Start()
bool is_dictionary_holder() const
Definition lookup-inl.h:268
static MaybeDirectHandle< JSReceiver > GetRoot(Isolate *isolate, DirectHandle< JSAny > lookup_start_object, size_t index, Configuration configuration)
Definition lookup-inl.h:384
Factory * factory() const
Definition lookup.h:187
DirectHandle< Name > GetName()
Definition lookup-inl.h:246
InternalIndex descriptor_number() const
Definition lookup-inl.h:360
bool ExtendingNonExtensible(DirectHandle< JSReceiver > receiver)
Definition lookup-inl.h:288
DirectHandle< Name > name() const
Definition lookup-inl.h:241
DirectHandle< Map > transition_map() const
Definition lookup-inl.h:272
bool check_prototype_chain() const
Definition lookup.h:205
static V8_WARN_UNUSED_RESULT HandleType< Name >::MaybeType ToName(Isolate *isolate, HandleType< Object > input)
static bool ToIntegerIndex(Tagged< Object > obj, size_t *index)
DirectHandle< Name > name_
Definition lookup.h:53
PropertyKey(Isolate *isolate, double index)
Definition lookup-inl.h:136
size_t index() const
Definition lookup.h:42
DirectHandle< Name > GetName(Isolate *isolate)
Definition lookup-inl.h:233
V8_INLINE bool IsNameForProtector(Tagged< HeapObject > object) const
Definition roots-inl.h:131
Register const index_
Node * receiver_
TNode< Object > receiver
ZoneVector< RpoNumber > & result
const char * name_
bool IsNumber(Tagged< Object > obj)
V8_INLINE DirectHandle< T > direct_handle(Tagged< T > object, Isolate *isolate)
too high values may cause the compiler to set high thresholds for inlining to as much as possible avoid inlined allocation of objects that cannot escape trace load stores from virtual maglev objects use TurboFan fast string builder analyze liveness of environment slots and zap dead values trace TurboFan load elimination emit data about basic block usage in builtins to this enable builtin reordering when run mksnapshot flag for emit warnings when applying builtin profile data verify register allocation in TurboFan randomly schedule instructions to stress dependency tracking enable store store elimination in TurboFan rewrite far to near simulate GC compiler thread race related to allow float parameters to be passed in simulator mode JS Wasm Run additional turbo_optimize_inlined_js_wasm_wrappers enable experimental feedback collection in generic lowering enable Turboshaft s WasmLoadElimination enable Turboshaft s low level load elimination for JS enable Turboshaft s escape analysis for string concatenation use enable Turbolev features that we want to ship in the not too far future trace individual Turboshaft reduction steps trace intermediate Turboshaft reduction steps invocation count threshold for early optimization Enables optimizations which favor memory size over execution speed Enables sampling allocation profiler with X as a sample interval min size of a semi the new space consists of two semi spaces max size of the Collect garbage after Collect garbage after keeps maps alive for< n > old space garbage collections print one detailed trace line in name
Definition flags.cc:2086
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Definition casting.h:150
#define RCS_SCOPE(...)
#define CHECK(condition)
Definition logging.h:124
#define DCHECK_IMPLIES(v1, v2)
Definition logging.h:493
#define DCHECK_NE(v1, v2)
Definition logging.h:486
#define CHECK_EQ(lhs, rhs)
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_EQ(v1, v2)
Definition logging.h:485