Support for post-fix count operations (x++, x--) where x is a global
variable for the top-level compiler. Review URL: http://codereview.chromium.org/342058 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3194 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
e09c4f20c5
commit
a07146c0cb
@ -380,7 +380,7 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
}
|
||||
|
||||
// If result_saved == true: the result is saved on top of the stack.
|
||||
// If result_saved == false: the result is in eax.
|
||||
// If result_saved == false: the result is in r0.
|
||||
bool result_saved = false;
|
||||
|
||||
for (int i = 0; i < expr->properties()->length(); i++) {
|
||||
@ -972,6 +972,81 @@ void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
VariableProxy* v = expr->expression()->AsVariableProxy();
|
||||
ASSERT(v->AsVariable() != NULL);
|
||||
ASSERT(v->AsVariable()->is_global());
|
||||
|
||||
Visit(v);
|
||||
|
||||
__ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS);
|
||||
|
||||
switch (expr->context()) {
|
||||
case Expression::kUninitialized:
|
||||
UNREACHABLE();
|
||||
case Expression::kValue: // Fall through
|
||||
case Expression::kTest: // Fall through
|
||||
case Expression::kTestValue: // Fall through
|
||||
case Expression::kValueTest:
|
||||
// Duplicate the result on the stack.
|
||||
__ push(r0);
|
||||
break;
|
||||
case Expression::kEffect:
|
||||
// Do not save result.
|
||||
break;
|
||||
}
|
||||
// Call runtime for +1/-1.
|
||||
__ push(r0);
|
||||
__ mov(ip, Operand(Smi::FromInt(1)));
|
||||
__ push(ip);
|
||||
if (expr->op() == Token::INC) {
|
||||
__ CallRuntime(Runtime::kNumberAdd, 2);
|
||||
} else {
|
||||
__ CallRuntime(Runtime::kNumberSub, 2);
|
||||
}
|
||||
// Call Store IC.
|
||||
__ mov(r2, Operand(v->AsVariable()->name()));
|
||||
__ ldr(ip, CodeGenerator::GlobalObject());
|
||||
__ push(ip);
|
||||
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
|
||||
__ Call(ic, RelocInfo::CODE_TARGET);
|
||||
// Restore up stack after store IC.
|
||||
__ add(sp, sp, Operand(kPointerSize));
|
||||
|
||||
switch (expr->context()) {
|
||||
case Expression::kUninitialized:
|
||||
UNREACHABLE();
|
||||
case Expression::kEffect: // Fall through
|
||||
case Expression::kValue:
|
||||
// Do nothing. Result in either on the stack for value context
|
||||
// or discarded for effect context.
|
||||
break;
|
||||
case Expression::kTest:
|
||||
__ pop(r0);
|
||||
TestAndBranch(r0, true_label_, false_label_);
|
||||
break;
|
||||
case Expression::kValueTest: {
|
||||
Label discard;
|
||||
__ ldr(r0, MemOperand(sp));
|
||||
TestAndBranch(r0, true_label_, &discard);
|
||||
__ bind(&discard);
|
||||
__ add(sp, sp, Operand(kPointerSize));
|
||||
__ b(false_label_);
|
||||
break;
|
||||
}
|
||||
case Expression::kTestValue: {
|
||||
Label discard;
|
||||
__ ldr(r0, MemOperand(sp));
|
||||
TestAndBranch(r0, &discard, false_label_);
|
||||
__ bind(&discard);
|
||||
__ add(sp, sp, Operand(kPointerSize));
|
||||
__ b(true_label_);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
|
||||
switch (expr->op()) {
|
||||
case Token::COMMA:
|
||||
|
@ -847,7 +847,11 @@ void CodeGenSelector::VisitUnaryOperation(UnaryOperation* expr) {
|
||||
|
||||
|
||||
void CodeGenSelector::VisitCountOperation(CountOperation* expr) {
|
||||
BAILOUT("CountOperation");
|
||||
// We support postfix count operations on global variables.
|
||||
if (expr->is_prefix()) BAILOUT("Prefix CountOperation");
|
||||
Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
|
||||
if (var == NULL || !var->is_global()) BAILOUT("non-global postincrement");
|
||||
ProcessExpression(expr->expression(), Expression::kValue);
|
||||
}
|
||||
|
||||
|
||||
|
@ -434,11 +434,6 @@ void FastCodeGenerator::VisitThrow(Throw* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
@ -993,6 +993,79 @@ void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
VariableProxy* v = expr->expression()->AsVariableProxy();
|
||||
ASSERT(v->AsVariable() != NULL);
|
||||
ASSERT(v->AsVariable()->is_global());
|
||||
|
||||
Visit(v);
|
||||
|
||||
__ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION);
|
||||
|
||||
switch (expr->context()) {
|
||||
case Expression::kUninitialized:
|
||||
UNREACHABLE();
|
||||
case Expression::kValue: // Fall through
|
||||
case Expression::kTest: // Fall through
|
||||
case Expression::kTestValue: // Fall through
|
||||
case Expression::kValueTest:
|
||||
// Duplicate the result on the stack.
|
||||
__ push(eax);
|
||||
break;
|
||||
case Expression::kEffect:
|
||||
// Do not save result.
|
||||
break;
|
||||
}
|
||||
// Call runtime for +1/-1.
|
||||
__ push(eax);
|
||||
__ push(Immediate(Smi::FromInt(1)));
|
||||
if (expr->op() == Token::INC) {
|
||||
__ CallRuntime(Runtime::kNumberAdd, 2);
|
||||
} else {
|
||||
__ CallRuntime(Runtime::kNumberSub, 2);
|
||||
}
|
||||
// Call Store IC.
|
||||
__ mov(ecx, v->AsVariable()->name());
|
||||
__ push(CodeGenerator::GlobalObject());
|
||||
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
|
||||
__ call(ic, RelocInfo::CODE_TARGET);
|
||||
// Restore up stack after store IC.
|
||||
__ add(Operand(esp), Immediate(kPointerSize));
|
||||
|
||||
switch (expr->context()) {
|
||||
case Expression::kUninitialized:
|
||||
UNREACHABLE();
|
||||
case Expression::kEffect: // Fall through
|
||||
case Expression::kValue:
|
||||
// Do nothing. Result in either on the stack for value context
|
||||
// or discarded for effect context.
|
||||
break;
|
||||
case Expression::kTest:
|
||||
__ pop(eax);
|
||||
TestAndBranch(eax, true_label_, false_label_);
|
||||
break;
|
||||
case Expression::kValueTest: {
|
||||
Label discard;
|
||||
__ mov(eax, Operand(esp, 0));
|
||||
TestAndBranch(eax, true_label_, &discard);
|
||||
__ bind(&discard);
|
||||
__ add(Operand(esp), Immediate(kPointerSize));
|
||||
__ jmp(false_label_);
|
||||
break;
|
||||
}
|
||||
case Expression::kTestValue: {
|
||||
Label discard;
|
||||
__ mov(eax, Operand(esp, 0));
|
||||
TestAndBranch(eax, &discard, false_label_);
|
||||
__ bind(&discard);
|
||||
__ add(Operand(esp), Immediate(kPointerSize));
|
||||
__ jmp(true_label_);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
|
||||
switch (expr->op()) {
|
||||
case Token::COMMA:
|
||||
|
@ -914,6 +914,78 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
|
||||
Move(expr->context(), rax);
|
||||
}
|
||||
|
||||
void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
VariableProxy* v = expr->expression()->AsVariableProxy();
|
||||
ASSERT(v->AsVariable() != NULL);
|
||||
ASSERT(v->AsVariable()->is_global());
|
||||
|
||||
Visit(v);
|
||||
|
||||
__ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION);
|
||||
|
||||
switch (expr->context()) {
|
||||
case Expression::kUninitialized:
|
||||
UNREACHABLE();
|
||||
case Expression::kValue: // Fall through
|
||||
case Expression::kTest: // Fall through
|
||||
case Expression::kTestValue: // Fall through
|
||||
case Expression::kValueTest:
|
||||
// Duplicate the result on the stack.
|
||||
__ push(rax);
|
||||
break;
|
||||
case Expression::kEffect:
|
||||
// Do not save result.
|
||||
break;
|
||||
}
|
||||
// Call runtime for +1/-1.
|
||||
__ push(rax);
|
||||
__ Push(Smi::FromInt(1));
|
||||
if (expr->op() == Token::INC) {
|
||||
__ CallRuntime(Runtime::kNumberAdd, 2);
|
||||
} else {
|
||||
__ CallRuntime(Runtime::kNumberSub, 2);
|
||||
}
|
||||
// Call Store IC.
|
||||
__ Move(rcx, v->AsVariable()->name());
|
||||
__ push(CodeGenerator::GlobalObject());
|
||||
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
|
||||
__ call(ic, RelocInfo::CODE_TARGET);
|
||||
// Restore up stack after store IC
|
||||
__ addq(rsp, Immediate(kPointerSize));
|
||||
|
||||
switch (expr->context()) {
|
||||
case Expression::kUninitialized:
|
||||
UNREACHABLE();
|
||||
case Expression::kEffect: // Fall through
|
||||
case Expression::kValue:
|
||||
// Do nothing. Result in either on the stack for value context
|
||||
// or discarded for effect context.
|
||||
break;
|
||||
case Expression::kTest:
|
||||
__ pop(rax);
|
||||
TestAndBranch(rax, true_label_, false_label_);
|
||||
break;
|
||||
case Expression::kValueTest: {
|
||||
Label discard;
|
||||
__ movq(rax, Operand(rsp, 0));
|
||||
TestAndBranch(rax, true_label_, &discard);
|
||||
__ bind(&discard);
|
||||
__ addq(rsp, Immediate(kPointerSize));
|
||||
__ jmp(false_label_);
|
||||
break;
|
||||
}
|
||||
case Expression::kTestValue: {
|
||||
Label discard;
|
||||
__ movq(rax, Operand(rsp, 0));
|
||||
TestAndBranch(rax, &discard, false_label_);
|
||||
__ bind(&discard);
|
||||
__ addq(rsp, Immediate(kPointerSize));
|
||||
__ jmp(true_label_);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
||||
Comment cmnt(masm_, "[ UnaryOperation");
|
||||
|
@ -53,3 +53,13 @@ assertEquals("2", eval('g'));
|
||||
// Test a second load.
|
||||
g = 3;
|
||||
assertEquals(3, eval('g'));
|
||||
|
||||
// Test postfix count operation
|
||||
var t;
|
||||
t = g++;
|
||||
assertEquals(3, t);
|
||||
assertEquals(4, g);
|
||||
|
||||
code = "g--; 1";
|
||||
assertEquals(1, eval(code));
|
||||
assertEquals(3, g);
|
||||
|
Loading…
Reference in New Issue
Block a user