| // Copyright 2015 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // Test embedded constant pool builder code. |
| |
| #include "src/v8.h" |
| |
| #include "src/assembler.h" |
| #include "test/cctest/cctest.h" |
| |
| namespace v8 { |
| namespace internal { |
| |
| const ConstantPoolEntry::Type kPtrType = ConstantPoolEntry::INTPTR; |
| const ConstantPoolEntry::Type kDblType = ConstantPoolEntry::DOUBLE; |
| const ConstantPoolEntry::Access kRegAccess = ConstantPoolEntry::REGULAR; |
| const ConstantPoolEntry::Access kOvflAccess = ConstantPoolEntry::OVERFLOWED; |
| |
| const int kReachBits = 6; // Use reach of 64-bytes to test overflow. |
| const int kReach = 1 << kReachBits; |
| |
| |
| TEST(ConstantPoolPointers) { |
| ConstantPoolBuilder builder(kReachBits, kReachBits); |
| const int kRegularCount = kReach / kPointerSize; |
| ConstantPoolEntry::Access access; |
| int pos = 0; |
| intptr_t value = 0; |
| bool sharing_ok = true; |
| |
| CHECK(builder.IsEmpty()); |
| while (builder.NextAccess(kPtrType) == kRegAccess) { |
| access = builder.AddEntry(pos++, value++, sharing_ok); |
| CHECK_EQ(access, kRegAccess); |
| } |
| CHECK(!builder.IsEmpty()); |
| CHECK_EQ(pos, kRegularCount); |
| |
| access = builder.AddEntry(pos, value, sharing_ok); |
| CHECK_EQ(access, kOvflAccess); |
| } |
| |
| |
| TEST(ConstantPoolDoubles) { |
| ConstantPoolBuilder builder(kReachBits, kReachBits); |
| const int kRegularCount = kReach / kDoubleSize; |
| ConstantPoolEntry::Access access; |
| int pos = 0; |
| double value = 0.0; |
| |
| CHECK(builder.IsEmpty()); |
| while (builder.NextAccess(kDblType) == kRegAccess) { |
| access = builder.AddEntry(pos++, value); |
| value += 0.5; |
| CHECK_EQ(access, kRegAccess); |
| } |
| CHECK(!builder.IsEmpty()); |
| CHECK_EQ(pos, kRegularCount); |
| |
| access = builder.AddEntry(pos, value); |
| CHECK_EQ(access, kOvflAccess); |
| } |
| |
| |
| TEST(ConstantPoolMixedTypes) { |
| ConstantPoolBuilder builder(kReachBits, kReachBits); |
| const int kRegularCount = (((kReach / (kDoubleSize + kPointerSize)) * 2) + |
| ((kPointerSize < kDoubleSize) ? 1 : 0)); |
| ConstantPoolEntry::Type type = kPtrType; |
| ConstantPoolEntry::Access access; |
| int pos = 0; |
| intptr_t ptrValue = 0; |
| double dblValue = 0.0; |
| bool sharing_ok = true; |
| |
| CHECK(builder.IsEmpty()); |
| while (builder.NextAccess(type) == kRegAccess) { |
| if (type == kPtrType) { |
| access = builder.AddEntry(pos++, ptrValue++, sharing_ok); |
| type = kDblType; |
| } else { |
| access = builder.AddEntry(pos++, dblValue); |
| dblValue += 0.5; |
| type = kPtrType; |
| } |
| CHECK_EQ(access, kRegAccess); |
| } |
| CHECK(!builder.IsEmpty()); |
| CHECK_EQ(pos, kRegularCount); |
| |
| access = builder.AddEntry(pos++, ptrValue, sharing_ok); |
| CHECK_EQ(access, kOvflAccess); |
| access = builder.AddEntry(pos, dblValue); |
| CHECK_EQ(access, kOvflAccess); |
| } |
| |
| |
| TEST(ConstantPoolMixedReach) { |
| const int ptrReachBits = kReachBits + 2; |
| const int ptrReach = 1 << ptrReachBits; |
| const int dblReachBits = kReachBits; |
| const int dblReach = kReach; |
| const int dblRegularCount = |
| Min(dblReach / kDoubleSize, ptrReach / (kDoubleSize + kPointerSize)); |
| const int ptrRegularCount = |
| ((ptrReach - (dblRegularCount * (kDoubleSize + kPointerSize))) / |
| kPointerSize) + |
| dblRegularCount; |
| ConstantPoolBuilder builder(ptrReachBits, dblReachBits); |
| ConstantPoolEntry::Access access; |
| int pos = 0; |
| intptr_t ptrValue = 0; |
| double dblValue = 0.0; |
| bool sharing_ok = true; |
| int ptrCount = 0; |
| int dblCount = 0; |
| |
| CHECK(builder.IsEmpty()); |
| while (builder.NextAccess(kDblType) == kRegAccess) { |
| access = builder.AddEntry(pos++, dblValue); |
| dblValue += 0.5; |
| dblCount++; |
| CHECK_EQ(access, kRegAccess); |
| |
| access = builder.AddEntry(pos++, ptrValue++, sharing_ok); |
| ptrCount++; |
| CHECK_EQ(access, kRegAccess); |
| } |
| CHECK(!builder.IsEmpty()); |
| CHECK_EQ(dblCount, dblRegularCount); |
| |
| while (ptrCount < ptrRegularCount) { |
| access = builder.AddEntry(pos++, dblValue); |
| dblValue += 0.5; |
| CHECK_EQ(access, kOvflAccess); |
| |
| access = builder.AddEntry(pos++, ptrValue++, sharing_ok); |
| ptrCount++; |
| CHECK_EQ(access, kRegAccess); |
| } |
| CHECK_EQ(builder.NextAccess(kPtrType), kOvflAccess); |
| |
| access = builder.AddEntry(pos++, ptrValue, sharing_ok); |
| CHECK_EQ(access, kOvflAccess); |
| access = builder.AddEntry(pos, dblValue); |
| CHECK_EQ(access, kOvflAccess); |
| } |
| |
| |
| TEST(ConstantPoolSharing) { |
| ConstantPoolBuilder builder(kReachBits, kReachBits); |
| const int kRegularCount = (((kReach / (kDoubleSize + kPointerSize)) * 2) + |
| ((kPointerSize < kDoubleSize) ? 1 : 0)); |
| ConstantPoolEntry::Access access; |
| |
| CHECK(builder.IsEmpty()); |
| |
| ConstantPoolEntry::Type type = kPtrType; |
| int pos = 0; |
| intptr_t ptrValue = 0; |
| double dblValue = 0.0; |
| bool sharing_ok = true; |
| while (builder.NextAccess(type) == kRegAccess) { |
| if (type == kPtrType) { |
| access = builder.AddEntry(pos++, ptrValue++, sharing_ok); |
| type = kDblType; |
| } else { |
| access = builder.AddEntry(pos++, dblValue); |
| dblValue += 0.5; |
| type = kPtrType; |
| } |
| CHECK_EQ(access, kRegAccess); |
| } |
| CHECK(!builder.IsEmpty()); |
| CHECK_EQ(pos, kRegularCount); |
| |
| type = kPtrType; |
| ptrValue = 0; |
| dblValue = 0.0; |
| while (pos < kRegularCount * 2) { |
| if (type == kPtrType) { |
| access = builder.AddEntry(pos++, ptrValue++, sharing_ok); |
| type = kDblType; |
| } else { |
| access = builder.AddEntry(pos++, dblValue); |
| dblValue += 0.5; |
| type = kPtrType; |
| } |
| CHECK_EQ(access, kRegAccess); |
| } |
| |
| access = builder.AddEntry(pos++, ptrValue, sharing_ok); |
| CHECK_EQ(access, kOvflAccess); |
| access = builder.AddEntry(pos, dblValue); |
| CHECK_EQ(access, kOvflAccess); |
| } |
| |
| |
| TEST(ConstantPoolNoSharing) { |
| ConstantPoolBuilder builder(kReachBits, kReachBits); |
| const int kRegularCount = (((kReach / (kDoubleSize + kPointerSize)) * 2) + |
| ((kPointerSize < kDoubleSize) ? 1 : 0)); |
| ConstantPoolEntry::Access access; |
| |
| CHECK(builder.IsEmpty()); |
| |
| ConstantPoolEntry::Type type = kPtrType; |
| int pos = 0; |
| intptr_t ptrValue = 0; |
| double dblValue = 0.0; |
| bool sharing_ok = false; |
| while (builder.NextAccess(type) == kRegAccess) { |
| if (type == kPtrType) { |
| access = builder.AddEntry(pos++, ptrValue++, sharing_ok); |
| type = kDblType; |
| } else { |
| access = builder.AddEntry(pos++, dblValue); |
| dblValue += 0.5; |
| type = kPtrType; |
| } |
| CHECK_EQ(access, kRegAccess); |
| } |
| CHECK(!builder.IsEmpty()); |
| CHECK_EQ(pos, kRegularCount); |
| |
| type = kPtrType; |
| ptrValue = 0; |
| dblValue = 0.0; |
| sharing_ok = true; |
| while (pos < kRegularCount * 2) { |
| if (type == kPtrType) { |
| access = builder.AddEntry(pos++, ptrValue++, sharing_ok); |
| type = kDblType; |
| CHECK_EQ(access, kOvflAccess); |
| } else { |
| access = builder.AddEntry(pos++, dblValue); |
| dblValue += 0.5; |
| type = kPtrType; |
| CHECK_EQ(access, kRegAccess); |
| } |
| } |
| |
| access = builder.AddEntry(pos++, ptrValue, sharing_ok); |
| CHECK_EQ(access, kOvflAccess); |
| access = builder.AddEntry(pos, dblValue); |
| CHECK_EQ(access, kOvflAccess); |
| } |
| |
| } // namespace internal |
| } // namespace v8 |