• 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