summaryrefslogtreecommitdiffstats
path: root/chromium/v8/src/objects/heap-object.h
blob: ba996bd8307b734fb42f244a5c073c6c64219bb6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_OBJECTS_HEAP_OBJECT_H_
#define V8_OBJECTS_HEAP_OBJECT_H_

#include "src/common/globals.h"
#include "src/objects/instance-type.h"
#include "src/objects/objects.h"
#include "src/objects/tagged-field.h"

// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"

namespace v8 {
namespace internal {

class Heap;
class PrimitiveHeapObject;
class ExternalPointerSlot;
class IndirectPointerSlot;
template <typename T>
class Tagged;

// HeapObject is the superclass for all classes describing heap allocated
// objects.
class HeapObject : public Object {
 public:
  bool is_null() const {
    return static_cast<Tagged_t>(ptr()) == static_cast<Tagged_t>(kNullAddress);
  }

  // [map]: Contains a map which contains the object's reflective
  // information.
  DECL_GETTER(map, Tagged<Map>)
  inline void set_map(Tagged<Map> value);

  // This method behaves the same as `set_map` but marks the map transition as
  // safe for the concurrent marker (object layout doesn't change) during
  // verification.
  inline void set_map_safe_transition(Tagged<Map> value);

  inline ObjectSlot map_slot() const;

  // The no-write-barrier version.  This is OK if the object is white and in
  // new space, or if the value is an immortal immutable object, like the maps
  // of primitive (non-JS) objects like strings, heap numbers etc.
  inline void set_map_no_write_barrier(Tagged<Map> value,
                                       RelaxedStoreTag = kRelaxedStore);
  inline void set_map_no_write_barrier(Tagged<Map> value, ReleaseStoreTag);
  inline void set_map_safe_transition_no_write_barrier(
      Tagged<Map> value, RelaxedStoreTag = kRelaxedStore);
  inline void set_map_safe_transition_no_write_barrier(Tagged<Map> value,
                                                       ReleaseStoreTag);

  // Access the map using acquire load and release store.
  DECL_ACQUIRE_GETTER(map, Tagged<Map>)
  inline void set_map(Tagged<Map> value, ReleaseStoreTag);
  inline void set_map_safe_transition(Tagged<Map> value, ReleaseStoreTag);

  // Compare-and-swaps map word using release store, returns true if the map
  // word was actually swapped.
  inline bool release_compare_and_swap_map_word_forwarded(
      MapWord old_map_word, Tagged<HeapObject> new_target_object);

  // Initialize the map immediately after the object is allocated.
  // Do not use this outside Heap.
  inline void set_map_after_allocation(
      Tagged<Map> value, WriteBarrierMode mode = UPDATE_WRITE_BARRIER);

  // During garbage collection, the map word of a heap object does not
  // necessarily contain a map pointer.
  DECL_RELAXED_GETTER(map_word, MapWord)
  inline void set_map_word(Tagged<Map> map, RelaxedStoreTag);
  inline void set_map_word_forwarded(Tagged<HeapObject> target_object,
                                     RelaxedStoreTag);

  // Access the map word using acquire load and release store.
  DECL_ACQUIRE_GETTER(map_word, MapWord)
  inline void set_map_word(Tagged<Map> map, ReleaseStoreTag);
  inline void set_map_word_forwarded(Tagged<HeapObject> target_object,
                                     ReleaseStoreTag);

  // This method exists to help remove GetIsolate/GetHeap from HeapObject, in a
  // way that doesn't require passing Isolate/Heap down huge call chains or to
  // places where it might not be safe to access it.
  inline ReadOnlyRoots GetReadOnlyRoots() const;
  // This version is intended to be used for the isolate values produced by
  // i::GetPtrComprCageBase(HeapObject) function which may return nullptr.
  inline ReadOnlyRoots GetReadOnlyRoots(PtrComprCageBase cage_base) const;
  // This is slower, but safe to call during bootstrapping.
  inline ReadOnlyRoots EarlyGetReadOnlyRoots() const;

  // Whether the object is in the RO heap and the RO heap is shared, or in the
  // writable shared heap.
  V8_INLINE bool InAnySharedSpace() const;

  V8_INLINE bool InWritableSharedSpace() const;

