Index: src/mips64/lithium-codegen-mips64.cc |
diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips64/lithium-codegen-mips64.cc |
similarity index 89% |
copy from src/mips/lithium-codegen-mips.cc |
copy to src/mips64/lithium-codegen-mips64.cc |
index 247572abc2eb75b48030069a8e8cdbe4f03d3544..bf856b4c6634904519b87c8092b752b665746dbb 100644 |
--- a/src/mips/lithium-codegen-mips.cc |
+++ b/src/mips64/lithium-codegen-mips64.cc |
@@ -1,36 +1,13 @@ |
-// Copyright 2012 the V8 project authors. All rights reserved.7 |
-// Redistribution and use in source and binary forms, with or without |
-// modification, are permitted provided that the following conditions are |
-// met: |
-// |
-// * Redistributions of source code must retain the above copyright |
-// notice, this list of conditions and the following disclaimer. |
-// * Redistributions in binary form must reproduce the above |
-// copyright notice, this list of conditions and the following |
-// disclaimer in the documentation and/or other materials provided |
-// with the distribution. |
-// * Neither the name of Google Inc. nor the names of its |
-// contributors may be used to endorse or promote products derived |
-// from this software without specific prior written permission. |
-// |
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
+// Copyright 2012 the V8 project authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
#include "src/v8.h" |
#include "src/code-stubs.h" |
#include "src/hydrogen-osr.h" |
-#include "src/mips/lithium-codegen-mips.h" |
-#include "src/mips/lithium-gap-resolver-mips.h" |
+#include "src/mips64/lithium-codegen-mips64.h" |
+#include "src/mips64/lithium-gap-resolver-mips64.h" |
#include "src/stub-cache.h" |
namespace v8 { |
@@ -148,13 +125,13 @@ bool LCodeGen::GeneratePrologue() { |
Label ok; |
int receiver_offset = info_->scope()->num_parameters() * kPointerSize; |
__ LoadRoot(at, Heap::kUndefinedValueRootIndex); |
- __ lw(a2, MemOperand(sp, receiver_offset)); |
+ __ ld(a2, MemOperand(sp, receiver_offset)); |
__ Branch(&ok, ne, a2, Operand(at)); |
- __ lw(a2, GlobalObjectOperand()); |
- __ lw(a2, FieldMemOperand(a2, GlobalObject::kGlobalProxyOffset)); |
+ __ ld(a2, GlobalObjectOperand()); |
+ __ ld(a2, FieldMemOperand(a2, GlobalObject::kGlobalProxyOffset)); |
- __ sw(a2, MemOperand(sp, receiver_offset)); |
+ __ sd(a2, MemOperand(sp, receiver_offset)); |
__ bind(&ok); |
} |
@@ -175,18 +152,18 @@ bool LCodeGen::GeneratePrologue() { |
int slots = GetStackSlotCount(); |
if (slots > 0) { |
if (FLAG_debug_code) { |
- __ Subu(sp, sp, Operand(slots * kPointerSize)); |
+ __ Dsubu(sp, sp, Operand(slots * kPointerSize)); |
__ Push(a0, a1); |
- __ Addu(a0, sp, Operand(slots * kPointerSize)); |
+ __ Daddu(a0, sp, Operand(slots * kPointerSize)); |
__ li(a1, Operand(kSlotsZapValue)); |
Label loop; |
__ bind(&loop); |
- __ Subu(a0, a0, Operand(kPointerSize)); |
- __ sw(a1, MemOperand(a0, 2 * kPointerSize)); |
+ __ Dsubu(a0, a0, Operand(kPointerSize)); |
+ __ sd(a1, MemOperand(a0, 2 * kPointerSize)); |
__ Branch(&loop, ne, a0, Operand(sp)); |
__ Pop(a0, a1); |
} else { |
- __ Subu(sp, sp, Operand(slots * kPointerSize)); |
+ __ Dsubu(sp, sp, Operand(slots * kPointerSize)); |
} |
} |
@@ -213,7 +190,7 @@ bool LCodeGen::GeneratePrologue() { |
// Context is returned in both v0. It replaces the context passed to us. |
// It's saved in the stack and kept live in cp. |
__ mov(cp, v0); |
- __ sw(v0, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
+ __ sd(v0, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
// Copy any necessary parameters into the context. |
int num_parameters = scope()->num_parameters(); |
for (int i = 0; i < num_parameters; i++) { |
@@ -222,10 +199,10 @@ bool LCodeGen::GeneratePrologue() { |
int parameter_offset = StandardFrameConstants::kCallerSPOffset + |
(num_parameters - 1 - i) * kPointerSize; |
// Load parameter from stack. |
- __ lw(a0, MemOperand(fp, parameter_offset)); |
+ __ ld(a0, MemOperand(fp, parameter_offset)); |
// Store it in the context. |
MemOperand target = ContextOperand(cp, var->index()); |
- __ sw(a0, target); |
+ __ sd(a0, target); |
// Update the write barrier. This clobbers a3 and a0. |
if (need_write_barrier) { |
__ RecordWriteContextSlot( |
@@ -262,7 +239,7 @@ void LCodeGen::GenerateOsrPrologue() { |
// optimized frame. |
int slots = GetStackSlotCount() - graph()->osr()->UnoptimizedFrameSlots(); |
ASSERT(slots >= 0); |
- __ Subu(sp, sp, Operand(slots * kPointerSize)); |
+ __ Dsubu(sp, sp, Operand(slots * kPointerSize)); |
} |
@@ -301,7 +278,8 @@ bool LCodeGen::GenerateDeferredCode() { |
__ MultiPush(cp.bit() | fp.bit() | ra.bit()); |
__ li(scratch0(), Operand(Smi::FromInt(StackFrame::STUB))); |
__ push(scratch0()); |
- __ Addu(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); |
+ __ Daddu(fp, sp, |
+ Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); |
Comment(";;; Deferred code"); |
} |
code->Generate(); |
@@ -354,7 +332,8 @@ bool LCodeGen::GenerateDeoptJumpTable() { |
ASSERT(info()->IsStub()); |
__ li(scratch0(), Operand(Smi::FromInt(StackFrame::STUB))); |
__ push(scratch0()); |
- __ Addu(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); |
+ __ Daddu(fp, sp, |
+ Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); |
__ Call(t9); |
} |
} else { |
@@ -419,7 +398,7 @@ Register LCodeGen::EmitLoadRegister(LOperand* op, Register scratch) { |
} |
return scratch; |
} else if (op->IsStackSlot()) { |
- __ lw(scratch, ToMemOperand(op)); |
+ __ ld(scratch, ToMemOperand(op)); |
return scratch; |
} |
UNREACHABLE(); |
@@ -482,17 +461,19 @@ bool LCodeGen::IsSmi(LConstantOperand* op) const { |
int32_t LCodeGen::ToInteger32(LConstantOperand* op) const { |
- return ToRepresentation(op, Representation::Integer32()); |
+ // return ToRepresentation(op, Representation::Integer32()); |
+ HConstant* constant = chunk_->LookupConstant(op); |
+ return constant->Integer32Value(); |
} |
-int32_t LCodeGen::ToRepresentation(LConstantOperand* op, |
+int32_t LCodeGen::ToRepresentation_donotuse(LConstantOperand* op, |
const Representation& r) const { |
HConstant* constant = chunk_->LookupConstant(op); |
int32_t value = constant->Integer32Value(); |
if (r.IsInteger32()) return value; |
ASSERT(r.IsSmiOrTagged()); |
- return reinterpret_cast<int32_t>(Smi::FromInt(value)); |
+ return reinterpret_cast<int64_t>(Smi::FromInt(value)); |
} |
@@ -529,11 +510,11 @@ Operand LCodeGen::ToOperand(LOperand* op) { |
return Operand(ToRegister(op)); |
} else if (op->IsDoubleRegister()) { |
Abort(kToOperandIsDoubleRegisterUnimplemented); |
- return Operand(0); |
+ return Operand((int64_t)0); |
} |
// Stack slots not implemented, use ToMemOperand instead. |
UNREACHABLE(); |
- return Operand(0); |
+ return Operand((int64_t)0); |
} |
@@ -560,12 +541,15 @@ MemOperand LCodeGen::ToMemOperand(LOperand* op) const { |
MemOperand LCodeGen::ToHighMemOperand(LOperand* op) const { |
ASSERT(op->IsDoubleStackSlot()); |
if (NeedsEagerFrame()) { |
- return MemOperand(fp, StackSlotOffset(op->index()) + kPointerSize); |
+ // return MemOperand(fp, StackSlotOffset(op->index()) + kPointerSize); |
+ return MemOperand(fp, StackSlotOffset(op->index()) + kIntSize); |
} else { |
// Retrieve parameter without eager stack-frame relative to the |
// stack-pointer. |
+ // return MemOperand( |
+ // sp, ArgumentsOffsetWithoutFrame(op->index()) + kPointerSize); |
return MemOperand( |
- sp, ArgumentsOffsetWithoutFrame(op->index()) + kPointerSize); |
+ sp, ArgumentsOffsetWithoutFrame(op->index()) + kIntSize); |
} |
} |
@@ -727,7 +711,7 @@ void LCodeGen::LoadContextFromDeferred(LOperand* context) { |
if (context->IsRegister()) { |
__ Move(cp, ToRegister(context)); |
} else if (context->IsStackSlot()) { |
- __ lw(cp, ToMemOperand(context)); |
+ __ ld(cp, ToMemOperand(context)); |
} else if (context->IsConstantOperand()) { |
HConstant* constant = |
chunk_->LookupConstant(LConstantOperand::cast(context)); |
@@ -1096,13 +1080,13 @@ void LCodeGen::DoModByPowerOf2I(LModByPowerOf2I* instr) { |
if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) { |
__ Branch(÷nd_is_not_negative, ge, dividend, Operand(zero_reg)); |
// Note: The code below even works when right contains kMinInt. |
- __ subu(dividend, zero_reg, dividend); |
+ __ dsubu(dividend, zero_reg, dividend); |
__ And(dividend, dividend, Operand(mask)); |
if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
DeoptimizeIf(eq, instr->environment(), dividend, Operand(zero_reg)); |
} |
__ Branch(USE_DELAY_SLOT, &done); |
- __ subu(dividend, zero_reg, dividend); |
+ __ dsubu(dividend, zero_reg, dividend); |
} |
__ bind(÷nd_is_not_negative); |
@@ -1123,8 +1107,8 @@ void LCodeGen::DoModByConstI(LModByConstI* instr) { |
} |
__ TruncatingDiv(result, dividend, Abs(divisor)); |
- __ Mul(result, result, Operand(Abs(divisor))); |
- __ Subu(result, dividend, Operand(result)); |
+ __ Dmul(result, result, Operand(Abs(divisor))); |
+ __ Dsubu(result, dividend, Operand(result)); |
// Check for negative zero. |
HMod* hmod = instr->hydrogen(); |
@@ -1144,7 +1128,7 @@ void LCodeGen::DoModI(LModI* instr) { |
const Register result_reg = ToRegister(instr->result()); |
// div runs in the background while we check for special cases. |
- __ div(left_reg, right_reg); |
+ __ ddiv(left_reg, right_reg); |
Label done; |
// Check for x % 0, we have to deopt in this case because we can't return a |
@@ -1171,6 +1155,7 @@ void LCodeGen::DoModI(LModI* instr) { |
// If we care about -0, test if the dividend is <0 and the result is 0. |
__ Branch(USE_DELAY_SLOT, &done, ge, left_reg, Operand(zero_reg)); |
__ mfhi(result_reg); |
+ |
if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
DeoptimizeIf(eq, instr->environment(), result_reg, Operand(zero_reg)); |
} |
@@ -1203,22 +1188,22 @@ void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { |
} |
if (divisor == -1) { // Nice shortcut, not needed for correctness. |
- __ Subu(result, zero_reg, dividend); |
+ __ Dsubu(result, zero_reg, dividend); |
return; |
} |
uint16_t shift = WhichPowerOf2Abs(divisor); |
if (shift == 0) { |
__ Move(result, dividend); |
} else if (shift == 1) { |
- __ srl(result, dividend, 31); |
- __ Addu(result, dividend, Operand(result)); |
+ __ dsrl32(result, dividend, 31); |
+ __ Daddu(result, dividend, Operand(result)); |
} else { |
- __ sra(result, dividend, 31); |
- __ srl(result, result, 32 - shift); |
- __ Addu(result, dividend, Operand(result)); |
+ __ dsra32(result, dividend, 31); |
+ __ dsrl32(result, result, 32 - shift); |
+ __ Daddu(result, dividend, Operand(result)); |
} |
- if (shift > 0) __ sra(result, result, shift); |
- if (divisor < 0) __ Subu(result, zero_reg, result); |
+ if (shift > 0) __ dsra(result, result, shift); |
+ if (divisor < 0) __ Dsubu(result, zero_reg, result); |
} |
@@ -1243,8 +1228,8 @@ void LCodeGen::DoDivByConstI(LDivByConstI* instr) { |
if (divisor < 0) __ Subu(result, zero_reg, result); |
if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { |
- __ Mul(scratch0(), result, Operand(divisor)); |
- __ Subu(scratch0(), scratch0(), dividend); |
+ __ Dmul(scratch0(), result, Operand(divisor)); |
+ __ Dsubu(scratch0(), scratch0(), dividend); |
DeoptimizeIf(ne, instr->environment(), scratch0(), Operand(zero_reg)); |
} |
} |
@@ -1259,7 +1244,7 @@ void LCodeGen::DoDivI(LDivI* instr) { |
// On MIPS div is asynchronous - it will run in the background while we |
// check for special cases. |
- __ div(dividend, divisor); |
+ __ ddiv(dividend, divisor); |
// Check for x / 0. |
if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { |
@@ -1301,7 +1286,7 @@ void LCodeGen::DoMultiplyAddD(LMultiplyAddD* instr) { |
// This is computed in-place. |
ASSERT(addend.is(ToDoubleRegister(instr->result()))); |
- __ madd_d(addend, addend, multiplier, multiplicand); |
+ __ Madd_d(addend, addend, multiplier, multiplicand, double_scratch0()); |
} |
@@ -1322,42 +1307,41 @@ void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) { |
// can simply do an arithmetic right shift. |
uint16_t shift = WhichPowerOf2Abs(divisor); |
if (divisor > 1) { |
- __ sra(result, dividend, shift); |
+ __ dsra(result, dividend, shift); |
return; |
} |
// If the divisor is negative, we have to negate and handle edge cases. |
- |
- // dividend can be the same register as result so save the value of it |
+ // Dividend can be the same register as result so save the value of it |
// for checking overflow. |
__ Move(scratch, dividend); |
- __ Subu(result, zero_reg, dividend); |
+ __ Dsubu(result, zero_reg, dividend); |
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
DeoptimizeIf(eq, instr->environment(), result, Operand(zero_reg)); |
} |
- // Dividing by -1 is basically negation, unless we overflow. |
__ Xor(scratch, scratch, result); |
+ // Dividing by -1 is basically negation, unless we overflow. |
if (divisor == -1) { |
if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { |
- DeoptimizeIf(ge, instr->environment(), scratch, Operand(zero_reg)); |
+ DeoptimizeIf(gt, instr->environment(), result, Operand(kMaxInt)); |
} |
return; |
} |
// If the negation could not overflow, simply shifting is OK. |
if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { |
- __ sra(result, result, shift); |
+ __ dsra(result, result, shift); |
return; |
} |
Label no_overflow, done; |
__ Branch(&no_overflow, lt, scratch, Operand(zero_reg)); |
- __ li(result, Operand(kMinInt / divisor)); |
+ __ li(result, Operand(kMinInt / divisor), CONSTANT_SIZE); |
__ Branch(&done); |
__ bind(&no_overflow); |
- __ sra(result, result, shift); |
+ __ dsra(result, result, shift); |
__ bind(&done); |
} |
@@ -1384,7 +1368,7 @@ void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { |
if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) || |
(divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) { |
__ TruncatingDiv(result, dividend, Abs(divisor)); |
- if (divisor < 0) __ Subu(result, zero_reg, result); |
+ if (divisor < 0) __ Dsubu(result, zero_reg, result); |
return; |
} |
@@ -1396,13 +1380,13 @@ void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { |
__ Branch(&needs_adjustment, divisor > 0 ? lt : gt, |
dividend, Operand(zero_reg)); |
__ TruncatingDiv(result, dividend, Abs(divisor)); |
- if (divisor < 0) __ Subu(result, zero_reg, result); |
+ if (divisor < 0) __ Dsubu(result, zero_reg, result); |
__ jmp(&done); |
__ bind(&needs_adjustment); |
- __ Addu(temp, dividend, Operand(divisor > 0 ? 1 : -1)); |
+ __ Daddu(temp, dividend, Operand(divisor > 0 ? 1 : -1)); |
__ TruncatingDiv(result, temp, Abs(divisor)); |
- if (divisor < 0) __ Subu(result, zero_reg, result); |
- __ Subu(result, result, Operand(1)); |
+ if (divisor < 0) __ Dsubu(result, zero_reg, result); |
+ __ Dsubu(result, result, Operand(1)); |
__ bind(&done); |
} |
@@ -1416,7 +1400,7 @@ void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) { |
// On MIPS div is asynchronous - it will run in the background while we |
// check for special cases. |
- __ div(dividend, divisor); |
+ __ ddiv(dividend, divisor); |
// Check for x / 0. |
if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { |
@@ -1448,7 +1432,7 @@ void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) { |
__ Branch(&done, eq, remainder, Operand(zero_reg), USE_DELAY_SLOT); |
__ Xor(remainder, remainder, Operand(divisor)); |
__ Branch(&done, ge, remainder, Operand(zero_reg)); |
- __ Subu(result, result, Operand(1)); |
+ __ Dsubu(result, result, Operand(1)); |
__ bind(&done); |
} |
@@ -1477,9 +1461,9 @@ void LCodeGen::DoMulI(LMulI* instr) { |
case -1: |
if (overflow) { |
__ SubuAndCheckForOverflow(result, zero_reg, left, scratch); |
- DeoptimizeIf(lt, instr->environment(), scratch, Operand(zero_reg)); |
+ DeoptimizeIf(gt, instr->environment(), scratch, Operand(kMaxInt)); |
} else { |
- __ Subu(result, zero_reg, left); |
+ __ Dsubu(result, zero_reg, left); |
} |
break; |
case 0: |
@@ -1503,25 +1487,25 @@ void LCodeGen::DoMulI(LMulI* instr) { |
if (IsPowerOf2(constant_abs)) { |
int32_t shift = WhichPowerOf2(constant_abs); |
- __ sll(result, left, shift); |
+ __ dsll(result, left, shift); |
// Correct the sign of the result if the constant is negative. |
- if (constant < 0) __ Subu(result, zero_reg, result); |
+ if (constant < 0) __ Dsubu(result, zero_reg, result); |
} else if (IsPowerOf2(constant_abs - 1)) { |
int32_t shift = WhichPowerOf2(constant_abs - 1); |
- __ sll(scratch, left, shift); |
- __ Addu(result, scratch, left); |
+ __ dsll(scratch, left, shift); |
+ __ Daddu(result, scratch, left); |
// Correct the sign of the result if the constant is negative. |
- if (constant < 0) __ Subu(result, zero_reg, result); |
+ if (constant < 0) __ Dsubu(result, zero_reg, result); |
} else if (IsPowerOf2(constant_abs + 1)) { |
int32_t shift = WhichPowerOf2(constant_abs + 1); |
- __ sll(scratch, left, shift); |
- __ Subu(result, scratch, left); |
+ __ dsll(scratch, left, shift); |
+ __ Dsubu(result, scratch, left); |
// Correct the sign of the result if the constant is negative. |
- if (constant < 0) __ Subu(result, zero_reg, result); |
+ if (constant < 0) __ Dsubu(result, zero_reg, result); |
} else { |
// Generate standard code. |
__ li(at, constant); |
- __ Mul(result, left, at); |
+ __ Dmul(result, left, at); |
} |
} |
@@ -1533,22 +1517,26 @@ void LCodeGen::DoMulI(LMulI* instr) { |
// hi:lo = left * right. |
if (instr->hydrogen()->representation().IsSmi()) { |
__ SmiUntag(result, left); |
- __ mult(result, right); |
+ __ dmult(result, right); |
__ mfhi(scratch); |
__ mflo(result); |
} else { |
- __ mult(left, right); |
+ __ dmult(left, right); |
__ mfhi(scratch); |
__ mflo(result); |
} |
- __ sra(at, result, 31); |
+ __ dsra32(at, result, 31); |
DeoptimizeIf(ne, instr->environment(), scratch, Operand(at)); |
+ if (!instr->hydrogen()->representation().IsSmi()) { |
+ DeoptimizeIf(gt, instr->environment(), result, Operand(kMaxInt)); |
+ DeoptimizeIf(lt, instr->environment(), result, Operand(kMinInt)); |
+ } |
} else { |
if (instr->hydrogen()->representation().IsSmi()) { |
__ SmiUntag(result, left); |
- __ Mul(result, result, right); |
+ __ Dmul(result, result, right); |
} else { |
- __ Mul(result, left, right); |
+ __ Dmul(result, left, right); |
} |
} |
@@ -1609,7 +1597,6 @@ void LCodeGen::DoShiftI(LShiftI* instr) { |
LOperand* right_op = instr->right(); |
Register left = ToRegister(instr->left()); |
Register result = ToRegister(instr->result()); |
- Register scratch = scratch0(); |
if (right_op->IsRegister()) { |
// No need to mask the right operand on MIPS, it is built into the variable |
@@ -1624,7 +1611,9 @@ void LCodeGen::DoShiftI(LShiftI* instr) { |
case Token::SHR: |
__ srlv(result, left, ToRegister(right_op)); |
if (instr->can_deopt()) { |
- DeoptimizeIf(lt, instr->environment(), result, Operand(zero_reg)); |
+ // TODO(yy): (-1) >>> 0. anything else? |
+ DeoptimizeIf(lt, instr->environment(), result, Operand(zero_reg)); |
+ DeoptimizeIf(gt, instr->environment(), result, Operand(kMaxInt)); |
} |
break; |
case Token::SHL: |
@@ -1666,15 +1655,8 @@ void LCodeGen::DoShiftI(LShiftI* instr) { |
break; |
case Token::SHL: |
if (shift_count != 0) { |
- if (instr->hydrogen_value()->representation().IsSmi() && |
- instr->can_deopt()) { |
- if (shift_count != 1) { |
- __ sll(result, left, shift_count - 1); |
- __ SmiTagCheckOverflow(result, result, scratch); |
- } else { |
- __ SmiTagCheckOverflow(result, left, scratch); |
- } |
- DeoptimizeIf(lt, instr->environment(), scratch, Operand(zero_reg)); |
+ if (instr->hydrogen_value()->representation().IsSmi()) { |
+ __ dsll(result, left, shift_count); |
} else { |
__ sll(result, left, shift_count); |
} |
@@ -1699,10 +1681,10 @@ void LCodeGen::DoSubI(LSubI* instr) { |
if (!can_overflow) { |
if (right->IsStackSlot()) { |
Register right_reg = EmitLoadRegister(right, at); |
- __ Subu(ToRegister(result), ToRegister(left), Operand(right_reg)); |
+ __ Dsubu(ToRegister(result), ToRegister(left), Operand(right_reg)); |
} else { |
ASSERT(right->IsRegister() || right->IsConstantOperand()); |
- __ Subu(ToRegister(result), ToRegister(left), ToOperand(right)); |
+ __ Dsubu(ToRegister(result), ToRegister(left), ToOperand(right)); |
} |
} else { // can_overflow. |
Register overflow = scratch0(); |
@@ -1723,6 +1705,12 @@ void LCodeGen::DoSubI(LSubI* instr) { |
overflow); // Reg at also used as scratch. |
} |
DeoptimizeIf(lt, instr->environment(), overflow, Operand(zero_reg)); |
+ if (!instr->hydrogen()->representation().IsSmi()) { |
+ DeoptimizeIf(gt, instr->environment(), |
+ ToRegister(result), Operand(kMaxInt)); |
+ DeoptimizeIf(lt, instr->environment(), |
+ ToRegister(result), Operand(kMinInt)); |
+ } |
} |
} |
@@ -1781,15 +1769,15 @@ void LCodeGen::DoDateField(LDateField* instr) { |
DeoptimizeIf(ne, instr->environment(), scratch, Operand(JS_DATE_TYPE)); |
if (index->value() == 0) { |
- __ lw(result, FieldMemOperand(object, JSDate::kValueOffset)); |
+ __ ld(result, FieldMemOperand(object, JSDate::kValueOffset)); |
} else { |
if (index->value() < JSDate::kFirstUncachedField) { |
ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); |
__ li(scratch, Operand(stamp)); |
- __ lw(scratch, MemOperand(scratch)); |
- __ lw(scratch0(), FieldMemOperand(object, JSDate::kCacheStampOffset)); |
+ __ ld(scratch, MemOperand(scratch)); |
+ __ ld(scratch0(), FieldMemOperand(object, JSDate::kCacheStampOffset)); |
__ Branch(&runtime, ne, scratch, Operand(scratch0())); |
- __ lw(result, FieldMemOperand(object, JSDate::kValueOffset + |
+ __ ld(result, FieldMemOperand(object, JSDate::kValueOffset + |
kPointerSize * index->value())); |
__ jmp(&done); |
} |
@@ -1817,11 +1805,11 @@ MemOperand LCodeGen::BuildSeqStringOperand(Register string, |
ASSERT(!scratch.is(string)); |
ASSERT(!scratch.is(ToRegister(index))); |
if (encoding == String::ONE_BYTE_ENCODING) { |
- __ Addu(scratch, string, ToRegister(index)); |
+ __ Daddu(scratch, string, ToRegister(index)); |
} else { |
STATIC_ASSERT(kUC16Size == 2); |
- __ sll(scratch, ToRegister(index), 1); |
- __ Addu(scratch, string, scratch); |
+ __ dsll(scratch, ToRegister(index), 1); |
+ __ Daddu(scratch, string, scratch); |
} |
return FieldMemOperand(scratch, SeqString::kHeaderSize); |
} |
@@ -1834,14 +1822,14 @@ void LCodeGen::DoSeqStringGetChar(LSeqStringGetChar* instr) { |
if (FLAG_debug_code) { |
Register scratch = scratch0(); |
- __ lw(scratch, FieldMemOperand(string, HeapObject::kMapOffset)); |
+ __ ld(scratch, FieldMemOperand(string, HeapObject::kMapOffset)); |
__ lbu(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); |
__ And(scratch, scratch, |
Operand(kStringRepresentationMask | kStringEncodingMask)); |
static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag; |
static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; |
- __ Subu(at, scratch, Operand(encoding == String::ONE_BYTE_ENCODING |
+ __ Dsubu(at, scratch, Operand(encoding == String::ONE_BYTE_ENCODING |
? one_byte_seq_type : two_byte_seq_type)); |
__ Check(eq, kUnexpectedStringType, at, Operand(zero_reg)); |
} |
@@ -1889,10 +1877,10 @@ void LCodeGen::DoAddI(LAddI* instr) { |
if (!can_overflow) { |
if (right->IsStackSlot()) { |
Register right_reg = EmitLoadRegister(right, at); |
- __ Addu(ToRegister(result), ToRegister(left), Operand(right_reg)); |
+ __ Daddu(ToRegister(result), ToRegister(left), Operand(right_reg)); |
} else { |
ASSERT(right->IsRegister() || right->IsConstantOperand()); |
- __ Addu(ToRegister(result), ToRegister(left), ToOperand(right)); |
+ __ Daddu(ToRegister(result), ToRegister(left), ToOperand(right)); |
} |
} else { // can_overflow. |
Register overflow = scratch0(); |
@@ -1914,6 +1902,13 @@ void LCodeGen::DoAddI(LAddI* instr) { |
overflow); // Reg at also used as scratch. |
} |
DeoptimizeIf(lt, instr->environment(), overflow, Operand(zero_reg)); |
+ // if not smi, it must int32. |
+ if (!instr->hydrogen()->representation().IsSmi()) { |
+ DeoptimizeIf(gt, instr->environment(), |
+ ToRegister(result), Operand(kMaxInt)); |
+ DeoptimizeIf(lt, instr->environment(), |
+ ToRegister(result), Operand(kMinInt)); |
+ } |
} |
} |
@@ -2141,7 +2136,7 @@ void LCodeGen::DoBranch(LBranch* instr) { |
EmitBranchF(instr, nue, dbl_scratch, kDoubleRegZero); |
} else if (type.IsString()) { |
ASSERT(!info()->IsStub()); |
- __ lw(at, FieldMemOperand(reg, String::kLengthOffset)); |
+ __ ld(at, FieldMemOperand(reg, String::kLengthOffset)); |
EmitBranch(instr, ne, at, Operand(zero_reg)); |
} else { |
ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); |
@@ -2178,7 +2173,7 @@ void LCodeGen::DoBranch(LBranch* instr) { |
const Register map = scratch0(); |
if (expected.NeedsMap()) { |
- __ lw(map, FieldMemOperand(reg, HeapObject::kMapOffset)); |
+ __ ld(map, FieldMemOperand(reg, HeapObject::kMapOffset)); |
if (expected.CanBeUndetectable()) { |
// Undetectable -> false. |
__ lbu(at, FieldMemOperand(map, Map::kBitFieldOffset)); |
@@ -2199,7 +2194,7 @@ void LCodeGen::DoBranch(LBranch* instr) { |
Label not_string; |
__ lbu(at, FieldMemOperand(map, Map::kInstanceTypeOffset)); |
__ Branch(¬_string, ge , at, Operand(FIRST_NONSTRING_TYPE)); |
- __ lw(at, FieldMemOperand(reg, String::kLengthOffset)); |
+ __ ld(at, FieldMemOperand(reg, String::kLengthOffset)); |
__ Branch(instr->TrueLabel(chunk_), ne, at, Operand(zero_reg)); |
__ Branch(instr->FalseLabel(chunk_)); |
__ bind(¬_string); |
@@ -2310,8 +2305,7 @@ void LCodeGen::DoCompareNumericAndBranch(LCompareNumericAndBranch* instr) { |
EmitBranchF(instr, cond, left_reg, right_reg); |
} else { |
Register cmp_left; |
- Operand cmp_right = Operand(0); |
- |
+ Operand cmp_right = Operand((int64_t)0); |
if (right->IsConstantOperand()) { |
int32_t value = ToInteger32(LConstantOperand::cast(right)); |
if (instr->hydrogen_value()->representation().IsSmi()) { |
@@ -2324,8 +2318,8 @@ void LCodeGen::DoCompareNumericAndBranch(LCompareNumericAndBranch* instr) { |
} else if (left->IsConstantOperand()) { |
int32_t value = ToInteger32(LConstantOperand::cast(left)); |
if (instr->hydrogen_value()->representation().IsSmi()) { |
- cmp_left = ToRegister(right); |
- cmp_right = Operand(Smi::FromInt(value)); |
+ cmp_left = ToRegister(right); |
+ cmp_right = Operand(Smi::FromInt(value)); |
} else { |
cmp_left = ToRegister(right); |
cmp_right = Operand(value); |
@@ -2377,6 +2371,9 @@ void LCodeGen::DoCompareMinusZeroAndBranch(LCompareMinusZeroAndBranch* instr) { |
DoubleRegister value = ToDoubleRegister(instr->value()); |
EmitFalseBranchF(instr, ne, value, kDoubleRegZero); |
__ FmoveHigh(scratch, value); |
+ // Only use low 32-bits of value. |
+ __ dsll32(scratch, scratch, 0); |
+ __ dsrl32(scratch, scratch, 0); |
__ li(at, 0x80000000); |
} else { |
Register value = ToRegister(instr->value()); |
@@ -2385,9 +2382,9 @@ void LCodeGen::DoCompareMinusZeroAndBranch(LCompareMinusZeroAndBranch* instr) { |
Heap::kHeapNumberMapRootIndex, |
instr->FalseLabel(chunk()), |
DO_SMI_CHECK); |
- __ lw(scratch, FieldMemOperand(value, HeapNumber::kExponentOffset)); |
+ __ lwu(scratch, FieldMemOperand(value, HeapNumber::kExponentOffset)); |
EmitFalseBranch(instr, ne, scratch, Operand(0x80000000)); |
- __ lw(scratch, FieldMemOperand(value, HeapNumber::kMantissaOffset)); |
+ __ lwu(scratch, FieldMemOperand(value, HeapNumber::kMantissaOffset)); |
__ mov(at, zero_reg); |
} |
EmitBranch(instr, eq, scratch, Operand(at)); |
@@ -2405,7 +2402,7 @@ Condition LCodeGen::EmitIsObject(Register input, |
__ Branch(is_object, eq, input, Operand(temp2)); |
// Load map. |
- __ lw(temp1, FieldMemOperand(input, HeapObject::kMapOffset)); |
+ __ ld(temp1, FieldMemOperand(input, HeapObject::kMapOffset)); |
// Undetectable objects behave like undefined. |
__ lbu(temp2, FieldMemOperand(temp1, Map::kBitFieldOffset)); |
__ And(temp2, temp2, Operand(1 << Map::kIsUndetectable)); |
@@ -2476,7 +2473,7 @@ void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { |
if (!instr->hydrogen()->value()->type().IsHeapObject()) { |
__ JumpIfSmi(input, instr->FalseLabel(chunk_)); |
} |
- __ lw(temp, FieldMemOperand(input, HeapObject::kMapOffset)); |
+ __ ld(temp, FieldMemOperand(input, HeapObject::kMapOffset)); |
__ lbu(temp, FieldMemOperand(temp, Map::kBitFieldOffset)); |
__ And(at, temp, Operand(1 << Map::kIsUndetectable)); |
EmitBranch(instr, ne, at, Operand(zero_reg)); |
@@ -2558,7 +2555,7 @@ void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { |
__ AssertString(input); |
- __ lw(result, FieldMemOperand(input, String::kHashFieldOffset)); |
+ __ lwu(result, FieldMemOperand(input, String::kHashFieldOffset)); |
__ IndexFromHash(result, result); |
} |
@@ -2568,7 +2565,7 @@ void LCodeGen::DoHasCachedArrayIndexAndBranch( |
Register input = ToRegister(instr->value()); |
Register scratch = scratch0(); |
- __ lw(scratch, |
+ __ lwu(scratch, |
FieldMemOperand(input, String::kHashFieldOffset)); |
__ And(at, scratch, Operand(String::kContainsCachedArrayIndexMask)); |
EmitBranch(instr, eq, at, Operand(zero_reg)); |
@@ -2607,14 +2604,14 @@ void LCodeGen::EmitClassOfTest(Label* is_true, |
// Faster code path to avoid two compares: subtract lower bound from the |
// actual type and do a signed compare with the width of the type range. |
__ GetObjectType(input, temp, temp2); |
- __ Subu(temp2, temp2, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
+ __ Dsubu(temp2, temp2, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
__ Branch(is_false, gt, temp2, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE - |
FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
} |
// Now we are in the FIRST-LAST_NONCALLABLE_SPEC_OBJECT_TYPE range. |
// Check if the constructor in the map is a function. |
- __ lw(temp, FieldMemOperand(temp, Map::kConstructorOffset)); |
+ __ ld(temp, FieldMemOperand(temp, Map::kConstructorOffset)); |
// Objects with a non-function constructor have class 'Object'. |
__ GetObjectType(temp, temp2, temp2); |
@@ -2626,8 +2623,8 @@ void LCodeGen::EmitClassOfTest(Label* is_true, |
// temp now contains the constructor function. Grab the |
// instance class name from there. |
- __ lw(temp, FieldMemOperand(temp, JSFunction::kSharedFunctionInfoOffset)); |
- __ lw(temp, FieldMemOperand(temp, |
+ __ ld(temp, FieldMemOperand(temp, JSFunction::kSharedFunctionInfoOffset)); |
+ __ ld(temp, FieldMemOperand(temp, |
SharedFunctionInfo::kInstanceClassNameOffset)); |
// The class name we are testing against is internalized since it's a literal. |
// The name in the constructor is internalized because of the way the context |
@@ -2658,7 +2655,7 @@ void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { |
Register reg = ToRegister(instr->value()); |
Register temp = ToRegister(instr->temp()); |
- __ lw(temp, FieldMemOperand(reg, HeapObject::kMapOffset)); |
+ __ ld(temp, FieldMemOperand(reg, HeapObject::kMapOffset)); |
EmitBranch(instr, eq, temp, Operand(instr->map())); |
} |
@@ -2719,7 +2716,7 @@ void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { |
// instanceof stub. |
Label cache_miss; |
Register map = temp; |
- __ lw(map, FieldMemOperand(object, HeapObject::kMapOffset)); |
+ __ ld(map, FieldMemOperand(object, HeapObject::kMapOffset)); |
Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); |
__ bind(deferred->map_check()); // Label for calculating code patching. |
@@ -2728,12 +2725,12 @@ void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { |
// the cached map. |
Handle<Cell> cell = factory()->NewCell(factory()->the_hole_value()); |
__ li(at, Operand(Handle<Object>(cell))); |
- __ lw(at, FieldMemOperand(at, PropertyCell::kValueOffset)); |
+ __ ld(at, FieldMemOperand(at, PropertyCell::kValueOffset)); |
__ BranchShort(&cache_miss, ne, map, Operand(at)); |
// We use Factory::the_hole_value() on purpose instead of loading from the |
// root array to force relocation to be able to later patch |
// with true or false. The distance from map check has to be constant. |
- __ li(result, Operand(factory()->the_hole_value()), CONSTANT_SIZE); |
+ __ li(result, Operand(factory()->the_hole_value())); |
__ Branch(&done); |
// The inlined call site cache did not match. Check null and string before |
@@ -2777,19 +2774,19 @@ void LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, |
PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
LoadContextFromDeferred(instr->context()); |
- // Get the temp register reserved by the instruction. This needs to be t0 as |
+ // Get the temp register reserved by the instruction. This needs to be a4 as |
// its slot of the pushing of safepoint registers is used to communicate the |
// offset to the location of the map check. |
Register temp = ToRegister(instr->temp()); |
- ASSERT(temp.is(t0)); |
+ ASSERT(temp.is(a4)); |
__ li(InstanceofStub::right(), instr->function()); |
- static const int kAdditionalDelta = 7; |
+ static const int kAdditionalDelta = 13; |
int delta = masm_->InstructionsGeneratedSince(map_check) + kAdditionalDelta; |
Label before_push_delta; |
__ bind(&before_push_delta); |
{ |
Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); |
- __ li(temp, Operand(delta * kPointerSize), CONSTANT_SIZE); |
+ __ li(temp, Operand(delta * kIntSize), CONSTANT_SIZE); |
__ StoreToSafepointRegisterSlot(temp, temp); |
} |
CallCodeGeneric(stub.GetCode(), |
@@ -2833,7 +2830,7 @@ void LCodeGen::DoReturn(LReturn* instr) { |
// managed by the register allocator and tearing down the frame, it's |
// safe to write to the context register. |
__ push(v0); |
- __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
+ __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
__ CallRuntime(Runtime::kTraceExit, 1); |
} |
if (info()->saves_caller_doubles()) { |
@@ -2849,14 +2846,14 @@ void LCodeGen::DoReturn(LReturn* instr) { |
int parameter_count = ToInteger32(instr->constant_parameter_count()); |
int32_t sp_delta = (parameter_count + 1) * kPointerSize; |
if (sp_delta != 0) { |
- __ Addu(sp, sp, Operand(sp_delta)); |
+ __ Daddu(sp, sp, Operand(sp_delta)); |
} |
} else { |
Register reg = ToRegister(instr->parameter_count()); |
// The argument count parameter is a smi |
__ SmiUntag(reg); |
- __ sll(at, reg, kPointerSizeLog2); |
- __ Addu(sp, sp, at); |
+ __ dsll(at, reg, kPointerSizeLog2); |
+ __ Daddu(sp, sp, at); |
} |
__ Jump(ra); |
@@ -2870,7 +2867,7 @@ void LCodeGen::DoReturn(LReturn* instr) { |
void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) { |
Register result = ToRegister(instr->result()); |
__ li(at, Operand(Handle<Object>(instr->hydrogen()->cell().handle()))); |
- __ lw(result, FieldMemOperand(at, Cell::kValueOffset)); |
+ __ ld(result, FieldMemOperand(at, Cell::kValueOffset)); |
if (instr->hydrogen()->RequiresHoleCheck()) { |
__ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
DeoptimizeIf(eq, instr->environment(), result, Operand(at)); |
@@ -2904,23 +2901,22 @@ void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { |
if (instr->hydrogen()->RequiresHoleCheck()) { |
// We use a temp to check the payload. |
Register payload = ToRegister(instr->temp()); |
- __ lw(payload, FieldMemOperand(cell, Cell::kValueOffset)); |
+ __ ld(payload, FieldMemOperand(cell, Cell::kValueOffset)); |
__ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
DeoptimizeIf(eq, instr->environment(), payload, Operand(at)); |
} |
// Store the value. |
- __ sw(value, FieldMemOperand(cell, Cell::kValueOffset)); |
+ __ sd(value, FieldMemOperand(cell, Cell::kValueOffset)); |
// Cells are always rescanned, so no write barrier here. |
} |
- |
void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { |
Register context = ToRegister(instr->context()); |
Register result = ToRegister(instr->result()); |
- __ lw(result, ContextOperand(context, instr->slot_index())); |
+ __ ld(result, ContextOperand(context, instr->slot_index())); |
if (instr->hydrogen()->RequiresHoleCheck()) { |
__ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
@@ -2945,7 +2941,7 @@ void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { |
Label skip_assignment; |
if (instr->hydrogen()->RequiresHoleCheck()) { |
- __ lw(scratch, target); |
+ __ ld(scratch, target); |
__ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
if (instr->hydrogen()->DeoptimizesOnHole()) { |
@@ -2955,7 +2951,7 @@ void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { |
} |
} |
- __ sw(value, target); |
+ __ sd(value, target); |
if (instr->hydrogen()->NeedsWriteBarrier()) { |
SmiCheck check_needed = |
instr->hydrogen()->value()->type().IsHeapObject() |
@@ -2978,7 +2974,6 @@ void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { |
HObjectAccess access = instr->hydrogen()->access(); |
int offset = access.offset(); |
Register object = ToRegister(instr->object()); |
- |
if (access.IsExternalMemory()) { |
Register result = ToRegister(instr->result()); |
MemOperand operand = MemOperand(object, offset); |
@@ -2994,11 +2989,27 @@ void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { |
Register result = ToRegister(instr->result()); |
if (!access.IsInobject()) { |
- __ lw(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
+ __ ld(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
object = result; |
} |
- MemOperand operand = FieldMemOperand(object, offset); |
- __ Load(result, operand, access.representation()); |
+ |
+ Representation representation = access.representation(); |
+ if (representation.IsSmi() && SmiValuesAre32Bits() && |
+ instr->hydrogen()->representation().IsInteger32()) { |
+ if (FLAG_debug_code) { |
+ // Verify this is really an Smi. |
+ Register scratch = scratch0(); |
+ __ Load(scratch, FieldMemOperand(object, offset), representation); |
+ __ AssertSmi(scratch); |
+ } |
+ |
+ // Read int value directly from upper half of the smi. |
+ STATIC_ASSERT(kSmiTag == 0); |
+ STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 32); |
+ offset += kPointerSize / 2; |
+ representation = Representation::Integer32(); |
+ } |
+ __ Load(result, FieldMemOperand(object, offset), representation); |
} |
@@ -3031,7 +3042,7 @@ void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { |
__ Branch(&non_instance, ne, scratch, Operand(zero_reg)); |
// Get the prototype or initial map from the function. |
- __ lw(result, |
+ __ ld(result, |
FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); |
// Check that the function has a prototype or an initial map. |
@@ -3044,13 +3055,13 @@ void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { |
__ Branch(&done, ne, scratch, Operand(MAP_TYPE)); |
// Get the prototype from the initial map. |
- __ lw(result, FieldMemOperand(result, Map::kPrototypeOffset)); |
+ __ ld(result, FieldMemOperand(result, Map::kPrototypeOffset)); |
__ Branch(&done); |
// Non-instance prototype: Fetch prototype from constructor field |
// in initial map. |
__ bind(&non_instance); |
- __ lw(result, FieldMemOperand(result, Map::kConstructorOffset)); |
+ __ ld(result, FieldMemOperand(result, Map::kConstructorOffset)); |
// All done. |
__ bind(&done); |
@@ -3073,37 +3084,37 @@ void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { |
if (instr->index()->IsConstantOperand()) { |
int const_index = ToInteger32(LConstantOperand::cast(instr->index())); |
int index = (const_length - const_index) + 1; |
- __ lw(result, MemOperand(arguments, index * kPointerSize)); |
+ __ ld(result, MemOperand(arguments, index * kPointerSize)); |
} else { |
Register index = ToRegister(instr->index()); |
__ li(at, Operand(const_length + 1)); |
- __ Subu(result, at, index); |
- __ sll(at, result, kPointerSizeLog2); |
- __ Addu(at, arguments, at); |
- __ lw(result, MemOperand(at)); |
+ __ Dsubu(result, at, index); |
+ __ dsll(at, result, kPointerSizeLog2); |
+ __ Daddu(at, arguments, at); |
+ __ ld(result, MemOperand(at)); |
} |
} else if (instr->index()->IsConstantOperand()) { |
Register length = ToRegister(instr->length()); |
int const_index = ToInteger32(LConstantOperand::cast(instr->index())); |
int loc = const_index - 1; |
if (loc != 0) { |
- __ Subu(result, length, Operand(loc)); |
- __ sll(at, result, kPointerSizeLog2); |
- __ Addu(at, arguments, at); |
- __ lw(result, MemOperand(at)); |
+ __ Dsubu(result, length, Operand(loc)); |
+ __ dsll(at, result, kPointerSizeLog2); |
+ __ Daddu(at, arguments, at); |
+ __ ld(result, MemOperand(at)); |
} else { |
- __ sll(at, length, kPointerSizeLog2); |
- __ Addu(at, arguments, at); |
- __ lw(result, MemOperand(at)); |
+ __ dsll(at, length, kPointerSizeLog2); |
+ __ Daddu(at, arguments, at); |
+ __ ld(result, MemOperand(at)); |
} |
} else { |
Register length = ToRegister(instr->length()); |
Register index = ToRegister(instr->index()); |
- __ Subu(result, length, index); |
- __ Addu(result, result, 1); |
- __ sll(at, result, kPointerSizeLog2); |
- __ Addu(at, arguments, at); |
- __ lw(result, MemOperand(at)); |
+ __ Dsubu(result, length, index); |
+ __ Daddu(result, result, 1); |
+ __ dsll(at, result, kPointerSizeLog2); |
+ __ Daddu(at, arguments, at); |
+ __ ld(result, MemOperand(at)); |
} |
} |
@@ -3124,7 +3135,8 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) { |
} |
int element_size_shift = ElementsKindToShiftSize(elements_kind); |
int shift_size = (instr->hydrogen()->key()->representation().IsSmi()) |
- ? (element_size_shift - kSmiTagSize) : element_size_shift; |
+ ? (element_size_shift - (kSmiTagSize + kSmiShiftSize)) |
+ : element_size_shift; |
int base_offset = instr->base_offset(); |
if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS || |
@@ -3134,10 +3146,19 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) { |
int base_offset = instr->base_offset(); |
FPURegister result = ToDoubleRegister(instr->result()); |
if (key_is_constant) { |
- __ Addu(scratch0(), external_pointer, constant_key << element_size_shift); |
+ __ Daddu(scratch0(), external_pointer, |
+ constant_key << element_size_shift); |
} else { |
- __ sll(scratch0(), key, shift_size); |
- __ Addu(scratch0(), scratch0(), external_pointer); |
+ if (shift_size < 0) { |
+ if (shift_size == -32) { |
+ __ dsra32(scratch0(), key, 0); |
+ } else { |
+ __ dsra(scratch0(), key, -shift_size); |
+ } |
+ } else { |
+ __ dsll(scratch0(), key, shift_size); |
+ } |
+ __ Daddu(scratch0(), scratch0(), external_pointer); |
} |
if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS || |
elements_kind == FLOAT32_ELEMENTS) { |
@@ -3218,26 +3239,34 @@ void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) { |
} |
base_offset += constant_key * kDoubleSize; |
} |
- __ Addu(scratch, elements, Operand(base_offset)); |
+ __ Daddu(scratch, elements, Operand(base_offset)); |
if (!key_is_constant) { |
key = ToRegister(instr->key()); |
int shift_size = (instr->hydrogen()->key()->representation().IsSmi()) |
- ? (element_size_shift - kSmiTagSize) : element_size_shift; |
- __ sll(at, key, shift_size); |
- __ Addu(scratch, scratch, at); |
+ ? (element_size_shift - (kSmiTagSize + kSmiShiftSize)) |
+ : element_size_shift; |
+ if (shift_size > 0) { |
+ __ dsll(at, key, shift_size); |
+ } else if (shift_size == -32) { |
+ __ dsra32(at, key, 0); |
+ } else { |
+ __ dsra(at, key, -shift_size); |
+ } |
+ __ Daddu(scratch, scratch, at); |
} |
__ ldc1(result, MemOperand(scratch)); |
if (instr->hydrogen()->RequiresHoleCheck()) { |
- __ lw(scratch, MemOperand(scratch, kHoleNanUpper32Offset)); |
+ __ lw(scratch, MemOperand(scratch, sizeof(kHoleNanLower32))); |
DeoptimizeIf(eq, instr->environment(), scratch, Operand(kHoleNanUpper32)); |
} |
} |
void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { |
+ HLoadKeyed* hinstr = instr->hydrogen(); |
Register elements = ToRegister(instr->elements()); |
Register result = ToRegister(instr->result()); |
Register scratch = scratch0(); |
@@ -3255,17 +3284,34 @@ void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { |
// during bound check elimination with the index argument to the bounds |
// check, which can be tagged, so that case must be handled here, too. |
if (instr->hydrogen()->key()->representation().IsSmi()) { |
- __ sll(scratch, key, kPointerSizeLog2 - kSmiTagSize); |
- __ addu(scratch, elements, scratch); |
+ __ SmiScale(scratch, key, kPointerSizeLog2); |
+ __ daddu(scratch, elements, scratch); |
} else { |
- __ sll(scratch, key, kPointerSizeLog2); |
- __ addu(scratch, elements, scratch); |
+ __ dsll(scratch, key, kPointerSizeLog2); |
+ __ daddu(scratch, elements, scratch); |
} |
} |
- __ lw(result, MemOperand(store_base, offset)); |
+ |
+ Representation representation = hinstr->representation(); |
+ if (representation.IsInteger32() && SmiValuesAre32Bits() && |
+ hinstr->elements_kind() == FAST_SMI_ELEMENTS) { |
+ ASSERT(!hinstr->RequiresHoleCheck()); |
+ if (FLAG_debug_code) { |
+ Register temp = scratch1(); |
+ __ Load(temp, MemOperand(store_base, offset), Representation::Smi()); |
+ __ AssertSmi(temp); |
+ } |
+ |
+ // Read int value directly from upper half of the smi. |
+ STATIC_ASSERT(kSmiTag == 0); |
+ STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 32); |
+ offset += kPointerSize / 2; |
+ } |
+ |
+ __ Load(result, MemOperand(store_base, offset), representation); |
// Check for the hole value. |
- if (instr->hydrogen()->RequiresHoleCheck()) { |
+ if (hinstr->RequiresHoleCheck()) { |
if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) { |
__ SmiTst(result, scratch); |
DeoptimizeIf(ne, instr->environment(), scratch, Operand(zero_reg)); |
@@ -3301,25 +3347,31 @@ MemOperand LCodeGen::PrepareKeyedOperand(Register key, |
if (base_offset == 0) { |
if (shift_size >= 0) { |
- __ sll(scratch0(), key, shift_size); |
- __ Addu(scratch0(), base, scratch0()); |
+ __ dsll(scratch0(), key, shift_size); |
+ __ Daddu(scratch0(), base, scratch0()); |
return MemOperand(scratch0()); |
} else { |
- ASSERT_EQ(-1, shift_size); |
- __ srl(scratch0(), key, 1); |
- __ Addu(scratch0(), base, scratch0()); |
+ if (shift_size == -32) { |
+ __ dsra32(scratch0(), key, 0); |
+ } else { |
+ __ dsra(scratch0(), key, -shift_size); |
+ } |
+ __ Daddu(scratch0(), base, scratch0()); |
return MemOperand(scratch0()); |
} |
} |
if (shift_size >= 0) { |
- __ sll(scratch0(), key, shift_size); |
- __ Addu(scratch0(), base, scratch0()); |
+ __ dsll(scratch0(), key, shift_size); |
+ __ Daddu(scratch0(), base, scratch0()); |
return MemOperand(scratch0(), base_offset); |
} else { |
- ASSERT_EQ(-1, shift_size); |
- __ sra(scratch0(), key, 1); |
- __ Addu(scratch0(), base, scratch0()); |
+ if (shift_size == -32) { |
+ __ dsra32(scratch0(), key, 0); |
+ } else { |
+ __ dsra(scratch0(), key, -shift_size); |
+ } |
+ __ Daddu(scratch0(), base, scratch0()); |
return MemOperand(scratch0(), base_offset); |
} |
} |
@@ -3341,12 +3393,12 @@ void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { |
Register result = ToRegister(instr->result()); |
if (instr->hydrogen()->from_inlined()) { |
- __ Subu(result, sp, 2 * kPointerSize); |
+ __ Dsubu(result, sp, 2 * kPointerSize); |
} else { |
// Check if the calling frame is an arguments adaptor frame. |
Label done, adapted; |
- __ lw(scratch, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
- __ lw(result, MemOperand(scratch, StandardFrameConstants::kContextOffset)); |
+ __ ld(scratch, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
+ __ ld(result, MemOperand(scratch, StandardFrameConstants::kContextOffset)); |
__ Xor(temp, result, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
// Result is the frame pointer for the frame if not adapted and for the real |
@@ -3364,12 +3416,12 @@ void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { |
Label done; |
// If no arguments adaptor frame the number of arguments is fixed. |
- __ Addu(result, zero_reg, Operand(scope()->num_parameters())); |
+ __ Daddu(result, zero_reg, Operand(scope()->num_parameters())); |
__ Branch(&done, eq, fp, Operand(elem)); |
// Arguments adaptor frame present. Get argument length from there. |
- __ lw(result, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
- __ lw(result, |
+ __ ld(result, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
+ __ ld(result, |
MemOperand(result, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
__ SmiUntag(result); |
@@ -3390,19 +3442,23 @@ void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) { |
Label global_object, result_in_receiver; |
if (!instr->hydrogen()->known_function()) { |
- // Do not transform the receiver to object for strict mode |
- // functions. |
- __ lw(scratch, |
+ // Do not transform the receiver to object for strict mode functions. |
+ __ ld(scratch, |
FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset)); |
- __ lw(scratch, |
- FieldMemOperand(scratch, SharedFunctionInfo::kCompilerHintsOffset)); |
// Do not transform the receiver to object for builtins. |
int32_t strict_mode_function_mask = |
- 1 << (SharedFunctionInfo::kStrictModeFunction + kSmiTagSize); |
- int32_t native_mask = 1 << (SharedFunctionInfo::kNative + kSmiTagSize); |
- __ And(scratch, scratch, Operand(strict_mode_function_mask | native_mask)); |
- __ Branch(&result_in_receiver, ne, scratch, Operand(zero_reg)); |
+ 1 << SharedFunctionInfo::kStrictModeBitWithinByte; |
+ int32_t native_mask = 1 << SharedFunctionInfo::kNativeBitWithinByte; |
+ |
+ __ lbu(at, |
+ FieldMemOperand(scratch, SharedFunctionInfo::kStrictModeByteOffset)); |
+ __ And(at, at, Operand(strict_mode_function_mask)); |
+ __ Branch(&result_in_receiver, ne, at, Operand(zero_reg)); |
+ __ lbu(at, |
+ FieldMemOperand(scratch, SharedFunctionInfo::kNativeByteOffset)); |
+ __ And(at, at, Operand(native_mask)); |
+ __ Branch(&result_in_receiver, ne, at, Operand(zero_reg)); |
} |
// Normal function. Replace undefined or null with global receiver. |
@@ -3418,13 +3474,13 @@ void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) { |
__ GetObjectType(receiver, scratch, scratch); |
DeoptimizeIf(lt, instr->environment(), |
scratch, Operand(FIRST_SPEC_OBJECT_TYPE)); |
- |
__ Branch(&result_in_receiver); |
+ |
__ bind(&global_object); |
- __ lw(result, FieldMemOperand(function, JSFunction::kContextOffset)); |
- __ lw(result, |
+ __ ld(result, FieldMemOperand(function, JSFunction::kContextOffset)); |
+ __ ld(result, |
ContextOperand(result, Context::GLOBAL_OBJECT_INDEX)); |
- __ lw(result, |
+ __ ld(result, |
FieldMemOperand(result, GlobalObject::kGlobalProxyOffset)); |
if (result.is(receiver)) { |
@@ -3459,21 +3515,21 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) { |
__ push(receiver); |
__ Move(receiver, length); |
// The arguments are at a one pointer size offset from elements. |
- __ Addu(elements, elements, Operand(1 * kPointerSize)); |
+ __ Daddu(elements, elements, Operand(1 * kPointerSize)); |
// Loop through the arguments pushing them onto the execution |
// stack. |
Label invoke, loop; |
// length is a small non-negative integer, due to the test above. |
__ Branch(USE_DELAY_SLOT, &invoke, eq, length, Operand(zero_reg)); |
- __ sll(scratch, length, 2); |
+ __ dsll(scratch, length, kPointerSizeLog2); |
__ bind(&loop); |
- __ Addu(scratch, elements, scratch); |
- __ lw(scratch, MemOperand(scratch)); |
+ __ Daddu(scratch, elements, scratch); |
+ __ ld(scratch, MemOperand(scratch)); |
__ push(scratch); |
- __ Subu(length, length, Operand(1)); |
+ __ Dsubu(length, length, Operand(1)); |
__ Branch(USE_DELAY_SLOT, &loop, ne, length, Operand(zero_reg)); |
- __ sll(scratch, length, 2); |
+ __ dsll(scratch, length, kPointerSizeLog2); |
__ bind(&invoke); |
ASSERT(instr->HasPointerMap()); |
@@ -3505,7 +3561,7 @@ void LCodeGen::DoDrop(LDrop* instr) { |
void LCodeGen::DoThisFunction(LThisFunction* instr) { |
Register result = ToRegister(instr->result()); |
- __ lw(result, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
+ __ ld(result, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
} |
@@ -3513,7 +3569,7 @@ void LCodeGen::DoContext(LContext* instr) { |
// If there is a non-return use, the context must be moved to a register. |
Register result = ToRegister(instr->result()); |
if (info()->IsOptimizing()) { |
- __ lw(result, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
+ __ ld(result, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
} else { |
// If there is no frame, the context must be in cp. |
ASSERT(result.is(cp)); |
@@ -3549,7 +3605,7 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function, |
} |
// Change context. |
- __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); |
+ __ ld(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); |
// Set r0 to arguments count if adaption is not needed. Assumes that r0 |
// is available to write to at this point. |
@@ -3558,7 +3614,7 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function, |
} |
// Invoke function. |
- __ lw(at, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); |
+ __ ld(at, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); |
__ Call(at); |
// Set up deoptimization. |
@@ -3580,14 +3636,14 @@ void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { |
Register scratch = scratch0(); |
// Deoptimize if not a heap number. |
- __ lw(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); |
+ __ ld(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); |
__ LoadRoot(at, Heap::kHeapNumberMapRootIndex); |
DeoptimizeIf(ne, instr->environment(), scratch, Operand(at)); |
Label done; |
Register exponent = scratch0(); |
scratch = no_reg; |
- __ lw(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); |
+ __ lwu(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); |
// Check the sign of the argument. If the argument is positive, just |
// return it. |
__ Move(result, input); |
@@ -3604,7 +3660,7 @@ void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { |
Register tmp1 = input.is(a1) ? a0 : a1; |
Register tmp2 = input.is(a2) ? a0 : a2; |
Register tmp3 = input.is(a3) ? a0 : a3; |
- Register tmp4 = input.is(t0) ? a0 : t0; |
+ Register tmp4 = input.is(a4) ? a0 : a4; |
// exponent: floating point exponent value. |
@@ -3623,14 +3679,14 @@ void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { |
__ mov(tmp1, v0); |
// Restore input_reg after call to runtime. |
__ LoadFromSafepointRegisterSlot(input, input); |
- __ lw(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); |
+ __ lwu(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); |
__ bind(&allocated); |
// exponent: floating point exponent value. |
// tmp1: allocated heap number. |
__ And(exponent, exponent, Operand(~HeapNumber::kSignMask)); |
__ sw(exponent, FieldMemOperand(tmp1, HeapNumber::kExponentOffset)); |
- __ lw(tmp2, FieldMemOperand(input, HeapNumber::kMantissaOffset)); |
+ __ lwu(tmp2, FieldMemOperand(input, HeapNumber::kMantissaOffset)); |
__ sw(tmp2, FieldMemOperand(tmp1, HeapNumber::kMantissaOffset)); |
__ StoreToSafepointRegisterSlot(tmp1, result); |
@@ -3647,7 +3703,7 @@ void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) { |
Label done; |
__ Branch(USE_DELAY_SLOT, &done, ge, input, Operand(zero_reg)); |
__ mov(result, input); |
- __ subu(result, zero_reg, input); |
+ __ dsubu(result, zero_reg, input); |
// Overflow if result is still negative, i.e. 0x80000000. |
DeoptimizeIf(lt, instr->environment(), result, Operand(zero_reg)); |
__ bind(&done); |
@@ -3709,7 +3765,7 @@ void LCodeGen::DoMathFloor(LMathFloor* instr) { |
// Test for -0. |
Label done; |
__ Branch(&done, ne, result, Operand(zero_reg)); |
- __ mfc1(scratch1, input.high()); |
+ __ mfhc1(scratch1, input); // Get exponent/sign bits. |
__ And(scratch1, scratch1, Operand(HeapNumber::kSignMask)); |
DeoptimizeIf(ne, instr->environment(), scratch1, Operand(zero_reg)); |
__ bind(&done); |
@@ -3725,7 +3781,7 @@ void LCodeGen::DoMathRound(LMathRound* instr) { |
Label done, check_sign_on_zero; |
// Extract exponent bits. |
- __ mfc1(result, input.high()); |
+ __ mfhc1(result, input); |
__ Ext(scratch, |
result, |
HeapNumber::kExponentShift, |
@@ -3755,7 +3811,10 @@ void LCodeGen::DoMathRound(LMathRound* instr) { |
// Check sign of the result: if the sign changed, the input |
// value was in ]0.5, 0[ and the result should be -0. |
- __ mfc1(result, double_scratch0().high()); |
+ __ mfhc1(result, double_scratch0()); |
+ // mfhc1 sign-extends, clear the upper bits. |
+ __ dsll32(result, result, 0); |
+ __ dsrl32(result, result, 0); |
__ Xor(result, result, Operand(scratch)); |
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
// ARM uses 'mi' here, which is 'lt' |
@@ -3785,7 +3844,7 @@ void LCodeGen::DoMathRound(LMathRound* instr) { |
// Test for -0. |
__ Branch(&done, ne, result, Operand(zero_reg)); |
__ bind(&check_sign_on_zero); |
- __ mfc1(scratch, input.high()); |
+ __ mfhc1(scratch, input); // Get exponent/sign bits. |
__ And(scratch, scratch, Operand(HeapNumber::kSignMask)); |
DeoptimizeIf(ne, instr->environment(), scratch, Operand(zero_reg)); |
} |
@@ -3841,9 +3900,9 @@ void LCodeGen::DoPower(LPower* instr) { |
} else if (exponent_type.IsTagged()) { |
Label no_deopt; |
__ JumpIfSmi(a2, &no_deopt); |
- __ lw(t3, FieldMemOperand(a2, HeapObject::kMapOffset)); |
+ __ ld(a7, FieldMemOperand(a2, HeapObject::kMapOffset)); |
__ LoadRoot(at, Heap::kHeapNumberMapRootIndex); |
- DeoptimizeIf(ne, instr->environment(), t3, Operand(at)); |
+ DeoptimizeIf(ne, instr->environment(), a7, Operand(at)); |
__ bind(&no_deopt); |
MathPowStub stub(isolate(), MathPowStub::TAGGED); |
__ CallStub(&stub); |
@@ -3924,7 +3983,7 @@ void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) { |
ASSERT(instr->target()->IsRegister()); |
Register target = ToRegister(instr->target()); |
generator.BeforeCall(__ CallSize(target)); |
- __ Addu(target, target, Operand(Code::kHeaderSize - kHeapObjectTag)); |
+ __ Daddu(target, target, Operand(Code::kHeaderSize - kHeapObjectTag)); |
__ Call(target); |
} |
generator.AfterCall(); |
@@ -3940,10 +3999,10 @@ void LCodeGen::DoCallJSFunction(LCallJSFunction* instr) { |
} |
// Change context. |
- __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); |
+ __ ld(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); |
// Load the code entry address |
- __ lw(at, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); |
+ __ ld(at, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); |
__ Call(at); |
RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); |
@@ -3996,8 +4055,8 @@ void LCodeGen::DoCallNewArray(LCallNewArray* instr) { |
Label packed_case; |
// We might need a change here, |
// look at the first argument. |
- __ lw(t1, MemOperand(sp, 0)); |
- __ Branch(&packed_case, eq, t1, Operand(zero_reg)); |
+ __ ld(a5, MemOperand(sp, 0)); |
+ __ Branch(&packed_case, eq, a5, Operand(zero_reg)); |
ElementsKind holey_kind = GetHoleyElementsKind(kind); |
ArraySingleArgumentConstructorStub stub(isolate(), |
@@ -4026,9 +4085,9 @@ void LCodeGen::DoCallRuntime(LCallRuntime* instr) { |
void LCodeGen::DoStoreCodeEntry(LStoreCodeEntry* instr) { |
Register function = ToRegister(instr->function()); |
Register code_object = ToRegister(instr->code_object()); |
- __ Addu(code_object, code_object, |
+ __ Daddu(code_object, code_object, |
Operand(Code::kHeaderSize - kHeapObjectTag)); |
- __ sw(code_object, |
+ __ sd(code_object, |
FieldMemOperand(function, JSFunction::kCodeEntryOffset)); |
} |
@@ -4038,10 +4097,10 @@ void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) { |
Register base = ToRegister(instr->base_object()); |
if (instr->offset()->IsConstantOperand()) { |
LConstantOperand* offset = LConstantOperand::cast(instr->offset()); |
- __ Addu(result, base, Operand(ToInteger32(offset))); |
+ __ Daddu(result, base, Operand(ToInteger32(offset))); |
} else { |
Register offset = ToRegister(instr->offset()); |
- __ Addu(result, base, offset); |
+ __ Daddu(result, base, offset); |
} |
} |
@@ -4050,10 +4109,10 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { |
Representation representation = instr->representation(); |
Register object = ToRegister(instr->object()); |
- Register scratch = scratch0(); |
+ Register scratch2 = scratch1(); |
+ Register scratch1 = scratch0(); |
HObjectAccess access = instr->hydrogen()->access(); |
int offset = access.offset(); |
- |
if (access.IsExternalMemory()) { |
Register value = ToRegister(instr->value()); |
MemOperand operand = MemOperand(object, offset); |
@@ -4078,13 +4137,13 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { |
if (instr->hydrogen()->has_transition()) { |
Handle<Map> transition = instr->hydrogen()->transition_map(); |
AddDeprecationDependency(transition); |
- __ li(scratch, Operand(transition)); |
- __ sw(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); |
+ __ li(scratch1, Operand(transition)); |
+ __ sd(scratch1, FieldMemOperand(object, HeapObject::kMapOffset)); |
if (instr->hydrogen()->NeedsWriteBarrierForMap()) { |
Register temp = ToRegister(instr->temp()); |
// Update the write barrier for the map field. |
__ RecordWriteForMap(object, |
- scratch, |
+ scratch1, |
temp, |
GetRAState(), |
kSaveFPRegs); |
@@ -4092,39 +4151,38 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { |
} |
// Do the store. |
+ Register destination = object; |
+ if (!access.IsInobject()) { |
+ destination = scratch1; |
+ __ ld(destination, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
+ } |
Register value = ToRegister(instr->value()); |
- if (access.IsInobject()) { |
- MemOperand operand = FieldMemOperand(object, offset); |
- __ Store(value, operand, representation); |
- if (instr->hydrogen()->NeedsWriteBarrier()) { |
- // Update the write barrier for the object for in-object properties. |
- __ RecordWriteField(object, |
- offset, |
- value, |
- scratch, |
- GetRAState(), |
- kSaveFPRegs, |
- EMIT_REMEMBERED_SET, |
- instr->hydrogen()->SmiCheckForWriteBarrier(), |
- instr->hydrogen()->PointersToHereCheckForValue()); |
- } |
- } else { |
- __ lw(scratch, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
- MemOperand operand = FieldMemOperand(scratch, offset); |
- __ Store(value, operand, representation); |
- if (instr->hydrogen()->NeedsWriteBarrier()) { |
- // Update the write barrier for the properties array. |
- // object is used as a scratch register. |
- __ RecordWriteField(scratch, |
- offset, |
- value, |
- object, |
- GetRAState(), |
- kSaveFPRegs, |
- EMIT_REMEMBERED_SET, |
- instr->hydrogen()->SmiCheckForWriteBarrier(), |
- instr->hydrogen()->PointersToHereCheckForValue()); |
+ if (representation.IsSmi() && SmiValuesAre32Bits() && |
+ instr->hydrogen()->value()->representation().IsInteger32()) { |
+ ASSERT(instr->hydrogen()->store_mode() == STORE_TO_INITIALIZED_ENTRY); |
+ if (FLAG_debug_code) { |
+ __ Load(scratch2, FieldMemOperand(destination, offset), representation); |
+ __ AssertSmi(scratch2); |
} |
+ |
+ // Store int value directly to upper half of the smi. |
+ offset += kPointerSize / 2; |
+ representation = Representation::Integer32(); |
+ } |
+ |
+ MemOperand operand = FieldMemOperand(destination, offset); |
+ __ Store(value, operand, representation); |
+ if (instr->hydrogen()->NeedsWriteBarrier()) { |
+ // Update the write barrier for the object for in-object properties. |
+ __ RecordWriteField(destination, |
+ offset, |
+ value, |
+ scratch2, |
+ GetRAState(), |
+ kSaveFPRegs, |
+ EMIT_REMEMBERED_SET, |
+ instr->hydrogen()->SmiCheckForWriteBarrier(), |
+ instr->hydrogen()->PointersToHereCheckForValue()); |
} |
} |
@@ -4143,7 +4201,7 @@ void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { |
void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { |
Condition cc = instr->hydrogen()->allow_equality() ? hi : hs; |
- Operand operand(0); |
+ Operand operand((int64_t)0); |
Register reg; |
if (instr->index()->IsConstantOperand()) { |
operand = ToOperand(instr->index()); |
@@ -4180,7 +4238,8 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { |
} |
int element_size_shift = ElementsKindToShiftSize(elements_kind); |
int shift_size = (instr->hydrogen()->key()->representation().IsSmi()) |
- ? (element_size_shift - kSmiTagSize) : element_size_shift; |
+ ? (element_size_shift - (kSmiTagSize + kSmiShiftSize)) |
+ : element_size_shift; |
int base_offset = instr->base_offset(); |
if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS || |
@@ -4191,14 +4250,22 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { |
FPURegister value(ToDoubleRegister(instr->value())); |
if (key_is_constant) { |
if (constant_key != 0) { |
- __ Addu(address, external_pointer, |
+ __ Daddu(address, external_pointer, |
Operand(constant_key << element_size_shift)); |
} else { |
address = external_pointer; |
} |
} else { |
- __ sll(address, key, shift_size); |
- __ Addu(address, external_pointer, address); |
+ if (shift_size < 0) { |
+ if (shift_size == -32) { |
+ __ dsra32(address, key, 0); |
+ } else { |
+ __ dsra(address, key, -shift_size); |
+ } |
+ } else { |
+ __ dsll(address, key, shift_size); |
+ } |
+ __ Daddu(address, external_pointer, address); |
} |
if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS || |
@@ -4271,14 +4338,20 @@ void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) { |
if (constant_key & 0xF0000000) { |
Abort(kArrayIndexConstantValueTooBig); |
} |
- __ Addu(scratch, elements, |
- Operand((constant_key << element_size_shift) + base_offset)); |
+ __ Daddu(scratch, elements, |
+ Operand((constant_key << element_size_shift) + base_offset)); |
} else { |
int shift_size = (instr->hydrogen()->key()->representation().IsSmi()) |
- ? (element_size_shift - kSmiTagSize) : element_size_shift; |
- __ Addu(scratch, elements, Operand(base_offset)); |
- __ sll(at, ToRegister(instr->key()), shift_size); |
- __ Addu(scratch, scratch, at); |
+ ? (element_size_shift - (kSmiTagSize + kSmiShiftSize)) |
+ : element_size_shift; |
+ __ Daddu(scratch, elements, Operand(base_offset)); |
+ ASSERT((shift_size == 3) || (shift_size == -29)); |
+ if (shift_size == 3) { |
+ __ dsll(at, ToRegister(instr->key()), 3); |
+ } else if (shift_size == -29) { |
+ __ dsra(at, ToRegister(instr->key()), 29); |
+ } |
+ __ Daddu(scratch, scratch, at); |
} |
if (instr->NeedsCanonicalization()) { |
@@ -4322,21 +4395,39 @@ void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { |
// during bound check elimination with the index argument to the bounds |
// check, which can be tagged, so that case must be handled here, too. |
if (instr->hydrogen()->key()->representation().IsSmi()) { |
- __ sll(scratch, key, kPointerSizeLog2 - kSmiTagSize); |
- __ addu(scratch, elements, scratch); |
+ __ SmiScale(scratch, key, kPointerSizeLog2); |
+ __ daddu(store_base, elements, scratch); |
} else { |
- __ sll(scratch, key, kPointerSizeLog2); |
- __ addu(scratch, elements, scratch); |
+ __ dsll(scratch, key, kPointerSizeLog2); |
+ __ daddu(store_base, elements, scratch); |
} |
} |
- __ sw(value, MemOperand(store_base, offset)); |
+ |
+ Representation representation = instr->hydrogen()->value()->representation(); |
+ if (representation.IsInteger32() && SmiValuesAre32Bits()) { |
+ ASSERT(instr->hydrogen()->store_mode() == STORE_TO_INITIALIZED_ENTRY); |
+ ASSERT(instr->hydrogen()->elements_kind() == FAST_SMI_ELEMENTS); |
+ if (FLAG_debug_code) { |
+ Register temp = scratch1(); |
+ __ Load(temp, MemOperand(store_base, offset), Representation::Smi()); |
+ __ AssertSmi(temp); |
+ } |
+ |
+ // Store int value directly to upper half of the smi. |
+ STATIC_ASSERT(kSmiTag == 0); |
+ STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 32); |
+ offset += kPointerSize / 2; |
+ representation = Representation::Integer32(); |
+ } |
+ |
+ __ Store(value, MemOperand(store_base, offset), representation); |
if (instr->hydrogen()->NeedsWriteBarrier()) { |
SmiCheck check_needed = |
instr->hydrogen()->value()->type().IsHeapObject() |
? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
// Compute address of modified element and store it into key register. |
- __ Addu(key, store_base, Operand(offset)); |
+ __ Daddu(key, store_base, Operand(offset)); |
__ RecordWrite(elements, |
key, |
value, |
@@ -4384,13 +4475,13 @@ void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { |
ElementsKind to_kind = instr->to_kind(); |
Label not_applicable; |
- __ lw(scratch, FieldMemOperand(object_reg, HeapObject::kMapOffset)); |
+ __ ld(scratch, FieldMemOperand(object_reg, HeapObject::kMapOffset)); |
__ Branch(¬_applicable, ne, scratch, Operand(from_map)); |
if (IsSimpleMapChangeTransition(from_kind, to_kind)) { |
Register new_map_reg = ToRegister(instr->new_map_temp()); |
__ li(new_map_reg, Operand(to_map)); |
- __ sw(new_map_reg, FieldMemOperand(object_reg, HeapObject::kMapOffset)); |
+ __ sd(new_map_reg, FieldMemOperand(object_reg, HeapObject::kMapOffset)); |
// Write barrier. |
__ RecordWriteForMap(object_reg, |
new_map_reg, |
@@ -4475,7 +4566,7 @@ void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) { |
// DoStringCharCodeAt above. |
if (instr->index()->IsConstantOperand()) { |
int const_index = ToInteger32(LConstantOperand::cast(instr->index())); |
- __ Addu(scratch, zero_reg, Operand(Smi::FromInt(const_index))); |
+ __ Daddu(scratch, zero_reg, Operand(Smi::FromInt(const_index))); |
__ push(scratch); |
} else { |
Register index = ToRegister(instr->index()); |
@@ -4515,9 +4606,9 @@ void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { |
__ Branch(deferred->entry(), hi, |
char_code, Operand(String::kMaxOneByteCharCode)); |
__ LoadRoot(result, Heap::kSingleCharacterStringCacheRootIndex); |
- __ sll(scratch, char_code, kPointerSizeLog2); |
- __ Addu(result, result, scratch); |
- __ lw(result, FieldMemOperand(result, FixedArray::kHeaderSize)); |
+ __ dsll(scratch, char_code, kPointerSizeLog2); |
+ __ Daddu(result, result, scratch); |
+ __ ld(result, FieldMemOperand(result, FixedArray::kHeaderSize)); |
__ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); |
__ Branch(deferred->entry(), eq, result, Operand(scratch)); |
__ bind(deferred->exit()); |
@@ -4549,7 +4640,7 @@ void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { |
FPURegister single_scratch = double_scratch0().low(); |
if (input->IsStackSlot()) { |
Register scratch = scratch0(); |
- __ lw(scratch, ToMemOperand(input)); |
+ __ ld(scratch, ToMemOperand(input)); |
__ mtc1(scratch, single_scratch); |
} else { |
__ mtc1(ToRegister(input), single_scratch); |
@@ -4564,35 +4655,7 @@ void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) { |
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 V8_FINAL : public LDeferredCode { |
- public: |
- DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr) |
- : LDeferredCode(codegen), instr_(instr) { } |
- virtual void Generate() V8_OVERRIDE { |
- codegen()->DoDeferredNumberTagIU(instr_, |
- instr_->value(), |
- instr_->temp1(), |
- instr_->temp2(), |
- SIGNED_INT32); |
- } |
- virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
- private: |
- LNumberTagI* instr_; |
- }; |
- |
- Register src = ToRegister(instr->value()); |
- Register dst = ToRegister(instr->result()); |
- Register overflow = scratch0(); |
- |
- DeferredNumberTagI* deferred = new(zone()) DeferredNumberTagI(this, instr); |
- __ SmiTagCheckOverflow(dst, src, overflow); |
- __ BranchOnOverflow(deferred->entry(), overflow); |
- __ bind(deferred->exit()); |
+ __ Cvt_d_uw(ToDoubleRegister(output), dbl_scratch, f22); // TODO(plind): f22? |
} |
@@ -4653,7 +4716,7 @@ void LCodeGen::DoDeferredNumberTagIU(LInstruction* instr, |
if (FLAG_inline_new) { |
__ LoadRoot(tmp3, Heap::kHeapNumberMapRootIndex); |
- __ AllocateHeapNumber(dst, tmp1, tmp2, tmp3, &slow, DONT_TAG_RESULT); |
+ __ AllocateHeapNumber(dst, tmp1, tmp2, tmp3, &slow, TAG_RESULT); |
__ Branch(&done); |
} |
@@ -4664,7 +4727,6 @@ void LCodeGen::DoDeferredNumberTagIU(LInstruction* instr, |
// result register is stored, as this register is in the pointer map, but |
// contains an integer value. |
__ mov(dst, zero_reg); |
- |
// Preserve the value of all registers. |
PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
@@ -4673,20 +4735,17 @@ void LCodeGen::DoDeferredNumberTagIU(LInstruction* instr, |
// They only call Runtime::kAllocateHeapNumber. |
// The corresponding HChange instructions are added in a phase that does |
// not have easy access to the local context. |
- __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
+ __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
__ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); |
RecordSafepointWithRegisters( |
instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); |
- __ Subu(v0, v0, kHeapObjectTag); |
__ StoreToSafepointRegisterSlot(v0, dst); |
} |
- |
// Done. Put the value in dbl_scratch into the value of the allocated heap |
// number. |
__ bind(&done); |
- __ sdc1(dbl_scratch, MemOperand(dst, HeapNumber::kValueOffset)); |
- __ Addu(dst, dst, kHeapObjectTag); |
+ __ sdc1(dbl_scratch, FieldMemOperand(dst, HeapNumber::kValueOffset)); |
} |
@@ -4721,7 +4780,7 @@ void LCodeGen::DoNumberTagD(LNumberTagD* instr) { |
__ bind(deferred->exit()); |
__ sdc1(input_reg, MemOperand(reg, HeapNumber::kValueOffset)); |
// Now that we have finished with the object's real address tag it |
- __ Addu(reg, reg, kHeapObjectTag); |
+ __ Daddu(reg, reg, kHeapObjectTag); |
} |
@@ -4738,11 +4797,11 @@ void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { |
// They only call Runtime::kAllocateHeapNumber. |
// The corresponding HChange instructions are added in a phase that does |
// not have easy access to the local context. |
- __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
+ __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
__ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); |
RecordSafepointWithRegisters( |
instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); |
- __ Subu(v0, v0, kHeapObjectTag); |
+ __ Dsubu(v0, v0, kHeapObjectTag); |
__ StoreToSafepointRegisterSlot(v0, reg); |
} |
@@ -4753,7 +4812,7 @@ void LCodeGen::DoSmiTag(LSmiTag* instr) { |
Register output = ToRegister(instr->result()); |
if (hchange->CheckFlag(HValue::kCanOverflow) && |
hchange->value()->CheckFlag(HValue::kUint32)) { |
- __ And(at, input, Operand(0xc0000000)); |
+ __ And(at, input, Operand(0x80000000)); |
DeoptimizeIf(ne, instr->environment(), at, Operand(zero_reg)); |
} |
if (hchange->CheckFlag(HValue::kCanOverflow) && |
@@ -4794,7 +4853,7 @@ void LCodeGen::EmitNumberUntagD(Register input_reg, |
// Smi check. |
__ UntagAndJumpIfSmi(scratch, input_reg, &load_smi); |
// Heap number map check. |
- __ lw(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
+ __ ld(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
__ LoadRoot(at, Heap::kHeapNumberMapRootIndex); |
if (can_convert_undefined_to_nan) { |
__ Branch(&convert, ne, scratch, Operand(at)); |
@@ -4804,9 +4863,9 @@ void LCodeGen::EmitNumberUntagD(Register input_reg, |
// Load heap number. |
__ ldc1(result_reg, FieldMemOperand(input_reg, HeapNumber::kValueOffset)); |
if (deoptimize_on_minus_zero) { |
- __ mfc1(at, result_reg.low()); |
+ __ mfc1(at, result_reg); |
__ Branch(&done, ne, at, Operand(zero_reg)); |
- __ mfc1(scratch, result_reg.high()); |
+ __ mfhc1(scratch, result_reg); // Get exponent/sign bits. |
DeoptimizeIf(eq, env, scratch, Operand(HeapNumber::kSignMask)); |
} |
__ Branch(&done); |
@@ -4846,7 +4905,7 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { |
// The input is a tagged HeapObject. |
// Heap number map check. |
- __ lw(scratch1, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
+ __ ld(scratch1, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
__ LoadRoot(at, Heap::kHeapNumberMapRootIndex); |
// This 'at' value and scratch1 map value are used for tests in both clauses |
// of the if. |
@@ -4904,7 +4963,7 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { |
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
__ Branch(&done, ne, input_reg, Operand(zero_reg)); |
- __ mfc1(scratch1, double_scratch.high()); |
+ __ mfhc1(scratch1, double_scratch); // Get exponent/sign bits. |
__ And(scratch1, scratch1, Operand(HeapNumber::kSignMask)); |
DeoptimizeIf(ne, instr->environment(), scratch1, Operand(zero_reg)); |
} |
@@ -4992,7 +5051,7 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) { |
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
Label done; |
__ Branch(&done, ne, result_reg, Operand(zero_reg)); |
- __ mfc1(scratch1, double_input.high()); |
+ __ mfhc1(scratch1, double_input); // Get exponent/sign bits. |
__ And(scratch1, scratch1, Operand(HeapNumber::kSignMask)); |
DeoptimizeIf(ne, instr->environment(), scratch1, Operand(zero_reg)); |
__ bind(&done); |
@@ -5025,14 +5084,13 @@ void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { |
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
Label done; |
__ Branch(&done, ne, result_reg, Operand(zero_reg)); |
- __ mfc1(scratch1, double_input.high()); |
+ __ mfhc1(scratch1, double_input); // Get exponent/sign bits. |
__ And(scratch1, scratch1, Operand(HeapNumber::kSignMask)); |
DeoptimizeIf(ne, instr->environment(), scratch1, Operand(zero_reg)); |
__ bind(&done); |
} |
} |
- __ SmiTagCheckOverflow(result_reg, result_reg, scratch1); |
- DeoptimizeIf(lt, instr->environment(), scratch1, Operand(zero_reg)); |
+ __ SmiTag(result_reg, result_reg); |
} |
@@ -5099,7 +5157,7 @@ void LCodeGen::DoCheckValue(LCheckValue* instr) { |
Register reg = ToRegister(instr->value()); |
Handle<Cell> cell = isolate()->factory()->NewCell(object); |
__ li(at, Operand(Handle<Object>(cell))); |
- __ lw(at, FieldMemOperand(at, Cell::kValueOffset)); |
+ __ ld(at, FieldMemOperand(at, Cell::kValueOffset)); |
DeoptimizeIf(ne, instr->environment(), reg, |
Operand(at)); |
} else { |
@@ -5154,7 +5212,7 @@ void LCodeGen::DoCheckMaps(LCheckMaps* instr) { |
LOperand* input = instr->value(); |
ASSERT(input->IsRegister()); |
Register reg = ToRegister(input); |
- __ lw(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset)); |
+ __ ld(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset)); |
DeferredCheckMaps* deferred = NULL; |
if (instr->hydrogen()->HasMigrationTarget()) { |
@@ -5206,7 +5264,7 @@ void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) { |
__ UntagAndJumpIfSmi(scratch, input_reg, &is_smi); |
// Check for heap number |
- __ lw(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
+ __ ld(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
__ Branch(&heap_number, eq, scratch, Operand(factory()->heap_number_map())); |
// Check for undefined. Undefined is converted to zero for clamping |
@@ -5302,14 +5360,14 @@ void LCodeGen::DoAllocate(LAllocate* instr) { |
int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); |
__ li(scratch, Operand(size - kHeapObjectTag)); |
} else { |
- __ Subu(scratch, ToRegister(instr->size()), Operand(kHeapObjectTag)); |
+ __ Dsubu(scratch, ToRegister(instr->size()), Operand(kHeapObjectTag)); |
} |
__ li(scratch2, Operand(isolate()->factory()->one_pointer_filler_map())); |
Label loop; |
__ bind(&loop); |
- __ Subu(scratch, scratch, Operand(kPointerSize)); |
- __ Addu(at, result, Operand(scratch)); |
- __ sw(scratch2, MemOperand(at)); |
+ __ Dsubu(scratch, scratch, Operand(kPointerSize)); |
+ __ Daddu(at, result, Operand(scratch)); |
+ __ sd(scratch2, MemOperand(at)); |
__ Branch(&loop, ge, scratch, Operand(zero_reg)); |
} |
} |
@@ -5332,7 +5390,8 @@ void LCodeGen::DoDeferredAllocate(LAllocate* instr) { |
} else { |
int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); |
if (size >= 0 && size <= Smi::kMaxValue) { |
- __ Push(Smi::FromInt(size)); |
+ __ li(v0, Operand(Smi::FromInt(size))); |
+ __ Push(v0); |
} else { |
// We should never get here at runtime => abort |
__ stop("invalid allocation size"); |
@@ -5352,7 +5411,8 @@ void LCodeGen::DoDeferredAllocate(LAllocate* instr) { |
} else { |
flags = AllocateTargetSpace::update(flags, NEW_SPACE); |
} |
- __ Push(Smi::FromInt(flags)); |
+ __ li(v0, Operand(Smi::FromInt(flags))); |
+ __ Push(v0); |
CallRuntimeFromDeferred( |
Runtime::kAllocateInTargetSpace, 2, instr, instr->context()); |
@@ -5372,23 +5432,23 @@ void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { |
ASSERT(ToRegister(instr->context()).is(cp)); |
Label materialized; |
// Registers will be used as follows: |
- // t3 = literals array. |
+ // a7 = literals array. |
// a1 = regexp literal. |
// a0 = regexp literal clone. |
- // a2 and t0-t2 are used as temporaries. |
+ // a2 and a4-a6 are used as temporaries. |
int literal_offset = |
FixedArray::OffsetOfElementAt(instr->hydrogen()->literal_index()); |
- __ li(t3, instr->hydrogen()->literals()); |
- __ lw(a1, FieldMemOperand(t3, literal_offset)); |
+ __ li(a7, instr->hydrogen()->literals()); |
+ __ ld(a1, FieldMemOperand(a7, literal_offset)); |
__ LoadRoot(at, Heap::kUndefinedValueRootIndex); |
__ Branch(&materialized, ne, a1, Operand(at)); |
// Create regexp literal using runtime function |
// Result will be in v0. |
- __ li(t2, Operand(Smi::FromInt(instr->hydrogen()->literal_index()))); |
- __ li(t1, Operand(instr->hydrogen()->pattern())); |
- __ li(t0, Operand(instr->hydrogen()->flags())); |
- __ Push(t3, t2, t1, t0); |
+ __ li(a6, Operand(Smi::FromInt(instr->hydrogen()->literal_index()))); |
+ __ li(a5, Operand(instr->hydrogen()->pattern())); |
+ __ li(a4, Operand(instr->hydrogen()->flags())); |
+ __ Push(a7, a6, a5, a4); |
CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr); |
__ mov(a1, v0); |
@@ -5409,14 +5469,14 @@ void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { |
// Copy the content into the newly allocated memory. |
// (Unroll copy loop once for better throughput). |
for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) { |
- __ lw(a3, FieldMemOperand(a1, i)); |
- __ lw(a2, FieldMemOperand(a1, i + kPointerSize)); |
- __ sw(a3, FieldMemOperand(v0, i)); |
- __ sw(a2, FieldMemOperand(v0, i + kPointerSize)); |
+ __ ld(a3, FieldMemOperand(a1, i)); |
+ __ ld(a2, FieldMemOperand(a1, i + kPointerSize)); |
+ __ sd(a3, FieldMemOperand(v0, i)); |
+ __ sd(a2, FieldMemOperand(v0, i + kPointerSize)); |
} |
if ((size % (2 * kPointerSize)) != 0) { |
- __ lw(a3, FieldMemOperand(a1, size - kPointerSize)); |
- __ sw(a3, FieldMemOperand(v0, size - kPointerSize)); |
+ __ ld(a3, FieldMemOperand(a1, size - kPointerSize)); |
+ __ sd(a3, FieldMemOperand(v0, size - kPointerSize)); |
} |
} |
@@ -5486,7 +5546,7 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label, |
Factory* factory = isolate()->factory(); |
if (String::Equals(type_name, factory->number_string())) { |
__ JumpIfSmi(input, true_label); |
- __ lw(input, FieldMemOperand(input, HeapObject::kMapOffset)); |
+ __ ld(input, FieldMemOperand(input, HeapObject::kMapOffset)); |
__ LoadRoot(at, Heap::kHeapNumberMapRootIndex); |
*cmp1 = input; |
*cmp2 = Operand(at); |
@@ -5534,7 +5594,7 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label, |
// slot. |
__ JumpIfSmi(input, false_label); |
// Check for undetectable objects => true. |
- __ lw(input, FieldMemOperand(input, HeapObject::kMapOffset)); |
+ __ ld(input, FieldMemOperand(input, HeapObject::kMapOffset)); |
__ lbu(at, FieldMemOperand(input, Map::kBitFieldOffset)); |
__ And(at, at, 1 << Map::kIsUndetectable); |
*cmp1 = at; |
@@ -5593,18 +5653,18 @@ void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { |
void LCodeGen::EmitIsConstructCall(Register temp1, Register temp2) { |
ASSERT(!temp1.is(temp2)); |
// Get the frame pointer for the calling frame. |
- __ lw(temp1, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
+ __ ld(temp1, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
// Skip the arguments adaptor frame if it exists. |
Label check_frame_marker; |
- __ lw(temp2, MemOperand(temp1, StandardFrameConstants::kContextOffset)); |
+ __ ld(temp2, MemOperand(temp1, StandardFrameConstants::kContextOffset)); |
__ Branch(&check_frame_marker, ne, temp2, |
Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
- __ lw(temp1, MemOperand(temp1, StandardFrameConstants::kCallerFPOffset)); |
+ __ ld(temp1, MemOperand(temp1, StandardFrameConstants::kCallerFPOffset)); |
// Check the marker in the calling frame. |
__ bind(&check_frame_marker); |
- __ lw(temp1, MemOperand(temp1, StandardFrameConstants::kMarkerOffset)); |
+ __ ld(temp1, MemOperand(temp1, StandardFrameConstants::kMarkerOffset)); |
} |
@@ -5739,7 +5799,7 @@ void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { |
__ LoadRoot(at, Heap::kUndefinedValueRootIndex); |
DeoptimizeIf(eq, instr->environment(), object, Operand(at)); |
- Register null_value = t1; |
+ Register null_value = a5; |
__ LoadRoot(null_value, Heap::kNullValueRootIndex); |
DeoptimizeIf(eq, instr->environment(), object, Operand(null_value)); |
@@ -5754,7 +5814,7 @@ void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { |
ASSERT(object.is(a0)); |
__ CheckEnumCache(null_value, &call_runtime); |
- __ lw(result, FieldMemOperand(object, HeapObject::kMapOffset)); |
+ __ ld(result, FieldMemOperand(object, HeapObject::kMapOffset)); |
__ Branch(&use_cache); |
// Get the set of properties to enumerate. |
@@ -5762,7 +5822,7 @@ void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { |
__ push(object); |
CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr); |
- __ lw(a1, FieldMemOperand(v0, HeapObject::kMapOffset)); |
+ __ ld(a1, FieldMemOperand(v0, HeapObject::kMapOffset)); |
ASSERT(result.is(v0)); |
__ LoadRoot(at, Heap::kMetaMapRootIndex); |
DeoptimizeIf(ne, instr->environment(), a1, Operand(at)); |
@@ -5781,9 +5841,9 @@ void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) { |
__ bind(&load_cache); |
__ LoadInstanceDescriptors(map, result); |
- __ lw(result, |
+ __ ld(result, |
FieldMemOperand(result, DescriptorArray::kEnumCacheOffset)); |
- __ lw(result, |
+ __ ld(result, |
FieldMemOperand(result, FixedArray::SizeFor(instr->idx()))); |
DeoptimizeIf(eq, instr->environment(), result, Operand(zero_reg)); |
@@ -5794,7 +5854,7 @@ void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) { |
void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { |
Register object = ToRegister(instr->value()); |
Register map = ToRegister(instr->map()); |
- __ lw(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset)); |
+ __ ld(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset)); |
DeoptimizeIf(ne, instr->environment(), map, Operand(scratch0())); |
} |
@@ -5851,22 +5911,20 @@ void LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) { |
__ And(scratch, index, Operand(Smi::FromInt(1))); |
__ Branch(deferred->entry(), ne, scratch, Operand(zero_reg)); |
- __ sra(index, index, 1); |
+ __ dsra(index, index, 1); |
__ Branch(USE_DELAY_SLOT, &out_of_object, lt, index, Operand(zero_reg)); |
- __ sll(scratch, index, kPointerSizeLog2 - kSmiTagSize); // In delay slot. |
- |
- STATIC_ASSERT(kPointerSizeLog2 > kSmiTagSize); |
- __ Addu(scratch, object, scratch); |
- __ lw(result, FieldMemOperand(scratch, JSObject::kHeaderSize)); |
+ __ SmiScale(scratch, index, kPointerSizeLog2); // In delay slot. |
+ __ Daddu(scratch, object, scratch); |
+ __ ld(result, FieldMemOperand(scratch, JSObject::kHeaderSize)); |
__ Branch(&done); |
__ bind(&out_of_object); |
- __ lw(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
+ __ ld(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
// Index is equal to negated out of object property index plus 1. |
- __ Subu(scratch, result, scratch); |
- __ lw(result, FieldMemOperand(scratch, |
+ __ Dsubu(scratch, result, scratch); |
+ __ ld(result, FieldMemOperand(scratch, |
FixedArray::kHeaderSize - kPointerSize)); |
__ bind(deferred->exit()); |
__ bind(&done); |
@@ -5875,7 +5933,7 @@ void LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) { |
void LCodeGen::DoStoreFrameContext(LStoreFrameContext* instr) { |
Register context = ToRegister(instr->context()); |
- __ sw(context, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
+ __ sd(context, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
} |