v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
js-objects-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_JS_OBJECTS_INL_H_
6#define V8_OBJECTS_JS_OBJECTS_INL_H_
7
9// Include the non-inl header before the rest of the headers.
10
11#include <optional>
12
13#include "src/common/globals.h"
27#include "src/objects/keys.h"
33#include "src/objects/slots.h"
34#include "src/objects/smi-inl.h"
35#include "src/objects/string.h"
37
38// Has to be the last include (doesn't have include guards):
40
41namespace v8::internal {
42
43#include "torque-generated/src/objects/js-objects-tq-inl.inc"
44
47TQ_OBJECT_CONSTRUCTORS_IMPL(JSObjectWithEmbedderSlots)
48TQ_OBJECT_CONSTRUCTORS_IMPL(JSAPIObjectWithEmbedderSlots)
49TQ_OBJECT_CONSTRUCTORS_IMPL(JSCustomElementsObject)
50TQ_OBJECT_CONSTRUCTORS_IMPL(JSSpecialObject)
51TQ_OBJECT_CONSTRUCTORS_IMPL(JSAsyncFromSyncIterator)
53TQ_OBJECT_CONSTRUCTORS_IMPL(JSGlobalObject)
54TQ_OBJECT_CONSTRUCTORS_IMPL(JSGlobalProxy)
55JSIteratorResult::JSIteratorResult(Address ptr) : JSObject(ptr) {}
56TQ_OBJECT_CONSTRUCTORS_IMPL(JSMessageObject)
57TQ_OBJECT_CONSTRUCTORS_IMPL(JSPrimitiveWrapper)
58TQ_OBJECT_CONSTRUCTORS_IMPL(JSStringIterator)
59TQ_OBJECT_CONSTRUCTORS_IMPL(JSValidIteratorWrapper)
60
62
66
67Tagged<FixedArrayBase> JSObject::elements(RelaxedLoadTag tag) const {
68 PtrComprCageBase cage_base = GetPtrComprCageBase(*this);
69 return elements(cage_base, tag);
70}
71
72Tagged<FixedArrayBase> JSObject::elements(PtrComprCageBase cage_base,
73 RelaxedLoadTag) const {
75 *this);
76}
77
78void JSObject::set_elements(Tagged<FixedArrayBase> value,
79 WriteBarrierMode mode) {
80 // Note the relaxed atomic store.
82 CONDITIONAL_WRITE_BARRIER(*this, kElementsOffset, value, mode);
83}
84
85MaybeHandle<Object> JSReceiver::GetProperty(Isolate* isolate,
87 DirectHandle<Name> name) {
88 LookupIterator it(isolate, receiver, name, receiver);
89 if (!it.IsFound()) return it.factory()->undefined_value();
90 return Object::GetProperty(&it);
91}
92
93MaybeHandle<Object> JSReceiver::GetElement(Isolate* isolate,
95 uint32_t index) {
96 LookupIterator it(isolate, receiver, index, receiver);
97 if (!it.IsFound()) return it.factory()->undefined_value();
98 return Object::GetProperty(&it);
99}
100
101Handle<Object> JSReceiver::GetDataProperty(Isolate* isolate,
103 DirectHandle<Name> name) {
104 LookupIterator it(isolate, object, name, object,
105 LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
106 if (!it.IsFound()) return it.factory()->undefined_value();
107 return GetDataProperty(&it);
108}
109
110MaybeDirectHandle<JSPrototype> JSReceiver::GetPrototype(
112 // We don't expect access checks to be needed on JSProxy objects.
113 DCHECK(!IsAccessCheckNeeded(*receiver) || IsJSObject(*receiver));
114
116 PrototypeIterator::END_AT_NON_HIDDEN);
117 do {
118 if (!iter.AdvanceFollowingProxies()) return {};
119 } while (!iter.IsAtEnd());
120 return PrototypeIterator::GetCurrent(iter);
121}
122
123MaybeHandle<Object> JSReceiver::GetProperty(Isolate* isolate,
125 const char* name) {
126 DirectHandle<String> str = isolate->factory()->InternalizeUtf8String(name);
127 return GetProperty(isolate, receiver, str);
128}
129
130// static
132 Isolate* isolate, DirectHandle<JSReceiver> object) {
133 return KeyAccumulator::GetKeys(isolate, object, KeyCollectionMode::kOwnOnly,
135 GetKeysConversion::kConvertToString);
136}
137
138bool JSObject::PrototypeHasNoElements(Isolate* isolate,
139 Tagged<JSObject> object) {
141 Tagged<HeapObject> prototype = Cast<HeapObject>(object->map()->prototype());
142 ReadOnlyRoots roots(isolate);
143 Tagged<HeapObject> null = roots.null_value();
144 Tagged<FixedArrayBase> empty_fixed_array = roots.empty_fixed_array();
145 Tagged<FixedArrayBase> empty_slow_element_dictionary =
146 roots.empty_slow_element_dictionary();
147 while (prototype != null) {
148 Tagged<Map> map = prototype->map();
149 if (IsCustomElementsReceiverMap(map)) return false;
150 Tagged<FixedArrayBase> elements = Cast<JSObject>(prototype)->elements();
151 if (elements != empty_fixed_array &&
152 elements != empty_slow_element_dictionary) {
153 return false;
154 }
155 prototype = Cast<HeapObject>(map->prototype());
156 }
157 return true;
158}
159
160ACCESSORS(JSReceiver, raw_properties_or_hash, Tagged<Object>,
161 kPropertiesOrHashOffset)
162RELAXED_ACCESSORS(JSReceiver, raw_properties_or_hash, Tagged<Object>,
163 kPropertiesOrHashOffset)
164
165void JSObject::EnsureCanContainHeapObjectElements(
166 DirectHandle<JSObject> object) {
167 JSObject::ValidateElements(*object);
168 ElementsKind elements_kind = object->map()->elements_kind();
169 if (!IsObjectElementsKind(elements_kind)) {
170 if (IsHoleyElementsKind(elements_kind)) {
171 TransitionElementsKind(object, HOLEY_ELEMENTS);
172 } else {
173 TransitionElementsKind(object, PACKED_ELEMENTS);
174 }
175 }
176}
177
178template <typename TSlot>
179void JSObject::EnsureCanContainElements(DirectHandle<JSObject> object,
180 TSlot objects, uint32_t count,
181 EnsureElementsMode mode) {
182 static_assert(std::is_same<TSlot, FullObjectSlot>::value ||
183 std::is_same<TSlot, ObjectSlot>::value,
184 "Only ObjectSlot and FullObjectSlot are expected here");
185 ElementsKind current_kind = object->GetElementsKind();
186 ElementsKind target_kind = current_kind;
187 {
190 bool is_holey = IsHoleyElementsKind(current_kind);
191 if (current_kind == HOLEY_ELEMENTS) return;
192 Tagged<Object> the_hole = GetReadOnlyRoots().the_hole_value();
193#ifdef V8_ENABLE_EXPERIMENTAL_UNDEFINED_DOUBLE
194 Tagged<Undefined> undefined = GetReadOnlyRoots().undefined_value();
195#endif // V8_ENABLE_EXPERIMENTAL_UNDEFINED_DOUBLE
196 for (uint32_t i = 0; i < count; ++i, ++objects) {
197 Tagged<Object> current = *objects;
198 if (current == the_hole
199#ifdef V8_ENABLE_EXPERIMENTAL_UNDEFINED_DOUBLE
200 || current == undefined
201#endif // V8_ENABLE_EXPERIMENTAL_UNDEFINED_DOUBLE
202 ) {
203 is_holey = true;
204 target_kind = GetHoleyElementsKind(target_kind);
205 } else if (!IsSmi(current)) {
206 if (mode == ALLOW_CONVERTED_DOUBLE_ELEMENTS && IsNumber(current)) {
207 if (IsSmiElementsKind(target_kind)) {
208 if (is_holey) {
209 target_kind = HOLEY_DOUBLE_ELEMENTS;
210 } else {
211 target_kind = PACKED_DOUBLE_ELEMENTS;
212 }
213 }
214 } else if (is_holey) {
215 target_kind = HOLEY_ELEMENTS;
216 break;
217 } else {
218 target_kind = PACKED_ELEMENTS;
219 }
220 }
221 }
222 }
223 if (target_kind != current_kind) {
224 TransitionElementsKind(object, target_kind);
225 }
226}
227
228void JSObject::EnsureCanContainElements(DirectHandle<JSObject> object,
230 uint32_t length,
231 EnsureElementsMode mode) {
233 if (elements->map() != roots.fixed_double_array_map()) {
234 DCHECK(elements->map() == roots.fixed_array_map() ||
235 elements->map() == roots.fixed_cow_array_map());
236 if (mode == ALLOW_COPIED_DOUBLE_ELEMENTS) {
238 }
239 ObjectSlot objects = Cast<FixedArray>(elements)->RawFieldOfFirstElement();
240 EnsureCanContainElements(object, objects, length, mode);
241 return;
242 }
243
245 if (object->GetElementsKind() == HOLEY_SMI_ELEMENTS) {
246 TransitionElementsKind(object, HOLEY_DOUBLE_ELEMENTS);
247 } else if (object->GetElementsKind() == PACKED_SMI_ELEMENTS) {
248 auto double_array = Cast<FixedDoubleArray>(elements);
249 for (uint32_t i = 0; i < length; ++i) {
250 if (double_array->is_the_hole(i)) {
251 TransitionElementsKind(object, HOLEY_DOUBLE_ELEMENTS);
252 return;
253 }
254 }
255 TransitionElementsKind(object, PACKED_DOUBLE_ELEMENTS);
256 }
257}
258
259void JSObject::SetMapAndElements(DirectHandle<JSObject> object,
260 DirectHandle<Map> new_map,
262 Isolate* isolate = object->GetIsolate();
263 JSObject::MigrateToMap(isolate, object, new_map);
264 DCHECK((object->map()->has_fast_smi_or_object_elements() ||
265 (*value == ReadOnlyRoots(isolate).empty_fixed_array()) ||
266 object->map()->has_fast_string_wrapper_elements()) ==
267 (value->map() == ReadOnlyRoots(isolate).fixed_array_map() ||
268 value->map() == ReadOnlyRoots(isolate).fixed_cow_array_map()));
269 DCHECK((*value == ReadOnlyRoots(isolate).empty_fixed_array()) ||
270 (object->map()->has_fast_double_elements() ==
271 IsFixedDoubleArray(*value)));
272 object->set_elements(*value);
273}
274
275void JSObject::initialize_elements() {
276 Tagged<FixedArrayBase> elements = map()->GetInitialElements();
277 set_elements(elements, SKIP_WRITE_BARRIER);
278}
279
281 return map(cage_base)->GetIndexedInterceptor(cage_base);
282}
283
285 return map(cage_base)->GetNamedInterceptor(cage_base);
286}
287
288// static
289int JSObject::GetHeaderSize(Tagged<Map> map) {
290 // Check for the most common kind of JavaScript object before
291 // falling into the generic switch. This speeds up the internal
292 // field operations considerably on average.
293 InstanceType instance_type = map->instance_type();
294 return instance_type == JS_OBJECT_TYPE
295 ? JSObject::kHeaderSize
296 : GetHeaderSize(instance_type, map->has_prototype_slot());
297}
298
299// static
300int JSObject::GetEmbedderFieldsStartOffset(Tagged<Map> map) {
301 // Embedder fields are located after the object header.
302 return GetHeaderSize(map);
303}
304
305int JSObject::GetEmbedderFieldsStartOffset() {
306 return GetEmbedderFieldsStartOffset(map());
307}
308
309// static
310bool JSObject::MayHaveEmbedderFields(Tagged<Map> map) {
311 InstanceType instance_type = map->instance_type();
312 // TODO(v8) It'd be nice if all objects with embedder data slots inherited
313 // from JSObjectJSAPIObjectWithEmbedderSlotsWithEmbedderSlots, but this is
314 // currently not possible due to instance_type constraints.
315 return InstanceTypeChecker::IsJSObjectWithEmbedderSlots(instance_type) ||
316 InstanceTypeChecker::IsJSAPIObjectWithEmbedderSlots(instance_type) ||
317 InstanceTypeChecker::IsJSSpecialObject(instance_type);
318}
319
320bool JSObject::MayHaveEmbedderFields() const {
321 return MayHaveEmbedderFields(map());
322}
323
324// static
325int JSObject::GetEmbedderFieldCount(Tagged<Map> map) {
326 int instance_size = map->instance_size();
327 if (instance_size == kVariableSizeSentinel) return 0;
328 // Embedder fields are located after the object header, whereas in-object
329 // properties are located at the end of the object. We don't have to round up
330 // the header size here because division by kEmbedderDataSlotSizeInTaggedSlots
331 // will swallow potential padding in case of (kTaggedSize !=
332 // kSystemPointerSize) anyway.
333 return (((instance_size - GetEmbedderFieldsStartOffset(map)) >>
335 map->GetInObjectProperties()) /
337}
338
339int JSObject::GetEmbedderFieldCount() const {
340 return GetEmbedderFieldCount(map());
341}
342
343int JSObject::GetEmbedderFieldOffset(int index) {
344 DCHECK_LT(static_cast<unsigned>(index),
345 static_cast<unsigned>(GetEmbedderFieldCount()));
346 return GetEmbedderFieldsStartOffset() + (kEmbedderDataSlotSize * index);
347}
348
349Tagged<Object> JSObject::GetEmbedderField(int index) {
350 return EmbedderDataSlot(Tagged(*this), index).load_tagged();
351}
352
353void JSObject::SetEmbedderField(int index, Tagged<Object> value) {
354 EmbedderDataSlot::store_tagged(Tagged(*this), index, value);
355}
356
357void JSObject::SetEmbedderField(int index, Tagged<Smi> value) {
358 EmbedderDataSlot(Tagged(*this), index).store_smi(value);
359}
360
361// static
362bool JSObject::IsDroppableApiObject(const Tagged<Map> map) {
363 auto instance_type = map->instance_type();
364 return InstanceTypeChecker::IsJSApiObject(instance_type) ||
365 instance_type == JS_SPECIAL_API_OBJECT_TYPE;
366}
367
368bool JSObject::IsDroppableApiObject() const {
369 return IsDroppableApiObject(map());
370}
371
372// Access fast-case object properties at index. The use of these routines
373// is needed to correctly distinguish between properties stored in-object and
374// properties stored in the properties array.
375Tagged<JSAny> JSObject::RawFastPropertyAt(FieldIndex index) const {
376 PtrComprCageBase cage_base = GetPtrComprCageBase(*this);
377 return RawFastPropertyAt(cage_base, index);
378}
379
380Tagged<JSAny> JSObject::RawFastPropertyAt(PtrComprCageBase cage_base,
381 FieldIndex index) const {
382 if (index.is_inobject()) {
383 return TaggedField<JSAny>::Relaxed_Load(cage_base, *this, index.offset());
384 } else {
385 return property_array(cage_base)->get(cage_base,
386 index.outobject_array_index());
387 }
388}
389
390// The SeqCst versions of RawFastPropertyAt are used for atomically accessing
391// shared struct fields.
392Tagged<JSAny> JSObject::RawFastPropertyAt(FieldIndex index,
393 SeqCstAccessTag tag) const {
394 PtrComprCageBase cage_base = GetPtrComprCageBase(*this);
395 return RawFastPropertyAt(cage_base, index, tag);
396}
397
398Tagged<JSAny> JSObject::RawFastPropertyAt(PtrComprCageBase cage_base,
399 FieldIndex index,
400 SeqCstAccessTag tag) const {
401 if (index.is_inobject()) {
402 return TaggedField<JSAny>::SeqCst_Load(cage_base, *this, index.offset());
403 } else {
404 return property_array(cage_base)->get(cage_base,
405 index.outobject_array_index(), tag);
406 }
407}
408
409std::optional<Tagged<Object>> JSObject::RawInobjectPropertyAt(
410 PtrComprCageBase cage_base, Tagged<Map> original_map,
411 FieldIndex index) const {
412 CHECK(index.is_inobject());
413
414 // This method implements a "snapshot" protocol to protect against reading out
415 // of bounds of an object. It's used to access a fast in-object property from
416 // a background thread with no locking. That caller does have the guarantee
417 // that a garbage collection cannot happen during its query. However, it must
418 // contend with the main thread altering the object in heavy ways through
419 // object migration. Specifically, the object can get smaller. Initially, this
420 // may seem benign, because object migration fills the freed-up space with
421 // FillerMap words which, even though they offer wrong values, are at
422 // least tagged values.
423
424 // However, there is an additional danger. Sweeper threads may discover the
425 // filler words and offer that space to the main thread for allocation. Should
426 // a HeapNumber be allocated into that space while we're reading a property at
427 // that location (from our out-of-date information), we risk interpreting a
428 // double value as a pointer. This must be prevented.
429 //
430 // We do this by:
431 //
432 // a) Reading the map first
433 // b) Reading the property with acquire semantics (but do not inspect it!)
434 // c) Re-read the map with acquire semantics.
435 //
436 // Only if the maps match can the property be inspected. It may have a "wrong"
437 // value, but it will be within the bounds of the objects instance size as
438 // given by the map and it will be a valid Smi or object pointer.
439 Tagged<Object> maybe_tagged_object =
440 TaggedField<Object>::Acquire_Load(cage_base, *this, index.offset());
441 if (original_map != map(cage_base, kAcquireLoad)) return {};
442 return maybe_tagged_object;
443}
444
445void JSObject::RawFastInobjectPropertyAtPut(FieldIndex index,
446 Tagged<Object> value,
447 WriteBarrierMode mode) {
448 DCHECK(index.is_inobject());
449 int offset = index.offset();
450 RELAXED_WRITE_FIELD(*this, offset, value);
451 CONDITIONAL_WRITE_BARRIER(*this, offset, value, mode);
452}
453
454void JSObject::RawFastInobjectPropertyAtPut(FieldIndex index,
455 Tagged<Object> value,
456 SeqCstAccessTag tag) {
457 DCHECK(index.is_inobject());
458 DCHECK(IsShared(value));
459 SEQ_CST_WRITE_FIELD(*this, index.offset(), value);
460 CONDITIONAL_WRITE_BARRIER(*this, index.offset(), value, UPDATE_WRITE_BARRIER);
461}
462
463void JSObject::FastPropertyAtPut(FieldIndex index, Tagged<Object> value,
464 WriteBarrierMode mode) {
465 if (index.is_inobject()) {
466 RawFastInobjectPropertyAtPut(index, value, mode);
467 } else {
469 property_array()->set(index.outobject_array_index(), value);
470 }
471}
472
473void JSObject::FastPropertyAtPut(FieldIndex index, Tagged<Object> value,
474 SeqCstAccessTag tag) {
475 if (index.is_inobject()) {
476 RawFastInobjectPropertyAtPut(index, value, tag);
477 } else {
478 property_array()->set(index.outobject_array_index(), value, tag);
479 }
480}
481
482void JSObject::WriteToField(InternalIndex descriptor, PropertyDetails details,
483 Tagged<Object> value) {
484 DCHECK_EQ(PropertyLocation::kField, details.location());
485 DCHECK_EQ(PropertyKind::kData, details.kind());
487 FieldIndex index = FieldIndex::ForDetails(map(), details);
488 if (details.representation().IsDouble()) {
489 // Manipulating the signaling NaN used for the hole and uninitialized
490 // double field sentinel in C++, e.g. with base::bit_cast or
491 // value()/set_value(), will change its value on ia32 (the x87 stack is used
492 // to return values and stores to the stack silently clear the signalling
493 // bit).
494 uint64_t bits;
495 if (IsSmi(value)) {
496 bits = base::bit_cast<uint64_t>(static_cast<double>(Smi::ToInt(value)));
497 } else if (IsUninitialized(value)) {
498 bits = kHoleNanInt64;
499 } else {
500 DCHECK(IsHeapNumber(value));
501 bits = Cast<HeapNumber>(value)->value_as_bits();
502 }
503 auto box = Cast<HeapNumber>(RawFastPropertyAt(index));
504 box->set_value_as_bits(bits);
505 } else {
506 FastPropertyAtPut(index, value);
507 }
508}
509
510Tagged<Object> JSObject::RawFastInobjectPropertyAtSwap(FieldIndex index,
511 Tagged<Object> value,
512 SeqCstAccessTag tag) {
513 DCHECK(index.is_inobject());
514 DCHECK(IsShared(value));
515 int offset = index.offset();
516 Tagged<Object> old_value = SEQ_CST_SWAP_FIELD(*this, offset, value);
518 return old_value;
519}
520
521Tagged<Object> JSObject::RawFastPropertyAtSwap(FieldIndex index,
522 Tagged<Object> value,
523 SeqCstAccessTag tag) {
524 if (index.is_inobject()) {
525 return RawFastInobjectPropertyAtSwap(index, value, tag);
526 }
527 return property_array()->Swap(index.outobject_array_index(), value, tag);
528}
529
530Tagged<Object> JSObject::RawFastInobjectPropertyAtCompareAndSwap(
531 FieldIndex index, Tagged<Object> expected, Tagged<Object> value,
532 SeqCstAccessTag tag) {
533 DCHECK(index.is_inobject());
534 DCHECK(IsShared(value));
535 Tagged<Object> previous_value =
536 SEQ_CST_COMPARE_AND_SWAP_FIELD(*this, index.offset(), expected, value);
537 if (previous_value == expected) {
538 CONDITIONAL_WRITE_BARRIER(*this, index.offset(), value,
540 }
541 return previous_value;
542}
543
544Tagged<Object> JSObject::RawFastPropertyAtCompareAndSwapInternal(
545 FieldIndex index, Tagged<Object> expected, Tagged<Object> value,
546 SeqCstAccessTag tag) {
547 if (index.is_inobject()) {
548 return RawFastInobjectPropertyAtCompareAndSwap(index, expected, value, tag);
549 }
550 return property_array()->CompareAndSwap(index.outobject_array_index(),
551 expected, value, tag);
552}
553
554int JSObject::GetInObjectPropertyOffset(int index) {
555 return map()->GetInObjectPropertyOffset(index);
556}
557
558Tagged<Object> JSObject::InObjectPropertyAt(int index) {
559 int offset = GetInObjectPropertyOffset(index);
560 return TaggedField<Object>::load(*this, offset);
561}
562
563Tagged<Object> JSObject::InObjectPropertyAtPut(int index, Tagged<Object> value,
564 WriteBarrierMode mode) {
565 // Adjust for the number of properties stored in the object.
566 int offset = GetInObjectPropertyOffset(index);
567 WRITE_FIELD(*this, offset, value);
568 CONDITIONAL_WRITE_BARRIER(*this, offset, value, mode);
569 return value;
570}
571
572void JSObject::InitializeBody(Tagged<Map> map, int start_offset,
573 bool is_slack_tracking_in_progress,
574 MapWord filler_map,
575 Tagged<Object> undefined_filler) {
576 int size = map->instance_size();
577 int offset = start_offset;
578
579 // embedder data slots need to be initialized separately
580 if (MayHaveEmbedderFields(map)) {
581 int embedder_field_start = GetEmbedderFieldsStartOffset(map);
582 int embedder_field_count = GetEmbedderFieldCount(map);
583
584 // fill start with references to the undefined value object
585 DCHECK_LE(offset, embedder_field_start);
586 while (offset < embedder_field_start) {
587 WRITE_FIELD(*this, offset, undefined_filler);
589 }
590
591 // initialize embedder data slots
592 DCHECK_EQ(offset, embedder_field_start);
593 for (int i = 0; i < embedder_field_count; i++) {
594 // TODO(v8): consider initializing embedded data slots with Smi::zero().
595 EmbedderDataSlot(Tagged<JSObject>(*this), i).Initialize(undefined_filler);
597 }
598 } else {
599 DCHECK_EQ(0, GetEmbedderFieldCount(map));
600 }
601
602 DCHECK_LE(offset, size);
603 if (is_slack_tracking_in_progress) {
604 int end_of_pre_allocated_offset =
605 size - (map->UnusedPropertyFields() * kTaggedSize);
606 DCHECK_LE(kHeaderSize, end_of_pre_allocated_offset);
607 DCHECK_LE(offset, end_of_pre_allocated_offset);
608 // fill pre allocated slots with references to the undefined value object
609 while (offset < end_of_pre_allocated_offset) {
610 WRITE_FIELD(*this, offset, undefined_filler);
612 }
613 // fill the remainder with one word filler objects (ie just a map word)
614 while (offset < size) {
615 Tagged<Object> fm = Tagged<Object>(filler_map.ptr());
616 WRITE_FIELD(*this, offset, fm);
618 }
619 } else {
620 while (offset < size) {
621 // fill everything with references to the undefined value object
622 WRITE_FIELD(*this, offset, undefined_filler);
624 }
625 }
626}
627
628template <typename T, template <typename> typename HandleType>
629 requires(std::is_convertible_v<HandleType<T>, DirectHandle<T>>)
630inline typename HandleType<Object>::MaybeType
631JSObject::DefineOwnPropertyIgnoreAttributes(LookupIterator* it,
632 HandleType<T> value,
633 PropertyAttributes attributes,
634 AccessorInfoHandling handling,
635 EnforceDefineSemantics semantics) {
636 MAYBE_RETURN_NULL(DefineOwnPropertyIgnoreAttributes(
637 it, value, attributes, Just(ShouldThrow::kThrowOnError), handling,
638 semantics));
639 return value;
640}
641
643
645 kExternalObjectValueTag)
646
647JSApiWrapper::JSApiWrapper(Tagged<JSObject> object) : object_(object) {
649}
650
651template <CppHeapPointerTag lower_bound, CppHeapPointerTag upper_bound>
652void* JSApiWrapper::GetCppHeapWrappable(
653 IsolateForPointerCompression isolate) const {
654 return reinterpret_cast<void*>(
655 object_->ReadCppHeapPointerField<lower_bound, upper_bound>(
656 kCppHeapWrappableOffset, isolate));
657}
658
659void* JSApiWrapper::GetCppHeapWrappable(
661 CppHeapPointerTagRange tag_range) const {
662 return reinterpret_cast<void*>(object_->ReadCppHeapPointerField(
663 kCppHeapWrappableOffset, isolate, tag_range));
664}
665
666template <CppHeapPointerTag tag>
667void JSApiWrapper::SetCppHeapWrappable(IsolateForPointerCompression isolate,
668 void* instance) {
669 object_->WriteLazilyInitializedCppHeapPointerField<tag>(
670 JSAPIObjectWithEmbedderSlots::kCppHeapWrappableOffset, isolate,
671 reinterpret_cast<Address>(instance));
672 WriteBarrier::ForCppHeapPointer(
673 object_,
674 object_->RawCppHeapPointerField(
675 JSAPIObjectWithEmbedderSlots::kCppHeapWrappableOffset),
676 instance);
677}
678
679void JSApiWrapper::SetCppHeapWrappable(IsolateForPointerCompression isolate,
680 void* instance, CppHeapPointerTag tag) {
681 object_->WriteLazilyInitializedCppHeapPointerField(
682 JSAPIObjectWithEmbedderSlots::kCppHeapWrappableOffset, isolate,
683 reinterpret_cast<Address>(instance), tag);
684 WriteBarrier::ForCppHeapPointer(
685 object_,
686 object_->RawCppHeapPointerField(
687 JSAPIObjectWithEmbedderSlots::kCppHeapWrappableOffset),
688 instance);
689}
690
691bool JSMessageObject::DidEnsureSourcePositionsAvailable() const {
692 return shared_info() == Smi::zero();
693}
694
695// static
696void JSMessageObject::EnsureSourcePositionsAvailable(
697 Isolate* isolate, DirectHandle<JSMessageObject> message) {
698 if (message->DidEnsureSourcePositionsAvailable()) {
699 DCHECK(message->script()->has_line_ends());
700 } else {
701 JSMessageObject::InitializeSourcePositions(isolate, message);
702 }
703}
704
705int JSMessageObject::GetStartPosition() const {
706 // TODO(cbruni): make this DCHECK stricter (>= 0).
707 DCHECK_LE(-1, start_position());
708 return start_position();
709}
710
711int JSMessageObject::GetEndPosition() const {
712 // TODO(cbruni): make this DCHECK stricter (>= 0).
713 DCHECK_LE(-1, end_position());
714 return end_position();
715}
716
717MessageTemplate JSMessageObject::type() const {
718 return MessageTemplateFromInt(raw_type());
719}
720
721void JSMessageObject::set_type(MessageTemplate value) {
722 set_raw_type(static_cast<int>(value));
723}
724
725ACCESSORS(JSMessageObject, shared_info, Tagged<Object>, kSharedInfoOffset)
726ACCESSORS(JSMessageObject, bytecode_offset, Tagged<Smi>, kBytecodeOffsetOffset)
727SMI_ACCESSORS(JSMessageObject, start_position, kStartPositionOffset)
728SMI_ACCESSORS(JSMessageObject, end_position, kEndPositionOffset)
729SMI_ACCESSORS(JSMessageObject, error_level, kErrorLevelOffset)
730SMI_ACCESSORS(JSMessageObject, raw_type, kMessageTypeOffset)
731
732DEF_GETTER(JSObject, GetElementsKind, ElementsKind) {
733 ElementsKind kind = map(cage_base)->elements_kind();
734#if VERIFY_HEAP && DEBUG
735 Tagged<FixedArrayBase> fixed_array = UncheckedCast<FixedArrayBase>(
737
738 // If a GC was caused while constructing this object, the elements
739 // pointer may point to a one pointer filler map.
740 if (ElementsAreSafeToExamine(cage_base)) {
741 Tagged<Map> map = fixed_array->map();
743 CHECK(map == GetReadOnlyRoots().fixed_array_map() ||
744 map == GetReadOnlyRoots().fixed_cow_array_map());
745 } else if (IsDoubleElementsKind(kind)) {
746 CHECK(IsFixedDoubleArray(fixed_array, cage_base) ||
747 fixed_array == GetReadOnlyRoots().empty_fixed_array());
748 } else if (kind == DICTIONARY_ELEMENTS) {
749 CHECK(IsFixedArray(fixed_array, cage_base));
750 CHECK(IsNumberDictionary(fixed_array, cage_base));
751 } else {
753 }
755 IsSloppyArgumentsElements(elements(cage_base)));
756 }
757#endif
758 return kind;
759}
760
761DEF_GETTER(JSObject, GetElementsAccessor, ElementsAccessor*) {
762 return ElementsAccessor::ForKind(GetElementsKind(cage_base));
763}
764
765DEF_GETTER(JSObject, HasObjectElements, bool) {
766 return IsObjectElementsKind(GetElementsKind(cage_base));
767}
768
769DEF_GETTER(JSObject, HasSmiElements, bool) {
770 return IsSmiElementsKind(GetElementsKind(cage_base));
771}
772
773DEF_GETTER(JSObject, HasSmiOrObjectElements, bool) {
774 return IsSmiOrObjectElementsKind(GetElementsKind(cage_base));
775}
776
777DEF_GETTER(JSObject, HasDoubleElements, bool) {
778 return IsDoubleElementsKind(GetElementsKind(cage_base));
779}
780
781DEF_GETTER(JSObject, HasHoleyElements, bool) {
782 return IsHoleyElementsKind(GetElementsKind(cage_base));
783}
784
785DEF_GETTER(JSObject, HasFastElements, bool) {
786 return IsFastElementsKind(GetElementsKind(cage_base));
787}
788
789DEF_GETTER(JSObject, HasFastPackedElements, bool) {
790 return IsFastPackedElementsKind(GetElementsKind(cage_base));
791}
792
793DEF_GETTER(JSObject, HasDictionaryElements, bool) {
794 return IsDictionaryElementsKind(GetElementsKind(cage_base));
795}
796
797DEF_GETTER(JSObject, HasPackedElements, bool) {
798 return GetElementsKind(cage_base) == PACKED_ELEMENTS;
799}
800
801DEF_GETTER(JSObject, HasAnyNonextensibleElements, bool) {
802 return IsAnyNonextensibleElementsKind(GetElementsKind(cage_base));
803}
804
805DEF_GETTER(JSObject, HasSealedElements, bool) {
806 return IsSealedElementsKind(GetElementsKind(cage_base));
807}
808
809DEF_GETTER(JSObject, HasSharedArrayElements, bool) {
810 return GetElementsKind(cage_base) == SHARED_ARRAY_ELEMENTS;
811}
812
813DEF_GETTER(JSObject, HasNonextensibleElements, bool) {
814 return IsNonextensibleElementsKind(GetElementsKind(cage_base));
815}
816
817DEF_GETTER(JSObject, HasFastArgumentsElements, bool) {
818 return IsFastArgumentsElementsKind(GetElementsKind(cage_base));
819}
820
821DEF_GETTER(JSObject, HasSlowArgumentsElements, bool) {
822 return IsSlowArgumentsElementsKind(GetElementsKind(cage_base));
823}
824
825DEF_GETTER(JSObject, HasSloppyArgumentsElements, bool) {
826 return IsSloppyArgumentsElementsKind(GetElementsKind(cage_base));
827}
828
829DEF_GETTER(JSObject, HasStringWrapperElements, bool) {
830 return IsStringWrapperElementsKind(GetElementsKind(cage_base));
831}
832
833DEF_GETTER(JSObject, HasFastStringWrapperElements, bool) {
834 return GetElementsKind(cage_base) == FAST_STRING_WRAPPER_ELEMENTS;
835}
836
837DEF_GETTER(JSObject, HasSlowStringWrapperElements, bool) {
838 return GetElementsKind(cage_base) == SLOW_STRING_WRAPPER_ELEMENTS;
839}
840
841DEF_GETTER(JSObject, HasTypedArrayOrRabGsabTypedArrayElements, bool) {
842 DCHECK(!elements(cage_base).is_null());
843 return map(cage_base)->has_typed_array_or_rab_gsab_typed_array_elements();
844}
845
846#define FIXED_TYPED_ELEMENTS_CHECK(Type, type, TYPE, ctype) \
847 DEF_GETTER(JSObject, HasFixed##Type##Elements, bool) { \
848 return map(cage_base)->elements_kind() == TYPE##_ELEMENTS; \
849 }
850
852
853#undef FIXED_TYPED_ELEMENTS_CHECK
854
855DEF_GETTER(JSObject, HasNamedInterceptor, bool) {
856 return map(cage_base)->has_named_interceptor();
857}
858
859DEF_GETTER(JSObject, HasIndexedInterceptor, bool) {
860 return map(cage_base)->has_indexed_interceptor();
861}
862
865 kPropertiesOrHashOffset,
866 !HasFastProperties(cage_base), true)
867
869 DCHECK(HasDictionaryElements(cage_base) ||
870 HasSlowStringWrapperElements(cage_base));
871 return Cast<NumberDictionary>(elements(cage_base));
872}
873
874void JSReceiver::initialize_properties(Isolate* isolate) {
875 ReadOnlyRoots roots(isolate);
876 DCHECK(!HeapLayout::InYoungGeneration(roots.empty_fixed_array()));
877 DCHECK(!HeapLayout::InYoungGeneration(roots.empty_property_dictionary()));
878 DCHECK(!HeapLayout::InYoungGeneration(
879 roots.empty_ordered_property_dictionary()));
880 if (map(isolate)->is_dictionary_map()) {
882 WRITE_FIELD(*this, kPropertiesOrHashOffset,
883 roots.empty_swiss_property_dictionary());
884 } else {
885 WRITE_FIELD(*this, kPropertiesOrHashOffset,
886 roots.empty_property_dictionary());
887 }
888 } else {
889 WRITE_FIELD(*this, kPropertiesOrHashOffset, roots.empty_fixed_array());
890 }
891}
892
893DEF_GETTER(JSReceiver, HasFastProperties, bool) {
894 Tagged<Object> raw_properties_or_hash_obj =
895 raw_properties_or_hash(cage_base, kRelaxedLoad);
896 DCHECK(IsSmi(raw_properties_or_hash_obj) ||
897 ((IsGlobalDictionary(raw_properties_or_hash_obj, cage_base) ||
898 IsPropertyDictionary(raw_properties_or_hash_obj, cage_base)) ==
899 map(cage_base)->is_dictionary_map()));
900 USE(raw_properties_or_hash_obj);
901 return !map(cage_base)->is_dictionary_map();
902}
903
905 DCHECK(!IsJSGlobalObject(*this, cage_base));
906 DCHECK(!HasFastProperties(cage_base));
908
909 Tagged<Object> prop = raw_properties_or_hash(cage_base);
910 if (IsSmi(prop)) {
911 return GetReadOnlyRoots().empty_property_dictionary();
912 }
913 return Cast<NameDictionary>(prop);
914}
915
917 DCHECK(!IsJSGlobalObject(*this, cage_base));
918 DCHECK(!HasFastProperties(cage_base));
920
921 Tagged<Object> prop = raw_properties_or_hash(cage_base);
922 if (IsSmi(prop)) {
923 return GetReadOnlyRoots().empty_swiss_property_dictionary();
924 }
925 return Cast<SwissNameDictionary>(prop);
926}
927
928// TODO(gsathya): Pass isolate directly to this function and access
929// the heap from this.
931 DCHECK(HasFastProperties(cage_base));
932 Tagged<Object> prop = raw_properties_or_hash(cage_base);
933 if (IsSmi(prop) || prop == GetReadOnlyRoots().empty_fixed_array()) {
934 return GetReadOnlyRoots().empty_property_array();
935 }
936 return Cast<PropertyArray>(prop);
937}
938
939std::optional<Tagged<NativeContext>> JSReceiver::GetCreationContext() {
941 Tagged<Map> meta_map = map()->map();
942 DCHECK(IsMapMap(meta_map));
943 Tagged<Object> maybe_native_context = meta_map->native_context_or_null();
944 if (IsNull(maybe_native_context)) return {};
945 DCHECK(IsNativeContext(maybe_native_context));
946 return Cast<NativeContext>(maybe_native_context);
947}
948
949MaybeDirectHandle<NativeContext> JSReceiver::GetCreationContext(
950 Isolate* isolate) {
952 std::optional<Tagged<NativeContext>> maybe_context = GetCreationContext();
953 if (!maybe_context.has_value()) return {};
954 return direct_handle(maybe_context.value(), isolate);
955}
956
957Maybe<bool> JSReceiver::HasProperty(Isolate* isolate,
959 DirectHandle<Name> name) {
960 return HasPropertyOrElement(isolate, object, PropertyKey(isolate, name));
961}
962
963Maybe<bool> JSReceiver::HasElement(Isolate* isolate,
965 uint32_t index) {
966 LookupIterator it(isolate, object, index, object);
967 return HasProperty(&it);
968}
969
970Maybe<bool> JSReceiver::HasPropertyOrElement(Isolate* isolate,
973 LookupIterator it(isolate, object, key, object);
974 return HasProperty(&it);
975}
976
977Maybe<bool> JSReceiver::HasOwnProperty(Isolate* isolate,
979 uint32_t index) {
980 if (IsJSObject(*object)) { // Shortcut.
981 LookupIterator it(isolate, object, index, object, LookupIterator::OWN);
982 return HasProperty(&it);
983 }
984
985 Maybe<PropertyAttributes> attributes =
986 JSReceiver::GetOwnPropertyAttributes(isolate, object, index);
987 MAYBE_RETURN(attributes, Nothing<bool>());
988 return Just(attributes.FromJust() != ABSENT);
989}
990
991Maybe<PropertyAttributes> JSReceiver::GetPropertyAttributes(
992 Isolate* isolate, DirectHandle<JSReceiver> object,
993 DirectHandle<Name> name) {
994 PropertyKey key(isolate, name);
995 LookupIterator it(isolate, object, key, object);
996 return GetPropertyAttributes(&it);
997}
998
999Maybe<PropertyAttributes> JSReceiver::GetOwnPropertyAttributes(
1000 Isolate* isolate, DirectHandle<JSReceiver> object,
1001 DirectHandle<Name> name) {
1002 PropertyKey key(isolate, name);
1003 LookupIterator it(isolate, object, key, object, LookupIterator::OWN);
1004 return GetPropertyAttributes(&it);
1005}
1006
1007Maybe<PropertyAttributes> JSReceiver::GetOwnPropertyAttributes(
1008 Isolate* isolate, DirectHandle<JSReceiver> object, uint32_t index) {
1009 LookupIterator it(isolate, object, index, object, LookupIterator::OWN);
1010 return GetPropertyAttributes(&it);
1011}
1012
1013Maybe<PropertyAttributes> JSReceiver::GetElementAttributes(
1014 Isolate* isolate, DirectHandle<JSReceiver> object, uint32_t index) {
1015 LookupIterator it(isolate, object, index, object);
1016 return GetPropertyAttributes(&it);
1017}
1018
1019Maybe<PropertyAttributes> JSReceiver::GetOwnElementAttributes(
1020 Isolate* isolate, DirectHandle<JSReceiver> object, uint32_t index) {
1021 LookupIterator it(isolate, object, index, object, LookupIterator::OWN);
1022 return GetPropertyAttributes(&it);
1023}
1024
1025Tagged<NativeContext> JSGlobalObject::native_context() {
1026 return *GetCreationContext();
1027}
1028
1029bool JSGlobalObject::IsDetached() {
1030 return global_proxy()->IsDetachedFrom(*this);
1031}
1032
1033bool JSGlobalProxy::IsDetachedFrom(Tagged<JSGlobalObject> global) const {
1034 const PrototypeIterator iter(this->GetIsolate(), Tagged<JSReceiver>(*this));
1035 return iter.GetCurrent() != global;
1036}
1037
1038inline int JSGlobalProxy::SizeWithEmbedderFields(int embedder_field_count) {
1039 DCHECK_GE(embedder_field_count, 0);
1040 return kHeaderSize + embedder_field_count * kEmbedderDataSlotSize;
1041}
1042
1043ACCESSORS(JSIteratorResult, value, Tagged<Object>, kValueOffset)
1044ACCESSORS(JSIteratorResult, done, Tagged<Object>, kDoneOffset)
1045
1046// If the fast-case backing storage takes up much more memory than a dictionary
1047// backing storage would, the object should have slow elements.
1048// static
1049static inline bool ShouldConvertToSlowElements(uint32_t used_elements,
1050 uint32_t new_capacity) {
1051 uint32_t size_threshold = NumberDictionary::kPreferFastElementsSizeFactor *
1052 NumberDictionary::ComputeCapacity(used_elements) *
1053 NumberDictionary::kEntrySize;
1054 return size_threshold <= new_capacity;
1055}
1056
1058 uint32_t capacity,
1059 uint32_t index,
1060 uint32_t* new_capacity) {
1061 static_assert(JSObject::kMaxUncheckedOldFastElementsLength <=
1062 JSObject::kMaxUncheckedFastElementsLength);
1063 if (index < capacity) {
1064 *new_capacity = capacity;
1065 return false;
1066 }
1067 if (index - capacity >= JSObject::kMaxGap) return true;
1068 *new_capacity = JSObject::NewElementsCapacity(index + 1);
1069 DCHECK_LT(index, *new_capacity);
1070 if (*new_capacity <= JSObject::kMaxUncheckedOldFastElementsLength ||
1071 (*new_capacity <= JSObject::kMaxUncheckedFastElementsLength &&
1072 HeapLayout::InYoungGeneration(object))) {
1073 return false;
1074 }
1075 return ShouldConvertToSlowElements(object->GetFastElementsUsage(),
1076 *new_capacity);
1077}
1078
1079} // namespace v8::internal
1080
1082
1083#endif // V8_OBJECTS_JS_OBJECTS_INL_H_
Builtins::Kind kind
Definition builtins.cc:40
V8_INLINE T FromJust() const &
Definition v8-maybe.h:64
V8_INLINE void store_smi(Tagged< Smi > value)
V8_INLINE Tagged< Object > load_tagged() const
V8_INLINE void Initialize(Tagged< Object > initial_value)
constexpr Address ptr() const
Definition objects.h:820
PropertyLocation location() const
Representation representation() const
V8_WARN_UNUSED_RESULT bool AdvanceFollowingProxies()
Tagged< T > GetCurrent() const
Definition prototype.h:52
constexpr bool IsDouble() const
Register const object_
#define V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL
Definition globals.h:242
uint32_t count
#define TYPED_ARRAYS(V)
#define MAYBE_RETURN_NULL(call)
Definition isolate.h:413
#define MAYBE_RETURN(call, value)
Definition isolate.h:408
Isolate * isolate
OptionalOpIndex index
int32_t offset
TNode< Object > receiver
std::map< const std::string, const std::string > map
#define FIXED_TYPED_ELEMENTS_CHECK(Type, type, TYPE, ctype)
@ DONT_ALLOW_DOUBLE_ELEMENTS
Definition objects.h:873
@ ALLOW_CONVERTED_DOUBLE_ELEMENTS
Definition objects.h:875
@ ALLOW_COPIED_DOUBLE_ELEMENTS
Definition objects.h:874
MessageTemplate MessageTemplateFromInt(int message_id)
bool IsSlowArgumentsElementsKind(ElementsKind kind)
constexpr int kTaggedSize
Definition globals.h:542
@ SKIP_WRITE_BARRIER
Definition objects.h:52
@ UPDATE_WRITE_BARRIER
Definition objects.h:55
constexpr bool IsHoleyElementsKind(ElementsKind kind)
bool IsNumber(Tagged< Object > obj)
ReadOnlyRoots GetReadOnlyRoots()
Definition roots-inl.h:86
bool IsSealedElementsKind(ElementsKind kind)
constexpr int kEmbedderDataSlotSize
Definition globals.h:664
bool IsCustomElementsReceiverMap(Tagged< Map > map)
constexpr bool IsSmiElementsKind(ElementsKind kind)
V8_INLINE constexpr bool IsSmi(TaggedImpl< kRefType, StorageType > obj)
Definition objects.h:665
constexpr uint64_t kHoleNanInt64
Definition globals.h:1960
bool IsAnyNonextensibleElementsKind(ElementsKind kind)
constexpr bool IsObjectElementsKind(ElementsKind kind)
bool IsNonextensibleElementsKind(ElementsKind kind)
@ SLOW_STRING_WRAPPER_ELEMENTS
@ FAST_STRING_WRAPPER_ELEMENTS
V8_INLINE DirectHandle< T > direct_handle(Tagged< T > object, Isolate *isolate)
const int kVariableSizeSentinel
Definition objects.h:84
bool IsSmiOrObjectElementsKind(ElementsKind kind)
bool IsFastArgumentsElementsKind(ElementsKind kind)
bool IsFastPackedElementsKind(ElementsKind kind)
V8_INLINE PtrComprCageBase GetPtrComprCageBase()
constexpr int kTaggedSizeLog2
Definition globals.h:543
constexpr int kEmbedderDataSlotSizeInTaggedSlots
Definition globals.h:666
ElementsKind GetHoleyElementsKind(ElementsKind packed_kind)
bool IsShared(Tagged< Object > obj)
bool IsSloppyArgumentsElementsKind(ElementsKind kind)
DONT_OVERRIDE DISABLE_ALLOCATION_SITES HOLEY_ELEMENTS
bool IsFastElementsKind(ElementsKind kind)
DONT_OVERRIDE DISABLE_ALLOCATION_SITES DISABLE_ALLOCATION_SITES HOLEY_DOUBLE_ELEMENTS
bool IsDictionaryElementsKind(ElementsKind kind)
static bool ShouldConvertToSlowElements(uint32_t used_elements, uint32_t new_capacity)
bool IsJSApiWrapperObject(Tagged< Map > map)
bool IsStringWrapperElementsKind(ElementsKind kind)
constexpr bool IsDoubleElementsKind(ElementsKind kind)
EnforceDefineSemantics
Definition objects.h:116
kInstanceDescriptorsOffset kTransitionsOrPrototypeInfoOffset IsNull(value)||IsJSProxy(value)||IsWasmObject(value)||(IsJSObject(value) &&(HeapLayout
Definition map-inl.h:70
CppHeapPointerTag
Definition v8-sandbox.h:28
Maybe< T > Just(const T &t)
Definition v8-maybe.h:117
#define SEQ_CST_COMPARE_AND_SWAP_FIELD(p, offset, expected, value)
#define EXTERNAL_POINTER_ACCESSORS(holder, name, type, offset, tag)
#define ACCESSORS(holder, name, type, offset)
#define RELEASE_ACQUIRE_ACCESSORS_CHECKED2(holder, name, type, offset, get_condition, set_condition)
#define WRITE_FIELD(p, offset, value)
#define TQ_OBJECT_CONSTRUCTORS_IMPL(Type)
#define SMI_ACCESSORS(holder, name, offset)
#define CONDITIONAL_WRITE_BARRIER(object, offset, value, mode)
#define SEQ_CST_WRITE_FIELD(p, offset, value)
#define SEQ_CST_SWAP_FIELD(p, offset, value)
#define RELAXED_WRITE_FIELD(p, offset, value)
#define RELAXED_ACCESSORS(holder, name, type, offset)
#define NEVER_READ_ONLY_SPACE_IMPL(Type)
#define DEF_GETTER(Camel, Lower, Bit)
#define DCHECK_LE(v1, v2)
Definition logging.h:490
#define CHECK_IMPLIES(lhs, rhs)
#define CHECK(condition)
Definition logging.h:124
#define DCHECK_GE(v1, v2)
Definition logging.h:488
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_LT(v1, v2)
Definition logging.h:489
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define USE(...)
Definition macros.h:293
#define V8_WARN_UNUSED_RESULT
Definition v8config.h:671
std::unique_ptr< ValueMirror > value
std::unique_ptr< ValueMirror > key