Index: src/arm/lithium-codegen-arm.cc |
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc |
index 8ab9531a7a51a0133e188467bfafd929087131e5..d4eade6992c9ab214b04ee610a4a082da8d8a3be 100644 |
--- a/src/arm/lithium-codegen-arm.cc |
+++ b/src/arm/lithium-codegen-arm.cc |
@@ -510,7 +510,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) { |
@@ -518,18 +519,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 |
@@ -538,6 +544,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()); |
} |
@@ -551,6 +559,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); |
} |
@@ -3020,11 +3030,10 @@ void LCodeGen::DoLoadKeyedSpecializedArrayElement( |
break; |
case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
__ ldr(result, mem_operand); |
- __ cmp(result, Operand(0x80000000)); |
- // 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(cs, instr->environment()); |
+ if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { |
+ __ cmp(result, Operand(0x80000000)); |
+ DeoptimizeIf(cs, instr->environment()); |
+ } |
break; |
case EXTERNAL_FLOAT_ELEMENTS: |
case EXTERNAL_DOUBLE_ELEMENTS: |
@@ -4262,12 +4271,24 @@ void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { |
} |
+void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) { |
+ LOperand* input = instr->InputAt(0); |
+ LOperand* output = instr->result(); |
+ |
+ SwVfpRegister flt_scratch = double_scratch0().low(); |
+ __ vmov(flt_scratch, ToRegister(input)); |
+ __ vcvt_f64_u32(ToDoubleRegister(output), flt_scratch); |
+} |
+ |
+ |
void LCodeGen::DoNumberTagI(LNumberTagI* instr) { |
class DeferredNumberTagI: public LDeferredCode { |
public: |
DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr) |
: LDeferredCode(codegen), instr_(instr) { } |
- virtual void Generate() { codegen()->DoDeferredNumberTagI(instr_); } |
+ virtual void Generate() { |
+ codegen()->DoDeferredNumberTagI(instr_, SIGNED_INT32); |
+ } |
virtual LInstruction* instr() { return instr_; } |
private: |
LNumberTagI* instr_; |
@@ -4283,7 +4304,33 @@ void LCodeGen::DoNumberTagI(LNumberTagI* instr) { |
} |
-void LCodeGen::DoDeferredNumberTagI(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()->DoDeferredNumberTagI(instr_, UNSIGNED_INT32); |
+ } |
+ 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); |
+ __ cmp(reg, Operand(Smi::kMaxValue)); |
+ __ b(hi, deferred->entry()); |
+ __ SmiTag(reg, reg); |
+ __ bind(deferred->exit()); |
+} |
+ |
+ |
+void LCodeGen::DoDeferredNumberTagI(LInstruction* instr, |
+ IntegerSignedness signedness) { |
Label slow; |
Register src = ToRegister(instr->InputAt(0)); |
Register dst = ToRegister(instr->result()); |
@@ -4293,16 +4340,22 @@ void LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) { |
// Preserve the value of all registers. |
PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
- // There was overflow, so bits 30 and 31 of the original integer |
- // disagree. Try to allocate a heap number in new space and store |
- // the value in there. If that fails, call the runtime system. |
Label done; |
- if (dst.is(src)) { |
- __ SmiUntag(src, dst); |
- __ eor(src, src, Operand(0x80000000)); |
+ if (signedness == SIGNED_INT32) { |
+ // There was overflow, so bits 30 and 31 of the original integer |
+ // disagree. Try to allocate a heap number in new space and store |
+ // the value in there. If that fails, call the runtime system. |
+ if (dst.is(src)) { |
+ __ SmiUntag(src, dst); |
+ __ eor(src, src, Operand(0x80000000)); |
+ } |
+ __ vmov(flt_scratch, src); |
+ __ vcvt_f64_s32(dbl_scratch, flt_scratch); |
+ } else { |
+ __ vmov(flt_scratch, src); |
+ __ vcvt_f64_u32(dbl_scratch, flt_scratch); |
} |
- __ vmov(flt_scratch, src); |
- __ vcvt_f64_s32(dbl_scratch, flt_scratch); |
+ |
if (FLAG_inline_new) { |
__ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); |
__ AllocateHeapNumber(r5, r3, r4, r6, &slow); |