v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
map.cc
Go to the documentation of this file.
1// Copyright 2019 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#include "src/objects/map.h"
6
7#include <optional>
8
10#include "src/common/globals.h"
18#include "src/logging/log.h"
28#include "src/objects/oddball.h"
31#include "src/roots/roots.h"
32#include "src/utils/ostreams.h"
34
35namespace v8::internal {
36
39 if (IsJSReceiverMap(*this)) {
40 return *this;
41 }
42 int constructor_function_index = GetConstructorFunctionIndex();
43 if (constructor_function_index != Map::kNoConstructorFunctionIndex) {
44 Tagged<Context> native_context = isolate->context()->native_context();
45 Tagged<JSFunction> constructor_function =
46 Cast<JSFunction>(native_context->get(constructor_function_index));
47 return constructor_function->initial_map();
48 }
49 return ReadOnlyRoots(isolate).null_value()->map();
50}
51
52// static
53std::optional<Tagged<JSFunction>> Map::GetConstructorFunction(
56 if (IsPrimitiveMap(map)) {
57 int const constructor_function_index = map->GetConstructorFunctionIndex();
58 if (constructor_function_index != kNoConstructorFunctionIndex) {
59 return Cast<JSFunction>(native_context->get(constructor_function_index));
60 }
61 }
62 return {};
63}
64
66 static_assert(kVisitorIdCount <= 256);
67
68 const int instance_type = map->instance_type();
69
70 if (instance_type < FIRST_NONSTRING_TYPE) {
71 switch (instance_type & kStringRepresentationMask) {
72 case kSeqStringTag:
73 if ((instance_type & kStringEncodingMask) == kOneByteStringTag) {
74 return kVisitSeqOneByteString;
75 } else {
76 return kVisitSeqTwoByteString;
77 }
78
79 case kConsStringTag:
80 if (IsShortcutCandidate(instance_type)) {
81 return kVisitShortcutCandidate;
82 } else {
83 return kVisitConsString;
84 }
85
87 return kVisitSlicedString;
88
90 return kVisitExternalString;
91
92 case kThinStringTag:
93 return kVisitThinString;
94 }
96 }
97
98 if (InstanceTypeChecker::IsJSApiObject(map->instance_type())) {
99 return kVisitJSApiObject;
100 }
101
102 switch (instance_type) {
103 case FILLER_TYPE:
104 return kVisitFiller;
105 case FREE_SPACE_TYPE:
106 return kVisitFreeSpace;
107
108 case EMBEDDER_DATA_ARRAY_TYPE:
109 return kVisitEmbedderDataArray;
110
111 case NAME_TO_INDEX_HASH_TABLE_TYPE:
112 case REGISTERED_SYMBOL_TABLE_TYPE:
113 case HASH_TABLE_TYPE:
114 case ORDERED_HASH_MAP_TYPE:
115 case ORDERED_HASH_SET_TYPE:
116 case ORDERED_NAME_DICTIONARY_TYPE:
117 case NAME_DICTIONARY_TYPE:
118 case GLOBAL_DICTIONARY_TYPE:
119 case NUMBER_DICTIONARY_TYPE:
120 case SIMPLE_NUMBER_DICTIONARY_TYPE:
121 return kVisitFixedArray;
122
123 case SLOPPY_ARGUMENTS_ELEMENTS_TYPE:
124 return kVisitSloppyArgumentsElements;
125
126 case AWAIT_CONTEXT_TYPE:
127 case BLOCK_CONTEXT_TYPE:
128 case CATCH_CONTEXT_TYPE:
129 case DEBUG_EVALUATE_CONTEXT_TYPE:
130 case EVAL_CONTEXT_TYPE:
131 case FUNCTION_CONTEXT_TYPE:
132 case MODULE_CONTEXT_TYPE:
133 case SCRIPT_CONTEXT_TYPE:
134 case WITH_CONTEXT_TYPE:
135 return kVisitContext;
136
137 case NATIVE_CONTEXT_TYPE:
138 return kVisitNativeContext;
139
140 case EPHEMERON_HASH_TABLE_TYPE:
141 return kVisitEphemeronHashTable;
142
143 case PROPERTY_ARRAY_TYPE:
144 return kVisitPropertyArray;
145
146 case FEEDBACK_CELL_TYPE:
147 return kVisitFeedbackCell;
148
149 case FEEDBACK_METADATA_TYPE:
150 return kVisitFeedbackMetadata;
151
152 case ODDBALL_TYPE:
153 return kVisitOddball;
154
155 case HOLE_TYPE:
156 return kVisitHole;
157
158 case MAP_TYPE:
159 return kVisitMap;
160
161 case CELL_TYPE:
162 return kVisitCell;
163
164 case PROPERTY_CELL_TYPE:
165 return kVisitPropertyCell;
166
167 case CONTEXT_SIDE_PROPERTY_CELL_TYPE:
168 return kVisitContextSidePropertyCell;
169
170 case TRANSITION_ARRAY_TYPE:
171 return kVisitTransitionArray;
172
173 case JS_WEAK_MAP_TYPE:
174 case JS_WEAK_SET_TYPE:
175 return kVisitJSWeakCollection;
176
177 case ACCESSOR_INFO_TYPE:
178 return kVisitAccessorInfo;
179
180 case INTERCEPTOR_INFO_TYPE:
181 return kVisitInterceptorInfo;
182
183 case FUNCTION_TEMPLATE_INFO_TYPE:
184 return kVisitFunctionTemplateInfo;
185
186 case OBJECT_TEMPLATE_INFO_TYPE:
187 return kVisitStruct;
188
189 case JS_PROXY_TYPE:
190 return kVisitStruct;
191
192 case SYMBOL_TYPE:
193 return kVisitSymbol;
194
195 case JS_ARRAY_BUFFER_TYPE:
196 return kVisitJSArrayBuffer;
197
198 case JS_DATA_VIEW_TYPE:
199 case JS_RAB_GSAB_DATA_VIEW_TYPE:
200 return kVisitJSDataViewOrRabGsabDataView;
201
202 case JS_EXTERNAL_OBJECT_TYPE:
203 return kVisitJSExternalObject;
204
205 case JS_FUNCTION_TYPE:
206 case JS_CLASS_CONSTRUCTOR_TYPE:
207 case JS_PROMISE_CONSTRUCTOR_TYPE:
208 case JS_REG_EXP_CONSTRUCTOR_TYPE:
209 case JS_ARRAY_CONSTRUCTOR_TYPE:
210#define TYPED_ARRAY_CONSTRUCTORS_SWITCH(Type, type, TYPE, Ctype) \
211 case TYPE##_TYPED_ARRAY_CONSTRUCTOR_TYPE:
213#undef TYPED_ARRAY_CONSTRUCTORS_SWITCH
214 return kVisitJSFunction;
215
216 case JS_TYPED_ARRAY_TYPE:
217 return kVisitJSTypedArray;
218
219 case SMALL_ORDERED_HASH_MAP_TYPE:
220 return kVisitSmallOrderedHashMap;
221
222 case SMALL_ORDERED_HASH_SET_TYPE:
223 return kVisitSmallOrderedHashSet;
224
225 case SMALL_ORDERED_NAME_DICTIONARY_TYPE:
226 return kVisitSmallOrderedNameDictionary;
227
228 case SWISS_NAME_DICTIONARY_TYPE:
229 return kVisitSwissNameDictionary;
230
231 case SHARED_FUNCTION_INFO_TYPE:
232 return kVisitSharedFunctionInfo;
233
234 case PREPARSE_DATA_TYPE:
235 return kVisitPreparseData;
236
237 case COVERAGE_INFO_TYPE:
238 return kVisitCoverageInfo;
239
240 // Objects that may have embedder fields but otherwise are just a regular
241 // JSObject.
242 case JS_PROMISE_TYPE: {
243 const bool has_raw_data_fields =
245 return has_raw_data_fields ? kVisitJSObject : kVisitJSObjectFast;
246 }
247
248 // Objects that are guaranteed to not have any embedder fields and just
249 // behave like regular JSObject.
250 case JS_ARGUMENTS_OBJECT_TYPE:
251 case JS_ARRAY_ITERATOR_PROTOTYPE_TYPE:
252 case JS_ARRAY_ITERATOR_TYPE:
253 case JS_ARRAY_TYPE:
254 case JS_ASYNC_DISPOSABLE_STACK_TYPE:
255 case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE:
256 case JS_ASYNC_FUNCTION_OBJECT_TYPE:
257 case JS_ASYNC_GENERATOR_OBJECT_TYPE:
258 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
259 case JS_DISPOSABLE_STACK_BASE_TYPE:
260 case JS_ERROR_TYPE:
261 case JS_GENERATOR_OBJECT_TYPE:
262 case JS_ITERATOR_FILTER_HELPER_TYPE:
263 case JS_ITERATOR_MAP_HELPER_TYPE:
264 case JS_ITERATOR_TAKE_HELPER_TYPE:
265 case JS_ITERATOR_DROP_HELPER_TYPE:
266 case JS_ITERATOR_FLAT_MAP_HELPER_TYPE:
267 case JS_ITERATOR_PROTOTYPE_TYPE:
268 case JS_MAP_ITERATOR_PROTOTYPE_TYPE:
269 case JS_MAP_KEY_ITERATOR_TYPE:
270 case JS_MAP_KEY_VALUE_ITERATOR_TYPE:
271 case JS_MAP_TYPE:
272 case JS_MAP_VALUE_ITERATOR_TYPE:
273 case JS_MESSAGE_OBJECT_TYPE:
274 case JS_MODULE_NAMESPACE_TYPE:
275 case JS_OBJECT_PROTOTYPE_TYPE:
276 case JS_OBJECT_TYPE:
277 case JS_PRIMITIVE_WRAPPER_TYPE:
278 case JS_PROMISE_PROTOTYPE_TYPE:
279 case JS_REG_EXP_PROTOTYPE_TYPE:
280 case JS_REG_EXP_STRING_ITERATOR_TYPE:
281 case JS_SET_ITERATOR_PROTOTYPE_TYPE:
282 case JS_SET_KEY_VALUE_ITERATOR_TYPE:
283 case JS_SET_PROTOTYPE_TYPE:
284 case JS_SET_TYPE:
285 case JS_SET_VALUE_ITERATOR_TYPE:
286 case JS_SYNC_DISPOSABLE_STACK_TYPE:
287 case JS_SHADOW_REALM_TYPE:
288 case JS_SHARED_ARRAY_TYPE:
289 case JS_SHARED_STRUCT_TYPE:
290 case JS_STRING_ITERATOR_PROTOTYPE_TYPE:
291 case JS_STRING_ITERATOR_TYPE:
292 case JS_TEMPORAL_CALENDAR_TYPE:
293 case JS_TEMPORAL_DURATION_TYPE:
294 case JS_TEMPORAL_INSTANT_TYPE:
295 case JS_TEMPORAL_PLAIN_DATE_TYPE:
296 case JS_TEMPORAL_PLAIN_DATE_TIME_TYPE:
297 case JS_TEMPORAL_PLAIN_MONTH_DAY_TYPE:
298 case JS_TEMPORAL_PLAIN_TIME_TYPE:
299 case JS_TEMPORAL_PLAIN_YEAR_MONTH_TYPE:
300 case JS_TEMPORAL_TIME_ZONE_TYPE:
301 case JS_TEMPORAL_ZONED_DATE_TIME_TYPE:
302 case JS_TYPED_ARRAY_PROTOTYPE_TYPE:
303 case JS_VALID_ITERATOR_WRAPPER_TYPE:
304 case JS_RAW_JSON_TYPE:
305#ifdef V8_INTL_SUPPORT
306 case JS_V8_BREAK_ITERATOR_TYPE:
307 case JS_COLLATOR_TYPE:
308 case JS_DATE_TIME_FORMAT_TYPE:
309 case JS_DISPLAY_NAMES_TYPE:
310 case JS_DURATION_FORMAT_TYPE:
311 case JS_LIST_FORMAT_TYPE:
312 case JS_LOCALE_TYPE:
313 case JS_NUMBER_FORMAT_TYPE:
314 case JS_PLURAL_RULES_TYPE:
315 case JS_RELATIVE_TIME_FORMAT_TYPE:
316 case JS_SEGMENT_ITERATOR_TYPE:
317 case JS_SEGMENTER_TYPE:
318 case JS_SEGMENTS_TYPE:
319#endif // V8_INTL_SUPPORT
320#if V8_ENABLE_WEBASSEMBLY
321 case WASM_EXCEPTION_PACKAGE_TYPE:
322 case WASM_MODULE_OBJECT_TYPE:
323 case WASM_VALUE_OBJECT_TYPE:
324#endif // V8_ENABLE_WEBASSEMBLY
325 case JS_BOUND_FUNCTION_TYPE:
326 case JS_WRAPPED_FUNCTION_TYPE: {
328 return kVisitJSObjectFast;
329 }
330 case JS_REG_EXP_TYPE:
331 return kVisitJSRegExp;
332
333 // Objects that are used as API wrapper objects and can have embedder
334 // fields. Note that there's more of these kinds (e.g. JS_ARRAY_BUFFER_TYPE)
335 // but they have their own visitor id for other reasons
336 case JS_API_OBJECT_TYPE:
337 case JS_GLOBAL_PROXY_TYPE:
338 case JS_GLOBAL_OBJECT_TYPE:
339 case JS_SPECIAL_API_OBJECT_TYPE:
340 return kVisitJSApiObject;
341
342 case JS_DATE_TYPE:
343 return kVisitJSDate;
344
345 case JS_WEAK_REF_TYPE:
346 return kVisitJSWeakRef;
347
348 case WEAK_CELL_TYPE:
349 return kVisitWeakCell;
350
351 case JS_FINALIZATION_REGISTRY_TYPE:
352 return kVisitJSFinalizationRegistry;
353
354 case JS_ATOMICS_MUTEX_TYPE:
355 case JS_ATOMICS_CONDITION_TYPE:
356 return kVisitJSSynchronizationPrimitive;
357
358 case HEAP_NUMBER_TYPE:
359 return kVisitHeapNumber;
360
361 case FOREIGN_TYPE:
362 return kVisitForeign;
363
364 case BIGINT_TYPE:
365 return kVisitBigInt;
366
367 case ALLOCATION_SITE_TYPE:
368 return kVisitAllocationSite;
369
370 // Here we list all structs explicitly on purpose. This forces new structs
371 // to choose a VisitorId explicitly.
372 case PROMISE_FULFILL_REACTION_JOB_TASK_TYPE:
373 case PROMISE_REJECT_REACTION_JOB_TASK_TYPE:
374 case CALLABLE_TASK_TYPE:
375 case CALLBACK_TASK_TYPE:
376 case PROMISE_RESOLVE_THENABLE_JOB_TASK_TYPE:
377 case ACCESS_CHECK_INFO_TYPE:
378 case ACCESSOR_PAIR_TYPE:
379 case ALIASED_ARGUMENTS_ENTRY_TYPE:
380 case ALLOCATION_MEMENTO_TYPE:
381 case ARRAY_BOILERPLATE_DESCRIPTION_TYPE:
382 case ASYNC_GENERATOR_REQUEST_TYPE:
383 case BREAK_POINT_TYPE:
384 case BREAK_POINT_INFO_TYPE:
385 case CLASS_BOILERPLATE_TYPE:
386 case CLASS_POSITIONS_TYPE:
387 case ENUM_CACHE_TYPE:
388 case ERROR_STACK_DATA_TYPE:
389 case FUNCTION_TEMPLATE_RARE_DATA_TYPE:
390 case MODULE_REQUEST_TYPE:
391 case PROMISE_CAPABILITY_TYPE:
392 case PROMISE_REACTION_TYPE:
393 case PROPERTY_DESCRIPTOR_OBJECT_TYPE:
394 case SCRIPT_TYPE:
395 case SCRIPT_OR_MODULE_TYPE:
396 case SOURCE_TEXT_MODULE_INFO_ENTRY_TYPE:
397 case STACK_FRAME_INFO_TYPE:
398 case STACK_TRACE_INFO_TYPE:
399 case TEMPLATE_OBJECT_DESCRIPTION_TYPE:
400 case TUPLE2_TYPE:
401#if V8_ENABLE_WEBASSEMBLY
402 case ASM_WASM_DATA_TYPE:
403 case WASM_EXCEPTION_TAG_TYPE:
404#endif
405 return kVisitStruct;
406
407 case PROTOTYPE_INFO_TYPE:
408 return kVisitPrototypeInfo;
409
410 case DEBUG_INFO_TYPE:
411 return kVisitDebugInfo;
412
413 case CALL_SITE_INFO_TYPE:
414 return kVisitCallSiteInfo;
415
416 case BYTECODE_WRAPPER_TYPE:
417 return kVisitBytecodeWrapper;
418
419 case CODE_WRAPPER_TYPE:
420 return kVisitCodeWrapper;
421
422 case REG_EXP_BOILERPLATE_DESCRIPTION_TYPE:
423 return kVisitRegExpBoilerplateDescription;
424
425 case REG_EXP_DATA_WRAPPER_TYPE:
426 return kVisitRegExpDataWrapper;
427
428 case LOAD_HANDLER_TYPE:
429 case STORE_HANDLER_TYPE:
430 return kVisitDataHandler;
431
432 case SOURCE_TEXT_MODULE_TYPE:
433 return kVisitSourceTextModule;
434 case SYNTHETIC_MODULE_TYPE:
435 return kVisitSyntheticModule;
436
437#if V8_ENABLE_WEBASSEMBLY
438 case WASM_ARRAY_TYPE:
439 return kVisitWasmArray;
440 case WASM_MEMORY_MAP_DESCRIPTOR_TYPE:
441 return kVisitWasmMemoryMapDescriptor;
442 case WASM_FUNC_REF_TYPE:
443 return kVisitWasmFuncRef;
444 case WASM_GLOBAL_OBJECT_TYPE:
445 return kVisitWasmGlobalObject;
446 case WASM_INSTANCE_OBJECT_TYPE:
447 return kVisitWasmInstanceObject;
448 case WASM_MEMORY_OBJECT_TYPE:
449 return kVisitWasmMemoryObject;
450 case WASM_NULL_TYPE:
451 return kVisitWasmNull;
452 case WASM_RESUME_DATA_TYPE:
453 return kVisitWasmResumeData;
454 case WASM_STRUCT_TYPE:
455 return kVisitWasmStruct;
456 case WASM_SUSPENDER_OBJECT_TYPE:
457 return kVisitWasmSuspenderObject;
458 case WASM_SUSPENDING_OBJECT_TYPE:
459 return kVisitWasmSuspendingObject;
460 case WASM_TABLE_OBJECT_TYPE:
461 return kVisitWasmTableObject;
462 case WASM_TAG_OBJECT_TYPE:
463 return kVisitWasmTagObject;
464 case WASM_TYPE_INFO_TYPE:
465 return kVisitWasmTypeInfo;
466#endif // V8_ENABLE_WEBASSEMBLY
467
468#define MAKE_TQ_CASE(TYPE, Name) \
469 case TYPE: \
470 return kVisit##Name;
471 TORQUE_INSTANCE_TYPE_TO_BODY_DESCRIPTOR_LIST(MAKE_TQ_CASE)
472#undef MAKE_TQ_CASE
473
474#define CASE(TypeCamelCase, TYPE_UPPER_CASE) \
475 case TYPE_UPPER_CASE##_TYPE: \
476 return kVisit##TypeCamelCase;
479#undef CASE
480 }
481 std::string name = ToString(map->instance_type());
482 FATAL("Instance type %s (code %d) not mapped to VisitorId.", name.c_str(),
483 instance_type);
484}
485
486// static
493
494// static
496 DCHECK(!wrapped_type.IsCleared());
497 Tagged<HeapObject> heap_object;
498 if (wrapped_type.GetHeapObjectIfWeak(&heap_object)) {
499 return Cast<FieldType>(heap_object);
500 }
501 return Cast<FieldType>(wrapped_type);
502}
503
507 PropertyAttributes attributes,
508 PropertyConstness constness,
509 Representation representation,
510 TransitionFlag flag) {
511 DCHECK(map->instance_descriptors(isolate)
512 ->Search(*name, map->NumberOfOwnDescriptors())
513 .is_not_found());
514
515 // Ensure the descriptor array does not get too big.
516 if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) {
517 return MaybeHandle<Map>();
518 }
519
520 // Compute the new index for new field.
521 int index = map->NextFreePropertyIndex();
522
523 if (map->instance_type() == JS_CONTEXT_EXTENSION_OBJECT_TYPE) {
524 constness = PropertyConstness::kMutable;
525 representation = Representation::Tagged();
526 type = FieldType::Any(isolate);
527 } else {
529 isolate, map->instance_type(), &representation, &type);
530 }
531
532 MaybeObjectDirectHandle wrapped_type = WrapFieldType(type);
533
534 Descriptor d = Descriptor::DataField(name, index, attributes, constness,
535 representation, wrapped_type);
536 Handle<Map> new_map = Map::CopyAddDescriptor(isolate, map, &d, flag);
537 new_map->AccountAddedPropertyField();
538 return new_map;
539}
540
543 DirectHandle<Object> constant,
544 PropertyAttributes attributes,
545 TransitionFlag flag) {
546 // Ensure the descriptor array does not get too big.
547 if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) {
548 return MaybeHandle<Map>();
549 }
550
551 Representation representation =
552 Object::OptimalRepresentation(*constant, isolate);
554 Object::OptimalType(*constant, isolate, representation);
555 return CopyWithField(isolate, map, name, type, attributes,
556 PropertyConstness::kConst, representation, flag);
557}
558
560 ConcurrencyMode cmode) const {
561 int target_number_of_fields = target->NumberOfFields(cmode);
562 int target_inobject = target->GetInObjectProperties();
563 int target_unused = target->UnusedPropertyFields();
564 int old_number_of_fields;
565
566 return InstancesNeedRewriting(target, target_number_of_fields,
567 target_inobject, target_unused,
568 &old_number_of_fields, cmode);
569}
570
572 int target_number_of_fields,
573 int target_inobject, int target_unused,
574 int* old_number_of_fields,
575 ConcurrencyMode cmode) const {
576 // If fields were added (or removed), rewrite the instance.
577 *old_number_of_fields = NumberOfFields(cmode);
578 DCHECK(target_number_of_fields >= *old_number_of_fields);
579 if (target_number_of_fields != *old_number_of_fields) return true;
580
581 // If smi descriptors were replaced by double descriptors, rewrite.
582 Tagged<DescriptorArray> old_desc = IsConcurrent(cmode)
585 Tagged<DescriptorArray> new_desc =
586 IsConcurrent(cmode) ? target->instance_descriptors(kAcquireLoad)
587 : target->instance_descriptors();
589 if (new_desc->GetDetails(i).representation().IsDouble() !=
590 old_desc->GetDetails(i).representation().IsDouble()) {
591 return true;
592 }
593 }
594
595 // If no fields were added, and no inobject properties were removed, setting
596 // the map is sufficient.
597 if (target_inobject == GetInObjectProperties()) return false;
598 // In-object slack tracking may have reduced the object size of the new map.
599 // In that case, succeed if all existing fields were inobject, and they still
600 // fit within the new inobject size.
601 DCHECK(target_inobject < GetInObjectProperties());
602 if (target_number_of_fields <= target_inobject) {
603 DCHECK(target_number_of_fields + target_unused == target_inobject);
604 return false;
605 }
606 // Otherwise, properties will need to be moved to the backing store.
607 return true;
608}
609
611 Tagged<DescriptorArray> descriptors = IsConcurrent(cmode)
614 int result = 0;
616 if (descriptors->GetDetails(i).location() == PropertyLocation::kField)
617 result++;
618 }
619 return result;
620}
621
624 int mutable_count = 0;
625 int const_count = 0;
627 PropertyDetails details = descriptors->GetDetails(i);
628 if (details.location() == PropertyLocation::kField) {
629 switch (details.constness()) {
631 mutable_count++;
632 break;
634 const_count++;
635 break;
636 }
637 }
638 }
639 return FieldCounts(mutable_count, const_count);
640}
641
643 if (is_deprecated()) return;
645 ReadOnlyRoots roots(isolate);
646 TransitionsAccessor transitions(isolate, *this);
647 transitions.ForEachTransition(
648 &no_gc, [&](Tagged<Map> map) { map->DeprecateTransitionTree(isolate); },
649 [&](Tagged<Map> map) {
650 if (v8_flags.move_prototype_transitions_first) {
651 map->DeprecateTransitionTree(isolate);
652 }
653 },
654 nullptr);
655 DCHECK(!IsFunctionTemplateInfo(constructor_or_back_pointer()));
657 set_is_deprecated(true);
658 if (v8_flags.log_maps) {
659 LOG(isolate, MapEvent("Deprecate", direct_handle(*this, isolate), {}));
660 }
664}
665
666// Installs |new_descriptors| over the current instance_descriptors to ensure
667// proper sharing of descriptor arrays.
669 Tagged<DescriptorArray> new_descriptors) {
670 PtrComprCageBase cage_base(isolate);
671 // Don't overwrite the empty descriptor array or initial map's descriptors.
672 if (NumberOfOwnDescriptors() == 0 ||
673 IsUndefined(GetBackPointer(cage_base), isolate)) {
674 return;
675 }
676
677 Tagged<DescriptorArray> to_replace = instance_descriptors(cage_base);
678 // Replace descriptors by new_descriptors in all maps that share it. The old
679 // descriptors will not be trimmed in the mark-compactor, we need to mark
680 // all its elements.
681 Tagged<Map> current = *this;
682#ifndef V8_DISABLE_WRITE_BARRIERS
684 to_replace->number_of_descriptors());
685#endif
686 while (current->instance_descriptors(cage_base) == to_replace) {
687 Tagged<Map> next;
688 if (!current->TryGetBackPointer(cage_base, &next)) {
689 break; // Stop overwriting at initial map.
690 }
691 current->SetEnumLength(kInvalidEnumCacheSentinel);
692 current->UpdateDescriptors(isolate, new_descriptors,
693 current->NumberOfOwnDescriptors());
694 current = next;
695 }
696 set_owns_descriptors(false);
697}
698
701 Tagged<Map> result = *this;
702 while (true) {
703 Tagged<Map> parent;
704 if (!result->TryGetBackPointer(cage_base, &parent)) {
705 // Initial map must not contain descriptors in the descriptors array
706 // that do not belong to the map.
707 DCHECK_LE(result->NumberOfOwnDescriptors(),
708 result->instance_descriptors(cage_base, kRelaxedLoad)
709 ->number_of_descriptors());
710 return result;
711 }
712 result = parent;
713 }
714}
715
717 InternalIndex descriptor) const {
721 ->GetDetails(descriptor)
722 .location());
723 Tagged<Map> result = *this;
724 while (true) {
725 Tagged<Map> parent;
726 if (!result->TryGetBackPointer(cage_base, &parent)) break;
727 if (parent->NumberOfOwnDescriptors() <= descriptor.as_int()) break;
728 result = parent;
729 }
730 return result;
731}
732
733namespace {
734
735Tagged<Map> SearchMigrationTarget(Isolate* isolate, Tagged<Map> old_map) {
737
738 Tagged<Map> target = old_map;
739 do {
740 target = TransitionsAccessor(isolate, target).GetMigrationTarget();
741 } while (!target.is_null() && target->is_deprecated());
742 if (target.is_null()) return Map();
743
745 isolate, old_map, ConcurrencyMode::kSynchronous) == target);
746 return target;
747}
748} // namespace
749
750// static
753 DisallowDeoptimization no_deoptimization(isolate);
754
755 if (!old_map->is_deprecated()) return old_map;
756
757 if (v8_flags.fast_map_update) {
758 Tagged<Map> target_map = SearchMigrationTarget(isolate, *old_map);
759 if (!target_map.is_null()) {
760 return handle(target_map, isolate);
761 }
762 }
763
764 std::optional<Tagged<Map>> new_map = MapUpdater::TryUpdateNoLock(
765 isolate, *old_map, ConcurrencyMode::kSynchronous);
766 if (!new_map.has_value()) return MaybeHandle<Map>();
767 if (v8_flags.fast_map_update) {
768 TransitionsAccessor::SetMigrationTarget(isolate, old_map, new_map.value());
769 }
770 return handle(new_map.value(), isolate);
771}
772
774 Tagged<Map> old_map,
775 ConcurrencyMode cmode) {
777
778 const int root_nof = NumberOfOwnDescriptors();
779 const int old_nof = old_map->NumberOfOwnDescriptors();
780 // TODO(jgruber,chromium:1239009): The main thread should use non-atomic
781 // reads, but this currently leads to odd behavior (see the linked bug).
782 // Investigate and fix this properly. Also below and in called functions.
783 Tagged<DescriptorArray> old_descriptors =
784 old_map->instance_descriptors(isolate, kAcquireLoad);
785
786 Tagged<Map> new_map = *this;
787 for (InternalIndex i : InternalIndex::Range(root_nof, old_nof)) {
788 PropertyDetails old_details = old_descriptors->GetDetails(i);
789 Tagged<Map> transition =
790 TransitionsAccessor(isolate, new_map, IsConcurrent(cmode))
791 .SearchTransition(old_descriptors->GetKey(i), old_details.kind(),
792 old_details.attributes());
793 if (transition.is_null()) return Map();
794 new_map = transition;
795 Tagged<DescriptorArray> new_descriptors =
796 new_map->instance_descriptors(isolate, kAcquireLoad);
797
798 PropertyDetails new_details = new_descriptors->GetDetails(i);
799 DCHECK_EQ(old_details.kind(), new_details.kind());
800 DCHECK_EQ(old_details.attributes(), new_details.attributes());
801 if (!IsGeneralizableTo(old_details.constness(), new_details.constness())) {
802 return Map();
803 }
804 DCHECK(IsGeneralizableTo(old_details.location(), new_details.location()));
805 if (!old_details.representation().fits_into(new_details.representation())) {
806 return Map();
807 }
808 if (new_details.location() == PropertyLocation::kField) {
809 if (new_details.kind() == PropertyKind::kData) {
810 Tagged<FieldType> new_type = new_descriptors->GetFieldType(i);
811 DCHECK_EQ(PropertyKind::kData, old_details.kind());
813 Tagged<FieldType> old_type = old_descriptors->GetFieldType(i);
814 if (!FieldType::NowIs(old_type, new_type)) {
815 return Map();
816 }
817 } else {
818 DCHECK_EQ(PropertyKind::kAccessor, new_details.kind());
819#ifdef DEBUG
820 Tagged<FieldType> new_type = new_descriptors->GetFieldType(i);
821 DCHECK(IsAny(new_type));
822#endif
823 UNREACHABLE();
824 }
825 } else {
827 if (old_details.location() == PropertyLocation::kField ||
828 old_descriptors->GetStrongValue(i) !=
829 new_descriptors->GetStrongValue(i)) {
830 return Map();
831 }
832 }
833 }
834 if (new_map->NumberOfOwnDescriptors() != old_nof) return Map();
835 return new_map;
836}
837
838// static
840 if (!map->is_deprecated()) return map;
841 if (v8_flags.fast_map_update) {
842 Tagged<Map> target_map = SearchMigrationTarget(isolate, *map);
843 if (!target_map.is_null()) {
844 return DirectHandle<Map>(target_map, isolate);
845 }
846 }
847 return MapUpdater{isolate, map}.Update();
848}
849
851 int slack) {
852 // Only supports adding slack to owned descriptors.
853 CHECK(map->owns_descriptors());
854
855 DirectHandle<DescriptorArray> descriptors(map->instance_descriptors(isolate),
856 isolate);
857 int old_size = map->NumberOfOwnDescriptors();
858 if (slack <= descriptors->number_of_slack_descriptors()) return;
859
860 DirectHandle<DescriptorArray> new_descriptors =
861 DescriptorArray::CopyUpTo(isolate, descriptors, old_size, slack);
862
864 if (old_size == 0) {
865 map->UpdateDescriptors(isolate, *new_descriptors,
866 map->NumberOfOwnDescriptors());
867 return;
868 }
869
870 // If the source descriptors had an enum cache we copy it. This ensures
871 // that the maps to which we push the new descriptor array back can rely
872 // on a cache always being available once it is set. If the map has more
873 // enumerated descriptors than available in the original cache, the cache
874 // will be lazily replaced by the extended cache when needed.
875 new_descriptors->CopyEnumCacheFrom(*descriptors);
876
877 // Replace descriptors by new_descriptors in all maps that share it. The old
878 // descriptors will not be trimmed in the mark-compactor, we need to mark
879 // all its elements.
880#ifndef V8_DISABLE_WRITE_BARRIERS
882 descriptors->number_of_descriptors());
883#endif
884
885 // Update the descriptors from {map} (inclusive) until the initial map
886 // (exclusive). In the case that {map} is the initial map, update it.
887 map->UpdateDescriptors(isolate, *new_descriptors,
888 map->NumberOfOwnDescriptors());
889 Tagged<Object> next = map->GetBackPointer();
890 if (IsUndefined(next, isolate)) return;
891
892 Tagged<Map> current = Cast<Map>(next);
893 while (current->instance_descriptors(isolate) == *descriptors) {
894 next = current->GetBackPointer();
895 if (IsUndefined(next, isolate)) break;
896 current->UpdateDescriptors(isolate, *new_descriptors,
897 current->NumberOfOwnDescriptors());
898 current = Cast<Map>(next);
899 }
900}
901
902// static
904 DirectHandle<JSPrototype> prototype) {
906 isolate->native_context()->object_function()->initial_map(), isolate);
907 if (map->prototype() == *prototype) return map;
908 if (IsNull(*prototype, isolate)) {
909 return isolate->slow_object_with_null_prototype_map();
910 }
912 DirectHandle<JSObject> js_prototype = Cast<JSObject>(prototype);
913 if (!js_prototype->map()->is_prototype_map()) {
914 JSObject::OptimizeAsPrototype(js_prototype);
915 }
917 Map::GetOrCreatePrototypeInfo(js_prototype, isolate);
918 // TODO(verwaest): Use inobject slack tracking for this map.
919 Tagged<HeapObject> map_obj;
920 if (info->ObjectCreateMap().GetHeapObjectIfWeak(&map_obj)) {
921 map = direct_handle(Cast<Map>(map_obj), isolate);
922 } else {
923 map = Map::CopyInitialMap(isolate, map);
924 Map::SetPrototype(isolate, map, prototype);
925 PrototypeInfo::SetObjectCreateMap(info, map, isolate);
926 }
927 return map;
928 }
929
930 return Map::TransitionRootMapToPrototypeForNewObject(isolate, map, prototype);
931}
932
933// static
935 DirectHandle<JSReceiver> prototype) {
936 DCHECK(IsUndefined(from->GetBackPointer()));
937
939 DirectHandle<JSObject> js_prototype = Cast<JSObject>(prototype);
940 if (!js_prototype->map()->is_prototype_map()) {
941 JSObject::OptimizeAsPrototype(js_prototype);
942 }
944 Map::GetOrCreatePrototypeInfo(js_prototype, isolate);
945 Tagged<HeapObject> map_obj;
947 if (info->GetDerivedMap(from).GetHeapObjectIfWeak(&map_obj)) {
948 map = handle(Cast<Map>(map_obj), isolate);
949 } else {
950 map = Map::CopyInitialMap(isolate, from);
951 map->set_new_target_is_base(false);
952 if (map->prototype() != *prototype) {
953 Map::SetPrototype(isolate, map, prototype);
954 }
955 PrototypeInfo::AddDerivedMap(info, map, isolate);
956 }
957 return map;
958 }
959
960 // The TransitionToPrototype map will not have new_target_is_base reset. But
961 // we don't need it to for proxies.
963 prototype);
964}
965
966static bool ContainsMap(MapHandlesSpan maps, Tagged<Map> map) {
967 DCHECK(!map.is_null());
968 for (DirectHandle<Map> current : maps) {
969 if (!current.is_null() && *current == map) return true;
970 }
971 return false;
972}
973
974static bool HasElementsKind(MapHandlesSpan maps, ElementsKind elements_kind) {
975 for (DirectHandle<Map> current : maps) {
976 if (!current.is_null() && current->elements_kind() == elements_kind)
977 return true;
978 }
979 return false;
980}
981
984 ConcurrencyMode cmode) {
986
987 if (IsDetached(isolate)) return Map();
988
989 ElementsKind kind = elements_kind();
990 bool is_packed = IsFastPackedElementsKind(kind);
991
992 Tagged<Map> transition;
994 // Check the state of the root map.
995 Tagged<Map> root_map = FindRootMap(isolate);
996 if (!EquivalentToForElementsKindTransition(root_map, cmode)) return Map();
997 root_map = root_map->LookupElementsTransitionMap(isolate, kind, cmode);
998 DCHECK(!root_map.is_null());
999 // Starting from the next existing elements kind transition try to
1000 // replay the property transitions that does not involve instance rewriting
1001 // (ElementsTransitionAndStoreStub does not support that).
1002 for (root_map = root_map->ElementsTransitionMap(isolate, cmode);
1003 !root_map.is_null() && root_map->has_fast_elements();
1004 root_map = root_map->ElementsTransitionMap(isolate, cmode)) {
1005 // If root_map's elements kind doesn't match any of the elements kind in
1006 // the candidates there is no need to do any additional work.
1007 if (!HasElementsKind(candidates, root_map->elements_kind())) continue;
1008 Tagged<Map> current =
1009 root_map->TryReplayPropertyTransitions(isolate, *this, cmode);
1010 if (current.is_null()) continue;
1011 if (InstancesNeedRewriting(current, cmode)) continue;
1012
1013 const bool current_is_packed =
1014 IsFastPackedElementsKind(current->elements_kind());
1015 if (ContainsMap(candidates, current) &&
1016 (is_packed || !current_is_packed)) {
1017 transition = current;
1018 is_packed = is_packed && current_is_packed;
1019 }
1020 }
1021 }
1022 return transition;
1023}
1024
1026 Tagged<Map> map,
1027 ElementsKind to_kind,
1028 ConcurrencyMode cmode) {
1030 // Ensure we are requested to search elements kind transition "near the root".
1031 DCHECK_EQ(map->FindRootMap(isolate)->NumberOfOwnDescriptors(),
1032 map->NumberOfOwnDescriptors());
1033 Tagged<Map> current_map = map;
1034
1035 ElementsKind kind = map->elements_kind();
1036 while (kind != to_kind) {
1037 Tagged<Map> next_map = current_map->ElementsTransitionMap(isolate, cmode);
1038 if (next_map.is_null()) return current_map;
1039 kind = next_map->elements_kind();
1040 current_map = next_map;
1041 }
1042
1043 DCHECK_EQ(to_kind, current_map->elements_kind());
1044 return current_map;
1045}
1046
1048 ElementsKind to_kind,
1049 ConcurrencyMode cmode) {
1050 Tagged<Map> to_map =
1051 FindClosestElementsTransition(isolate, *this, to_kind, cmode);
1052 if (to_map->elements_kind() == to_kind) return to_map;
1053 return Map();
1054}
1055
1057 if (isolate->initial_array_prototype()->map() == *this) {
1058 return true;
1059 }
1060
1061 if (isolate->initial_object_prototype()->map() == *this) {
1062 return true;
1063 }
1064
1065 return false;
1066}
1067
1070 ElementsKind to_kind) {
1071 ElementsKind from_kind = map->elements_kind();
1072 if (from_kind == to_kind) return map;
1073
1074 // We should never be trying to go backwards in the elements kind manifold.
1076 to_kind != GetPackedElementsKind(from_kind));
1077
1078 Tagged<Context> native_context = isolate->context()->native_context();
1079 if (from_kind == FAST_SLOPPY_ARGUMENTS_ELEMENTS) {
1080 if (*map == native_context->fast_aliased_arguments_map()) {
1082 return direct_handle(native_context->slow_aliased_arguments_map(),
1083 isolate);
1084 }
1085 } else if (from_kind == SLOW_SLOPPY_ARGUMENTS_ELEMENTS) {
1086 if (*map == native_context->slow_aliased_arguments_map()) {
1088 return direct_handle(native_context->fast_aliased_arguments_map(),
1089 isolate);
1090 }
1091 } else if (IsFastElementsKind(from_kind) && IsFastElementsKind(to_kind)) {
1092 // Reuse map transitions for JSArrays.
1094 if (native_context->GetInitialJSArrayMap(from_kind) == *map) {
1095 Tagged<Object> maybe_transitioned_map =
1097 if (IsMap(maybe_transitioned_map)) {
1098 return direct_handle(Cast<Map>(maybe_transitioned_map), isolate);
1099 }
1100 }
1101 }
1102
1103 DCHECK(!IsUndefined(*map, isolate));
1104
1105 bool allow_store_transition = IsTransitionElementsKind(from_kind);
1106 // Only store fast element maps in ascending generality.
1107 if (IsFastElementsKind(to_kind)) {
1108 allow_store_transition =
1109 allow_store_transition && IsTransitionableFastElementsKind(from_kind) &&
1110 IsMoreGeneralElementsKindTransition(from_kind, to_kind);
1111 }
1112
1113 if (!allow_store_transition) {
1114 return Map::CopyAsElementsKind(isolate, map, to_kind, OMIT_TRANSITION);
1115 }
1116
1117 return MapUpdater{isolate, map}.ReconfigureElementsKind(to_kind);
1118}
1119
1121 Handle<Map> map,
1122 ElementsKind to_kind) {
1123 DCHECK(IsTransitionElementsKind(map->elements_kind()));
1124
1125 Handle<Map> current_map = map;
1126
1127 ElementsKind kind = map->elements_kind();
1128 TransitionFlag flag;
1129 if (map->IsDetached(isolate)) {
1130 flag = OMIT_TRANSITION;
1131 } else {
1132 flag = INSERT_TRANSITION;
1133 if (IsFastElementsKind(kind)) {
1134 while (kind != to_kind && !IsTerminalElementsKind(kind)) {
1136 current_map = Map::CopyAsElementsKind(isolate, current_map, kind, flag);
1137 }
1138 }
1139 }
1140
1141 // In case we are exiting the fast elements kind system, just add the map in
1142 // the end.
1143 if (kind != to_kind) {
1144 current_map = Map::CopyAsElementsKind(isolate, current_map, to_kind, flag);
1145 }
1146
1147 DCHECK(current_map->elements_kind() == to_kind);
1148 return current_map;
1149}
1150
1151// static
1152std::optional<Tagged<Map>> Map::TryAsElementsKind(Isolate* isolate,
1155 ConcurrencyMode cmode) {
1156 Tagged<Map> closest_map =
1157 FindClosestElementsTransition(isolate, *map, kind, cmode);
1158 if (closest_map->elements_kind() != kind) return {};
1159 return closest_map;
1160}
1161
1162// static
1165 Handle<Map> closest_map(
1166 FindClosestElementsTransition(isolate, *map, kind,
1168 isolate);
1169
1170 if (closest_map->elements_kind() == kind) {
1171 return closest_map;
1172 }
1173
1174 return AddMissingElementsTransitions(isolate, closest_map, kind);
1175}
1176
1178 int result = 0;
1181 if ((int{descs->GetDetails(i).attributes()} & ONLY_ENUMERABLE) == 0 &&
1182 !Object::FilterKey(descs->GetKey(i), ENUMERABLE_STRINGS)) {
1183 result++;
1184 }
1185 }
1186 return result;
1187}
1188
1190 int number_of_own_descriptors = NumberOfOwnDescriptors();
1192 // Search properties backwards to find the last field.
1193 for (int i = number_of_own_descriptors - 1; i >= 0; --i) {
1194 PropertyDetails details = descs->GetDetails(InternalIndex(i));
1195 if (details.location() == PropertyLocation::kField) {
1196 return details.field_index() + details.field_width_in_words();
1197 }
1198 }
1199 return 0;
1200}
1201
1203 // Wrapped string elements aren't explicitly stored in the elements backing
1204 // store, but are loaded indirectly from the underlying string.
1205 return !IsStringWrapperElementsKind(elements_kind()) &&
1206 !IsSpecialReceiverMap(*this) && !is_dictionary_map();
1207}
1208
1210 // If this map has TypedArray elements kind, we won't look at the prototype
1211 // chain, so we can return early.
1212 if (IsTypedArrayElementsKind(elements_kind())) return false;
1213
1214 for (PrototypeIterator iter(isolate, *this); !iter.IsAtEnd();
1215 iter.Advance()) {
1216 // Be conservative, don't look into any JSReceivers that may have custom
1217 // elements. For example, into JSProxies, String wrappers (which have have
1218 // non-configurable, non-writable elements), API objects, etc.
1219 if (IsCustomElementsReceiverMap(iter.GetCurrent()->map())) return true;
1220
1221 Tagged<JSObject> current = iter.GetCurrent<JSObject>();
1222 ElementsKind elements_kind = current->GetElementsKind(isolate);
1223 // If this prototype has TypedArray elements kind, we won't look any further
1224 // in the prototype chain, so we can return early.
1225 if (IsTypedArrayElementsKind(elements_kind)) return false;
1226 if (IsFrozenElementsKind(elements_kind)) return true;
1227
1228 if (IsDictionaryElementsKind(elements_kind) &&
1229 current->element_dictionary(isolate)->requires_slow_elements()) {
1230 return true;
1231 }
1232
1233 if (IsSlowArgumentsElementsKind(elements_kind)) {
1235 Cast<SloppyArgumentsElements>(current->elements(isolate));
1236 Tagged<Object> arguments = elements->arguments();
1237 if (Cast<NumberDictionary>(arguments)->requires_slow_elements()) {
1238 return true;
1239 }
1240 }
1241 }
1242
1243 return false;
1244}
1245
1247 int instance_size, int inobject_properties) {
1248 Handle<Map> result = isolate->factory()->NewMap(
1249 src_handle, src_handle->instance_type(), instance_size,
1250 TERMINAL_FAST_ELEMENTS_KIND, inobject_properties);
1251
1252 // We have to set the bitfields before any potential GCs could happen because
1253 // heap verification might fail otherwise.
1254 {
1256 Tagged<Map> src = *src_handle;
1257 Tagged<Map> raw = *result;
1258 raw->set_constructor_or_back_pointer(src->GetConstructorRaw());
1259 raw->set_bit_field(src->bit_field());
1260 raw->set_bit_field2(src->bit_field2());
1261 int new_bit_field3 = src->bit_field3();
1262 new_bit_field3 = Bits3::OwnsDescriptorsBit::update(new_bit_field3, true);
1263 new_bit_field3 =
1264 Bits3::NumberOfOwnDescriptorsBits::update(new_bit_field3, 0);
1265 new_bit_field3 = Bits3::EnumLengthBits::update(new_bit_field3,
1267 new_bit_field3 = Bits3::IsDeprecatedBit::update(new_bit_field3, false);
1268 new_bit_field3 =
1269 Bits3::IsInRetainedMapListBit::update(new_bit_field3, false);
1270 if (!src->is_dictionary_map()) {
1271 new_bit_field3 = Bits3::IsUnstableBit::update(new_bit_field3, false);
1272 }
1273 // Same as bit_field comment above.
1274 raw->set_bit_field3(new_bit_field3);
1275 raw->clear_padding();
1276 }
1277 DirectHandle<JSPrototype> prototype(src_handle->prototype(), isolate);
1278 Map::SetPrototype(isolate, result, prototype);
1279 return result;
1280}
1281
1283 ElementsKind new_elements_kind,
1284 DirectHandle<JSPrototype> new_prototype,
1285 PropertyNormalizationMode mode, bool use_cache,
1286 const char* reason) {
1287 DCHECK(!fast_map->is_dictionary_map());
1288
1289 Tagged<Map> meta_map = fast_map->map();
1290 if (fast_map->is_prototype_map()) {
1291 use_cache = false;
1292 }
1294 if (use_cache) {
1295 Tagged<Object> normalized_map_cache =
1296 meta_map->native_context()->normalized_map_cache();
1297 use_cache = !IsUndefined(normalized_map_cache, isolate);
1298 if (use_cache) {
1300 direct_handle(normalized_map_cache, isolate));
1301 }
1302 }
1303
1304 Handle<Map> new_map;
1305 if (use_cache && cache
1306 ->Get(isolate, fast_map, new_elements_kind,
1307 new_prototype.is_null() ? fast_map->prototype()
1308 : *new_prototype,
1309 mode)
1310 .ToHandle(&new_map)) {
1311#ifdef VERIFY_HEAP
1312 if (v8_flags.verify_heap) new_map->DictionaryMapVerify(isolate);
1313#endif
1314#ifdef ENABLE_SLOW_DCHECKS
1315 if (v8_flags.enable_slow_asserts) {
1316 // The cached map should match newly created normalized map bit-by-bit,
1317 // except for the code cache, which can contain some ICs which can be
1318 // applied to the shared map, dependent code and weak cell cache.
1319 DirectHandle<Map> fresh = Map::CopyNormalized(isolate, fast_map, mode);
1320 fresh->set_elements_kind(new_elements_kind);
1321 if (!new_prototype.is_null()) {
1322 Map::SetPrototype(isolate, fresh, new_prototype);
1323 }
1324
1325 static_assert(Map::kPrototypeValidityCellOffset ==
1326 Map::kDependentCodeOffset + kTaggedSize);
1327 DCHECK_EQ(0, memcmp(reinterpret_cast<void*>(fresh->address()),
1328 reinterpret_cast<void*>(new_map->address()),
1329 Map::kBitField3Offset));
1330 // The IsInRetainedMapListBit might be different if the {new_map}
1331 // that we got from the {cache} was already embedded into optimized
1332 // code somewhere.
1333 // The IsMigrationTargetBit might be different if the {new_map} from
1334 // {cache} has already been marked as a migration target.
1335 constexpr int ignored_bit_field3_bits =
1336 Bits3::IsInRetainedMapListBit::kMask |
1337 Bits3::IsMigrationTargetBit::kMask;
1338 DCHECK_EQ(fresh->bit_field3() & ~ignored_bit_field3_bits,
1339 new_map->bit_field3() & ~ignored_bit_field3_bits);
1340 int offset = Map::kBitField3Offset + kInt32Size;
1341 DCHECK_EQ(0, memcmp(reinterpret_cast<void*>(fresh->address() + offset),
1342 reinterpret_cast<void*>(new_map->address() + offset),
1343 Map::kDependentCodeOffset - offset));
1344 offset = Map::kPrototypeValidityCellOffset + kTaggedSize;
1345 if (new_map->is_prototype_map()) {
1346 // For prototype maps, the PrototypeInfo is not copied.
1347 static_assert(Map::kTransitionsOrPrototypeInfoOffset ==
1348 Map::kPrototypeValidityCellOffset + kTaggedSize);
1349 offset = kTransitionsOrPrototypeInfoOffset + kTaggedSize;
1350 DCHECK_EQ(fresh->raw_transitions(), Smi::zero());
1351 }
1352 DCHECK_EQ(0, memcmp(reinterpret_cast<void*>(fresh->address() + offset),
1353 reinterpret_cast<void*>(new_map->address() + offset),
1354 Map::kSize - offset));
1355 }
1356#endif
1357 if (v8_flags.log_maps) {
1358 LOG(isolate, MapEvent("NormalizeCached", fast_map, new_map, reason));
1359 }
1360 } else {
1361 new_map = Map::CopyNormalized(isolate, fast_map, mode);
1362 new_map->set_elements_kind(new_elements_kind);
1363 if (!new_prototype.is_null()) {
1364 Map::SetPrototype(isolate, new_map, new_prototype);
1365 DCHECK(new_map->is_dictionary_map() && !new_map->is_deprecated());
1366 }
1367 if (use_cache) {
1368 cache->Set(isolate, fast_map, new_map);
1369 }
1370 if (v8_flags.log_maps) {
1371 LOG(isolate, MapEvent("Normalize", fast_map, new_map, reason));
1372 }
1373 }
1374 fast_map->NotifyLeafMapLayoutChange(isolate);
1375 return new_map;
1376}
1377
1380 int new_instance_size = map->instance_size();
1381 if (mode == CLEAR_INOBJECT_PROPERTIES) {
1382 new_instance_size -= map->GetInObjectProperties() * kTaggedSize;
1383 }
1384
1386 isolate, map, new_instance_size,
1387 mode == CLEAR_INOBJECT_PROPERTIES ? 0 : map->GetInObjectProperties());
1388 {
1390 Tagged<Map> raw = *result;
1391 // Clear the unused_property_fields explicitly as this field should not
1392 // be accessed for normalized maps.
1393 raw->SetInObjectUnusedPropertyFields(0);
1394 raw->set_is_dictionary_map(true);
1395 raw->set_is_migration_target(false);
1396 raw->set_may_have_interesting_properties(true);
1397 raw->set_construction_counter(kNoSlackTracking);
1398 }
1399
1400#ifdef VERIFY_HEAP
1401 if (v8_flags.verify_heap) result->DictionaryMapVerify(isolate);
1402#endif
1403
1404 return result;
1405}
1406
1407// Return an immutable prototype exotic object version of the input map.
1408// Never even try to cache it in the transition tree, as it is intended
1409// for the global object and its prototype chain, and excluding it saves
1410// memory on the map transition tree.
1411
1412// static
1414 DirectHandle<Map> map) {
1415 DirectHandle<Map> new_map = Map::Copy(isolate, map, "ImmutablePrototype");
1416 new_map->set_is_immutable_proto(true);
1417 return new_map;
1418}
1419
1420namespace {
1421void EnsureInitialMap(Isolate* isolate, DirectHandle<Map> map) {
1422#ifdef DEBUG
1423 Tagged<Object> maybe_constructor = map->GetConstructor();
1424 DCHECK((IsJSFunction(maybe_constructor) &&
1425 *map == Cast<JSFunction>(maybe_constructor)->initial_map()) ||
1426 // Below are the exceptions to the check above.
1427 // |Function|'s initial map is a |sloppy_function_map| but
1428 // other function map variants such as sloppy with name or readonly
1429 // prototype or various strict function maps variants, etc. also
1430 // have Function as a constructor.
1431 *map == *isolate->strict_function_map() ||
1432 *map == *isolate->strict_function_with_name_map() ||
1433 // Same applies to |GeneratorFunction|'s initial map and generator
1434 // function map variants.
1435 *map == *isolate->generator_function_with_name_map() ||
1436 // Same applies to |AsyncFunction|'s initial map and other async
1437 // function map variants.
1438 *map == *isolate->async_function_with_name_map());
1439#endif
1440 // Initial maps must not contain descriptors in the descriptors array
1441 // that do not belong to the map.
1442 DCHECK_EQ(map->NumberOfOwnDescriptors(),
1443 map->instance_descriptors(isolate)->number_of_descriptors());
1444}
1445} // namespace
1446
1447// static
1450 EnsureInitialMap(isolate, map);
1451 return CopyNormalized(isolate, map, mode);
1452}
1453
1454// static
1456 int instance_size, int inobject_properties,
1457 int unused_property_fields) {
1458 EnsureInitialMap(isolate, map);
1459
1461 RawCopy(isolate, map, instance_size, inobject_properties);
1462
1463 // Please note instance_type and instance_size are set when allocated.
1464 result->SetInObjectUnusedPropertyFields(unused_property_fields);
1465
1466 int number_of_own_descriptors = map->NumberOfOwnDescriptors();
1467 if (number_of_own_descriptors > 0) {
1468 // The copy will use the same descriptors array without ownership.
1469 Tagged<DescriptorArray> descriptors = map->instance_descriptors(isolate);
1470 result->set_owns_descriptors(false);
1471 result->UpdateDescriptors(isolate, descriptors, number_of_own_descriptors);
1472
1474 result->GetInObjectProperties() - result->UnusedPropertyFields());
1475 }
1476
1477 return result;
1478}
1479
1482 RawCopy(isolate, map, map->instance_size(),
1483 IsJSObjectMap(*map) ? map->GetInObjectProperties() : 0);
1484
1485 // Please note instance_type and instance_size are set when allocated.
1486 if (IsJSObjectMap(*map)) {
1487 result->CopyUnusedPropertyFields(*map);
1488 }
1489 map->NotifyLeafMapLayoutChange(isolate);
1490 return result;
1491}
1492
1495 Descriptor* descriptor) {
1496 // Sanity check. This path is only to be taken if the map owns its descriptor
1497 // array, implying that its NumberOfOwnDescriptors equals the number of
1498 // descriptors in the descriptor array.
1499 DCHECK_EQ(map->NumberOfOwnDescriptors(),
1500 map->instance_descriptors(isolate)->number_of_descriptors());
1501
1502 Handle<Map> result = CopyDropDescriptors(isolate, map);
1503 DirectHandle<Name> name = descriptor->GetKey();
1504
1505 // Properly mark the {result} if the {name} is an "interesting symbol".
1506 if (name->IsInteresting(isolate)) {
1507 result->set_may_have_interesting_properties(true);
1508 }
1509
1510 // Ensure there's space for the new descriptor in the shared descriptor array.
1511 if (descriptors->number_of_slack_descriptors() == 0) {
1512 int old_size = descriptors->number_of_descriptors();
1513 if (old_size == 0) {
1514 descriptors = DescriptorArray::Allocate(isolate, 0, 1);
1515 } else {
1516 int slack = SlackForArraySize(old_size, kMaxNumberOfDescriptors);
1517 EnsureDescriptorSlack(isolate, map, slack);
1518 descriptors = direct_handle(map->instance_descriptors(isolate), isolate);
1519 }
1520 }
1521
1522 {
1524 descriptors->Append(descriptor);
1525 result->InitializeDescriptors(isolate, *descriptors);
1526 }
1527
1528 DCHECK(result->NumberOfOwnDescriptors() == map->NumberOfOwnDescriptors() + 1);
1530
1531 return result;
1532}
1533
1536 TransitionKindFlag transition_kind,
1537 bool force_connect) {
1538 DCHECK_EQ(parent->map(), child->map());
1539 DCHECK_IMPLIES(name->IsInteresting(isolate),
1540 child->may_have_interesting_properties());
1541 DCHECK_IMPLIES(parent->may_have_interesting_properties(),
1542 child->may_have_interesting_properties());
1543 if (!IsUndefined(parent->GetBackPointer(), isolate)) {
1544 parent->set_owns_descriptors(false);
1545 } else if (!parent->IsDetached(isolate)) {
1546 // |parent| is initial map and it must not contain descriptors in the
1547 // descriptors array that do not belong to the map.
1548 DCHECK_EQ(parent->NumberOfOwnDescriptors(),
1549 parent->instance_descriptors(isolate)->number_of_descriptors());
1550 }
1551 if (parent->IsDetached(isolate) && !force_connect) {
1552 DCHECK(child->IsDetached(isolate));
1553 if (v8_flags.log_maps) {
1554 LOG(isolate, MapEvent("Transition", parent, child, "prototype", name));
1555 }
1556 } else {
1557 TransitionsAccessor::Insert(isolate, parent, name, child, transition_kind);
1558 if (v8_flags.log_maps) {
1559 LOG(isolate, MapEvent("Transition", parent, child, "", name));
1560 }
1561 }
1562}
1563
1565 Isolate* isolate, DirectHandle<Map> map,
1567 MaybeDirectHandle<Name> maybe_name, const char* reason,
1568 TransitionKindFlag transition_kind) {
1569 DCHECK(descriptors->IsSortedNoDuplicates());
1570
1571 Handle<Map> result = CopyDropDescriptors(isolate, map);
1572 bool is_connected = false;
1573
1574 // Properly mark the {result} if the {name} is an "interesting symbol".
1576 if (maybe_name.ToHandle(&name) && name->IsInteresting(isolate)) {
1577 result->set_may_have_interesting_properties(true);
1578 }
1579
1580 if (map->is_prototype_map()) {
1581 result->InitializeDescriptors(isolate, *descriptors);
1582 } else {
1583 if (flag == INSERT_TRANSITION &&
1585 result->InitializeDescriptors(isolate, *descriptors);
1586
1587 DCHECK(!maybe_name.is_null());
1588 ConnectTransition(isolate, map, result, name, transition_kind);
1589 is_connected = true;
1590 } else if ((transition_kind == PROTOTYPE_TRANSITION &&
1591 v8_flags.move_prototype_transitions_first) ||
1592 isolate->bootstrapper()->IsActive()) {
1593 // Prototype transitions are always between root maps. UpdatePrototype
1594 // uses the MapUpdater and instance migration. Thus, field generalization
1595 // is allowed to happen lazily.
1596 DCHECK_IMPLIES(transition_kind == PROTOTYPE_TRANSITION,
1597 IsUndefined(map->GetBackPointer()));
1598 result->InitializeDescriptors(isolate, *descriptors);
1599 } else {
1600 DCHECK_IMPLIES(transition_kind == PROTOTYPE_TRANSITION,
1601 !v8_flags.move_prototype_transitions_first);
1602 descriptors->GeneralizeAllFields(transition_kind == PROTOTYPE_TRANSITION);
1603 result->InitializeDescriptors(isolate, *descriptors);
1604 }
1605 }
1606 if (v8_flags.log_maps && !is_connected) {
1607 LOG(isolate,
1608 MapEvent("ReplaceDescriptors", map, result, reason,
1609 maybe_name.is_null() ? DirectHandle<HeapObject>() : name));
1610 }
1611 return result;
1612}
1613
1614// Creates transition tree starting from |split_map| and adding all descriptors
1615// starting from descriptor with index |split_map|.NumberOfOwnDescriptors().
1616// The way how it is done is tricky because of GC and special descriptors
1617// marking logic.
1619 Isolate* isolate, DirectHandle<Map> split_map,
1620 DirectHandle<DescriptorArray> descriptors) {
1621 DCHECK(descriptors->IsSortedNoDuplicates());
1622 int split_nof = split_map->NumberOfOwnDescriptors();
1623 int nof_descriptors = descriptors->number_of_descriptors();
1624 CHECK_LT(split_nof, nof_descriptors);
1625
1626 // Start with creating last map which will own full descriptors array.
1627 // This is necessary to guarantee that GC will mark the whole descriptor
1628 // array if any of the allocations happening below fail.
1629 // Number of unused properties is temporarily incorrect and the layout
1630 // descriptor could unnecessarily be in slow mode but we will fix after
1631 // all the other intermediate maps are created.
1632 // Also the last map might have interesting symbols, we temporarily set
1633 // the flag and clear it right before the descriptors are installed. This
1634 // makes heap verification happy and ensures the flag ends up accurate.
1635 Handle<Map> last_map = CopyDropDescriptors(isolate, split_map);
1636 last_map->InitializeDescriptors(isolate, *descriptors);
1637 last_map->SetInObjectUnusedPropertyFields(0);
1638 last_map->set_may_have_interesting_properties(true);
1639
1640 // During creation of intermediate maps we violate descriptors sharing
1641 // invariant since the last map is not yet connected to the transition tree
1642 // we create here. But it is safe because GC never trims map's descriptors
1643 // if there are no dead transitions from that map and this is exactly the
1644 // case for all the intermediate maps we create here.
1645 DirectHandle<Map> map = split_map;
1646 for (InternalIndex i : InternalIndex::Range(split_nof, nof_descriptors - 1)) {
1647 DirectHandle<Map> new_map = CopyDropDescriptors(isolate, map);
1648 // Force connection of these maps to prevent split_map being a root map to
1649 // be treated as detached.
1650 InstallDescriptors(isolate, map, new_map, i, descriptors,
1651 /* force_connect */ true);
1652 DCHECK_EQ(*new_map->GetBackPointer(), *map);
1653 map = new_map;
1654 }
1655 map->NotifyLeafMapLayoutChange(isolate);
1656 last_map->set_may_have_interesting_properties(false);
1657 InstallDescriptors(isolate, map, last_map, InternalIndex(nof_descriptors - 1),
1658 descriptors);
1659 return last_map;
1660}
1661
1662// Since this method is used to rewrite an existing transition tree, it can
1663// always insert transitions without checking.
1665 DirectHandle<Map> child,
1666 InternalIndex new_descriptor,
1668 bool force_connect) {
1669 DCHECK(descriptors->IsSortedNoDuplicates());
1670
1671 child->SetInstanceDescriptors(isolate, *descriptors,
1672 new_descriptor.as_int() + 1);
1673 child->CopyUnusedPropertyFields(*parent);
1674 PropertyDetails details = descriptors->GetDetails(new_descriptor);
1675 if (details.location() == PropertyLocation::kField) {
1676 child->AccountAddedPropertyField();
1677 }
1678
1679 DirectHandle<Name> name(descriptors->GetKey(new_descriptor), isolate);
1680 if (parent->may_have_interesting_properties() ||
1681 name->IsInteresting(isolate)) {
1682 child->set_may_have_interesting_properties(true);
1683 }
1684 ConnectTransition(isolate, parent, child, name, SIMPLE_PROPERTY_TRANSITION,
1685 force_connect);
1686}
1687
1690 // Only certain objects are allowed to have non-terminal fast transitional
1691 // elements kinds.
1692 DCHECK(IsJSObjectMap(*map));
1694 !map->CanHaveFastTransitionableElementsKind(),
1696
1697 Tagged<Map> maybe_elements_transition_map;
1698 if (flag == INSERT_TRANSITION) {
1699 // Ensure we are requested to add elements kind transition "near the root".
1700 DCHECK_EQ(map->FindRootMap(isolate)->NumberOfOwnDescriptors(),
1701 map->NumberOfOwnDescriptors());
1702
1703 maybe_elements_transition_map =
1704 map->ElementsTransitionMap(isolate, ConcurrencyMode::kSynchronous);
1705 DCHECK(maybe_elements_transition_map.is_null() ||
1706 (maybe_elements_transition_map->elements_kind() ==
1710 IsMoreGeneralElementsKindTransition(map->elements_kind(), kind));
1711 DCHECK(kind != map->elements_kind());
1712 }
1713
1714 bool insert_transition =
1715 flag == INSERT_TRANSITION &&
1717 maybe_elements_transition_map.is_null();
1718
1719 if (insert_transition) {
1720 Handle<Map> new_map = CopyForElementsTransition(isolate, map);
1721 new_map->set_elements_kind(kind);
1722
1723 DirectHandle<Name> name = isolate->factory()->elements_transition_symbol();
1724 ConnectTransition(isolate, map, new_map, name, SPECIAL_TRANSITION);
1725 return new_map;
1726 }
1727
1728 // Create a new free-floating map only if we are not allowed to store it.
1729 Handle<Map> new_map = Copy(isolate, map, "CopyAsElementsKind");
1730 new_map->set_elements_kind(kind);
1731 return new_map;
1732}
1733
1735 Isolate* isolate, DirectHandle<Map> initial_map,
1737 DCHECK(InstanceTypeChecker::IsJSFunction(initial_map->instance_type()));
1738 // Initial map for sloppy mode function is stored in the function
1739 // constructor. Initial maps for strict mode are cached as special transitions
1740 // using |strict_function_transition_symbol| as a key.
1741 if (is_sloppy(shared_info->language_mode())) return initial_map;
1742
1743 DirectHandle<Map> function_map(Cast<Map>(isolate->native_context()->get(
1744 shared_info->function_map_index())),
1745 isolate);
1746
1747 static_assert(LanguageModeSize == 2);
1748 DCHECK_EQ(LanguageMode::kStrict, shared_info->language_mode());
1749 DirectHandle<Symbol> transition_symbol =
1750 isolate->factory()->strict_function_transition_symbol();
1752 isolate, initial_map, *transition_symbol);
1753 if (!maybe_transition.is_null()) {
1754 return maybe_transition.ToHandleChecked();
1755 }
1756 initial_map->NotifyLeafMapLayoutChange(isolate);
1757
1758 // Create new map taking descriptors from the |function_map| and all
1759 // the other details from the |initial_map|.
1760 DirectHandle<Map> map =
1761 Map::CopyInitialMap(isolate, function_map, initial_map->instance_size(),
1762 initial_map->GetInObjectProperties(),
1763 initial_map->UnusedPropertyFields());
1764 map->SetConstructor(initial_map->GetConstructor());
1765 map->set_prototype(initial_map->prototype());
1766 map->set_construction_counter(initial_map->construction_counter());
1767
1768 if (TransitionsAccessor::CanHaveMoreTransitions(isolate, initial_map)) {
1769 Map::ConnectTransition(isolate, initial_map, map, transition_symbol,
1771 }
1772 return map;
1773}
1774
1776 DirectHandle<Map> map) {
1777 DCHECK(!map->IsDetached(isolate));
1778 DCHECK(!map->is_dictionary_map());
1779 Handle<Map> new_map = CopyDropDescriptors(isolate, map);
1780
1781 if (map->owns_descriptors()) {
1782 // In case the map owned its own descriptors, share the descriptors and
1783 // transfer ownership to the new map.
1784 // The properties did not change, so reuse descriptors.
1785 map->set_owns_descriptors(false);
1786 new_map->InitializeDescriptors(isolate, map->instance_descriptors(isolate));
1787 } else {
1788 // In case the map did not own its own descriptors, a split is forced by
1789 // copying the map; creating a new descriptor array cell.
1791 map->instance_descriptors(isolate), isolate);
1792 int number_of_own_descriptors = map->NumberOfOwnDescriptors();
1794 isolate, descriptors, number_of_own_descriptors);
1795 new_map->InitializeDescriptors(isolate, *new_descriptors);
1796 }
1797 return new_map;
1798}
1799
1801 Isolate* isolate, DirectHandle<Map> map,
1802 DirectHandle<JSPrototype> prototype) {
1803 // For simplicity we always copy descriptors although it would be possible to
1804 // share them in some situations.
1805 Handle<Map> new_map =
1806 Copy(isolate, map, "TransitionToPrototype", PROTOTYPE_TRANSITION);
1807 Map::SetPrototype(isolate, new_map, prototype);
1808 return new_map;
1809}
1810
1812 const char* reason, TransitionKindFlag kind) {
1813 DirectHandle<DescriptorArray> descriptors(map->instance_descriptors(isolate),
1814 isolate);
1815 int number_of_own_descriptors = map->NumberOfOwnDescriptors();
1817 isolate, descriptors, number_of_own_descriptors);
1818 auto res =
1819 CopyReplaceDescriptors(isolate, map, new_descriptors, OMIT_TRANSITION,
1820 MaybeDirectHandle<Name>(), reason, kind);
1821 return res;
1822}
1823
1824Handle<Map> Map::Create(Isolate* isolate, int inobject_properties) {
1825 Handle<Map> copy_handle =
1826 Copy(isolate,
1827 direct_handle(isolate->object_function()->initial_map(), isolate),
1828 "MapCreate");
1830 Tagged<Map> copy = *copy_handle;
1831
1832 // Check that we do not overflow the instance size when adding the extra
1833 // inobject properties. If the instance size overflows, we allocate as many
1834 // properties as we can as inobject properties.
1835 if (inobject_properties > JSObject::kMaxInObjectProperties) {
1836 inobject_properties = JSObject::kMaxInObjectProperties;
1837 }
1838
1839 int new_instance_size =
1840 JSObject::kHeaderSize + kTaggedSize * inobject_properties;
1841
1842 // Adjust the map with the extra inobject properties.
1843 copy->set_instance_size(new_instance_size);
1844 copy->SetInObjectPropertiesStartInWords(JSObject::kHeaderSize / kTaggedSize);
1845 DCHECK_EQ(copy->GetInObjectProperties(), inobject_properties);
1846 copy->SetInObjectUnusedPropertyFields(inobject_properties);
1847 copy->set_visitor_id(Map::GetVisitorId(copy));
1848
1849 return copy_handle;
1850}
1851
1853 Isolate* isolate, DirectHandle<Map> map, PropertyAttributes attrs_to_add,
1854 DirectHandle<Symbol> transition_marker, const char* reason,
1855 bool old_map_is_dictionary_elements_kind) {
1856 int num_descriptors = map->NumberOfOwnDescriptors();
1859 isolate, direct_handle(map->instance_descriptors(isolate), isolate),
1860 num_descriptors, attrs_to_add);
1861 // Do not track transitions during bootstrapping.
1862 TransitionFlag flag =
1863 isolate->bootstrapper()->IsActive() ? OMIT_TRANSITION : INSERT_TRANSITION;
1864 Handle<Map> new_map =
1865 CopyReplaceDescriptors(isolate, map, new_desc, flag, transition_marker,
1866 reason, SPECIAL_TRANSITION);
1867 new_map->set_is_extensible(false);
1868 if (!IsTypedArrayOrRabGsabTypedArrayElementsKind(map->elements_kind())) {
1869 ElementsKind new_kind = IsStringWrapperElementsKind(map->elements_kind())
1872 if (!old_map_is_dictionary_elements_kind) {
1873 switch (map->elements_kind()) {
1874 case PACKED_ELEMENTS:
1875 if (attrs_to_add == SEALED) {
1876 new_kind = PACKED_SEALED_ELEMENTS;
1877 } else if (attrs_to_add == FROZEN) {
1878 new_kind = PACKED_FROZEN_ELEMENTS;
1879 } else {
1881 }
1882 break;
1884 if (attrs_to_add == SEALED) {
1885 new_kind = PACKED_SEALED_ELEMENTS;
1886 } else if (attrs_to_add == FROZEN) {
1887 new_kind = PACKED_FROZEN_ELEMENTS;
1888 }
1889 break;
1891 if (attrs_to_add == FROZEN) {
1892 new_kind = PACKED_FROZEN_ELEMENTS;
1893 }
1894 break;
1895 case HOLEY_ELEMENTS:
1896 if (attrs_to_add == SEALED) {
1897 new_kind = HOLEY_SEALED_ELEMENTS;
1898 } else if (attrs_to_add == FROZEN) {
1899 new_kind = HOLEY_FROZEN_ELEMENTS;
1900 } else {
1902 }
1903 break;
1905 if (attrs_to_add == SEALED) {
1906 new_kind = HOLEY_SEALED_ELEMENTS;
1907 } else if (attrs_to_add == FROZEN) {
1908 new_kind = HOLEY_FROZEN_ELEMENTS;
1909 }
1910 break;
1912 if (attrs_to_add == FROZEN) {
1913 new_kind = HOLEY_FROZEN_ELEMENTS;
1914 }
1915 break;
1916 default:
1917 break;
1918 }
1919 }
1920 new_map->set_elements_kind(new_kind);
1921 }
1922 return new_map;
1923}
1924
1925namespace {
1926
1927bool CanHoldValue(Tagged<DescriptorArray> descriptors, InternalIndex descriptor,
1928 PropertyConstness constness, Tagged<Object> value) {
1929 PropertyDetails details = descriptors->GetDetails(descriptor);
1930 if (details.location() == PropertyLocation::kField) {
1931 if (details.kind() == PropertyKind::kData) {
1932 return IsGeneralizableTo(constness, details.constness()) &&
1933 Object::FitsRepresentation(value, details.representation()) &&
1934 FieldType::NowContains(descriptors->GetFieldType(descriptor),
1935 value);
1936 } else {
1938 return false;
1939 }
1940
1941 } else {
1945 return false;
1946 }
1947 UNREACHABLE();
1948}
1949
1950DirectHandle<Map> UpdateDescriptorForValue(Isolate* isolate,
1951 DirectHandle<Map> map,
1952 InternalIndex descriptor,
1953 PropertyConstness constness,
1954 DirectHandle<Object> value) {
1955 if (CanHoldValue(map->instance_descriptors(isolate), descriptor, constness,
1956 *value)) {
1957 return map;
1958 }
1959
1960 PropertyAttributes attributes =
1961 map->instance_descriptors(isolate)->GetDetails(descriptor).attributes();
1962 Representation representation =
1963 Object::OptimalRepresentation(*value, isolate);
1964 DirectHandle<FieldType> type =
1965 Object::OptimalType(*value, isolate, representation);
1966
1967 MapUpdater mu(isolate, map);
1968 return mu.ReconfigureToDataField(descriptor, attributes, constness,
1969 representation, type);
1970}
1971
1972} // namespace
1973
1974// static
1977 InternalIndex descriptor,
1978 PropertyConstness constness,
1979 DirectHandle<Object> value) {
1980 // The map should already be fully updated before storing the property.
1981 DCHECK(!map->is_deprecated());
1982 // Dictionaries can store any property value.
1983 DCHECK(!map->is_dictionary_map());
1984 return UpdateDescriptorForValue(isolate, map, descriptor, constness, value);
1985}
1986
1988 Isolate* isolate, DirectHandle<Map> map, DirectHandle<Name> name,
1989 DirectHandle<Object> value, PropertyAttributes attributes,
1990 PropertyConstness constness, StoreOrigin store_origin) {
1991 RCS_SCOPE(isolate,
1992 map->IsDetached(isolate)
1993 ? RuntimeCallCounterId::kPrototypeMap_TransitionToDataProperty
1994 : RuntimeCallCounterId::kMap_TransitionToDataProperty);
1995
1996 DCHECK(IsUniqueName(*name));
1997 DCHECK(!map->is_dictionary_map());
1998
1999 // Migrate to the newest map before storing the property.
2000 map = Update(isolate, map);
2001
2003 isolate, map, *name, PropertyKind::kData, attributes);
2004 Handle<Map> transition;
2005 if (maybe_transition.ToHandle(&transition)) {
2006 InternalIndex descriptor = transition->LastAdded();
2007
2008 DCHECK_EQ(attributes, transition->instance_descriptors(isolate)
2009 ->GetDetails(descriptor)
2010 .attributes());
2011
2012 return UpdateDescriptorForValue(isolate, transition, descriptor, constness,
2013 value);
2014 }
2015
2016 // Do not track transitions during bootstrapping.
2017 TransitionFlag flag =
2018 isolate->bootstrapper()->IsActive() ? OMIT_TRANSITION : INSERT_TRANSITION;
2019 MaybeDirectHandle<Map> maybe_map;
2020 if (!map->TooManyFastProperties(store_origin)) {
2021 Representation representation =
2022 Object::OptimalRepresentation(*value, isolate);
2024 Object::OptimalType(*value, isolate, representation);
2025 maybe_map = Map::CopyWithField(isolate, map, name, type, attributes,
2026 constness, representation, flag);
2027 }
2028
2030 if (!maybe_map.ToHandle(&result)) {
2031 const char* reason = "TooManyFastProperties";
2032#if V8_TRACE_MAPS
2033 std::unique_ptr<base::ScopedVector<char>> buffer;
2034 if (v8_flags.log_maps) {
2035 base::ScopedVector<char> name_buffer(100);
2036 name->NameShortPrint(name_buffer);
2037 buffer.reset(new base::ScopedVector<char>(128));
2038 SNPrintF(*buffer, "TooManyFastProperties %s", name_buffer.begin());
2039 reason = buffer->begin();
2040 }
2041#endif
2042 DirectHandle<Object> maybe_constructor(map->GetConstructor(), isolate);
2043 if (v8_flags.feedback_normalization && map->new_target_is_base() &&
2044 IsJSFunction(*maybe_constructor) &&
2045 !Cast<JSFunction>(*maybe_constructor)->shared()->native()) {
2046 auto constructor = Cast<JSFunction>(maybe_constructor);
2047 DCHECK_NE(*constructor, constructor->native_context()->object_function());
2048 DirectHandle<Map> initial_map(constructor->initial_map(), isolate);
2049 result = Map::Normalize(isolate, initial_map, CLEAR_INOBJECT_PROPERTIES,
2050 reason);
2051 initial_map->DeprecateTransitionTree(isolate);
2053 isolate);
2054 JSFunction::SetInitialMap(isolate, constructor, result, prototype);
2055
2056 // Deoptimize all code that embeds the previous initial map.
2058 isolate, *initial_map, DependentCode::kInitialMapChangedGroup);
2059 if (!result->EquivalentToForNormalization(*map,
2061 result =
2062 Map::Normalize(isolate, map, CLEAR_INOBJECT_PROPERTIES, reason);
2063 }
2064 } else {
2065 result = Map::Normalize(isolate, map, CLEAR_INOBJECT_PROPERTIES, reason);
2066 }
2067 }
2068
2069 return result;
2070}
2071
2073 Isolate* isolate, DirectHandle<Map> map, DirectHandle<Name> name,
2076 RCS_SCOPE(
2077 isolate,
2078 map->IsDetached(isolate)
2079 ? RuntimeCallCounterId::kPrototypeMap_TransitionToAccessorProperty
2080 : RuntimeCallCounterId::kMap_TransitionToAccessorProperty);
2081
2082 // At least one of the accessors needs to be a new value.
2083 DCHECK(!IsNull(*getter, isolate) || !IsNull(*setter, isolate));
2084 DCHECK(IsUniqueName(*name));
2085
2086 // Migrate to the newest map before transitioning to the new property.
2087 map = Update(isolate, map);
2088
2089 // Dictionary maps can always have additional data properties.
2090 if (map->is_dictionary_map()) return map;
2091
2092 PropertyNormalizationMode mode = map->is_prototype_map()
2095
2096 MaybeDirectHandle<Map> maybe_transition =
2098 isolate, map, *name, PropertyKind::kAccessor, attributes);
2099 DirectHandle<Map> transition;
2100 if (maybe_transition.ToHandle(&transition)) {
2101 Tagged<DescriptorArray> descriptors =
2102 transition->instance_descriptors(isolate);
2103 InternalIndex last_descriptor = transition->LastAdded();
2104 DCHECK(descriptors->GetKey(last_descriptor)->Equals(*name));
2105
2107 descriptors->GetDetails(last_descriptor).kind());
2108 DCHECK_EQ(attributes,
2109 descriptors->GetDetails(last_descriptor).attributes());
2110
2111 DirectHandle<Object> maybe_pair(
2112 descriptors->GetStrongValue(last_descriptor), isolate);
2113 if (!IsAccessorPair(*maybe_pair)) {
2114 return Map::Normalize(isolate, map, mode,
2115 "TransitionToAccessorFromNonPair");
2116 }
2117
2118 auto pair = Cast<AccessorPair>(maybe_pair);
2119 if (!pair->Equals(*getter, *setter)) {
2120 return Map::Normalize(isolate, map, mode,
2121 "TransitionToDifferentAccessor");
2122 }
2123
2124 return transition;
2125 }
2126
2128 Tagged<DescriptorArray> old_descriptors = map->instance_descriptors(isolate);
2129 if (descriptor.is_found()) {
2130 if (descriptor != map->LastAdded()) {
2131 return Map::Normalize(isolate, map, mode, "AccessorsOverwritingNonLast");
2132 }
2133 PropertyDetails old_details = old_descriptors->GetDetails(descriptor);
2134 if (old_details.kind() != PropertyKind::kAccessor) {
2135 return Map::Normalize(isolate, map, mode,
2136 "AccessorsOverwritingNonAccessors");
2137 }
2138
2139 if (old_details.attributes() != attributes) {
2140 return Map::Normalize(isolate, map, mode, "AccessorsWithAttributes");
2141 }
2142
2143 DirectHandle<Object> maybe_pair(old_descriptors->GetStrongValue(descriptor),
2144 isolate);
2145 if (!IsAccessorPair(*maybe_pair)) {
2146 return Map::Normalize(isolate, map, mode, "AccessorsOverwritingNonPair");
2147 }
2148
2149 auto current_pair = Cast<AccessorPair>(maybe_pair);
2150 if (current_pair->Equals(*getter, *setter)) return map;
2151
2152 bool overwriting_accessor = false;
2153 if (!IsNull(*getter, isolate) &&
2154 !IsNull(current_pair->get(ACCESSOR_GETTER), isolate) &&
2155 current_pair->get(ACCESSOR_GETTER) != *getter) {
2156 overwriting_accessor = true;
2157 }
2158 if (!IsNull(*setter, isolate) &&
2159 !IsNull(current_pair->get(ACCESSOR_SETTER), isolate) &&
2160 current_pair->get(ACCESSOR_SETTER) != *setter) {
2161 overwriting_accessor = true;
2162 }
2163 if (overwriting_accessor) {
2164 return Map::Normalize(isolate, map, mode,
2165 "AccessorsOverwritingAccessors");
2166 }
2167
2168 pair = AccessorPair::Copy(isolate, Cast<AccessorPair>(maybe_pair));
2169 } else if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors ||
2170 map->TooManyFastProperties(StoreOrigin::kNamed)) {
2171 return Map::Normalize(isolate, map, CLEAR_INOBJECT_PROPERTIES,
2172 "TooManyAccessors");
2173 } else {
2174 pair = isolate->factory()->NewAccessorPair();
2175 }
2176
2177 pair->SetComponents(*getter, *setter);
2178
2179 // Do not track transitions during bootstrapping.
2180 TransitionFlag flag =
2181 isolate->bootstrapper()->IsActive() ? OMIT_TRANSITION : INSERT_TRANSITION;
2182 Descriptor d = Descriptor::AccessorConstant(name, pair, attributes);
2183 return Map::CopyInsertDescriptor(isolate, map, &d, flag);
2184}
2185
2187 Descriptor* descriptor,
2188 TransitionFlag flag) {
2189 DirectHandle<DescriptorArray> descriptors(map->instance_descriptors(isolate),
2190 isolate);
2191
2192 // Share descriptors only if map owns descriptors and is not an initial map.
2193 if (flag == INSERT_TRANSITION && map->owns_descriptors() &&
2194 !IsUndefined(map->GetBackPointer(), isolate) &&
2196 return ShareDescriptor(isolate, map, descriptors, descriptor);
2197 }
2198
2199 int nof = map->NumberOfOwnDescriptors();
2200 DirectHandle<DescriptorArray> new_descriptors =
2201 DescriptorArray::CopyUpTo(isolate, descriptors, nof, 1);
2202 new_descriptors->Append(descriptor);
2203
2204 return CopyReplaceDescriptors(isolate, map, new_descriptors, flag,
2205 descriptor->GetKey(), "CopyAddDescriptor",
2207}
2208
2210 Descriptor* descriptor,
2211 TransitionFlag flag) {
2212 DirectHandle<DescriptorArray> old_descriptors(
2213 map->instance_descriptors(isolate), isolate);
2214
2215 // We replace the key if it is already present.
2216 InternalIndex index =
2217 old_descriptors->SearchWithCache(isolate, *descriptor->GetKey(), *map);
2218 if (index.is_found()) {
2219 return CopyReplaceDescriptor(isolate, map, old_descriptors, descriptor,
2220 index, flag);
2221 }
2222 return CopyAddDescriptor(isolate, map, descriptor, flag);
2223}
2224
2226 Isolate* isolate, DirectHandle<Map> map,
2227 DirectHandle<DescriptorArray> descriptors, Descriptor* descriptor,
2228 InternalIndex insertion_index, TransitionFlag flag) {
2229 DirectHandle<Name> key = descriptor->GetKey();
2230 DCHECK_EQ(*key, descriptors->GetKey(insertion_index));
2231 // This function does not support replacing property fields as
2232 // that would break property field counters.
2235 descriptors->GetDetails(insertion_index).location());
2236
2238 isolate, descriptors, map->NumberOfOwnDescriptors());
2239
2240 new_descriptors->Replace(insertion_index, descriptor);
2241
2242 TransitionKindFlag simple_flag =
2243 (insertion_index.as_int() == descriptors->number_of_descriptors() - 1)
2246 return CopyReplaceDescriptors(isolate, map, new_descriptors, flag, key,
2247 "CopyReplaceDescriptor", simple_flag);
2248}
2249
2250int Map::Hash(Isolate* isolate, Tagged<HeapObject> prototype) {
2251 // For performance reasons we only hash the 2 most variable fields of a map:
2252 // prototype and bit_field2.
2253
2254 int prototype_hash;
2255 if (IsNull(prototype)) {
2256 // No identity hash for null, so just pick a random number.
2257 prototype_hash = 1;
2258 } else {
2260 prototype_hash = receiver->GetOrCreateIdentityHash(isolate).value();
2261 }
2262
2263 return prototype_hash ^ bit_field2();
2264}
2265
2266namespace {
2267
2268bool CheckEquivalentModuloProto(const Tagged<Map> first,
2269 const Tagged<Map> second) {
2270 return first->GetConstructorRaw() == second->GetConstructorRaw() &&
2271 first->instance_type() == second->instance_type() &&
2272 first->bit_field() == second->bit_field() &&
2273 first->is_extensible() == second->is_extensible() &&
2274 first->new_target_is_base() == second->new_target_is_base();
2275}
2276
2277} // namespace
2278
2280 const Tagged<Map> other, ConcurrencyMode cmode,
2281 DirectHandle<HeapObject> new_prototype) const {
2282 CHECK_EQ(GetConstructor(), other->GetConstructor());
2283 CHECK_EQ(instance_type(), other->instance_type());
2284
2285 if (bit_field() != other->bit_field()) return false;
2286 if (new_prototype.is_null()) {
2287 if (prototype() != other->prototype()) return false;
2288 } else {
2289 if (*new_prototype != other->prototype()) return false;
2290 }
2291 if (new_target_is_base() != other->new_target_is_base()) return false;
2292 if (InstanceTypeChecker::IsJSFunction(instance_type())) {
2293 // JSFunctions require more checks to ensure that sloppy function is
2294 // not equivalent to strict function.
2295 int nof =
2296 std::min(NumberOfOwnDescriptors(), other->NumberOfOwnDescriptors());
2297 Tagged<DescriptorArray> this_descriptors =
2300 Tagged<DescriptorArray> that_descriptors =
2301 IsConcurrent(cmode) ? other->instance_descriptors(kAcquireLoad)
2302 : other->instance_descriptors();
2303 return this_descriptors->IsEqualUpTo(that_descriptors, nof);
2304 }
2305 return true;
2306}
2307
2309 ConcurrencyMode cmode) const {
2310 if (!EquivalentToForTransition(other, cmode)) {
2311 return false;
2312 }
2313#ifdef DEBUG
2314 // Ensure that we don't try to generate elements kind transitions from maps
2315 // with fields that may be generalized in-place. This must already be handled
2316 // during addition of a new field.
2317 Tagged<DescriptorArray> descriptors = IsConcurrent(cmode)
2321 PropertyDetails details = descriptors->GetDetails(i);
2322 if (details.location() == PropertyLocation::kField) {
2324 descriptors->GetFieldType(i)));
2325 }
2326 }
2327#endif
2328 return true;
2329}
2330
2332 ElementsKind elements_kind,
2333 Tagged<HeapObject> other_prototype,
2334 PropertyNormalizationMode mode) const {
2335 int properties =
2336 mode == CLEAR_INOBJECT_PROPERTIES ? 0 : other->GetInObjectProperties();
2337 // Make sure the elements_kind bits are in bit_field2.
2338 DCHECK_EQ(this->elements_kind(),
2339 Map::Bits2::ElementsKindBits::decode(bit_field2()));
2340 int adjusted_other_bit_field2 =
2341 Map::Bits2::ElementsKindBits::update(other->bit_field2(), elements_kind);
2342 return CheckEquivalentModuloProto(*this, other) &&
2343 prototype() == other_prototype &&
2344 bit_field2() == adjusted_other_bit_field2 &&
2345 GetInObjectProperties() == properties &&
2348}
2349
2351 // Has to be an initial map.
2352 DCHECK(IsUndefined(GetBackPointer(), isolate));
2353
2354 int slack = UnusedPropertyFields();
2355 TransitionsAccessor transitions(isolate, *this);
2357 slack = std::min(slack, map->UnusedPropertyFields());
2358 };
2359 transitions.TraverseTransitionTree(callback);
2360 return slack;
2361}
2362
2364 Tagged<DescriptorArray> descriptors,
2365 int number_of_own_descriptors,
2366 WriteBarrierMode barrier_mode) {
2368 HeapLayout::InReadOnlySpace(descriptors));
2369 set_instance_descriptors(descriptors, kReleaseStore, barrier_mode);
2370 SetNumberOfOwnDescriptors(number_of_own_descriptors);
2371#ifndef V8_DISABLE_WRITE_BARRIERS
2372 WriteBarrier::ForDescriptorArray(descriptors, number_of_own_descriptors);
2373#endif
2374}
2375
2376// static
2378 DirectHandle<JSObject> prototype, Isolate* isolate) {
2380 {
2381 Tagged<PrototypeInfo> prototype_info;
2382 if (prototype->map()->TryGetPrototypeInfo(&prototype_info)) {
2383 return direct_handle(prototype_info, isolate);
2384 }
2385 }
2386 DirectHandle<PrototypeInfo> proto_info =
2387 isolate->factory()->NewPrototypeInfo();
2388 prototype->map()->set_prototype_info(*proto_info, kReleaseStore);
2389 return proto_info;
2390}
2391
2392// static
2394 DirectHandle<Map> prototype_map, Isolate* isolate) {
2395 {
2396 Tagged<Object> maybe_proto_info = prototype_map->prototype_info();
2397 if (PrototypeInfo::IsPrototypeInfoFast(maybe_proto_info)) {
2398 return direct_handle(Cast<PrototypeInfo>(maybe_proto_info), isolate);
2399 }
2400 }
2401 DirectHandle<PrototypeInfo> proto_info =
2402 isolate->factory()->NewPrototypeInfo();
2403 prototype_map->set_prototype_info(*proto_info, kReleaseStore);
2404 return proto_info;
2405}
2406
2407// static
2409 Isolate* isolate) {
2410 DCHECK(map->is_prototype_map());
2411 if (value == false && !map->has_prototype_info()) {
2412 // "False" is the implicit default value, so there's nothing to do.
2413 return;
2414 }
2415 GetOrCreatePrototypeInfo(map, isolate)->set_should_be_fast_map(value);
2416}
2417
2418// static
2420 DirectHandle<Map> map, Isolate* isolate) {
2421 DirectHandle<Object> maybe_prototype;
2422 if (IsJSGlobalObjectMap(*map)) {
2423 DCHECK(map->is_prototype_map());
2424 // Global object is prototype of a global proxy and therefore we can
2425 // use its validity cell for guarding global object's prototype change.
2426 maybe_prototype = isolate->global_object();
2427 } else {
2428 maybe_prototype = direct_handle(
2429 map->GetPrototypeChainRootMap(isolate)->prototype(), isolate);
2430 }
2431 if (!IsJSObjectThatCanBeTrackedAsPrototype(*maybe_prototype)) {
2432 return handle(Map::kPrototypeChainValidSmi, isolate);
2433 }
2434 auto prototype = Cast<JSObject>(maybe_prototype);
2435 // Ensure the prototype is registered with its own prototypes so its cell
2436 // will be invalidated when necessary.
2437 JSObject::LazyRegisterPrototypeUser(direct_handle(prototype->map(), isolate),
2438 isolate);
2439
2440 Tagged<Object> maybe_cell =
2441 prototype->map()->prototype_validity_cell(kRelaxedLoad);
2442 // Return existing cell if it's still valid.
2443 if (IsCell(maybe_cell)) {
2444 Tagged<Cell> cell = Cast<Cell>(maybe_cell);
2445 if (cell->value() == Map::kPrototypeChainValidSmi) {
2446 return handle(cell, isolate);
2447 }
2448 }
2449 // Otherwise create a new cell.
2450 Handle<Cell> cell = isolate->factory()->NewCell(Map::kPrototypeChainValidSmi);
2451 prototype->map()->set_prototype_validity_cell(*cell, kRelaxedStore);
2452 return cell;
2453}
2454
2455// static
2457 DCHECK(map->is_prototype_map());
2458 Tagged<Object> maybe_cell = map->prototype_validity_cell(kRelaxedLoad);
2459 if (IsCell(maybe_cell)) {
2460 Tagged<Cell> cell = Cast<Cell>(maybe_cell);
2461 return cell->value() != Map::kPrototypeChainValidSmi;
2462 }
2463 return true;
2464}
2465
2466// static
2468 DirectHandle<JSPrototype> prototype,
2469 bool enable_prototype_setup_mode) {
2470 RCS_SCOPE(isolate, RuntimeCallCounterId::kMap_SetPrototype);
2471
2472 if (IsJSObjectThatCanBeTrackedAsPrototype(*prototype)) {
2473 DirectHandle<JSObject> prototype_jsobj = Cast<JSObject>(prototype);
2474 JSObject::OptimizeAsPrototype(prototype_jsobj, enable_prototype_setup_mode);
2475 } else {
2476 DCHECK(IsNull(*prototype, isolate) || IsJSProxy(*prototype) ||
2477 IsWasmObject(*prototype) ||
2479 }
2480
2481 WriteBarrierMode wb_mode =
2482 IsNull(*prototype, isolate) ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER;
2483 map->set_prototype(*prototype, wb_mode);
2484}
2485
2488 if (UnusedPropertyFields() == 0) return;
2489 set_construction_counter(Map::kSlackTrackingCounterStart);
2490}
2491
2493 Isolate* isolate, DirectHandle<Map> map,
2494 DirectHandle<JSPrototype> prototype) {
2495 DCHECK(IsUndefined(map->GetBackPointer()));
2496 Handle<Map> new_map = TransitionToUpdatePrototype(isolate, map, prototype);
2497 if (new_map->GetBackPointer() != *map &&
2498 map->IsInobjectSlackTrackingInProgress()) {
2499 // Advance the construction count on the base map to keep it in sync with
2500 // the transitioned map.
2501 map->InobjectSlackTrackingStep(isolate);
2502 }
2503 return new_map;
2504}
2505
2507 Isolate* isolate, DirectHandle<Map> map,
2508 DirectHandle<JSPrototype> prototype) {
2509 Handle<Map> new_map;
2510 DCHECK_IMPLIES(v8_flags.move_prototype_transitions_first,
2511 IsUndefined(map->GetBackPointer()));
2513 isolate, *map, *prototype)) {
2514 new_map = handle(*maybe_map, isolate);
2515 } else {
2516 new_map = CopyForPrototypeTransition(isolate, map, prototype);
2517 if (!map->IsDetached(isolate)) {
2518 TransitionsAccessor::PutPrototypeTransition(isolate, map, prototype,
2519 new_map);
2520 }
2521 }
2522 DCHECK_IMPLIES(map->IsInobjectSlackTrackingInProgress(),
2523 new_map->IsInobjectSlackTrackingInProgress());
2524 CHECK_IMPLIES(map->IsInobjectSlackTrackingInProgress(),
2525 map->construction_counter() <= new_map->construction_counter());
2526 return new_map;
2527}
2528
2531 isolate->factory()->NewWeakFixedArray(kEntries, AllocationType::kOld));
2532 return Cast<NormalizedMapCache>(array);
2533}
2534
2536 DirectHandle<Map> fast_map,
2537 ElementsKind elements_kind,
2538 Tagged<HeapObject> prototype,
2541 Tagged<MaybeObject> value =
2542 WeakFixedArray::get(GetIndex(isolate, *fast_map, *prototype));
2543 Tagged<HeapObject> heap_object;
2544 if (!value.GetHeapObjectIfWeak(&heap_object)) {
2545 return MaybeHandle<Map>();
2546 }
2547
2548 Tagged<Map> normalized_map = Cast<Map>(heap_object);
2549 CHECK(normalized_map->is_dictionary_map());
2550 if (!normalized_map->EquivalentToForNormalization(*fast_map, elements_kind,
2551 prototype, mode)) {
2552 return MaybeHandle<Map>();
2553 }
2554 return handle(normalized_map, isolate);
2555}
2556
2558 DirectHandle<Map> normalized_map) {
2560 DCHECK(normalized_map->is_dictionary_map());
2561 WeakFixedArray::set(GetIndex(isolate, *fast_map, normalized_map->prototype()),
2562 MakeWeak(*normalized_map));
2563}
2564
2565} // namespace v8::internal
Builtins::Kind kind
Definition builtins.cc:40
PropertyT * getter
#define SLOW_DCHECK(condition)
Definition checks.h:21
constexpr T * begin() const
Definition vector.h:96
static NEVER_READ_ONLY_SPACE DirectHandle< AccessorPair > Copy(Isolate *isolate, DirectHandle< AccessorPair > pair)
Definition objects.cc:4004
static int ArrayMapIndex(ElementsKind elements_kind)
Definition contexts.h:676
static void DeoptimizeDependencyGroups(Isolate *isolate, ObjectT object, DependencyGroups groups)
static DirectHandle< DescriptorArray > CopyUpToAddAttributes(Isolate *isolate, DirectHandle< DescriptorArray > desc, int enumeration_index, PropertyAttributes attributes, int slack=0)
Definition objects.cc:3711
static V8_EXPORT_PRIVATE Handle< DescriptorArray > Allocate(IsolateT *isolate, int nof_descriptors, int slack, AllocationType allocation=AllocationType::kYoung)
static DirectHandle< DescriptorArray > CopyUpTo(Isolate *isolate, DirectHandle< DescriptorArray > desc, int enumeration_index, int slack=0)
Definition objects.cc:3704
static Descriptor DataField(Isolate *isolate, DirectHandle< Name > key, int field_index, PropertyAttributes attributes, Representation representation)
Definition property.cc:81
DirectHandle< Name > GetKey() const
Definition property.h:29
static Descriptor AccessorConstant(DirectHandle< Name > key, DirectHandle< Object > foreign, PropertyAttributes attributes)
Definition property.cc:118
PropertyDetails GetDetails() const
Definition property.h:31
V8_INLINE bool is_null() const
Definition handles.h:693
V8_INLINE Address address() const
Definition handles.h:695
static Tagged< Map > AsClass(Tagged< FieldType > type)
Definition field-type.cc:51
static V8_EXPORT_PRIVATE Tagged< FieldType > Any()
Definition field-type.cc:22
static bool NowContains(Tagged< FieldType > type, Tagged< Object > value)
static bool NowIs(Tagged< FieldType > type, Tagged< FieldType > other)
Definition field-type.cc:68
V8_INLINE Address address() const
Definition handles.h:73
static V8_INLINE bool InWritableSharedSpace(Tagged< HeapObject > object)
static V8_INLINE bool InReadOnlySpace(Tagged< HeapObject > object)
constexpr int as_int() const
static void SetInitialMap(Isolate *isolate, DirectHandle< JSFunction > function, DirectHandle< Map > map, DirectHandle< JSPrototype > prototype)
static const int kMaxInObjectProperties
Definition js-objects.h:959
static void OptimizeAsPrototype(DirectHandle< JSObject > object, bool enable_setup_mode=true)
int GetEmbedderFieldCount() const
static void LazyRegisterPrototypeUser(DirectHandle< Map > user, Isolate *isolate)
DirectHandle< Map > ReconfigureElementsKind(ElementsKind elements_kind)
static std::optional< Tagged< Map > > TryUpdateNoLock(Isolate *isolate, Tagged< Map > old_map, ConcurrencyMode cmode) V8_WARN_UNUSED_RESULT
static Handle< Map > CopyForElementsTransition(Isolate *isolate, DirectHandle< Map > map)
Definition map.cc:1775
static V8_EXPORT_PRIVATE Handle< Map > Create(Isolate *isolate, int inobject_properties)
Definition map.cc:1824
static bool IsPrototypeChainInvalidated(Tagged< Map > map)
Definition map.cc:2456
int NumberOfEnumerableProperties() const
Definition map.cc:1177
InternalIndex::Range IterateOwnDescriptors() const
Definition map-inl.h:245
static std::optional< Tagged< JSFunction > > GetConstructorFunction(Tagged< Map > map, Tagged< Context > native_context)
Definition map.cc:53
int NumberOfFields(ConcurrencyMode cmode) const
Definition map.cc:610
static DirectHandle< PrototypeInfo > GetOrCreatePrototypeInfo(DirectHandle< Map > prototype_map, Isolate *isolate)
Definition map.cc:2377
static V8_EXPORT_PRIVATE Handle< Map > TransitionToUpdatePrototype(Isolate *isolate, DirectHandle< Map > map, DirectHandle< JSPrototype > prototype)
Definition map.cc:2506
static V8_EXPORT_PRIVATE void EnsureDescriptorSlack(Isolate *isolate, DirectHandle< Map > map, int slack)
Definition map.cc:850
bool EquivalentToForTransition(const Tagged< Map > other, ConcurrencyMode cmode, DirectHandle< HeapObject > new_prototype={}) const
Definition map.cc:2279
static constexpr Tagged< Smi > kPrototypeChainValidSmi
Definition map.h:519
static Handle< Map > CopyForPrototypeTransition(Isolate *isolate, DirectHandle< Map > map, DirectHandle< JSPrototype > prototype)
Definition map.cc:1800
V8_EXPORT_PRIVATE static V8_WARN_UNUSED_RESULT MaybeHandle< Map > CopyWithConstant(Isolate *isolate, DirectHandle< Map > map, DirectHandle< Name > name, DirectHandle< Object > constant, PropertyAttributes attributes, TransitionFlag flag)
Definition map.cc:541
static V8_EXPORT_PRIVATE Handle< Map > CopyInsertDescriptor(Isolate *isolate, DirectHandle< Map > map, Descriptor *descriptor, TransitionFlag flag)
Definition map.cc:2209
static DirectHandle< Map > GetObjectCreateMap(Isolate *isolate, DirectHandle< JSPrototype > prototype)
Definition map.cc:903
static const int kSlackTrackingCounterStart
Definition map.h:347
static const int kNoSlackTracking
Definition map.h:349
static Handle< Map > CopyDropDescriptors(Isolate *isolate, DirectHandle< Map > map)
Definition map.cc:1480
static void SetShouldBeFastPrototypeMap(DirectHandle< Map > map, bool value, Isolate *isolate)
Definition map.cc:2408
static Handle< UnionOf< Smi, Cell > > GetOrCreatePrototypeChainValidityCell(DirectHandle< Map > map, Isolate *isolate)
Definition map.cc:2419
static Handle< Map > Copy(Isolate *isolate, DirectHandle< Map > map, const char *reason, TransitionKindFlag kind=SPECIAL_TRANSITION)
Definition map.cc:1811
bool IsDetached(Isolate *isolate) const
Definition map-inl.h:173
bool IsInobjectSlackTrackingInProgress() const
Definition map-inl.h:1014
bool EquivalentToForNormalization(const Tagged< Map > other, ElementsKind elements_kind, Tagged< HeapObject > prototype, PropertyNormalizationMode mode) const
Definition map.cc:2331
static V8_EXPORT_PRIVATE DirectHandle< Map > TransitionToDataProperty(Isolate *isolate, DirectHandle< Map > map, DirectHandle< Name > name, DirectHandle< Object > value, PropertyAttributes attributes, PropertyConstness constness, StoreOrigin store_origin)
Definition map.cc:1987
static void InstallDescriptors(Isolate *isolate, DirectHandle< Map > parent_map, DirectHandle< Map > child_map, InternalIndex new_descriptor, DirectHandle< DescriptorArray > descriptors, bool force_connect=false)
Definition map.cc:1664
static DirectHandle< Map > AsLanguageMode(Isolate *isolate, DirectHandle< Map > initial_map, DirectHandle< SharedFunctionInfo > shared_info)
Definition map.cc:1734
static V8_EXPORT_PRIVATE MaybeHandle< Map > TryUpdate(Isolate *isolate, Handle< Map > map) V8_WARN_UNUSED_RESULT
Definition map.cc:751
static MaybeObjectDirectHandle WrapFieldType(DirectHandle< FieldType > type)
Definition map.cc:487
static V8_EXPORT_PRIVATE DirectHandle< Map > PrepareForDataProperty(Isolate *isolate, DirectHandle< Map > old_map, InternalIndex descriptor_number, PropertyConstness constness, DirectHandle< Object > value)
Definition map.cc:1975
void StartInobjectSlackTracking()
Definition map.cc:2486
Tagged< Map > LookupElementsTransitionMap(Isolate *isolate, ElementsKind elements_kind, ConcurrencyMode cmode)
Definition map.cc:1047
V8_EXPORT_PRIVATE Tagged< Map > FindRootMap(PtrComprCageBase cage_base) const
Definition map.cc:699
static V8_EXPORT_PRIVATE Handle< Map > TransitionRootMapToPrototypeForNewObject(Isolate *isolate, DirectHandle< Map > map, DirectHandle< JSPrototype > prototype)
Definition map.cc:2492
static void ConnectTransition(Isolate *isolate, DirectHandle< Map > parent, DirectHandle< Map > child, DirectHandle< Name > name, TransitionKindFlag transition_kind, bool force_connect=false)
Definition map.cc:1534
void SetNumberOfOwnDescriptors(int number)
Definition map-inl.h:237
bool IsMapInArrayPrototypeChain(Isolate *isolate) const
Definition map.cc:1056
FieldCounts GetFieldCounts() const
Definition map.cc:622
static bool IsMostGeneralFieldType(Representation representation, Tagged< FieldType > field_type)
Definition map-inl.h:157
Tagged< Map > GetPrototypeChainRootMap(Isolate *isolate) const
Definition map.cc:37
int GetInObjectProperties() const
Definition map-inl.h:341
bool OnlyHasSimpleProperties() const
Definition map.cc:1202
void ReplaceDescriptors(Isolate *isolate, Tagged< DescriptorArray > new_descriptors)
Definition map.cc:668
static Handle< Map > CopyAsElementsKind(Isolate *isolate, DirectHandle< Map > map, ElementsKind kind, TransitionFlag flag)
Definition map.cc:1688
static Handle< Map > CopyAddDescriptor(Isolate *isolate, DirectHandle< Map > map, Descriptor *descriptor, TransitionFlag flag)
Definition map.cc:2186
void DeprecateTransitionTree(Isolate *isolate)
Definition map.cc:642
static V8_EXPORT_PRIVATE void SetPrototype(Isolate *isolate, DirectHandle< Map > map, DirectHandle< JSPrototype > prototype, bool enable_prototype_setup_mode=true)
Definition map.cc:2467
int ComputeMinObjectSlack(Isolate *isolate)
Definition map.cc:2350
bool ShouldCheckForReadOnlyElementsInPrototypeChain(Isolate *isolate)
Definition map.cc:1209
V8_EXPORT_PRIVATE void SetInstanceDescriptors(Isolate *isolate, Tagged< DescriptorArray > descriptors, int number_of_own_descriptors, WriteBarrierMode barrier_mode=UPDATE_WRITE_BARRIER)
Definition map.cc:2363
bool EquivalentToForElementsKindTransition(const Tagged< Map > other, ConcurrencyMode cmode) const
Definition map.cc:2308
V8_EXPORT_PRIVATE Tagged< Map > FindElementsKindTransitionedMap(Isolate *isolate, MapHandlesSpan candidates, ConcurrencyMode cmode)
Definition map.cc:982
static V8_EXPORT_PRIVATE Handle< Map > Normalize(Isolate *isolate, DirectHandle< Map > map, ElementsKind new_elements_kind, DirectHandle< JSPrototype > new_prototype, PropertyNormalizationMode mode, bool use_cache, const char *reason)
Definition map.cc:1282
int Hash(Isolate *isolate, Tagged< HeapObject > prototype)
Definition map.cc:2250
Tagged< UnionOf< Smi, MaybeWeak< Map >, TransitionArray > > Isolate * isolate
Definition map.h:502
static V8_EXPORT_PRIVATE DirectHandle< Map > Update(Isolate *isolate, DirectHandle< Map > map)
Definition map.cc:839
static std::optional< Tagged< Map > > TryAsElementsKind(Isolate *isolate, DirectHandle< Map > map, ElementsKind kind, ConcurrencyMode cmode)
Definition map.cc:1152
static V8_EXPORT_PRIVATE Tagged< FieldType > UnwrapFieldType(Tagged< MaybeObject > wrapped_type)
Definition map.cc:495
static V8_EXPORT_PRIVATE Handle< Map > CopyForPreventExtensions(Isolate *isolate, DirectHandle< Map > map, PropertyAttributes attrs_to_add, DirectHandle< Symbol > transition_marker, const char *reason, bool old_map_is_dictionary_elements_kind=false)
Definition map.cc:1852
static Handle< Map > GetDerivedMap(Isolate *isolate, DirectHandle< Map > from, DirectHandle< JSReceiver > prototype)
Definition map.cc:934
static Handle< Map > CopyReplaceDescriptors(Isolate *isolate, DirectHandle< Map > map, DirectHandle< DescriptorArray > descriptors, TransitionFlag flag, MaybeDirectHandle< Name > maybe_name, const char *reason, TransitionKindFlag transition_kind)
Definition map.cc:1564
static void GeneralizeIfCanHaveTransitionableFastElementsKind(Isolate *isolate, InstanceType instance_type, Representation *representation, DirectHandle< FieldType > *field_type)
Definition map-inl.h:180
static V8_EXPORT_PRIVATE VisitorId GetVisitorId(Tagged< Map > map)
Definition map.cc:65
static V8_EXPORT_PRIVATE Handle< Map > AsElementsKind(Isolate *isolate, DirectHandle< Map > map, ElementsKind kind)
Definition map.cc:1163
static V8_EXPORT_PRIVATE Handle< Map > AddMissingTransitions(Isolate *isolate, DirectHandle< Map > map, DirectHandle< DescriptorArray > descriptors)
Definition map.cc:1618
int NumberOfOwnDescriptors() const
Definition map-inl.h:232
static Handle< Map > CopyReplaceDescriptor(Isolate *isolate, DirectHandle< Map > map, DirectHandle< DescriptorArray > descriptors, Descriptor *descriptor, InternalIndex index, TransitionFlag flag)
Definition map.cc:2225
static int SlackForArraySize(int old_size, int size_limit)
Definition map-inl.h:1030
static Handle< Map > ShareDescriptor(Isolate *isolate, DirectHandle< Map > map, DirectHandle< DescriptorArray > descriptors, Descriptor *descriptor)
Definition map.cc:1493
static Handle< Map > RawCopy(Isolate *isolate, DirectHandle< Map > map, int instance_size, int inobject_properties)
Definition map.cc:1246
int GetConstructorFunctionIndex() const
Definition map-inl.h:346
V8_EXPORT_PRIVATE Tagged< Map > FindFieldOwner(PtrComprCageBase cage_base, InternalIndex descriptor) const
Definition map.cc:716
static Handle< Map > CopyNormalized(Isolate *isolate, DirectHandle< Map > map, PropertyNormalizationMode mode)
Definition map.cc:1378
static DirectHandle< Map > TransitionElementsTo(Isolate *isolate, DirectHandle< Map > map, ElementsKind to_kind)
Definition map.cc:1068
static DirectHandle< Map > CopyInitialMapNormalized(Isolate *isolate, DirectHandle< Map > map, PropertyNormalizationMode mode=CLEAR_INOBJECT_PROPERTIES)
Definition map.cc:1448
V8_EXPORT_PRIVATE static V8_WARN_UNUSED_RESULT MaybeHandle< Map > CopyWithField(Isolate *isolate, DirectHandle< Map > map, DirectHandle< Name > name, DirectHandle< FieldType > type, PropertyAttributes attributes, PropertyConstness constness, Representation representation, TransitionFlag flag)
Definition map.cc:504
Tagged< Map > TryReplayPropertyTransitions(Isolate *isolate, Tagged< Map > map, ConcurrencyMode cmode)
Definition map.cc:773
bool InstancesNeedRewriting(Tagged< Map > target, ConcurrencyMode cmode) const
Definition map.cc:559
bool CanBeDeprecated() const
Definition map-inl.h:709
int UnusedPropertyFields() const
Definition map-inl.h:384
static DirectHandle< Map > TransitionToImmutableProto(Isolate *isolate, DirectHandle< Map > map)
Definition map.cc:1413
int NextFreePropertyIndex() const
Definition map.cc:1189
static V8_EXPORT_PRIVATE DirectHandle< Map > TransitionToAccessorProperty(Isolate *isolate, DirectHandle< Map > map, DirectHandle< Name > name, InternalIndex descriptor, DirectHandle< Object > getter, DirectHandle< Object > setter, PropertyAttributes attributes)
Definition map.cc:2072
static const int kNoConstructorFunctionIndex
Definition map.h:257
static Handle< Map > CopyInitialMap(Isolate *isolate, DirectHandle< Map > map)
Definition map-inl.h:1008
void NotifyLeafMapLayoutChange(Isolate *isolate)
Definition map-inl.h:721
V8_INLINE DirectHandle< T > ToHandleChecked() const
V8_WARN_UNUSED_RESULT V8_INLINE bool ToHandle(DirectHandle< S > *out) const
V8_INLINE bool is_null() const
V8_WARN_UNUSED_RESULT V8_INLINE bool ToHandle(Handle< S > *out) const
static MaybeObjectDirectHandle Weak(Tagged< Object > object, Isolate *isolate)
static int GetIndex(Isolate *isolate, Tagged< Map > map, Tagged< HeapObject > prototype)
Definition map-inl.h:1046
void Set(Isolate *isolate, DirectHandle< Map > fast_map, DirectHandle< Map > normalized_map)
Definition map.cc:2557
static const int kEntries
Definition map.h:1098
V8_WARN_UNUSED_RESULT MaybeHandle< Map > Get(Isolate *isolate, DirectHandle< Map > fast_map, ElementsKind elements_kind, Tagged< HeapObject > prototype, PropertyNormalizationMode mode)
Definition map.cc:2535
static NEVER_READ_ONLY_SPACE DirectHandle< NormalizedMapCache > New(Isolate *isolate)
Definition map.cc:2529
static DirectHandle< FieldType > OptimalType(Tagged< Object > obj, Isolate *isolate, Representation representation)
Definition objects.cc:224
static Representation OptimalRepresentation(Tagged< Object > obj, PtrComprCageBase cage_base)
static bool FilterKey(Tagged< Object > obj, PropertyFilter filter)
static bool FitsRepresentation(Tagged< Object > obj, Representation representation, bool allow_coercion=true)
PropertyAttributes attributes() const
PropertyLocation location() const
Representation representation() const
PropertyConstness constness() const
static void AddDerivedMap(DirectHandle< PrototypeInfo > info, DirectHandle< Map > to, Isolate *isolate)
static void SetObjectCreateMap(DirectHandle< PrototypeInfo > info, DirectHandle< Map > map, Isolate *isolate)
static bool IsPrototypeInfoFast(Tagged< Object > object)
bool fits_into(const Representation &other) const
static constexpr Representation Tagged()
static constexpr Tagged< Smi > zero()
Definition smi.h:99
void set(int index, Tagged< ElementT > value, WriteBarrierMode mode=kDefaultMode)
constexpr bool IsCleared() const
bool GetHeapObjectIfWeak(Tagged< HeapObject > *result) const
V8_INLINE constexpr bool is_null() const
Definition tagged.h:502
static bool CanHaveMoreTransitions(Isolate *isolate, DirectHandle< Map > map)
static std::optional< Tagged< Map > > GetPrototypeTransition(Isolate *isolate, Tagged< Map > map, Tagged< Object > prototype)
Tagged< Map > SearchTransition(Tagged< Name > name, PropertyKind kind, PropertyAttributes attributes)
static bool PutPrototypeTransition(Isolate *isolate, DirectHandle< Map >, DirectHandle< Object > prototype, DirectHandle< Map > target_map)
static void SetMigrationTarget(Isolate *isolate, DirectHandle< Map > map, Tagged< Map > migration_target)
std::function< void(Tagged< Map >)> TraverseCallback
static void Insert(Isolate *isolate, DirectHandle< Map > map, DirectHandle< Name > name, DirectHandle< Map > target, TransitionKindFlag flag)
Definition transitions.h:85
Tagged< Map > SearchSpecial(Tagged< Symbol > name)
static void ForDescriptorArray(Tagged< DescriptorArray >, int number_of_own_descriptors)
#define COMPRESS_POINTERS_BOOL
Definition globals.h:99
ZoneVector< OpIndex > candidates
LineAndColumn current
#define TYPED_ARRAYS(V)
int32_t offset
TNode< Object > target
TNode< Object > receiver
TNode< Object > callback
std::map< const std::string, const std::string > map
double second
ZoneVector< RpoNumber > & result
#define LOG(isolate, Call)
Definition log.h:78
#define MAKE_TQ_CASE(TYPE, Name)
V8_INLINE const Operation & Get(const Graph &graph, OpIndex index)
Definition graph.h:1231
V8_INLINE IndirectHandle< T > handle(Tagged< T > object, Isolate *isolate)
Definition handles-inl.h:72
const uint32_t kStringEncodingMask
constexpr const char * ToString(DeoptimizeKind kind)
Definition globals.h:880
bool IsSlowArgumentsElementsKind(ElementsKind kind)
constexpr int kTaggedSize
Definition globals.h:542
bool IsPrimitiveMap(Tagged< Map > map)
Definition map-inl.h:754
@ SKIP_WRITE_BARRIER
Definition objects.h:52
@ UPDATE_WRITE_BARRIER
Definition objects.h:55
bool is_sloppy(LanguageMode language_mode)
Definition globals.h:773
constexpr bool IsHoleyElementsKind(ElementsKind kind)
static bool ContainsMap(MapHandlesSpan maps, Tagged< Map > map)
Definition map.cc:966
static Handle< Map > AddMissingElementsTransitions(Isolate *isolate, Handle< Map > map, ElementsKind to_kind)
Definition map.cc:1120
bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind, ElementsKind to_kind)
bool IsTransitionElementsKind(ElementsKind kind)
Map::Bits1::HasPrototypeSlotBit Map::Bits1::HasNamedInterceptorBit Map::Bits1::IsUndetectableBit Map::Bits1::IsConstructorBit bit_field2
Definition map-inl.h:123
@ INSERT_TRANSITION
Definition objects.h:66
@ OMIT_TRANSITION
Definition objects.h:66
bool IsCustomElementsReceiverMap(Tagged< Map > map)
bool IsTypedArrayElementsKind(ElementsKind kind)
ElementsKind GetPackedElementsKind(ElementsKind holey_kind)
bool IsSpecialReceiverMap(Tagged< Map > map)
@ HOLEY_NONEXTENSIBLE_ELEMENTS
@ SLOW_STRING_WRAPPER_ELEMENTS
@ PACKED_NONEXTENSIBLE_ELEMENTS
@ TERMINAL_FAST_ELEMENTS_KIND
@ SLOW_SLOPPY_ARGUMENTS_ELEMENTS
@ FAST_SLOPPY_ARGUMENTS_ELEMENTS
V8_INLINE DirectHandle< T > direct_handle(Tagged< T > object, Isolate *isolate)
too high values may cause the compiler to set high thresholds for inlining to as much as possible avoid inlined allocation of objects that cannot escape trace load stores from virtual maglev objects use TurboFan fast string builder analyze liveness of environment slots and zap dead values trace TurboFan load elimination emit data about basic block usage in builtins to this enable builtin reordering when run mksnapshot flag for emit warnings when applying builtin profile data verify register allocation in TurboFan randomly schedule instructions to stress dependency tracking enable store store elimination in TurboFan rewrite far to near simulate GC compiler thread race related to allow float parameters to be passed in simulator mode JS Wasm Run additional turbo_optimize_inlined_js_wasm_wrappers enable experimental feedback collection in generic lowering enable Turboshaft s WasmLoadElimination enable Turboshaft s low level load elimination for JS enable Turboshaft s escape analysis for string concatenation use enable Turbolev features that we want to ship in the not too far future trace individual Turboshaft reduction steps trace intermediate Turboshaft reduction steps invocation count threshold for early optimization Enables optimizations which favor memory size over execution speed Enables sampling allocation profiler with X as a sample interval min size of a semi the new space consists of two semi spaces max size of the Collect garbage after Collect garbage after keeps maps alive for< n > old space garbage collections print one detailed trace line in name
Definition flags.cc:2086
@ SIMPLE_PROPERTY_TRANSITION
Definition objects.h:73
@ PROPERTY_TRANSITION
Definition objects.h:74
@ PROTOTYPE_TRANSITION
Definition objects.h:75
@ SPECIAL_TRANSITION
Definition objects.h:76
return Cast< NumberDictionary >(elements(cage_base))
const uint32_t kOneByteStringTag
bool IsFastPackedElementsKind(ElementsKind kind)
static bool IsShortcutCandidate(int type)
static const int kInvalidEnumCacheSentinel
bool IsClass(Tagged< FieldType > obj)
Definition field-type.cc:48
instance_descriptors
Definition map-inl.h:52
DONT_OVERRIDE DISABLE_ALLOCATION_SITES HOLEY_ELEMENTS
Map::Bits1::HasPrototypeSlotBit Map::Bits1::HasNamedInterceptorBit Map::Bits1::IsUndetectableBit Map::Bits1::IsConstructorBit Map::Bits2::IsImmutablePrototypeBit is_deprecated
Definition map-inl.h:129
bool IsFrozenElementsKind(ElementsKind kind)
ElementsKind GetNextTransitionElementsKind(ElementsKind kind)
const uint32_t kStringRepresentationMask
bool IsJSObjectThatCanBeTrackedAsPrototype(Tagged< Object > obj)
Definition objects-inl.h:96
bool IsTerminalElementsKind(ElementsKind kind)
constexpr int kInt32Size
Definition globals.h:401
bool IsFastElementsKind(ElementsKind kind)
Tagged< MaybeWeak< T > > MakeWeak(Tagged< T > value)
Definition tagged.h:893
static const int kMaxNumberOfDescriptors
bool IsDictionaryElementsKind(ElementsKind kind)
V8_EXPORT_PRIVATE FlagValues v8_flags
bool IsAny(Tagged< FieldType > obj)
Definition field-type.h:51
bool IsUniqueName(Tagged< Name > obj)
V8_INLINE bool IsWasmObject(T obj, Isolate *=nullptr)
Definition objects.h:725
static bool HasElementsKind(MapHandlesSpan maps, ElementsKind elements_kind)
Definition map.cc:974
static Tagged< Map > FindClosestElementsTransition(Isolate *isolate, Tagged< Map > map, ElementsKind to_kind, ConcurrencyMode cmode)
Definition map.cc:1025
bool IsGeneralizableTo(PropertyLocation a, PropertyLocation b)
bool IsTypedArrayOrRabGsabTypedArrayElementsKind(ElementsKind kind)
bool IsStringWrapperElementsKind(ElementsKind kind)
@ ACCESSOR_GETTER
Definition objects.h:879
@ ACCESSOR_SETTER
Definition objects.h:879
bool IsTransitionableFastElementsKind(ElementsKind from_kind)
constructor_or_back_pointer
Definition map-inl.h:870
kInstanceDescriptorsOffset kTransitionsOrPrototypeInfoOffset IsNull(value)||IsJSProxy(value)||IsWasmObject(value)||(IsJSObject(value) &&(HeapLayout
Definition map-inl.h:70
@ kVisitorIdCount
Definition map.h:136
constexpr bool IsConcurrent(ConcurrencyMode mode)
Definition globals.h:2599
kInstanceDescriptorsOffset kTransitionsOrPrototypeInfoOffset prototype
Definition map-inl.h:69
static const size_t LanguageModeSize
Definition globals.h:753
!IsContextMap !IsContextMap native_context
Definition map-inl.h:877
PropertyNormalizationMode
Definition objects.h:60
@ KEEP_INOBJECT_PROPERTIES
Definition objects.h:62
@ CLEAR_INOBJECT_PROPERTIES
Definition objects.h:61
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Definition casting.h:150
static constexpr ReleaseStoreTag kReleaseStore
Definition globals.h:2910
static constexpr RelaxedLoadTag kRelaxedLoad
Definition globals.h:2909
static constexpr RelaxedStoreTag kRelaxedStore
Definition globals.h:2911
static constexpr AcquireLoadTag kAcquireLoad
Definition globals.h:2908
#define SIMPLE_HEAP_OBJECT_LIST2(V)
#define CONCRETE_TRUSTED_OBJECT_TYPE_LIST2(V)
#define RCS_SCOPE(...)
#define FATAL(...)
Definition logging.h:47
#define DCHECK_LE(v1, v2)
Definition logging.h:490
#define CHECK_IMPLIES(lhs, rhs)
#define CHECK(condition)
Definition logging.h:124
#define CHECK_LT(lhs, rhs)
#define DCHECK_IMPLIES(v1, v2)
Definition logging.h:493
#define DCHECK_NE(v1, v2)
Definition logging.h:486
#define CHECK_EQ(lhs, rhs)
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define TYPED_ARRAY_CONSTRUCTORS_SWITCH(Type, type, TYPE, Ctype)