deps: update v8 to 4.3.61.21
[platform/upstream/nodejs.git] / deps / v8 / test / cctest / test-transitions.cc
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.
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
16 using namespace v8::internal;
17
18
19 //
20 // Helper functions.
21 //
22
23 static 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
33 TEST(PropertyDetailsFieldsConsistency) {
34   CheckPropertyDetailsFieldsConsistency(DATA, kData, kField);
35   CheckPropertyDetailsFieldsConsistency(DATA_CONSTANT, kData, kDescriptor);
36   CheckPropertyDetailsFieldsConsistency(ACCESSOR, kAccessor, kField);
37   CheckPropertyDetailsFieldsConsistency(ACCESSOR_CONSTANT, kAccessor,
38                                         kDescriptor);
39 }
40
41
42 TEST(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
62   CHECK(map0->raw_transitions()->IsSmi());
63
64   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));
71
72   TransitionArray::Insert(map0, name2, map2, SIMPLE_PROPERTY_TRANSITION);
73   CHECK(TransitionArray::IsFullTransitionArray(map0->raw_transitions()));
74
75   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   }
86
87   DCHECK(TransitionArray::IsSortedNoDuplicates(*map0));
88 }
89
90
91 TEST(TransitionArray_FullFieldTransitions) {
92   CcTest::InitializeVM();
93   v8::HandleScope scope(CcTest::isolate());
94   Isolate* isolate = CcTest::i_isolate();
95   Factory* factory = isolate->factory();
96
97   Handle<String> name1 = factory->InternalizeUtf8String("foo");
98   Handle<String> name2 = factory->InternalizeUtf8String("bar");
99   PropertyAttributes attributes = NONE;
100
101   Handle<Map> map0 = Map::Create(isolate, 0);
102   Handle<Map> map1 =
103       Map::CopyWithField(map0, name1, handle(HeapType::Any(), isolate),
104                          attributes, Representation::Tagged(),
105                          OMIT_TRANSITION).ToHandleChecked();
106   Handle<Map> map2 =
107       Map::CopyWithField(map0, name2, handle(HeapType::Any(), isolate),
108                          attributes, Representation::Tagged(),
109                          OMIT_TRANSITION).ToHandleChecked();
110
111   CHECK(map0->raw_transitions()->IsSmi());
112
113   TransitionArray::Insert(map0, name1, map1, PROPERTY_TRANSITION);
114   CHECK(TransitionArray::IsFullTransitionArray(map0->raw_transitions()));
115   CHECK_EQ(*map1,
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));
120
121   TransitionArray::Insert(map0, name2, map2, PROPERTY_TRANSITION);
122   CHECK(TransitionArray::IsFullTransitionArray(map0->raw_transitions()));
123
124   CHECK_EQ(*map1,
125            TransitionArray::SearchTransition(*map0, kData, *name1, attributes));
126   CHECK_EQ(*map2,
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));
134   }
135
136   DCHECK(TransitionArray::IsSortedNoDuplicates(*map0));
137 }
138
139
140 TEST(TransitionArray_DifferentFieldNames) {
141   CcTest::InitializeVM();
142   v8::HandleScope scope(CcTest::isolate());
143   Isolate* isolate = CcTest::i_isolate();
144   Factory* factory = isolate->factory();
145
146   const int PROPS_COUNT = 10;
147   Handle<String> names[PROPS_COUNT];
148   Handle<Map> maps[PROPS_COUNT];
149   PropertyAttributes attributes = NONE;
150
151   Handle<Map> map0 = Map::Create(isolate, 0);
152   CHECK(map0->raw_transitions()->IsSmi());
153
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());
158     Handle<Map> map =
159         Map::CopyWithField(map0, name, handle(HeapType::Any(), isolate),
160                            attributes, Representation::Tagged(),
161                            OMIT_TRANSITION).ToHandleChecked();
162     names[i] = name;
163     maps[i] = map;
164
165     TransitionArray::Insert(map0, name, map, PROPERTY_TRANSITION);
166   }
167
168   for (int i = 0; i < PROPS_COUNT; i++) {
169     CHECK_EQ(*maps[i], TransitionArray::SearchTransition(
170                            *map0, kData, *names[i], attributes));
171   }
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);
178         break;
179       }
180     }
181   }
182
183   DCHECK(TransitionArray::IsSortedNoDuplicates(*map0));
184 }
185
186
187 TEST(TransitionArray_SameFieldNamesDifferentAttributesSimple) {
188   CcTest::InitializeVM();
189   v8::HandleScope scope(CcTest::isolate());
190   Isolate* isolate = CcTest::i_isolate();
191   Factory* factory = isolate->factory();
192
193   Handle<Map> map0 = Map::Create(isolate, 0);
194   CHECK(map0->raw_transitions()->IsSmi());
195
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");
200
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);
204
205     Handle<Map> map =
206         Map::CopyWithField(map0, name, handle(HeapType::Any(), isolate),
207                            attributes, Representation::Tagged(),
208                            OMIT_TRANSITION).ToHandleChecked();
209     attr_maps[i] = map;
210
211     TransitionArray::Insert(map0, name, map, PROPERTY_TRANSITION);
212   }
213
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));
222   }
223
224   DCHECK(TransitionArray::IsSortedNoDuplicates(*map0));
225 }
226
227
228 TEST(TransitionArray_SameFieldNamesDifferentAttributes) {
229   CcTest::InitializeVM();
230   v8::HandleScope scope(CcTest::isolate());
231   Isolate* isolate = CcTest::i_isolate();
232   Factory* factory = isolate->factory();
233
234   const int PROPS_COUNT = 10;
235   Handle<String> names[PROPS_COUNT];
236   Handle<Map> maps[PROPS_COUNT];
237
238   Handle<Map> map0 = Map::Create(isolate, 0);
239   CHECK(map0->raw_transitions()->IsSmi());
240
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());
246     Handle<Map> map =
247         Map::CopyWithField(map0, name, handle(HeapType::Any(), isolate), NONE,
248                            Representation::Tagged(),
249                            OMIT_TRANSITION).ToHandleChecked();
250     names[i] = name;
251     maps[i] = map;
252
253     TransitionArray::Insert(map0, name, map, PROPERTY_TRANSITION);
254   }
255
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");
260
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);
264
265     Handle<Map> map =
266         Map::CopyWithField(map0, name, handle(HeapType::Any(), isolate),
267                            attributes, Representation::Tagged(),
268                            OMIT_TRANSITION).ToHandleChecked();
269     attr_maps[i] = map;
270
271     TransitionArray::Insert(map0, name, map, PROPERTY_TRANSITION);
272   }
273
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));
279   }
280
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);
287     if (key == *name) {
288       // Attributes transition.
289       PropertyAttributes attributes =
290           target->GetLastDescriptorDetails().attributes();
291       CHECK_EQ(*attr_maps[static_cast<int>(attributes)], target);
292     } else {
293       for (int j = 0; j < PROPS_COUNT; j++) {
294         if (*names[j] == key) {
295           CHECK_EQ(*maps[j], target);
296           break;
297         }
298       }
299     }
300   }
301
302   DCHECK(TransitionArray::IsSortedNoDuplicates(*map0));
303 }