Bug 1425583 - RegisterOrSP abstraction. r=sstangl

--HG--
extra : rebase_source : ac4dd5aaff54ec34cefddebe2f8edfad7897d2a7
extra : source : 1d94ec0ef6c57b003d1cd1e053c1d6d4ca0fa6c8
This commit is contained in:
Lars T Hansen 2018-01-19 11:21:03 +01:00
Родитель b37e65e581
Коммит f634ea8511
12 изменённых файлов: 201 добавлений и 39 удалений

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

@ -1551,7 +1551,7 @@ MacroAssembler::generateBailoutTail(Register scratch, Register bailoutInfo)
{
// Prepare a register set for use in this case.
AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All());
MOZ_ASSERT(!regs.has(getStackPointer()));
MOZ_ASSERT_IF(!IsHiddenSP(getStackPointer()), !regs.has(AsRegister(getStackPointer())));
regs.take(bailoutInfo);
// Reset SP to the point where clobbering starts.
@ -3141,12 +3141,18 @@ MacroAssembler::wasmEmitOldTrapOutOfLineCode()
}
void
MacroAssembler::wasmEmitStackCheck(Register sp, Register scratch, Label* onOverflow)
MacroAssembler::wasmEmitStackCheck(RegisterOrSP sp, Register scratch, Label* onOverflow)
{
branchPtr(Assembler::AboveOrEqual,
Address(WasmTlsReg, offsetof(wasm::TlsData, stackLimit)),
sp,
onOverflow);
if (IsHiddenSP(sp)) {
branchStackPtrRhs(Assembler::AboveOrEqual,
Address(WasmTlsReg, offsetof(wasm::TlsData, stackLimit)),
onOverflow);
} else {
branchPtr(Assembler::AboveOrEqual,
Address(WasmTlsReg, offsetof(wasm::TlsData, stackLimit)),
AsRegister(sp),
onOverflow);
}
}
void

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

@ -421,6 +421,10 @@ class MacroAssembler : public MacroAssemblerSpecific
return size();
}
#ifdef JS_HAS_HIDDEN_SP
void Push(RegisterOrSP reg);
#endif
//{{{ check_macroassembler_decl_style
public:
// ===============================================================
@ -1564,7 +1568,7 @@ class MacroAssembler : public MacroAssemblerSpecific
void wasmEmitOldTrapOutOfLineCode();
// Perform a stack-overflow test, branching to the given Label on overflow.
void wasmEmitStackCheck(Register sp, Register scratch, Label* onOverflow);
void wasmEmitStackCheck(RegisterOrSP sp, Register scratch, Label* onOverflow);
void emitPreBarrierFastPath(JSRuntime* rt, MIRType type, Register temp1, Register temp2,
Register temp3, Label* noBarrier);

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

@ -35,7 +35,10 @@ MoveOperand::MoveOperand(MacroAssembler& masm, const ABIArg& arg)
break;
case ABIArg::Stack:
kind_ = MEMORY;
code_ = masm.getStackPointer().code();
if (IsHiddenSP(masm.getStackPointer()))
MOZ_CRASH("Hidden SP cannot be represented as register code on this platform");
else
code_ = AsRegister(masm.getStackPointer()).code();
disp_ = arg.offsetFromArgBase();
break;
case ABIArg::Uninitialized:

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

