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