Use typefeedback for bitwise operations.
authorfschneider@chromium.org <fschneider@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 20 Jan 2011 12:47:22 +0000 (12:47 +0000)
committerfschneider@chromium.org <fschneider@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 20 Jan 2011 12:47:22 +0000 (12:47 +0000)
Add a generic tagged version for all bitwise operation that
invoke the generic stub. This allows us to perform generic
bitwise operations (i.e. on non-integers) without deoptimizing.

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

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

src/hydrogen-instructions.cc
src/hydrogen-instructions.h
src/hydrogen.cc
src/ia32/lithium-ia32.cc

index b13bb0c..0a90aaa 100644 (file)
@@ -1255,6 +1255,11 @@ HType HUnaryPredicate::CalculateInferredType() const {
 }
 
 
+HType HBitwiseBinaryOperation::CalculateInferredType() const {
+  return HType::TaggedNumber();
+}
+
+
 HType HArithmeticBinaryOperation::CalculateInferredType() const {
   return HType::TaggedNumber();
 }
index d8d3f6f..d18919c 100644 (file)
@@ -2043,16 +2043,26 @@ class HBitwiseBinaryOperation: public HBinaryOperation {
  public:
   HBitwiseBinaryOperation(HValue* left, HValue* right)
       : HBinaryOperation(left, right) {
-    // Default to truncating, Integer32, UseGVN.
-    set_representation(Representation::Integer32());
-    SetFlag(kTruncatingToInt32);
-    SetFlag(kUseGVN);
+    set_representation(Representation::Tagged());
+    SetFlag(kFlexibleRepresentation);
+    SetFlagMask(AllSideEffects());
   }
 
   virtual Representation RequiredInputRepresentation(int index) const {
-    return Representation::Integer32();
+    return representation();
   }
 
+  virtual void RepresentationChanged(Representation to) {
+    if (!to.IsTagged()) {
+      ASSERT(to.IsInteger32());
+      ClearFlagMask(AllSideEffects());
+      SetFlag(kTruncatingToInt32);
+      SetFlag(kUseGVN);
+    }
+  }
+
+  HType CalculateInferredType() const;
+
   DECLARE_INSTRUCTION(BitwiseBinaryOperation)
 };
 
index b906127..53c08f6 100644 (file)
@@ -4820,7 +4820,12 @@ HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr,
   if (FLAG_trace_representation) {
     PrintF("Info: %s/%s\n", info.ToString(), ToRepresentation(info).Mnemonic());
   }
-  AssumeRepresentation(instr, ToRepresentation(info));
+  Representation rep = ToRepresentation(info);
+  // We only generate either int32 or generic tagged bitwise operations.
+  if (instr->IsBitwiseBinaryOperation() && rep.IsDouble()) {
+    rep = Representation::Integer32();
+  }
+  AssumeRepresentation(instr, rep);
   return instr;
 }
 
@@ -4901,7 +4906,8 @@ void HGraphBuilder::AssumeRepresentation(HValue* value, Representation r) {
              graph_->GetMaximumValueID());
     }
     value->ChangeRepresentation(r);
-    // The representation of the value is dictated by type feedback.
+    // The representation of the value is dictated by type feedback and
+    // will not be changed later.
     value->ClearFlag(HValue::kFlexibleRepresentation);
   } else if (FLAG_trace_representation) {
     PrintF("No representation assumed\n");
index 799e077..9a199cc 100644 (file)
@@ -162,6 +162,12 @@ const char* LArithmeticT::Mnemonic() const {
     case Token::MUL: return "mul-t";
     case Token::MOD: return "mod-t";
     case Token::DIV: return "div-t";
+    case Token::BIT_AND: return "bit-and-t";
+    case Token::BIT_OR: return "bit-or-t";
+    case Token::BIT_XOR: return "bit-xor-t";
+    case Token::SHL: return "sal-t";
+    case Token::SAR: return "sar-t";
+    case Token::SHR: return "shr-t";
     default:
       UNREACHABLE();
       return NULL;
@@ -739,18 +745,38 @@ LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
 
 LInstruction* LChunkBuilder::DoBit(Token::Value op,
                                    HBitwiseBinaryOperation* instr) {
-  ASSERT(instr->representation().IsInteger32());
-  ASSERT(instr->left()->representation().IsInteger32());
-  ASSERT(instr->right()->representation().IsInteger32());
+  if (instr->representation().IsInteger32()) {
+    ASSERT(instr->left()->representation().IsInteger32());
+    ASSERT(instr->right()->representation().IsInteger32());
 
-  LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
-  LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
-  return DefineSameAsFirst(new LBitI(op, left, right));
+    LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
+    LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
+    return DefineSameAsFirst(new LBitI(op, left, right));
+  } else {
+    ASSERT(instr->representation().IsTagged());
+    ASSERT(instr->left()->representation().IsTagged());
+    ASSERT(instr->right()->representation().IsTagged());
+
+    LOperand* left = UseFixed(instr->left(), edx);
+    LOperand* right = UseFixed(instr->right(), eax);
+    LArithmeticT* result = new LArithmeticT(op, left, right);
+    return MarkAsCall(DefineFixed(result, eax), instr);
+  }
 }
 
 
 LInstruction* LChunkBuilder::DoShift(Token::Value op,
                                      HBitwiseBinaryOperation* instr) {
+  if (instr->representation().IsTagged()) {
+    ASSERT(instr->left()->representation().IsTagged());
+    ASSERT(instr->right()->representation().IsTagged());
+
+    LOperand* left = UseFixed(instr->left(), edx);
+    LOperand* right = UseFixed(instr->right(), eax);
+    LArithmeticT* result = new LArithmeticT(op, left, right);
+    return MarkAsCall(DefineFixed(result, eax), instr);
+  }
+
   ASSERT(instr->representation().IsInteger32());
   ASSERT(instr->OperandAt(0)->representation().IsInteger32());
   ASSERT(instr->OperandAt(1)->representation().IsInteger32());