TEST(TestAlignmentCalculations) {
- // Maximum fill amounts should be consistent.
+ // Maximum fill amounts are consistent.
int maximum_double_misalignment = kDoubleSize - kPointerSize;
+ int maximum_simd128_misalignment = kSimd128Size - kPointerSize;
int max_word_fill = Heap::GetMaximumFillToAlign(kWordAligned);
CHECK_EQ(0, max_word_fill);
int max_double_fill = Heap::GetMaximumFillToAlign(kDoubleAligned);
CHECK_EQ(maximum_double_misalignment, max_double_fill);
int max_double_unaligned_fill = Heap::GetMaximumFillToAlign(kDoubleUnaligned);
CHECK_EQ(maximum_double_misalignment, max_double_unaligned_fill);
+ int max_simd128_unaligned_fill =
+ Heap::GetMaximumFillToAlign(kSimd128Unaligned);
+ CHECK_EQ(maximum_simd128_misalignment, max_simd128_unaligned_fill);
Address base = reinterpret_cast<Address>(NULL);
int fill = 0;
CHECK_EQ(maximum_double_misalignment, fill);
fill = Heap::GetFillToAlign(base + kPointerSize, kDoubleUnaligned);
CHECK_EQ(0, fill);
+
+ // 128 bit SIMD types have 2 or 4 possible alignments, depending on platform.
+ fill = Heap::GetFillToAlign(base, kSimd128Unaligned);
+ CHECK_EQ((3 * kPointerSize) & kSimd128AlignmentMask, fill);
+ fill = Heap::GetFillToAlign(base + kPointerSize, kSimd128Unaligned);
+ CHECK_EQ((2 * kPointerSize) & kSimd128AlignmentMask, fill);
+ fill = Heap::GetFillToAlign(base + 2 * kPointerSize, kSimd128Unaligned);
+ CHECK_EQ(kPointerSize, fill);
+ fill = Heap::GetFillToAlign(base + 3 * kPointerSize, kSimd128Unaligned);
+ CHECK_EQ(0, fill);
}
}
+// Get new space allocation into the desired alignment.
+static Address AlignNewSpace(AllocationAlignment alignment, int offset) {
+ Address* top_addr = CcTest::heap()->new_space()->allocation_top_address();
+ int fill = Heap::GetFillToAlign(*top_addr, alignment);
+ if (fill) {
+ NewSpaceAllocateAligned(fill + offset, kWordAligned);
+ }
+ return *top_addr;
+}
+
+
TEST(TestAlignedAllocation) {
// Double misalignment is 4 on 32-bit platforms, 0 on 64-bit ones.
const intptr_t double_misalignment = kDoubleSize - kPointerSize;
+ Address* top_addr = CcTest::heap()->new_space()->allocation_top_address();
+ Address start;
+ HeapObject* obj;
+ HeapObject* filler;
if (double_misalignment) {
- Address* top_addr = CcTest::heap()->new_space()->allocation_top_address();
- // Align the top for the first test.
- if (!IsAddressAligned(*top_addr, kDoubleAlignment))
- NewSpaceAllocateAligned(kPointerSize, kWordAligned);
-
- // Allocate a pointer sized object that must be double aligned.
- Address start = *top_addr;
- HeapObject* obj1 = NewSpaceAllocateAligned(kPointerSize, kDoubleAligned);
- CHECK(IsAddressAligned(obj1->address(), kDoubleAlignment));
- // Only the object was allocated.
+ // Allocate a pointer sized object that must be double aligned at an
+ // aligned address.
+ start = AlignNewSpace(kDoubleAligned, 0);
+ obj = NewSpaceAllocateAligned(kPointerSize, kDoubleAligned);
+ CHECK(IsAddressAligned(obj->address(), kDoubleAlignment));
+ // There is no filler.
CHECK_EQ(kPointerSize, *top_addr - start);
- // top is now misaligned.
- // Allocate a second pointer sized object that must be double aligned.
- HeapObject* obj2 = NewSpaceAllocateAligned(kPointerSize, kDoubleAligned);
- CHECK(IsAddressAligned(obj2->address(), kDoubleAlignment));
- // There should be a filler object in between the two objects.
- CHECK(HeapObject::FromAddress(start + kPointerSize)->IsFiller());
- // Two objects and a filler object were allocated.
- CHECK_EQ(2 * kPointerSize + double_misalignment, *top_addr - start);
-
- // Similarly for kDoubleUnaligned. top is misaligned.
- start = *top_addr;
- obj1 = NewSpaceAllocateAligned(kPointerSize, kDoubleUnaligned);
- CHECK(IsAddressAligned(obj1->address(), kDoubleAlignment, kPointerSize));
- CHECK_EQ(kPointerSize, *top_addr - start);
- obj2 = NewSpaceAllocateAligned(kPointerSize, kDoubleUnaligned);
- CHECK(IsAddressAligned(obj2->address(), kDoubleAlignment, kPointerSize));
- CHECK(HeapObject::FromAddress(start + kPointerSize)->IsFiller());
- CHECK_EQ(2 * kPointerSize + double_misalignment, *top_addr - start);
- }
-}
+ // Allocate a second pointer sized object that must be double aligned at an
+ // unaligned address.
+ start = AlignNewSpace(kDoubleAligned, kPointerSize);
+ obj = NewSpaceAllocateAligned(kPointerSize, kDoubleAligned);
+ CHECK(IsAddressAligned(obj->address(), kDoubleAlignment));
+ // There is a filler object before the object.
+ filler = HeapObject::FromAddress(start);
+ CHECK(obj != filler && filler->IsFiller() &&
+ filler->Size() == kPointerSize);
+ CHECK_EQ(kPointerSize + double_misalignment, *top_addr - start);
-// Force allocation to happen from the free list, at a desired misalignment.
-static Address SetUpFreeListAllocation(int misalignment) {
- Heap* heap = CcTest::heap();
- OldSpace* old_space = heap->old_space();
- Address top = old_space->top();
- // First, allocate enough filler to get the linear area into the desired
- // misalignment.
- const intptr_t maximum_misalignment = 2 * kPointerSize;
- const intptr_t maximum_misalignment_mask = maximum_misalignment - 1;
- intptr_t top_alignment = OffsetFrom(top) & maximum_misalignment_mask;
- int filler_size = misalignment - static_cast<int>(top_alignment);
- if (filler_size < 0) filler_size += maximum_misalignment;
- if (filler_size) {
- // Create the filler object.
- AllocationResult allocation = old_space->AllocateRawUnaligned(filler_size);
- HeapObject* obj = NULL;
- allocation.To(&obj);
- heap->CreateFillerObjectAt(obj->address(), filler_size);
- }
- top = old_space->top();
- old_space->EmptyAllocationInfo();
- return top;
+ // Similarly for kDoubleUnaligned.
+ start = AlignNewSpace(kDoubleUnaligned, 0);
+ obj = NewSpaceAllocateAligned(kPointerSize, kDoubleUnaligned);
+ CHECK(IsAddressAligned(obj->address(), kDoubleAlignment, kPointerSize));
+ CHECK_EQ(kPointerSize, *top_addr - start);
+ start = AlignNewSpace(kDoubleUnaligned, kPointerSize);
+ obj = NewSpaceAllocateAligned(kPointerSize, kDoubleUnaligned);
+ CHECK(IsAddressAligned(obj->address(), kDoubleAlignment, kPointerSize));
+ // There is a filler object before the object.
+ filler = HeapObject::FromAddress(start);
+ CHECK(obj != filler && filler->IsFiller() &&
+ filler->Size() == kPointerSize);
+ CHECK_EQ(kPointerSize + double_misalignment, *top_addr - start);
+ }
+
+ // Now test SIMD alignment. There are 2 or 4 possible alignments, depending
+ // on platform.
+ start = AlignNewSpace(kSimd128Unaligned, 0);
+ obj = NewSpaceAllocateAligned(kPointerSize, kSimd128Unaligned);
+ CHECK(IsAddressAligned(obj->address(), kSimd128Alignment, kPointerSize));
+ // There is no filler.
+ CHECK_EQ(kPointerSize, *top_addr - start);
+ start = AlignNewSpace(kSimd128Unaligned, kPointerSize);
+ obj = NewSpaceAllocateAligned(kPointerSize, kSimd128Unaligned);
+ CHECK(IsAddressAligned(obj->address(), kSimd128Alignment, kPointerSize));
+ // There is a filler object before the object.
+ filler = HeapObject::FromAddress(start);
+ CHECK(obj != filler && filler->IsFiller() &&
+ filler->Size() == kSimd128Size - kPointerSize);
+ CHECK_EQ(kPointerSize + kSimd128Size - kPointerSize, *top_addr - start);
+
+ if (double_misalignment) {
+ // Test the 2 other alignments possible on 32 bit platforms.
+ start = AlignNewSpace(kSimd128Unaligned, 2 * kPointerSize);
+ obj = NewSpaceAllocateAligned(kPointerSize, kSimd128Unaligned);
+ CHECK(IsAddressAligned(obj->address(), kSimd128Alignment, kPointerSize));
+ // There is a filler object before the object.
+ filler = HeapObject::FromAddress(start);
+ CHECK(obj != filler && filler->IsFiller() &&
+ filler->Size() == 2 * kPointerSize);
+ CHECK_EQ(kPointerSize + 2 * kPointerSize, *top_addr - start);
+ start = AlignNewSpace(kSimd128Unaligned, 3 * kPointerSize);
+ obj = NewSpaceAllocateAligned(kPointerSize, kSimd128Unaligned);
+ CHECK(IsAddressAligned(obj->address(), kSimd128Alignment, kPointerSize));
+ // There is a filler object before the object.
+ filler = HeapObject::FromAddress(start);
+ CHECK(obj != filler && filler->IsFiller() &&
+ filler->Size() == kPointerSize);
+ CHECK_EQ(kPointerSize + kPointerSize, *top_addr - start);
+ }
}
}
+// Get old space allocation into the desired alignment.
+static Address AlignOldSpace(AllocationAlignment alignment, int offset) {
+ Address* top_addr = CcTest::heap()->old_space()->allocation_top_address();
+ int fill = Heap::GetFillToAlign(*top_addr, alignment);
+ int allocation = fill + offset;
+ if (allocation) {
+ OldSpaceAllocateAligned(allocation, kWordAligned);
+ }
+ Address top = *top_addr;
+ // Now force the remaining allocation onto the free list.
+ CcTest::heap()->old_space()->EmptyAllocationInfo();
+ return top;
+}
+
+
// Test the case where allocation must be done from the free list, so filler
// may precede or follow the object.
TEST(TestAlignedOverAllocation) {
// Double misalignment is 4 on 32-bit platforms, 0 on 64-bit ones.
const intptr_t double_misalignment = kDoubleSize - kPointerSize;
+ Address start;
+ HeapObject* obj;
+ HeapObject* filler1;
+ HeapObject* filler2;
if (double_misalignment) {
- Address start = SetUpFreeListAllocation(0);
- HeapObject* obj1 = OldSpaceAllocateAligned(kPointerSize, kDoubleAligned);
- // The object should be aligned, and a filler object should be created.
- CHECK(IsAddressAligned(obj1->address(), kDoubleAlignment));
- CHECK(HeapObject::FromAddress(start)->IsFiller() &&
- HeapObject::FromAddress(start + kPointerSize)->IsFiller());
+ start = AlignOldSpace(kDoubleAligned, 0);
+ obj = OldSpaceAllocateAligned(kPointerSize, kDoubleAligned);
+ // The object is aligned, and a filler object is created after.
+ CHECK(IsAddressAligned(obj->address(), kDoubleAlignment));
+ filler1 = HeapObject::FromAddress(start + kPointerSize);
+ CHECK(obj != filler1 && filler1->IsFiller() &&
+ filler1->Size() == kPointerSize);
// Try the opposite alignment case.
- start = SetUpFreeListAllocation(kPointerSize);
- HeapObject* obj2 = OldSpaceAllocateAligned(kPointerSize, kDoubleAligned);
- CHECK(IsAddressAligned(obj2->address(), kDoubleAlignment));
- CHECK(HeapObject::FromAddress(start)->IsFiller() &&
- HeapObject::FromAddress(start + kPointerSize)->IsFiller());
+ start = AlignOldSpace(kDoubleAligned, kPointerSize);
+ obj = OldSpaceAllocateAligned(kPointerSize, kDoubleAligned);
+ CHECK(IsAddressAligned(obj->address(), kDoubleAlignment));
+ filler1 = HeapObject::FromAddress(start);
+ CHECK(obj != filler1);
+ CHECK(filler1->IsFiller());
+ CHECK(filler1->Size() == kPointerSize);
+ CHECK(obj != filler1 && filler1->IsFiller() &&
+ filler1->Size() == kPointerSize);
// Similarly for kDoubleUnaligned.
- start = SetUpFreeListAllocation(0);
- obj1 = OldSpaceAllocateAligned(kPointerSize, kDoubleUnaligned);
- // The object should be aligned, and a filler object should be created.
- CHECK(IsAddressAligned(obj1->address(), kDoubleAlignment, kPointerSize));
- CHECK(HeapObject::FromAddress(start)->IsFiller() &&
- HeapObject::FromAddress(start + kPointerSize)->IsFiller());
+ start = AlignOldSpace(kDoubleUnaligned, 0);
+ obj = OldSpaceAllocateAligned(kPointerSize, kDoubleUnaligned);
+ // The object is aligned, and a filler object is created after.
+ CHECK(IsAddressAligned(obj->address(), kDoubleAlignment, kPointerSize));
+ filler1 = HeapObject::FromAddress(start + kPointerSize);
+ CHECK(obj != filler1 && filler1->IsFiller() &&
+ filler1->Size() == kPointerSize);
// Try the opposite alignment case.
- start = SetUpFreeListAllocation(kPointerSize);
- obj2 = OldSpaceAllocateAligned(kPointerSize, kDoubleUnaligned);
- CHECK(IsAddressAligned(obj2->address(), kDoubleAlignment, kPointerSize));
- CHECK(HeapObject::FromAddress(start)->IsFiller() &&
- HeapObject::FromAddress(start + kPointerSize)->IsFiller());
+ start = AlignOldSpace(kDoubleUnaligned, kPointerSize);
+ obj = OldSpaceAllocateAligned(kPointerSize, kDoubleUnaligned);
+ CHECK(IsAddressAligned(obj->address(), kDoubleAlignment, kPointerSize));
+ filler1 = HeapObject::FromAddress(start);
+ CHECK(obj != filler1 && filler1->IsFiller() &&
+ filler1->Size() == kPointerSize);
+ }
+
+ // Now test SIMD alignment. There are 2 or 4 possible alignments, depending
+ // on platform.
+ start = AlignOldSpace(kSimd128Unaligned, 0);
+ obj = OldSpaceAllocateAligned(kPointerSize, kSimd128Unaligned);
+ CHECK(IsAddressAligned(obj->address(), kSimd128Alignment, kPointerSize));
+ // There is a filler object after the object.
+ filler1 = HeapObject::FromAddress(start + kPointerSize);
+ CHECK(obj != filler1 && filler1->IsFiller() &&
+ filler1->Size() == kSimd128Size - kPointerSize);
+ start = AlignOldSpace(kSimd128Unaligned, kPointerSize);
+ obj = OldSpaceAllocateAligned(kPointerSize, kSimd128Unaligned);
+ CHECK(IsAddressAligned(obj->address(), kSimd128Alignment, kPointerSize));
+ // There is a filler object before the object.
+ filler1 = HeapObject::FromAddress(start);
+ CHECK(obj != filler1 && filler1->IsFiller() &&
+ filler1->Size() == kSimd128Size - kPointerSize);
+
+ if (double_misalignment) {
+ // Test the 2 other alignments possible on 32 bit platforms.
+ start = AlignOldSpace(kSimd128Unaligned, 2 * kPointerSize);
+ obj = OldSpaceAllocateAligned(kPointerSize, kSimd128Unaligned);
+ CHECK(IsAddressAligned(obj->address(), kSimd128Alignment, kPointerSize));
+ // There are filler objects before and after the object.
+ filler1 = HeapObject::FromAddress(start);
+ CHECK(obj != filler1 && filler1->IsFiller() &&
+ filler1->Size() == 2 * kPointerSize);
+ filler2 = HeapObject::FromAddress(start + 3 * kPointerSize);
+ CHECK(obj != filler2 && filler2->IsFiller() &&
+ filler2->Size() == kPointerSize);
+ start = AlignOldSpace(kSimd128Unaligned, 3 * kPointerSize);
+ obj = OldSpaceAllocateAligned(kPointerSize, kSimd128Unaligned);
+ CHECK(IsAddressAligned(obj->address(), kSimd128Alignment, kPointerSize));
+ // There are filler objects before and after the object.
+ filler1 = HeapObject::FromAddress(start);
+ CHECK(obj != filler1 && filler1->IsFiller() &&
+ filler1->Size() == kPointerSize);
+ filler2 = HeapObject::FromAddress(start + 2 * kPointerSize);
+ CHECK(obj != filler2 && filler2->IsFiller() &&
+ filler2->Size() == 2 * kPointerSize);
}
}