// 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" using namespace v8::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); }