Fix bug in propagation of type information into registers.
authorfschneider@chromium.org <fschneider@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 17 Mar 2010 09:49:03 +0000 (09:49 +0000)
committerfschneider@chromium.org <fschneider@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 17 Mar 2010 09:49:03 +0000 (09:49 +0000)
The number type information of results has to be also copied when
calling ToRegister with a fixed register as destination.

Also fix an unbound label and a missing CpuFeatures scope.

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

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

src/ia32/codegen-ia32.cc
src/ia32/register-allocator-ia32.cc
src/x64/register-allocator-x64.cc

index 07cd555..b0793b6 100644 (file)
@@ -1578,6 +1578,7 @@ Result CodeGenerator::LikelySmiBinaryOperation(Token::Value op,
     // if right is a smi we make a fast case if left is either a smi
     // or a heapnumber.
     if (CpuFeatures::IsSupported(SSE2) && right->number_info().IsSmi()) {
+      CpuFeatures::Scope use_sse2(SSE2);
       __ mov(answer.reg(), left->reg());
       // Fast case - both are actually smis.
       if (!left->number_info().IsSmi()) {
@@ -1608,6 +1609,7 @@ Result CodeGenerator::LikelySmiBinaryOperation(Token::Value op,
       __ SmiUntag(answer.reg());
     }
 
+    __ bind(&do_op);
     __ SmiUntag(ecx);
     // Perform the operation.
     switch (op) {
@@ -6652,7 +6654,6 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
           break;
       }
       frame_->Push(&value);
-
     } else {
       Load(node->expression());
       bool overwrite =
@@ -6663,38 +6664,58 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
           GenericUnaryOpStub stub(Token::SUB, overwrite);
           Result operand = frame_->Pop();
           Result answer = frame_->CallStub(&stub, &operand);
+          answer.set_number_info(NumberInfo::Number());
           frame_->Push(&answer);
           break;
         }
-
         case Token::BIT_NOT: {
           // Smi check.
           JumpTarget smi_label;
           JumpTarget continue_label;
           Result operand = frame_->Pop();
+          NumberInfo operand_info = operand.number_info();
           operand.ToRegister();
-          __ test(operand.reg(), Immediate(kSmiTagMask));
-          smi_label.Branch(zero, &operand, taken);
-
-          GenericUnaryOpStub stub(Token::BIT_NOT, overwrite);
-          Result answer = frame_->CallStub(&stub, &operand);
-          continue_label.Jump(&answer);
-
-          smi_label.Bind(&answer);
-          answer.ToRegister();
-          frame_->Spill(answer.reg());
-          __ not_(answer.reg());
-          __ and_(answer.reg(), ~kSmiTagMask);  // Remove inverted smi-tag.
-
-          continue_label.Bind(&answer);
-          frame_->Push(&answer);
+          if (operand_info.IsSmi()) {
+            if (FLAG_debug_code) {
+              __ AbortIfNotSmi(operand.reg(), "Operand not a smi.");
+            }
+            frame_->Spill(operand.reg());
+            // Set smi tag bit. It will be reset by the not operation.
+            __ lea(operand.reg(), Operand(operand.reg(), kSmiTagMask));
+            __ not_(operand.reg());
+            Result answer = operand;
+            answer.set_number_info(NumberInfo::Smi());
+            frame_->Push(&answer);
+          } else {
+            __ test(operand.reg(), Immediate(kSmiTagMask));
+            smi_label.Branch(zero, &operand, taken);
+
+            GenericUnaryOpStub stub(Token::BIT_NOT, overwrite);
+            Result answer = frame_->CallStub(&stub, &operand);
+            continue_label.Jump(&answer);
+
+            smi_label.Bind(&answer);
+            answer.ToRegister();
+            frame_->Spill(answer.reg());
+            // Set smi tag bit. It will be reset by the not operation.
+            __ lea(answer.reg(), Operand(answer.reg(), kSmiTagMask));
+            __ not_(answer.reg());
+
+            continue_label.Bind(&answer);
+            if (operand_info.IsInteger32()) {
+              answer.set_number_info(NumberInfo::Integer32());
+            } else {
+              answer.set_number_info(NumberInfo::Number());
+            }
+            frame_->Push(&answer);
+          }
           break;
         }
-
         case Token::ADD: {
           // Smi check.
           JumpTarget continue_label;
           Result operand = frame_->Pop();
+          NumberInfo operand_info = operand.number_info();
           operand.ToRegister();
           __ test(operand.reg(), Immediate(kSmiTagMask));
           continue_label.Branch(zero, &operand, taken);
@@ -6704,10 +6725,16 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
                                               CALL_FUNCTION, 1);
 
           continue_label.Bind(&answer);
+          if (operand_info.IsSmi()) {
+            answer.set_number_info(NumberInfo::Smi());
+          } else if (operand_info.IsInteger32()) {
+            answer.set_number_info(NumberInfo::Integer32());
+          } else {
+            answer.set_number_info(NumberInfo::Number());
+          }
           frame_->Push(&answer);
           break;
         }
-
         default:
           // NOT, DELETE, TYPEOF, and VOID are handled outside the
           // switch.
index f04390e..0129314 100644 (file)
@@ -122,6 +122,7 @@ void Result::ToRegister(Register target) {
         }
       }
     }
+    fresh.set_number_info(number_info());
     fresh.set_untagged_int32(is_untagged_int32());
     *this = fresh;
   } else if (is_register() && reg().is(target)) {
index d4a47e8..9dc97b8 100644 (file)
@@ -44,6 +44,7 @@ void Result::ToRegister() {
     ASSERT(fresh.is_valid());
     CodeGeneratorScope::Current()->masm()->Move(fresh.reg(), handle());
     // This result becomes a copy of the fresh one.
+    fresh.set_number_info(number_info());
     *this = fresh;
   }
   ASSERT(is_register());
@@ -61,6 +62,7 @@ void Result::ToRegister(Register target) {
       ASSERT(is_constant());
       CodeGeneratorScope::Current()->masm()->Move(fresh.reg(), handle());
     }
+    fresh.set_number_info(number_info());
     *this = fresh;
   } else if (is_register() && reg().is(target)) {
     ASSERT(CodeGeneratorScope::Current()->has_valid_frame());