Commit 9227a8da authored by Milad Fa's avatar Milad Fa Committed by V8 LUCI CQ

PPC/s390: [regexp] Fix stack growth for global regexps

Port 3e3a027d

Original Commit Message:

    Irregexp reentrancy (crrev.com/c/3162604) introduced a bug for global
    regexp execution in which each iteration would use a new stack region
    (i.e. we forgot to pop the regexp stack pointer when starting a new
    iteration).

    This CL fixes that by popping the stack pointer on the loop backedge.

    At a high level:

    - Initialize the backtrack_stackpointer earlier and avoid clobbering
      it by setup code.
    - Pop it on the loop backedge.
    - Slightly refactor Push/Pop operations to avoid unneeded memory
      accesses.

R=jgruber@chromium.org, joransiu@ca.ibm.com, junyan@redhat.com, midawson@redhat.com
BUG=
LOG=N

Change-Id: Iafe6814d3695e83fced6a46209accf5e712d56f6
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3198391Reviewed-by: 's avatarJunliang Yan <junyan@redhat.com>
Commit-Queue: Milad Fa <mfarazma@redhat.com>
Cr-Commit-Position: refs/heads/main@{#77180}
parent 3cfb9308
......@@ -665,26 +665,26 @@ void RegExpMacroAssemblerPPC::StoreRegExpStackPointerToMemory(
__ StoreU64(src, MemOperand(scratch));
}
void RegExpMacroAssemblerPPC::PushRegExpBasePointer(Register scratch1,
Register scratch2) {
LoadRegExpStackPointerFromMemory(scratch1);
void RegExpMacroAssemblerPPC::PushRegExpBasePointer(Register stack_pointer,
Register scratch) {
ExternalReference ref =
ExternalReference::address_of_regexp_stack_memory_top_address(isolate());
__ mov(scratch2, Operand(ref));
__ LoadU64(scratch2, MemOperand(scratch2));
__ SubS64(scratch2, scratch1, scratch2);
__ StoreU64(scratch2, MemOperand(frame_pointer(), kRegExpStackBasePointer));
__ mov(scratch, Operand(ref));
__ LoadU64(scratch, MemOperand(scratch));
__ SubS64(scratch, stack_pointer, scratch);
__ StoreU64(scratch, MemOperand(frame_pointer(), kRegExpStackBasePointer));
}
void RegExpMacroAssemblerPPC::PopRegExpBasePointer(Register scratch1,
Register scratch2) {
void RegExpMacroAssemblerPPC::PopRegExpBasePointer(Register stack_pointer_out,
Register scratch) {
ExternalReference ref =
ExternalReference::address_of_regexp_stack_memory_top_address(isolate());
__ LoadU64(scratch1, MemOperand(frame_pointer(), kRegExpStackBasePointer));
__ mov(scratch2, Operand(ref));
__ LoadU64(scratch2, MemOperand(scratch2));
__ AddS64(scratch1, scratch1, scratch2);
StoreRegExpStackPointerToMemory(scratch1, scratch2);
__ LoadU64(stack_pointer_out,
MemOperand(frame_pointer(), kRegExpStackBasePointer));
__ mov(scratch, Operand(ref));
__ LoadU64(scratch, MemOperand(scratch));
__ AddS64(stack_pointer_out, stack_pointer_out, scratch);
StoreRegExpStackPointerToMemory(stack_pointer_out, scratch);
}
Handle<HeapObject> RegExpMacroAssemblerPPC::GetCode(Handle<String> source) {
......@@ -743,37 +743,44 @@ Handle<HeapObject> RegExpMacroAssemblerPPC::GetCode(Handle<String> source) {
kBacktrackCount - kSystemPointerSize);
__ push(r3); // The regexp stack base ptr.
// Initialize backtrack stack pointer. It must not be clobbered from here
// on. Note the backtrack_stackpointer is callee-saved.
STATIC_ASSERT(backtrack_stackpointer() == r29);
LoadRegExpStackPointerFromMemory(backtrack_stackpointer());
// Store the regexp base pointer - we'll later restore it / write it to
// memory when returning from this irregexp code object.
PushRegExpBasePointer(r3, r4);
// Check if we have space on the stack for registers.
Label stack_limit_hit;
Label stack_ok;
ExternalReference stack_limit =
ExternalReference::address_of_jslimit(isolate());
__ mov(r3, Operand(stack_limit));
__ LoadU64(r3, MemOperand(r3));
__ sub(r3, sp, r3, LeaveOE, SetRC);
// Handle it if the stack pointer is already below the stack limit.
__ ble(&stack_limit_hit, cr0);
// Check if there is room for the variable number of registers above
// the stack limit.
__ CmpU64(r3, Operand(num_registers_ * kSystemPointerSize), r0);
__ bge(&stack_ok);
// Exit with OutOfMemory exception. There is not enough space on the stack
// for our working registers.
__ li(r3, Operand(EXCEPTION));
__ b(&return_r3);
__ bind(&stack_limit_hit);
CallCheckStackGuardState(r3);
__ cmpi(r3, Operand::Zero());
// If returned value is non-zero, we exit with the returned value as result.
__ bne(&return_r3);
PushRegExpBasePointer(backtrack_stackpointer(), r4);
{
// Check if we have space on the stack for registers.
Label stack_limit_hit, stack_ok;
ExternalReference stack_limit =
ExternalReference::address_of_jslimit(isolate());
__ mov(r3, Operand(stack_limit));
__ LoadU64(r3, MemOperand(r3));
__ sub(r3, sp, r3, LeaveOE, SetRC);
// Handle it if the stack pointer is already below the stack limit.
__ ble(&stack_limit_hit, cr0);
// Check if there is room for the variable number of registers above
// the stack limit.
__ CmpU64(r3, Operand(num_registers_ * kSystemPointerSize), r0);
__ bge(&stack_ok);
// Exit with OutOfMemory exception. There is not enough space on the stack
// for our working registers.
__ li(r3, Operand(EXCEPTION));
__ b(&return_r3);
__ bind(&stack_limit_hit);
CallCheckStackGuardState(r3);
__ cmpi(r3, Operand::Zero());
// If returned value is non-zero, we exit with the returned value as
// result.
__ bne(&return_r3);
__ bind(&stack_ok);
__ bind(&stack_ok);
}
// Allocate space on stack for registers.
__ AddS64(sp, sp, Operand(-num_registers_ * kSystemPointerSize), r0);
......@@ -800,18 +807,21 @@ Handle<HeapObject> RegExpMacroAssemblerPPC::GetCode(Handle<String> source) {
// Initialize code pointer register
__ mov(code_pointer(), Operand(masm_->CodeObject()));
Label load_char_start_regexp, start_regexp;
// Load newline if index is at start, previous character otherwise.
__ cmpi(r4, Operand::Zero());
__ bne(&load_char_start_regexp);
__ li(current_character(), Operand('\n'));
__ b(&start_regexp);
// Global regexp restarts matching here.
__ bind(&load_char_start_regexp);
// Load previous char as initial value of current character register.
LoadCurrentCharacterUnchecked(-1, 1);
__ bind(&start_regexp);
Label load_char_start_regexp;
{
Label start_regexp;
// Load newline if index is at start, previous character otherwise.
__ cmpi(r4, Operand::Zero());
__ bne(&load_char_start_regexp);
__ li(current_character(), Operand('\n'));
__ b(&start_regexp);
// Global regexp restarts matching here.
__ bind(&load_char_start_regexp);
// Load previous char as initial value of current character register.
LoadCurrentCharacterUnchecked(-1, 1);
__ bind(&start_regexp);
}
// Initialize on-stack registers.
if (num_saved_registers_ > 0) { // Always is, if generated from a regexp.
......@@ -833,9 +843,6 @@ Handle<HeapObject> RegExpMacroAssemblerPPC::GetCode(Handle<String> source) {
}
}
// Initialize backtrack stack pointer.
LoadRegExpStackPointerFromMemory(backtrack_stackpointer());
__ b(&start_label_);
// Exit code:
......@@ -906,6 +913,10 @@ Handle<HeapObject> RegExpMacroAssemblerPPC::GetCode(Handle<String> source) {
// Prepare r3 to initialize registers with its value in the next run.
__ LoadU64(r3, MemOperand(frame_pointer(), kStringStartMinusOne));
// Restore the original regexp stack pointer value (effectively, pop the
// stored base pointer).
PopRegExpBasePointer(backtrack_stackpointer(), r5);
if (global_with_zero_length_check()) {
// Special case for zero-length matches.
// r25: capture start index
......@@ -938,7 +949,7 @@ Handle<HeapObject> RegExpMacroAssemblerPPC::GetCode(Handle<String> source) {
__ bind(&return_r3);
// Restore the original regexp stack pointer value (effectively, pop the
// stored base pointer).
PopRegExpBasePointer(r4, r5);
PopRegExpBasePointer(backtrack_stackpointer(), r5);
// Skip sp past regexp registers and local variables..
__ mr(sp, frame_pointer());
......
......@@ -179,8 +179,8 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerPPC
void LoadRegExpStackPointerFromMemory(Register dst);
void StoreRegExpStackPointerToMemory(Register src, Register scratch);
void PushRegExpBasePointer(Register scratch1, Register scratch2);
void PopRegExpBasePointer(Register scratch1, Register scratch2);
void PushRegExpBasePointer(Register stack_pointer, Register scratch);
void PopRegExpBasePointer(Register stack_pointer_out, Register scratch);
Isolate* isolate() const { return masm_->isolate(); }
......
......@@ -642,26 +642,26 @@ void RegExpMacroAssemblerS390::StoreRegExpStackPointerToMemory(
__ StoreU64(src, MemOperand(scratch));
}
void RegExpMacroAssemblerS390::PushRegExpBasePointer(Register scratch1,
Register scratch2) {
LoadRegExpStackPointerFromMemory(scratch1);
void RegExpMacroAssemblerS390::PushRegExpBasePointer(Register stack_pointer,
Register scratch) {
ExternalReference ref =
ExternalReference::address_of_regexp_stack_memory_top_address(isolate());
__ mov(scratch2, Operand(ref));
__ LoadU64(scratch2, MemOperand(scratch2));
__ SubS64(scratch2, scratch1, scratch2);
__ StoreU64(scratch2, MemOperand(frame_pointer(), kRegExpStackBasePointer));
__ mov(scratch, Operand(ref));
__ LoadU64(scratch, MemOperand(scratch));
__ SubS64(scratch, stack_pointer, scratch);
__ StoreU64(scratch, MemOperand(frame_pointer(), kRegExpStackBasePointer));
}
void RegExpMacroAssemblerS390::PopRegExpBasePointer(Register scratch1,
Register scratch2) {
void RegExpMacroAssemblerS390::PopRegExpBasePointer(Register stack_pointer_out,
Register scratch) {
ExternalReference ref =
ExternalReference::address_of_regexp_stack_memory_top_address(isolate());
__ LoadU64(scratch1, MemOperand(frame_pointer(), kRegExpStackBasePointer));
__ mov(scratch2, Operand(ref));
__ LoadU64(scratch2, MemOperand(scratch2));
__ AddS64(scratch1, scratch1, scratch2);
StoreRegExpStackPointerToMemory(scratch1, scratch2);
__ LoadU64(stack_pointer_out,
MemOperand(frame_pointer(), kRegExpStackBasePointer));
__ mov(scratch, Operand(ref));
__ LoadU64(scratch, MemOperand(scratch));
__ AddS64(stack_pointer_out, stack_pointer_out, scratch);
StoreRegExpStackPointerToMemory(stack_pointer_out, scratch);
}
Handle<HeapObject> RegExpMacroAssemblerS390::GetCode(Handle<String> source) {
......@@ -728,37 +728,43 @@ Handle<HeapObject> RegExpMacroAssemblerS390::GetCode(Handle<String> source) {
kBacktrackCount - kSystemPointerSize);
__ push(r1); // The regexp stack base ptr.
// Initialize backtrack stack pointer. It must not be clobbered from here on.
// Note the backtrack_stackpointer is callee-saved.
STATIC_ASSERT(backtrack_stackpointer() == r13);
LoadRegExpStackPointerFromMemory(backtrack_stackpointer());
// Store the regexp base pointer - we'll later restore it / write it to
// memory when returning from this irregexp code object.
PushRegExpBasePointer(r2, r3);
// Check if we have space on the stack for registers.
Label stack_limit_hit;
Label stack_ok;
PushRegExpBasePointer(backtrack_stackpointer(), r3);
{
// Check if we have space on the stack for registers.
Label stack_limit_hit, stack_ok;
ExternalReference stack_limit =
ExternalReference::address_of_jslimit(isolate());
__ mov(r2, Operand(stack_limit));
__ LoadU64(r2, MemOperand(r2));
__ SubS64(r2, sp, r2);
// Handle it if the stack pointer is already below the stack limit.
__ ble(&stack_limit_hit);
// Check if there is room for the variable number of registers above
// the stack limit.
__ CmpU64(r2, Operand(num_registers_ * kSystemPointerSize));
__ bge(&stack_ok);
// Exit with OutOfMemory exception. There is not enough space on the stack
// for our working registers.
__ mov(r2, Operand(EXCEPTION));
__ b(&return_r2);
ExternalReference stack_limit =
ExternalReference::address_of_jslimit(isolate());
__ mov(r2, Operand(stack_limit));
__ LoadU64(r2, MemOperand(r2));
__ SubS64(r2, sp, r2);
// Handle it if the stack pointer is already below the stack limit.
__ ble(&stack_limit_hit);
// Check if there is room for the variable number of registers above
// the stack limit.
__ CmpU64(r2, Operand(num_registers_ * kSystemPointerSize));
__ bge(&stack_ok);
// Exit with OutOfMemory exception. There is not enough space on the stack
// for our working registers.
__ mov(r2, Operand(EXCEPTION));
__ b(&return_r2);
__ bind(&stack_limit_hit);
CallCheckStackGuardState(r2);
__ CmpS64(r2, Operand::Zero());
// If returned value is non-zero, we exit with the returned value as result.
__ bne(&return_r2);
__ bind(&stack_limit_hit);
CallCheckStackGuardState(r2);
__ CmpS64(r2, Operand::Zero());
// If returned value is non-zero, we exit with the returned value as result.
__ bne(&return_r2);
__ bind(&stack_ok);
__ bind(&stack_ok);
}
// Allocate space on stack for registers.
__ lay(sp, MemOperand(sp, (-num_registers_ * kSystemPointerSize)));
......@@ -786,18 +792,21 @@ Handle<HeapObject> RegExpMacroAssemblerS390::GetCode(Handle<String> source) {
// Initialize code pointer register
__ mov(code_pointer(), Operand(masm_->CodeObject()));
Label load_char_start_regexp, start_regexp;
// Load newline if index is at start, previous character otherwise.
__ CmpS64(r3, Operand::Zero());
__ bne(&load_char_start_regexp);
__ mov(current_character(), Operand('\n'));
__ b(&start_regexp);
// Global regexp restarts matching here.
__ bind(&load_char_start_regexp);
// Load previous char as initial value of current character register.
LoadCurrentCharacterUnchecked(-1, 1);
__ bind(&start_regexp);
Label load_char_start_regexp;
{
Label start_regexp;
// Load newline if index is at start, previous character otherwise.
__ CmpS64(r3, Operand::Zero());
__ bne(&load_char_start_regexp);
__ mov(current_character(), Operand('\n'));
__ b(&start_regexp);
// Global regexp restarts matching here.
__ bind(&load_char_start_regexp);
// Load previous char as initial value of current character register.
LoadCurrentCharacterUnchecked(-1, 1);
__ bind(&start_regexp);
}
// Initialize on-stack registers.
if (num_saved_registers_ > 0) { // Always is, if generated from a regexp.
......@@ -819,9 +828,6 @@ Handle<HeapObject> RegExpMacroAssemblerS390::GetCode(Handle<String> source) {
}
}
// Initialize backtrack stack pointer.
LoadRegExpStackPointerFromMemory(backtrack_stackpointer());
__ b(&start_label_);
// Exit code:
......@@ -914,6 +920,10 @@ Handle<HeapObject> RegExpMacroAssemblerS390::GetCode(Handle<String> source) {
// Prepare r2 to initialize registers with its value in the next run.
__ LoadU64(r2, MemOperand(frame_pointer(), kStringStartMinusOne));
// Restore the original regexp stack pointer value (effectively, pop the
// stored base pointer).
PopRegExpBasePointer(backtrack_stackpointer(), r4);
if (global_with_zero_length_check()) {
// Special case for zero-length matches.
// r6: capture start index
......@@ -945,7 +955,7 @@ Handle<HeapObject> RegExpMacroAssemblerS390::GetCode(Handle<String> source) {
__ bind(&return_r2);
// Restore the original regexp stack pointer value (effectively, pop the
// stored base pointer).
PopRegExpBasePointer(r3, r4);
PopRegExpBasePointer(backtrack_stackpointer(), r4);
// Skip sp past regexp registers and local variables..
__ mov(sp, frame_pointer());
......
......@@ -177,8 +177,8 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerS390
void LoadRegExpStackPointerFromMemory(Register dst);
void StoreRegExpStackPointerToMemory(Register src, Register scratch);
void PushRegExpBasePointer(Register scratch1, Register scratch2);
void PopRegExpBasePointer(Register scratch1, Register scratch2);
void PushRegExpBasePointer(Register stack_pointer, Register scratch);
void PopRegExpBasePointer(Register stack_pointer_out, Register scratch);
Isolate* isolate() const { return masm_->isolate(); }
......
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