1 // Copyright 2015 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.
10 #include "src/code-stubs.h"
11 #include "src/compilation-cache.h"
12 #include "src/execution.h"
13 #include "src/factory.h"
14 #include "src/global-handles.h"
15 #include "src/ic/stub-cache.h"
16 #include "src/macro-assembler.h"
17 #include "src/smart-pointers.h"
18 #include "test/cctest/cctest.h"
20 using namespace v8::internal;
23 // TODO(ishell): fix this once ReconfigureProperty supports "non equivalent"
25 const bool IS_NON_EQUIVALENT_TRANSITION_SUPPORTED = false;
28 // TODO(ishell): fix this once TransitionToPrototype stops generalizing
29 // all field representations (similar to crbug/448711 where elements kind
30 // and observed transitions caused generalization of all field representations).
31 const bool IS_PROTO_TRANS_ISSUE_FIXED = false;
34 // TODO(ishell): fix this once TransitionToAccessorProperty is able to always
35 // keep map in fast mode.
36 const bool IS_ACCESSOR_FIELD_SUPPORTED = false;
39 // Number of properties used in the tests.
40 const int kPropCount = 7;
47 static Handle<String> MakeString(const char* str) {
48 Isolate* isolate = CcTest::i_isolate();
49 Factory* factory = isolate->factory();
50 return factory->InternalizeUtf8String(str);
54 static Handle<String> MakeName(const char* str, int suffix) {
55 EmbeddedVector<char, 128> buffer;
56 SNPrintF(buffer, "%s%d", str, suffix);
57 return MakeString(buffer.start());
61 static Handle<AccessorPair> CreateAccessorPair(bool with_getter,
63 Isolate* isolate = CcTest::i_isolate();
64 Factory* factory = isolate->factory();
65 Handle<AccessorPair> pair = factory->NewAccessorPair();
66 Handle<String> empty_string = factory->empty_string();
68 Handle<JSFunction> func = factory->NewFunction(empty_string);
69 pair->set_getter(*func);
72 Handle<JSFunction> func = factory->NewFunction(empty_string);
73 pair->set_setter(*func);
79 static bool EqualDetails(DescriptorArray* descriptors, int descriptor,
80 PropertyType type, PropertyAttributes attributes,
81 Representation representation, int field_index = -1) {
82 PropertyDetails details = descriptors->GetDetails(descriptor);
83 if (details.type() != type) return false;
84 if (details.attributes() != attributes) return false;
85 if (!details.representation().Equals(representation)) return false;
86 if (field_index >= 0 && details.field_index() != field_index) return false;
92 static const int MAX_PROPERTIES = 10;
94 PropertyType types_[MAX_PROPERTIES];
95 PropertyAttributes attributes_[MAX_PROPERTIES];
96 Representation representations_[MAX_PROPERTIES];
97 // HeapType for kField, value for DATA_CONSTANT and getter for
99 Handle<Object> values_[MAX_PROPERTIES];
100 // Setter for ACCESSOR_CONSTANT.
101 Handle<Object> setter_values_[MAX_PROPERTIES];
102 int number_of_properties_;
105 explicit Expectations(Isolate* isolate)
106 : isolate_(isolate), number_of_properties_(0) {}
108 void Init(int index, PropertyType type, PropertyAttributes attributes,
109 Representation representation, Handle<Object> value) {
110 DCHECK(index < MAX_PROPERTIES);
111 types_[index] = type;
112 attributes_[index] = attributes;
113 representations_[index] = representation;
114 values_[index] = value;
119 os << "Expectations: #" << number_of_properties_ << "\n";
120 for (int i = 0; i < number_of_properties_; i++) {
121 os << " " << i << ": ";
122 os << "Descriptor @ ";
123 if (types_[i] == ACCESSOR_CONSTANT) {
124 os << "(get: " << Brief(*values_[i])
125 << ", set: " << Brief(*setter_values_[i]) << ") ";
127 os << Brief(*values_[i]);
138 case ACCESSOR_CONSTANT:
145 os << ": " << representations_[i].Mnemonic();
146 os << ", attrs: " << attributes_[i] << ")\n";
150 Handle<HeapType> GetFieldType(int index) {
151 CHECK(index < MAX_PROPERTIES);
152 CHECK(types_[index] == DATA || types_[index] == ACCESSOR);
153 return Handle<HeapType>::cast(values_[index]);
156 void SetDataField(int index, PropertyAttributes attrs,
157 Representation representation, Handle<HeapType> value) {
158 Init(index, DATA, attrs, representation, value);
161 void SetDataField(int index, Representation representation,
162 Handle<HeapType> value) {
163 SetDataField(index, attributes_[index], representation, value);
166 void SetAccessorField(int index, PropertyAttributes attrs) {
167 Init(index, ACCESSOR, attrs, Representation::Tagged(),
168 HeapType::Any(isolate_));
171 void SetAccessorField(int index) {
172 SetAccessorField(index, attributes_[index]);
175 void SetDataConstant(int index, PropertyAttributes attrs,
176 Handle<JSFunction> value) {
177 Init(index, DATA_CONSTANT, attrs, Representation::HeapObject(), value);
180 void SetDataConstant(int index, Handle<JSFunction> value) {
181 SetDataConstant(index, attributes_[index], value);
184 void SetAccessorConstant(int index, PropertyAttributes attrs,
185 Handle<Object> getter, Handle<Object> setter) {
186 Init(index, ACCESSOR_CONSTANT, attrs, Representation::Tagged(), getter);
187 setter_values_[index] = setter;
190 void SetAccessorConstantComponent(int index, PropertyAttributes attrs,
191 AccessorComponent component,
192 Handle<Object> accessor) {
193 CHECK_EQ(ACCESSOR_CONSTANT, types_[index]);
194 CHECK(index < number_of_properties_);
195 if (component == ACCESSOR_GETTER) {
196 values_[index] = accessor;
198 setter_values_[index] = accessor;
202 void SetAccessorConstant(int index, PropertyAttributes attrs,
203 Handle<AccessorPair> pair) {
204 Handle<Object> getter = handle(pair->getter(), isolate_);
205 Handle<Object> setter = handle(pair->setter(), isolate_);
206 SetAccessorConstant(index, attrs, getter, setter);
209 void SetAccessorConstant(int index, Handle<Object> getter,
210 Handle<Object> setter) {
211 SetAccessorConstant(index, attributes_[index], getter, setter);
214 void SetAccessorConstant(int index, Handle<AccessorPair> pair) {
215 Handle<Object> getter = handle(pair->getter(), isolate_);
216 Handle<Object> setter = handle(pair->setter(), isolate_);
217 SetAccessorConstant(index, getter, setter);
220 void GeneralizeRepresentation(int index) {
221 CHECK(index < number_of_properties_);
222 representations_[index] = Representation::Tagged();
223 if (types_[index] == DATA || types_[index] == ACCESSOR) {
224 values_[index] = HeapType::Any(isolate_);
229 bool Check(DescriptorArray* descriptors, int descriptor) const {
230 PropertyType type = types_[descriptor];
231 if (!EqualDetails(descriptors, descriptor, type, attributes_[descriptor],
232 representations_[descriptor])) {
235 Object* expected_value = *values_[descriptor];
236 Object* value = descriptors->GetValue(descriptor);
240 return HeapType::cast(expected_value)->Equals(HeapType::cast(value));
243 return value == expected_value;
245 case ACCESSOR_CONSTANT: {
246 if (value == expected_value) return true;
247 if (!value->IsAccessorPair()) return false;
248 AccessorPair* pair = AccessorPair::cast(value);
249 return pair->Equals(expected_value, *setter_values_[descriptor]);
256 bool Check(Map* map, int expected_nof) const {
257 CHECK(number_of_properties_ <= MAX_PROPERTIES);
258 CHECK_EQ(expected_nof, map->NumberOfOwnDescriptors());
259 CHECK(!map->is_dictionary_map());
261 DescriptorArray* descriptors = map->instance_descriptors();
262 CHECK(expected_nof <= number_of_properties_);
263 for (int i = 0; i < expected_nof; i++) {
264 if (!Check(descriptors, i)) {
266 Check(descriptors, i);
273 bool Check(Map* map) const { return Check(map, number_of_properties_); }
277 // Helper methods for initializing expectations and adding properties to
281 Handle<Map> AddDataField(Handle<Map> map, PropertyAttributes attributes,
282 Representation representation,
283 Handle<HeapType> heap_type) {
284 CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
285 int property_index = number_of_properties_++;
286 SetDataField(property_index, attributes, representation, heap_type);
288 Handle<String> name = MakeName("prop", property_index);
289 return Map::CopyWithField(map, name, heap_type, attributes, representation,
290 INSERT_TRANSITION).ToHandleChecked();
293 Handle<Map> AddDataConstant(Handle<Map> map, PropertyAttributes attributes,
294 Handle<JSFunction> value) {
295 CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
296 int property_index = number_of_properties_++;
297 SetDataConstant(property_index, attributes, value);
299 Handle<String> name = MakeName("prop", property_index);
300 return Map::CopyWithConstant(map, name, value, attributes,
301 INSERT_TRANSITION).ToHandleChecked();
304 Handle<Map> TransitionToDataField(Handle<Map> map,
305 PropertyAttributes attributes,
306 Representation representation,
307 Handle<HeapType> heap_type,
308 Handle<Object> value) {
309 CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
310 int property_index = number_of_properties_++;
311 SetDataField(property_index, attributes, representation, heap_type);
313 Handle<String> name = MakeName("prop", property_index);
314 return Map::TransitionToDataProperty(
315 map, name, value, attributes, Object::CERTAINLY_NOT_STORE_FROM_KEYED);
318 Handle<Map> TransitionToDataConstant(Handle<Map> map,
319 PropertyAttributes attributes,
320 Handle<JSFunction> value) {
321 CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
322 int property_index = number_of_properties_++;
323 SetDataConstant(property_index, attributes, value);
325 Handle<String> name = MakeName("prop", property_index);
326 return Map::TransitionToDataProperty(
327 map, name, value, attributes, Object::CERTAINLY_NOT_STORE_FROM_KEYED);
330 Handle<Map> FollowDataTransition(Handle<Map> map,
331 PropertyAttributes attributes,
332 Representation representation,
333 Handle<HeapType> heap_type) {
334 CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
335 int property_index = number_of_properties_++;
336 SetDataField(property_index, attributes, representation, heap_type);
338 Handle<String> name = MakeName("prop", property_index);
339 int t = map->SearchTransition(kData, *name, attributes);
340 CHECK_NE(TransitionArray::kNotFound, t);
341 return handle(map->GetTransition(t));
344 Handle<Map> AddAccessorConstant(Handle<Map> map,
345 PropertyAttributes attributes,
346 Handle<AccessorPair> pair) {
347 CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
348 int property_index = number_of_properties_++;
349 SetAccessorConstant(property_index, attributes, pair);
351 Handle<String> name = MakeName("prop", property_index);
353 AccessorConstantDescriptor new_desc(name, pair, attributes);
354 return Map::CopyInsertDescriptor(map, &new_desc, INSERT_TRANSITION);
357 Handle<Map> AddAccessorConstant(Handle<Map> map,
358 PropertyAttributes attributes,
359 Handle<Object> getter,
360 Handle<Object> setter) {
361 CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
362 int property_index = number_of_properties_++;
363 SetAccessorConstant(property_index, attributes, getter, setter);
365 Handle<String> name = MakeName("prop", property_index);
367 CHECK(!getter->IsNull() || !setter->IsNull());
368 Factory* factory = isolate_->factory();
370 if (!getter->IsNull()) {
371 Handle<AccessorPair> pair = factory->NewAccessorPair();
372 pair->SetComponents(*getter, *factory->null_value());
373 AccessorConstantDescriptor new_desc(name, pair, attributes);
374 map = Map::CopyInsertDescriptor(map, &new_desc, INSERT_TRANSITION);
376 if (!setter->IsNull()) {
377 Handle<AccessorPair> pair = factory->NewAccessorPair();
378 pair->SetComponents(*getter, *setter);
379 AccessorConstantDescriptor new_desc(name, pair, attributes);
380 map = Map::CopyInsertDescriptor(map, &new_desc, INSERT_TRANSITION);
385 Handle<Map> TransitionToAccessorConstant(Handle<Map> map,
386 PropertyAttributes attributes,
387 Handle<AccessorPair> pair) {
388 CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
389 int property_index = number_of_properties_++;
390 SetAccessorConstant(property_index, attributes, pair);
392 Handle<String> name = MakeName("prop", property_index);
394 Isolate* isolate = CcTest::i_isolate();
395 Handle<Object> getter(pair->getter(), isolate);
396 Handle<Object> setter(pair->setter(), isolate);
398 map = Map::TransitionToAccessorProperty(map, name, ACCESSOR_GETTER, getter,
400 CHECK(!map->is_deprecated());
401 CHECK(!map->is_dictionary_map());
403 map = Map::TransitionToAccessorProperty(map, name, ACCESSOR_SETTER, setter,
405 CHECK(!map->is_deprecated());
406 CHECK(!map->is_dictionary_map());
412 ////////////////////////////////////////////////////////////////////////////////
413 // A set of tests for property reconfiguration that makes new transition tree
417 TEST(ReconfigureAccessorToNonExistingDataField) {
418 CcTest::InitializeVM();
419 v8::HandleScope scope(CcTest::isolate());
420 Isolate* isolate = CcTest::i_isolate();
421 Handle<HeapType> any_type = HeapType::Any(isolate);
422 Handle<HeapType> none_type = HeapType::None(isolate);
423 Handle<AccessorPair> pair = CreateAccessorPair(true, true);
425 Expectations expectations(isolate);
427 // Create a map, add required properties to it and initialize expectations.
428 Handle<Map> initial_map = Map::Create(isolate, 0);
429 Handle<Map> map = initial_map;
430 map = expectations.AddAccessorConstant(map, NONE, pair);
432 CHECK(!map->is_deprecated());
433 CHECK(map->is_stable());
434 CHECK(expectations.Check(*map));
436 Handle<Map> new_map = Map::ReconfigureProperty(
437 map, 0, kData, NONE, Representation::None(), none_type, FORCE_FIELD);
438 // |map| did not change.
439 CHECK(!map->is_deprecated());
440 CHECK(map->is_stable());
441 CHECK(expectations.Check(*map));
443 expectations.SetDataField(0, NONE, Representation::None(), none_type);
445 CHECK(!new_map->is_deprecated());
446 CHECK(new_map->is_stable());
447 CHECK(expectations.Check(*new_map));
449 Handle<Map> new_map2 = Map::ReconfigureProperty(
450 map, 0, kData, NONE, Representation::None(), none_type, FORCE_FIELD);
451 CHECK_EQ(*new_map, *new_map2);
453 Handle<Object> value(Smi::FromInt(0), isolate);
454 Handle<Map> prepared_map = Map::PrepareForDataProperty(new_map, 0, value);
455 // None to Smi generalization is trivial, map does not change.
456 CHECK_EQ(*new_map, *prepared_map);
458 expectations.SetDataField(0, NONE, Representation::Smi(), any_type);
459 CHECK(prepared_map->is_stable());
460 CHECK(expectations.Check(*prepared_map));
462 // Now create an object with |map|, migrate it to |prepared_map| and ensure
463 // that the data property is uninitialized.
464 Factory* factory = isolate->factory();
465 Handle<JSObject> obj = factory->NewJSObjectFromMap(map);
466 JSObject::MigrateToMap(obj, prepared_map);
467 FieldIndex index = FieldIndex::ForDescriptor(*prepared_map, 0);
468 CHECK(obj->RawFastPropertyAt(index)->IsUninitialized());
475 // This test checks that the LookupIterator machinery involved in
476 // JSObject::SetOwnPropertyIgnoreAttributes() does not try to migrate object
477 // to a map with a property with None representation.
478 TEST(ReconfigureAccessorToNonExistingDataFieldHeavy) {
479 CcTest::InitializeVM();
480 Isolate* isolate = CcTest::i_isolate();
481 Factory* factory = isolate->factory();
482 v8::HandleScope scope(CcTest::isolate());
485 "function getter() { return 1; };"
486 "function setter() {};"
488 "Object.defineProperty(o, 'foo', "
489 " { get: getter, set: setter, "
490 " configurable: true, enumerable: true});");
492 Handle<String> foo_str = factory->InternalizeUtf8String("foo");
493 Handle<String> obj_name = factory->InternalizeUtf8String("o");
495 Handle<Object> obj_value =
496 Object::GetProperty(isolate->global_object(), obj_name).ToHandleChecked();
497 CHECK(obj_value->IsJSObject());
498 Handle<JSObject> obj = Handle<JSObject>::cast(obj_value);
500 CHECK_EQ(1, obj->map()->NumberOfOwnDescriptors());
501 CHECK(obj->map()->instance_descriptors()->GetValue(0)->IsAccessorPair());
503 Handle<Object> value(Smi::FromInt(42), isolate);
504 JSObject::SetOwnPropertyIgnoreAttributes(
505 obj, foo_str, value, NONE, JSObject::DONT_FORCE_FIELD).ToHandleChecked();
507 // Check that the property contains |value|.
508 CHECK_EQ(1, obj->map()->NumberOfOwnDescriptors());
509 FieldIndex index = FieldIndex::ForDescriptor(obj->map(), 0);
510 Object* the_value = obj->RawFastPropertyAt(index);
511 CHECK(the_value->IsSmi());
512 CHECK_EQ(42, Smi::cast(the_value)->value());
516 ////////////////////////////////////////////////////////////////////////////////
517 // A set of tests for representation generalization case.
520 static void TestGeneralizeRepresentation(Representation from_representation,
521 Handle<HeapType> from_type,
522 Representation to_representation,
523 Handle<HeapType> to_type,
524 Representation expected_representation,
525 Handle<HeapType> expected_type) {
526 Isolate* isolate = CcTest::i_isolate();
528 Expectations expectations(isolate);
530 // Create a map, add required properties to it and initialize expectations.
531 Handle<Map> initial_map = Map::Create(isolate, 0);
532 Handle<Map> map = initial_map;
533 for (int i = 0; i < kPropCount; i++) {
534 map = expectations.AddDataField(map, NONE, from_representation, from_type);
536 CHECK(!map->is_deprecated());
537 CHECK(map->is_stable());
538 CHECK(expectations.Check(*map));
541 FakeStubForTesting stub(isolate);
543 // Create new maps by generalizing representation of propX field.
544 Handle<Map> maps[kPropCount];
545 for (int i = 0; i < kPropCount; i++) {
546 Handle<Map> field_owner(map->FindFieldOwner(i), isolate);
547 CompilationInfo info(&stub, isolate, &zone);
548 CHECK(!info.HasAbortedDueToDependencyChange());
550 Map::AddDependentCompilationInfo(field_owner,
551 DependentCode::kFieldTypeGroup, &info);
553 Handle<Map> new_map = Map::ReconfigureProperty(
554 map, i, kData, NONE, to_representation, to_type, FORCE_FIELD);
557 expectations.SetDataField(i, expected_representation, expected_type);
559 CHECK(map->is_deprecated());
560 CHECK(!info.HasAbortedDueToDependencyChange());
561 info.RollbackDependencies(); // Properly cleanup compilation info.
563 CHECK_NE(*map, *new_map);
564 CHECK(i == 0 || maps[i - 1]->is_deprecated());
566 CHECK(!new_map->is_deprecated());
567 CHECK(!new_map->is_dictionary_map());
568 CHECK(expectations.Check(*new_map));
571 Handle<Map> active_map = maps[kPropCount - 1];
572 CHECK(!active_map->is_deprecated());
574 // Update all deprecated maps and check that they are now the same.
575 Handle<Map> updated_map = Map::Update(map);
576 CHECK_EQ(*active_map, *updated_map);
577 for (int i = 0; i < kPropCount; i++) {
578 updated_map = Map::Update(maps[i]);
579 CHECK_EQ(*active_map, *updated_map);
584 static void TestGeneralizeRepresentationTrivial(
585 Representation from_representation, Handle<HeapType> from_type,
586 Representation to_representation, Handle<HeapType> to_type,
587 Representation expected_representation, Handle<HeapType> expected_type,
588 bool expected_field_type_dependency = true) {
589 Isolate* isolate = CcTest::i_isolate();
591 Expectations expectations(isolate);
593 // Create a map, add required properties to it and initialize expectations.
594 Handle<Map> initial_map = Map::Create(isolate, 0);
595 Handle<Map> map = initial_map;
596 for (int i = 0; i < kPropCount; i++) {
597 map = expectations.AddDataField(map, NONE, from_representation, from_type);
599 CHECK(!map->is_deprecated());
600 CHECK(map->is_stable());
601 CHECK(expectations.Check(*map));
604 FakeStubForTesting stub(isolate);
606 // Create new maps by generalizing representation of propX field.
607 for (int i = 0; i < kPropCount; i++) {
608 Handle<Map> field_owner(map->FindFieldOwner(i), isolate);
609 CompilationInfo info(&stub, isolate, &zone);
610 CHECK(!info.HasAbortedDueToDependencyChange());
612 Map::AddDependentCompilationInfo(field_owner,
613 DependentCode::kFieldTypeGroup, &info);
615 Handle<Map> new_map = Map::ReconfigureProperty(
616 map, i, kData, NONE, to_representation, to_type, FORCE_FIELD);
618 expectations.SetDataField(i, expected_representation, expected_type);
620 CHECK_EQ(*map, *new_map);
621 CHECK_EQ(expected_field_type_dependency,
622 info.HasAbortedDueToDependencyChange());
624 info.RollbackDependencies(); // Properly cleanup compilation info.
626 CHECK_EQ(*map, *new_map);
627 CHECK(!new_map->is_deprecated());
628 CHECK(!new_map->is_dictionary_map());
629 CHECK(expectations.Check(*new_map));
632 Handle<Map> updated_map = Map::Update(map);
633 CHECK_EQ(*map, *updated_map);
637 TEST(GeneralizeRepresentationSmiToDouble) {
638 CcTest::InitializeVM();
639 v8::HandleScope scope(CcTest::isolate());
640 Isolate* isolate = CcTest::i_isolate();
641 Handle<HeapType> any_type = HeapType::Any(isolate);
643 TestGeneralizeRepresentation(Representation::Smi(), any_type,
644 Representation::Double(), any_type,
645 Representation::Double(), any_type);
649 TEST(GeneralizeRepresentationSmiToTagged) {
650 CcTest::InitializeVM();
651 v8::HandleScope scope(CcTest::isolate());
652 Isolate* isolate = CcTest::i_isolate();
653 Handle<HeapType> any_type = HeapType::Any(isolate);
654 Handle<HeapType> value_type =
655 HeapType::Class(Map::Create(isolate, 0), isolate);
657 TestGeneralizeRepresentation(Representation::Smi(), any_type,
658 Representation::HeapObject(), value_type,
659 Representation::Tagged(), any_type);
663 TEST(GeneralizeRepresentationDoubleToTagged) {
664 CcTest::InitializeVM();
665 v8::HandleScope scope(CcTest::isolate());
666 Isolate* isolate = CcTest::i_isolate();
667 Handle<HeapType> any_type = HeapType::Any(isolate);
668 Handle<HeapType> value_type =
669 HeapType::Class(Map::Create(isolate, 0), isolate);
671 TestGeneralizeRepresentation(Representation::Double(), any_type,
672 Representation::HeapObject(), value_type,
673 Representation::Tagged(), any_type);
677 TEST(GeneralizeRepresentationHeapObjectToTagged) {
678 CcTest::InitializeVM();
679 v8::HandleScope scope(CcTest::isolate());
680 Isolate* isolate = CcTest::i_isolate();
681 Handle<HeapType> any_type = HeapType::Any(isolate);
682 Handle<HeapType> value_type =
683 HeapType::Class(Map::Create(isolate, 0), isolate);
685 TestGeneralizeRepresentation(Representation::HeapObject(), value_type,
686 Representation::Smi(), any_type,
687 Representation::Tagged(), any_type);
691 TEST(GeneralizeRepresentationHeapObjectToHeapObject) {
692 CcTest::InitializeVM();
693 v8::HandleScope scope(CcTest::isolate());
694 Isolate* isolate = CcTest::i_isolate();
695 Handle<HeapType> any_type = HeapType::Any(isolate);
697 const int kMaxClassesPerFieldType = 1;
698 Handle<HeapType> current_type =
699 HeapType::Class(Map::Create(isolate, 0), isolate);
701 for (int i = 0; i < kMaxClassesPerFieldType; i++) {
702 Handle<HeapType> new_type =
703 HeapType::Class(Map::Create(isolate, 0), isolate);
705 Handle<HeapType> expected_type =
706 (i < kMaxClassesPerFieldType - 1)
707 ? HeapType::Union(current_type, new_type, isolate)
710 TestGeneralizeRepresentationTrivial(
711 Representation::HeapObject(), current_type,
712 Representation::HeapObject(), new_type, Representation::HeapObject(),
714 current_type = expected_type;
717 Handle<HeapType> new_type = HeapType::Class(Map::Create(isolate, 0), isolate);
719 TestGeneralizeRepresentationTrivial(
720 Representation::HeapObject(), any_type, Representation::HeapObject(),
721 new_type, Representation::HeapObject(), any_type, false);
725 TEST(GeneralizeRepresentationNoneToSmi) {
726 CcTest::InitializeVM();
727 v8::HandleScope scope(CcTest::isolate());
728 Isolate* isolate = CcTest::i_isolate();
729 Handle<HeapType> none_type = HeapType::None(isolate);
730 Handle<HeapType> any_type = HeapType::Any(isolate);
732 // None -> Smi representation change is trivial.
733 TestGeneralizeRepresentationTrivial(Representation::None(), none_type,
734 Representation::Smi(), any_type,
735 Representation::Smi(), any_type);
739 TEST(GeneralizeRepresentationNoneToDouble) {
740 CcTest::InitializeVM();
741 v8::HandleScope scope(CcTest::isolate());
742 Isolate* isolate = CcTest::i_isolate();
743 Handle<HeapType> none_type = HeapType::None(isolate);
744 Handle<HeapType> any_type = HeapType::Any(isolate);
746 // None -> Double representation change is NOT trivial.
747 TestGeneralizeRepresentation(Representation::None(), none_type,
748 Representation::Double(), any_type,
749 Representation::Double(), any_type);
753 TEST(GeneralizeRepresentationNoneToHeapObject) {
754 CcTest::InitializeVM();
755 v8::HandleScope scope(CcTest::isolate());
756 Isolate* isolate = CcTest::i_isolate();
757 Handle<HeapType> none_type = HeapType::None(isolate);
758 Handle<HeapType> value_type =
759 HeapType::Class(Map::Create(isolate, 0), isolate);
761 // None -> HeapObject representation change is trivial.
762 TestGeneralizeRepresentationTrivial(Representation::None(), none_type,
763 Representation::HeapObject(), value_type,
764 Representation::HeapObject(), value_type);
768 TEST(GeneralizeRepresentationNoneToTagged) {
769 CcTest::InitializeVM();
770 v8::HandleScope scope(CcTest::isolate());
771 Isolate* isolate = CcTest::i_isolate();
772 Handle<HeapType> none_type = HeapType::None(isolate);
773 Handle<HeapType> any_type = HeapType::Any(isolate);
775 // None -> HeapObject representation change is trivial.
776 TestGeneralizeRepresentationTrivial(Representation::None(), none_type,
777 Representation::Tagged(), any_type,
778 Representation::Tagged(), any_type);
782 ////////////////////////////////////////////////////////////////////////////////
783 // A set of tests for representation generalization case with kAccessor
787 TEST(GeneralizeRepresentationWithAccessorProperties) {
788 CcTest::InitializeVM();
789 v8::HandleScope scope(CcTest::isolate());
790 Isolate* isolate = CcTest::i_isolate();
791 Handle<HeapType> any_type = HeapType::Any(isolate);
792 Handle<AccessorPair> pair = CreateAccessorPair(true, true);
794 const int kAccessorProp = kPropCount / 2;
795 Expectations expectations(isolate);
797 // Create a map, add required properties to it and initialize expectations.
798 Handle<Map> initial_map = Map::Create(isolate, 0);
799 Handle<Map> map = initial_map;
800 for (int i = 0; i < kPropCount; i++) {
801 if (i == kAccessorProp) {
802 map = expectations.AddAccessorConstant(map, NONE, pair);
805 expectations.AddDataField(map, NONE, Representation::Smi(), any_type);
808 CHECK(!map->is_deprecated());
809 CHECK(map->is_stable());
810 CHECK(expectations.Check(*map));
812 // Create new maps by generalizing representation of propX field.
813 Handle<Map> maps[kPropCount];
814 for (int i = 0; i < kPropCount; i++) {
815 if (i == kAccessorProp) {
816 // Skip accessor property reconfiguration.
817 maps[i] = maps[i - 1];
820 Handle<Map> new_map = Map::ReconfigureProperty(
821 map, i, kData, NONE, Representation::Double(), any_type, FORCE_FIELD);
824 expectations.SetDataField(i, Representation::Double(), any_type);
826 CHECK(map->is_deprecated());
827 CHECK_NE(*map, *new_map);
828 CHECK(i == 0 || maps[i - 1]->is_deprecated());
830 CHECK(!new_map->is_deprecated());
831 CHECK(!new_map->is_dictionary_map());
832 CHECK(expectations.Check(*new_map));
835 Handle<Map> active_map = maps[kPropCount - 1];
836 CHECK(!active_map->is_deprecated());
838 // Update all deprecated maps and check that they are now the same.
839 Handle<Map> updated_map = Map::Update(map);
840 CHECK_EQ(*active_map, *updated_map);
841 for (int i = 0; i < kPropCount; i++) {
842 updated_map = Map::Update(maps[i]);
843 CHECK_EQ(*active_map, *updated_map);
848 ////////////////////////////////////////////////////////////////////////////////
849 // A set of tests for attribute reconfiguration case.
852 // This test ensures that representation/field type generalization is correctly
853 // propagated from one branch of transition tree (|map2|) to another (|map|).
855 // + - p2B - p3 - p4: |map2|
857 // {} - p0 - p1 - p2A - p3 - p4: |map|
859 // where "p2A" and "p2B" differ only in the attributes.
861 static void TestReconfigureDataFieldAttribute_GeneralizeRepresentation(
862 Representation from_representation, Handle<HeapType> from_type,
863 Representation to_representation, Handle<HeapType> to_type,
864 Representation expected_representation, Handle<HeapType> expected_type) {
865 Isolate* isolate = CcTest::i_isolate();
867 Expectations expectations(isolate);
869 // Create a map, add required properties to it and initialize expectations.
870 Handle<Map> initial_map = Map::Create(isolate, 0);
871 Handle<Map> map = initial_map;
872 for (int i = 0; i < kPropCount; i++) {
873 map = expectations.AddDataField(map, NONE, from_representation, from_type);
875 CHECK(!map->is_deprecated());
876 CHECK(map->is_stable());
877 CHECK(expectations.Check(*map));
880 // Create another branch in transition tree (property at index |kSplitProp|
881 // has different attributes), initialize expectations.
882 const int kSplitProp = kPropCount / 2;
883 Expectations expectations2(isolate);
885 Handle<Map> map2 = initial_map;
886 for (int i = 0; i < kSplitProp; i++) {
887 map2 = expectations2.FollowDataTransition(map2, NONE, from_representation,
891 expectations2.AddDataField(map2, READ_ONLY, to_representation, to_type);
893 for (int i = kSplitProp + 1; i < kPropCount; i++) {
894 map2 = expectations2.AddDataField(map2, NONE, to_representation, to_type);
896 CHECK(!map2->is_deprecated());
897 CHECK(map2->is_stable());
898 CHECK(expectations2.Check(*map2));
901 FakeStubForTesting stub(isolate);
902 Handle<Map> field_owner(map->FindFieldOwner(kSplitProp), isolate);
903 CompilationInfo info(&stub, isolate, &zone);
904 CHECK(!info.HasAbortedDueToDependencyChange());
905 Map::AddDependentCompilationInfo(field_owner, DependentCode::kFieldTypeGroup,
908 // Reconfigure attributes of property |kSplitProp| of |map2| to NONE, which
909 // should generalize representations in |map1|.
910 Handle<Map> new_map =
911 Map::ReconfigureExistingProperty(map2, kSplitProp, kData, NONE);
913 // |map2| should be left unchanged.
914 CHECK(!map2->is_deprecated());
915 CHECK_NE(*map2, *new_map);
916 CHECK(expectations2.Check(*map2));
918 // |map| should be deprecated and |new_map| should match new expectations.
919 for (int i = kSplitProp; i < kPropCount; i++) {
920 expectations.SetDataField(i, expected_representation, expected_type);
922 CHECK(map->is_deprecated());
923 CHECK(!info.HasAbortedDueToDependencyChange());
924 info.RollbackDependencies(); // Properly cleanup compilation info.
925 CHECK_NE(*map, *new_map);
927 CHECK(!new_map->is_deprecated());
928 CHECK(!new_map->is_dictionary_map());
929 CHECK(expectations.Check(*new_map));
931 // Update deprecated |map|, it should become |new_map|.
932 Handle<Map> updated_map = Map::Update(map);
933 CHECK_EQ(*new_map, *updated_map);
937 // This test ensures that trivial representation/field type generalization
938 // (from HeapObject to HeapObject) is correctly propagated from one branch of
939 // transition tree (|map2|) to another (|map|).
941 // + - p2B - p3 - p4: |map2|
943 // {} - p0 - p1 - p2A - p3 - p4: |map|
945 // where "p2A" and "p2B" differ only in the attributes.
947 static void TestReconfigureDataFieldAttribute_GeneralizeRepresentationTrivial(
948 Representation from_representation, Handle<HeapType> from_type,
949 Representation to_representation, Handle<HeapType> to_type,
950 Representation expected_representation, Handle<HeapType> expected_type,
951 bool expected_field_type_dependency = true) {
952 Isolate* isolate = CcTest::i_isolate();
954 Expectations expectations(isolate);
956 // Create a map, add required properties to it and initialize expectations.
957 Handle<Map> initial_map = Map::Create(isolate, 0);
958 Handle<Map> map = initial_map;
959 for (int i = 0; i < kPropCount; i++) {
960 map = expectations.AddDataField(map, NONE, from_representation, from_type);
962 CHECK(!map->is_deprecated());
963 CHECK(map->is_stable());
964 CHECK(expectations.Check(*map));
967 // Create another branch in transition tree (property at index |kSplitProp|
968 // has different attributes), initialize expectations.
969 const int kSplitProp = kPropCount / 2;
970 Expectations expectations2(isolate);
972 Handle<Map> map2 = initial_map;
973 for (int i = 0; i < kSplitProp; i++) {
974 map2 = expectations2.FollowDataTransition(map2, NONE, from_representation,
978 expectations2.AddDataField(map2, READ_ONLY, to_representation, to_type);
980 for (int i = kSplitProp + 1; i < kPropCount; i++) {
981 map2 = expectations2.AddDataField(map2, NONE, to_representation, to_type);
983 CHECK(!map2->is_deprecated());
984 CHECK(map2->is_stable());
985 CHECK(expectations2.Check(*map2));
988 FakeStubForTesting stub(isolate);
989 Handle<Map> field_owner(map->FindFieldOwner(kSplitProp), isolate);
990 CompilationInfo info(&stub, isolate, &zone);
991 CHECK(!info.HasAbortedDueToDependencyChange());
992 Map::AddDependentCompilationInfo(field_owner, DependentCode::kFieldTypeGroup,
995 // Reconfigure attributes of property |kSplitProp| of |map2| to NONE, which
996 // should generalize representations in |map1|.
997 Handle<Map> new_map =
998 Map::ReconfigureExistingProperty(map2, kSplitProp, kData, NONE);
1000 // |map2| should be left unchanged.
1001 CHECK(!map2->is_deprecated());
1002 CHECK_NE(*map2, *new_map);
1003 CHECK(expectations2.Check(*map2));
1005 // In trivial case |map| should be returned as a result of the property
1006 // reconfiguration, respective field types should be generalized and
1007 // respective code dependencies should be invalidated. |map| should be NOT
1008 // deprecated and it should match new expectations.
1009 for (int i = kSplitProp; i < kPropCount; i++) {
1010 expectations.SetDataField(i, expected_representation, expected_type);
1012 CHECK(!map->is_deprecated());
1013 CHECK_EQ(*map, *new_map);
1014 CHECK_EQ(expected_field_type_dependency,
1015 info.HasAbortedDueToDependencyChange());
1016 info.RollbackDependencies(); // Properly cleanup compilation info.
1018 CHECK(!new_map->is_deprecated());
1019 CHECK(!new_map->is_dictionary_map());
1020 CHECK(expectations.Check(*new_map));
1022 Handle<Map> updated_map = Map::Update(map);
1023 CHECK_EQ(*new_map, *updated_map);
1027 TEST(ReconfigureDataFieldAttribute_GeneralizeRepresentationSmiToDouble) {
1028 CcTest::InitializeVM();
1029 v8::HandleScope scope(CcTest::isolate());
1030 Isolate* isolate = CcTest::i_isolate();
1031 Handle<HeapType> any_type = HeapType::Any(isolate);
1033 TestReconfigureDataFieldAttribute_GeneralizeRepresentation(
1034 Representation::Smi(), any_type, Representation::Double(), any_type,
1035 Representation::Double(), any_type);
1039 TEST(ReconfigureDataFieldAttribute_GeneralizeRepresentationSmiToTagged) {
1040 CcTest::InitializeVM();
1041 v8::HandleScope scope(CcTest::isolate());
1042 Isolate* isolate = CcTest::i_isolate();
1043 Handle<HeapType> any_type = HeapType::Any(isolate);
1044 Handle<HeapType> value_type =
1045 HeapType::Class(Map::Create(isolate, 0), isolate);
1047 TestReconfigureDataFieldAttribute_GeneralizeRepresentation(
1048 Representation::Smi(), any_type, Representation::HeapObject(), value_type,
1049 Representation::Tagged(), any_type);
1053 TEST(ReconfigureDataFieldAttribute_GeneralizeRepresentationDoubleToTagged) {
1054 CcTest::InitializeVM();
1055 v8::HandleScope scope(CcTest::isolate());
1056 Isolate* isolate = CcTest::i_isolate();
1057 Handle<HeapType> any_type = HeapType::Any(isolate);
1058 Handle<HeapType> value_type =
1059 HeapType::Class(Map::Create(isolate, 0), isolate);
1061 TestReconfigureDataFieldAttribute_GeneralizeRepresentation(
1062 Representation::Double(), any_type, Representation::HeapObject(),
1063 value_type, Representation::Tagged(), any_type);
1067 TEST(ReconfigureDataFieldAttribute_GeneralizeRepresentationHeapObjToHeapObj) {
1068 CcTest::InitializeVM();
1069 v8::HandleScope scope(CcTest::isolate());
1070 Isolate* isolate = CcTest::i_isolate();
1071 Handle<HeapType> any_type = HeapType::Any(isolate);
1073 const int kMaxClassesPerFieldType = 1;
1074 Handle<HeapType> current_type =
1075 HeapType::Class(Map::Create(isolate, 0), isolate);
1077 for (int i = 0; i < kMaxClassesPerFieldType; i++) {
1078 Handle<HeapType> new_type =
1079 HeapType::Class(Map::Create(isolate, 0), isolate);
1081 Handle<HeapType> expected_type =
1082 (i < kMaxClassesPerFieldType - 1)
1083 ? HeapType::Union(current_type, new_type, isolate)
1086 TestReconfigureDataFieldAttribute_GeneralizeRepresentationTrivial(
1087 Representation::HeapObject(), current_type,
1088 Representation::HeapObject(), new_type, Representation::HeapObject(),
1090 current_type = expected_type;
1093 Handle<HeapType> new_type = HeapType::Class(Map::Create(isolate, 0), isolate);
1095 TestReconfigureDataFieldAttribute_GeneralizeRepresentationTrivial(
1096 Representation::HeapObject(), any_type, Representation::HeapObject(),
1097 new_type, Representation::HeapObject(), any_type, false);
1101 TEST(ReconfigureDataFieldAttribute_GeneralizeRepresentationHeapObjectToTagged) {
1102 CcTest::InitializeVM();
1103 v8::HandleScope scope(CcTest::isolate());
1104 Isolate* isolate = CcTest::i_isolate();
1105 Handle<HeapType> any_type = HeapType::Any(isolate);
1106 Handle<HeapType> value_type =
1107 HeapType::Class(Map::Create(isolate, 0), isolate);
1109 TestReconfigureDataFieldAttribute_GeneralizeRepresentation(
1110 Representation::HeapObject(), value_type, Representation::Smi(), any_type,
1111 Representation::Tagged(), any_type);
1115 // Checks that given |map| is deprecated and that it updates to given |new_map|
1116 // which in turn should match expectations.
1117 struct CheckDeprecated {
1118 void Check(Handle<Map> map, Handle<Map> new_map,
1119 const Expectations& expectations) {
1120 CHECK(map->is_deprecated());
1121 CHECK_NE(*map, *new_map);
1123 CHECK(!new_map->is_deprecated());
1124 CHECK(!new_map->is_dictionary_map());
1125 CHECK(expectations.Check(*new_map));
1127 // Update deprecated |map|, it should become |new_map|.
1128 Handle<Map> updated_map = Map::Update(map);
1129 CHECK_EQ(*new_map, *updated_map);
1134 // Checks that given |map| is NOT deprecated, equals to given |new_map| and
1135 // matches expectations.
1136 struct CheckSameMap {
1137 void Check(Handle<Map> map, Handle<Map> new_map,
1138 const Expectations& expectations) {
1139 CHECK(!map->is_deprecated());
1140 CHECK_EQ(*map, *new_map);
1142 CHECK(!new_map->is_deprecated());
1143 CHECK(!new_map->is_dictionary_map());
1144 CHECK(expectations.Check(*new_map));
1146 // Update deprecated |map|, it should become |new_map|.
1147 Handle<Map> updated_map = Map::Update(map);
1148 CHECK_EQ(*new_map, *updated_map);
1153 // Checks that given |map| is NOT deprecated, and |new_map| is a result of
1154 // copy-generalize-all-representations.
1155 struct CheckCopyGeneralizeAllRepresentations {
1156 void Check(Handle<Map> map, Handle<Map> new_map, Expectations& expectations) {
1157 CHECK(!map->is_deprecated());
1158 CHECK_NE(*map, *new_map);
1160 CHECK(new_map->GetBackPointer()->IsUndefined());
1161 for (int i = 0; i < kPropCount; i++) {
1162 expectations.GeneralizeRepresentation(i);
1165 CHECK(!new_map->is_deprecated());
1166 CHECK(!new_map->is_dictionary_map());
1167 CHECK(expectations.Check(*new_map));
1172 // This test ensures that representation/field type generalization is correctly
1173 // propagated from one branch of transition tree (|map2|) to another (|map1|).
1175 // + - p2B - p3 - p4: |map2|
1177 // {} - p0 - p1: |map|
1179 // + - p2A - p3 - p4: |map1|
1181 // + - the property customized by the TestConfig provided
1183 // where "p2A" and "p2B" differ only in the attributes.
1185 template <typename TestConfig, typename Checker>
1186 static void TestReconfigureProperty_CustomPropertyAfterTargetMap(
1187 TestConfig& config, Checker& checker) {
1188 Isolate* isolate = CcTest::i_isolate();
1189 Handle<HeapType> any_type = HeapType::Any(isolate);
1191 const int kCustomPropIndex = kPropCount - 2;
1192 Expectations expectations(isolate);
1194 const int kSplitProp = 2;
1195 CHECK(kSplitProp < kCustomPropIndex);
1197 const Representation representation = Representation::Smi();
1199 // Create common part of transition tree.
1200 Handle<Map> initial_map = Map::Create(isolate, 0);
1201 Handle<Map> map = initial_map;
1202 for (int i = 0; i < kSplitProp; i++) {
1203 map = expectations.AddDataField(map, NONE, representation, any_type);
1205 CHECK(!map->is_deprecated());
1206 CHECK(map->is_stable());
1207 CHECK(expectations.Check(*map));
1210 // Create branch to |map1|.
1211 Handle<Map> map1 = map;
1212 Expectations expectations1 = expectations;
1213 for (int i = kSplitProp; i < kCustomPropIndex; i++) {
1214 map1 = expectations1.AddDataField(map1, NONE, representation, any_type);
1216 map1 = config.AddPropertyAtBranch(1, expectations1, map1);
1217 for (int i = kCustomPropIndex + 1; i < kPropCount; i++) {
1218 map1 = expectations1.AddDataField(map1, NONE, representation, any_type);
1220 CHECK(!map1->is_deprecated());
1221 CHECK(map1->is_stable());
1222 CHECK(expectations1.Check(*map1));
1225 // Create another branch in transition tree (property at index |kSplitProp|
1226 // has different attributes), initialize expectations.
1227 Handle<Map> map2 = map;
1228 Expectations expectations2 = expectations;
1229 map2 = expectations2.AddDataField(map2, READ_ONLY, representation, any_type);
1230 for (int i = kSplitProp + 1; i < kCustomPropIndex; i++) {
1231 map2 = expectations2.AddDataField(map2, NONE, representation, any_type);
1233 map2 = config.AddPropertyAtBranch(2, expectations2, map2);
1234 for (int i = kCustomPropIndex + 1; i < kPropCount; i++) {
1235 map2 = expectations2.AddDataField(map2, NONE, representation, any_type);
1237 CHECK(!map2->is_deprecated());
1238 CHECK(map2->is_stable());
1239 CHECK(expectations2.Check(*map2));
1242 // Reconfigure attributes of property |kSplitProp| of |map2| to NONE, which
1243 // should generalize representations in |map1|.
1244 Handle<Map> new_map =
1245 Map::ReconfigureExistingProperty(map2, kSplitProp, kData, NONE);
1247 // |map2| should be left unchanged.
1248 CHECK(!map2->is_deprecated());
1249 CHECK_NE(*map2, *new_map);
1250 CHECK(expectations2.Check(*map2));
1252 config.UpdateExpectations(kCustomPropIndex, expectations1);
1253 checker.Check(map1, new_map, expectations1);
1257 TEST(ReconfigureDataFieldAttribute_SameDataConstantAfterTargetMap) {
1258 CcTest::InitializeVM();
1259 v8::HandleScope scope(CcTest::isolate());
1262 Handle<JSFunction> js_func_;
1264 Isolate* isolate = CcTest::i_isolate();
1265 Factory* factory = isolate->factory();
1266 js_func_ = factory->NewFunction(factory->empty_string());
1269 Handle<Map> AddPropertyAtBranch(int branch_id, Expectations& expectations,
1271 CHECK(branch_id == 1 || branch_id == 2);
1272 // Add the same data constant property at both transition tree branches.
1273 return expectations.AddDataConstant(map, NONE, js_func_);
1276 void UpdateExpectations(int property_index, Expectations& expectations) {
1277 // Expectations stay the same.
1282 // Two branches are "compatible" so the |map1| should NOT be deprecated.
1283 CheckSameMap checker;
1284 TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker);
1288 TEST(ReconfigureDataFieldAttribute_DataConstantToDataFieldAfterTargetMap) {
1289 CcTest::InitializeVM();
1290 v8::HandleScope scope(CcTest::isolate());
1293 Handle<JSFunction> js_func1_;
1294 Handle<JSFunction> js_func2_;
1296 Isolate* isolate = CcTest::i_isolate();
1297 Factory* factory = isolate->factory();
1298 js_func1_ = factory->NewFunction(factory->empty_string());
1299 js_func2_ = factory->NewFunction(factory->empty_string());
1302 Handle<Map> AddPropertyAtBranch(int branch_id, Expectations& expectations,
1304 CHECK(branch_id == 1 || branch_id == 2);
1305 Handle<JSFunction> js_func = branch_id == 1 ? js_func1_ : js_func2_;
1306 return expectations.AddDataConstant(map, NONE, js_func);
1309 void UpdateExpectations(int property_index, Expectations& expectations) {
1310 Isolate* isolate = CcTest::i_isolate();
1311 Handle<HeapType> any_type = HeapType::Any(isolate);
1312 expectations.SetDataField(property_index, Representation::HeapObject(),
1318 // Two branches are "incompatible" so the |map1| should be deprecated.
1319 CheckDeprecated checker;
1320 TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker);
1324 TEST(ReconfigureDataFieldAttribute_SameAccessorConstantAfterTargetMap) {
1325 CcTest::InitializeVM();
1326 v8::HandleScope scope(CcTest::isolate());
1329 Handle<AccessorPair> pair_;
1330 TestConfig() { pair_ = CreateAccessorPair(true, true); }
1332 Handle<Map> AddPropertyAtBranch(int branch_id, Expectations& expectations,
1334 CHECK(branch_id == 1 || branch_id == 2);
1335 // Add the same accessor constant property at both transition tree
1337 return expectations.AddAccessorConstant(map, NONE, pair_);
1340 bool UpdateExpectations(int property_index, Expectations& expectations) {
1341 // Two branches are "compatible" so the |map1| should NOT be deprecated.
1347 CheckSameMap checker;
1348 TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker);
1352 TEST(ReconfigureDataFieldAttribute_AccConstantToAccFieldAfterTargetMap) {
1353 CcTest::InitializeVM();
1354 v8::HandleScope scope(CcTest::isolate());
1357 Handle<AccessorPair> pair1_;
1358 Handle<AccessorPair> pair2_;
1360 pair1_ = CreateAccessorPair(true, true);
1361 pair2_ = CreateAccessorPair(true, true);
1364 Handle<Map> AddPropertyAtBranch(int branch_id, Expectations& expectations,
1366 CHECK(branch_id == 1 || branch_id == 2);
1367 Handle<AccessorPair> pair = branch_id == 1 ? pair1_ : pair2_;
1368 return expectations.AddAccessorConstant(map, NONE, pair);
1371 void UpdateExpectations(int property_index, Expectations& expectations) {
1372 if (IS_ACCESSOR_FIELD_SUPPORTED) {
1373 expectations.SetAccessorField(property_index);
1375 // Currently we have a copy-generalize-all-representations case and
1376 // ACCESSOR property becomes ACCESSOR_CONSTANT.
1377 expectations.SetAccessorConstant(property_index, pair2_);
1383 if (IS_ACCESSOR_FIELD_SUPPORTED) {
1384 CheckCopyGeneralizeAllRepresentations checker;
1385 TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker);
1387 // Currently we have a copy-generalize-all-representations case.
1388 CheckCopyGeneralizeAllRepresentations checker;
1389 TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker);
1394 ////////////////////////////////////////////////////////////////////////////////
1395 // A set of tests checking split map deprecation.
1398 TEST(ReconfigurePropertySplitMapTransitionsOverflow) {
1399 CcTest::InitializeVM();
1400 v8::HandleScope scope(CcTest::isolate());
1401 Isolate* isolate = CcTest::i_isolate();
1402 Handle<HeapType> any_type = HeapType::Any(isolate);
1404 Expectations expectations(isolate);
1406 // Create a map, add required properties to it and initialize expectations.
1407 Handle<Map> initial_map = Map::Create(isolate, 0);
1408 Handle<Map> map = initial_map;
1409 for (int i = 0; i < kPropCount; i++) {
1410 map = expectations.AddDataField(map, NONE, Representation::Smi(), any_type);
1412 CHECK(!map->is_deprecated());
1413 CHECK(map->is_stable());
1415 // Generalize representation of property at index |kSplitProp|.
1416 const int kSplitProp = kPropCount / 2;
1417 Handle<Map> split_map;
1418 Handle<Map> map2 = initial_map;
1420 for (int i = 0; i < kSplitProp + 1; i++) {
1421 if (i == kSplitProp) {
1425 Handle<String> name = MakeName("prop", i);
1426 int t = map2->SearchTransition(kData, *name, NONE);
1427 CHECK_NE(TransitionArray::kNotFound, t);
1428 map2 = handle(map2->GetTransition(t));
1431 map2 = Map::ReconfigureProperty(map2, kSplitProp, kData, NONE,
1432 Representation::Double(), any_type,
1434 expectations.SetDataField(kSplitProp, Representation::Double(), any_type);
1436 CHECK(expectations.Check(*split_map, kSplitProp));
1437 CHECK(expectations.Check(*map2, kSplitProp + 1));
1440 // At this point |map| should be deprecated and disconnected from the
1442 CHECK(map->is_deprecated());
1443 CHECK(!split_map->is_deprecated());
1444 CHECK(!map2->is_deprecated());
1446 // Fill in transition tree of |map2| so that it can't have more transitions.
1447 for (int i = 0; i < TransitionArray::kMaxNumberOfTransitions; i++) {
1448 CHECK(map2->CanHaveMoreTransitions());
1449 Handle<String> name = MakeName("foo", i);
1450 Map::CopyWithField(map2, name, any_type, NONE, Representation::Smi(),
1451 INSERT_TRANSITION).ToHandleChecked();
1453 CHECK(!map2->CanHaveMoreTransitions());
1455 // Try to update |map|, since there is no place for propX transition at |map2|
1456 // |map| should become "copy-generalized".
1457 Handle<Map> updated_map = Map::Update(map);
1458 CHECK(updated_map->GetBackPointer()->IsUndefined());
1460 for (int i = 0; i < kPropCount; i++) {
1461 expectations.SetDataField(i, Representation::Tagged(), any_type);
1463 CHECK(expectations.Check(*updated_map));
1467 ////////////////////////////////////////////////////////////////////////////////
1468 // A set of tests involving special transitions (such as elements kind
1469 // transition, observed transition or prototype transition).
1472 // This test ensures that representation/field type generalization is correctly
1473 // propagated from one branch of transition tree (|map2|) to another (|map|).
1477 // * - special transition
1479 // {} - p0 - p1 - p2A - p3 - p4A: |map|
1481 // where "p4A" and "p4B" are exactly the same properties.
1483 // TODO(ishell): unify this test template with
1484 // TestReconfigureDataFieldAttribute_GeneralizeRepresentation once
1485 // IS_PROTO_TRANS_ISSUE_FIXED and IS_NON_EQUIVALENT_TRANSITION_SUPPORTED are
1487 template <typename TestConfig>
1488 static void TestGeneralizeRepresentationWithSpecialTransition(
1489 TestConfig& config, Representation from_representation,
1490 Handle<HeapType> from_type, Representation to_representation,
1491 Handle<HeapType> to_type, Representation expected_representation,
1492 Handle<HeapType> expected_type) {
1493 Isolate* isolate = CcTest::i_isolate();
1495 Expectations expectations(isolate);
1497 // Create a map, add required properties to it and initialize expectations.
1498 Handle<Map> initial_map = Map::Create(isolate, 0);
1499 Handle<Map> map = initial_map;
1500 for (int i = 0; i < kPropCount; i++) {
1501 map = expectations.AddDataField(map, NONE, from_representation, from_type);
1503 CHECK(!map->is_deprecated());
1504 CHECK(map->is_stable());
1505 CHECK(expectations.Check(*map));
1507 // Apply some special transition to |map|.
1508 CHECK(map->owns_descriptors());
1509 Handle<Map> map2 = config.Transition(map);
1511 // |map| should still match expectations.
1512 CHECK(!map->is_deprecated());
1513 CHECK(expectations.Check(*map));
1515 Expectations expectations2 = expectations;
1516 if (config.generalizes_representations()) {
1517 for (int i = 0; i < kPropCount; i++) {
1518 expectations2.GeneralizeRepresentation(i);
1522 CHECK(!map2->is_deprecated());
1523 CHECK(map2->is_stable());
1524 CHECK(expectations2.Check(*map2));
1526 // Create new maps by generalizing representation of propX field.
1527 Handle<Map> maps[kPropCount];
1528 for (int i = 0; i < kPropCount; i++) {
1529 Handle<Map> new_map = Map::ReconfigureProperty(
1530 map, i, kData, NONE, to_representation, to_type, FORCE_FIELD);
1533 expectations.SetDataField(i, expected_representation, expected_type);
1535 CHECK(map->is_deprecated());
1536 CHECK_NE(*map, *new_map);
1537 CHECK(i == 0 || maps[i - 1]->is_deprecated());
1538 CHECK(expectations.Check(*new_map));
1540 Handle<Map> new_map2 = Map::Update(map2);
1541 CHECK(!new_map2->is_deprecated());
1542 CHECK(!new_map2->is_dictionary_map());
1544 if (!IS_NON_EQUIVALENT_TRANSITION_SUPPORTED) {
1545 // In case of non-equivalent transition currently we generalize all
1547 for (int i = 0; i < kPropCount; i++) {
1548 expectations2.GeneralizeRepresentation(i);
1550 CHECK(new_map2->GetBackPointer()->IsUndefined());
1551 CHECK(expectations2.Check(*new_map2));
1553 CHECK(expectations.Check(*new_map2));
1557 Handle<Map> active_map = maps[kPropCount - 1];
1558 CHECK(!active_map->is_deprecated());
1560 // Update all deprecated maps and check that they are now the same.
1561 Handle<Map> updated_map = Map::Update(map);
1562 CHECK_EQ(*active_map, *updated_map);
1563 for (int i = 0; i < kPropCount; i++) {
1564 updated_map = Map::Update(maps[i]);
1565 CHECK_EQ(*active_map, *updated_map);
1570 TEST(ElementsKindTransitionFromMapOwningDescriptor) {
1571 CcTest::InitializeVM();
1572 v8::HandleScope scope(CcTest::isolate());
1573 Isolate* isolate = CcTest::i_isolate();
1574 Handle<HeapType> any_type = HeapType::Any(isolate);
1575 Handle<HeapType> value_type =
1576 HeapType::Class(Map::Create(isolate, 0), isolate);
1579 Handle<Map> Transition(Handle<Map> map) {
1580 return Map::CopyAsElementsKind(map, DICTIONARY_ELEMENTS,
1583 // TODO(ishell): remove once IS_PROTO_TRANS_ISSUE_FIXED is removed.
1584 bool generalizes_representations() const { return false; }
1587 TestGeneralizeRepresentationWithSpecialTransition(
1588 config, Representation::Smi(), any_type, Representation::HeapObject(),
1589 value_type, Representation::Tagged(), any_type);
1593 TEST(ElementsKindTransitionFromMapNotOwningDescriptor) {
1594 CcTest::InitializeVM();
1595 v8::HandleScope scope(CcTest::isolate());
1596 Isolate* isolate = CcTest::i_isolate();
1597 Handle<HeapType> any_type = HeapType::Any(isolate);
1598 Handle<HeapType> value_type =
1599 HeapType::Class(Map::Create(isolate, 0), isolate);
1602 Handle<Map> Transition(Handle<Map> map) {
1603 Isolate* isolate = CcTest::i_isolate();
1604 Handle<HeapType> any_type = HeapType::Any(isolate);
1606 // Add one more transition to |map| in order to prevent descriptors
1608 CHECK(map->owns_descriptors());
1609 Map::CopyWithField(map, MakeString("foo"), any_type, NONE,
1610 Representation::Smi(),
1611 INSERT_TRANSITION).ToHandleChecked();
1612 CHECK(!map->owns_descriptors());
1614 return Map::CopyAsElementsKind(map, DICTIONARY_ELEMENTS,
1617 // TODO(ishell): remove once IS_PROTO_TRANS_ISSUE_FIXED is removed.
1618 bool generalizes_representations() const { return false; }
1621 TestGeneralizeRepresentationWithSpecialTransition(
1622 config, Representation::Smi(), any_type, Representation::HeapObject(),
1623 value_type, Representation::Tagged(), any_type);
1627 TEST(ForObservedTransitionFromMapOwningDescriptor) {
1628 CcTest::InitializeVM();
1629 v8::HandleScope scope(CcTest::isolate());
1630 Isolate* isolate = CcTest::i_isolate();
1631 Handle<HeapType> any_type = HeapType::Any(isolate);
1632 Handle<HeapType> value_type =
1633 HeapType::Class(Map::Create(isolate, 0), isolate);
1636 Handle<Map> Transition(Handle<Map> map) {
1637 return Map::CopyForObserved(map);
1639 // TODO(ishell): remove once IS_PROTO_TRANS_ISSUE_FIXED is removed.
1640 bool generalizes_representations() const { return false; }
1643 TestGeneralizeRepresentationWithSpecialTransition(
1644 config, Representation::Smi(), any_type, Representation::HeapObject(),
1645 value_type, Representation::Tagged(), any_type);
1649 TEST(ForObservedTransitionFromMapNotOwningDescriptor) {
1650 CcTest::InitializeVM();
1651 v8::HandleScope scope(CcTest::isolate());
1652 Isolate* isolate = CcTest::i_isolate();
1653 Handle<HeapType> any_type = HeapType::Any(isolate);
1654 Handle<HeapType> value_type =
1655 HeapType::Class(Map::Create(isolate, 0), isolate);
1658 Handle<Map> Transition(Handle<Map> map) {
1659 Isolate* isolate = CcTest::i_isolate();
1660 Handle<HeapType> any_type = HeapType::Any(isolate);
1662 // Add one more transition to |map| in order to prevent descriptors
1664 CHECK(map->owns_descriptors());
1665 Map::CopyWithField(map, MakeString("foo"), any_type, NONE,
1666 Representation::Smi(),
1667 INSERT_TRANSITION).ToHandleChecked();
1668 CHECK(!map->owns_descriptors());
1670 return Map::CopyForObserved(map);
1672 // TODO(ishell): remove once IS_PROTO_TRANS_ISSUE_FIXED is removed.
1673 bool generalizes_representations() const { return false; }
1676 TestGeneralizeRepresentationWithSpecialTransition(
1677 config, Representation::Smi(), any_type, Representation::HeapObject(),
1678 value_type, Representation::Tagged(), any_type);
1682 TEST(PrototypeTransitionFromMapOwningDescriptor) {
1683 CcTest::InitializeVM();
1684 v8::HandleScope scope(CcTest::isolate());
1685 Isolate* isolate = CcTest::i_isolate();
1687 Handle<HeapType> any_type = HeapType::Any(isolate);
1688 Handle<HeapType> value_type =
1689 HeapType::Class(Map::Create(isolate, 0), isolate);
1692 Handle<JSObject> prototype_;
1695 Isolate* isolate = CcTest::i_isolate();
1696 Factory* factory = isolate->factory();
1697 prototype_ = factory->NewJSObjectFromMap(Map::Create(isolate, 0));
1700 Handle<Map> Transition(Handle<Map> map) {
1701 return Map::TransitionToPrototype(map, prototype_, REGULAR_PROTOTYPE);
1703 // TODO(ishell): remove once IS_PROTO_TRANS_ISSUE_FIXED is removed.
1704 bool generalizes_representations() const {
1705 return !IS_PROTO_TRANS_ISSUE_FIXED;
1709 TestGeneralizeRepresentationWithSpecialTransition(
1710 config, Representation::Smi(), any_type, Representation::HeapObject(),
1711 value_type, Representation::Tagged(), any_type);
1715 TEST(PrototypeTransitionFromMapNotOwningDescriptor) {
1716 CcTest::InitializeVM();
1717 v8::HandleScope scope(CcTest::isolate());
1718 Isolate* isolate = CcTest::i_isolate();
1720 Handle<HeapType> any_type = HeapType::Any(isolate);
1721 Handle<HeapType> value_type =
1722 HeapType::Class(Map::Create(isolate, 0), isolate);
1725 Handle<JSObject> prototype_;
1728 Isolate* isolate = CcTest::i_isolate();
1729 Factory* factory = isolate->factory();
1730 prototype_ = factory->NewJSObjectFromMap(Map::Create(isolate, 0));
1733 Handle<Map> Transition(Handle<Map> map) {
1734 Isolate* isolate = CcTest::i_isolate();
1735 Handle<HeapType> any_type = HeapType::Any(isolate);
1737 // Add one more transition to |map| in order to prevent descriptors
1739 CHECK(map->owns_descriptors());
1740 Map::CopyWithField(map, MakeString("foo"), any_type, NONE,
1741 Representation::Smi(),
1742 INSERT_TRANSITION).ToHandleChecked();
1743 CHECK(!map->owns_descriptors());
1745 return Map::TransitionToPrototype(map, prototype_, REGULAR_PROTOTYPE);
1747 // TODO(ishell): remove once IS_PROTO_TRANS_ISSUE_FIXED is removed.
1748 bool generalizes_representations() const {
1749 return !IS_PROTO_TRANS_ISSUE_FIXED;
1753 TestGeneralizeRepresentationWithSpecialTransition(
1754 config, Representation::Smi(), any_type, Representation::HeapObject(),
1755 value_type, Representation::Tagged(), any_type);
1759 ////////////////////////////////////////////////////////////////////////////////
1760 // A set of tests for higher level transitioning mechanics.
1763 struct TransitionToDataFieldOperator {
1764 Representation representation_;
1765 PropertyAttributes attributes_;
1766 Handle<HeapType> heap_type_;
1767 Handle<Object> value_;
1769 TransitionToDataFieldOperator(Representation representation,
1770 Handle<HeapType> heap_type,
1771 Handle<Object> value,
1772 PropertyAttributes attributes = NONE)
1773 : representation_(representation),
1774 attributes_(attributes),
1775 heap_type_(heap_type),
1778 Handle<Map> DoTransition(Expectations& expectations, Handle<Map> map) {
1779 return expectations.TransitionToDataField(map, attributes_, representation_,
1780 heap_type_, value_);
1785 struct TransitionToDataConstantOperator {
1786 PropertyAttributes attributes_;
1787 Handle<JSFunction> value_;
1789 TransitionToDataConstantOperator(Handle<JSFunction> value,
1790 PropertyAttributes attributes = NONE)
1791 : attributes_(attributes), value_(value) {}
1793 Handle<Map> DoTransition(Expectations& expectations, Handle<Map> map) {
1794 return expectations.TransitionToDataConstant(map, attributes_, value_);
1799 struct TransitionToAccessorConstantOperator {
1800 PropertyAttributes attributes_;
1801 Handle<AccessorPair> pair_;
1803 TransitionToAccessorConstantOperator(Handle<AccessorPair> pair,
1804 PropertyAttributes attributes = NONE)
1805 : attributes_(attributes), pair_(pair) {}
1807 Handle<Map> DoTransition(Expectations& expectations, Handle<Map> map) {
1808 return expectations.TransitionToAccessorConstant(map, attributes_, pair_);
1813 struct ReconfigureAsDataPropertyOperator {
1815 Representation representation_;
1816 PropertyAttributes attributes_;
1817 Handle<HeapType> heap_type_;
1819 ReconfigureAsDataPropertyOperator(int descriptor,
1820 Representation representation,
1821 Handle<HeapType> heap_type,
1822 PropertyAttributes attributes = NONE)
1823 : descriptor_(descriptor),
1824 representation_(representation),
1825 attributes_(attributes),
1826 heap_type_(heap_type) {}
1828 Handle<Map> DoTransition(Expectations& expectations, Handle<Map> map) {
1829 expectations.SetDataField(descriptor_, representation_, heap_type_);
1830 return Map::ReconfigureExistingProperty(map, descriptor_, kData,
1836 struct ReconfigureAsAccessorPropertyOperator {
1838 PropertyAttributes attributes_;
1840 ReconfigureAsAccessorPropertyOperator(int descriptor,
1841 PropertyAttributes attributes = NONE)
1842 : descriptor_(descriptor), attributes_(attributes) {}
1844 Handle<Map> DoTransition(Expectations& expectations, Handle<Map> map) {
1845 expectations.SetAccessorField(descriptor_);
1846 return Map::ReconfigureExistingProperty(map, descriptor_, kAccessor,
1852 // Checks that representation/field type generalization happened.
1853 struct FieldGeneralizationChecker {
1855 Representation representation_;
1856 PropertyAttributes attributes_;
1857 Handle<HeapType> heap_type_;
1859 FieldGeneralizationChecker(int descriptor, Representation representation,
1860 Handle<HeapType> heap_type,
1861 PropertyAttributes attributes = NONE)
1862 : descriptor_(descriptor),
1863 representation_(representation),
1864 attributes_(attributes),
1865 heap_type_(heap_type) {}
1867 void Check(Expectations& expectations2, Handle<Map> map1, Handle<Map> map2) {
1868 CHECK(!map2->is_deprecated());
1870 CHECK(map1->is_deprecated());
1871 CHECK_NE(*map1, *map2);
1872 Handle<Map> updated_map = Map::Update(map1);
1873 CHECK_EQ(*map2, *updated_map);
1875 expectations2.SetDataField(descriptor_, representation_, heap_type_);
1876 CHECK(expectations2.Check(*map2));
1881 // Checks that existing transition was taken as is.
1882 struct SameMapChecker {
1883 void Check(Expectations& expectations, Handle<Map> map1, Handle<Map> map2) {
1884 CHECK(!map2->is_deprecated());
1885 CHECK_EQ(*map1, *map2);
1886 CHECK(expectations.Check(*map2));
1891 // Checks that both |map1| and |map2| should stays non-deprecated, this is
1892 // the case when property kind is change.
1893 struct PropertyKindReconfigurationChecker {
1894 void Check(Expectations& expectations, Handle<Map> map1, Handle<Map> map2) {
1895 CHECK(!map1->is_deprecated());
1896 CHECK(!map2->is_deprecated());
1897 CHECK_NE(*map1, *map2);
1898 CHECK(expectations.Check(*map2));
1903 // This test transitions to various property types under different
1906 // 1) create a |map| with p0..p3 properties.
1907 // 2) create |map1| by adding "p4" to |map0|.
1908 // 3) create |map2| by transition to "p4" from |map0|.
1912 // {} - p0 - p1 - pA - p3: |map|
1916 // where "p4A" and "p4B" differ only in the attributes.
1918 template <typename TransitionOp1, typename TransitionOp2, typename Checker>
1919 static void TestTransitionTo(TransitionOp1& transition_op1,
1920 TransitionOp2& transition_op2, Checker& checker) {
1921 Isolate* isolate = CcTest::i_isolate();
1922 Handle<HeapType> any_type = HeapType::Any(isolate);
1924 Expectations expectations(isolate);
1926 // Create a map, add required properties to it and initialize expectations.
1927 Handle<Map> initial_map = Map::Create(isolate, 0);
1928 Handle<Map> map = initial_map;
1929 for (int i = 0; i < kPropCount - 1; i++) {
1930 map = expectations.AddDataField(map, NONE, Representation::Smi(), any_type);
1932 CHECK(expectations.Check(*map));
1934 Expectations expectations1 = expectations;
1935 Handle<Map> map1 = transition_op1.DoTransition(expectations1, map);
1936 CHECK(expectations1.Check(*map1));
1938 Expectations expectations2 = expectations;
1939 Handle<Map> map2 = transition_op2.DoTransition(expectations2, map);
1941 // Let the test customization do the check.
1942 checker.Check(expectations2, map1, map2);
1946 TEST(TransitionDataFieldToDataField) {
1947 CcTest::InitializeVM();
1948 v8::HandleScope scope(CcTest::isolate());
1949 Isolate* isolate = CcTest::i_isolate();
1950 Handle<HeapType> any_type = HeapType::Any(isolate);
1952 Handle<Object> value1 = handle(Smi::FromInt(0), isolate);
1953 TransitionToDataFieldOperator transition_op1(Representation::Smi(), any_type,
1956 Handle<Object> value2 = isolate->factory()->NewHeapNumber(0);
1957 TransitionToDataFieldOperator transition_op2(Representation::Double(),
1960 FieldGeneralizationChecker checker(kPropCount - 1, Representation::Double(),
1962 TestTransitionTo(transition_op1, transition_op2, checker);
1966 TEST(TransitionDataConstantToSameDataConstant) {
1967 CcTest::InitializeVM();
1968 v8::HandleScope scope(CcTest::isolate());
1969 Isolate* isolate = CcTest::i_isolate();
1970 Factory* factory = isolate->factory();
1972 Handle<JSFunction> js_func = factory->NewFunction(factory->empty_string());
1973 TransitionToDataConstantOperator transition_op(js_func);
1975 SameMapChecker checker;
1976 TestTransitionTo(transition_op, transition_op, checker);
1980 TEST(TransitionDataConstantToAnotherDataConstant) {
1981 CcTest::InitializeVM();
1982 v8::HandleScope scope(CcTest::isolate());
1983 Isolate* isolate = CcTest::i_isolate();
1984 Factory* factory = isolate->factory();
1985 Handle<HeapType> any_type = HeapType::Any(isolate);
1987 Handle<JSFunction> js_func1 = factory->NewFunction(factory->empty_string());
1988 TransitionToDataConstantOperator transition_op1(js_func1);
1990 Handle<JSFunction> js_func2 = factory->NewFunction(factory->empty_string());
1991 TransitionToDataConstantOperator transition_op2(js_func2);
1993 FieldGeneralizationChecker checker(kPropCount - 1,
1994 Representation::HeapObject(), any_type);
1995 TestTransitionTo(transition_op1, transition_op2, checker);
1999 TEST(TransitionDataConstantToDataField) {
2000 CcTest::InitializeVM();
2001 v8::HandleScope scope(CcTest::isolate());
2002 Isolate* isolate = CcTest::i_isolate();
2003 Factory* factory = isolate->factory();
2004 Handle<HeapType> any_type = HeapType::Any(isolate);
2006 Handle<JSFunction> js_func1 = factory->NewFunction(factory->empty_string());
2007 TransitionToDataConstantOperator transition_op1(js_func1);
2009 Handle<Object> value2 = isolate->factory()->NewHeapNumber(0);
2010 TransitionToDataFieldOperator transition_op2(Representation::Double(),
2013 FieldGeneralizationChecker checker(kPropCount - 1, Representation::Tagged(),
2015 TestTransitionTo(transition_op1, transition_op2, checker);
2019 TEST(TransitionAccessorConstantToSameAccessorConstant) {
2020 CcTest::InitializeVM();
2021 v8::HandleScope scope(CcTest::isolate());
2023 Handle<AccessorPair> pair = CreateAccessorPair(true, true);
2024 TransitionToAccessorConstantOperator transition_op(pair);
2026 SameMapChecker checker;
2027 TestTransitionTo(transition_op, transition_op, checker);
2031 // TODO(ishell): add this test once IS_ACCESSOR_FIELD_SUPPORTED is supported.
2032 // TEST(TransitionAccessorConstantToAnotherAccessorConstant)