| Index: src/mips/lithium-codegen-mips.cc
|
| diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc
|
| index 50fe4ac0ced14ee445d4c3cb8995d56c52b8e120..e373c9ab18e3db3642309e67416d0bd98dec9bf7 100644
|
| --- a/src/mips/lithium-codegen-mips.cc
|
| +++ b/src/mips/lithium-codegen-mips.cc
|
| @@ -471,7 +471,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) {
|
| @@ -479,18 +480,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
|
| @@ -499,6 +505,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());
|
| }
|
| @@ -512,6 +520,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);
|
| }
|
| @@ -2769,11 +2779,10 @@ void LCodeGen::DoLoadKeyedSpecializedArrayElement(
|
| break;
|
| case EXTERNAL_UNSIGNED_INT_ELEMENTS:
|
| __ lw(result, mem_operand);
|
| - // 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(Ugreater_equal, instr->environment(),
|
| - result, Operand(0x80000000));
|
| + if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
|
| + DeoptimizeIf(Ugreater_equal, instr->environment(),
|
| + result, Operand(0x80000000));
|
| + }
|
| break;
|
| case EXTERNAL_FLOAT_ELEMENTS:
|
| case EXTERNAL_DOUBLE_ELEMENTS:
|
| @@ -4059,12 +4068,24 @@ void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
|
| }
|
|
|
|
|
| +void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) {
|
| + LOperand* input = instr->InputAt(0);
|
| + LOperand* output = instr->result();
|
| +
|
| + FPURegister dbl_scratch = double_scratch0();
|
| + __ mtc1(ToRegister(input), dbl_scratch);
|
| + __ Cvt_d_uw(ToDoubleRegister(output), dbl_scratch, f22);
|
| +}
|
| +
|
| +
|
| 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_;
|
| @@ -4081,7 +4102,32 @@ 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);
|
| + __ Branch(deferred->entry(), hi, reg, Operand(Smi::kMaxValue));
|
| + __ 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());
|
| @@ -4090,16 +4136,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);
|
| - __ Xor(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);
|
| + __ Xor(src, src, Operand(0x80000000));
|
| + }
|
| + __ mtc1(src, dbl_scratch);
|
| + __ cvt_d_w(dbl_scratch, dbl_scratch);
|
| + } else {
|
| + __ mtc1(src, dbl_scratch);
|
| + __ Cvt_d_uw(dbl_scratch, dbl_scratch, f22);
|
| }
|
| - __ mtc1(src, dbl_scratch);
|
| - __ cvt_d_w(dbl_scratch, dbl_scratch);
|
| +
|
| if (FLAG_inline_new) {
|
| __ LoadRoot(t2, Heap::kHeapNumberMapRootIndex);
|
| __ AllocateHeapNumber(t1, a3, t0, t2, &slow);
|
|
|