Bug 1204194 - IonMonkey: MIPS: Split shareable code to mips-shared in MoveEmitter-mips32. r=nbp

---
 .../MoveEmitter-mips-shared.cpp}                   | 182 ++------------------
 .../MoveEmitter-mips-shared.h}                     |  35 ++--
 js/src/jit/mips32/MoveEmitter-mips32.cpp           | 190 ---------------------
 js/src/jit/mips32/MoveEmitter-mips32.h             |  42 +----
 js/src/moz.build                                   |   1 +
 5 files changed, 39 insertions(+), 411 deletions(-)
 copy js/src/jit/{mips32/MoveEmitter-mips32.cpp => mips-shared/MoveEmitter-mips-shared.cpp} (45%)
 copy js/src/jit/{mips32/MoveEmitter-mips32.h => mips-shared/MoveEmitter-mips-shared.h} (65%)

--HG--
rename : js/src/jit/mips32/MoveEmitter-mips32.cpp => js/src/jit/mips-shared/MoveEmitter-mips-shared.cpp
rename : js/src/jit/mips32/MoveEmitter-mips32.h => js/src/jit/mips-shared/MoveEmitter-mips-shared.h
This commit is contained in:
Heiher 2015-09-16 17:01:24 +08:00
Родитель 65e669153f
Коммит 4d95da1500
5 изменённых файлов: 267 добавлений и 227 удалений

Просмотреть файл

