Commit 3a2575c2 authored by Anton Bikineev's avatar Anton Bikineev Committed by V8 LUCI CQ

Reland "cppgc: Try to fix test IteratePointersFindsCalleeSavedRegisters, vol.2"

Fix crash on Mac64 Debug build. The reason of the failure: misaligned
stack. Fix: apply attribute to force the stack be realigned.

Original description:
> The previous attempt has broken the tsan bot. The only reliable way to
> make sure that registers are not clobbered is by doing direct call from
> inline assembly, which is what this CL does.

> Change-Id: I6adbd5e735949a7cc4cc7fc686ee8c428863ffb9
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2859947
> Commit-Queue: Anton Bikineev <bikineev@chromium.org>
> Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#74313}

Change-Id: I842d6876c2cf287cfe74e53e7cb45028dff61a56
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2865748
Commit-Queue: Anton Bikineev <bikineev@chromium.org>
Reviewed-by: 's avatarMichael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#74336}
parent 99f4bb84
......@@ -305,6 +305,26 @@ TEST_F(GCStackTest, IteratePointersFindsParameterNesting8) {
#ifdef FOR_ALL_CALLEE_SAVED_REGS
namespace {
// We manually call into this function from inline assembly. Therefore we need
// to make sure that:
// 1) there is no .plt indirection (i.e. visibility is hidden);
// 2) stack is realigned in the function prologue.
V8_NOINLINE
#if !defined(V8_OS_WIN)
__attribute__((visibility("hidden")))
#endif
#ifdef __has_attribute
#if __has_attribute(force_align_arg_pointer)
__attribute__((force_align_arg_pointer))
#endif
#endif
extern "C" void
IteratePointersNoMangling(Stack* stack, StackVisitor* visitor) {
stack->IteratePointers(visitor);
}
} // namespace
TEST_F(GCStackTest, IteratePointersFindsCalleeSavedRegisters) {
auto scanner = std::make_unique<StackScanner>();
......@@ -321,22 +341,37 @@ TEST_F(GCStackTest, IteratePointersFindsCalleeSavedRegisters) {
auto* local_stack = GetStack();
auto* local_scanner = scanner.get();
#define MOVE_TO_REG_AND_CALL_IMPL(needle_reg, arg1, arg2) \
asm volatile("mov %0, %%" needle_reg "\n mov %1, %%" arg1 \
"\n mov %2, %%" arg2 \
"\n call %P3" \
"\n mov $0, %%" needle_reg \
: \
: "r"(local_scanner->needle()), "r"(local_stack), \
"r"(local_scanner), "i"(IteratePointersNoMangling) \
: "memory", needle_reg, arg1, arg2, "cc");
#ifdef V8_OS_WIN
#define MOVE_TO_REG_AND_CALL(reg) MOVE_TO_REG_AND_CALL_IMPL(reg, "rcx", "rdx")
#else // !V8_OS_WIN
#define MOVE_TO_REG_AND_CALL(reg) MOVE_TO_REG_AND_CALL_IMPL(reg, "rdi", "rsi")
#endif // V8_OS_WIN
// Moves |local_scanner->needle()| into a callee-saved register, leaving the
// callee-saved register as the only register referencing the needle.
// (Ignoring implementation-dependent dirty registers/stack.)
#define KEEP_ALIVE_FROM_CALLEE_SAVED(reg) \
local_scanner->Reset(); \
/* This moves the temporary into the calee-saved register. */ \
asm("mov %0, %%" reg : : "r"(local_scanner->needle()) : reg); \
/* Register is unprotected from here till the actual invocation. */ \
local_stack->IteratePointers(local_scanner); \
/* Wrap the inline assembly in a lambda to rely on the compiler for saving \
caller-saved registers. */ \
[local_stack, local_scanner]() V8_NOINLINE { MOVE_TO_REG_AND_CALL(reg) }(); \
EXPECT_TRUE(local_scanner->found()) \
<< "pointer in callee-saved register not found. register: " << reg \
<< std::endl; \
/* Clear out the register again */ \
asm("mov $0, %%" reg : : : reg);
<< std::endl;
FOR_ALL_CALLEE_SAVED_REGS(KEEP_ALIVE_FROM_CALLEE_SAVED)
#undef MOVE_TO_REG_AND_CALL
#undef MOVE_TO_REG_AND_CALL_IMPL
#undef KEEP_ALIVE_FROM_CALLEE_SAVED
#undef FOR_ALL_CALLEE_SAVED_REGS
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment