* to *string_base)
* - void** string_base (location of a handle containing the string)
* - return address
+ * ebp-> - old ebp
* - backup of caller esi
* - backup of caller edi
* - backup of caller ebx
- * ebp-> - old ebp
* - register 0 ebp[-4] (Only positions must be stored in the first
* - register 1 ebp[-8] num_saved_registers_ registers)
* - ...
// Entry code:
__ bind(&entry_label_);
+ // Start new stack frame.
+ __ push(ebp);
+ __ mov(ebp, esp);
// Save callee-save registers. Order here should correspond to order of
// kBackup_ebx etc.
__ push(esi);
__ j(above_equal, &stack_ok, taken);
// Exit with exception.
__ mov(eax, EXCEPTION);
- Label exit_without_leave;
- __ jmp(&exit_without_leave);
+ __ jmp(&exit_label_);
__ bind(&stack_limit_hit);
int num_arguments = 2;
__ j(equal, &retry_stack_check);
// Return value was non-zero. Exit with exception.
__ mov(eax, EXCEPTION);
- __ jmp(&exit_without_leave);
+ __ jmp(&exit_label_);
__ bind(&stack_ok);
// Allocate space on stack for registers.
- __ enter(Immediate(num_registers_ * kPointerSize));
+ __ sub(Operand(esp), Immediate(num_registers_ * kPointerSize));
// Load string length.
__ mov(esi, Operand(ebp, kInputEndOffset));
// Load input position.
// Fill saved registers with initial value = start offset - 1
// Fill in stack push order, to avoid accessing across an unwritten
// page (a problem on Windows).
- const int kRegisterZeroEBPOffset = -1;
- __ mov(ecx, kRegisterZeroEBPOffset);
- // Set eax to address of char before start of input.
+ __ mov(ecx, kRegisterZero);
+ // Set eax to address of char before start of input
+ // (effectively string position -1).
__ lea(eax, Operand(edi, -char_size()));
Label init_loop;
__ bind(&init_loop);
- __ mov(Operand(ebp, ecx, times_4, +0), eax);
- __ sub(Operand(ecx), Immediate(1));
- __ cmp(ecx, -num_saved_registers_);
- __ j(greater_equal, &init_loop);
+ __ mov(Operand(ebp, ecx, times_1, +0), eax);
+ __ sub(Operand(ecx), Immediate(kPointerSize));
+ __ cmp(ecx, kRegisterZero - num_saved_registers_ * kPointerSize);
+ __ j(greater, &init_loop);
}
- // Ensure that we have written to each stack page. Skipping a page on
- // Windows can cause segmentation faults. Assuming page size is 4k.
+ // Ensure that we have written to each stack page, in order. Skipping a page
+ // on Windows can cause segmentation faults. Assuming page size is 4k.
const int kPageSize = 4096;
const int kRegistersPerPage = kPageSize / kPointerSize;
for (int i = num_saved_registers_ + kRegistersPerPage - 1;
// Exit code:
if (success_label_.is_linked()) {
- // Success
+ // Save captures when successful.
__ bind(&success_label_);
if (num_saved_registers_ > 0) {
// copy captures to output
}
// Exit and return eax
__ bind(&exit_label_);
- __ leave();
- __ bind(&exit_without_leave); // For exiting before doing enter.
+ // Skip esp past regexp registers.
+ __ lea(esp, Operand(ebp, kBackup_ebx));
+ // Restore callee-save registers.
__ pop(ebx);
__ pop(edi);
__ pop(esi);
+ // Exit function frame, restore previus one.
+ __ pop(ebp);
__ ret(0);
// Backtrack code (branch target for conditional backtracks).
if (num_registers_ <= register_index) {
num_registers_ = register_index + 1;
}
- return Operand(ebp, -(register_index + 1) * kPointerSize);
+ return Operand(ebp, kRegisterZero - register_index * kPointerSize);
}
bool at_start);
private:
- // Offsets from ebp of arguments to function and stored registers.
- static const int kBackup_ebx = sizeof(uint32_t);
- static const int kBackup_edi = kBackup_ebx + sizeof(uint32_t);
- static const int kBackup_esi = kBackup_edi + sizeof(uint32_t);
- static const int kReturn_eip = kBackup_esi + sizeof(uint32_t);
- static const int kInputBuffer = kReturn_eip + sizeof(uint32_t);
- static const int kInputStartOffset = kInputBuffer + sizeof(uint32_t);
- static const int kInputEndOffset = kInputStartOffset + sizeof(uint32_t);
- static const int kRegisterOutput = kInputEndOffset + sizeof(uint32_t);
- static const int kAtStart = kRegisterOutput + sizeof(uint32_t);
- static const int kStackHighEnd = kAtStart + sizeof(uint32_t);
+ // Offsets from ebp of function parameters and stored registers.
+ static const int kFramePointer = 0;
+ // Above the frame pointer - function parameters and return address.
+ static const int kReturn_eip = kFramePointer + kPointerSize;
+ static const int kInputBuffer = kReturn_eip + kPointerSize;
+ static const int kInputStartOffset = kInputBuffer + kPointerSize;
+ static const int kInputEndOffset = kInputStartOffset + kPointerSize;
+ static const int kRegisterOutput = kInputEndOffset + kPointerSize;
+ static const int kAtStart = kRegisterOutput + kPointerSize;
+ static const int kStackHighEnd = kAtStart + kPointerSize;
+ // Below the frame pointer - local stack variables.
+ static const int kBackup_esi = kFramePointer - kPointerSize;
+ static const int kBackup_edi = kBackup_esi - kPointerSize;
+ static const int kBackup_ebx = kBackup_edi - kPointerSize;
+ // First register address. Following registers are below it on the stack.
+ static const int kRegisterZero = kBackup_ebx - kPointerSize;
// Initial size of code buffer.
static const size_t kRegExpCodeSize = 1024;
// Initial size of constant buffers allocated during compilation.
static const int kRegExpConstantsSize = 256;
- // Only unroll loops up to this length.
- static const int kMaxInlineStringTests = 32;
// Compares two-byte strings case insensitively.
// Called from generated RegExp code.