@ -0,0 +1,186 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "jit/mips-shared/MoveEmitter-mips-shared.h"
#include "jit/MacroAssembler-inl.h"
using namespace js;
using namespace js::jit;
void
MoveEmitterMIPSShared::emit(const MoveResolver& moves)
{
if (moves.numCycles()) {
// Reserve stack for cycle resolution
masm.reserveStack(moves.numCycles() * sizeof(double));
pushedAtCycle_ = masm.framePushed();
}
for (size_t i = 0; i < moves.numMoves(); i++)
emit(moves.getMove(i));
}
Address
MoveEmitterMIPSShared::cycleSlot(uint32_t slot, uint32_t subslot) const
{
int32_t offset = masm.framePushed() - pushedAtCycle_;
MOZ_ASSERT(Imm16::IsInSignedRange(offset));
return Address(StackPointer, offset + slot * sizeof(double) + subslot);
}
int32_t
MoveEmitterMIPSShared::getAdjustedOffset(const MoveOperand& operand)
{
MOZ_ASSERT(operand.isMemoryOrEffectiveAddress());
if (operand.base() != StackPointer)
return operand.disp();
// Adjust offset if stack pointer has been moved.
return operand.disp() + masm.framePushed() - pushedAtStart_;
}
Address
MoveEmitterMIPSShared::getAdjustedAddress(const MoveOperand& operand)
{
return Address(operand.base(), getAdjustedOffset(operand));
}
Register
MoveEmitterMIPSShared::tempReg()
{
spilledReg_ = SecondScratchReg;
return SecondScratchReg;
}
void
MoveEmitterMIPSShared::emitMove(const MoveOperand& from, const MoveOperand& to)
{
if (from.isGeneralReg()) {
// Second scratch register should not be moved by MoveEmitter.
MOZ_ASSERT(from.reg() != spilledReg_);
if (to.isGeneralReg())
masm.movePtr(from.reg(), to.reg());
else if (to.isMemory())
masm.storePtr(from.reg(), getAdjustedAddress(to));
else
MOZ_CRASH("Invalid emitMove arguments.");
} else if (from.isMemory()) {
if (to.isGeneralReg()) {
masm.loadPtr(getAdjustedAddress(from), to.reg());
} else if (to.isMemory()) {
masm.loadPtr(getAdjustedAddress(from), tempReg());
masm.storePtr(tempReg(), getAdjustedAddress(to));
} else {
MOZ_CRASH("Invalid emitMove arguments.");
}
} else if (from.isEffectiveAddress()) {
if (to.isGeneralReg()) {
masm.computeEffectiveAddress(getAdjustedAddress(from), to.reg());
} else if (to.isMemory()) {
masm.computeEffectiveAddress(getAdjustedAddress(from), tempReg());
masm.storePtr(tempReg(), getAdjustedAddress(to));
} else {
MOZ_CRASH("Invalid emitMove arguments.");
}
} else {
MOZ_CRASH("Invalid emitMove arguments.");
}
}
void
MoveEmitterMIPSShared::emitFloat32Move(const MoveOperand& from, const MoveOperand& to)
{
// Ensure that we can use ScratchFloat32Reg in memory move.
MOZ_ASSERT_IF(from.isFloatReg(), from.floatReg() != ScratchFloat32Reg);
MOZ_ASSERT_IF(to.isFloatReg(), to.floatReg() != ScratchFloat32Reg);
if (from.isFloatReg()) {
if (to.isFloatReg()) {
masm.moveFloat32(from.floatReg(), to.floatReg());
} else if (to.isGeneralReg()) {
// This should only be used when passing float parameter in a1,a2,a3
MOZ_ASSERT(to.reg() == a1 || to.reg() == a2 || to.reg() == a3);
masm.moveFromFloat32(from.floatReg(), to.reg());
} else {
MOZ_ASSERT(to.isMemory());
masm.storeFloat32(from.floatReg(), getAdjustedAddress(to));
}
} else if (to.isFloatReg()) {
MOZ_ASSERT(from.isMemory());
masm.loadFloat32(getAdjustedAddress(from), to.floatReg());
} else if (to.isGeneralReg()) {
MOZ_ASSERT(from.isMemory());
// This should only be used when passing float parameter in a1,a2,a3
MOZ_ASSERT(to.reg() == a1 || to.reg() == a2 || to.reg() == a3);
masm.loadPtr(getAdjustedAddress(from), to.reg());
} else {
MOZ_ASSERT(from.isMemory());
MOZ_ASSERT(to.isMemory());
masm.loadFloat32(getAdjustedAddress(from), ScratchFloat32Reg);
masm.storeFloat32(ScratchFloat32Reg, getAdjustedAddress(to));
}
}
void
MoveEmitterMIPSShared::emit(const MoveOp& move)
{
const MoveOperand& from = move.from();
const MoveOperand& to = move.to();
if (move.isCycleEnd() && move.isCycleBegin()) {
// A fun consequence of aliased registers is you can have multiple
// cycles at once, and one can end exactly where another begins.
breakCycle(from, to, move.endCycleType(), move.cycleBeginSlot());
completeCycle(from, to, move.type(), move.cycleEndSlot());
return;
}
if (move.isCycleEnd()) {
MOZ_ASSERT(inCycle_);
completeCycle(from, to, move.type(), move.cycleEndSlot());
MOZ_ASSERT(inCycle_ > 0);
inCycle_--;
return;
}
if (move.isCycleBegin()) {
breakCycle(from, to, move.endCycleType(), move.cycleBeginSlot());
inCycle_++;
}
switch (move.type()) {
case MoveOp::FLOAT32:
emitFloat32Move(from, to);
break;
case MoveOp::DOUBLE:
emitDoubleMove(from, to);
break;
case MoveOp::INT32:
MOZ_ASSERT(sizeof(uintptr_t) == sizeof(int32_t));
case MoveOp::GENERAL:
emitMove(from, to);
break;
default:
MOZ_CRASH("Unexpected move type");
}
}
void
MoveEmitterMIPSShared::assertDone()
{
MOZ_ASSERT(inCycle_ == 0);
}
void
MoveEmitterMIPSShared::finish()
{
assertDone();
masm.freeStack(masm.framePushed() - pushedAtStart_);
}

Просмотреть файл

