| Index: src/x64/lithium-codegen-x64.cc
 | 
| diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
 | 
| index d34436b93433d3cd01ec4ee8cc1e19e5ceb48149..f845f77393bba67ff20fff430872c2dcc62106c4 100644
 | 
| --- a/src/x64/lithium-codegen-x64.cc
 | 
| +++ b/src/x64/lithium-codegen-x64.cc
 | 
| @@ -397,7 +397,8 @@ void LCodeGen::WriteTranslation(LEnvironment* environment,
 | 
|          translation->MarkDuplicate();
 | 
|          AddToTranslation(translation,
 | 
|                           environment->spilled_registers()[value->index()],
 | 
| -                         environment->HasTaggedValueAt(i));
 | 
| +                         environment->HasTaggedValueAt(i),
 | 
| +                         environment->HasUint32ValueAt(i));
 | 
|        } else if (
 | 
|            value->IsDoubleRegister() &&
 | 
|            environment->spilled_double_registers()[value->index()] != NULL) {
 | 
| @@ -405,18 +406,23 @@ void LCodeGen::WriteTranslation(LEnvironment* environment,
 | 
|          AddToTranslation(
 | 
|              translation,
 | 
|              environment->spilled_double_registers()[value->index()],
 | 
| +            false,
 | 
|              false);
 | 
|        }
 | 
|      }
 | 
|  
 | 
| -    AddToTranslation(translation, value, environment->HasTaggedValueAt(i));
 | 
| +    AddToTranslation(translation,
 | 
| +                     value,
 | 
| +                     environment->HasTaggedValueAt(i),
 | 
| +                     environment->HasUint32ValueAt(i));
 | 
|    }
 | 
|  }
 | 
|  
 | 
|  
 | 
