Commit 3e3a027d authored by Jakob Gruber's avatar Jakob Gruber Committed by V8 LUCI CQ

[regexp] Fix stack growth for global regexps

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.

Bug: v8:11382
Change-Id: Ibad6235767e110089a2b346034f923590b286a05
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3194251Reviewed-by: 's avatarPatrick Thier <pthier@chromium.org>
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/main@{#77158}
parent d6c01059
......@@ -628,26 +628,26 @@ void RegExpMacroAssemblerARM::StoreRegExpStackPointerToMemory(
__ str(src, MemOperand(scratch));
}
void RegExpMacroAssemblerARM::PushRegExpBasePointer(Register scratch1,
Register scratch2) {
LoadRegExpStackPointerFromMemory(scratch1);
void RegExpMacroAssemblerARM::PushRegExpBasePointer(Register stack_pointer,
Register scratch) {
ExternalReference ref =
ExternalReference::address_of_regexp_stack_memory_top_address(isolate());
__ mov(scratch2, Operand(ref));
__ ldr(scratch2, MemOperand(scratch2));
__ sub(scratch2, scratch1, scratch2);
__ str(scratch2, MemOperand(frame_pointer(), kRegExpStackBasePointer));
__ mov(scratch, Operand(ref));
__ ldr(scratch, MemOperand(scratch));
__ sub(scratch, stack_pointer, scratch);
__ str(scratch, MemOperand(frame_pointer(), kRegExpStackBasePointer));
}
void RegExpMacroAssemblerARM::PopRegExpBasePointer(Register scratch1,
Register scratch2) {
void RegExpMacroAssemblerARM::PopRegExpBasePointer(Register stack_pointer_out,
Register scratch) {
ExternalReference ref =
ExternalReference::address_of_regexp_stack_memory_top_address(isolate());
__ ldr(scratch1, MemOperand(frame_pointer(), kRegExpStackBasePointer));
__ mov(scratch2, Operand(ref));
__ ldr(scratch2, MemOperand(scratch2));
__ add(scratch1, scratch1, scratch2);
StoreRegExpStackPointerToMemory(scratch1, scratch2);
__ ldr(stack_pointer_out,
MemOperand(frame_pointer(), kRegExpStackBasePointer));
__ mov(scratch, Operand(ref));
__ ldr(scratch, MemOperand(scratch));
__ add(stack_pointer_out, stack_pointer_out, scratch);
StoreRegExpStackPointerToMemory(stack_pointer_out, scratch);
}
Handle<HeapObject> RegExpMacroAssemblerARM::GetCode(Handle<String> source) {
......@@ -688,37 +688,43 @@ Handle<HeapObject> RegExpMacroAssemblerARM::GetCode(Handle<String> source) {
kBacktrackCount - kSystemPointerSize);
__ push(r0); // 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() == r8);
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(r0, r1);
// Check if we have space on the stack for registers.
Label stack_limit_hit;
Label stack_ok;
PushRegExpBasePointer(backtrack_stackpointer(), r1);
{
// 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(r0, Operand(stack_limit));
__ ldr(r0, MemOperand(r0));
__ sub(r0, sp, r0, SetCC);
// Handle it if the stack pointer is already below the stack limit.
__ b(ls, &stack_limit_hit);
// Check if there is room for the variable number of registers above
// the stack limit.
__ cmp(r0, Operand(num_registers_ * kPointerSize));
__ b(hs, &stack_ok);
// Exit with OutOfMemory exception. There is not enough space on the stack
// for our working registers.
__ mov(r0, Operand(EXCEPTION));
__ jmp(&return_r0);
ExternalReference stack_limit =
ExternalReference::address_of_jslimit(isolate());
__ mov(r0, Operand(stack_limit));
__ ldr(r0, MemOperand(r0));
__ sub(r0, sp, r0, SetCC);
// Handle it if the stack pointer is already below the stack limit.
__ b(ls, &stack_limit_hit);
// Check if there is room for the variable number of registers above
// the stack limit.
__ cmp(r0, Operand(num_registers_ * kPointerSize));
__ b(hs, &stack_ok);
// Exit with OutOfMemory exception. There is not enough space on the stack
// for our working registers.
__ mov(r0, Operand(EXCEPTION));
__ jmp(&return_r0);
__ bind(&stack_limit_hit);
CallCheckStackGuardState();
__ cmp(r0, Operand::Zero());
// If returned value is non-zero, we exit with the returned value as result.
__ b(ne, &return_r0);
__ bind(&stack_limit_hit);
CallCheckStackGuardState();
__ cmp(r0, Operand::Zero());
// If returned value is non-zero, we exit with the returned value as result.
__ b(ne, &return_r0);
__ bind(&stack_ok);
__ bind(&stack_ok);
}
// Allocate space on stack for registers.
__ AllocateStackSpace(num_registers_ * kPointerSize);
......@@ -740,18 +746,21 @@ Handle<HeapObject> RegExpMacroAssemblerARM::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.
__ cmp(r1, Operand::Zero());
__ b(ne, &load_char_start_regexp);
__ mov(current_character(), Operand('\n'), LeaveCC, eq);
__ jmp(&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.
__ cmp(r1, Operand::Zero());
__ b(ne, &load_char_start_regexp);
__ mov(current_character(), Operand('\n'), LeaveCC, eq);
__ jmp(&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.
......@@ -772,9 +781,6 @@ Handle<HeapObject> RegExpMacroAssemblerARM::GetCode(Handle<String> source) {
}
}
// Initialize backtrack stack pointer.
LoadRegExpStackPointerFromMemory(backtrack_stackpointer());
__ jmp(&start_label_);
// Exit code:
......@@ -841,6 +847,10 @@ Handle<HeapObject> RegExpMacroAssemblerARM::GetCode(Handle<String> source) {
// Prepare r0 to initialize registers with its value in the next run.
__ ldr(r0, MemOperand(frame_pointer(), kStringStartMinusOne));
// Restore the original regexp stack pointer value (effectively, pop the
// stored base pointer).
PopRegExpBasePointer(backtrack_stackpointer(), r2);
if (global_with_zero_length_check()) {
// Special case for zero-length matches.
// r4: capture start index
......@@ -873,7 +883,7 @@ Handle<HeapObject> RegExpMacroAssemblerARM::GetCode(Handle<String> source) {
__ bind(&return_r0);
// Restore the original regexp stack pointer value (effectively, pop the
// stored base pointer).
PopRegExpBasePointer(r1, r2);
PopRegExpBasePointer(backtrack_stackpointer(), r2);
// Skip sp past regexp registers and local variables..
__ mov(sp, frame_pointer());
......
......@@ -181,8 +181,8 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerARM
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(); }
......
......@@ -710,26 +710,26 @@ void RegExpMacroAssemblerARM64::StoreRegExpStackPointerToMemory(
__ Str(src, MemOperand(scratch));
}
void RegExpMacroAssemblerARM64::PushRegExpBasePointer(Register scratch1,
Register scratch2) {
LoadRegExpStackPointerFromMemory(scratch1);
void RegExpMacroAssemblerARM64::PushRegExpBasePointer(Register stack_pointer,
Register scratch) {
ExternalReference ref =
ExternalReference::address_of_regexp_stack_memory_top_address(isolate());
__ Mov(scratch2, ref);
__ Ldr(scratch2, MemOperand(scratch2));
__ Sub(scratch2, scratch1, scratch2);
__ Str(scratch2, MemOperand(frame_pointer(), kRegExpStackBasePointer));
__ Mov(scratch, ref);
__ Ldr(scratch, MemOperand(scratch));
__ Sub(scratch, stack_pointer, scratch);
__ Str(scratch, MemOperand(frame_pointer(), kRegExpStackBasePointer));
}
void RegExpMacroAssemblerARM64::PopRegExpBasePointer(Register scratch1,
Register scratch2) {
void RegExpMacroAssemblerARM64::PopRegExpBasePointer(Register stack_pointer_out,
Register scratch) {
ExternalReference ref =
ExternalReference::address_of_regexp_stack_memory_top_address(isolate());
__ Ldr(scratch1, MemOperand(frame_pointer(), kRegExpStackBasePointer));
__ Mov(scratch2, ref);
__ Ldr(scratch2, MemOperand(scratch2));
__ Add(scratch1, scratch1, scratch2);
StoreRegExpStackPointerToMemory(scratch1, scratch2);
__ Ldr(stack_pointer_out,
MemOperand(frame_pointer(), kRegExpStackBasePointer));
__ Mov(scratch, ref);
__ Ldr(scratch, MemOperand(scratch));
__ Add(stack_pointer_out, stack_pointer_out, scratch);
StoreRegExpStackPointerToMemory(stack_pointer_out, scratch);
}
Handle<HeapObject> RegExpMacroAssemblerARM64::GetCode(Handle<String> source) {
......@@ -786,9 +786,14 @@ Handle<HeapObject> RegExpMacroAssemblerARM64::GetCode(Handle<String> source) {
((kNumberOfStackLocals * kWRegPerXReg) + align_mask) & ~align_mask);
__ Claim(kNumberOfStackLocals * kWRegPerXReg);
// Initialize backtrack stack pointer. It must not be clobbered from here on.
// Note the backtrack_stackpointer is callee-saved.
STATIC_ASSERT(backtrack_stackpointer() == x23);
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(x10, x11);
PushRegExpBasePointer(backtrack_stackpointer(), x11);
// Set the number of registers we will need to allocate, that is:
// - (num_registers_ - kNumCachedRegisters) (W registers)
......@@ -797,35 +802,36 @@ Handle<HeapObject> RegExpMacroAssemblerARM64::GetCode(Handle<String> source) {
const int num_wreg_to_allocate =
(num_stack_registers + align_mask) & ~align_mask;
// Check if we have space on the stack.
Label stack_limit_hit;
Label stack_ok;
{
// Check if we have space on the stack.
Label stack_limit_hit, stack_ok;
ExternalReference stack_limit =
ExternalReference::address_of_jslimit(isolate());
__ Mov(x10, stack_limit);
__ Ldr(x10, MemOperand(x10));
__ Subs(x10, sp, x10);
ExternalReference stack_limit =
ExternalReference::address_of_jslimit(isolate());
__ Mov(x10, stack_limit);
__ Ldr(x10, MemOperand(x10));
__ Subs(x10, sp, x10);
// Handle it if the stack pointer is already below the stack limit.
__ B(ls, &stack_limit_hit);
// Handle it if the stack pointer is already below the stack limit.
__ B(ls, &stack_limit_hit);
// Check if there is room for the variable number of registers above
// the stack limit.
__ Cmp(x10, num_wreg_to_allocate * kWRegSize);
__ B(hs, &stack_ok);
// Check if there is room for the variable number of registers above
// the stack limit.
__ Cmp(x10, num_wreg_to_allocate * kWRegSize);
__ B(hs, &stack_ok);
// Exit with OutOfMemory exception. There is not enough space on the stack
// for our working registers.
__ Mov(w0, EXCEPTION);
__ B(&return_w0);
// Exit with OutOfMemory exception. There is not enough space on the stack
// for our working registers.
__ Mov(w0, EXCEPTION);
__ B(&return_w0);
__ Bind(&stack_limit_hit);
CallCheckStackGuardState(x10);
// If returned value is non-zero, we exit with the returned value as result.
__ Cbnz(w0, &return_w0);
__ Bind(&stack_limit_hit);
CallCheckStackGuardState(x10);
// If returned value is non-zero, we exit with the returned value as result.
__ Cbnz(w0, &return_w0);
__ Bind(&stack_ok);
__ Bind(&stack_ok);
}
// Allocate space on stack.
__ Claim(num_wreg_to_allocate, kWRegSize);
......@@ -858,25 +864,26 @@ Handle<HeapObject> RegExpMacroAssemblerARM64::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.
__ Cbnz(start_offset(), &load_char_start_regexp);
__ Mov(current_character(), '\n');
__ B(&start_regexp);
Label load_char_start_regexp;
{
Label start_regexp;
// Load newline if index is at start, previous character otherwise.
__ Cbnz(start_offset(), &load_char_start_regexp);
__ Mov(current_character(), '\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);
}
// 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) {
ClearRegisters(0, num_saved_registers_ - 1);
}
// Initialize backtrack stack pointer.
LoadRegExpStackPointerFromMemory(backtrack_stackpointer());
// Execute.
__ B(&start_label_);
......@@ -1027,6 +1034,10 @@ Handle<HeapObject> RegExpMacroAssemblerARM64::GetCode(Handle<String> source) {
// Update output size on the frame before we restart matching.
__ Str(output_size, MemOperand(frame_pointer(), kOutputSize));
// Restore the original regexp stack pointer value (effectively, pop the
// stored base pointer).
PopRegExpBasePointer(backtrack_stackpointer(), x11);
if (global_with_zero_length_check()) {
// Special case for zero-length matches.
__ Cmp(current_input_offset(), first_capture_start);
......@@ -1059,7 +1070,7 @@ Handle<HeapObject> RegExpMacroAssemblerARM64::GetCode(Handle<String> source) {
__ Bind(&return_w0);
// Restore the original regexp stack pointer value (effectively, pop the
// stored base pointer).
PopRegExpBasePointer(x10, x11);
PopRegExpBasePointer(backtrack_stackpointer(), x11);
// Set stack pointer back to first register to retain.
__ Mov(sp, fp);
......
......@@ -262,8 +262,8 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerARM64
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(); }
......
......@@ -663,24 +663,24 @@ void RegExpMacroAssemblerIA32::StoreRegExpStackPointerToMemory(
__ mov(__ ExternalReferenceAsOperand(ref, scratch), src);
}
void RegExpMacroAssemblerIA32::PushRegExpBasePointer(Register scratch1,
Register scratch2) {
LoadRegExpStackPointerFromMemory(scratch1);
void RegExpMacroAssemblerIA32::PushRegExpBasePointer(Register stack_pointer,
Register scratch) {
ExternalReference ref =
ExternalReference::address_of_regexp_stack_memory_top_address(isolate());
__ mov(scratch2, __ ExternalReferenceAsOperand(ref, scratch2));
__ sub(scratch1, scratch2);
__ mov(Operand(ebp, kRegExpStackBasePointer), scratch1);
__ mov(scratch, __ ExternalReferenceAsOperand(ref, scratch));
__ sub(scratch, stack_pointer);
__ mov(Operand(ebp, kRegExpStackBasePointer), scratch);
}
void RegExpMacroAssemblerIA32::PopRegExpBasePointer(Register scratch1,
Register scratch2) {
void RegExpMacroAssemblerIA32::PopRegExpBasePointer(Register stack_pointer_out,
Register scratch) {
ExternalReference ref =
ExternalReference::address_of_regexp_stack_memory_top_address(isolate());
__ mov(scratch1, Operand(ebp, kRegExpStackBasePointer));
__ mov(scratch2, __ ExternalReferenceAsOperand(ref, scratch2));
__ add(scratch1, scratch2);
StoreRegExpStackPointerToMemory(scratch1, scratch2);
__ mov(scratch, Operand(ebp, kRegExpStackBasePointer));
__ mov(stack_pointer_out,
__ ExternalReferenceAsOperand(ref, stack_pointer_out));
__ sub(stack_pointer_out, scratch);
StoreRegExpStackPointerToMemory(stack_pointer_out, scratch);
}
Handle<HeapObject> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) {
......@@ -717,36 +717,45 @@ Handle<HeapObject> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) {
kBacktrackCount - kSystemPointerSize);
__ push(Immediate(0)); // The regexp stack base ptr.
// Initialize backtrack stack pointer. It must not be clobbered from here on.
// Note the backtrack_stackpointer is *not* callee-saved.
STATIC_ASSERT(backtrack_stackpointer() == ecx);
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(ecx, eax);
PushRegExpBasePointer(backtrack_stackpointer(), eax);
{
// 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(eax, esp);
__ sub(eax, StaticVariable(stack_limit));
// Handle it if the stack pointer is already below the stack limit.
__ j(below_equal, &stack_limit_hit);
// Check if there is room for the variable number of registers above
// the stack limit.
__ cmp(eax, num_registers_ * kSystemPointerSize);
__ j(above_equal, &stack_ok);
// Exit with OutOfMemory exception. There is not enough space on the stack
// for our working registers.
__ mov(eax, EXCEPTION);
__ jmp(&return_eax);
// Check if we have space on the stack for registers.
Label stack_limit_hit;
Label stack_ok;
__ bind(&stack_limit_hit);
__ push(backtrack_stackpointer());
CallCheckStackGuardState(ebx);
__ pop(backtrack_stackpointer());
__ or_(eax, eax);
// If returned value is non-zero, we exit with the returned value as result.
__ j(not_zero, &return_eax);
__ bind(&stack_ok);
}
ExternalReference stack_limit =
ExternalReference::address_of_jslimit(isolate());
__ mov(ecx, esp);
__ sub(ecx, StaticVariable(stack_limit));
// Handle it if the stack pointer is already below the stack limit.
__ j(below_equal, &stack_limit_hit);
// Check if there is room for the variable number of registers above
// the stack limit.
__ cmp(ecx, num_registers_ * kSystemPointerSize);
__ j(above_equal, &stack_ok);
// Exit with OutOfMemory exception. There is not enough space on the stack
// for our working registers.
__ mov(eax, EXCEPTION);
__ jmp(&return_eax);
__ bind(&stack_limit_hit);
CallCheckStackGuardState(ebx);
__ or_(eax, eax);
// If returned value is non-zero, we exit with the returned value as result.
__ j(not_zero, &return_eax);
__ bind(&stack_ok);
// Load start index for later use.
__ mov(ebx, Operand(ebp, kStartIndex));
......@@ -771,18 +780,22 @@ Handle<HeapObject> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) {
// position registers.
__ mov(Operand(ebp, kStringStartMinusOne), eax);
Label load_char_start_regexp, start_regexp;
// Load newline if index is at start, previous character otherwise.
__ cmp(Operand(ebp, kStartIndex), Immediate(0));
__ j(not_equal, &load_char_start_regexp, Label::kNear);
__ mov(current_character(), '\n');
__ jmp(&start_regexp, Label::kNear);
// 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.
__ cmp(Operand(ebp, kStartIndex), Immediate(0));
__ j(not_equal, &load_char_start_regexp, Label::kNear);
__ mov(current_character(), '\n');
__ jmp(&start_regexp, Label::kNear);
// 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.
......@@ -790,6 +803,8 @@ Handle<HeapObject> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) {
// Fill in stack push order, to avoid accessing across an unwritten
// page (a problem on Windows).
if (num_saved_registers_ > 8) {
DCHECK_EQ(ecx, backtrack_stackpointer());
__ push(ecx);
__ mov(ecx, kRegisterZero);
Label init_loop;
__ bind(&init_loop);
......@@ -797,6 +812,7 @@ Handle<HeapObject> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) {
__ sub(ecx, Immediate(kSystemPointerSize));
__ cmp(ecx, kRegisterZero - num_saved_registers_ * kSystemPointerSize);
__ j(greater, &init_loop);
__ pop(ecx);
} else { // Unroll the loop.
for (int i = 0; i < num_saved_registers_; i++) {
__ mov(register_location(i), eax);
......@@ -804,9 +820,6 @@ Handle<HeapObject> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) {
}
}
// Initialize backtrack stack pointer.
LoadRegExpStackPointerFromMemory(backtrack_stackpointer());
__ jmp(&start_label_);
// Exit code:
......@@ -859,6 +872,10 @@ Handle<HeapObject> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) {
// Prepare eax to initialize registers with its value in the next run.
__ mov(eax, Operand(ebp, kStringStartMinusOne));
// Restore the original regexp stack pointer value (effectively, pop the
// stored base pointer).
PopRegExpBasePointer(backtrack_stackpointer(), ebx);
if (global_with_zero_length_check()) {
// Special case for zero-length matches.
// edx: capture start index
......@@ -893,7 +910,7 @@ Handle<HeapObject> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) {
__ bind(&return_eax);
// Restore the original regexp stack pointer value (effectively, pop the
// stored base pointer).
PopRegExpBasePointer(ecx, ebx);
PopRegExpBasePointer(backtrack_stackpointer(), ebx);
// Skip esp past regexp registers.
__ lea(esp, Operand(ebp, kLastCalleeSaveRegister));
......
......@@ -177,8 +177,8 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerIA32
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(); }
......
......@@ -674,24 +674,24 @@ void RegExpMacroAssemblerX64::StoreRegExpStackPointerToMemory(
__ movq(__ ExternalReferenceAsOperand(ref, scratch), src);
}
void RegExpMacroAssemblerX64::PushRegExpBasePointer(Register scratch1,
Register scratch2) {
LoadRegExpStackPointerFromMemory(scratch1);
void RegExpMacroAssemblerX64::PushRegExpBasePointer(Register stack_pointer,
Register scratch) {
ExternalReference ref =
ExternalReference::address_of_regexp_stack_memory_top_address(isolate());
__ movq(scratch2, __ ExternalReferenceAsOperand(ref, scratch2));
__ subq(scratch1, scratch2);
__ movq(Operand(rbp, kRegExpStackBasePointer), scratch1);
__ movq(scratch, __ ExternalReferenceAsOperand(ref, scratch));
__ subq(scratch, stack_pointer);
__ movq(Operand(rbp, kRegExpStackBasePointer), scratch);
}
void RegExpMacroAssemblerX64::PopRegExpBasePointer(Register scratch1,
Register scratch2) {
void RegExpMacroAssemblerX64::PopRegExpBasePointer(Register stack_pointer_out,
Register scratch) {
ExternalReference ref =
ExternalReference::address_of_regexp_stack_memory_top_address(isolate());
__ movq(scratch1, Operand(rbp, kRegExpStackBasePointer));
__ movq(scratch2, __ ExternalReferenceAsOperand(ref, scratch2));
__ addq(scratch1, scratch2);
StoreRegExpStackPointerToMemory(scratch1, scratch2);
__ movq(scratch, Operand(rbp, kRegExpStackBasePointer));
__ movq(stack_pointer_out,
__ ExternalReferenceAsOperand(ref, stack_pointer_out));
__ subq(stack_pointer_out, scratch);
StoreRegExpStackPointerToMemory(stack_pointer_out, scratch);
}
Handle<HeapObject> RegExpMacroAssemblerX64::GetCode(Handle<String> source) {
......@@ -754,38 +754,46 @@ Handle<HeapObject> RegExpMacroAssemblerX64::GetCode(Handle<String> source) {
kBacktrackCount - kSystemPointerSize);
__ Push(Immediate(0)); // The regexp stack base ptr.
// Initialize backtrack stack pointer. It must not be clobbered from here on.
// Note the backtrack_stackpointer is *not* callee-saved.
STATIC_ASSERT(backtrack_stackpointer() == rcx);
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(rcx, kScratchRegister);
// Check if we have space on the stack for registers.
Label stack_limit_hit;
Label stack_ok;
PushRegExpBasePointer(backtrack_stackpointer(), kScratchRegister);
{
// Check if we have space on the stack for registers.
Label stack_limit_hit, stack_ok;
ExternalReference stack_limit =
ExternalReference::address_of_jslimit(isolate());
__ movq(r9, rsp);
__ Move(kScratchRegister, stack_limit);
__ subq(r9, Operand(kScratchRegister, 0));
// Handle it if the stack pointer is already below the stack limit.
__ j(below_equal, &stack_limit_hit);
// Check if there is room for the variable number of registers above
// the stack limit.
__ cmpq(r9, Immediate(num_registers_ * kSystemPointerSize));
__ j(above_equal, &stack_ok);
// Exit with OutOfMemory exception. There is not enough space on the stack
// for our working registers.
__ Move(rax, EXCEPTION);
__ jmp(&return_rax);
ExternalReference stack_limit =
ExternalReference::address_of_jslimit(isolate());
__ movq(rcx, rsp);
__ Move(kScratchRegister, stack_limit);
__ subq(rcx, Operand(kScratchRegister, 0));
// Handle it if the stack pointer is already below the stack limit.
__ j(below_equal, &stack_limit_hit);
// Check if there is room for the variable number of registers above
// the stack limit.
__ cmpq(rcx, Immediate(num_registers_ * kSystemPointerSize));
__ j(above_equal, &stack_ok);
// Exit with OutOfMemory exception. There is not enough space on the stack
// for our working registers.
__ Move(rax, EXCEPTION);
__ jmp(&return_rax);
__ bind(&stack_limit_hit);
__ Move(code_object_pointer(), masm_.CodeObject());
CallCheckStackGuardState(); // Preserves no registers beside rbp and rsp.
__ testq(rax, rax);
// If returned value is non-zero, we exit with the returned value as result.
__ j(not_zero, &return_rax);
__ bind(&stack_limit_hit);
__ Move(code_object_pointer(), masm_.CodeObject());
__ pushq(backtrack_stackpointer());
CallCheckStackGuardState(); // Preserves no registers beside rbp and rsp.
__ popq(backtrack_stackpointer());
__ testq(rax, rax);
// If returned value is non-zero, we exit with the returned value as result.
__ j(not_zero, &return_rax);
__ bind(&stack_ok);
__ bind(&stack_ok);
}
// Allocate space on stack for registers.
__ AllocateStackSpace(num_registers_ * kSystemPointerSize);
......@@ -811,18 +819,23 @@ Handle<HeapObject> RegExpMacroAssemblerX64::GetCode(Handle<String> source) {
// Initialize code object pointer.
__ Move(code_object_pointer(), masm_.CodeObject());
Label load_char_start_regexp, start_regexp;
// Load newline if index is at start, previous character otherwise.
__ cmpl(Operand(rbp, kStartIndex), Immediate(0));
__ j(not_equal, &load_char_start_regexp, Label::kNear);
__ Move(current_character(), '\n');
__ jmp(&start_regexp, Label::kNear);
Label load_char_start_regexp; // Execution restarts here for global regexps.
{
Label 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);
// Load newline if index is at start, previous character otherwise.
__ cmpl(Operand(rbp, kStartIndex), Immediate(0));
__ j(not_equal, &load_char_start_regexp, Label::kNear);
__ Move(current_character(), '\n');
__ jmp(&start_regexp, Label::kNear);
// 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) {
......@@ -830,13 +843,13 @@ Handle<HeapObject> RegExpMacroAssemblerX64::GetCode(Handle<String> source) {
// Fill in stack push order, to avoid accessing across an unwritten
// page (a problem on Windows).
if (num_saved_registers_ > 8) {
__ Move(rcx, kRegisterZero);
__ Move(r9, kRegisterZero);
Label init_loop;
__ bind(&init_loop);
__ movq(Operand(rbp, rcx, times_1, 0), rax);
__ subq(rcx, Immediate(kSystemPointerSize));
__ cmpq(rcx, Immediate(kRegisterZero -
num_saved_registers_ * kSystemPointerSize));
__ movq(Operand(rbp, r9, times_1, 0), rax);
__ subq(r9, Immediate(kSystemPointerSize));
__ cmpq(r9, Immediate(kRegisterZero -
num_saved_registers_ * kSystemPointerSize));
__ j(greater, &init_loop);
} else { // Unroll the loop.
for (int i = 0; i < num_saved_registers_; i++) {
......@@ -845,9 +858,6 @@ Handle<HeapObject> RegExpMacroAssemblerX64::GetCode(Handle<String> source) {
}
}
// Initialize backtrack stack pointer.
LoadRegExpStackPointerFromMemory(backtrack_stackpointer());
__ jmp(&start_label_);
// Exit code:
......@@ -899,6 +909,10 @@ Handle<HeapObject> RegExpMacroAssemblerX64::GetCode(Handle<String> source) {
// Prepare rax to initialize registers with its value in the next run.
__ movq(rax, Operand(rbp, kStringStartMinusOne));
// Restore the original regexp stack pointer value (effectively, pop the
// stored base pointer).
PopRegExpBasePointer(backtrack_stackpointer(), kScratchRegister);
if (global_with_zero_length_check()) {
// Special case for zero-length matches.
// rdx: capture start index
......@@ -934,7 +948,7 @@ Handle<HeapObject> RegExpMacroAssemblerX64::GetCode(Handle<String> source) {
__ bind(&return_rax);
// Restore the original regexp stack pointer value (effectively, pop the
// stored base pointer).
PopRegExpBasePointer(rcx, kScratchRegister);
PopRegExpBasePointer(backtrack_stackpointer(), kScratchRegister);
#ifdef V8_TARGET_OS_WIN
// Restore callee save registers.
......
......@@ -226,8 +226,8 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerX64
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 scratch_pointer, Register scratch);
void PopRegExpBasePointer(Register scratch_pointer_out, Register scratch);
inline void ReadPositionFromRegister(Register dst, int reg);
......
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