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