The "enter" opcode was slow and crashes for large arguments on Windows.
authorlrn@chromium.org <lrn@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 13 Jan 2009 10:16:02 +0000 (10:16 +0000)
committerlrn@chromium.org <lrn@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 13 Jan 2009 10:16:02 +0000 (10:16 +0000)
git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1066 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/regexp-macro-assembler-ia32.cc
src/regexp-macro-assembler-ia32.h

index b21b5d8..7afc46d 100644 (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);
 }
 
 
index 8831821..341668c 100644 (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.