Revision: 3194 Author: [email protected] Date: Mon Nov 2 02:22:22 2009 Log: 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 http://code.google.com/p/v8/source/detail?r=3194 Modified: /branches/bleeding_edge/src/arm/fast-codegen-arm.cc /branches/bleeding_edge/src/compiler.cc /branches/bleeding_edge/src/fast-codegen.cc /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc /branches/bleeding_edge/src/x64/fast-codegen-x64.cc /branches/bleeding_edge/test/mjsunit/compiler/globals.js ======================================= --- /branches/bleeding_edge/src/arm/fast-codegen-arm.cc Mon Nov 2 02:17:12 2009 +++ /branches/bleeding_edge/src/arm/fast-codegen-arm.cc Mon Nov 2 02:22:22 2009 @@ -380,7 +380,7 @@ } // 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++) { @@ -970,6 +970,81 @@ UNREACHABLE(); } } + + +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) { ======================================= --- /branches/bleeding_edge/src/compiler.cc Mon Nov 2 02:17:12 2009 +++ /branches/bleeding_edge/src/compiler.cc Mon Nov 2 02:22:22 2009 @@ -847,7 +847,11 @@ 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); } ======================================= --- /branches/bleeding_edge/src/fast-codegen.cc Mon Nov 2 00:44:19 2009 +++ /branches/bleeding_edge/src/fast-codegen.cc Mon Nov 2 02:22:22 2009 @@ -432,11 +432,6 @@ void FastCodeGenerator::VisitThrow(Throw* expr) { UNREACHABLE(); } - - -void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { - UNREACHABLE(); -} void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) { ======================================= --- /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc Mon Nov 2 02:17:12 2009 +++ /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc Mon Nov 2 02:22:22 2009 @@ -991,6 +991,79 @@ UNREACHABLE(); } } + + +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) { ======================================= --- /branches/bleeding_edge/src/x64/fast-codegen-x64.cc Mon Nov 2 02:17:12 2009 +++ /branches/bleeding_edge/src/x64/fast-codegen-x64.cc Mon Nov 2 02:22:22 2009 @@ -913,6 +913,78 @@ __ CallRuntime(function, arg_count); 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) { ======================================= --- /branches/bleeding_edge/test/mjsunit/compiler/globals.js Wed Oct 21 02:38:21 2009 +++ /branches/bleeding_edge/test/mjsunit/compiler/globals.js Mon Nov 2 02:22:22 2009 @@ -53,3 +53,13 @@ // 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); --~--~---------~--~----~------------~-------~--~----~ v8-dev mailing list [email protected] http://groups.google.com/group/v8-dev -~----------~----~----~----~------~----~------~--~---
