The "enter" opcode was slow and crashes for large arguments on Windows.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1066 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
lrn@chromium.org 2009-01-13 10:16:02 +00:00
parent 7c56f0dd9a
commit 70af3cc4ba
2 changed files with 39 additions and 31 deletions

View File

@ -63,10 +63,10 @@ namespace v8 { namespace internal {
* 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)
* - ...
@ -600,6 +600,9 @@ Handle<Object> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) {
// 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);
@ -624,8 +627,7 @@ Handle<Object> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) {
__ 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;
@ -641,12 +643,12 @@ Handle<Object> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) {
__ 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.
@ -663,19 +665,19 @@ Handle<Object> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) {
// 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;
@ -700,7 +702,7 @@ Handle<Object> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) {
// Exit code:
if (success_label_.is_linked()) {
// Success
// Save captures when successful.
__ bind(&success_label_);
if (num_saved_registers_ > 0) {
// copy captures to output
@ -720,11 +722,14 @@ Handle<Object> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) {
}
// 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).
@ -1043,7 +1048,7 @@ Operand RegExpMacroAssemblerIA32::register_location(int register_index) {
if (num_registers_ <= register_index) {
num_registers_ = register_index + 1;
}
return Operand(ebp, -(register_index + 1) * kPointerSize);
return Operand(ebp, kRegisterZero - register_index * kPointerSize);
}

View File

@ -116,24 +116,27 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler {
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.