Index: test/cctest/test-unboxed-doubles.cc |
diff --git a/test/cctest/test-unboxed-doubles.cc b/test/cctest/test-unboxed-doubles.cc |
index 270cadbfe3144046082f11c903fa865e55b5ba4e..a12bf47f96fcf7a98a506afd2dde2d1ae4c3a004 100644 |
--- a/test/cctest/test-unboxed-doubles.cc |
+++ b/test/cctest/test-unboxed-doubles.cc |
@@ -31,6 +31,8 @@ static double GetDoubleFieldValue(JSObject* obj, FieldIndex field_index) { |
} |
} |
+const int kNumberOfBits = 32; |
+ |
enum TestPropertyKind { |
PROP_CONSTANT, |
@@ -103,6 +105,14 @@ TEST(LayoutDescriptorBasicFast) { |
CHECK_EQ(true, layout_desc->IsTagged(i)); |
} |
CHECK(layout_desc->IsFastPointerLayout()); |
+ |
+ int sequence_length; |
+ CHECK_EQ(true, layout_desc->IsTagged(0, std::numeric_limits<int>::max(), |
+ &sequence_length)); |
+ CHECK_EQ(std::numeric_limits<int>::max(), sequence_length); |
+ |
+ CHECK_EQ(true, layout_desc->IsTagged(0, 7, &sequence_length)); |
+ CHECK_EQ(7, sequence_length); |
} |
@@ -196,6 +206,239 @@ TEST(LayoutDescriptorBasicSlow) { |
} |
+static void TestLayoutDescriptorQueries(int layout_descriptor_length, |
+ int* bit_flip_positions, |
+ int max_sequence_length) { |
+ Handle<LayoutDescriptor> layout_descriptor = LayoutDescriptor::NewForTesting( |
+ CcTest::i_isolate(), layout_descriptor_length); |
+ layout_descriptor_length = layout_descriptor->capacity(); |
+ LayoutDescriptor* layout_desc = *layout_descriptor; |
+ |
+ { |
+ // Fill in the layout descriptor. |
+ int cur_bit_flip_index = 0; |
+ bool tagged = true; |
+ for (int i = 0; i < layout_descriptor_length; i++) { |
+ if (i == bit_flip_positions[cur_bit_flip_index]) { |
+ tagged = !tagged; |
+ ++cur_bit_flip_index; |
+ CHECK(i < bit_flip_positions[cur_bit_flip_index]); // check test data |
+ } |
+ layout_desc = layout_desc->SetTaggedForTesting(i, tagged); |
+ } |
+ } |
+ |
+ if (layout_desc->IsFastPointerLayout()) { |
+ return; |
+ } |
+ |
+ { |
+ // Check queries. |
+ int cur_bit_flip_index = 0; |
+ bool tagged = true; |
+ for (int i = 0; i < layout_descriptor_length; i++) { |
+ if (i == bit_flip_positions[cur_bit_flip_index]) { |
+ tagged = !tagged; |
+ ++cur_bit_flip_index; |
+ } |
+ CHECK_EQ(tagged, layout_desc->IsTagged(i)); |
+ |
+ int next_bit_flip_position = bit_flip_positions[cur_bit_flip_index]; |
+ int expected_sequence_length; |
+ if (next_bit_flip_position < layout_desc->capacity()) { |
+ expected_sequence_length = next_bit_flip_position - i; |
+ } else { |
+ expected_sequence_length = tagged ? std::numeric_limits<int>::max() |
+ : (layout_desc->capacity() - i); |
+ } |
+ expected_sequence_length = |
+ Min(expected_sequence_length, max_sequence_length); |
+ int sequence_length; |
+ CHECK_EQ(tagged, |
+ layout_desc->IsTagged(i, max_sequence_length, &sequence_length)); |
+ CHECK(sequence_length > 0); |
+ |
+ CHECK_EQ(expected_sequence_length, sequence_length); |
+ } |
+ |
+ int sequence_length; |
+ CHECK_EQ(true, |
+ layout_desc->IsTagged(layout_descriptor_length, |
+ max_sequence_length, &sequence_length)); |
+ CHECK_EQ(max_sequence_length, sequence_length); |
+ } |
+} |
+ |
+ |
+static void TestLayoutDescriptorQueriesFast(int max_sequence_length) { |
+ { |
+ LayoutDescriptor* layout_desc = LayoutDescriptor::FastPointerLayout(); |
+ int sequence_length; |
+ for (int i = 0; i < kNumberOfBits; i++) { |
+ CHECK_EQ(true, |
+ layout_desc->IsTagged(i, max_sequence_length, &sequence_length)); |
+ CHECK(sequence_length > 0); |
+ CHECK_EQ(max_sequence_length, sequence_length); |
+ } |
+ } |
+ |
+ { |
+ int bit_flip_positions[] = {1000}; |
+ TestLayoutDescriptorQueries(kSmiValueSize, bit_flip_positions, |
+ max_sequence_length); |
+ } |
+ |
+ { |
+ int bit_flip_positions[] = {0, 1000}; |
+ TestLayoutDescriptorQueries(kSmiValueSize, bit_flip_positions, |
+ max_sequence_length); |
+ } |
+ |
+ { |
+ int bit_flip_positions[kNumberOfBits + 1]; |
+ for (int i = 0; i <= kNumberOfBits; i++) { |
+ bit_flip_positions[i] = i; |
+ } |
+ TestLayoutDescriptorQueries(kSmiValueSize, bit_flip_positions, |
+ max_sequence_length); |
+ } |
+ |
+ { |
+ int bit_flip_positions[] = {3, 7, 8, 10, 15, 21, 30, 1000}; |
+ TestLayoutDescriptorQueries(kSmiValueSize, bit_flip_positions, |
+ max_sequence_length); |
+ } |
+ |
+ { |
+ int bit_flip_positions[] = {0, 1, 2, 3, 5, 7, 9, |
+ 12, 15, 18, 22, 26, 29, 1000}; |
+ TestLayoutDescriptorQueries(kSmiValueSize, bit_flip_positions, |
+ max_sequence_length); |
+ } |
+} |
+ |
+ |
+TEST(LayoutDescriptorQueriesFastLimited7) { |
+ CcTest::InitializeVM(); |
+ v8::HandleScope scope(CcTest::isolate()); |
+ |
+ TestLayoutDescriptorQueriesFast(7); |
+} |
+ |
+ |
+TEST(LayoutDescriptorQueriesFastLimited13) { |
+ CcTest::InitializeVM(); |
+ v8::HandleScope scope(CcTest::isolate()); |
+ |
+ TestLayoutDescriptorQueriesFast(13); |
+} |
+ |
+ |
+TEST(LayoutDescriptorQueriesFastUnlimited) { |
+ CcTest::InitializeVM(); |
+ v8::HandleScope scope(CcTest::isolate()); |
+ |
+ TestLayoutDescriptorQueriesFast(std::numeric_limits<int>::max()); |
+} |
+ |
+ |
+static void TestLayoutDescriptorQueriesSlow(int max_sequence_length) { |
+ { |
+ int bit_flip_positions[] = {10000}; |
+ TestLayoutDescriptorQueries(kMaxNumberOfDescriptors, bit_flip_positions, |
+ max_sequence_length); |
+ } |
+ |
+ { |
+ int bit_flip_positions[] = {0, 10000}; |
+ TestLayoutDescriptorQueries(kMaxNumberOfDescriptors, bit_flip_positions, |
+ max_sequence_length); |
+ } |
+ |
+ { |
+ int bit_flip_positions[kMaxNumberOfDescriptors + 1]; |
+ for (int i = 0; i < kMaxNumberOfDescriptors; i++) { |
+ bit_flip_positions[i] = i; |
+ } |
+ bit_flip_positions[kMaxNumberOfDescriptors] = 10000; |
+ TestLayoutDescriptorQueries(kMaxNumberOfDescriptors, bit_flip_positions, |
+ max_sequence_length); |
+ } |
+ |
+ { |
+ int bit_flip_positions[] = {3, 7, 8, 10, 15, 21, 30, |
+ 37, 54, 80, 99, 383, 10000}; |
+ TestLayoutDescriptorQueries(kMaxNumberOfDescriptors, bit_flip_positions, |
+ max_sequence_length); |
+ } |
+ |
+ { |
+ int bit_flip_positions[] = {0, 10, 20, 30, 50, 70, 90, |
+ 120, 150, 180, 220, 260, 290, 10000}; |
+ TestLayoutDescriptorQueries(kMaxNumberOfDescriptors, bit_flip_positions, |
+ max_sequence_length); |
+ } |
+ |
+ { |
+ int bit_flip_positions[kMaxNumberOfDescriptors + 1]; |
+ int cur = 0; |
+ for (int i = 0; i < kMaxNumberOfDescriptors; i++) { |
+ bit_flip_positions[i] = cur; |
+ cur = (cur + 1) * 2; |
+ } |
+ CHECK(cur < 10000); |
+ bit_flip_positions[kMaxNumberOfDescriptors] = 10000; |
+ TestLayoutDescriptorQueries(kMaxNumberOfDescriptors, bit_flip_positions, |
+ max_sequence_length); |
+ } |
+ |
+ { |
+ int bit_flip_positions[kMaxNumberOfDescriptors + 1]; |
+ int cur = 3; |
+ for (int i = 0; i < kMaxNumberOfDescriptors; i++) { |
+ bit_flip_positions[i] = cur; |
+ cur = (cur + 1) * 2; |
+ } |
+ CHECK(cur < 10000); |
+ bit_flip_positions[kMaxNumberOfDescriptors] = 10000; |
+ TestLayoutDescriptorQueries(kMaxNumberOfDescriptors, bit_flip_positions, |
+ max_sequence_length); |
+ } |
+} |
+ |
+ |
+TEST(LayoutDescriptorQueriesSlowLimited7) { |
+ CcTest::InitializeVM(); |
+ v8::HandleScope scope(CcTest::isolate()); |
+ |
+ TestLayoutDescriptorQueriesSlow(7); |
+} |
+ |
+ |
+TEST(LayoutDescriptorQueriesSlowLimited13) { |
+ CcTest::InitializeVM(); |
+ v8::HandleScope scope(CcTest::isolate()); |
+ |
+ TestLayoutDescriptorQueriesSlow(13); |
+} |
+ |
+ |
+TEST(LayoutDescriptorQueriesSlowLimited42) { |
+ CcTest::InitializeVM(); |
+ v8::HandleScope scope(CcTest::isolate()); |
+ |
+ TestLayoutDescriptorQueriesSlow(42); |
+} |
+ |
+ |
+TEST(LayoutDescriptorQueriesSlowUnlimited) { |
+ CcTest::InitializeVM(); |
+ v8::HandleScope scope(CcTest::isolate()); |
+ |
+ TestLayoutDescriptorQueriesSlow(std::numeric_limits<int>::max()); |
+} |
+ |
+ |
TEST(LayoutDescriptorCreateNewFast) { |
CcTest::InitializeVM(); |
Isolate* isolate = CcTest::i_isolate(); |
@@ -708,6 +951,151 @@ TEST(DoScavenge) { |
} |
+static void TestLayoutDescriptorHelper(Isolate* isolate, |
+ int inobject_properties, |
+ Handle<DescriptorArray> descriptors, |
+ int number_of_descriptors) { |
+ Handle<Map> map = Map::Create(isolate, inobject_properties); |
+ |
+ Handle<LayoutDescriptor> layout_descriptor = LayoutDescriptor::New( |
+ map, descriptors, descriptors->number_of_descriptors()); |
+ map->InitializeDescriptors(*descriptors, *layout_descriptor); |
+ DCHECK(layout_descriptor->IsConsistentWithMap(*map)); |
+ |
+ LayoutDescriptorHelper helper(*map); |
+ bool all_fields_tagged = true; |
+ |
+ int instance_size = map->instance_size(); |
+ |
+ int end_offset = instance_size * 2; |
+ int first_non_tagged_field_offset = end_offset; |
+ for (int i = 0; i < number_of_descriptors; i++) { |
+ PropertyDetails details = descriptors->GetDetails(i); |
+ if (details.type() != FIELD) continue; |
+ FieldIndex index = FieldIndex::ForDescriptor(*map, i); |
+ if (!index.is_inobject()) continue; |
+ all_fields_tagged &= !details.representation().IsDouble(); |
+ bool expected_tagged = !index.is_double(); |
+ if (!expected_tagged) { |
+ first_non_tagged_field_offset = |
+ Min(first_non_tagged_field_offset, index.offset()); |
+ } |
+ |
+ int end_of_region_offset; |
+ CHECK_EQ(expected_tagged, helper.IsTagged(index.offset())); |
+ CHECK_EQ(expected_tagged, helper.IsTagged(index.offset(), instance_size, |
+ &end_of_region_offset)); |
+ CHECK(end_of_region_offset > 0); |
+ CHECK(end_of_region_offset % kPointerSize == 0); |
+ CHECK(end_of_region_offset <= instance_size); |
+ |
+ for (int offset = index.offset(); offset < end_of_region_offset; |
+ offset += kPointerSize) { |
+ CHECK_EQ(expected_tagged, helper.IsTagged(index.offset())); |
+ } |
+ if (end_of_region_offset < instance_size) { |
+ CHECK_EQ(!expected_tagged, helper.IsTagged(end_of_region_offset)); |
+ } else { |
+ CHECK_EQ(true, helper.IsTagged(end_of_region_offset)); |
+ } |
+ } |
+ |
+ for (int offset = 0; offset < JSObject::kHeaderSize; offset += kPointerSize) { |
+ // Header queries |
+ CHECK_EQ(true, helper.IsTagged(offset)); |
+ int end_of_region_offset; |
+ CHECK_EQ(true, helper.IsTagged(offset, end_offset, &end_of_region_offset)); |
+ CHECK_EQ(first_non_tagged_field_offset, end_of_region_offset); |
+ |
+ // Out of bounds queries |
+ CHECK_EQ(true, helper.IsTagged(offset + instance_size)); |
+ } |
+ |
+ CHECK_EQ(all_fields_tagged, helper.all_fields_tagged()); |
+} |
+ |
+ |
+TEST(LayoutDescriptorHelperMixed) { |
+ CcTest::InitializeVM(); |
+ Isolate* isolate = CcTest::i_isolate(); |
+ v8::HandleScope scope(CcTest::isolate()); |
+ |
+ Handle<LayoutDescriptor> layout_descriptor; |
+ const int kPropsCount = kSmiValueSize * 3; |
+ TestPropertyKind props[kPropsCount]; |
+ for (int i = 0; i < kPropsCount; i++) { |
+ props[i] = static_cast<TestPropertyKind>(i % PROP_KIND_NUMBER); |
+ } |
+ Handle<DescriptorArray> descriptors = |
+ CreateDescriptorArray(isolate, props, kPropsCount); |
+ |
+ TestLayoutDescriptorHelper(isolate, 0, descriptors, kPropsCount); |
+ |
+ TestLayoutDescriptorHelper(isolate, 13, descriptors, kPropsCount); |
+ |
+ TestLayoutDescriptorHelper(isolate, kSmiValueSize, descriptors, kPropsCount); |
+ |
+ TestLayoutDescriptorHelper(isolate, kSmiValueSize * 2, descriptors, |
+ kPropsCount); |
+ |
+ TestLayoutDescriptorHelper(isolate, kPropsCount, descriptors, kPropsCount); |
+} |
+ |
+ |
+TEST(LayoutDescriptorHelperAllTagged) { |
+ CcTest::InitializeVM(); |
+ Isolate* isolate = CcTest::i_isolate(); |
+ v8::HandleScope scope(CcTest::isolate()); |
+ |
+ Handle<LayoutDescriptor> layout_descriptor; |
+ const int kPropsCount = kSmiValueSize * 3; |
+ TestPropertyKind props[kPropsCount]; |
+ for (int i = 0; i < kPropsCount; i++) { |
+ props[i] = PROP_TAGGED; |
+ } |
+ Handle<DescriptorArray> descriptors = |
+ CreateDescriptorArray(isolate, props, kPropsCount); |
+ |
+ TestLayoutDescriptorHelper(isolate, 0, descriptors, kPropsCount); |
+ |
+ TestLayoutDescriptorHelper(isolate, 13, descriptors, kPropsCount); |
+ |
+ TestLayoutDescriptorHelper(isolate, kSmiValueSize, descriptors, kPropsCount); |
+ |
+ TestLayoutDescriptorHelper(isolate, kSmiValueSize * 2, descriptors, |
+ kPropsCount); |
+ |
+ TestLayoutDescriptorHelper(isolate, kPropsCount, descriptors, kPropsCount); |
+} |
+ |
+ |
+TEST(LayoutDescriptorHelperAllDoubles) { |
+ CcTest::InitializeVM(); |
+ Isolate* isolate = CcTest::i_isolate(); |
+ v8::HandleScope scope(CcTest::isolate()); |
+ |
+ Handle<LayoutDescriptor> layout_descriptor; |
+ const int kPropsCount = kSmiValueSize * 3; |
+ TestPropertyKind props[kPropsCount]; |
+ for (int i = 0; i < kPropsCount; i++) { |
+ props[i] = PROP_DOUBLE; |
+ } |
+ Handle<DescriptorArray> descriptors = |
+ CreateDescriptorArray(isolate, props, kPropsCount); |
+ |
+ TestLayoutDescriptorHelper(isolate, 0, descriptors, kPropsCount); |
+ |
+ TestLayoutDescriptorHelper(isolate, 13, descriptors, kPropsCount); |
+ |
+ TestLayoutDescriptorHelper(isolate, kSmiValueSize, descriptors, kPropsCount); |
+ |
+ TestLayoutDescriptorHelper(isolate, kSmiValueSize * 2, descriptors, |
+ kPropsCount); |
+ |
+ TestLayoutDescriptorHelper(isolate, kPropsCount, descriptors, kPropsCount); |
+} |
+ |
+ |
TEST(StoreBufferScanOnScavenge) { |
CcTest::InitializeVM(); |
Isolate* isolate = CcTest::i_isolate(); |