|  void LCodeGen::AddToTranslation(Translation* translation,
 | 
|                                  LOperand* op,
 | 
| -                                bool is_tagged) {
 | 
| +                                bool is_tagged,
 | 
| +                                bool is_uint32) {
 | 
|    if (op == NULL) {
 | 
|      // TODO(twuerthinger): Introduce marker operands to indicate that this value
 | 
|      // is not present and must be reconstructed from the deoptimizer. Currently
 | 
| @@ -425,6 +431,8 @@ void LCodeGen::AddToTranslation(Translation* translation,
 | 
|    } else if (op->IsStackSlot()) {
 | 
|      if (is_tagged) {
 | 
|        translation->StoreStackSlot(op->index());
 | 
| +    } else if (is_uint32) {
 | 
| +      translation->StoreUint32StackSlot(op->index());
 | 
|      } else {
 | 
|        translation->StoreInt32StackSlot(op->index());
 | 
|      }
 | 
| @@ -438,6 +446,8 @@ void LCodeGen::AddToTranslation(Translation* translation,
 | 
|      Register reg = ToRegister(op);
 | 
|      if (is_tagged) {
 | 
|        translation->StoreRegister(reg);
 | 
| +    } else if (is_uint32) {
 | 
| +      translation->StoreUint32Register(reg);
 | 
|      } else {
 | 
|        translation->StoreInt32Register(reg);
 | 
|      }
 | 
| @@ -2722,11 +2732,10 @@ void LCodeGen::DoLoadKeyedSpecializedArrayElement(
 | 
|          break;
 | 
|        case EXTERNAL_UNSIGNED_INT_ELEMENTS:
 | 
|          __ movl(result, operand);
 | 
| -        __ testl(result, result);
 | 
| -        // TODO(danno): we could be more clever here, perhaps having a special
 | 
| -        // version of the stub that detects if the overflow case actually
 | 
| -        // happens, and generate code that returns a double rather than int.
 | 
| -        DeoptimizeIf(negative, instr->environment());
 | 
| +        if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
 | 
| +          __ testl(result, result);
 | 
| +          DeoptimizeIf(negative, instr->environment());
 | 
| +        }
 | 
|          break;
 | 
|        case EXTERNAL_FLOAT_ELEMENTS:
 | 
|        case EXTERNAL_DOUBLE_ELEMENTS:
 | 
| @@ -3989,6 +3998,17 @@ void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
 | 
|  }
 | 
|  
 | 
|  
 | 
| +void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) {
 | 
| +  LOperand* input = instr->InputAt(0);
 | 
| +  LOperand* output = instr->result();
 | 
| +  LOperand* temp = instr->TempAt(0);
 | 
| +
 | 
| +  __ LoadUint32(ToDoubleRegister(output),
 | 
| +                ToRegister(input),
 | 
| +                ToDoubleRegister(temp));
 | 
| +}
 | 
| +
 | 
| +
 | 
|  void LCodeGen::DoNumberTagI(LNumberTagI* instr) {
 | 
|    LOperand* input = instr->InputAt(0);
 | 
|    ASSERT(input->IsRegister() && input->Equals(instr->result()));
 | 
| @@ -3998,6 +4018,66 @@ void LCodeGen::DoNumberTagI(LNumberTagI* instr) {
 | 
|  }
 | 
|  
 | 
|  
 | 
| +void LCodeGen::DoNumberTagU(LNumberTagU* instr) {
 | 
| +  class DeferredNumberTagU: public LDeferredCode {
 | 
| +   public:
 | 
| +    DeferredNumberTagU(LCodeGen* codegen, LNumberTagU* instr)
 | 
| +        : LDeferredCode(codegen), instr_(instr) { }
 | 
| +    virtual void Generate() {
 | 
| +      codegen()->DoDeferredNumberTagU(instr_);
 | 
| +    }
 | 
| +    virtual LInstruction* instr() { return instr_; }
 | 
| +   private:
 | 
| +    LNumberTagU* instr_;
 | 
| +  };
 | 
| +
 | 
| +  LOperand* input = instr->InputAt(0);
 | 
| +  ASSERT(input->IsRegister() && input->Equals(instr->result()));
 | 
| +  Register reg = ToRegister(input);
 | 
| +
 | 
| +  DeferredNumberTagU* deferred = new(zone()) DeferredNumberTagU(this, instr);
 | 
| +  __ cmpl(reg, Immediate(Smi::kMaxValue));
 | 
| +  __ j(above, deferred->entry());
 | 
| +  __ Integer32ToSmi(reg, reg);
 | 
| +  __ bind(deferred->exit());
 | 
| +}
 | 
| +
 | 
| +
 | 
| +void LCodeGen::DoDeferredNumberTagU(LNumberTagU* instr) {
 | 
| +  Label slow;
 | 
| +  Register reg = ToRegister(instr->InputAt(0));
 | 
| +  Register tmp = reg.is(rax) ? rcx : rax;
 | 
| +
 | 
| +  // Preserve the value of all registers.
 | 
| +  PushSafepointRegistersScope scope(this);
 | 
| +
 | 
| +  Label done;
 | 
| +  __ LoadUint32(xmm0, reg, xmm1);
 | 
| +
 | 
| +  if (FLAG_inline_new) {
 | 
| +    __ AllocateHeapNumber(reg, tmp, &slow);
 | 
| +    __ jmp(&done, Label::kNear);
 | 
| +  }
 | 
| +
 | 
| +  // Slow case: Call the runtime system to do the number allocation.
 | 
| +  __ bind(&slow);
 | 
| +
 | 
| +  // Put a valid pointer value in the stack slot where the result
 | 
| +  // register is stored, as this register is in the pointer map, but contains an
 | 
| +  // integer value.
 | 
| +  __ StoreToSafepointRegisterSlot(reg, Immediate(0));
 | 
| +
 | 
| +  CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr);
 | 
| +  if (!reg.is(rax)) __ movq(reg, rax);
 | 
| +
 | 
| +  // Done. Put the value in xmm0 into the value of the allocated heap
 | 
| +  // number.
 | 
| +  __ bind(&done);
 | 
| +  __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), xmm0);
 | 
| +  __ StoreToSafepointRegisterSlot(reg, reg);
 | 
| +}
 | 
| +
 | 
| +
 | 
|  void LCodeGen::DoNumberTagD(LNumberTagD* instr) {
 | 
|    class DeferredNumberTagD: public LDeferredCode {
 | 
|     public:
 | 
| 
 |