Reland "[ptr-cage] Reserve base registers on x64 (r14) and arm64 (x28)"

This is a reland of 0c63aa9eee

Fixes the correctness fuzzing BUILD.gn breakage.

Original change's description:
> [ptr-cage] Reserve base registers on x64 (r14) and arm64 (x28)
>
> Also add a V8_COMPRESS_POINTERS_IN_SHARED_CAGE define when pointer
> compression is enabled.
>
> This CL is to get performance numbers for reserving an extra register.
> There is no actual pointer cage yet, and the base register will always
> have the same value as the root register. The pointer decompression code
> is switched to using the base register instead of the root register.
>
> Bug: v8:11460
> Change-Id: I40bae556c2098608fb6fc193a52694e3f54754bd
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2716075
> Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
> Reviewed-by: Ross McIlroy <rmcilroy@chromium.org>
> Reviewed-by: Leszek Swirski <leszeks@chromium.org>
> Commit-Queue: Shu-yu Guo <syg@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#73204}

TBR=rmcilroy@chromium.org,jkummerow@chromium.org,leszeks@chromium.org

Bug: v8:11460
Change-Id: Iecf6b783392a384b40ab33e0f4ce13538a8f81ee
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2737681
Reviewed-by: Shu-yu Guo <syg@chromium.org>
Commit-Queue: Shu-yu Guo <syg@chromium.org>
Cr-Commit-Position: refs/heads/master@{#73207}
This commit is contained in:
Shu-yu Guo 2021-03-04 16:55:44 -08:00 committed by Commit Bot
parent 5300b26dcf
commit eed7206347
15 changed files with 130 additions and 46 deletions

View File

@ -108,6 +108,7 @@ declare_args() {
# Enable pointer compression (sets -dV8_COMPRESS_POINTERS).
v8_enable_pointer_compression = ""
v8_enable_pointer_compression_shared_cage = ""
v8_enable_31bit_smis_on_64bit_arch = false
# Sets -dOBJECT_PRINT.
@ -324,6 +325,9 @@ if (v8_enable_pointer_compression == "") {
v8_enable_pointer_compression =
v8_current_cpu == "arm64" || v8_current_cpu == "x64"
}
if (v8_enable_pointer_compression_shared_cage == "") {
v8_enable_pointer_compression_shared_cage = v8_enable_pointer_compression
}
if (v8_enable_fast_torque == "") {
v8_enable_fast_torque = v8_enable_fast_mksnapshot
}
@ -362,6 +366,7 @@ if (v8_multi_arch_build &&
rebase_path(get_label_info(":d8", "root_out_dir"), root_build_dir) ==
"clang_x64_pointer_compression") {
v8_enable_pointer_compression = !v8_enable_pointer_compression
v8_enable_pointer_compression_shared_cage = v8_enable_pointer_compression
}
if (v8_enable_shared_ro_heap == "") {
v8_enable_shared_ro_heap = !v8_enable_pointer_compression
@ -388,6 +393,10 @@ assert(!v8_use_multi_snapshots || !v8_control_flow_integrity,
assert(!v8_enable_heap_sandbox || v8_enable_pointer_compression,
"V8 Heap Sandbox requires pointer compression")
assert(
!v8_enable_pointer_compression_shared_cage || v8_enable_pointer_compression,
"Can't share a pointer compression cage if pointers aren't compressed")
assert(!v8_enable_unconditional_write_barriers || !v8_disable_write_barriers,
"Write barriers can't be both enabled and disabled")
@ -527,6 +536,7 @@ config("external_startup_data") {
external_v8_defines = [
"V8_ENABLE_CHECKS",
"V8_COMPRESS_POINTERS",
"V8_COMPRESS_POINTERS_IN_SHARED_CAGE",
"V8_31BIT_SMIS_ON_64BIT_ARCH",
"V8_COMPRESS_ZONES",
"V8_HEAP_SANDBOX",
@ -544,6 +554,9 @@ if (v8_enable_v8_checks) {
if (v8_enable_pointer_compression) {
enabled_external_v8_defines += [ "V8_COMPRESS_POINTERS" ]
}
if (v8_enable_pointer_compression_shared_cage) {
enabled_external_v8_defines += [ "V8_COMPRESS_POINTERS_IN_SHARED_CAGE" ]
}
if (v8_enable_pointer_compression || v8_enable_31bit_smis_on_64bit_arch) {
enabled_external_v8_defines += [ "V8_31BIT_SMIS_ON_64BIT_ARCH" ]
}

View File

@ -17,7 +17,7 @@ namespace detail {
// Avoid using kScratchRegister(==r10) since the macro-assembler doesn't use
// this scope and will conflict.
static constexpr Register kScratchRegisters[] = {r8, r9, r11, r12, r14, r15};
static constexpr Register kScratchRegisters[] = {r8, r9, r11, r12, r15};
static constexpr int kNumScratchRegisters = arraysize(kScratchRegisters);
} // namespace detail

View File

@ -632,6 +632,11 @@ void Generate_JSEntryVariant(MacroAssembler* masm, StackFrame::Type type,
// Initialize the root register.
// C calling convention. The first argument is passed in x0.
__ Mov(kRootRegister, x0);
#ifdef V8_COMPRESS_POINTERS_IN_SHARED_CAGE
// Initialize the pointer cage base register.
__ Mov(kPointerCageBaseRegister, x0);
#endif
}
// Set up fp. It points to the {fp, lr} pair pushed as the last step in
@ -910,10 +915,13 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
__ Mov(x23, x19);
__ Mov(x24, x19);
__ Mov(x25, x19);
#ifndef V8_COMPRESS_POINTERS_IN_SHARED_CAGE
__ Mov(x28, x19);
#endif
// Don't initialize the reserved registers.
// x26 : root register (kRootRegister).
// x27 : context pointer (cp).
// x28 : pointer cage base register (kPointerCageBaseRegister).
// x29 : frame pointer (fp).
Handle<Code> builtin = is_construct

View File

@ -377,6 +377,12 @@ void Generate_JSEntryVariant(MacroAssembler* masm, StackFrame::Type type,
// Initialize the root register.
// C calling convention. The first argument is passed in arg_reg_1.
__ movq(kRootRegister, arg_reg_1);
#ifdef V8_COMPRESS_POINTERS_IN_SHARED_CAGE
// Initialize the pointer cage base register.
// TODO(syg): Actually make a cage.
__ movq(kPointerCageBaseRegister, arg_reg_1);
#endif
}
// Save copies of the top frame descriptor on the stack.
@ -1633,7 +1639,7 @@ void Builtins::Generate_BaselineOutOfLinePrologue(MacroAssembler* masm) {
__ incl(
FieldOperand(feedback_vector, FeedbackVector::kInvocationCountOffset));
Register return_address = r12;
Register return_address = r15;
__ RecordComment("[ Frame Setup");
// Save the return address, so that we can push it to the end of the newly
@ -2810,8 +2816,8 @@ void Builtins::Generate_CEntry(MacroAssembler* masm, int result_size,
DCHECK(save_doubles == kDontSaveFPRegs);
DCHECK(!builtin_exit_frame);
__ EnterApiExitFrame(arg_stack_space);
// Move argc into r14 (argv is already in r15).
__ movq(r14, rax);
// Move argc into r12 (argv is already in r15).
__ movq(r12, rax);
} else {
__ EnterExitFrame(
arg_stack_space, save_doubles == kSaveFPRegs,
@ -2821,7 +2827,7 @@ void Builtins::Generate_CEntry(MacroAssembler* masm, int result_size,
// rbx: pointer to builtin function (C callee-saved).
// rbp: frame pointer of exit frame (restored after C call).
// rsp: stack pointer (restored after C call).
// r14: number of arguments including receiver (C callee-saved).
// r12: number of arguments including receiver (C callee-saved).
// r15: argv pointer (C callee-saved).
// Check stack alignment.
@ -2834,7 +2840,7 @@ void Builtins::Generate_CEntry(MacroAssembler* masm, int result_size,
if (result_size <= kMaxRegisterResultSize) {
// Pass a pointer to the Arguments object as the first argument.
// Return result in single register (rax), or a register pair (rax, rdx).
__ movq(kCCallArg0, r14); // argc.
__ movq(kCCallArg0, r12); // argc.
__ movq(kCCallArg1, r15); // argv.
__ Move(kCCallArg2, ExternalReference::isolate_address(masm->isolate()));
} else {
@ -2842,7 +2848,7 @@ void Builtins::Generate_CEntry(MacroAssembler* masm, int result_size,
// Pass a pointer to the result location as the first argument.
__ leaq(kCCallArg0, StackSpaceOperand(kArgExtraStackSpace));
// Pass a pointer to the Arguments object as the second argument.
__ movq(kCCallArg1, r14); // argc.
__ movq(kCCallArg1, r12); // argc.
__ movq(kCCallArg2, r15); // argv.
__ Move(kCCallArg3, ExternalReference::isolate_address(masm->isolate()));
}
@ -2866,12 +2872,12 @@ void Builtins::Generate_CEntry(MacroAssembler* masm, int result_size,
// should have returned the exception sentinel.
if (FLAG_debug_code) {
Label okay;
__ LoadRoot(r14, RootIndex::kTheHoleValue);
__ LoadRoot(kScratchRegister, RootIndex::kTheHoleValue);
ExternalReference pending_exception_address = ExternalReference::Create(
IsolateAddressId::kPendingExceptionAddress, masm->isolate());
Operand pending_exception_operand =
masm->ExternalReferenceAsOperand(pending_exception_address);
__ cmp_tagged(r14, pending_exception_operand);
__ cmp_tagged(kScratchRegister, pending_exception_operand);
__ j(equal, &okay, Label::kNear);
__ int3();
__ bind(&okay);
@ -3212,7 +3218,7 @@ void Builtins::Generate_GenericJSToWasmWrapper(MacroAssembler* masm) {
kLastSpillOffset - kSystemPointerSize;
// For Integer section.
// Set the current_int_param_slot to point to the start of the section.
Register current_int_param_slot = r14;
Register current_int_param_slot = r10;
__ leaq(current_int_param_slot, MemOperand(rsp, -kSystemPointerSize));
Register params_size = param_count;
param_count = no_reg;
@ -3326,7 +3332,7 @@ void Builtins::Generate_GenericJSToWasmWrapper(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r8 : start_int_section
// -- rdi : start_float_section
// -- r14 : current_int_param_slot
// -- r10 : current_int_param_slot
// -- r15 : current_float_param_slot
// -- r11 : valuetypes_array_ptr
// -- r12 : valuetype
@ -3758,7 +3764,7 @@ int Offset(ExternalReference ref0, ExternalReference ref1) {
}
// Calls an API function. Allocates HandleScope, extracts returned value
// from handle and propagates exceptions. Clobbers r14, r15, rbx and
// from handle and propagates exceptions. Clobbers r12, r15, rbx and
// caller-save registers. Restores context. On return removes
// stack_space * kSystemPointerSize (GCed).
void CallApiFunctionAndReturn(MacroAssembler* masm, Register function_address,
@ -3785,7 +3791,7 @@ void CallApiFunctionAndReturn(MacroAssembler* masm, Register function_address,
DCHECK(rdx == function_address || r8 == function_address);
// Allocate HandleScope in callee-save registers.
Register prev_next_address_reg = r14;
Register prev_next_address_reg = r12;
Register prev_limit_reg = rbx;
Register base_reg = r15;
__ Move(base_reg, next_address);

View File

@ -1036,6 +1036,9 @@ void TurboAssembler::Uxtw(const Register& rd, const Register& rn) {
void TurboAssembler::InitializeRootRegister() {
ExternalReference isolate_root = ExternalReference::isolate_root(isolate());
Mov(kRootRegister, Operand(isolate_root));
#ifdef V8_COMPRESS_POINTERS_IN_SHARED_CAGE
Mov(kPointerCageBaseRegister, Operand(isolate_root));
#endif
}
void MacroAssembler::SmiTag(Register dst, Register src) {

View File

@ -2816,14 +2816,14 @@ void TurboAssembler::DecompressTaggedPointer(const Register& destination,
const MemOperand& field_operand) {
RecordComment("[ DecompressTaggedPointer");
Ldr(destination.W(), field_operand);
Add(destination, kRootRegister, destination);
Add(destination, kPointerCageBaseRegister, destination);
RecordComment("]");
}
void TurboAssembler::DecompressTaggedPointer(const Register& destination,
const Register& source) {
RecordComment("[ DecompressTaggedPointer");
Add(destination, kRootRegister, Operand(source, UXTW));
Add(destination, kPointerCageBaseRegister, Operand(source, UXTW));
RecordComment("]");
}
@ -2831,7 +2831,7 @@ void TurboAssembler::DecompressAnyTagged(const Register& destination,
const MemOperand& field_operand) {
RecordComment("[ DecompressAnyTagged");
Ldr(destination.W(), field_operand);
Add(destination, kRootRegister, destination);
Add(destination, kPointerCageBaseRegister, destination);
RecordComment("]");
}

View File

@ -30,11 +30,21 @@ namespace internal {
// x18 is the platform register and is reserved for the use of platform ABIs.
// It is known to be reserved by the OS at least on Windows and iOS.
#define ALLOCATABLE_GENERAL_REGISTERS(R) \
#define ALWAYS_ALLOCATABLE_GENERAL_REGISTERS(R) \
R(x0) R(x1) R(x2) R(x3) R(x4) R(x5) R(x6) R(x7) \
R(x8) R(x9) R(x10) R(x11) R(x12) R(x13) R(x14) R(x15) \
R(x19) R(x20) R(x21) R(x22) R(x23) R(x24) R(x25) \
R(x27) R(x28)
R(x27)
#ifdef V8_COMPRESS_POINTERS_IN_SHARED_CAGE
#define MAYBE_ALLOCATABLE_GENERAL_REGISTERS(R)
#else
#define MAYBE_ALLOCATABLE_GENERAL_REGISTERS(R) R(x28)
#endif
#define ALLOCATABLE_GENERAL_REGISTERS(V) \
ALWAYS_ALLOCATABLE_GENERAL_REGISTERS(V) \
MAYBE_ALLOCATABLE_GENERAL_REGISTERS(V)
#define FLOAT_REGISTERS(V) \
V(s0) V(s1) V(s2) V(s3) V(s4) V(s5) V(s6) V(s7) \
@ -458,6 +468,12 @@ ALIAS_REGISTER(Register, wip1, w17);
// Root register.
ALIAS_REGISTER(Register, kRootRegister, x26);
ALIAS_REGISTER(Register, rr, x26);
// Pointer cage base register.
#ifdef V8_COMPRESS_POINTERS_IN_SHARED_CAGE
ALIAS_REGISTER(Register, kPointerCageBaseRegister, x28);
#else
ALIAS_REGISTER(Register, kPointerCageBaseRegister, kRootRegister);
#endif
// Context pointer register.
ALIAS_REGISTER(Register, cp, x27);
ALIAS_REGISTER(Register, fp, x29);

View File

@ -25,6 +25,9 @@ void CallInterfaceDescriptorData::InitializePlatformSpecific(
// within the calling convention are disallowed.
#ifdef DEBUG
CHECK_NE(registers[i], kRootRegister);
#ifdef V8_COMPRESS_POINTERS_IN_SHARED_CAGE
CHECK_NE(registers[i], kPointerCageBaseRegister);
#endif
// Check for duplicated registers.
for (int j = i + 1; j < register_parameter_count; j++) {
CHECK_NE(registers[i], registers[j]);

View File

@ -288,7 +288,7 @@ void TurboAssembler::DecompressTaggedPointer(Register destination,
Operand field_operand) {
RecordComment("[ DecompressTaggedPointer");
movl(destination, field_operand);
addq(destination, kRootRegister);
addq(destination, kPointerCageBaseRegister);
RecordComment("]");
}
@ -296,7 +296,7 @@ void TurboAssembler::DecompressTaggedPointer(Register destination,
Register source) {
RecordComment("[ DecompressTaggedPointer");
movl(destination, source);
addq(destination, kRootRegister);
addq(destination, kPointerCageBaseRegister);
RecordComment("]");
}
@ -304,7 +304,7 @@ void TurboAssembler::DecompressAnyTagged(Register destination,
Operand field_operand) {
RecordComment("[ DecompressAnyTagged");
movl(destination, field_operand);
addq(destination, kRootRegister);
addq(destination, kPointerCageBaseRegister);
RecordComment("]");
}
@ -3383,7 +3383,7 @@ void TurboAssembler::AllocateStackSpace(int bytes) {
}
#endif
void MacroAssembler::EnterExitFramePrologue(bool save_rax,
void MacroAssembler::EnterExitFramePrologue(Register saved_rax_reg,
StackFrame::Type frame_type) {
DCHECK(frame_type == StackFrame::EXIT ||
frame_type == StackFrame::BUILTIN_EXIT);
@ -3403,8 +3403,8 @@ void MacroAssembler::EnterExitFramePrologue(bool save_rax,
Push(Immediate(0)); // Saved entry sp, patched before call.
// Save the frame pointer and the context in top.
if (save_rax) {
movq(r14, rax); // Backup rax in callee-save register.
if (saved_rax_reg != no_reg) {
movq(saved_rax_reg, rax); // Backup rax in callee-save register.
}
Store(
@ -3453,18 +3453,19 @@ void MacroAssembler::EnterExitFrameEpilogue(int arg_stack_space,
void MacroAssembler::EnterExitFrame(int arg_stack_space, bool save_doubles,
StackFrame::Type frame_type) {
EnterExitFramePrologue(true, frame_type);
Register saved_rax_reg = r12;
EnterExitFramePrologue(saved_rax_reg, frame_type);
// Set up argv in callee-saved register r15. It is reused in LeaveExitFrame,
// so it must be retained across the C-call.
int offset = StandardFrameConstants::kCallerSPOffset - kSystemPointerSize;
leaq(r15, Operand(rbp, r14, times_system_pointer_size, offset));
leaq(r15, Operand(rbp, saved_rax_reg, times_system_pointer_size, offset));
EnterExitFrameEpilogue(arg_stack_space, save_doubles);
}
void MacroAssembler::EnterApiExitFrame(int arg_stack_space) {
EnterExitFramePrologue(false, StackFrame::EXIT);
EnterExitFramePrologue(no_reg, StackFrame::EXIT);
EnterExitFrameEpilogue(arg_stack_space, false);
}

View File

@ -704,6 +704,9 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
void InitializeRootRegister() {
ExternalReference isolate_root = ExternalReference::isolate_root(isolate());
Move(kRootRegister, isolate_root);
#ifdef V8_COMPRESS_POINTERS_IN_SHARED_CAGE
Move(kPointerCageBaseRegister, isolate_root);
#endif
}
void SaveRegisters(RegList registers);
@ -1146,7 +1149,8 @@ class V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler {
Register actual_parameter_count, Label* done,
InvokeFlag flag);
void EnterExitFramePrologue(bool save_rax, StackFrame::Type frame_type);
void EnterExitFramePrologue(Register saved_rax_reg,
StackFrame::Type frame_type);
// Allocates arg_stack_space * kSystemPointerSize memory (not GCed) on the
// stack accessible via StackSpaceOperand.

View File

@ -29,20 +29,29 @@ namespace internal {
V(r14) \
V(r15)
#define ALLOCATABLE_GENERAL_REGISTERS(V) \
V(rax) \
V(rbx) \
V(rdx) \
V(rcx) \
V(rsi) \
V(rdi) \
V(r8) \
V(r9) \
V(r11) \
V(r12) \
V(r14) \
#define ALWAYS_ALLOCATABLE_GENERAL_REGISTERS(V) \
V(rax) \
V(rbx) \
V(rdx) \
V(rcx) \
V(rsi) \
V(rdi) \
V(r8) \
V(r9) \
V(r11) \
V(r12) \
V(r15)
#ifdef V8_COMPRESS_POINTERS_IN_SHARED_CAGE
#define MAYBE_ALLOCATABLE_GENERAL_REGISTERS(V)
#else
#define MAYBE_ALLOCATABLE_GENERAL_REGISTERS(V) V(r14)
#endif
#define ALLOCATABLE_GENERAL_REGISTERS(V) \
ALWAYS_ALLOCATABLE_GENERAL_REGISTERS(V) \
MAYBE_ALLOCATABLE_GENERAL_REGISTERS(V)
enum RegisterCode {
#define REGISTER_CODE(R) kRegCode_##R,
GENERAL_REGISTERS(REGISTER_CODE)
@ -201,7 +210,7 @@ constexpr Register kAllocateSizeRegister = rdx;
constexpr Register kSpeculationPoisonRegister = r12;
constexpr Register kInterpreterAccumulatorRegister = rax;
constexpr Register kInterpreterBytecodeOffsetRegister = r9;
constexpr Register kInterpreterBytecodeArrayRegister = r14;
constexpr Register kInterpreterBytecodeArrayRegister = r12;
constexpr Register kInterpreterDispatchTableRegister = r15;
constexpr Register kJavaScriptCallArgCountRegister = rax;
@ -221,6 +230,11 @@ constexpr Register kWasmInstanceRegister = rsi;
constexpr Register kScratchRegister = r10;
constexpr XMMRegister kScratchDoubleReg = xmm15;
constexpr Register kRootRegister = r13; // callee save
#ifdef V8_COMPRESS_POINTERS_IN_SHARED_CAGE
constexpr Register kPointerCageBaseRegister = r14; // callee save
#else
constexpr Register kPointerCageBaseRegister = kRootRegister;
#endif
constexpr Register kOffHeapTrampolineRegister = kScratchRegister;

View File

@ -962,6 +962,10 @@ void Deoptimizer::DoComputeOutputFrames() {
FrameDescription* topmost = output_[count - 1];
topmost->GetRegisterValues()->SetRegister(kRootRegister.code(),
isolate()->isolate_root());
#ifdef V8_COMPRESS_POINTERS_IN_SHARED_CAGE
topmost->GetRegisterValues()->SetRegister(kPointerCageBaseRegister.code(),
isolate()->isolate_root());
#endif
// Print some helpful diagnostic information.
if (verbose_tracing_enabled()) {

View File

@ -58,11 +58,15 @@ constexpr RegList kLiftoffAssemblerFpCacheRegs = LowDwVfpRegister::ListOf(
#elif V8_TARGET_ARCH_ARM64
// x16: ip0, x17: ip1, x18: platform register, x26: root, x27: cp, x29: fp,
// x30: lr, x31: xzr.
// x16: ip0, x17: ip1, x18: platform register, x26: root, x27: cp, x8: base,
// x29: fp, x30: lr, x31: xzr.
constexpr RegList kLiftoffAssemblerGpCacheRegs =
CPURegister::ListOf(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12,
#ifdef V8_COMPRESS_POINTERS_IN_SHARED_CAGE
x13, x14, x15, x19, x20, x21, x22, x23, x24, x25);
#else
x13, x14, x15, x19, x20, x21, x22, x23, x24, x25, x28);
#endif
// d15: fp_zero, d30-d31: macro-assembler scratch V Registers.
constexpr RegList kLiftoffAssemblerFpCacheRegs = CPURegister::ListOf(

View File

@ -60,10 +60,18 @@ using F0 = int();
static void EntryCode(MacroAssembler* masm) {
// Smi constant register is callee save.
__ pushq(kRootRegister);
#ifdef V8_COMPRESS_POINTERS_IN_SHARED_CAGE
__ pushq(kPointerCageBaseRegister);
#endif
__ InitializeRootRegister();
}
static void ExitCode(MacroAssembler* masm) { __ popq(kRootRegister); }
static void ExitCode(MacroAssembler* masm) {
#ifdef V8_COMPRESS_POINTERS_IN_SHARED_CAGE
__ popq(kPointerCageBaseRegister);
#endif
__ popq(kRootRegister);
}
TEST(Smi) {
// Check that C++ Smi operations work as expected.

View File

@ -121,7 +121,7 @@ TEST(DisasmPoisonPolymorphicLoad) {
"csdb", // spec. barrier
"ldur w<<BSt:[0-9]+>>, \\[<<Obj>>, #[0-9]+\\]", // load backing store
// branchful decompress
"add x<<BSt>>, x26, x<<BSt>>", // Add root to ref
"add x<<BSt>>, x2[68], x<<BSt>>", // Add root to ref
"and x<<BSt>>, x<<BSt>>, " + kPReg, // apply the poison
"ldur w<<Prop:[0-9]+>>, \\[x<<BSt>>, #[0-9]+\\]", // load the property
"and x<<Prop>>, x<<Prop>>, " + kPReg, // apply the poison
@ -194,7 +194,7 @@ TEST(DisasmPoisonMonomorphicLoadFloat64) {
"csel " + kPReg + ", xzr, " + kPReg + ", ne", // update the poison
"csdb", // spec. barrier
"ldur w<<F1:[0-9]+>>, \\[<<Obj>>, #11\\]", // load heap number
"add x<<F1>>, x26, x<<F1>>", // Decompress ref
"add x<<F1>>, x2[68], x<<F1>>", // Decompress ref
"and x<<F1>>, x<<F1>>, " + kPReg, // apply the poison
"add <<Addr:x[0-9]+>>, x<<F1>>, #0x[0-9a-f]+", // addr. calculation
"and <<Addr>>, <<Addr>>, " + kPReg, // apply the poison