@ -0,0 +1,75 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef jit_mips_shared_MoveEmitter_mips_shared_h
#define jit_mips_shared_MoveEmitter_mips_shared_h
#include "jit/MacroAssembler.h"
#include "jit/MoveResolver.h"
namespace js {
namespace jit {
class MoveEmitterMIPSShared
{
protected:
uint32_t inCycle_;
MacroAssembler& masm;
// Original stack push value.
uint32_t pushedAtStart_;
// These store stack offsets to spill locations, snapshotting
// codegen->framePushed_ at the time they were allocated. They are -1 if no
// stack space has been allocated for that particular spill.
int32_t pushedAtCycle_;
int32_t pushedAtSpill_;
// These are registers that are available for temporary use. They may be
// assigned InvalidReg. If no corresponding spill space has been assigned,
// then these registers do not need to be spilled.
Register spilledReg_;
FloatRegister spilledFloatReg_;
void assertDone();
Register tempReg();
FloatRegister tempFloatReg();
Address cycleSlot(uint32_t slot, uint32_t subslot) const;
int32_t getAdjustedOffset(const MoveOperand& operand);
Address getAdjustedAddress(const MoveOperand& operand);
void emitMove(const MoveOperand& from, const MoveOperand& to);
void emitFloat32Move(const MoveOperand& from, const MoveOperand& to);
virtual void emitDoubleMove(const MoveOperand& from, const MoveOperand& to) = 0;
virtual void breakCycle(const MoveOperand& from, const MoveOperand& to,
MoveOp::Type type, uint32_t slot) = 0;
virtual void completeCycle(const MoveOperand& from, const MoveOperand& to,
MoveOp::Type type, uint32_t slot) = 0;
void emit(const MoveOp& move);
public:
MoveEmitterMIPSShared(MacroAssembler& masm)
: inCycle_(0),
masm(masm),
pushedAtCycle_(-1),
pushedAtSpill_(-1),
pushedAtStart_(masm.framePushed()),
spilledReg_(InvalidReg),
spilledFloatReg_(InvalidFloatReg)
{ }
~MoveEmitterMIPSShared() {
assertDone();
}
void emit(const MoveResolver& moves);
void finish();
void setScratchRegister(Register reg) {}
};
} // namespace jit
} // namespace js
#endif /* jit_mips_shared_MoveEmitter_mips_shared_h */

Просмотреть файл