@ -117,6 +117,82 @@ struct Register {
}
};
// Architectures where the stack pointer is not a plain register with a standard
// register encoding must define JS_HAS_HIDDEN_SP and HiddenSPEncoding.
#ifdef JS_HAS_HIDDEN_SP
struct RegisterOrSP
{
// The register code -- but possibly one that cannot be represented as a bit
// position in a 32-bit vector.
const uint32_t code;
explicit RegisterOrSP(uint32_t code) : code(code) {}
explicit RegisterOrSP(Register r) : code(r.code()) {}
};
static inline bool
IsHiddenSP(RegisterOrSP r)
{
return r.code == HiddenSPEncoding;
}
static inline Register
AsRegister(RegisterOrSP r)
{
MOZ_ASSERT(!IsHiddenSP(r));
return Register::FromCode(r.code);
}
inline bool
operator == (Register r, RegisterOrSP e) {
return r.code() == e.code;
}
inline bool
operator != (Register r, RegisterOrSP e) {
return !(r == e);
}
inline bool
operator == (RegisterOrSP e, Register r) {
return r == e;
}
inline bool
operator != (RegisterOrSP e, Register r) {
return r != e;
}
inline bool
operator == (RegisterOrSP lhs, RegisterOrSP rhs) {
return lhs.code == rhs.code;
}
inline bool
operator != (RegisterOrSP lhs, RegisterOrSP rhs) {
return !(lhs == rhs);
}
#else
// On platforms where there's nothing special about SP, make RegisterOrSP be
// just Register, and return false for IsHiddenSP(r) for any r so that we use
// "normal" code for handling the SP. This reduces ifdeffery throughout the
// jit.
typedef Register RegisterOrSP;
static inline bool
IsHiddenSP(RegisterOrSP r)
{
return false;
}
static inline Register
AsRegister(RegisterOrSP r)
{
return r;
}
#endif
template <> inline Register::SetType
Register::LiveAsIndexableSet<RegTypeName::GPR>(SetType set)
{

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

@ -10,10 +10,14 @@
#include "mozilla/Assertions.h"
#include "mozilla/MathAlgorithms.h"
#include "jit/arm64/vixl/Instructions-vixl.h"
#include "jit/shared/Architecture-shared.h"
#include "js/Utility.h"
#define JS_HAS_HIDDEN_SP
static const uint32_t HiddenSPEncoding = vixl::kSPRegInternalCode;
namespace js {
namespace jit {

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

@ -219,10 +219,19 @@ MacroAssemblerCompat::handleFailureWithHandlerTail(void* handler, Label* profile
void
MacroAssemblerCompat::profilerEnterFrame(Register framePtr, Register scratch)
{
profilerEnterFrame(RegisterOrSP(framePtr), scratch);
}
void
MacroAssemblerCompat::profilerEnterFrame(RegisterOrSP framePtr, Register scratch)
{
asMasm().loadJSContext(scratch);
loadPtr(Address(scratch, offsetof(JSContext, profilingActivation_)), scratch);
storePtr(framePtr, Address(scratch, JitActivation::offsetOfLastProfilingFrame()));
if (IsHiddenSP(framePtr))
storeStackPtr(Address(scratch, JitActivation::offsetOfLastProfilingFrame()));
else
storePtr(AsRegister(framePtr), Address(scratch, JitActivation::offsetOfLastProfilingFrame()));
storePtr(ImmPtr(nullptr), Address(scratch, JitActivation::offsetOfLastProfilingCallSite()));
}
@ -242,6 +251,16 @@ MacroAssembler::reserveStack(uint32_t amount)
adjustFrame(amount);
}
void
MacroAssembler::Push(RegisterOrSP reg)
{
if (IsHiddenSP(reg))
push(sp);
else
push(AsRegister(reg));
adjustFrame(sizeof(intptr_t));
}
//{{{ check_macroassembler_style
// ===============================================================
// MacroAssembler high-level usage.

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

@ -72,11 +72,18 @@ class MacroAssemblerCompat : public vixl::MacroAssembler
bool oom() const {
return Assembler::oom() || !enoughMemory_;
}
static ARMRegister toARMRegister(RegisterOrSP r, size_t size) {
if (IsHiddenSP(r)) {
MOZ_ASSERT(size == 64);
return sp;
}
return ARMRegister(AsRegister(r), size);
}
static MemOperand toMemOperand(const Address& a) {
return MemOperand(ARMRegister(a.base, 64), a.offset);
return MemOperand(toARMRegister(a.base, 64), a.offset);
}
void doBaseIndex(const vixl::CPURegister& rt, const BaseIndex& addr, vixl::LoadStoreOp op) {
const ARMRegister base = ARMRegister(addr.base, 64);
const ARMRegister base = toARMRegister(addr.base, 64);
const ARMRegister index = ARMRegister(addr.index, 64);
const unsigned scale = addr.scale;
@ -175,6 +182,11 @@ class MacroAssemblerCompat : public vixl::MacroAssembler
void push(Register reg) {
vixl::MacroAssembler::Push(ARMRegister(reg, 64));
}
void push(RegisterOrSP reg) {
if (IsHiddenSP(reg))
vixl::MacroAssembler::Push(sp);
vixl::MacroAssembler::Push(toARMRegister(reg, 64));
}
void push(Register r0, Register r1) {
vixl::MacroAssembler::Push(ARMRegister(r0, 64), ARMRegister(r1, 64));
}
@ -761,7 +773,7 @@ class MacroAssemblerCompat : public vixl::MacroAssembler
Ldr(ARMRegister(dest, 64), MemOperand(address));
}
void loadPtr(const BaseIndex& src, Register dest) {
Register base = src.base;
ARMRegister base = toARMRegister(src.base, 64);
uint32_t scale = Imm32::ShiftOf(src.scale).value;
ARMRegister dest64(dest, 64);
ARMRegister index64(src.index, 64);
@ -769,16 +781,16 @@ class MacroAssemblerCompat : public vixl::MacroAssembler
if (src.offset) {
vixl::UseScratchRegisterScope temps(this);
const ARMRegister scratch = temps.AcquireX();
MOZ_ASSERT(!scratch.Is(ARMRegister(base, 64)));
MOZ_ASSERT(!scratch.Is(base));
MOZ_ASSERT(!scratch.Is(dest64));
MOZ_ASSERT(!scratch.Is(index64));
Add(scratch, ARMRegister(base, 64), Operand(int64_t(src.offset)));
Add(scratch, base, Operand(int64_t(src.offset)));
Ldr(dest64, MemOperand(scratch, index64, vixl::LSL, scale));
return;
}
Ldr(dest64, MemOperand(ARMRegister(base, 64), index64, vixl::LSL, scale));
Ldr(dest64, MemOperand(base, index64, vixl::LSL, scale));
}
void loadPrivate(const Address& src, Register dest);
@ -1077,7 +1089,7 @@ class MacroAssemblerCompat : public vixl::MacroAssembler
Ldr(ARMFPRegister(dest, 64), MemOperand(src));
}
void loadDouble(const BaseIndex& src, FloatRegister dest) {
ARMRegister base(src.base, 64);
ARMRegister base = toARMRegister(src.base, 64);
ARMRegister index(src.index, 64);
if (src.offset == 0) {
@ -1098,7 +1110,7 @@ class MacroAssemblerCompat : public vixl::MacroAssembler
fcvt(ARMFPRegister(dest, 64), ARMFPRegister(dest, 32));
}
void loadFloatAsDouble(const BaseIndex& src, FloatRegister dest) {
ARMRegister base(src.base, 64);
ARMRegister base = toARMRegister(src.base, 64);
ARMRegister index(src.index, 64);
if (src.offset == 0) {
Ldr(ARMFPRegister(dest, 32), MemOperand(base, index, vixl::LSL, unsigned(src.scale)));
@ -1118,7 +1130,7 @@ class MacroAssemblerCompat : public vixl::MacroAssembler
Ldr(ARMFPRegister(dest, 32), toMemOperand(addr));
}
void loadFloat32(const BaseIndex& src, FloatRegister dest) {
ARMRegister base(src.base, 64);
ARMRegister base = toARMRegister(src.base, 64);
ARMRegister index(src.index, 64);
if (src.offset == 0) {
Ldr(ARMFPRegister(dest, 32), MemOperand(base, index, vixl::LSL, unsigned(src.scale)));
@ -1875,11 +1887,14 @@ class MacroAssemblerCompat : public vixl::MacroAssembler
}
void computeEffectiveAddress(const Address& address, Register dest) {
Add(ARMRegister(dest, 64), ARMRegister(address.base, 64), Operand(address.offset));
Add(ARMRegister(dest, 64), toARMRegister(address.base, 64), Operand(address.offset));
}
void computeEffectiveAddress(const Address& address, RegisterOrSP dest) {
Add(toARMRegister(dest, 64), toARMRegister(address.base, 64), Operand(address.offset));
}
void computeEffectiveAddress(const BaseIndex& address, Register dest) {
ARMRegister dest64(dest, 64);
ARMRegister base64(address.base, 64);
ARMRegister base64 = toARMRegister(address.base, 64);
ARMRegister index64(address.index, 64);
Add(dest64, base64, Operand(index64, vixl::LSL, address.scale));
@ -1895,6 +1910,7 @@ class MacroAssemblerCompat : public vixl::MacroAssembler
void handleFailureWithHandlerTail(void* handler, Label* profilerExitTail);
void profilerEnterFrame(Register framePtr, Register scratch);
void profilerEnterFrame(RegisterOrSP framePtr, Register scratch);
void profilerExitFrame() {
jump(GetJitContext()->runtime->jitRuntime()->getProfilerExitFrameTail());
}
@ -1960,7 +1976,7 @@ class MacroAssemblerCompat : public vixl::MacroAssembler
#ifdef DEBUG
vixl::UseScratchRegisterScope temps(this);
const ARMRegister scratch64 = temps.AcquireX();
MOZ_ASSERT(scratch64.asUnsized() != reg.asUnsized());
MOZ_ASSERT_IF(!reg.IsSP(), scratch64.asUnsized() != reg.asUnsized());
Label aligned;
Mov(scratch64, reg);
Tst(scratch64, Operand(StackAlignment - 1));

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

@ -265,8 +265,10 @@ class Register : public CPURegister {
}
js::jit::Register asUnsized() const {
if (code_ == kSPRegInternalCode)
return js::jit::Register::FromCode((js::jit::Register::Code)kZeroRegCode);
// asUnsized() is only ever used on temp registers or on registers that
// are known not to be SP, and there should be no risk of it being
// applied to SP. Check anyway.
VIXL_ASSERT(code_ != kSPRegInternalCode);
return js::jit::Register::FromCode((js::jit::Register::Code)code_);
}
@ -706,6 +708,9 @@ class Operand {
explicit Operand(js::jit::Register, int32_t) {
MOZ_CRASH("Operand with implicit Address");
}
explicit Operand(js::jit::RegisterOrSP, int32_t) {
MOZ_CRASH("Operand with implicit Address");
}
bool IsImmediate() const;
bool IsShiftedRegister() const;
@ -777,7 +782,7 @@ class MemOperand {
// Adapter constructors using C++11 delegating.
// TODO: If sp == kSPRegInternalCode, the xzr check isn't necessary.
explicit MemOperand(js::jit::Address addr)
: MemOperand(addr.base.code() == 31 ? sp : Register(addr.base, 64),
: MemOperand(IsHiddenSP(addr.base) ? sp : Register(AsRegister(addr.base), 64),
(ptrdiff_t)addr.offset) {
}

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

@ -2224,12 +2224,8 @@ class MacroAssembler : public js::jit::Assembler {
return sp_;
}
const js::jit::Register getStackPointer() const {
int code = sp_.code();
if (code == kSPRegInternalCode) {
code = 31;
}
return js::jit::Register::FromCode(code);
const js::jit::RegisterOrSP getStackPointer() const {
return js::jit::RegisterOrSP(sp_.code());
}
CPURegList* TmpList() { return &tmp_list_; }

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

@ -308,13 +308,18 @@ struct PatchedAbsoluteAddress
// 32-bit offset.
struct Address
{
Register base;
RegisterOrSP base;
int32_t offset;
Address(Register base, int32_t offset) : base(base), offset(offset)
Address(Register base, int32_t offset) : base(RegisterOrSP(base)), offset(offset)
{ }
Address() : base(Registers::Invalid), offset(0)
#ifdef JS_HAS_HIDDEN_SP
Address(RegisterOrSP base, int32_t offset) : base(base), offset(offset)
{ }
#endif
Address() : base(RegisterOrSP(Registers::Invalid)), offset(0)
{ }
};
@ -340,17 +345,23 @@ HighWord(const Address& address) {
// index with a scale, and a constant, 32-bit offset.
struct BaseIndex
{
Register base;
RegisterOrSP base;
Register index;
Scale scale;
int32_t offset;
BaseIndex(Register base, Register index, Scale scale, int32_t offset = 0)
: base(base), index(index), scale(scale), offset(offset)
: base(RegisterOrSP(base)), index(index), scale(scale), offset(offset)
{ }
#ifdef JS_HAS_HIDDEN_SP
BaseIndex(RegisterOrSP base, Register index, Scale scale, int32_t offset = 0)
: base(base), index(index), scale(scale), offset(offset)
{ }
#endif
BaseIndex()
: base(Registers::Invalid)
: base(RegisterOrSP(Registers::Invalid))
, index(Registers::Invalid)
, scale(TimesOne)
, offset(0)
@ -384,8 +395,14 @@ HighWord(const BaseIndex& address) {
struct BaseValueIndex : BaseIndex
{
BaseValueIndex(Register base, Register index, int32_t offset = 0)
: BaseIndex(RegisterOrSP(base), index, ValueScale, offset)
{ }
#ifdef JS_HAS_HIDDEN_SP
BaseValueIndex(RegisterOrSP base, Register index, int32_t offset = 0)
: BaseIndex(base, index, ValueScale, offset)
{ }
#endif
};
// Specifies the address of an indexed Value within object elements from a
@ -397,6 +414,14 @@ struct BaseObjectElementIndex : BaseValueIndex
{
NativeObject::elementsSizeMustNotOverflow();
}
#ifdef JS_HAS_HIDDEN_SP
BaseObjectElementIndex(RegisterOrSP base, Register index, int32_t offset = 0)
: BaseValueIndex(base, index, offset)
{
NativeObject::elementsSizeMustNotOverflow();
}
#endif
};
// Like BaseObjectElementIndex, except for object slots.
@ -407,6 +432,14 @@ struct BaseObjectSlotIndex : BaseValueIndex
{
NativeObject::slotsSizeMustNotOverflow();
}
#ifdef JS_HAS_HIDDEN_SP
BaseObjectSlotIndex(RegisterOrSP base, Register index)
: BaseValueIndex(base, index)
{
NativeObject::slotsSizeMustNotOverflow();
}
#endif
};
class Relocation {

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

@ -985,7 +985,7 @@ class BaseStackFrame
CodeOffset stackAddOffset_;
// The stack pointer, cached for brevity.
Register sp_;
RegisterOrSP sp_;
public:
@ -1178,7 +1178,7 @@ class BaseStackFrame
void allocStack(Register tmp0, Register tmp1, Label* stackOverflowLabel) {
stackAddOffset_ = masm.sub32FromStackPtrWithPatch(tmp0);
masm.wasmEmitStackCheck(tmp0, tmp1, stackOverflowLabel);
masm.wasmEmitStackCheck(RegisterOrSP(tmp0), tmp1, stackOverflowLabel);
}
void patchAllocStack() {

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

@ -137,7 +137,7 @@ SetupABIArguments(MacroAssembler& masm, const FuncExport& fe, Register argv, Reg
masm.storePtr(scratch, Address(masm.getStackPointer(), iter->offsetFromArgBase()));
break;
case MIRType::Int64: {
Register sp = masm.getStackPointer();
RegisterOrSP sp = masm.getStackPointer();
#if JS_BITS_PER_WORD == 32
masm.load32(LowWord(src), scratch);
masm.store32(scratch, LowWord(Address(sp, iter->offsetFromArgBase())));