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
This commit is contained in:
fschneider@chromium.org 2009-10-22 09:29:03 +00:00
parent d8f7b36624
commit ee9d2d6cee
5 changed files with 104 additions and 11 deletions

View 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.
}
}

View 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.
}

View File

@ -284,11 +284,6 @@ void FastCodeGenerator::VisitLiteral(Literal* expr) {
}
void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
UNREACHABLE();
}
void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
UNREACHABLE();
}

View 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.
}
}

View 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.
}
}