Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(902)

Unified Diff: test/cctest/test-migrations.cc

Issue 1368403003: [cctest] adding tests for elements kind map migrations (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: adding file to gyp Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « test/cctest/test-field-type-tracking.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: test/cctest/test-migrations.cc
diff --git a/test/cctest/test-migrations.cc b/test/cctest/test-migrations.cc
deleted file mode 100644
index d441990e3c5b17ef4d07b5cda25a5968b8605f5b..0000000000000000000000000000000000000000
--- a/test/cctest/test-migrations.cc
+++ /dev/null
@@ -1,2182 +0,0 @@
-// Copyright 2015 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stdlib.h>
-#include <utility>
-
-#include "src/v8.h"
-
-#include "src/compilation-cache.h"
-#include "src/execution.h"
-#include "src/factory.h"
-#include "src/global-handles.h"
-#include "src/ic/stub-cache.h"
-#include "src/macro-assembler.h"
-#include "test/cctest/cctest.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).
-const bool IS_PROTO_TRANS_ISSUE_FIXED = false;
-
-
-// TODO(ishell): fix this once TransitionToAccessorProperty is able to always
-// keep map in fast mode.
-const bool IS_ACCESSOR_FIELD_SUPPORTED = false;
-
-
-// Number of properties used in the tests.
-const int kPropCount = 7;
-
-
-//
-// Helper functions.
-//
-
-static Handle<String> MakeString(const char* str) {
- Isolate* isolate = CcTest::i_isolate();
- Factory* factory = isolate->factory();
- return factory->InternalizeUtf8String(str);
-}
-
-
-static Handle<String> MakeName(const char* str, int suffix) {
- EmbeddedVector<char, 128> buffer;
- SNPrintF(buffer, "%s%d", str, suffix);
- return MakeString(buffer.start());
-}
-
-
-static Handle<AccessorPair> CreateAccessorPair(bool with_getter,
- bool with_setter) {
- Isolate* isolate = CcTest::i_isolate();
- Factory* factory = isolate->factory();
- Handle<AccessorPair> pair = factory->NewAccessorPair();
- Handle<String> empty_string = factory->empty_string();
- if (with_getter) {
- Handle<JSFunction> func = factory->NewFunction(empty_string);
- pair->set_getter(*func);
- }
- if (with_setter) {
- Handle<JSFunction> func = factory->NewFunction(empty_string);
- pair->set_setter(*func);
- }
- return pair;
-}
-
-
-static bool EqualDetails(DescriptorArray* descriptors, int descriptor,
- PropertyType type, PropertyAttributes attributes,
- Representation representation, int field_index = -1) {
- PropertyDetails details = descriptors->GetDetails(descriptor);
- if (details.type() != type) return false;
- if (details.attributes() != attributes) return false;
- if (!details.representation().Equals(representation)) return false;
- if (field_index >= 0 && details.field_index() != field_index) return false;
- return true;
-}
-
-
-class Expectations {
- static const int MAX_PROPERTIES = 10;
- Isolate* isolate_;
- PropertyType types_[MAX_PROPERTIES];
- PropertyAttributes attributes_[MAX_PROPERTIES];
- Representation representations_[MAX_PROPERTIES];
- // HeapType for kField, value for DATA_CONSTANT and getter for
- // ACCESSOR_CONSTANT.
- Handle<Object> values_[MAX_PROPERTIES];
- // Setter for ACCESSOR_CONSTANT.
- Handle<Object> setter_values_[MAX_PROPERTIES];
- int number_of_properties_;
-
- public:
- explicit Expectations(Isolate* isolate)
- : isolate_(isolate), number_of_properties_(0) {}
-
- void Init(int index, PropertyType type, PropertyAttributes attributes,
- Representation representation, Handle<Object> value) {
- DCHECK(index < MAX_PROPERTIES);
- types_[index] = type;
- attributes_[index] = attributes;
- representations_[index] = representation;
- values_[index] = value;
- }
-
- void Print() const {
- OFStream os(stdout);
- os << "Expectations: #" << number_of_properties_ << "\n";
- for (int i = 0; i < number_of_properties_; i++) {
- os << " " << i << ": ";
- os << "Descriptor @ ";
- if (types_[i] == ACCESSOR_CONSTANT) {
- os << "(get: " << Brief(*values_[i])
- << ", set: " << Brief(*setter_values_[i]) << ") ";
- } else {
- os << Brief(*values_[i]);
- }
- os << " (";
- switch (types_[i]) {
- case DATA_CONSTANT:
- os << "immutable ";
- // Fall through.
- case DATA:
- os << "data";
- break;
-
- case ACCESSOR_CONSTANT:
- os << "immutable ";
- // Fall through.
- case ACCESSOR:
- os << "accessor";
- break;
- }
- os << ": " << representations_[i].Mnemonic();
- os << ", attrs: " << attributes_[i] << ")\n";
- }
- os << "\n";
- }
-
- Handle<HeapType> GetFieldType(int index) {
- CHECK(index < MAX_PROPERTIES);
- CHECK(types_[index] == DATA || types_[index] == ACCESSOR);
- return Handle<HeapType>::cast(values_[index]);
- }
-
- void SetDataField(int index, PropertyAttributes attrs,
- Representation representation, Handle<HeapType> value) {
- Init(index, DATA, attrs, representation, value);
- }
-
- void SetDataField(int index, Representation representation,
- Handle<HeapType> value) {
- SetDataField(index, attributes_[index], representation, value);
- }
-
- void SetAccessorField(int index, PropertyAttributes attrs) {
- Init(index, ACCESSOR, attrs, Representation::Tagged(),
- HeapType::Any(isolate_));
- }
-
- void SetAccessorField(int index) {
- SetAccessorField(index, attributes_[index]);
- }
-
- void SetDataConstant(int index, PropertyAttributes attrs,
- Handle<JSFunction> value) {
- Init(index, DATA_CONSTANT, attrs, Representation::HeapObject(), value);
- }
-
- void SetDataConstant(int index, Handle<JSFunction> value) {
- SetDataConstant(index, attributes_[index], value);
- }
-
- void SetAccessorConstant(int index, PropertyAttributes attrs,
- Handle<Object> getter, Handle<Object> setter) {
- Init(index, ACCESSOR_CONSTANT, attrs, Representation::Tagged(), getter);
- setter_values_[index] = setter;
- }
-
- void SetAccessorConstantComponent(int index, PropertyAttributes attrs,
- AccessorComponent component,
- Handle<Object> accessor) {
- CHECK_EQ(ACCESSOR_CONSTANT, types_[index]);
- CHECK(index < number_of_properties_);
- if (component == ACCESSOR_GETTER) {
- values_[index] = accessor;
- } else {
- setter_values_[index] = accessor;
- }
- }
-
- void SetAccessorConstant(int index, PropertyAttributes attrs,
- Handle<AccessorPair> pair) {
- Handle<Object> getter = handle(pair->getter(), isolate_);
- Handle<Object> setter = handle(pair->setter(), isolate_);
- SetAccessorConstant(index, attrs, getter, setter);
- }
-
- void SetAccessorConstant(int index, Handle<Object> getter,
- Handle<Object> setter) {
- SetAccessorConstant(index, attributes_[index], getter, setter);
- }
-
- void SetAccessorConstant(int index, Handle<AccessorPair> pair) {
- Handle<Object> getter = handle(pair->getter(), isolate_);
- Handle<Object> setter = handle(pair->setter(), isolate_);
- SetAccessorConstant(index, getter, setter);
- }
-
- void GeneralizeRepresentation(int index) {
- CHECK(index < number_of_properties_);
- representations_[index] = Representation::Tagged();
- if (types_[index] == DATA || types_[index] == ACCESSOR) {
- values_[index] = HeapType::Any(isolate_);
- }
- }
-
-
- bool Check(DescriptorArray* descriptors, int descriptor) const {
- PropertyType type = types_[descriptor];
- if (!EqualDetails(descriptors, descriptor, type, attributes_[descriptor],
- representations_[descriptor])) {
- return false;
- }
- Object* value = descriptors->GetValue(descriptor);
- Object* expected_value = *values_[descriptor];
- switch (type) {
- case DATA:
- case ACCESSOR: {
- HeapType* type = descriptors->GetFieldType(descriptor);
- return HeapType::cast(expected_value)->Equals(type);
- }
-
- case DATA_CONSTANT:
- return value == expected_value;
-
- case ACCESSOR_CONSTANT: {
- if (value == expected_value) return true;
- if (!value->IsAccessorPair()) return false;
- AccessorPair* pair = AccessorPair::cast(value);
- return pair->Equals(expected_value, *setter_values_[descriptor]);
- }
- }
- UNREACHABLE();
- return false;
- }
-
- bool Check(Map* map, int expected_nof) const {
- CHECK(number_of_properties_ <= MAX_PROPERTIES);
- CHECK_EQ(expected_nof, map->NumberOfOwnDescriptors());
- CHECK(!map->is_dictionary_map());
-
- DescriptorArray* descriptors = map->instance_descriptors();
- CHECK(expected_nof <= number_of_properties_);
- for (int i = 0; i < expected_nof; i++) {
- if (!Check(descriptors, i)) {
- Print();
-#ifdef OBJECT_PRINT
- descriptors->Print();
-#endif
- Check(descriptors, i);
- return false;
- }
- }
- return true;
- }
-
- bool Check(Map* map) const { return Check(map, number_of_properties_); }
-
-
- //
- // Helper methods for initializing expectations and adding properties to
- // given |map|.
- //
-
- Handle<Map> AddDataField(Handle<Map> map, PropertyAttributes attributes,
- Representation representation,
- Handle<HeapType> heap_type) {
- CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
- int property_index = number_of_properties_++;
- SetDataField(property_index, attributes, representation, heap_type);
-
- Handle<String> name = MakeName("prop", property_index);
- return Map::CopyWithField(map, name, heap_type, attributes, representation,
- INSERT_TRANSITION).ToHandleChecked();
- }
-
- Handle<Map> AddDataConstant(Handle<Map> map, PropertyAttributes attributes,
- Handle<JSFunction> value) {
- CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
- int property_index = number_of_properties_++;
- SetDataConstant(property_index, attributes, value);
-
- Handle<String> name = MakeName("prop", property_index);
- return Map::CopyWithConstant(map, name, value, attributes,
- INSERT_TRANSITION).ToHandleChecked();
- }
-
- Handle<Map> TransitionToDataField(Handle<Map> map,
- PropertyAttributes attributes,
- Representation representation,
- Handle<HeapType> 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);
-
- Handle<String> name = MakeName("prop", property_index);
- return Map::TransitionToDataProperty(
- map, name, value, attributes, Object::CERTAINLY_NOT_STORE_FROM_KEYED);
- }
-
- Handle<Map> TransitionToDataConstant(Handle<Map> map,
- PropertyAttributes attributes,
- Handle<JSFunction> value) {
- CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
- int property_index = number_of_properties_++;
- SetDataConstant(property_index, attributes, value);
-
- Handle<String> name = MakeName("prop", property_index);
- return Map::TransitionToDataProperty(
- map, name, value, attributes, Object::CERTAINLY_NOT_STORE_FROM_KEYED);
- }
-
- Handle<Map> FollowDataTransition(Handle<Map> map,
- PropertyAttributes attributes,
- Representation representation,
- Handle<HeapType> heap_type) {
- CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
- int property_index = number_of_properties_++;
- SetDataField(property_index, attributes, representation, heap_type);
-
- Handle<String> name = MakeName("prop", property_index);
- Map* target =
- TransitionArray::SearchTransition(*map, kData, *name, attributes);
- CHECK(target != NULL);
- return handle(target);
- }
-
- Handle<Map> AddAccessorConstant(Handle<Map> map,
- PropertyAttributes attributes,
- Handle<AccessorPair> pair) {
- CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
- int property_index = number_of_properties_++;
- SetAccessorConstant(property_index, attributes, pair);
-
- Handle<String> name = MakeName("prop", property_index);
-
- AccessorConstantDescriptor new_desc(name, pair, attributes);
- return Map::CopyInsertDescriptor(map, &new_desc, INSERT_TRANSITION);
- }
-
- Handle<Map> AddAccessorConstant(Handle<Map> map,
- PropertyAttributes attributes,
- Handle<Object> getter,
- Handle<Object> setter) {
- CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
- int property_index = number_of_properties_++;
- SetAccessorConstant(property_index, attributes, getter, setter);
-
- Handle<String> name = MakeName("prop", property_index);
-
- CHECK(!getter->IsNull() || !setter->IsNull());
- Factory* factory = isolate_->factory();
-
- if (!getter->IsNull()) {
- Handle<AccessorPair> pair = factory->NewAccessorPair();
- pair->SetComponents(*getter, *factory->null_value());
- AccessorConstantDescriptor new_desc(name, pair, attributes);
- map = Map::CopyInsertDescriptor(map, &new_desc, INSERT_TRANSITION);
- }
- if (!setter->IsNull()) {
- Handle<AccessorPair> pair = factory->NewAccessorPair();
- pair->SetComponents(*getter, *setter);
- AccessorConstantDescriptor new_desc(name, pair, attributes);
- map = Map::CopyInsertDescriptor(map, &new_desc, INSERT_TRANSITION);
- }
- return map;
- }
-
- Handle<Map> TransitionToAccessorConstant(Handle<Map> map,
- PropertyAttributes attributes,
- Handle<AccessorPair> pair) {
- CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
- int property_index = number_of_properties_++;
- SetAccessorConstant(property_index, attributes, pair);
-
- Handle<String> name = MakeName("prop", property_index);
-
- Isolate* isolate = CcTest::i_isolate();
- Handle<Object> getter(pair->getter(), isolate);
- Handle<Object> setter(pair->setter(), isolate);
-
- map = Map::TransitionToAccessorProperty(map, name, ACCESSOR_GETTER, getter,
- attributes);
- CHECK(!map->is_deprecated());
- CHECK(!map->is_dictionary_map());
-
- map = Map::TransitionToAccessorProperty(map, name, ACCESSOR_SETTER, setter,
- attributes);
- CHECK(!map->is_deprecated());
- CHECK(!map->is_dictionary_map());
- return map;
- }
-};
-
-
-////////////////////////////////////////////////////////////////////////////////
-// A set of tests for property reconfiguration that makes new transition tree
-// branch.
-//
-
-TEST(ReconfigureAccessorToNonExistingDataField) {
- CcTest::InitializeVM();
- v8::HandleScope scope(CcTest::isolate());
- Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
- Handle<HeapType> none_type = HeapType::None(isolate);
- Handle<AccessorPair> pair = CreateAccessorPair(true, true);
-
- 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;
- map = expectations.AddAccessorConstant(map, NONE, pair);
-
- CHECK(!map->is_deprecated());
- CHECK(map->is_stable());
- CHECK(expectations.Check(*map));
-
- Handle<Map> new_map = Map::ReconfigureProperty(
- map, 0, kData, NONE, Representation::None(), none_type, FORCE_FIELD);
- // |map| did not change except marked unstable.
- CHECK(!map->is_deprecated());
- CHECK(!map->is_stable());
- CHECK(expectations.Check(*map));
-
- expectations.SetDataField(0, NONE, Representation::None(), none_type);
-
- CHECK(!new_map->is_deprecated());
- CHECK(new_map->is_stable());
- CHECK(expectations.Check(*new_map));
-
- Handle<Map> new_map2 = Map::ReconfigureProperty(
- map, 0, kData, NONE, Representation::None(), none_type, FORCE_FIELD);
- CHECK_EQ(*new_map, *new_map2);
-
- Handle<Object> value(Smi::FromInt(0), isolate);
- Handle<Map> prepared_map = Map::PrepareForDataProperty(new_map, 0, 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);
- CHECK(prepared_map->is_stable());
- CHECK(expectations.Check(*prepared_map));
-
- // Now create an object with |map|, migrate it to |prepared_map| and ensure
- // that the data property is uninitialized.
- Factory* factory = isolate->factory();
- Handle<JSObject> obj = factory->NewJSObjectFromMap(map);
- JSObject::MigrateToMap(obj, prepared_map);
- FieldIndex index = FieldIndex::ForDescriptor(*prepared_map, 0);
- CHECK(obj->RawFastPropertyAt(index)->IsUninitialized());
-#ifdef VERIFY_HEAP
- obj->ObjectVerify();
-#endif
-}
-
-
-// This test checks that the LookupIterator machinery involved in
-// JSObject::SetOwnPropertyIgnoreAttributes() does not try to migrate object
-// to a map with a property with None representation.
-TEST(ReconfigureAccessorToNonExistingDataFieldHeavy) {
- CcTest::InitializeVM();
- Isolate* isolate = CcTest::i_isolate();
- Factory* factory = isolate->factory();
- v8::HandleScope scope(CcTest::isolate());
-
- CompileRun(
- "function getter() { return 1; };"
- "function setter() {};"
- "var o = {};"
- "Object.defineProperty(o, 'foo', "
- " { get: getter, set: setter, "
- " configurable: true, enumerable: true});");
-
- Handle<String> foo_str = factory->InternalizeUtf8String("foo");
- Handle<String> obj_name = factory->InternalizeUtf8String("o");
-
- Handle<Object> obj_value =
- Object::GetProperty(isolate->global_object(), obj_name).ToHandleChecked();
- CHECK(obj_value->IsJSObject());
- Handle<JSObject> obj = Handle<JSObject>::cast(obj_value);
-
- CHECK_EQ(1, obj->map()->NumberOfOwnDescriptors());
- CHECK(obj->map()->instance_descriptors()->GetValue(0)->IsAccessorPair());
-
- Handle<Object> value(Smi::FromInt(42), isolate);
- JSObject::SetOwnPropertyIgnoreAttributes(obj, foo_str, value, NONE).Check();
-
- // Check that the property contains |value|.
- CHECK_EQ(1, obj->map()->NumberOfOwnDescriptors());
- FieldIndex index = FieldIndex::ForDescriptor(obj->map(), 0);
- Object* the_value = obj->RawFastPropertyAt(index);
- CHECK(the_value->IsSmi());
- CHECK_EQ(42, Smi::cast(the_value)->value());
-}
-
-
-////////////////////////////////////////////////////////////////////////////////
-// A set of tests for representation 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.
-//
-// {} - p0 - p1 - p2: |detach_point_map|
-// |
-// X - detached at |detach_property_at_index|
-// |
-// + - p3 - p4: |map|
-//
-// 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<HeapType> from_type,
- Representation to_representation, Handle<HeapType> to_type,
- Representation expected_representation, Handle<HeapType> expected_type,
- bool expected_deprecation, bool expected_field_type_dependency) {
- Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
-
- CHECK(detach_property_at_index >= -1 &&
- detach_property_at_index < kPropCount);
- CHECK(property_index < kPropCount);
- CHECK_NE(detach_property_at_index, property_index);
-
- const bool is_detached_map = detach_property_at_index >= 0;
-
- 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;
- 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);
- } else {
- map =
- expectations.AddDataField(map, NONE, Representation::Smi(), any_type);
- if (i == detach_property_at_index) {
- detach_point_map = map;
- }
- }
- }
- CHECK(!map->is_deprecated());
- CHECK(map->is_stable());
- CHECK(expectations.Check(*map));
-
- Zone zone;
-
- if (is_detached_map) {
- detach_point_map = Map::ReconfigureProperty(
- detach_point_map, detach_property_at_index, kData, NONE,
- Representation::Tagged(), any_type, FORCE_FIELD);
- expectations.SetDataField(detach_property_at_index,
- Representation::Tagged(), any_type);
- CHECK(map->is_deprecated());
- CHECK(expectations.Check(*detach_point_map,
- detach_point_map->NumberOfOwnDescriptors()));
- }
-
- // Create new maps by generalizing representation of propX field.
- Handle<Map> field_owner(map->FindFieldOwner(property_index), isolate);
- CompilationInfo info("testing", isolate, &zone);
- CHECK(!info.dependencies()->HasAborted());
-
- info.dependencies()->AssumeFieldType(field_owner);
-
- Handle<Map> new_map =
- Map::ReconfigureProperty(map, property_index, kData, NONE,
- to_representation, to_type, FORCE_FIELD);
-
- expectations.SetDataField(property_index, expected_representation,
- expected_type);
-
- CHECK(!new_map->is_deprecated());
- CHECK(expectations.Check(*new_map));
-
- if (is_detached_map) {
- CHECK(!map->is_stable());
- CHECK(map->is_deprecated());
- CHECK_NE(*map, *new_map);
- CHECK_EQ(expected_field_type_dependency && !field_owner->is_deprecated(),
- info.dependencies()->HasAborted());
-
- } else if (expected_deprecation) {
- CHECK(!map->is_stable());
- CHECK(map->is_deprecated());
- CHECK(field_owner->is_deprecated());
- CHECK_NE(*map, *new_map);
- CHECK(!info.dependencies()->HasAborted());
-
- } else {
- CHECK(!field_owner->is_deprecated());
- CHECK(map->is_stable()); // Map did not change, must be left stable.
- CHECK_EQ(*map, *new_map);
-
- CHECK_EQ(expected_field_type_dependency, info.dependencies()->HasAborted());
- }
-
- info.dependencies()->Rollback(); // Properly cleanup compilation info.
-
- // Update all deprecated maps and check that they are now the same.
- Handle<Map> updated_map = Map::Update(map);
- CHECK_EQ(*new_map, *updated_map);
-}
-
-
-static void TestGeneralizeRepresentation(
- Representation from_representation, Handle<HeapType> from_type,
- Representation to_representation, Handle<HeapType> to_type,
- Representation expected_representation, Handle<HeapType> expected_type,
- 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);
- }
-
- 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);
- }
-
- // Check that reconfiguration to the very same field works correctly.
- Representation representation = from_representation;
- Handle<HeapType> type = from_type;
- TestGeneralizeRepresentation(-1, 2, representation, type, representation,
- type, representation, type, false, false);
- }
-}
-
-
-static void TestGeneralizeRepresentation(Representation from_representation,
- Handle<HeapType> from_type,
- Representation to_representation,
- Handle<HeapType> to_type,
- Representation expected_representation,
- Handle<HeapType> expected_type) {
- 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);
-}
-
-
-static void TestGeneralizeRepresentationTrivial(
- Representation from_representation, Handle<HeapType> from_type,
- Representation to_representation, Handle<HeapType> to_type,
- Representation expected_representation, Handle<HeapType> expected_type,
- 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);
-}
-
-
-TEST(GeneralizeRepresentationSmiToDouble) {
- CcTest::InitializeVM();
- v8::HandleScope scope(CcTest::isolate());
- Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
-
- TestGeneralizeRepresentation(Representation::Smi(), any_type,
- Representation::Double(), any_type,
- Representation::Double(), any_type);
-}
-
-
-TEST(GeneralizeRepresentationSmiToTagged) {
- CcTest::InitializeVM();
- v8::HandleScope scope(CcTest::isolate());
- Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
- Handle<HeapType> value_type =
- HeapType::Class(Map::Create(isolate, 0), isolate);
-
- TestGeneralizeRepresentation(Representation::Smi(), any_type,
- Representation::HeapObject(), value_type,
- Representation::Tagged(), any_type);
-}
-
-
-TEST(GeneralizeRepresentationDoubleToTagged) {
- CcTest::InitializeVM();
- v8::HandleScope scope(CcTest::isolate());
- Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
- Handle<HeapType> value_type =
- HeapType::Class(Map::Create(isolate, 0), isolate);
-
- TestGeneralizeRepresentation(Representation::Double(), any_type,
- Representation::HeapObject(), value_type,
- Representation::Tagged(), any_type);
-}
-
-
-TEST(GeneralizeRepresentationHeapObjectToTagged) {
- CcTest::InitializeVM();
- v8::HandleScope scope(CcTest::isolate());
- Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
- Handle<HeapType> value_type =
- HeapType::Class(Map::Create(isolate, 0), isolate);
-
- TestGeneralizeRepresentation(Representation::HeapObject(), value_type,
- Representation::Smi(), any_type,
- Representation::Tagged(), any_type);
-}
-
-
-TEST(GeneralizeRepresentationHeapObjectToHeapObject) {
- CcTest::InitializeVM();
- v8::HandleScope scope(CcTest::isolate());
- Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
-
- const int kMaxClassesPerFieldType = 1;
- Handle<HeapType> current_type =
- HeapType::Class(Map::Create(isolate, 0), isolate);
-
- for (int i = 0; i < kMaxClassesPerFieldType; i++) {
- Handle<HeapType> new_type =
- HeapType::Class(Map::Create(isolate, 0), isolate);
-
- Handle<HeapType> expected_type =
- (i < kMaxClassesPerFieldType - 1)
- ? HeapType::Union(current_type, new_type, isolate)
- : any_type;
-
- TestGeneralizeRepresentationTrivial(
- Representation::HeapObject(), current_type,
- Representation::HeapObject(), new_type, Representation::HeapObject(),
- expected_type);
- current_type = expected_type;
- }
-
- Handle<HeapType> new_type = HeapType::Class(Map::Create(isolate, 0), isolate);
-
- TestGeneralizeRepresentationTrivial(
- Representation::HeapObject(), any_type, Representation::HeapObject(),
- new_type, Representation::HeapObject(), any_type, false);
-}
-
-
-TEST(GeneralizeRepresentationNoneToSmi) {
- CcTest::InitializeVM();
- v8::HandleScope scope(CcTest::isolate());
- Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> none_type = HeapType::None(isolate);
- Handle<HeapType> any_type = HeapType::Any(isolate);
-
- // None -> Smi representation change is trivial.
- TestGeneralizeRepresentationTrivial(Representation::None(), none_type,
- Representation::Smi(), any_type,
- Representation::Smi(), any_type);
-}
-
-
-TEST(GeneralizeRepresentationNoneToDouble) {
- CcTest::InitializeVM();
- v8::HandleScope scope(CcTest::isolate());
- Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> none_type = HeapType::None(isolate);
- Handle<HeapType> any_type = HeapType::Any(isolate);
-
- // None -> Double representation change is NOT trivial.
- TestGeneralizeRepresentation(Representation::None(), none_type,
- Representation::Double(), any_type,
- Representation::Double(), any_type);
-}
-
-
-TEST(GeneralizeRepresentationNoneToHeapObject) {
- CcTest::InitializeVM();
- v8::HandleScope scope(CcTest::isolate());
- Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> none_type = HeapType::None(isolate);
- Handle<HeapType> value_type =
- HeapType::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);
-}
-
-
-TEST(GeneralizeRepresentationNoneToTagged) {
- CcTest::InitializeVM();
- v8::HandleScope scope(CcTest::isolate());
- Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> none_type = HeapType::None(isolate);
- Handle<HeapType> any_type = HeapType::Any(isolate);
-
- // None -> HeapObject representation change is trivial.
- TestGeneralizeRepresentationTrivial(Representation::None(), none_type,
- Representation::Tagged(), any_type,
- Representation::Tagged(), any_type);
-}
-
-
-////////////////////////////////////////////////////////////////////////////////
-// A set of tests for representation generalization case with kAccessor
-// properties.
-//
-
-TEST(GeneralizeRepresentationWithAccessorProperties) {
- CcTest::InitializeVM();
- v8::HandleScope scope(CcTest::isolate());
- Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
- Handle<AccessorPair> pair = CreateAccessorPair(true, true);
-
- const int kAccessorProp = kPropCount / 2;
- 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++) {
- if (i == kAccessorProp) {
- map = expectations.AddAccessorConstant(map, NONE, pair);
- } else {
- map =
- expectations.AddDataField(map, NONE, Representation::Smi(), any_type);
- }
- }
- CHECK(!map->is_deprecated());
- CHECK(map->is_stable());
- CHECK(expectations.Check(*map));
-
- // Create new maps by generalizing representation of propX field.
- Handle<Map> maps[kPropCount];
- for (int i = 0; i < kPropCount; i++) {
- if (i == kAccessorProp) {
- // Skip accessor property reconfiguration.
- maps[i] = maps[i - 1];
- continue;
- }
- Handle<Map> new_map = Map::ReconfigureProperty(
- map, i, kData, NONE, Representation::Double(), any_type, FORCE_FIELD);
- maps[i] = new_map;
-
- expectations.SetDataField(i, Representation::Double(), any_type);
-
- CHECK(!map->is_stable());
- CHECK(map->is_deprecated());
- CHECK_NE(*map, *new_map);
- CHECK(i == 0 || maps[i - 1]->is_deprecated());
-
- CHECK(!new_map->is_deprecated());
- CHECK(expectations.Check(*new_map));
- }
-
- Handle<Map> active_map = maps[kPropCount - 1];
- CHECK(!active_map->is_deprecated());
-
- // Update all deprecated maps and check that they are now the same.
- Handle<Map> updated_map = Map::Update(map);
- CHECK_EQ(*active_map, *updated_map);
- for (int i = 0; i < kPropCount; i++) {
- updated_map = Map::Update(maps[i]);
- CHECK_EQ(*active_map, *updated_map);
- }
-}
-
-
-////////////////////////////////////////////////////////////////////////////////
-// 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|).
-//
-// + - p2B - p3 - p4: |map2|
-// |
-// {} - p0 - p1 - p2A - p3 - p4: |map|
-//
-// where "p2A" and "p2B" differ only in the attributes.
-//
-static void TestReconfigureDataFieldAttribute_GeneralizeRepresentation(
- Representation from_representation, Handle<HeapType> from_type,
- Representation to_representation, Handle<HeapType> to_type,
- Representation expected_representation, Handle<HeapType> expected_type) {
- 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_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_representation,
- from_type);
- }
- map2 =
- expectations2.AddDataField(map2, READ_ONLY, to_representation, to_type);
-
- for (int i = kSplitProp + 1; i < kPropCount; i++) {
- map2 = expectations2.AddDataField(map2, NONE, to_representation, to_type);
- }
- CHECK(!map2->is_deprecated());
- CHECK(map2->is_stable());
- CHECK(expectations2.Check(*map2));
-
- Zone zone;
- Handle<Map> field_owner(map->FindFieldOwner(kSplitProp), isolate);
- CompilationInfo info("testing", isolate, &zone);
- CHECK(!info.dependencies()->HasAborted());
- info.dependencies()->AssumeFieldType(field_owner);
-
- // Reconfigure attributes of property |kSplitProp| of |map2| to NONE, which
- // should generalize representations in |map1|.
- Handle<Map> new_map =
- Map::ReconfigureExistingProperty(map2, kSplitProp, kData, NONE);
-
- // |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));
-
- // |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);
- }
- CHECK(map->is_deprecated());
- CHECK(!info.dependencies()->HasAborted());
- info.dependencies()->Rollback(); // Properly cleanup compilation info.
- 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(map);
- 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|).
-//
-// + - p2B - p3 - p4: |map2|
-// |
-// {} - p0 - p1 - p2A - p3 - p4: |map|
-//
-// where "p2A" and "p2B" differ only in the attributes.
-//
-static void TestReconfigureDataFieldAttribute_GeneralizeRepresentationTrivial(
- Representation from_representation, Handle<HeapType> from_type,
- Representation to_representation, Handle<HeapType> to_type,
- Representation expected_representation, Handle<HeapType> expected_type,
- bool expected_field_type_dependency = true) {
- 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_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_representation,
- from_type);
- }
- map2 =
- expectations2.AddDataField(map2, READ_ONLY, to_representation, to_type);
-
- for (int i = kSplitProp + 1; i < kPropCount; i++) {
- map2 = expectations2.AddDataField(map2, NONE, to_representation, to_type);
- }
- CHECK(!map2->is_deprecated());
- CHECK(map2->is_stable());
- CHECK(expectations2.Check(*map2));
-
- Zone zone;
- Handle<Map> field_owner(map->FindFieldOwner(kSplitProp), isolate);
- CompilationInfo info("testing", isolate, &zone);
- CHECK(!info.dependencies()->HasAborted());
- info.dependencies()->AssumeFieldType(field_owner);
-
- // Reconfigure attributes of property |kSplitProp| of |map2| to NONE, which
- // should generalize representations in |map1|.
- Handle<Map> new_map =
- Map::ReconfigureExistingProperty(map2, kSplitProp, kData, NONE);
-
- // |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));
-
- // 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_representation, expected_type);
- }
- CHECK(!map->is_deprecated());
- CHECK_EQ(*map, *new_map);
- CHECK_EQ(expected_field_type_dependency, info.dependencies()->HasAborted());
- info.dependencies()->Rollback(); // Properly cleanup compilation info.
-
- CHECK(!new_map->is_deprecated());
- CHECK(expectations.Check(*new_map));
-
- Handle<Map> updated_map = Map::Update(map);
- CHECK_EQ(*new_map, *updated_map);
-}
-
-
-TEST(ReconfigureDataFieldAttribute_GeneralizeRepresentationSmiToDouble) {
- CcTest::InitializeVM();
- v8::HandleScope scope(CcTest::isolate());
- Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
-
- TestReconfigureDataFieldAttribute_GeneralizeRepresentation(
- Representation::Smi(), any_type, Representation::Double(), any_type,
- Representation::Double(), any_type);
-}
-
-
-TEST(ReconfigureDataFieldAttribute_GeneralizeRepresentationSmiToTagged) {
- CcTest::InitializeVM();
- v8::HandleScope scope(CcTest::isolate());
- Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
- Handle<HeapType> value_type =
- HeapType::Class(Map::Create(isolate, 0), isolate);
-
- TestReconfigureDataFieldAttribute_GeneralizeRepresentation(
- Representation::Smi(), any_type, Representation::HeapObject(), value_type,
- Representation::Tagged(), any_type);
-}
-
-
-TEST(ReconfigureDataFieldAttribute_GeneralizeRepresentationDoubleToTagged) {
- CcTest::InitializeVM();
- v8::HandleScope scope(CcTest::isolate());
- Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
- Handle<HeapType> value_type =
- HeapType::Class(Map::Create(isolate, 0), isolate);
-
- TestReconfigureDataFieldAttribute_GeneralizeRepresentation(
- Representation::Double(), any_type, Representation::HeapObject(),
- value_type, Representation::Tagged(), any_type);
-}
-
-
-TEST(ReconfigureDataFieldAttribute_GeneralizeRepresentationHeapObjToHeapObj) {
- CcTest::InitializeVM();
- v8::HandleScope scope(CcTest::isolate());
- Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
-
- const int kMaxClassesPerFieldType = 1;
- Handle<HeapType> current_type =
- HeapType::Class(Map::Create(isolate, 0), isolate);
-
- for (int i = 0; i < kMaxClassesPerFieldType; i++) {
- Handle<HeapType> new_type =
- HeapType::Class(Map::Create(isolate, 0), isolate);
-
- Handle<HeapType> expected_type =
- (i < kMaxClassesPerFieldType - 1)
- ? HeapType::Union(current_type, new_type, isolate)
- : any_type;
-
- TestReconfigureDataFieldAttribute_GeneralizeRepresentationTrivial(
- Representation::HeapObject(), current_type,
- Representation::HeapObject(), new_type, Representation::HeapObject(),
- expected_type);
- current_type = expected_type;
- }
-
- Handle<HeapType> new_type = HeapType::Class(Map::Create(isolate, 0), isolate);
-
- TestReconfigureDataFieldAttribute_GeneralizeRepresentationTrivial(
- Representation::HeapObject(), any_type, Representation::HeapObject(),
- new_type, Representation::HeapObject(), any_type, false);
-}
-
-
-TEST(ReconfigureDataFieldAttribute_GeneralizeRepresentationHeapObjectToTagged) {
- CcTest::InitializeVM();
- v8::HandleScope scope(CcTest::isolate());
- Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
- Handle<HeapType> value_type =
- HeapType::Class(Map::Create(isolate, 0), isolate);
-
- TestReconfigureDataFieldAttribute_GeneralizeRepresentation(
- Representation::HeapObject(), value_type, Representation::Smi(), any_type,
- Representation::Tagged(), any_type);
-}
-
-
-// Checks that given |map| is deprecated and that it updates to given |new_map|
-// which in turn should match expectations.
-struct CheckDeprecated {
- void Check(Handle<Map> map, Handle<Map> new_map,
- const Expectations& expectations) {
- CHECK(map->is_deprecated());
- 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(map);
- CHECK_EQ(*new_map, *updated_map);
- }
-};
-
-
-// Checks that given |map| is NOT deprecated, equals to given |new_map| and
-// matches expectations.
-struct CheckSameMap {
- void Check(Handle<Map> map, Handle<Map> new_map,
- const Expectations& expectations) {
- // |map| was not reconfigured, therefore it should stay stable.
- CHECK(map->is_stable());
- CHECK(!map->is_deprecated());
- CHECK_EQ(*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(map);
- CHECK_EQ(*new_map, *updated_map);
- }
-};
-
-
-// Checks that given |map| is NOT deprecated and matches expectations.
-// |new_map| is unrelated to |map|.
-struct CheckUnrelated {
- void Check(Handle<Map> map, Handle<Map> new_map,
- const Expectations& expectations) {
- CHECK(!map->is_deprecated());
- CHECK_NE(*map, *new_map);
- CHECK(expectations.Check(*map));
-
- CHECK(new_map->is_stable());
- CHECK(!new_map->is_deprecated());
- }
-};
-
-
-// Checks that given |map| is NOT deprecated, and |new_map| is a result of
-// copy-generalize-all-representations.
-struct CheckCopyGeneralizeAllRepresentations {
- void Check(Handle<Map> map, Handle<Map> new_map, Expectations& expectations) {
- CHECK(!map->is_deprecated());
- CHECK_NE(*map, *new_map);
-
- CHECK(new_map->GetBackPointer()->IsUndefined());
- for (int i = 0; i < kPropCount; i++) {
- expectations.GeneralizeRepresentation(i);
- }
-
- CHECK(!new_map->is_deprecated());
- CHECK(expectations.Check(*new_map));
- }
-};
-
-
-// This test ensures that representation/field type generalization is correctly
-// propagated from one branch of transition tree (|map2|) to another (|map1|).
-//
-// + - p2B - p3 - p4: |map2|
-// |
-// {} - p0 - p1: |map|
-// |
-// + - p2A - p3 - p4: |map1|
-// |
-// + - the property customized by the TestConfig provided
-//
-// where "p2A" and "p2B" differ only in the attributes.
-//
-template <typename TestConfig, typename Checker>
-static void TestReconfigureProperty_CustomPropertyAfterTargetMap(
- TestConfig& config, Checker& checker) {
- Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
-
- const int kCustomPropIndex = kPropCount - 2;
- Expectations expectations(isolate);
-
- const int kSplitProp = 2;
- CHECK(kSplitProp < kCustomPropIndex);
-
- 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);
- }
- CHECK(!map->is_deprecated());
- CHECK(map->is_stable());
- CHECK(expectations.Check(*map));
-
-
- // Create branch to |map1|.
- Handle<Map> map1 = map;
- Expectations expectations1 = expectations;
- for (int i = kSplitProp; i < kCustomPropIndex; i++) {
- map1 = expectations1.AddDataField(map1, NONE, 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);
- }
- CHECK(!map1->is_deprecated());
- CHECK(map1->is_stable());
- CHECK(expectations1.Check(*map1));
-
-
- // Create another branch in transition tree (property at index |kSplitProp|
- // has different attributes), initialize expectations.
- Handle<Map> map2 = map;
- Expectations expectations2 = expectations;
- map2 = expectations2.AddDataField(map2, READ_ONLY, representation, any_type);
- for (int i = kSplitProp + 1; i < kCustomPropIndex; i++) {
- map2 = expectations2.AddDataField(map2, NONE, 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);
- }
- CHECK(!map2->is_deprecated());
- CHECK(map2->is_stable());
- CHECK(expectations2.Check(*map2));
-
-
- // Reconfigure attributes of property |kSplitProp| of |map2| to NONE, which
- // should generalize representations in |map1|.
- Handle<Map> new_map =
- Map::ReconfigureExistingProperty(map2, kSplitProp, kData, NONE);
-
- // |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));
-
- config.UpdateExpectations(kCustomPropIndex, expectations1);
- checker.Check(map1, new_map, expectations1);
-}
-
-
-TEST(ReconfigureDataFieldAttribute_SameDataConstantAfterTargetMap) {
- CcTest::InitializeVM();
- v8::HandleScope scope(CcTest::isolate());
-
- struct TestConfig {
- Handle<JSFunction> js_func_;
- TestConfig() {
- Isolate* isolate = CcTest::i_isolate();
- Factory* factory = isolate->factory();
- js_func_ = factory->NewFunction(factory->empty_string());
- }
-
- Handle<Map> AddPropertyAtBranch(int branch_id, Expectations& expectations,
- Handle<Map> map) {
- CHECK(branch_id == 1 || branch_id == 2);
- // Add the same data constant property at both transition tree branches.
- return expectations.AddDataConstant(map, NONE, js_func_);
- }
-
- void UpdateExpectations(int property_index, Expectations& expectations) {
- // Expectations stay the same.
- }
- };
-
- TestConfig config;
- // Two branches are "compatible" so the |map1| should NOT be deprecated.
- CheckSameMap checker;
- TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker);
-}
-
-
-TEST(ReconfigureDataFieldAttribute_DataConstantToDataFieldAfterTargetMap) {
- CcTest::InitializeVM();
- v8::HandleScope scope(CcTest::isolate());
-
- struct TestConfig {
- Handle<JSFunction> js_func1_;
- Handle<JSFunction> js_func2_;
- TestConfig() {
- Isolate* isolate = CcTest::i_isolate();
- Factory* factory = isolate->factory();
- js_func1_ = factory->NewFunction(factory->empty_string());
- js_func2_ = factory->NewFunction(factory->empty_string());
- }
-
- Handle<Map> AddPropertyAtBranch(int branch_id, Expectations& expectations,
- Handle<Map> map) {
- CHECK(branch_id == 1 || branch_id == 2);
- Handle<JSFunction> js_func = branch_id == 1 ? js_func1_ : js_func2_;
- return expectations.AddDataConstant(map, NONE, js_func);
- }
-
- void UpdateExpectations(int property_index, Expectations& expectations) {
- Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
- expectations.SetDataField(property_index, Representation::HeapObject(),
- any_type);
- }
- };
-
- TestConfig config;
- // Two branches are "incompatible" so the |map1| should be deprecated.
- CheckDeprecated checker;
- TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker);
-}
-
-
-TEST(ReconfigureDataFieldAttribute_DataConstantToAccConstantAfterTargetMap) {
- CcTest::InitializeVM();
- v8::HandleScope scope(CcTest::isolate());
-
- struct TestConfig {
- Handle<JSFunction> js_func_;
- Handle<AccessorPair> pair_;
- TestConfig() {
- Isolate* isolate = CcTest::i_isolate();
- Factory* factory = isolate->factory();
- js_func_ = factory->NewFunction(factory->empty_string());
- pair_ = CreateAccessorPair(true, true);
- }
-
- Handle<Map> AddPropertyAtBranch(int branch_id, Expectations& expectations,
- Handle<Map> map) {
- CHECK(branch_id == 1 || branch_id == 2);
- if (branch_id == 1) {
- return expectations.AddDataConstant(map, NONE, js_func_);
- } else {
- return expectations.AddAccessorConstant(map, NONE, pair_);
- }
- }
-
- void UpdateExpectations(int property_index, Expectations& expectations) {}
- };
-
- TestConfig config;
- // These are completely separate branches in transition tree.
- CheckUnrelated checker;
- TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker);
-}
-
-
-TEST(ReconfigureDataFieldAttribute_SameAccessorConstantAfterTargetMap) {
- CcTest::InitializeVM();
- v8::HandleScope scope(CcTest::isolate());
-
- struct TestConfig {
- Handle<AccessorPair> pair_;
- TestConfig() { pair_ = CreateAccessorPair(true, true); }
-
- Handle<Map> AddPropertyAtBranch(int branch_id, Expectations& expectations,
- Handle<Map> map) {
- CHECK(branch_id == 1 || branch_id == 2);
- // Add the same accessor constant property at both transition tree
- // branches.
- return expectations.AddAccessorConstant(map, NONE, pair_);
- }
-
- void UpdateExpectations(int property_index, Expectations& expectations) {
- // Two branches are "compatible" so the |map1| should NOT be deprecated.
- }
- };
-
- TestConfig config;
- CheckSameMap checker;
- TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker);
-}
-
-
-TEST(ReconfigureDataFieldAttribute_AccConstantToAccFieldAfterTargetMap) {
- CcTest::InitializeVM();
- v8::HandleScope scope(CcTest::isolate());
-
- struct TestConfig {
- Handle<AccessorPair> pair1_;
- Handle<AccessorPair> pair2_;
- TestConfig() {
- pair1_ = CreateAccessorPair(true, true);
- pair2_ = CreateAccessorPair(true, true);
- }
-
- Handle<Map> AddPropertyAtBranch(int branch_id, Expectations& expectations,
- Handle<Map> map) {
- CHECK(branch_id == 1 || branch_id == 2);
- Handle<AccessorPair> pair = branch_id == 1 ? pair1_ : pair2_;
- return expectations.AddAccessorConstant(map, NONE, pair);
- }
-
- void UpdateExpectations(int property_index, Expectations& expectations) {
- if (IS_ACCESSOR_FIELD_SUPPORTED) {
- expectations.SetAccessorField(property_index);
- } else {
- // Currently we have a copy-generalize-all-representations case and
- // ACCESSOR property becomes ACCESSOR_CONSTANT.
- expectations.SetAccessorConstant(property_index, pair2_);
- }
- }
- };
-
- TestConfig config;
- if (IS_ACCESSOR_FIELD_SUPPORTED) {
- CheckCopyGeneralizeAllRepresentations checker;
- TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker);
- } else {
- // Currently we have a copy-generalize-all-representations case.
- CheckCopyGeneralizeAllRepresentations checker;
- TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker);
- }
-}
-
-
-TEST(ReconfigureDataFieldAttribute_AccConstantToDataFieldAfterTargetMap) {
- CcTest::InitializeVM();
- v8::HandleScope scope(CcTest::isolate());
-
- struct TestConfig {
- Handle<AccessorPair> pair_;
- TestConfig() { pair_ = CreateAccessorPair(true, true); }
-
- Handle<Map> AddPropertyAtBranch(int branch_id, Expectations& expectations,
- Handle<Map> map) {
- CHECK(branch_id == 1 || branch_id == 2);
- if (branch_id == 1) {
- return expectations.AddAccessorConstant(map, NONE, pair_);
- } else {
- Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
- return expectations.AddDataField(map, NONE, Representation::Smi(),
- any_type);
- }
- }
-
- void UpdateExpectations(int property_index, Expectations& expectations) {}
- };
-
- TestConfig config;
- // These are completely separate branches in transition tree.
- CheckUnrelated checker;
- TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker);
-}
-
-
-////////////////////////////////////////////////////////////////////////////////
-// A set of tests checking split map deprecation.
-//
-
-TEST(ReconfigurePropertySplitMapTransitionsOverflow) {
- CcTest::InitializeVM();
- v8::HandleScope scope(CcTest::isolate());
- Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(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, Representation::Smi(), any_type);
- }
- CHECK(!map->is_deprecated());
- CHECK(map->is_stable());
-
- // Generalize representation of property at index |kSplitProp|.
- const int kSplitProp = kPropCount / 2;
- Handle<Map> split_map;
- Handle<Map> map2 = initial_map;
- {
- for (int i = 0; i < kSplitProp + 1; i++) {
- if (i == kSplitProp) {
- split_map = map2;
- }
-
- Handle<String> name = MakeName("prop", i);
- Map* target =
- TransitionArray::SearchTransition(*map2, kData, *name, NONE);
- CHECK(target != NULL);
- map2 = handle(target);
- }
-
- map2 = Map::ReconfigureProperty(map2, kSplitProp, kData, NONE,
- Representation::Double(), any_type,
- FORCE_FIELD);
- expectations.SetDataField(kSplitProp, Representation::Double(), any_type);
-
- CHECK(expectations.Check(*split_map, kSplitProp));
- CHECK(expectations.Check(*map2, kSplitProp + 1));
- }
-
- // At this point |map| should be deprecated and disconnected from the
- // transition tree.
- CHECK(map->is_deprecated());
- CHECK(!split_map->is_deprecated());
- CHECK(map2->is_stable());
- CHECK(!map2->is_deprecated());
-
- // Fill in transition tree of |map2| so that it can't have more transitions.
- 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).ToHandleChecked();
- }
- CHECK(!TransitionArray::CanHaveMoreTransitions(map2));
-
- // Try to update |map|, since there is no place for propX transition at |map2|
- // |map| should become "copy-generalized".
- Handle<Map> updated_map = Map::Update(map);
- CHECK(updated_map->GetBackPointer()->IsUndefined());
-
- for (int i = 0; i < kPropCount; i++) {
- expectations.SetDataField(i, Representation::Tagged(), any_type);
- }
- CHECK(expectations.Check(*updated_map));
-}
-
-
-////////////////////////////////////////////////////////////////////////////////
-// A set of tests involving special transitions (such as elements kind
-// 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|).
-//
-// p4B: |map2|
-// |
-// * - special transition
-// |
-// {} - p0 - p1 - p2A - p3 - p4A: |map|
-//
-// where "p4A" and "p4B" are exactly the same properties.
-//
-// TODO(ishell): unify this test template with
-// TestReconfigureDataFieldAttribute_GeneralizeRepresentation 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<HeapType> from_type, Representation to_representation,
- Handle<HeapType> to_type, Representation expected_representation,
- Handle<HeapType> expected_type) {
- 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_representation, from_type);
- }
- CHECK(!map->is_deprecated());
- CHECK(map->is_stable());
- CHECK(expectations.Check(*map));
-
- // Apply some special transition to |map|.
- CHECK(map->owns_descriptors());
- Handle<Map> map2 = config.Transition(map);
-
- // |map| should still match expectations.
- CHECK(!map->is_deprecated());
- CHECK(expectations.Check(*map));
-
- Expectations expectations2 = expectations;
- if (config.generalizes_representations()) {
- for (int i = 0; i < kPropCount; i++) {
- expectations2.GeneralizeRepresentation(i);
- }
- }
-
- CHECK(!map2->is_deprecated());
- CHECK(map2->is_stable());
- CHECK(expectations2.Check(*map2));
-
- // Create new maps by generalizing representation of propX field.
- 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, FORCE_FIELD);
- maps[i] = new_map;
-
- expectations.SetDataField(i, expected_representation, expected_type);
-
- 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(map2);
- CHECK(!new_map2->is_deprecated());
- CHECK(!new_map2->is_dictionary_map());
-
- Handle<Map> tmp_map;
- if (Map::TryUpdate(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);
- }
-
- if (config.is_non_equevalent_transition()) {
- // In case of non-equivalent transition currently we generalize all
- // representations.
- for (int i = 0; i < kPropCount; i++) {
- expectations2.GeneralizeRepresentation(i);
- }
- CHECK(new_map2->GetBackPointer()->IsUndefined());
- CHECK(expectations2.Check(*new_map2));
- } else {
- CHECK(!new_map2->GetBackPointer()->IsUndefined());
- CHECK(expectations2.Check(*new_map2));
- }
- }
-
- Handle<Map> active_map = maps[kPropCount - 1];
- CHECK(!active_map->is_deprecated());
-
- // Update all deprecated maps and check that they are now the same.
- Handle<Map> updated_map = Map::Update(map);
- CHECK_EQ(*active_map, *updated_map);
- for (int i = 0; i < kPropCount; i++) {
- updated_map = Map::Update(maps[i]);
- CHECK_EQ(*active_map, *updated_map);
- }
-}
-
-
-TEST(ElementsKindTransitionFromMapOwningDescriptor) {
- CcTest::InitializeVM();
- v8::HandleScope scope(CcTest::isolate());
- Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
- Handle<HeapType> value_type =
- HeapType::Class(Map::Create(isolate, 0), isolate);
-
- struct TestConfig {
- Handle<Map> Transition(Handle<Map> map) {
- return Map::CopyAsElementsKind(map, DICTIONARY_ELEMENTS,
- INSERT_TRANSITION);
- }
- // TODO(ishell): remove once IS_PROTO_TRANS_ISSUE_FIXED is removed.
- bool generalizes_representations() const { return false; }
- bool is_non_equevalent_transition() const { return false; }
- };
- TestConfig config;
- TestGeneralizeRepresentationWithSpecialTransition(
- config, Representation::Smi(), any_type, Representation::HeapObject(),
- value_type, Representation::Tagged(), any_type);
-}
-
-
-TEST(ElementsKindTransitionFromMapNotOwningDescriptor) {
- CcTest::InitializeVM();
- v8::HandleScope scope(CcTest::isolate());
- Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
- Handle<HeapType> value_type =
- HeapType::Class(Map::Create(isolate, 0), isolate);
-
- struct TestConfig {
- Handle<Map> Transition(Handle<Map> map) {
- Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
-
- // Add one more transition to |map| in order to prevent descriptors
- // ownership.
- CHECK(map->owns_descriptors());
- Map::CopyWithField(map, MakeString("foo"), any_type, NONE,
- Representation::Smi(),
- INSERT_TRANSITION).ToHandleChecked();
- CHECK(!map->owns_descriptors());
-
- return Map::CopyAsElementsKind(map, DICTIONARY_ELEMENTS,
- INSERT_TRANSITION);
- }
- // TODO(ishell): remove once IS_PROTO_TRANS_ISSUE_FIXED is removed.
- bool generalizes_representations() const { return false; }
- bool is_non_equevalent_transition() const { return false; }
- };
- TestConfig config;
- TestGeneralizeRepresentationWithSpecialTransition(
- config, Representation::Smi(), any_type, Representation::HeapObject(),
- value_type, Representation::Tagged(), any_type);
-}
-
-
-TEST(ForObservedTransitionFromMapOwningDescriptor) {
- CcTest::InitializeVM();
- v8::HandleScope scope(CcTest::isolate());
- Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
- Handle<HeapType> value_type =
- HeapType::Class(Map::Create(isolate, 0), isolate);
-
- struct TestConfig {
- Handle<Map> Transition(Handle<Map> map) {
- return Map::CopyForObserved(map);
- }
- // TODO(ishell): remove once IS_PROTO_TRANS_ISSUE_FIXED is removed.
- bool generalizes_representations() const { return false; }
- bool is_non_equevalent_transition() const { return true; }
- };
- TestConfig config;
- TestGeneralizeRepresentationWithSpecialTransition(
- config, Representation::Smi(), any_type, Representation::HeapObject(),
- value_type, Representation::Tagged(), any_type);
-}
-
-
-TEST(ForObservedTransitionFromMapNotOwningDescriptor) {
- CcTest::InitializeVM();
- v8::HandleScope scope(CcTest::isolate());
- Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
- Handle<HeapType> value_type =
- HeapType::Class(Map::Create(isolate, 0), isolate);
-
- struct TestConfig {
- Handle<Map> Transition(Handle<Map> map) {
- Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
-
- // Add one more transition to |map| in order to prevent descriptors
- // ownership.
- CHECK(map->owns_descriptors());
- Map::CopyWithField(map, MakeString("foo"), any_type, NONE,
- Representation::Smi(),
- INSERT_TRANSITION).ToHandleChecked();
- CHECK(!map->owns_descriptors());
-
- return Map::CopyForObserved(map);
- }
- // TODO(ishell): remove once IS_PROTO_TRANS_ISSUE_FIXED is removed.
- bool generalizes_representations() const { return false; }
- bool is_non_equevalent_transition() const { return true; }
- };
- TestConfig config;
- TestGeneralizeRepresentationWithSpecialTransition(
- config, Representation::Smi(), any_type, Representation::HeapObject(),
- value_type, Representation::Tagged(), any_type);
-}
-
-
-TEST(PrototypeTransitionFromMapOwningDescriptor) {
- CcTest::InitializeVM();
- v8::HandleScope scope(CcTest::isolate());
- Isolate* isolate = CcTest::i_isolate();
-
- Handle<HeapType> any_type = HeapType::Any(isolate);
- Handle<HeapType> value_type =
- HeapType::Class(Map::Create(isolate, 0), isolate);
-
- struct TestConfig {
- Handle<JSObject> prototype_;
-
- TestConfig() {
- Isolate* isolate = CcTest::i_isolate();
- Factory* factory = isolate->factory();
- prototype_ = factory->NewJSObjectFromMap(Map::Create(isolate, 0));
- }
-
- Handle<Map> Transition(Handle<Map> map) {
- return Map::TransitionToPrototype(map, prototype_, REGULAR_PROTOTYPE);
- }
- // TODO(ishell): remove once IS_PROTO_TRANS_ISSUE_FIXED is removed.
- bool generalizes_representations() const {
- return !IS_PROTO_TRANS_ISSUE_FIXED;
- }
- bool is_non_equevalent_transition() const { return true; }
- };
- TestConfig config;
- TestGeneralizeRepresentationWithSpecialTransition(
- config, Representation::Smi(), any_type, Representation::HeapObject(),
- value_type, Representation::Tagged(), any_type);
-}
-
-
-TEST(PrototypeTransitionFromMapNotOwningDescriptor) {
- CcTest::InitializeVM();
- v8::HandleScope scope(CcTest::isolate());
- Isolate* isolate = CcTest::i_isolate();
-
- Handle<HeapType> any_type = HeapType::Any(isolate);
- Handle<HeapType> value_type =
- HeapType::Class(Map::Create(isolate, 0), isolate);
-
- struct TestConfig {
- Handle<JSObject> prototype_;
-
- TestConfig() {
- Isolate* isolate = CcTest::i_isolate();
- Factory* factory = isolate->factory();
- prototype_ = factory->NewJSObjectFromMap(Map::Create(isolate, 0));
- }
-
- Handle<Map> Transition(Handle<Map> map) {
- Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
-
- // Add one more transition to |map| in order to prevent descriptors
- // ownership.
- CHECK(map->owns_descriptors());
- Map::CopyWithField(map, MakeString("foo"), any_type, NONE,
- Representation::Smi(),
- INSERT_TRANSITION).ToHandleChecked();
- CHECK(!map->owns_descriptors());
-
- return Map::TransitionToPrototype(map, prototype_, REGULAR_PROTOTYPE);
- }
- // TODO(ishell): remove once IS_PROTO_TRANS_ISSUE_FIXED is removed.
- bool generalizes_representations() const {
- return !IS_PROTO_TRANS_ISSUE_FIXED;
- }
- bool is_non_equevalent_transition() const { return true; }
- };
- TestConfig config;
- TestGeneralizeRepresentationWithSpecialTransition(
- config, Representation::Smi(), any_type, Representation::HeapObject(),
- value_type, Representation::Tagged(), any_type);
-}
-
-
-////////////////////////////////////////////////////////////////////////////////
-// A set of tests for higher level transitioning mechanics.
-//
-
-struct TransitionToDataFieldOperator {
- Representation representation_;
- PropertyAttributes attributes_;
- Handle<HeapType> heap_type_;
- Handle<Object> value_;
-
- TransitionToDataFieldOperator(Representation representation,
- Handle<HeapType> heap_type,
- Handle<Object> value,
- PropertyAttributes attributes = NONE)
- : 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_);
- }
-};
-
-
-struct TransitionToDataConstantOperator {
- PropertyAttributes attributes_;
- Handle<JSFunction> value_;
-
- TransitionToDataConstantOperator(Handle<JSFunction> value,
- PropertyAttributes attributes = NONE)
- : attributes_(attributes), value_(value) {}
-
- Handle<Map> DoTransition(Expectations& expectations, Handle<Map> map) {
- return expectations.TransitionToDataConstant(map, attributes_, value_);
- }
-};
-
-
-struct TransitionToAccessorConstantOperator {
- PropertyAttributes attributes_;
- Handle<AccessorPair> pair_;
-
- TransitionToAccessorConstantOperator(Handle<AccessorPair> pair,
- PropertyAttributes attributes = NONE)
- : attributes_(attributes), pair_(pair) {}
-
- Handle<Map> DoTransition(Expectations& expectations, Handle<Map> map) {
- return expectations.TransitionToAccessorConstant(map, attributes_, pair_);
- }
-};
-
-
-struct ReconfigureAsDataPropertyOperator {
- int descriptor_;
- Representation representation_;
- PropertyAttributes attributes_;
- Handle<HeapType> heap_type_;
-
- ReconfigureAsDataPropertyOperator(int descriptor,
- Representation representation,
- Handle<HeapType> heap_type,
- PropertyAttributes attributes = NONE)
- : descriptor_(descriptor),
- representation_(representation),
- attributes_(attributes),
- heap_type_(heap_type) {}
-
- Handle<Map> DoTransition(Expectations& expectations, Handle<Map> map) {
- expectations.SetDataField(descriptor_, representation_, heap_type_);
- return Map::ReconfigureExistingProperty(map, descriptor_, kData,
- attributes_);
- }
-};
-
-
-struct ReconfigureAsAccessorPropertyOperator {
- int descriptor_;
- PropertyAttributes attributes_;
-
- ReconfigureAsAccessorPropertyOperator(int descriptor,
- PropertyAttributes attributes = NONE)
- : descriptor_(descriptor), attributes_(attributes) {}
-
- Handle<Map> DoTransition(Expectations& expectations, Handle<Map> map) {
- expectations.SetAccessorField(descriptor_);
- return Map::ReconfigureExistingProperty(map, descriptor_, kAccessor,
- attributes_);
- }
-};
-
-
-// Checks that representation/field type generalization happened.
-struct FieldGeneralizationChecker {
- int descriptor_;
- Representation representation_;
- PropertyAttributes attributes_;
- Handle<HeapType> heap_type_;
-
- FieldGeneralizationChecker(int descriptor, Representation representation,
- Handle<HeapType> heap_type,
- PropertyAttributes attributes = NONE)
- : descriptor_(descriptor),
- representation_(representation),
- attributes_(attributes),
- heap_type_(heap_type) {}
-
- void Check(Expectations& expectations2, Handle<Map> map1, Handle<Map> map2) {
- CHECK(!map2->is_deprecated());
-
- CHECK(map1->is_deprecated());
- CHECK_NE(*map1, *map2);
- Handle<Map> updated_map = Map::Update(map1);
- CHECK_EQ(*map2, *updated_map);
-
- expectations2.SetDataField(descriptor_, attributes_, representation_,
- heap_type_);
- CHECK(expectations2.Check(*map2));
- }
-};
-
-
-// Checks that existing transition was taken as is.
-struct SameMapChecker {
- void Check(Expectations& expectations, Handle<Map> map1, Handle<Map> map2) {
- CHECK(!map2->is_deprecated());
- CHECK_EQ(*map1, *map2);
- CHECK(expectations.Check(*map2));
- }
-};
-
-
-// Checks that both |map1| and |map2| should stays non-deprecated, this is
-// the case when property kind is change.
-struct PropertyKindReconfigurationChecker {
- void Check(Expectations& expectations, Handle<Map> map1, Handle<Map> map2) {
- CHECK(!map1->is_deprecated());
- CHECK(!map2->is_deprecated());
- CHECK_NE(*map1, *map2);
- CHECK(expectations.Check(*map2));
- }
-};
-
-
-// This test transitions to various property types under different
-// circumstances.
-// Plan:
-// 1) create a |map| with p0..p3 properties.
-// 2) create |map1| by adding "p4" to |map0|.
-// 3) create |map2| by transition to "p4" from |map0|.
-//
-// + - p4B: |map2|
-// |
-// {} - p0 - p1 - pA - p3: |map|
-// |
-// + - p4A: |map1|
-//
-// where "p4A" and "p4B" differ only in the attributes.
-//
-template <typename TransitionOp1, typename TransitionOp2, typename Checker>
-static void TestTransitionTo(TransitionOp1& transition_op1,
- TransitionOp2& transition_op2, Checker& checker) {
- Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(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 - 1; i++) {
- map = expectations.AddDataField(map, NONE, Representation::Smi(), any_type);
- }
- CHECK(expectations.Check(*map));
-
- Expectations expectations1 = expectations;
- Handle<Map> map1 = transition_op1.DoTransition(expectations1, map);
- CHECK(expectations1.Check(*map1));
-
- Expectations expectations2 = expectations;
- Handle<Map> map2 = transition_op2.DoTransition(expectations2, map);
-
- // Let the test customization do the check.
- checker.Check(expectations2, map1, map2);
-}
-
-
-TEST(TransitionDataFieldToDataField) {
- CcTest::InitializeVM();
- v8::HandleScope scope(CcTest::isolate());
- Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
-
- Handle<Object> value1 = handle(Smi::FromInt(0), isolate);
- TransitionToDataFieldOperator transition_op1(Representation::Smi(), any_type,
- value1);
-
- Handle<Object> value2 = isolate->factory()->NewHeapNumber(0);
- TransitionToDataFieldOperator transition_op2(Representation::Double(),
- any_type, value2);
-
- FieldGeneralizationChecker checker(kPropCount - 1, Representation::Double(),
- any_type);
- TestTransitionTo(transition_op1, transition_op2, checker);
-}
-
-
-TEST(TransitionDataConstantToSameDataConstant) {
- CcTest::InitializeVM();
- v8::HandleScope scope(CcTest::isolate());
- Isolate* isolate = CcTest::i_isolate();
- Factory* factory = isolate->factory();
-
- Handle<JSFunction> js_func = factory->NewFunction(factory->empty_string());
- TransitionToDataConstantOperator transition_op(js_func);
-
- SameMapChecker checker;
- TestTransitionTo(transition_op, transition_op, checker);
-}
-
-
-TEST(TransitionDataConstantToAnotherDataConstant) {
- CcTest::InitializeVM();
- v8::HandleScope scope(CcTest::isolate());
- Isolate* isolate = CcTest::i_isolate();
- Factory* factory = isolate->factory();
- Handle<HeapType> any_type = HeapType::Any(isolate);
-
- Handle<JSFunction> js_func1 = factory->NewFunction(factory->empty_string());
- TransitionToDataConstantOperator transition_op1(js_func1);
-
- Handle<JSFunction> js_func2 = factory->NewFunction(factory->empty_string());
- TransitionToDataConstantOperator transition_op2(js_func2);
-
- FieldGeneralizationChecker checker(kPropCount - 1,
- Representation::HeapObject(), any_type);
- TestTransitionTo(transition_op1, transition_op2, checker);
-}
-
-
-TEST(TransitionDataConstantToDataField) {
- CcTest::InitializeVM();
- v8::HandleScope scope(CcTest::isolate());
- Isolate* isolate = CcTest::i_isolate();
- Factory* factory = isolate->factory();
- Handle<HeapType> any_type = HeapType::Any(isolate);
-
- Handle<JSFunction> js_func1 = factory->NewFunction(factory->empty_string());
- TransitionToDataConstantOperator transition_op1(js_func1);
-
- Handle<Object> value2 = isolate->factory()->NewHeapNumber(0);
- TransitionToDataFieldOperator transition_op2(Representation::Double(),
- any_type, value2);
-
- FieldGeneralizationChecker checker(kPropCount - 1, Representation::Tagged(),
- any_type);
- TestTransitionTo(transition_op1, transition_op2, checker);
-}
-
-
-TEST(TransitionAccessorConstantToSameAccessorConstant) {
- CcTest::InitializeVM();
- v8::HandleScope scope(CcTest::isolate());
-
- Handle<AccessorPair> pair = CreateAccessorPair(true, true);
- TransitionToAccessorConstantOperator transition_op(pair);
-
- SameMapChecker checker;
- TestTransitionTo(transition_op, transition_op, checker);
-}
-
-
-// TODO(ishell): add this test once IS_ACCESSOR_FIELD_SUPPORTED is supported.
-// TEST(TransitionAccessorConstantToAnotherAccessorConstant)
« no previous file with comments | « test/cctest/test-field-type-tracking.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698