1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
10 #include "src/compilation-cache.h"
11 #include "src/execution.h"
12 #include "src/factory.h"
13 #include "src/global-handles.h"
14 #include "test/cctest/cctest.h"
16 using namespace v8::internal;
23 static void CheckPropertyDetailsFieldsConsistency(PropertyType type,
25 PropertyLocation location) {
26 int type_value = PropertyDetails::TypeField::encode(type);
27 int kind_location_value = PropertyDetails::KindField::encode(kind) |
28 PropertyDetails::LocationField::encode(location);
29 CHECK_EQ(type_value, kind_location_value);
33 TEST(PropertyDetailsFieldsConsistency) {
34 CheckPropertyDetailsFieldsConsistency(DATA, kData, kField);
35 CheckPropertyDetailsFieldsConsistency(DATA_CONSTANT, kData, kDescriptor);
36 CheckPropertyDetailsFieldsConsistency(ACCESSOR, kAccessor, kField);
37 CheckPropertyDetailsFieldsConsistency(ACCESSOR_CONSTANT, kAccessor,
42 TEST(TransitionArray_SimpleFieldTransitions) {
43 CcTest::InitializeVM();
44 v8::HandleScope scope(CcTest::isolate());
45 Isolate* isolate = CcTest::i_isolate();
46 Factory* factory = isolate->factory();
48 Handle<String> name1 = factory->InternalizeUtf8String("foo");
49 Handle<String> name2 = factory->InternalizeUtf8String("bar");
50 PropertyAttributes attributes = NONE;
52 Handle<Map> map0 = Map::Create(isolate, 0);
54 Map::CopyWithField(map0, name1, handle(HeapType::Any(), isolate),
55 attributes, Representation::Tagged(),
56 OMIT_TRANSITION).ToHandleChecked();
58 Map::CopyWithField(map0, name2, handle(HeapType::Any(), isolate),
59 attributes, Representation::Tagged(),
60 OMIT_TRANSITION).ToHandleChecked();
62 CHECK(map0->raw_transitions()->IsSmi());
64 TransitionArray::Insert(map0, name1, map1, SIMPLE_PROPERTY_TRANSITION);
65 CHECK(TransitionArray::IsSimpleTransition(map0->raw_transitions()));
67 TransitionArray::SearchTransition(*map0, kData, *name1, attributes));
68 CHECK_EQ(1, TransitionArray::NumberOfTransitions(map0->raw_transitions()));
69 CHECK_EQ(*name1, TransitionArray::GetKey(map0->raw_transitions(), 0));
70 CHECK_EQ(*map1, TransitionArray::GetTarget(map0->raw_transitions(), 0));
72 TransitionArray::Insert(map0, name2, map2, SIMPLE_PROPERTY_TRANSITION);
73 CHECK(TransitionArray::IsFullTransitionArray(map0->raw_transitions()));
76 TransitionArray::SearchTransition(*map0, kData, *name1, attributes));
78 TransitionArray::SearchTransition(*map0, kData, *name2, attributes));
79 CHECK_EQ(2, TransitionArray::NumberOfTransitions(map0->raw_transitions()));
80 for (int i = 0; i < 2; i++) {
81 Name* key = TransitionArray::GetKey(map0->raw_transitions(), i);
82 Map* target = TransitionArray::GetTarget(map0->raw_transitions(), i);
83 CHECK((key == *name1 && target == *map1) ||
84 (key == *name2 && target == *map2));
87 DCHECK(TransitionArray::IsSortedNoDuplicates(*map0));
91 TEST(TransitionArray_FullFieldTransitions) {
92 CcTest::InitializeVM();
93 v8::HandleScope scope(CcTest::isolate());
94 Isolate* isolate = CcTest::i_isolate();
95 Factory* factory = isolate->factory();
97 Handle<String> name1 = factory->InternalizeUtf8String("foo");
98 Handle<String> name2 = factory->InternalizeUtf8String("bar");
99 PropertyAttributes attributes = NONE;
101 Handle<Map> map0 = Map::Create(isolate, 0);
103 Map::CopyWithField(map0, name1, handle(HeapType::Any(), isolate),
104 attributes, Representation::Tagged(),
105 OMIT_TRANSITION).ToHandleChecked();
107 Map::CopyWithField(map0, name2, handle(HeapType::Any(), isolate),
108 attributes, Representation::Tagged(),
109 OMIT_TRANSITION).ToHandleChecked();
111 CHECK(map0->raw_transitions()->IsSmi());
113 TransitionArray::Insert(map0, name1, map1, PROPERTY_TRANSITION);
114 CHECK(TransitionArray::IsFullTransitionArray(map0->raw_transitions()));
116 TransitionArray::SearchTransition(*map0, kData, *name1, attributes));
117 CHECK_EQ(1, TransitionArray::NumberOfTransitions(map0->raw_transitions()));
118 CHECK_EQ(*name1, TransitionArray::GetKey(map0->raw_transitions(), 0));
119 CHECK_EQ(*map1, TransitionArray::GetTarget(map0->raw_transitions(), 0));
121 TransitionArray::Insert(map0, name2, map2, PROPERTY_TRANSITION);
122 CHECK(TransitionArray::IsFullTransitionArray(map0->raw_transitions()));
125 TransitionArray::SearchTransition(*map0, kData, *name1, attributes));
127 TransitionArray::SearchTransition(*map0, kData, *name2, attributes));
128 CHECK_EQ(2, TransitionArray::NumberOfTransitions(map0->raw_transitions()));
129 for (int i = 0; i < 2; i++) {
130 Name* key = TransitionArray::GetKey(map0->raw_transitions(), i);
131 Map* target = TransitionArray::GetTarget(map0->raw_transitions(), i);
132 CHECK((key == *name1 && target == *map1) ||
133 (key == *name2 && target == *map2));
136 DCHECK(TransitionArray::IsSortedNoDuplicates(*map0));
140 TEST(TransitionArray_DifferentFieldNames) {
141 CcTest::InitializeVM();
142 v8::HandleScope scope(CcTest::isolate());
143 Isolate* isolate = CcTest::i_isolate();
144 Factory* factory = isolate->factory();
146 const int PROPS_COUNT = 10;
147 Handle<String> names[PROPS_COUNT];
148 Handle<Map> maps[PROPS_COUNT];
149 PropertyAttributes attributes = NONE;
151 Handle<Map> map0 = Map::Create(isolate, 0);
152 CHECK(map0->raw_transitions()->IsSmi());
154 for (int i = 0; i < PROPS_COUNT; i++) {
155 EmbeddedVector<char, 64> buffer;
156 SNPrintF(buffer, "prop%d", i);
157 Handle<String> name = factory->InternalizeUtf8String(buffer.start());
159 Map::CopyWithField(map0, name, handle(HeapType::Any(), isolate),
160 attributes, Representation::Tagged(),
161 OMIT_TRANSITION).ToHandleChecked();
165 TransitionArray::Insert(map0, name, map, PROPERTY_TRANSITION);
168 for (int i = 0; i < PROPS_COUNT; i++) {
169 CHECK_EQ(*maps[i], TransitionArray::SearchTransition(
170 *map0, kData, *names[i], attributes));
172 for (int i = 0; i < PROPS_COUNT; i++) {
173 Name* key = TransitionArray::GetKey(map0->raw_transitions(), i);
174 Map* target = TransitionArray::GetTarget(map0->raw_transitions(), i);
175 for (int j = 0; j < PROPS_COUNT; j++) {
176 if (*names[i] == key) {
177 CHECK_EQ(*maps[i], target);
183 DCHECK(TransitionArray::IsSortedNoDuplicates(*map0));
187 TEST(TransitionArray_SameFieldNamesDifferentAttributesSimple) {
188 CcTest::InitializeVM();
189 v8::HandleScope scope(CcTest::isolate());
190 Isolate* isolate = CcTest::i_isolate();
191 Factory* factory = isolate->factory();
193 Handle<Map> map0 = Map::Create(isolate, 0);
194 CHECK(map0->raw_transitions()->IsSmi());
196 const int ATTRS_COUNT = (READ_ONLY | DONT_ENUM | DONT_DELETE) + 1;
197 STATIC_ASSERT(ATTRS_COUNT == 8);
198 Handle<Map> attr_maps[ATTRS_COUNT];
199 Handle<String> name = factory->InternalizeUtf8String("foo");
201 // Add transitions for same field name but different attributes.
202 for (int i = 0; i < ATTRS_COUNT; i++) {
203 PropertyAttributes attributes = static_cast<PropertyAttributes>(i);
206 Map::CopyWithField(map0, name, handle(HeapType::Any(), isolate),
207 attributes, Representation::Tagged(),
208 OMIT_TRANSITION).ToHandleChecked();
211 TransitionArray::Insert(map0, name, map, PROPERTY_TRANSITION);
214 // Ensure that transitions for |name| field are valid.
215 for (int i = 0; i < ATTRS_COUNT; i++) {
216 PropertyAttributes attributes = static_cast<PropertyAttributes>(i);
217 CHECK_EQ(*attr_maps[i], TransitionArray::SearchTransition(
218 *map0, kData, *name, attributes));
219 // All transitions use the same key, so this check doesn't need to
220 // care about ordering.
221 CHECK_EQ(*name, TransitionArray::GetKey(map0->raw_transitions(), i));
224 DCHECK(TransitionArray::IsSortedNoDuplicates(*map0));
228 TEST(TransitionArray_SameFieldNamesDifferentAttributes) {
229 CcTest::InitializeVM();
230 v8::HandleScope scope(CcTest::isolate());
231 Isolate* isolate = CcTest::i_isolate();
232 Factory* factory = isolate->factory();
234 const int PROPS_COUNT = 10;
235 Handle<String> names[PROPS_COUNT];
236 Handle<Map> maps[PROPS_COUNT];
238 Handle<Map> map0 = Map::Create(isolate, 0);
239 CHECK(map0->raw_transitions()->IsSmi());
241 // Some number of fields.
242 for (int i = 0; i < PROPS_COUNT; i++) {
243 EmbeddedVector<char, 64> buffer;
244 SNPrintF(buffer, "prop%d", i);
245 Handle<String> name = factory->InternalizeUtf8String(buffer.start());
247 Map::CopyWithField(map0, name, handle(HeapType::Any(), isolate), NONE,
248 Representation::Tagged(),
249 OMIT_TRANSITION).ToHandleChecked();
253 TransitionArray::Insert(map0, name, map, PROPERTY_TRANSITION);
256 const int ATTRS_COUNT = (READ_ONLY | DONT_ENUM | DONT_DELETE) + 1;
257 STATIC_ASSERT(ATTRS_COUNT == 8);
258 Handle<Map> attr_maps[ATTRS_COUNT];
259 Handle<String> name = factory->InternalizeUtf8String("foo");
261 // Add transitions for same field name but different attributes.
262 for (int i = 0; i < ATTRS_COUNT; i++) {
263 PropertyAttributes attributes = static_cast<PropertyAttributes>(i);
266 Map::CopyWithField(map0, name, handle(HeapType::Any(), isolate),
267 attributes, Representation::Tagged(),
268 OMIT_TRANSITION).ToHandleChecked();
271 TransitionArray::Insert(map0, name, map, PROPERTY_TRANSITION);
274 // Ensure that transitions for |name| field are valid.
275 for (int i = 0; i < ATTRS_COUNT; i++) {
276 PropertyAttributes attr = static_cast<PropertyAttributes>(i);
277 CHECK_EQ(*attr_maps[i],
278 TransitionArray::SearchTransition(*map0, kData, *name, attr));
281 // Ensure that info about the other fields still valid.
282 CHECK_EQ(PROPS_COUNT + ATTRS_COUNT,
283 TransitionArray::NumberOfTransitions(map0->raw_transitions()));
284 for (int i = 0; i < PROPS_COUNT + ATTRS_COUNT; i++) {
285 Name* key = TransitionArray::GetKey(map0->raw_transitions(), i);
286 Map* target = TransitionArray::GetTarget(map0->raw_transitions(), i);
288 // Attributes transition.
289 PropertyAttributes attributes =
290 target->GetLastDescriptorDetails().attributes();
291 CHECK_EQ(*attr_maps[static_cast<int>(attributes)], target);
293 for (int j = 0; j < PROPS_COUNT; j++) {
294 if (*names[j] == key) {
295 CHECK_EQ(*maps[j], target);
302 DCHECK(TransitionArray::IsSortedNoDuplicates(*map0));