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" |
11 #include "src/execution.h" | 11 #include "src/execution.h" |
12 #include "src/factory.h" | 12 #include "src/factory.h" |
13 #include "src/global-handles.h" | 13 #include "src/global-handles.h" |
14 #include "src/ic/ic.h" | 14 #include "src/ic/ic.h" |
15 #include "src/macro-assembler.h" | 15 #include "src/macro-assembler.h" |
16 #include "test/cctest/cctest.h" | 16 #include "test/cctest/cctest.h" |
17 | 17 |
18 using namespace v8::base; | 18 using namespace v8::base; |
19 using namespace v8::internal; | 19 using namespace v8::internal; |
20 | 20 |
21 #if (V8_DOUBLE_FIELDS_UNBOXING) | 21 #if (V8_DOUBLE_FIELDS_UNBOXING) |
22 | 22 |
23 | 23 |
| 24 // |
| 25 // Helper functions. |
| 26 // |
| 27 |
| 28 static Handle<String> MakeString(const char* str) { |
| 29 Isolate* isolate = CcTest::i_isolate(); |
| 30 Factory* factory = isolate->factory(); |
| 31 return factory->InternalizeUtf8String(str); |
| 32 } |
| 33 |
| 34 |
| 35 static Handle<String> MakeName(const char* str, int suffix) { |
| 36 EmbeddedVector<char, 128> buffer; |
| 37 SNPrintF(buffer, "%s%d", str, suffix); |
| 38 return MakeString(buffer.start()); |
| 39 } |
| 40 |
| 41 |
24 static double GetDoubleFieldValue(JSObject* obj, FieldIndex field_index) { | 42 static double GetDoubleFieldValue(JSObject* obj, FieldIndex field_index) { |
25 if (obj->IsUnboxedDoubleField(field_index)) { | 43 if (obj->IsUnboxedDoubleField(field_index)) { |
26 return obj->RawFastDoublePropertyAt(field_index); | 44 return obj->RawFastDoublePropertyAt(field_index); |
27 } else { | 45 } else { |
28 Object* value = obj->RawFastPropertyAt(field_index); | 46 Object* value = obj->RawFastPropertyAt(field_index); |
29 DCHECK(value->IsMutableHeapNumber()); | 47 DCHECK(value->IsMutableHeapNumber()); |
30 return HeapNumber::cast(value)->value(); | 48 return HeapNumber::cast(value)->value(); |
31 } | 49 } |
32 } | 50 } |
33 | 51 |
(...skipping 560 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
594 int next_field_offset = 0; | 612 int next_field_offset = 0; |
595 for (int i = 0; i < kPropsCount; i++) { | 613 for (int i = 0; i < kPropsCount; i++) { |
596 EmbeddedVector<char, 64> buffer; | 614 EmbeddedVector<char, 64> buffer; |
597 SNPrintF(buffer, "prop%d", i); | 615 SNPrintF(buffer, "prop%d", i); |
598 Handle<String> name = factory->InternalizeUtf8String(buffer.start()); | 616 Handle<String> name = factory->InternalizeUtf8String(buffer.start()); |
599 | 617 |
600 Handle<LayoutDescriptor> layout_descriptor; | 618 Handle<LayoutDescriptor> layout_descriptor; |
601 TestPropertyKind kind = props[i]; | 619 TestPropertyKind kind = props[i]; |
602 if (kind == PROP_CONSTANT) { | 620 if (kind == PROP_CONSTANT) { |
603 DataConstantDescriptor d(name, func, NONE); | 621 DataConstantDescriptor d(name, func, NONE); |
604 layout_descriptor = LayoutDescriptor::Append(map, d.GetDetails()); | 622 layout_descriptor = LayoutDescriptor::ShareAppend(map, d.GetDetails()); |
605 descriptors->Append(&d); | 623 descriptors->Append(&d); |
606 | 624 |
607 } else { | 625 } else { |
608 DataDescriptor f(name, next_field_offset, NONE, representations[kind]); | 626 DataDescriptor f(name, next_field_offset, NONE, representations[kind]); |
609 int field_width_in_words = f.GetDetails().field_width_in_words(); | 627 int field_width_in_words = f.GetDetails().field_width_in_words(); |
610 next_field_offset += field_width_in_words; | 628 next_field_offset += field_width_in_words; |
611 layout_descriptor = LayoutDescriptor::Append(map, f.GetDetails()); | 629 layout_descriptor = LayoutDescriptor::ShareAppend(map, f.GetDetails()); |
612 descriptors->Append(&f); | 630 descriptors->Append(&f); |
613 | 631 |
614 int field_index = f.GetDetails().field_index(); | 632 int field_index = f.GetDetails().field_index(); |
615 bool is_inobject = field_index < map->inobject_properties(); | 633 bool is_inobject = field_index < map->inobject_properties(); |
616 for (int bit = 0; bit < field_width_in_words; bit++) { | 634 for (int bit = 0; bit < field_width_in_words; bit++) { |
617 CHECK_EQ(is_inobject && (kind == PROP_DOUBLE), | 635 CHECK_EQ(is_inobject && (kind == PROP_DOUBLE), |
618 !layout_descriptor->IsTagged(field_index + bit)); | 636 !layout_descriptor->IsTagged(field_index + bit)); |
619 } | 637 } |
620 CHECK(layout_descriptor->IsTagged(next_field_offset)); | 638 CHECK(layout_descriptor->IsTagged(next_field_offset)); |
621 } | 639 } |
(...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1089 | 1107 |
1090 TestLayoutDescriptorHelper(isolate, kSmiValueSize, descriptors, kPropsCount); | 1108 TestLayoutDescriptorHelper(isolate, kSmiValueSize, descriptors, kPropsCount); |
1091 | 1109 |
1092 TestLayoutDescriptorHelper(isolate, kSmiValueSize * 2, descriptors, | 1110 TestLayoutDescriptorHelper(isolate, kSmiValueSize * 2, descriptors, |
1093 kPropsCount); | 1111 kPropsCount); |
1094 | 1112 |
1095 TestLayoutDescriptorHelper(isolate, kPropsCount, descriptors, kPropsCount); | 1113 TestLayoutDescriptorHelper(isolate, kPropsCount, descriptors, kPropsCount); |
1096 } | 1114 } |
1097 | 1115 |
1098 | 1116 |
| 1117 TEST(LayoutDescriptorSharing) { |
| 1118 CcTest::InitializeVM(); |
| 1119 v8::HandleScope scope(CcTest::isolate()); |
| 1120 Isolate* isolate = CcTest::i_isolate(); |
| 1121 Handle<HeapType> any_type = HeapType::Any(isolate); |
| 1122 |
| 1123 Handle<Map> split_map; |
| 1124 { |
| 1125 Handle<Map> map = Map::Create(isolate, 64); |
| 1126 for (int i = 0; i < 32; i++) { |
| 1127 Handle<String> name = MakeName("prop", i); |
| 1128 map = Map::CopyWithField(map, name, any_type, NONE, Representation::Smi(), |
| 1129 INSERT_TRANSITION).ToHandleChecked(); |
| 1130 } |
| 1131 split_map = Map::CopyWithField(map, MakeString("dbl"), any_type, NONE, |
| 1132 Representation::Double(), |
| 1133 INSERT_TRANSITION).ToHandleChecked(); |
| 1134 } |
| 1135 Handle<LayoutDescriptor> split_layout_descriptor( |
| 1136 split_map->layout_descriptor(), isolate); |
| 1137 DCHECK(split_layout_descriptor->IsConsistentWithMap(*split_map)); |
| 1138 CHECK(split_layout_descriptor->IsSlowLayout()); |
| 1139 CHECK(split_map->owns_descriptors()); |
| 1140 |
| 1141 Handle<Map> map1 = Map::CopyWithField(split_map, MakeString("foo"), any_type, |
| 1142 NONE, Representation::Double(), |
| 1143 INSERT_TRANSITION).ToHandleChecked(); |
| 1144 CHECK(!split_map->owns_descriptors()); |
| 1145 CHECK_EQ(*split_layout_descriptor, split_map->layout_descriptor()); |
| 1146 |
| 1147 // Layout descriptors should be shared with |split_map|. |
| 1148 CHECK(map1->owns_descriptors()); |
| 1149 CHECK_EQ(*split_layout_descriptor, map1->layout_descriptor()); |
| 1150 DCHECK(map1->layout_descriptor()->IsConsistentWithMap(*map1)); |
| 1151 |
| 1152 Handle<Map> map2 = Map::CopyWithField(split_map, MakeString("bar"), any_type, |
| 1153 NONE, Representation::Tagged(), |
| 1154 INSERT_TRANSITION).ToHandleChecked(); |
| 1155 |
| 1156 // Layout descriptors should not be shared with |split_map|. |
| 1157 CHECK(map2->owns_descriptors()); |
| 1158 CHECK_NE(*split_layout_descriptor, map2->layout_descriptor()); |
| 1159 DCHECK(map2->layout_descriptor()->IsConsistentWithMap(*map2)); |
| 1160 } |
| 1161 |
| 1162 |
1099 TEST(StoreBufferScanOnScavenge) { | 1163 TEST(StoreBufferScanOnScavenge) { |
1100 CcTest::InitializeVM(); | 1164 CcTest::InitializeVM(); |
1101 Isolate* isolate = CcTest::i_isolate(); | 1165 Isolate* isolate = CcTest::i_isolate(); |
1102 Factory* factory = isolate->factory(); | 1166 Factory* factory = isolate->factory(); |
1103 v8::HandleScope scope(CcTest::isolate()); | 1167 v8::HandleScope scope(CcTest::isolate()); |
1104 | 1168 |
1105 CompileRun( | 1169 CompileRun( |
1106 "function A() {" | 1170 "function A() {" |
1107 " this.x = 42.5;" | 1171 " this.x = 42.5;" |
1108 " this.o = {};" | 1172 " this.o = {};" |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1153 MemoryChunk* chunk = MemoryChunk::FromAddress(obj->address()); | 1217 MemoryChunk* chunk = MemoryChunk::FromAddress(obj->address()); |
1154 chunk->set_scan_on_scavenge(true); | 1218 chunk->set_scan_on_scavenge(true); |
1155 | 1219 |
1156 // Trigger GCs and force evacuation. Should not crash there. | 1220 // Trigger GCs and force evacuation. Should not crash there. |
1157 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags); | 1221 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags); |
1158 | 1222 |
1159 CHECK_EQ(boom_value, GetDoubleFieldValue(*obj, field_index)); | 1223 CHECK_EQ(boom_value, GetDoubleFieldValue(*obj, field_index)); |
1160 } | 1224 } |
1161 | 1225 |
1162 #endif | 1226 #endif |
OLD | NEW |