diff options
author | Michaël Zasso <targos@protonmail.com> | 2017-05-02 10:50:00 +0200 |
---|---|---|
committer | Michaël Zasso <targos@protonmail.com> | 2017-05-06 20:02:35 +0200 |
commit | 60d1aac8d225e844e68ae48e8f3d58802e635fbe (patch) | |
tree | 922f347dd054db18d88666fad7181e5a777f4022 /deps/v8/test/cctest/test-field-type-tracking.cc | |
parent | 73d9c0f903ae371cd5011af64c3a6f69a1bda978 (diff) | |
download | android-node-v8-60d1aac8d225e844e68ae48e8f3d58802e635fbe.tar.gz android-node-v8-60d1aac8d225e844e68ae48e8f3d58802e635fbe.tar.bz2 android-node-v8-60d1aac8d225e844e68ae48e8f3d58802e635fbe.zip |
deps: update V8 to 5.8.283.38
PR-URL: https://github.com/nodejs/node/pull/12784
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Gibson Fahnestock <gibfahn@gmail.com>
Diffstat (limited to 'deps/v8/test/cctest/test-field-type-tracking.cc')
-rw-r--r-- | deps/v8/test/cctest/test-field-type-tracking.cc | 888 |
1 files changed, 580 insertions, 308 deletions
diff --git a/deps/v8/test/cctest/test-field-type-tracking.cc b/deps/v8/test/cctest/test-field-type-tracking.cc index 4abde16cd6..04e23790ad 100644 --- a/deps/v8/test/cctest/test-field-type-tracking.cc +++ b/deps/v8/test/cctest/test-field-type-tracking.cc @@ -18,13 +18,16 @@ #include "src/global-handles.h" #include "src/ic/stub-cache.h" #include "src/macro-assembler.h" +#include "src/objects-inl.h" +#include "src/property.h" +#include "src/transitions.h" using namespace v8::internal; // TODO(ishell): fix this once TransitionToPrototype stops generalizing // all field representations (similar to crbug/448711 where elements kind -// and observed transitions caused generalization of all field representations). +// and observed transitions caused generalization of all fields). const bool IS_PROTO_TRANS_ISSUE_FIXED = false; @@ -79,6 +82,7 @@ class Expectations { ElementsKind elements_kind_; PropertyKind kinds_[MAX_PROPERTIES]; PropertyLocation locations_[MAX_PROPERTIES]; + PropertyConstness constnesses_[MAX_PROPERTIES]; PropertyAttributes attributes_[MAX_PROPERTIES]; Representation representations_[MAX_PROPERTIES]; // FieldType for kField, value for DATA_CONSTANT and getter for @@ -100,11 +104,12 @@ class Expectations { isolate->object_function()->initial_map()->elements_kind()) {} void Init(int index, PropertyKind kind, PropertyAttributes attributes, - PropertyLocation location, Representation representation, - Handle<Object> value) { + PropertyConstness constness, PropertyLocation location, + Representation representation, Handle<Object> value) { CHECK(index < MAX_PROPERTIES); kinds_[index] = kind; locations_[index] = location; + constnesses_[index] = constness; attributes_[index] = attributes; representations_[index] = representation; values_[index] = value; @@ -126,6 +131,7 @@ class Expectations { } os << " ("; + if (constnesses_[i] == kConst) os << "const "; os << (kinds_[i] == kData ? "data " : "accessor "); if (locations_[i] == kField) { os << "field" @@ -149,18 +155,20 @@ class Expectations { } void SetDataField(int index, PropertyAttributes attrs, - Representation representation, + PropertyConstness constness, Representation representation, Handle<FieldType> field_type) { - Init(index, kData, attrs, kField, representation, field_type); + Init(index, kData, attrs, constness, kField, representation, field_type); } - void SetDataField(int index, Representation representation, + void SetDataField(int index, PropertyConstness constness, + Representation representation, Handle<FieldType> field_type) { - SetDataField(index, attributes_[index], representation, field_type); + SetDataField(index, attributes_[index], constness, representation, + field_type); } void SetAccessorField(int index, PropertyAttributes attrs) { - Init(index, kAccessor, attrs, kDescriptor, Representation::Tagged(), + Init(index, kAccessor, attrs, kConst, kDescriptor, Representation::Tagged(), FieldType::Any(isolate_)); } @@ -170,7 +178,15 @@ class Expectations { void SetDataConstant(int index, PropertyAttributes attrs, Handle<JSFunction> value) { - Init(index, kData, attrs, kDescriptor, Representation::HeapObject(), value); + if (FLAG_track_constant_fields) { + Handle<FieldType> field_type(FieldType::Class(value->map()), isolate_); + Init(index, kData, attrs, kConst, kField, Representation::HeapObject(), + field_type); + + } else { + Init(index, kData, attrs, kConst, kDescriptor, + Representation::HeapObject(), value); + } } void SetDataConstant(int index, Handle<JSFunction> value) { @@ -179,7 +195,7 @@ class Expectations { void SetAccessorConstant(int index, PropertyAttributes attrs, Handle<Object> getter, Handle<Object> setter) { - Init(index, kAccessor, attrs, kDescriptor, Representation::Tagged(), + Init(index, kAccessor, attrs, kConst, kDescriptor, Representation::Tagged(), getter); setter_values_[index] = setter; } @@ -215,7 +231,7 @@ class Expectations { SetAccessorConstant(index, getter, setter); } - void GeneralizeRepresentation(int index) { + void GeneralizeField(int index) { CHECK(index < number_of_properties_); representations_[index] = Representation::Tagged(); if (locations_[index] == kField) { @@ -223,12 +239,12 @@ class Expectations { } } - bool Check(DescriptorArray* descriptors, int descriptor) const { PropertyDetails details = descriptors->GetDetails(descriptor); if (details.kind() != kinds_[descriptor]) return false; if (details.location() != locations_[descriptor]) return false; + if (details.constness() != constnesses_[descriptor]) return false; PropertyAttributes expected_attributes = attributes_[descriptor]; if (details.attributes() != expected_attributes) return false; @@ -250,6 +266,7 @@ class Expectations { } else { // kDescriptor if (details.kind() == kData) { + CHECK(!FLAG_track_constant_fields); return value == expected_value; } else { // kAccessor @@ -300,15 +317,17 @@ class Expectations { } Handle<Map> AddDataField(Handle<Map> map, PropertyAttributes attributes, + PropertyConstness constness, Representation representation, Handle<FieldType> heap_type) { CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors()); int property_index = number_of_properties_++; - SetDataField(property_index, attributes, representation, heap_type); + SetDataField(property_index, attributes, constness, representation, + heap_type); Handle<String> name = MakeName("prop", property_index); - return Map::CopyWithField(map, name, heap_type, attributes, representation, - INSERT_TRANSITION) + return Map::CopyWithField(map, name, heap_type, attributes, constness, + representation, INSERT_TRANSITION) .ToHandleChecked(); } @@ -326,16 +345,19 @@ class Expectations { Handle<Map> TransitionToDataField(Handle<Map> map, PropertyAttributes attributes, + PropertyConstness constness, Representation representation, Handle<FieldType> heap_type, Handle<Object> value) { CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors()); int property_index = number_of_properties_++; - SetDataField(property_index, attributes, representation, heap_type); + SetDataField(property_index, attributes, constness, representation, + heap_type); Handle<String> name = MakeName("prop", property_index); return Map::TransitionToDataProperty( - map, name, value, attributes, Object::CERTAINLY_NOT_STORE_FROM_KEYED); + map, name, value, attributes, constness, + Object::CERTAINLY_NOT_STORE_FROM_KEYED); } Handle<Map> TransitionToDataConstant(Handle<Map> map, @@ -347,16 +369,19 @@ class Expectations { Handle<String> name = MakeName("prop", property_index); return Map::TransitionToDataProperty( - map, name, value, attributes, Object::CERTAINLY_NOT_STORE_FROM_KEYED); + map, name, value, attributes, kConst, + Object::CERTAINLY_NOT_STORE_FROM_KEYED); } Handle<Map> FollowDataTransition(Handle<Map> map, PropertyAttributes attributes, + PropertyConstness constness, Representation representation, Handle<FieldType> heap_type) { CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors()); int property_index = number_of_properties_++; - SetDataField(property_index, attributes, representation, heap_type); + SetDataField(property_index, attributes, constness, representation, + heap_type); Handle<String> name = MakeName("prop", property_index); Map* target = @@ -461,7 +486,9 @@ TEST(ReconfigureAccessorToNonExistingDataField) { CHECK(!map->is_stable()); CHECK(expectations.Check(*map)); - expectations.SetDataField(0, NONE, Representation::None(), none_type); + // Property kind reconfiguration always makes the field mutable. + expectations.SetDataField(0, NONE, kMutable, Representation::None(), + none_type); CHECK(!new_map->is_deprecated()); CHECK(new_map->is_stable()); @@ -472,11 +499,12 @@ TEST(ReconfigureAccessorToNonExistingDataField) { CHECK_EQ(*new_map, *new_map2); Handle<Object> value(Smi::kZero, isolate); - Handle<Map> prepared_map = Map::PrepareForDataProperty(new_map, 0, value); + Handle<Map> prepared_map = + Map::PrepareForDataProperty(new_map, 0, kConst, value); // None to Smi generalization is trivial, map does not change. CHECK_EQ(*new_map, *prepared_map); - expectations.SetDataField(0, NONE, Representation::Smi(), any_type); + expectations.SetDataField(0, NONE, kMutable, Representation::Smi(), any_type); CHECK(prepared_map->is_stable()); CHECK(expectations.Check(*prepared_map)); @@ -534,12 +562,19 @@ TEST(ReconfigureAccessorToNonExistingDataFieldHeavy) { //////////////////////////////////////////////////////////////////////////////// -// A set of tests for representation generalization case. +// A set of tests for field generalization case. // -// This test ensures that representation/field type generalization at -// |property_index| is done correctly independently of the fact that the |map| -// is detached from transition tree or not. +// <Constness, Representation, FieldType> data. +struct CRFTData { + PropertyConstness constness; + Representation representation; + Handle<FieldType> type; +}; + +// This test ensures that field generalization at |property_index| is done +// correctly independently of the fact that the |map| is detached from +// transition tree or not. // // {} - p0 - p1 - p2: |detach_point_map| // | @@ -549,12 +584,11 @@ TEST(ReconfigureAccessorToNonExistingDataFieldHeavy) { // // Detaching does not happen if |detach_property_at_index| is -1. // -static void TestGeneralizeRepresentation( - int detach_property_at_index, int property_index, - Representation from_representation, Handle<FieldType> from_type, - Representation to_representation, Handle<FieldType> to_type, - Representation expected_representation, Handle<FieldType> expected_type, - bool expected_deprecation, bool expected_field_type_dependency) { +static 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_type_dependency) { Isolate* isolate = CcTest::i_isolate(); Handle<FieldType> any_type = FieldType::Any(isolate); @@ -573,11 +607,11 @@ static void TestGeneralizeRepresentation( Handle<Map> detach_point_map; for (int i = 0; i < kPropCount; i++) { if (i == property_index) { - map = - expectations.AddDataField(map, NONE, from_representation, from_type); + map = expectations.AddDataField(map, NONE, from.constness, + from.representation, from.type); } else { - map = - expectations.AddDataField(map, NONE, Representation::Smi(), any_type); + map = expectations.AddDataField(map, NONE, kDefaultFieldConstness, + Representation::Smi(), any_type); if (i == detach_property_at_index) { detach_point_map = map; } @@ -593,7 +627,7 @@ static void TestGeneralizeRepresentation( detach_point_map = Map::ReconfigureProperty( detach_point_map, detach_property_at_index, kData, NONE, Representation::Tagged(), any_type); - expectations.SetDataField(detach_property_at_index, + expectations.SetDataField(detach_property_at_index, kDefaultFieldConstness, Representation::Tagged(), any_type); CHECK(map->is_deprecated()); CHECK(expectations.Check(*detach_point_map, @@ -608,10 +642,10 @@ static void TestGeneralizeRepresentation( dependencies.AssumeFieldOwner(field_owner); Handle<Map> new_map = Map::ReconfigureProperty( - map, property_index, kData, NONE, to_representation, to_type); + map, property_index, kData, NONE, to.representation, to.type); - expectations.SetDataField(property_index, expected_representation, - expected_type); + expectations.SetDataField(property_index, expected.constness, + expected.representation, expected.type); CHECK(!new_map->is_deprecated()); CHECK(expectations.Check(*new_map)); @@ -656,84 +690,65 @@ static void TestGeneralizeRepresentation( CHECK_EQ(*new_map, *updated_map); } -static void TestGeneralizeRepresentation( - Representation from_representation, Handle<FieldType> from_type, - Representation to_representation, Handle<FieldType> to_type, - Representation expected_representation, Handle<FieldType> expected_type, - bool expected_deprecation, bool expected_field_type_dependency) { +static void TestGeneralizeField(const CRFTData& from, const CRFTData& to, + const CRFTData& expected, + bool expected_deprecation, + bool expected_field_type_dependency) { // 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++) { - TestGeneralizeRepresentation( - -1, indices[i], from_representation, from_type, to_representation, - to_type, expected_representation, expected_type, expected_deprecation, - expected_field_type_dependency); + TestGeneralizeField(-1, indices[i], from, to, expected, + expected_deprecation, expected_field_type_dependency); } - if (!from_representation.IsNone()) { + if (!from.representation.IsNone()) { // Check the cases when the map being reconfigured is NOT a part of the // transition tree. "None -> anything" representation changes make sense // only for "attached" maps. int indices[] = {0, kPropCount - 1}; for (int i = 0; i < static_cast<int>(arraysize(indices)); i++) { - TestGeneralizeRepresentation( - indices[i], 2, from_representation, from_type, to_representation, - to_type, expected_representation, expected_type, expected_deprecation, - expected_field_type_dependency); + TestGeneralizeField(indices[i], 2, from, to, expected, + expected_deprecation, expected_field_type_dependency); } // Check that reconfiguration to the very same field works correctly. - Representation representation = from_representation; - Handle<FieldType> type = from_type; - TestGeneralizeRepresentation(-1, 2, representation, type, representation, - type, representation, type, false, false); + CRFTData data = from; + TestGeneralizeField(-1, 2, data, data, data, false, false); } } -static void TestGeneralizeRepresentation(Representation from_representation, - Handle<FieldType> from_type, - Representation to_representation, - Handle<FieldType> to_type, - Representation expected_representation, - Handle<FieldType> expected_type) { +static void TestGeneralizeField(const CRFTData& from, const CRFTData& to, + const CRFTData& expected) { const bool expected_deprecation = true; const bool expected_field_type_dependency = false; - TestGeneralizeRepresentation( - from_representation, from_type, to_representation, to_type, - expected_representation, expected_type, expected_deprecation, - expected_field_type_dependency); + TestGeneralizeField(from, to, expected, expected_deprecation, + expected_field_type_dependency); } -static void TestGeneralizeRepresentationTrivial( - Representation from_representation, Handle<FieldType> from_type, - Representation to_representation, Handle<FieldType> to_type, - Representation expected_representation, Handle<FieldType> expected_type, +static void TestGeneralizeFieldTrivial( + const CRFTData& from, const CRFTData& to, const CRFTData& expected, bool expected_field_type_dependency = true) { const bool expected_deprecation = false; - TestGeneralizeRepresentation( - from_representation, from_type, to_representation, to_type, - expected_representation, expected_type, expected_deprecation, - expected_field_type_dependency); + TestGeneralizeField(from, to, expected, expected_deprecation, + expected_field_type_dependency); } - -TEST(GeneralizeRepresentationSmiToDouble) { +TEST(GeneralizeSmiFieldToDouble) { CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); Isolate* isolate = CcTest::i_isolate(); Handle<FieldType> any_type = FieldType::Any(isolate); - TestGeneralizeRepresentation(Representation::Smi(), any_type, - Representation::Double(), any_type, - Representation::Double(), any_type); + TestGeneralizeField({kMutable, Representation::Smi(), any_type}, + {kMutable, Representation::Double(), any_type}, + {kMutable, Representation::Double(), any_type}); } - -TEST(GeneralizeRepresentationSmiToTagged) { +TEST(GeneralizeSmiFieldToTagged) { CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); Isolate* isolate = CcTest::i_isolate(); @@ -741,13 +756,12 @@ TEST(GeneralizeRepresentationSmiToTagged) { Handle<FieldType> value_type = FieldType::Class(Map::Create(isolate, 0), isolate); - TestGeneralizeRepresentation(Representation::Smi(), any_type, - Representation::HeapObject(), value_type, - Representation::Tagged(), any_type); + TestGeneralizeField({kMutable, Representation::Smi(), any_type}, + {kMutable, Representation::HeapObject(), value_type}, + {kMutable, Representation::Tagged(), any_type}); } - -TEST(GeneralizeRepresentationDoubleToTagged) { +TEST(GeneralizeDoubleFieldToTagged) { CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); Isolate* isolate = CcTest::i_isolate(); @@ -755,13 +769,12 @@ TEST(GeneralizeRepresentationDoubleToTagged) { Handle<FieldType> value_type = FieldType::Class(Map::Create(isolate, 0), isolate); - TestGeneralizeRepresentation(Representation::Double(), any_type, - Representation::HeapObject(), value_type, - Representation::Tagged(), any_type); + TestGeneralizeField({kMutable, Representation::Double(), any_type}, + {kMutable, Representation::HeapObject(), value_type}, + {kMutable, Representation::Tagged(), any_type}); } - -TEST(GeneralizeRepresentationHeapObjectToTagged) { +TEST(GeneralizeHeapObjectFieldToTagged) { CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); Isolate* isolate = CcTest::i_isolate(); @@ -769,13 +782,12 @@ TEST(GeneralizeRepresentationHeapObjectToTagged) { Handle<FieldType> value_type = FieldType::Class(Map::Create(isolate, 0), isolate); - TestGeneralizeRepresentation(Representation::HeapObject(), value_type, - Representation::Smi(), any_type, - Representation::Tagged(), any_type); + TestGeneralizeField({kMutable, Representation::HeapObject(), value_type}, + {kMutable, Representation::Smi(), any_type}, + {kMutable, Representation::Tagged(), any_type}); } - -TEST(GeneralizeRepresentationHeapObjectToHeapObject) { +TEST(GeneralizeHeapObjectFieldToHeapObject) { CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); Isolate* isolate = CcTest::i_isolate(); @@ -789,21 +801,21 @@ TEST(GeneralizeRepresentationHeapObjectToHeapObject) { Handle<FieldType> expected_type = any_type; - TestGeneralizeRepresentationTrivial( - Representation::HeapObject(), current_type, - Representation::HeapObject(), new_type, Representation::HeapObject(), - expected_type); - current_type = expected_type; + TestGeneralizeFieldTrivial( + {kMutable, Representation::HeapObject(), current_type}, + {kMutable, Representation::HeapObject(), new_type}, + {kMutable, Representation::HeapObject(), expected_type}); + current_type = expected_type; - new_type = FieldType::Class(Map::Create(isolate, 0), isolate); + new_type = FieldType::Class(Map::Create(isolate, 0), isolate); - TestGeneralizeRepresentationTrivial( - Representation::HeapObject(), any_type, Representation::HeapObject(), - new_type, Representation::HeapObject(), any_type, false); + TestGeneralizeFieldTrivial({kMutable, Representation::HeapObject(), any_type}, + {kMutable, Representation::HeapObject(), new_type}, + {kMutable, Representation::HeapObject(), any_type}, + false); } - -TEST(GeneralizeRepresentationNoneToSmi) { +TEST(GeneralizeNoneFieldToSmi) { CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); Isolate* isolate = CcTest::i_isolate(); @@ -811,13 +823,12 @@ TEST(GeneralizeRepresentationNoneToSmi) { Handle<FieldType> any_type = FieldType::Any(isolate); // None -> Smi representation change is trivial. - TestGeneralizeRepresentationTrivial(Representation::None(), none_type, - Representation::Smi(), any_type, - Representation::Smi(), any_type); + TestGeneralizeFieldTrivial({kMutable, Representation::None(), none_type}, + {kMutable, Representation::Smi(), any_type}, + {kMutable, Representation::Smi(), any_type}); } - -TEST(GeneralizeRepresentationNoneToDouble) { +TEST(GeneralizeNoneFieldToDouble) { CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); Isolate* isolate = CcTest::i_isolate(); @@ -825,13 +836,12 @@ TEST(GeneralizeRepresentationNoneToDouble) { Handle<FieldType> any_type = FieldType::Any(isolate); // None -> Double representation change is NOT trivial. - TestGeneralizeRepresentation(Representation::None(), none_type, - Representation::Double(), any_type, - Representation::Double(), any_type); + TestGeneralizeField({kMutable, Representation::None(), none_type}, + {kMutable, Representation::Double(), any_type}, + {kMutable, Representation::Double(), any_type}); } - -TEST(GeneralizeRepresentationNoneToHeapObject) { +TEST(GeneralizeNoneFieldToHeapObject) { CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); Isolate* isolate = CcTest::i_isolate(); @@ -840,13 +850,13 @@ TEST(GeneralizeRepresentationNoneToHeapObject) { FieldType::Class(Map::Create(isolate, 0), isolate); // None -> HeapObject representation change is trivial. - TestGeneralizeRepresentationTrivial(Representation::None(), none_type, - Representation::HeapObject(), value_type, - Representation::HeapObject(), value_type); + TestGeneralizeFieldTrivial( + {kMutable, Representation::None(), none_type}, + {kMutable, Representation::HeapObject(), value_type}, + {kMutable, Representation::HeapObject(), value_type}); } - -TEST(GeneralizeRepresentationNoneToTagged) { +TEST(GeneralizeNoneFieldToTagged) { CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); Isolate* isolate = CcTest::i_isolate(); @@ -854,18 +864,17 @@ TEST(GeneralizeRepresentationNoneToTagged) { Handle<FieldType> any_type = FieldType::Any(isolate); // None -> HeapObject representation change is trivial. - TestGeneralizeRepresentationTrivial(Representation::None(), none_type, - Representation::Tagged(), any_type, - Representation::Tagged(), any_type); + TestGeneralizeFieldTrivial({kMutable, Representation::None(), none_type}, + {kMutable, Representation::Tagged(), any_type}, + {kMutable, Representation::Tagged(), any_type}); } //////////////////////////////////////////////////////////////////////////////// -// A set of tests for representation generalization case with kAccessor -// properties. +// A set of tests for field generalization case with kAccessor properties. // -TEST(GeneralizeRepresentationWithAccessorProperties) { +TEST(GeneralizeFieldWithAccessorProperties) { CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); Isolate* isolate = CcTest::i_isolate(); @@ -882,8 +891,8 @@ TEST(GeneralizeRepresentationWithAccessorProperties) { if (i == kAccessorProp) { map = expectations.AddAccessorConstant(map, NONE, pair); } else { - map = - expectations.AddDataField(map, NONE, Representation::Smi(), any_type); + map = expectations.AddDataField(map, NONE, kMutable, + Representation::Smi(), any_type); } } CHECK(!map->is_deprecated()); @@ -902,7 +911,7 @@ TEST(GeneralizeRepresentationWithAccessorProperties) { map, i, kData, NONE, Representation::Double(), any_type); maps[i] = new_map; - expectations.SetDataField(i, Representation::Double(), any_type); + expectations.SetDataField(i, kMutable, Representation::Double(), any_type); CHECK(!map->is_stable()); CHECK(map->is_deprecated()); @@ -930,8 +939,8 @@ TEST(GeneralizeRepresentationWithAccessorProperties) { // A set of tests for attribute reconfiguration case. // -// This test ensures that representation/field type generalization is correctly -// propagated from one branch of transition tree (|map2|) to another (|map|). +// This test ensures that field generalization is correctly propagated from one +// branch of transition tree (|map2|) to another (|map|). // // + - p2B - p3 - p4: |map2| // | @@ -939,10 +948,8 @@ TEST(GeneralizeRepresentationWithAccessorProperties) { // // where "p2A" and "p2B" differ only in the attributes. // -static void TestReconfigureDataFieldAttribute_GeneralizeRepresentation( - Representation from_representation, Handle<FieldType> from_type, - Representation to_representation, Handle<FieldType> to_type, - Representation expected_representation, Handle<FieldType> expected_type) { +static void TestReconfigureDataFieldAttribute_GeneralizeField( + const CRFTData& from, const CRFTData& to, const CRFTData& expected) { Isolate* isolate = CcTest::i_isolate(); Expectations expectations(isolate); @@ -951,7 +958,8 @@ static void TestReconfigureDataFieldAttribute_GeneralizeRepresentation( 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_representation, from_type); + map = expectations.AddDataField(map, NONE, from.constness, + from.representation, from.type); } CHECK(!map->is_deprecated()); CHECK(map->is_stable()); @@ -965,14 +973,15 @@ static void TestReconfigureDataFieldAttribute_GeneralizeRepresentation( Handle<Map> map2 = initial_map; for (int i = 0; i < kSplitProp; i++) { - map2 = expectations2.FollowDataTransition(map2, NONE, from_representation, - from_type); + map2 = expectations2.FollowDataTransition(map2, NONE, from.constness, + from.representation, from.type); } - map2 = - expectations2.AddDataField(map2, READ_ONLY, to_representation, to_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_representation, to_type); + map2 = expectations2.AddDataField(map2, NONE, to.constness, + to.representation, to.type); } CHECK(!map2->is_deprecated()); CHECK(map2->is_stable()); @@ -997,7 +1006,8 @@ static void TestReconfigureDataFieldAttribute_GeneralizeRepresentation( // |map| should be deprecated and |new_map| should match new expectations. for (int i = kSplitProp; i < kPropCount; i++) { - expectations.SetDataField(i, expected_representation, expected_type); + expectations.SetDataField(i, expected.constness, expected.representation, + expected.type); } CHECK(map->is_deprecated()); CHECK(!dependencies.HasAborted()); @@ -1012,10 +1022,9 @@ static void TestReconfigureDataFieldAttribute_GeneralizeRepresentation( CHECK_EQ(*new_map, *updated_map); } - -// This test ensures that trivial representation/field type generalization -// (from HeapObject to HeapObject) is correctly propagated from one branch of -// transition tree (|map2|) to another (|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| // | @@ -1023,10 +1032,8 @@ static void TestReconfigureDataFieldAttribute_GeneralizeRepresentation( // // where "p2A" and "p2B" differ only in the attributes. // -static void TestReconfigureDataFieldAttribute_GeneralizeRepresentationTrivial( - Representation from_representation, Handle<FieldType> from_type, - Representation to_representation, Handle<FieldType> to_type, - Representation expected_representation, Handle<FieldType> expected_type, +static void TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial( + const CRFTData& from, const CRFTData& to, const CRFTData& expected, bool expected_field_type_dependency = true) { Isolate* isolate = CcTest::i_isolate(); @@ -1036,7 +1043,8 @@ static void TestReconfigureDataFieldAttribute_GeneralizeRepresentationTrivial( 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_representation, from_type); + map = expectations.AddDataField(map, NONE, from.constness, + from.representation, from.type); } CHECK(!map->is_deprecated()); CHECK(map->is_stable()); @@ -1050,14 +1058,15 @@ static void TestReconfigureDataFieldAttribute_GeneralizeRepresentationTrivial( Handle<Map> map2 = initial_map; for (int i = 0; i < kSplitProp; i++) { - map2 = expectations2.FollowDataTransition(map2, NONE, from_representation, - from_type); + map2 = expectations2.FollowDataTransition(map2, NONE, from.constness, + from.representation, from.type); } - map2 = - expectations2.AddDataField(map2, READ_ONLY, to_representation, to_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_representation, to_type); + map2 = expectations2.AddDataField(map2, NONE, to.constness, + to.representation, to.type); } CHECK(!map2->is_deprecated()); CHECK(map2->is_stable()); @@ -1085,7 +1094,8 @@ static void TestReconfigureDataFieldAttribute_GeneralizeRepresentationTrivial( // 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_representation, expected_type); + expectations.SetDataField(i, expected.constness, expected.representation, + expected.type); } CHECK(!map->is_deprecated()); CHECK_EQ(*map, *new_map); @@ -1099,20 +1109,36 @@ static void TestReconfigureDataFieldAttribute_GeneralizeRepresentationTrivial( CHECK_EQ(*new_map, *updated_map); } - -TEST(ReconfigureDataFieldAttribute_GeneralizeRepresentationSmiToDouble) { +TEST(ReconfigureDataFieldAttribute_GeneralizeSmiFieldToDouble) { CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); Isolate* isolate = CcTest::i_isolate(); Handle<FieldType> any_type = FieldType::Any(isolate); - TestReconfigureDataFieldAttribute_GeneralizeRepresentation( - Representation::Smi(), any_type, Representation::Double(), any_type, - Representation::Double(), any_type); -} + if (FLAG_track_constant_fields) { + TestReconfigureDataFieldAttribute_GeneralizeField( + {kConst, Representation::Smi(), any_type}, + {kConst, Representation::Double(), any_type}, + {kConst, Representation::Double(), any_type}); + + TestReconfigureDataFieldAttribute_GeneralizeField( + {kConst, Representation::Smi(), any_type}, + {kMutable, Representation::Double(), any_type}, + {kMutable, Representation::Double(), any_type}); + + TestReconfigureDataFieldAttribute_GeneralizeField( + {kMutable, Representation::Smi(), any_type}, + {kConst, Representation::Double(), any_type}, + {kMutable, Representation::Double(), any_type}); + } + TestReconfigureDataFieldAttribute_GeneralizeField( + {kMutable, Representation::Smi(), any_type}, + {kMutable, Representation::Double(), any_type}, + {kMutable, Representation::Double(), any_type}); +} -TEST(ReconfigureDataFieldAttribute_GeneralizeRepresentationSmiToTagged) { +TEST(ReconfigureDataFieldAttribute_GeneralizeSmiFieldToTagged) { CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); Isolate* isolate = CcTest::i_isolate(); @@ -1120,13 +1146,30 @@ TEST(ReconfigureDataFieldAttribute_GeneralizeRepresentationSmiToTagged) { Handle<FieldType> value_type = FieldType::Class(Map::Create(isolate, 0), isolate); - TestReconfigureDataFieldAttribute_GeneralizeRepresentation( - Representation::Smi(), any_type, Representation::HeapObject(), value_type, - Representation::Tagged(), any_type); -} + if (FLAG_track_constant_fields) { + TestReconfigureDataFieldAttribute_GeneralizeField( + {kConst, Representation::Smi(), any_type}, + {kConst, Representation::HeapObject(), value_type}, + {kConst, Representation::Tagged(), any_type}); + TestReconfigureDataFieldAttribute_GeneralizeField( + {kConst, Representation::Smi(), any_type}, + {kMutable, Representation::HeapObject(), value_type}, + {kMutable, Representation::Tagged(), any_type}); + + TestReconfigureDataFieldAttribute_GeneralizeField( + {kMutable, Representation::Smi(), any_type}, + {kConst, Representation::HeapObject(), value_type}, + {kMutable, Representation::Tagged(), any_type}); + } -TEST(ReconfigureDataFieldAttribute_GeneralizeRepresentationDoubleToTagged) { + TestReconfigureDataFieldAttribute_GeneralizeField( + {kMutable, Representation::Smi(), any_type}, + {kMutable, Representation::HeapObject(), value_type}, + {kMutable, Representation::Tagged(), any_type}); +} + +TEST(ReconfigureDataFieldAttribute_GeneralizeDoubleFieldToTagged) { CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); Isolate* isolate = CcTest::i_isolate(); @@ -1134,13 +1177,30 @@ TEST(ReconfigureDataFieldAttribute_GeneralizeRepresentationDoubleToTagged) { Handle<FieldType> value_type = FieldType::Class(Map::Create(isolate, 0), isolate); - TestReconfigureDataFieldAttribute_GeneralizeRepresentation( - Representation::Double(), any_type, Representation::HeapObject(), - value_type, Representation::Tagged(), any_type); -} + if (FLAG_track_constant_fields) { + TestReconfigureDataFieldAttribute_GeneralizeField( + {kConst, Representation::Double(), any_type}, + {kConst, Representation::HeapObject(), value_type}, + {kConst, Representation::Tagged(), any_type}); + + TestReconfigureDataFieldAttribute_GeneralizeField( + {kConst, Representation::Double(), any_type}, + {kMutable, Representation::HeapObject(), value_type}, + {kMutable, Representation::Tagged(), any_type}); + TestReconfigureDataFieldAttribute_GeneralizeField( + {kMutable, Representation::Double(), any_type}, + {kConst, Representation::HeapObject(), value_type}, + {kMutable, Representation::Tagged(), any_type}); + } + + TestReconfigureDataFieldAttribute_GeneralizeField( + {kMutable, Representation::Double(), any_type}, + {kMutable, Representation::HeapObject(), value_type}, + {kMutable, Representation::Tagged(), any_type}); +} -TEST(ReconfigureDataFieldAttribute_GeneralizeRepresentationHeapObjToHeapObj) { +TEST(ReconfigureDataFieldAttribute_GeneralizeHeapObjFieldToHeapObj) { CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); Isolate* isolate = CcTest::i_isolate(); @@ -1154,20 +1214,59 @@ TEST(ReconfigureDataFieldAttribute_GeneralizeRepresentationHeapObjToHeapObj) { Handle<FieldType> expected_type = any_type; - TestReconfigureDataFieldAttribute_GeneralizeRepresentationTrivial( - Representation::HeapObject(), current_type, Representation::HeapObject(), - new_type, Representation::HeapObject(), expected_type); + // Check generalizations that trigger deopts. + if (FLAG_track_constant_fields) { + TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial( + {kConst, Representation::HeapObject(), current_type}, + {kConst, Representation::HeapObject(), new_type}, + {kConst, Representation::HeapObject(), expected_type}); + + // Currently, kConst to kMutable migration causes map change, therefore + // non-trivial generalization. + TestReconfigureDataFieldAttribute_GeneralizeField( + {kConst, Representation::HeapObject(), current_type}, + {kMutable, Representation::HeapObject(), new_type}, + {kMutable, Representation::HeapObject(), expected_type}); + + TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial( + {kMutable, Representation::HeapObject(), current_type}, + {kConst, Representation::HeapObject(), new_type}, + {kMutable, Representation::HeapObject(), expected_type}); + } + TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial( + {kMutable, Representation::HeapObject(), current_type}, + {kMutable, Representation::HeapObject(), new_type}, + {kMutable, Representation::HeapObject(), expected_type}); current_type = expected_type; + // Check generalizations that do not trigger deopts. new_type = FieldType::Class(Map::Create(isolate, 0), isolate); - TestReconfigureDataFieldAttribute_GeneralizeRepresentationTrivial( - Representation::HeapObject(), any_type, Representation::HeapObject(), - new_type, Representation::HeapObject(), any_type, false); + if (FLAG_track_constant_fields) { + TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial( + {kConst, Representation::HeapObject(), any_type}, + {kConst, Representation::HeapObject(), new_type}, + {kConst, Representation::HeapObject(), any_type}, false); + + // Currently, kConst to kMutable migration causes map change, therefore + // non-trivial generalization. + TestReconfigureDataFieldAttribute_GeneralizeField( + {kConst, Representation::HeapObject(), any_type}, + {kMutable, Representation::HeapObject(), new_type}, + {kMutable, Representation::HeapObject(), any_type}); + + TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial( + {kMutable, Representation::HeapObject(), any_type}, + {kConst, Representation::HeapObject(), new_type}, + {kMutable, Representation::HeapObject(), any_type}, false); + } + TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial( + {kMutable, Representation::HeapObject(), any_type}, + {kMutable, Representation::HeapObject(), new_type}, + {kMutable, Representation::HeapObject(), any_type}, false); } - -TEST(ReconfigureDataFieldAttribute_GeneralizeRepresentationHeapObjectToTagged) { +TEST(ReconfigureDataFieldAttribute_GeneralizeHeapObjectFieldToTagged) { CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); Isolate* isolate = CcTest::i_isolate(); @@ -1175,9 +1274,10 @@ TEST(ReconfigureDataFieldAttribute_GeneralizeRepresentationHeapObjectToTagged) { Handle<FieldType> value_type = FieldType::Class(Map::Create(isolate, 0), isolate); - TestReconfigureDataFieldAttribute_GeneralizeRepresentation( - Representation::HeapObject(), value_type, Representation::Smi(), any_type, - Representation::Tagged(), any_type); + TestReconfigureDataFieldAttribute_GeneralizeField( + {kMutable, Representation::HeapObject(), value_type}, + {kMutable, Representation::Smi(), any_type}, + {kMutable, Representation::Tagged(), any_type}); } @@ -1243,7 +1343,7 @@ struct CheckCopyGeneralizeAllFields { CHECK(new_map->GetBackPointer()->IsUndefined(map->GetIsolate())); for (int i = 0; i < kPropCount; i++) { - expectations.GeneralizeRepresentation(i); + expectations.GeneralizeField(i); } CHECK(!new_map->is_deprecated()); @@ -1251,9 +1351,8 @@ struct CheckCopyGeneralizeAllFields { } }; - -// This test ensures that representation/field type generalization is correctly -// propagated from one branch of transition tree (|map2|) to another (|map1|). +// This test ensures that field generalization is correctly propagated from one +// branch of transition tree (|map2|) to another (|map1|). // // + - p2B - p3 - p4: |map2| // | @@ -1277,13 +1376,15 @@ static void TestReconfigureProperty_CustomPropertyAfterTargetMap( const int kSplitProp = 2; CHECK(kSplitProp < kCustomPropIndex); + const PropertyConstness constness = kMutable; const Representation representation = Representation::Smi(); // Create common part of transition tree. Handle<Map> initial_map = Map::Create(isolate, 0); Handle<Map> map = initial_map; for (int i = 0; i < kSplitProp; i++) { - map = expectations.AddDataField(map, NONE, representation, any_type); + map = expectations.AddDataField(map, NONE, constness, representation, + any_type); } CHECK(!map->is_deprecated()); CHECK(map->is_stable()); @@ -1294,11 +1395,13 @@ static void TestReconfigureProperty_CustomPropertyAfterTargetMap( Handle<Map> map1 = map; Expectations expectations1 = expectations; for (int i = kSplitProp; i < kCustomPropIndex; i++) { - map1 = expectations1.AddDataField(map1, NONE, representation, any_type); + map1 = expectations1.AddDataField(map1, NONE, constness, representation, + any_type); } map1 = config.AddPropertyAtBranch(1, expectations1, map1); for (int i = kCustomPropIndex + 1; i < kPropCount; i++) { - map1 = expectations1.AddDataField(map1, NONE, representation, any_type); + map1 = expectations1.AddDataField(map1, NONE, constness, representation, + any_type); } CHECK(!map1->is_deprecated()); CHECK(map1->is_stable()); @@ -1309,13 +1412,16 @@ static void TestReconfigureProperty_CustomPropertyAfterTargetMap( // has different attributes), initialize expectations. Handle<Map> map2 = map; Expectations expectations2 = expectations; - map2 = expectations2.AddDataField(map2, READ_ONLY, representation, any_type); + map2 = expectations2.AddDataField(map2, READ_ONLY, constness, representation, + any_type); for (int i = kSplitProp + 1; i < kCustomPropIndex; i++) { - map2 = expectations2.AddDataField(map2, NONE, representation, any_type); + map2 = expectations2.AddDataField(map2, NONE, constness, representation, + any_type); } map2 = config.AddPropertyAtBranch(2, expectations2, map2); for (int i = kCustomPropIndex + 1; i < kPropCount; i++) { - map2 = expectations2.AddDataField(map2, NONE, representation, any_type); + map2 = expectations2.AddDataField(map2, NONE, constness, representation, + any_type); } CHECK(!map2->is_deprecated()); CHECK(map2->is_stable()); @@ -1403,15 +1509,23 @@ TEST(ReconfigureDataFieldAttribute_DataConstantToDataFieldAfterTargetMap) { } void UpdateExpectations(int property_index, Expectations& expectations) { - expectations.SetDataField(property_index, Representation::HeapObject(), - function_type_); + PropertyConstness expected_constness = + FLAG_track_constant_fields ? kConst : kMutable; + expectations.SetDataField(property_index, expected_constness, + Representation::HeapObject(), function_type_); } }; TestConfig config; - // Two branches are "incompatible" so the |map1| should be deprecated. - CheckDeprecated checker; - TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker); + if (FLAG_track_constant_fields) { + CheckSameMap checker; + TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker); + + } else { + // Two branches are "incompatible" so the |map1| should be deprecated. + CheckDeprecated checker; + TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker); + } } @@ -1534,8 +1648,8 @@ TEST(ReconfigureDataFieldAttribute_AccConstantToDataFieldAfterTargetMap) { } else { Isolate* isolate = CcTest::i_isolate(); Handle<FieldType> any_type = FieldType::Any(isolate); - return expectations.AddDataField(map, NONE, Representation::Smi(), - any_type); + return expectations.AddDataField(map, NONE, kDefaultFieldConstness, + Representation::Smi(), any_type); } } @@ -1553,8 +1667,8 @@ TEST(ReconfigureDataFieldAttribute_AccConstantToDataFieldAfterTargetMap) { // A set of tests for elements kind reconfiguration case. // -// This test ensures that representation/field type generalization is correctly -// propagated from one branch of transition tree (|map2) to another (|map|). +// This test ensures that field generalization is correctly propagated from one +// branch of transition tree (|map2) to another (|map|). // // + - p0 - p1 - p2A - p3 - p4: |map| // | @@ -1564,10 +1678,8 @@ TEST(ReconfigureDataFieldAttribute_AccConstantToDataFieldAfterTargetMap) { // // where "p2A" and "p2B" differ only in the representation/field type. // -static void TestReconfigureElementsKind_GeneralizeRepresentation( - Representation from_representation, Handle<FieldType> from_type, - Representation to_representation, Handle<FieldType> to_type, - Representation expected_representation, Handle<FieldType> expected_type) { +static void TestReconfigureElementsKind_GeneralizeField( + const CRFTData& from, const CRFTData& to, const CRFTData& expected) { Isolate* isolate = CcTest::i_isolate(); Expectations expectations(isolate, FAST_SMI_ELEMENTS); @@ -1579,7 +1691,8 @@ static void TestReconfigureElementsKind_GeneralizeRepresentation( Handle<Map> map = initial_map; map = expectations.AsElementsKind(map, FAST_ELEMENTS); for (int i = 0; i < kPropCount; i++) { - map = expectations.AddDataField(map, NONE, from_representation, from_type); + map = expectations.AddDataField(map, NONE, from.constness, + from.representation, from.type); } CHECK(!map->is_deprecated()); CHECK(map->is_stable()); @@ -1593,10 +1706,11 @@ static void TestReconfigureElementsKind_GeneralizeRepresentation( Handle<Map> map2 = initial_map; for (int i = 0; i < kPropCount; i++) { if (i == kDiffProp) { - map2 = expectations2.AddDataField(map2, NONE, to_representation, to_type); + map2 = expectations2.AddDataField(map2, NONE, to.constness, + to.representation, to.type); } else { - map2 = expectations2.AddDataField(map2, NONE, from_representation, - from_type); + map2 = expectations2.AddDataField(map2, NONE, from.constness, + from.representation, from.type); } } CHECK(!map2->is_deprecated()); @@ -1620,7 +1734,8 @@ static void TestReconfigureElementsKind_GeneralizeRepresentation( CHECK(expectations2.Check(*map2)); // |map| should be deprecated and |new_map| should match new expectations. - expectations.SetDataField(kDiffProp, expected_representation, expected_type); + expectations.SetDataField(kDiffProp, expected.constness, + expected.representation, expected.type); CHECK(map->is_deprecated()); CHECK(!dependencies.HasAborted()); @@ -1644,9 +1759,9 @@ static void TestReconfigureElementsKind_GeneralizeRepresentation( } } -// This test ensures that trivial representation/field type generalization -// (from HeapObject to HeapObject) is correctly propagated from one branch of -// transition tree (|map2|) to another (|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|). // // + - p0 - p1 - p2A - p3 - p4: |map| // | @@ -1656,10 +1771,8 @@ static void TestReconfigureElementsKind_GeneralizeRepresentation( // // where "p2A" and "p2B" differ only in the representation/field type. // -static void TestReconfigureElementsKind_GeneralizeRepresentationTrivial( - Representation from_representation, Handle<FieldType> from_type, - Representation to_representation, Handle<FieldType> to_type, - Representation expected_representation, Handle<FieldType> expected_type, +static void TestReconfigureElementsKind_GeneralizeFieldTrivial( + const CRFTData& from, const CRFTData& to, const CRFTData& expected, bool expected_field_type_dependency = true) { Isolate* isolate = CcTest::i_isolate(); @@ -1672,7 +1785,8 @@ static void TestReconfigureElementsKind_GeneralizeRepresentationTrivial( Handle<Map> map = initial_map; map = expectations.AsElementsKind(map, FAST_ELEMENTS); for (int i = 0; i < kPropCount; i++) { - map = expectations.AddDataField(map, NONE, from_representation, from_type); + map = expectations.AddDataField(map, NONE, from.constness, + from.representation, from.type); } CHECK(!map->is_deprecated()); CHECK(map->is_stable()); @@ -1686,10 +1800,11 @@ static void TestReconfigureElementsKind_GeneralizeRepresentationTrivial( Handle<Map> map2 = initial_map; for (int i = 0; i < kPropCount; i++) { if (i == kDiffProp) { - map2 = expectations2.AddDataField(map2, NONE, to_representation, to_type); + map2 = expectations2.AddDataField(map2, NONE, to.constness, + to.representation, to.type); } else { - map2 = expectations2.AddDataField(map2, NONE, from_representation, - from_type); + map2 = expectations2.AddDataField(map2, NONE, from.constness, + from.representation, from.type); } } CHECK(!map2->is_deprecated()); @@ -1716,7 +1831,8 @@ static void TestReconfigureElementsKind_GeneralizeRepresentationTrivial( // 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_representation, expected_type); + expectations.SetDataField(kDiffProp, expected.constness, + expected.representation, expected.type); CHECK(!map->is_deprecated()); CHECK_EQ(*map, *new_map); CHECK_EQ(expected_field_type_dependency, dependencies.HasAborted()); @@ -1738,18 +1854,35 @@ static void TestReconfigureElementsKind_GeneralizeRepresentationTrivial( } } -TEST(ReconfigureElementsKind_GeneralizeRepresentationSmiToDouble) { +TEST(ReconfigureElementsKind_GeneralizeSmiFieldToDouble) { CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); Isolate* isolate = CcTest::i_isolate(); Handle<FieldType> any_type = FieldType::Any(isolate); - TestReconfigureElementsKind_GeneralizeRepresentation( - Representation::Smi(), any_type, Representation::Double(), any_type, - Representation::Double(), any_type); + if (FLAG_track_constant_fields) { + TestReconfigureElementsKind_GeneralizeField( + {kConst, Representation::Smi(), any_type}, + {kConst, Representation::Double(), any_type}, + {kConst, Representation::Double(), any_type}); + + TestReconfigureElementsKind_GeneralizeField( + {kConst, Representation::Smi(), any_type}, + {kMutable, Representation::Double(), any_type}, + {kMutable, Representation::Double(), any_type}); + + TestReconfigureElementsKind_GeneralizeField( + {kMutable, Representation::Smi(), any_type}, + {kConst, Representation::Double(), any_type}, + {kMutable, Representation::Double(), any_type}); + } + TestReconfigureElementsKind_GeneralizeField( + {kMutable, Representation::Smi(), any_type}, + {kMutable, Representation::Double(), any_type}, + {kMutable, Representation::Double(), any_type}); } -TEST(ReconfigureElementsKind_GeneralizeRepresentationSmiToTagged) { +TEST(ReconfigureElementsKind_GeneralizeSmiFieldToTagged) { CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); Isolate* isolate = CcTest::i_isolate(); @@ -1757,12 +1890,29 @@ TEST(ReconfigureElementsKind_GeneralizeRepresentationSmiToTagged) { Handle<FieldType> value_type = FieldType::Class(Map::Create(isolate, 0), isolate); - TestReconfigureElementsKind_GeneralizeRepresentation( - Representation::Smi(), any_type, Representation::HeapObject(), value_type, - Representation::Tagged(), any_type); + if (FLAG_track_constant_fields) { + TestReconfigureElementsKind_GeneralizeField( + {kConst, Representation::Smi(), any_type}, + {kConst, Representation::HeapObject(), value_type}, + {kConst, Representation::Tagged(), any_type}); + + TestReconfigureElementsKind_GeneralizeField( + {kConst, Representation::Smi(), any_type}, + {kMutable, Representation::HeapObject(), value_type}, + {kMutable, Representation::Tagged(), any_type}); + + TestReconfigureElementsKind_GeneralizeField( + {kMutable, Representation::Smi(), any_type}, + {kConst, Representation::HeapObject(), value_type}, + {kMutable, Representation::Tagged(), any_type}); + } + TestReconfigureElementsKind_GeneralizeField( + {kMutable, Representation::Smi(), any_type}, + {kMutable, Representation::HeapObject(), value_type}, + {kMutable, Representation::Tagged(), any_type}); } -TEST(ReconfigureElementsKind_GeneralizeRepresentationDoubleToTagged) { +TEST(ReconfigureElementsKind_GeneralizeDoubleFieldToTagged) { CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); Isolate* isolate = CcTest::i_isolate(); @@ -1770,12 +1920,29 @@ TEST(ReconfigureElementsKind_GeneralizeRepresentationDoubleToTagged) { Handle<FieldType> value_type = FieldType::Class(Map::Create(isolate, 0), isolate); - TestReconfigureElementsKind_GeneralizeRepresentation( - Representation::Double(), any_type, Representation::HeapObject(), - value_type, Representation::Tagged(), any_type); + if (FLAG_track_constant_fields) { + TestReconfigureElementsKind_GeneralizeField( + {kConst, Representation::Double(), any_type}, + {kConst, Representation::HeapObject(), value_type}, + {kConst, Representation::Tagged(), any_type}); + + TestReconfigureElementsKind_GeneralizeField( + {kConst, Representation::Double(), any_type}, + {kMutable, Representation::HeapObject(), value_type}, + {kMutable, Representation::Tagged(), any_type}); + + TestReconfigureElementsKind_GeneralizeField( + {kMutable, Representation::Double(), any_type}, + {kConst, Representation::HeapObject(), value_type}, + {kMutable, Representation::Tagged(), any_type}); + } + TestReconfigureElementsKind_GeneralizeField( + {kMutable, Representation::Double(), any_type}, + {kMutable, Representation::HeapObject(), value_type}, + {kMutable, Representation::Tagged(), any_type}); } -TEST(ReconfigureElementsKind_GeneralizeRepresentationHeapObjToHeapObj) { +TEST(ReconfigureElementsKind_GeneralizeHeapObjFieldToHeapObj) { CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); Isolate* isolate = CcTest::i_isolate(); @@ -1789,19 +1956,59 @@ TEST(ReconfigureElementsKind_GeneralizeRepresentationHeapObjToHeapObj) { Handle<FieldType> expected_type = any_type; - TestReconfigureElementsKind_GeneralizeRepresentationTrivial( - Representation::HeapObject(), current_type, Representation::HeapObject(), - new_type, Representation::HeapObject(), expected_type); + // Check generalizations that trigger deopts. + if (FLAG_track_constant_fields) { + TestReconfigureElementsKind_GeneralizeFieldTrivial( + {kConst, Representation::HeapObject(), current_type}, + {kConst, Representation::HeapObject(), new_type}, + {kConst, Representation::HeapObject(), expected_type}); + + // Currently, kConst to kMutable migration causes map change, therefore + // non-trivial generalization. + TestReconfigureElementsKind_GeneralizeField( + {kConst, Representation::HeapObject(), current_type}, + {kMutable, Representation::HeapObject(), new_type}, + {kMutable, Representation::HeapObject(), expected_type}); + + TestReconfigureElementsKind_GeneralizeFieldTrivial( + {kMutable, Representation::HeapObject(), current_type}, + {kConst, Representation::HeapObject(), new_type}, + {kMutable, Representation::HeapObject(), expected_type}); + } + TestReconfigureElementsKind_GeneralizeFieldTrivial( + {kMutable, Representation::HeapObject(), current_type}, + {kMutable, Representation::HeapObject(), new_type}, + {kMutable, Representation::HeapObject(), expected_type}); current_type = expected_type; + // Check generalizations that do not trigger deopts. new_type = FieldType::Class(Map::Create(isolate, 0), isolate); - TestReconfigureElementsKind_GeneralizeRepresentationTrivial( - Representation::HeapObject(), any_type, Representation::HeapObject(), - new_type, Representation::HeapObject(), any_type, false); + if (FLAG_track_constant_fields) { + TestReconfigureElementsKind_GeneralizeFieldTrivial( + {kConst, Representation::HeapObject(), any_type}, + {kConst, Representation::HeapObject(), new_type}, + {kConst, Representation::HeapObject(), any_type}, false); + + // Currently, kConst to kMutable migration causes map change, therefore + // non-trivial generalization. + TestReconfigureElementsKind_GeneralizeField( + {kConst, Representation::HeapObject(), any_type}, + {kMutable, Representation::HeapObject(), new_type}, + {kMutable, Representation::HeapObject(), any_type}); + + TestReconfigureElementsKind_GeneralizeFieldTrivial( + {kMutable, Representation::HeapObject(), any_type}, + {kConst, Representation::HeapObject(), new_type}, + {kMutable, Representation::HeapObject(), any_type}, false); + } + TestReconfigureElementsKind_GeneralizeFieldTrivial( + {kMutable, Representation::HeapObject(), any_type}, + {kMutable, Representation::HeapObject(), new_type}, + {kMutable, Representation::HeapObject(), any_type}, false); } -TEST(ReconfigureElementsKind_GeneralizeRepresentationHeapObjectToTagged) { +TEST(ReconfigureElementsKind_GeneralizeHeapObjectFieldToTagged) { CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); Isolate* isolate = CcTest::i_isolate(); @@ -1809,9 +2016,26 @@ TEST(ReconfigureElementsKind_GeneralizeRepresentationHeapObjectToTagged) { Handle<FieldType> value_type = FieldType::Class(Map::Create(isolate, 0), isolate); - TestReconfigureElementsKind_GeneralizeRepresentation( - Representation::HeapObject(), value_type, Representation::Smi(), any_type, - Representation::Tagged(), any_type); + if (FLAG_track_constant_fields) { + TestReconfigureElementsKind_GeneralizeField( + {kConst, Representation::HeapObject(), value_type}, + {kConst, Representation::Smi(), any_type}, + {kConst, Representation::Tagged(), any_type}); + + TestReconfigureElementsKind_GeneralizeField( + {kConst, Representation::HeapObject(), value_type}, + {kMutable, Representation::Smi(), any_type}, + {kMutable, Representation::Tagged(), any_type}); + + TestReconfigureElementsKind_GeneralizeField( + {kMutable, Representation::HeapObject(), value_type}, + {kConst, Representation::Smi(), any_type}, + {kMutable, Representation::Tagged(), any_type}); + } + TestReconfigureElementsKind_GeneralizeField( + {kMutable, Representation::HeapObject(), value_type}, + {kMutable, Representation::Smi(), any_type}, + {kMutable, Representation::Tagged(), any_type}); } //////////////////////////////////////////////////////////////////////////////// @@ -1830,7 +2054,8 @@ TEST(ReconfigurePropertySplitMapTransitionsOverflow) { 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, Representation::Smi(), any_type); + map = expectations.AddDataField(map, NONE, kMutable, Representation::Smi(), + any_type); } CHECK(!map->is_deprecated()); CHECK(map->is_stable()); @@ -1854,7 +2079,8 @@ TEST(ReconfigurePropertySplitMapTransitionsOverflow) { map2 = Map::ReconfigureProperty(map2, kSplitProp, kData, NONE, Representation::Double(), any_type); - expectations.SetDataField(kSplitProp, Representation::Double(), any_type); + expectations.SetDataField(kSplitProp, kMutable, Representation::Double(), + any_type); CHECK(expectations.Check(*split_map, kSplitProp)); CHECK(expectations.Check(*map2, kSplitProp + 1)); @@ -1871,8 +2097,8 @@ TEST(ReconfigurePropertySplitMapTransitionsOverflow) { for (int i = 0; i < TransitionArray::kMaxNumberOfTransitions; i++) { CHECK(TransitionArray::CanHaveMoreTransitions(map2)); Handle<String> name = MakeName("foo", i); - Map::CopyWithField(map2, name, any_type, NONE, Representation::Smi(), - INSERT_TRANSITION) + Map::CopyWithField(map2, name, any_type, NONE, kMutable, + Representation::Smi(), INSERT_TRANSITION) .ToHandleChecked(); } CHECK(!TransitionArray::CanHaveMoreTransitions(map2)); @@ -1883,7 +2109,7 @@ TEST(ReconfigurePropertySplitMapTransitionsOverflow) { CHECK(updated_map->GetBackPointer()->IsUndefined(isolate)); for (int i = 0; i < kPropCount; i++) { - expectations.SetDataField(i, Representation::Tagged(), any_type); + expectations.SetDataField(i, kMutable, Representation::Tagged(), any_type); } CHECK(expectations.Check(*updated_map)); } @@ -1894,8 +2120,8 @@ TEST(ReconfigurePropertySplitMapTransitionsOverflow) { // transition, observed transition or prototype transition). // -// This test ensures that representation/field type generalization is correctly -// propagated from one branch of transition tree (|map2|) to another (|map|). +// This test ensures that field generalization is correctly propagated from one +// branch of transition tree (|map2|) to another (|map|). // // p4B: |map2| // | @@ -1906,15 +2132,14 @@ TEST(ReconfigurePropertySplitMapTransitionsOverflow) { // where "p4A" and "p4B" are exactly the same properties. // // TODO(ishell): unify this test template with -// TestReconfigureDataFieldAttribute_GeneralizeRepresentation once +// TestReconfigureDataFieldAttribute_GeneralizeField once // IS_PROTO_TRANS_ISSUE_FIXED and IS_NON_EQUIVALENT_TRANSITION_SUPPORTED are // fixed. template <typename TestConfig> -static void TestGeneralizeRepresentationWithSpecialTransition( - TestConfig& config, Representation from_representation, - Handle<FieldType> from_type, Representation to_representation, - Handle<FieldType> to_type, Representation expected_representation, - Handle<FieldType> expected_type) { +static void TestGeneralizeFieldWithSpecialTransition(TestConfig& config, + const CRFTData& from, + const CRFTData& to, + const CRFTData& expected) { Isolate* isolate = CcTest::i_isolate(); Expectations expectations(isolate); @@ -1923,7 +2148,8 @@ static void TestGeneralizeRepresentationWithSpecialTransition( 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_representation, from_type); + map = expectations.AddDataField(map, NONE, from.constness, + from.representation, from.type); } CHECK(!map->is_deprecated()); CHECK(map->is_stable()); @@ -1941,7 +2167,7 @@ static void TestGeneralizeRepresentationWithSpecialTransition( if (config.generalizes_representations()) { for (int i = 0; i < kPropCount; i++) { - expectations2.GeneralizeRepresentation(i); + expectations2.GeneralizeField(i); } } @@ -1953,10 +2179,11 @@ static void TestGeneralizeRepresentationWithSpecialTransition( Handle<Map> maps[kPropCount]; for (int i = 0; i < kPropCount; i++) { Handle<Map> new_map = Map::ReconfigureProperty(map, i, kData, NONE, - to_representation, to_type); + to.representation, to.type); maps[i] = new_map; - expectations.SetDataField(i, expected_representation, expected_type); + expectations.SetDataField(i, expected.constness, expected.representation, + expected.type); CHECK(map->is_deprecated()); CHECK_NE(*map, *new_map); @@ -1978,7 +2205,7 @@ static void TestGeneralizeRepresentationWithSpecialTransition( // In case of non-equivalent transition currently we generalize all // representations. for (int i = 0; i < kPropCount; i++) { - expectations2.GeneralizeRepresentation(i); + expectations2.GeneralizeField(i); } CHECK(new_map2->GetBackPointer()->IsUndefined(isolate)); CHECK(expectations2.Check(*new_map2)); @@ -2021,9 +2248,10 @@ TEST(ElementsKindTransitionFromMapOwningDescriptor) { bool is_non_equevalent_transition() const { return true; } }; TestConfig config; - TestGeneralizeRepresentationWithSpecialTransition( - config, Representation::Smi(), any_type, Representation::HeapObject(), - value_type, Representation::Tagged(), any_type); + TestGeneralizeFieldWithSpecialTransition( + config, {kMutable, Representation::Smi(), any_type}, + {kMutable, Representation::HeapObject(), value_type}, + {kMutable, Representation::Tagged(), any_type}); } @@ -2043,7 +2271,7 @@ TEST(ElementsKindTransitionFromMapNotOwningDescriptor) { // Add one more transition to |map| in order to prevent descriptors // ownership. CHECK(map->owns_descriptors()); - Map::CopyWithField(map, MakeString("foo"), any_type, NONE, + Map::CopyWithField(map, MakeString("foo"), any_type, NONE, kMutable, Representation::Smi(), INSERT_TRANSITION) .ToHandleChecked(); CHECK(!map->owns_descriptors()); @@ -2058,9 +2286,10 @@ TEST(ElementsKindTransitionFromMapNotOwningDescriptor) { bool is_non_equevalent_transition() const { return true; } }; TestConfig config; - TestGeneralizeRepresentationWithSpecialTransition( - config, Representation::Smi(), any_type, Representation::HeapObject(), - value_type, Representation::Tagged(), any_type); + TestGeneralizeFieldWithSpecialTransition( + config, {kMutable, Representation::Smi(), any_type}, + {kMutable, Representation::HeapObject(), value_type}, + {kMutable, Representation::Tagged(), any_type}); } @@ -2092,9 +2321,10 @@ TEST(PrototypeTransitionFromMapOwningDescriptor) { bool is_non_equevalent_transition() const { return true; } }; TestConfig config; - TestGeneralizeRepresentationWithSpecialTransition( - config, Representation::Smi(), any_type, Representation::HeapObject(), - value_type, Representation::Tagged(), any_type); + TestGeneralizeFieldWithSpecialTransition( + config, {kMutable, Representation::Smi(), any_type}, + {kMutable, Representation::HeapObject(), value_type}, + {kMutable, Representation::Tagged(), any_type}); } @@ -2123,7 +2353,7 @@ TEST(PrototypeTransitionFromMapNotOwningDescriptor) { // Add one more transition to |map| in order to prevent descriptors // ownership. CHECK(map->owns_descriptors()); - Map::CopyWithField(map, MakeString("foo"), any_type, NONE, + Map::CopyWithField(map, MakeString("foo"), any_type, NONE, kMutable, Representation::Smi(), INSERT_TRANSITION) .ToHandleChecked(); CHECK(!map->owns_descriptors()); @@ -2137,9 +2367,10 @@ TEST(PrototypeTransitionFromMapNotOwningDescriptor) { bool is_non_equevalent_transition() const { return true; } }; TestConfig config; - TestGeneralizeRepresentationWithSpecialTransition( - config, Representation::Smi(), any_type, Representation::HeapObject(), - value_type, Representation::Tagged(), any_type); + TestGeneralizeFieldWithSpecialTransition( + config, {kMutable, Representation::Smi(), any_type}, + {kMutable, Representation::HeapObject(), value_type}, + {kMutable, Representation::Tagged(), any_type}); } @@ -2148,23 +2379,26 @@ TEST(PrototypeTransitionFromMapNotOwningDescriptor) { // struct TransitionToDataFieldOperator { + PropertyConstness constness_; Representation representation_; PropertyAttributes attributes_; Handle<FieldType> heap_type_; Handle<Object> value_; - TransitionToDataFieldOperator(Representation representation, + TransitionToDataFieldOperator(PropertyConstness constness, + Representation representation, Handle<FieldType> heap_type, Handle<Object> value, PropertyAttributes attributes = NONE) - : representation_(representation), + : constness_(constness), + representation_(representation), attributes_(attributes), heap_type_(heap_type), value_(value) {} Handle<Map> DoTransition(Expectations& expectations, Handle<Map> map) { - return expectations.TransitionToDataField(map, attributes_, representation_, - heap_type_, value_); + return expectations.TransitionToDataField( + map, attributes_, constness_, representation_, heap_type_, value_); } }; @@ -2213,7 +2447,8 @@ struct ReconfigureAsDataPropertyOperator { heap_type_(heap_type) {} Handle<Map> DoTransition(Expectations& expectations, Handle<Map> map) { - expectations.SetDataField(descriptor_, representation_, heap_type_); + expectations.SetDataField(descriptor_, kMutable, representation_, + heap_type_); return Map::ReconfigureExistingProperty(map, descriptor_, kData, attributes_); } @@ -2235,18 +2470,20 @@ struct ReconfigureAsAccessorPropertyOperator { } }; - -// Checks that representation/field type generalization happened. +// Checks that field generalization happened. struct FieldGeneralizationChecker { int descriptor_; + PropertyConstness constness_; Representation representation_; PropertyAttributes attributes_; Handle<FieldType> heap_type_; - FieldGeneralizationChecker(int descriptor, Representation representation, + FieldGeneralizationChecker(int descriptor, PropertyConstness constness, + Representation representation, Handle<FieldType> heap_type, PropertyAttributes attributes = NONE) : descriptor_(descriptor), + constness_(constness), representation_(representation), attributes_(attributes), heap_type_(heap_type) {} @@ -2259,8 +2496,8 @@ struct FieldGeneralizationChecker { Handle<Map> updated_map = Map::Update(map1); CHECK_EQ(*map2, *updated_map); - expectations2.SetDataField(descriptor_, attributes_, representation_, - heap_type_); + expectations2.SetDataField(descriptor_, attributes_, constness_, + representation_, heap_type_); CHECK(expectations2.Check(*map2)); } }; @@ -2315,7 +2552,8 @@ static void TestTransitionTo(TransitionOp1& transition_op1, Handle<Map> initial_map = Map::Create(isolate, 0); Handle<Map> map = initial_map; for (int i = 0; i < kPropCount - 1; i++) { - map = expectations.AddDataField(map, NONE, Representation::Smi(), any_type); + map = expectations.AddDataField(map, NONE, kMutable, Representation::Smi(), + any_type); } CHECK(expectations.Check(*map)); @@ -2338,15 +2576,15 @@ TEST(TransitionDataFieldToDataField) { Handle<FieldType> any_type = FieldType::Any(isolate); Handle<Object> value1 = handle(Smi::kZero, isolate); - TransitionToDataFieldOperator transition_op1(Representation::Smi(), any_type, - value1); + TransitionToDataFieldOperator transition_op1(kMutable, Representation::Smi(), + any_type, value1); Handle<Object> value2 = isolate->factory()->NewHeapNumber(0); - TransitionToDataFieldOperator transition_op2(Representation::Double(), - any_type, value2); + TransitionToDataFieldOperator transition_op2( + kMutable, Representation::Double(), any_type, value2); - FieldGeneralizationChecker checker(kPropCount - 1, Representation::Double(), - any_type); + FieldGeneralizationChecker checker(kPropCount - 1, kMutable, + Representation::Double(), any_type); TestTransitionTo(transition_op1, transition_op2, checker); } @@ -2386,9 +2624,15 @@ TEST(TransitionDataConstantToAnotherDataConstant) { factory->NewFunction(sloppy_map, info, isolate->native_context()); TransitionToDataConstantOperator transition_op2(js_func2); - FieldGeneralizationChecker checker( - kPropCount - 1, Representation::HeapObject(), function_type); - TestTransitionTo(transition_op1, transition_op2, checker); + if (FLAG_track_constant_fields) { + SameMapChecker checker; + TestTransitionTo(transition_op1, transition_op2, checker); + + } else { + FieldGeneralizationChecker checker( + kPropCount - 1, kMutable, Representation::HeapObject(), function_type); + TestTransitionTo(transition_op1, transition_op2, checker); + } } @@ -2403,11 +2647,11 @@ TEST(TransitionDataConstantToDataField) { TransitionToDataConstantOperator transition_op1(js_func1); Handle<Object> value2 = isolate->factory()->NewHeapNumber(0); - TransitionToDataFieldOperator transition_op2(Representation::Double(), - any_type, value2); + TransitionToDataFieldOperator transition_op2( + kMutable, Representation::Double(), any_type, value2); - FieldGeneralizationChecker checker(kPropCount - 1, Representation::Tagged(), - any_type); + FieldGeneralizationChecker checker(kPropCount - 1, kMutable, + Representation::Tagged(), any_type); TestTransitionTo(transition_op1, transition_op2, checker); } @@ -2436,3 +2680,31 @@ TEST(FieldTypeConvertSimple) { // TODO(ishell): add this test once IS_ACCESSOR_FIELD_SUPPORTED is supported. // TEST(TransitionAccessorConstantToAnotherAccessorConstant) + +TEST(HoleyMutableHeapNumber) { + CcTest::InitializeVM(); + v8::HandleScope scope(CcTest::isolate()); + Isolate* isolate = CcTest::i_isolate(); + + Handle<HeapNumber> mhn = isolate->factory()->NewMutableHeapNumber(); + CHECK_EQ(kHoleNanInt64, mhn->value_as_bits()); + + mhn = isolate->factory()->NewHeapNumber(0.0, MUTABLE); + CHECK_EQ(V8_UINT64_C(0), mhn->value_as_bits()); + + mhn->set_value_as_bits(kHoleNanInt64); + CHECK_EQ(kHoleNanInt64, mhn->value_as_bits()); + + // Ensure that new storage for uninitialized value or mutable heap number + // with uninitialized sentinel (kHoleNanInt64) is a mutable heap number + // with uninitialized sentinel. + Handle<Object> obj = + Object::NewStorageFor(isolate, isolate->factory()->uninitialized_value(), + Representation::Double()); + CHECK(obj->IsMutableHeapNumber()); + CHECK_EQ(kHoleNanInt64, HeapNumber::cast(*obj)->value_as_bits()); + + obj = Object::NewStorageFor(isolate, mhn, Representation::Double()); + CHECK(obj->IsMutableHeapNumber()); + CHECK_EQ(kHoleNanInt64, HeapNumber::cast(*obj)->value_as_bits()); +} |