blob: 8834f9ade1e03a5b83a09a8075430d1e48da5073 [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"
13#include "src/global-handles.h"
14#include "test/cctest/cctest.h"
15
16using namespace v8::internal;
17
18
19//
20// Helper functions.
21//
22
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023static void CheckPropertyDetailsFieldsConsistency(PropertyType type,
24 PropertyKind kind,
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);
30}
31
32
33TEST(PropertyDetailsFieldsConsistency) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000034 CheckPropertyDetailsFieldsConsistency(DATA, kData, kField);
35 CheckPropertyDetailsFieldsConsistency(DATA_CONSTANT, kData, kDescriptor);
36 CheckPropertyDetailsFieldsConsistency(ACCESSOR, kAccessor, kField);
37 CheckPropertyDetailsFieldsConsistency(ACCESSOR_CONSTANT, kAccessor,
38 kDescriptor);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040039}
40
41
42TEST(TransitionArray_SimpleFieldTransitions) {
43 CcTest::InitializeVM();
44 v8::HandleScope scope(CcTest::isolate());
45 Isolate* isolate = CcTest::i_isolate();
46 Factory* factory = isolate->factory();
47
48 Handle<String> name1 = factory->InternalizeUtf8String("foo");
49 Handle<String> name2 = factory->InternalizeUtf8String("bar");
50 PropertyAttributes attributes = NONE;
51
52 Handle<Map> map0 = Map::Create(isolate, 0);
53 Handle<Map> map1 =
54 Map::CopyWithField(map0, name1, handle(HeapType::Any(), isolate),
55 attributes, Representation::Tagged(),
56 OMIT_TRANSITION).ToHandleChecked();
57 Handle<Map> map2 =
58 Map::CopyWithField(map0, name2, handle(HeapType::Any(), isolate),
59 attributes, Representation::Tagged(),
60 OMIT_TRANSITION).ToHandleChecked();
61
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000062 CHECK(map0->raw_transitions()->IsSmi());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040063
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000064 TransitionArray::Insert(map0, name1, map1, SIMPLE_PROPERTY_TRANSITION);
65 CHECK(TransitionArray::IsSimpleTransition(map0->raw_transitions()));
66 CHECK_EQ(*map1,
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));
Emily Bernierd0a1eb72015-03-24 16:35:39 -040071
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000072 TransitionArray::Insert(map0, name2, map2, SIMPLE_PROPERTY_TRANSITION);
73 CHECK(TransitionArray::IsFullTransitionArray(map0->raw_transitions()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -040074
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000075 CHECK_EQ(*map1,
76 TransitionArray::SearchTransition(*map0, kData, *name1, attributes));
77 CHECK_EQ(*map2,
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));
85 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -040086
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000087#ifdef DEBUG
88 CHECK(TransitionArray::IsSortedNoDuplicates(*map0));
89#endif
Emily Bernierd0a1eb72015-03-24 16:35:39 -040090}
91
92
93TEST(TransitionArray_FullFieldTransitions) {
94 CcTest::InitializeVM();
95 v8::HandleScope scope(CcTest::isolate());
96 Isolate* isolate = CcTest::i_isolate();
97 Factory* factory = isolate->factory();
98
99 Handle<String> name1 = factory->InternalizeUtf8String("foo");
100 Handle<String> name2 = factory->InternalizeUtf8String("bar");
101 PropertyAttributes attributes = NONE;
102
103 Handle<Map> map0 = Map::Create(isolate, 0);
104 Handle<Map> map1 =
105 Map::CopyWithField(map0, name1, handle(HeapType::Any(), isolate),
106 attributes, Representation::Tagged(),
107 OMIT_TRANSITION).ToHandleChecked();
108 Handle<Map> map2 =
109 Map::CopyWithField(map0, name2, handle(HeapType::Any(), isolate),
110 attributes, Representation::Tagged(),
111 OMIT_TRANSITION).ToHandleChecked();
112
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000113 CHECK(map0->raw_transitions()->IsSmi());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400114
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000115 TransitionArray::Insert(map0, name1, map1, PROPERTY_TRANSITION);
116 CHECK(TransitionArray::IsFullTransitionArray(map0->raw_transitions()));
117 CHECK_EQ(*map1,
118 TransitionArray::SearchTransition(*map0, kData, *name1, attributes));
119 CHECK_EQ(1, TransitionArray::NumberOfTransitions(map0->raw_transitions()));
120 CHECK_EQ(*name1, TransitionArray::GetKey(map0->raw_transitions(), 0));
121 CHECK_EQ(*map1, TransitionArray::GetTarget(map0->raw_transitions(), 0));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400122
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000123 TransitionArray::Insert(map0, name2, map2, PROPERTY_TRANSITION);
124 CHECK(TransitionArray::IsFullTransitionArray(map0->raw_transitions()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400125
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000126 CHECK_EQ(*map1,
127 TransitionArray::SearchTransition(*map0, kData, *name1, attributes));
128 CHECK_EQ(*map2,
129 TransitionArray::SearchTransition(*map0, kData, *name2, attributes));
130 CHECK_EQ(2, TransitionArray::NumberOfTransitions(map0->raw_transitions()));
131 for (int i = 0; i < 2; i++) {
132 Name* key = TransitionArray::GetKey(map0->raw_transitions(), i);
133 Map* target = TransitionArray::GetTarget(map0->raw_transitions(), i);
134 CHECK((key == *name1 && target == *map1) ||
135 (key == *name2 && target == *map2));
136 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400137
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000138#ifdef DEBUG
139 CHECK(TransitionArray::IsSortedNoDuplicates(*map0));
140#endif
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400141}
142
143
144TEST(TransitionArray_DifferentFieldNames) {
145 CcTest::InitializeVM();
146 v8::HandleScope scope(CcTest::isolate());
147 Isolate* isolate = CcTest::i_isolate();
148 Factory* factory = isolate->factory();
149
150 const int PROPS_COUNT = 10;
151 Handle<String> names[PROPS_COUNT];
152 Handle<Map> maps[PROPS_COUNT];
153 PropertyAttributes attributes = NONE;
154
155 Handle<Map> map0 = Map::Create(isolate, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000156 CHECK(map0->raw_transitions()->IsSmi());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400157
158 for (int i = 0; i < PROPS_COUNT; i++) {
159 EmbeddedVector<char, 64> buffer;
160 SNPrintF(buffer, "prop%d", i);
161 Handle<String> name = factory->InternalizeUtf8String(buffer.start());
162 Handle<Map> map =
163 Map::CopyWithField(map0, name, handle(HeapType::Any(), isolate),
164 attributes, Representation::Tagged(),
165 OMIT_TRANSITION).ToHandleChecked();
166 names[i] = name;
167 maps[i] = map;
168
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000169 TransitionArray::Insert(map0, name, map, PROPERTY_TRANSITION);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400170 }
171
172 for (int i = 0; i < PROPS_COUNT; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000173 CHECK_EQ(*maps[i], TransitionArray::SearchTransition(
174 *map0, kData, *names[i], attributes));
175 }
176 for (int i = 0; i < PROPS_COUNT; i++) {
177 Name* key = TransitionArray::GetKey(map0->raw_transitions(), i);
178 Map* target = TransitionArray::GetTarget(map0->raw_transitions(), i);
179 for (int j = 0; j < PROPS_COUNT; j++) {
180 if (*names[i] == key) {
181 CHECK_EQ(*maps[i], target);
182 break;
183 }
184 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400185 }
186
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000187#ifdef DEBUG
188 CHECK(TransitionArray::IsSortedNoDuplicates(*map0));
189#endif
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400190}
191
192
193TEST(TransitionArray_SameFieldNamesDifferentAttributesSimple) {
194 CcTest::InitializeVM();
195 v8::HandleScope scope(CcTest::isolate());
196 Isolate* isolate = CcTest::i_isolate();
197 Factory* factory = isolate->factory();
198
199 Handle<Map> map0 = Map::Create(isolate, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000200 CHECK(map0->raw_transitions()->IsSmi());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400201
202 const int ATTRS_COUNT = (READ_ONLY | DONT_ENUM | DONT_DELETE) + 1;
203 STATIC_ASSERT(ATTRS_COUNT == 8);
204 Handle<Map> attr_maps[ATTRS_COUNT];
205 Handle<String> name = factory->InternalizeUtf8String("foo");
206
207 // Add transitions for same field name but different attributes.
208 for (int i = 0; i < ATTRS_COUNT; i++) {
209 PropertyAttributes attributes = static_cast<PropertyAttributes>(i);
210
211 Handle<Map> map =
212 Map::CopyWithField(map0, name, handle(HeapType::Any(), isolate),
213 attributes, Representation::Tagged(),
214 OMIT_TRANSITION).ToHandleChecked();
215 attr_maps[i] = map;
216
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000217 TransitionArray::Insert(map0, name, map, PROPERTY_TRANSITION);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400218 }
219
220 // Ensure that transitions for |name| field are valid.
221 for (int i = 0; i < ATTRS_COUNT; i++) {
222 PropertyAttributes attributes = static_cast<PropertyAttributes>(i);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000223 CHECK_EQ(*attr_maps[i], TransitionArray::SearchTransition(
224 *map0, kData, *name, attributes));
225 // All transitions use the same key, so this check doesn't need to
226 // care about ordering.
227 CHECK_EQ(*name, TransitionArray::GetKey(map0->raw_transitions(), i));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400228 }
229
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000230#ifdef DEBUG
231 CHECK(TransitionArray::IsSortedNoDuplicates(*map0));
232#endif
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400233}
234
235
236TEST(TransitionArray_SameFieldNamesDifferentAttributes) {
237 CcTest::InitializeVM();
238 v8::HandleScope scope(CcTest::isolate());
239 Isolate* isolate = CcTest::i_isolate();
240 Factory* factory = isolate->factory();
241
242 const int PROPS_COUNT = 10;
243 Handle<String> names[PROPS_COUNT];
244 Handle<Map> maps[PROPS_COUNT];
245
246 Handle<Map> map0 = Map::Create(isolate, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000247 CHECK(map0->raw_transitions()->IsSmi());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400248
249 // Some number of fields.
250 for (int i = 0; i < PROPS_COUNT; i++) {
251 EmbeddedVector<char, 64> buffer;
252 SNPrintF(buffer, "prop%d", i);
253 Handle<String> name = factory->InternalizeUtf8String(buffer.start());
254 Handle<Map> map =
255 Map::CopyWithField(map0, name, handle(HeapType::Any(), isolate), NONE,
256 Representation::Tagged(),
257 OMIT_TRANSITION).ToHandleChecked();
258 names[i] = name;
259 maps[i] = map;
260
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000261 TransitionArray::Insert(map0, name, map, PROPERTY_TRANSITION);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400262 }
263
264 const int ATTRS_COUNT = (READ_ONLY | DONT_ENUM | DONT_DELETE) + 1;
265 STATIC_ASSERT(ATTRS_COUNT == 8);
266 Handle<Map> attr_maps[ATTRS_COUNT];
267 Handle<String> name = factory->InternalizeUtf8String("foo");
268
269 // Add transitions for same field name but different attributes.
270 for (int i = 0; i < ATTRS_COUNT; i++) {
271 PropertyAttributes attributes = static_cast<PropertyAttributes>(i);
272
273 Handle<Map> map =
274 Map::CopyWithField(map0, name, handle(HeapType::Any(), isolate),
275 attributes, Representation::Tagged(),
276 OMIT_TRANSITION).ToHandleChecked();
277 attr_maps[i] = map;
278
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000279 TransitionArray::Insert(map0, name, map, PROPERTY_TRANSITION);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400280 }
281
282 // Ensure that transitions for |name| field are valid.
283 for (int i = 0; i < ATTRS_COUNT; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000284 PropertyAttributes attr = static_cast<PropertyAttributes>(i);
285 CHECK_EQ(*attr_maps[i],
286 TransitionArray::SearchTransition(*map0, kData, *name, attr));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400287 }
288
289 // Ensure that info about the other fields still valid.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000290 CHECK_EQ(PROPS_COUNT + ATTRS_COUNT,
291 TransitionArray::NumberOfTransitions(map0->raw_transitions()));
292 for (int i = 0; i < PROPS_COUNT + ATTRS_COUNT; i++) {
293 Name* key = TransitionArray::GetKey(map0->raw_transitions(), i);
294 Map* target = TransitionArray::GetTarget(map0->raw_transitions(), i);
295 if (key == *name) {
296 // Attributes transition.
297 PropertyAttributes attributes =
298 target->GetLastDescriptorDetails().attributes();
299 CHECK_EQ(*attr_maps[static_cast<int>(attributes)], target);
300 } else {
301 for (int j = 0; j < PROPS_COUNT; j++) {
302 if (*names[j] == key) {
303 CHECK_EQ(*maps[j], target);
304 break;
305 }
306 }
307 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400308 }
309
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000310#ifdef DEBUG
311 CHECK(TransitionArray::IsSortedNoDuplicates(*map0));
312#endif
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400313}