Fast compiler support for regexp literals.
authorfschneider@chromium.org <fschneider@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 22 Oct 2009 09:29:03 +0000 (09:29 +0000)
committerfschneider@chromium.org <fschneider@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 22 Oct 2009 09:29:03 +0000 (09:29 +0000)
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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3109 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/arm/fast-codegen-arm.cc
src/compiler.cc
src/fast-codegen.cc
src/ia32/fast-codegen-ia32.cc
src/x64/fast-codegen-x64.cc

index 5f243a2..c8acd6d 100644 (file)
@@ -215,6 +215,35 @@ void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
   }
 }
 
+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 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
       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.
     }
   }
 
index f306557..1c77a0c 100644 (file)
@@ -458,11 +458,6 @@ CodeGenSelector::CodeGenTag CodeGenSelector::Select(FunctionLiteral* fun) {
   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::VisitLiteral(Literal* expr) {
 
 
 void CodeGenSelector::VisitRegExpLiteral(RegExpLiteral* expr) {
-  BAILOUT("RegExpLiteral");
+  // RegexpLiterals are supported.
 }
 
 
index 59d4645..be99f99 100644 (file)
@@ -284,11 +284,6 @@ void FastCodeGenerator::VisitLiteral(Literal* expr) {
 }
 
 
-void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
-  UNREACHABLE();
-}
-
-
 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
   UNREACHABLE();
 }
index d78c31c..ed0ba92 100644 (file)
@@ -206,6 +206,37 @@ void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
 }
 
 
+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) {
   Comment cmnt(masm_, "[ Assignment");
   ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR);
@@ -328,6 +359,10 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
     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.
     }
   }
 
index e7a9e88..6e8ec9c 100644 (file)
@@ -222,6 +222,37 @@ void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
 }
 
 
+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) {
   Comment cmnt(masm_, "[ Assignment");
   ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR);
@@ -341,6 +372,10 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
     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.
     }
   }