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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3109 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent d8f7b366
......@@ -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.
}
}
......
......@@ -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.
}
......
......@@ -284,11 +284,6 @@ void FastCodeGenerator::VisitLiteral(Literal* expr) {
}
void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
UNREACHABLE();
}
void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
UNREACHABLE();
}
......
......@@ -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.
}
}
......
......@@ -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.
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment