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