1 // Copyright 2017 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_MAP_H_
6 #define V8_OBJECTS_MAP_H_
7 
8 #include "src/base/bit-field.h"
9 #include "src/common/globals.h"
10 #include "src/objects/code.h"
11 #include "src/objects/heap-object.h"
12 #include "src/objects/internal-index.h"
13 #include "src/objects/objects.h"
14 #include "torque-generated/bit-fields.h"
15 #include "torque-generated/visitor-lists.h"
16 
17 // Has to be the last include (doesn't have include guards):
18 #include "src/objects/object-macros.h"
19 
20 namespace v8 {
21 namespace internal {
22 
23 class WasmTypeInfo;
24 
25 enum InstanceType : uint16_t;
26 
27 #define DATA_ONLY_VISITOR_ID_LIST(V) \
28   V(BigInt)                          \
29   V(ByteArray)                       \
30   V(CoverageInfo)                    \
31   V(DataObject)                      \
32   V(FeedbackMetadata)                \
33   V(FixedDoubleArray)
34 
35 #define POINTER_VISITOR_ID_LIST(V)      \
36   V(AllocationSite)                     \
37   V(BytecodeArray)                      \
38   V(Cell)                               \
39   V(Code)                               \
40   V(CodeDataContainer)                  \
41   V(DataHandler)                        \
42   V(EmbedderDataArray)                  \
43   V(EphemeronHashTable)                 \
44   V(FeedbackCell)                       \
45   V(FreeSpace)                          \
46   V(JSApiObject)                        \
47   V(JSArrayBuffer)                      \
48   V(JSDataView)                         \
49   V(JSFunction)                         \
50   V(JSObject)                           \
51   V(JSObjectFast)                       \
52   V(JSTypedArray)                       \
53   V(JSWeakRef)                          \
54   V(JSWeakCollection)                   \
55   V(Map)                                \
56   V(NativeContext)                      \
57   V(PreparseData)                       \
58   V(PropertyArray)                      \
59   V(PropertyCell)                       \
60   V(PrototypeInfo)                      \
61   V(ShortcutCandidate)                  \
62   V(SmallOrderedHashMap)                \
63   V(SmallOrderedHashSet)                \
64   V(SmallOrderedNameDictionary)         \
65   V(SourceTextModule)                   \
66   V(Struct)                             \
67   V(SwissNameDictionary)                \
68   V(Symbol)                             \
69   V(SyntheticModule)                    \
70   V(TransitionArray)                    \
71   IF_WASM(V, WasmArray)                 \
72   IF_WASM(V, WasmCapiFunctionData)      \
73   IF_WASM(V, WasmExportedFunctionData)  \
74   IF_WASM(V, WasmFunctionData)          \
75   IF_WASM(V, WasmIndirectFunctionTable) \
76   IF_WASM(V, WasmInstanceObject)        \
77   IF_WASM(V, WasmJSFunctionData)        \
78   IF_WASM(V, WasmStruct)                \
79   IF_WASM(V, WasmTypeInfo)              \
80   V(WeakCell)
81 
82 #define TORQUE_VISITOR_ID_LIST(V)     \
83   TORQUE_DATA_ONLY_VISITOR_ID_LIST(V) \
84   TORQUE_POINTER_VISITOR_ID_LIST(V)
85 
86 // Objects with the same visitor id are processed in the same way by
87 // the heap visitors. The visitor ids for data only objects must precede
88 // other visitor ids. We rely on kDataOnlyVisitorIdCount for quick check
89 // of whether an object contains only data or may contain pointers.
90 enum VisitorId {
91 #define VISITOR_ID_ENUM_DECL(id) kVisit##id,
92   DATA_ONLY_VISITOR_ID_LIST(VISITOR_ID_ENUM_DECL)
93       TORQUE_DATA_ONLY_VISITOR_ID_LIST(VISITOR_ID_ENUM_DECL)
94           kDataOnlyVisitorIdCount,
95   POINTER_VISITOR_ID_LIST(VISITOR_ID_ENUM_DECL)
96       TORQUE_POINTER_VISITOR_ID_LIST(VISITOR_ID_ENUM_DECL)
97 #undef VISITOR_ID_ENUM_DECL
98           kVisitorIdCount
99 };
100 
101 enum class ObjectFields {
102   kDataOnly,
103   kMaybePointers,
104 };
105 
106 using MapHandles = std::vector<Handle<Map>>;
107 
108 #include "torque-generated/src/objects/map-tq.inc"
109 
110 // All heap objects have a Map that describes their structure.
111 //  A Map contains information about:
112 //  - Size information about the object
113 //  - How to iterate over an object (for garbage collection)
114 //
115 // Map layout:
116 // +---------------+-------------------------------------------------+
117 // |   _ Type _    | _ Description _                                 |
118 // +---------------+-------------------------------------------------+
119 // | TaggedPointer | map - Always a pointer to the MetaMap root      |
120 // +---------------+-------------------------------------------------+
121 // | Int           | The first int field                             |
122 //  `---+----------+-------------------------------------------------+
123 //      | Byte     | [instance_size]                                 |
124 //      +----------+-------------------------------------------------+
125 //      | Byte     | If Map for a primitive type:                    |
126 //      |          |   native context index for constructor fn       |
127 //      |          | If Map for an Object type:                      |
128 //      |          |   inobject properties start offset in words     |
129 //      +----------+-------------------------------------------------+
130 //      | Byte     | [used_or_unused_instance_size_in_words]         |
131 //      |          | For JSObject in fast mode this byte encodes     |
132 //      |          | the size of the object that includes only       |
133 //      |          | the used property fields or the slack size      |
134 //      |          | in properties backing store.                    |
135 //      +----------+-------------------------------------------------+
136 //      | Byte     | [visitor_id]                                    |
137 // +----+----------+-------------------------------------------------+
138 // | Int           | The second int field                            |
139 //  `---+----------+-------------------------------------------------+
140 //      | Short    | [instance_type]                                 |
141 //      +----------+-------------------------------------------------+
142 //      | Byte     | [bit_field]                                     |
143 //      |          |   - has_non_instance_prototype (bit 0)          |
144 //      |          |   - is_callable (bit 1)                         |
145 //      |          |   - has_named_interceptor (bit 2)               |
146 //      |          |   - has_indexed_interceptor (bit 3)             |
147 //      |          |   - is_undetectable (bit 4)                     |
148 //      |          |   - is_access_check_needed (bit 5)              |
149 //      |          |   - is_constructor (bit 6)                      |
150 //      |          |   - has_prototype_slot (bit 7)                  |
151 //      +----------+-------------------------------------------------+
152 //      | Byte     | [bit_field2]                                    |
153 //      |          |   - new_target_is_base (bit 0)                  |
154 //      |          |   - is_immutable_proto (bit 1)                  |
155 //      |          |   - elements_kind (bits 2..7)                   |
156 // +----+----------+-------------------------------------------------+
157 // | Int           | [bit_field3]                                    |
158 // |               |   - enum_length (bit 0..9)                      |
159 // |               |   - number_of_own_descriptors (bit 10..19)      |
160 // |               |   - is_prototype_map (bit 20)                   |
161 // |               |   - is_dictionary_map (bit 21)                  |
162 // |               |   - owns_descriptors (bit 22)                   |
163 // |               |   - is_in_retained_map_list (bit 23)            |
164 // |               |   - is_deprecated (bit 24)                      |
165 // |               |   - is_unstable (bit 25)                        |
166 // |               |   - is_migration_target (bit 26)                |
167 // |               |   - is_extensible (bit 28)                      |
168 // |               |   - may_have_interesting_symbols (bit 28)       |
169 // |               |   - construction_counter (bit 29..31)           |
170 // |               |                                                 |
171 // +*****************************************************************+
172 // | Int           | On systems with 64bit pointer types, there      |
173 // |               | is an unused 32bits after bit_field3            |
174 // +*****************************************************************+
175 // | TaggedPointer | [prototype]                                     |
176 // +---------------+-------------------------------------------------+
177 // | TaggedPointer | [constructor_or_back_pointer_or_native_context] |
178 // +---------------+-------------------------------------------------+
179 // | TaggedPointer | [instance_descriptors]                          |
180 // +*****************************************************************+
181 // | TaggedPointer | [dependent_code]                                |
182 // +---------------+-------------------------------------------------+
183 // | TaggedPointer | [prototype_validity_cell]                       |
184 // +---------------+-------------------------------------------------+
185 // | TaggedPointer | If Map is a prototype map:                      |
186 // |               |   [prototype_info]                              |
187 // |               | Else:                                           |
188 // |               |   [raw_transitions]                             |
189 // +---------------+-------------------------------------------------+
190 
191 class Map : public TorqueGeneratedMap<Map, HeapObject> {
192  public:
193   // Instance size.
194   // Size in bytes or kVariableSizeSentinel if instances do not have
195   // a fixed size.
196   DECL_INT_ACCESSORS(instance_size)
197   // Size in words or kVariableSizeSentinel if instances do not have
198   // a fixed size.
199   DECL_INT_ACCESSORS(instance_size_in_words)
200 
201   // [inobject_properties_start_or_constructor_function_index]:
202   // Provides access to the inobject properties start offset in words in case of
203   // JSObject maps, or the constructor function index in case of primitive maps.
204   DECL_INT_ACCESSORS(inobject_properties_start_or_constructor_function_index)
205 
206   // Get/set the in-object property area start offset in words in the object.
207   inline int GetInObjectPropertiesStartInWords() const;
208   inline void SetInObjectPropertiesStartInWords(int value);
209   // Count of properties allocated in the object (JSObject only).
210   inline int GetInObjectProperties() const;
211   // Index of the constructor function in the native context (primitives only),
212   // or the special sentinel value to indicate that there is no object wrapper
213   // for the primitive (i.e. in case of null or undefined).
214   static const int kNoConstructorFunctionIndex = 0;
215   inline int GetConstructorFunctionIndex() const;
216   inline void SetConstructorFunctionIndex(int value);
217   static base::Optional<JSFunction> GetConstructorFunction(
218       Map map, Context native_context);
219 
220   // Retrieve interceptors.
221   DECL_GETTER(GetNamedInterceptor, InterceptorInfo)
222   DECL_GETTER(GetIndexedInterceptor, InterceptorInfo)
223 
224   // Instance type.
225   DECL_PRIMITIVE_ACCESSORS(instance_type, InstanceType)
226 
227   // Returns the size of the used in-object area including object header
228   // (only used for JSObject in fast mode, for the other kinds of objects it
229   // is equal to the instance size).
230   inline int UsedInstanceSize() const;
231 
232   // Tells how many unused property fields (in-object or out-of object) are
233   // available in the instance (only used for JSObject in fast mode).
234   inline int UnusedPropertyFields() const;
235   // Tells how many unused in-object property words are present.
236   inline int UnusedInObjectProperties() const;
237   // Updates the counters tracking unused fields in the object.
238   inline void SetInObjectUnusedPropertyFields(int unused_property_fields);
239   // Updates the counters tracking unused fields in the property array.
240   inline void SetOutOfObjectUnusedPropertyFields(int unused_property_fields);
241   inline void CopyUnusedPropertyFields(Map map);
242   inline void CopyUnusedPropertyFieldsAdjustedForInstanceSize(Map map);
243   inline void AccountAddedPropertyField();
244   inline void AccountAddedOutOfObjectPropertyField(
245       int unused_in_property_array);
246 
247   //
248   // Bit field.
249   //
250   // The setter in this pair calls the relaxed setter if concurrent marking is
251   // on, or performs the write non-atomically if it's off. The read is always
252   // non-atomically. This is done to have wider TSAN coverage on the cases where
253   // it's possible.
254   DECL_PRIMITIVE_ACCESSORS(bit_field, byte)
255 
256   // Atomic accessors, used for allowlisting legitimate concurrent accesses.
257   DECL_PRIMITIVE_ACCESSORS(relaxed_bit_field, byte)
258 
259   // Bit positions for |bit_field|.
260   struct Bits1 {
261     DEFINE_TORQUE_GENERATED_MAP_BIT_FIELDS1()
262   };
263 
264   //
265   // Bit field 2.
266   //
267   DECL_PRIMITIVE_ACCESSORS(bit_field2, byte)
268 
269   // Bit positions for |bit_field2|.
270   struct Bits2 {
271     DEFINE_TORQUE_GENERATED_MAP_BIT_FIELDS2()
272   };
273 
274   //
275   // Bit field 3.
276   //
277   // {bit_field3} calls the relaxed accessors if concurrent marking is on, or
278   // performs the read/write non-atomically if it's off. This is done to have
279   // wider TSAN coverage on the cases where it's possible.
280   DECL_PRIMITIVE_ACCESSORS(bit_field3, uint32_t)
281 
282   DECL_PRIMITIVE_ACCESSORS(relaxed_bit_field3, uint32_t)
283   DECL_PRIMITIVE_ACCESSORS(release_acquire_bit_field3, uint32_t)
284 
285   // Clear uninitialized padding space. This ensures that the snapshot content
286   // is deterministic. Depending on the V8 build mode there could be no padding.
287   V8_INLINE void clear_padding();
288 
289   // Bit positions for |bit_field3|.
290   struct Bits3 {
291     DEFINE_TORQUE_GENERATED_MAP_BIT_FIELDS3()
292   };
293 
294   // Ensure that Torque-defined bit widths for |bit_field3| are as expected.
295   STATIC_ASSERT(Bits3::EnumLengthBits::kSize == kDescriptorIndexBitCount);
296   STATIC_ASSERT(Bits3::NumberOfOwnDescriptorsBits::kSize ==
297                 kDescriptorIndexBitCount);
298 
299   STATIC_ASSERT(Bits3::NumberOfOwnDescriptorsBits::kMax >=
300                 kMaxNumberOfDescriptors);
301 
302   static const int kSlackTrackingCounterStart = 7;
303   static const int kSlackTrackingCounterEnd = 1;
304   static const int kNoSlackTracking = 0;
305   STATIC_ASSERT(kSlackTrackingCounterStart <=
306                 Bits3::ConstructionCounterBits::kMax);
307 
308   // Inobject slack tracking is the way to reclaim unused inobject space.
309   //
310   // The instance size is initially determined by adding some slack to
311   // expected_nof_properties (to allow for a few extra properties added
312   // after the constructor). There is no guarantee that the extra space
313   // will not be wasted.
314   //
315   // Here is the algorithm to reclaim the unused inobject space:
316   // - Detect the first constructor call for this JSFunction.
317   //   When it happens enter the "in progress" state: initialize construction
318   //   counter in the initial_map.
319   // - While the tracking is in progress initialize unused properties of a new
320   //   object with one_pointer_filler_map instead of undefined_value (the "used"
321   //   part is initialized with undefined_value as usual). This way they can
322   //   be resized quickly and safely.
323   // - Once enough objects have been created  compute the 'slack'
324   //   (traverse the map transition tree starting from the
325   //   initial_map and find the lowest value of unused_property_fields).
326   // - Traverse the transition tree again and decrease the instance size
327   //   of every map. Existing objects will resize automatically (they are
328   //   filled with one_pointer_filler_map). All further allocations will
329   //   use the adjusted instance size.
330   // - SharedFunctionInfo's expected_nof_properties left unmodified since
331   //   allocations made using different closures could actually create different
332   //   kind of objects (see prototype inheritance pattern).
333   //
334   //  Important: inobject slack tracking is not attempted during the snapshot
335   //  creation.
336 
337   static const int kGenerousAllocationCount =
338       kSlackTrackingCounterStart - kSlackTrackingCounterEnd + 1;
339 
340   // Starts the tracking by initializing object constructions countdown counter.
341   void StartInobjectSlackTracking();
342 
343   // True if the object constructions countdown counter is a range
344   // [kSlackTrackingCounterEnd, kSlackTrackingCounterStart].
345   inline bool IsInobjectSlackTrackingInProgress() const;
346 
347   // Does the tracking step.
348   inline void InobjectSlackTrackingStep(Isolate* isolate);
349 
350   // Computes inobject slack for the transition tree starting at this initial
351   // map.
352   int ComputeMinObjectSlack(Isolate* isolate);
353   inline int InstanceSizeFromSlack(int slack) const;
354 
355   // Completes inobject slack tracking for the transition tree starting at this
356   // initial map.
357   V8_EXPORT_PRIVATE void CompleteInobjectSlackTracking(Isolate* isolate);
358 
359   // Tells whether the object in the prototype property will be used
360   // for instances created from this function.  If the prototype
361   // property is set to a value that is not a JSObject, the prototype
362   // property will not be used to create instances of the function.
363   // See ECMA-262, 13.2.2.
364   DECL_BOOLEAN_ACCESSORS(has_non_instance_prototype)
365 
366   // Tells whether the instance has a [[Construct]] internal method.
367   // This property is implemented according to ES6, section 7.2.4.
368   DECL_BOOLEAN_ACCESSORS(is_constructor)
369 
370   // Tells whether the instance with this map may have properties for
371   // interesting symbols on it.
372   // An "interesting symbol" is one for which Name::IsInterestingSymbol()
373   // returns true, i.e. a well-known symbol like @@toStringTag.
374   DECL_BOOLEAN_ACCESSORS(may_have_interesting_symbols)
375 
376   DECL_BOOLEAN_ACCESSORS(has_prototype_slot)
377 
378   // Records and queries whether the instance has a named interceptor.
379   DECL_BOOLEAN_ACCESSORS(has_named_interceptor)
380 
381   // Records and queries whether the instance has an indexed interceptor.
382   DECL_BOOLEAN_ACCESSORS(has_indexed_interceptor)
383 
384   // Tells whether the instance is undetectable.
385   // An undetectable object is a special class of JSObject: 'typeof' operator
386   // returns undefined, ToBoolean returns false. Otherwise it behaves like
387   // a normal JS object.  It is useful for implementing undetectable
388   // document.all in Firefox & Safari.
389   // See https://bugzilla.mozilla.org/show_bug.cgi?id=248549.
390   DECL_BOOLEAN_ACCESSORS(is_undetectable)
391 
392   // Tells whether the instance has a [[Call]] internal method.
393   // This property is implemented according to ES6, section 7.2.3.
394   DECL_BOOLEAN_ACCESSORS(is_callable)
395 
396   DECL_BOOLEAN_ACCESSORS(new_target_is_base)
397   DECL_BOOLEAN_ACCESSORS(is_extensible)
398   DECL_BOOLEAN_ACCESSORS(is_prototype_map)
399   inline bool is_abandoned_prototype_map() const;
400 
401   // Whether the instance has been added to the retained map list by
402   // Heap::AddRetainedMap.
403   DECL_BOOLEAN_ACCESSORS(is_in_retained_map_list)
404 
405   DECL_PRIMITIVE_ACCESSORS(elements_kind, ElementsKind)
406 
407   // Tells whether the instance has fast elements that are only Smis.
408   inline bool has_fast_smi_elements() const;
409 
410   // Tells whether the instance has fast elements.
411   inline bool has_fast_object_elements() const;
412   inline bool has_fast_smi_or_object_elements() const;
413   inline bool has_fast_double_elements() const;
414   inline bool has_fast_elements() const;
415   inline bool has_sloppy_arguments_elements() const;
416   inline bool has_fast_sloppy_arguments_elements() const;
417   inline bool has_fast_string_wrapper_elements() const;
418   inline bool has_typed_array_elements() const;
419   inline bool has_rab_gsab_typed_array_elements() const;
420   inline bool has_typed_array_or_rab_gsab_typed_array_elements() const;
421   inline bool has_any_typed_array_or_wasm_array_elements() const;
422   inline bool has_dictionary_elements() const;
423   inline bool has_any_nonextensible_elements() const;
424   inline bool has_nonextensible_elements() const;
425   inline bool has_sealed_elements() const;
426   inline bool has_frozen_elements() const;
427 
428   // Weakly checks whether a map is detached from all transition trees. If this
429   // returns true, the map is guaranteed to be detached. If it returns false,
430   // there is no guarantee it is attached.
431   inline bool IsDetached(Isolate* isolate) const;
432 
433   // Returns true if there is an object with potentially read-only elements
434   // in the prototype chain. It could be a Proxy, a string wrapper,
435   // an object with DICTIONARY_ELEMENTS potentially containing read-only
436   // elements or an object with any frozen elements, or a slow arguments object.
437   bool MayHaveReadOnlyElementsInPrototypeChain(Isolate* isolate);
438 
439   inline Map ElementsTransitionMap(Isolate* isolate, ConcurrencyMode cmode);
440 
441   inline FixedArrayBase GetInitialElements() const;
442 
443   // [raw_transitions]: Provides access to the transitions storage field.
444   // Don't call set_raw_transitions() directly to overwrite transitions, use
445   // the TransitionArray::ReplaceTransitions() wrapper instead!
446   DECL_ACCESSORS(raw_transitions, MaybeObject)
447   DECL_RELEASE_ACQUIRE_WEAK_ACCESSORS(raw_transitions)
448   // [prototype_info]: Per-prototype metadata. Aliased with transitions
449   // (which prototype maps don't have).
450   DECL_GETTER(prototype_info, Object)
451   DECL_RELEASE_ACQUIRE_ACCESSORS(prototype_info, Object)
452   // PrototypeInfo is created lazily using this helper (which installs it on
453   // the given prototype's map).
454   static Handle<PrototypeInfo> GetOrCreatePrototypeInfo(
455       Handle<JSObject> prototype, Isolate* isolate);
456   static Handle<PrototypeInfo> GetOrCreatePrototypeInfo(
457       Handle<Map> prototype_map, Isolate* isolate);
458   inline bool should_be_fast_prototype_map() const;
459   static void SetShouldBeFastPrototypeMap(Handle<Map> map, bool value,
460                                           Isolate* isolate);
461 
462   // [prototype chain validity cell]: Associated with a prototype object,
463   // stored in that object's map, indicates that prototype chains through this
464   // object are currently valid. The cell will be invalidated and replaced when
465   // the prototype chain changes. When there's nothing to guard (for example,
466   // when direct prototype is null or Proxy) this function returns Smi with
467   // |kPrototypeChainValid| sentinel value.
468   static Handle<Object> GetOrCreatePrototypeChainValidityCell(Handle<Map> map,
469                                                               Isolate* isolate);
470   static const int kPrototypeChainValid = 0;
471   static const int kPrototypeChainInvalid = 1;
472 
473   static bool IsPrototypeChainInvalidated(Map map);
474 
475   // Return the map of the root of object's prototype chain.
476   Map GetPrototypeChainRootMap(Isolate* isolate) const;
477 
478   V8_EXPORT_PRIVATE Map FindRootMap(Isolate* isolate) const;
479   V8_EXPORT_PRIVATE Map FindFieldOwner(Isolate* isolate,
480                                        InternalIndex descriptor) const;
481 
482   inline int GetInObjectPropertyOffset(int index) const;
483 
484   class FieldCounts {
485    public:
FieldCounts(int mutable_count,int const_count)486     FieldCounts(int mutable_count, int const_count)
487         : mutable_count_(mutable_count), const_count_(const_count) {}
488 
GetTotal()489     int GetTotal() const { return mutable_count() + const_count(); }
490 
mutable_count()491     int mutable_count() const { return mutable_count_; }
const_count()492     int const_count() const { return const_count_; }
493 
494    private:
495     int mutable_count_;
496     int const_count_;
497   };
498 
499   FieldCounts GetFieldCounts() const;
500   int NumberOfFields(ConcurrencyMode cmode) const;
501 
502   bool HasOutOfObjectProperties() const;
503 
504   // TODO(ishell): candidate with JSObject::MigrateToMap().
505   bool InstancesNeedRewriting(Map target, ConcurrencyMode cmode) const;
506   bool InstancesNeedRewriting(Map target, int target_number_of_fields,
507                               int target_inobject, int target_unused,
508                               int* old_number_of_fields,
509                               ConcurrencyMode cmode) const;
510   // Returns true if the |field_type| is the most general one for
511   // given |representation|.
512   static inline bool IsMostGeneralFieldType(Representation representation,
513                                             FieldType field_type);
514   static inline bool FieldTypeIsCleared(Representation rep, FieldType type);
515 
516   // Generalizes representation and field_type if objects with given
517   // instance type can have fast elements that can be transitioned by
518   // stubs or optimized code to more general elements kind.
519   // This generalization is necessary in order to ensure that elements kind
520   // transitions performed by stubs / optimized code don't silently transition
521   // fields with representation "Tagged" back to "Smi" or "HeapObject" or
522   // fields with HeapObject representation and "Any" type back to "Class" type.
523   static inline void GeneralizeIfCanHaveTransitionableFastElementsKind(
524       Isolate* isolate, InstanceType instance_type,
525       Representation* representation, Handle<FieldType>* field_type);
526 
527   V8_EXPORT_PRIVATE static Handle<Map> PrepareForDataProperty(
528       Isolate* isolate, Handle<Map> old_map, InternalIndex descriptor_number,
529       PropertyConstness constness, Handle<Object> value);
530 
531   V8_EXPORT_PRIVATE static Handle<Map> Normalize(Isolate* isolate,
532                                                  Handle<Map> map,
533                                                  ElementsKind new_elements_kind,
534                                                  PropertyNormalizationMode mode,
535                                                  const char* reason);
536 
537   inline static Handle<Map> Normalize(Isolate* isolate, Handle<Map> fast_map,
538                                       PropertyNormalizationMode mode,
539                                       const char* reason);
540 
541   // Tells whether the map is used for JSObjects in dictionary mode (ie
542   // normalized objects, ie objects for which HasFastProperties returns false).
543   // A map can never be used for both dictionary mode and fast mode JSObjects.
544   // False by default and for HeapObjects that are not JSObjects.
545   DECL_BOOLEAN_ACCESSORS(is_dictionary_map)
546 
547   // Tells whether the instance needs security checks when accessing its
548   // properties.
549   DECL_BOOLEAN_ACCESSORS(is_access_check_needed)
550 
551   // [prototype]: implicit prototype object.
552   DECL_ACCESSORS(prototype, HeapObject)
553   // TODO(jkummerow): make set_prototype private.
554   V8_EXPORT_PRIVATE static void SetPrototype(
555       Isolate* isolate, Handle<Map> map, Handle<HeapObject> prototype,
556       bool enable_prototype_setup_mode = true);
557 
558   // [constructor]: points back to the function or FunctionTemplateInfo
559   // responsible for this map.
560   // The field overlaps with the back pointer. All maps in a transition tree
561   // have the same constructor, so maps with back pointers can walk the
562   // back pointer chain until they find the map holding their constructor.
563   // Returns null_value if there's neither a constructor function nor a
564   // FunctionTemplateInfo available.
565   // The field also overlaps with the native context pointer for context maps,
566   // and with the Wasm type info for WebAssembly object maps.
567   DECL_ACCESSORS(constructor_or_back_pointer, Object)
568   DECL_RELAXED_ACCESSORS(constructor_or_back_pointer, Object)
569   DECL_ACCESSORS(native_context, NativeContext)
570   DECL_ACCESSORS(native_context_or_null, Object)
571   DECL_ACCESSORS(wasm_type_info, WasmTypeInfo)
572   DECL_GETTER(GetConstructor, Object)
573   DECL_GETTER(GetFunctionTemplateInfo, FunctionTemplateInfo)
574   inline void SetConstructor(Object constructor,
575                              WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
576   // Constructor getter that performs at most the given number of steps
577   // in the transition tree. Returns either the constructor or the map at
578   // which the walk has stopped.
579   inline Object TryGetConstructor(Isolate* isolate, int max_steps);
580   // [back pointer]: points back to the parent map from which a transition
581   // leads to this map. The field overlaps with the constructor (see above).
582   DECL_GETTER(GetBackPointer, HeapObject)
583   inline void SetBackPointer(HeapObject value,
584                              WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
585 
586   // [instance descriptors]: describes the object.
587   DECL_ACCESSORS(instance_descriptors, DescriptorArray)
588   DECL_RELAXED_ACCESSORS(instance_descriptors, DescriptorArray)
589   DECL_ACQUIRE_GETTER(instance_descriptors, DescriptorArray)
590   V8_EXPORT_PRIVATE void SetInstanceDescriptors(Isolate* isolate,
591                                                 DescriptorArray descriptors,
592                                                 int number_of_own_descriptors);
593 
594   inline void UpdateDescriptors(Isolate* isolate, DescriptorArray descriptors,
595                                 int number_of_own_descriptors);
596   inline void InitializeDescriptors(Isolate* isolate,
597                                     DescriptorArray descriptors);
598 
599   // [dependent code]: list of optimized codes that weakly embed this map.
600   DECL_ACCESSORS(dependent_code, DependentCode)
601 
602   // [prototype_validity_cell]: Cell containing the validity bit for prototype
603   // chains or Smi(0) if uninitialized.
604   // The meaning of this validity cell is different for prototype maps and
605   // non-prototype maps.
606   // For prototype maps the validity bit "guards" modifications of prototype
607   // chains going through this object. When a prototype object changes, both its
608   // own validity cell and those of all "downstream" prototypes are invalidated;
609   // handlers for a given receiver embed the currently valid cell for that
610   // receiver's prototype during their creation and check it on execution.
611   // For non-prototype maps which are used as transitioning store handlers this
612   // field contains the validity cell which guards modifications of this map's
613   // prototype.
614   DECL_ACCESSORS(prototype_validity_cell, Object)
615 
616   // Returns true if prototype validity cell value represents "valid" prototype
617   // chain state.
618   inline bool IsPrototypeValidityCellValid() const;
619 
620   inline Name GetLastDescriptorName(Isolate* isolate) const;
621   inline PropertyDetails GetLastDescriptorDetails(Isolate* isolate) const;
622 
623   inline InternalIndex LastAdded() const;
624 
625   inline int NumberOfOwnDescriptors() const;
626   inline void SetNumberOfOwnDescriptors(int number);
627   inline InternalIndex::Range IterateOwnDescriptors() const;
628 
629   inline Cell RetrieveDescriptorsPointer();
630 
631   // Checks whether all properties are stored either in the map or on the object
632   // (inobject, properties, or elements backing store), requiring no special
633   // checks.
634   bool OnlyHasSimpleProperties() const;
635   inline int EnumLength() const;
636   inline void SetEnumLength(int length);
637 
638   DECL_BOOLEAN_ACCESSORS(owns_descriptors)
639 
640   inline void mark_unstable();
641   inline bool is_stable() const;
642 
643   DECL_BOOLEAN_ACCESSORS(is_migration_target)
644 
645   DECL_BOOLEAN_ACCESSORS(is_immutable_proto)
646 
647   // This counter is used for in-object slack tracking.
648   // The in-object slack tracking is considered enabled when the counter is
649   // non zero. The counter only has a valid count for initial maps. For
650   // transitioned maps only kNoSlackTracking has a meaning, namely that inobject
651   // slack tracking already finished for the transition tree. Any other value
652   // indicates that either inobject slack tracking is still in progress, or that
653   // the map isn't part of the transition tree anymore.
654   DECL_INT_ACCESSORS(construction_counter)
655 
656   DECL_BOOLEAN_ACCESSORS(is_deprecated)
657   inline bool CanBeDeprecated() const;
658 
659   // Returns a non-deprecated version of the input. If the input was not
660   // deprecated, it is directly returned. Otherwise, the non-deprecated version
661   // is found by re-transitioning from the root of the transition tree using the
662   // descriptor array of the map. Returns MaybeHandle<Map>() if no updated map
663   // is found.
664   V8_EXPORT_PRIVATE static MaybeHandle<Map> TryUpdate(
665       Isolate* isolate, Handle<Map> map) V8_WARN_UNUSED_RESULT;
666 
667   // Returns a non-deprecated version of the input. This method may deprecate
668   // existing maps along the way if encodings conflict. Not for use while
669   // gathering type feedback. Use TryUpdate in those cases instead.
670   V8_EXPORT_PRIVATE static Handle<Map> Update(Isolate* isolate,
671                                               Handle<Map> map);
672 
673   static inline Handle<Map> CopyInitialMap(Isolate* isolate, Handle<Map> map);
674   V8_EXPORT_PRIVATE static Handle<Map> CopyInitialMap(
675       Isolate* isolate, Handle<Map> map, int instance_size,
676       int in_object_properties, int unused_property_fields);
677   static Handle<Map> CopyInitialMapNormalized(
678       Isolate* isolate, Handle<Map> map,
679       PropertyNormalizationMode mode = CLEAR_INOBJECT_PROPERTIES);
680   static Handle<Map> CopyDropDescriptors(Isolate* isolate, Handle<Map> map);
681   V8_EXPORT_PRIVATE static Handle<Map> CopyInsertDescriptor(
682       Isolate* isolate, Handle<Map> map, Descriptor* descriptor,
683       TransitionFlag flag);
684 
685   static MaybeObjectHandle WrapFieldType(Isolate* isolate,
686                                          Handle<FieldType> type);
687   V8_EXPORT_PRIVATE static FieldType UnwrapFieldType(MaybeObject wrapped_type);
688 
689   V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT static MaybeHandle<Map> CopyWithField(
690       Isolate* isolate, Handle<Map> map, Handle<Name> name,
691       Handle<FieldType> type, PropertyAttributes attributes,
692       PropertyConstness constness, Representation representation,
693       TransitionFlag flag);
694 
695   V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT static MaybeHandle<Map>
696   CopyWithConstant(Isolate* isolate, Handle<Map> map, Handle<Name> name,
697                    Handle<Object> constant, PropertyAttributes attributes,
698                    TransitionFlag flag);
699 
700   // Returns a new map with all transitions dropped from the given map and
701   // the ElementsKind set.
702   static Handle<Map> TransitionElementsTo(Isolate* isolate, Handle<Map> map,
703                                           ElementsKind to_kind);
704 
705   static base::Optional<Map> TryAsElementsKind(Isolate* isolate,
706                                                Handle<Map> map,
707                                                ElementsKind kind,
708                                                ConcurrencyMode cmode);
709   V8_EXPORT_PRIVATE static Handle<Map> AsElementsKind(Isolate* isolate,
710                                                       Handle<Map> map,
711                                                       ElementsKind kind);
712 
713   static Handle<Map> CopyAsElementsKind(Isolate* isolate, Handle<Map> map,
714                                         ElementsKind kind, TransitionFlag flag);
715 
716   static Handle<Map> AsLanguageMode(Isolate* isolate, Handle<Map> initial_map,
717                                     Handle<SharedFunctionInfo> shared_info);
718 
719   V8_EXPORT_PRIVATE static Handle<Map> CopyForPreventExtensions(
720       Isolate* isolate, Handle<Map> map, PropertyAttributes attrs_to_add,
721       Handle<Symbol> transition_marker, const char* reason,
722       bool old_map_is_dictionary_elements_kind = false);
723 
724   // Maximal number of fast properties. Used to restrict the number of map
725   // transitions to avoid an explosion in the number of maps for objects used as
726   // dictionaries.
727   inline bool TooManyFastProperties(StoreOrigin store_origin) const;
728   V8_EXPORT_PRIVATE static Handle<Map> TransitionToDataProperty(
729       Isolate* isolate, Handle<Map> map, Handle<Name> name,
730       Handle<Object> value, PropertyAttributes attributes,
731       PropertyConstness constness, StoreOrigin store_origin);
732   V8_EXPORT_PRIVATE static Handle<Map> TransitionToAccessorProperty(
733       Isolate* isolate, Handle<Map> map, Handle<Name> name,
734       InternalIndex descriptor, Handle<Object> getter, Handle<Object> setter,
735       PropertyAttributes attributes);
736 
737   inline void AppendDescriptor(Isolate* isolate, Descriptor* desc);
738 
739   // Returns a copy of the map, prepared for inserting into the transition
740   // tree (if the |map| owns descriptors then the new one will share
741   // descriptors with |map|).
742   static Handle<Map> CopyForElementsTransition(Isolate* isolate,
743                                                Handle<Map> map);
744 
745   // Returns a copy of the map, with all transitions dropped from the
746   // instance descriptors.
747   static Handle<Map> Copy(Isolate* isolate, Handle<Map> map,
748                           const char* reason);
749   V8_EXPORT_PRIVATE static Handle<Map> Create(Isolate* isolate,
750                                               int inobject_properties);
751 
752   // Returns the next free property index (only valid for FAST MODE).
753   int NextFreePropertyIndex() const;
754 
755   // Returns the number of enumerable properties.
756   int NumberOfEnumerableProperties() const;
757 
758   static inline int SlackForArraySize(int old_size, int size_limit);
759 
760   V8_EXPORT_PRIVATE static void EnsureDescriptorSlack(Isolate* isolate,
761                                                       Handle<Map> map,
762                                                       int slack);
763 
764   // Returns the map to be used for instances when the given {prototype} is
765   // passed to an Object.create call. Might transition the given {prototype}.
766   static Handle<Map> GetObjectCreateMap(Isolate* isolate,
767                                         Handle<HeapObject> prototype);
768 
769   // Computes a hash value for this map, to be used in HashTables and such.
770   int Hash();
771 
772   // Returns the transitioned map for this map with the most generic
773   // elements_kind that's found in |candidates|, or |nullptr| if no match is
774   // found at all.
775   V8_EXPORT_PRIVATE Map FindElementsKindTransitionedMap(
776       Isolate* isolate, MapHandles const& candidates, ConcurrencyMode cmode);
777 
778   inline bool CanTransition() const;
779 
780   static Map GetInstanceTypeMap(ReadOnlyRoots roots, InstanceType type);
781 
782 #define DECL_TESTER(Type, ...) inline bool Is##Type##Map() const;
783   INSTANCE_TYPE_CHECKERS(DECL_TESTER)
784 #undef DECL_TESTER
785   inline bool IsBooleanMap() const;
786   inline bool IsNullOrUndefinedMap() const;
787   inline bool IsPrimitiveMap() const;
788   inline bool IsSpecialReceiverMap() const;
789   inline bool IsCustomElementsReceiverMap() const;
790 
791   bool IsMapInArrayPrototypeChain(Isolate* isolate) const;
792 
793   // Dispatched behavior.
794   void MapPrint(std::ostream& os);
795   DECL_VERIFIER(Map)
796 
797 #ifdef VERIFY_HEAP
798   void DictionaryMapVerify(Isolate* isolate);
799 #endif
800 
DECL_PRIMITIVE_ACCESSORS(visitor_id,VisitorId)801   DECL_PRIMITIVE_ACCESSORS(visitor_id, VisitorId)
802 
803   static ObjectFields ObjectFieldsFrom(VisitorId visitor_id) {
804     return (visitor_id < kDataOnlyVisitorIdCount)
805                ? ObjectFields::kDataOnly
806                : ObjectFields::kMaybePointers;
807   }
808 
809   V8_EXPORT_PRIVATE static Handle<Map> TransitionToPrototype(
810       Isolate* isolate, Handle<Map> map, Handle<HeapObject> prototype);
811 
812   static Handle<Map> TransitionToImmutableProto(Isolate* isolate,
813                                                 Handle<Map> map);
814 
815   static const int kMaxPreAllocatedPropertyFields = 255;
816 
817   STATIC_ASSERT(kInstanceTypeOffset == Internals::kMapInstanceTypeOffset);
818 
819   class BodyDescriptor;
820 
821   // Compares this map to another to see if they describe equivalent objects,
822   // up to the given |elements_kind|.
823   // If |mode| is set to CLEAR_INOBJECT_PROPERTIES, |other| is treated as if
824   // it had exactly zero inobject properties.
825   // The "shared" flags of both this map and |other| are ignored.
826   bool EquivalentToForNormalization(const Map other, ElementsKind elements_kind,
827                                     PropertyNormalizationMode mode) const;
828   inline bool EquivalentToForNormalization(
829       const Map other, PropertyNormalizationMode mode) const;
830 
831   void PrintMapDetails(std::ostream& os);
832 
833   static inline Handle<Map> AddMissingTransitionsForTesting(
834       Isolate* isolate, Handle<Map> split_map,
835       Handle<DescriptorArray> descriptors);
836 
837   // Fires when the layout of an object with a leaf map changes.
838   // This includes adding transitions to the leaf map or changing
839   // the descriptor array.
840   inline void NotifyLeafMapLayoutChange(Isolate* isolate);
841 
842   V8_EXPORT_PRIVATE static VisitorId GetVisitorId(Map map);
843 
844   // Returns true if objects with given instance type are allowed to have
845   // fast transitionable elements kinds. This predicate is used to ensure
846   // that objects that can have transitionable fast elements kind will not
847   // get in-place generalizable fields because the elements kind transition
848   // performed by stubs or optimized code can't properly generalize such
849   // fields.
850   static inline bool CanHaveFastTransitionableElementsKind(
851       InstanceType instance_type);
852   inline bool CanHaveFastTransitionableElementsKind() const;
853 
854   // Maps for Wasm objects can use certain fields for other purposes.
855   inline uint8_t WasmByte1() const;
856   inline uint8_t WasmByte2() const;
857   inline void SetWasmByte1(uint8_t value);
858   inline void SetWasmByte2(uint8_t value);
859 
860  private:
861   // This byte encodes either the instance size without the in-object slack or
862   // the slack size in properties backing store.
863   // Let H be JSObject::kHeaderSize / kTaggedSize.
864   // If value >= H then:
865   //     - all field properties are stored in the object.
866   //     - there is no property array.
867   //     - value * kTaggedSize is the actual object size without the slack.
868   // Otherwise:
869   //     - there is no slack in the object.
870   //     - the property array has value slack slots.
871   // Note that this encoding requires that H = JSObject::kFieldsAdded.
872   DECL_INT_ACCESSORS(used_or_unused_instance_size_in_words)
873 
874   // Returns the map that this (root) map transitions to if its elements_kind
875   // is changed to |elements_kind|, or |nullptr| if no such map is cached yet.
876   Map LookupElementsTransitionMap(Isolate* isolate, ElementsKind elements_kind,
877                                   ConcurrencyMode cmode);
878 
879   // Tries to replay property transitions starting from this (root) map using
880   // the descriptor array of the |map|. The |root_map| is expected to have
881   // proper elements kind and therefore elements kinds transitions are not
882   // taken by this function. Returns |nullptr| if matching transition map is
883   // not found.
884   Map TryReplayPropertyTransitions(Isolate* isolate, Map map,
885                                    ConcurrencyMode cmode);
886 
887   static void ConnectTransition(Isolate* isolate, Handle<Map> parent,
888                                 Handle<Map> child, Handle<Name> name,
889                                 SimpleTransitionFlag flag);
890 
891   bool EquivalentToForTransition(const Map other, ConcurrencyMode cmode) const;
892   bool EquivalentToForElementsKindTransition(const Map other,
893                                              ConcurrencyMode cmode) const;
894   static Handle<Map> RawCopy(Isolate* isolate, Handle<Map> map,
895                              int instance_size, int inobject_properties);
896   static Handle<Map> ShareDescriptor(Isolate* isolate, Handle<Map> map,
897                                      Handle<DescriptorArray> descriptors,
898                                      Descriptor* descriptor);
899   V8_EXPORT_PRIVATE static Handle<Map> AddMissingTransitions(
900       Isolate* isolate, Handle<Map> map, Handle<DescriptorArray> descriptors);
901   static void InstallDescriptors(Isolate* isolate, Handle<Map> parent_map,
902                                  Handle<Map> child_map,
903                                  InternalIndex new_descriptor,
904                                  Handle<DescriptorArray> descriptors);
905   static Handle<Map> CopyAddDescriptor(Isolate* isolate, Handle<Map> map,
906                                        Descriptor* descriptor,
907                                        TransitionFlag flag);
908   static Handle<Map> CopyReplaceDescriptors(Isolate* isolate, Handle<Map> map,
909                                             Handle<DescriptorArray> descriptors,
910                                             TransitionFlag flag,
911                                             MaybeHandle<Name> maybe_name,
912                                             const char* reason,
913                                             SimpleTransitionFlag simple_flag);
914 
915   static Handle<Map> CopyReplaceDescriptor(Isolate* isolate, Handle<Map> map,
916                                            Handle<DescriptorArray> descriptors,
917                                            Descriptor* descriptor,
918                                            InternalIndex index,
919                                            TransitionFlag flag);
920   static Handle<Map> CopyNormalized(Isolate* isolate, Handle<Map> map,
921                                     PropertyNormalizationMode mode);
922 
923   void DeprecateTransitionTree(Isolate* isolate);
924 
925   void ReplaceDescriptors(Isolate* isolate, DescriptorArray new_descriptors);
926 
927   // This is the equivalent of IsMap() but avoids reading the instance type so
928   // it can be used concurrently without acquire load.
929   V8_INLINE bool ConcurrentIsMap(PtrComprCageBase cage_base,
930                                  const Object& object) const;
931 
932   // Use the high-level instance_descriptors/SetInstanceDescriptors instead.
933   DECL_RELEASE_SETTER(instance_descriptors, DescriptorArray)
934 
935   // Hide inherited accessors from the generated superclass.
936   DECL_ACCESSORS(constructor_or_back_pointer_or_native_context, Object)
937   DECL_ACCESSORS(transitions_or_prototype_info, Object)
938 
939   static const int kFastPropertiesSoftLimit = 12;
940   static const int kMaxFastProperties = 128;
941 
942   friend class MapUpdater;
943   template <typename ConcreteVisitor, typename MarkingState>
944   friend class MarkingVisitorBase;
945 
946   TQ_OBJECT_CONSTRUCTORS(Map)
947 };
948 
949 // The cache for maps used by normalized (dictionary mode) objects.
950 // Such maps do not have property descriptors, so a typical program
951 // needs very limited number of distinct normalized maps.
952 class NormalizedMapCache : public WeakFixedArray {
953  public:
954   NEVER_READ_ONLY_SPACE
955   static Handle<NormalizedMapCache> New(Isolate* isolate);
956 
957   V8_WARN_UNUSED_RESULT MaybeHandle<Map> Get(Handle<Map> fast_map,
958                                              ElementsKind elements_kind,
959                                              PropertyNormalizationMode mode);
960   void Set(Handle<Map> fast_map, Handle<Map> normalized_map);
961 
962   DECL_CAST(NormalizedMapCache)
963   DECL_VERIFIER(NormalizedMapCache)
964 
965  private:
966   friend bool HeapObject::IsNormalizedMapCache(
967       PtrComprCageBase cage_base) const;
968 
969   static const int kEntries = 64;
970 
971   static inline int GetIndex(Handle<Map> map);
972 
973   // The following declarations hide base class methods.
974   Object get(int index);
975   void set(int index, Object value);
976 
977   OBJECT_CONSTRUCTORS(NormalizedMapCache, WeakFixedArray);
978 };
979 
980 }  // namespace internal
981 }  // namespace v8
982 
983 #include "src/objects/object-macros-undef.h"
984 
985 #endif  // V8_OBJECTS_MAP_H_
986