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