| Index: runtime/vm/intermediate_language_ia32.cc
 | 
| diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc
 | 
| index d3cf96f2d48b2e25499580adf751714da298d901..828bbd2537b523d6c829415fed40aad93fe4e36d 100644
 | 
| --- a/runtime/vm/intermediate_language_ia32.cc
 | 
| +++ b/runtime/vm/intermediate_language_ia32.cc
 | 
| @@ -175,15 +175,25 @@ LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Isolate* isolate,
 | 
|  void UnboxedConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
 | 
|    // The register allocator drops constant definitions that have no uses.
 | 
|    if (!locs()->out(0).IsInvalid()) {
 | 
| -     XmmRegister result = locs()->out(0).fpu_reg();
 | 
| -    if (constant_address() == 0) {
 | 
| -      Register boxed = locs()->temp(0).reg();
 | 
| -      __ LoadObjectSafely(boxed, value());
 | 
| -      __ movsd(result, FieldAddress(boxed, Double::value_offset()));
 | 
| -    } else if (Utils::DoublesBitEqual(Double::Cast(value()).value(), 0.0)) {
 | 
| -      __ xorps(result, result);
 | 
| -    } else {
 | 
| -      __ movsd(result, Address::Absolute(constant_address()));
 | 
| +    switch (representation()) {
 | 
| +      case kUnboxedDouble: {
 | 
| +        XmmRegister result = locs()->out(0).fpu_reg();
 | 
| +        if (constant_address() == 0) {
 | 
| +          Register boxed = locs()->temp(0).reg();
 | 
| +          __ LoadObjectSafely(boxed, value());
 | 
| +          __ movsd(result, FieldAddress(boxed, Double::value_offset()));
 | 
| +        } else if (Utils::DoublesBitEqual(Double::Cast(value()).value(), 0.0)) {
 | 
| +          __ xorps(result, result);
 | 
| +        } else {
 | 
| +          __ movsd(result, Address::Absolute(constant_address()));
 | 
| +        }
 | 
| +        break;
 | 
| +      }
 | 
| +      case kUnboxedInt32:
 | 
| +        __ movl(locs()->out(0).reg(), Immediate(Smi::Cast(value()).Value()));
 | 
| +        break;
 | 
| +      default:
 | 
| +        UNREACHABLE();
 | 
|      }
 | 
|    }
 | 
|  }
 | 
