cppgc: Fix test IteratePointersFindsCalleeSavedRegisters
call the compiler can clobber the tested register. Moving this tricky part into a noninlinable lambda allows to reduce pressure from the register allocator and thereby avoid such clobbering. Subtle: between the first inline assembly and the IteratePointers() Change-Id: Ibeca8fa2f4fd54d07c2f585a4e876504a6a991b7 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2859843 Commit-Queue: Anton Bikineev <bikineev@chromium.org> Reviewed-by: Michael Lippautz <mlippautz@chromium.org> Cr-Commit-Position: refs/heads/master@{#74280}
This commit is contained in:
parent
530080c44a
commit
4ff37d3a3f
@ -308,6 +308,8 @@ TEST_F(GCStackTest, IteratePointersFindsParameterNesting8) {
|
||||
|
||||
#ifdef FOR_ALL_CALLEE_SAVED_REGS
|
||||
|
||||
// Note: the test is brittle and can fail on some archs/configurations (see
|
||||
// below).
|
||||
TEST_F(GCStackTest, IteratePointersFindsCalleeSavedRegisters) {
|
||||
auto scanner = std::make_unique<StackScanner>();
|
||||
|
||||
@ -327,17 +329,32 @@ TEST_F(GCStackTest, IteratePointersFindsCalleeSavedRegisters) {
|
||||
// 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.)
|
||||
//
|
||||
// Subtle: between the first inline assembly and the IteratePointers() call the
|
||||
// compiler can clobber the tested register. Moving this tricky part into a
|
||||
// noninlinable lambda allows to reduce pressure from the register allocator and
|
||||
// thereby avoid such clobbering.
|
||||
#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. */ \
|
||||
const bool found = [local_scanner, local_stack]() V8_NOINLINE { \
|
||||
/* This moves the temporary into the callee-saved register. */ \
|
||||
asm volatile("mov %0, %%" reg \
|
||||
: \
|
||||
: "r"(local_scanner->needle()) \
|
||||
: "memory", reg); \
|
||||
/* Register is unprotected from here till the actual invocation. The \
|
||||
* compiler is free to clobber the register which makes the test \
|
||||
* fail. */ \
|
||||
local_stack->IteratePointers(local_scanner); \
|
||||
EXPECT_TRUE(local_scanner->found()) \
|
||||
/* Clear out the register again */ \
|
||||
asm volatile("mov $0, %%" reg : : : "memory", reg); \
|
||||
return local_scanner->found(); \
|
||||
}(); \
|
||||
EXPECT_TRUE(found) \
|
||||
<< "pointer in callee-saved register not found. register: " << reg \
|
||||
<< std::endl; \
|
||||
/* Clear out the register again */ \
|
||||
asm("mov $0, %%" reg : : : reg);
|
||||
}
|
||||
|
||||
FOR_ALL_CALLEE_SAVED_REGS(KEEP_ALIVE_FROM_CALLEE_SAVED)
|
||||
#undef KEEP_ALIVE_FROM_CALLEE_SAVED
|
||||
|
Loading…
Reference in New Issue
Block a user