blob: b7eb50f1c954d1c4a8272c613f06aeb32325c50e [file] [log] [blame]
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001// 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.
4
5#include <stdlib.h>
6#include <utility>
7
8#include "src/v8.h"
9
10#include "src/compilation-cache.h"
11#include "src/execution.h"
12#include "src/factory.h"
Ben Murdoch097c5b22016-05-18 11:27:45 +010013#include "src/field-type.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040014#include "src/global-handles.h"
15#include "test/cctest/cctest.h"
16
17using namespace v8::internal;
18
19
20//
21// Helper functions.
22//
23
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024static void CheckPropertyDetailsFieldsConsistency(PropertyType type,
25 PropertyKind kind,
26 PropertyLocation location) {
27 int type_value = PropertyDetails::TypeField::encode(type);
28 int kind_location_value = PropertyDetails::KindField::encode(kind) |
29 PropertyDetails::LocationField::encode(location);
30 CHECK_EQ(type_value, kind_location_value);
31}
32
33
34TEST(PropertyDetailsFieldsConsistency) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000035 CheckPropertyDetailsFieldsConsistency(DATA, kData, kField);
36 CheckPropertyDetailsFieldsConsistency(DATA_CONSTANT, kData, kDescriptor);
37 CheckPropertyDetailsFieldsConsistency(ACCESSOR, kAccessor, kField);
38 CheckPropertyDetailsFieldsConsistency(ACCESSOR_CONSTANT, kAccessor,
39 kDescriptor);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040040}
41
42
43TEST(TransitionArray_SimpleFieldTransitions) {
44 CcTest::InitializeVM();
45 v8::HandleScope scope(CcTest::isolate());
46 Isolate* isolate = CcTest::i_isolate();
47 Factory* factory = isolate->factory();
48
49 Handle<String> name1 = factory->InternalizeUtf8String("foo");
50 Handle<String> name2 = factory->InternalizeUtf8String("bar");
51 PropertyAttributes attributes = NONE;
52
53 Handle<Map> map0 = Map::Create(isolate, 0);
54 Handle<Map> map1 =
Ben Murdoch097c5b22016-05-18 11:27:45 +010055 Map::CopyWithField(map0, name1, handle(FieldType::Any(), isolate),
56 attributes, Representation::Tagged(), OMIT_TRANSITION)
57 .ToHandleChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040058 Handle<Map> map2 =
Ben Murdoch097c5b22016-05-18 11:27:45 +010059 Map::CopyWithField(map0, name2, handle(FieldType::Any(), isolate),
60 attributes, Representation::Tagged(), OMIT_TRANSITION)
61 .ToHandleChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040062
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000063 CHECK(map0->raw_transitions()->IsSmi());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040064
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000065 TransitionArray::Insert(map0, name1, map1, SIMPLE_PROPERTY_TRANSITION);
66 CHECK(TransitionArray::IsSimpleTransition(map0->raw_transitions()));
67 CHECK_EQ(*map1,
68 TransitionArray::SearchTransition(*map0, kData, *name1, attributes));
69 CHECK_EQ(1, TransitionArray::NumberOfTransitions(map0->raw_transitions()));
70 CHECK_EQ(*name1, TransitionArray::GetKey(map0->raw_transitions(), 0));
71 CHECK_EQ(*map1, TransitionArray::GetTarget(map0->raw_transitions(), 0));
Emily Bernierd0a1eb72015-03-24 16:35:39 -040072
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000073 TransitionArray::Insert(map0, name2, map2, SIMPLE_PROPERTY_TRANSITION);
74 CHECK(TransitionArray::IsFullTransitionArray(map0->raw_transitions()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -040075
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000076 CHECK_EQ(*map1,
77 TransitionArray::SearchTransition(*map0, kData, *name1, attributes));
78 CHECK_EQ(*map2,
79 TransitionArray::SearchTransition(*map0, kData, *name2, attributes));
80 CHECK_EQ(2, TransitionArray::NumberOfTransitions(map0->raw_transitions()));
81 for (int i = 0; i < 2; i++) {
82 Name* key = TransitionArray::GetKey(map0->raw_transitions(), i);
83 Map* target = TransitionArray::GetTarget(map0->raw_transitions(), i);
84 CHECK((key == *name1 && target == *map1) ||
85 (key == *name2 && target == *map2));
86 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -040087
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000088#ifdef DEBUG
89 CHECK(TransitionArray::IsSortedNoDuplicates(*map0));
90#endif
Emily Bernierd0a1eb72015-03-24 16:35:39 -040091}
92
93
94TEST(TransitionArray_FullFieldTransitions) {
95 CcTest::InitializeVM();
96 v8::HandleScope scope(CcTest::isolate());
97 Isolate* isolate = CcTest::i_isolate();
98 Factory* factory = isolate->factory();
99
100 Handle<String> name1 = factory->InternalizeUtf8String("foo");
101 Handle<String> name2 = factory->InternalizeUtf8String("bar");
102 PropertyAttributes attributes = NONE;
103
104 Handle<Map> map0 = Map::Create(isolate, 0);
105 Handle<Map> map1 =
Ben Murdoch097c5b22016-05-18 11:27:45 +0100106 Map::CopyWithField(map0, name1, handle(FieldType::Any(), isolate),
107 attributes, Representation::Tagged(), OMIT_TRANSITION)
108 .ToHandleChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400109 Handle<Map> map2 =
Ben Murdoch097c5b22016-05-18 11:27:45 +0100110 Map::CopyWithField(map0, name2, handle(FieldType::Any(), isolate),
111 attributes, Representation::Tagged(), OMIT_TRANSITION)
112 .ToHandleChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400113
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000114 CHECK(map0->raw_transitions()->IsSmi());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400115
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000116 TransitionArray::Insert(map0, name1, map1, PROPERTY_TRANSITION);
117 CHECK(TransitionArray::IsFullTransitionArray(map0->raw_transitions()));
118 CHECK_EQ(*map1,
119 TransitionArray::SearchTransition(*map0, kData, *name1, attributes));
120 CHECK_EQ(1, TransitionArray::NumberOfTransitions(map0->raw_transitions()));
121 CHECK_EQ(*name1, TransitionArray::GetKey(map0->raw_transitions(), 0));
122 CHECK_EQ(*map1, TransitionArray::GetTarget(map0->raw_transitions(), 0));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400123
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000124 TransitionArray::Insert(map0, name2, map2, PROPERTY_TRANSITION);
125 CHECK(TransitionArray::IsFullTransitionArray(map0->raw_transitions()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400126
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000127 CHECK_EQ(*map1,
128 TransitionArray::SearchTransition(*map0, kData, *name1, attributes));
129 CHECK_EQ(*map2,
130 TransitionArray::SearchTransition(*map0, kData, *name2, attributes));
131 CHECK_EQ(2, TransitionArray::NumberOfTransitions(map0->raw_transitions()));
132 for (int i = 0; i < 2; i++) {
133 Name* key = TransitionArray::GetKey(map0->raw_transitions(), i);
134 Map* target = TransitionArray::GetTarget(map0->raw_transitions(), i);
135 CHECK((key == *name1 && target == *map1) ||
136 (key == *name2 && target == *map2));
137 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400138
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000139#ifdef DEBUG
140 CHECK(TransitionArray::IsSortedNoDuplicates(*map0));
141#endif
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400142}
143
144
145TEST(TransitionArray_DifferentFieldNames) {
146 CcTest::InitializeVM();
147 v8::HandleScope scope(CcTest::isolate());
148 Isolate* isolate = CcTest::i_isolate();
149 Factory* factory = isolate->factory();
150
151 const int PROPS_COUNT = 10;
152 Handle<String> names[PROPS_COUNT];
153 Handle<Map> maps[PROPS_COUNT];
154 PropertyAttributes attributes = NONE;
155
156 Handle<Map> map0 = Map::Create(isolate, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000157 CHECK(map0->raw_transitions()->IsSmi());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400158
159 for (int i = 0; i < PROPS_COUNT; i++) {
160 EmbeddedVector<char, 64> buffer;
161 SNPrintF(buffer, "prop%d", i);
162 Handle<String> name = factory->InternalizeUtf8String(buffer.start());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100163 Handle<Map> map = Map::CopyWithField(
164 map0, name, handle(FieldType::Any(), isolate),
165 attributes, Representation::Tagged(), OMIT_TRANSITION)
166 .ToHandleChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400167 names[i] = name;
168 maps[i] = map;
169
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000170 TransitionArray::Insert(map0, name, map, PROPERTY_TRANSITION);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400171 }
172
173 for (int i = 0; i < PROPS_COUNT; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000174 CHECK_EQ(*maps[i], TransitionArray::SearchTransition(
175 *map0, kData, *names[i], attributes));
176 }
177 for (int i = 0; i < PROPS_COUNT; i++) {
178 Name* key = TransitionArray::GetKey(map0->raw_transitions(), i);
179 Map* target = TransitionArray::GetTarget(map0->raw_transitions(), i);
180 for (int j = 0; j < PROPS_COUNT; j++) {
181 if (*names[i] == key) {
182 CHECK_EQ(*maps[i], target);
183 break;
184 }
185 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400186 }
187
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000188#ifdef DEBUG
189 CHECK(TransitionArray::IsSortedNoDuplicates(*map0));
190#endif
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400191}
192
193
194TEST(TransitionArray_SameFieldNamesDifferentAttributesSimple) {
195 CcTest::InitializeVM();
196 v8::HandleScope scope(CcTest::isolate());
197 Isolate* isolate = CcTest::i_isolate();
198 Factory* factory = isolate->factory();
199
200 Handle<Map> map0 = Map::Create(isolate, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000201 CHECK(map0->raw_transitions()->IsSmi());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400202
203 const int ATTRS_COUNT = (READ_ONLY | DONT_ENUM | DONT_DELETE) + 1;
204 STATIC_ASSERT(ATTRS_COUNT == 8);
205 Handle<Map> attr_maps[ATTRS_COUNT];
206 Handle<String> name = factory->InternalizeUtf8String("foo");
207
208 // Add transitions for same field name but different attributes.
209 for (int i = 0; i < ATTRS_COUNT; i++) {
210 PropertyAttributes attributes = static_cast<PropertyAttributes>(i);
211
Ben Murdoch097c5b22016-05-18 11:27:45 +0100212 Handle<Map> map = Map::CopyWithField(
213 map0, name, handle(FieldType::Any(), isolate),
214 attributes, Representation::Tagged(), OMIT_TRANSITION)
215 .ToHandleChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400216 attr_maps[i] = map;
217
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000218 TransitionArray::Insert(map0, name, map, PROPERTY_TRANSITION);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400219 }
220
221 // Ensure that transitions for |name| field are valid.
222 for (int i = 0; i < ATTRS_COUNT; i++) {
223 PropertyAttributes attributes = static_cast<PropertyAttributes>(i);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000224 CHECK_EQ(*attr_maps[i], TransitionArray::SearchTransition(
225 *map0, kData, *name, attributes));
226 // All transitions use the same key, so this check doesn't need to
227 // care about ordering.
228 CHECK_EQ(*name, TransitionArray::GetKey(map0->raw_transitions(), i));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400229 }
230
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000231#ifdef DEBUG
232 CHECK(TransitionArray::IsSortedNoDuplicates(*map0));
233#endif
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400234}
235
236
237TEST(TransitionArray_SameFieldNamesDifferentAttributes) {
238 CcTest::InitializeVM();
239 v8::HandleScope scope(CcTest::isolate());
240 Isolate* isolate = CcTest::i_isolate();
241 Factory* factory = isolate->factory();
242
243 const int PROPS_COUNT = 10;
244 Handle<String> names[PROPS_COUNT];
245 Handle<Map> maps[PROPS_COUNT];
246
247 Handle<Map> map0 = Map::Create(isolate, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000248 CHECK(map0->raw_transitions()->IsSmi());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400249
250 // Some number of fields.
251 for (int i = 0; i < PROPS_COUNT; i++) {
252 EmbeddedVector<char, 64> buffer;
253 SNPrintF(buffer, "prop%d", i);
254 Handle<String> name = factory->InternalizeUtf8String(buffer.start());
255 Handle<Map> map =
Ben Murdoch097c5b22016-05-18 11:27:45 +0100256 Map::CopyWithField(map0, name, handle(FieldType::Any(), isolate), NONE,
257 Representation::Tagged(), OMIT_TRANSITION)
258 .ToHandleChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400259 names[i] = name;
260 maps[i] = map;
261
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000262 TransitionArray::Insert(map0, name, map, PROPERTY_TRANSITION);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400263 }
264
265 const int ATTRS_COUNT = (READ_ONLY | DONT_ENUM | DONT_DELETE) + 1;
266 STATIC_ASSERT(ATTRS_COUNT == 8);
267 Handle<Map> attr_maps[ATTRS_COUNT];
268 Handle<String> name = factory->InternalizeUtf8String("foo");
269
270 // Add transitions for same field name but different attributes.
271 for (int i = 0; i < ATTRS_COUNT; i++) {
272 PropertyAttributes attributes = static_cast<PropertyAttributes>(i);
273
Ben Murdoch097c5b22016-05-18 11:27:45 +0100274 Handle<Map> map = Map::CopyWithField(
275 map0, name, handle(FieldType::Any(), isolate),
276 attributes, Representation::Tagged(), OMIT_TRANSITION)
277 .ToHandleChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400278 attr_maps[i] = map;
279
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000280 TransitionArray::Insert(map0, name, map, PROPERTY_TRANSITION);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400281 }
282
283 // Ensure that transitions for |name| field are valid.
284 for (int i = 0; i < ATTRS_COUNT; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000285 PropertyAttributes attr = static_cast<PropertyAttributes>(i);
286 CHECK_EQ(*attr_maps[i],
287 TransitionArray::SearchTransition(*map0, kData, *name, attr));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400288 }
289
290 // Ensure that info about the other fields still valid.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000291 CHECK_EQ(PROPS_COUNT + ATTRS_COUNT,
292 TransitionArray::NumberOfTransitions(map0->raw_transitions()));
293 for (int i = 0; i < PROPS_COUNT + ATTRS_COUNT; i++) {
294 Name* key = TransitionArray::GetKey(map0->raw_transitions(), i);
295 Map* target = TransitionArray::GetTarget(map0->raw_transitions(), i);
296 if (key == *name) {
297 // Attributes transition.
298 PropertyAttributes attributes =
299 target->GetLastDescriptorDetails().attributes();
300 CHECK_EQ(*attr_maps[static_cast<int>(attributes)], target);
301 } else {
302 for (int j = 0; j < PROPS_COUNT; j++) {
303 if (*names[j] == key) {
304 CHECK_EQ(*maps[j], target);
305 break;
306 }
307 }
308 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400309 }
310
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000311#ifdef DEBUG
312 CHECK(TransitionArray::IsSortedNoDuplicates(*map0));
313#endif
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400314}