| 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 |