1// Copyright 2012 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// Review notes:
6//
7// - The use of macros in these inline functions may seem superfluous
8// but it is absolutely needed to make sure gcc generates optimal
9// code. gcc is not happy when attempting to inline too deep.
10//
11
12#ifndef V8_OBJECTS_OBJECTS_INL_H_
13#define V8_OBJECTS_OBJECTS_INL_H_
14
15#include "src/base/bits.h"
16#include "src/base/memory.h"
17#include "src/base/numbers/double.h"
18#include "src/builtins/builtins.h"
19#include "src/common/globals.h"
20#include "src/common/ptr-compr-inl.h"
21#include "src/handles/handles-inl.h"
22#include "src/heap/factory.h"
23#include "src/heap/heap-write-barrier-inl.h"
24#include "src/heap/read-only-heap-inl.h"
25#include "src/numbers/conversions-inl.h"
26#include "src/objects/bigint.h"
27#include "src/objects/heap-number-inl.h"
28#include "src/objects/heap-object.h"
29#include "src/objects/js-proxy-inl.h"  // TODO(jkummerow): Drop.
30#include "src/objects/keys.h"
31#include "src/objects/literal-objects.h"
32#include "src/objects/lookup-inl.h"  // TODO(jkummerow): Drop.
33#include "src/objects/objects.h"
34#include "src/objects/oddball-inl.h"
35#include "src/objects/property-details.h"
36#include "src/objects/property.h"
37#include "src/objects/regexp-match-info-inl.h"
38#include "src/objects/shared-function-info.h"
39#include "src/objects/slots-inl.h"
40#include "src/objects/smi-inl.h"
41#include "src/objects/tagged-field-inl.h"
42#include "src/objects/tagged-impl-inl.h"
43#include "src/objects/tagged-index.h"
44#include "src/objects/templates.h"
45#include "src/sandbox/external-pointer-inl.h"
46#include "src/sandbox/sandboxed-pointer-inl.h"
47
48// Has to be the last include (doesn't have include guards):
49#include "src/objects/object-macros.h"
50
51namespace v8 {
52namespace internal {
53
54PropertyDetails::PropertyDetails(Smi smi) { value_ = smi.value(); }
55
56Smi PropertyDetails::AsSmi() const {
57  // Ensure the upper 2 bits have the same value by sign extending it. This is
58  // necessary to be able to use the 31st bit of the property details.
59  int value = value_ << 1;
60  return Smi::FromInt(value >> 1);
61}
62
63int PropertyDetails::field_width_in_words() const {
64  DCHECK_EQ(location(), PropertyLocation::kField);
65  return 1;
66}
67
68DEF_GETTER(HeapObject, IsClassBoilerplate, bool) {
69  return IsFixedArrayExact(cage_base);
70}
71
72bool Object::IsTaggedIndex() const {
73  return IsSmi() && TaggedIndex::IsValid(TaggedIndex(ptr()).value());
74}
75
76bool Object::InSharedHeap() const {
77  return IsHeapObject() && HeapObject::cast(*this).InSharedHeap();
78}
79
80bool Object::InSharedWritableHeap() const {
81  return IsHeapObject() && HeapObject::cast(*this).InSharedWritableHeap();
82}
83
84#define IS_TYPE_FUNCTION_DEF(type_)                                        \
85  bool Object::Is##type_() const {                                         \
86    return IsHeapObject() && HeapObject::cast(*this).Is##type_();          \
87  }                                                                        \
88  bool Object::Is##type_(PtrComprCageBase cage_base) const {               \
89    return IsHeapObject() && HeapObject::cast(*this).Is##type_(cage_base); \
90  }
91HEAP_OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DEF)
92IS_TYPE_FUNCTION_DEF(HashTableBase)
93IS_TYPE_FUNCTION_DEF(SmallOrderedHashTable)
94IS_TYPE_FUNCTION_DEF(CodeT)
95#undef IS_TYPE_FUNCTION_DEF
96
97#define IS_TYPE_FUNCTION_DEF(Type, Value)                        \
98  bool Object::Is##Type(Isolate* isolate) const {                \
99    return Is##Type(ReadOnlyRoots(isolate));                     \
100  }                                                              \
101  bool Object::Is##Type(LocalIsolate* isolate) const {           \
102    return Is##Type(ReadOnlyRoots(isolate));                     \
103  }                                                              \
104  bool Object::Is##Type(ReadOnlyRoots roots) const {             \
105    return *this == roots.Value();                               \
106  }                                                              \
107  bool Object::Is##Type() const {                                \
108    return IsHeapObject() && HeapObject::cast(*this).Is##Type(); \
109  }                                                              \
110  bool HeapObject::Is##Type(Isolate* isolate) const {            \
111    return Object::Is##Type(isolate);                            \
112  }                                                              \
113  bool HeapObject::Is##Type(LocalIsolate* isolate) const {       \
114    return Object::Is##Type(isolate);                            \
115  }                                                              \
116  bool HeapObject::Is##Type(ReadOnlyRoots roots) const {         \
117    return Object::Is##Type(roots);                              \
118  }                                                              \
119  bool HeapObject::Is##Type() const { return Is##Type(GetReadOnlyRoots()); }
120ODDBALL_LIST(IS_TYPE_FUNCTION_DEF)
121#undef IS_TYPE_FUNCTION_DEF
122
123bool Object::IsNullOrUndefined(Isolate* isolate) const {
124  return IsNullOrUndefined(ReadOnlyRoots(isolate));
125}
126
127bool Object::IsNullOrUndefined(ReadOnlyRoots roots) const {
128  return IsNull(roots) || IsUndefined(roots);
129}
130
131bool Object::IsNullOrUndefined() const {
132  return IsHeapObject() && HeapObject::cast(*this).IsNullOrUndefined();
133}
134
135bool Object::IsZero() const { return *this == Smi::zero(); }
136
137bool Object::IsPublicSymbol() const {
138  return IsSymbol() && !Symbol::cast(*this).is_private();
139}
140bool Object::IsPrivateSymbol() const {
141  return IsSymbol() && Symbol::cast(*this).is_private();
142}
143
144bool Object::IsNoSharedNameSentinel() const {
145  return *this == SharedFunctionInfo::kNoSharedNameSentinel;
146}
147
148template <class T,
149          typename std::enable_if<(std::is_arithmetic<T>::value ||
150                                   std::is_enum<T>::value) &&
151                                      !std::is_floating_point<T>::value,
152                                  int>::type>
153T Object::Relaxed_ReadField(size_t offset) const {
154  // Pointer compression causes types larger than kTaggedSize to be
155  // unaligned. Atomic loads must be aligned.
156  DCHECK_IMPLIES(COMPRESS_POINTERS_BOOL, sizeof(T) <= kTaggedSize);
157  using AtomicT = typename base::AtomicTypeFromByteWidth<sizeof(T)>::type;
158  return static_cast<T>(base::AsAtomicImpl<AtomicT>::Relaxed_Load(
159      reinterpret_cast<AtomicT*>(field_address(offset))));
160}
161
162template <class T,
163          typename std::enable_if<(std::is_arithmetic<T>::value ||
164                                   std::is_enum<T>::value) &&
165                                      !std::is_floating_point<T>::value,
166                                  int>::type>
167void Object::Relaxed_WriteField(size_t offset, T value) {
168  // Pointer compression causes types larger than kTaggedSize to be
169  // unaligned. Atomic stores must be aligned.
170  DCHECK_IMPLIES(COMPRESS_POINTERS_BOOL, sizeof(T) <= kTaggedSize);
171  using AtomicT = typename base::AtomicTypeFromByteWidth<sizeof(T)>::type;
172  base::AsAtomicImpl<AtomicT>::Relaxed_Store(
173      reinterpret_cast<AtomicT*>(field_address(offset)),
174      static_cast<AtomicT>(value));
175}
176
177bool HeapObject::InSharedHeap() const {
178  if (IsReadOnlyHeapObject(*this)) return V8_SHARED_RO_HEAP_BOOL;
179  return InSharedWritableHeap();
180}
181
182bool HeapObject::InSharedWritableHeap() const {
183  return BasicMemoryChunk::FromHeapObject(*this)->InSharedHeap();
184}
185
186bool HeapObject::IsNullOrUndefined(Isolate* isolate) const {
187  return IsNullOrUndefined(ReadOnlyRoots(isolate));
188}
189
190bool HeapObject::IsNullOrUndefined(ReadOnlyRoots roots) const {
191  return Object::IsNullOrUndefined(roots);
192}
193
194bool HeapObject::IsNullOrUndefined() const {
195  return IsNullOrUndefined(GetReadOnlyRoots());
196}
197
198DEF_GETTER(HeapObject, IsCodeT, bool) {
199  return V8_EXTERNAL_CODE_SPACE_BOOL ? IsCodeDataContainer(cage_base)
200                                     : IsCode(cage_base);
201}
202
203DEF_GETTER(HeapObject, IsUniqueName, bool) {
204  return IsInternalizedString(cage_base) || IsSymbol(cage_base);
205}
206
207DEF_GETTER(HeapObject, IsFunction, bool) {
208  return IsJSFunctionOrBoundFunctionOrWrappedFunction();
209}
210
211DEF_GETTER(HeapObject, IsCallable, bool) {
212  return map(cage_base).is_callable();
213}
214
215DEF_GETTER(HeapObject, IsCallableJSProxy, bool) {
216  return IsCallable(cage_base) && IsJSProxy(cage_base);
217}
218
219DEF_GETTER(HeapObject, IsCallableApiObject, bool) {
220  InstanceType type = map(cage_base).instance_type();
221  return IsCallable(cage_base) &&
222         (type == JS_API_OBJECT_TYPE || type == JS_SPECIAL_API_OBJECT_TYPE);
223}
224
225DEF_GETTER(HeapObject, IsNonNullForeign, bool) {
226  return IsForeign(cage_base) &&
227         Foreign::cast(*this).foreign_address() != kNullAddress;
228}
229
230DEF_GETTER(HeapObject, IsConstructor, bool) {
231  return map(cage_base).is_constructor();
232}
233
234DEF_GETTER(HeapObject, IsSourceTextModuleInfo, bool) {
235  return map(cage_base) == GetReadOnlyRoots(cage_base).module_info_map();
236}
237
238DEF_GETTER(HeapObject, IsConsString, bool) {
239  if (!IsString(cage_base)) return false;
240  return StringShape(String::cast(*this).map(cage_base)).IsCons();
241}
242
243DEF_GETTER(HeapObject, IsThinString, bool) {
244  if (!IsString(cage_base)) return false;
245  return StringShape(String::cast(*this).map(cage_base)).IsThin();
246}
247
248DEF_GETTER(HeapObject, IsSlicedString, bool) {
249  if (!IsString(cage_base)) return false;
250  return StringShape(String::cast(*this).map(cage_base)).IsSliced();
251}
252
253DEF_GETTER(HeapObject, IsSeqString, bool) {
254  if (!IsString(cage_base)) return false;
255  return StringShape(String::cast(*this).map(cage_base)).IsSequential();
256}
257
258DEF_GETTER(HeapObject, IsSeqOneByteString, bool) {
259  if (!IsString(cage_base)) return false;
260  return StringShape(String::cast(*this).map(cage_base)).IsSequential() &&
261         String::cast(*this).IsOneByteRepresentation(cage_base);
262}
263
264DEF_GETTER(HeapObject, IsSeqTwoByteString, bool) {
265  if (!IsString(cage_base)) return false;
266  return StringShape(String::cast(*this).map(cage_base)).IsSequential() &&
267         String::cast(*this).IsTwoByteRepresentation(cage_base);
268}
269
270DEF_GETTER(HeapObject, IsExternalOneByteString, bool) {
271  if (!IsString(cage_base)) return false;
272  return StringShape(String::cast(*this).map(cage_base)).IsExternal() &&
273         String::cast(*this).IsOneByteRepresentation(cage_base);
274}
275
276DEF_GETTER(HeapObject, IsExternalTwoByteString, bool) {
277  if (!IsString(cage_base)) return false;
278  return StringShape(String::cast(*this).map(cage_base)).IsExternal() &&
279         String::cast(*this).IsTwoByteRepresentation(cage_base);
280}
281
282bool Object::IsNumber() const {
283  if (IsSmi()) return true;
284  HeapObject this_heap_object = HeapObject::cast(*this);
285  PtrComprCageBase cage_base = GetPtrComprCageBase(this_heap_object);
286  return this_heap_object.IsHeapNumber(cage_base);
287}
288
289bool Object::IsNumber(PtrComprCageBase cage_base) const {
290  return IsSmi() || IsHeapNumber(cage_base);
291}
292
293bool Object::IsNumeric() const {
294  if (IsSmi()) return true;
295  HeapObject this_heap_object = HeapObject::cast(*this);
296  PtrComprCageBase cage_base = GetPtrComprCageBase(this_heap_object);
297  return this_heap_object.IsHeapNumber(cage_base) ||
298         this_heap_object.IsBigInt(cage_base);
299}
300
301bool Object::IsNumeric(PtrComprCageBase cage_base) const {
302  return IsNumber(cage_base) || IsBigInt(cage_base);
303}
304
305DEF_GETTER(HeapObject, IsArrayList, bool) {
306  return map(cage_base) ==
307         GetReadOnlyRoots(cage_base).unchecked_array_list_map();
308}
309
310DEF_GETTER(HeapObject, IsRegExpMatchInfo, bool) {
311  return IsFixedArrayExact(cage_base);
312}
313
314DEF_GETTER(HeapObject, IsDeoptimizationData, bool) {
315  // Must be a fixed array.
316  if (!IsFixedArrayExact(cage_base)) return false;
317
318  // There's no sure way to detect the difference between a fixed array and
319  // a deoptimization data array.  Since this is used for asserts we can
320  // check that the length is zero or else the fixed size plus a multiple of
321  // the entry size.
322  int length = FixedArray::cast(*this).length();
323  if (length == 0) return true;
324
325  length -= DeoptimizationData::kFirstDeoptEntryIndex;
326  return length >= 0 && length % DeoptimizationData::kDeoptEntrySize == 0;
327}
328
329DEF_GETTER(HeapObject, IsHandlerTable, bool) {
330  return IsFixedArrayExact(cage_base);
331}
332
333DEF_GETTER(HeapObject, IsTemplateList, bool) {
334  if (!IsFixedArrayExact(cage_base)) return false;
335  if (FixedArray::cast(*this).length() < 1) return false;
336  return true;
337}
338
339DEF_GETTER(HeapObject, IsDependentCode, bool) {
340  return IsWeakArrayList(cage_base);
341}
342
343DEF_GETTER(HeapObject, IsOSROptimizedCodeCache, bool) {
344  return IsWeakFixedArray(cage_base);
345}
346
347bool HeapObject::IsAbstractCode() const {
348  // TODO(v8:11880): Either make AbstractCode be ByteArray|CodeT or
349  // ensure this version is not called for hot code.
350  PtrComprCageBase cage_base = GetPtrComprCageBaseSlow(*this);
351  return HeapObject::IsAbstractCode(cage_base);
352}
353bool HeapObject::IsAbstractCode(PtrComprCageBase cage_base) const {
354  return IsBytecodeArray(cage_base) || IsCode(cage_base);
355}
356
357DEF_GETTER(HeapObject, IsStringWrapper, bool) {
358  return IsJSPrimitiveWrapper(cage_base) &&
359         JSPrimitiveWrapper::cast(*this).value().IsString(cage_base);
360}
361
362DEF_GETTER(HeapObject, IsBooleanWrapper, bool) {
363  return IsJSPrimitiveWrapper(cage_base) &&
364         JSPrimitiveWrapper::cast(*this).value().IsBoolean(cage_base);
365}
366
367DEF_GETTER(HeapObject, IsScriptWrapper, bool) {
368  return IsJSPrimitiveWrapper(cage_base) &&
369         JSPrimitiveWrapper::cast(*this).value().IsScript(cage_base);
370}
371
372DEF_GETTER(HeapObject, IsNumberWrapper, bool) {
373  return IsJSPrimitiveWrapper(cage_base) &&
374         JSPrimitiveWrapper::cast(*this).value().IsNumber(cage_base);
375}
376
377DEF_GETTER(HeapObject, IsBigIntWrapper, bool) {
378  return IsJSPrimitiveWrapper(cage_base) &&
379         JSPrimitiveWrapper::cast(*this).value().IsBigInt(cage_base);
380}
381
382DEF_GETTER(HeapObject, IsSymbolWrapper, bool) {
383  return IsJSPrimitiveWrapper(cage_base) &&
384         JSPrimitiveWrapper::cast(*this).value().IsSymbol(cage_base);
385}
386
387DEF_GETTER(HeapObject, IsStringSet, bool) { return IsHashTable(cage_base); }
388
389DEF_GETTER(HeapObject, IsObjectHashSet, bool) { return IsHashTable(cage_base); }
390
391DEF_GETTER(HeapObject, IsCompilationCacheTable, bool) {
392  return IsHashTable(cage_base);
393}
394
395DEF_GETTER(HeapObject, IsMapCache, bool) { return IsHashTable(cage_base); }
396
397DEF_GETTER(HeapObject, IsObjectHashTable, bool) {
398  return IsHashTable(cage_base);
399}
400
401DEF_GETTER(HeapObject, IsHashTableBase, bool) { return IsHashTable(cage_base); }
402
403#if V8_ENABLE_WEBASSEMBLY
404DEF_GETTER(HeapObject, IsWasmExceptionPackage, bool) {
405  // It is not possible to check for the existence of certain properties on the
406  // underlying {JSReceiver} here because that requires calling handlified code.
407  return IsJSReceiver(cage_base);
408}
409#endif  // V8_ENABLE_WEBASSEMBLY
410
411bool Object::IsPrimitive() const {
412  if (IsSmi()) return true;
413  HeapObject this_heap_object = HeapObject::cast(*this);
414  PtrComprCageBase cage_base = GetPtrComprCageBase(this_heap_object);
415  return this_heap_object.map(cage_base).IsPrimitiveMap();
416}
417
418bool Object::IsPrimitive(PtrComprCageBase cage_base) const {
419  return IsSmi() || HeapObject::cast(*this).map(cage_base).IsPrimitiveMap();
420}
421
422// static
423Maybe<bool> Object::IsArray(Handle<Object> object) {
424  if (object->IsSmi()) return Just(false);
425  Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object);
426  if (heap_object->IsJSArray()) return Just(true);
427  if (!heap_object->IsJSProxy()) return Just(false);
428  return JSProxy::IsArray(Handle<JSProxy>::cast(object));
429}
430
431DEF_GETTER(HeapObject, IsUndetectable, bool) {
432  return map(cage_base).is_undetectable();
433}
434
435DEF_GETTER(HeapObject, IsAccessCheckNeeded, bool) {
436  if (IsJSGlobalProxy(cage_base)) {
437    const JSGlobalProxy proxy = JSGlobalProxy::cast(*this);
438    JSGlobalObject global = proxy.GetIsolate()->context().global_object();
439    return proxy.IsDetachedFrom(global);
440  }
441  return map(cage_base).is_access_check_needed();
442}
443
444#define MAKE_STRUCT_PREDICATE(NAME, Name, name)                           \
445  bool Object::Is##Name() const {                                         \
446    return IsHeapObject() && HeapObject::cast(*this).Is##Name();          \
447  }                                                                       \
448  bool Object::Is##Name(PtrComprCageBase cage_base) const {               \
449    return IsHeapObject() && HeapObject::cast(*this).Is##Name(cage_base); \
450  }
451STRUCT_LIST(MAKE_STRUCT_PREDICATE)
452#undef MAKE_STRUCT_PREDICATE
453
454double Object::Number() const {
455  DCHECK(IsNumber());
456  return IsSmi() ? static_cast<double>(Smi(this->ptr()).value())
457                 : HeapNumber::unchecked_cast(*this).value();
458}
459
460// static
461bool Object::SameNumberValue(double value1, double value2) {
462  // SameNumberValue(NaN, NaN) is true.
463  if (value1 != value2) {
464    return std::isnan(value1) && std::isnan(value2);
465  }
466  // SameNumberValue(0.0, -0.0) is false.
467  return (std::signbit(value1) == std::signbit(value2));
468}
469
470bool Object::IsNaN() const {
471  return this->IsHeapNumber() && std::isnan(HeapNumber::cast(*this).value());
472}
473
474bool Object::IsMinusZero() const {
475  return this->IsHeapNumber() &&
476         i::IsMinusZero(HeapNumber::cast(*this).value());
477}
478
479OBJECT_CONSTRUCTORS_IMPL(BigIntBase, PrimitiveHeapObject)
480OBJECT_CONSTRUCTORS_IMPL(BigInt, BigIntBase)
481OBJECT_CONSTRUCTORS_IMPL(FreshlyAllocatedBigInt, BigIntBase)
482
483// ------------------------------------
484// Cast operations
485
486CAST_ACCESSOR(BigIntBase)
487CAST_ACCESSOR(BigInt)
488
489bool Object::HasValidElements() {
490  // Dictionary is covered under FixedArray. ByteArray is used
491  // for the JSTypedArray backing stores.
492  return IsFixedArray() || IsFixedDoubleArray() || IsByteArray();
493}
494
495bool Object::FilterKey(PropertyFilter filter) {
496  DCHECK(!IsPropertyCell());
497  if (filter == PRIVATE_NAMES_ONLY) {
498    if (!IsSymbol()) return true;
499    return !Symbol::cast(*this).is_private_name();
500  } else if (IsSymbol()) {
501    if (filter & SKIP_SYMBOLS) return true;
502
503    if (Symbol::cast(*this).is_private()) return true;
504  } else {
505    if (filter & SKIP_STRINGS) return true;
506  }
507  return false;
508}
509
510Representation Object::OptimalRepresentation(PtrComprCageBase cage_base) const {
511  if (IsSmi()) {
512    return Representation::Smi();
513  }
514  HeapObject heap_object = HeapObject::cast(*this);
515  if (heap_object.IsHeapNumber(cage_base)) {
516    return Representation::Double();
517  } else if (heap_object.IsUninitialized(
518                 heap_object.GetReadOnlyRoots(cage_base))) {
519    return Representation::None();
520  }
521  return Representation::HeapObject();
522}
523
524ElementsKind Object::OptimalElementsKind(PtrComprCageBase cage_base) const {
525  if (IsSmi()) return PACKED_SMI_ELEMENTS;
526  if (IsNumber(cage_base)) return PACKED_DOUBLE_ELEMENTS;
527  return PACKED_ELEMENTS;
528}
529
530bool Object::FitsRepresentation(Representation representation,
531                                bool allow_coercion) const {
532  if (representation.IsSmi()) {
533    return IsSmi();
534  } else if (representation.IsDouble()) {
535    return allow_coercion ? IsNumber() : IsHeapNumber();
536  } else if (representation.IsHeapObject()) {
537    return IsHeapObject();
538  } else if (representation.IsNone()) {
539    return false;
540  }
541  return true;
542}
543
544bool Object::ToUint32(uint32_t* value) const {
545  if (IsSmi()) {
546    int num = Smi::ToInt(*this);
547    if (num < 0) return false;
548    *value = static_cast<uint32_t>(num);
549    return true;
550  }
551  if (IsHeapNumber()) {
552    double num = HeapNumber::cast(*this).value();
553    return DoubleToUint32IfEqualToSelf(num, value);
554  }
555  return false;
556}
557
558// static
559MaybeHandle<JSReceiver> Object::ToObject(Isolate* isolate,
560                                         Handle<Object> object,
561                                         const char* method_name) {
562  if (object->IsJSReceiver()) return Handle<JSReceiver>::cast(object);
563  return ToObjectImpl(isolate, object, method_name);
564}
565
566// static
567MaybeHandle<Name> Object::ToName(Isolate* isolate, Handle<Object> input) {
568  if (input->IsName()) return Handle<Name>::cast(input);
569  return ConvertToName(isolate, input);
570}
571
572// static
573MaybeHandle<Object> Object::ToPropertyKey(Isolate* isolate,
574                                          Handle<Object> value) {
575  if (value->IsSmi() || HeapObject::cast(*value).IsName()) return value;
576  return ConvertToPropertyKey(isolate, value);
577}
578
579// static
580MaybeHandle<Object> Object::ToPrimitive(Isolate* isolate, Handle<Object> input,
581                                        ToPrimitiveHint hint) {
582  if (input->IsPrimitive()) return input;
583  return JSReceiver::ToPrimitive(isolate, Handle<JSReceiver>::cast(input),
584                                 hint);
585}
586
587// static
588MaybeHandle<Object> Object::ToNumber(Isolate* isolate, Handle<Object> input) {
589  if (input->IsNumber()) return input;  // Shortcut.
590  return ConvertToNumberOrNumeric(isolate, input, Conversion::kToNumber);
591}
592
593// static
594MaybeHandle<Object> Object::ToNumeric(Isolate* isolate, Handle<Object> input) {
595  if (input->IsNumber() || input->IsBigInt()) return input;  // Shortcut.
596  return ConvertToNumberOrNumeric(isolate, input, Conversion::kToNumeric);
597}
598
599// static
600MaybeHandle<Object> Object::ToInteger(Isolate* isolate, Handle<Object> input) {
601  if (input->IsSmi()) return input;
602  return ConvertToInteger(isolate, input);
603}
604
605// static
606MaybeHandle<Object> Object::ToInt32(Isolate* isolate, Handle<Object> input) {
607  if (input->IsSmi()) return input;
608  return ConvertToInt32(isolate, input);
609}
610
611// static
612MaybeHandle<Object> Object::ToUint32(Isolate* isolate, Handle<Object> input) {
613  if (input->IsSmi()) return handle(Smi::cast(*input).ToUint32Smi(), isolate);
614  return ConvertToUint32(isolate, input);
615}
616
617// static
618MaybeHandle<String> Object::ToString(Isolate* isolate, Handle<Object> input) {
619  if (input->IsString()) return Handle<String>::cast(input);
620  return ConvertToString(isolate, input);
621}
622
623// static
624MaybeHandle<Object> Object::ToLength(Isolate* isolate, Handle<Object> input) {
625  if (input->IsSmi()) {
626    int value = std::max(Smi::ToInt(*input), 0);
627    return handle(Smi::FromInt(value), isolate);
628  }
629  return ConvertToLength(isolate, input);
630}
631
632// static
633MaybeHandle<Object> Object::ToIndex(Isolate* isolate, Handle<Object> input,
634                                    MessageTemplate error_index) {
635  if (input->IsSmi() && Smi::ToInt(*input) >= 0) return input;
636  return ConvertToIndex(isolate, input, error_index);
637}
638
639MaybeHandle<Object> Object::GetProperty(Isolate* isolate, Handle<Object> object,
640                                        Handle<Name> name) {
641  LookupIterator it(isolate, object, name);
642  if (!it.IsFound()) return it.factory()->undefined_value();
643  return GetProperty(&it);
644}
645
646MaybeHandle<Object> Object::GetElement(Isolate* isolate, Handle<Object> object,
647                                       uint32_t index) {
648  LookupIterator it(isolate, object, index);
649  if (!it.IsFound()) return it.factory()->undefined_value();
650  return GetProperty(&it);
651}
652
653MaybeHandle<Object> Object::SetElement(Isolate* isolate, Handle<Object> object,
654                                       uint32_t index, Handle<Object> value,
655                                       ShouldThrow should_throw) {
656  LookupIterator it(isolate, object, index);
657  MAYBE_RETURN_NULL(
658      SetProperty(&it, value, StoreOrigin::kMaybeKeyed, Just(should_throw)));
659  return value;
660}
661
662Address Object::ReadSandboxedPointerField(size_t offset,
663                                          PtrComprCageBase cage_base) const {
664  return i::ReadSandboxedPointerField(field_address(offset), cage_base);
665}
666
667void Object::WriteSandboxedPointerField(size_t offset,
668                                        PtrComprCageBase cage_base,
669                                        Address value) {
670  i::WriteSandboxedPointerField(field_address(offset), cage_base, value);
671}
672
673void Object::WriteSandboxedPointerField(size_t offset, Isolate* isolate,
674                                        Address value) {
675  i::WriteSandboxedPointerField(field_address(offset),
676                                PtrComprCageBase(isolate), value);
677}
678
679void Object::InitExternalPointerField(size_t offset, Isolate* isolate,
680                                      ExternalPointerTag tag) {
681  i::InitExternalPointerField(field_address(offset), isolate, tag);
682}
683
684void Object::InitExternalPointerField(size_t offset, Isolate* isolate,
685                                      Address value, ExternalPointerTag tag) {
686  i::InitExternalPointerField(field_address(offset), isolate, value, tag);
687}
688
689Address Object::ReadExternalPointerField(size_t offset, Isolate* isolate,
690                                         ExternalPointerTag tag) const {
691  return i::ReadExternalPointerField(field_address(offset), isolate, tag);
692}
693
694void Object::WriteExternalPointerField(size_t offset, Isolate* isolate,
695                                       Address value, ExternalPointerTag tag) {
696  i::WriteExternalPointerField(field_address(offset), isolate, value, tag);
697}
698
699ObjectSlot HeapObject::RawField(int byte_offset) const {
700  return ObjectSlot(field_address(byte_offset));
701}
702
703MaybeObjectSlot HeapObject::RawMaybeWeakField(int byte_offset) const {
704  return MaybeObjectSlot(field_address(byte_offset));
705}
706
707CodeObjectSlot HeapObject::RawCodeField(int byte_offset) const {
708  return CodeObjectSlot(field_address(byte_offset));
709}
710
711ExternalPointer_t HeapObject::RawExternalPointerField(int byte_offset) const {
712  return ReadRawExternalPointerField(field_address(byte_offset));
713}
714
715MapWord MapWord::FromMap(const Map map) {
716  DCHECK(map.is_null() || !MapWord::IsPacked(map.ptr()));
717#ifdef V8_MAP_PACKING
718  return MapWord(Pack(map.ptr()));
719#else
720  return MapWord(map.ptr());
721#endif
722}
723
724Map MapWord::ToMap() const {
725#ifdef V8_MAP_PACKING
726  return Map::unchecked_cast(Object(Unpack(value_)));
727#else
728  return Map::unchecked_cast(Object(value_));
729#endif
730}
731
732bool MapWord::IsForwardingAddress() const {
733  return (value_ & kForwardingTagMask) == kForwardingTag;
734}
735
736MapWord MapWord::FromForwardingAddress(HeapObject object) {
737  return MapWord(object.ptr() - kHeapObjectTag);
738}
739
740HeapObject MapWord::ToForwardingAddress() {
741  DCHECK(IsForwardingAddress());
742  HeapObject obj = HeapObject::FromAddress(value_);
743  // For objects allocated outside of the main pointer compression cage the
744  // variant with explicit cage base must be used.
745  DCHECK_IMPLIES(V8_EXTERNAL_CODE_SPACE_BOOL, !IsCodeSpaceObject(obj));
746  return obj;
747}
748
749HeapObject MapWord::ToForwardingAddress(PtrComprCageBase host_cage_base) {
750  DCHECK(IsForwardingAddress());
751  if (V8_EXTERNAL_CODE_SPACE_BOOL) {
752    // Recompress value_ using proper host_cage_base since the map word
753    // has the upper 32 bits that correspond to the main cage base value.
754    Address value =
755        DecompressTaggedPointer(host_cage_base, CompressTagged(value_));
756    return HeapObject::FromAddress(value);
757  }
758  return HeapObject::FromAddress(value_);
759}
760
761#ifdef VERIFY_HEAP
762void HeapObject::VerifyObjectField(Isolate* isolate, int offset) {
763  VerifyPointer(isolate, TaggedField<Object>::load(isolate, *this, offset));
764  STATIC_ASSERT(!COMPRESS_POINTERS_BOOL || kTaggedSize == kInt32Size);
765}
766
767void HeapObject::VerifyMaybeObjectField(Isolate* isolate, int offset) {
768  MaybeObject::VerifyMaybeObjectPointer(
769      isolate, TaggedField<MaybeObject>::load(isolate, *this, offset));
770  STATIC_ASSERT(!COMPRESS_POINTERS_BOOL || kTaggedSize == kInt32Size);
771}
772
773void HeapObject::VerifySmiField(int offset) {
774  CHECK(TaggedField<Object>::load(*this, offset).IsSmi());
775  STATIC_ASSERT(!COMPRESS_POINTERS_BOOL || kTaggedSize == kInt32Size);
776}
777
778#endif
779
780ReadOnlyRoots HeapObject::GetReadOnlyRoots() const {
781  return ReadOnlyHeap::GetReadOnlyRoots(*this);
782}
783
784ReadOnlyRoots HeapObject::GetReadOnlyRoots(PtrComprCageBase cage_base) const {
785#ifdef V8_COMPRESS_POINTERS_IN_ISOLATE_CAGE
786  DCHECK_NE(cage_base.address(), 0);
787  return ReadOnlyRoots(Isolate::FromRootAddress(cage_base.address()));
788#else
789  return GetReadOnlyRoots();
790#endif
791}
792
793Map HeapObject::map() const {
794  // This method is never used for objects located in code space (Code and
795  // free space fillers) and thus it is fine to use auto-computed cage base
796  // value.
797  DCHECK_IMPLIES(V8_EXTERNAL_CODE_SPACE_BOOL, !IsCodeSpaceObject(*this));
798  PtrComprCageBase cage_base = GetPtrComprCageBase(*this);
799  return HeapObject::map(cage_base);
800}
801Map HeapObject::map(PtrComprCageBase cage_base) const {
802  return map_word(cage_base, kRelaxedLoad).ToMap();
803}
804
805void HeapObject::set_map(Map value) {
806  set_map<EmitWriteBarrier::kYes>(value, kRelaxedStore,
807                                  VerificationMode::kPotentialLayoutChange);
808}
809
810void HeapObject::set_map(Map value, ReleaseStoreTag tag) {
811  set_map<EmitWriteBarrier::kYes>(value, kReleaseStore,
812                                  VerificationMode::kPotentialLayoutChange);
813}
814
815void HeapObject::set_map_safe_transition(Map value) {
816  set_map<EmitWriteBarrier::kYes>(value, kRelaxedStore,
817                                  VerificationMode::kSafeMapTransition);
818}
819
820void HeapObject::set_map_safe_transition(Map value, ReleaseStoreTag tag) {
821  set_map<EmitWriteBarrier::kYes>(value, kReleaseStore,
822                                  VerificationMode::kSafeMapTransition);
823}
824
825// Unsafe accessor omitting write barrier.
826void HeapObject::set_map_no_write_barrier(Map value, RelaxedStoreTag tag) {
827  set_map<EmitWriteBarrier::kNo>(value, kRelaxedStore,
828                                 VerificationMode::kPotentialLayoutChange);
829}
830
831void HeapObject::set_map_no_write_barrier(Map value, ReleaseStoreTag tag) {
832  set_map<EmitWriteBarrier::kNo>(value, kReleaseStore,
833                                 VerificationMode::kPotentialLayoutChange);
834}
835
836template <HeapObject::EmitWriteBarrier emit_write_barrier, typename MemoryOrder>
837void HeapObject::set_map(Map value, MemoryOrder order, VerificationMode mode) {
838#if V8_ENABLE_WEBASSEMBLY
839  // In {WasmGraphBuilder::SetMap} and {WasmGraphBuilder::LoadMap}, we treat
840  // maps as immutable. Therefore we are not allowed to mutate them here.
841  DCHECK(!value.IsWasmStructMap() && !value.IsWasmArrayMap());
842#endif
843  // Object layout changes are currently not supported on background threads.
844  // This method might change object layout and therefore can't be used on
845  // background threads.
846  DCHECK_IMPLIES(mode != VerificationMode::kSafeMapTransition,
847                 !LocalHeap::Current());
848#ifdef VERIFY_HEAP
849  if (FLAG_verify_heap && !value.is_null()) {
850    Heap* heap = GetHeapFromWritableObject(*this);
851    if (mode == VerificationMode::kSafeMapTransition) {
852      heap->VerifySafeMapTransition(*this, value);
853    } else {
854      DCHECK_EQ(mode, VerificationMode::kPotentialLayoutChange);
855      heap->VerifyObjectLayoutChange(*this, value);
856    }
857  }
858#endif
859  set_map_word(MapWord::FromMap(value), order);
860#ifndef V8_DISABLE_WRITE_BARRIERS
861  if (!value.is_null()) {
862    if (emit_write_barrier == EmitWriteBarrier::kYes) {
863      WriteBarrier::Marking(*this, map_slot(), value);
864    } else {
865      DCHECK_EQ(emit_write_barrier, EmitWriteBarrier::kNo);
866      SLOW_DCHECK(!WriteBarrier::IsRequired(*this, value));
867    }
868  }
869#endif
870}
871
872void HeapObject::set_map_after_allocation(Map value, WriteBarrierMode mode) {
873  MapWord mapword = MapWord::FromMap(value);
874  set_map_word(mapword, kRelaxedStore);
875#ifndef V8_DISABLE_WRITE_BARRIERS
876  if (mode != SKIP_WRITE_BARRIER) {
877    DCHECK(!value.is_null());
878    WriteBarrier::Marking(*this, map_slot(), value);
879  } else {
880    SLOW_DCHECK(!WriteBarrier::IsRequired(*this, value));
881  }
882#endif
883}
884
885DEF_ACQUIRE_GETTER(HeapObject, map, Map) {
886  return map_word(cage_base, kAcquireLoad).ToMap();
887}
888
889ObjectSlot HeapObject::map_slot() const {
890  return ObjectSlot(MapField::address(*this));
891}
892
893MapWord HeapObject::map_word(RelaxedLoadTag tag) const {
894  // This method is never used for objects located in code space (Code and
895  // free space fillers) and thus it is fine to use auto-computed cage base
896  // value.
897  DCHECK_IMPLIES(V8_EXTERNAL_CODE_SPACE_BOOL, !IsCodeSpaceObject(*this));
898  PtrComprCageBase cage_base = GetPtrComprCageBase(*this);
899  return HeapObject::map_word(cage_base, tag);
900}
901MapWord HeapObject::map_word(PtrComprCageBase cage_base,
902                             RelaxedLoadTag tag) const {
903  return MapField::Relaxed_Load_Map_Word(cage_base, *this);
904}
905
906void HeapObject::set_map_word(MapWord map_word, RelaxedStoreTag) {
907  MapField::Relaxed_Store_Map_Word(*this, map_word);
908}
909
910MapWord HeapObject::map_word(AcquireLoadTag tag) const {
911  // This method is never used for objects located in code space (Code and
912  // free space fillers) and thus it is fine to use auto-computed cage base
913  // value.
914  DCHECK_IMPLIES(V8_EXTERNAL_CODE_SPACE_BOOL, !IsCodeSpaceObject(*this));
915  PtrComprCageBase cage_base = GetPtrComprCageBase(*this);
916  return HeapObject::map_word(cage_base, tag);
917}
918MapWord HeapObject::map_word(PtrComprCageBase cage_base,
919                             AcquireLoadTag tag) const {
920  return MapField::Acquire_Load_No_Unpack(cage_base, *this);
921}
922
923void HeapObject::set_map_word(MapWord map_word, ReleaseStoreTag) {
924  MapField::Release_Store_Map_Word(*this, map_word);
925}
926
927bool HeapObject::release_compare_and_swap_map_word(MapWord old_map_word,
928                                                   MapWord new_map_word) {
929  Tagged_t result =
930      MapField::Release_CompareAndSwap(*this, old_map_word, new_map_word);
931  return result == static_cast<Tagged_t>(old_map_word.ptr());
932}
933
934// TODO(v8:11880): consider dropping parameterless version.
935int HeapObject::Size() const {
936  DCHECK_IMPLIES(V8_EXTERNAL_CODE_SPACE_BOOL, !IsCodeSpaceObject(*this));
937  PtrComprCageBase cage_base = GetPtrComprCageBase(*this);
938  return HeapObject::Size(cage_base);
939}
940int HeapObject::Size(PtrComprCageBase cage_base) const {
941  return SizeFromMap(map(cage_base));
942}
943
944inline bool IsSpecialReceiverInstanceType(InstanceType instance_type) {
945  return instance_type <= LAST_SPECIAL_RECEIVER_TYPE;
946}
947
948// This should be in objects/map-inl.h, but can't, because of a cyclic
949// dependency.
950bool Map::IsSpecialReceiverMap() const {
951  bool result = IsSpecialReceiverInstanceType(instance_type());
952  DCHECK_IMPLIES(!result,
953                 !has_named_interceptor() && !is_access_check_needed());
954  return result;
955}
956
957inline bool IsCustomElementsReceiverInstanceType(InstanceType instance_type) {
958  return instance_type <= LAST_CUSTOM_ELEMENTS_RECEIVER;
959}
960
961// This should be in objects/map-inl.h, but can't, because of a cyclic
962// dependency.
963bool Map::IsCustomElementsReceiverMap() const {
964  return IsCustomElementsReceiverInstanceType(instance_type());
965}
966
967bool Object::ToArrayLength(uint32_t* index) const {
968  return Object::ToUint32(index);
969}
970
971bool Object::ToArrayIndex(uint32_t* index) const {
972  return Object::ToUint32(index) && *index != kMaxUInt32;
973}
974
975bool Object::ToIntegerIndex(size_t* index) const {
976  if (IsSmi()) {
977    int num = Smi::ToInt(*this);
978    if (num < 0) return false;
979    *index = static_cast<size_t>(num);
980    return true;
981  }
982  if (IsHeapNumber()) {
983    double num = HeapNumber::cast(*this).value();
984    if (!(num >= 0)) return false;  // Negation to catch NaNs.
985    constexpr double max =
986        std::min(kMaxSafeInteger,
987                 // The maximum size_t is reserved as "invalid" sentinel.
988                 static_cast<double>(std::numeric_limits<size_t>::max() - 1));
989    if (num > max) return false;
990    size_t result = static_cast<size_t>(num);
991    if (num != result) return false;  // Conversion lost fractional precision.
992    *index = result;
993    return true;
994  }
995  return false;
996}
997
998WriteBarrierMode HeapObject::GetWriteBarrierMode(
999    const DisallowGarbageCollection& promise) {
1000  return GetWriteBarrierModeForObject(*this, &promise);
1001}
1002
1003// static
1004AllocationAlignment HeapObject::RequiredAlignment(Map map) {
1005  // TODO(v8:4153): We should think about requiring double alignment
1006  // in general for ByteArray, since they are used as backing store for typed
1007  // arrays now.
1008  // TODO(ishell, v8:8875): Consider using aligned allocations for BigInt.
1009  if (USE_ALLOCATION_ALIGNMENT_BOOL) {
1010    int instance_type = map.instance_type();
1011    if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) return kDoubleAligned;
1012    if (instance_type == HEAP_NUMBER_TYPE) return kDoubleUnaligned;
1013  }
1014  return kTaggedAligned;
1015}
1016
1017Address HeapObject::GetFieldAddress(int field_offset) const {
1018  return field_address(field_offset);
1019}
1020
1021// static
1022Maybe<bool> Object::GreaterThan(Isolate* isolate, Handle<Object> x,
1023                                Handle<Object> y) {
1024  Maybe<ComparisonResult> result = Compare(isolate, x, y);
1025  if (result.IsJust()) {
1026    switch (result.FromJust()) {
1027      case ComparisonResult::kGreaterThan:
1028        return Just(true);
1029      case ComparisonResult::kLessThan:
1030      case ComparisonResult::kEqual:
1031      case ComparisonResult::kUndefined:
1032        return Just(false);
1033    }
1034  }
1035  return Nothing<bool>();
1036}
1037
1038// static
1039Maybe<bool> Object::GreaterThanOrEqual(Isolate* isolate, Handle<Object> x,
1040                                       Handle<Object> y) {
1041  Maybe<ComparisonResult> result = Compare(isolate, x, y);
1042  if (result.IsJust()) {
1043    switch (result.FromJust()) {
1044      case ComparisonResult::kEqual:
1045      case ComparisonResult::kGreaterThan:
1046        return Just(true);
1047      case ComparisonResult::kLessThan:
1048      case ComparisonResult::kUndefined:
1049        return Just(false);
1050    }
1051  }
1052  return Nothing<bool>();
1053}
1054
1055// static
1056Maybe<bool> Object::LessThan(Isolate* isolate, Handle<Object> x,
1057                             Handle<Object> y) {
1058  Maybe<ComparisonResult> result = Compare(isolate, x, y);
1059  if (result.IsJust()) {
1060    switch (result.FromJust()) {
1061      case ComparisonResult::kLessThan:
1062        return Just(true);
1063      case ComparisonResult::kEqual:
1064      case ComparisonResult::kGreaterThan:
1065      case ComparisonResult::kUndefined:
1066        return Just(false);
1067    }
1068  }
1069  return Nothing<bool>();
1070}
1071
1072// static
1073Maybe<bool> Object::LessThanOrEqual(Isolate* isolate, Handle<Object> x,
1074                                    Handle<Object> y) {
1075  Maybe<ComparisonResult> result = Compare(isolate, x, y);
1076  if (result.IsJust()) {
1077    switch (result.FromJust()) {
1078      case ComparisonResult::kEqual:
1079      case ComparisonResult::kLessThan:
1080        return Just(true);
1081      case ComparisonResult::kGreaterThan:
1082      case ComparisonResult::kUndefined:
1083        return Just(false);
1084    }
1085  }
1086  return Nothing<bool>();
1087}
1088
1089MaybeHandle<Object> Object::GetPropertyOrElement(Isolate* isolate,
1090                                                 Handle<Object> object,
1091                                                 Handle<Name> name) {
1092  PropertyKey key(isolate, name);
1093  LookupIterator it(isolate, object, key);
1094  return GetProperty(&it);
1095}
1096
1097MaybeHandle<Object> Object::SetPropertyOrElement(
1098    Isolate* isolate, Handle<Object> object, Handle<Name> name,
1099    Handle<Object> value, Maybe<ShouldThrow> should_throw,
1100    StoreOrigin store_origin) {
1101  PropertyKey key(isolate, name);
1102  LookupIterator it(isolate, object, key);
1103  MAYBE_RETURN_NULL(SetProperty(&it, value, store_origin, should_throw));
1104  return value;
1105}
1106
1107MaybeHandle<Object> Object::GetPropertyOrElement(Handle<Object> receiver,
1108                                                 Handle<Name> name,
1109                                                 Handle<JSReceiver> holder) {
1110  Isolate* isolate = holder->GetIsolate();
1111  PropertyKey key(isolate, name);
1112  LookupIterator it(isolate, receiver, key, holder);
1113  return GetProperty(&it);
1114}
1115
1116// static
1117Object Object::GetSimpleHash(Object object) {
1118  DisallowGarbageCollection no_gc;
1119  if (object.IsSmi()) {
1120    uint32_t hash = ComputeUnseededHash(Smi::ToInt(object));
1121    return Smi::FromInt(hash & Smi::kMaxValue);
1122  }
1123  auto instance_type = HeapObject::cast(object).map().instance_type();
1124  if (InstanceTypeChecker::IsHeapNumber(instance_type)) {
1125    double num = HeapNumber::cast(object).value();
1126    if (std::isnan(num)) return Smi::FromInt(Smi::kMaxValue);
1127    // Use ComputeUnseededHash for all values in Signed32 range, including -0,
1128    // which is considered equal to 0 because collections use SameValueZero.
1129    uint32_t hash;
1130    // Check range before conversion to avoid undefined behavior.
1131    if (num >= kMinInt && num <= kMaxInt && FastI2D(FastD2I(num)) == num) {
1132      hash = ComputeUnseededHash(FastD2I(num));
1133    } else {
1134      hash = ComputeLongHash(base::double_to_uint64(num));
1135    }
1136    return Smi::FromInt(hash & Smi::kMaxValue);
1137  } else if (InstanceTypeChecker::IsName(instance_type)) {
1138    uint32_t hash = Name::cast(object).EnsureHash();
1139    return Smi::FromInt(hash);
1140  } else if (InstanceTypeChecker::IsOddball(instance_type)) {
1141    uint32_t hash = Oddball::cast(object).to_string().EnsureHash();
1142    return Smi::FromInt(hash);
1143  } else if (InstanceTypeChecker::IsBigInt(instance_type)) {
1144    uint32_t hash = BigInt::cast(object).Hash();
1145    return Smi::FromInt(hash & Smi::kMaxValue);
1146  } else if (InstanceTypeChecker::IsSharedFunctionInfo(instance_type)) {
1147    uint32_t hash = SharedFunctionInfo::cast(object).Hash();
1148    return Smi::FromInt(hash & Smi::kMaxValue);
1149  }
1150  DCHECK(object.IsJSReceiver());
1151  return object;
1152}
1153
1154Object Object::GetHash() {
1155  DisallowGarbageCollection no_gc;
1156  Object hash = GetSimpleHash(*this);
1157  if (hash.IsSmi()) return hash;
1158
1159  DCHECK(IsJSReceiver());
1160  JSReceiver receiver = JSReceiver::cast(*this);
1161  return receiver.GetIdentityHash();
1162}
1163
1164bool Object::IsShared() const {
1165  // This logic should be kept in sync with fast paths in
1166  // CodeStubAssembler::SharedValueBarrier.
1167
1168  // Smis are trivially shared.
1169  if (IsSmi()) return true;
1170
1171  HeapObject object = HeapObject::cast(*this);
1172
1173  // RO objects are shared when the RO space is shared.
1174  if (IsReadOnlyHeapObject(object)) {
1175    return ReadOnlyHeap::IsReadOnlySpaceShared();
1176  }
1177
1178  // Check if this object is already shared.
1179  switch (object.map().instance_type()) {
1180    case SHARED_STRING_TYPE:
1181    case SHARED_ONE_BYTE_STRING_TYPE:
1182    case JS_SHARED_STRUCT_TYPE:
1183      DCHECK(object.InSharedHeap());
1184      return true;
1185    case INTERNALIZED_STRING_TYPE:
1186    case ONE_BYTE_INTERNALIZED_STRING_TYPE:
1187      if (FLAG_shared_string_table) {
1188        DCHECK(object.InSharedHeap());
1189        return true;
1190      }
1191      return false;
1192    case HEAP_NUMBER_TYPE:
1193      return object.InSharedWritableHeap();
1194    default:
1195      return false;
1196  }
1197}
1198
1199// static
1200MaybeHandle<Object> Object::Share(Isolate* isolate, Handle<Object> value,
1201                                  ShouldThrow throw_if_cannot_be_shared) {
1202  // Sharing values requires the RO space be shared.
1203  DCHECK(ReadOnlyHeap::IsReadOnlySpaceShared());
1204  if (value->IsShared()) return value;
1205  return ShareSlow(isolate, Handle<HeapObject>::cast(value),
1206                   throw_if_cannot_be_shared);
1207}
1208
1209// https://tc39.es/ecma262/#sec-canbeheldweakly
1210bool Object::CanBeHeldWeakly() const {
1211  if (IsJSReceiver()) {
1212    // TODO(v8:12547) Shared structs and arrays should only be able to point
1213    // to shared values in weak collections. For now, disallow them as weak
1214    // collection keys.
1215    if (FLAG_harmony_struct) {
1216      return !IsJSSharedStruct();
1217    }
1218    return true;
1219  }
1220  return IsSymbol() && !Symbol::cast(*this).is_in_public_symbol_table();
1221}
1222
1223Handle<Object> ObjectHashTableShape::AsHandle(Handle<Object> key) {
1224  return key;
1225}
1226
1227Relocatable::Relocatable(Isolate* isolate) {
1228  isolate_ = isolate;
1229  prev_ = isolate->relocatable_top();
1230  isolate->set_relocatable_top(this);
1231}
1232
1233Relocatable::~Relocatable() {
1234  DCHECK_EQ(isolate_->relocatable_top(), this);
1235  isolate_->set_relocatable_top(prev_);
1236}
1237
1238// Predictably converts HeapObject or Address to uint32 by calculating
1239// offset of the address in respective MemoryChunk.
1240static inline uint32_t ObjectAddressForHashing(Address object) {
1241  uint32_t value = static_cast<uint32_t>(object);
1242  return value & kPageAlignmentMask;
1243}
1244
1245static inline Handle<Object> MakeEntryPair(Isolate* isolate, size_t index,
1246                                           Handle<Object> value) {
1247  Handle<Object> key = isolate->factory()->SizeToString(index);
1248  Handle<FixedArray> entry_storage = isolate->factory()->NewFixedArray(2);
1249  {
1250    entry_storage->set(0, *key, SKIP_WRITE_BARRIER);
1251    entry_storage->set(1, *value, SKIP_WRITE_BARRIER);
1252  }
1253  return isolate->factory()->NewJSArrayWithElements(entry_storage,
1254                                                    PACKED_ELEMENTS, 2);
1255}
1256
1257static inline Handle<Object> MakeEntryPair(Isolate* isolate, Handle<Object> key,
1258                                           Handle<Object> value) {
1259  Handle<FixedArray> entry_storage = isolate->factory()->NewFixedArray(2);
1260  {
1261    entry_storage->set(0, *key, SKIP_WRITE_BARRIER);
1262    entry_storage->set(1, *value, SKIP_WRITE_BARRIER);
1263  }
1264  return isolate->factory()->NewJSArrayWithElements(entry_storage,
1265                                                    PACKED_ELEMENTS, 2);
1266}
1267
1268FreshlyAllocatedBigInt FreshlyAllocatedBigInt::cast(Object object) {
1269  SLOW_DCHECK(object.IsBigInt());
1270  return FreshlyAllocatedBigInt(object.ptr());
1271}
1272
1273}  // namespace internal
1274}  // namespace v8
1275
1276#include "src/objects/object-macros-undef.h"
1277
1278#endif  // V8_OBJECTS_OBJECTS_INL_H_
1279