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:
parent
d8f7b36624
commit
ee9d2d6cee
@ -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.
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user