| 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));
|
| }
|
|
|
|
|
|
|