| Index: dart/runtime/vm/intermediate_language.cc
 | 
| ===================================================================
 | 
| --- dart/runtime/vm/intermediate_language.cc	(revision 31530)
 | 
| +++ dart/runtime/vm/intermediate_language.cc	(working copy)
 | 
| @@ -1455,6 +1455,31 @@
 | 
|  }
 | 
|  
 | 
|  
 | 
| +LocationSummary* DebugStepCheckInstr::MakeLocationSummary(bool opt) const {
 | 
| +  const intptr_t kNumInputs = 0;
 | 
| +  const intptr_t kNumTemps = 0;
 | 
| +  LocationSummary* locs =
 | 
| +      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
 | 
| +  return locs;
 | 
| +}
 | 
| +
 | 
| +
 | 
| +void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
 | 
| +  ASSERT(!compiler->is_optimizing());
 | 
| +  const ExternalLabel label("debug_step_check",
 | 
| +                            StubCode::DebugStepCheckEntryPoint());
 | 
| +  compiler->GenerateCall(token_pos(),
 | 
| +                         &label,
 | 
| +                         PcDescriptors::kReturn,
 | 
| +                         locs());
 | 
| +}
 | 
| +
 | 
| +
 | 
| +Instruction* DebugStepCheckInstr::Canonicalize(FlowGraph* flow_graph) {
 | 
| +  return NULL;
 | 
| +}
 | 
| +
 | 
| +
 | 
|  Definition* BoxDoubleInstr::Canonicalize(FlowGraph* flow_graph) {
 | 
|    if (input_use_list() == NULL) {
 | 
|      // Environments can accomodate any representation. No need to box.
 | 
| @@ -2618,6 +2643,30 @@
 | 
|  }
 | 
|  
 | 
|  
 | 
| +static int64_t ConstantAbsMax(const Range* range) {
 | 
| +  if (range == NULL) return Smi::kMaxValue;
 | 
| +  const int64_t abs_min = Utils::Abs(Range::ConstantMin(range).value());
 | 
| +  const int64_t abs_max = Utils::Abs(Range::ConstantMax(range).value());
 | 
| +  return abs_min > abs_max ? abs_min : abs_max;
 | 
| +}
 | 
| +
 | 
| +
 | 
| +static bool OnlyPositiveOrZero(const Range* a, const Range* b) {
 | 
| +  if ((a == NULL) || (b == NULL)) return false;
 | 
| +  if (Range::ConstantMin(a).value() < 0) return false;
 | 
| +  if (Range::ConstantMin(b).value() < 0) return false;
 | 
| +  return true;
 | 
| +}
 | 
| +
 | 
| +
 | 
| +static bool OnlyNegativeOrZero(const Range* a, const Range* b) {
 | 
| +  if ((a == NULL) || (b == NULL)) return false;
 | 
| +  if (Range::ConstantMax(a).value() > 0) return false;
 | 
| +  if (Range::ConstantMax(b).value() > 0) return false;
 | 
| +  return true;
 | 
| +}
 | 
| +
 | 
| +
 | 
|  void BinarySmiOpInstr::InferRange() {
 | 
|    // TODO(vegorov): canonicalize BinarySmiOp to always have constant on the
 | 
|    // right and a non-constant on the left.
 | 
| @@ -2674,6 +2723,27 @@
 | 
|        }
 | 
|        break;
 | 
|  
 | 
| +    case Token::kMUL: {
 | 
| +      const int64_t left_max = ConstantAbsMax(left_range);
 | 
| +      const int64_t right_max = ConstantAbsMax(right_range);
 | 
| +      if ((left_max < 0x7FFFFFFF) && (right_max < 0x7FFFFFFF)) {
 | 
| +        // Product of left and right max values stays in 64 bit range.
 | 
| +        const int64_t result_max = left_max * right_max;
 | 
| +        if (Smi::IsValid64(result_max) && Smi::IsValid64(-result_max)) {
 | 
| +          const intptr_t r_min =
 | 
| +              OnlyPositiveOrZero(left_range, right_range) ? 0 : -result_max;
 | 
| +          min = RangeBoundary::FromConstant(r_min);
 | 
| +          const intptr_t r_max =
 | 
| +              OnlyNegativeOrZero(left_range, right_range) ? 0 : result_max;
 | 
| +          max = RangeBoundary::FromConstant(r_max);
 | 
| +          break;
 | 
| +        }
 | 
| +      }
 | 
| +      if (range_ == NULL) {
 | 
| +        range_ = Range::Unknown();
 | 
| +      }
 | 
| +      return;
 | 
| +    }
 | 
|      case Token::kBIT_AND:
 | 
|        if (Range::ConstantMin(right_range).value() >= 0) {
 | 
|          min = RangeBoundary::FromConstant(0);
 | 
| 
 |