| Index: src/hydrogen-instructions.h | 
| diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h | 
| index ad274657687f14f1def2209166fcbd317fc3294f..fd4db3427869285a7c1ee7574df5e6c1f2fc3872 100644 | 
| --- a/src/hydrogen-instructions.h | 
| +++ b/src/hydrogen-instructions.h | 
| @@ -295,9 +295,9 @@ class Range: public ZoneObject { | 
| void AddConstant(int32_t value); | 
| void Sar(int32_t value); | 
| void Shl(int32_t value); | 
| -  bool AddAndCheckOverflow(Range* other); | 
| -  bool SubAndCheckOverflow(Range* other); | 
| -  bool MulAndCheckOverflow(Range* other); | 
| +  bool AddAndCheckOverflow(const Representation& r, Range* other); | 
| +  bool SubAndCheckOverflow(const Representation& r, Range* other); | 
| +  bool MulAndCheckOverflow(const Representation& r, Range* other); | 
|  | 
| private: | 
| int32_t lower_; | 
| @@ -806,6 +806,8 @@ class HValue: public ZoneObject { | 
| kIsArguments, | 
| kTruncatingToInt32, | 
| kAllUsesTruncatingToInt32, | 
| +    kTruncatingToSmi, | 
| +    kAllUsesTruncatingToSmi, | 
| // Set after an instruction is killed. | 
| kIsDead, | 
| // Instructions that are allowed to produce full range unsigned integer | 
| @@ -892,6 +894,7 @@ class HValue: public ZoneObject { | 
| HUseIterator uses() const { return HUseIterator(use_list_); } | 
|  | 
| virtual bool EmitAtUses() { return false; } | 
| + | 
| Representation representation() const { return representation_; } | 
| void ChangeRepresentation(Representation r) { | 
| ASSERT(CheckFlag(kFlexibleRepresentation)); | 
| @@ -1167,6 +1170,7 @@ class HValue: public ZoneObject { | 
| } | 
| Representation RepresentationFromUses(); | 
| Representation RepresentationFromUseRequirements(); | 
| +  bool HasNonSmiUse(); | 
| virtual void UpdateRepresentation(Representation new_rep, | 
| HInferRepresentationPhase* h_infer, | 
| const char* reason); | 
| @@ -1715,7 +1719,8 @@ class HChange: public HUnaryOperation { | 
| public: | 
| HChange(HValue* value, | 
| Representation to, | 
| -          bool is_truncating, | 
| +          bool is_truncating_to_smi, | 
| +          bool is_truncating_to_int32, | 
| bool allow_undefined_as_nan) | 
| : HUnaryOperation(value) { | 
| ASSERT(!value->representation().IsNone()); | 
| @@ -1724,7 +1729,8 @@ class HChange: public HUnaryOperation { | 
| set_representation(to); | 
| SetFlag(kUseGVN); | 
| if (allow_undefined_as_nan) SetFlag(kAllowUndefinedAsNaN); | 
| -    if (is_truncating) SetFlag(kTruncatingToInt32); | 
| +    if (is_truncating_to_smi) SetFlag(kTruncatingToSmi); | 
| +    if (is_truncating_to_int32) SetFlag(kTruncatingToInt32); | 
| if (value->representation().IsSmi() || value->type().IsSmi()) { | 
| set_type(HType::Smi()); | 
| } else { | 
| @@ -2625,6 +2631,7 @@ class HUnaryMathOperation: public HTemplateInstruction<2> { | 
| switch (op) { | 
| case kMathFloor: | 
| case kMathRound: | 
| +        // TODO(verwaest): Set representation to flexible int starting as smi. | 
| set_representation(Representation::Integer32()); | 
| break; | 
| case kMathAbs: | 
| @@ -3288,7 +3295,7 @@ class HConstant: public HTemplateInstruction<0> { | 
| } | 
|  | 
| virtual Representation KnownOptimalRepresentation() { | 
| -    if (HasSmiValue()) return Representation::Smi(); | 
| +    if (HasSmiValue() && kSmiValueSize == 31) return Representation::Smi(); | 
| if (HasInteger32Value()) return Representation::Integer32(); | 
| if (HasNumberValue()) return Representation::Double(); | 
| return Representation::Tagged(); | 
| @@ -3450,7 +3457,7 @@ class HBinaryOperation: public HTemplateInstruction<3> { | 
| // Otherwise, if there is only one use of the right operand, it would be | 
| // better off on the left for platforms that only have 2-arg arithmetic | 
| // ops (e.g ia32, x64) that clobber the left operand. | 
| -    return (right()->UseCount() == 1); | 
| +    return right()->UseCount() == 1; | 
| } | 
|  | 
| HValue* BetterLeftOperand() { | 
| @@ -3475,24 +3482,28 @@ class HBinaryOperation: public HTemplateInstruction<3> { | 
| return observed_input_representation_[index - 1]; | 
| } | 
|  | 
| -  virtual void InferRepresentation(HInferRepresentationPhase* h_infer); | 
| -  virtual Representation RepresentationFromInputs(); | 
| -  virtual void AssumeRepresentation(Representation r); | 
| - | 
| virtual void UpdateRepresentation(Representation new_rep, | 
| HInferRepresentationPhase* h_infer, | 
| const char* reason) { | 
| -    // By default, binary operations don't handle Smis. | 
| -    if (new_rep.IsSmi()) { | 
| -      new_rep = Representation::Integer32(); | 
| -    } | 
| -    HValue::UpdateRepresentation(new_rep, h_infer, reason); | 
| +    Representation rep = !FLAG_smi_binop && new_rep.IsSmi() | 
| +        ? Representation::Integer32() : new_rep; | 
| +    HValue::UpdateRepresentation(rep, h_infer, reason); | 
| } | 
|  | 
| +  virtual void InferRepresentation(HInferRepresentationPhase* h_infer); | 
| +  virtual Representation RepresentationFromInputs(); | 
| +  Representation RepresentationFromOutput(); | 
| +  virtual void AssumeRepresentation(Representation r); | 
| + | 
| virtual bool IsCommutative() const { return false; } | 
|  | 
| virtual void PrintDataTo(StringStream* stream); | 
|  | 
| +  virtual Representation RequiredInputRepresentation(int index) { | 
| +    if (index == 0) return Representation::Tagged(); | 
| +    return representation(); | 
| +  } | 
| + | 
| DECLARE_ABSTRACT_INSTRUCTION(BinaryOperation) | 
|  | 
| private: | 
| @@ -3771,15 +3782,9 @@ class HBitwiseBinaryOperation: public HBinaryOperation { | 
| SetAllSideEffects(); | 
| } | 
|  | 
| -  virtual Representation RequiredInputRepresentation(int index) { | 
| -    return index == 0 | 
| -        ? Representation::Tagged() | 
| -        : representation(); | 
| -  } | 
| - | 
| virtual void RepresentationChanged(Representation to) { | 
| if (!to.IsTagged()) { | 
| -      ASSERT(to.IsInteger32()); | 
| +      ASSERT(to.IsSmiOrInteger32()); | 
| ClearAllSideEffects(); | 
| SetFlag(kUseGVN); | 
| } else { | 
| @@ -3792,10 +3797,14 @@ class HBitwiseBinaryOperation: public HBinaryOperation { | 
| HInferRepresentationPhase* h_infer, | 
| const char* reason) { | 
| // We only generate either int32 or generic tagged bitwise operations. | 
| -    if (new_rep.IsSmi() || new_rep.IsDouble()) { | 
| -      new_rep = Representation::Integer32(); | 
| -    } | 
| -    HValue::UpdateRepresentation(new_rep, h_infer, reason); | 
| +    if (new_rep.IsDouble()) new_rep = Representation::Integer32(); | 
| +    HBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason); | 
| +  } | 
| + | 
| +  virtual Representation observed_input_representation(int index) { | 
| +    Representation r = HBinaryOperation::observed_input_representation(index); | 
| +    if (r.IsDouble()) return Representation::Integer32(); | 
| +    return r; | 
| } | 
|  | 
| virtual void initialize_output_representation(Representation observed) { | 
| @@ -3861,11 +3870,6 @@ class HArithmeticBinaryOperation: public HBinaryOperation { | 
| } | 
|  | 
| virtual HType CalculateInferredType(); | 
| -  virtual Representation RequiredInputRepresentation(int index) { | 
| -    return index == 0 | 
| -        ? Representation::Tagged() | 
| -        : representation(); | 
| -  } | 
|  | 
| DECLARE_ABSTRACT_INSTRUCTION(ArithmeticBinaryOperation) | 
|  | 
| @@ -4425,6 +4429,13 @@ class HMul: public HArithmeticBinaryOperation { | 
| return !representation().IsTagged(); | 
| } | 
|  | 
| +  virtual void UpdateRepresentation(Representation new_rep, | 
| +                                    HInferRepresentationPhase* h_infer, | 
| +                                    const char* reason) { | 
| +    if (new_rep.IsSmi()) new_rep = Representation::Integer32(); | 
| +    HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason); | 
| +  } | 
| + | 
| DECLARE_CONCRETE_INSTRUCTION(Mul) | 
|  | 
| protected: | 
| @@ -4464,6 +4475,13 @@ class HMod: public HArithmeticBinaryOperation { | 
|  | 
| virtual HValue* Canonicalize(); | 
|  | 
| +  virtual void UpdateRepresentation(Representation new_rep, | 
| +                                    HInferRepresentationPhase* h_infer, | 
| +                                    const char* reason) { | 
| +    if (new_rep.IsSmi()) new_rep = Representation::Integer32(); | 
| +    HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason); | 
| +  } | 
| + | 
| DECLARE_CONCRETE_INSTRUCTION(Mod) | 
|  | 
| protected: | 
| @@ -4506,6 +4524,13 @@ class HDiv: public HArithmeticBinaryOperation { | 
|  | 
| virtual HValue* Canonicalize(); | 
|  | 
| +  virtual void UpdateRepresentation(Representation new_rep, | 
| +                                    HInferRepresentationPhase* h_infer, | 
| +                                    const char* reason) { | 
| +    if (new_rep.IsSmi()) new_rep = Representation::Integer32(); | 
| +    HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason); | 
| +  } | 
| + | 
| DECLARE_CONCRETE_INSTRUCTION(Div) | 
|  | 
| protected: | 
| @@ -4546,11 +4571,11 @@ class HMathMinMax: public HArithmeticBinaryOperation { | 
| virtual Representation RepresentationFromInputs() { | 
| Representation left_rep = left()->representation(); | 
| Representation right_rep = right()->representation(); | 
| -    if ((left_rep.IsNone() || left_rep.IsInteger32()) && | 
| -        (right_rep.IsNone() || right_rep.IsInteger32())) { | 
| -      return Representation::Integer32(); | 
| -    } | 
| -    return Representation::Double(); | 
| +    Representation result = Representation::Smi(); | 
| +    result = result.generalize(left_rep); | 
| +    result = result.generalize(right_rep); | 
| +    if (result.IsTagged()) return Representation::Double(); | 
| +    return result; | 
| } | 
|  | 
| virtual bool IsCommutative() const { return true; } | 
| @@ -4605,6 +4630,27 @@ class HBitwise: public HBitwiseBinaryOperation { | 
| HBitwise(Token::Value op, HValue* context, HValue* left, HValue* right) | 
| : HBitwiseBinaryOperation(context, left, right), op_(op) { | 
| ASSERT(op == Token::BIT_AND || op == Token::BIT_OR || op == Token::BIT_XOR); | 
| +    // BIT_AND with a smi-range positive value will always unset the | 
| +    // entire sign-extension of the smi-sign. | 
| +    if (op == Token::BIT_AND && | 
| +        ((left->IsConstant() && | 
| +          left->representation().IsSmi() && | 
| +          HConstant::cast(left)->Integer32Value() >= 0) || | 
| +         (right->IsConstant() && | 
| +          right->representation().IsSmi() && | 
| +          HConstant::cast(right)->Integer32Value() >= 0))) { | 
| +      SetFlag(kTruncatingToSmi); | 
| +    // BIT_OR with a smi-range negative value will always set the entire | 
| +    // sign-extension of the smi-sign. | 
| +    } else if (op == Token::BIT_OR && | 
| +        ((left->IsConstant() && | 
| +          left->representation().IsSmi() && | 
| +          HConstant::cast(left)->Integer32Value() < 0) || | 
| +         (right->IsConstant() && | 
| +          right->representation().IsSmi() && | 
| +          HConstant::cast(right)->Integer32Value() < 0))) { | 
| +      SetFlag(kTruncatingToSmi); | 
| +    } | 
| } | 
|  | 
| Token::Value op_; | 
| @@ -4620,6 +4666,13 @@ class HShl: public HBitwiseBinaryOperation { | 
|  | 
| virtual Range* InferRange(Zone* zone); | 
|  | 
| +  virtual void UpdateRepresentation(Representation new_rep, | 
| +                                    HInferRepresentationPhase* h_infer, | 
| +                                    const char* reason) { | 
| +    if (new_rep.IsSmi()) new_rep = Representation::Integer32(); | 
| +    HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason); | 
| +  } | 
| + | 
| DECLARE_CONCRETE_INSTRUCTION(Shl) | 
|  | 
| protected: | 
| @@ -4652,6 +4705,13 @@ class HShr: public HBitwiseBinaryOperation { | 
|  | 
| virtual Range* InferRange(Zone* zone); | 
|  | 
| +  virtual void UpdateRepresentation(Representation new_rep, | 
| +                                    HInferRepresentationPhase* h_infer, | 
| +                                    const char* reason) { | 
| +    if (new_rep.IsSmi()) new_rep = Representation::Integer32(); | 
| +    HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason); | 
| +  } | 
| + | 
| DECLARE_CONCRETE_INSTRUCTION(Shr) | 
|  | 
| protected: | 
| @@ -4684,6 +4744,13 @@ class HSar: public HBitwiseBinaryOperation { | 
|  | 
| virtual Range* InferRange(Zone* zone); | 
|  | 
| +  virtual void UpdateRepresentation(Representation new_rep, | 
| +                                    HInferRepresentationPhase* h_infer, | 
| +                                    const char* reason) { | 
| +    if (new_rep.IsSmi()) new_rep = Representation::Integer32(); | 
| +    HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason); | 
| +  } | 
| + | 
| DECLARE_CONCRETE_INSTRUCTION(Sar) | 
|  | 
| protected: | 
| @@ -4702,6 +4769,13 @@ class HRor: public HBitwiseBinaryOperation { | 
| ChangeRepresentation(Representation::Integer32()); | 
| } | 
|  | 
| +  virtual void UpdateRepresentation(Representation new_rep, | 
| +                                    HInferRepresentationPhase* h_infer, | 
| +                                    const char* reason) { | 
| +    if (new_rep.IsSmi()) new_rep = Representation::Integer32(); | 
| +    HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason); | 
| +  } | 
| + | 
| DECLARE_CONCRETE_INSTRUCTION(Ror) | 
|  | 
| protected: | 
|  |