OLD | NEW |
| (Empty) |
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 ConnectTransition(Handle<Map> parent, | |
24 Handle<TransitionArray> transitions, | |
25 Handle<Map> child) { | |
26 if (!parent->HasTransitionArray() || *transitions != parent->transitions()) { | |
27 parent->set_transitions(*transitions); | |
28 } | |
29 child->SetBackPointer(*parent); | |
30 } | |
31 | |
32 | |
33 TEST(TransitionArray_SimpleFieldTransitions) { | |
34 CcTest::InitializeVM(); | |
35 v8::HandleScope scope(CcTest::isolate()); | |
36 Isolate* isolate = CcTest::i_isolate(); | |
37 Factory* factory = isolate->factory(); | |
38 | |
39 Handle<String> name1 = factory->InternalizeUtf8String("foo"); | |
40 Handle<String> name2 = factory->InternalizeUtf8String("bar"); | |
41 PropertyAttributes attributes = NONE; | |
42 | |
43 Handle<Map> map0 = Map::Create(isolate, 0); | |
44 Handle<Map> map1 = | |
45 Map::CopyWithField(map0, name1, handle(HeapType::Any(), isolate), | |
46 attributes, Representation::Tagged(), | |
47 OMIT_TRANSITION).ToHandleChecked(); | |
48 Handle<Map> map2 = | |
49 Map::CopyWithField(map0, name2, handle(HeapType::Any(), isolate), | |
50 attributes, Representation::Tagged(), | |
51 OMIT_TRANSITION).ToHandleChecked(); | |
52 | |
53 CHECK(!map0->HasTransitionArray()); | |
54 Handle<TransitionArray> transitions = TransitionArray::Allocate(isolate, 0); | |
55 CHECK(transitions->IsFullTransitionArray()); | |
56 | |
57 int transition; | |
58 transitions = | |
59 transitions->Insert(map0, name1, map1, SIMPLE_PROPERTY_TRANSITION); | |
60 ConnectTransition(map0, transitions, map1); | |
61 CHECK(transitions->IsSimpleTransition()); | |
62 transition = transitions->Search(FIELD, *name1, attributes); | |
63 CHECK_EQ(TransitionArray::kSimpleTransitionIndex, transition); | |
64 CHECK_EQ(*name1, transitions->GetKey(transition)); | |
65 CHECK_EQ(*map1, transitions->GetTarget(transition)); | |
66 | |
67 transitions = | |
68 transitions->Insert(map0, name2, map2, SIMPLE_PROPERTY_TRANSITION); | |
69 ConnectTransition(map0, transitions, map2); | |
70 CHECK(transitions->IsFullTransitionArray()); | |
71 | |
72 transition = transitions->Search(FIELD, *name1, attributes); | |
73 CHECK_EQ(*name1, transitions->GetKey(transition)); | |
74 CHECK_EQ(*map1, transitions->GetTarget(transition)); | |
75 | |
76 transition = transitions->Search(FIELD, *name2, attributes); | |
77 CHECK_EQ(*name2, transitions->GetKey(transition)); | |
78 CHECK_EQ(*map2, transitions->GetTarget(transition)); | |
79 | |
80 DCHECK(transitions->IsSortedNoDuplicates()); | |
81 } | |
82 | |
83 | |
84 TEST(TransitionArray_FullFieldTransitions) { | |
85 CcTest::InitializeVM(); | |
86 v8::HandleScope scope(CcTest::isolate()); | |
87 Isolate* isolate = CcTest::i_isolate(); | |
88 Factory* factory = isolate->factory(); | |
89 | |
90 Handle<String> name1 = factory->InternalizeUtf8String("foo"); | |
91 Handle<String> name2 = factory->InternalizeUtf8String("bar"); | |
92 PropertyAttributes attributes = NONE; | |
93 | |
94 Handle<Map> map0 = Map::Create(isolate, 0); | |
95 Handle<Map> map1 = | |
96 Map::CopyWithField(map0, name1, handle(HeapType::Any(), isolate), | |
97 attributes, Representation::Tagged(), | |
98 OMIT_TRANSITION).ToHandleChecked(); | |
99 Handle<Map> map2 = | |
100 Map::CopyWithField(map0, name2, handle(HeapType::Any(), isolate), | |
101 attributes, Representation::Tagged(), | |
102 OMIT_TRANSITION).ToHandleChecked(); | |
103 | |
104 CHECK(!map0->HasTransitionArray()); | |
105 Handle<TransitionArray> transitions = TransitionArray::Allocate(isolate, 0); | |
106 CHECK(transitions->IsFullTransitionArray()); | |
107 | |
108 int transition; | |
109 transitions = transitions->Insert(map0, name1, map1, PROPERTY_TRANSITION); | |
110 ConnectTransition(map0, transitions, map1); | |
111 CHECK(transitions->IsFullTransitionArray()); | |
112 transition = transitions->Search(FIELD, *name1, attributes); | |
113 CHECK_EQ(*name1, transitions->GetKey(transition)); | |
114 CHECK_EQ(*map1, transitions->GetTarget(transition)); | |
115 | |
116 transitions = transitions->Insert(map0, name2, map2, PROPERTY_TRANSITION); | |
117 ConnectTransition(map0, transitions, map2); | |
118 CHECK(transitions->IsFullTransitionArray()); | |
119 | |
120 transition = transitions->Search(FIELD, *name1, attributes); | |
121 CHECK_EQ(*name1, transitions->GetKey(transition)); | |
122 CHECK_EQ(*map1, transitions->GetTarget(transition)); | |
123 | |
124 transition = transitions->Search(FIELD, *name2, attributes); | |
125 CHECK_EQ(*name2, transitions->GetKey(transition)); | |
126 CHECK_EQ(*map2, transitions->GetTarget(transition)); | |
127 | |
128 DCHECK(transitions->IsSortedNoDuplicates()); | |
129 } | |
130 | |
131 | |
132 TEST(TransitionArray_DifferentFieldNames) { | |
133 CcTest::InitializeVM(); | |
134 v8::HandleScope scope(CcTest::isolate()); | |
135 Isolate* isolate = CcTest::i_isolate(); | |
136 Factory* factory = isolate->factory(); | |
137 | |
138 const int PROPS_COUNT = 10; | |
139 Handle<String> names[PROPS_COUNT]; | |
140 Handle<Map> maps[PROPS_COUNT]; | |
141 PropertyAttributes attributes = NONE; | |
142 | |
143 Handle<Map> map0 = Map::Create(isolate, 0); | |
144 CHECK(!map0->HasTransitionArray()); | |
145 Handle<TransitionArray> transitions = TransitionArray::Allocate(isolate, 0); | |
146 CHECK(transitions->IsFullTransitionArray()); | |
147 | |
148 for (int i = 0; i < PROPS_COUNT; i++) { | |
149 EmbeddedVector<char, 64> buffer; | |
150 SNPrintF(buffer, "prop%d", i); | |
151 Handle<String> name = factory->InternalizeUtf8String(buffer.start()); | |
152 Handle<Map> map = | |
153 Map::CopyWithField(map0, name, handle(HeapType::Any(), isolate), | |
154 attributes, Representation::Tagged(), | |
155 OMIT_TRANSITION).ToHandleChecked(); | |
156 names[i] = name; | |
157 maps[i] = map; | |
158 | |
159 transitions = transitions->Insert(map0, name, map, PROPERTY_TRANSITION); | |
160 ConnectTransition(map0, transitions, map); | |
161 } | |
162 | |
163 for (int i = 0; i < PROPS_COUNT; i++) { | |
164 int transition = transitions->Search(FIELD, *names[i], attributes); | |
165 CHECK_EQ(*names[i], transitions->GetKey(transition)); | |
166 CHECK_EQ(*maps[i], transitions->GetTarget(transition)); | |
167 } | |
168 | |
169 DCHECK(transitions->IsSortedNoDuplicates()); | |
170 } | |
171 | |
172 | |
173 TEST(TransitionArray_SameFieldNamesDifferentAttributesSimple) { | |
174 CcTest::InitializeVM(); | |
175 v8::HandleScope scope(CcTest::isolate()); | |
176 Isolate* isolate = CcTest::i_isolate(); | |
177 Factory* factory = isolate->factory(); | |
178 | |
179 Handle<Map> map0 = Map::Create(isolate, 0); | |
180 CHECK(!map0->HasTransitionArray()); | |
181 Handle<TransitionArray> transitions = TransitionArray::Allocate(isolate, 0); | |
182 CHECK(transitions->IsFullTransitionArray()); | |
183 | |
184 const int ATTRS_COUNT = (READ_ONLY | DONT_ENUM | DONT_DELETE) + 1; | |
185 STATIC_ASSERT(ATTRS_COUNT == 8); | |
186 Handle<Map> attr_maps[ATTRS_COUNT]; | |
187 Handle<String> name = factory->InternalizeUtf8String("foo"); | |
188 | |
189 // Add transitions for same field name but different attributes. | |
190 for (int i = 0; i < ATTRS_COUNT; i++) { | |
191 PropertyAttributes attributes = static_cast<PropertyAttributes>(i); | |
192 | |
193 Handle<Map> map = | |
194 Map::CopyWithField(map0, name, handle(HeapType::Any(), isolate), | |
195 attributes, Representation::Tagged(), | |
196 OMIT_TRANSITION).ToHandleChecked(); | |
197 attr_maps[i] = map; | |
198 | |
199 transitions = transitions->Insert(map0, name, map, PROPERTY_TRANSITION); | |
200 ConnectTransition(map0, transitions, map); | |
201 } | |
202 | |
203 // Ensure that transitions for |name| field are valid. | |
204 for (int i = 0; i < ATTRS_COUNT; i++) { | |
205 PropertyAttributes attributes = static_cast<PropertyAttributes>(i); | |
206 | |
207 int transition = transitions->Search(FIELD, *name, attributes); | |
208 CHECK_EQ(*name, transitions->GetKey(transition)); | |
209 CHECK_EQ(*attr_maps[i], transitions->GetTarget(transition)); | |
210 } | |
211 | |
212 DCHECK(transitions->IsSortedNoDuplicates()); | |
213 } | |
214 | |
215 | |
216 TEST(TransitionArray_SameFieldNamesDifferentAttributes) { | |
217 CcTest::InitializeVM(); | |
218 v8::HandleScope scope(CcTest::isolate()); | |
219 Isolate* isolate = CcTest::i_isolate(); | |
220 Factory* factory = isolate->factory(); | |
221 | |
222 const int PROPS_COUNT = 10; | |
223 Handle<String> names[PROPS_COUNT]; | |
224 Handle<Map> maps[PROPS_COUNT]; | |
225 | |
226 Handle<Map> map0 = Map::Create(isolate, 0); | |
227 CHECK(!map0->HasTransitionArray()); | |
228 Handle<TransitionArray> transitions = TransitionArray::Allocate(isolate, 0); | |
229 CHECK(transitions->IsFullTransitionArray()); | |
230 | |
231 // Some number of fields. | |
232 for (int i = 0; i < PROPS_COUNT; i++) { | |
233 EmbeddedVector<char, 64> buffer; | |
234 SNPrintF(buffer, "prop%d", i); | |
235 Handle<String> name = factory->InternalizeUtf8String(buffer.start()); | |
236 Handle<Map> map = | |
237 Map::CopyWithField(map0, name, handle(HeapType::Any(), isolate), NONE, | |
238 Representation::Tagged(), | |
239 OMIT_TRANSITION).ToHandleChecked(); | |
240 names[i] = name; | |
241 maps[i] = map; | |
242 | |
243 transitions = transitions->Insert(map0, name, map, PROPERTY_TRANSITION); | |
244 ConnectTransition(map0, transitions, map); | |
245 } | |
246 | |
247 const int ATTRS_COUNT = (READ_ONLY | DONT_ENUM | DONT_DELETE) + 1; | |
248 STATIC_ASSERT(ATTRS_COUNT == 8); | |
249 Handle<Map> attr_maps[ATTRS_COUNT]; | |
250 Handle<String> name = factory->InternalizeUtf8String("foo"); | |
251 | |
252 // Add transitions for same field name but different attributes. | |
253 for (int i = 0; i < ATTRS_COUNT; i++) { | |
254 PropertyAttributes attributes = static_cast<PropertyAttributes>(i); | |
255 | |
256 Handle<Map> map = | |
257 Map::CopyWithField(map0, name, handle(HeapType::Any(), isolate), | |
258 attributes, Representation::Tagged(), | |
259 OMIT_TRANSITION).ToHandleChecked(); | |
260 attr_maps[i] = map; | |
261 | |
262 transitions = transitions->Insert(map0, name, map, PROPERTY_TRANSITION); | |
263 ConnectTransition(map0, transitions, map); | |
264 } | |
265 | |
266 // Ensure that transitions for |name| field are valid. | |
267 for (int i = 0; i < ATTRS_COUNT; i++) { | |
268 PropertyAttributes attributes = static_cast<PropertyAttributes>(i); | |
269 | |
270 int transition = transitions->Search(FIELD, *name, attributes); | |
271 CHECK_EQ(*name, transitions->GetKey(transition)); | |
272 CHECK_EQ(*attr_maps[i], transitions->GetTarget(transition)); | |
273 } | |
274 | |
275 // Ensure that info about the other fields still valid. | |
276 for (int i = 0; i < PROPS_COUNT; i++) { | |
277 int transition = transitions->Search(FIELD, *names[i], NONE); | |
278 CHECK_EQ(*names[i], transitions->GetKey(transition)); | |
279 CHECK_EQ(*maps[i], transitions->GetTarget(transition)); | |
280 } | |
281 | |
282 DCHECK(transitions->IsSortedNoDuplicates()); | |
283 } | |
OLD | NEW |