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 is_frozen_or_sealed_elements() const; |
425 | |
426 | // Returns true if the current map doesn't have DICTIONARY_ELEMENTS but if a |
427 | // map with DICTIONARY_ELEMENTS was found in the prototype chain. |
428 | bool DictionaryElementsInPrototypeChainOnly(Isolate* isolate); |
429 | |
430 | inline Map ElementsTransitionMap(); |
431 | |
432 | inline FixedArrayBase GetInitialElements() const; |
433 | |
434 | // [raw_transitions]: Provides access to the transitions storage field. |
435 | // Don't call set_raw_transitions() directly to overwrite transitions, use |
436 | // the TransitionArray::ReplaceTransitions() wrapper instead! |
437 | DECL_ACCESSORS(raw_transitions, MaybeObject) |
438 | // [prototype_info]: Per-prototype metadata. Aliased with transitions |
439 | // (which prototype maps don't have). |
440 | DECL_ACCESSORS(prototype_info, Object) |
441 | // PrototypeInfo is created lazily using this helper (which installs it on |
442 | // the given prototype's map). |
443 | static Handle<PrototypeInfo> GetOrCreatePrototypeInfo( |
444 | Handle<JSObject> prototype, Isolate* isolate); |
445 | static Handle<PrototypeInfo> GetOrCreatePrototypeInfo( |
446 | Handle<Map> prototype_map, Isolate* isolate); |
447 | inline bool should_be_fast_prototype_map() const; |
448 | static void SetShouldBeFastPrototypeMap(Handle<Map> map, bool value, |
449 | Isolate* isolate); |
450 | |
451 | // [prototype chain validity cell]: Associated with a prototype object, |
452 | // stored in that object's map, indicates that prototype chains through this |
453 | // object are currently valid. The cell will be invalidated and replaced when |
454 | // the prototype chain changes. When there's nothing to guard (for example, |
455 | // when direct prototype is null or Proxy) this function returns Smi with |
456 | // |kPrototypeChainValid| sentinel value. |
457 | static Handle<Object> GetOrCreatePrototypeChainValidityCell(Handle<Map> map, |
458 | Isolate* isolate); |
459 | static const int kPrototypeChainValid = 0; |
460 | static const int kPrototypeChainInvalid = 1; |
461 | |
462 | static bool IsPrototypeChainInvalidated(Map map); |
463 | |
464 | // Return the map of the root of object's prototype chain. |
465 | Map GetPrototypeChainRootMap(Isolate* isolate) const; |
466 | |
467 | V8_EXPORT_PRIVATE Map FindRootMap(Isolate* isolate) const; |
468 | V8_EXPORT_PRIVATE Map FindFieldOwner(Isolate* isolate, int descriptor) const; |
469 | |
470 | inline int GetInObjectPropertyOffset(int index) const; |
471 | |
472 | class FieldCounts { |
473 | public: |
474 | FieldCounts(int mutable_count, int const_count) |
475 | : mutable_count_(mutable_count), const_count_(const_count) {} |
476 | |
477 | int GetTotal() const { return mutable_count() + const_count(); } |
478 | |
479 | int mutable_count() const { return mutable_count_; } |
480 | int const_count() const { return const_count_; } |
481 | |
482 | private: |
483 | int mutable_count_; |
484 | int const_count_; |
485 | }; |
486 | |
487 | FieldCounts GetFieldCounts() const; |
488 | int NumberOfFields() const; |
489 | |
490 | bool HasOutOfObjectProperties() const; |
491 | |
492 | // Returns true if transition to the given map requires special |
493 | // synchronization with the concurrent marker. |
494 | bool TransitionRequiresSynchronizationWithGC(Map target) const; |
495 | // Returns true if transition to the given map removes a tagged in-object |
496 | // field. |
497 | bool TransitionRemovesTaggedField(Map target) const; |
498 | // Returns true if transition to the given map replaces a tagged in-object |
499 | // field with an untagged in-object field. |
500 | bool TransitionChangesTaggedFieldToUntaggedField(Map target) const; |
501 | |
502 | // TODO(ishell): candidate with JSObject::MigrateToMap(). |
503 | bool InstancesNeedRewriting(Map target) const; |
504 | bool InstancesNeedRewriting(Map target, int target_number_of_fields, |
505 | int target_inobject, int target_unused, |
506 | int* old_number_of_fields) const; |
507 | V8_WARN_UNUSED_RESULT static Handle<FieldType> GeneralizeFieldType( |
508 | Representation rep1, Handle<FieldType> type1, Representation rep2, |
509 | Handle<FieldType> type2, Isolate* isolate); |
510 | static void GeneralizeField(Isolate* isolate, Handle<Map> map, |
511 | int modify_index, PropertyConstness new_constness, |
512 | Representation new_representation, |
513 | Handle<FieldType> new_field_type); |
514 | // Returns true if the |field_type| is the most general one for |
515 | // given |representation|. |
516 | static inline bool IsMostGeneralFieldType(Representation representation, |
517 | FieldType field_type); |
518 | |
519 | // Generalizes constness, representation and field_type if objects with given |
520 | // instance type can have fast elements that can be transitioned by stubs or |
521 | // optimized code to more general elements kind. |
522 | // This generalization is necessary in order to ensure that elements kind |
523 | // transitions performed by stubs / optimized code don't silently transition |
524 | // PropertyConstness::kMutable fields back to VariableMode::kConst state or |
525 | // fields with HeapObject representation and "Any" type back to "Class" type. |
526 | static inline void GeneralizeIfCanHaveTransitionableFastElementsKind( |
527 | Isolate* isolate, InstanceType instance_type, |
528 | PropertyConstness* constness, Representation* representation, |
529 | Handle<FieldType>* field_type); |
530 | |
531 | V8_EXPORT_PRIVATE static Handle<Map> ReconfigureProperty( |
532 | Isolate* isolate, Handle<Map> map, int modify_index, |
533 | PropertyKind new_kind, PropertyAttributes new_attributes, |
534 | Representation new_representation, Handle<FieldType> new_field_type); |
535 | |
536 | V8_EXPORT_PRIVATE static Handle<Map> ReconfigureElementsKind( |
537 | Isolate* isolate, Handle<Map> map, ElementsKind new_elements_kind); |
538 | |
539 | V8_EXPORT_PRIVATE static Handle<Map> PrepareForDataProperty( |
540 | Isolate* isolate, Handle<Map> old_map, int descriptor_number, |
541 | PropertyConstness constness, Handle<Object> value); |
542 | |
543 | V8_EXPORT_PRIVATE static Handle<Map> Normalize(Isolate* isolate, |
544 | Handle<Map> map, |
545 | PropertyNormalizationMode mode, |
546 | const char* reason); |
547 | |
548 | // Tells whether the map is used for JSObjects in dictionary mode (ie |
549 | // normalized objects, ie objects for which HasFastProperties returns false). |
550 | // A map can never be used for both dictionary mode and fast mode JSObjects. |
551 | // False by default and for HeapObjects that are not JSObjects. |
552 | DECL_BOOLEAN_ACCESSORS(is_dictionary_map) |
553 | |
554 | // Tells whether the instance needs security checks when accessing its |
555 | // properties. |
556 | DECL_BOOLEAN_ACCESSORS(is_access_check_needed) |
557 | |
558 | // [prototype]: implicit prototype object. |
559 | DECL_ACCESSORS(prototype, HeapObject) |
560 | // TODO(jkummerow): make set_prototype private. |
561 | V8_EXPORT_PRIVATE static void SetPrototype( |
562 | Isolate* isolate, Handle<Map> map, Handle<HeapObject> prototype, |
563 | bool enable_prototype_setup_mode = true); |
564 | |
565 | // [constructor]: points back to the function or FunctionTemplateInfo |
566 | // responsible for this map. |
567 | // The field overlaps with the back pointer. All maps in a transition tree |
568 | // have the same constructor, so maps with back pointers can walk the |
569 | // back pointer chain until they find the map holding their constructor. |
570 | // Returns null_value if there's neither a constructor function nor a |
571 | // FunctionTemplateInfo available. |
572 | DECL_ACCESSORS(constructor_or_backpointer, Object) |
573 | inline Object GetConstructor() const; |
574 | inline FunctionTemplateInfo GetFunctionTemplateInfo() const; |
575 | inline void SetConstructor(Object constructor, |
576 | WriteBarrierMode mode = UPDATE_WRITE_BARRIER); |
577 | // [back pointer]: points back to the parent map from which a transition |
578 | // leads to this map. The field overlaps with the constructor (see above). |
579 | inline HeapObject GetBackPointer() const; |
580 | inline void SetBackPointer(Object value, |
581 | WriteBarrierMode mode = UPDATE_WRITE_BARRIER); |
582 | |
583 | // [instance descriptors]: describes the object. |
584 | inline DescriptorArray instance_descriptors() const; |
585 | inline DescriptorArray synchronized_instance_descriptors() const; |
586 | V8_EXPORT_PRIVATE void SetInstanceDescriptors(Isolate* isolate, |
587 | DescriptorArray descriptors, |
588 | int number_of_own_descriptors); |
589 | |
590 | // [layout descriptor]: describes the object layout. |
591 | DECL_ACCESSORS(layout_descriptor, LayoutDescriptor) |
592 | // |layout descriptor| accessor which can be used from GC. |
593 | inline LayoutDescriptor layout_descriptor_gc_safe() const; |
594 | inline bool HasFastPointerLayout() const; |
595 | |
596 | // |layout descriptor| accessor that is safe to call even when |
597 | // FLAG_unbox_double_fields is disabled (in this case Map does not contain |
598 | // |layout_descriptor| field at all). |
599 | inline LayoutDescriptor GetLayoutDescriptor() const; |
600 | |
601 | inline void UpdateDescriptors(Isolate* isolate, DescriptorArray descriptors, |
602 | LayoutDescriptor layout_descriptor, |
603 | int number_of_own_descriptors); |
604 | inline void InitializeDescriptors(Isolate* isolate, |
605 | DescriptorArray descriptors, |
606 | LayoutDescriptor layout_descriptor); |
607 | |
608 | // [dependent code]: list of optimized codes that weakly embed this map. |
609 | DECL_ACCESSORS(dependent_code, DependentCode) |
610 | |
611 | // [prototype_validity_cell]: Cell containing the validity bit for prototype |
612 | // chains or Smi(0) if uninitialized. |
613 | // The meaning of this validity cell is different for prototype maps and |
614 | // non-prototype maps. |
615 | // For prototype maps the validity bit "guards" modifications of prototype |
616 | // chains going through this object. When a prototype object changes, both its |
617 | // own validity cell and those of all "downstream" prototypes are invalidated; |
618 | // handlers for a given receiver embed the currently valid cell for that |
619 | // receiver's prototype during their creation and check it on execution. |
620 | // For non-prototype maps which are used as transitioning store handlers this |
621 | // field contains the validity cell which guards modifications of this map's |
622 | // prototype. |
623 | DECL_ACCESSORS(prototype_validity_cell, Object) |
624 | |
625 | // Returns true if prototype validity cell value represents "valid" prototype |
626 | // chain state. |
627 | inline bool IsPrototypeValidityCellValid() const; |
628 | |
629 | inline PropertyDetails GetLastDescriptorDetails() const; |
630 | |
631 | inline int LastAdded() const; |
632 | |
633 | inline int NumberOfOwnDescriptors() const; |
634 | inline void SetNumberOfOwnDescriptors(int number); |
635 | |
636 | inline Cell RetrieveDescriptorsPointer(); |
637 | |
638 | // Checks whether all properties are stored either in the map or on the object |
639 | // (inobject, properties, or elements backing store), requiring no special |
640 | // checks. |
641 | bool OnlyHasSimpleProperties() const; |
642 | inline int EnumLength() const; |
643 | inline void SetEnumLength(int length); |
644 | |
645 | DECL_BOOLEAN_ACCESSORS(owns_descriptors) |
646 | |
647 | inline void mark_unstable(); |
648 | inline bool is_stable() const; |
649 | |
650 | DECL_BOOLEAN_ACCESSORS(is_migration_target) |
651 | |
652 | DECL_BOOLEAN_ACCESSORS(is_immutable_proto) |
653 | |
654 | // This counter is used for in-object slack tracking. |
655 | // The in-object slack tracking is considered enabled when the counter is |
656 | // non zero. The counter only has a valid count for initial maps. For |
657 | // transitioned maps only kNoSlackTracking has a meaning, namely that inobject |
658 | // slack tracking already finished for the transition tree. Any other value |
659 | // indicates that either inobject slack tracking is still in progress, or that |
660 | // the map isn't part of the transition tree anymore. |
661 | DECL_INT_ACCESSORS(construction_counter) |
662 | |
663 | DECL_BOOLEAN_ACCESSORS(is_deprecated) |
664 | inline bool CanBeDeprecated() const; |
665 | // Returns a non-deprecated version of the input. If the input was not |
666 | // deprecated, it is directly returned. Otherwise, the non-deprecated version |
667 | // is found by re-transitioning from the root of the transition tree using the |
668 | // descriptor array of the map. Returns MaybeHandle<Map>() if no updated map |
669 | // is found. |
670 | V8_EXPORT_PRIVATE static MaybeHandle<Map> TryUpdate( |
671 | Isolate* isolate, Handle<Map> map) V8_WARN_UNUSED_RESULT; |
672 | V8_EXPORT_PRIVATE static Map TryUpdateSlow(Isolate* isolate, |
673 | Map map) V8_WARN_UNUSED_RESULT; |
674 | |
675 | // Returns a non-deprecated version of the input. This method may deprecate |
676 | // existing maps along the way if encodings conflict. Not for use while |
677 | // gathering type feedback. Use TryUpdate in those cases instead. |
678 | V8_EXPORT_PRIVATE static Handle<Map> Update(Isolate* isolate, |
679 | Handle<Map> map); |
680 | |
681 | static inline Handle<Map> CopyInitialMap(Isolate* isolate, Handle<Map> map); |
682 | V8_EXPORT_PRIVATE static Handle<Map> CopyInitialMap( |
683 | Isolate* isolate, Handle<Map> map, int instance_size, |
684 | int in_object_properties, int unused_property_fields); |
685 | static Handle<Map> CopyInitialMapNormalized( |
686 | Isolate* isolate, Handle<Map> map, |
687 | PropertyNormalizationMode mode = CLEAR_INOBJECT_PROPERTIES); |
688 | static Handle<Map> CopyDropDescriptors(Isolate* isolate, Handle<Map> map); |
689 | V8_EXPORT_PRIVATE static Handle<Map> CopyInsertDescriptor( |
690 | Isolate* isolate, Handle<Map> map, Descriptor* descriptor, |
691 | TransitionFlag flag); |
692 | |
693 | static MaybeObjectHandle WrapFieldType(Isolate* isolate, |
694 | Handle<FieldType> type); |
695 | V8_EXPORT_PRIVATE static FieldType UnwrapFieldType(MaybeObject wrapped_type); |
696 | |
697 | V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT static MaybeHandle<Map> CopyWithField( |
698 | Isolate* isolate, Handle<Map> map, Handle<Name> name, |
699 | Handle<FieldType> type, PropertyAttributes attributes, |
700 | PropertyConstness constness, Representation representation, |
701 | TransitionFlag flag); |
702 | |
703 | V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT static MaybeHandle<Map> |
704 | CopyWithConstant(Isolate* isolate, Handle<Map> map, Handle<Name> name, |
705 | Handle<Object> constant, PropertyAttributes attributes, |
706 | TransitionFlag flag); |
707 | |
708 | // Returns a new map with all transitions dropped from the given map and |
709 | // the ElementsKind set. |
710 | static Handle<Map> TransitionElementsTo(Isolate* isolate, Handle<Map> map, |
711 | ElementsKind to_kind); |
712 | |
713 | V8_EXPORT_PRIVATE static Handle<Map> AsElementsKind(Isolate* isolate, |
714 | Handle<Map> map, |
715 | ElementsKind kind); |
716 | |
717 | static Handle<Map> CopyAsElementsKind(Isolate* isolate, Handle<Map> map, |
718 | ElementsKind kind, TransitionFlag flag); |
719 | |
720 | static Handle<Map> AsLanguageMode(Isolate* isolate, Handle<Map> initial_map, |
721 | Handle<SharedFunctionInfo> shared_info); |
722 | |
723 | V8_EXPORT_PRIVATE static Handle<Map> CopyForPreventExtensions( |
724 | Isolate* isolate, Handle<Map> map, PropertyAttributes attrs_to_add, |
725 | Handle<Symbol> transition_marker, const char* reason); |
726 | |
727 | static Handle<Map> FixProxy(Handle<Map> map, InstanceType type, int size); |
728 | |
729 | // Maximal number of fast properties. Used to restrict the number of map |
730 | // transitions to avoid an explosion in the number of maps for objects used as |
731 | // dictionaries. |
732 | inline bool TooManyFastProperties(StoreOrigin store_origin) const; |
733 | V8_EXPORT_PRIVATE static Handle<Map> TransitionToDataProperty( |
734 | Isolate* isolate, Handle<Map> map, Handle<Name> name, |
735 | Handle<Object> value, PropertyAttributes attributes, |
736 | PropertyConstness constness, StoreOrigin store_origin); |
737 | V8_EXPORT_PRIVATE static Handle<Map> TransitionToAccessorProperty( |
738 | Isolate* isolate, Handle<Map> map, Handle<Name> name, int descriptor, |
739 | Handle<Object> getter, Handle<Object> setter, |
740 | PropertyAttributes attributes); |
741 | V8_EXPORT_PRIVATE static Handle<Map> ReconfigureExistingProperty( |
742 | Isolate* isolate, Handle<Map> map, int descriptor, PropertyKind kind, |
743 | PropertyAttributes attributes); |
744 | |
745 | inline void AppendDescriptor(Isolate* isolate, Descriptor* desc); |
746 | |
747 | // Returns a copy of the map, prepared for inserting into the transition |
748 | // tree (if the |map| owns descriptors then the new one will share |
749 | // descriptors with |map|). |
750 | static Handle<Map> CopyForElementsTransition(Isolate* isolate, |
751 | Handle<Map> map); |
752 | |
753 | // Returns a copy of the map, with all transitions dropped from the |
754 | // instance descriptors. |
755 | static Handle<Map> Copy(Isolate* isolate, Handle<Map> map, |
756 | const char* reason); |
757 | V8_EXPORT_PRIVATE static Handle<Map> Create(Isolate* isolate, |
758 | int inobject_properties); |
759 | |
760 | // Returns the next free property index (only valid for FAST MODE). |
761 | int NextFreePropertyIndex() const; |
762 | |
763 | // Returns the number of enumerable properties. |
764 | int NumberOfEnumerableProperties() const; |
765 | |
766 | DECL_CAST(Map) |
767 | |
768 | static inline int SlackForArraySize(int old_size, int size_limit); |
769 | |
770 | V8_EXPORT_PRIVATE static void EnsureDescriptorSlack(Isolate* isolate, |
771 | Handle<Map> map, |
772 | int slack); |
773 | |
774 | // Returns the map to be used for instances when the given {prototype} is |
775 | // passed to an Object.create call. Might transition the given {prototype}. |
776 | static Handle<Map> GetObjectCreateMap(Isolate* isolate, |
777 | Handle<HeapObject> prototype); |
778 | |
779 | // Similar to {GetObjectCreateMap} but does not transition {prototype} and |
780 | // fails gracefully by returning an empty handle instead. |
781 | static MaybeHandle<Map> TryGetObjectCreateMap(Isolate* isolate, |
782 | Handle<HeapObject> prototype); |
783 | |
784 | // Computes a hash value for this map, to be used in HashTables and such. |
785 | int Hash(); |
786 | |
787 | // Returns the transitioned map for this map with the most generic |
788 | // elements_kind that's found in |candidates|, or |nullptr| if no match is |
789 | // found at all. |
790 | V8_EXPORT_PRIVATE Map FindElementsKindTransitionedMap( |
791 | Isolate* isolate, MapHandles const& candidates); |
792 | |
793 | inline bool CanTransition() const; |
794 | |
795 | #define DECL_TESTER(Type, ...) inline bool Is##Type##Map() const; |
796 | INSTANCE_TYPE_CHECKERS(DECL_TESTER) |
797 | #undef DECL_TESTER |
798 | inline bool IsBooleanMap() const; |
799 | inline bool IsNullOrUndefinedMap() const; |
800 | inline bool IsPrimitiveMap() const; |
801 | inline bool IsSpecialReceiverMap() const; |
802 | inline bool IsCustomElementsReceiverMap() const; |
803 | |
804 | bool IsMapInArrayPrototypeChain(Isolate* isolate) const; |
805 | |
806 | // Dispatched behavior. |
807 | void MapPrint(std::ostream& os); |
808 | DECL_VERIFIER(Map) |
809 | |
810 | #ifdef VERIFY_HEAP |
811 | void DictionaryMapVerify(Isolate* isolate); |
812 | #endif |
813 | |
814 | DECL_PRIMITIVE_ACCESSORS(visitor_id, VisitorId) |
815 | |
816 | static ObjectFields ObjectFieldsFrom(VisitorId visitor_id) { |
817 | return (visitor_id < kDataOnlyVisitorIdCount) |
818 | ? ObjectFields::kDataOnly |
819 | : ObjectFields::kMaybePointers; |
820 | } |
821 | |
822 | V8_EXPORT_PRIVATE static Handle<Map> TransitionToPrototype( |
823 | Isolate* isolate, Handle<Map> map, Handle<HeapObject> prototype); |
824 | |
825 | static Handle<Map> TransitionToImmutableProto(Isolate* isolate, |
826 | Handle<Map> map); |
827 | |
828 | static const int kMaxPreAllocatedPropertyFields = 255; |
829 | |
830 | // Layout description. |
831 | #define MAP_FIELDS(V) \ |
832 | /* Raw data fields. */ \ |
833 | V(kInstanceSizeInWordsOffset, kUInt8Size) \ |
834 | V(kInObjectPropertiesStartOrConstructorFunctionIndexOffset, kUInt8Size) \ |
835 | V(kUsedOrUnusedInstanceSizeInWordsOffset, kUInt8Size) \ |
836 | V(kVisitorIdOffset, kUInt8Size) \ |
837 | V(kInstanceTypeOffset, kUInt16Size) \ |
838 | V(kBitFieldOffset, kUInt8Size) \ |
839 | V(kBitField2Offset, kUInt8Size) \ |
840 | V(kBitField3Offset, kUInt32Size) \ |
841 | /* Adds padding to make tagged fields kTaggedSize-aligned. */ \ |
842 | V(kOptionalPaddingOffset, OBJECT_POINTER_PADDING(kOptionalPaddingOffset)) \ |
843 | /* Pointer fields. */ \ |
844 | V(kPointerFieldsBeginOffset, 0) \ |
845 | V(kPrototypeOffset, kTaggedSize) \ |
846 | V(kConstructorOrBackPointerOffset, kTaggedSize) \ |
847 | V(kTransitionsOrPrototypeInfoOffset, kTaggedSize) \ |
848 | V(kDescriptorsOffset, kTaggedSize) \ |
849 | V(kLayoutDescriptorOffset, FLAG_unbox_double_fields ? kTaggedSize : 0) \ |
850 | V(kDependentCodeOffset, kTaggedSize) \ |
851 | V(kPrototypeValidityCellOffset, kTaggedSize) \ |
852 | V(kPointerFieldsEndOffset, 0) \ |
853 | /* Total size. */ \ |
854 | V(kSize, 0) |
855 | |
856 | DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, MAP_FIELDS) |
857 | #undef MAP_FIELDS |
858 | |
859 | STATIC_ASSERT(kInstanceTypeOffset == Internals::kMapInstanceTypeOffset); |
860 | |
861 | class BodyDescriptor; |
862 | |
863 | // Compares this map to another to see if they describe equivalent objects. |
864 | // If |mode| is set to CLEAR_INOBJECT_PROPERTIES, |other| is treated as if |
865 | // it had exactly zero inobject properties. |
866 | // The "shared" flags of both this map and |other| are ignored. |
867 | bool EquivalentToForNormalization(const Map other, |
868 | PropertyNormalizationMode mode) const; |
869 | |
870 | // Returns true if given field is unboxed double. |
871 | inline bool IsUnboxedDoubleField(FieldIndex index) const; |
872 | |
873 | void PrintMapDetails(std::ostream& os); |
874 | |
875 | static inline Handle<Map> AddMissingTransitionsForTesting( |
876 | Isolate* isolate, Handle<Map> split_map, |
877 | Handle<DescriptorArray> descriptors, |
878 | Handle<LayoutDescriptor> full_layout_descriptor); |
879 | |
880 | // Fires when the layout of an object with a leaf map changes. |
881 | // This includes adding transitions to the leaf map or changing |
882 | // the descriptor array. |
883 | inline void NotifyLeafMapLayoutChange(Isolate* isolate); |
884 | |
885 | V8_EXPORT_PRIVATE static VisitorId GetVisitorId(Map map); |
886 | |
887 | // Returns true if objects with given instance type are allowed to have |
888 | // fast transitionable elements kinds. This predicate is used to ensure |
889 | // that objects that can have transitionable fast elements kind will not |
890 | // get in-place generalizable fields because the elements kind transition |
891 | // performed by stubs or optimized code can't properly generalize such |
892 | // fields. |
893 | static inline bool CanHaveFastTransitionableElementsKind( |
894 | InstanceType instance_type); |
895 | inline bool CanHaveFastTransitionableElementsKind() const; |
896 | |
897 | // Whether this is the map of the given native context's global proxy. |
898 | bool IsMapOfGlobalProxy(Handle<NativeContext> native_context) const; |
899 | |
900 | private: |
901 | // This byte encodes either the instance size without the in-object slack or |
902 | // the slack size in properties backing store. |
903 | // Let H be JSObject::kHeaderSize / kTaggedSize. |
904 | // If value >= H then: |
905 | // - all field properties are stored in the object. |
906 | // - there is no property array. |
907 | // - value * kTaggedSize is the actual object size without the slack. |
908 | // Otherwise: |
909 | // - there is no slack in the object. |
910 | // - the property array has value slack slots. |
911 | // Note that this encoding requires that H = JSObject::kFieldsAdded. |
912 | DECL_INT_ACCESSORS(used_or_unused_instance_size_in_words) |
913 | |
914 | // Returns the map that this (root) map transitions to if its elements_kind |
915 | // is changed to |elements_kind|, or |nullptr| if no such map is cached yet. |
916 | Map LookupElementsTransitionMap(Isolate* isolate, ElementsKind elements_kind); |
917 | |
918 | // Tries to replay property transitions starting from this (root) map using |
919 | // the descriptor array of the |map|. The |root_map| is expected to have |
920 | // proper elements kind and therefore elements kinds transitions are not |
921 | // taken by this function. Returns |nullptr| if matching transition map is |
922 | // not found. |
923 | Map TryReplayPropertyTransitions(Isolate* isolate, Map map); |
924 | |
925 | static void ConnectTransition(Isolate* isolate, Handle<Map> parent, |
926 | Handle<Map> child, Handle<Name> name, |
927 | SimpleTransitionFlag flag); |
928 | |
929 | bool EquivalentToForTransition(const Map other) const; |
930 | bool EquivalentToForElementsKindTransition(const Map other) const; |
931 | static Handle<Map> RawCopy(Isolate* isolate, Handle<Map> map, |
932 | int instance_size, int inobject_properties); |
933 | static Handle<Map> ShareDescriptor(Isolate* isolate, Handle<Map> map, |
934 | Handle<DescriptorArray> descriptors, |
935 | Descriptor* descriptor); |
936 | V8_EXPORT_PRIVATE static Handle<Map> AddMissingTransitions( |
937 | Isolate* isolate, Handle<Map> map, Handle<DescriptorArray> descriptors, |
938 | Handle<LayoutDescriptor> full_layout_descriptor); |
939 | static void InstallDescriptors( |
940 | Isolate* isolate, Handle<Map> parent_map, Handle<Map> child_map, |
941 | int new_descriptor, Handle<DescriptorArray> descriptors, |
942 | Handle<LayoutDescriptor> full_layout_descriptor); |
943 | static Handle<Map> CopyAddDescriptor(Isolate* isolate, Handle<Map> map, |
944 | Descriptor* descriptor, |
945 | TransitionFlag flag); |
946 | static Handle<Map> CopyReplaceDescriptors( |
947 | Isolate* isolate, Handle<Map> map, Handle<DescriptorArray> descriptors, |
948 | Handle<LayoutDescriptor> layout_descriptor, TransitionFlag flag, |
949 | MaybeHandle<Name> maybe_name, const char* reason, |
950 | SimpleTransitionFlag simple_flag); |
951 | |
952 | static Handle<Map> CopyReplaceDescriptor(Isolate* isolate, Handle<Map> map, |
953 | Handle<DescriptorArray> descriptors, |
954 | Descriptor* descriptor, int index, |
955 | TransitionFlag flag); |
956 | static Handle<Map> CopyNormalized(Isolate* isolate, Handle<Map> map, |
957 | PropertyNormalizationMode mode); |
958 | |
959 | // TODO(ishell): Move to MapUpdater. |
960 | static Handle<Map> CopyGeneralizeAllFields(Isolate* isolate, Handle<Map> map, |
961 | ElementsKind elements_kind, |
962 | int modify_index, |
963 | PropertyKind kind, |
964 | PropertyAttributes attributes, |
965 | const char* reason); |
966 | |
967 | void DeprecateTransitionTree(Isolate* isolate); |
968 | |
969 | void ReplaceDescriptors(Isolate* isolate, DescriptorArray new_descriptors, |
970 | LayoutDescriptor new_layout_descriptor); |
971 | |
972 | // Update field type of the given descriptor to new representation and new |
973 | // type. The type must be prepared for storing in descriptor array: |
974 | // it must be either a simple type or a map wrapped in a weak cell. |
975 | void UpdateFieldType(Isolate* isolate, int descriptor_number, |
976 | Handle<Name> name, PropertyConstness new_constness, |
977 | Representation new_representation, |
978 | const MaybeObjectHandle& new_wrapped_type); |
979 | |
980 | // TODO(ishell): Move to MapUpdater. |
981 | void PrintReconfiguration(Isolate* isolate, FILE* file, int modify_index, |
982 | PropertyKind kind, PropertyAttributes attributes); |
983 | // TODO(ishell): Move to MapUpdater. |
984 | void PrintGeneralization( |
985 | Isolate* isolate, FILE* file, const char* reason, int modify_index, |
986 | int split, int descriptors, bool constant_to_field, |
987 | Representation old_representation, Representation new_representation, |
988 | MaybeHandle<FieldType> old_field_type, MaybeHandle<Object> old_value, |
989 | MaybeHandle<FieldType> new_field_type, MaybeHandle<Object> new_value); |
990 | |
991 | // Use the high-level instance_descriptors/SetInstanceDescriptors instead. |
992 | inline void set_synchronized_instance_descriptors( |
993 | DescriptorArray array, WriteBarrierMode mode = UPDATE_WRITE_BARRIER); |
994 | |
995 | static const int kFastPropertiesSoftLimit = 12; |
996 | static const int kMaxFastProperties = 128; |
997 | |
998 | friend class MapUpdater; |
999 | |
1000 | OBJECT_CONSTRUCTORS(Map, HeapObject); |
1001 | }; |
1002 | |
1003 | // The cache for maps used by normalized (dictionary mode) objects. |
1004 | // Such maps do not have property descriptors, so a typical program |
1005 | // needs very limited number of distinct normalized maps. |
1006 | class NormalizedMapCache : public WeakFixedArray { |
1007 | public: |
1008 | NEVER_READ_ONLY_SPACE |
1009 | static Handle<NormalizedMapCache> New(Isolate* isolate); |
1010 | |
1011 | V8_WARN_UNUSED_RESULT MaybeHandle<Map> Get(Handle<Map> fast_map, |
1012 | PropertyNormalizationMode mode); |
1013 | void Set(Handle<Map> fast_map, Handle<Map> normalized_map); |
1014 | |
1015 | DECL_CAST(NormalizedMapCache) |
1016 | DECL_VERIFIER(NormalizedMapCache) |
1017 | |
1018 | private: |
1019 | friend bool HeapObject::IsNormalizedMapCache() const; |
1020 | |
1021 | static const int kEntries = 64; |
1022 | |
1023 | static inline int GetIndex(Handle<Map> map); |
1024 | |
1025 | // The following declarations hide base class methods. |
1026 | Object get(int index); |
1027 | void set(int index, Object value); |
1028 | |
1029 | OBJECT_CONSTRUCTORS(NormalizedMapCache, WeakFixedArray); |
1030 | }; |
1031 | |
1032 | } // namespace internal |
1033 | } // namespace v8 |
1034 | |
1035 | #include "src/objects/object-macros-undef.h" |
1036 | |
1037 | #endif // V8_OBJECTS_MAP_H_ |
1038 | |