| @@ -1042,7 +1052,7 @@ LocationSummary* LoadIndexedInstr::MakeLocationSummary(Isolate* isolate,
 | 
|    locs->set_in(0, Location::RequiresRegister());
 | 
|    if (CanBeImmediateIndex(index(), class_id())) {
 | 
|      // CanBeImmediateIndex must return false for unsafe smis.
 | 
| -    locs->set_in(1, Location::Constant(index()->BoundConstant()));
 | 
| +    locs->set_in(1, Location::Constant(index()->definition()->AsConstant()));
 | 
|    } else {
 | 
|      // The index is either untagged (element size == 1) or a smi (for all
 | 
|      // element sizes > 1).
 | 
| @@ -1238,7 +1248,7 @@ LocationSummary* StoreIndexedInstr::MakeLocationSummary(Isolate* isolate,
 | 
|    locs->set_in(0, Location::RequiresRegister());
 | 
|    if (CanBeImmediateIndex(index(), class_id())) {
 | 
|      // CanBeImmediateIndex must return false for unsafe smis.
 | 
| -    locs->set_in(1, Location::Constant(index()->BoundConstant()));
 | 
| +    locs->set_in(1, Location::Constant(index()->definition()->AsConstant()));
 | 
|    } else {
 | 
|      // The index is either untagged (element size == 1) or a smi (for all
 | 
|      // element sizes > 1).
 | 
| @@ -2775,7 +2785,7 @@ LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Isolate* isolate,
 | 
|        summary->set_in(0, Location::RequiresRegister());
 | 
|        ConstantInstr* right_constant = right()->definition()->AsConstant();
 | 
|        // The programmer only controls one bit, so the constant is safe.
 | 
| -      summary->set_in(1, Location::Constant(right_constant->value()));
 | 
| +      summary->set_in(1, Location::Constant(right_constant));
 | 
|        summary->set_temp(0, Location::RequiresRegister());
 | 
|        summary->set_out(0, Location::SameAsFirstInput());
 | 
|      } else {
 | 
| @@ -3139,6 +3149,289 @@ void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
 | 
|  }
 | 
|  
 | 
|  
 | 
| +LocationSummary* BinaryInt32OpInstr::MakeLocationSummary(Isolate* isolate,
 | 
| +                                                         bool opt) const {
 | 
| +  const intptr_t kNumInputs = 2;
 | 
| +  if (op_kind() == Token::kTRUNCDIV) {
 | 
| +    UNREACHABLE();
 | 
| +    return NULL;
 | 
| +  } else if (op_kind() == Token::kMOD) {
 | 
| +     UNREACHABLE();
 | 
| +    return NULL;
 | 
| +  } else if (op_kind() == Token::kSHR) {
 | 
| +    const intptr_t kNumTemps = 0;
 | 
| +    LocationSummary* summary = new(isolate) LocationSummary(
 | 
| +        isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
 | 
| +    summary->set_in(0, Location::RequiresRegister());
 | 
| +    summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX));
 | 
| +    summary->set_out(0, Location::SameAsFirstInput());
 | 
| +    return summary;
 | 
| +  } else if (op_kind() == Token::kSHL) {
 | 
| +    const intptr_t kNumTemps = !IsTruncating() ? 1 : 0;
 | 
| +    LocationSummary* summary = new(isolate) LocationSummary(
 | 
| +        isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
 | 
| +    summary->set_in(0, Location::RequiresRegister());
 | 
| +    summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX));
 | 
| +    if (!IsTruncating()) {
 | 
| +      summary->set_temp(0, Location::RequiresRegister());
 | 
| +    }
 | 
| +    summary->set_out(0, Location::SameAsFirstInput());
 | 
| +    return summary;
 | 
| +  } else {
 | 
| +    const intptr_t kNumTemps = 0;
 | 
| +    LocationSummary* summary = new(isolate) LocationSummary(
 | 
| +        isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
 | 
| +    summary->set_in(0, Location::RequiresRegister());
 | 
| +    ConstantInstr* constant = right()->definition()->AsConstant();
 | 
| +    if (constant != NULL) {
 | 
| +      summary->set_in(1, Location::RegisterOrSmiConstant(right()));
 | 
| +    } else {
 | 
| +      summary->set_in(1, Location::PrefersRegister());
 | 
| +    }
 | 
| +    summary->set_out(0, Location::SameAsFirstInput());
 | 
| +    return summary;
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +
 | 
| +static void EmitInt32ShiftLeft(FlowGraphCompiler* compiler,
 | 
| +                               BinaryInt32OpInstr* shift_left) {
 | 
| +  const bool is_truncating = shift_left->IsTruncating();
 | 
| +  const LocationSummary& locs = *shift_left->locs();
 | 
| +  Register left = locs.in(0).reg();
 | 
| +  Register result = locs.out(0).reg();
 | 
| +  ASSERT(left == result);
 | 
| +  Label* deopt = shift_left->CanDeoptimize() ?
 | 
| +      compiler->AddDeoptStub(shift_left->deopt_id(), ICData::kDeoptBinarySmiOp)
 | 
| +      : NULL;
 | 
| +  ASSERT(locs.in(1).IsConstant());
 | 
| +
 | 
| +  const Object& constant = locs.in(1).constant();
 | 
| +  ASSERT(constant.IsSmi());
 | 
| +  // shll operation masks the count to 5 bits.
 | 
| +  const intptr_t kCountLimit = 0x1F;
 | 
| +  const intptr_t value = Smi::Cast(constant).Value();
 | 
| +  if (value == 0) {
 | 
| +    // No code needed.
 | 
| +  } else if ((value < 0) || (value >= kCountLimit)) {
 | 
| +    // This condition may not be known earlier in some cases because
 | 
| +    // of constant propagation, inlining, etc.
 | 
| +    if ((value >= kCountLimit) && is_truncating) {
 | 
| +      __ xorl(result, result);
 | 
| +    } else {
 | 
| +      // Result is Mint or exception.
 | 
| +      __ jmp(deopt);
 | 
| +    }
 | 
| +  } else {
 | 
| +    if (!is_truncating) {
 | 
| +      // Check for overflow.
 | 
| +      Register temp = locs.temp(0).reg();
 | 
| +      __ movl(temp, left);
 | 
| +      __ shll(left, Immediate(value));
 | 
| +      __ sarl(left, Immediate(value));
 | 
| +      __ cmpl(left, temp);
 | 
| +      __ j(NOT_EQUAL, deopt);  // Overflow.
 | 
| +    }
 | 
| +    // Shift for result now we know there is no overflow.
 | 
| +    __ shll(left, Immediate(value));
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +
 | 
| +void BinaryInt32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
 | 
| +  if (op_kind() == Token::kSHL) {
 | 
| +    EmitInt32ShiftLeft(compiler, this);
 | 
| +    return;
 | 
| +  }
 | 
| +
 | 
| +  Register left = locs()->in(0).reg();
 | 
| +  Register result = locs()->out(0).reg();
 | 
| +  ASSERT(left == result);
 | 
| +  Label* deopt = NULL;
 | 
| +  if (CanDeoptimize()) {
 | 
| +    deopt  = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp);
 | 
| +  }
 | 
| +
 | 
| +  if (locs()->in(1).IsConstant()) {
 | 
| +    const Object& constant = locs()->in(1).constant();
 | 
| +    ASSERT(constant.IsSmi());
 | 
| +    const intptr_t value = Smi::Cast(constant).Value();
 | 
| +    switch (op_kind()) {
 | 
| +    case Token::kADD:
 | 
| +        if (value != 0) {
 | 
| +          // Checking overflow without emitting an instruction would be wrong.
 | 
| +          __ addl(left, Immediate(value));
 | 
| +          if (deopt != NULL) __ j(OVERFLOW, deopt);
 | 
| +        }
 | 
| +        break;
 | 
| +      case Token::kSUB: {
 | 
| +        if (value != 0) {
 | 
| +          // Checking overflow without emitting an instruction would be wrong.
 | 
| +          __ subl(left, Immediate(value));
 | 
| +          if (deopt != NULL) __ j(OVERFLOW, deopt);
 | 
| +        }
 | 
| +        break;
 | 
| +      }
 | 
| +      case Token::kMUL: {
 | 
| +        if (value == 2) {
 | 
| +          __ shll(left, Immediate(1));
 | 
| +        } else {
 | 
| +          __ imull(left, Immediate(value));
 | 
| +        }
 | 
| +        if (deopt != NULL) __ j(OVERFLOW, deopt);
 | 
| +        break;
 | 
| +      }
 | 
| +      case Token::kTRUNCDIV: {
 | 
| +        UNREACHABLE();
 | 
| +        break;
 | 
| +      }
 | 
| +      case Token::kBIT_AND: {
 | 
| +        // No overflow check.
 | 
| +        __ andl(left, Immediate(value));
 | 
| +        break;
 | 
| +      }
 | 
| +      case Token::kBIT_OR: {
 | 
| +        // No overflow check.
 | 
| +        __ orl(left, Immediate(value));
 | 
| +        break;
 | 
| +      }
 | 
| +      case Token::kBIT_XOR: {
 | 
| +        // No overflow check.
 | 
| +        __ xorl(left, Immediate(value));
 | 
| +        break;
 | 
| +      }
 | 
| +      case Token::kSHR: {
 | 
| +        // sarl operation masks the count to 5 bits.
 | 
| +        const intptr_t kCountLimit = 0x1F;
 | 
| +        if (value == 0) {
 | 
| +          // TODO(vegorov): should be handled outside.
 | 
| +          break;
 | 
| +        } else if (value < 0) {
 | 
| +          // TODO(vegorov): should be handled outside.
 | 
| +          __ jmp(deopt);
 | 
| +          break;
 | 
| +        }
 | 
| +
 | 
| +        if (value >= kCountLimit) {
 | 
| +          __ sarl(left, Immediate(kCountLimit));
 | 
| +        } else {
 | 
| +          __ sarl(left, Immediate(value));
 | 
| +        }
 | 
| +
 | 
| +        break;
 | 
| +      }
 | 
| +
 | 
| +      default:
 | 
| +        UNREACHABLE();
 | 
| +        break;
 | 
| +    }
 | 
| +    return;
 | 
| +  }  // if locs()->in(1).IsConstant()
 | 
| +
 | 
| +  if (locs()->in(1).IsStackSlot()) {
 | 
| +    const Address& right = locs()->in(1).ToStackSlotAddress();
 | 
| +    switch (op_kind()) {
 | 
| +      case Token::kADD: {
 | 
| +        __ addl(left, right);
 | 
| +        if (deopt != NULL) __ j(OVERFLOW, deopt);
 | 
| +        break;
 | 
| +      }
 | 
| +      case Token::kSUB: {
 | 
| +        __ subl(left, right);
 | 
| +        if (deopt != NULL) __ j(OVERFLOW, deopt);
 | 
| +        break;
 | 
| +      }
 | 
| +      case Token::kMUL: {
 | 
| +        __ imull(left, right);
 | 
| +        if (deopt != NULL) __ j(OVERFLOW, deopt);
 | 
| +        break;
 | 
| +      }
 | 
| +      case Token::kBIT_AND: {
 | 
| +        // No overflow check.
 | 
| +        __ andl(left, right);
 | 
| +        break;
 | 
| +      }
 | 
| +      case Token::kBIT_OR: {
 | 
| +        // No overflow check.
 | 
| +        __ orl(left, right);
 | 
| +        break;
 | 
| +      }
 | 
| +      case Token::kBIT_XOR: {
 | 
| +        // No overflow check.
 | 
| +        __ xorl(left, right);
 | 
| +        break;
 | 
| +      }
 | 
| +      default:
 | 
| +        UNREACHABLE();
 | 
| +    }
 | 
| +    return;
 | 
| +  }  // if locs()->in(1).IsStackSlot.
 | 
| +
 | 
| +  // if locs()->in(1).IsRegister.
 | 
| +  Register right = locs()->in(1).reg();
 | 
| +  switch (op_kind()) {
 | 
| +    case Token::kADD: {
 | 
| +      __ addl(left, right);
 | 
| +      if (deopt != NULL) __ j(OVERFLOW, deopt);
 | 
| +      break;
 | 
| +    }
 | 
| +    case Token::kSUB: {
 | 
| +      __ subl(left, right);
 | 
| +      if (deopt != NULL) __ j(OVERFLOW, deopt);
 | 
| +      break;
 | 
| +    }
 | 
| +    case Token::kMUL: {
 | 
| +      __ imull(left, right);
 | 
| +      if (deopt != NULL) __ j(OVERFLOW, deopt);
 | 
| +      break;
 | 
| +    }
 | 
| +    case Token::kBIT_AND: {
 | 
| +      // No overflow check.
 | 
| +      __ andl(left, right);
 | 
| +      break;
 | 
| +    }
 | 
| +    case Token::kBIT_OR: {
 | 
| +      // No overflow check.
 | 
| +      __ orl(left, right);
 | 
| +      break;
 | 
| +    }
 | 
| +    case Token::kBIT_XOR: {
 | 
| +      // No overflow check.
 | 
| +      __ xorl(left, right);
 | 
| +      break;
 | 
| +    }
 | 
| +    case Token::kTRUNCDIV: {
 | 
| +      UNREACHABLE();
 | 
| +      break;
 | 
| +    }
 | 
| +    case Token::kMOD: {
 | 
| +      UNREACHABLE();
 | 
| +      break;
 | 
| +    }
 | 
| +    case Token::kSHR: {
 | 
| +      UNREACHABLE();
 | 
| +      break;
 | 
| +    }
 | 
| +    case Token::kDIV: {
 | 
| +      // Dispatches to 'Double./'.
 | 
| +      // TODO(srdjan): Implement as conversion to double and double division.
 | 
| +      UNREACHABLE();
 | 
| +      break;
 | 
| +    }
 | 
| +    case Token::kOR:
 | 
| +    case Token::kAND: {
 | 
| +      // Flow graph builder has dissected this operation to guarantee correct
 | 
| +      // behavior (short-circuit evaluation).
 | 
| +      UNREACHABLE();
 | 
| +      break;
 | 
| +    }
 | 
| +    default:
 | 
| +      UNREACHABLE();
 | 
| +      break;
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +
 | 
|  LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Isolate* isolate,
 | 
|                                                               bool opt) const {
 | 
|    intptr_t left_cid = left()->Type()->ToCid();
 | 
| @@ -4673,6 +4966,25 @@ void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
 | 
|  }
 | 
|  
 | 
|  
 | 
| +LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Isolate* isolate,
 | 
| +                                                       bool opt) const {
 | 
| +  const intptr_t kNumInputs = 1;
 | 
| +  const intptr_t kNumTemps = 0;
 | 
| +  LocationSummary* result = new(isolate) LocationSummary(
 | 
| +      isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
 | 
| +  result->set_in(0, Location::WritableRegister());
 | 
| +  result->set_out(0, Location::RequiresFpuRegister());
 | 
| +  return result;
 | 
| +}
 | 
| +
 | 
| +
 | 
| +void Int32ToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
 | 
| +  Register value = locs()->in(0).reg();
 | 
| +  FpuRegister result = locs()->out(0).fpu_reg();
 | 
| +  __ cvtsi2sd(result, value);
 | 
| +}
 | 
| +
 | 
| +
 | 
|  LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Isolate* isolate,
 | 
|                                                         bool opt) const {
 | 
|    const intptr_t kNumInputs = 1;
 | 
| @@ -5910,16 +6222,6 @@ CompileType UnaryUint32OpInstr::ComputeType() const {
 | 
|  }
 | 
|  
 | 
|  
 | 
| -CompileType BoxUint32Instr::ComputeType() const {
 | 
| -  return CompileType::Int();
 | 
| -}
 | 
| -
 | 
| -
 | 
| -CompileType UnboxUint32Instr::ComputeType() const {
 | 
| -  return CompileType::Int();
 | 
| -}
 | 
| -
 | 
| -
 | 
|  LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Isolate* isolate,
 | 
|                                                            bool opt) const {
 | 
|    const intptr_t kNumInputs = 2;
 | 
| @@ -6092,9 +6394,14 @@ LocationSummary* BoxUint32Instr::MakeLocationSummary(Isolate* isolate,
 | 
|    const intptr_t kNumInputs = 1;
 | 
|    const intptr_t kNumTemps = 0;
 | 
|    LocationSummary* summary = new(isolate) LocationSummary(
 | 
| -      isolate, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath);
 | 
| +      isolate,
 | 
| +      kNumInputs,
 | 
| +      kNumTemps,
 | 
| +      ValueFitsSmi() ? LocationSummary::kNoCall
 | 
| +                     : LocationSummary::kCallOnSlowPath);
 | 
|    summary->set_in(0, Location::RequiresRegister());
 | 
| -  summary->set_out(0, Location::RequiresRegister());
 | 
| +  summary->set_out(0, ValueFitsSmi() ? Location::SameAsFirstInput()
 | 
| +                                     : Location::RequiresRegister());
 | 
|    return summary;
 | 
|  }
 | 
|  
 | 
| @@ -6102,27 +6409,68 @@ LocationSummary* BoxUint32Instr::MakeLocationSummary(Isolate* isolate,
 | 
|  void BoxUint32Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
 | 
|    Register value = locs()->in(0).reg();
 | 
|    Register out = locs()->out(0).reg();
 | 
| -  ASSERT(value != out);
 | 
|  
 | 
|    Label not_smi, done;
 | 
|  
 | 
| -  // TODO(johnmccutchan): Use range information to fast path smi / mint boxing.
 | 
| -  // Test if this value is <= kSmiMax.
 | 
| -  __ cmpl(value, Immediate(kSmiMax));
 | 
| -  __ j(ABOVE, ¬_smi);
 | 
| -  // Smi.
 | 
| -  __ movl(out, value);
 | 
| -  __ SmiTag(out);
 | 
| -  __ jmp(&done);
 | 
| -  __ Bind(¬_smi);
 | 
| -  // Allocate a mint.
 | 
| -  BoxAllocationSlowPath::Allocate(
 | 
| -      compiler, this, compiler->mint_class(), out, kNoRegister);
 | 
| -  // Copy low word into mint.
 | 
| -  __ movl(FieldAddress(out, Mint::value_offset()), value);
 | 
| -  // Zero high word.
 | 
| -  __ movl(FieldAddress(out, Mint::value_offset() + kWordSize), Immediate(0));
 | 
| -  __ Bind(&done);
 | 
| +  if (ValueFitsSmi()) {
 | 
| +    ASSERT(value == out);
 | 
| +    __ SmiTag(value);
 | 
| +  } else {
 | 
| +    ASSERT(value != out);
 | 
| +    __ cmpl(value, Immediate(kSmiMax));
 | 
| +    __ j(ABOVE, ¬_smi);
 | 
| +    // Smi.
 | 
| +    __ movl(out, value);
 | 
| +    __ SmiTag(out);
 | 
| +    __ jmp(&done);
 | 
| +    __ Bind(¬_smi);
 | 
| +    // Allocate a mint.
 | 
| +    BoxAllocationSlowPath::Allocate(
 | 
| +        compiler, this, compiler->mint_class(), out, kNoRegister);
 | 
| +    // Copy low word into mint.
 | 
| +    __ movl(FieldAddress(out, Mint::value_offset()), value);
 | 
| +    // Zero high word.
 | 
| +    __ movl(FieldAddress(out, Mint::value_offset() + kWordSize), Immediate(0));
 | 
| +    __ Bind(&done);
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +
 | 
| +LocationSummary* BoxInt32Instr::MakeLocationSummary(Isolate* isolate,
 | 
| +                                                    bool opt) const {
 | 
| +  const intptr_t kNumInputs = 1;
 | 
| +  const intptr_t kNumTemps = 0;
 | 
| +  LocationSummary* summary = new(isolate) LocationSummary(
 | 
| +      isolate, kNumInputs, kNumTemps,
 | 
| +      ValueFitsSmi() ? LocationSummary::kNoCall
 | 
| +                     : LocationSummary::kCallOnSlowPath);
 | 
| +  summary->set_in(0, ValueFitsSmi() ? Location::RequiresRegister()
 | 
| +                                    : Location::WritableRegister());
 | 
| +  summary->set_out(0, ValueFitsSmi() ? Location::SameAsFirstInput()
 | 
| +                                     : Location::RequiresRegister());
 | 
| +  return summary;
 | 
| +}
 | 
| +
 | 
| +
 | 
| +void BoxInt32Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
 | 
| +  Register value = locs()->in(0).reg();
 | 
| +  Register out = locs()->out(0).reg();
 | 
| +
 | 
| +  if (out != value) {
 | 
| +    __ movl(out, value);
 | 
| +  }
 | 
| +  __ shll(out, Immediate(1));
 | 
| +  if (!ValueFitsSmi()) {
 | 
| +    Label done;
 | 
| +    __ j(NO_OVERFLOW, &done);
 | 
| +    // Allocate a mint.
 | 
| +    BoxAllocationSlowPath::Allocate(
 | 
| +        compiler, this, compiler->mint_class(), out, kNoRegister);
 | 
| +    __ movl(FieldAddress(out, Mint::value_offset()), value);
 | 
| +    __ sarl(value, Immediate(31));  // Sign extend.
 | 
| +    __ movl(FieldAddress(out, Mint::value_offset() + kWordSize), value);
 | 
| +    __ Bind(&done);
 | 
| +  }
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -6171,35 +6519,142 @@ void UnboxUint32Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
 | 
|  }
 | 
|  
 | 
|  
 | 
| +LocationSummary* UnboxInt32Instr::MakeLocationSummary(Isolate* isolate,
 | 
| +                                                       bool opt) const {
 | 
| +  const intptr_t value_cid = value()->Type()->ToCid();
 | 
| +  const intptr_t kNumInputs = 1;
 | 
| +  const intptr_t kNumTemps = CanDeoptimize() ? 1 : 0;
 | 
| +  LocationSummary* summary = new(isolate) LocationSummary(
 | 
| +      isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
 | 
| +  summary->set_in(0, Location::RequiresRegister());
 | 
| +  if (kNumTemps > 0) {
 | 
| +    summary->set_temp(0, Location::RequiresRegister());
 | 
| +  }
 | 
| +  summary->set_out(0, (value_cid == kSmiCid) ? Location::SameAsFirstInput()
 | 
| +                                             : Location::RequiresRegister());
 | 
| +  return summary;
 | 
| +}
 | 
| +
 | 
| +
 | 
| +static void LoadInt32FromMint(FlowGraphCompiler* compiler,
 | 
| +                              Register mint,
 | 
| +                              Register result,
 | 
| +                              Register temp,
 | 
| +                              Label* deopt) {
 | 
| +  __ movl(result, FieldAddress(mint, Mint::value_offset()));
 | 
| +  if (deopt != NULL) {
 | 
| +    __ movl(temp, result);
 | 
| +    __ sarl(temp, Immediate(31));
 | 
| +    __ cmpl(temp, FieldAddress(mint, Mint::value_offset() + kWordSize));
 | 
| +    __ j(NOT_EQUAL, deopt);
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +
 | 
| +void UnboxInt32Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
 | 
| +  const intptr_t value_cid = value()->Type()->ToCid();
 | 
| +  const Register value = locs()->in(0).reg();
 | 
| +  const Register result = locs()->out(0).reg();
 | 
| +
 | 
| +  // TODO(johnmccutchan): Emit better code for constant inputs.
 | 
| +  if (value_cid == kMintCid) {
 | 
| +    Register temp = CanDeoptimize() ? locs()->temp(0).reg() : kNoRegister;
 | 
| +    Label* deopt = CanDeoptimize() ?
 | 
| +        compiler->AddDeoptStub(deopt_id_, ICData::kDeoptUnboxInteger) : NULL;
 | 
| +    LoadInt32FromMint(compiler,
 | 
| +                      value,
 | 
| +                      result,
 | 
| +                      temp,
 | 
| +                      deopt);
 | 
| +  } else if (value_cid == kSmiCid) {
 | 
| +    ASSERT(value == result);
 | 
| +    __ SmiUntag(value);
 | 
| +  } else {
 | 
| +    Register temp = locs()->temp(0).reg();
 | 
| +    Label* deopt = compiler->AddDeoptStub(deopt_id_,
 | 
| +                                          ICData::kDeoptUnboxInteger);
 | 
| +    Label is_smi, done;
 | 
| +    __ testl(value, Immediate(kSmiTagMask));
 | 
| +    __ j(ZERO, &is_smi);
 | 
| +    __ CompareClassId(value, kMintCid, temp);
 | 
| +    __ j(NOT_EQUAL, deopt);
 | 
| +    LoadInt32FromMint(compiler,
 | 
| +                      value,
 | 
| +                      result,
 | 
| +                      temp,
 | 
| +                      deopt);
 | 
| +    __ movl(value, FieldAddress(value, Mint::value_offset()));
 | 
| +    __ jmp(&done);
 | 
| +    __ Bind(&is_smi);
 | 
| +    __ SmiUntag(value);
 | 
| +    __ Bind(&done);
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +
 | 
|  LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Isolate* isolate,
 | 
|                                                                 bool opt) const {
 | 
|    const intptr_t kNumInputs = 1;
 | 
|    const intptr_t kNumTemps = 0;
 | 
|    LocationSummary* summary = new(isolate) LocationSummary(
 | 
|        isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
 | 
| -  if (from() == kUnboxedMint) {
 | 
| -    summary->set_in(0, Location::Pair(Location::RequiresRegister(),
 | 
| -                                      Location::RequiresRegister()));
 | 
| +  if ((from() == kUnboxedInt32 || from() == kUnboxedUint32) &&
 | 
| +      (to() == kUnboxedInt32 || to() == kUnboxedUint32)) {
 | 
| +    summary->set_in(0, Location::RequiresRegister());
 | 
| +    summary->set_out(0, Location::SameAsFirstInput());
 | 
| +  } else if (from() == kUnboxedMint) {
 | 
| +    summary->set_in(0, Location::Pair(
 | 
| +        CanDeoptimize() ? Location::WritableRegister()
 | 
| +                        : Location::RequiresRegister(),
 | 
| +        Location::RequiresRegister()));
 | 
|      summary->set_out(0, Location::RequiresRegister());
 | 
| -  } else {
 | 
| -    ASSERT(from() == kUnboxedUint32);
 | 
| +  } else if (from() == kUnboxedUint32) {
 | 
|      summary->set_in(0, Location::RequiresRegister());
 | 
|      summary->set_out(0, Location::Pair(Location::RequiresRegister(),
 | 
|                                         Location::RequiresRegister()));
 | 
| +  } else if (from() == kUnboxedInt32) {
 | 
| +    summary->set_in(0, Location::RegisterLocation(EAX));
 | 
| +    summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX),
 | 
| +                                       Location::RegisterLocation(EDX)));
 | 
|    }
 | 
|    return summary;
 | 
|  }
 | 
|  
 | 
|  
 | 
|  void UnboxedIntConverterInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
 | 
| -  if (from() == kUnboxedMint) {
 | 
| +  if (from() == kUnboxedInt32 && to() == kUnboxedUint32) {
 | 
| +    // Representations are bitwise equivalent.
 | 
| +    ASSERT(locs()->out(0).reg() == locs()->in(0).reg());
 | 
| +  } else if (from() == kUnboxedUint32 && to() == kUnboxedInt32) {
 | 
| +    // Representations are bitwise equivalent.
 | 
| +    ASSERT(locs()->out(0).reg() == locs()->in(0).reg());
 | 
| +    if (CanDeoptimize()) {
 | 
| +      Label* deopt =
 | 
| +          compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnboxInteger);
 | 
| +      __ testl(locs()->out(0).reg(), locs()->out(0).reg());
 | 
| +      __ j(NEGATIVE, deopt);
 | 
| +    }
 | 
| +  } else if (from() == kUnboxedMint) {
 | 
| +    // TODO(vegorov) kUnboxedMint -> kInt32 conversion is currently usually
 | 
| +    // dominated by a CheckSmi(BoxInteger(val)) which is an artifact of ordering
 | 
| +    // of optimization passes and the way we check smi-ness of values.
 | 
| +    // Optimize it away.
 | 
| +    ASSERT(to() == kUnboxedInt32 || to() == kUnboxedUint32);
 | 
|      PairLocation* in_pair = locs()->in(0).AsPairLocation();
 | 
|      Register in_lo = in_pair->At(0).reg();
 | 
| +    Register in_hi = in_pair->At(1).reg();
 | 
|      Register out = locs()->out(0).reg();
 | 
|      // Copy low word.
 | 
|      __ movl(out, in_lo);
 | 
| -  } else {
 | 
| -    ASSERT(from() == kUnboxedUint32);
 | 
| +    if (CanDeoptimize()) {
 | 
| +      Label* deopt =
 | 
| +          compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnboxInteger);
 | 
| +      __ sarl(in_lo, Immediate(31));
 | 
| +      __ cmpl(in_lo, in_hi);
 | 
| +      __ j(NOT_EQUAL, deopt);
 | 
| +    }
 | 
| +  } else if (from() == kUnboxedUint32) {
 | 
| +    ASSERT(to() == kUnboxedMint);
 | 
|      Register in = locs()->in(0).reg();
 | 
|      PairLocation* out_pair = locs()->out(0).AsPairLocation();
 | 
|      Register out_lo = out_pair->At(0).reg();
 | 
| @@ -6208,6 +6663,16 @@ void UnboxedIntConverterInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
 | 
|      __ movl(out_lo, in);
 | 
|      // Zero upper word.
 | 
|      __ xorl(out_hi, out_hi);
 | 
| +  } else if (from() == kUnboxedInt32) {
 | 
| +    ASSERT(to() == kUnboxedMint);
 | 
| +    PairLocation* out_pair = locs()->out(0).AsPairLocation();
 | 
| +    Register out_lo = out_pair->At(0).reg();
 | 
| +    Register out_hi = out_pair->At(1).reg();
 | 
| +    ASSERT(locs()->in(0).reg() == EAX);
 | 
| +    ASSERT(out_lo == EAX && out_hi == EDX);
 | 
| +    __ cdq();
 | 
| +  } else {
 | 
| +    UNREACHABLE();
 | 
|    }
 | 
|  }
 | 
|  
 | 
| 
 |