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:
parent
273e860cc1
commit
c1e7dd83a4
@ -732,7 +732,7 @@ void FastCodeGenerator::VisitProperty(Property* expr) {
|
|||||||
if (key->AsLiteral() != NULL && key->AsLiteral()->handle()->IsSymbol() &&
|
if (key->AsLiteral() != NULL && key->AsLiteral()->handle()->IsSymbol() &&
|
||||||
!String::cast(*(key->AsLiteral()->handle()))->AsArrayIndex(&dummy)) {
|
!String::cast(*(key->AsLiteral()->handle()))->AsArrayIndex(&dummy)) {
|
||||||
// Do a NAMED property load.
|
// 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()));
|
__ mov(r2, Operand(key->AsLiteral()->handle()));
|
||||||
Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
|
Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
|
||||||
__ Call(ic, RelocInfo::CODE_TARGET);
|
__ Call(ic, RelocInfo::CODE_TARGET);
|
||||||
@ -915,9 +915,9 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
|
|||||||
|
|
||||||
|
|
||||||
void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
||||||
Comment cmnt(masm_, "[ UnaryOperation");
|
|
||||||
switch (expr->op()) {
|
switch (expr->op()) {
|
||||||
case Token::VOID:
|
case Token::VOID: {
|
||||||
|
Comment cmnt(masm_, "[ UnaryOperation (VOID)");
|
||||||
Visit(expr->expression());
|
Visit(expr->expression());
|
||||||
ASSERT_EQ(Expression::kEffect, expr->expression()->context());
|
ASSERT_EQ(Expression::kEffect, expr->expression()->context());
|
||||||
switch (expr->context()) {
|
switch (expr->context()) {
|
||||||
@ -940,8 +940,10 @@ void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case Token::NOT: {
|
case Token::NOT: {
|
||||||
|
Comment cmnt(masm_, "[ UnaryOperation (NOT)");
|
||||||
ASSERT_EQ(Expression::kTest, expr->expression()->context());
|
ASSERT_EQ(Expression::kTest, expr->expression()->context());
|
||||||
|
|
||||||
Label push_true;
|
Label push_true;
|
||||||
@ -1006,6 +1008,38 @@ void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
|||||||
break;
|
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:
|
default:
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
@ -987,6 +987,9 @@ void CodeGenSelector::VisitUnaryOperation(UnaryOperation* expr) {
|
|||||||
case Token::NOT:
|
case Token::NOT:
|
||||||
ProcessExpression(expr->expression(), Expression::kTest);
|
ProcessExpression(expr->expression(), Expression::kTest);
|
||||||
break;
|
break;
|
||||||
|
case Token::TYPEOF:
|
||||||
|
ProcessExpression(expr->expression(), Expression::kValue);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
BAILOUT("UnaryOperation");
|
BAILOUT("UnaryOperation");
|
||||||
}
|
}
|
||||||
|
@ -916,9 +916,9 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
|
|||||||
|
|
||||||
|
|
||||||
void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
||||||
Comment cmnt(masm_, "[ UnaryOperation");
|
|
||||||
switch (expr->op()) {
|
switch (expr->op()) {
|
||||||
case Token::VOID:
|
case Token::VOID: {
|
||||||
|
Comment cmnt(masm_, "[ UnaryOperation (VOID)");
|
||||||
Visit(expr->expression());
|
Visit(expr->expression());
|
||||||
ASSERT_EQ(Expression::kEffect, expr->expression()->context());
|
ASSERT_EQ(Expression::kEffect, expr->expression()->context());
|
||||||
switch (expr->context()) {
|
switch (expr->context()) {
|
||||||
@ -940,8 +940,10 @@ void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case Token::NOT: {
|
case Token::NOT: {
|
||||||
|
Comment cmnt(masm_, "[ UnaryOperation (NOT)");
|
||||||
ASSERT_EQ(Expression::kTest, expr->expression()->context());
|
ASSERT_EQ(Expression::kTest, expr->expression()->context());
|
||||||
|
|
||||||
Label push_true;
|
Label push_true;
|
||||||
@ -1002,6 +1004,37 @@ void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
|||||||
break;
|
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:
|
default:
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
@ -991,9 +991,9 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
|||||||
|
|
||||||
|
|
||||||
void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
||||||
Comment cmnt(masm_, "[ UnaryOperation");
|
|
||||||
switch (expr->op()) {
|
switch (expr->op()) {
|
||||||
case Token::VOID:
|
case Token::VOID: {
|
||||||
|
Comment cmnt(masm_, "[ UnaryOperation (VOID)");
|
||||||
Visit(expr->expression());
|
Visit(expr->expression());
|
||||||
ASSERT_EQ(Expression::kEffect, expr->expression()->context());
|
ASSERT_EQ(Expression::kEffect, expr->expression()->context());
|
||||||
switch (expr->context()) {
|
switch (expr->context()) {
|
||||||
@ -1015,8 +1015,10 @@ void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case Token::NOT: {
|
case Token::NOT: {
|
||||||
|
Comment cmnt(masm_, "[ UnaryOperation (NOT)");
|
||||||
ASSERT_EQ(Expression::kTest, expr->expression()->context());
|
ASSERT_EQ(Expression::kTest, expr->expression()->context());
|
||||||
|
|
||||||
Label push_true;
|
Label push_true;
|
||||||
@ -1077,6 +1079,37 @@ void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
|||||||
break;
|
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:
|
default:
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user