  V8_INLINE bool InReadOnlySpace() const;

  // Converts an address to a HeapObject pointer.
  static inline Tagged<HeapObject> FromAddress(Address address) {
    DCHECK_TAG_ALIGNED(address);
    return Tagged<HeapObject>::unchecked_cast(
        Tagged<Object>(address + kHeapObjectTag));
  }

  // Returns the address of this HeapObject.
  inline Address address() const { return ptr() - kHeapObjectTag; }

  // Iterates over pointers contained in the object (including the Map).
  // If it's not performance critical iteration use the non-templatized
  // version.
  void Iterate(PtrComprCageBase cage_base, ObjectVisitor* v);

  template <typename ObjectVisitor>
  inline void IterateFast(PtrComprCageBase cage_base, ObjectVisitor* v);

  template <typename ObjectVisitor>
  inline void IterateFast(Tagged<Map> map, ObjectVisitor* v);

  template <typename ObjectVisitor>
  inline void IterateFast(Tagged<Map> map, int object_size, ObjectVisitor* v);

  // Iterates over all pointers contained in the object except the
  // first map pointer.  The object type is given in the first
  // parameter. This function does not access the map pointer in the
  // object, and so is safe to call while the map pointer is modified.
  // If it's not performance critical iteration use the non-templatized
  // version.
  void IterateBody(PtrComprCageBase cage_base, ObjectVisitor* v);
  void IterateBody(Tagged<Map> map, int object_size, ObjectVisitor* v);

  template <typename ObjectVisitor>
  inline void IterateBodyFast(PtrComprCageBase cage_base, ObjectVisitor* v);

  template <typename ObjectVisitor>
  inline void IterateBodyFast(Tagged<Map> map, int object_size,
                              ObjectVisitor* v);

  // Returns the heap object's size in bytes
  DECL_GETTER(Size, int)

  // Given a heap object's map pointer, returns the heap size in bytes
  // Useful when the map pointer field is used for other purposes.
  // GC internal.
  V8_EXPORT_PRIVATE int SizeFromMap(Tagged<Map> map) const;

  template <class T, typename std::enable_if<std::is_arithmetic<T>::value ||
                                                 std::is_enum<T>::value,
                                             int>::type = 0>
  inline T ReadField(size_t offset) const {
    return ReadMaybeUnalignedValue<T>(field_address(offset));
  }

  template <class T, typename std::enable_if<std::is_arithmetic<T>::value ||
                                                 std::is_enum<T>::value,
                                             int>::type = 0>
  inline void WriteField(size_t offset, T value) const {
    return WriteMaybeUnalignedValue<T>(field_address(offset), value);
  }

  // Atomically reads a field using relaxed memory ordering. Can only be used
  // with integral types whose size is <= kTaggedSize (to guarantee alignment).
  template <class T,
            typename std::enable_if<(std::is_arithmetic<T>::value ||
                                     std::is_enum<T>::value) &&
                                        !std::is_floating_point<T>::value,
                                    int>::type = 0>
  inline T Relaxed_ReadField(size_t offset) const;

  // Atomically writes a field using relaxed memory ordering. Can only be used
  // with integral types whose size is <= kTaggedSize (to guarantee alignment).
  template <class T,
            typename std::enable_if<(std::is_arithmetic<T>::value ||
                                     std::is_enum<T>::value) &&
                                        !std::is_floating_point<T>::value,
                                    int>::type = 0>
  inline void Relaxed_WriteField(size_t offset, T value);

  // Atomically compares and swaps a field using seq cst memory ordering.
  // Contains the required logic to properly handle number comparison.
  template <typename CompareAndSwapImpl>
  static Tagged<Object> SeqCst_CompareAndSwapField(
      Tagged<Object> expected_value, Tagged<Object> new_value,
      CompareAndSwapImpl compare_and_swap_impl);

  //
  // SandboxedPointer_t field accessors.
  //
  inline Address ReadSandboxedPointerField(size_t offset,
                                           PtrComprCageBase cage_base) const;
  inline void WriteSandboxedPointerField(size_t offset,
                                         PtrComprCageBase cage_base,
                                         Address value);
  inline void WriteSandboxedPointerField(size_t offset, Isolate* isolate,
                                         Address value);

