Commit f72a7196 authored by Igor Sheludko's avatar Igor Sheludko Committed by Commit Bot

[test] Cleanup field type tracking cctests

... by adding ChangeAlertMechanism enum instead of two bool values and
removing code duplication in tests.

Bug: v8:11074
Change-Id: I90f63bd1c9e858dc3b0a4f190c19f092437257cd
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2536458Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71185}
parent 2869fdfb
......@@ -38,6 +38,7 @@ const bool IS_ACCESSOR_FIELD_SUPPORTED = false;
// Number of properties used in the tests.
const int kPropCount = 7;
enum ChangeAlertMechanism { kDeprecation, kFieldOwnerDependency, kNoAlert };
//
// Helper functions.
......@@ -633,8 +634,8 @@ static void CheckCodeObjectForDeopt(const CRFTData& from,
//
void TestGeneralizeField(int detach_property_at_index, int property_index,
const CRFTData& from, const CRFTData& to,
const CRFTData& expected, bool expected_deprecation,
bool expected_field_owner_dependency) {
const CRFTData& expected,
ChangeAlertMechanism expected_alert) {
Isolate* isolate = CcTest::i_isolate();
Handle<FieldType> any_type = FieldType::Any(isolate);
......@@ -715,9 +716,9 @@ void TestGeneralizeField(int detach_property_at_index, int property_index,
CHECK(!map->is_stable());
CHECK(map->is_deprecated());
CHECK_NE(*map, *new_map);
should_deopt =
expected_field_owner_dependency && !field_owner->is_deprecated();
} else if (expected_deprecation) {
should_deopt = (expected_alert == kFieldOwnerDependency) &&
!field_owner->is_deprecated();
} else if (expected_alert == kDeprecation) {
CHECK(!map->is_stable());
CHECK(map->is_deprecated());
CHECK(field_owner->is_deprecated());
......@@ -726,7 +727,7 @@ void TestGeneralizeField(int detach_property_at_index, int property_index,
CHECK(!field_owner->is_deprecated());
CHECK(map->is_stable()); // Map did not change, must be left stable.
CHECK_EQ(*map, *new_map);
should_deopt = expected_field_owner_dependency;
should_deopt = (expected_alert == kFieldOwnerDependency);
}
CheckCodeObjectForDeopt(from, expected, code_field_type, code_field_repr,
......@@ -750,15 +751,14 @@ void TestGeneralizeField(int detach_property_at_index, int property_index,
}
void TestGeneralizeField(const CRFTData& from, const CRFTData& to,
const CRFTData& expected, bool expected_deprecation,
bool expected_field_owner_dependency) {
const CRFTData& expected,
ChangeAlertMechanism expected_alert) {
// Check the cases when the map being reconfigured is a part of the
// transition tree.
STATIC_ASSERT(kPropCount > 4);
int indices[] = {0, 2, kPropCount - 1};
for (int i = 0; i < static_cast<int>(arraysize(indices)); i++) {
TestGeneralizeField(-1, indices[i], from, to, expected,
expected_deprecation, expected_field_owner_dependency);
TestGeneralizeField(-1, indices[i], from, to, expected, expected_alert);
}
if (!from.representation.IsNone()) {
......@@ -767,35 +767,15 @@ void TestGeneralizeField(const CRFTData& from, const CRFTData& to,
// only for "attached" maps.
int indices[] = {0, kPropCount - 1};
for (int i = 0; i < static_cast<int>(arraysize(indices)); i++) {
TestGeneralizeField(indices[i], 2, from, to, expected,
expected_deprecation,
expected_field_owner_dependency);
TestGeneralizeField(indices[i], 2, from, to, expected, expected_alert);
}
// Check that reconfiguration to the very same field works correctly.
CRFTData data = from;
TestGeneralizeField(-1, 2, data, data, data, false, false);
TestGeneralizeField(-1, 2, data, data, data, kNoAlert);
}
}
void TestGeneralizeField(const CRFTData& from, const CRFTData& to,
const CRFTData& expected) {
const bool expected_deprecation = true;
const bool expected_field_owner_dependency = false;
TestGeneralizeField(from, to, expected, expected_deprecation,
expected_field_owner_dependency);
}
void TestGeneralizeFieldTrivial(const CRFTData& from, const CRFTData& to,
const CRFTData& expected,
bool expected_field_owner_dependency = true) {
const bool expected_deprecation = false;
TestGeneralizeField(from, to, expected, expected_deprecation,
expected_field_owner_dependency);
}
} // namespace
TEST(GeneralizeSmiFieldToDouble) {
......@@ -808,7 +788,8 @@ TEST(GeneralizeSmiFieldToDouble) {
TestGeneralizeField(
{PropertyConstness::kMutable, Representation::Smi(), any_type},
{PropertyConstness::kMutable, Representation::Double(), any_type},
{PropertyConstness::kMutable, Representation::Double(), any_type});
{PropertyConstness::kMutable, Representation::Double(), any_type},
kDeprecation);
}
TEST(GeneralizeSmiFieldToTagged) {
......@@ -823,8 +804,8 @@ TEST(GeneralizeSmiFieldToTagged) {
TestGeneralizeField(
{PropertyConstness::kMutable, Representation::Smi(), any_type},
{PropertyConstness::kMutable, Representation::HeapObject(), value_type},
{PropertyConstness::kMutable, Representation::Tagged(), any_type}, false,
true);
{PropertyConstness::kMutable, Representation::Tagged(), any_type},
kFieldOwnerDependency);
}
TEST(GeneralizeDoubleFieldToTagged) {
......@@ -840,7 +821,7 @@ TEST(GeneralizeDoubleFieldToTagged) {
{PropertyConstness::kMutable, Representation::Double(), any_type},
{PropertyConstness::kMutable, Representation::HeapObject(), value_type},
{PropertyConstness::kMutable, Representation::Tagged(), any_type},
FLAG_unbox_double_fields, !FLAG_unbox_double_fields);
FLAG_unbox_double_fields ? kDeprecation : kFieldOwnerDependency);
}
TEST(GeneralizeHeapObjectFieldToTagged) {
......@@ -855,8 +836,8 @@ TEST(GeneralizeHeapObjectFieldToTagged) {
TestGeneralizeField(
{PropertyConstness::kMutable, Representation::HeapObject(), value_type},
{PropertyConstness::kMutable, Representation::Smi(), any_type},
{PropertyConstness::kMutable, Representation::Tagged(), any_type}, false,
true);
{PropertyConstness::kMutable, Representation::Tagged(), any_type},
kFieldOwnerDependency);
}
TEST(GeneralizeHeapObjectFieldToHeapObject) {
......@@ -874,20 +855,21 @@ TEST(GeneralizeHeapObjectFieldToHeapObject) {
Handle<FieldType> expected_type = any_type;
TestGeneralizeFieldTrivial(
TestGeneralizeField(
{PropertyConstness::kMutable, Representation::HeapObject(), current_type},
{PropertyConstness::kMutable, Representation::HeapObject(), new_type},
{PropertyConstness::kMutable, Representation::HeapObject(),
expected_type});
expected_type},
kFieldOwnerDependency);
current_type = expected_type;
new_type = FieldType::Class(Map::Create(isolate, 0), isolate);
TestGeneralizeFieldTrivial(
TestGeneralizeField(
{PropertyConstness::kMutable, Representation::HeapObject(), any_type},
{PropertyConstness::kMutable, Representation::HeapObject(), new_type},
{PropertyConstness::kMutable, Representation::HeapObject(), any_type},
false);
kNoAlert);
}
TEST(GeneralizeNoneFieldToSmi) {
......@@ -899,10 +881,11 @@ TEST(GeneralizeNoneFieldToSmi) {
Handle<FieldType> any_type = FieldType::Any(isolate);
// None -> Smi representation change is trivial.
TestGeneralizeFieldTrivial(
TestGeneralizeField(
{PropertyConstness::kMutable, Representation::None(), none_type},
{PropertyConstness::kMutable, Representation::Smi(), any_type},
{PropertyConstness::kMutable, Representation::Smi(), any_type});
{PropertyConstness::kMutable, Representation::Smi(), any_type},
kFieldOwnerDependency);
}
TEST(GeneralizeNoneFieldToDouble) {
......@@ -917,7 +900,8 @@ TEST(GeneralizeNoneFieldToDouble) {
TestGeneralizeField(
{PropertyConstness::kMutable, Representation::None(), none_type},
{PropertyConstness::kMutable, Representation::Double(), any_type},
{PropertyConstness::kMutable, Representation::Double(), any_type});
{PropertyConstness::kMutable, Representation::Double(), any_type},
kDeprecation);
}
TEST(GeneralizeNoneFieldToHeapObject) {
......@@ -930,10 +914,11 @@ TEST(GeneralizeNoneFieldToHeapObject) {
FieldType::Class(Map::Create(isolate, 0), isolate);
// None -> HeapObject representation change is trivial.
TestGeneralizeFieldTrivial(
TestGeneralizeField(
{PropertyConstness::kMutable, Representation::None(), none_type},
{PropertyConstness::kMutable, Representation::HeapObject(), value_type},
{PropertyConstness::kMutable, Representation::HeapObject(), value_type});
{PropertyConstness::kMutable, Representation::HeapObject(), value_type},
kFieldOwnerDependency);
}
TEST(GeneralizeNoneFieldToTagged) {
......@@ -945,10 +930,11 @@ TEST(GeneralizeNoneFieldToTagged) {
Handle<FieldType> any_type = FieldType::Any(isolate);
// None -> HeapObject representation change is trivial.
TestGeneralizeFieldTrivial(
TestGeneralizeField(
{PropertyConstness::kMutable, Representation::None(), none_type},
{PropertyConstness::kMutable, Representation::Tagged(), any_type},
{PropertyConstness::kMutable, Representation::Tagged(), any_type});
{PropertyConstness::kMutable, Representation::Tagged(), any_type},
kFieldOwnerDependency);
}
......@@ -1036,110 +1022,9 @@ namespace {
//
// where "p2A" and "p2B" differ only in the attributes.
//
void TestReconfigureDataFieldAttribute_GeneralizeFieldWithDeprecation(
const CRFTData& from, const CRFTData& to, const CRFTData& expected) {
Isolate* isolate = CcTest::i_isolate();
Expectations expectations(isolate);
// Create a map, add required properties to it and initialize expectations.
Handle<Map> initial_map = Map::Create(isolate, 0);
Handle<Map> map = initial_map;
for (int i = 0; i < kPropCount; i++) {
map = expectations.AddDataField(map, NONE, from.constness,
from.representation, from.type);
}
CHECK(!map->is_deprecated());
CHECK(map->is_stable());
CHECK(expectations.Check(*map));
// Create another branch in transition tree (property at index |kSplitProp|
// has different attributes), initialize expectations.
const int kSplitProp = kPropCount / 2;
Expectations expectations2(isolate);
Handle<Map> map2 = initial_map;
for (int i = 0; i < kSplitProp; i++) {
map2 = expectations2.FollowDataTransition(map2, NONE, from.constness,
from.representation, from.type);
}
map2 = expectations2.AddDataField(map2, READ_ONLY, to.constness,
to.representation, to.type);
for (int i = kSplitProp + 1; i < kPropCount; i++) {
map2 = expectations2.AddDataField(map2, NONE, to.constness,
to.representation, to.type);
}
CHECK(!map2->is_deprecated());
CHECK(map2->is_stable());
CHECK(expectations2.Check(*map2));
// Create dummy optimized code object to test correct dependencies
// on the field owner.
Handle<Code> code_field_type = CreateDummyOptimizedCode(isolate);
Handle<Code> code_field_repr = CreateDummyOptimizedCode(isolate);
Handle<Code> code_field_const = CreateDummyOptimizedCode(isolate);
Handle<Map> field_owner(
map->FindFieldOwner(isolate, InternalIndex(kSplitProp)), isolate);
DependentCode::InstallDependency(isolate,
MaybeObjectHandle::Weak(code_field_type),
field_owner, DependentCode::kFieldTypeGroup);
DependentCode::InstallDependency(
isolate, MaybeObjectHandle::Weak(code_field_repr), field_owner,
DependentCode::kFieldRepresentationGroup);
DependentCode::InstallDependency(
isolate, MaybeObjectHandle::Weak(code_field_const), field_owner,
DependentCode::kFieldConstGroup);
CHECK(!code_field_type->marked_for_deoptimization());
CHECK(!code_field_repr->marked_for_deoptimization());
CHECK(!code_field_const->marked_for_deoptimization());
// Reconfigure attributes of property |kSplitProp| of |map2| to NONE, which
// should generalize representations in |map1|.
Handle<Map> new_map =
Map::ReconfigureExistingProperty(isolate, map2, InternalIndex(kSplitProp),
kData, NONE, PropertyConstness::kConst);
// |map2| should be left unchanged but marked unstable.
CHECK(!map2->is_stable());
CHECK(!map2->is_deprecated());
CHECK_NE(*map2, *new_map);
CHECK(expectations2.Check(*map2));
for (int i = kSplitProp; i < kPropCount; i++) {
expectations.SetDataField(i, expected.constness, expected.representation,
expected.type);
}
// |map| should be deprecated and |new_map| should match new expectations.
CHECK(map->is_deprecated());
CHECK(!code_field_type->marked_for_deoptimization());
CHECK(!code_field_repr->marked_for_deoptimization());
CHECK(!code_field_const->marked_for_deoptimization());
CHECK_NE(*map, *new_map);
CHECK(!new_map->is_deprecated());
CHECK(expectations.Check(*new_map));
// Update deprecated |map|, it should become |new_map|.
Handle<Map> updated_map = Map::Update(isolate, map);
CHECK_EQ(*new_map, *updated_map);
CheckMigrationTarget(isolate, *map, *updated_map);
}
// This test ensures that trivial field generalization (from HeapObject to
// HeapObject) is correctly propagated from one branch of transition tree
// (|map2|) to another (|map|).
//
// + - p2B - p3 - p4: |map2|
// |
// {} - p0 - p1 - p2A - p3 - p4: |map|
//
// where "p2A" and "p2B" differ only in the attributes.
//
// TODO(ishell): rename to XXX_GeneralizeFieldInplace here and around.
void TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
void TestReconfigureDataFieldAttribute_GeneralizeField(
const CRFTData& from, const CRFTData& to, const CRFTData& expected,
bool expected_field_owner_dependency = true) {
ChangeAlertMechanism expected_alert) {
Isolate* isolate = CcTest::i_isolate();
Expectations expectations(isolate);
......@@ -1208,41 +1093,44 @@ void TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
CHECK_NE(*map2, *new_map);
CHECK(expectations2.Check(*map2));
// In trivial case |map| should be returned as a result of the property
// reconfiguration, respective field types should be generalized and
// respective code dependencies should be invalidated. |map| should be NOT
// deprecated and it should match new expectations.
for (int i = kSplitProp; i < kPropCount; i++) {
expectations.SetDataField(i, expected.constness, expected.representation,
expected.type);
}
CHECK(!map->is_deprecated());
CHECK_EQ(*map, *new_map);
CheckCodeObjectForDeopt(from, expected, code_field_type, code_field_repr,
code_field_const, expected_field_owner_dependency);
CHECK(!new_map->is_deprecated());
CHECK(expectations.Check(*new_map));
if (expected_alert == kDeprecation) {
// |map| should be deprecated and |new_map| should match new expectations.
CHECK(map->is_deprecated());
CHECK(!code_field_type->marked_for_deoptimization());
CHECK(!code_field_repr->marked_for_deoptimization());
CHECK(!code_field_const->marked_for_deoptimization());
CHECK_NE(*map, *new_map);
Handle<Map> updated_map = Map::Update(isolate, map);
CHECK_EQ(*new_map, *updated_map);
}
CHECK(!new_map->is_deprecated());
CHECK(expectations.Check(*new_map));
// This is an entry point to either
// TestReconfigureDataFieldAttribute_GeneralizeFieldWithDeprecation() or
// TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial() depending on
// whether the deprecation is expected or not. In the latter case the relevant
// code dependencies must be triggered.
void TestReconfigureDataFieldAttribute_GeneralizeField(
const CRFTData& from, const CRFTData& to, const CRFTData& expected,
bool expected_deprecation) {
if (expected_deprecation) {
TestReconfigureDataFieldAttribute_GeneralizeFieldWithDeprecation(from, to,
expected);
// Update deprecated |map|, it should become |new_map|.
Handle<Map> updated_map = Map::Update(isolate, map);
CHECK_EQ(*new_map, *updated_map);
CheckMigrationTarget(isolate, *map, *updated_map);
} else {
const bool expected_field_owner_dependency = true;
TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
from, to, expected, expected_field_owner_dependency);
CHECK(expected_alert == kFieldOwnerDependency ||
expected_alert == kNoAlert);
// In case of in-place generalization |map| should be returned as a result
// of the property reconfiguration, respective field types should be
// generalized and respective code dependencies should be invalidated.
// |map| should be NOT deprecated and it should match new expectations.
CHECK(!map->is_deprecated());
CHECK_EQ(*map, *new_map);
bool expect_deopt = expected_alert == kFieldOwnerDependency;
CheckCodeObjectForDeopt(from, expected, code_field_type, code_field_repr,
code_field_const, expect_deopt);
CHECK(!new_map->is_deprecated());
CHECK(expectations.Check(*new_map));
Handle<Map> updated_map = Map::Update(isolate, map);
CHECK_EQ(*new_map, *updated_map);
}
}
......@@ -1258,22 +1146,26 @@ TEST(ReconfigureDataFieldAttribute_GeneralizeSmiFieldToDouble) {
TestReconfigureDataFieldAttribute_GeneralizeField(
{PropertyConstness::kConst, Representation::Smi(), any_type},
{PropertyConstness::kConst, Representation::Double(), any_type},
{PropertyConstness::kConst, Representation::Double(), any_type}, true);
{PropertyConstness::kConst, Representation::Double(), any_type},
kDeprecation);
TestReconfigureDataFieldAttribute_GeneralizeField(
{PropertyConstness::kConst, Representation::Smi(), any_type},
{PropertyConstness::kMutable, Representation::Double(), any_type},
{PropertyConstness::kMutable, Representation::Double(), any_type}, true);
{PropertyConstness::kMutable, Representation::Double(), any_type},
kDeprecation);
TestReconfigureDataFieldAttribute_GeneralizeField(
{PropertyConstness::kMutable, Representation::Smi(), any_type},
{PropertyConstness::kConst, Representation::Double(), any_type},
{PropertyConstness::kMutable, Representation::Double(), any_type}, true);
{PropertyConstness::kMutable, Representation::Double(), any_type},
kDeprecation);
TestReconfigureDataFieldAttribute_GeneralizeField(
{PropertyConstness::kMutable, Representation::Smi(), any_type},
{PropertyConstness::kMutable, Representation::Double(), any_type},
{PropertyConstness::kMutable, Representation::Double(), any_type}, true);
{PropertyConstness::kMutable, Representation::Double(), any_type},
kDeprecation);
}
TEST(ReconfigureDataFieldAttribute_GeneralizeSmiFieldToTagged) {
......@@ -1285,25 +1177,29 @@ TEST(ReconfigureDataFieldAttribute_GeneralizeSmiFieldToTagged) {
Handle<FieldType> value_type =
FieldType::Class(Map::Create(isolate, 0), isolate);
TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
TestReconfigureDataFieldAttribute_GeneralizeField(
{PropertyConstness::kConst, Representation::Smi(), any_type},
{PropertyConstness::kConst, Representation::HeapObject(), value_type},
{PropertyConstness::kConst, Representation::Tagged(), any_type});
{PropertyConstness::kConst, Representation::Tagged(), any_type},
kFieldOwnerDependency);
TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
TestReconfigureDataFieldAttribute_GeneralizeField(
{PropertyConstness::kConst, Representation::Smi(), any_type},
{PropertyConstness::kMutable, Representation::HeapObject(), value_type},
{PropertyConstness::kMutable, Representation::Tagged(), any_type});
{PropertyConstness::kMutable, Representation::Tagged(), any_type},
kFieldOwnerDependency);
TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
TestReconfigureDataFieldAttribute_GeneralizeField(
{PropertyConstness::kMutable, Representation::Smi(), any_type},
{PropertyConstness::kConst, Representation::HeapObject(), value_type},
{PropertyConstness::kMutable, Representation::Tagged(), any_type});
{PropertyConstness::kMutable, Representation::Tagged(), any_type},
kFieldOwnerDependency);
TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
TestReconfigureDataFieldAttribute_GeneralizeField(
{PropertyConstness::kMutable, Representation::Smi(), any_type},
{PropertyConstness::kMutable, Representation::HeapObject(), value_type},
{PropertyConstness::kMutable, Representation::Tagged(), any_type});
{PropertyConstness::kMutable, Representation::Tagged(), any_type},
kFieldOwnerDependency);
}
TEST(ReconfigureDataFieldAttribute_GeneralizeDoubleFieldToTagged) {
......@@ -1319,25 +1215,25 @@ TEST(ReconfigureDataFieldAttribute_GeneralizeDoubleFieldToTagged) {
{PropertyConstness::kConst, Representation::Double(), any_type},
{PropertyConstness::kConst, Representation::HeapObject(), value_type},
{PropertyConstness::kConst, Representation::Tagged(), any_type},
FLAG_unbox_double_fields);
FLAG_unbox_double_fields ? kDeprecation : kFieldOwnerDependency);
TestReconfigureDataFieldAttribute_GeneralizeField(
{PropertyConstness::kConst, Representation::Double(), any_type},
{PropertyConstness::kMutable, Representation::HeapObject(), value_type},
{PropertyConstness::kMutable, Representation::Tagged(), any_type},
FLAG_unbox_double_fields);
FLAG_unbox_double_fields ? kDeprecation : kFieldOwnerDependency);
TestReconfigureDataFieldAttribute_GeneralizeField(
{PropertyConstness::kMutable, Representation::Double(), any_type},
{PropertyConstness::kConst, Representation::HeapObject(), value_type},
{PropertyConstness::kMutable, Representation::Tagged(), any_type},
FLAG_unbox_double_fields);
FLAG_unbox_double_fields ? kDeprecation : kFieldOwnerDependency);
TestReconfigureDataFieldAttribute_GeneralizeField(
{PropertyConstness::kMutable, Representation::Double(), any_type},
{PropertyConstness::kMutable, Representation::HeapObject(), value_type},
{PropertyConstness::kMutable, Representation::Tagged(), any_type},
FLAG_unbox_double_fields);
FLAG_unbox_double_fields ? kDeprecation : kFieldOwnerDependency);
}
TEST(ReconfigureDataFieldAttribute_GeneralizeHeapObjFieldToHeapObj) {
......@@ -1356,59 +1252,64 @@ TEST(ReconfigureDataFieldAttribute_GeneralizeHeapObjFieldToHeapObj) {
Handle<FieldType> expected_type = any_type;
// Check generalizations that trigger deopts.
TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
TestReconfigureDataFieldAttribute_GeneralizeField(
{PropertyConstness::kConst, Representation::HeapObject(), current_type},
{PropertyConstness::kConst, Representation::HeapObject(), new_type},
{PropertyConstness::kConst, Representation::HeapObject(), expected_type});
{PropertyConstness::kConst, Representation::HeapObject(), expected_type},
kFieldOwnerDependency);
// PropertyConstness::kConst to PropertyConstness::kMutable migration does
// not create a new map, therefore trivial generalization.
TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
TestReconfigureDataFieldAttribute_GeneralizeField(
{PropertyConstness::kConst, Representation::HeapObject(), current_type},
{PropertyConstness::kMutable, Representation::HeapObject(), new_type},
{PropertyConstness::kMutable, Representation::HeapObject(),
expected_type});
expected_type},
kFieldOwnerDependency);
TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
TestReconfigureDataFieldAttribute_GeneralizeField(
{PropertyConstness::kMutable, Representation::HeapObject(), current_type},
{PropertyConstness::kConst, Representation::HeapObject(), new_type},
{PropertyConstness::kMutable, Representation::HeapObject(),
expected_type});
expected_type},
kFieldOwnerDependency);
TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
TestReconfigureDataFieldAttribute_GeneralizeField(
{PropertyConstness::kMutable, Representation::HeapObject(), current_type},
{PropertyConstness::kMutable, Representation::HeapObject(), new_type},
{PropertyConstness::kMutable, Representation::HeapObject(),
expected_type});
expected_type},
kFieldOwnerDependency);
current_type = expected_type;
// Check generalizations that do not trigger deopts.
new_type = FieldType::Class(Map::Create(isolate, 0), isolate);
TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
TestReconfigureDataFieldAttribute_GeneralizeField(
{PropertyConstness::kConst, Representation::HeapObject(), any_type},
{PropertyConstness::kConst, Representation::HeapObject(), new_type},
{PropertyConstness::kConst, Representation::HeapObject(), any_type},
false);
kNoAlert);
// PropertyConstness::kConst to PropertyConstness::kMutable migration does
// not create a new map, therefore trivial generalization.
TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
TestReconfigureDataFieldAttribute_GeneralizeField(
{PropertyConstness::kConst, Representation::HeapObject(), any_type},
{PropertyConstness::kMutable, Representation::HeapObject(), new_type},
{PropertyConstness::kMutable, Representation::HeapObject(), any_type});
{PropertyConstness::kMutable, Representation::HeapObject(), any_type},
kFieldOwnerDependency);
TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
TestReconfigureDataFieldAttribute_GeneralizeField(
{PropertyConstness::kMutable, Representation::HeapObject(), any_type},
{PropertyConstness::kConst, Representation::HeapObject(), new_type},
{PropertyConstness::kMutable, Representation::HeapObject(), any_type},
false);
kNoAlert);
TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
TestReconfigureDataFieldAttribute_GeneralizeField(
{PropertyConstness::kMutable, Representation::HeapObject(), any_type},
{PropertyConstness::kMutable, Representation::HeapObject(), new_type},
{PropertyConstness::kMutable, Representation::HeapObject(), any_type},
false);
kNoAlert);
}
TEST(ReconfigureDataFieldAttribute_GeneralizeHeapObjectFieldToTagged) {
......@@ -1420,10 +1321,11 @@ TEST(ReconfigureDataFieldAttribute_GeneralizeHeapObjectFieldToTagged) {
Handle<FieldType> value_type =
FieldType::Class(Map::Create(isolate, 0), isolate);
TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
TestReconfigureDataFieldAttribute_GeneralizeField(
{PropertyConstness::kMutable, Representation::HeapObject(), value_type},
{PropertyConstness::kMutable, Representation::Smi(), any_type},
{PropertyConstness::kMutable, Representation::Tagged(), any_type});
{PropertyConstness::kMutable, Representation::Tagged(), any_type},
kFieldOwnerDependency);
}
// Checks that given |map| is deprecated and that it updates to given |new_map|
......@@ -1799,9 +1701,8 @@ TEST(ReconfigureDataFieldAttribute_AccConstantToDataFieldAfterTargetMap) {
namespace {
// This test ensures that trivial field generalization (from HeapObject to
// HeapObject) is correctly propagated from one branch of transition tree
// (|map2|) to another (|map|).
// This test ensures that in-place field generalization is correctly propagated
// from one branch of transition tree (|map2|) to another (|map|).
//
// + - p0 - p1 - p2A - p3 - p4: |map|
// |
......@@ -1811,7 +1712,7 @@ namespace {
//
// where "p2A" and "p2B" differ only in the representation/field type.
//
static void TestReconfigureElementsKind_GeneralizeFieldTrivial(
static void TestReconfigureElementsKind_GeneralizeFieldInPlace(
const CRFTData& from, const CRFTData& to, const CRFTData& expected) {
Isolate* isolate = CcTest::i_isolate();
......@@ -1882,10 +1783,10 @@ static void TestReconfigureElementsKind_GeneralizeFieldTrivial(
CHECK_NE(*map2, *new_map);
CHECK(expectations2.Check(*map2));
// In trivial case |map| should be returned as a result of the elements
// kind reconfiguration, respective field types should be generalized and
// respective code dependencies should be invalidated. |map| should be NOT
// deprecated and it should match new expectations.
// In case of in-place generalization |map| should be returned as a result of
// the elements kind reconfiguration, respective field types should be
// generalized and respective code dependencies should be invalidated.
// |map| should be NOT deprecated and it should match new expectations.
expectations.SetDataField(kDiffProp, expected.constness,
expected.representation, expected.type);
CHECK(!map->is_deprecated());
......@@ -1921,22 +1822,22 @@ TEST(ReconfigureElementsKind_GeneralizeSmiFieldToDouble) {
Handle<FieldType> any_type = FieldType::Any(isolate);
TestReconfigureElementsKind_GeneralizeFieldTrivial(
TestReconfigureElementsKind_GeneralizeFieldInPlace(
{PropertyConstness::kConst, Representation::Smi(), any_type},
{PropertyConstness::kConst, Representation::Double(), any_type},
{PropertyConstness::kConst, Representation::Double(), any_type});
TestReconfigureElementsKind_GeneralizeFieldTrivial(
TestReconfigureElementsKind_GeneralizeFieldInPlace(
{PropertyConstness::kConst, Representation::Smi(), any_type},
{PropertyConstness::kMutable, Representation::Double(), any_type},
{PropertyConstness::kMutable, Representation::Double(), any_type});
TestReconfigureElementsKind_GeneralizeFieldTrivial(
TestReconfigureElementsKind_GeneralizeFieldInPlace(
{PropertyConstness::kMutable, Representation::Smi(), any_type},
{PropertyConstness::kConst, Representation::Double(), any_type},
{PropertyConstness::kMutable, Representation::Double(), any_type});
TestReconfigureElementsKind_GeneralizeFieldTrivial(
TestReconfigureElementsKind_GeneralizeFieldInPlace(
{PropertyConstness::kMutable, Representation::Smi(), any_type},
{PropertyConstness::kMutable, Representation::Double(), any_type},
{PropertyConstness::kMutable, Representation::Double(), any_type});
......@@ -1951,22 +1852,22 @@ TEST(ReconfigureElementsKind_GeneralizeSmiFieldToTagged) {
Handle<FieldType> value_type =
FieldType::Class(Map::Create(isolate, 0), isolate);
TestReconfigureElementsKind_GeneralizeFieldTrivial(
TestReconfigureElementsKind_GeneralizeFieldInPlace(
{PropertyConstness::kConst, Representation::Smi(), any_type},
{PropertyConstness::kConst, Representation::HeapObject(), value_type},
{PropertyConstness::kConst, Representation::Tagged(), any_type});
TestReconfigureElementsKind_GeneralizeFieldTrivial(
TestReconfigureElementsKind_GeneralizeFieldInPlace(
{PropertyConstness::kConst, Representation::Smi(), any_type},
{PropertyConstness::kMutable, Representation::HeapObject(), value_type},
{PropertyConstness::kMutable, Representation::Tagged(), any_type});
TestReconfigureElementsKind_GeneralizeFieldTrivial(
TestReconfigureElementsKind_GeneralizeFieldInPlace(
{PropertyConstness::kMutable, Representation::Smi(), any_type},
{PropertyConstness::kConst, Representation::HeapObject(), value_type},
{PropertyConstness::kMutable, Representation::Tagged(), any_type});
TestReconfigureElementsKind_GeneralizeFieldTrivial(
TestReconfigureElementsKind_GeneralizeFieldInPlace(
{PropertyConstness::kMutable, Representation::Smi(), any_type},
{PropertyConstness::kMutable, Representation::HeapObject(), value_type},
{PropertyConstness::kMutable, Representation::Tagged(), any_type});
......@@ -1981,22 +1882,22 @@ TEST(ReconfigureElementsKind_GeneralizeDoubleFieldToTagged) {
Handle<FieldType> value_type =
FieldType::Class(Map::Create(isolate, 0), isolate);
TestReconfigureElementsKind_GeneralizeFieldTrivial(
TestReconfigureElementsKind_GeneralizeFieldInPlace(
{PropertyConstness::kConst, Representation::Double(), any_type},
{PropertyConstness::kConst, Representation::HeapObject(), value_type},
{PropertyConstness::kConst, Representation::Tagged(), any_type});
TestReconfigureElementsKind_GeneralizeFieldTrivial(
TestReconfigureElementsKind_GeneralizeFieldInPlace(
{PropertyConstness::kConst, Representation::Double(), any_type},
{PropertyConstness::kMutable, Representation::HeapObject(), value_type},
{PropertyConstness::kMutable, Representation::Tagged(), any_type});
TestReconfigureElementsKind_GeneralizeFieldTrivial(
TestReconfigureElementsKind_GeneralizeFieldInPlace(
{PropertyConstness::kMutable, Representation::Double(), any_type},
{PropertyConstness::kConst, Representation::HeapObject(), value_type},
{PropertyConstness::kMutable, Representation::Tagged(), any_type});
TestReconfigureElementsKind_GeneralizeFieldTrivial(
TestReconfigureElementsKind_GeneralizeFieldInPlace(
{PropertyConstness::kMutable, Representation::Double(), any_type},
{PropertyConstness::kMutable, Representation::HeapObject(), value_type},
{PropertyConstness::kMutable, Representation::Tagged(), any_type});
......@@ -2018,26 +1919,26 @@ TEST(ReconfigureElementsKind_GeneralizeHeapObjFieldToHeapObj) {
Handle<FieldType> expected_type = any_type;
// Check generalizations that trigger deopts.
TestReconfigureElementsKind_GeneralizeFieldTrivial(
TestReconfigureElementsKind_GeneralizeFieldInPlace(
{PropertyConstness::kConst, Representation::HeapObject(), current_type},
{PropertyConstness::kConst, Representation::HeapObject(), new_type},
{PropertyConstness::kConst, Representation::HeapObject(), expected_type});
// PropertyConstness::kConst to PropertyConstness::kMutable migration does
// not create a new map, therefore trivial generalization.
TestReconfigureElementsKind_GeneralizeFieldTrivial(
TestReconfigureElementsKind_GeneralizeFieldInPlace(
{PropertyConstness::kConst, Representation::HeapObject(), current_type},
{PropertyConstness::kMutable, Representation::HeapObject(), new_type},
{PropertyConstness::kMutable, Representation::HeapObject(),
expected_type});
TestReconfigureElementsKind_GeneralizeFieldTrivial(
TestReconfigureElementsKind_GeneralizeFieldInPlace(
{PropertyConstness::kMutable, Representation::HeapObject(), current_type},
{PropertyConstness::kConst, Representation::HeapObject(), new_type},
{PropertyConstness::kMutable, Representation::HeapObject(),
expected_type});
TestReconfigureElementsKind_GeneralizeFieldTrivial(
TestReconfigureElementsKind_GeneralizeFieldInPlace(
{PropertyConstness::kMutable, Representation::HeapObject(), current_type},
{PropertyConstness::kMutable, Representation::HeapObject(), new_type},
{PropertyConstness::kMutable, Representation::HeapObject(),
......@@ -2047,24 +1948,24 @@ TEST(ReconfigureElementsKind_GeneralizeHeapObjFieldToHeapObj) {
// Check generalizations that do not trigger deopts.
new_type = FieldType::Class(Map::Create(isolate, 0), isolate);
TestReconfigureElementsKind_GeneralizeFieldTrivial(
TestReconfigureElementsKind_GeneralizeFieldInPlace(
{PropertyConstness::kConst, Representation::HeapObject(), any_type},
{PropertyConstness::kConst, Representation::HeapObject(), new_type},
{PropertyConstness::kConst, Representation::HeapObject(), any_type});
// PropertyConstness::kConst to PropertyConstness::kMutable migration does
// not create a new map, therefore trivial generalization.
TestReconfigureElementsKind_GeneralizeFieldTrivial(
TestReconfigureElementsKind_GeneralizeFieldInPlace(
{PropertyConstness::kConst, Representation::HeapObject(), any_type},
{PropertyConstness::kMutable, Representation::HeapObject(), new_type},
{PropertyConstness::kMutable, Representation::HeapObject(), any_type});
TestReconfigureElementsKind_GeneralizeFieldTrivial(
TestReconfigureElementsKind_GeneralizeFieldInPlace(
{PropertyConstness::kMutable, Representation::HeapObject(), any_type},
{PropertyConstness::kConst, Representation::HeapObject(), new_type},
{PropertyConstness::kMutable, Representation::HeapObject(), any_type});
TestReconfigureElementsKind_GeneralizeFieldTrivial(
TestReconfigureElementsKind_GeneralizeFieldInPlace(
{PropertyConstness::kMutable, Representation::HeapObject(), any_type},
{PropertyConstness::kMutable, Representation::HeapObject(), new_type},
{PropertyConstness::kMutable, Representation::HeapObject(), any_type});
......@@ -2079,22 +1980,22 @@ TEST(ReconfigureElementsKind_GeneralizeHeapObjectFieldToTagged) {
Handle<FieldType> value_type =
FieldType::Class(Map::Create(isolate, 0), isolate);
TestReconfigureElementsKind_GeneralizeFieldTrivial(
TestReconfigureElementsKind_GeneralizeFieldInPlace(
{PropertyConstness::kConst, Representation::HeapObject(), value_type},
{PropertyConstness::kConst, Representation::Smi(), any_type},
{PropertyConstness::kConst, Representation::Tagged(), any_type});
TestReconfigureElementsKind_GeneralizeFieldTrivial(
TestReconfigureElementsKind_GeneralizeFieldInPlace(
{PropertyConstness::kConst, Representation::HeapObject(), value_type},
{PropertyConstness::kMutable, Representation::Smi(), any_type},
{PropertyConstness::kMutable, Representation::Tagged(), any_type});
TestReconfigureElementsKind_GeneralizeFieldTrivial(
TestReconfigureElementsKind_GeneralizeFieldInPlace(
{PropertyConstness::kMutable, Representation::HeapObject(), value_type},
{PropertyConstness::kConst, Representation::Smi(), any_type},
{PropertyConstness::kMutable, Representation::Tagged(), any_type});
TestReconfigureElementsKind_GeneralizeFieldTrivial(
TestReconfigureElementsKind_GeneralizeFieldInPlace(
{PropertyConstness::kMutable, Representation::HeapObject(), value_type},
{PropertyConstness::kMutable, Representation::Smi(), any_type},
{PropertyConstness::kMutable, Representation::Tagged(), any_type});
......@@ -2199,7 +2100,7 @@ TEST(ReconfigurePropertySplitMapTransitionsOverflow) {
template <typename TestConfig>
static void TestGeneralizeFieldWithSpecialTransition(
TestConfig* config, const CRFTData& from, const CRFTData& to,
const CRFTData& expected, bool expected_deprecation) {
const CRFTData& expected, ChangeAlertMechanism expected_alert) {
Isolate* isolate = CcTest::i_isolate();
Expectations expectations(isolate);
......@@ -2246,46 +2147,62 @@ static void TestGeneralizeFieldWithSpecialTransition(
expectations.SetDataField(i, expected.constness, expected.representation,
expected.type);
if (expected_deprecation) {
CHECK(map->is_deprecated());
CHECK_NE(*map, *new_map);
CHECK(i == 0 || maps[i - 1]->is_deprecated());
CHECK(expectations.Check(*new_map));
Handle<Map> new_map2 = Map::Update(isolate, map2);
CHECK(!new_map2->is_deprecated());
CHECK(!new_map2->is_dictionary_map());
Handle<Map> tmp_map;
if (Map::TryUpdate(isolate, map2).ToHandle(&tmp_map)) {
// If Map::TryUpdate() manages to succeed the result must match the
// result of Map::Update().
CHECK_EQ(*new_map2, *tmp_map);
} else {
// Equivalent transitions should always find the updated map.
CHECK(config->is_non_equivalent_transition());
}
switch (expected_alert) {
case kDeprecation: {
CHECK(map->is_deprecated());
CHECK_NE(*map, *new_map);
CHECK(i == 0 || maps[i - 1]->is_deprecated());
CHECK(expectations.Check(*new_map));
Handle<Map> new_map2 = Map::Update(isolate, map2);
CHECK(!new_map2->is_deprecated());
CHECK(!new_map2->is_dictionary_map());
Handle<Map> tmp_map;
if (Map::TryUpdate(isolate, map2).ToHandle(&tmp_map)) {
// If Map::TryUpdate() manages to succeed the result must match the
// result of Map::Update().
CHECK_EQ(*new_map2, *tmp_map);
} else {
// Equivalent transitions should always find the updated map.
CHECK(config->is_non_equivalent_transition());
}
if (config->is_non_equivalent_transition()) {
// In case of non-equivalent transition currently we generalize all
// representations.
for (int i = 0; i < kPropCount; i++) {
expectations2.GeneralizeField(i);
if (config->is_non_equivalent_transition()) {
// In case of non-equivalent transition currently we generalize all
// representations.
for (int i = 0; i < kPropCount; i++) {
expectations2.GeneralizeField(i);
}
CHECK(new_map2->GetBackPointer().IsUndefined(isolate));
CHECK(expectations2.Check(*new_map2));
} else {
expectations2.SetDataField(i, expected.constness,
expected.representation, expected.type);
CHECK(!new_map2->GetBackPointer().IsUndefined(isolate));
CHECK(expectations2.Check(*new_map2));
}
CHECK(new_map2->GetBackPointer().IsUndefined(isolate));
CHECK(expectations2.Check(*new_map2));
} else {
break;
}
case kFieldOwnerDependency: {
CHECK(!map->is_deprecated());
// TODO(ishell): Review expectations once IS_PROTO_TRANS_ISSUE_FIXED is
// removed.
CHECK(!IS_PROTO_TRANS_ISSUE_FIXED);
CHECK_EQ(*map, *new_map);
CHECK(expectations.Check(*new_map));
CHECK(!map2->is_deprecated());
CHECK_NE(*map2, *new_map);
expectations2.SetDataField(i, expected.constness,
expected.representation, expected.type);
CHECK(!new_map2->GetBackPointer().IsUndefined(isolate));
CHECK(expectations2.Check(*new_map2));
CHECK(expectations2.Check(*map2));
break;
}
} else {
CHECK(!map->is_deprecated());
// TODO(ishell): Update test expectations properly.
// CHECK_EQ(*map2, *new_map);
// CHECK(expectations2.Check(*new_map));
case kNoAlert:
UNREACHABLE();
break;
}
}
......@@ -2348,14 +2265,14 @@ TEST(ElementsKindTransitionFromMapOwningDescriptor) {
{PropertyConstness::kMutable, Representation::Smi(), any_type},
{PropertyConstness::kMutable, Representation::HeapObject(), value_type},
{PropertyConstness::kMutable, Representation::Tagged(), any_type},
false);
kFieldOwnerDependency);
TestGeneralizeFieldWithSpecialTransition(
&configs[i],
{PropertyConstness::kMutable, Representation::Double(), any_type},
{PropertyConstness::kMutable, Representation::HeapObject(), value_type},
{PropertyConstness::kMutable, Representation::Tagged(), any_type},
FLAG_unbox_double_fields);
FLAG_unbox_double_fields ? kDeprecation : kFieldOwnerDependency);
}
}
......@@ -2416,14 +2333,14 @@ TEST(ElementsKindTransitionFromMapNotOwningDescriptor) {
{PropertyConstness::kMutable, Representation::Smi(), any_type},
{PropertyConstness::kMutable, Representation::HeapObject(), value_type},
{PropertyConstness::kMutable, Representation::Tagged(), any_type},
false);
kFieldOwnerDependency);
TestGeneralizeFieldWithSpecialTransition(
&configs[i],
{PropertyConstness::kMutable, Representation::Double(), any_type},
{PropertyConstness::kMutable, Representation::HeapObject(), value_type},
{PropertyConstness::kMutable, Representation::Tagged(), any_type},
FLAG_unbox_double_fields);
FLAG_unbox_double_fields ? kDeprecation : kFieldOwnerDependency);
}
}
......@@ -2459,14 +2376,15 @@ TEST(PrototypeTransitionFromMapOwningDescriptor) {
TestGeneralizeFieldWithSpecialTransition(
&config, {PropertyConstness::kMutable, Representation::Smi(), any_type},
{PropertyConstness::kMutable, Representation::HeapObject(), value_type},
{PropertyConstness::kMutable, Representation::Tagged(), any_type}, false);
{PropertyConstness::kMutable, Representation::Tagged(), any_type},
kFieldOwnerDependency);
TestGeneralizeFieldWithSpecialTransition(
&config,
{PropertyConstness::kMutable, Representation::Double(), any_type},
{PropertyConstness::kMutable, Representation::HeapObject(), value_type},
{PropertyConstness::kMutable, Representation::Tagged(), any_type},
FLAG_unbox_double_fields);
FLAG_unbox_double_fields ? kDeprecation : kFieldOwnerDependency);
}
TEST(PrototypeTransitionFromMapNotOwningDescriptor) {
......@@ -2512,14 +2430,15 @@ TEST(PrototypeTransitionFromMapNotOwningDescriptor) {
TestGeneralizeFieldWithSpecialTransition(
&config, {PropertyConstness::kMutable, Representation::Smi(), any_type},
{PropertyConstness::kMutable, Representation::HeapObject(), value_type},
{PropertyConstness::kMutable, Representation::Tagged(), any_type}, false);
{PropertyConstness::kMutable, Representation::Tagged(), any_type},
kFieldOwnerDependency);
TestGeneralizeFieldWithSpecialTransition(
&config,
{PropertyConstness::kMutable, Representation::Double(), any_type},
{PropertyConstness::kMutable, Representation::HeapObject(), value_type},
{PropertyConstness::kMutable, Representation::Tagged(), any_type},
FLAG_unbox_double_fields);
FLAG_unbox_double_fields ? kDeprecation : kFieldOwnerDependency);
}
////////////////////////////////////////////////////////////////////////////////
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment