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";
151 Handle<HeapType> GetFieldType(int index) {
152 CHECK(index < MAX_PROPERTIES);
153 CHECK(types_[index] == DATA || types_[index] == ACCESSOR);
154 return Handle<HeapType>::cast(values_[index]);
157 void SetDataField(int index, PropertyAttributes attrs,
158 Representation representation, Handle<HeapType> value) {
159 Init(index, DATA, attrs, representation, value);
162 void SetDataField(int index, Representation representation,
163 Handle<HeapType> value) {
164 SetDataField(index, attributes_[index], representation, value);
167 void SetAccessorField(int index, PropertyAttributes attrs) {
168 Init(index, ACCESSOR, attrs, Representation::Tagged(),
169 HeapType::Any(isolate_));
172 void SetAccessorField(int index) {
173 SetAccessorField(index, attributes_[index]);
176 void SetDataConstant(int index, PropertyAttributes attrs,
177 Handle<JSFunction> value) {
178 Init(index, DATA_CONSTANT, attrs, Representation::HeapObject(), value);
181 void SetDataConstant(int index, Handle<JSFunction> value) {
182 SetDataConstant(index, attributes_[index], value);
185 void SetAccessorConstant(int index, PropertyAttributes attrs,
186 Handle<Object> getter, Handle<Object> setter) {
187 Init(index, ACCESSOR_CONSTANT, attrs, Representation::Tagged(), getter);
188 setter_values_[index] = setter;
191 void SetAccessorConstantComponent(int index, PropertyAttributes attrs,
192 AccessorComponent component,
193 Handle<Object> accessor) {
194 CHECK_EQ(ACCESSOR_CONSTANT, types_[index]);
195 CHECK(index < number_of_properties_);
196 if (component == ACCESSOR_GETTER) {
197 values_[index] = accessor;
199 setter_values_[index] = accessor;
203 void SetAccessorConstant(int index, PropertyAttributes attrs,
204 Handle<AccessorPair> pair) {
205 Handle<Object> getter = handle(pair->getter(), isolate_);
206 Handle<Object> setter = handle(pair->setter(), isolate_);
207 SetAccessorConstant(index, attrs, getter, setter);
210 void SetAccessorConstant(int index, Handle<Object> getter,
211 Handle<Object> setter) {
212 SetAccessorConstant(index, attributes_[index], getter, setter);
215 void SetAccessorConstant(int index, Handle<AccessorPair> pair) {
216 Handle<Object> getter = handle(pair->getter(), isolate_);
217 Handle<Object> setter = handle(pair->setter(), isolate_);
218 SetAccessorConstant(index, getter, setter);
221 void GeneralizeRepresentation(int index) {
222 CHECK(index < number_of_properties_);
223 representations_[index] = Representation::Tagged();
224 if (types_[index] == DATA || types_[index] == ACCESSOR) {
225 values_[index] = HeapType::Any(isolate_);
230 bool Check(DescriptorArray* descriptors, int descriptor) const {
231 PropertyType type = types_[descriptor];
232 if (!EqualDetails(descriptors, descriptor, type, attributes_[descriptor],
233 representations_[descriptor])) {
236 Object* value = descriptors->GetValue(descriptor);
237 Object* expected_value = *values_[descriptor];
241 HeapType* type = descriptors->GetFieldType(descriptor);
242 return HeapType::cast(expected_value)->Equals(type);
246 return value == expected_value;
248 case ACCESSOR_CONSTANT: {
249 if (value == expected_value) return true;
250 if (!value->IsAccessorPair()) return false;
251 AccessorPair* pair = AccessorPair::cast(value);
252 return pair->Equals(expected_value, *setter_values_[descriptor]);
259 bool Check(Map* map, int expected_nof) const {
260 CHECK(number_of_properties_ <= MAX_PROPERTIES);
261 CHECK_EQ(expected_nof, map->NumberOfOwnDescriptors());
262 CHECK(!map->is_dictionary_map());
264 DescriptorArray* descriptors = map->instance_descriptors();
265 CHECK(expected_nof <= number_of_properties_);
266 for (int i = 0; i < expected_nof; i++) {
267 if (!Check(descriptors, i)) {
270 descriptors->Print();
272 Check(descriptors, i);
279 bool Check(Map* map) const { return Check(map, number_of_properties_); }
283 // Helper methods for initializing expectations and adding properties to
287 Handle<Map> AddDataField(Handle<Map> map, PropertyAttributes attributes,
288 Representation representation,
289 Handle<HeapType> heap_type) {
290 CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
291 int property_index = number_of_properties_++;
292 SetDataField(property_index, attributes, representation, heap_type);
294 Handle<String> name = MakeName("prop", property_index);
295 return Map::CopyWithField(map, name, heap_type, attributes, representation,
296 INSERT_TRANSITION).ToHandleChecked();
299 Handle<Map> AddDataConstant(Handle<Map> map, PropertyAttributes attributes,
300 Handle<JSFunction> value) {
301 CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
302 int property_index = number_of_properties_++;
303 SetDataConstant(property_index, attributes, value);
305 Handle<String> name = MakeName("prop", property_index);
306 return Map::CopyWithConstant(map, name, value, attributes,
307 INSERT_TRANSITION).ToHandleChecked();
310 Handle<Map> TransitionToDataField(Handle<Map> map,
311 PropertyAttributes attributes,
312 Representation representation,
313 Handle<HeapType> heap_type,
314 Handle<Object> value) {
315 CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
316 int property_index = number_of_properties_++;
317 SetDataField(property_index, attributes, representation, heap_type);
319 Handle<String> name = MakeName("prop", property_index);
320 return Map::TransitionToDataProperty(
321 map, name, value, attributes, Object::CERTAINLY_NOT_STORE_FROM_KEYED);
324 Handle<Map> TransitionToDataConstant(Handle<Map> map,
325 PropertyAttributes attributes,
326 Handle<JSFunction> value) {
327 CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
328 int property_index = number_of_properties_++;
329 SetDataConstant(property_index, attributes, value);
331 Handle<String> name = MakeName("prop", property_index);
332 return Map::TransitionToDataProperty(
333 map, name, value, attributes, Object::CERTAINLY_NOT_STORE_FROM_KEYED);
336 Handle<Map> FollowDataTransition(Handle<Map> map,
337 PropertyAttributes attributes,
338 Representation representation,
339 Handle<HeapType> heap_type) {
340 CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
341 int property_index = number_of_properties_++;
342 SetDataField(property_index, attributes, representation, heap_type);
344 Handle<String> name = MakeName("prop", property_index);
346 TransitionArray::SearchTransition(*map, kData, *name, attributes);
347 CHECK(target != NULL);
348 return handle(target);
351 Handle<Map> AddAccessorConstant(Handle<Map> map,
352 PropertyAttributes attributes,
353 Handle<AccessorPair> pair) {
354 CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
355 int property_index = number_of_properties_++;
356 SetAccessorConstant(property_index, attributes, pair);
358 Handle<String> name = MakeName("prop", property_index);
360 AccessorConstantDescriptor new_desc(name, pair, attributes);
361 return Map::CopyInsertDescriptor(map, &new_desc, INSERT_TRANSITION);
364 Handle<Map> AddAccessorConstant(Handle<Map> map,
365 PropertyAttributes attributes,
366 Handle<Object> getter,
367 Handle<Object> setter) {
368 CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
369 int property_index = number_of_properties_++;
370 SetAccessorConstant(property_index, attributes, getter, setter);
372 Handle<String> name = MakeName("prop", property_index);
374 CHECK(!getter->IsNull() || !setter->IsNull());
375 Factory* factory = isolate_->factory();
377 if (!getter->IsNull()) {
378 Handle<AccessorPair> pair = factory->NewAccessorPair();
379 pair->SetComponents(*getter, *factory->null_value());
380 AccessorConstantDescriptor new_desc(name, pair, attributes);
381 map = Map::CopyInsertDescriptor(map, &new_desc, INSERT_TRANSITION);
383 if (!setter->IsNull()) {
384 Handle<AccessorPair> pair = factory->NewAccessorPair();
385 pair->SetComponents(*getter, *setter);
386 AccessorConstantDescriptor new_desc(name, pair, attributes);
387 map = Map::CopyInsertDescriptor(map, &new_desc, INSERT_TRANSITION);
392 Handle<Map> TransitionToAccessorConstant(Handle<Map> map,
393 PropertyAttributes attributes,
394 Handle<AccessorPair> pair) {
395 CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
396 int property_index = number_of_properties_++;
397 SetAccessorConstant(property_index, attributes, pair);
399 Handle<String> name = MakeName("prop", property_index);
401 Isolate* isolate = CcTest::i_isolate();
402 Handle<Object> getter(pair->getter(), isolate);
403 Handle<Object> setter(pair->setter(), isolate);
405 map = Map::TransitionToAccessorProperty(map, name, ACCESSOR_GETTER, getter,
407 CHECK(!map->is_deprecated());
408 CHECK(!map->is_dictionary_map());
410 map = Map::TransitionToAccessorProperty(map, name, ACCESSOR_SETTER, setter,
412 CHECK(!map->is_deprecated());
413 CHECK(!map->is_dictionary_map());
419 ////////////////////////////////////////////////////////////////////////////////
420 // A set of tests for property reconfiguration that makes new transition tree
424 TEST(ReconfigureAccessorToNonExistingDataField) {
425 CcTest::InitializeVM();
426 v8::HandleScope scope(CcTest::isolate());
427 Isolate* isolate = CcTest::i_isolate();
428 Handle<HeapType> any_type = HeapType::Any(isolate);
429 Handle<HeapType> none_type = HeapType::None(isolate);
430 Handle<AccessorPair> pair = CreateAccessorPair(true, true);
432 Expectations expectations(isolate);
434 // Create a map, add required properties to it and initialize expectations.
435 Handle<Map> initial_map = Map::Create(isolate, 0);
436 Handle<Map> map = initial_map;
437 map = expectations.AddAccessorConstant(map, NONE, pair);
439 CHECK(!map->is_deprecated());
440 CHECK(map->is_stable());
441 CHECK(expectations.Check(*map));
443 Handle<Map> new_map = Map::ReconfigureProperty(
444 map, 0, kData, NONE, Representation::None(), none_type, FORCE_FIELD);
445 // |map| did not change.
446 CHECK(!map->is_deprecated());
447 CHECK(map->is_stable());
448 CHECK(expectations.Check(*map));
450 expectations.SetDataField(0, NONE, Representation::None(), none_type);
452 CHECK(!new_map->is_deprecated());
453 CHECK(new_map->is_stable());
454 CHECK(expectations.Check(*new_map));
456 Handle<Map> new_map2 = Map::ReconfigureProperty(
457 map, 0, kData, NONE, Representation::None(), none_type, FORCE_FIELD);
458 CHECK_EQ(*new_map, *new_map2);
460 Handle<Object> value(Smi::FromInt(0), isolate);
461 Handle<Map> prepared_map = Map::PrepareForDataProperty(new_map, 0, value);
462 // None to Smi generalization is trivial, map does not change.
463 CHECK_EQ(*new_map, *prepared_map);
465 expectations.SetDataField(0, NONE, Representation::Smi(), any_type);
466 CHECK(prepared_map->is_stable());
467 CHECK(expectations.Check(*prepared_map));
469 // Now create an object with |map|, migrate it to |prepared_map| and ensure
470 // that the data property is uninitialized.
471 Factory* factory = isolate->factory();
472 Handle<JSObject> obj = factory->NewJSObjectFromMap(map);
473 JSObject::MigrateToMap(obj, prepared_map);
474 FieldIndex index = FieldIndex::ForDescriptor(*prepared_map, 0);
475 CHECK(obj->RawFastPropertyAt(index)->IsUninitialized());
482 // This test checks that the LookupIterator machinery involved in
483 // JSObject::SetOwnPropertyIgnoreAttributes() does not try to migrate object
484 // to a map with a property with None representation.
485 TEST(ReconfigureAccessorToNonExistingDataFieldHeavy) {
486 CcTest::InitializeVM();
487 Isolate* isolate = CcTest::i_isolate();
488 Factory* factory = isolate->factory();
489 v8::HandleScope scope(CcTest::isolate());
492 "function getter() { return 1; };"
493 "function setter() {};"
495 "Object.defineProperty(o, 'foo', "
496 " { get: getter, set: setter, "
497 " configurable: true, enumerable: true});");
499 Handle<String> foo_str = factory->InternalizeUtf8String("foo");
500 Handle<String> obj_name = factory->InternalizeUtf8String("o");
502 Handle<Object> obj_value =
503 Object::GetProperty(isolate->global_object(), obj_name).ToHandleChecked();
504 CHECK(obj_value->IsJSObject());
505 Handle<JSObject> obj = Handle<JSObject>::cast(obj_value);
507 CHECK_EQ(1, obj->map()->NumberOfOwnDescriptors());
508 CHECK(obj->map()->instance_descriptors()->GetValue(0)->IsAccessorPair());
510 Handle<Object> value(Smi::FromInt(42), isolate);
511 JSObject::SetOwnPropertyIgnoreAttributes(
512 obj, foo_str, value, NONE, JSObject::DONT_FORCE_FIELD).ToHandleChecked();
514 // Check that the property contains |value|.
515 CHECK_EQ(1, obj->map()->NumberOfOwnDescriptors());
516 FieldIndex index = FieldIndex::ForDescriptor(obj->map(), 0);
517 Object* the_value = obj->RawFastPropertyAt(index);
518 CHECK(the_value->IsSmi());
519 CHECK_EQ(42, Smi::cast(the_value)->value());
523 ////////////////////////////////////////////////////////////////////////////////
524 // A set of tests for representation generalization case.
527 // This test ensures that representation/field type generalization at
528 // |property_index| is done correctly independently of the fact that the |map|
529 // is detached from transition tree or not.
531 // {} - p0 - p1 - p2: |detach_point_map|
533 // X - detached at |detach_property_at_index|
535 // + - p3 - p4: |map|
537 // Detaching does not happen if |detach_property_at_index| is -1.
539 static void TestGeneralizeRepresentation(
540 int detach_property_at_index, int property_index,
541 Representation from_representation, Handle<HeapType> from_type,
542 Representation to_representation, Handle<HeapType> to_type,
543 Representation expected_representation, Handle<HeapType> expected_type,
544 bool expected_deprecation, bool expected_field_type_dependency) {
545 Isolate* isolate = CcTest::i_isolate();
546 Handle<HeapType> any_type = HeapType::Any(isolate);
548 CHECK(detach_property_at_index >= -1 &&
549 detach_property_at_index < kPropCount);
550 CHECK(property_index < kPropCount);
551 CHECK_NE(detach_property_at_index, property_index);
553 const bool is_detached_map = detach_property_at_index >= 0;
555 Expectations expectations(isolate);
557 // Create a map, add required properties to it and initialize expectations.
558 Handle<Map> initial_map = Map::Create(isolate, 0);
559 Handle<Map> map = initial_map;
560 Handle<Map> detach_point_map;
561 for (int i = 0; i < kPropCount; i++) {
562 if (i == property_index) {
564 expectations.AddDataField(map, NONE, from_representation, from_type);
567 expectations.AddDataField(map, NONE, Representation::Smi(), any_type);
568 if (i == detach_property_at_index) {
569 detach_point_map = map;
573 CHECK(!map->is_deprecated());
574 CHECK(map->is_stable());
575 CHECK(expectations.Check(*map));
578 FakeStubForTesting stub(isolate);
580 if (is_detached_map) {
581 detach_point_map = Map::ReconfigureProperty(
582 detach_point_map, detach_property_at_index, kData, NONE,
583 Representation::Tagged(), any_type, FORCE_FIELD);
584 expectations.SetDataField(detach_property_at_index,
585 Representation::Tagged(), any_type);
586 CHECK(map->is_deprecated());
587 CHECK(expectations.Check(*detach_point_map,
588 detach_point_map->NumberOfOwnDescriptors()));
591 // Create new maps by generalizing representation of propX field.
592 Handle<Map> field_owner(map->FindFieldOwner(property_index), isolate);
593 CompilationInfo info(&stub, isolate, &zone);
594 CHECK(!info.HasAbortedDueToDependencyChange());
596 Map::AddDependentCompilationInfo(field_owner, DependentCode::kFieldTypeGroup,
599 Handle<Map> new_map =
600 Map::ReconfigureProperty(map, property_index, kData, NONE,
601 to_representation, to_type, FORCE_FIELD);
603 expectations.SetDataField(property_index, expected_representation,
606 CHECK(!new_map->is_deprecated());
607 CHECK(expectations.Check(*new_map));
609 if (is_detached_map) {
610 CHECK(map->is_deprecated());
611 CHECK_NE(*map, *new_map);
612 CHECK_EQ(expected_field_type_dependency && !field_owner->is_deprecated(),
613 info.HasAbortedDueToDependencyChange());
615 } else if (expected_deprecation) {
616 CHECK(map->is_deprecated());
617 CHECK(field_owner->is_deprecated());
618 CHECK_NE(*map, *new_map);
619 CHECK(!info.HasAbortedDueToDependencyChange());
622 CHECK(!field_owner->is_deprecated());
623 CHECK_EQ(*map, *new_map);
625 CHECK_EQ(expected_field_type_dependency,
626 info.HasAbortedDueToDependencyChange());
629 info.RollbackDependencies(); // Properly cleanup compilation info.
631 // Update all deprecated maps and check that they are now the same.
632 Handle<Map> updated_map = Map::Update(map);
633 CHECK_EQ(*new_map, *updated_map);
637 static void TestGeneralizeRepresentation(
638 Representation from_representation, Handle<HeapType> from_type,
639 Representation to_representation, Handle<HeapType> to_type,
640 Representation expected_representation, Handle<HeapType> expected_type,
641 bool expected_deprecation, bool expected_field_type_dependency) {
642 // Check the cases when the map being reconfigured is a part of the
644 STATIC_ASSERT(kPropCount > 4);
645 int indices[] = {0, 2, kPropCount - 1};
646 for (int i = 0; i < static_cast<int>(arraysize(indices)); i++) {
647 TestGeneralizeRepresentation(
648 -1, indices[i], from_representation, from_type, to_representation,
649 to_type, expected_representation, expected_type, expected_deprecation,
650 expected_field_type_dependency);
653 if (!from_representation.IsNone()) {
654 // Check the cases when the map being reconfigured is NOT a part of the
655 // transition tree. "None -> anything" representation changes make sense
656 // only for "attached" maps.
657 int indices[] = {0, kPropCount - 1};
658 for (int i = 0; i < static_cast<int>(arraysize(indices)); i++) {
659 TestGeneralizeRepresentation(
660 indices[i], 2, from_representation, from_type, to_representation,
661 to_type, expected_representation, expected_type, expected_deprecation,
662 expected_field_type_dependency);
668 static void TestGeneralizeRepresentation(Representation from_representation,
669 Handle<HeapType> from_type,
670 Representation to_representation,
671 Handle<HeapType> to_type,
672 Representation expected_representation,
673 Handle<HeapType> expected_type) {
674 const bool expected_deprecation = true;
675 const bool expected_field_type_dependency = false;
677 TestGeneralizeRepresentation(
678 from_representation, from_type, to_representation, to_type,
679 expected_representation, expected_type, expected_deprecation,
680 expected_field_type_dependency);
684 static void TestGeneralizeRepresentationTrivial(
685 Representation from_representation, Handle<HeapType> from_type,
686 Representation to_representation, Handle<HeapType> to_type,
687 Representation expected_representation, Handle<HeapType> expected_type,
688 bool expected_field_type_dependency = true) {
689 const bool expected_deprecation = false;
691 TestGeneralizeRepresentation(
692 from_representation, from_type, to_representation, to_type,
693 expected_representation, expected_type, expected_deprecation,
694 expected_field_type_dependency);
698 TEST(GeneralizeRepresentationSmiToDouble) {
699 CcTest::InitializeVM();
700 v8::HandleScope scope(CcTest::isolate());
701 Isolate* isolate = CcTest::i_isolate();
702 Handle<HeapType> any_type = HeapType::Any(isolate);
704 TestGeneralizeRepresentation(Representation::Smi(), any_type,
705 Representation::Double(), any_type,
706 Representation::Double(), any_type);
710 TEST(GeneralizeRepresentationSmiToTagged) {
711 CcTest::InitializeVM();
712 v8::HandleScope scope(CcTest::isolate());
713 Isolate* isolate = CcTest::i_isolate();
714 Handle<HeapType> any_type = HeapType::Any(isolate);
715 Handle<HeapType> value_type =
716 HeapType::Class(Map::Create(isolate, 0), isolate);
718 TestGeneralizeRepresentation(Representation::Smi(), any_type,
719 Representation::HeapObject(), value_type,
720 Representation::Tagged(), any_type);
724 TEST(GeneralizeRepresentationDoubleToTagged) {
725 CcTest::InitializeVM();
726 v8::HandleScope scope(CcTest::isolate());
727 Isolate* isolate = CcTest::i_isolate();
728 Handle<HeapType> any_type = HeapType::Any(isolate);
729 Handle<HeapType> value_type =
730 HeapType::Class(Map::Create(isolate, 0), isolate);
732 TestGeneralizeRepresentation(Representation::Double(), any_type,
733 Representation::HeapObject(), value_type,
734 Representation::Tagged(), any_type);
738 TEST(GeneralizeRepresentationHeapObjectToTagged) {
739 CcTest::InitializeVM();
740 v8::HandleScope scope(CcTest::isolate());
741 Isolate* isolate = CcTest::i_isolate();
742 Handle<HeapType> any_type = HeapType::Any(isolate);
743 Handle<HeapType> value_type =
744 HeapType::Class(Map::Create(isolate, 0), isolate);
746 TestGeneralizeRepresentation(Representation::HeapObject(), value_type,
747 Representation::Smi(), any_type,
748 Representation::Tagged(), any_type);
752 TEST(GeneralizeRepresentationHeapObjectToHeapObject) {
753 CcTest::InitializeVM();
754 v8::HandleScope scope(CcTest::isolate());
755 Isolate* isolate = CcTest::i_isolate();
756 Handle<HeapType> any_type = HeapType::Any(isolate);
758 const int kMaxClassesPerFieldType = 1;
759 Handle<HeapType> current_type =
760 HeapType::Class(Map::Create(isolate, 0), isolate);
762 for (int i = 0; i < kMaxClassesPerFieldType; i++) {
763 Handle<HeapType> new_type =
764 HeapType::Class(Map::Create(isolate, 0), isolate);
766 Handle<HeapType> expected_type =
767 (i < kMaxClassesPerFieldType - 1)
768 ? HeapType::Union(current_type, new_type, isolate)
771 TestGeneralizeRepresentationTrivial(
772 Representation::HeapObject(), current_type,
773 Representation::HeapObject(), new_type, Representation::HeapObject(),
775 current_type = expected_type;
778 Handle<HeapType> new_type = HeapType::Class(Map::Create(isolate, 0), isolate);
780 TestGeneralizeRepresentationTrivial(
781 Representation::HeapObject(), any_type, Representation::HeapObject(),
782 new_type, Representation::HeapObject(), any_type, false);
786 TEST(GeneralizeRepresentationNoneToSmi) {
787 CcTest::InitializeVM();
788 v8::HandleScope scope(CcTest::isolate());
789 Isolate* isolate = CcTest::i_isolate();
790 Handle<HeapType> none_type = HeapType::None(isolate);
791 Handle<HeapType> any_type = HeapType::Any(isolate);
793 // None -> Smi representation change is trivial.
794 TestGeneralizeRepresentationTrivial(Representation::None(), none_type,
795 Representation::Smi(), any_type,
796 Representation::Smi(), any_type);
800 TEST(GeneralizeRepresentationNoneToDouble) {
801 CcTest::InitializeVM();
802 v8::HandleScope scope(CcTest::isolate());
803 Isolate* isolate = CcTest::i_isolate();
804 Handle<HeapType> none_type = HeapType::None(isolate);
805 Handle<HeapType> any_type = HeapType::Any(isolate);
807 // None -> Double representation change is NOT trivial.
808 TestGeneralizeRepresentation(Representation::None(), none_type,
809 Representation::Double(), any_type,
810 Representation::Double(), any_type);
814 TEST(GeneralizeRepresentationNoneToHeapObject) {
815 CcTest::InitializeVM();
816 v8::HandleScope scope(CcTest::isolate());
817 Isolate* isolate = CcTest::i_isolate();
818 Handle<HeapType> none_type = HeapType::None(isolate);
819 Handle<HeapType> value_type =
820 HeapType::Class(Map::Create(isolate, 0), isolate);
822 // None -> HeapObject representation change is trivial.
823 TestGeneralizeRepresentationTrivial(Representation::None(), none_type,
824 Representation::HeapObject(), value_type,
825 Representation::HeapObject(), value_type);
829 TEST(GeneralizeRepresentationNoneToTagged) {
830 CcTest::InitializeVM();
831 v8::HandleScope scope(CcTest::isolate());
832 Isolate* isolate = CcTest::i_isolate();
833 Handle<HeapType> none_type = HeapType::None(isolate);
834 Handle<HeapType> any_type = HeapType::Any(isolate);
836 // None -> HeapObject representation change is trivial.
837 TestGeneralizeRepresentationTrivial(Representation::None(), none_type,
838 Representation::Tagged(), any_type,
839 Representation::Tagged(), any_type);
843 ////////////////////////////////////////////////////////////////////////////////
844 // A set of tests for representation generalization case with kAccessor
848 TEST(GeneralizeRepresentationWithAccessorProperties) {
849 CcTest::InitializeVM();
850 v8::HandleScope scope(CcTest::isolate());
851 Isolate* isolate = CcTest::i_isolate();
852 Handle<HeapType> any_type = HeapType::Any(isolate);
853 Handle<AccessorPair> pair = CreateAccessorPair(true, true);
855 const int kAccessorProp = kPropCount / 2;
856 Expectations expectations(isolate);
858 // Create a map, add required properties to it and initialize expectations.
859 Handle<Map> initial_map = Map::Create(isolate, 0);
860 Handle<Map> map = initial_map;
861 for (int i = 0; i < kPropCount; i++) {
862 if (i == kAccessorProp) {
863 map = expectations.AddAccessorConstant(map, NONE, pair);
866 expectations.AddDataField(map, NONE, Representation::Smi(), any_type);
869 CHECK(!map->is_deprecated());
870 CHECK(map->is_stable());
871 CHECK(expectations.Check(*map));
873 // Create new maps by generalizing representation of propX field.
874 Handle<Map> maps[kPropCount];
875 for (int i = 0; i < kPropCount; i++) {
876 if (i == kAccessorProp) {
877 // Skip accessor property reconfiguration.
878 maps[i] = maps[i - 1];
881 Handle<Map> new_map = Map::ReconfigureProperty(
882 map, i, kData, NONE, Representation::Double(), any_type, FORCE_FIELD);
885 expectations.SetDataField(i, Representation::Double(), any_type);
887 CHECK(map->is_deprecated());
888 CHECK_NE(*map, *new_map);
889 CHECK(i == 0 || maps[i - 1]->is_deprecated());
891 CHECK(!new_map->is_deprecated());
892 CHECK(expectations.Check(*new_map));
895 Handle<Map> active_map = maps[kPropCount - 1];
896 CHECK(!active_map->is_deprecated());
898 // Update all deprecated maps and check that they are now the same.
899 Handle<Map> updated_map = Map::Update(map);
900 CHECK_EQ(*active_map, *updated_map);
901 for (int i = 0; i < kPropCount; i++) {
902 updated_map = Map::Update(maps[i]);
903 CHECK_EQ(*active_map, *updated_map);
908 ////////////////////////////////////////////////////////////////////////////////
909 // A set of tests for attribute reconfiguration case.
912 // This test ensures that representation/field type generalization is correctly
913 // propagated from one branch of transition tree (|map2|) to another (|map|).
915 // + - p2B - p3 - p4: |map2|
917 // {} - p0 - p1 - p2A - p3 - p4: |map|
919 // where "p2A" and "p2B" differ only in the attributes.
921 static void TestReconfigureDataFieldAttribute_GeneralizeRepresentation(
922 Representation from_representation, Handle<HeapType> from_type,
923 Representation to_representation, Handle<HeapType> to_type,
924 Representation expected_representation, Handle<HeapType> expected_type) {
925 Isolate* isolate = CcTest::i_isolate();
927 Expectations expectations(isolate);
929 // Create a map, add required properties to it and initialize expectations.
930 Handle<Map> initial_map = Map::Create(isolate, 0);
931 Handle<Map> map = initial_map;
932 for (int i = 0; i < kPropCount; i++) {
933 map = expectations.AddDataField(map, NONE, from_representation, from_type);
935 CHECK(!map->is_deprecated());
936 CHECK(map->is_stable());
937 CHECK(expectations.Check(*map));
940 // Create another branch in transition tree (property at index |kSplitProp|
941 // has different attributes), initialize expectations.
942 const int kSplitProp = kPropCount / 2;
943 Expectations expectations2(isolate);
945 Handle<Map> map2 = initial_map;
946 for (int i = 0; i < kSplitProp; i++) {
947 map2 = expectations2.FollowDataTransition(map2, NONE, from_representation,
951 expectations2.AddDataField(map2, READ_ONLY, to_representation, to_type);
953 for (int i = kSplitProp + 1; i < kPropCount; i++) {
954 map2 = expectations2.AddDataField(map2, NONE, to_representation, to_type);
956 CHECK(!map2->is_deprecated());
957 CHECK(map2->is_stable());
958 CHECK(expectations2.Check(*map2));
961 FakeStubForTesting stub(isolate);
962 Handle<Map> field_owner(map->FindFieldOwner(kSplitProp), isolate);
963 CompilationInfo info(&stub, isolate, &zone);
964 CHECK(!info.HasAbortedDueToDependencyChange());
965 Map::AddDependentCompilationInfo(field_owner, DependentCode::kFieldTypeGroup,
968 // Reconfigure attributes of property |kSplitProp| of |map2| to NONE, which
969 // should generalize representations in |map1|.
970 Handle<Map> new_map =
971 Map::ReconfigureExistingProperty(map2, kSplitProp, kData, NONE);
973 // |map2| should be left unchanged.
974 CHECK(!map2->is_deprecated());
975 CHECK_NE(*map2, *new_map);
976 CHECK(expectations2.Check(*map2));
978 // |map| should be deprecated and |new_map| should match new expectations.
979 for (int i = kSplitProp; i < kPropCount; i++) {
980 expectations.SetDataField(i, expected_representation, expected_type);
982 CHECK(map->is_deprecated());
983 CHECK(!info.HasAbortedDueToDependencyChange());
984 info.RollbackDependencies(); // Properly cleanup compilation info.
985 CHECK_NE(*map, *new_map);
987 CHECK(!new_map->is_deprecated());
988 CHECK(expectations.Check(*new_map));
990 // Update deprecated |map|, it should become |new_map|.
991 Handle<Map> updated_map = Map::Update(map);
992 CHECK_EQ(*new_map, *updated_map);
996 // This test ensures that trivial representation/field type generalization
997 // (from HeapObject to HeapObject) is correctly propagated from one branch of
998 // transition tree (|map2|) to another (|map|).
1000 // + - p2B - p3 - p4: |map2|
1002 // {} - p0 - p1 - p2A - p3 - p4: |map|
1004 // where "p2A" and "p2B" differ only in the attributes.
1006 static void TestReconfigureDataFieldAttribute_GeneralizeRepresentationTrivial(
1007 Representation from_representation, Handle<HeapType> from_type,
1008 Representation to_representation, Handle<HeapType> to_type,
1009 Representation expected_representation, Handle<HeapType> expected_type,
1010 bool expected_field_type_dependency = true) {
1011 Isolate* isolate = CcTest::i_isolate();
1013 Expectations expectations(isolate);
1015 // Create a map, add required properties to it and initialize expectations.
1016 Handle<Map> initial_map = Map::Create(isolate, 0);
1017 Handle<Map> map = initial_map;
1018 for (int i = 0; i < kPropCount; i++) {
1019 map = expectations.AddDataField(map, NONE, from_representation, from_type);
1021 CHECK(!map->is_deprecated());
1022 CHECK(map->is_stable());
1023 CHECK(expectations.Check(*map));
1026 // Create another branch in transition tree (property at index |kSplitProp|
1027 // has different attributes), initialize expectations.
1028 const int kSplitProp = kPropCount / 2;
1029 Expectations expectations2(isolate);
1031 Handle<Map> map2 = initial_map;
1032 for (int i = 0; i < kSplitProp; i++) {
1033 map2 = expectations2.FollowDataTransition(map2, NONE, from_representation,
1037 expectations2.AddDataField(map2, READ_ONLY, to_representation, to_type);
1039 for (int i = kSplitProp + 1; i < kPropCount; i++) {
1040 map2 = expectations2.AddDataField(map2, NONE, to_representation, to_type);
1042 CHECK(!map2->is_deprecated());
1043 CHECK(map2->is_stable());
1044 CHECK(expectations2.Check(*map2));
1047 FakeStubForTesting stub(isolate);
1048 Handle<Map> field_owner(map->FindFieldOwner(kSplitProp), isolate);
1049 CompilationInfo info(&stub, isolate, &zone);
1050 CHECK(!info.HasAbortedDueToDependencyChange());
1051 Map::AddDependentCompilationInfo(field_owner, DependentCode::kFieldTypeGroup,
1054 // Reconfigure attributes of property |kSplitProp| of |map2| to NONE, which
1055 // should generalize representations in |map1|.
1056 Handle<Map> new_map =
1057 Map::ReconfigureExistingProperty(map2, kSplitProp, kData, NONE);
1059 // |map2| should be left unchanged.
1060 CHECK(!map2->is_deprecated());
1061 CHECK_NE(*map2, *new_map);
1062 CHECK(expectations2.Check(*map2));
1064 // In trivial case |map| should be returned as a result of the property
1065 // reconfiguration, respective field types should be generalized and
1066 // respective code dependencies should be invalidated. |map| should be NOT
1067 // deprecated and it should match new expectations.
1068 for (int i = kSplitProp; i < kPropCount; i++) {
1069 expectations.SetDataField(i, expected_representation, expected_type);
1071 CHECK(!map->is_deprecated());
1072 CHECK_EQ(*map, *new_map);
1073 CHECK_EQ(expected_field_type_dependency,
1074 info.HasAbortedDueToDependencyChange());
1075 info.RollbackDependencies(); // Properly cleanup compilation info.
1077 CHECK(!new_map->is_deprecated());
1078 CHECK(expectations.Check(*new_map));
1080 Handle<Map> updated_map = Map::Update(map);
1081 CHECK_EQ(*new_map, *updated_map);
1085 TEST(ReconfigureDataFieldAttribute_GeneralizeRepresentationSmiToDouble) {
1086 CcTest::InitializeVM();
1087 v8::HandleScope scope(CcTest::isolate());
1088 Isolate* isolate = CcTest::i_isolate();
1089 Handle<HeapType> any_type = HeapType::Any(isolate);
1091 TestReconfigureDataFieldAttribute_GeneralizeRepresentation(
1092 Representation::Smi(), any_type, Representation::Double(), any_type,
1093 Representation::Double(), any_type);
1097 TEST(ReconfigureDataFieldAttribute_GeneralizeRepresentationSmiToTagged) {
1098 CcTest::InitializeVM();
1099 v8::HandleScope scope(CcTest::isolate());
1100 Isolate* isolate = CcTest::i_isolate();
1101 Handle<HeapType> any_type = HeapType::Any(isolate);
1102 Handle<HeapType> value_type =
1103 HeapType::Class(Map::Create(isolate, 0), isolate);
1105 TestReconfigureDataFieldAttribute_GeneralizeRepresentation(
1106 Representation::Smi(), any_type, Representation::HeapObject(), value_type,
1107 Representation::Tagged(), any_type);
1111 TEST(ReconfigureDataFieldAttribute_GeneralizeRepresentationDoubleToTagged) {
1112 CcTest::InitializeVM();
1113 v8::HandleScope scope(CcTest::isolate());
1114 Isolate* isolate = CcTest::i_isolate();
1115 Handle<HeapType> any_type = HeapType::Any(isolate);
1116 Handle<HeapType> value_type =
1117 HeapType::Class(Map::Create(isolate, 0), isolate);
1119 TestReconfigureDataFieldAttribute_GeneralizeRepresentation(
1120 Representation::Double(), any_type, Representation::HeapObject(),
1121 value_type, Representation::Tagged(), any_type);
1125 TEST(ReconfigureDataFieldAttribute_GeneralizeRepresentationHeapObjToHeapObj) {
1126 CcTest::InitializeVM();
1127 v8::HandleScope scope(CcTest::isolate());
1128 Isolate* isolate = CcTest::i_isolate();
1129 Handle<HeapType> any_type = HeapType::Any(isolate);
1131 const int kMaxClassesPerFieldType = 1;
1132 Handle<HeapType> current_type =
1133 HeapType::Class(Map::Create(isolate, 0), isolate);
1135 for (int i = 0; i < kMaxClassesPerFieldType; i++) {
1136 Handle<HeapType> new_type =
1137 HeapType::Class(Map::Create(isolate, 0), isolate);
1139 Handle<HeapType> expected_type =
1140 (i < kMaxClassesPerFieldType - 1)
1141 ? HeapType::Union(current_type, new_type, isolate)
1144 TestReconfigureDataFieldAttribute_GeneralizeRepresentationTrivial(
1145 Representation::HeapObject(), current_type,
1146 Representation::HeapObject(), new_type, Representation::HeapObject(),
1148 current_type = expected_type;
1151 Handle<HeapType> new_type = HeapType::Class(Map::Create(isolate, 0), isolate);
1153 TestReconfigureDataFieldAttribute_GeneralizeRepresentationTrivial(
1154 Representation::HeapObject(), any_type, Representation::HeapObject(),
1155 new_type, Representation::HeapObject(), any_type, false);
1159 TEST(ReconfigureDataFieldAttribute_GeneralizeRepresentationHeapObjectToTagged) {
1160 CcTest::InitializeVM();
1161 v8::HandleScope scope(CcTest::isolate());
1162 Isolate* isolate = CcTest::i_isolate();
1163 Handle<HeapType> any_type = HeapType::Any(isolate);
1164 Handle<HeapType> value_type =
1165 HeapType::Class(Map::Create(isolate, 0), isolate);
1167 TestReconfigureDataFieldAttribute_GeneralizeRepresentation(
1168 Representation::HeapObject(), value_type, Representation::Smi(), any_type,
1169 Representation::Tagged(), any_type);
1173 // Checks that given |map| is deprecated and that it updates to given |new_map|
1174 // which in turn should match expectations.
1175 struct CheckDeprecated {
1176 void Check(Handle<Map> map, Handle<Map> new_map,
1177 const Expectations& expectations) {
1178 CHECK(map->is_deprecated());
1179 CHECK_NE(*map, *new_map);
1181 CHECK(!new_map->is_deprecated());
1182 CHECK(expectations.Check(*new_map));
1184 // Update deprecated |map|, it should become |new_map|.
1185 Handle<Map> updated_map = Map::Update(map);
1186 CHECK_EQ(*new_map, *updated_map);
1191 // Checks that given |map| is NOT deprecated, equals to given |new_map| and
1192 // matches expectations.
1193 struct CheckSameMap {
1194 void Check(Handle<Map> map, Handle<Map> new_map,
1195 const Expectations& expectations) {
1196 CHECK(!map->is_deprecated());
1197 CHECK_EQ(*map, *new_map);
1199 CHECK(!new_map->is_deprecated());
1200 CHECK(expectations.Check(*new_map));
1202 // Update deprecated |map|, it should become |new_map|.
1203 Handle<Map> updated_map = Map::Update(map);
1204 CHECK_EQ(*new_map, *updated_map);
1209 // Checks that given |map| is NOT deprecated, and |new_map| is a result of
1210 // copy-generalize-all-representations.
1211 struct CheckCopyGeneralizeAllRepresentations {
1212 void Check(Handle<Map> map, Handle<Map> new_map, Expectations& expectations) {
1213 CHECK(!map->is_deprecated());
1214 CHECK_NE(*map, *new_map);
1216 CHECK(new_map->GetBackPointer()->IsUndefined());
1217 for (int i = 0; i < kPropCount; i++) {
1218 expectations.GeneralizeRepresentation(i);
1221 CHECK(!new_map->is_deprecated());
1222 CHECK(expectations.Check(*new_map));
1227 // This test ensures that representation/field type generalization is correctly
1228 // propagated from one branch of transition tree (|map2|) to another (|map1|).
1230 // + - p2B - p3 - p4: |map2|
1232 // {} - p0 - p1: |map|
1234 // + - p2A - p3 - p4: |map1|
1236 // + - the property customized by the TestConfig provided
1238 // where "p2A" and "p2B" differ only in the attributes.
1240 template <typename TestConfig, typename Checker>
1241 static void TestReconfigureProperty_CustomPropertyAfterTargetMap(
1242 TestConfig& config, Checker& checker) {
1243 Isolate* isolate = CcTest::i_isolate();
1244 Handle<HeapType> any_type = HeapType::Any(isolate);
1246 const int kCustomPropIndex = kPropCount - 2;
1247 Expectations expectations(isolate);
1249 const int kSplitProp = 2;
1250 CHECK(kSplitProp < kCustomPropIndex);
1252 const Representation representation = Representation::Smi();
1254 // Create common part of transition tree.
1255 Handle<Map> initial_map = Map::Create(isolate, 0);
1256 Handle<Map> map = initial_map;
1257 for (int i = 0; i < kSplitProp; i++) {
1258 map = expectations.AddDataField(map, NONE, representation, any_type);
1260 CHECK(!map->is_deprecated());
1261 CHECK(map->is_stable());
1262 CHECK(expectations.Check(*map));
1265 // Create branch to |map1|.
1266 Handle<Map> map1 = map;
1267 Expectations expectations1 = expectations;
1268 for (int i = kSplitProp; i < kCustomPropIndex; i++) {
1269 map1 = expectations1.AddDataField(map1, NONE, representation, any_type);
1271 map1 = config.AddPropertyAtBranch(1, expectations1, map1);
1272 for (int i = kCustomPropIndex + 1; i < kPropCount; i++) {
1273 map1 = expectations1.AddDataField(map1, NONE, representation, any_type);
1275 CHECK(!map1->is_deprecated());
1276 CHECK(map1->is_stable());
1277 CHECK(expectations1.Check(*map1));
1280 // Create another branch in transition tree (property at index |kSplitProp|
1281 // has different attributes), initialize expectations.
1282 Handle<Map> map2 = map;
1283 Expectations expectations2 = expectations;
1284 map2 = expectations2.AddDataField(map2, READ_ONLY, representation, any_type);
1285 for (int i = kSplitProp + 1; i < kCustomPropIndex; i++) {
1286 map2 = expectations2.AddDataField(map2, NONE, representation, any_type);
1288 map2 = config.AddPropertyAtBranch(2, expectations2, map2);
1289 for (int i = kCustomPropIndex + 1; i < kPropCount; i++) {
1290 map2 = expectations2.AddDataField(map2, NONE, representation, any_type);
1292 CHECK(!map2->is_deprecated());
1293 CHECK(map2->is_stable());
1294 CHECK(expectations2.Check(*map2));
1297 // Reconfigure attributes of property |kSplitProp| of |map2| to NONE, which
1298 // should generalize representations in |map1|.
1299 Handle<Map> new_map =
1300 Map::ReconfigureExistingProperty(map2, kSplitProp, kData, NONE);
1302 // |map2| should be left unchanged.
1303 CHECK(!map2->is_deprecated());
1304 CHECK_NE(*map2, *new_map);
1305 CHECK(expectations2.Check(*map2));
1307 config.UpdateExpectations(kCustomPropIndex, expectations1);
1308 checker.Check(map1, new_map, expectations1);
1312 TEST(ReconfigureDataFieldAttribute_SameDataConstantAfterTargetMap) {
1313 CcTest::InitializeVM();
1314 v8::HandleScope scope(CcTest::isolate());
1317 Handle<JSFunction> js_func_;
1319 Isolate* isolate = CcTest::i_isolate();
1320 Factory* factory = isolate->factory();
1321 js_func_ = factory->NewFunction(factory->empty_string());
1324 Handle<Map> AddPropertyAtBranch(int branch_id, Expectations& expectations,
1326 CHECK(branch_id == 1 || branch_id == 2);
1327 // Add the same data constant property at both transition tree branches.
1328 return expectations.AddDataConstant(map, NONE, js_func_);
1331 void UpdateExpectations(int property_index, Expectations& expectations) {
1332 // Expectations stay the same.
1337 // Two branches are "compatible" so the |map1| should NOT be deprecated.
1338 CheckSameMap checker;
1339 TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker);
1343 TEST(ReconfigureDataFieldAttribute_DataConstantToDataFieldAfterTargetMap) {
1344 CcTest::InitializeVM();
1345 v8::HandleScope scope(CcTest::isolate());
1348 Handle<JSFunction> js_func1_;
1349 Handle<JSFunction> js_func2_;
1351 Isolate* isolate = CcTest::i_isolate();
1352 Factory* factory = isolate->factory();
1353 js_func1_ = factory->NewFunction(factory->empty_string());
1354 js_func2_ = factory->NewFunction(factory->empty_string());
1357 Handle<Map> AddPropertyAtBranch(int branch_id, Expectations& expectations,
1359 CHECK(branch_id == 1 || branch_id == 2);
1360 Handle<JSFunction> js_func = branch_id == 1 ? js_func1_ : js_func2_;
1361 return expectations.AddDataConstant(map, NONE, js_func);
1364 void UpdateExpectations(int property_index, Expectations& expectations) {
1365 Isolate* isolate = CcTest::i_isolate();
1366 Handle<HeapType> any_type = HeapType::Any(isolate);
1367 expectations.SetDataField(property_index, Representation::HeapObject(),
1373 // Two branches are "incompatible" so the |map1| should be deprecated.
1374 CheckDeprecated checker;
1375 TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker);
1379 TEST(ReconfigureDataFieldAttribute_SameAccessorConstantAfterTargetMap) {
1380 CcTest::InitializeVM();
1381 v8::HandleScope scope(CcTest::isolate());
1384 Handle<AccessorPair> pair_;
1385 TestConfig() { pair_ = CreateAccessorPair(true, true); }
1387 Handle<Map> AddPropertyAtBranch(int branch_id, Expectations& expectations,
1389 CHECK(branch_id == 1 || branch_id == 2);
1390 // Add the same accessor constant property at both transition tree
1392 return expectations.AddAccessorConstant(map, NONE, pair_);
1395 bool UpdateExpectations(int property_index, Expectations& expectations) {
1396 // Two branches are "compatible" so the |map1| should NOT be deprecated.
1402 CheckSameMap checker;
1403 TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker);
1407 TEST(ReconfigureDataFieldAttribute_AccConstantToAccFieldAfterTargetMap) {
1408 CcTest::InitializeVM();
1409 v8::HandleScope scope(CcTest::isolate());
1412 Handle<AccessorPair> pair1_;
1413 Handle<AccessorPair> pair2_;
1415 pair1_ = CreateAccessorPair(true, true);
1416 pair2_ = CreateAccessorPair(true, true);
1419 Handle<Map> AddPropertyAtBranch(int branch_id, Expectations& expectations,
1421 CHECK(branch_id == 1 || branch_id == 2);
1422 Handle<AccessorPair> pair = branch_id == 1 ? pair1_ : pair2_;
1423 return expectations.AddAccessorConstant(map, NONE, pair);
1426 void UpdateExpectations(int property_index, Expectations& expectations) {
1427 if (IS_ACCESSOR_FIELD_SUPPORTED) {
1428 expectations.SetAccessorField(property_index);
1430 // Currently we have a copy-generalize-all-representations case and
1431 // ACCESSOR property becomes ACCESSOR_CONSTANT.
1432 expectations.SetAccessorConstant(property_index, pair2_);
1438 if (IS_ACCESSOR_FIELD_SUPPORTED) {
1439 CheckCopyGeneralizeAllRepresentations checker;
1440 TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker);
1442 // Currently we have a copy-generalize-all-representations case.
1443 CheckCopyGeneralizeAllRepresentations checker;
1444 TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker);
1449 ////////////////////////////////////////////////////////////////////////////////
1450 // A set of tests checking split map deprecation.
1453 TEST(ReconfigurePropertySplitMapTransitionsOverflow) {
1454 CcTest::InitializeVM();
1455 v8::HandleScope scope(CcTest::isolate());
1456 Isolate* isolate = CcTest::i_isolate();
1457 Handle<HeapType> any_type = HeapType::Any(isolate);
1459 Expectations expectations(isolate);
1461 // Create a map, add required properties to it and initialize expectations.
1462 Handle<Map> initial_map = Map::Create(isolate, 0);
1463 Handle<Map> map = initial_map;
1464 for (int i = 0; i < kPropCount; i++) {
1465 map = expectations.AddDataField(map, NONE, Representation::Smi(), any_type);
1467 CHECK(!map->is_deprecated());
1468 CHECK(map->is_stable());
1470 // Generalize representation of property at index |kSplitProp|.
1471 const int kSplitProp = kPropCount / 2;
1472 Handle<Map> split_map;
1473 Handle<Map> map2 = initial_map;
1475 for (int i = 0; i < kSplitProp + 1; i++) {
1476 if (i == kSplitProp) {
1480 Handle<String> name = MakeName("prop", i);
1482 TransitionArray::SearchTransition(*map2, kData, *name, NONE);
1483 CHECK(target != NULL);
1484 map2 = handle(target);
1487 map2 = Map::ReconfigureProperty(map2, kSplitProp, kData, NONE,
1488 Representation::Double(), any_type,
1490 expectations.SetDataField(kSplitProp, Representation::Double(), any_type);
1492 CHECK(expectations.Check(*split_map, kSplitProp));
1493 CHECK(expectations.Check(*map2, kSplitProp + 1));
1496 // At this point |map| should be deprecated and disconnected from the
1498 CHECK(map->is_deprecated());
1499 CHECK(!split_map->is_deprecated());
1500 CHECK(!map2->is_deprecated());
1502 // Fill in transition tree of |map2| so that it can't have more transitions.
1503 for (int i = 0; i < TransitionArray::kMaxNumberOfTransitions; i++) {
1504 CHECK(TransitionArray::CanHaveMoreTransitions(map2));
1505 Handle<String> name = MakeName("foo", i);
1506 Map::CopyWithField(map2, name, any_type, NONE, Representation::Smi(),
1507 INSERT_TRANSITION).ToHandleChecked();
1509 CHECK(!TransitionArray::CanHaveMoreTransitions(map2));
1511 // Try to update |map|, since there is no place for propX transition at |map2|
1512 // |map| should become "copy-generalized".
1513 Handle<Map> updated_map = Map::Update(map);
1514 CHECK(updated_map->GetBackPointer()->IsUndefined());
1516 for (int i = 0; i < kPropCount; i++) {
1517 expectations.SetDataField(i, Representation::Tagged(), any_type);
1519 CHECK(expectations.Check(*updated_map));
1523 ////////////////////////////////////////////////////////////////////////////////
1524 // A set of tests involving special transitions (such as elements kind
1525 // transition, observed transition or prototype transition).
1528 // This test ensures that representation/field type generalization is correctly
1529 // propagated from one branch of transition tree (|map2|) to another (|map|).
1533 // * - special transition
1535 // {} - p0 - p1 - p2A - p3 - p4A: |map|
1537 // where "p4A" and "p4B" are exactly the same properties.
1539 // TODO(ishell): unify this test template with
1540 // TestReconfigureDataFieldAttribute_GeneralizeRepresentation once
1541 // IS_PROTO_TRANS_ISSUE_FIXED and IS_NON_EQUIVALENT_TRANSITION_SUPPORTED are
1543 template <typename TestConfig>
1544 static void TestGeneralizeRepresentationWithSpecialTransition(
1545 TestConfig& config, Representation from_representation,
1546 Handle<HeapType> from_type, Representation to_representation,
1547 Handle<HeapType> to_type, Representation expected_representation,
1548 Handle<HeapType> expected_type) {
1549 Isolate* isolate = CcTest::i_isolate();
1551 Expectations expectations(isolate);
1553 // Create a map, add required properties to it and initialize expectations.
1554 Handle<Map> initial_map = Map::Create(isolate, 0);
1555 Handle<Map> map = initial_map;
1556 for (int i = 0; i < kPropCount; i++) {
1557 map = expectations.AddDataField(map, NONE, from_representation, from_type);
1559 CHECK(!map->is_deprecated());
1560 CHECK(map->is_stable());
1561 CHECK(expectations.Check(*map));
1563 // Apply some special transition to |map|.
1564 CHECK(map->owns_descriptors());
1565 Handle<Map> map2 = config.Transition(map);
1567 // |map| should still match expectations.
1568 CHECK(!map->is_deprecated());
1569 CHECK(expectations.Check(*map));
1571 Expectations expectations2 = expectations;
1572 if (config.generalizes_representations()) {
1573 for (int i = 0; i < kPropCount; i++) {
1574 expectations2.GeneralizeRepresentation(i);
1578 CHECK(!map2->is_deprecated());
1579 CHECK(map2->is_stable());
1580 CHECK(expectations2.Check(*map2));
1582 // Create new maps by generalizing representation of propX field.
1583 Handle<Map> maps[kPropCount];
1584 for (int i = 0; i < kPropCount; i++) {
1585 Handle<Map> new_map = Map::ReconfigureProperty(
1586 map, i, kData, NONE, to_representation, to_type, FORCE_FIELD);
1589 expectations.SetDataField(i, expected_representation, expected_type);
1591 CHECK(map->is_deprecated());
1592 CHECK_NE(*map, *new_map);
1593 CHECK(i == 0 || maps[i - 1]->is_deprecated());
1594 CHECK(expectations.Check(*new_map));
1596 Handle<Map> new_map2 = Map::Update(map2);
1597 CHECK(!new_map2->is_deprecated());
1598 CHECK(!new_map2->is_dictionary_map());
1600 if (!IS_NON_EQUIVALENT_TRANSITION_SUPPORTED) {
1601 // In case of non-equivalent transition currently we generalize all
1603 for (int i = 0; i < kPropCount; i++) {
1604 expectations2.GeneralizeRepresentation(i);
1606 CHECK(new_map2->GetBackPointer()->IsUndefined());
1607 CHECK(expectations2.Check(*new_map2));
1609 CHECK(expectations.Check(*new_map2));
1613 Handle<Map> active_map = maps[kPropCount - 1];
1614 CHECK(!active_map->is_deprecated());
1616 // Update all deprecated maps and check that they are now the same.
1617 Handle<Map> updated_map = Map::Update(map);
1618 CHECK_EQ(*active_map, *updated_map);
1619 for (int i = 0; i < kPropCount; i++) {
1620 updated_map = Map::Update(maps[i]);
1621 CHECK_EQ(*active_map, *updated_map);
1626 TEST(ElementsKindTransitionFromMapOwningDescriptor) {
1627 CcTest::InitializeVM();
1628 v8::HandleScope scope(CcTest::isolate());
1629 Isolate* isolate = CcTest::i_isolate();
1630 Handle<HeapType> any_type = HeapType::Any(isolate);
1631 Handle<HeapType> value_type =
1632 HeapType::Class(Map::Create(isolate, 0), isolate);
1635 Handle<Map> Transition(Handle<Map> map) {
1636 return Map::CopyAsElementsKind(map, DICTIONARY_ELEMENTS,
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(ElementsKindTransitionFromMapNotOwningDescriptor) {
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::CopyAsElementsKind(map, DICTIONARY_ELEMENTS,
1673 // TODO(ishell): remove once IS_PROTO_TRANS_ISSUE_FIXED is removed.
1674 bool generalizes_representations() const { return false; }
1677 TestGeneralizeRepresentationWithSpecialTransition(
1678 config, Representation::Smi(), any_type, Representation::HeapObject(),
1679 value_type, Representation::Tagged(), any_type);
1683 TEST(ForObservedTransitionFromMapOwningDescriptor) {
1684 CcTest::InitializeVM();
1685 v8::HandleScope scope(CcTest::isolate());
1686 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<Map> Transition(Handle<Map> map) {
1693 return Map::CopyForObserved(map);
1695 // TODO(ishell): remove once IS_PROTO_TRANS_ISSUE_FIXED is removed.
1696 bool generalizes_representations() const { return false; }
1699 TestGeneralizeRepresentationWithSpecialTransition(
1700 config, Representation::Smi(), any_type, Representation::HeapObject(),
1701 value_type, Representation::Tagged(), any_type);
1705 TEST(ForObservedTransitionFromMapNotOwningDescriptor) {
1706 CcTest::InitializeVM();
1707 v8::HandleScope scope(CcTest::isolate());
1708 Isolate* isolate = CcTest::i_isolate();
1709 Handle<HeapType> any_type = HeapType::Any(isolate);
1710 Handle<HeapType> value_type =
1711 HeapType::Class(Map::Create(isolate, 0), isolate);
1714 Handle<Map> Transition(Handle<Map> map) {
1715 Isolate* isolate = CcTest::i_isolate();
1716 Handle<HeapType> any_type = HeapType::Any(isolate);
1718 // Add one more transition to |map| in order to prevent descriptors
1720 CHECK(map->owns_descriptors());
1721 Map::CopyWithField(map, MakeString("foo"), any_type, NONE,
1722 Representation::Smi(),
1723 INSERT_TRANSITION).ToHandleChecked();
1724 CHECK(!map->owns_descriptors());
1726 return Map::CopyForObserved(map);
1728 // TODO(ishell): remove once IS_PROTO_TRANS_ISSUE_FIXED is removed.
1729 bool generalizes_representations() const { return false; }
1732 TestGeneralizeRepresentationWithSpecialTransition(
1733 config, Representation::Smi(), any_type, Representation::HeapObject(),
1734 value_type, Representation::Tagged(), any_type);
1738 TEST(PrototypeTransitionFromMapOwningDescriptor) {
1739 CcTest::InitializeVM();
1740 v8::HandleScope scope(CcTest::isolate());
1741 Isolate* isolate = CcTest::i_isolate();
1743 Handle<HeapType> any_type = HeapType::Any(isolate);
1744 Handle<HeapType> value_type =
1745 HeapType::Class(Map::Create(isolate, 0), isolate);
1748 Handle<JSObject> prototype_;
1751 Isolate* isolate = CcTest::i_isolate();
1752 Factory* factory = isolate->factory();
1753 prototype_ = factory->NewJSObjectFromMap(Map::Create(isolate, 0));
1756 Handle<Map> Transition(Handle<Map> map) {
1757 return Map::TransitionToPrototype(map, prototype_, REGULAR_PROTOTYPE);
1759 // TODO(ishell): remove once IS_PROTO_TRANS_ISSUE_FIXED is removed.
1760 bool generalizes_representations() const {
1761 return !IS_PROTO_TRANS_ISSUE_FIXED;
1765 TestGeneralizeRepresentationWithSpecialTransition(
1766 config, Representation::Smi(), any_type, Representation::HeapObject(),
1767 value_type, Representation::Tagged(), any_type);
1771 TEST(PrototypeTransitionFromMapNotOwningDescriptor) {
1772 CcTest::InitializeVM();
1773 v8::HandleScope scope(CcTest::isolate());
1774 Isolate* isolate = CcTest::i_isolate();
1776 Handle<HeapType> any_type = HeapType::Any(isolate);
1777 Handle<HeapType> value_type =
1778 HeapType::Class(Map::Create(isolate, 0), isolate);
1781 Handle<JSObject> prototype_;
1784 Isolate* isolate = CcTest::i_isolate();
1785 Factory* factory = isolate->factory();
1786 prototype_ = factory->NewJSObjectFromMap(Map::Create(isolate, 0));
1789 Handle<Map> Transition(Handle<Map> map) {
1790 Isolate* isolate = CcTest::i_isolate();
1791 Handle<HeapType> any_type = HeapType::Any(isolate);
1793 // Add one more transition to |map| in order to prevent descriptors
1795 CHECK(map->owns_descriptors());
1796 Map::CopyWithField(map, MakeString("foo"), any_type, NONE,
1797 Representation::Smi(),
1798 INSERT_TRANSITION).ToHandleChecked();
1799 CHECK(!map->owns_descriptors());
1801 return Map::TransitionToPrototype(map, prototype_, REGULAR_PROTOTYPE);
1803 // TODO(ishell): remove once IS_PROTO_TRANS_ISSUE_FIXED is removed.
1804 bool generalizes_representations() const {
1805 return !IS_PROTO_TRANS_ISSUE_FIXED;
1809 TestGeneralizeRepresentationWithSpecialTransition(
1810 config, Representation::Smi(), any_type, Representation::HeapObject(),
1811 value_type, Representation::Tagged(), any_type);
1815 ////////////////////////////////////////////////////////////////////////////////
1816 // A set of tests for higher level transitioning mechanics.
1819 struct TransitionToDataFieldOperator {
1820 Representation representation_;
1821 PropertyAttributes attributes_;
1822 Handle<HeapType> heap_type_;
1823 Handle<Object> value_;
1825 TransitionToDataFieldOperator(Representation representation,
1826 Handle<HeapType> heap_type,
1827 Handle<Object> value,
1828 PropertyAttributes attributes = NONE)
1829 : representation_(representation),
1830 attributes_(attributes),
1831 heap_type_(heap_type),
1834 Handle<Map> DoTransition(Expectations& expectations, Handle<Map> map) {
1835 return expectations.TransitionToDataField(map, attributes_, representation_,
1836 heap_type_, value_);
1841 struct TransitionToDataConstantOperator {
1842 PropertyAttributes attributes_;
1843 Handle<JSFunction> value_;
1845 TransitionToDataConstantOperator(Handle<JSFunction> value,
1846 PropertyAttributes attributes = NONE)
1847 : attributes_(attributes), value_(value) {}
1849 Handle<Map> DoTransition(Expectations& expectations, Handle<Map> map) {
1850 return expectations.TransitionToDataConstant(map, attributes_, value_);
1855 struct TransitionToAccessorConstantOperator {
1856 PropertyAttributes attributes_;
1857 Handle<AccessorPair> pair_;
1859 TransitionToAccessorConstantOperator(Handle<AccessorPair> pair,
1860 PropertyAttributes attributes = NONE)
1861 : attributes_(attributes), pair_(pair) {}
1863 Handle<Map> DoTransition(Expectations& expectations, Handle<Map> map) {
1864 return expectations.TransitionToAccessorConstant(map, attributes_, pair_);
1869 struct ReconfigureAsDataPropertyOperator {
1871 Representation representation_;
1872 PropertyAttributes attributes_;
1873 Handle<HeapType> heap_type_;
1875 ReconfigureAsDataPropertyOperator(int descriptor,
1876 Representation representation,
1877 Handle<HeapType> heap_type,
1878 PropertyAttributes attributes = NONE)
1879 : descriptor_(descriptor),
1880 representation_(representation),
1881 attributes_(attributes),
1882 heap_type_(heap_type) {}
1884 Handle<Map> DoTransition(Expectations& expectations, Handle<Map> map) {
1885 expectations.SetDataField(descriptor_, representation_, heap_type_);
1886 return Map::ReconfigureExistingProperty(map, descriptor_, kData,
1892 struct ReconfigureAsAccessorPropertyOperator {
1894 PropertyAttributes attributes_;
1896 ReconfigureAsAccessorPropertyOperator(int descriptor,
1897 PropertyAttributes attributes = NONE)
1898 : descriptor_(descriptor), attributes_(attributes) {}
1900 Handle<Map> DoTransition(Expectations& expectations, Handle<Map> map) {
1901 expectations.SetAccessorField(descriptor_);
1902 return Map::ReconfigureExistingProperty(map, descriptor_, kAccessor,
1908 // Checks that representation/field type generalization happened.
1909 struct FieldGeneralizationChecker {
1911 Representation representation_;
1912 PropertyAttributes attributes_;
1913 Handle<HeapType> heap_type_;
1915 FieldGeneralizationChecker(int descriptor, Representation representation,
1916 Handle<HeapType> heap_type,
1917 PropertyAttributes attributes = NONE)
1918 : descriptor_(descriptor),
1919 representation_(representation),
1920 attributes_(attributes),
1921 heap_type_(heap_type) {}
1923 void Check(Expectations& expectations2, Handle<Map> map1, Handle<Map> map2) {
1924 CHECK(!map2->is_deprecated());
1926 CHECK(map1->is_deprecated());
1927 CHECK_NE(*map1, *map2);
1928 Handle<Map> updated_map = Map::Update(map1);
1929 CHECK_EQ(*map2, *updated_map);
1931 expectations2.SetDataField(descriptor_, representation_, heap_type_);
1932 CHECK(expectations2.Check(*map2));
1937 // Checks that existing transition was taken as is.
1938 struct SameMapChecker {
1939 void Check(Expectations& expectations, Handle<Map> map1, Handle<Map> map2) {
1940 CHECK(!map2->is_deprecated());
1941 CHECK_EQ(*map1, *map2);
1942 CHECK(expectations.Check(*map2));
1947 // Checks that both |map1| and |map2| should stays non-deprecated, this is
1948 // the case when property kind is change.
1949 struct PropertyKindReconfigurationChecker {
1950 void Check(Expectations& expectations, Handle<Map> map1, Handle<Map> map2) {
1951 CHECK(!map1->is_deprecated());
1952 CHECK(!map2->is_deprecated());
1953 CHECK_NE(*map1, *map2);
1954 CHECK(expectations.Check(*map2));
1959 // This test transitions to various property types under different
1962 // 1) create a |map| with p0..p3 properties.
1963 // 2) create |map1| by adding "p4" to |map0|.
1964 // 3) create |map2| by transition to "p4" from |map0|.
1968 // {} - p0 - p1 - pA - p3: |map|
1972 // where "p4A" and "p4B" differ only in the attributes.
1974 template <typename TransitionOp1, typename TransitionOp2, typename Checker>
1975 static void TestTransitionTo(TransitionOp1& transition_op1,
1976 TransitionOp2& transition_op2, Checker& checker) {
1977 Isolate* isolate = CcTest::i_isolate();
1978 Handle<HeapType> any_type = HeapType::Any(isolate);
1980 Expectations expectations(isolate);
1982 // Create a map, add required properties to it and initialize expectations.
1983 Handle<Map> initial_map = Map::Create(isolate, 0);
1984 Handle<Map> map = initial_map;
1985 for (int i = 0; i < kPropCount - 1; i++) {
1986 map = expectations.AddDataField(map, NONE, Representation::Smi(), any_type);
1988 CHECK(expectations.Check(*map));
1990 Expectations expectations1 = expectations;
1991 Handle<Map> map1 = transition_op1.DoTransition(expectations1, map);
1992 CHECK(expectations1.Check(*map1));
1994 Expectations expectations2 = expectations;
1995 Handle<Map> map2 = transition_op2.DoTransition(expectations2, map);
1997 // Let the test customization do the check.
1998 checker.Check(expectations2, map1, map2);
2002 TEST(TransitionDataFieldToDataField) {
2003 CcTest::InitializeVM();
2004 v8::HandleScope scope(CcTest::isolate());
2005 Isolate* isolate = CcTest::i_isolate();
2006 Handle<HeapType> any_type = HeapType::Any(isolate);
2008 Handle<Object> value1 = handle(Smi::FromInt(0), isolate);
2009 TransitionToDataFieldOperator transition_op1(Representation::Smi(), any_type,
2012 Handle<Object> value2 = isolate->factory()->NewHeapNumber(0);
2013 TransitionToDataFieldOperator transition_op2(Representation::Double(),
2016 FieldGeneralizationChecker checker(kPropCount - 1, Representation::Double(),
2018 TestTransitionTo(transition_op1, transition_op2, checker);
2022 TEST(TransitionDataConstantToSameDataConstant) {
2023 CcTest::InitializeVM();
2024 v8::HandleScope scope(CcTest::isolate());
2025 Isolate* isolate = CcTest::i_isolate();
2026 Factory* factory = isolate->factory();
2028 Handle<JSFunction> js_func = factory->NewFunction(factory->empty_string());
2029 TransitionToDataConstantOperator transition_op(js_func);
2031 SameMapChecker checker;
2032 TestTransitionTo(transition_op, transition_op, checker);
2036 TEST(TransitionDataConstantToAnotherDataConstant) {
2037 CcTest::InitializeVM();
2038 v8::HandleScope scope(CcTest::isolate());
2039 Isolate* isolate = CcTest::i_isolate();
2040 Factory* factory = isolate->factory();
2041 Handle<HeapType> any_type = HeapType::Any(isolate);
2043 Handle<JSFunction> js_func1 = factory->NewFunction(factory->empty_string());
2044 TransitionToDataConstantOperator transition_op1(js_func1);
2046 Handle<JSFunction> js_func2 = factory->NewFunction(factory->empty_string());
2047 TransitionToDataConstantOperator transition_op2(js_func2);
2049 FieldGeneralizationChecker checker(kPropCount - 1,
2050 Representation::HeapObject(), any_type);
2051 TestTransitionTo(transition_op1, transition_op2, checker);
2055 TEST(TransitionDataConstantToDataField) {
2056 CcTest::InitializeVM();
2057 v8::HandleScope scope(CcTest::isolate());
2058 Isolate* isolate = CcTest::i_isolate();
2059 Factory* factory = isolate->factory();
2060 Handle<HeapType> any_type = HeapType::Any(isolate);
2062 Handle<JSFunction> js_func1 = factory->NewFunction(factory->empty_string());
2063 TransitionToDataConstantOperator transition_op1(js_func1);
2065 Handle<Object> value2 = isolate->factory()->NewHeapNumber(0);
2066 TransitionToDataFieldOperator transition_op2(Representation::Double(),
2069 FieldGeneralizationChecker checker(kPropCount - 1, Representation::Tagged(),
2071 TestTransitionTo(transition_op1, transition_op2, checker);
2075 TEST(TransitionAccessorConstantToSameAccessorConstant) {
2076 CcTest::InitializeVM();
2077 v8::HandleScope scope(CcTest::isolate());
2079 Handle<AccessorPair> pair = CreateAccessorPair(true, true);
2080 TransitionToAccessorConstantOperator transition_op(pair);
2082 SameMapChecker checker;
2083 TestTransitionTo(transition_op, transition_op, checker);
2087 // TODO(ishell): add this test once IS_ACCESSOR_FIELD_SUPPORTED is supported.
2088 // TEST(TransitionAccessorConstantToAnotherAccessorConstant)