Support for post-fix count operations (x++, x--) where x is a global
authorfschneider@chromium.org <fschneider@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 2 Nov 2009 10:22:22 +0000 (10:22 +0000)
committerfschneider@chromium.org <fschneider@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 2 Nov 2009 10:22:22 +0000 (10:22 +0000)
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

src/arm/fast-codegen-arm.cc
src/compiler.cc
src/fast-codegen.cc
src/ia32/fast-codegen-ia32.cc
src/x64/fast-codegen-x64.cc
test/mjsunit/compiler/globals.js

index 6e8537a..967d53e 100644 (file)
@@ -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:
index e70b64a..e9db632 100644 (file)
@@ -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);
 }
 
 
index 7d7b21f..615821f 100644 (file)
@@ -434,11 +434,6 @@ void FastCodeGenerator::VisitThrow(Throw* expr) {
 }
 
 
-void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
-  UNREACHABLE();
-}
-
-
 void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
   UNREACHABLE();
 }
index a2114e5..9225934 100644 (file)
@@ -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:
index 70ce36a..d9cfa29 100644 (file)
@@ -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");
index 066f927..0abd5dd 100644 (file)
@@ -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);