  //
  // BoundedSize field accessors.
  //
  inline size_t ReadBoundedSizeField(size_t offset) const;
  inline void WriteBoundedSizeField(size_t offset, size_t value);

  //
  // ExternalPointer_t field accessors.
  //
  template <ExternalPointerTag tag>
  inline void InitExternalPointerField(size_t offset, Isolate* isolate,
                                       Address value);
  template <ExternalPointerTag tag>
  inline Address ReadExternalPointerField(size_t offset,
                                          Isolate* isolate) const;
  template <ExternalPointerTag tag>
  inline void WriteExternalPointerField(size_t offset, Isolate* isolate,
                                        Address value);

  template <ExternalPointerTag tag>
  inline void WriteLazilyInitializedExternalPointerField(size_t offset,
                                                         Isolate* isolate,
                                                         Address value);

  inline void ResetLazilyInitializedExternalPointerField(size_t offset);

  //
  // IndirectPointer field accessors.
  //
  inline Tagged<Object> ReadIndirectPointerField(size_t offset) const;

  //
  // CodePointer field accessors.
  //
  inline void InitCodePointerTableEntryField(size_t offset, Isolate* isolate,
                                             Tagged<Code> owning_code,
                                             Address entrypoint);
  inline Address ReadCodeEntrypointField(size_t offset) const;
  inline void WriteCodeEntrypointField(size_t offset, Address value);

  // Returns the field at offset in obj, as a read/write Object reference.
  // Does no checking, and is safe to use during GC, while maps are invalid.
  // Does not invoke write barrier, so should only be assigned to
  // during marking GC.
  inline ObjectSlot RawField(int byte_offset) const;
  inline MaybeObjectSlot RawMaybeWeakField(int byte_offset) const;
  inline InstructionStreamSlot RawInstructionStreamField(int byte_offset) const;
  inline ExternalPointerSlot RawExternalPointerField(int byte_offset) const;
  inline IndirectPointerSlot RawIndirectPointerField(int byte_offset) const;

  DECL_CAST(HeapObject)

  // Return the write barrier mode for this. Callers of this function
  // must be able to present a reference to an DisallowGarbageCollection
  // object as a sign that they are not going to use this function
  // from code that allocates and thus invalidates the returned write
  // barrier mode.
  inline WriteBarrierMode GetWriteBarrierMode(
      const DisallowGarbageCollection& promise);

  // Dispatched behavior.
  void HeapObjectShortPrint(std::ostream& os);
#ifdef OBJECT_PRINT
  void PrintHeader(std::ostream& os, const char* id);
#endif
  DECL_PRINTER(HeapObject)
  EXPORT_DECL_VERIFIER(HeapObject)
#ifdef VERIFY_HEAP
  inline void VerifyObjectField(Isolate* isolate, int offset);
  inline void VerifySmiField(int offset);
  inline void VerifyMaybeObjectField(Isolate* isolate, int offset);

  // Verify a pointer is a valid HeapObject pointer that points to object
  // areas in the heap.
  static void VerifyHeapPointer(Isolate* isolate, Tagged<Object> p);
  static void VerifyCodePointer(Isolate* isolate, Tagged<Object> p);
#endif

  static inline AllocationAlignment RequiredAlignment(Tagged<Map> map);
  bool inline CheckRequiredAlignment(PtrComprCageBase cage_base) const;

  // Whether the object needs rehashing. That is the case if the object's
  // content depends on v8_flags.hash_seed. When the object is deserialized into
  // a heap with a different hash seed, these objects need to adapt.
  bool NeedsRehashing(InstanceType instance_type) const;
  bool NeedsRehashing(PtrComprCageBase cage_base) const;

  // Rehashing support is not implemented for all objects that need rehashing.
  // With objects that need rehashing but cannot be rehashed, rehashing has to
  // be disabled.
  bool CanBeRehashed(PtrComprCageBase cage_base) const;

  // Rehash the object based on the layout inferred from its map.
  template <typename IsolateT>
  void RehashBasedOnMap(IsolateT* isolate);

  // Layout description.
#define HEAP_OBJECT_FIELDS(V) \
  V(kMapOffset, kTaggedSize)  \
  /* Header size. */          \
  V(kHeaderSize, 0)

