Adding Smi support to Add, Sub, Mul, and Bitwise
authorverwaest@chromium.org <verwaest@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 25 Jul 2013 11:53:38 +0000 (11:53 +0000)
committerverwaest@chromium.org <verwaest@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 25 Jul 2013 11:53:38 +0000 (11:53 +0000)
R=svenpanne@chromium.org

Review URL: https://chromiumcodereview.appspot.com/20070005

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

20 files changed:
src/arm/lithium-arm.cc
src/arm/lithium-codegen-arm.cc
src/arm/lithium-codegen-arm.h
src/arm/lithium-gap-resolver-arm.cc
src/flag-definitions.h
src/hydrogen-canonicalize.cc
src/hydrogen-instructions.cc
src/hydrogen-instructions.h
src/hydrogen-minus-zero.cc
src/hydrogen-representation-changes.cc
src/hydrogen.cc
src/ia32/lithium-codegen-ia32.cc
src/ia32/lithium-codegen-ia32.h
src/ia32/lithium-gap-resolver-ia32.cc
src/ia32/lithium-ia32.cc
src/type-info.cc
src/types.cc
src/x64/lithium-codegen-x64.cc
src/x64/lithium-codegen-x64.h
src/x64/lithium-x64.cc

index 07f007d..65abeca 100644 (file)
@@ -778,8 +778,8 @@ LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op,
          op == Token::SUB);
   HValue* left = instr->left();
   HValue* right = instr->right();
-  ASSERT(left->representation().IsSmiOrTagged());
-  ASSERT(right->representation().IsSmiOrTagged());
+  ASSERT(left->representation().IsTagged());
+  ASSERT(right->representation().IsTagged());
   LOperand* left_operand = UseFixed(left, r1);
   LOperand* right_operand = UseFixed(right, r0);
   LArithmeticT* result =
