Revision: 3109
Author: [email protected]
Date: Thu Oct 22 02:29:03 2009
Log: Fast compiler support for regexp literals.

For .result = /abc.*/g we generate the following IA-32 code:

    ...
    mov ebx,[edi+0x17]
    mov eax,[ebx+0xb]
    cmp eax, 0xf5d0e135         ;; object: 0xf5d0e135 <undefined>
    jnz done
    push ebx
    push 0x2
    push 0xf5d13805             ;; object: 0xf5d13805 <String[5]: abc.*>
    push 0xf5d13815             ;; object: 0xf5d13815 <String[1]: g>
    call RuntimeStub_MaterializeRegExpLiteral
  done:
    push eax
    pop [ebp+0xf4]
    ...

This is very similar to the code previously generated except we do not
generate deferred code for the case where we call the runtime.

On ARM we use the stm instruction to make pushing the arguments more  
compact.

Review URL: http://codereview.chromium.org/300037
http://code.google.com/p/v8/source/detail?r=3109

Modified:
  /branches/bleeding_edge/src/arm/fast-codegen-arm.cc
  /branches/bleeding_edge/src/compiler.cc
  /branches/bleeding_edge/src/fast-codegen.cc
  /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc
  /branches/bleeding_edge/src/x64/fast-codegen-x64.cc

=======================================
--- /branches/bleeding_edge/src/arm/fast-codegen-arm.cc Wed Oct 21 02:38:21  
2009
+++ /branches/bleeding_edge/src/arm/fast-codegen-arm.cc Thu Oct 22 02:29:03  
2009
@@ -215,6 +215,35 @@
    }
  }

+void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
+  Comment cmnt(masm_, "[ RegExp Literal");
+  Label done;
+  // Registers will be used as follows:
+  // r4 = JS function, literals array
+  // r3 = literal index
+  // r2 = RegExp pattern
+  // r1 = RegExp flags
+  // r0 = temp + return value (RegExp literal)
+  __ ldr(r0, MemOperand(fp,  JavaScriptFrameConstants::kFunctionOffset));
+  __ ldr(r4,  FieldMemOperand(r0, JSFunction::kLiteralsOffset));
+  int literal_offset =
+    FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
+  __ ldr(r0, FieldMemOperand(r4, literal_offset));
+  __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
+  __ cmp(r0, ip);
+  __ b(ne, &done);
+  __ mov(r3, Operand(Smi::FromInt(expr->literal_index())));
+  __ mov(r2, Operand(expr->pattern()));
+  __ mov(r1, Operand(expr->flags()));
+  __ stm(db_w, sp, r4.bit() | r3.bit() | r2.bit() | r1.bit());
+  __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
+  __ bind(&done);
+  if (expr->location().is_temporary()) {
+    __ push(r0);
+  } else {
+    ASSERT(expr->location().is_nowhere());
+  }
+}

  void FastCodeGenerator::VisitAssignment(Assignment* expr) {
    Comment cmnt(masm_, "[ Assignment");
@@ -342,6 +371,10 @@
        ASSERT(args->at(i)->AsLiteral() != NULL);
        __ mov(r0, Operand(args->at(i)->AsLiteral()->handle()));
        __ push(r0);
+    } else {
+      ASSERT(args->at(i)->location().is_temporary());
+      // If location is temporary, it is already on the stack,
+      // so nothing to do here.
      }
    }

=======================================
--- /branches/bleeding_edge/src/compiler.cc     Wed Oct 21 04:56:05 2009
+++ /branches/bleeding_edge/src/compiler.cc     Thu Oct 22 02:29:03 2009
@@ -458,11 +458,6 @@
    ASSERT(scope->num_heap_slots() == 0);
    ASSERT(scope->arguments() == NULL);

-  if (fun->materialized_literal_count() > 0) {
-    if (FLAG_trace_bailout) PrintF("Unsupported literal\n");
-    return NORMAL;
-  }
-
    has_supported_syntax_ = true;
    VisitDeclarations(fun->scope()->declarations());
    if (!has_supported_syntax_) return NORMAL;