  DEFINE_FIELD_OFFSET_CONSTANTS(Object::kHeaderSize, HEAP_OBJECT_FIELDS)
#undef HEAP_OBJECT_FIELDS

  static_assert(kMapOffset == Internals::kHeapObjectMapOffset);

  using MapField = TaggedField<MapWord, HeapObject::kMapOffset>;

  inline Address GetFieldAddress(int field_offset) const;

 protected:
  OBJECT_CONSTRUCTORS(HeapObject, Object);

  inline Address field_address(size_t offset) const {
    return ptr() + offset - kHeapObjectTag;
  }

 private:
  enum class VerificationMode {
    kSafeMapTransition,
    kPotentialLayoutChange,
  };

  enum class EmitWriteBarrier {
    kYes,
    kNo,
  };

  template <EmitWriteBarrier emit_write_barrier, typename MemoryOrder>
  V8_INLINE void set_map(Tagged<Map> value, MemoryOrder order,
                         VerificationMode mode);
};

OBJECT_CONSTRUCTORS_IMPL(HeapObject, Object)
CAST_ACCESSOR(HeapObject)

// Define Tagged<HeapObject> now that HeapObject exists.
constexpr HeapObject Tagged<HeapObject>::operator*() const {
  return ToRawPtr();
}
constexpr detail::TaggedOperatorArrowRef<HeapObject>
Tagged<HeapObject>::operator->() const {
  return detail::TaggedOperatorArrowRef<HeapObject>{ToRawPtr()};
}
// Implicit conversions and explicit casts to/from raw pointers
// TODO(leszeks): Remove once we're using Tagged everywhere.
// NOLINTNEXTLINE
constexpr Tagged<HeapObject>::operator HeapObject() {
  static_assert(kTaggedCanConvertToRawObjects);
  return ToRawPtr();
}
constexpr HeapObject Tagged<HeapObject>::ToRawPtr() const {
  return HeapObject(this->ptr(), HeapObject::SkipTypeCheckTag{});
}

// Overload Is* predicates for HeapObject.
#define IS_TYPE_FUNCTION_DECL(Type)                                            \
  V8_INLINE bool Is##Type(Tagged<HeapObject> obj);                             \
  V8_INLINE bool Is##Type(Tagged<HeapObject> obj, PtrComprCageBase cage_base); \
  V8_INLINE bool Is##Type(HeapObject obj);                                     \
  V8_INLINE bool Is##Type(HeapObject obj, PtrComprCageBase cage_base);
HEAP_OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DECL)
IS_TYPE_FUNCTION_DECL(HashTableBase)
IS_TYPE_FUNCTION_DECL(SmallOrderedHashTable)
#undef IS_TYPE_FUNCTION_DECL

// Most calls to Is<Oddball> should go via the Tagged<Object> overloads, withst
// an Isolate/LocalIsolate/ReadOnlyRoots parameter.
#define IS_TYPE_FUNCTION_DECL(Type, Value, _)      \
  V8_INLINE bool Is##Type(Tagged<HeapObject> obj); \
  V8_INLINE bool Is##Type(HeapObject obj);
ODDBALL_LIST(IS_TYPE_FUNCTION_DECL)
HOLE_LIST(IS_TYPE_FUNCTION_DECL)
IS_TYPE_FUNCTION_DECL(NullOrUndefined, , /* unused */)
#undef IS_TYPE_FUNCTION_DECL

#define DECL_STRUCT_PREDICATE(NAME, Name, name)                                \
  V8_INLINE bool Is##Name(Tagged<HeapObject> obj);                             \
  V8_INLINE bool Is##Name(Tagged<HeapObject> obj, PtrComprCageBase cage_base); \
  V8_INLINE bool Is##Name(HeapObject obj);                                     \
  V8_INLINE bool Is##Name(HeapObject obj, PtrComprCageBase cage_base);
STRUCT_LIST(DECL_STRUCT_PREDICATE)
#undef DECL_STRUCT_PREDICATE

}  // namespace internal
}  // namespace v8

#include "src/objects/object-macros-undef.h"

#endif  // V8_OBJECTS_HEAP_OBJECT_H_