@ -11,68 +11,6 @@
using namespace js;
using namespace js::jit;
MoveEmitterMIPS::MoveEmitterMIPS(MacroAssembler& masm)
: inCycle_(0),
masm(masm),
pushedAtCycle_(-1),
pushedAtSpill_(-1),
spilledReg_(InvalidReg),
spilledFloatReg_(InvalidFloatReg)
{
pushedAtStart_ = masm.framePushed();
}
void
MoveEmitterMIPS::emit(const MoveResolver& moves)
{
if (moves.numCycles()) {
// Reserve stack for cycle resolution
masm.reserveStack(moves.numCycles() * sizeof(double));
pushedAtCycle_ = masm.framePushed();
}
for (size_t i = 0; i < moves.numMoves(); i++)
emit(moves.getMove(i));
}
MoveEmitterMIPS::~MoveEmitterMIPS()
{
assertDone();
}
Address
MoveEmitterMIPS::cycleSlot(uint32_t slot, uint32_t subslot) const
{
int32_t offset = masm.framePushed() - pushedAtCycle_;
MOZ_ASSERT(Imm16::IsInSignedRange(offset));
return Address(StackPointer, offset + slot * sizeof(double) + subslot);
}
int32_t
MoveEmitterMIPS::getAdjustedOffset(const MoveOperand& operand)
{
MOZ_ASSERT(operand.isMemoryOrEffectiveAddress());
if (operand.base() != StackPointer)
return operand.disp();
// Adjust offset if stack pointer has been moved.
return operand.disp() + masm.framePushed() - pushedAtStart_;
}
Address
MoveEmitterMIPS::getAdjustedAddress(const MoveOperand& operand)
{
return Address(operand.base(), getAdjustedOffset(operand));
}
Register
MoveEmitterMIPS::tempReg()
{
spilledReg_ = SecondScratchReg;
return SecondScratchReg;
}
void
MoveEmitterMIPS::breakCycle(const MoveOperand& from, const MoveOperand& to,
MoveOp::Type type, uint32_t slotId)
@ -175,76 +113,6 @@ MoveEmitterMIPS::completeCycle(const MoveOperand& from, const MoveOperand& to,
}
}
void
MoveEmitterMIPS::emitMove(const MoveOperand& from, const MoveOperand& to)
{
if (from.isGeneralReg()) {
// Second scratch register should not be moved by MoveEmitter.
MOZ_ASSERT(from.reg() != spilledReg_);
if (to.isGeneralReg())
masm.movePtr(from.reg(), to.reg());
else if (to.isMemory())
masm.storePtr(from.reg(), getAdjustedAddress(to));
else
MOZ_CRASH("Invalid emitMove arguments.");
} else if (from.isMemory()) {
if (to.isGeneralReg()) {
masm.loadPtr(getAdjustedAddress(from), to.reg());
} else if (to.isMemory()) {
masm.loadPtr(getAdjustedAddress(from), tempReg());
masm.storePtr(tempReg(), getAdjustedAddress(to));
} else {
MOZ_CRASH("Invalid emitMove arguments.");
}
} else if (from.isEffectiveAddress()) {
if (to.isGeneralReg()) {
masm.computeEffectiveAddress(getAdjustedAddress(from), to.reg());
} else if (to.isMemory()) {
masm.computeEffectiveAddress(getAdjustedAddress(from), tempReg());
masm.storePtr(tempReg(), getAdjustedAddress(to));
} else {
MOZ_CRASH("Invalid emitMove arguments.");
}
} else {
MOZ_CRASH("Invalid emitMove arguments.");
}
}
void
MoveEmitterMIPS::emitFloat32Move(const MoveOperand& from, const MoveOperand& to)
{
// Ensure that we can use ScratchFloat32Reg in memory move.
MOZ_ASSERT_IF(from.isFloatReg(), from.floatReg() != ScratchFloat32Reg);
MOZ_ASSERT_IF(to.isFloatReg(), to.floatReg() != ScratchFloat32Reg);
if (from.isFloatReg()) {
if (to.isFloatReg()) {
masm.moveFloat32(from.floatReg(), to.floatReg());
} else if (to.isGeneralReg()) {
// This should only be used when passing float parameter in a1,a2,a3
MOZ_ASSERT(to.reg() == a1 || to.reg() == a2 || to.reg() == a3);
masm.moveFromFloat32(from.floatReg(), to.reg());
} else {
MOZ_ASSERT(to.isMemory());
masm.storeFloat32(from.floatReg(), getAdjustedAddress(to));
}
} else if (to.isFloatReg()) {
MOZ_ASSERT(from.isMemory());
masm.loadFloat32(getAdjustedAddress(from), to.floatReg());
} else if (to.isGeneralReg()) {
MOZ_ASSERT(from.isMemory());
// This should only be used when passing float parameter in a1,a2,a3
MOZ_ASSERT(to.reg() == a1 || to.reg() == a2 || to.reg() == a3);
masm.loadPtr(getAdjustedAddress(from), to.reg());
} else {
MOZ_ASSERT(from.isMemory());
MOZ_ASSERT(to.isMemory());
masm.loadFloat32(getAdjustedAddress(from), ScratchFloat32Reg);
masm.storeFloat32(ScratchFloat32Reg, getAdjustedAddress(to));
}
}
void
MoveEmitterMIPS::emitDoubleMove(const MoveOperand& from, const MoveOperand& to)
{
@ -286,61 +154,3 @@ MoveEmitterMIPS::emitDoubleMove(const MoveOperand& from, const MoveOperand& to)
masm.storeDouble(ScratchDoubleReg, getAdjustedAddress(to));
}
}
void
MoveEmitterMIPS::emit(const MoveOp& move)
{
const MoveOperand& from = move.from();
const MoveOperand& to = move.to();
if (move.isCycleEnd() && move.isCycleBegin()) {
// A fun consequence of aliased registers is you can have multiple
// cycles at once, and one can end exactly where another begins.
breakCycle(from, to, move.endCycleType(), move.cycleBeginSlot());
completeCycle(from, to, move.type(), move.cycleEndSlot());
return;
}
if (move.isCycleEnd()) {
MOZ_ASSERT(inCycle_);
completeCycle(from, to, move.type(), move.cycleEndSlot());
MOZ_ASSERT(inCycle_ > 0);
inCycle_--;
return;
}
if (move.isCycleBegin()) {
breakCycle(from, to, move.endCycleType(), move.cycleBeginSlot());
inCycle_++;
}
switch (move.type()) {
case MoveOp::FLOAT32:
emitFloat32Move(from, to);
break;
case MoveOp::DOUBLE:
emitDoubleMove(from, to);
break;
case MoveOp::INT32:
MOZ_ASSERT(sizeof(uintptr_t) == sizeof(int32_t));
case MoveOp::GENERAL:
emitMove(from, to);
break;
default:
MOZ_CRASH("Unexpected move type");
}
}
void
MoveEmitterMIPS::assertDone()
{
MOZ_ASSERT(inCycle_ == 0);
}
void
MoveEmitterMIPS::finish()
{
assertDone();
masm.freeStack(masm.framePushed() - pushedAtStart_);
}

