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