Implement typeof in fast compiler.

Review URL: http://codereview.chromium.org/354027

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3222 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
whesse@chromium.org 2009-11-05 10:15:25 +00:00
parent 273e860cc1
commit c1e7dd83a4
4 changed files with 110 additions and 7 deletions

View File

@ -732,7 +732,7 @@ void FastCodeGenerator::VisitProperty(Property* expr) {
if (key->AsLiteral() != NULL && key->AsLiteral()->handle()->IsSymbol() &&
!String::cast(*(key->AsLiteral()->handle()))->AsArrayIndex(&dummy)) {
// Do a NAMED property load.
// The IC expects the property name in ecx and the receiver on the stack.
// The IC expects the property name in r2 and the receiver on the stack.
__ mov(r2, Operand(key->AsLiteral()->handle()));
Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
__ Call(ic, RelocInfo::CODE_TARGET);
@ -915,9 +915,9 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
Comment cmnt(masm_, "[ UnaryOperation");
switch (expr->op()) {
case Token::VOID:
case Token::VOID: {
Comment cmnt(masm_, "[ UnaryOperation (VOID)");
Visit(expr->expression());
ASSERT_EQ(Expression::kEffect, expr->expression()->context());
switch (expr->context()) {
@ -940,8 +940,10 @@ void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
break;
}
break;
}
case Token::NOT: {
Comment cmnt(masm_, "[ UnaryOperation (NOT)");
ASSERT_EQ(Expression::kTest, expr->expression()->context());
Label push_true;
@ -1006,6 +1008,38 @@ void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
break;
}
case Token::TYPEOF: {
Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
ASSERT_EQ(Expression::kValue, expr->expression()->context());
VariableProxy* proxy = expr->expression()->AsVariableProxy();
if (proxy != NULL && proxy->var()->is_global()) {
Comment cmnt(masm_, "Global variable");
__ ldr(r0, CodeGenerator::GlobalObject());
__ push(r0);
__ mov(r2, Operand(proxy->name()));
Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
// Use a regular load, not a contextual load, to avoid a reference
// error.
__ Call(ic, RelocInfo::CODE_TARGET);
__ str(r0, MemOperand(sp));
} else if (proxy != NULL &&
proxy->var()->slot() != NULL &&
proxy->var()->slot()->type() == Slot::LOOKUP) {
__ mov(r0, Operand(proxy->name()));
__ stm(db_w, sp, cp.bit() | r0.bit());
__ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
__ push(r0);
} else {
// This expression cannot throw a reference error at the top level.
Visit(expr->expression());
}
__ CallRuntime(Runtime::kTypeof, 1);
Move(expr->context(), r0);
break;
}
default:
UNREACHABLE();
}

View File

@ -987,6 +987,9 @@ void CodeGenSelector::VisitUnaryOperation(UnaryOperation* expr) {
case Token::NOT:
ProcessExpression(expr->expression(), Expression::kTest);
break;
case Token::TYPEOF:
ProcessExpression(expr->expression(), Expression::kValue);
break;
default:
BAILOUT("UnaryOperation");
}

View File

@ -916,9 +916,9 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
Comment cmnt(masm_, "[ UnaryOperation");
switch (expr->op()) {
case Token::VOID:
case Token::VOID: {
Comment cmnt(masm_, "[ UnaryOperation (VOID)");
Visit(expr->expression());
ASSERT_EQ(Expression::kEffect, expr->expression()->context());
switch (expr->context()) {
@ -940,8 +940,10 @@ void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
break;
}
break;
}
case Token::NOT: {
Comment cmnt(masm_, "[ UnaryOperation (NOT)");
ASSERT_EQ(Expression::kTest, expr->expression()->context());
Label push_true;
@ -1002,6 +1004,37 @@ void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
break;
}
case Token::TYPEOF: {
Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
ASSERT_EQ(Expression::kValue, expr->expression()->context());
VariableProxy* proxy = expr->expression()->AsVariableProxy();
if (proxy != NULL && proxy->var()->is_global()) {
Comment cmnt(masm_, "Global variable");
__ push(CodeGenerator::GlobalObject());
__ mov(ecx, Immediate(proxy->name()));
Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
// Use a regular load, not a contextual load, to avoid a reference
// error.
__ call(ic, RelocInfo::CODE_TARGET);
__ mov(Operand(esp, 0), eax);
} else if (proxy != NULL &&
proxy->var()->slot() != NULL &&
proxy->var()->slot()->type() == Slot::LOOKUP) {
__ push(esi);
__ push(Immediate(proxy->name()));
__ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
__ push(eax);
} else {
// This expression cannot throw a reference error at the top level.
Visit(expr->expression());
}
__ CallRuntime(Runtime::kTypeof, 1);
Move(expr->context(), eax);
break;
}
default:
UNREACHABLE();
}

View File

@ -991,9 +991,9 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
Comment cmnt(masm_, "[ UnaryOperation");
switch (expr->op()) {
case Token::VOID:
case Token::VOID: {
Comment cmnt(masm_, "[ UnaryOperation (VOID)");
Visit(expr->expression());
ASSERT_EQ(Expression::kEffect, expr->expression()->context());
switch (expr->context()) {
@ -1015,8 +1015,10 @@ void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
break;
}
break;
}
case Token::NOT: {
Comment cmnt(masm_, "[ UnaryOperation (NOT)");
ASSERT_EQ(Expression::kTest, expr->expression()->context());
Label push_true;
@ -1077,6 +1079,37 @@ void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
break;
}
case Token::TYPEOF: {
Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
ASSERT_EQ(Expression::kValue, expr->expression()->context());
VariableProxy* proxy = expr->expression()->AsVariableProxy();
if (proxy != NULL && proxy->var()->is_global()) {
Comment cmnt(masm_, "Global variable");
__ push(CodeGenerator::GlobalObject());
__ Move(rcx, proxy->name());
Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
// Use a regular load, not a contextual load, to avoid a reference
// error.
__ Call(ic, RelocInfo::CODE_TARGET);
__ movq(Operand(rsp, 0), rax);
} else if (proxy != NULL &&
proxy->var()->slot() != NULL &&
proxy->var()->slot()->type() == Slot::LOOKUP) {
__ push(rsi);
__ Push(proxy->name());
__ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
__ push(rax);
} else {
// This expression cannot throw a reference error at the top level.
Visit(expr->expression());
}
__ CallRuntime(Runtime::kTypeof, 1);
Move(expr->context(), rax);
break;
}
default:
UNREACHABLE();
}