@@ -1313,17 +1313,17 @@ LInstruction* LChunkBuilder::DoShl(HShl* instr) {
 
 
 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) {
-  if (instr->representation().IsInteger32()) {
-    ASSERT(instr->left()->representation().IsInteger32());
-    ASSERT(instr->right()->representation().IsInteger32());
+  if (instr->representation().IsSmiOrInteger32()) {
+    ASSERT(instr->left()->representation().Equals(instr->representation()));
+    ASSERT(instr->right()->representation().Equals(instr->representation()));
 
     LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
     LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand());
     return DefineAsRegister(new(zone()) LBitI(left, right));
   } else {
-    ASSERT(instr->representation().IsSmiOrTagged());
-    ASSERT(instr->left()->representation().IsSmiOrTagged());
-    ASSERT(instr->right()->representation().IsSmiOrTagged());
+    ASSERT(instr->representation().IsTagged());
+    ASSERT(instr->left()->representation().IsTagged());
+    ASSERT(instr->right()->representation().IsTagged());
 
     LOperand* left = UseFixed(instr->left(), r1);
     LOperand* right = UseFixed(instr->right(), r0);
@@ -1345,7 +1345,9 @@ LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) {
 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
   if (instr->representation().IsDouble()) {
     return DoArithmeticD(Token::DIV, instr);
-  } else if (instr->representation().IsInteger32()) {
+  } else if (instr->representation().IsSmiOrInteger32()) {
+    ASSERT(instr->left()->representation().Equals(instr->representation()));
+    ASSERT(instr->right()->representation().Equals(instr->representation()));
     if (instr->HasPowerOf2Divisor()) {
       ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero));
       LOperand* value = UseRegisterAtStart(instr->left());
@@ -1436,9 +1438,9 @@ LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
 LInstruction* LChunkBuilder::DoMod(HMod* instr) {
   HValue* left = instr->left();
   HValue* right = instr->right();
-  if (instr->representation().IsInteger32()) {
-    ASSERT(left->representation().IsInteger32());
-    ASSERT(right->representation().IsInteger32());
+  if (instr->representation().IsSmiOrInteger32()) {
+    ASSERT(instr->left()->representation().Equals(instr->representation()));
+    ASSERT(instr->right()->representation().Equals(instr->representation()));
     if (instr->HasPowerOf2Divisor()) {
       ASSERT(!right->CanBeZero());
       LModI* mod = new(zone()) LModI(UseRegisterAtStart(left),
@@ -1478,7 +1480,7 @@ LInstruction* LChunkBuilder::DoMod(HMod* instr) {
           ? AssignEnvironment(result)
           : result;
     }
-  } else if (instr->representation().IsSmiOrTagged()) {
+  } else if (instr->representation().IsTagged()) {
     return DoArithmeticT(Token::MOD, instr);
   } else {
     ASSERT(instr->representation().IsDouble());
@@ -1494,9 +1496,9 @@ LInstruction* LChunkBuilder::DoMod(HMod* instr) {
 
 
 LInstruction* LChunkBuilder::DoMul(HMul* instr) {
-  if (instr->representation().IsInteger32()) {
-    ASSERT(instr->left()->representation().IsInteger32());
-    ASSERT(instr->right()->representation().IsInteger32());
+  if (instr->representation().IsSmiOrInteger32()) {
+    ASSERT(instr->left()->representation().Equals(instr->representation()));
+    ASSERT(instr->right()->representation().Equals(instr->representation()));
     LOperand* left;
     LOperand* right = UseOrConstant(instr->BetterRightOperand());
     LOperand* temp = NULL;
@@ -1545,9 +1547,9 @@ LInstruction* LChunkBuilder::DoMul(HMul* instr) {
 
 
 LInstruction* LChunkBuilder::DoSub(HSub* instr) {
-  if (instr->representation().IsInteger32()) {
-    ASSERT(instr->left()->representation().IsInteger32());
-    ASSERT(instr->right()->representation().IsInteger32());
+  if (instr->representation().IsSmiOrInteger32()) {
+    ASSERT(instr->left()->representation().Equals(instr->representation()));
+    ASSERT(instr->right()->representation().Equals(instr->representation()));
 
     if (instr->left()->IsConstant()) {
       // If lhs is constant, do reverse subtraction instead.
@@ -1575,9 +1577,9 @@ LInstruction* LChunkBuilder::DoSub(HSub* instr) {
 
 
 LInstruction* LChunkBuilder::DoRSub(HSub* instr) {
-  ASSERT(instr->representation().IsInteger32());
-  ASSERT(instr->left()->representation().IsInteger32());
-  ASSERT(instr->right()->representation().IsInteger32());
+  ASSERT(instr->representation().IsSmiOrInteger32());
+  ASSERT(instr->left()->representation().Equals(instr->representation()));
+  ASSERT(instr->right()->representation().Equals(instr->representation()));
 
   // Note: The lhs of the subtraction becomes the rhs of the
   // reverse-subtraction.
@@ -1613,9 +1615,9 @@ LInstruction* LChunkBuilder::DoMultiplySub(HValue* minuend, HMul* mul) {
 
 
 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
-  if (instr->representation().IsInteger32()) {
-    ASSERT(instr->left()->representation().IsInteger32());
-    ASSERT(instr->right()->representation().IsInteger32());
+  if (instr->representation().IsSmiOrInteger32()) {
+    ASSERT(instr->left()->representation().Equals(instr->representation()));
+    ASSERT(instr->right()->representation().Equals(instr->representation()));
     LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
     LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand());
     LAddI* add = new(zone()) LAddI(left, right);
@@ -1636,7 +1638,7 @@ LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
 
     return DoArithmeticD(Token::ADD, instr);
   } else {
-    ASSERT(instr->representation().IsSmiOrTagged());
+    ASSERT(instr->representation().IsTagged());
     return DoArithmeticT(Token::ADD, instr);
   }
 }
@@ -1645,9 +1647,9 @@ LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) {
   LOperand* left = NULL;
   LOperand* right = NULL;
-  if (instr->representation().IsInteger32()) {
-    ASSERT(instr->left()->representation().IsInteger32());
-    ASSERT(instr->right()->representation().IsInteger32());
+  if (instr->representation().IsSmiOrInteger32()) {
+    ASSERT(instr->left()->representation().Equals(instr->representation()));
+    ASSERT(instr->right()->representation().Equals(instr->representation()));
     left = UseRegisterAtStart(instr->BetterLeftOperand());
     right = UseOrConstantAtStart(instr->BetterRightOperand());
   } else {
@@ -2201,8 +2203,7 @@ LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
 
 
 LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
-  ASSERT(instr->key()->representation().IsInteger32() ||
-         instr->key()->representation().IsSmi());
+  ASSERT(instr->key()->representation().IsSmiOrInteger32());
   ElementsKind elements_kind = instr->elements_kind();
   LOperand* key = UseRegisterOrConstantAtStart(instr->key());
   LLoadKeyed* result = NULL;
index db90e91..8f28651 100644 (file)
@@ -494,9 +494,18 @@ bool LCodeGen::IsSmi(LConstantOperand* op) const {
 }
 
 
-int LCodeGen::ToInteger32(LConstantOperand* op) const {
+int32_t LCodeGen::ToInteger32(LConstantOperand* op) const {
+  return ToRepresentation(op, Representation::Integer32());
+}
+
+
+int32_t LCodeGen::ToRepresentation(LConstantOperand* op,
+                                   const Representation& r) const {
   HConstant* constant = chunk_->LookupConstant(op);
-  return constant->Integer32Value();
+  int32_t value = constant->Integer32Value();
+  if (r.IsInteger32()) return value;
+  ASSERT(r.IsSmiOrTagged());
+  return reinterpret_cast<int32_t>(Smi::FromInt(value));
 }
 
 
@@ -518,7 +527,10 @@ Operand LCodeGen::ToOperand(LOperand* op) {
     LConstantOperand* const_op = LConstantOperand::cast(op);
     HConstant* constant = chunk()->LookupConstant(const_op);
     Representation r = chunk_->LookupLiteralRepresentation(const_op);
-    if (r.IsInteger32()) {
+    if (r.IsSmi()) {
+      ASSERT(constant->HasSmiValue());
+      return Operand(Smi::FromInt(constant->Integer32Value()));
+    } else if (r.IsInteger32()) {
       ASSERT(constant->HasInteger32Value());
       return Operand(constant->Integer32Value());
     } else if (r.IsDouble()) {
@@ -1540,7 +1552,9 @@ void LCodeGen::DoMulI(LMulI* instr) {
 
   if (right_op->IsConstantOperand() && !can_overflow) {
     // Use optimized code for specific constants.
-    int32_t constant = ToInteger32(LConstantOperand::cast(right_op));
+    int32_t constant = ToRepresentation(
+        LConstantOperand::cast(right_op),
+        instr->hydrogen()->right()->representation());
 
     if (bailout_on_minus_zero && (constant < 0)) {
       // The case of a null constant will be handled separately.
@@ -1604,11 +1618,21 @@ void LCodeGen::DoMulI(LMulI* instr) {
 
     if (can_overflow) {
       // scratch:result = left * right.
-      __ smull(result, scratch, left, right);
+      if (instr->hydrogen()->representation().IsSmi()) {
+        __ SmiUntag(result, left);
+        __ smull(result, scratch, result, right);
+      } else {
+        __ smull(result, scratch, left, right);
+      }
       __ cmp(scratch, Operand(result, ASR, 31));
       DeoptimizeIf(ne, instr->environment());
     } else {
-      __ mul(result, left, right);
+      if (instr->hydrogen()->representation().IsSmi()) {
+        __ SmiUntag(result, left);
+        __ mul(result, result, right);
+      } else {
+        __ mul(result, left, right);
+      }
     }
 
     if (bailout_on_minus_zero) {
@@ -1958,7 +1982,7 @@ void LCodeGen::DoMathMinMax(LMathMinMax* instr) {
   LOperand* left = instr->left();
   LOperand* right = instr->right();
   HMathMinMax::Operation operation = instr->hydrogen()->operation();
-  if (instr->hydrogen()->representation().IsInteger32()) {
+  if (instr->hydrogen()->representation().IsSmiOrInteger32()) {
     Condition condition = (operation == HMathMinMax::kMathMin) ? le : ge;
     Register left_reg = ToRegister(left);
     Operand right_op = (right->IsRegister() || right->IsConstantOperand())
index 51d16fa..ae4a09f 100644 (file)
@@ -115,7 +115,8 @@ class LCodeGen BASE_EMBEDDED {
   DwVfpRegister EmitLoadDoubleRegister(LOperand* op,
                                        SwVfpRegister flt_scratch,
                                        DwVfpRegister dbl_scratch);
-  int ToInteger32(LConstantOperand* op) const;
+  int ToRepresentation(LConstantOperand* op, const Representation& r) const;
+  int32_t ToInteger32(LConstantOperand* op) const;
   Smi* ToSmi(LConstantOperand* op) const;
   double ToDouble(LConstantOperand* op) const;
   Operand ToOperand(LOperand* op);
index 902817e..7a3c968 100644 (file)
@@ -247,10 +247,10 @@ void LGapResolver::EmitMove(int index) {
     LConstantOperand* constant_source = LConstantOperand::cast(source);
     if (destination->IsRegister()) {
       Register dst = cgen_->ToRegister(destination);
-      if (cgen_->IsSmi(constant_source)) {
-        __ mov(dst, Operand(cgen_->ToSmi(constant_source)));
-      } else if (cgen_->IsInteger32(constant_source)) {
-        __ mov(dst, Operand(cgen_->ToInteger32(constant_source)));
+      Representation r = cgen_->IsSmi(constant_source)
+          ? Representation::Smi() : Representation::Integer32();
+      if (cgen_->IsInteger32(constant_source)) {
+        __ mov(dst, Operand(cgen_->ToRepresentation(constant_source, r)));
       } else {
         __ LoadObject(dst, cgen_->ToHandle(constant_source));
       }
@@ -261,11 +261,11 @@ void LGapResolver::EmitMove(int index) {
     } else {
       ASSERT(destination->IsStackSlot());
       ASSERT(!in_cycle_);  // Constant moves happen after all cycles are gone.
-      if (cgen_->IsSmi(constant_source)) {
-        __ mov(kSavedValueRegister, Operand(cgen_->ToSmi(constant_source)));
-      } else if (cgen_->IsInteger32(constant_source)) {
+      Representation r = cgen_->IsSmi(constant_source)
+          ? Representation::Smi() : Representation::Integer32();
+      if (cgen_->IsInteger32(constant_source)) {
         __ mov(kSavedValueRegister,
-               Operand(cgen_->ToInteger32(constant_source)));
+               Operand(cgen_->ToRepresentation(constant_source, r)));
       } else {
         __ LoadObject(kSavedValueRegister,
                       cgen_->ToHandle(constant_source));
index c32fe49..72159c0 100644 (file)
@@ -208,6 +208,7 @@ DEFINE_bool(track_computed_fields, true, "track computed boilerplate fields")
 DEFINE_implication(track_double_fields, track_fields)
 DEFINE_implication(track_heap_object_fields, track_fields)
 DEFINE_implication(track_computed_fields, track_fields)
+DEFINE_bool(smi_binop, true, "support smi representation in binary operations")
 
 // Flags for data representation optimizations
 DEFINE_bool(unbox_double_arrays, true, "automatically unbox arrays of doubles")
index 40cbe4c..6432343 100644 (file)
@@ -38,11 +38,18 @@ void HCanonicalizePhase::Run() {
   for (int i = 0; i < blocks->length(); ++i) {
     for (HInstructionIterator it(blocks->at(i)); !it.Done(); it.Advance()) {
       HInstruction* instr = it.Current();
-      if (instr->IsArithmeticBinaryOperation() &&
-          instr->representation().IsInteger32() &&
-          instr->HasAtLeastOneUseWithFlagAndNoneWithout(
-              HInstruction::kTruncatingToInt32)) {
-        instr->SetFlag(HInstruction::kAllUsesTruncatingToInt32);
+      if (instr->IsArithmeticBinaryOperation()) {
+        if (instr->representation().IsInteger32()) {
+          if (instr->HasAtLeastOneUseWithFlagAndNoneWithout(
+                  HInstruction::kTruncatingToInt32)) {
+            instr->SetFlag(HInstruction::kAllUsesTruncatingToInt32);
+          }
+        } else if (instr->representation().IsSmi()) {
+          if (instr->HasAtLeastOneUseWithFlagAndNoneWithout(
+                  HInstruction::kTruncatingToSmi)) {
+            instr->SetFlag(HInstruction::kAllUsesTruncatingToSmi);
+          }
+        }
       }
     }
   }
index 707e818..5fe3af1 100644 (file)
@@ -84,9 +84,9 @@ void HValue::InferRepresentation(HInferRepresentationPhase* h_infer) {
   UpdateRepresentation(new_rep, h_infer, "inputs");
   new_rep = RepresentationFromUses();
   UpdateRepresentation(new_rep, h_infer, "uses");
-  new_rep = RepresentationFromUseRequirements();
-  if (new_rep.fits_into(Representation::Integer32())) {
-    UpdateRepresentation(new_rep, h_infer, "use requirements");
+  if (representation().IsSmi() && HasNonSmiUse()) {
+    UpdateRepresentation(
+        Representation::Integer32(), h_infer, "use requirements");
   }
 }
 
@@ -259,34 +259,56 @@ HValue* RangeEvaluationContext::ConvertGuarantee(HValue* guarantee) {
 }
 
 
-static int32_t ConvertAndSetOverflow(int64_t result, bool* overflow) {
-  if (result > kMaxInt) {
-    *overflow = true;
-    return kMaxInt;
-  }
-  if (result < kMinInt) {
-    *overflow = true;
-    return kMinInt;
+static int32_t ConvertAndSetOverflow(Representation r,
+                                     int64_t result,
+                                     bool* overflow) {
+  if (r.IsSmi()) {
+    if (result > Smi::kMaxValue) {
+      *overflow = true;
+      return Smi::kMaxValue;
+    }
+    if (result < Smi::kMinValue) {
+      *overflow = true;
+      return Smi::kMinValue;
+    }
+  } else {
+    if (result > kMaxInt) {
+      *overflow = true;
+      return kMaxInt;
+    }
+    if (result < kMinInt) {
+      *overflow = true;
+      return kMinInt;
+    }
   }
   return static_cast<int32_t>(result);
 }
 
 
-static int32_t AddWithoutOverflow(int32_t a, int32_t b, bool* overflow) {
+static int32_t AddWithoutOverflow(Representation r,
+                                  int32_t a,
+                                  int32_t b,
+                                  bool* overflow) {
   int64_t result = static_cast<int64_t>(a) + static_cast<int64_t>(b);
-  return ConvertAndSetOverflow(result, overflow);
+  return ConvertAndSetOverflow(r, result, overflow);
 }
 
 
-static int32_t SubWithoutOverflow(int32_t a, int32_t b, bool* overflow) {
+static int32_t SubWithoutOverflow(Representation r,
+                                  int32_t a,
+                                  int32_t b,
+                                  bool* overflow) {
   int64_t result = static_cast<int64_t>(a) - static_cast<int64_t>(b);
-  return ConvertAndSetOverflow(result, overflow);
+  return ConvertAndSetOverflow(r, result, overflow);
 }
 
 
-static int32_t MulWithoutOverflow(int32_t a, int32_t b, bool* overflow) {
+static int32_t MulWithoutOverflow(const Representation& r,
+                                  int32_t a,
+                                  int32_t b,
+                                  bool* overflow) {
   int64_t result = static_cast<int64_t>(a) * static_cast<int64_t>(b);
-  return ConvertAndSetOverflow(result, overflow);
+  return ConvertAndSetOverflow(r, result, overflow);
 }
 
 
@@ -306,8 +328,9 @@ int32_t Range::Mask() const {
 void Range::AddConstant(int32_t value) {
   if (value == 0) return;
   bool may_overflow = false;  // Overflow is ignored here.
-  lower_ = AddWithoutOverflow(lower_, value, &may_overflow);
-  upper_ = AddWithoutOverflow(upper_, value, &may_overflow);
+  Representation r = Representation::Integer32();
+  lower_ = AddWithoutOverflow(r, lower_, value, &may_overflow);
+  upper_ = AddWithoutOverflow(r, upper_, value, &may_overflow);
 #ifdef DEBUG
   Verify();
 #endif
@@ -366,10 +389,10 @@ void Range::Shl(int32_t value) {
 }
 
 
-bool Range::AddAndCheckOverflow(Range* other) {
+bool Range::AddAndCheckOverflow(const Representation& r, Range* other) {
   bool may_overflow = false;
-  lower_ = AddWithoutOverflow(lower_, other->lower(), &may_overflow);
-  upper_ = AddWithoutOverflow(upper_, other->upper(), &may_overflow);
+  lower_ = AddWithoutOverflow(r, lower_, other->lower(), &may_overflow);
+  upper_ = AddWithoutOverflow(r, upper_, other->upper(), &may_overflow);
   KeepOrder();
 #ifdef DEBUG
   Verify();
@@ -378,10 +401,10 @@ bool Range::AddAndCheckOverflow(Range* other) {
 }
 
 
-bool Range::SubAndCheckOverflow(Range* other) {
+bool Range::SubAndCheckOverflow(const Representation& r, Range* other) {
   bool may_overflow = false;
-  lower_ = SubWithoutOverflow(lower_, other->upper(), &may_overflow);
-  upper_ = SubWithoutOverflow(upper_, other->lower(), &may_overflow);
+  lower_ = SubWithoutOverflow(r, lower_, other->upper(), &may_overflow);
+  upper_ = SubWithoutOverflow(r, upper_, other->lower(), &may_overflow);
   KeepOrder();
 #ifdef DEBUG
   Verify();
@@ -406,12 +429,12 @@ void Range::Verify() const {
 #endif
 
 
-bool Range::MulAndCheckOverflow(Range* other) {
+bool Range::MulAndCheckOverflow(const Representation& r, Range* other) {
   bool may_overflow = false;
-  int v1 = MulWithoutOverflow(lower_, other->lower(), &may_overflow);
-  int v2 = MulWithoutOverflow(lower_, other->upper(), &may_overflow);
-  int v3 = MulWithoutOverflow(upper_, other->lower(), &may_overflow);
-  int v4 = MulWithoutOverflow(upper_, other->upper(), &may_overflow);
+  int v1 = MulWithoutOverflow(r, lower_, other->lower(), &may_overflow);
+  int v2 = MulWithoutOverflow(r, lower_, other->upper(), &may_overflow);
+  int v3 = MulWithoutOverflow(r, upper_, other->lower(), &may_overflow);
+  int v4 = MulWithoutOverflow(r, upper_, other->upper(), &may_overflow);
   lower_ = Min(Min(v1, v2), Min(v3, v4));
   upper_ = Max(Max(v1, v2), Max(v3, v4));
 #ifdef DEBUG
@@ -1431,7 +1454,7 @@ void HLoadFieldByIndex::PrintDataTo(StringStream* stream) {
 
 
 HValue* HBitwise::Canonicalize() {
-  if (!representation().IsInteger32()) return this;
+  if (!representation().IsSmiOrInteger32()) return this;
   // If x is an int32, then x & -1 == x, x | 0 == x and x ^ 0 == x.
   int32_t nop_constant = (op() == Token::BIT_AND) ? -1 : 0;
   if (left()->EqualsInteger32Constant(nop_constant) &&
@@ -1551,7 +1574,7 @@ HValue* HUnaryMathOperation::Canonicalize() {
 
     // If the input is integer32 then we replace the floor instruction
     // with its input.
-    if (val->representation().IsInteger32()) return val;
+    if (val->representation().IsSmiOrInteger32()) return val;
 
     if (val->IsDiv() && (val->UseCount() == 1)) {
       HDiv* hdiv = HDiv::cast(val);
@@ -1561,8 +1584,8 @@ HValue* HUnaryMathOperation::Canonicalize() {
       HValue* new_left = SimplifiedDividendForMathFloorOfDiv(left);
       if (new_left == NULL &&
           hdiv->observed_input_representation(1).IsSmiOrInteger32()) {
-        new_left = new(block()->zone())
-            HChange(left, Representation::Integer32(), false, false);
+        new_left = new(block()->zone()) HChange(
+            left, Representation::Integer32(), false, false, false);
         HChange::cast(new_left)->InsertBefore(this);
       }
       HValue* new_right =
@@ -1572,8 +1595,8 @@ HValue* HUnaryMathOperation::Canonicalize() {
           CpuFeatures::IsSupported(SUDIV) &&
 #endif
           hdiv->observed_input_representation(2).IsSmiOrInteger32()) {
-        new_right = new(block()->zone())
-            HChange(right, Representation::Integer32(), false, false);
+        new_right = new(block()->zone()) HChange(
+            right, Representation::Integer32(), false, false, false);
         HChange::cast(new_right)->InsertBefore(this);
       }
 
@@ -1743,7 +1766,7 @@ void HInstanceOf::PrintDataTo(StringStream* stream) {
 
 Range* HValue::InferRange(Zone* zone) {
   Range* result;
-  if (type().IsSmi()) {
+  if (representation().IsSmi() || type().IsSmi()) {
     result = new(zone) Range(Smi::kMinValue, Smi::kMaxValue);
     result->set_can_be_minus_zero(false);
   } else {
@@ -1758,10 +1781,11 @@ Range* HValue::InferRange(Zone* zone) {
 
 Range* HChange::InferRange(Zone* zone) {
   Range* input_range = value()->range();
-  if (from().IsInteger32() &&
-      to().IsSmiOrTagged() &&
-      !value()->CheckFlag(HInstruction::kUint32) &&
-      input_range != NULL && input_range->IsInSmiRange()) {
+  if (from().IsInteger32() && !value()->CheckFlag(HInstruction::kUint32) &&
+      (to().IsSmi() ||
+       (to().IsTagged() &&
+        input_range != NULL &&
+        input_range->IsInSmiRange()))) {
     set_type(HType::Smi());
     ClearGVNFlag(kChangesNewSpacePromotion);
   }
@@ -1769,7 +1793,9 @@ Range* HChange::InferRange(Zone* zone) {
       ? input_range->Copy(zone)
       : HValue::InferRange(zone);
   result->set_can_be_minus_zero(!to().IsSmiOrInteger32() ||
-                                !CheckFlag(kAllUsesTruncatingToInt32));
+                                !(CheckFlag(kAllUsesTruncatingToInt32) ||
+                                  CheckFlag(kAllUsesTruncatingToSmi)));
+  if (to().IsSmi()) result->ClampToSmi();
   return result;
 }
 
@@ -1806,15 +1832,18 @@ Range* HPhi::InferRange(Zone* zone) {
 
 
 Range* HAdd::InferRange(Zone* zone) {
-  if (representation().IsInteger32()) {
+  Representation r = representation();
+  if (r.IsSmiOrInteger32()) {
     Range* a = left()->range();
     Range* b = right()->range();
     Range* res = a->Copy(zone);
-    if (!res->AddAndCheckOverflow(b) ||
-        CheckFlag(kAllUsesTruncatingToInt32)) {
+    if (!res->AddAndCheckOverflow(r, b) ||
+        (r.IsInteger32() && CheckFlag(kAllUsesTruncatingToInt32)) ||
+        (r.IsSmi() && CheckFlag(kAllUsesTruncatingToSmi))) {
       ClearFlag(kCanOverflow);
     }
-    res->set_can_be_minus_zero(!CheckFlag(kAllUsesTruncatingToInt32) &&
+    res->set_can_be_minus_zero(!CheckFlag(kAllUsesTruncatingToSmi) &&
+                               !CheckFlag(kAllUsesTruncatingToInt32) &&
                                a->CanBeMinusZero() && b->CanBeMinusZero());
     return res;
   } else {
@@ -1824,15 +1853,18 @@ Range* HAdd::InferRange(Zone* zone) {
 
 
 Range* HSub::InferRange(Zone* zone) {
-  if (representation().IsInteger32()) {
+  Representation r = representation();
+  if (r.IsSmiOrInteger32()) {
     Range* a = left()->range();
     Range* b = right()->range();
     Range* res = a->Copy(zone);
-    if (!res->SubAndCheckOverflow(b) ||
-        CheckFlag(kAllUsesTruncatingToInt32)) {
+    if (!res->SubAndCheckOverflow(r, b) ||
+        (r.IsInteger32() && CheckFlag(kAllUsesTruncatingToInt32)) ||
+        (r.IsSmi() && CheckFlag(kAllUsesTruncatingToSmi))) {
       ClearFlag(kCanOverflow);
     }
-    res->set_can_be_minus_zero(!CheckFlag(kAllUsesTruncatingToInt32) &&
+    res->set_can_be_minus_zero(!CheckFlag(kAllUsesTruncatingToSmi) &&
+                               !CheckFlag(kAllUsesTruncatingToInt32) &&
                                a->CanBeMinusZero() && b->CanBeZero());
     return res;
   } else {
@@ -1842,17 +1874,19 @@ Range* HSub::InferRange(Zone* zone) {
 
 
 Range* HMul::InferRange(Zone* zone) {
-  if (representation().IsInteger32()) {
+  Representation r = representation();
+  if (r.IsSmiOrInteger32()) {
     Range* a = left()->range();
     Range* b = right()->range();
     Range* res = a->Copy(zone);
-    if (!res->MulAndCheckOverflow(b)) {
+    if (!res->MulAndCheckOverflow(r, b)) {
       // Clearing the kCanOverflow flag when kAllUsesAreTruncatingToInt32
       // would be wrong, because truncated integer multiplication is too
       // precise and therefore not the same as converting to Double and back.
       ClearFlag(kCanOverflow);
     }
-    res->set_can_be_minus_zero(!CheckFlag(kAllUsesTruncatingToInt32) &&
+    res->set_can_be_minus_zero(!CheckFlag(kAllUsesTruncatingToSmi) &&
+                               !CheckFlag(kAllUsesTruncatingToInt32) &&
                                ((a->CanBeZero() && b->CanBeNegative()) ||
                                 (a->CanBeNegative() && b->CanBeZero())));
     return res;
@@ -2415,7 +2449,7 @@ bool InductionVariableData::ComputeInductionVariableLimit(
 
 
 Range* HMathMinMax::InferRange(Zone* zone) {
-  if (representation().IsInteger32()) {
+  if (representation().IsSmiOrInteger32()) {
     Range* a = left()->range();
     Range* b = right()->range();
     Range* res = a->Copy(zone);
@@ -2500,6 +2534,7 @@ void HPhi::InitRealUses(int phi_id) {
   // Compute a conservative approximation of truncating uses before inferring
   // representations. The proper, exact computation will be done later, when
   // inserting representation changes.
+  SetFlag(kTruncatingToSmi);
   SetFlag(kTruncatingToInt32);
   for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
     HValue* value = it.value();
@@ -2510,8 +2545,13 @@ void HPhi::InitRealUses(int phi_id) {
         PrintF("#%d Phi is used by real #%d %s as %s\n",
                id(), value->id(), value->Mnemonic(), rep.Mnemonic());
       }
-      if (!value->IsSimulate() && !value->CheckFlag(kTruncatingToInt32)) {
-        ClearFlag(kTruncatingToInt32);
+      if (!value->IsSimulate()) {
+        if (!value->CheckFlag(kTruncatingToSmi)) {
+          ClearFlag(kTruncatingToSmi);
+        }
+        if (!value->CheckFlag(kTruncatingToInt32)) {
+          ClearFlag(kTruncatingToInt32);
+        }
       }
     }
   }
@@ -2698,7 +2738,7 @@ HConstant::HConstant(double double_value,
 
 void HConstant::Initialize(Representation r) {
   if (r.IsNone()) {
-    if (has_smi_value_) {
+    if (has_smi_value_ && kSmiValueSize == 31) {
       r = Representation::Smi();
     } else if (has_int32_value_) {
       r = Representation::Integer32();
@@ -2805,25 +2845,18 @@ void HBinaryOperation::InferRepresentation(HInferRepresentationPhase* h_infer) {
   ASSERT(CheckFlag(kFlexibleRepresentation));
   Representation new_rep = RepresentationFromInputs();
   UpdateRepresentation(new_rep, h_infer, "inputs");
-  // When the operation has information about its own output type, don't look
-  // at uses.
-  if (!observed_output_representation_.IsNone()) return;
-  new_rep = RepresentationFromUses();
-  UpdateRepresentation(new_rep, h_infer, "uses");
-  new_rep = RepresentationFromUseRequirements();
-  if (new_rep.fits_into(Representation::Integer32())) {
-    UpdateRepresentation(new_rep, h_infer, "use requirements");
+  if (observed_output_representation_.IsNone()) {
+    new_rep = RepresentationFromUses();
+    UpdateRepresentation(new_rep, h_infer, "uses");
+  } else {
+    new_rep = RepresentationFromOutput();
+    UpdateRepresentation(new_rep, h_infer, "output");
   }
-}
 
-
-bool HBinaryOperation::IgnoreObservedOutputRepresentation(
-    Representation current_rep) {
-  return observed_output_representation_.IsDouble() &&
-         current_rep.IsInteger32() &&
-         // Mul in Integer32 mode would be too precise.
-         !this->IsMul() &&
-         CheckUsesForFlag(kTruncatingToInt32);
+  if (representation().IsSmi() && HasNonSmiUse()) {
+    UpdateRepresentation(
+        Representation::Integer32(), h_infer, "use requirements");
+  }
 }
 
 
@@ -2832,28 +2865,38 @@ Representation HBinaryOperation::RepresentationFromInputs() {
   // the currently assumed output representation.
   Representation rep = representation();
   for (int i = 1; i <= 2; ++i) {
-    Representation input_rep = observed_input_representation(i);
-    if (input_rep.is_more_general_than(rep)) rep = input_rep;
+    rep = rep.generalize(observed_input_representation(i));
   }
   // If any of the actual input representation is more general than what we
   // have so far but not Tagged, use that representation instead.
   Representation left_rep = left()->representation();
   Representation right_rep = right()->representation();
+  if (!left_rep.IsTagged()) rep = rep.generalize(left_rep);
+  if (!right_rep.IsTagged()) rep = rep.generalize(right_rep);
 
-  if (left_rep.is_more_general_than(rep) && !left_rep.IsTagged()) {
-    rep = left_rep;
-  }
-  if (right_rep.is_more_general_than(rep) && !right_rep.IsTagged()) {
-    rep = right_rep;
-  }
+  return rep;
+}
+
+
+bool HBinaryOperation::IgnoreObservedOutputRepresentation(
+    Representation current_rep) {
+  return ((current_rep.IsInteger32() && CheckUsesForFlag(kTruncatingToInt32)) ||
+          (current_rep.IsSmi() && CheckUsesForFlag(kTruncatingToSmi))) &&
+         // Mul in Integer32 mode would be too precise.
+         !this->IsMul();
+}
+
+
+Representation HBinaryOperation::RepresentationFromOutput() {
+  Representation rep = representation();
   // Consider observed output representation, but ignore it if it's Double,
   // this instruction is not a division, and all its uses are truncating
   // to Integer32.
   if (observed_output_representation_.is_more_general_than(rep) &&
       !IgnoreObservedOutputRepresentation(rep)) {
-    rep = observed_output_representation_;
+    return observed_output_representation_;
   }
-  return rep;
+  return Representation::None();
 }
 
 
@@ -3790,29 +3833,28 @@ HType HFunctionLiteral::CalculateInferredType() {
 HValue* HUnaryMathOperation::EnsureAndPropagateNotMinusZero(
     BitVector* visited) {
   visited->Add(id());
-  if (representation().IsInteger32() &&
-      !value()->representation().IsInteger32()) {
+  if (representation().IsSmiOrInteger32() &&
+      !value()->representation().Equals(representation())) {
     if (value()->range() == NULL || value()->range()->CanBeMinusZero()) {
       SetFlag(kBailoutOnMinusZero);
     }
   }
-  if (RequiredInputRepresentation(0).IsInteger32() &&
-      representation().IsInteger32()) {
+  if (RequiredInputRepresentation(0).IsSmiOrInteger32() &&
+      representation().Equals(RequiredInputRepresentation(0))) {
     return value();
   }
   return NULL;
 }
 
 
-
 HValue* HChange::EnsureAndPropagateNotMinusZero(BitVector* visited) {
   visited->Add(id());
-  if (from().IsInteger32()) return NULL;
+  if (from().IsSmiOrInteger32()) return NULL;
   if (CanTruncateToInt32()) return NULL;
   if (value()->range() == NULL || value()->range()->CanBeMinusZero()) {
     SetFlag(kBailoutOnMinusZero);
   }
-  ASSERT(!from().IsInteger32() || !to().IsInteger32());
+  ASSERT(!from().IsSmiOrInteger32() || !to().IsSmiOrInteger32());
   return NULL;
 }
 
@@ -3899,7 +3941,7 @@ bool HStoreKeyed::NeedsCanonicalization() {
   }
 
   if (value()->IsChange()) {
-    if (HChange::cast(value())->from().IsInteger32()) {
+    if (HChange::cast(value())->from().IsSmiOrInteger32()) {
       return false;
     }
     if (HChange::cast(value())->value()->type().IsSmi()) {
@@ -3910,8 +3952,8 @@ bool HStoreKeyed::NeedsCanonicalization() {
 }
 
 
-#define H_CONSTANT_INT32(val)                                                  \
-new(zone) HConstant(static_cast<int32_t>(val), Representation::Integer32())
+#define H_CONSTANT_INT(val)                                                  \
+new(zone) HConstant(static_cast<int32_t>(val))
 #define H_CONSTANT_DOUBLE(val)                                                 \
 new(zone) HConstant(static_cast<double>(val), Representation::Double())
 
@@ -3924,7 +3966,7 @@ HInstruction* HInstr::New(                                                     \
     if ((c_left->HasNumberValue() && c_right->HasNumberValue())) {             \
       double double_res = c_left->DoubleValue() op c_right->DoubleValue();     \
       if (TypeInfo::IsInt32Double(double_res)) {                               \
-        return H_CONSTANT_INT32(double_res);                                   \
+        return H_CONSTANT_INT(double_res);                                   \
       }                                                                        \
       return H_CONSTANT_DOUBLE(double_res);                                    \
     }                                                                          \
@@ -4123,7 +4165,7 @@ HInstruction* HMod::New(Zone* zone,
         if ((res == 0) && (dividend < 0)) {
           return H_CONSTANT_DOUBLE(-0.0);
         }
-        return H_CONSTANT_INT32(res);
+        return H_CONSTANT_INT(res);
       }
     }
   }
@@ -4141,7 +4183,7 @@ HInstruction* HDiv::New(
       if (c_right->DoubleValue() != 0) {
         double double_res = c_left->DoubleValue() / c_right->DoubleValue();
         if (TypeInfo::IsInt32Double(double_res)) {
-          return H_CONSTANT_INT32(double_res);
+          return H_CONSTANT_INT(double_res);
         }
         return H_CONSTANT_DOUBLE(double_res);
       } else {
@@ -4178,7 +4220,7 @@ HInstruction* HBitwise::New(
           result = 0;  // Please the compiler.
           UNREACHABLE();
       }
-      return H_CONSTANT_INT32(result);
+      return H_CONSTANT_INT(result);
     }
   }
   return new(zone) HBitwise(op, context, left, right);
@@ -4192,7 +4234,7 @@ HInstruction* HInstr::New(                                                     \
     HConstant* c_left = HConstant::cast(left);                                 \
     HConstant* c_right = HConstant::cast(right);                               \
     if ((c_left->HasNumberValue() && c_right->HasNumberValue())) {             \
-      return H_CONSTANT_INT32(result);                                         \
+      return H_CONSTANT_INT(result);                                           \
     }                                                                          \
   }                                                                            \
   return new(zone) HInstr(context, left, right);                               \
@@ -4218,14 +4260,14 @@ HInstruction* HShr::New(
       if ((right_val == 0) && (left_val < 0)) {
         return H_CONSTANT_DOUBLE(static_cast<uint32_t>(left_val));
       }
-      return H_CONSTANT_INT32(static_cast<uint32_t>(left_val) >> right_val);
+      return H_CONSTANT_INT(static_cast<uint32_t>(left_val) >> right_val);
     }
   }
   return new(zone) HShr(context, left, right);
 }
 
 
-#undef H_CONSTANT_INT32
+#undef H_CONSTANT_INT
 #undef H_CONSTANT_DOUBLE
 
 
@@ -4250,8 +4292,7 @@ void HPhi::SimplifyConstantInputs() {
       continue;
     } else if (operand->HasDoubleValue()) {
       HConstant* integer_input =
-          new(graph->zone()) HConstant(DoubleToInt32(operand->DoubleValue()),
-                                       Representation::Integer32());
+          new(graph->zone()) HConstant(DoubleToInt32(operand->DoubleValue()));
       integer_input->InsertAfter(operand);
       SetOperandAt(i, integer_input);
     } else if (operand == graph->GetConstantTrue()) {
@@ -4266,7 +4307,7 @@ void HPhi::SimplifyConstantInputs() {
     HValue* use = it.value();
     if (use->IsBinaryOperation()) {
       HBinaryOperation::cast(use)->set_observed_input_representation(
-          it.index(), Representation::Integer32());
+          it.index(), Representation::Smi());
     }
   }
 }
@@ -4315,6 +4356,17 @@ Representation HValue::RepresentationFromUseRequirements() {
 }
 
 
+bool HValue::HasNonSmiUse() {
+  for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
+    // We check for observed_input_representation elsewhere.
+    Representation use_rep =
+        it.value()->RequiredInputRepresentation(it.index());
+    if (!use_rep.IsNone() && !use_rep.IsSmi()) return true;
+  }
+  return false;
+}
+
+
 // Node-specific verification code is only included in debug mode.
 #ifdef DEBUG
 
index b43efc8..786ff87 100644 (file)
@@ -294,9 +294,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_;
@@ -805,6 +805,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
@@ -891,6 +893,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));
@@ -1166,6 +1169,7 @@ class HValue: public ZoneObject {
   }
   Representation RepresentationFromUses();
   Representation RepresentationFromUseRequirements();
+  bool HasNonSmiUse();
   virtual void UpdateRepresentation(Representation new_rep,
                                     HInferRepresentationPhase* h_infer,
                                     const char* reason);
@@ -1714,7 +1718,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());
@@ -1723,7 +1728,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 {
@@ -2624,6 +2630,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:
@@ -3525,7 +3532,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();
@@ -3687,7 +3694,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() {
@@ -3712,24 +3719,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:
@@ -4015,15 +4026,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 {
@@ -4036,10 +4041,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) {
@@ -4105,11 +4114,6 @@ class HArithmeticBinaryOperation: public HBinaryOperation {
   }
 
   virtual HType CalculateInferredType();
-  virtual Representation RequiredInputRepresentation(int index) {
-    return index == 0
-        ? Representation::Tagged()
-        : representation();
-  }
 
   DECLARE_ABSTRACT_INSTRUCTION(ArithmeticBinaryOperation)
 
@@ -4646,6 +4650,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:
@@ -4685,6 +4696,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:
@@ -4727,6 +4745,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:
@@ -4767,11 +4792,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; }
@@ -4826,6 +4851,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_;
@@ -4841,6 +4887,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:
@@ -4873,6 +4926,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:
@@ -4905,6 +4965,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:
@@ -4923,6 +4990,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:
index e962895..28ae6eb 100644 (file)
@@ -41,10 +41,10 @@ void HComputeMinusZeroChecksPhase::Run() {
         // int32-to-tagged and int32-to-double.
         Representation from = change->value()->representation();
         ASSERT(from.Equals(change->from()));
-        if (from.IsInteger32()) {
+        if (from.IsSmiOrInteger32()) {
           ASSERT(change->to().IsTagged() ||
                  change->to().IsDouble() ||
-                 change->to().IsSmi());
+                 change->to().IsSmiOrInteger32());
           ASSERT(visited_.IsEmpty());
           PropagateMinusZeroChecks(change->value());
           visited_.Clear();
index 45d35b2..63b7b4d 100644 (file)
@@ -45,13 +45,14 @@ void HRepresentationChangesPhase::InsertRepresentationChangeForUse(
   // information we treat constants like normal instructions and insert the
   // change instructions for them.
   HInstruction* new_value = NULL;
-  bool is_truncating = use_value->CheckFlag(HValue::kTruncatingToInt32);
+  bool is_truncating_to_smi = use_value->CheckFlag(HValue::kTruncatingToSmi);
+  bool is_truncating_to_int = use_value->CheckFlag(HValue::kTruncatingToInt32);
   bool allow_undefined_as_nan =
       use_value->CheckFlag(HValue::kAllowUndefinedAsNaN);
   if (value->IsConstant()) {
     HConstant* constant = HConstant::cast(value);
     // Try to create a new copy of the constant with the new representation.
-    if (is_truncating && to.IsInteger32()) {
+    if (is_truncating_to_int && to.IsInteger32()) {
       Maybe<HConstant*> res = constant->CopyToTruncatedInt32(graph()->zone());
       if (res.has_value) new_value = res.value;
     } else {
@@ -61,7 +62,8 @@ void HRepresentationChangesPhase::InsertRepresentationChangeForUse(
 
   if (new_value == NULL) {
     new_value = new(graph()->zone()) HChange(value, to,
-                                             is_truncating,
+                                             is_truncating_to_smi,
+                                             is_truncating_to_int,
                                              allow_undefined_as_nan);
   }
 
@@ -108,6 +110,8 @@ void HRepresentationChangesPhase::Run() {
     HPhi* phi = phi_list->at(i);
     if (phi->representation().IsInteger32()) {
       phi->SetFlag(HValue::kTruncatingToInt32);
+    } else if (phi->representation().IsSmi()) {
+      phi->SetFlag(HValue::kTruncatingToSmi);
     }
   }
 
@@ -119,13 +123,18 @@ void HRepresentationChangesPhase::Run() {
       HValue* use = it.value();
       Representation input_representation =
           use->RequiredInputRepresentation(it.index());
-      if (!input_representation.IsInteger32() ||
-          !use->CheckFlag(HValue::kTruncatingToInt32)) {
+      if ((phi->representation().IsInteger32() &&
+           !(input_representation.IsInteger32() &&
+             use->CheckFlag(HValue::kTruncatingToInt32))) ||
+          (phi->representation().IsSmi() &&
+           !(input_representation.IsSmi() ||
+             use->CheckFlag(HValue::kTruncatingToSmi)))) {
         if (FLAG_trace_representation) {
           PrintF("#%d Phi is not truncating because of #%d %s\n",
                  phi->id(), it.value()->id(), it.value()->Mnemonic());
         }
         phi->ClearFlag(HValue::kTruncatingToInt32);
+        phi->ClearFlag(HValue::kTruncatingToSmi);
         worklist.Add(phi, zone());
         break;
       }
@@ -137,13 +146,16 @@ void HRepresentationChangesPhase::Run() {
     for (int i = 0; i < current->OperandCount(); ++i) {
       HValue* input = current->OperandAt(i);
       if (input->IsPhi() &&
-          input->representation().IsInteger32() &&
-          input->CheckFlag(HValue::kTruncatingToInt32)) {
+          ((input->representation().IsInteger32() &&
+            input->CheckFlag(HValue::kTruncatingToInt32)) ||
+           (input->representation().IsSmi() &&
+            input->CheckFlag(HValue::kTruncatingToSmi)))) {
         if (FLAG_trace_representation) {
           PrintF("#%d Phi is not truncating because of #%d %s\n",
                  input->id(), current->id(), current->Mnemonic());
         }
         input->ClearFlag(HValue::kTruncatingToInt32);
+        input->ClearFlag(HValue::kTruncatingToSmi);
         worklist.Add(HPhi::cast(input), zone());
       }
     }
index 0aae861..853c0c0 100644 (file)
@@ -1871,11 +1871,8 @@ HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize(
     base_size += AllocationMemento::kSize;
   }
 
-  if (IsFastDoubleElementsKind(kind_)) {
-    base_size += FixedDoubleArray::kHeaderSize;
-  } else {
-    base_size += FixedArray::kHeaderSize;
-  }
+  STATIC_ASSERT(FixedDoubleArray::kHeaderSize == FixedArray::kHeaderSize);
+  base_size += FixedArray::kHeaderSize;
 
   HInstruction* elements_size_value =
       builder()->Add<HConstant>(elements_size());
@@ -3790,7 +3787,6 @@ void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
                                         environment()->LookupContext(),
                                         current_index,
                                         graph()->GetConstant1());
-    new_index->AssumeRepresentation(Representation::Integer32());
     PushAndAdd(new_index);
     body_exit = current_block();
   }
index 69ea696..d022a82 100644 (file)
@@ -656,9 +656,18 @@ XMMRegister LCodeGen::ToDoubleRegister(LOperand* op) const {
 }
 
 
-int LCodeGen::ToInteger32(LConstantOperand* op) const {
+int32_t LCodeGen::ToInteger32(LConstantOperand* op) const {
+  return ToRepresentation(op, Representation::Integer32());
+}
+
+
+int32_t LCodeGen::ToRepresentation(LConstantOperand* op,
+                                   const Representation& r) const {
   HConstant* constant = chunk_->LookupConstant(op);
-  return constant->Integer32Value();
+  int32_t value = constant->Integer32Value();
+  if (r.IsInteger32()) return value;
+  ASSERT(r.IsSmiOrTagged());
+  return reinterpret_cast<int32_t>(Smi::FromInt(value));
 }
 
 
@@ -1619,6 +1628,9 @@ void LCodeGen::DoMulI(LMulI* instr) {
       __ imul(left, left, constant);
     }
   } else {
+    if (instr->hydrogen()->representation().IsSmi()) {
+      __ SmiUntag(left);
+    }
     __ imul(left, ToOperand(right));
   }
 
@@ -1655,7 +1667,8 @@ void LCodeGen::DoBitI(LBitI* instr) {
   ASSERT(left->IsRegister());
 
   if (right->IsConstantOperand()) {
-    int right_operand = ToInteger32(LConstantOperand::cast(right));
+    int right_operand = ToRepresentation(LConstantOperand::cast(right),
+                                         instr->hydrogen()->representation());
     switch (instr->op()) {
       case Token::BIT_AND:
         __ and_(ToRegister(left), right_operand);
@@ -1766,7 +1779,8 @@ void LCodeGen::DoSubI(LSubI* instr) {
   ASSERT(left->Equals(instr->result()));
 
   if (right->IsConstantOperand()) {
-    __ sub(ToOperand(left), ToInteger32Immediate(right));
+    __ sub(ToOperand(left),
+           ToImmediate(right, instr->hydrogen()->representation()));
   } else {
     __ sub(ToRegister(left), ToOperand(right));
   }
@@ -1975,7 +1989,8 @@ void LCodeGen::DoAddI(LAddI* instr) {
 
   if (LAddI::UseLea(instr->hydrogen()) && !left->Equals(instr->result())) {
     if (right->IsConstantOperand()) {
-      int32_t offset = ToInteger32(LConstantOperand::cast(right));
+      int32_t offset = ToRepresentation(LConstantOperand::cast(right),
+                                        instr->hydrogen()->representation());
       __ lea(ToRegister(instr->result()), MemOperand(ToRegister(left), offset));
     } else {
       Operand address(ToRegister(left), ToRegister(right), times_1, 0);
@@ -1983,7 +1998,8 @@ void LCodeGen::DoAddI(LAddI* instr) {
     }
   } else {
     if (right->IsConstantOperand()) {
-      __ add(ToOperand(left), ToInteger32Immediate(right));
+      __ add(ToOperand(left),
+             ToImmediate(right, instr->hydrogen()->representation()));
     } else {
       __ add(ToRegister(left), ToOperand(right));
     }
@@ -2000,17 +2016,18 @@ void LCodeGen::DoMathMinMax(LMathMinMax* instr) {
   LOperand* right = instr->right();
   ASSERT(left->Equals(instr->result()));
   HMathMinMax::Operation operation = instr->hydrogen()->operation();
-  if (instr->hydrogen()->representation().IsInteger32()) {
+  if (instr->hydrogen()->representation().IsSmiOrInteger32()) {
     Label return_left;
     Condition condition = (operation == HMathMinMax::kMathMin)
         ? less_equal
         : greater_equal;
     if (right->IsConstantOperand()) {
       Operand left_op = ToOperand(left);
-      Immediate right_imm = ToInteger32Immediate(right);
-      __ cmp(left_op, right_imm);
+      Immediate immediate = ToImmediate(LConstantOperand::cast(instr->right()),
+                                        instr->hydrogen()->representation());
+      __ cmp(left_op, immediate);
       __ j(condition, &return_left, Label::kNear);
-      __ mov(left_op, right_imm);
+      __ mov(left_op, immediate);
     } else {
       Register left_reg = ToRegister(left);
       Operand right_op = ToOperand(right);
@@ -2378,19 +2395,11 @@ void LCodeGen::DoCompareNumericAndBranch(LCompareNumericAndBranch* instr) {
       __ j(parity_even, instr->FalseLabel(chunk_));
     } else {
       if (right->IsConstantOperand()) {
-        int32_t const_value = ToInteger32(LConstantOperand::cast(right));
-        if (instr->hydrogen_value()->representation().IsSmi()) {
-          __ cmp(ToOperand(left), Immediate(Smi::FromInt(const_value)));
-        } else {
-          __ cmp(ToOperand(left), Immediate(const_value));
-        }
+        __ cmp(ToOperand(left),
+               ToImmediate(right, instr->hydrogen()->representation()));
       } else if (left->IsConstantOperand()) {
-        int32_t const_value = ToInteger32(LConstantOperand::cast(left));
-        if (instr->hydrogen_value()->representation().IsSmi()) {
-          __ cmp(ToOperand(right), Immediate(Smi::FromInt(const_value)));
-        } else {
-          __ cmp(ToOperand(right), Immediate(const_value));
-        }
+        __ cmp(ToOperand(right),
+               ToImmediate(left, instr->hydrogen()->representation()));
         // We transposed the operands. Reverse the condition.
         cc = ReverseCondition(cc);
       } else {
@@ -4441,14 +4450,10 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
   if (instr->hydrogen()->skip_check() && !FLAG_debug_code) return;
 
   if (instr->index()->IsConstantOperand()) {
-    int constant_index =
-        ToInteger32(LConstantOperand::cast(instr->index()));
-    if (instr->hydrogen()->length()->representation().IsSmi()) {
-      __ cmp(ToOperand(instr->length()),
-             Immediate(Smi::FromInt(constant_index)));
-    } else {
-      __ cmp(ToOperand(instr->length()), Immediate(constant_index));
-    }
+    Immediate immediate =
+        ToImmediate(LConstantOperand::cast(instr->index()),
+                    instr->hydrogen()->length()->representation());
+    __ cmp(ToOperand(instr->length()), immediate);
     Condition condition =
         instr->hydrogen()->allow_equality() ? below : below_equal;
     ApplyCheckIf(condition, instr);
@@ -4616,10 +4621,11 @@ void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
     __ mov(operand, ToRegister(instr->value()));
   } else {
     LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
-    if (IsInteger32(operand_value)) {
-      Smi* smi_value = Smi::FromInt(ToInteger32(operand_value));
-      __ mov(operand, Immediate(smi_value));
+    if (IsSmi(operand_value)) {
+      Immediate immediate = ToImmediate(operand_value, Representation::Smi());
+      __ mov(operand, immediate);
     } else {
+      ASSERT(!IsInteger32(operand_value));
       Handle<Object> handle_value = ToHandle(operand_value);
       __ mov(operand, handle_value);
     }
@@ -4782,8 +4788,9 @@ void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) {
   // DoStringCharCodeAt above.
   STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
   if (instr->index()->IsConstantOperand()) {
-    int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
-    __ push(Immediate(Smi::FromInt(const_index)));
+    Immediate immediate = ToImmediate(LConstantOperand::cast(instr->index()),
+                                      Representation::Smi());
+    __ push(immediate);
   } else {
     Register index = ToRegister(instr->index());
     __ SmiTag(index);
index 83911ce..6574532 100644 (file)
@@ -109,11 +109,8 @@ class LCodeGen BASE_EMBEDDED {
 
   bool IsInteger32(LConstantOperand* op) const;
   bool IsSmi(LConstantOperand* op) const;
-  Immediate ToInteger32Immediate(LOperand* op) const {
-    return Immediate(ToInteger32(LConstantOperand::cast(op)));
-  }
-  Immediate ToSmiImmediate(LOperand* op) const {
-    return Immediate(Smi::FromInt(ToInteger32(LConstantOperand::cast(op))));
+  Immediate ToImmediate(LOperand* op, const Representation& r) const {
+    return Immediate(ToRepresentation(LConstantOperand::cast(op), r));
   }
   double ToDouble(LConstantOperand* op) const;
 
@@ -298,7 +295,8 @@ class LCodeGen BASE_EMBEDDED {
   Register ToRegister(int index) const;
   XMMRegister ToDoubleRegister(int index) const;
   X87Register ToX87Register(int index) const;
-  int ToInteger32(LConstantOperand* op) const;
+  int ToRepresentation(LConstantOperand* op, const Representation& r) const;
+  int32_t ToInteger32(LConstantOperand* op) const;
 
   Operand BuildFastArrayOperand(LOperand* elements_pointer,
                                 LOperand* key,
index e884a9d..b5bc18b 100644 (file)
@@ -306,10 +306,10 @@ void LGapResolver::EmitMove(int index) {
     LConstantOperand* constant_source = LConstantOperand::cast(source);
     if (destination->IsRegister()) {
       Register dst = cgen_->ToRegister(destination);
-      if (cgen_->IsSmi(constant_source)) {
-        __ Set(dst, cgen_->ToSmiImmediate(constant_source));
-      } else if (cgen_->IsInteger32(constant_source)) {
-        __ Set(dst, cgen_->ToInteger32Immediate(constant_source));
+      Representation r = cgen_->IsSmi(constant_source)
+          ? Representation::Smi() : Representation::Integer32();
+      if (cgen_->IsInteger32(constant_source)) {
+        __ Set(dst, cgen_->ToImmediate(constant_source, r));
       } else {
         __ LoadObject(dst, cgen_->ToHandle(constant_source));
       }
@@ -339,10 +339,10 @@ void LGapResolver::EmitMove(int index) {
     } else {
       ASSERT(destination->IsStackSlot());
       Operand dst = cgen_->ToOperand(destination);
-      if (cgen_->IsSmi(constant_source)) {
-        __ Set(dst, cgen_->ToSmiImmediate(constant_source));
-      } else if (cgen_->IsInteger32(constant_source)) {
-        __ Set(dst, cgen_->ToInteger32Immediate(constant_source));
+      Representation r = cgen_->IsSmi(constant_source)
+          ? Representation::Smi() : Representation::Integer32();
+      if (cgen_->IsInteger32(constant_source)) {
+        __ Set(dst, cgen_->ToImmediate(constant_source, r));
       } else {
         Register tmp = EnsureTempRegister();
         __ LoadObject(tmp, cgen_->ToHandle(constant_source));
index aec96e0..f03cd72 100644 (file)
@@ -832,8 +832,8 @@ LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op,
          op == Token::SUB);
   HValue* left = instr->left();
   HValue* right = instr->right();
-  ASSERT(left->representation().IsSmiOrTagged());
-  ASSERT(right->representation().IsSmiOrTagged());
+  ASSERT(left->representation().IsTagged());
+  ASSERT(right->representation().IsTagged());
   LOperand* context = UseFixed(instr->context(), esi);
   LOperand* left_operand = UseFixed(left, edx);
   LOperand* right_operand = UseFixed(right, eax);
@@ -1399,9 +1399,10 @@ LInstruction* LChunkBuilder::DoShl(HShl* instr) {
 
 
 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) {
-  if (instr->representation().IsInteger32()) {
-    ASSERT(instr->left()->representation().IsInteger32());
-    ASSERT(instr->right()->representation().IsInteger32());
+  if (instr->representation().IsSmiOrInteger32()) {
+    ASSERT(instr->left()->representation().IsSmiOrInteger32());
+    ASSERT(instr->right()->representation().Equals(
+        instr->left()->representation()));
 
     LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
     LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand());
@@ -1434,7 +1435,9 @@ LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) {
 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
   if (instr->representation().IsDouble()) {
     return DoArithmeticD(Token::DIV, instr);
-  } else if (instr->representation().IsInteger32()) {
+  } else if (instr->representation().IsSmiOrInteger32()) {
+    ASSERT(instr->left()->representation().Equals(instr->representation()));
+    ASSERT(instr->right()->representation().Equals(instr->representation()));
     if (instr->HasPowerOf2Divisor()) {
       ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero));
       LOperand* value = UseRegisterAtStart(instr->left());
@@ -1450,7 +1453,7 @@ LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
     LDivI* result = new(zone()) LDivI(dividend, divisor, temp);
     return AssignEnvironment(DefineFixed(result, eax));
   } else {
-    ASSERT(instr->representation().IsSmiOrTagged());
+    ASSERT(instr->representation().IsTagged());
     return DoArithmeticT(Token::DIV, instr);
   }
 }
@@ -1516,9 +1519,10 @@ LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
 LInstruction* LChunkBuilder::DoMod(HMod* instr) {
   HValue* left = instr->left();
   HValue* right = instr->right();
-  if (instr->representation().IsInteger32()) {
-    ASSERT(left->representation().IsInteger32());
-    ASSERT(right->representation().IsInteger32());
+  if (instr->representation().IsSmiOrInteger32()) {
+    ASSERT(left->representation().IsSmiOrInteger32());
+    ASSERT(right->representation().Equals(left->representation()));
+
     if (instr->HasPowerOf2Divisor()) {
       ASSERT(!right->CanBeZero());
       LModI* mod = new(zone()) LModI(UseRegisterAtStart(left),
@@ -1567,9 +1571,9 @@ LInstruction* LChunkBuilder::DoMod(HMod* instr) {
 
 
 LInstruction* LChunkBuilder::DoMul(HMul* instr) {
-  if (instr->representation().IsInteger32()) {
-    ASSERT(instr->left()->representation().IsInteger32());
-    ASSERT(instr->right()->representation().IsInteger32());
+  if (instr->representation().IsSmiOrInteger32()) {
+    ASSERT(instr->left()->representation().Equals(instr->representation()));
+    ASSERT(instr->right()->representation().Equals(instr->representation()));
     LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
     LOperand* right = UseOrConstant(instr->BetterRightOperand());
     LOperand* temp = NULL;
@@ -1585,16 +1589,17 @@ LInstruction* LChunkBuilder::DoMul(HMul* instr) {
   } else if (instr->representation().IsDouble()) {
     return DoArithmeticD(Token::MUL, instr);
   } else {
-    ASSERT(instr->representation().IsSmiOrTagged());
+    ASSERT(instr->representation().IsTagged());
     return DoArithmeticT(Token::MUL, instr);
   }
 }
 
 
 LInstruction* LChunkBuilder::DoSub(HSub* instr) {
-  if (instr->representation().IsInteger32()) {
-    ASSERT(instr->left()->representation().IsInteger32());
-    ASSERT(instr->right()->representation().IsInteger32());
+  if (instr->representation().IsSmiOrInteger32()) {
+    ASSERT(instr->left()->representation().IsSmiOrInteger32());
+    ASSERT(instr->right()->representation().Equals(
+        instr->left()->representation()));
     LOperand* left = UseRegisterAtStart(instr->left());
     LOperand* right = UseOrConstantAtStart(instr->right());
     LSubI* sub = new(zone()) LSubI(left, right);
@@ -1613,14 +1618,15 @@ LInstruction* LChunkBuilder::DoSub(HSub* instr) {
 
 
 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
-  if (instr->representation().IsInteger32()) {
+  if (instr->representation().IsSmiOrInteger32()) {
+    ASSERT(instr->left()->representation().IsSmiOrInteger32());
+    ASSERT(instr->right()->representation().Equals(
+        instr->left()->representation()));
     // Check to see if it would be advantageous to use an lea instruction rather
     // than an add. This is the case when no overflow check is needed and there
     // are multiple uses of the add's inputs, so using a 3-register add will
     // preserve all input values for later uses.
     bool use_lea = LAddI::UseLea(instr);
-    ASSERT(instr->left()->representation().IsInteger32());
-    ASSERT(instr->right()->representation().IsInteger32());
     LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
     HValue* right_candidate = instr->BetterRightOperand();
     LOperand* right = use_lea
@@ -1647,9 +1653,10 @@ LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) {
   LOperand* left = NULL;
   LOperand* right = NULL;
-  if (instr->representation().IsInteger32()) {
-    ASSERT(instr->left()->representation().IsInteger32());
-    ASSERT(instr->right()->representation().IsInteger32());
+  if (instr->representation().IsSmiOrInteger32()) {
+    ASSERT(instr->left()->representation().IsSmiOrInteger32());
+    ASSERT(instr->right()->representation().Equals(
+        instr->left()->representation()));
     left = UseRegisterAtStart(instr->BetterLeftOperand());
     right = UseOrConstantAtStart(instr->BetterRightOperand());
   } else {
@@ -2253,8 +2260,7 @@ LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
 
 
 LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
-  ASSERT(instr->key()->representation().IsInteger32() ||
-         instr->key()->representation().IsSmi());
+  ASSERT(instr->key()->representation().IsSmiOrInteger32());
   ElementsKind elements_kind = instr->elements_kind();
   bool clobbers_key = ExternalArrayOpRequiresTemp(
       instr->key()->representation(), elements_kind);
index b905a74..769df07 100644 (file)
@@ -709,8 +709,7 @@ void TypeFeedbackOracle::SetInfo(TypeFeedbackId ast_id, Object* target) {
 
 Representation Representation::FromType(TypeInfo info) {
   if (info.IsUninitialized()) return Representation::None();
-  // TODO(verwaest): Return Smi rather than Integer32.
-  if (info.IsSmi()) return Representation::Integer32();
+  if (info.IsSmi()) return Representation::Smi();
   if (info.IsInteger32()) return Representation::Integer32();
   if (info.IsDouble()) return Representation::Double();
   if (info.IsNumber()) return Representation::Double();
index bea140e..70ddccd 100644 (file)
@@ -483,6 +483,7 @@ Type* Type::Optional(Handle<Type> type) {
 
 Representation Representation::FromType(Handle<Type> type) {
   if (type->Is(Type::None())) return Representation::None();
+  if (type->Is(Type::Smi())) return Representation::Smi();
   if (type->Is(Type::Signed32())) return Representation::Integer32();
   if (type->Is(Type::Number())) return Representation::Double();
   return Representation::Tagged();
index 2806b85..2378f2b 100644 (file)
@@ -410,7 +410,7 @@ bool LCodeGen::IsTaggedConstant(LConstantOperand* op) const {
 }
 
 
-int LCodeGen::ToInteger32(LConstantOperand* op) const {
+int32_t LCodeGen::ToInteger32(LConstantOperand* op) const {
   HConstant* constant = chunk_->LookupConstant(op);
   return constant->Integer32Value();
 }
@@ -1299,9 +1299,19 @@ void LCodeGen::DoMulI(LMulI* instr) {
       __ imull(left, left, Immediate(right_value));
     }
   } else if (right->IsStackSlot()) {
-    __ imull(left, ToOperand(right));
+    if (instr->hydrogen_value()->representation().IsSmi()) {
+      __ SmiToInteger32(left, left);
+      __ imul(left, ToOperand(right));
+    } else {
+      __ imull(left, ToOperand(right));
+    }
   } else {
-    __ imull(left, ToRegister(right));
+    if (instr->hydrogen_value()->representation().IsSmi()) {
+      __ SmiToInteger32(left, left);
+      __ imul(left, ToRegister(right));
+    } else {
+      __ imull(left, ToRegister(right));
+    }
   }
 
   if (can_overflow) {
@@ -1358,13 +1368,13 @@ void LCodeGen::DoBitI(LBitI* instr) {
   } else if (right->IsStackSlot()) {
     switch (instr->op()) {
       case Token::BIT_AND:
-        __ andl(ToRegister(left), ToOperand(right));
+        __ and_(ToRegister(left), ToOperand(right));
         break;
       case Token::BIT_OR:
-        __ orl(ToRegister(left), ToOperand(right));
+        __ or_(ToRegister(left), ToOperand(right));
         break;
       case Token::BIT_XOR:
-        __ xorl(ToRegister(left), ToOperand(right));
+        __ xor_(ToRegister(left), ToOperand(right));
         break;
       default:
         UNREACHABLE();
@@ -1374,13 +1384,13 @@ void LCodeGen::DoBitI(LBitI* instr) {
     ASSERT(right->IsRegister());
     switch (instr->op()) {
       case Token::BIT_AND:
-        __ andl(ToRegister(left), ToRegister(right));
+        __ and_(ToRegister(left), ToRegister(right));
         break;
       case Token::BIT_OR:
-        __ orl(ToRegister(left), ToRegister(right));
+        __ or_(ToRegister(left), ToRegister(right));
         break;
       case Token::BIT_XOR:
-        __ xorl(ToRegister(left), ToRegister(right));
+        __ xor_(ToRegister(left), ToRegister(right));
         break;
       default:
         UNREACHABLE();
@@ -1463,9 +1473,17 @@ void LCodeGen::DoSubI(LSubI* instr) {
     __ subl(ToRegister(left),
             Immediate(ToInteger32(LConstantOperand::cast(right))));
   } else if (right->IsRegister()) {
-    __ subl(ToRegister(left), ToRegister(right));
+    if (instr->hydrogen_value()->representation().IsSmi()) {
+      __ subq(ToRegister(left), ToRegister(right));
+    } else {
+      __ subl(ToRegister(left), ToRegister(right));
+    }
   } else {
-    __ subl(ToRegister(left), ToOperand(right));
+    if (instr->hydrogen_value()->representation().IsSmi()) {
+      __ subq(ToRegister(left), ToOperand(right));
+    } else {
+      __ subl(ToRegister(left), ToOperand(right));
+    }
   }
 
   if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
@@ -1646,16 +1664,28 @@ void LCodeGen::DoAddI(LAddI* instr) {
               MemOperand(ToRegister(left), offset));
     } else {
       Operand address(ToRegister(left), ToRegister(right), times_1, 0);
-      __ leal(ToRegister(instr->result()), address);
+      if (instr->hydrogen()->representation().IsSmi()) {
+        __ lea(ToRegister(instr->result()), address);
+      } else {
+        __ leal(ToRegister(instr->result()), address);
+      }
     }
   } else {
     if (right->IsConstantOperand()) {
       __ addl(ToRegister(left),
               Immediate(ToInteger32(LConstantOperand::cast(right))));
     } else if (right->IsRegister()) {
-      __ addl(ToRegister(left), ToRegister(right));
+      if (instr->hydrogen_value()->representation().IsSmi()) {
+        __ addq(ToRegister(left), ToRegister(right));
+      } else {
+        __ addl(ToRegister(left), ToRegister(right));
+      }
     } else {
-      __ addl(ToRegister(left), ToOperand(right));
+      if (instr->hydrogen_value()->representation().IsSmi()) {
+        __ addq(ToRegister(left), ToOperand(right));
+      } else {
+        __ addl(ToRegister(left), ToOperand(right));
+      }
     }
     if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
       DeoptimizeIf(overflow, instr->environment());
index ca195ba..5ad1c40 100644 (file)
@@ -102,7 +102,8 @@ class LCodeGen BASE_EMBEDDED {
   XMMRegister ToDoubleRegister(LOperand* op) const;
   bool IsInteger32Constant(LConstantOperand* op) const;
   bool IsSmiConstant(LConstantOperand* op) const;
-  int ToInteger32(LConstantOperand* op) const;
+  int ToRepresentation(LConstantOperand* op, const Representation& r) const;
+  int32_t ToInteger32(LConstantOperand* op) const;
   Smi* ToSmi(LConstantOperand* op) const;
   double ToDouble(LConstantOperand* op) const;
   bool IsTaggedConstant(LConstantOperand* op) const;
index 1f1098e..c1d81c0 100644 (file)
@@ -787,8 +787,8 @@ LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op,
          op == Token::SUB);
   HValue* left = instr->left();
   HValue* right = instr->right();
-  ASSERT(left->representation().IsSmiOrTagged());
-  ASSERT(right->representation().IsSmiOrTagged());
+  ASSERT(left->representation().IsTagged());
+  ASSERT(right->representation().IsTagged());
   LOperand* left_operand = UseFixed(left, rdx);
   LOperand* right_operand = UseFixed(right, rax);
   LArithmeticT* result =
@@ -1319,17 +1319,17 @@ LInstruction* LChunkBuilder::DoShl(HShl* instr) {
 
 
 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) {
-  if (instr->representation().IsInteger32()) {
-    ASSERT(instr->left()->representation().IsInteger32());
-    ASSERT(instr->right()->representation().IsInteger32());
+  if (instr->representation().IsSmiOrInteger32()) {
+    ASSERT(instr->left()->representation().Equals(instr->representation()));
+    ASSERT(instr->right()->representation().Equals(instr->representation()));
 
     LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
     LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand());
     return DefineSameAsFirst(new(zone()) LBitI(left, right));
   } else {
-    ASSERT(instr->representation().IsSmiOrTagged());
-    ASSERT(instr->left()->representation().IsSmiOrTagged());
-    ASSERT(instr->right()->representation().IsSmiOrTagged());
+    ASSERT(instr->representation().IsTagged());
+    ASSERT(instr->left()->representation().IsTagged());
+    ASSERT(instr->right()->representation().IsTagged());
 
     LOperand* left = UseFixed(instr->left(), rdx);
     LOperand* right = UseFixed(instr->right(), rax);
@@ -1352,7 +1352,9 @@ LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) {
 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
   if (instr->representation().IsDouble()) {
     return DoArithmeticD(Token::DIV, instr);
-  } else if (instr->representation().IsInteger32()) {
+  } else if (instr->representation().IsSmiOrInteger32()) {
+    ASSERT(instr->left()->representation().Equals(instr->representation()));
+    ASSERT(instr->right()->representation().Equals(instr->representation()));
     if (instr->HasPowerOf2Divisor()) {
       ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero));
       LOperand* value = UseRegisterAtStart(instr->left());
@@ -1368,7 +1370,7 @@ LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
     LDivI* result = new(zone()) LDivI(dividend, divisor, temp);
     return AssignEnvironment(DefineFixed(result, rax));
   } else {
-    ASSERT(instr->representation().IsSmiOrTagged());
+    ASSERT(instr->representation().IsTagged());
     return DoArithmeticT(Token::DIV, instr);
   }
 }
@@ -1432,9 +1434,9 @@ LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
 LInstruction* LChunkBuilder::DoMod(HMod* instr) {
   HValue* left = instr->left();
   HValue* right = instr->right();
-  if (instr->representation().IsInteger32()) {
-    ASSERT(left->representation().IsInteger32());
-    ASSERT(right->representation().IsInteger32());
+  if (instr->representation().IsSmiOrInteger32()) {
+    ASSERT(left->representation().Equals(instr->representation()));
+    ASSERT(right->representation().Equals(instr->representation()));
     if (instr->HasPowerOf2Divisor()) {
       ASSERT(!right->CanBeZero());
       LModI* mod = new(zone()) LModI(UseRegisterAtStart(left),
@@ -1467,7 +1469,7 @@ LInstruction* LChunkBuilder::DoMod(HMod* instr) {
           ? AssignEnvironment(result)
           : result;
     }
-  } else if (instr->representation().IsSmiOrTagged()) {
+  } else if (instr->representation().IsTagged()) {
     return DoArithmeticT(Token::MOD, instr);
   } else {
     ASSERT(instr->representation().IsDouble());
@@ -1483,9 +1485,9 @@ LInstruction* LChunkBuilder::DoMod(HMod* instr) {
 
 
 LInstruction* LChunkBuilder::DoMul(HMul* instr) {
-  if (instr->representation().IsInteger32()) {
-    ASSERT(instr->left()->representation().IsInteger32());
-    ASSERT(instr->right()->representation().IsInteger32());
+  if (instr->representation().IsSmiOrInteger32()) {
+    ASSERT(instr->left()->representation().Equals(instr->representation()));
+    ASSERT(instr->right()->representation().Equals(instr->representation()));
     LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
     LOperand* right = UseOrConstant(instr->BetterRightOperand());
     LMulI* mul = new(zone()) LMulI(left, right);
@@ -1497,16 +1499,16 @@ LInstruction* LChunkBuilder::DoMul(HMul* instr) {
   } else if (instr->representation().IsDouble()) {
     return DoArithmeticD(Token::MUL, instr);
   } else {
-    ASSERT(instr->representation().IsSmiOrTagged());
+    ASSERT(instr->representation().IsTagged());
     return DoArithmeticT(Token::MUL, instr);
   }
 }
 
 
 LInstruction* LChunkBuilder::DoSub(HSub* instr) {
-  if (instr->representation().IsInteger32()) {
-    ASSERT(instr->left()->representation().IsInteger32());
-    ASSERT(instr->right()->representation().IsInteger32());
+  if (instr->representation().IsSmiOrInteger32()) {
+    ASSERT(instr->left()->representation().Equals(instr->representation()));
+    ASSERT(instr->right()->representation().Equals(instr->representation()));
     LOperand* left = UseRegisterAtStart(instr->left());
     LOperand* right = UseOrConstantAtStart(instr->right());
     LSubI* sub = new(zone()) LSubI(left, right);
@@ -1518,21 +1520,21 @@ LInstruction* LChunkBuilder::DoSub(HSub* instr) {
   } else if (instr->representation().IsDouble()) {
     return DoArithmeticD(Token::SUB, instr);
   } else {
-    ASSERT(instr->representation().IsSmiOrTagged());
+    ASSERT(instr->representation().IsTagged());
     return DoArithmeticT(Token::SUB, instr);
   }
 }
 
 
 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
-  if (instr->representation().IsInteger32()) {
+  if (instr->representation().IsSmiOrInteger32()) {
     // Check to see if it would be advantageous to use an lea instruction rather
     // than an add. This is the case when no overflow check is needed and there
     // are multiple uses of the add's inputs, so using a 3-register add will
     // preserve all input values for later uses.
     bool use_lea = LAddI::UseLea(instr);
-    ASSERT(instr->left()->representation().IsInteger32());
-    ASSERT(instr->right()->representation().IsInteger32());
+    ASSERT(instr->left()->representation().Equals(instr->representation()));
+    ASSERT(instr->right()->representation().Equals(instr->representation()));
     LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
     HValue* right_candidate = instr->BetterRightOperand();
     LOperand* right = use_lea
@@ -1550,7 +1552,7 @@ LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
   } else if (instr->representation().IsDouble()) {
     return DoArithmeticD(Token::ADD, instr);
   } else {
-    ASSERT(instr->representation().IsSmiOrTagged());
+    ASSERT(instr->representation().IsTagged());
     return DoArithmeticT(Token::ADD, instr);
   }
   return NULL;