Implement SUB and BIT_NOT unary operations in full codegenerator.
authorager@chromium.org <ager@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 28 Jan 2010 08:15:00 +0000 (08:15 +0000)
committerager@chromium.org <ager@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 28 Jan 2010 08:15:00 +0000 (08:15 +0000)
This change depends on landing the BIT_NOT unary op stub on arm. That
change is out for review.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3727 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/arm/full-codegen-arm.cc
src/full-codegen.cc
src/ia32/full-codegen-ia32.cc
src/x64/full-codegen-x64.cc

index 8d1cfebc75806f440576413d1caff46ebc709e0a..1e7efd209afcb778b29ab4784ea57d313526a9d9 100644 (file)
@@ -1372,6 +1372,45 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
       break;
     }
 
+    case Token::SUB: {
+      Comment cmt(masm_, "[ UnaryOperation (SUB)");
+      bool overwrite =
+          (expr->expression()->AsBinaryOperation() != NULL &&
+           expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
+      GenericUnaryOpStub stub(Token::SUB, overwrite);
+      // GenericUnaryOpStub expects the argument to be in the
+      // accumulator register r0.
+      VisitForValue(expr->expression(), kAccumulator);
+      __ CallStub(&stub);
+      Apply(context_, r0);
+      break;
+    }
+
+    case Token::BIT_NOT: {
+      Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)");
+      bool overwrite =
+          (expr->expression()->AsBinaryOperation() != NULL &&
+           expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
+      GenericUnaryOpStub stub(Token::BIT_NOT, overwrite);
+      // GenericUnaryOpStub expects the argument to be in the
+      // accumulator register r0.
+      VisitForValue(expr->expression(), kAccumulator);
+      // Avoid calling the stub for Smis.
+      Label smi, done;
+      __ tst(result_register(), Operand(kSmiTagMask));
+      __ b(eq, &smi);
+      // Non-smi: call stub leaving result in accumulator register.
+      __ CallStub(&stub);
+      __ b(&done);
+      // Perform operation directly on Smis.
+      __ bind(&smi);
+      __ mvn(result_register(), Operand(result_register()));
+      // Bit-clear inverted smi-tag.
+      __ bic(result_register(), result_register(), Operand(kSmiTagMask));
+      __ bind(&done);
+      Apply(context_, result_register());
+    }
+
     default:
       UNREACHABLE();
   }
index 5bd294feee80cd8840f0eb8862b75c0a35d3b2e8..a14b09fbabf8384694cfa4064760bfc3bd05332b 100644 (file)
@@ -387,17 +387,15 @@ void FullCodeGenSyntaxChecker::VisitCallRuntime(CallRuntime* expr) {
 void FullCodeGenSyntaxChecker::VisitUnaryOperation(UnaryOperation* expr) {
   switch (expr->op()) {
     case Token::ADD:
+    case Token::BIT_NOT:
     case Token::NOT:
+    case Token::SUB:
     case Token::TYPEOF:
     case Token::VOID:
       Visit(expr->expression());
       break;
-    case Token::BIT_NOT:
-      BAILOUT("UnaryOperation: BIT_NOT");
     case Token::DELETE:
       BAILOUT("UnaryOperation: DELETE");
-    case Token::SUB:
-      BAILOUT("UnaryOperation: SUB");
     default:
       UNREACHABLE();
   }
index 03fe54da53927f8688633be16bf360d68cae452d..db5b6cb2cc43880d6a3049b256d733a8ffc2e356 100644 (file)
@@ -1476,6 +1476,44 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
       break;
     }
 
+    case Token::SUB: {
+      Comment cmt(masm_, "[ UnaryOperation (SUB)");
+      bool overwrite =
+          (expr->expression()->AsBinaryOperation() != NULL &&
+           expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
+      GenericUnaryOpStub stub(Token::SUB, overwrite);
+      // GenericUnaryOpStub expects the argument to be in the
+      // accumulator register eax.
+      VisitForValue(expr->expression(), kAccumulator);
+      __ CallStub(&stub);
+      Apply(context_, eax);
+      break;
+    }
+
+    case Token::BIT_NOT: {
+      Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)");
+      bool overwrite =
+          (expr->expression()->AsBinaryOperation() != NULL &&
+           expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
+      GenericUnaryOpStub stub(Token::BIT_NOT, overwrite);
+      // GenericUnaryOpStub expects the argument to be in the
+      // accumulator register eax.
+      VisitForValue(expr->expression(), kAccumulator);
+      // Avoid calling the stub for Smis.
+      Label smi, done;
+      __ test(result_register(), Immediate(kSmiTagMask));
+      __ j(zero, &smi);
+      // Non-smi: call stub leaving result in accumulator register.
+      __ CallStub(&stub);
+      __ jmp(&done);
+      // Perform operation directly on Smis.
+      __ bind(&smi);
+      __ not_(result_register());
+      __ and_(result_register(), ~kSmiTagMask);  // Remove inverted smi-tag.
+      __ bind(&done);
+      Apply(context_, result_register());
+    }
+
     default:
       UNREACHABLE();
   }
index 375510922293eaff625ab64de3932985f52d3347..d93d69e3c11064210dec738072fa1bd3fe876fb2 100644 (file)
@@ -1474,8 +1474,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
       Comment cmt(masm_, "[ UnaryOperation (ADD)");
       VisitForValue(expr->expression(), kAccumulator);
       Label no_conversion;
-      Condition is_smi;
-      is_smi = masm_->CheckSmi(result_register());
+      Condition is_smi = masm_->CheckSmi(result_register());
       __ j(is_smi, &no_conversion);
       __ push(result_register());
       __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION);
@@ -1484,6 +1483,43 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
       break;
     }
 
+    case Token::SUB: {
+      Comment cmt(masm_, "[ UnaryOperation (SUB)");
+      bool overwrite =
+          (expr->expression()->AsBinaryOperation() != NULL &&
+           expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
+      GenericUnaryOpStub stub(Token::SUB, overwrite);
+      // GenericUnaryOpStub expects the argument to be in the
+      // accumulator register rax.
+      VisitForValue(expr->expression(), kAccumulator);
+      __ CallStub(&stub);
+      Apply(context_, rax);
+      break;
+    }
+
+    case Token::BIT_NOT: {
+      Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)");
+      bool overwrite =
+          (expr->expression()->AsBinaryOperation() != NULL &&
+           expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
+      GenericUnaryOpStub stub(Token::BIT_NOT, overwrite);
+      // GenericUnaryOpStub expects the argument to be in the
+      // accumulator register rax.
+      VisitForValue(expr->expression(), kAccumulator);
+      // Avoid calling the stub for Smis.
+      Label smi, done;
+      Condition is_smi = masm_->CheckSmi(result_register());
+      __ j(is_smi, &smi);
+      // Non-smi: call stub leaving result in accumulator register.
+      __ CallStub(&stub);
+      __ jmp(&done);
+      // Perform operation directly on Smis.
+      __ bind(&smi);
+      __ SmiNot(result_register(), result_register());
+      __ bind(&done);
+      Apply(context_, result_register());
+    }
+
     default:
       UNREACHABLE();
   }