v8/test/cctest/test-transitions.cc
marja 8e7241fdde Include only stuff you need, part 6: Fix cctest.h.
Rebuilding (after touching certain files) is crazy slow because
includes are out of control. Many of these files we need to rebuild are
cctests which pull in more includes than they need.

BUG=v8:5294

Review-Url: https://codereview.chromium.org/2304553002
Cr-Commit-Position: refs/heads/master@{#39080}
2016-09-01 12:02:16 +00:00

319 lines
11 KiB
C++

// Copyright 2014 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/field-type.h"
#include "src/global-handles.h"
// FIXME(mstarzinger, marja): This is weird, but required because of the missing
// (disallowed) include: src/field-type.h -> src/objects-inl.h
#include "src/objects-inl.h"
#include "src/transitions.h"
#include "test/cctest/cctest.h"
using namespace v8::internal;
//
// Helper functions.
//
static void CheckPropertyDetailsFieldsConsistency(PropertyType type,
PropertyKind kind,
PropertyLocation location) {
int type_value = PropertyDetails::TypeField::encode(type);
int kind_location_value = PropertyDetails::KindField::encode(kind) |
PropertyDetails::LocationField::encode(location);
CHECK_EQ(type_value, kind_location_value);
}
TEST(PropertyDetailsFieldsConsistency) {
CheckPropertyDetailsFieldsConsistency(DATA, kData, kField);
CheckPropertyDetailsFieldsConsistency(DATA_CONSTANT, kData, kDescriptor);
CheckPropertyDetailsFieldsConsistency(ACCESSOR, kAccessor, kField);
CheckPropertyDetailsFieldsConsistency(ACCESSOR_CONSTANT, kAccessor,
kDescriptor);
}
TEST(TransitionArray_SimpleFieldTransitions) {
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Factory* factory = isolate->factory();
Handle<String> name1 = factory->InternalizeUtf8String("foo");
Handle<String> name2 = factory->InternalizeUtf8String("bar");
PropertyAttributes attributes = NONE;
Handle<Map> map0 = Map::Create(isolate, 0);
Handle<Map> map1 =
Map::CopyWithField(map0, name1, handle(FieldType::Any(), isolate),
attributes, Representation::Tagged(), OMIT_TRANSITION)
.ToHandleChecked();
Handle<Map> map2 =
Map::CopyWithField(map0, name2, handle(FieldType::Any(), isolate),
attributes, Representation::Tagged(), OMIT_TRANSITION)
.ToHandleChecked();
CHECK(map0->raw_transitions()->IsSmi());
TransitionArray::Insert(map0, name1, map1, SIMPLE_PROPERTY_TRANSITION);
CHECK(TransitionArray::IsSimpleTransition(map0->raw_transitions()));
CHECK_EQ(*map1,
TransitionArray::SearchTransition(*map0, kData, *name1, attributes));
CHECK_EQ(1, TransitionArray::NumberOfTransitions(map0->raw_transitions()));
CHECK_EQ(*name1, TransitionArray::GetKey(map0->raw_transitions(), 0));
CHECK_EQ(*map1, TransitionArray::GetTarget(map0->raw_transitions(), 0));
TransitionArray::Insert(map0, name2, map2, SIMPLE_PROPERTY_TRANSITION);
CHECK(TransitionArray::IsFullTransitionArray(map0->raw_transitions()));
CHECK_EQ(*map1,
TransitionArray::SearchTransition(*map0, kData, *name1, attributes));
CHECK_EQ(*map2,
TransitionArray::SearchTransition(*map0, kData, *name2, attributes));
CHECK_EQ(2, TransitionArray::NumberOfTransitions(map0->raw_transitions()));
for (int i = 0; i < 2; i++) {
Name* key = TransitionArray::GetKey(map0->raw_transitions(), i);
Map* target = TransitionArray::GetTarget(map0->raw_transitions(), i);
CHECK((key == *name1 && target == *map1) ||
(key == *name2 && target == *map2));
}
#ifdef DEBUG
CHECK(TransitionArray::IsSortedNoDuplicates(*map0));
#endif
}
TEST(TransitionArray_FullFieldTransitions) {
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Factory* factory = isolate->factory();
Handle<String> name1 = factory->InternalizeUtf8String("foo");
Handle<String> name2 = factory->InternalizeUtf8String("bar");
PropertyAttributes attributes = NONE;
Handle<Map> map0 = Map::Create(isolate, 0);
Handle<Map> map1 =
Map::CopyWithField(map0, name1, handle(FieldType::Any(), isolate),
attributes, Representation::Tagged(), OMIT_TRANSITION)
.ToHandleChecked();
Handle<Map> map2 =
Map::CopyWithField(map0, name2, handle(FieldType::Any(), isolate),
attributes, Representation::Tagged(), OMIT_TRANSITION)
.ToHandleChecked();
CHECK(map0->raw_transitions()->IsSmi());
TransitionArray::Insert(map0, name1, map1, PROPERTY_TRANSITION);
CHECK(TransitionArray::IsFullTransitionArray(map0->raw_transitions()));
CHECK_EQ(*map1,
TransitionArray::SearchTransition(*map0, kData, *name1, attributes));
CHECK_EQ(1, TransitionArray::NumberOfTransitions(map0->raw_transitions()));
CHECK_EQ(*name1, TransitionArray::GetKey(map0->raw_transitions(), 0));
CHECK_EQ(*map1, TransitionArray::GetTarget(map0->raw_transitions(), 0));
TransitionArray::Insert(map0, name2, map2, PROPERTY_TRANSITION);
CHECK(TransitionArray::IsFullTransitionArray(map0->raw_transitions()));
CHECK_EQ(*map1,
TransitionArray::SearchTransition(*map0, kData, *name1, attributes));
CHECK_EQ(*map2,
TransitionArray::SearchTransition(*map0, kData, *name2, attributes));
CHECK_EQ(2, TransitionArray::NumberOfTransitions(map0->raw_transitions()));
for (int i = 0; i < 2; i++) {
Name* key = TransitionArray::GetKey(map0->raw_transitions(), i);
Map* target = TransitionArray::GetTarget(map0->raw_transitions(), i);
CHECK((key == *name1 && target == *map1) ||
(key == *name2 && target == *map2));
}
#ifdef DEBUG
CHECK(TransitionArray::IsSortedNoDuplicates(*map0));
#endif
}
TEST(TransitionArray_DifferentFieldNames) {
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Factory* factory = isolate->factory();
const int PROPS_COUNT = 10;
Handle<String> names[PROPS_COUNT];
Handle<Map> maps[PROPS_COUNT];
PropertyAttributes attributes = NONE;
Handle<Map> map0 = Map::Create(isolate, 0);
CHECK(map0->raw_transitions()->IsSmi());
for (int i = 0; i < PROPS_COUNT; i++) {
EmbeddedVector<char, 64> buffer;
SNPrintF(buffer, "prop%d", i);
Handle<String> name = factory->InternalizeUtf8String(buffer.start());
Handle<Map> map = Map::CopyWithField(
map0, name, handle(FieldType::Any(), isolate),
attributes, Representation::Tagged(), OMIT_TRANSITION)
.ToHandleChecked();
names[i] = name;
maps[i] = map;
TransitionArray::Insert(map0, name, map, PROPERTY_TRANSITION);
}
for (int i = 0; i < PROPS_COUNT; i++) {
CHECK_EQ(*maps[i], TransitionArray::SearchTransition(
*map0, kData, *names[i], attributes));
}
for (int i = 0; i < PROPS_COUNT; i++) {
Name* key = TransitionArray::GetKey(map0->raw_transitions(), i);
Map* target = TransitionArray::GetTarget(map0->raw_transitions(), i);
for (int j = 0; j < PROPS_COUNT; j++) {
if (*names[i] == key) {
CHECK_EQ(*maps[i], target);
break;
}
}
}
#ifdef DEBUG
CHECK(TransitionArray::IsSortedNoDuplicates(*map0));
#endif
}
TEST(TransitionArray_SameFieldNamesDifferentAttributesSimple) {
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Factory* factory = isolate->factory();
Handle<Map> map0 = Map::Create(isolate, 0);
CHECK(map0->raw_transitions()->IsSmi());
const int ATTRS_COUNT = (READ_ONLY | DONT_ENUM | DONT_DELETE) + 1;
STATIC_ASSERT(ATTRS_COUNT == 8);
Handle<Map> attr_maps[ATTRS_COUNT];
Handle<String> name = factory->InternalizeUtf8String("foo");
// Add transitions for same field name but different attributes.
for (int i = 0; i < ATTRS_COUNT; i++) {
PropertyAttributes attributes = static_cast<PropertyAttributes>(i);
Handle<Map> map = Map::CopyWithField(
map0, name, handle(FieldType::Any(), isolate),
attributes, Representation::Tagged(), OMIT_TRANSITION)
.ToHandleChecked();
attr_maps[i] = map;
TransitionArray::Insert(map0, name, map, PROPERTY_TRANSITION);
}
// Ensure that transitions for |name| field are valid.
for (int i = 0; i < ATTRS_COUNT; i++) {
PropertyAttributes attributes = static_cast<PropertyAttributes>(i);
CHECK_EQ(*attr_maps[i], TransitionArray::SearchTransition(
*map0, kData, *name, attributes));
// All transitions use the same key, so this check doesn't need to
// care about ordering.
CHECK_EQ(*name, TransitionArray::GetKey(map0->raw_transitions(), i));
}
#ifdef DEBUG
CHECK(TransitionArray::IsSortedNoDuplicates(*map0));
#endif
}
TEST(TransitionArray_SameFieldNamesDifferentAttributes) {
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Factory* factory = isolate->factory();
const int PROPS_COUNT = 10;
Handle<String> names[PROPS_COUNT];
Handle<Map> maps[PROPS_COUNT];
Handle<Map> map0 = Map::Create(isolate, 0);
CHECK(map0->raw_transitions()->IsSmi());
// Some number of fields.
for (int i = 0; i < PROPS_COUNT; i++) {
EmbeddedVector<char, 64> buffer;
SNPrintF(buffer, "prop%d", i);
Handle<String> name = factory->InternalizeUtf8String(buffer.start());
Handle<Map> map =
Map::CopyWithField(map0, name, handle(FieldType::Any(), isolate), NONE,
Representation::Tagged(), OMIT_TRANSITION)
.ToHandleChecked();
names[i] = name;
maps[i] = map;
TransitionArray::Insert(map0, name, map, PROPERTY_TRANSITION);
}
const int ATTRS_COUNT = (READ_ONLY | DONT_ENUM | DONT_DELETE) + 1;
STATIC_ASSERT(ATTRS_COUNT == 8);
Handle<Map> attr_maps[ATTRS_COUNT];
Handle<String> name = factory->InternalizeUtf8String("foo");
// Add transitions for same field name but different attributes.
for (int i = 0; i < ATTRS_COUNT; i++) {
PropertyAttributes attributes = static_cast<PropertyAttributes>(i);
Handle<Map> map = Map::CopyWithField(
map0, name, handle(FieldType::Any(), isolate),
attributes, Representation::Tagged(), OMIT_TRANSITION)
.ToHandleChecked();
attr_maps[i] = map;
TransitionArray::Insert(map0, name, map, PROPERTY_TRANSITION);
}
// Ensure that transitions for |name| field are valid.
for (int i = 0; i < ATTRS_COUNT; i++) {
PropertyAttributes attr = static_cast<PropertyAttributes>(i);
CHECK_EQ(*attr_maps[i],
TransitionArray::SearchTransition(*map0, kData, *name, attr));
}
// Ensure that info about the other fields still valid.
CHECK_EQ(PROPS_COUNT + ATTRS_COUNT,
TransitionArray::NumberOfTransitions(map0->raw_transitions()));
for (int i = 0; i < PROPS_COUNT + ATTRS_COUNT; i++) {
Name* key = TransitionArray::GetKey(map0->raw_transitions(), i);
Map* target = TransitionArray::GetTarget(map0->raw_transitions(), i);
if (key == *name) {
// Attributes transition.
PropertyAttributes attributes =
target->GetLastDescriptorDetails().attributes();
CHECK_EQ(*attr_maps[static_cast<int>(attributes)], target);
} else {
for (int j = 0; j < PROPS_COUNT; j++) {
if (*names[j] == key) {
CHECK_EQ(*maps[j], target);
break;
}
}
}
}
#ifdef DEBUG
CHECK(TransitionArray::IsSortedNoDuplicates(*map0));
#endif
}