Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(477)

Side by Side Diff: test/cctest/test-migrations.cc

Issue 888623002: Property reconfiguring implemented. Tests added. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« src/objects.cc ('K') | « test/cctest/cctest.gyp ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2015 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 "src/ic/stub-cache.h"
15 #include "src/macro-assembler.h"
16 #include "src/smart-pointers.h"
17 #include "test/cctest/cctest.h"
18
19 using namespace v8::internal;
20
21
22 // TODO(ishell): fix this once ReconfigureProperty supports
23 // "non equivalent" transitions.
24 const bool IS_NON_EQUIVALENT_TRANSITION_SUPPORTED = false;
25
26
27 // TODO(ishell): fix this once TransitionToPrototype stops generalizing
28 // all field representations (crbug/448711).
29 const bool IS_CRBUG_448711_FIXED = false;
30
31
32 // TODO(ishell): fix this once TransitionToAccessorProperty is able to always
33 // keep map in fast mode.
34 const bool IS_ACCESSOR_FIELD_SUPPORTED = false;
35
36
37 //
38 // Helper functions.
39 //
40
41 static Handle<String> MakeString(const char* str) {
42 Isolate* isolate = CcTest::i_isolate();
43 Factory* factory = isolate->factory();
44 return factory->InternalizeUtf8String(str);
45 }
46
47
48 static Handle<String> MakeName(const char* str, int suffix) {
49 EmbeddedVector<char, 128> buffer;
50 SNPrintF(buffer, "%s%d", str, suffix);
51 return MakeString(buffer.start());
52 }
53
54
55 static Handle<AccessorPair> CreateAccessorPair(bool with_getter,
56 bool with_setter) {
57 Isolate* isolate = CcTest::i_isolate();
58 Factory* factory = isolate->factory();
59 Handle<AccessorPair> pair = factory->NewAccessorPair();
60 if (with_getter) {
61 pair->set_getter(*factory->NewFunction(factory->empty_string()));
62 }
63 if (with_setter) {
64 pair->set_setter(*factory->NewFunction(factory->empty_string()));
65 }
66 return pair;
67 }
68
69
70 static bool EqualDetails(DescriptorArray* descriptors, int descriptor,
71 PropertyType type, PropertyAttributes attributes,
72 Representation representation, int field_index = -1) {
73 PropertyDetails details = descriptors->GetDetails(descriptor);
74 if (details.type() != type) return false;
75 if (details.attributes() != attributes) return false;
76 if (!details.representation().Equals(representation)) return false;
77 if (field_index >= 0 && details.field_index() != field_index) return false;
78 return true;
79 }
80
81
82 class Expectations {
83 static const int MAX_PROPERTIES = 64;
84 Isolate* isolate_;
85 PropertyType types_[MAX_PROPERTIES];
86 PropertyAttributes attributes_[MAX_PROPERTIES];
87 Representation representations_[MAX_PROPERTIES];
88 // HeapType for kField, value for DATA_CONSTANT and getter for
89 // ACCESSOR_CONSTANT.
90 Handle<Object> values_[MAX_PROPERTIES];
91 // Setter for ACCESSOR_CONSTANT.
92 Handle<Object> setter_values_[MAX_PROPERTIES];
93 int number_of_properties_;
94
95 public:
96 explicit Expectations(Isolate* isolate)
97 : isolate_(isolate), number_of_properties_(0) {}
98
99 void Init(int index, PropertyType type, PropertyAttributes attributes,
100 Representation representation, Handle<Object> value) {
101 DCHECK(index < MAX_PROPERTIES);
102 types_[index] = type;
103 attributes_[index] = attributes;
104 representations_[index] = representation;
105 values_[index] = value;
106 }
107
108 Handle<HeapType> GetFieldType(int index) {
109 CHECK(index < MAX_PROPERTIES);
110 CHECK(types_[index] == DATA || types_[index] == ACCESSOR);
111 return Handle<HeapType>::cast(values_[index]);
112 }
113
114 void SetDataField(int index, PropertyAttributes attrs,
115 Representation representation, Handle<HeapType> value) {
116 Init(index, DATA, attrs, representation, value);
117 }
118
119 void SetDataField(int index, Representation representation,
120 Handle<HeapType> value) {
121 SetDataField(index, attributes_[index], representation, value);
122 }
123
124 void SetAccessorField(int index, PropertyAttributes attrs) {
125 Init(index, ACCESSOR, attrs, Representation::Tagged(),
126 HeapType::Any(isolate_));
127 }
128
129 void SetAccessorField(int index) {
130 SetAccessorField(index, attributes_[index]);
131 }
132
133 void SetDataConstant(int index, PropertyAttributes attrs,
134 Handle<JSFunction> value) {
135 Init(index, DATA_CONSTANT, attrs, Representation::HeapObject(), value);
136 }
137
138 void SetDataConstant(int index, Handle<JSFunction> value) {
139 SetDataConstant(index, attributes_[index], value);
140 }
141
142 void SetAccessorConstant(int index, PropertyAttributes attrs,
143 Handle<Object> getter, Handle<Object> setter) {
144 Init(index, ACCESSOR_CONSTANT, attrs, Representation::Tagged(), getter);
145 setter_values_[index] = setter;
146 }
147
148 void SetAccessorConstantComponent(int index, PropertyAttributes attrs,
149 AccessorComponent component,
150 Handle<Object> accessor) {
151 CHECK_EQ(ACCESSOR_CONSTANT, types_[index]);
152 CHECK(index < number_of_properties_);
153 if (component == ACCESSOR_GETTER) {
154 values_[index] = accessor;
155 } else {
156 setter_values_[index] = accessor;
157 }
158 }
159
160 void SetAccessorConstant(int index, PropertyAttributes attrs,
161 Handle<AccessorPair> pair) {
162 Handle<Object> getter = handle(pair->getter(), isolate_);
163 Handle<Object> setter = handle(pair->setter(), isolate_);
164 SetAccessorConstant(index, attrs, getter, setter);
165 }
166
167 void SetAccessorConstant(int index, Handle<Object> getter,
168 Handle<Object> setter) {
169 SetAccessorConstant(index, attributes_[index], getter, setter);
170 }
171
172 void SetAccessorConstant(int index, Handle<AccessorPair> pair) {
173 Handle<Object> getter = handle(pair->getter(), isolate_);
174 Handle<Object> setter = handle(pair->setter(), isolate_);
175 SetAccessorConstant(index, getter, setter);
176 }
177
178 void GeneralizeRepresentation(int index) {
179 CHECK(index < number_of_properties_);
180 representations_[index] = Representation::Tagged();
181 if (types_[index] == DATA || types_[index] == ACCESSOR) {
182 values_[index] = HeapType::Any(isolate_);
183 }
184 }
185
186
187 bool Check(DescriptorArray* descriptors, int descriptor) {
188 PropertyType type = types_[descriptor];
189 if (!EqualDetails(descriptors, descriptor, type, attributes_[descriptor],
190 representations_[descriptor])) {
191 return false;
192 }
193 Object* expected_value = *values_[descriptor];
194 Object* value = descriptors->GetValue(descriptor);
195 switch (type) {
196 case DATA:
197 case ACCESSOR:
198 return HeapType::cast(expected_value)->Equals(HeapType::cast(value));
199
200 case DATA_CONSTANT:
201 return value == expected_value;
202
203 case ACCESSOR_CONSTANT: {
204 if (value == expected_value) return true;
205 if (!value->IsAccessorPair()) return false;
206 AccessorPair* pair = AccessorPair::cast(value);
207 return pair->Equals(expected_value, *setter_values_[descriptor]);
208 }
209 }
210 UNREACHABLE();
211 return false;
212 }
213
214 bool Check(Map* map, int expected_nof) {
215 CHECK(number_of_properties_ <= MAX_PROPERTIES);
216 CHECK_EQ(expected_nof, map->NumberOfOwnDescriptors());
217 CHECK(!map->is_dictionary_map());
218
219 DescriptorArray* descriptors = map->instance_descriptors();
220 CHECK(expected_nof <= number_of_properties_);
221 for (int i = 0; i < expected_nof; i++) {
222 if (!Check(descriptors, i)) {
223 Check(descriptors, i);
224 return false;
225 }
226 }
227 return true;
228 }
229
230 bool Check(Map* map) { return Check(map, number_of_properties_); }
231
232
233 //
234 // Helper methods for initializing expectations and adding properties to
235 // given |map|.
236 //
237
238 Handle<Map> AddDataField(Handle<Map> map, PropertyAttributes attributes,
239 Representation representation,
240 Handle<HeapType> heap_type) {
241 CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
242 int property_index = number_of_properties_++;
243 SetDataField(property_index, attributes, representation, heap_type);
244
245 Handle<String> name = MakeName("prop", property_index);
246 return Map::CopyWithField(map, name, heap_type, attributes, representation,
247 INSERT_TRANSITION).ToHandleChecked();
248 }
249
250 Handle<Map> AddDataConstant(Handle<Map> map, PropertyAttributes attributes,
251 Handle<JSFunction> value) {
252 CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
253 int property_index = number_of_properties_++;
254 SetDataConstant(property_index, attributes, value);
255
256 Handle<String> name = MakeName("prop", property_index);
257 return Map::CopyWithConstant(map, name, value, attributes,
258 INSERT_TRANSITION).ToHandleChecked();
259 }
260
261 Handle<Map> FollowDataTransition(Handle<Map> map,
262 PropertyAttributes attributes,
263 Representation representation,
264 Handle<HeapType> heap_type) {
265 CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
266 int property_index = number_of_properties_++;
267 SetDataField(property_index, attributes, representation, heap_type);
268
269 Handle<String> name = MakeName("prop", property_index);
270 int t = map->SearchTransition(kData, *name, attributes);
271 CHECK_NE(TransitionArray::kNotFound, t);
272 return handle(map->GetTransition(t));
273 }
274
275 Handle<Map> AddAccessorConstant(Handle<Map> map,
276 PropertyAttributes attributes,
277 Handle<AccessorPair> pair) {
278 CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
279 int property_index = number_of_properties_++;
280 SetAccessorConstant(property_index, attributes, pair);
281
282 Handle<String> name = MakeName("prop", property_index);
283
284 AccessorConstantDescriptor new_desc(name, pair, attributes);
285 return Map::CopyInsertDescriptor(map, &new_desc, INSERT_TRANSITION);
286 }
287
288 Handle<Map> AddAccessorConstant(Handle<Map> map,
289 PropertyAttributes attributes,
290 Handle<Object> getter,
291 Handle<Object> setter) {
292 CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
293 int property_index = number_of_properties_++;
294 SetAccessorConstant(property_index, attributes, getter, setter);
295
296 Handle<String> name = MakeName("prop", property_index);
297
298 CHECK(!getter->IsNull() || !setter->IsNull());
299 Factory* factory = isolate_->factory();
300
301 if (!getter->IsNull()) {
302 Handle<AccessorPair> pair = factory->NewAccessorPair();
303 pair->SetComponents(*getter, *factory->null_value());
304 AccessorConstantDescriptor new_desc(name, pair, attributes);
305 map = Map::CopyInsertDescriptor(map, &new_desc, INSERT_TRANSITION);
306 }
307 if (!setter->IsNull()) {
308 Handle<AccessorPair> pair = factory->NewAccessorPair();
309 pair->SetComponents(*getter, *setter);
310 AccessorConstantDescriptor new_desc(name, pair, attributes);
311 map = Map::CopyInsertDescriptor(map, &new_desc, INSERT_TRANSITION);
312 }
313 return map;
314 }
315 };
316
317
318 ////////////////////////////////////////////////////////////////////////////////
319 // A set of tests for basic transitioning mechanics.
320 //
321
322 TEST(TransitionToDataFieldProperty) {
323 CcTest::InitializeVM();
324 v8::HandleScope scope(CcTest::isolate());
325 Isolate* isolate = CcTest::i_isolate();
326 Factory* factory = isolate->factory();
327 Handle<HeapType> any_type = HeapType::Any(isolate);
328
329 const int kPropCount = 50;
330 Expectations expectations(isolate);
331
332 // Create a map, add required properties to it and initialize expectations.
333 Handle<Map> initial_map = Map::Create(isolate, 0);
334 Handle<Map> map = initial_map;
335 Handle<Map> intermediate_maps[kPropCount];
336 Representation representations[] = {
337 Representation::Smi(), Representation::Double(),
338 Representation::HeapObject(), Representation::Tagged()};
339 // values[i] must fit into representations[i].
340 Handle<Object> values[] = {
341 handle(Smi::FromInt(0), isolate), factory->NewHeapNumber(0),
342 factory->NewJSObjectFromMap(Map::Create(isolate, 0)),
343 factory->undefined_value()};
344 const int kValuesCount = arraysize(values);
345 CHECK_EQ(kValuesCount, arraysize(representations));
346
347 for (int i = 0; i < kPropCount; i++) {
348 PropertyAttributes attributes = static_cast<PropertyAttributes>(i % 8);
349 Representation r = representations[i % kValuesCount];
350 CHECK(values[i % kValuesCount]->FitsRepresentation(r));
351
352 map = expectations.AddDataField(map, attributes, r, any_type);
353 intermediate_maps[i] = map;
354 }
355 CHECK(!map->is_deprecated());
356 CHECK(map->is_stable());
357 CHECK(expectations.Check(*map));
358 for (int i = 0; i < kPropCount; i++) {
359 CHECK(expectations.Check(*intermediate_maps[i], i + 1));
360 }
361
362 // Try to follow same transitions from the |initial_map|.
363 Handle<Map> map2 = initial_map;
364 for (int i = 0; i < kPropCount; i++) {
365 PropertyAttributes attributes = static_cast<PropertyAttributes>(i % 8);
366 Handle<String> name = MakeName("prop", i);
367 map2 = Map::TransitionToDataProperty(
368 map2, name, values[i % kValuesCount], attributes,
369 Object::CERTAINLY_NOT_STORE_FROM_KEYED);
370
371 CHECK(!map2->is_deprecated());
372 CHECK(!map2->is_dictionary_map());
373 CHECK_EQ(*intermediate_maps[i], *map2);
374 CHECK(expectations.Check(*map2, i + 1));
375 }
376 }
377
378
379 TEST(TransitionToDataConstantProperty) {
380 CcTest::InitializeVM();
381 v8::HandleScope scope(CcTest::isolate());
382 Isolate* isolate = CcTest::i_isolate();
383 Factory* factory = isolate->factory();
384
385 const int kPropCount = 50;
386 Expectations expectations(isolate);
387
388 Handle<JSFunction> functions[kPropCount];
389 for (int i = 0; i < kPropCount; i++) {
390 functions[i] = factory->NewFunction(factory->empty_string());
391 }
392
393 // Create a map, add required properties to it and initialize expectations.
394 Handle<Map> initial_map = Map::Create(isolate, 0);
395 Handle<Map> map = initial_map;
396 Handle<Map> intermediate_maps[kPropCount];
397 for (int i = 0; i < kPropCount; i++) {
398 PropertyAttributes attributes = static_cast<PropertyAttributes>(i % 8);
399 map = expectations.AddDataConstant(map, attributes, functions[i]);
400 intermediate_maps[i] = map;
401 }
402 CHECK(!map->is_deprecated());
403 CHECK(map->is_stable());
404 CHECK(expectations.Check(*map));
405 for (int i = 0; i < kPropCount; i++) {
406 CHECK(expectations.Check(*intermediate_maps[i], i + 1));
407 }
408
409 // Try to follow same transitions from the |initial_map|.
410 Handle<Map> map2 = initial_map;
411 for (int i = 0; i < kPropCount; i++) {
412 PropertyAttributes attributes = static_cast<PropertyAttributes>(i % 8);
413 Handle<String> name = MakeName("prop", i);
414 map2 =
415 Map::TransitionToDataProperty(map2, name, functions[i], attributes,
416 Object::CERTAINLY_NOT_STORE_FROM_KEYED);
417
418 CHECK(!map2->is_deprecated());
419 CHECK(!map2->is_dictionary_map());
420 CHECK_EQ(*intermediate_maps[i], *map2);
421 CHECK(expectations.Check(*map2, i + 1));
422 }
423 }
424
425
426 TEST(TransitionToAccessorConstantProperty) {
427 CcTest::InitializeVM();
428 v8::HandleScope scope(CcTest::isolate());
429 Isolate* isolate = CcTest::i_isolate();
430
431 const int kPropCount = 50;
432 Expectations expectations(isolate);
433
434 Handle<AccessorPair> accessor_pairs[kPropCount];
435 for (int i = 0; i < kPropCount; i++) {
436 // Getter only accessors.
437 accessor_pairs[i] = CreateAccessorPair(true, false);
438 }
439
440 // Create a map, add required properties to it and initialize expectations.
441 Handle<Map> initial_map = Map::Create(isolate, 0);
442 Handle<Map> map = initial_map;
443 Handle<Map> intermediate_maps[kPropCount];
444 for (int i = 0; i < kPropCount; i++) {
445 PropertyAttributes attributes = static_cast<PropertyAttributes>(i % 8);
446 map = expectations.AddAccessorConstant(
447 map, attributes, handle(accessor_pairs[i]->getter(), isolate),
448 handle(accessor_pairs[i]->setter(), isolate));
449 intermediate_maps[i] = map;
450 }
451 CHECK(!map->is_deprecated());
452 CHECK(map->is_stable());
453 CHECK(expectations.Check(*map));
454 for (int i = 0; i < kPropCount; i++) {
455 CHECK(expectations.Check(*intermediate_maps[i], i + 1));
456 }
457
458 // Try to follow same transitions from the |initial_map|.
459 Handle<Map> map2 = initial_map;
460 for (int i = 0; i < kPropCount; i++) {
461 PropertyAttributes attributes = static_cast<PropertyAttributes>(i % 8);
462 Handle<String> name = MakeName("prop", i);
463 Handle<Object> getter(accessor_pairs[i]->getter(), isolate);
464 Handle<Object> setter(accessor_pairs[i]->setter(), isolate);
465
466 map2 = Map::TransitionToAccessorProperty(map2, name, ACCESSOR_GETTER,
467 getter, attributes);
468 CHECK(!map2->is_deprecated());
469 CHECK(!map2->is_dictionary_map());
470
471 map2 = Map::TransitionToAccessorProperty(map2, name, ACCESSOR_SETTER,
472 setter, attributes);
473 CHECK(!map2->is_deprecated());
474 CHECK(!map2->is_dictionary_map());
475 CHECK_EQ(*intermediate_maps[i], *map2);
476 CHECK(expectations.Check(*map2, i + 1));
477 }
478 }
479
480
481 ////////////////////////////////////////////////////////////////////////////////
482 // A set of tests for representation generalization case.
483 //
484
485 TEST(GeneralizeRepresentationSmiToDouble) {
486 CcTest::InitializeVM();
487 v8::HandleScope scope(CcTest::isolate());
488 Isolate* isolate = CcTest::i_isolate();
489 Handle<HeapType> any_type = HeapType::Any(isolate);
490
491 const int kPropCount = 5;
492 Expectations expectations(isolate);
493
494 // Create a map, add required properties to it and initialize expectations.
495 Handle<Map> initial_map = Map::Create(isolate, 0);
496 Handle<Map> map = initial_map;
497 for (int i = 0; i < kPropCount; i++) {
498 map = expectations.AddDataField(map, NONE, Representation::Smi(), any_type);
499 }
500 CHECK(!map->is_deprecated());
501 CHECK(map->is_stable());
502 CHECK(expectations.Check(*map));
503
504 // Create new maps by generalizing representation of propX field to double.
505 Handle<Map> maps[kPropCount];
506 for (int i = 0; i < kPropCount; i++) {
507 Handle<Map> new_map = Map::ReconfigureProperty(
508 map, i, kData, NONE, Representation::Double(), any_type, FORCE_FIELD);
509 maps[i] = new_map;
510
511 expectations.SetDataField(i, Representation::Double(), any_type);
512
513 CHECK(map->is_deprecated());
514 CHECK_NE(*map, *new_map);
515 CHECK(i == 0 || maps[i - 1]->is_deprecated());
516
517 CHECK(!new_map->is_deprecated());
518 CHECK(!new_map->is_dictionary_map());
519 CHECK(expectations.Check(*new_map));
520 }
521
522 Handle<Map> active_map = maps[kPropCount - 1];
523 CHECK(!active_map->is_deprecated());
524
525 // Update all deprecated maps and check that they are now the same.
526 CHECK_EQ(*active_map, *Map::Update(map));
527 for (int i = 0; i < kPropCount; i++) {
528 CHECK_EQ(*active_map, *Map::Update(maps[i]));
529 }
530 }
531
532
533 TEST(GeneralizeRepresentationSmiToTagged) {
534 CcTest::InitializeVM();
535 v8::HandleScope scope(CcTest::isolate());
536 Isolate* isolate = CcTest::i_isolate();
537 Handle<HeapType> any_type = HeapType::Any(isolate);
538 Handle<HeapType> value_type =
539 HeapType::Class(Map::Create(isolate, 0), isolate);
540
541 const int kPropCount = 5;
542 Expectations expectations(isolate);
543
544 // Create a map, add required properties to it and initialize expectations.
545 Handle<Map> initial_map = Map::Create(isolate, 0);
546 Handle<Map> map = initial_map;
547 for (int i = 0; i < kPropCount; i++) {
548 map = expectations.AddDataField(map, NONE, Representation::Smi(), any_type);
549 }
550 CHECK(!map->is_deprecated());
551 CHECK(map->is_stable());
552 CHECK(expectations.Check(*map));
553
554 // Create new maps by generalizing representation of propX field to heap
555 // object.
556 Handle<Map> maps[kPropCount];
557 for (int i = 0; i < kPropCount; i++) {
558 Handle<Map> new_map = Map::ReconfigureProperty(map, i, kData, NONE,
559 Representation::HeapObject(),
560 value_type, FORCE_FIELD);
561 maps[i] = new_map;
562
563 expectations.SetDataField(i, Representation::Tagged(), any_type);
564
565 CHECK(map->is_deprecated());
566 CHECK_NE(*map, *new_map);
567 CHECK(i == 0 || maps[i - 1]->is_deprecated());
568
569 CHECK(!new_map->is_deprecated());
570 CHECK(!new_map->is_dictionary_map());
571 CHECK(expectations.Check(*new_map));
572 }
573
574 Handle<Map> active_map = maps[kPropCount - 1];
575 CHECK(!active_map->is_deprecated());
576
577 // Update all deprecated maps and check that they are now the same.
578 CHECK_EQ(*active_map, *Map::Update(map));
579 for (int i = 0; i < kPropCount; i++) {
580 CHECK_EQ(*active_map, *Map::Update(maps[i]));
581 }
582 }
583
584
585 TEST(GeneralizeRepresentationDoubleToTagged) {
586 CcTest::InitializeVM();
587 v8::HandleScope scope(CcTest::isolate());
588 Isolate* isolate = CcTest::i_isolate();
589 Handle<HeapType> any_type = HeapType::Any(isolate);
590 Handle<HeapType> value_type =
591 HeapType::Class(Map::Create(isolate, 0), isolate);
592
593 const int kPropCount = 5;
594 Expectations expectations(isolate);
595
596 // Create a map, add required properties to it and initialize expectations.
597 Handle<Map> initial_map = Map::Create(isolate, 0);
598 Handle<Map> map = initial_map;
599 for (int i = 0; i < kPropCount; i++) {
600 map = expectations.AddDataField(map, NONE, Representation::Double(),
601 any_type);
602 }
603 CHECK(!map->is_deprecated());
604 CHECK(map->is_stable());
605 CHECK(expectations.Check(*map));
606
607 // Create new maps by generalizing representation of propX field to heap
608 // object.
609 Handle<Map> maps[kPropCount];
610 for (int i = 0; i < kPropCount; i++) {
611 Handle<Map> new_map = Map::ReconfigureProperty(map, i, kData, NONE,
612 Representation::HeapObject(),
613 value_type, FORCE_FIELD);
614 maps[i] = new_map;
615
616 expectations.SetDataField(i, Representation::Tagged(), any_type);
617
618 CHECK(map->is_deprecated());
619 CHECK_NE(*map, *new_map);
620 CHECK(i == 0 || maps[i - 1]->is_deprecated());
621
622 CHECK(!new_map->is_deprecated());
623 CHECK(!new_map->is_dictionary_map());
624 CHECK(expectations.Check(*new_map));
625 }
626
627 Handle<Map> active_map = maps[kPropCount - 1];
628 CHECK(!active_map->is_deprecated());
629
630 // Update all deprecated maps and check that they are now the same.
631 CHECK_EQ(*active_map, *Map::Update(map));
632 for (int i = 0; i < kPropCount; i++) {
633 CHECK_EQ(*active_map, *Map::Update(maps[i]));
634 }
635 }
636
637
638 TEST(GeneralizeRepresentationHeapObjectToTagged) {
639 CcTest::InitializeVM();
640 v8::HandleScope scope(CcTest::isolate());
641 Isolate* isolate = CcTest::i_isolate();
642 Handle<HeapType> any_type = HeapType::Any(isolate);
643 Handle<HeapType> value_type =
644 HeapType::Class(Map::Create(isolate, 0), isolate);
645
646 const int kPropCount = 5;
647 Expectations expectations(isolate);
648
649 // Create a map, add required properties to it and initialize expectations.
650 Handle<Map> initial_map = Map::Create(isolate, 0);
651 Handle<Map> map = initial_map;
652 for (int i = 0; i < kPropCount; i++) {
653 map = expectations.AddDataField(map, NONE, Representation::HeapObject(),
654 value_type);
655 }
656 CHECK(!map->is_deprecated());
657 CHECK(map->is_stable());
658 CHECK(expectations.Check(*map));
659
660 // Create new maps by generalizing representation of propX field to smi.
661 Handle<Map> maps[kPropCount];
662 for (int i = 0; i < kPropCount; i++) {
663 Handle<Map> new_map = Map::ReconfigureProperty(
664 map, i, kData, NONE, Representation::Smi(), any_type, FORCE_FIELD);
665 maps[i] = new_map;
666
667 expectations.SetDataField(i, Representation::Tagged(), any_type);
668
669 CHECK(map->is_deprecated());
670 CHECK_NE(*map, *new_map);
671 CHECK(i == 0 || maps[i - 1]->is_deprecated());
672
673 CHECK(!new_map->is_deprecated());
674 CHECK(!new_map->is_dictionary_map());
675 CHECK(expectations.Check(*new_map));
676 }
677
678 Handle<Map> active_map = maps[kPropCount - 1];
679 CHECK(!active_map->is_deprecated());
680
681 // Update all deprecated maps and check that they are now the same.
682 CHECK_EQ(*active_map, *Map::Update(map));
683 for (int i = 0; i < kPropCount; i++) {
684 CHECK_EQ(*active_map, *Map::Update(maps[i]));
685 }
686 }
Toon Verwaest 2015/01/30 13:02:53 Seems like you could merge the few tests above int
687
688
689 TEST(GeneralizeRepresentationHeapObjectToHeapObject) {
690 CcTest::InitializeVM();
691 v8::HandleScope scope(CcTest::isolate());
692 Isolate* isolate = CcTest::i_isolate();
693 Handle<HeapType> value_type =
694 HeapType::Class(Map::Create(isolate, 0), isolate);
695
696 const int kPropCount = 5;
697 Expectations expectations(isolate);
698
699 // Create a map, add required properties to it and initialize expectations.
700 Handle<Map> initial_map = Map::Create(isolate, 0);
701 Handle<Map> map = initial_map;
702 for (int i = 0; i < kPropCount; i++) {
703 map = expectations.AddDataField(map, NONE, Representation::HeapObject(),
704 value_type);
705 }
706 CHECK(!map->is_deprecated());
707 CHECK(map->is_stable());
708 CHECK(expectations.Check(*map));
709
710 // Create some value types.
711 static const int kAdditionalValueTypesCount = 4;
712 Handle<HeapType> value_types[kAdditionalValueTypesCount];
713 for (int i = 0; i < kAdditionalValueTypesCount; i++) {
714 Handle<Map> value_map = Map::Create(isolate, 0);
715 CHECK(value_map->is_stable());
716 value_types[i] = HeapType::Class(value_map, isolate);
717 }
718
719 Zone zone;
720
721 // Create new maps by generalizing representation of propX field to various
722 // HeapObject types with stable maps.
723 for (int val_index = 0; val_index < kAdditionalValueTypesCount; val_index++) {
724 Handle<Map> maps[kPropCount];
725 for (int i = 0; i < kPropCount; i++) {
726 Handle<Map> field_owner(map->FindFieldOwner(i), isolate);
727 CompilationInfo info(isolate, &zone);
728 CHECK(!info.HasAbortedDueToDependencyChange());
729
730 Map::AddDependentCompilationInfo(field_owner,
731 DependentCode::kFieldTypeGroup, &info);
732
733 Handle<Map> new_map = Map::ReconfigureProperty(
734 map, i, kData, NONE, Representation::HeapObject(),
735 value_types[val_index], FORCE_FIELD);
736 maps[i] = new_map;
737
738 expectations.SetDataField(
739 i, Representation::HeapObject(),
740 HeapType::Union(value_types[val_index], expectations.GetFieldType(i),
741 isolate));
742
743 // Maps should stay the same but field type modification should trigger
744 // respective dependents to deoptimize.
745 CHECK_EQ(*map, *new_map);
746 CHECK(info.HasAbortedDueToDependencyChange());
747 info.RollbackDependencies(); // Properly cleanup compilation info.
748
749 CHECK(!new_map->is_deprecated());
750 CHECK(!new_map->is_dictionary_map());
751 CHECK(expectations.Check(*new_map));
752 }
753
754 Handle<Map> active_map = maps[kPropCount - 1];
755 CHECK(!active_map->is_deprecated());
756
757 // Update all deprecated maps and check that they are now the same.
758 CHECK_EQ(*active_map, *Map::Update(map));
759 for (int i = 0; i < kPropCount; i++) {
760 CHECK_EQ(*active_map, *Map::Update(maps[i]));
761 }
762 }
763 }
764
765
766 TEST(GeneralizeRepresentationNoneToSmi) {
767 CcTest::InitializeVM();
768 v8::HandleScope scope(CcTest::isolate());
769 Isolate* isolate = CcTest::i_isolate();
770 Handle<HeapType> none_type = HeapType::None(isolate);
771 Handle<HeapType> any_type = HeapType::Any(isolate);
772
773 const int kPropCount = 5;
774 Expectations expectations(isolate);
775
776 // Create a map, add required properties to it and initialize expectations.
777 Handle<Map> initial_map = Map::Create(isolate, 0);
778 Handle<Map> map = initial_map;
779 for (int i = 0; i < kPropCount; i++) {
780 map =
781 expectations.AddDataField(map, NONE, Representation::None(), none_type);
782 }
783 CHECK(!map->is_deprecated());
784 CHECK(map->is_stable());
785 CHECK(expectations.Check(*map));
786
787 // Create new maps by generalizing representation of propX field to smi.
788 for (int i = 0; i < kPropCount; i++) {
789 Handle<Map> new_map = Map::ReconfigureProperty(
790 map, i, kData, NONE, Representation::Smi(), any_type, FORCE_FIELD);
791
792 expectations.SetDataField(i, Representation::Smi(), any_type);
793
794 CHECK_EQ(*map, *new_map); // None -> Smi change is trivial.
795 CHECK(!new_map->is_deprecated());
796 CHECK(!new_map->is_dictionary_map());
797 CHECK(expectations.Check(*new_map));
798 }
799
800 CHECK_EQ(*map, *Map::Update(map));
801 }
802
803
804 TEST(GeneralizeRepresentationNoneToDouble) {
805 CcTest::InitializeVM();
806 v8::HandleScope scope(CcTest::isolate());
807 Isolate* isolate = CcTest::i_isolate();
808 Handle<HeapType> none_type = HeapType::None(isolate);
809 Handle<HeapType> any_type = HeapType::Any(isolate);
810
811 const int kPropCount = 5;
812 Expectations expectations(isolate);
813
814 // Create a map, add required properties to it and initialize expectations.
815 Handle<Map> initial_map = Map::Create(isolate, 0);
816 Handle<Map> map = initial_map;
817 for (int i = 0; i < kPropCount; i++) {
818 map =
819 expectations.AddDataField(map, NONE, Representation::None(), none_type);
820 }
821 CHECK(!map->is_deprecated());
822 CHECK(map->is_stable());
823 CHECK(expectations.Check(*map));
824
825 // Create new maps by generalizing representation of propX field to heap
826 // object.
827 Handle<Map> maps[kPropCount];
828 for (int i = 0; i < kPropCount; i++) {
829 Handle<Map> new_map = Map::ReconfigureProperty(
830 map, i, kData, NONE, Representation::Double(), any_type, FORCE_FIELD);
831 maps[i] = new_map;
832
833 expectations.SetDataField(i, Representation::Double(), any_type);
834
835 CHECK(map->is_deprecated()); // None -> Double change is NOT trivial.
836 CHECK_NE(*map, *new_map);
837 CHECK(i == 0 || maps[i - 1]->is_deprecated());
838
839 CHECK(!new_map->is_deprecated());
840 CHECK(!new_map->is_dictionary_map());
841 CHECK(expectations.Check(*new_map));
842 }
843
844 Handle<Map> active_map = maps[kPropCount - 1];
845 CHECK(!active_map->is_deprecated());
846
847 // Update all deprecated maps and check that they are now the same.
848 CHECK_EQ(*active_map, *Map::Update(map));
849 for (int i = 0; i < kPropCount; i++) {
850 CHECK_EQ(*active_map, *Map::Update(maps[i]));
851 }
852 }
853
854
855 TEST(GeneralizeRepresentationNoneToHeapObject) {
856 CcTest::InitializeVM();
857 v8::HandleScope scope(CcTest::isolate());
858 Isolate* isolate = CcTest::i_isolate();
859 Handle<HeapType> none_type = HeapType::None(isolate);
860 Handle<HeapType> value_type =
861 HeapType::Class(Map::Create(isolate, 0), isolate);
862
863 const int kPropCount = 5;
864 Expectations expectations(isolate);
865
866 // Create a map, add required properties to it and initialize expectations.
867 Handle<Map> initial_map = Map::Create(isolate, 0);
868 Handle<Map> map = initial_map;
869 for (int i = 0; i < kPropCount; i++) {
870 map =
871 expectations.AddDataField(map, NONE, Representation::None(), none_type);
872 }
873 CHECK(!map->is_deprecated());
874 CHECK(map->is_stable());
875 CHECK(expectations.Check(*map));
876
877 // Create new maps by generalizing representation of propX field to heap
878 // object.
879 for (int i = 0; i < kPropCount; i++) {
880 Handle<Map> new_map = Map::ReconfigureProperty(map, i, kData, NONE,
881 Representation::HeapObject(),
882 value_type, FORCE_FIELD);
883
884 expectations.SetDataField(i, Representation::HeapObject(), value_type);
885
886 CHECK_EQ(*map, *new_map); // None -> HeapObject change is trivial.
887 CHECK(!new_map->is_deprecated());
888 CHECK(!new_map->is_dictionary_map());
889 CHECK(expectations.Check(*new_map));
890 }
891
892 CHECK_EQ(*map, *Map::Update(map));
893 }
894
895
896 TEST(GeneralizeRepresentationNoneToTagged) {
897 CcTest::InitializeVM();
898 v8::HandleScope scope(CcTest::isolate());
899 Isolate* isolate = CcTest::i_isolate();
900 Handle<HeapType> none_type = HeapType::None(isolate);
901 Handle<HeapType> any_type = HeapType::Any(isolate);
902
903 const int kPropCount = 5;
904 Expectations expectations(isolate);
905
906 // Create a map, add required properties to it and initialize expectations.
907 Handle<Map> initial_map = Map::Create(isolate, 0);
908 Handle<Map> map = initial_map;
909 for (int i = 0; i < kPropCount; i++) {
910 map =
911 expectations.AddDataField(map, NONE, Representation::None(), none_type);
912 }
913 CHECK(!map->is_deprecated());
914 CHECK(map->is_stable());
915 CHECK(expectations.Check(*map));
916
917 // Create new maps by generalizing representation of propX field to heap
918 // object.
919 for (int i = 0; i < kPropCount; i++) {
920 Handle<Map> new_map = Map::ReconfigureProperty(
921 map, i, kData, NONE, Representation::Tagged(), any_type, FORCE_FIELD);
922
923 expectations.SetDataField(i, Representation::Tagged(), any_type);
924
925 CHECK_EQ(*map, *new_map); // None -> Tagged change is trivial.
926 CHECK(!new_map->is_deprecated());
927 CHECK(!new_map->is_dictionary_map());
928 CHECK(expectations.Check(*new_map));
929 }
930
931 CHECK_EQ(*map, *Map::Update(map));
932 }
933
934
935 ////////////////////////////////////////////////////////////////////////////////
936 // A set of tests for representation generalization case with kAccessor
937 // properties.
938 //
939
940 TEST(GeneralizeRepresentationWithAccessorProperties) {
941 CcTest::InitializeVM();
942 v8::HandleScope scope(CcTest::isolate());
943 Isolate* isolate = CcTest::i_isolate();
944 Handle<HeapType> any_type = HeapType::Any(isolate);
945 Handle<AccessorPair> pair = CreateAccessorPair(true, true);
946
947 const int kPropCount = 5;
948 const int kAccessorProp = kPropCount / 2;
949 Expectations expectations(isolate);
950
951 // Create a map, add required properties to it and initialize expectations.
952 Handle<Map> initial_map = Map::Create(isolate, 0);
953 Handle<Map> map = initial_map;
954 for (int i = 0; i < kPropCount; i++) {
955 if (i == kAccessorProp) {
956 map = expectations.AddAccessorConstant(map, NONE, pair);
957 } else {
958 map =
959 expectations.AddDataField(map, NONE, Representation::Smi(), any_type);
960 }
961 }
962 CHECK(!map->is_deprecated());
963 CHECK(map->is_stable());
964 CHECK(expectations.Check(*map));
965
966 // Create new maps by generalizing representation of propX field to double.
967 Handle<Map> maps[kPropCount];
968 for (int i = 0; i < kPropCount; i++) {
969 if (i == kAccessorProp) {
970 // Skip accessor property reconfiguration.
971 maps[i] = maps[i - 1];
972 continue;
973 }
974 Handle<Map> new_map = Map::ReconfigureProperty(
975 map, i, kData, NONE, Representation::Double(), any_type, FORCE_FIELD);
976 maps[i] = new_map;
977
978 expectations.SetDataField(i, Representation::Double(), any_type);
979
980 CHECK(map->is_deprecated());
981 CHECK_NE(*map, *new_map);
982 CHECK(i == 0 || maps[i - 1]->is_deprecated());
983
984 CHECK(!new_map->is_deprecated());
985 CHECK(!new_map->is_dictionary_map());
986 CHECK(expectations.Check(*new_map));
987 }
988
989 Handle<Map> active_map = maps[kPropCount - 1];
990 CHECK(!active_map->is_deprecated());
991
992 // Update all deprecated maps and check that they are now the same.
993 CHECK_EQ(*active_map, *Map::Update(map));
994 for (int i = 0; i < kPropCount; i++) {
995 CHECK_EQ(*active_map, *Map::Update(maps[i]));
996 }
997 }
998
999
1000 ////////////////////////////////////////////////////////////////////////////////
1001 // A set of tests for property location change case.
1002 //
1003
1004 TEST(ReconfigureDataConstantToDataField) {
1005 CcTest::InitializeVM();
1006 v8::HandleScope scope(CcTest::isolate());
1007 Isolate* isolate = CcTest::i_isolate();
1008 Factory* factory = isolate->factory();
1009 Handle<HeapType> any_type = HeapType::Any(isolate);
1010 Handle<JSFunction> js_func = factory->NewFunction(factory->empty_string());
1011
1012 const int kPropCount = 5;
1013 Expectations expectations(isolate);
1014
1015 // Create a map, add required properties to it and initialize expectations.
1016 Handle<Map> initial_map = Map::Create(isolate, 0);
1017 Handle<Map> map = initial_map;
1018
1019 for (int i = 0; i < kPropCount; i++) {
1020 map = expectations.AddDataConstant(map, NONE, js_func);
1021 }
1022 CHECK(!map->is_deprecated());
1023 CHECK(map->is_stable());
1024 CHECK(expectations.Check(*map));
1025
1026 // Create new maps by forcing propX to become a field.
1027 Handle<Map> maps[kPropCount];
1028 for (int i = 0; i < kPropCount; i++) {
1029 Handle<Map> new_map = Map::ReconfigureProperty(map, i, kData, NONE,
1030 Representation::HeapObject(),
1031 any_type, FORCE_FIELD);
1032 maps[i] = new_map;
1033
1034 expectations.SetDataField(i, Representation::HeapObject(), any_type);
1035
1036 CHECK(map->is_deprecated());
1037 CHECK_NE(*map, *new_map);
1038 CHECK(i == 0 || maps[i - 1]->is_deprecated());
1039
1040 CHECK(!new_map->is_deprecated());
1041 CHECK(!new_map->is_dictionary_map());
1042 CHECK(expectations.Check(*new_map));
1043 }
1044
1045 Handle<Map> active_map = maps[kPropCount - 1];
1046 CHECK(!active_map->is_deprecated());
1047
1048 // Update all deprecated maps and check that they are now the same.
1049 CHECK_EQ(*active_map, *Map::Update(map));
1050 for (int i = 0; i < kPropCount; i++) {
1051 CHECK_EQ(*active_map, *Map::Update(maps[i]));
1052 }
1053 }
1054
1055
1056 TEST(ReconfigureAccessorConstantToAccessorField) {
1057 CcTest::InitializeVM();
1058 v8::HandleScope scope(CcTest::isolate());
1059 Isolate* isolate = CcTest::i_isolate();
1060 Factory* factory = isolate->factory();
1061 Handle<JSFunction> getter = factory->NewFunction(factory->empty_string());
1062 Handle<JSFunction> setter = factory->NewFunction(factory->empty_string());
1063
1064 const int kPropCount = 5;
1065 Expectations expectations(isolate);
1066
1067 Handle<AccessorPair> accessor_pairs[kPropCount];
1068 for (int i = 0; i < kPropCount; i++) {
1069 // Getter only accessors.
1070 accessor_pairs[i] = CreateAccessorPair(true, false);
1071 }
1072
1073 // Create a map, add required properties to it and initialize expectations.
1074 Handle<Map> initial_map = Map::Create(isolate, 0);
1075 Handle<Map> map = initial_map;
1076 Handle<Map> intermediate_maps[kPropCount];
1077 for (int i = 0; i < kPropCount; i++) {
1078 map = expectations.AddAccessorConstant(
1079 map, NONE, handle(accessor_pairs[i]->getter(), isolate),
1080 handle(accessor_pairs[i]->setter(), isolate));
1081 intermediate_maps[i] = map;
1082 }
1083 CHECK(!map->is_deprecated());
1084 CHECK(map->is_stable());
1085 CHECK(expectations.Check(*map));
1086 for (int i = 0; i < kPropCount; i++) {
1087 CHECK(expectations.Check(*intermediate_maps[i], i + 1));
1088 }
1089
1090 // Try to follow same transitions from the |initial_map|.
1091 Handle<Map> map2 = initial_map;
1092 for (int i = 0; i < kPropCount; i++) {
1093 Handle<String> name = MakeName("prop", i);
1094 map2 = Map::TransitionToAccessorProperty(map2, name, ACCESSOR_GETTER,
1095 getter, NONE);
1096 if (IS_ACCESSOR_FIELD_SUPPORTED) {
1097 CHECK(!map2->is_dictionary_map());
1098 } else {
1099 CHECK(map2->is_dictionary_map());
1100 }
1101
1102 map2 = Map::TransitionToAccessorProperty(map2, name, ACCESSOR_SETTER,
1103 setter, NONE);
1104 if (IS_ACCESSOR_FIELD_SUPPORTED) {
1105 CHECK(!map2->is_dictionary_map());
1106 CHECK(expectations.Check(*map2, i + 1));
1107 } else {
1108 CHECK(map2->is_dictionary_map());
1109 }
1110 }
1111
1112 if (!IS_ACCESSOR_FIELD_SUPPORTED) {
1113 CHECK(map2->is_dictionary_map());
1114 }
1115 }
1116
1117
1118 ////////////////////////////////////////////////////////////////////////////////
1119 // A set of tests for attribute reconfiguration case.
1120 //
1121
1122 TEST(ReconfigureDataFieldAttribute_GeneralizeRepresentationSmiToDouble) {
Toon Verwaest 2015/01/30 13:02:53 Same here?
1123 CcTest::InitializeVM();
1124 v8::HandleScope scope(CcTest::isolate());
1125 Isolate* isolate = CcTest::i_isolate();
1126 Handle<HeapType> any_type = HeapType::Any(isolate);
1127
1128 const int kPropCount = 5;
1129 Expectations expectations(isolate);
1130
1131 // Create a map, add required properties to it and initialize expectations.
1132 Handle<Map> initial_map = Map::Create(isolate, 0);
1133 Handle<Map> map = initial_map;
1134 for (int i = 0; i < kPropCount; i++) {
1135 map = expectations.AddDataField(map, NONE, Representation::Smi(), any_type);
1136 }
1137 CHECK(!map->is_deprecated());
1138 CHECK(map->is_stable());
1139 CHECK(expectations.Check(*map));
1140
1141
1142 // Create another branch in transition tree (property at index |kSplitProp|
1143 // has different attributes), initialize expectations.
1144 const int kSplitProp = kPropCount / 2;
1145 Expectations expectations2(isolate);
1146
1147 Handle<Map> map2 = initial_map;
1148 for (int i = 0; i < kSplitProp; i++) {
1149 map2 = expectations2.FollowDataTransition(map2, NONE, Representation::Smi(),
1150 any_type);
1151 }
1152 map2 = expectations2.AddDataField(map2, READ_ONLY, Representation::Double(),
1153 any_type);
1154
1155 for (int i = kSplitProp + 1; i < kPropCount; i++) {
1156 map2 = expectations2.AddDataField(map2, NONE, Representation::Double(),
1157 any_type);
1158 }
1159 CHECK(!map2->is_deprecated());
1160 CHECK(map2->is_stable());
1161 CHECK(expectations2.Check(*map2));
1162
1163
1164 // Reconfigure attributes of property |kSplitProp| of |map2| to NONE, which
1165 // should generalize representations in |map1|.
1166 Handle<Map> new_map =
1167 Map::ReconfigureExistingProperty(map2, kSplitProp, kData, NONE);
1168
1169 // |map2| should be left unchanged.
1170 CHECK(!map2->is_deprecated());
1171 CHECK_NE(*map2, *new_map);
1172 CHECK(expectations2.Check(*map2));
1173
1174 // |map| should be deprecated and |new_map| should match new expectations.
1175 for (int i = kSplitProp; i < kPropCount; i++) {
1176 expectations.SetDataField(i, Representation::Double(), any_type);
1177 }
1178 CHECK(map->is_deprecated());
1179 CHECK_NE(*map, *new_map);
1180
1181 CHECK(!new_map->is_deprecated());
1182 CHECK(!new_map->is_dictionary_map());
1183 CHECK(expectations.Check(*new_map));
1184
1185 // Update deprecated |map|, it should become |new_map|.
1186 CHECK_EQ(*new_map, *Map::Update(map));
1187 }
1188
1189
1190 TEST(ReconfigureDataFieldAttribute_GeneralizeRepresentationSmiToTagged) {
1191 CcTest::InitializeVM();
1192 v8::HandleScope scope(CcTest::isolate());
1193 Isolate* isolate = CcTest::i_isolate();
1194 Handle<HeapType> any_type = HeapType::Any(isolate);
1195 Handle<HeapType> value_type =
1196 HeapType::Class(Map::Create(isolate, 0), isolate);
1197
1198 const int kPropCount = 5;
1199 Expectations expectations(isolate);
1200
1201 // Create a map, add required properties to it and initialize expectations.
1202 Handle<Map> initial_map = Map::Create(isolate, 0);
1203 Handle<Map> map = initial_map;
1204 for (int i = 0; i < kPropCount; i++) {
1205 map = expectations.AddDataField(map, NONE, Representation::Smi(), any_type);
1206 }
1207 CHECK(!map->is_deprecated());
1208 CHECK(map->is_stable());
1209 CHECK(expectations.Check(*map));
1210
1211 // Create another branch in transition tree (property at index |kSplitProp|
1212 // has different attributes), initialize expectations.
1213 const int kSplitProp = kPropCount / 2;
1214 Expectations expectations2(isolate);
1215
1216 Handle<Map> map2 = initial_map;
1217 for (int i = 0; i < kSplitProp; i++) {
1218 map2 = expectations2.FollowDataTransition(map2, NONE, Representation::Smi(),
1219 any_type);
1220 }
1221 map2 = expectations2.AddDataField(map2, READ_ONLY,
1222 Representation::HeapObject(), value_type);
1223
1224 for (int i = kSplitProp + 1; i < kPropCount; i++) {
1225 map2 = expectations2.AddDataField(map2, NONE, Representation::HeapObject(),
1226 value_type);
1227 }
1228 CHECK(!map2->is_deprecated());
1229 CHECK(map2->is_stable());
1230 CHECK(expectations2.Check(*map2));
1231
1232
1233 // Reconfigure attributes of property |kSplitProp| of |map2| to NONE, which
1234 // should generalize representations in |map1|.
1235 Handle<Map> new_map =
1236 Map::ReconfigureExistingProperty(map2, kSplitProp, kData, NONE);
1237
1238 // |map2| should be left unchanged.
1239 CHECK(!map2->is_deprecated());
1240 CHECK_NE(*map2, *new_map);
1241 CHECK(expectations2.Check(*map2));
1242
1243 // |map| should be deprecated and |new_map| should match new expectations.
1244 for (int i = kSplitProp; i < kPropCount; i++) {
1245 expectations.SetDataField(i, Representation::Tagged(), any_type);
1246 }
1247 CHECK(map->is_deprecated());
1248 CHECK_NE(*map, *new_map);
1249
1250 CHECK(!new_map->is_deprecated());
1251 CHECK(!new_map->is_dictionary_map());
1252 CHECK(expectations.Check(*new_map));
1253
1254 // Update deprecated |map|, it should become |new_map|.
1255 CHECK_EQ(*new_map, *Map::Update(map));
1256 }
1257
1258
1259 TEST(ReconfigureDataFieldAttribute_GeneralizeRepresentationDoubleToTagged) {
1260 CcTest::InitializeVM();
1261 v8::HandleScope scope(CcTest::isolate());
1262 Isolate* isolate = CcTest::i_isolate();
1263 Handle<HeapType> any_type = HeapType::Any(isolate);
1264 Handle<HeapType> value_type =
1265 HeapType::Class(Map::Create(isolate, 0), isolate);
1266
1267 const int kPropCount = 5;
1268 Expectations expectations(isolate);
1269
1270 // Create a map, add required properties to it and initialize expectations.
1271 Handle<Map> initial_map = Map::Create(isolate, 0);
1272 Handle<Map> map = initial_map;
1273 for (int i = 0; i < kPropCount; i++) {
1274 map = expectations.AddDataField(map, NONE, Representation::Double(),
1275 any_type);
1276 }
1277 CHECK(!map->is_deprecated());
1278 CHECK(map->is_stable());
1279 CHECK(expectations.Check(*map));
1280
1281
1282 // Create another branch in transition tree (property at index |kSplitProp|
1283 // has different attributes), initialize expectations.
1284 const int kSplitProp = kPropCount / 2;
1285 Expectations expectations2(isolate);
1286
1287 Handle<Map> map2 = initial_map;
1288 for (int i = 0; i < kSplitProp; i++) {
1289 map2 = expectations2.FollowDataTransition(
1290 map2, NONE, Representation::Double(), any_type);
1291 }
1292 map2 = expectations2.AddDataField(map2, READ_ONLY,
1293 Representation::HeapObject(), value_type);
1294
1295 for (int i = kSplitProp + 1; i < kPropCount; i++) {
1296 map2 = expectations2.AddDataField(map2, NONE, Representation::HeapObject(),
1297 value_type);
1298 }
1299 CHECK(!map2->is_deprecated());
1300 CHECK(map2->is_stable());
1301 CHECK(expectations2.Check(*map2));
1302
1303
1304 // Reconfigure attributes of property |kSplitProp| of |map2| to NONE, which
1305 // should generalize representations in |map1|.
1306 Handle<Map> new_map =
1307 Map::ReconfigureExistingProperty(map2, kSplitProp, kData, NONE);
1308
1309 // |map2| should be left unchanged.
1310 CHECK(!map2->is_deprecated());
1311 CHECK_NE(*map2, *new_map);
1312 CHECK(expectations2.Check(*map2));
1313
1314 // |map| should be deprecated and |new_map| should match new expectations.
1315 for (int i = kSplitProp; i < kPropCount; i++) {
1316 expectations.SetDataField(i, Representation::Tagged(), any_type);
1317 }
1318 CHECK(map->is_deprecated());
1319 CHECK_NE(*map, *new_map);
1320
1321 CHECK(!new_map->is_deprecated());
1322 CHECK(!new_map->is_dictionary_map());
1323 CHECK(expectations.Check(*new_map));
1324
1325 // Update deprecated |map|, it should become |new_map|.
1326 CHECK_EQ(*new_map, *Map::Update(map));
1327 }
1328
1329
1330 TEST(ReconfigureDataFieldAttribute_GeneralizeRepresentationHeapObjectToTagged) {
1331 CcTest::InitializeVM();
1332 v8::HandleScope scope(CcTest::isolate());
1333 Isolate* isolate = CcTest::i_isolate();
1334 Handle<HeapType> any_type = HeapType::Any(isolate);
1335 Handle<HeapType> value_type =
1336 HeapType::Class(Map::Create(isolate, 0), isolate);
1337
1338 const int kPropCount = 5;
1339 Expectations expectations(isolate);
1340
1341 // Create a map, add required properties to it and initialize expectations.
1342 Handle<Map> initial_map = Map::Create(isolate, 0);
1343 Handle<Map> map = initial_map;
1344 for (int i = 0; i < kPropCount; i++) {
1345 map = expectations.AddDataField(map, NONE, Representation::HeapObject(),
1346 value_type);
1347 }
1348 CHECK(!map->is_deprecated());
1349 CHECK(map->is_stable());
1350 CHECK(expectations.Check(*map));
1351
1352
1353 // Create another branch in transition tree (property at index |kSplitProp|
1354 // has different attributes), initialize expectations.
1355 const int kSplitProp = kPropCount / 2;
1356 Expectations expectations2(isolate);
1357
1358 Handle<Map> map2 = initial_map;
1359 for (int i = 0; i < kSplitProp; i++) {
1360 map2 = expectations2.FollowDataTransition(
1361 map2, NONE, Representation::HeapObject(), value_type);
1362 }
1363 map2 = expectations2.AddDataField(map2, READ_ONLY, Representation::Smi(),
1364 any_type);
1365
1366 for (int i = kSplitProp + 1; i < kPropCount; i++) {
1367 map2 =
1368 expectations2.AddDataField(map2, NONE, Representation::Smi(), any_type);
1369 }
1370 CHECK(!map2->is_deprecated());
1371 CHECK(map2->is_stable());
1372 CHECK(expectations2.Check(*map2));
1373
1374
1375 // Reconfigure attributes of property |kSplitProp| of |map2| to NONE, which
1376 // should generalize representations in |map1|.
1377 Handle<Map> new_map =
1378 Map::ReconfigureExistingProperty(map2, kSplitProp, kData, NONE);
1379
1380 // |map2| should be left unchanged.
1381 CHECK(!map2->is_deprecated());
1382 CHECK_NE(*map2, *new_map);
1383 CHECK(expectations2.Check(*map2));
1384
1385 // |map| should be deprecated and |new_map| should match new expectations.
1386 for (int i = kSplitProp; i < kPropCount; i++) {
1387 expectations.SetDataField(i, Representation::Tagged(), any_type);
1388 }
1389 CHECK(map->is_deprecated());
1390 CHECK_NE(*map, *new_map);
1391
1392 CHECK(!new_map->is_deprecated());
1393 CHECK(!new_map->is_dictionary_map());
1394 CHECK(expectations.Check(*new_map));
1395
1396 // Update deprecated |map|, it should become |new_map|.
1397 CHECK_EQ(*new_map, *Map::Update(map));
1398 }
1399
1400
1401 TEST(ReconfigureDataFieldAttribute_SameDataConstantAfterTargetMap) {
1402 CcTest::InitializeVM();
1403 v8::HandleScope scope(CcTest::isolate());
1404 Isolate* isolate = CcTest::i_isolate();
1405 Factory* factory = isolate->factory();
1406 Handle<HeapType> any_type = HeapType::Any(isolate);
1407 Handle<JSFunction> js_func = factory->NewFunction(factory->empty_string());
1408 Handle<HeapType> value_type =
1409 HeapType::Class(Map::Create(isolate, 0), isolate);
1410
1411 const int kPropCount = 7;
1412 const int kConstantPropIndex = 5;
1413 Expectations expectations(isolate);
1414
1415 // Create a map, add required properties to it and initialize expectations.
1416 Handle<Map> initial_map = Map::Create(isolate, 0);
1417 Handle<Map> map = initial_map;
1418 for (int i = 0; i < kPropCount; i++) {
1419 if (i == kConstantPropIndex) {
1420 map = expectations.AddDataConstant(map, NONE, js_func);
1421
1422 } else {
1423 map =
1424 expectations.AddDataField(map, NONE, Representation::Smi(), any_type);
1425 }
1426 }
1427 CHECK(!map->is_deprecated());
1428 CHECK(map->is_stable());
1429 CHECK(expectations.Check(*map));
1430
1431 // Create another branch in transition tree (property at index |kSplitProp|
1432 // has different attributes), initialize expectations.
1433 const int kSplitProp = 2;
1434 Expectations expectations2(isolate);
1435
1436 Handle<Map> map2 = initial_map;
1437 for (int i = 0; i < kSplitProp; i++) {
1438 map2 = expectations2.FollowDataTransition(map2, NONE, Representation::Smi(),
1439 any_type);
1440 }
1441 map2 = expectations2.AddDataField(map2, READ_ONLY,
1442 Representation::HeapObject(), value_type);
1443
1444 for (int i = kSplitProp + 1; i < kPropCount; i++) {
1445 if (i == kConstantPropIndex) {
1446 map2 = expectations2.AddDataConstant(map2, NONE, js_func);
1447
1448 } else {
1449 map2 = expectations2.AddDataField(map2, NONE, Representation::Smi(),
1450 any_type);
1451 }
1452 }
1453 CHECK(!map2->is_deprecated());
1454 CHECK(map2->is_stable());
1455 CHECK(expectations2.Check(*map2));
1456
1457
1458 // Reconfigure attributes of property |kSplitProp| of |map2| to NONE, which
1459 // should generalize representations in |map1|.
1460 Handle<Map> new_map =
1461 Map::ReconfigureExistingProperty(map2, kSplitProp, kData, NONE);
1462
1463 // |map2| should be left unchanged.
1464 CHECK(!map2->is_deprecated());
1465 CHECK_NE(*map2, *new_map);
1466 CHECK(expectations2.Check(*map2));
1467
1468 // |map| should be deprecated and |new_map| should match new expectations.
1469 expectations.SetDataField(kSplitProp, Representation::Tagged(), any_type);
1470
1471 CHECK(map->is_deprecated());
1472 CHECK_NE(*map, *new_map);
1473
1474 CHECK(!new_map->is_deprecated());
1475 CHECK(!new_map->is_dictionary_map());
1476 CHECK(expectations.Check(*new_map));
1477
1478 // Update deprecated |map|, it should become |new_map|.
1479 CHECK_EQ(*new_map, *Map::Update(map));
1480 }
1481
1482
1483 TEST(ReconfigureDataFieldAttribute_DataConstantToDataFieldAfterTargetMap) {
1484 CcTest::InitializeVM();
1485 v8::HandleScope scope(CcTest::isolate());
1486 Isolate* isolate = CcTest::i_isolate();
1487 Factory* factory = isolate->factory();
1488 Handle<HeapType> any_type = HeapType::Any(isolate);
1489 Handle<JSFunction> js_func = factory->NewFunction(factory->empty_string());
1490 Handle<JSFunction> js_func2 = factory->NewFunction(factory->empty_string());
1491 Handle<HeapType> value_type =
1492 HeapType::Class(Map::Create(isolate, 0), isolate);
1493
1494 const int kPropCount = 7;
1495 const int kConstantPropIndex = 5;
1496 Expectations expectations(isolate);
1497
1498 // Create a map, add required properties to it and initialize expectations.
1499 Handle<Map> initial_map = Map::Create(isolate, 0);
1500 Handle<Map> map = initial_map;
1501 for (int i = 0; i < kPropCount; i++) {
1502 if (i == kConstantPropIndex) {
1503 map = expectations.AddDataConstant(map, NONE, js_func);
1504
1505 } else {
1506 map =
1507 expectations.AddDataField(map, NONE, Representation::Smi(), any_type);
1508 }
1509 }
1510 CHECK(!map->is_deprecated());
1511 CHECK(map->is_stable());
1512 CHECK(expectations.Check(*map));
1513
1514 // Create another branch in transition tree (property at index |kSplitProp|
1515 // has different attributes), initialize expectations.
1516 const int kSplitProp = 2;
1517 Expectations expectations2(isolate);
1518
1519 Handle<Map> map2 = initial_map;
1520 for (int i = 0; i < kSplitProp; i++) {
1521 map2 = expectations2.FollowDataTransition(map2, NONE, Representation::Smi(),
1522 any_type);
1523 }
1524 map2 = expectations2.AddDataField(map2, READ_ONLY,
1525 Representation::HeapObject(), value_type);
1526
1527 for (int i = kSplitProp + 1; i < kPropCount; i++) {
1528 if (i == kConstantPropIndex) {
1529 map2 = expectations2.AddDataConstant(map2, NONE, js_func2);
1530
1531 } else {
1532 map2 = expectations2.AddDataField(map2, NONE, Representation::Smi(),
1533 any_type);
1534 }
1535 }
1536 CHECK(!map2->is_deprecated());
1537 CHECK(map2->is_stable());
1538 CHECK(expectations2.Check(*map2));
1539
1540
1541 // Reconfigure attributes of property |kSplitProp| of |map2| to NONE, which
1542 // should generalize representations in |map1|.
1543 Handle<Map> new_map =
1544 Map::ReconfigureExistingProperty(map2, kSplitProp, kData, NONE);
1545
1546 // |map2| should be left unchanged.
1547 CHECK(!map2->is_deprecated());
1548 CHECK_NE(*map2, *new_map);
1549 CHECK(expectations2.Check(*map2));
1550
1551 // |map| should be deprecated and |new_map| should match new expectations.
1552 expectations.SetDataField(kSplitProp, Representation::Tagged(), any_type);
1553 expectations.SetDataField(kConstantPropIndex, Representation::HeapObject(),
1554 any_type);
1555
1556 CHECK(map->is_deprecated());
1557 CHECK_NE(*map, *new_map);
1558
1559 CHECK(!new_map->is_deprecated());
1560 CHECK(!new_map->is_dictionary_map());
1561 CHECK(expectations.Check(*new_map));
1562
1563 // Update deprecated |map|, it should become |new_map|.
1564 CHECK_EQ(*new_map, *Map::Update(map));
1565 }
1566
1567
1568 TEST(ReconfigureDataFieldAttribute_SameAccessorConstantAfterTargetMap) {
1569 CcTest::InitializeVM();
1570 v8::HandleScope scope(CcTest::isolate());
1571 Isolate* isolate = CcTest::i_isolate();
1572 Handle<HeapType> any_type = HeapType::Any(isolate);
1573 Handle<AccessorPair> pair = CreateAccessorPair(true, true);
1574 Handle<HeapType> value_type =
1575 HeapType::Class(Map::Create(isolate, 0), isolate);
1576
1577 const int kPropCount = 7;
1578 const int kConstantPropIndex = 5;
1579 Expectations expectations(isolate);
1580
1581 // Create a map, add required properties to it and initialize expectations.
1582 Handle<Map> initial_map = Map::Create(isolate, 0);
1583 Handle<Map> map = initial_map;
1584 for (int i = 0; i < kPropCount; i++) {
1585 if (i == kConstantPropIndex) {
1586 map = expectations.AddAccessorConstant(map, NONE, pair);
1587
1588 } else {
1589 map =
1590 expectations.AddDataField(map, NONE, Representation::Smi(), any_type);
1591 }
1592 }
1593 CHECK(!map->is_deprecated());
1594 CHECK(map->is_stable());
1595 CHECK(expectations.Check(*map));
1596
1597 // Create another branch in transition tree (property at index |kSplitProp|
1598 // has different attributes), initialize expectations.
1599 const int kSplitProp = 2;
1600 Expectations expectations2(isolate);
1601
1602 Handle<Map> map2 = initial_map;
1603 for (int i = 0; i < kSplitProp; i++) {
1604 map2 = expectations2.FollowDataTransition(map2, NONE, Representation::Smi(),
1605 any_type);
1606 }
1607 map2 = expectations2.AddDataField(map2, READ_ONLY,
1608 Representation::HeapObject(), value_type);
1609
1610 for (int i = kSplitProp + 1; i < kPropCount; i++) {
1611 if (i == kConstantPropIndex) {
1612 map2 = expectations2.AddAccessorConstant(map2, NONE, pair);
1613
1614 } else {
1615 map2 = expectations2.AddDataField(map2, NONE, Representation::Smi(),
1616 any_type);
1617 }
1618 }
1619 CHECK(!map2->is_deprecated());
1620 CHECK(map2->is_stable());
1621 CHECK(expectations2.Check(*map2));
1622
1623
1624 // Reconfigure attributes of property |kSplitProp| of |map2| to NONE, which
1625 // should generalize representations in |map1|.
1626 Handle<Map> new_map =
1627 Map::ReconfigureExistingProperty(map2, kSplitProp, kData, NONE);
1628
1629 // |map2| should be left unchanged.
1630 CHECK(!map2->is_deprecated());
1631 CHECK_NE(*map2, *new_map);
1632 CHECK(expectations2.Check(*map2));
1633
1634 // |map| should be deprecated and |new_map| should match new expectations.
1635 expectations.SetDataField(kSplitProp, Representation::Tagged(), any_type);
1636
1637 CHECK(map->is_deprecated());
1638 CHECK_NE(*map, *new_map);
1639
1640 CHECK(!new_map->is_deprecated());
1641 CHECK(!new_map->is_dictionary_map());
1642 CHECK(expectations.Check(*new_map));
1643
1644 // Update deprecated |map|, it should become |new_map|.
1645 CHECK_EQ(*new_map, *Map::Update(map));
1646 }
1647
1648
1649 TEST(ReconfigureDataFieldAttribute_AccConstantToAccFieldAfterTargetMap) {
1650 CcTest::InitializeVM();
1651 v8::HandleScope scope(CcTest::isolate());
1652 Isolate* isolate = CcTest::i_isolate();
1653 Handle<HeapType> any_type = HeapType::Any(isolate);
1654 Handle<AccessorPair> pair = CreateAccessorPair(true, true);
1655 Handle<AccessorPair> pair2 = CreateAccessorPair(true, true);
1656 Handle<HeapType> value_type =
1657 HeapType::Class(Map::Create(isolate, 0), isolate);
1658
1659 const int kPropCount = 7;
1660 const int kConstantPropIndex = 5;
1661 Expectations expectations(isolate);
1662
1663 // Create a map, add required properties to it and initialize expectations.
1664 Handle<Map> initial_map = Map::Create(isolate, 0);
1665 Handle<Map> map = initial_map;
1666 for (int i = 0; i < kPropCount; i++) {
1667 if (i == kConstantPropIndex) {
1668 map = expectations.AddAccessorConstant(map, NONE, pair);
1669
1670 } else {
1671 map =
1672 expectations.AddDataField(map, NONE, Representation::Smi(), any_type);
1673 }
1674 }
1675 CHECK(!map->is_deprecated());
1676 CHECK(map->is_stable());
1677 CHECK(expectations.Check(*map));
1678
1679 // Create another branch in transition tree (property at index |kSplitProp|
1680 // has different attributes), initialize expectations.
1681 const int kSplitProp = 2;
1682 Expectations expectations2(isolate);
1683
1684 Handle<Map> map2 = initial_map;
1685 for (int i = 0; i < kSplitProp; i++) {
1686 map2 = expectations2.FollowDataTransition(map2, NONE, Representation::Smi(),
1687 any_type);
1688 }
1689 map2 = expectations2.AddDataField(map2, READ_ONLY,
1690 Representation::HeapObject(), value_type);
1691
1692 for (int i = kSplitProp + 1; i < kPropCount; i++) {
1693 if (i == kConstantPropIndex) {
1694 map2 = expectations2.AddAccessorConstant(map2, NONE, pair2);
1695
1696 } else {
1697 map2 = expectations2.AddDataField(map2, NONE, Representation::Smi(),
1698 any_type);
1699 }
1700 }
1701 CHECK(!map2->is_deprecated());
1702 CHECK(map2->is_stable());
1703 CHECK(expectations2.Check(*map2));
1704
1705
1706 // Reconfigure attributes of property |kSplitProp| of |map2| to NONE, which
1707 // should generalize representations in |map1|.
1708 Handle<Map> new_map =
1709 Map::ReconfigureExistingProperty(map2, kSplitProp, kData, NONE);
1710
1711 // |map2| should be left unchanged.
1712 CHECK(!map2->is_deprecated());
1713 CHECK_NE(*map2, *new_map);
1714 CHECK(expectations2.Check(*map2));
1715
1716 // |map| should be deprecated and |new_map| should match new expectations.
1717 if (IS_ACCESSOR_FIELD_SUPPORTED) {
1718 expectations.SetDataField(kSplitProp, Representation::Tagged(), any_type);
1719 expectations.SetAccessorField(kConstantPropIndex);
1720
1721 CHECK(map->is_deprecated());
1722 CHECK_NE(*map, *new_map);
1723
1724 CHECK(!new_map->is_deprecated());
1725 CHECK(!new_map->is_dictionary_map());
1726 CHECK(expectations.Check(*new_map));
1727
1728 // Update deprecated |map|, it should become |new_map|.
1729 CHECK_EQ(*new_map, *Map::Update(map));
1730 } else {
1731 // Currently we have a copy-generalize all representations case.
1732 CHECK(new_map->GetBackPointer()->IsUndefined());
1733 for (int i = 0; i < kPropCount; i++) {
1734 if (i == kConstantPropIndex) {
1735 expectations.SetAccessorConstant(i, pair2);
1736
1737 } else {
1738 expectations.SetDataField(i, Representation::Tagged(), any_type);
1739 }
1740 }
1741 CHECK(!map->is_deprecated());
1742 CHECK_NE(*map, *new_map);
1743
1744 CHECK(!new_map->is_deprecated());
1745 CHECK(!new_map->is_dictionary_map());
1746 CHECK(expectations.Check(*new_map));
1747 }
1748 }
1749
1750
1751 ////////////////////////////////////////////////////////////////////////////////
1752 // A set of tests checking split map deprecation.
1753 //
1754
1755 TEST(ReconfigurePropertySplitMapTransitionsOverflow) {
1756 CcTest::InitializeVM();
1757 v8::HandleScope scope(CcTest::isolate());
1758 Isolate* isolate = CcTest::i_isolate();
1759 Handle<HeapType> any_type = HeapType::Any(isolate);
1760
1761 const int kPropCount = 5;
1762 Expectations expectations(isolate);
1763
1764 // Create a map, add required properties to it and initialize expectations.
1765 Handle<Map> initial_map = Map::Create(isolate, 0);
1766 Handle<Map> map = initial_map;
1767 for (int i = 0; i < kPropCount; i++) {
1768 map = expectations.AddDataField(map, NONE, Representation::Smi(), any_type);
1769 }
1770 CHECK(!map->is_deprecated());
1771 CHECK(map->is_stable());
1772
1773 // Generalize representation of property at index |kSplitProp|.
1774 const int kSplitProp = kPropCount / 2;
1775 Handle<Map> split_map;
1776 Handle<Map> map2 = initial_map;
1777 {
1778 for (int i = 0; i < kSplitProp + 1; i++) {
1779 if (i == kSplitProp) {
1780 split_map = map2;
1781 }
1782
1783 Handle<String> name = MakeName("prop", i);
1784 int t = map2->SearchTransition(kData, *name, NONE);
1785 CHECK_NE(TransitionArray::kNotFound, t);
1786 map2 = handle(map2->GetTransition(t));
1787 }
1788
1789 map2 = Map::ReconfigureProperty(map2, kSplitProp, kData, NONE,
1790 Representation::Double(), any_type,
1791 FORCE_FIELD);
1792 expectations.SetDataField(kSplitProp, Representation::Double(), any_type);
1793
1794 CHECK(expectations.Check(*split_map, kSplitProp));
1795 CHECK(expectations.Check(*map2, kSplitProp + 1));
1796 }
1797
1798 // At this point |map| should be deprecated and disconnected from the
1799 // transition tree.
1800 CHECK(map->is_deprecated());
1801 CHECK(!split_map->is_deprecated());
1802 CHECK(!map2->is_deprecated());
1803
1804 // Fill in transition tree of |map2| so that it can't have more transitions.
1805 for (int i = 0; i < TransitionArray::kMaxNumberOfTransitions; i++) {
1806 CHECK(map2->CanHaveMoreTransitions());
1807 Handle<String> name = MakeName("foo", i);
1808 Map::CopyWithField(map2, name, any_type, NONE, Representation::Smi(),
1809 INSERT_TRANSITION).ToHandleChecked();
1810 }
1811 CHECK(!map2->CanHaveMoreTransitions());
1812
1813 // Try to update |map|, since there is no place for propX transition at |map2|
1814 // |map| should become "copy-generalized".
1815 Handle<Map> updated_map = Map::Update(map);
1816 CHECK(updated_map->GetBackPointer()->IsUndefined());
1817
1818 for (int i = 0; i < kPropCount; i++) {
1819 expectations.SetDataField(i, Representation::Tagged(), any_type);
1820 }
1821 CHECK(expectations.Check(*updated_map));
1822 }
1823
1824
1825 ////////////////////////////////////////////////////////////////////////////////
1826 // A set of tests involving special transitions.
1827 //
1828
1829 TEST(ElementsKindTransitionFromMapOwningDescriptor) {
1830 CcTest::InitializeVM();
1831 v8::HandleScope scope(CcTest::isolate());
1832 Isolate* isolate = CcTest::i_isolate();
1833 Handle<HeapType> value_type1 =
1834 HeapType::Class(Map::Create(isolate, 0), isolate);
1835 Handle<HeapType> value_type2 =
1836 HeapType::Class(Map::Create(isolate, 0), isolate);
1837
1838 const int kPropCount = 5;
1839 Expectations expectations(isolate);
1840
1841 // Create a map, add required properties to it and initialize expectations.
1842 Handle<Map> initial_map = Map::Create(isolate, 0);
1843 Handle<Map> map = initial_map;
1844 for (int i = 0; i < kPropCount; i++) {
1845 map = expectations.AddDataField(map, NONE, Representation::HeapObject(),
1846 value_type1);
1847 }
1848 CHECK(!map->is_deprecated());
1849 CHECK(map->is_stable());
1850 CHECK(expectations.Check(*map));
1851
1852 CHECK(map->owns_descriptors());
1853
1854 // Create an elements kind transition, it should always match |expectations|.
1855 Handle<Map> map2 =
1856 Map::CopyAsElementsKind(map, DICTIONARY_ELEMENTS, INSERT_TRANSITION);
1857 CHECK(!map2->is_deprecated());
1858 CHECK(map2->is_stable());
1859 CHECK(expectations.Check(*map2));
1860
1861 // |map1| should still match expectations.
1862 CHECK(!map->is_deprecated());
1863 CHECK(expectations.Check(*map));
1864
1865 // Create new maps by generalizing representation of propX field to various
1866 // HeapObject types with stable maps.
1867 Handle<Map> maps[kPropCount];
1868 for (int i = 0; i < kPropCount; i++) {
1869 Handle<Map> new_map = Map::ReconfigureProperty(map, i, kData, NONE,
1870 Representation::HeapObject(),
1871 value_type2, FORCE_FIELD);
1872 maps[i] = new_map;
1873
1874 expectations.SetDataField(
1875 i, Representation::HeapObject(),
1876 HeapType::Union(value_type2, expectations.GetFieldType(i), isolate));
1877
1878 // Maps should stay the same but field type modification should trigger
1879 // respective dependents to deoptimize.
1880 CHECK_EQ(*map, *new_map);
1881 CHECK(!new_map->is_deprecated());
1882 CHECK(!new_map->is_dictionary_map());
1883 CHECK(expectations.Check(*new_map));
1884
1885 if (IS_NON_EQUIVALENT_TRANSITION_SUPPORTED) {
1886 Handle<Map> new_map2 = Map::Update(map2);
1887 CHECK(!new_map2->is_deprecated());
1888 CHECK(!new_map2->is_dictionary_map());
1889 CHECK(expectations.Check(*new_map2));
1890 }
1891 }
1892
1893 Handle<Map> active_map = maps[kPropCount - 1];
1894 CHECK(!active_map->is_deprecated());
1895
1896 // Update all deprecated maps and check that they are now the same.
1897 CHECK_EQ(*active_map, *Map::Update(map));
1898 for (int i = 0; i < kPropCount; i++) {
1899 CHECK_EQ(*active_map, *Map::Update(maps[i]));
1900 }
1901 }
1902
1903
1904 TEST(ElementsKindTransitionFromMapNotOwningDescriptor) {
1905 if (!IS_CRBUG_448711_FIXED) return;
1906 CcTest::InitializeVM();
1907 v8::HandleScope scope(CcTest::isolate());
1908 Isolate* isolate = CcTest::i_isolate();
1909 Handle<HeapType> any_type = HeapType::Any(isolate);
1910 Handle<HeapType> value_type1 =
1911 HeapType::Class(Map::Create(isolate, 0), isolate);
1912 Handle<HeapType> value_type2 =
1913 HeapType::Class(Map::Create(isolate, 0), isolate);
1914
1915 const int kPropCount = 5;
1916 Expectations expectations(isolate);
1917
1918 // Create a map, add required properties to it and initialize expectations.
1919 Handle<Map> initial_map = Map::Create(isolate, 0);
1920 Handle<Map> map = initial_map;
1921 for (int i = 0; i < kPropCount; i++) {
1922 map = expectations.AddDataField(map, NONE, Representation::HeapObject(),
1923 value_type1);
1924 }
1925 CHECK(!map->is_deprecated());
1926 CHECK(map->is_stable());
1927 CHECK(expectations.Check(*map));
1928
1929 // Add one more transition to |map| in order to prevent descriptors ownership.
1930 CHECK(map->owns_descriptors());
1931 Map::CopyWithField(map, MakeString("foo"), any_type, NONE,
1932 Representation::Smi(),
1933 INSERT_TRANSITION).ToHandleChecked();
1934 CHECK(!map->owns_descriptors());
1935
1936 // Create an elements kind transition, it should always match |expectations|.
1937 Handle<Map> map2 =
1938 Map::CopyAsElementsKind(map, DICTIONARY_ELEMENTS, INSERT_TRANSITION);
1939 CHECK(!map2->is_deprecated());
1940 CHECK(map2->is_stable());
1941 CHECK(expectations.Check(*map2));
1942
1943 // |map1| should still match expectations.
1944 CHECK(!map->is_deprecated());
1945 CHECK(expectations.Check(*map));
1946
1947 // Create new maps by generalizing representation of propX field to various
1948 // HeapObject types with stable maps.
1949 Handle<Map> maps[kPropCount];
1950 for (int i = 0; i < kPropCount; i++) {
1951 Handle<Map> new_map = Map::ReconfigureProperty(map, i, kData, NONE,
1952 Representation::HeapObject(),
1953 value_type2, FORCE_FIELD);
1954 maps[i] = new_map;
1955
1956 expectations.SetDataField(
1957 i, Representation::HeapObject(),
1958 HeapType::Union(value_type2, expectations.GetFieldType(i), isolate));
1959
1960 // Maps should stay the same but field type modification should trigger
1961 // respective dependents to deoptimize.
1962 CHECK_EQ(*map, *new_map);
1963 CHECK(!new_map->is_deprecated());
1964 CHECK(!new_map->is_dictionary_map());
1965 CHECK(expectations.Check(*new_map));
1966
1967 if (IS_NON_EQUIVALENT_TRANSITION_SUPPORTED) {
1968 Handle<Map> new_map2 = Map::Update(map2);
1969 CHECK(!new_map2->is_deprecated());
1970 CHECK(!new_map2->is_dictionary_map());
1971 CHECK(expectations.Check(*new_map2));
1972 }
1973 }
1974
1975 Handle<Map> active_map = maps[kPropCount - 1];
1976 CHECK(!active_map->is_deprecated());
1977
1978 // Update all deprecated maps and check that they are now the same.
1979 CHECK_EQ(*active_map, *Map::Update(map));
1980 for (int i = 0; i < kPropCount; i++) {
1981 CHECK_EQ(*active_map, *Map::Update(maps[i]));
1982 }
1983 }
1984
1985
1986 TEST(ForObservedTransitionFromMapOwningDescriptor) {
1987 CcTest::InitializeVM();
1988 v8::HandleScope scope(CcTest::isolate());
1989 Isolate* isolate = CcTest::i_isolate();
1990 Handle<HeapType> value_type1 =
1991 HeapType::Class(Map::Create(isolate, 0), isolate);
1992 Handle<HeapType> value_type2 =
1993 HeapType::Class(Map::Create(isolate, 0), isolate);
1994
1995 const int kPropCount = 5;
1996 Expectations expectations(isolate);
1997
1998 // Create a map, add required properties to it and initialize expectations.
1999 Handle<Map> initial_map = Map::Create(isolate, 0);
2000 Handle<Map> map = initial_map;
2001 for (int i = 0; i < kPropCount; i++) {
2002 map = expectations.AddDataField(map, NONE, Representation::HeapObject(),
2003 value_type1);
2004 }
2005 CHECK(!map->is_deprecated());
2006 CHECK(map->is_stable());
2007 CHECK(expectations.Check(*map));
2008
2009 CHECK(map->owns_descriptors());
2010
2011 // Create "for-observed" transition, it should always match |expectations|.
2012 Handle<Map> map2 = Map::CopyForObserved(map);
2013 CHECK(!map2->is_deprecated());
2014 CHECK(map2->is_stable());
2015 CHECK(expectations.Check(*map2));
2016
2017 // |map1| should still match expectations.
2018 CHECK(!map->is_deprecated());
2019 CHECK(expectations.Check(*map));
2020
2021 // Create new maps by generalizing representation of propX field to various
2022 // HeapObject types with stable maps.
2023 Handle<Map> maps[kPropCount];
2024 for (int i = 0; i < kPropCount; i++) {
2025 Handle<Map> new_map = Map::ReconfigureProperty(map, i, kData, NONE,
2026 Representation::HeapObject(),
2027 value_type2, FORCE_FIELD);
2028 maps[i] = new_map;
2029
2030 expectations.SetDataField(
2031 i, Representation::HeapObject(),
2032 HeapType::Union(value_type2, expectations.GetFieldType(i), isolate));
2033
2034 // Maps should stay the same but field type modification should trigger
2035 // respective dependents to deoptimize.
2036 CHECK_EQ(*map, *new_map);
2037 CHECK(!new_map->is_deprecated());
2038 CHECK(!new_map->is_dictionary_map());
2039 CHECK(expectations.Check(*new_map));
2040
2041 if (IS_NON_EQUIVALENT_TRANSITION_SUPPORTED) {
2042 Handle<Map> new_map2 = Map::Update(map2);
2043 CHECK(!new_map2->is_deprecated());
2044 CHECK(!new_map2->is_dictionary_map());
2045 CHECK(expectations.Check(*new_map2));
2046 }
2047 }
2048
2049 Handle<Map> active_map = maps[kPropCount - 1];
2050 CHECK(!active_map->is_deprecated());
2051
2052 // Update all deprecated maps and check that they are now the same.
2053 CHECK_EQ(*active_map, *Map::Update(map));
2054 for (int i = 0; i < kPropCount; i++) {
2055 CHECK_EQ(*active_map, *Map::Update(maps[i]));
2056 }
2057 }
2058
2059
2060 TEST(ForObservedTransitionFromMapNotOwningDescriptor) {
2061 if (!IS_CRBUG_448711_FIXED) return;
2062 CcTest::InitializeVM();
2063 v8::HandleScope scope(CcTest::isolate());
2064 Isolate* isolate = CcTest::i_isolate();
2065 Handle<HeapType> any_type = HeapType::Any(isolate);
2066 Handle<HeapType> value_type1 =
2067 HeapType::Class(Map::Create(isolate, 0), isolate);
2068 Handle<HeapType> value_type2 =
2069 HeapType::Class(Map::Create(isolate, 0), isolate);
2070
2071 const int kPropCount = 5;
2072 Expectations expectations(isolate);
2073
2074 // Create a map, add required properties to it and initialize expectations.
2075 Handle<Map> initial_map = Map::Create(isolate, 0);
2076 Handle<Map> map = initial_map;
2077 for (int i = 0; i < kPropCount; i++) {
2078 map = expectations.AddDataField(map, NONE, Representation::HeapObject(),
2079 value_type1);
2080 }
2081 CHECK(!map->is_deprecated());
2082 CHECK(map->is_stable());
2083 CHECK(expectations.Check(*map));
2084
2085 // Add one more transition to |map| in order to prevent descriptors ownership.
2086 CHECK(map->owns_descriptors());
2087 Map::CopyWithField(map, MakeString("foo"), any_type, NONE,
2088 Representation::Smi(),
2089 INSERT_TRANSITION).ToHandleChecked();
2090 CHECK(!map->owns_descriptors());
2091
2092 // Create "for-observed" transition, it should always match |expectations|.
2093 Handle<Map> map2 = Map::CopyForObserved(map);
2094 CHECK(!map2->is_deprecated());
2095 CHECK(map2->is_stable());
2096 CHECK(expectations.Check(*map2));
2097
2098 // |map1| should still match expectations.
2099 CHECK(!map->is_deprecated());
2100 CHECK(expectations.Check(*map));
2101
2102 // Create new maps by generalizing representation of propX field to various
2103 // HeapObject types with stable maps.
2104 Handle<Map> maps[kPropCount];
2105 for (int i = 0; i < kPropCount; i++) {
2106 Handle<Map> new_map = Map::ReconfigureProperty(map, i, kData, NONE,
2107 Representation::HeapObject(),
2108 value_type2, FORCE_FIELD);
2109 maps[i] = new_map;
2110
2111 expectations.SetDataField(
2112 i, Representation::HeapObject(),
2113 HeapType::Union(value_type2, expectations.GetFieldType(i), isolate));
2114
2115 // Maps should stay the same but field type modification should trigger
2116 // respective dependents to deoptimize.
2117 CHECK_EQ(*map, *new_map);
2118 CHECK(!new_map->is_deprecated());
2119 CHECK(!new_map->is_dictionary_map());
2120 CHECK(expectations.Check(*new_map));
2121
2122 if (IS_NON_EQUIVALENT_TRANSITION_SUPPORTED) {
2123 Handle<Map> new_map2 = Map::Update(map2);
2124 CHECK(!new_map2->is_deprecated());
2125 CHECK(!new_map2->is_dictionary_map());
2126 CHECK(expectations.Check(*new_map2));
2127 }
2128 }
2129
2130 Handle<Map> active_map = maps[kPropCount - 1];
2131 CHECK(!active_map->is_deprecated());
2132
2133 // Update all deprecated maps and check that they are now the same.
2134 CHECK_EQ(*active_map, *Map::Update(map));
2135 for (int i = 0; i < kPropCount; i++) {
2136 CHECK_EQ(*active_map, *Map::Update(maps[i]));
2137 }
2138 }
2139
2140
2141 TEST(PrototypeTransitionFromMapOwningDescriptor) {
2142 CcTest::InitializeVM();
2143 v8::HandleScope scope(CcTest::isolate());
2144 Isolate* isolate = CcTest::i_isolate();
2145 Factory* factory = isolate->factory();
2146 Handle<HeapType> any_type = HeapType::Any(isolate);
2147 Handle<JSObject> prototype =
2148 factory->NewJSObjectFromMap(Map::Create(isolate, 0));
2149
2150 const int kPropCount = 5;
2151 Expectations expectations(isolate);
2152
2153 // Create a map, add required properties to it and initialize expectations.
2154 Handle<Map> initial_map = Map::Create(isolate, 0);
2155 Handle<Map> map = initial_map;
2156 for (int i = 0; i < kPropCount; i++) {
2157 map = expectations.AddDataField(map, NONE, Representation::Smi(), any_type);
2158 }
2159 CHECK(!map->is_deprecated());
2160 CHECK(map->is_stable());
2161 CHECK(expectations.Check(*map));
2162
2163 CHECK(map->owns_descriptors());
2164
2165 // Create prototype transition, it should always match |expectations|.
2166 Handle<Map> map2 =
2167 Map::TransitionToPrototype(map, prototype, REGULAR_PROTOTYPE);
2168
2169 CHECK(!map2->is_deprecated());
2170 CHECK(map2->is_stable());
2171 if (IS_CRBUG_448711_FIXED) {
2172 CHECK(expectations.Check(*map2));
2173 }
2174
2175 // |map1| should still match expectations.
2176 CHECK(!map->is_deprecated());
2177 CHECK(expectations.Check(*map));
2178
2179 CHECK_EQ(*map2,
2180 *Map::TransitionToPrototype(map, prototype, REGULAR_PROTOTYPE));
2181
2182 // Create new maps by generalizing representation of propX field to double.
2183 Handle<Map> maps[kPropCount];
2184 for (int i = 0; i < kPropCount; i++) {
2185 Handle<Map> new_map = Map::ReconfigureProperty(
2186 map, i, kData, NONE, Representation::Double(), any_type, FORCE_FIELD);
2187 maps[i] = new_map;
2188
2189 expectations.SetDataField(i, Representation::Double(), any_type);
2190
2191 CHECK(map->is_deprecated());
2192 CHECK_NE(*map, *new_map);
2193 CHECK(i == 0 || maps[i - 1]->is_deprecated());
2194
2195 CHECK(!new_map->is_deprecated());
2196 CHECK(!new_map->is_dictionary_map());
2197 CHECK(expectations.Check(*new_map));
2198
2199 if (IS_NON_EQUIVALENT_TRANSITION_SUPPORTED) {
2200 Handle<Map> new_map2 = Map::Update(map2);
2201 CHECK(!new_map2->is_deprecated());
2202 CHECK(!new_map2->is_dictionary_map());
2203 CHECK(expectations.Check(*new_map2));
2204 }
2205 }
2206 }
2207
2208
2209 TEST(GeneralizeRepresentationWithPrototypeTransition) {
2210 CcTest::InitializeVM();
2211 v8::HandleScope scope(CcTest::isolate());
2212 Isolate* isolate = CcTest::i_isolate();
2213 Factory* factory = isolate->factory();
2214 Handle<HeapType> any_type = HeapType::Any(isolate);
2215 Handle<JSObject> prototype =
2216 factory->NewJSObjectFromMap(Map::Create(isolate, 0));
2217 Handle<JSFunction> js_func = factory->NewFunction(factory->empty_string());
2218
2219 const int kPropCount = 5;
2220 Expectations expectations(isolate);
2221
2222 // Create a map, add required properties to it and initialize expectations.
2223 Handle<Map> initial_map = Map::Create(isolate, 0);
2224 Handle<Map> map = initial_map;
2225 map = expectations.AddDataConstant(map, NONE, js_func);
2226 map = Map::TransitionToPrototype(map, prototype, REGULAR_PROTOTYPE);
2227 if (!IS_CRBUG_448711_FIXED) {
2228 expectations.GeneralizeRepresentation(0);
2229 }
2230 for (int i = 1; i < kPropCount; i++) {
2231 map = expectations.AddDataField(map, NONE, Representation::Smi(), any_type);
2232 }
2233 CHECK(!map->is_deprecated());
2234 CHECK(map->is_stable());
2235 CHECK(expectations.Check(*map));
2236
2237 // Create new maps by generalizing representation of propX field to double.
2238 Handle<Map> maps[kPropCount];
2239 for (int i = 0; i < kPropCount; i++) {
2240 Handle<Map> new_map = Map::ReconfigureProperty(
2241 map, i, kData, NONE, Representation::Double(), any_type, FORCE_FIELD);
2242 maps[i] = new_map;
2243
2244 if (!IS_NON_EQUIVALENT_TRANSITION_SUPPORTED) {
2245 // If we reconfigure the property that was added before prototype
2246 // transition, we would get Gen
2247 CHECK(i != 0 || new_map->GetBackPointer()->IsUndefined());
2248 }
2249
2250 if (IS_NON_EQUIVALENT_TRANSITION_SUPPORTED && IS_CRBUG_448711_FIXED) {
2251 expectations.SetDataField(i, Representation::Double(), any_type);
2252
2253 CHECK(map->is_deprecated());
2254 CHECK_NE(*map, *new_map);
2255 CHECK(i == 0 || maps[i - 1]->is_deprecated());
2256
2257 CHECK(!new_map->is_deprecated());
2258 CHECK(!new_map->is_dictionary_map());
2259 CHECK(expectations.Check(*new_map));
2260 }
2261 }
2262 }
OLDNEW
« src/objects.cc ('K') | « test/cctest/cctest.gyp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698