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