| 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/accessors.h" |
| 10 #include "src/compilation-cache.h" | 11 #include "src/compilation-cache.h" |
| 11 #include "src/execution.h" | 12 #include "src/execution.h" |
| 12 #include "src/factory.h" | 13 #include "src/factory.h" |
| 13 #include "src/field-type.h" | 14 #include "src/field-type.h" |
| 14 #include "src/global-handles.h" | 15 #include "src/global-handles.h" |
| 15 #include "src/ic/ic.h" | 16 #include "src/ic/ic.h" |
| 16 #include "src/macro-assembler.h" | 17 #include "src/macro-assembler.h" |
| 17 #include "test/cctest/cctest.h" | 18 #include "test/cctest/cctest.h" |
| 18 #include "test/cctest/heap/heap-utils.h" | 19 #include "test/cctest/heap/heap-utils.h" |
| 19 | 20 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 71 } | 72 } |
| 72 | 73 |
| 73 void WriteToField(JSObject* object, int descriptor, Object* value) { | 74 void WriteToField(JSObject* object, int descriptor, Object* value) { |
| 74 DescriptorArray* descriptors = object->map()->instance_descriptors(); | 75 DescriptorArray* descriptors = object->map()->instance_descriptors(); |
| 75 PropertyDetails details = descriptors->GetDetails(descriptor); | 76 PropertyDetails details = descriptors->GetDetails(descriptor); |
| 76 object->WriteToField(descriptor, details, value); | 77 object->WriteToField(descriptor, details, value); |
| 77 } | 78 } |
| 78 | 79 |
| 79 const int kNumberOfBits = 32; | 80 const int kNumberOfBits = 32; |
| 80 | 81 |
| 81 | |
| 82 enum TestPropertyKind { | 82 enum TestPropertyKind { |
| 83 PROP_CONSTANT, | 83 PROP_ACCESSOR_INFO, |
| 84 PROP_SMI, | 84 PROP_SMI, |
| 85 PROP_DOUBLE, | 85 PROP_DOUBLE, |
| 86 PROP_TAGGED, | 86 PROP_TAGGED, |
| 87 PROP_KIND_NUMBER | 87 PROP_KIND_NUMBER |
| 88 }; | 88 }; |
| 89 | 89 |
| 90 static Representation representations[PROP_KIND_NUMBER] = { | 90 static Representation representations[PROP_KIND_NUMBER] = { |
| 91 Representation::None(), Representation::Smi(), Representation::Double(), | 91 Representation::None(), Representation::Smi(), Representation::Double(), |
| 92 Representation::Tagged()}; | 92 Representation::Tagged()}; |
| 93 | 93 |
| 94 | 94 |
| 95 static Handle<DescriptorArray> CreateDescriptorArray(Isolate* isolate, | 95 static Handle<DescriptorArray> CreateDescriptorArray(Isolate* isolate, |
| 96 TestPropertyKind* props, | 96 TestPropertyKind* props, |
| 97 int kPropsCount) { | 97 int kPropsCount) { |
| 98 Factory* factory = isolate->factory(); | 98 Factory* factory = isolate->factory(); |
| 99 | 99 |
| 100 Handle<String> func_name = factory->InternalizeUtf8String("func"); | |
| 101 Handle<JSFunction> func = factory->NewFunction(func_name); | |
| 102 | |
| 103 Handle<DescriptorArray> descriptors = | 100 Handle<DescriptorArray> descriptors = |
| 104 DescriptorArray::Allocate(isolate, 0, kPropsCount); | 101 DescriptorArray::Allocate(isolate, 0, kPropsCount); |
| 105 | 102 |
| 106 int next_field_offset = 0; | 103 int next_field_offset = 0; |
| 107 for (int i = 0; i < kPropsCount; i++) { | 104 for (int i = 0; i < kPropsCount; i++) { |
| 108 EmbeddedVector<char, 64> buffer; | 105 EmbeddedVector<char, 64> buffer; |
| 109 SNPrintF(buffer, "prop%d", i); | 106 SNPrintF(buffer, "prop%d", i); |
| 110 Handle<String> name = factory->InternalizeUtf8String(buffer.start()); | 107 Handle<String> name = factory->InternalizeUtf8String(buffer.start()); |
| 111 | 108 |
| 112 TestPropertyKind kind = props[i]; | 109 TestPropertyKind kind = props[i]; |
| 113 | 110 |
| 114 if (kind == PROP_CONSTANT) { | 111 Descriptor d; |
| 115 Descriptor d = Descriptor::DataConstant(name, func, NONE); | 112 if (kind == PROP_ACCESSOR_INFO) { |
| 116 descriptors->Append(&d); | 113 Handle<AccessorInfo> info = |
| 114 Accessors::MakeAccessor(isolate, name, nullptr, nullptr, NONE); |
| 115 d = Descriptor::AccessorConstant(name, info, NONE); |
| 117 | 116 |
| 118 } else { | 117 } else { |
| 119 Descriptor d = Descriptor::DataField(name, next_field_offset, NONE, | 118 d = Descriptor::DataField(name, next_field_offset, NONE, |
| 120 representations[kind]); | 119 representations[kind]); |
| 121 next_field_offset += d.GetDetails().field_width_in_words(); | 120 } |
| 122 descriptors->Append(&d); | 121 descriptors->Append(&d); |
| 122 PropertyDetails details = d.GetDetails(); |
| 123 if (details.location() == kField) { |
| 124 next_field_offset += details.field_width_in_words(); |
| 123 } | 125 } |
| 124 } | 126 } |
| 125 return descriptors; | 127 return descriptors; |
| 126 } | 128 } |
| 127 | 129 |
| 128 | 130 |
| 129 TEST(LayoutDescriptorBasicFast) { | 131 TEST(LayoutDescriptorBasicFast) { |
| 130 CcTest::InitializeVM(); | 132 CcTest::InitializeVM(); |
| 131 v8::HandleScope scope(CcTest::isolate()); | 133 v8::HandleScope scope(CcTest::isolate()); |
| 132 | 134 |
| (...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 481 } | 483 } |
| 482 | 484 |
| 483 | 485 |
| 484 TEST(LayoutDescriptorCreateNewFast) { | 486 TEST(LayoutDescriptorCreateNewFast) { |
| 485 CcTest::InitializeVM(); | 487 CcTest::InitializeVM(); |
| 486 Isolate* isolate = CcTest::i_isolate(); | 488 Isolate* isolate = CcTest::i_isolate(); |
| 487 v8::HandleScope scope(CcTest::isolate()); | 489 v8::HandleScope scope(CcTest::isolate()); |
| 488 | 490 |
| 489 Handle<LayoutDescriptor> layout_descriptor; | 491 Handle<LayoutDescriptor> layout_descriptor; |
| 490 TestPropertyKind props[] = { | 492 TestPropertyKind props[] = { |
| 491 PROP_CONSTANT, | 493 PROP_ACCESSOR_INFO, |
| 492 PROP_TAGGED, // field #0 | 494 PROP_TAGGED, // field #0 |
| 493 PROP_CONSTANT, | 495 PROP_ACCESSOR_INFO, |
| 494 PROP_DOUBLE, // field #1 | 496 PROP_DOUBLE, // field #1 |
| 495 PROP_CONSTANT, | 497 PROP_ACCESSOR_INFO, |
| 496 PROP_TAGGED, // field #2 | 498 PROP_TAGGED, // field #2 |
| 497 PROP_CONSTANT, | 499 PROP_ACCESSOR_INFO, |
| 498 }; | 500 }; |
| 499 const int kPropsCount = arraysize(props); | 501 const int kPropsCount = arraysize(props); |
| 500 | 502 |
| 501 Handle<DescriptorArray> descriptors = | 503 Handle<DescriptorArray> descriptors = |
| 502 CreateDescriptorArray(isolate, props, kPropsCount); | 504 CreateDescriptorArray(isolate, props, kPropsCount); |
| 503 | 505 |
| 504 { | 506 { |
| 505 Handle<Map> map = Map::Create(isolate, 0); | 507 Handle<Map> map = Map::Create(isolate, 0); |
| 506 layout_descriptor = LayoutDescriptor::New(map, descriptors, kPropsCount); | 508 layout_descriptor = LayoutDescriptor::New(map, descriptors, kPropsCount); |
| 507 CHECK_EQ(LayoutDescriptor::FastPointerLayout(), *layout_descriptor); | 509 CHECK_EQ(LayoutDescriptor::FastPointerLayout(), *layout_descriptor); |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 609 CHECK_EQ(layout_desc, LayoutDescriptor::cast(layout_desc)); | 611 CHECK_EQ(layout_desc, LayoutDescriptor::cast(layout_desc)); |
| 610 } | 612 } |
| 611 } | 613 } |
| 612 | 614 |
| 613 | 615 |
| 614 static Handle<LayoutDescriptor> TestLayoutDescriptorAppend( | 616 static Handle<LayoutDescriptor> TestLayoutDescriptorAppend( |
| 615 Isolate* isolate, int inobject_properties, TestPropertyKind* props, | 617 Isolate* isolate, int inobject_properties, TestPropertyKind* props, |
| 616 int kPropsCount) { | 618 int kPropsCount) { |
| 617 Factory* factory = isolate->factory(); | 619 Factory* factory = isolate->factory(); |
| 618 | 620 |
| 619 Handle<String> func_name = factory->InternalizeUtf8String("func"); | |
| 620 Handle<JSFunction> func = factory->NewFunction(func_name); | |
| 621 | |
| 622 Handle<DescriptorArray> descriptors = | 621 Handle<DescriptorArray> descriptors = |
| 623 DescriptorArray::Allocate(isolate, 0, kPropsCount); | 622 DescriptorArray::Allocate(isolate, 0, kPropsCount); |
| 624 | 623 |
| 625 Handle<Map> map = Map::Create(isolate, inobject_properties); | 624 Handle<Map> map = Map::Create(isolate, inobject_properties); |
| 626 map->InitializeDescriptors(*descriptors, | 625 map->InitializeDescriptors(*descriptors, |
| 627 LayoutDescriptor::FastPointerLayout()); | 626 LayoutDescriptor::FastPointerLayout()); |
| 628 | 627 |
| 629 int next_field_offset = 0; | 628 int next_field_offset = 0; |
| 630 for (int i = 0; i < kPropsCount; i++) { | 629 for (int i = 0; i < kPropsCount; i++) { |
| 631 EmbeddedVector<char, 64> buffer; | 630 EmbeddedVector<char, 64> buffer; |
| 632 SNPrintF(buffer, "prop%d", i); | 631 SNPrintF(buffer, "prop%d", i); |
| 633 Handle<String> name = factory->InternalizeUtf8String(buffer.start()); | 632 Handle<String> name = factory->InternalizeUtf8String(buffer.start()); |
| 634 | 633 |
| 635 Handle<LayoutDescriptor> layout_descriptor; | 634 Handle<LayoutDescriptor> layout_descriptor; |
| 636 TestPropertyKind kind = props[i]; | 635 TestPropertyKind kind = props[i]; |
| 637 if (kind == PROP_CONSTANT) { | 636 Descriptor d; |
| 638 Descriptor d = Descriptor::DataConstant(name, func, NONE); | 637 if (kind == PROP_ACCESSOR_INFO) { |
| 639 layout_descriptor = LayoutDescriptor::ShareAppend(map, d.GetDetails()); | 638 Handle<AccessorInfo> info = |
| 640 descriptors->Append(&d); | 639 Accessors::MakeAccessor(isolate, name, nullptr, nullptr, NONE); |
| 640 d = Descriptor::AccessorConstant(name, info, NONE); |
| 641 | 641 |
| 642 } else { | 642 } else { |
| 643 Descriptor d = Descriptor::DataField(name, next_field_offset, NONE, | 643 d = Descriptor::DataField(name, next_field_offset, NONE, |
| 644 representations[kind]); | 644 representations[kind]); |
| 645 int field_width_in_words = d.GetDetails().field_width_in_words(); | 645 } |
| 646 PropertyDetails details = d.GetDetails(); |
| 647 layout_descriptor = LayoutDescriptor::ShareAppend(map, details); |
| 648 descriptors->Append(&d); |
| 649 if (details.location() == kField) { |
| 650 int field_width_in_words = details.field_width_in_words(); |
| 646 next_field_offset += field_width_in_words; | 651 next_field_offset += field_width_in_words; |
| 647 layout_descriptor = LayoutDescriptor::ShareAppend(map, d.GetDetails()); | |
| 648 descriptors->Append(&d); | |
| 649 | 652 |
| 650 int field_index = d.GetDetails().field_index(); | 653 int field_index = details.field_index(); |
| 651 bool is_inobject = field_index < map->GetInObjectProperties(); | 654 bool is_inobject = field_index < map->GetInObjectProperties(); |
| 652 for (int bit = 0; bit < field_width_in_words; bit++) { | 655 for (int bit = 0; bit < field_width_in_words; bit++) { |
| 653 CHECK_EQ(is_inobject && (kind == PROP_DOUBLE), | 656 CHECK_EQ(is_inobject && (kind == PROP_DOUBLE), |
| 654 !layout_descriptor->IsTagged(field_index + bit)); | 657 !layout_descriptor->IsTagged(field_index + bit)); |
| 655 } | 658 } |
| 656 CHECK(layout_descriptor->IsTagged(next_field_offset)); | 659 CHECK(layout_descriptor->IsTagged(next_field_offset)); |
| 657 } | 660 } |
| 658 map->InitializeDescriptors(*descriptors, *layout_descriptor); | 661 map->InitializeDescriptors(*descriptors, *layout_descriptor); |
| 659 } | 662 } |
| 660 Handle<LayoutDescriptor> layout_descriptor(map->layout_descriptor(), isolate); | 663 Handle<LayoutDescriptor> layout_descriptor(map->layout_descriptor(), isolate); |
| (...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 951 v8::HandleScope scope(CcTest::isolate()); | 954 v8::HandleScope scope(CcTest::isolate()); |
| 952 Isolate* isolate = CcTest::i_isolate(); | 955 Isolate* isolate = CcTest::i_isolate(); |
| 953 | 956 |
| 954 const int kFieldCount = 128; | 957 const int kFieldCount = 128; |
| 955 const int kSplitFieldIndex = 32; | 958 const int kSplitFieldIndex = 32; |
| 956 const int kTrimmedLayoutDescriptorLength = 64; | 959 const int kTrimmedLayoutDescriptorLength = 64; |
| 957 | 960 |
| 958 Handle<FieldType> any_type = FieldType::Any(isolate); | 961 Handle<FieldType> any_type = FieldType::Any(isolate); |
| 959 Handle<Map> map = Map::Create(isolate, kFieldCount); | 962 Handle<Map> map = Map::Create(isolate, kFieldCount); |
| 960 for (int i = 0; i < kSplitFieldIndex; i++) { | 963 for (int i = 0; i < kSplitFieldIndex; i++) { |
| 961 map = Map::CopyWithField(map, MakeName("prop", i), any_type, NONE, | 964 map = Map::CopyWithField(map, MakeName("prop", i), any_type, NONE, kMutable, |
| 962 Representation::Smi(), | 965 Representation::Smi(), INSERT_TRANSITION) |
| 963 INSERT_TRANSITION).ToHandleChecked(); | 966 .ToHandleChecked(); |
| 964 } | 967 } |
| 965 map = Map::CopyWithField(map, MakeName("dbl", kSplitFieldIndex), any_type, | 968 map = |
| 966 NONE, Representation::Double(), | 969 Map::CopyWithField(map, MakeName("dbl", kSplitFieldIndex), any_type, NONE, |
| 967 INSERT_TRANSITION).ToHandleChecked(); | 970 kMutable, Representation::Double(), INSERT_TRANSITION) |
| 971 .ToHandleChecked(); |
| 968 CHECK(map->layout_descriptor()->IsConsistentWithMap(*map, true)); | 972 CHECK(map->layout_descriptor()->IsConsistentWithMap(*map, true)); |
| 969 CHECK(map->layout_descriptor()->IsSlowLayout()); | 973 CHECK(map->layout_descriptor()->IsSlowLayout()); |
| 970 CHECK(map->owns_descriptors()); | 974 CHECK(map->owns_descriptors()); |
| 971 CHECK_EQ(2, map->layout_descriptor()->length()); | 975 CHECK_EQ(2, map->layout_descriptor()->length()); |
| 972 | 976 |
| 973 { | 977 { |
| 974 // Add transitions to double fields. | 978 // Add transitions to double fields. |
| 975 v8::HandleScope scope(CcTest::isolate()); | 979 v8::HandleScope scope(CcTest::isolate()); |
| 976 | 980 |
| 977 Handle<Map> tmp_map = map; | 981 Handle<Map> tmp_map = map; |
| 978 for (int i = kSplitFieldIndex + 1; i < kFieldCount; i++) { | 982 for (int i = kSplitFieldIndex + 1; i < kFieldCount; i++) { |
| 979 tmp_map = Map::CopyWithField(tmp_map, MakeName("dbl", i), any_type, NONE, | 983 tmp_map = Map::CopyWithField(tmp_map, MakeName("dbl", i), any_type, NONE, |
| 980 Representation::Double(), | 984 kMutable, Representation::Double(), |
| 981 INSERT_TRANSITION).ToHandleChecked(); | 985 INSERT_TRANSITION) |
| 986 .ToHandleChecked(); |
| 982 CHECK(tmp_map->layout_descriptor()->IsConsistentWithMap(*tmp_map, true)); | 987 CHECK(tmp_map->layout_descriptor()->IsConsistentWithMap(*tmp_map, true)); |
| 983 } | 988 } |
| 984 // Check that descriptors are shared. | 989 // Check that descriptors are shared. |
| 985 CHECK(tmp_map->owns_descriptors()); | 990 CHECK(tmp_map->owns_descriptors()); |
| 986 CHECK_EQ(map->instance_descriptors(), tmp_map->instance_descriptors()); | 991 CHECK_EQ(map->instance_descriptors(), tmp_map->instance_descriptors()); |
| 987 CHECK_EQ(map->layout_descriptor(), tmp_map->layout_descriptor()); | 992 CHECK_EQ(map->layout_descriptor(), tmp_map->layout_descriptor()); |
| 988 } | 993 } |
| 989 CHECK(map->layout_descriptor()->IsSlowLayout()); | 994 CHECK(map->layout_descriptor()->IsSlowLayout()); |
| 990 CHECK_EQ(4, map->layout_descriptor()->length()); | 995 CHECK_EQ(4, map->layout_descriptor()->length()); |
| 991 | 996 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1009 CHECK(map->layout_descriptor()->IsSlowLayout()); | 1014 CHECK(map->layout_descriptor()->IsSlowLayout()); |
| 1010 CHECK_EQ(2, map->layout_descriptor()->length()); | 1015 CHECK_EQ(2, map->layout_descriptor()->length()); |
| 1011 | 1016 |
| 1012 { | 1017 { |
| 1013 // Add transitions to tagged fields. | 1018 // Add transitions to tagged fields. |
| 1014 v8::HandleScope scope(CcTest::isolate()); | 1019 v8::HandleScope scope(CcTest::isolate()); |
| 1015 | 1020 |
| 1016 Handle<Map> tmp_map = map; | 1021 Handle<Map> tmp_map = map; |
| 1017 for (int i = kSplitFieldIndex + 1; i < kFieldCount - 1; i++) { | 1022 for (int i = kSplitFieldIndex + 1; i < kFieldCount - 1; i++) { |
| 1018 tmp_map = Map::CopyWithField(tmp_map, MakeName("tagged", i), any_type, | 1023 tmp_map = Map::CopyWithField(tmp_map, MakeName("tagged", i), any_type, |
| 1019 NONE, Representation::Tagged(), | 1024 NONE, kMutable, Representation::Tagged(), |
| 1020 INSERT_TRANSITION).ToHandleChecked(); | 1025 INSERT_TRANSITION) |
| 1026 .ToHandleChecked(); |
| 1021 CHECK(tmp_map->layout_descriptor()->IsConsistentWithMap(*tmp_map, true)); | 1027 CHECK(tmp_map->layout_descriptor()->IsConsistentWithMap(*tmp_map, true)); |
| 1022 } | 1028 } |
| 1023 tmp_map = Map::CopyWithField(tmp_map, MakeString("dbl"), any_type, NONE, | 1029 tmp_map = |
| 1024 Representation::Double(), | 1030 Map::CopyWithField(tmp_map, MakeString("dbl"), any_type, NONE, kMutable, |
| 1025 INSERT_TRANSITION).ToHandleChecked(); | 1031 Representation::Double(), INSERT_TRANSITION) |
| 1032 .ToHandleChecked(); |
| 1026 CHECK(tmp_map->layout_descriptor()->IsConsistentWithMap(*tmp_map, true)); | 1033 CHECK(tmp_map->layout_descriptor()->IsConsistentWithMap(*tmp_map, true)); |
| 1027 // Check that descriptors are shared. | 1034 // Check that descriptors are shared. |
| 1028 CHECK(tmp_map->owns_descriptors()); | 1035 CHECK(tmp_map->owns_descriptors()); |
| 1029 CHECK_EQ(map->instance_descriptors(), tmp_map->instance_descriptors()); | 1036 CHECK_EQ(map->instance_descriptors(), tmp_map->instance_descriptors()); |
| 1030 } | 1037 } |
| 1031 CHECK(map->layout_descriptor()->IsSlowLayout()); | 1038 CHECK(map->layout_descriptor()->IsSlowLayout()); |
| 1032 } | 1039 } |
| 1033 | 1040 |
| 1034 | 1041 |
| 1035 TEST(DoScavenge) { | 1042 TEST(DoScavenge) { |
| 1036 CcTest::InitializeVM(); | 1043 CcTest::InitializeVM(); |
| 1037 v8::HandleScope scope(CcTest::isolate()); | 1044 v8::HandleScope scope(CcTest::isolate()); |
| 1038 Isolate* isolate = CcTest::i_isolate(); | 1045 Isolate* isolate = CcTest::i_isolate(); |
| 1039 Factory* factory = isolate->factory(); | 1046 Factory* factory = isolate->factory(); |
| 1040 | 1047 |
| 1041 // The plan: create |obj| with double field in new space, do scanvenge so | 1048 // The plan: create |obj| with double field in new space, do scanvenge so |
| 1042 // that |obj| is moved to old space, construct a double value that looks like | 1049 // that |obj| is moved to old space, construct a double value that looks like |
| 1043 // a pointer to "from space" pointer. Do scavenge one more time and ensure | 1050 // a pointer to "from space" pointer. Do scavenge one more time and ensure |
| 1044 // that it didn't crash or corrupt the double value stored in the object. | 1051 // that it didn't crash or corrupt the double value stored in the object. |
| 1045 | 1052 |
| 1046 Handle<FieldType> any_type = FieldType::Any(isolate); | 1053 Handle<FieldType> any_type = FieldType::Any(isolate); |
| 1047 Handle<Map> map = Map::Create(isolate, 10); | 1054 Handle<Map> map = Map::Create(isolate, 10); |
| 1048 map = Map::CopyWithField(map, MakeName("prop", 0), any_type, NONE, | 1055 map = Map::CopyWithField(map, MakeName("prop", 0), any_type, NONE, kMutable, |
| 1049 Representation::Double(), | 1056 Representation::Double(), INSERT_TRANSITION) |
| 1050 INSERT_TRANSITION).ToHandleChecked(); | 1057 .ToHandleChecked(); |
| 1051 | 1058 |
| 1052 // Create object in new space. | 1059 // Create object in new space. |
| 1053 Handle<JSObject> obj = factory->NewJSObjectFromMap(map, NOT_TENURED); | 1060 Handle<JSObject> obj = factory->NewJSObjectFromMap(map, NOT_TENURED); |
| 1054 | 1061 |
| 1055 Handle<HeapNumber> heap_number = factory->NewHeapNumber(42.5); | 1062 Handle<HeapNumber> heap_number = factory->NewHeapNumber(42.5); |
| 1056 WriteToField(*obj, 0, *heap_number); | 1063 WriteToField(*obj, 0, *heap_number); |
| 1057 | 1064 |
| 1058 { | 1065 { |
| 1059 // Ensure the object is properly set up. | 1066 // Ensure the object is properly set up. |
| 1060 FieldIndex field_index = FieldIndex::ForDescriptor(*map, 0); | 1067 FieldIndex field_index = FieldIndex::ForDescriptor(*map, 0); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1100 PagedSpace* old_space = heap->old_space(); | 1107 PagedSpace* old_space = heap->old_space(); |
| 1101 | 1108 |
| 1102 // The plan: create |obj_value| in old space and ensure that it is allocated | 1109 // The plan: create |obj_value| in old space and ensure that it is allocated |
| 1103 // on evacuation candidate page, create |obj| with double and tagged fields | 1110 // on evacuation candidate page, create |obj| with double and tagged fields |
| 1104 // in new space and write |obj_value| to tagged field of |obj|, do two | 1111 // in new space and write |obj_value| to tagged field of |obj|, do two |
| 1105 // scavenges to promote |obj| to old space, a GC in old space and ensure that | 1112 // scavenges to promote |obj| to old space, a GC in old space and ensure that |
| 1106 // the tagged value was properly updated after candidates evacuation. | 1113 // the tagged value was properly updated after candidates evacuation. |
| 1107 | 1114 |
| 1108 Handle<FieldType> any_type = FieldType::Any(isolate); | 1115 Handle<FieldType> any_type = FieldType::Any(isolate); |
| 1109 Handle<Map> map = Map::Create(isolate, 10); | 1116 Handle<Map> map = Map::Create(isolate, 10); |
| 1110 map = Map::CopyWithField(map, MakeName("prop", 0), any_type, NONE, | 1117 map = Map::CopyWithField(map, MakeName("prop", 0), any_type, NONE, kMutable, |
| 1111 Representation::Double(), | 1118 Representation::Double(), INSERT_TRANSITION) |
| 1112 INSERT_TRANSITION).ToHandleChecked(); | 1119 .ToHandleChecked(); |
| 1113 map = Map::CopyWithField(map, MakeName("prop", 1), any_type, NONE, | 1120 map = Map::CopyWithField(map, MakeName("prop", 1), any_type, NONE, kMutable, |
| 1114 Representation::Tagged(), | 1121 Representation::Tagged(), INSERT_TRANSITION) |
| 1115 INSERT_TRANSITION).ToHandleChecked(); | 1122 .ToHandleChecked(); |
| 1116 | 1123 |
| 1117 // Create |obj_value| in old space. | 1124 // Create |obj_value| in old space. |
| 1118 Handle<HeapObject> obj_value; | 1125 Handle<HeapObject> obj_value; |
| 1119 Page* ec_page; | 1126 Page* ec_page; |
| 1120 { | 1127 { |
| 1121 AlwaysAllocateScope always_allocate(isolate); | 1128 AlwaysAllocateScope always_allocate(isolate); |
| 1122 // Make sure |obj_value| is placed on an old-space evacuation candidate. | 1129 // Make sure |obj_value| is placed on an old-space evacuation candidate. |
| 1123 heap::SimulateFullSpace(old_space); | 1130 heap::SimulateFullSpace(old_space); |
| 1124 obj_value = factory->NewJSArray(32 * KB, FAST_HOLEY_ELEMENTS, TENURED); | 1131 obj_value = factory->NewJSArray(32 * KB, FAST_HOLEY_ELEMENTS, TENURED); |
| 1125 ec_page = Page::FromAddress(obj_value->address()); | 1132 ec_page = Page::FromAddress(obj_value->address()); |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1328 CcTest::InitializeVM(); | 1335 CcTest::InitializeVM(); |
| 1329 v8::HandleScope scope(CcTest::isolate()); | 1336 v8::HandleScope scope(CcTest::isolate()); |
| 1330 Isolate* isolate = CcTest::i_isolate(); | 1337 Isolate* isolate = CcTest::i_isolate(); |
| 1331 Handle<FieldType> any_type = FieldType::Any(isolate); | 1338 Handle<FieldType> any_type = FieldType::Any(isolate); |
| 1332 | 1339 |
| 1333 Handle<Map> split_map; | 1340 Handle<Map> split_map; |
| 1334 { | 1341 { |
| 1335 Handle<Map> map = Map::Create(isolate, 64); | 1342 Handle<Map> map = Map::Create(isolate, 64); |
| 1336 for (int i = 0; i < 32; i++) { | 1343 for (int i = 0; i < 32; i++) { |
| 1337 Handle<String> name = MakeName("prop", i); | 1344 Handle<String> name = MakeName("prop", i); |
| 1338 map = Map::CopyWithField(map, name, any_type, NONE, Representation::Smi(), | 1345 map = Map::CopyWithField(map, name, any_type, NONE, kMutable, |
| 1339 INSERT_TRANSITION).ToHandleChecked(); | 1346 Representation::Smi(), INSERT_TRANSITION) |
| 1347 .ToHandleChecked(); |
| 1340 } | 1348 } |
| 1341 split_map = Map::CopyWithField(map, MakeString("dbl"), any_type, NONE, | 1349 split_map = |
| 1342 Representation::Double(), | 1350 Map::CopyWithField(map, MakeString("dbl"), any_type, NONE, kMutable, |
| 1343 INSERT_TRANSITION).ToHandleChecked(); | 1351 Representation::Double(), INSERT_TRANSITION) |
| 1352 .ToHandleChecked(); |
| 1344 } | 1353 } |
| 1345 Handle<LayoutDescriptor> split_layout_descriptor( | 1354 Handle<LayoutDescriptor> split_layout_descriptor( |
| 1346 split_map->layout_descriptor(), isolate); | 1355 split_map->layout_descriptor(), isolate); |
| 1347 CHECK(split_layout_descriptor->IsConsistentWithMap(*split_map, true)); | 1356 CHECK(split_layout_descriptor->IsConsistentWithMap(*split_map, true)); |
| 1348 CHECK(split_layout_descriptor->IsSlowLayout()); | 1357 CHECK(split_layout_descriptor->IsSlowLayout()); |
| 1349 CHECK(split_map->owns_descriptors()); | 1358 CHECK(split_map->owns_descriptors()); |
| 1350 | 1359 |
| 1351 Handle<Map> map1 = Map::CopyWithField(split_map, MakeString("foo"), any_type, | 1360 Handle<Map> map1 = |
| 1352 NONE, Representation::Double(), | 1361 Map::CopyWithField(split_map, MakeString("foo"), any_type, NONE, kMutable, |
| 1353 INSERT_TRANSITION).ToHandleChecked(); | 1362 Representation::Double(), INSERT_TRANSITION) |
| 1363 .ToHandleChecked(); |
| 1354 CHECK(!split_map->owns_descriptors()); | 1364 CHECK(!split_map->owns_descriptors()); |
| 1355 CHECK_EQ(*split_layout_descriptor, split_map->layout_descriptor()); | 1365 CHECK_EQ(*split_layout_descriptor, split_map->layout_descriptor()); |
| 1356 | 1366 |
| 1357 // Layout descriptors should be shared with |split_map|. | 1367 // Layout descriptors should be shared with |split_map|. |
| 1358 CHECK(map1->owns_descriptors()); | 1368 CHECK(map1->owns_descriptors()); |
| 1359 CHECK_EQ(*split_layout_descriptor, map1->layout_descriptor()); | 1369 CHECK_EQ(*split_layout_descriptor, map1->layout_descriptor()); |
| 1360 CHECK(map1->layout_descriptor()->IsConsistentWithMap(*map1, true)); | 1370 CHECK(map1->layout_descriptor()->IsConsistentWithMap(*map1, true)); |
| 1361 | 1371 |
| 1362 Handle<Map> map2 = Map::CopyWithField(split_map, MakeString("bar"), any_type, | 1372 Handle<Map> map2 = |
| 1363 NONE, Representation::Tagged(), | 1373 Map::CopyWithField(split_map, MakeString("bar"), any_type, NONE, kMutable, |
| 1364 INSERT_TRANSITION).ToHandleChecked(); | 1374 Representation::Tagged(), INSERT_TRANSITION) |
| 1375 .ToHandleChecked(); |
| 1365 | 1376 |
| 1366 // Layout descriptors should not be shared with |split_map|. | 1377 // Layout descriptors should not be shared with |split_map|. |
| 1367 CHECK(map2->owns_descriptors()); | 1378 CHECK(map2->owns_descriptors()); |
| 1368 CHECK_NE(*split_layout_descriptor, map2->layout_descriptor()); | 1379 CHECK_NE(*split_layout_descriptor, map2->layout_descriptor()); |
| 1369 CHECK(map2->layout_descriptor()->IsConsistentWithMap(*map2, true)); | 1380 CHECK(map2->layout_descriptor()->IsConsistentWithMap(*map2, true)); |
| 1370 } | 1381 } |
| 1371 | 1382 |
| 1372 | 1383 |
| 1373 static void TestWriteBarrier(Handle<Map> map, Handle<Map> new_map, | 1384 static void TestWriteBarrier(Handle<Map> map, Handle<Map> new_map, |
| 1374 int tagged_descriptor, int double_descriptor, | 1385 int tagged_descriptor, int double_descriptor, |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1524 | 1535 |
| 1525 Handle<FieldType> any_type = FieldType::Any(isolate); | 1536 Handle<FieldType> any_type = FieldType::Any(isolate); |
| 1526 | 1537 |
| 1527 CompileRun("function func() { return 1; }"); | 1538 CompileRun("function func() { return 1; }"); |
| 1528 | 1539 |
| 1529 Handle<JSObject> func = GetObject("func"); | 1540 Handle<JSObject> func = GetObject("func"); |
| 1530 | 1541 |
| 1531 Handle<Map> map = Map::Create(isolate, 10); | 1542 Handle<Map> map = Map::Create(isolate, 10); |
| 1532 map = Map::CopyWithConstant(map, MakeName("prop", 0), func, NONE, | 1543 map = Map::CopyWithConstant(map, MakeName("prop", 0), func, NONE, |
| 1533 INSERT_TRANSITION).ToHandleChecked(); | 1544 INSERT_TRANSITION).ToHandleChecked(); |
| 1534 map = Map::CopyWithField(map, MakeName("prop", 1), any_type, NONE, | 1545 map = Map::CopyWithField(map, MakeName("prop", 1), any_type, NONE, kMutable, |
| 1535 Representation::Double(), | 1546 Representation::Double(), INSERT_TRANSITION) |
| 1536 INSERT_TRANSITION).ToHandleChecked(); | 1547 .ToHandleChecked(); |
| 1537 map = Map::CopyWithField(map, MakeName("prop", 2), any_type, NONE, | 1548 map = Map::CopyWithField(map, MakeName("prop", 2), any_type, NONE, kMutable, |
| 1538 Representation::Tagged(), | 1549 Representation::Tagged(), INSERT_TRANSITION) |
| 1539 INSERT_TRANSITION).ToHandleChecked(); | 1550 .ToHandleChecked(); |
| 1540 | 1551 |
| 1541 // Shift fields right by turning constant property to a field. | 1552 // Shift fields right by turning constant property to a field. |
| 1542 Handle<Map> new_map = Map::ReconfigureProperty( | 1553 Handle<Map> new_map = Map::ReconfigureProperty( |
| 1543 map, 0, kData, NONE, Representation::Tagged(), any_type); | 1554 map, 0, kData, NONE, Representation::Tagged(), any_type); |
| 1544 | 1555 |
| 1545 if (write_barrier_kind == OLD_TO_NEW_WRITE_BARRIER) { | 1556 if (write_barrier_kind == OLD_TO_NEW_WRITE_BARRIER) { |
| 1546 TestWriteBarrier(map, new_map, 2, 1); | 1557 TestWriteBarrier(map, new_map, 2, 1); |
| 1547 } else { | 1558 } else { |
| 1548 CHECK_EQ(OLD_TO_OLD_WRITE_BARRIER, write_barrier_kind); | 1559 CHECK_EQ(OLD_TO_OLD_WRITE_BARRIER, write_barrier_kind); |
| 1549 TestIncrementalWriteBarrier(map, new_map, 2, 1); | 1560 TestIncrementalWriteBarrier(map, new_map, 2, 1); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1562 | 1573 |
| 1563 // TODO(ishell): add respective tests for property kind reconfiguring from | 1574 // TODO(ishell): add respective tests for property kind reconfiguring from |
| 1564 // accessor field to double, once accessor fields are supported by | 1575 // accessor field to double, once accessor fields are supported by |
| 1565 // Map::ReconfigureProperty(). | 1576 // Map::ReconfigureProperty(). |
| 1566 | 1577 |
| 1567 | 1578 |
| 1568 // TODO(ishell): add respective tests for fast property removal case once | 1579 // TODO(ishell): add respective tests for fast property removal case once |
| 1569 // Map::ReconfigureProperty() supports that. | 1580 // Map::ReconfigureProperty() supports that. |
| 1570 | 1581 |
| 1571 #endif | 1582 #endif |
| OLD | NEW |