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: |