diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc index b13bb0c4d8..0a90aaae0f 100644 --- a/src/hydrogen-instructions.cc +++ b/src/hydrogen-instructions.cc @@ -1255,6 +1255,11 @@ HType HUnaryPredicate::CalculateInferredType() const { } +HType HBitwiseBinaryOperation::CalculateInferredType() const { + return HType::TaggedNumber(); +} + + HType HArithmeticBinaryOperation::CalculateInferredType() const { return HType::TaggedNumber(); } diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h index d8d3f6fdf1..d18919c3b0 100644 --- a/src/hydrogen-instructions.h +++ b/src/hydrogen-instructions.h @@ -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) }; diff --git a/src/hydrogen.cc b/src/hydrogen.cc index b906127d46..53c08f6b43 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -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"); diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc index 799e077a33..9a199cc04a 100644 --- a/src/ia32/lithium-ia32.cc +++ b/src/ia32/lithium-ia32.cc @@ -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());