Просмотреть файл

@ -7,55 +7,23 @@
#ifndef jit_mips32_MoveEmitter_mips32_h
#define jit_mips32_MoveEmitter_mips32_h
#include "jit/MacroAssembler.h"
#include "jit/MoveResolver.h"
#include "jit/mips-shared/MoveEmitter-mips-shared.h"
namespace js {
namespace jit {
class MoveEmitterMIPS
class MoveEmitterMIPS : public MoveEmitterMIPSShared
{
uint32_t inCycle_;
MacroAssembler& masm;
// Original stack push value.
uint32_t pushedAtStart_;
// These store stack offsets to spill locations, snapshotting
// codegen->framePushed_ at the time they were allocated. They are -1 if no
// stack space has been allocated for that particular spill.
int32_t pushedAtCycle_;
int32_t pushedAtSpill_;
// These are registers that are available for temporary use. They may be
// assigned InvalidReg. If no corresponding spill space has been assigned,
// then these registers do not need to be spilled.
Register spilledReg_;
FloatRegister spilledFloatReg_;
void assertDone();
Register tempReg();
FloatRegister tempFloatReg();
Address cycleSlot(uint32_t slot, uint32_t subslot) const;
int32_t getAdjustedOffset(const MoveOperand& operand);
Address getAdjustedAddress(const MoveOperand& operand);
void emitMove(const MoveOperand& from, const MoveOperand& to);
void emitFloat32Move(const MoveOperand& from, const MoveOperand& to);
void emitDoubleMove(const MoveOperand& from, const MoveOperand& to);
void breakCycle(const MoveOperand& from, const MoveOperand& to,
MoveOp::Type type, uint32_t slot);
void completeCycle(const MoveOperand& from, const MoveOperand& to,
MoveOp::Type type, uint32_t slot);
void emit(const MoveOp& move);
public:
MoveEmitterMIPS(MacroAssembler& masm);
~MoveEmitterMIPS();
void emit(const MoveResolver& moves);
void finish();
void setScratchRegister(Register reg) {}
MoveEmitterMIPS(MacroAssembler& masm)
: MoveEmitterMIPSShared(masm)
{ }
};
typedef MoveEmitterMIPS MoveEmitter;

Просмотреть файл

@ -471,6 +471,7 @@ elif CONFIG['JS_CODEGEN_MIPS32']:
'jit/mips-shared/Bailouts-mips-shared.cpp',
'jit/mips-shared/BaselineIC-mips-shared.cpp',
'jit/mips-shared/Lowering-mips-shared.cpp',
'jit/mips-shared/MoveEmitter-mips-shared.cpp',
]
if CONFIG['JS_CODEGEN_MIPS32']:
UNIFIED_SOURCES += [