@@ -639,7 +634,7 @@


  void CodeGenSelector::VisitRegExpLiteral(RegExpLiteral* expr) {
-  BAILOUT("RegExpLiteral");
+  // RegexpLiterals are supported.
  }


=======================================
--- /branches/bleeding_edge/src/fast-codegen.cc Wed Oct 21 04:56:05 2009
+++ /branches/bleeding_edge/src/fast-codegen.cc Thu Oct 22 02:29:03 2009
@@ -282,11 +282,6 @@
  void FastCodeGenerator::VisitLiteral(Literal* expr) {
    // No code is emitted (here) for simple literals.
  }
-
-
-void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
-  UNREACHABLE();
-}


  void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
=======================================
--- /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc       Wed Oct 21  
02:38:21 2009
+++ /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc       Thu Oct 22  
02:29:03 2009
@@ -204,6 +204,37 @@
      }
    }
  }
+
+
+void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
+  Comment cmnt(masm_, "[ RegExp Literal");
+  Label done;
+  // Registers will be used as follows:
+  // edi = JS function.
+  // ebx = literals array.
+  // eax = regexp literal.
+  __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
+  __ mov(ebx, FieldOperand(edi, JSFunction::kLiteralsOffset));
+  int literal_offset =
+    FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
+  __ mov(eax, FieldOperand(ebx, literal_offset));
+  __ cmp(eax, Factory::undefined_value());
+  __ j(not_equal, &done);
+  // Create regexp literal using runtime function
+  // Result will be in eax.
+  __ push(ebx);
+  __ push(Immediate(Smi::FromInt(expr->literal_index())));
+  __ push(Immediate(expr->pattern()));
+  __ push(Immediate(expr->flags()));
+  __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
+  // Label done:
+  __ bind(&done);
+  if (expr->location().is_temporary()) {
+    __ push(eax);
+  } else {
+    ASSERT(expr->location().is_nowhere());
+  }
+}


  void FastCodeGenerator::VisitAssignment(Assignment* expr) {
@@ -328,6 +359,10 @@
      if (args->at(i)->location().is_constant()) {
        ASSERT(args->at(i)->AsLiteral() != NULL);
        __ push(Immediate(args->at(i)->AsLiteral()->handle()));
+    } else {
+      ASSERT(args->at(i)->location().is_temporary());
+      // If location is temporary, it is already on the stack,
+      // so nothing to do here.
      }
    }

=======================================
--- /branches/bleeding_edge/src/x64/fast-codegen-x64.cc Wed Oct 21 02:38:21  
2009
+++ /branches/bleeding_edge/src/x64/fast-codegen-x64.cc Thu Oct 22 02:29:03  
2009
@@ -220,6 +220,37 @@
      }
    }
  }
+
+
+void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
+  Comment cmnt(masm_, "[ RegExp Literal");
+  Label done;
+  // Registers will be used as follows:
+  // rdi = JS function.
+  // rbx = literals array.
+  // rax = regexp literal.
+  __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
+  __ movq(rbx, FieldOperand(rdi, JSFunction::kLiteralsOffset));
+  int literal_offset =
+    FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
+  __ movq(rax, FieldOperand(rbx, literal_offset));
+  __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
+  __ j(not_equal, &done);
+  // Create regexp literal using runtime function
+  // Result will be in rax.
+  __ push(rbx);
+  __ Push(Smi::FromInt(expr->literal_index()));
+  __ Push(expr->pattern());
+  __ Push(expr->flags());
+  __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
+  // Label done:
+  __ bind(&done);
+  if (expr->location().is_temporary()) {
+    __ push(rax);
+  } else {
+    ASSERT(expr->location().is_nowhere());
+  }
+}


  void FastCodeGenerator::VisitAssignment(Assignment* expr) {
@@ -341,6 +372,10 @@
      if (args->at(i)->location().is_constant()) {
        ASSERT(args->at(i)->AsLiteral() != NULL);
        __ Push(args->at(i)->AsLiteral()->handle());
+    } else {
+      ASSERT(args->at(i)->location().is_temporary());
+      // If location is temporary, it is already on the stack,
+      // so nothing to do here.
      }
    }


--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---

Reply via email to