e639eafea3
This is a reland of352b9ecbdb
The test/fix CL has been merged in, as the fixes to return slot accounting are needed to fix Arm64 issues turned up by the fuzzers: https://chromium-review.googlesource.com/c/v8/v8/+/2644139 The reverted fix for Wasm return slot allocation is added in patchset #2, to avoid fuzzer issues that it fixed: https://chromium-review.googlesource.com/c/v8/v8/+/2683024 TBR=neis@chromium.org Original change's description: > Reland "Reland "[compiler][wasm] Align Frame slots to value size"" > > This is a reland of1694925c72
> > Minor fix to linkage for constexpr. > > TBR=ahaas@chromium.org,neis@chromium.org > > Original change's description: > > Reland "[compiler][wasm] Align Frame slots to value size" > > > > This is a reland ofcddaf66c37
> > > > Original change's description: > > > [compiler][wasm] Align Frame slots to value size > > > > > > - Adds an AlignedSlotAllocator class and tests, to unify slot > > > allocation. This attempts to use alignment holes for smaller > > > values. > > > - Reworks Frame to use the new allocator for stack slots. > > > - Reworks LinkageAllocator to use the new allocator for stack > > > slots and for ARMv7 FP register aliasing. > > > - Fixes the RegisterAllocator to align spill slots. > > > - Fixes InstructionSelector to align spill slots. > > > > > > Bug: v8:9198 > > > > > > Change-Id: Ida148db428be89ef95de748ec5fc0e7b0358f523 > > > Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2512840 > > > Commit-Queue: Bill Budge <bbudge@chromium.org> > > > Reviewed-by: Georg Neis <neis@chromium.org> > > > Reviewed-by: Andreas Haas <ahaas@chromium.org> > > > Cr-Commit-Position: refs/heads/master@{#71644} > > > > Bug: v8:9198 > > Change-Id: Ib91fa6746370c38496706341e12d05c7bf999389 > > Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2633390 > > Commit-Queue: Bill Budge <bbudge@chromium.org> > > Reviewed-by: Andreas Haas <ahaas@chromium.org> > > Reviewed-by: Georg Neis <neis@chromium.org> > > Cr-Commit-Position: refs/heads/master@{#72195} > > Bug: v8:9198 > Change-Id: I91e02b823af8ec925dacf075388fb22e3eeb3384 > Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2640890 > Reviewed-by: Bill Budge <bbudge@chromium.org> > Commit-Queue: Bill Budge <bbudge@chromium.org> > Cr-Commit-Position: refs/heads/master@{#72209} Bug: v8:9198 Change-Id: Ia5cf63af4e5991bc7cf42da9972ffd044fc829f0 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2733177 Commit-Queue: Bill Budge <bbudge@chromium.org> Reviewed-by: Andreas Haas <ahaas@chromium.org> Cr-Commit-Position: refs/heads/master@{#73238}
243 lines
8.8 KiB
C++
243 lines
8.8 KiB
C++
// Copyright 2021 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.
|
|
|
|
#include "src/compiler/frame.h"
|
|
|
|
#include "src/codegen/aligned-slot-allocator.h"
|
|
#include "testing/gtest-support.h"
|
|
|
|
namespace v8 {
|
|
namespace internal {
|
|
namespace compiler {
|
|
|
|
namespace {
|
|
constexpr int kSlotSize = AlignedSlotAllocator::kSlotSize;
|
|
|
|
constexpr int kFixed1 = 1;
|
|
constexpr int kFixed3 = 3;
|
|
} // namespace
|
|
|
|
class FrameTest : public ::testing::Test {
|
|
public:
|
|
FrameTest() = default;
|
|
~FrameTest() override = default;
|
|
};
|
|
|
|
TEST_F(FrameTest, Constructor) {
|
|
Frame frame(kFixed3);
|
|
EXPECT_EQ(kFixed3, frame.GetTotalFrameSlotCount());
|
|
EXPECT_EQ(kFixed3, frame.GetFixedSlotCount());
|
|
EXPECT_EQ(0, frame.GetSpillSlotCount());
|
|
EXPECT_EQ(0, frame.GetReturnSlotCount());
|
|
}
|
|
|
|
TEST_F(FrameTest, ReserveSpillSlots) {
|
|
Frame frame(kFixed3);
|
|
constexpr int kReserve2 = 2;
|
|
|
|
frame.ReserveSpillSlots(kReserve2);
|
|
EXPECT_EQ(kFixed3 + kReserve2, frame.GetTotalFrameSlotCount());
|
|
EXPECT_EQ(kFixed3, frame.GetFixedSlotCount());
|
|
EXPECT_EQ(kReserve2, frame.GetSpillSlotCount());
|
|
EXPECT_EQ(0, frame.GetReturnSlotCount());
|
|
}
|
|
|
|
TEST_F(FrameTest, EnsureReturnSlots) {
|
|
Frame frame(kFixed3);
|
|
constexpr int kReturn3 = 3;
|
|
constexpr int kReturn5 = 5;
|
|
constexpr int kReturn2 = 2;
|
|
|
|
frame.EnsureReturnSlots(kReturn3);
|
|
EXPECT_EQ(kFixed3 + kReturn3, frame.GetTotalFrameSlotCount());
|
|
EXPECT_EQ(kFixed3, frame.GetFixedSlotCount());
|
|
EXPECT_EQ(0, frame.GetSpillSlotCount());
|
|
EXPECT_EQ(kReturn3, frame.GetReturnSlotCount());
|
|
|
|
// Returns should grow by 2 slots.
|
|
frame.EnsureReturnSlots(kReturn5);
|
|
EXPECT_EQ(kFixed3 + kReturn5, frame.GetTotalFrameSlotCount());
|
|
EXPECT_EQ(kFixed3, frame.GetFixedSlotCount());
|
|
EXPECT_EQ(0, frame.GetSpillSlotCount());
|
|
EXPECT_EQ(kReturn5, frame.GetReturnSlotCount());
|
|
|
|
// Returns shouldn't grow.
|
|
frame.EnsureReturnSlots(kReturn2);
|
|
EXPECT_EQ(kFixed3 + kReturn5, frame.GetTotalFrameSlotCount());
|
|
EXPECT_EQ(kFixed3, frame.GetFixedSlotCount());
|
|
EXPECT_EQ(0, frame.GetSpillSlotCount());
|
|
EXPECT_EQ(kReturn5, frame.GetReturnSlotCount());
|
|
}
|
|
|
|
TEST_F(FrameTest, AllocateSavedCalleeRegisterSlots) {
|
|
Frame frame(kFixed3);
|
|
constexpr int kFirstSlots = 2;
|
|
constexpr int kSecondSlots = 3;
|
|
|
|
frame.AllocateSavedCalleeRegisterSlots(kFirstSlots);
|
|
EXPECT_EQ(kFixed3 + kFirstSlots, frame.GetTotalFrameSlotCount());
|
|
EXPECT_EQ(kFixed3, frame.GetFixedSlotCount());
|
|
EXPECT_EQ(0, frame.GetSpillSlotCount());
|
|
EXPECT_EQ(0, frame.GetReturnSlotCount());
|
|
|
|
frame.AllocateSavedCalleeRegisterSlots(kSecondSlots);
|
|
EXPECT_EQ(kFixed3 + kFirstSlots + kSecondSlots,
|
|
frame.GetTotalFrameSlotCount());
|
|
EXPECT_EQ(kFixed3, frame.GetFixedSlotCount());
|
|
EXPECT_EQ(0, frame.GetSpillSlotCount());
|
|
EXPECT_EQ(0, frame.GetReturnSlotCount());
|
|
}
|
|
|
|
TEST_F(FrameTest, AlignSavedCalleeRegisterSlots) {
|
|
Frame frame(kFixed3);
|
|
constexpr int kSlots = 2; // An even number leaves the slots misaligned.
|
|
|
|
frame.AllocateSavedCalleeRegisterSlots(kSlots);
|
|
|
|
// Align, which should add 1 padding slot.
|
|
frame.AlignSavedCalleeRegisterSlots(2 * kSlotSize);
|
|
EXPECT_EQ(kFixed3 + kSlots + 1, frame.GetTotalFrameSlotCount());
|
|
EXPECT_EQ(kFixed3, frame.GetFixedSlotCount());
|
|
EXPECT_EQ(1, frame.GetSpillSlotCount()); // padding
|
|
EXPECT_EQ(0, frame.GetReturnSlotCount());
|
|
|
|
// Align again, which should not add a padding slot.
|
|
frame.AlignSavedCalleeRegisterSlots(2 * kSlotSize);
|
|
EXPECT_EQ(kFixed3 + kSlots + 1, frame.GetTotalFrameSlotCount());
|
|
EXPECT_EQ(kFixed3, frame.GetFixedSlotCount());
|
|
EXPECT_EQ(1, frame.GetSpillSlotCount()); // padding
|
|
EXPECT_EQ(0, frame.GetReturnSlotCount());
|
|
}
|
|
|
|
TEST_F(FrameTest, AllocateSpillSlotAligned) {
|
|
Frame frame(kFixed1);
|
|
|
|
// Allocate a quad slot, which must add 3 padding slots. Frame returns the
|
|
// last index of the 4 slot allocation.
|
|
int end = kFixed1 + 3 + 4;
|
|
int slot = kFixed1 + 3 + 4 - 1;
|
|
EXPECT_EQ(slot, frame.AllocateSpillSlot(4 * kSlotSize, 4 * kSlotSize));
|
|
EXPECT_EQ(end, frame.GetTotalFrameSlotCount());
|
|
EXPECT_EQ(kFixed1, frame.GetFixedSlotCount());
|
|
EXPECT_EQ(end - kFixed1, frame.GetSpillSlotCount());
|
|
EXPECT_EQ(0, frame.GetReturnSlotCount());
|
|
|
|
// Allocate a double slot, which should leave the first padding slot and
|
|
// take the last two slots of padding.
|
|
slot = kFixed1 + 1 + 2 - 1;
|
|
EXPECT_EQ(slot, frame.AllocateSpillSlot(2 * kSlotSize, 2 * kSlotSize));
|
|
EXPECT_EQ(end, frame.GetTotalFrameSlotCount());
|
|
EXPECT_EQ(kFixed1, frame.GetFixedSlotCount());
|
|
EXPECT_EQ(end - kFixed1, frame.GetSpillSlotCount());
|
|
EXPECT_EQ(0, frame.GetReturnSlotCount());
|
|
|
|
// Allocate a single slot, which should take the last padding slot.
|
|
slot = kFixed1;
|
|
EXPECT_EQ(slot, frame.AllocateSpillSlot(kSlotSize, kSlotSize));
|
|
EXPECT_EQ(end, frame.GetTotalFrameSlotCount());
|
|
EXPECT_EQ(kFixed1, frame.GetFixedSlotCount());
|
|
EXPECT_EQ(end - kFixed1, frame.GetSpillSlotCount());
|
|
EXPECT_EQ(0, frame.GetReturnSlotCount());
|
|
}
|
|
|
|
TEST_F(FrameTest, AllocateSpillSlotAlignedWithReturns) {
|
|
Frame frame(kFixed3);
|
|
constexpr int kReturn3 = 3;
|
|
constexpr int kReturn5 = 5;
|
|
|
|
frame.EnsureReturnSlots(kReturn3);
|
|
|
|
// Allocate a double slot, which must add 1 padding slot. This should occupy
|
|
// slots 4 and 5, and AllocateSpillSlot returns the last slot index.
|
|
EXPECT_EQ(kFixed3 + 2, frame.AllocateSpillSlot(2 * kSlotSize, 2 * kSlotSize));
|
|
EXPECT_EQ(kFixed3 + kReturn3 + 3, frame.GetTotalFrameSlotCount());
|
|
EXPECT_EQ(kFixed3, frame.GetFixedSlotCount());
|
|
EXPECT_EQ(3, frame.GetSpillSlotCount());
|
|
EXPECT_EQ(kReturn3, frame.GetReturnSlotCount());
|
|
|
|
frame.EnsureReturnSlots(kReturn5);
|
|
|
|
// Allocate a single slot, which should take the padding slot.
|
|
EXPECT_EQ(kFixed3, frame.AllocateSpillSlot(kSlotSize, kSlotSize));
|
|
EXPECT_EQ(kFixed3 + kReturn5 + 3, frame.GetTotalFrameSlotCount());
|
|
EXPECT_EQ(kFixed3, frame.GetFixedSlotCount());
|
|
EXPECT_EQ(3, frame.GetSpillSlotCount());
|
|
EXPECT_EQ(kReturn5, frame.GetReturnSlotCount());
|
|
}
|
|
|
|
TEST_F(FrameTest, AllocateSpillSlotAndEndSpillArea) {
|
|
Frame frame(kFixed3);
|
|
|
|
// Allocate a double slot, which must add 1 padding slot.
|
|
EXPECT_EQ(kFixed3 + 2, frame.AllocateSpillSlot(2 * kSlotSize, 2 * kSlotSize));
|
|
|
|
// Allocate an unaligned double slot. This should be at the end.
|
|
EXPECT_EQ(kFixed3 + 4, frame.AllocateSpillSlot(2 * kSlotSize));
|
|
EXPECT_EQ(kFixed3 + 5, frame.GetTotalFrameSlotCount());
|
|
EXPECT_EQ(kFixed3, frame.GetFixedSlotCount());
|
|
EXPECT_EQ(5, frame.GetSpillSlotCount());
|
|
EXPECT_EQ(0, frame.GetReturnSlotCount());
|
|
|
|
// Allocate a single slot. This should not be the padding slot, since that
|
|
// area has been closed by the unaligned allocation.
|
|
EXPECT_EQ(kFixed3 + 5, frame.AllocateSpillSlot(kSlotSize, kSlotSize));
|
|
EXPECT_EQ(kFixed3 + 6, frame.GetTotalFrameSlotCount());
|
|
EXPECT_EQ(kFixed3, frame.GetFixedSlotCount());
|
|
EXPECT_EQ(6, frame.GetSpillSlotCount());
|
|
EXPECT_EQ(0, frame.GetReturnSlotCount());
|
|
}
|
|
|
|
TEST_F(FrameTest, AllocateSpillSlotOverAligned) {
|
|
Frame frame(kFixed1);
|
|
|
|
// Allocate a 4-aligned double slot, which must add 3 padding slots. This
|
|
// also terminates the slot area. Returns the starting slot in this case.
|
|
EXPECT_EQ(kFixed1 + 4, frame.AllocateSpillSlot(2 * kSlotSize, 4 * kSlotSize));
|
|
EXPECT_EQ(kFixed1 + 5, frame.GetTotalFrameSlotCount());
|
|
EXPECT_EQ(kFixed1, frame.GetFixedSlotCount());
|
|
EXPECT_EQ(5, frame.GetSpillSlotCount());
|
|
EXPECT_EQ(0, frame.GetReturnSlotCount());
|
|
|
|
// Allocate a single slot. This should not use any padding slot.
|
|
EXPECT_EQ(kFixed1 + 5, frame.AllocateSpillSlot(kSlotSize, kSlotSize));
|
|
EXPECT_EQ(kFixed1 + 6, frame.GetTotalFrameSlotCount());
|
|
EXPECT_EQ(kFixed1, frame.GetFixedSlotCount());
|
|
EXPECT_EQ(6, frame.GetSpillSlotCount());
|
|
EXPECT_EQ(0, frame.GetReturnSlotCount());
|
|
}
|
|
|
|
TEST_F(FrameTest, AllocateSpillSlotUnderAligned) {
|
|
Frame frame(kFixed1);
|
|
|
|
// Allocate a 1-aligned double slot. This also terminates the slot area.
|
|
EXPECT_EQ(kFixed1 + 1, frame.AllocateSpillSlot(2 * kSlotSize, kSlotSize));
|
|
EXPECT_EQ(kFixed1 + 2, frame.GetTotalFrameSlotCount());
|
|
EXPECT_EQ(kFixed1, frame.GetFixedSlotCount());
|
|
EXPECT_EQ(2, frame.GetSpillSlotCount());
|
|
EXPECT_EQ(0, frame.GetReturnSlotCount());
|
|
}
|
|
|
|
TEST_F(FrameTest, AlignFrame) {
|
|
Frame frame(kFixed3);
|
|
constexpr int kReturn3 = 3;
|
|
|
|
frame.EnsureReturnSlots(kReturn3);
|
|
|
|
// Allocate two single slots, which leaves spill slots not 2-aligned.
|
|
EXPECT_EQ(kFixed3, frame.AllocateSpillSlot(kSlotSize, kSlotSize));
|
|
EXPECT_EQ(kFixed3 + 1, frame.AllocateSpillSlot(kSlotSize, kSlotSize));
|
|
|
|
// Align to 2 slots. This should pad the spill and return slot areas.
|
|
frame.AlignFrame(2 * kSlotSize);
|
|
|
|
EXPECT_EQ(kFixed3 + 3 + kReturn3 + 1, frame.GetTotalFrameSlotCount());
|
|
EXPECT_EQ(kFixed3, frame.GetFixedSlotCount());
|
|
EXPECT_EQ(3, frame.GetSpillSlotCount());
|
|
EXPECT_EQ(kReturn3 + 1, frame.GetReturnSlotCount());
|
|
}
|
|
|
|
} // namespace compiler
|
|
} // namespace internal
|
|
} // namespace v8
|