OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <stdlib.h> | 5 #include <stdlib.h> |
6 #include <utility> | 6 #include <utility> |
7 | 7 |
8 #include "src/v8.h" | 8 #include "src/v8.h" |
9 | 9 |
10 #include "src/compilation-cache.h" | 10 #include "src/compilation-cache.h" |
(...skipping 12 matching lines...) Expand all Loading... |
23 | 23 |
24 // | 24 // |
25 // Helper functions. | 25 // Helper functions. |
26 // | 26 // |
27 | 27 |
28 | 28 |
29 static void InitializeVerifiedMapDescriptors( | 29 static void InitializeVerifiedMapDescriptors( |
30 Map* map, DescriptorArray* descriptors, | 30 Map* map, DescriptorArray* descriptors, |
31 LayoutDescriptor* layout_descriptor) { | 31 LayoutDescriptor* layout_descriptor) { |
32 map->InitializeDescriptors(descriptors, layout_descriptor); | 32 map->InitializeDescriptors(descriptors, layout_descriptor); |
33 CHECK(layout_descriptor->IsConsistentWithMap(map)); | 33 CHECK(layout_descriptor->IsConsistentWithMap(map, true)); |
34 } | 34 } |
35 | 35 |
36 | 36 |
37 static Handle<String> MakeString(const char* str) { | 37 static Handle<String> MakeString(const char* str) { |
38 Isolate* isolate = CcTest::i_isolate(); | 38 Isolate* isolate = CcTest::i_isolate(); |
39 Factory* factory = isolate->factory(); | 39 Factory* factory = isolate->factory(); |
40 return factory->InternalizeUtf8String(str); | 40 return factory->InternalizeUtf8String(str); |
41 } | 41 } |
42 | 42 |
43 | 43 |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
223 LayoutDescriptor* layout_desc = *layout_descriptor; | 223 LayoutDescriptor* layout_desc = *layout_descriptor; |
224 // Play with the bits but leave it in consistent state with map at the end. | 224 // Play with the bits but leave it in consistent state with map at the end. |
225 for (int i = 1; i < kPropsCount - 1; i++) { | 225 for (int i = 1; i < kPropsCount - 1; i++) { |
226 layout_desc = layout_desc->SetTaggedForTesting(i, false); | 226 layout_desc = layout_desc->SetTaggedForTesting(i, false); |
227 CHECK_EQ(false, layout_desc->IsTagged(i)); | 227 CHECK_EQ(false, layout_desc->IsTagged(i)); |
228 layout_desc = layout_desc->SetTaggedForTesting(i, true); | 228 layout_desc = layout_desc->SetTaggedForTesting(i, true); |
229 CHECK_EQ(true, layout_desc->IsTagged(i)); | 229 CHECK_EQ(true, layout_desc->IsTagged(i)); |
230 } | 230 } |
231 CHECK(layout_desc->IsSlowLayout()); | 231 CHECK(layout_desc->IsSlowLayout()); |
232 CHECK(!layout_desc->IsFastPointerLayout()); | 232 CHECK(!layout_desc->IsFastPointerLayout()); |
233 CHECK(layout_descriptor->IsConsistentWithMap(*map)); | 233 CHECK(layout_descriptor->IsConsistentWithMap(*map, true)); |
234 } | 234 } |
235 } | 235 } |
236 | 236 |
237 | 237 |
238 static void TestLayoutDescriptorQueries(int layout_descriptor_length, | 238 static void TestLayoutDescriptorQueries(int layout_descriptor_length, |
239 int* bit_flip_positions, | 239 int* bit_flip_positions, |
240 int max_sequence_length) { | 240 int max_sequence_length) { |
241 Handle<LayoutDescriptor> layout_descriptor = LayoutDescriptor::NewForTesting( | 241 Handle<LayoutDescriptor> layout_descriptor = LayoutDescriptor::NewForTesting( |
242 CcTest::i_isolate(), layout_descriptor_length); | 242 CcTest::i_isolate(), layout_descriptor_length); |
243 layout_descriptor_length = layout_descriptor->capacity(); | 243 layout_descriptor_length = layout_descriptor->capacity(); |
(...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
637 bool is_inobject = field_index < map->inobject_properties(); | 637 bool is_inobject = field_index < map->inobject_properties(); |
638 for (int bit = 0; bit < field_width_in_words; bit++) { | 638 for (int bit = 0; bit < field_width_in_words; bit++) { |
639 CHECK_EQ(is_inobject && (kind == PROP_DOUBLE), | 639 CHECK_EQ(is_inobject && (kind == PROP_DOUBLE), |
640 !layout_descriptor->IsTagged(field_index + bit)); | 640 !layout_descriptor->IsTagged(field_index + bit)); |
641 } | 641 } |
642 CHECK(layout_descriptor->IsTagged(next_field_offset)); | 642 CHECK(layout_descriptor->IsTagged(next_field_offset)); |
643 } | 643 } |
644 map->InitializeDescriptors(*descriptors, *layout_descriptor); | 644 map->InitializeDescriptors(*descriptors, *layout_descriptor); |
645 } | 645 } |
646 Handle<LayoutDescriptor> layout_descriptor(map->layout_descriptor(), isolate); | 646 Handle<LayoutDescriptor> layout_descriptor(map->layout_descriptor(), isolate); |
647 CHECK(layout_descriptor->IsConsistentWithMap(*map)); | 647 CHECK(layout_descriptor->IsConsistentWithMap(*map, true)); |
648 return layout_descriptor; | 648 return layout_descriptor; |
649 } | 649 } |
650 | 650 |
651 | 651 |
652 TEST(LayoutDescriptorAppend) { | 652 TEST(LayoutDescriptorAppend) { |
653 CcTest::InitializeVM(); | 653 CcTest::InitializeVM(); |
654 Isolate* isolate = CcTest::i_isolate(); | 654 Isolate* isolate = CcTest::i_isolate(); |
655 v8::HandleScope scope(CcTest::isolate()); | 655 v8::HandleScope scope(CcTest::isolate()); |
656 | 656 |
657 Handle<LayoutDescriptor> layout_descriptor; | 657 Handle<LayoutDescriptor> layout_descriptor; |
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
906 Map::Normalize(map, KEEP_INOBJECT_PROPERTIES, "testing"); | 906 Map::Normalize(map, KEEP_INOBJECT_PROPERTIES, "testing"); |
907 JSObject::MigrateToMap(object, normalized_map); | 907 JSObject::MigrateToMap(object, normalized_map); |
908 CHECK(!object->HasFastProperties()); | 908 CHECK(!object->HasFastProperties()); |
909 CHECK(object->map()->HasFastPointerLayout()); | 909 CHECK(object->map()->HasFastPointerLayout()); |
910 | 910 |
911 // Trigger GCs and heap verification. | 911 // Trigger GCs and heap verification. |
912 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags); | 912 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags); |
913 } | 913 } |
914 | 914 |
915 | 915 |
| 916 TEST(DescriptorArrayTrimming) { |
| 917 CcTest::InitializeVM(); |
| 918 v8::HandleScope scope(CcTest::isolate()); |
| 919 Isolate* isolate = CcTest::i_isolate(); |
| 920 |
| 921 const int kFieldCount = 128; |
| 922 const int kSplitFieldIndex = 32; |
| 923 const int kTrimmedLayoutDescriptorLength = 64; |
| 924 |
| 925 Handle<HeapType> any_type = HeapType::Any(isolate); |
| 926 Handle<Map> map = Map::Create(isolate, kFieldCount); |
| 927 for (int i = 0; i < kSplitFieldIndex; i++) { |
| 928 map = Map::CopyWithField(map, MakeName("prop", i), any_type, NONE, |
| 929 Representation::Smi(), |
| 930 INSERT_TRANSITION).ToHandleChecked(); |
| 931 } |
| 932 map = Map::CopyWithField(map, MakeName("dbl", kSplitFieldIndex), any_type, |
| 933 NONE, Representation::Double(), |
| 934 INSERT_TRANSITION).ToHandleChecked(); |
| 935 CHECK(map->layout_descriptor()->IsConsistentWithMap(*map, true)); |
| 936 CHECK(map->layout_descriptor()->IsSlowLayout()); |
| 937 CHECK(map->owns_descriptors()); |
| 938 CHECK_EQ(2, map->layout_descriptor()->length()); |
| 939 |
| 940 { |
| 941 // Add transitions to double fields. |
| 942 v8::HandleScope scope(CcTest::isolate()); |
| 943 |
| 944 Handle<Map> tmp_map = map; |
| 945 for (int i = kSplitFieldIndex + 1; i < kFieldCount; i++) { |
| 946 tmp_map = Map::CopyWithField(tmp_map, MakeName("dbl", i), any_type, NONE, |
| 947 Representation::Double(), |
| 948 INSERT_TRANSITION).ToHandleChecked(); |
| 949 CHECK(tmp_map->layout_descriptor()->IsConsistentWithMap(*tmp_map, true)); |
| 950 } |
| 951 // Check that descriptors are shared. |
| 952 CHECK(tmp_map->owns_descriptors()); |
| 953 CHECK_EQ(map->instance_descriptors(), tmp_map->instance_descriptors()); |
| 954 CHECK_EQ(map->layout_descriptor(), tmp_map->layout_descriptor()); |
| 955 } |
| 956 CHECK(map->layout_descriptor()->IsSlowLayout()); |
| 957 CHECK_EQ(4, map->layout_descriptor()->length()); |
| 958 |
| 959 // The unused tail of the layout descriptor is now "durty" because of sharing. |
| 960 CHECK(map->layout_descriptor()->IsConsistentWithMap(*map)); |
| 961 for (int i = kSplitFieldIndex + 1; i < kTrimmedLayoutDescriptorLength; i++) { |
| 962 CHECK(!map->layout_descriptor()->IsTagged(i)); |
| 963 } |
| 964 CHECK_LT(map->NumberOfOwnDescriptors(), |
| 965 map->instance_descriptors()->number_of_descriptors()); |
| 966 |
| 967 // Call GC that should trim both |map|'s descriptor array and layout |
| 968 // descriptor. |
| 969 CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags); |
| 970 |
| 971 // The unused tail of the layout descriptor is now "clean" again. |
| 972 CHECK(map->layout_descriptor()->IsConsistentWithMap(*map, true)); |
| 973 CHECK(map->owns_descriptors()); |
| 974 CHECK_EQ(map->NumberOfOwnDescriptors(), |
| 975 map->instance_descriptors()->number_of_descriptors()); |
| 976 CHECK(map->layout_descriptor()->IsSlowLayout()); |
| 977 CHECK_EQ(2, map->layout_descriptor()->length()); |
| 978 |
| 979 { |
| 980 // Add transitions to tagged fields. |
| 981 v8::HandleScope scope(CcTest::isolate()); |
| 982 |
| 983 Handle<Map> tmp_map = map; |
| 984 for (int i = kSplitFieldIndex + 1; i < kFieldCount - 1; i++) { |
| 985 tmp_map = Map::CopyWithField(tmp_map, MakeName("tagged", i), any_type, |
| 986 NONE, Representation::Tagged(), |
| 987 INSERT_TRANSITION).ToHandleChecked(); |
| 988 CHECK(tmp_map->layout_descriptor()->IsConsistentWithMap(*tmp_map, true)); |
| 989 } |
| 990 tmp_map = Map::CopyWithField(tmp_map, MakeString("dbl"), any_type, NONE, |
| 991 Representation::Double(), |
| 992 INSERT_TRANSITION).ToHandleChecked(); |
| 993 CHECK(tmp_map->layout_descriptor()->IsConsistentWithMap(*tmp_map, true)); |
| 994 // Check that descriptors are shared. |
| 995 CHECK(tmp_map->owns_descriptors()); |
| 996 CHECK_EQ(map->instance_descriptors(), tmp_map->instance_descriptors()); |
| 997 } |
| 998 CHECK(map->layout_descriptor()->IsSlowLayout()); |
| 999 } |
| 1000 |
| 1001 |
916 TEST(DoScavenge) { | 1002 TEST(DoScavenge) { |
917 CcTest::InitializeVM(); | 1003 CcTest::InitializeVM(); |
918 v8::HandleScope scope(CcTest::isolate()); | 1004 v8::HandleScope scope(CcTest::isolate()); |
919 Isolate* isolate = CcTest::i_isolate(); | 1005 Isolate* isolate = CcTest::i_isolate(); |
920 Factory* factory = isolate->factory(); | 1006 Factory* factory = isolate->factory(); |
921 | 1007 |
922 // The plan: create |obj| with double field in new space, do scanvenge so | 1008 // The plan: create |obj| with double field in new space, do scanvenge so |
923 // that |obj| is moved to old space, construct a double value that looks like | 1009 // that |obj| is moved to old space, construct a double value that looks like |
924 // a pointer to "from space" pointer. Do scavenge one more time and ensure | 1010 // a pointer to "from space" pointer. Do scavenge one more time and ensure |
925 // that it didn't crash or corrupt the double value stored in the object. | 1011 // that it didn't crash or corrupt the double value stored in the object. |
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1218 Handle<String> name = MakeName("prop", i); | 1304 Handle<String> name = MakeName("prop", i); |
1219 map = Map::CopyWithField(map, name, any_type, NONE, Representation::Smi(), | 1305 map = Map::CopyWithField(map, name, any_type, NONE, Representation::Smi(), |
1220 INSERT_TRANSITION).ToHandleChecked(); | 1306 INSERT_TRANSITION).ToHandleChecked(); |
1221 } | 1307 } |
1222 split_map = Map::CopyWithField(map, MakeString("dbl"), any_type, NONE, | 1308 split_map = Map::CopyWithField(map, MakeString("dbl"), any_type, NONE, |
1223 Representation::Double(), | 1309 Representation::Double(), |
1224 INSERT_TRANSITION).ToHandleChecked(); | 1310 INSERT_TRANSITION).ToHandleChecked(); |
1225 } | 1311 } |
1226 Handle<LayoutDescriptor> split_layout_descriptor( | 1312 Handle<LayoutDescriptor> split_layout_descriptor( |
1227 split_map->layout_descriptor(), isolate); | 1313 split_map->layout_descriptor(), isolate); |
1228 CHECK(split_layout_descriptor->IsConsistentWithMap(*split_map)); | 1314 CHECK(split_layout_descriptor->IsConsistentWithMap(*split_map, true)); |
1229 CHECK(split_layout_descriptor->IsSlowLayout()); | 1315 CHECK(split_layout_descriptor->IsSlowLayout()); |
1230 CHECK(split_map->owns_descriptors()); | 1316 CHECK(split_map->owns_descriptors()); |
1231 | 1317 |
1232 Handle<Map> map1 = Map::CopyWithField(split_map, MakeString("foo"), any_type, | 1318 Handle<Map> map1 = Map::CopyWithField(split_map, MakeString("foo"), any_type, |
1233 NONE, Representation::Double(), | 1319 NONE, Representation::Double(), |
1234 INSERT_TRANSITION).ToHandleChecked(); | 1320 INSERT_TRANSITION).ToHandleChecked(); |
1235 CHECK(!split_map->owns_descriptors()); | 1321 CHECK(!split_map->owns_descriptors()); |
1236 CHECK_EQ(*split_layout_descriptor, split_map->layout_descriptor()); | 1322 CHECK_EQ(*split_layout_descriptor, split_map->layout_descriptor()); |
1237 | 1323 |
1238 // Layout descriptors should be shared with |split_map|. | 1324 // Layout descriptors should be shared with |split_map|. |
1239 CHECK(map1->owns_descriptors()); | 1325 CHECK(map1->owns_descriptors()); |
1240 CHECK_EQ(*split_layout_descriptor, map1->layout_descriptor()); | 1326 CHECK_EQ(*split_layout_descriptor, map1->layout_descriptor()); |
1241 CHECK(map1->layout_descriptor()->IsConsistentWithMap(*map1)); | 1327 CHECK(map1->layout_descriptor()->IsConsistentWithMap(*map1, true)); |
1242 | 1328 |
1243 Handle<Map> map2 = Map::CopyWithField(split_map, MakeString("bar"), any_type, | 1329 Handle<Map> map2 = Map::CopyWithField(split_map, MakeString("bar"), any_type, |
1244 NONE, Representation::Tagged(), | 1330 NONE, Representation::Tagged(), |
1245 INSERT_TRANSITION).ToHandleChecked(); | 1331 INSERT_TRANSITION).ToHandleChecked(); |
1246 | 1332 |
1247 // Layout descriptors should not be shared with |split_map|. | 1333 // Layout descriptors should not be shared with |split_map|. |
1248 CHECK(map2->owns_descriptors()); | 1334 CHECK(map2->owns_descriptors()); |
1249 CHECK_NE(*split_layout_descriptor, map2->layout_descriptor()); | 1335 CHECK_NE(*split_layout_descriptor, map2->layout_descriptor()); |
1250 CHECK(map2->layout_descriptor()->IsConsistentWithMap(*map2)); | 1336 CHECK(map2->layout_descriptor()->IsConsistentWithMap(*map2, true)); |
1251 } | 1337 } |
1252 | 1338 |
1253 | 1339 |
1254 TEST(StoreBufferScanOnScavenge) { | 1340 TEST(StoreBufferScanOnScavenge) { |
1255 CcTest::InitializeVM(); | 1341 CcTest::InitializeVM(); |
1256 Isolate* isolate = CcTest::i_isolate(); | 1342 Isolate* isolate = CcTest::i_isolate(); |
1257 Factory* factory = isolate->factory(); | 1343 Factory* factory = isolate->factory(); |
1258 v8::HandleScope scope(CcTest::isolate()); | 1344 v8::HandleScope scope(CcTest::isolate()); |
1259 | 1345 |
1260 Handle<HeapType> any_type = HeapType::Any(isolate); | 1346 Handle<HeapType> any_type = HeapType::Any(isolate); |
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1595 | 1681 |
1596 // TODO(ishell): add respective tests for property kind reconfiguring from | 1682 // TODO(ishell): add respective tests for property kind reconfiguring from |
1597 // accessor field to double, once accessor fields are supported by | 1683 // accessor field to double, once accessor fields are supported by |
1598 // Map::ReconfigureProperty(). | 1684 // Map::ReconfigureProperty(). |
1599 | 1685 |
1600 | 1686 |
1601 // TODO(ishell): add respective tests for fast property removal case once | 1687 // TODO(ishell): add respective tests for fast property removal case once |
1602 // Map::ReconfigureProperty() supports that. | 1688 // Map::ReconfigureProperty() supports that. |
1603 | 1689 |
1604 #endif | 1690 #endif |
OLD | NEW |