mirror of
https://github.com/classilla/tenfourfox.git
synced 2024-09-25 17:55:23 +00:00
226 lines
6.8 KiB
C++
226 lines
6.8 KiB
C++
/* -*- 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_Registers_h
|
|
#define jit_Registers_h
|
|
|
|
#include "mozilla/Array.h"
|
|
|
|
#include "jit/IonTypes.h"
|
|
#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
|
|
# include "jit/x86-shared/Architecture-x86-shared.h"
|
|
#elif defined(JS_CODEGEN_ARM)
|
|
# include "jit/arm/Architecture-arm.h"
|
|
#elif defined(JS_CODEGEN_ARM64)
|
|
# include "jit/arm64/Architecture-arm64.h"
|
|
#elif defined(JS_CODEGEN_MIPS32)
|
|
# include "jit/mips32/Architecture-mips32.h"
|
|
#elif defined(JS_CODEGEN_MIPS64)
|
|
# include "jit/mips64/Architecture-mips64.h"
|
|
#elif defined(JS_CODEGEN_PPC_OSX)
|
|
# include "jit/osxppc/Architecture-ppc.h"
|
|
#elif defined(JS_CODEGEN_NONE)
|
|
# include "jit/none/Architecture-none.h"
|
|
#else
|
|
# error "Unknown architecture!"
|
|
#endif
|
|
|
|
namespace js {
|
|
namespace jit {
|
|
|
|
struct Register {
|
|
typedef Registers Codes;
|
|
typedef Codes::Encoding Encoding;
|
|
typedef Codes::Code Code;
|
|
typedef Codes::SetType SetType;
|
|
|
|
Codes::Encoding reg_;
|
|
static Register FromCode(Code i) {
|
|
MOZ_ASSERT(i < Registers::Total);
|
|
Register r = { Encoding(i) };
|
|
return r;
|
|
}
|
|
static Register FromName(const char* name) {
|
|
Code code = Registers::FromName(name);
|
|
Register r = { Encoding(code) };
|
|
return r;
|
|
}
|
|
MOZ_CONSTEXPR Code code() const {
|
|
return Code(reg_);
|
|
}
|
|
Encoding encoding() const {
|
|
MOZ_ASSERT(Code(reg_) < Registers::Total);
|
|
return reg_;
|
|
}
|
|
const char* name() const {
|
|
return Registers::GetName(code());
|
|
}
|
|
bool operator ==(Register other) const {
|
|
return reg_ == other.reg_;
|
|
}
|
|
bool operator !=(Register other) const {
|
|
return reg_ != other.reg_;
|
|
}
|
|
bool volatile_() const {
|
|
return !!((SetType(1) << code()) & Registers::VolatileMask);
|
|
}
|
|
bool aliases(const Register& other) const {
|
|
return reg_ == other.reg_;
|
|
}
|
|
uint32_t numAliased() const {
|
|
return 1;
|
|
}
|
|
|
|
// N.B. FloatRegister is an explicit outparam here because msvc-2010
|
|
// miscompiled it on win64 when the value was simply returned. This
|
|
// now has an explicit outparam for compatability.
|
|
void aliased(uint32_t aliasIdx, Register* ret) const {
|
|
MOZ_ASSERT(aliasIdx == 0);
|
|
*ret = *this;
|
|
}
|
|
|
|
SetType alignedOrDominatedAliasedSet() const {
|
|
return SetType(1) << code();
|
|
}
|
|
|
|
static uint32_t SetSize(SetType x) {
|
|
return Codes::SetSize(x);
|
|
}
|
|
static uint32_t FirstBit(SetType x) {
|
|
return Codes::FirstBit(x);
|
|
}
|
|
static uint32_t LastBit(SetType x) {
|
|
return Codes::LastBit(x);
|
|
}
|
|
};
|
|
|
|
struct Register64
|
|
{
|
|
#ifdef JS_PUNBOX64
|
|
Register reg;
|
|
#else
|
|
Register high;
|
|
Register low;
|
|
#endif
|
|
|
|
#ifdef JS_PUNBOX64
|
|
explicit MOZ_CONSTEXPR Register64(Register r)
|
|
: reg(r)
|
|
{}
|
|
#else
|
|
MOZ_CONSTEXPR Register64(Register h, Register l)
|
|
: high(h), low(l)
|
|
{}
|
|
#endif
|
|
};
|
|
|
|
class RegisterDump
|
|
{
|
|
public:
|
|
typedef mozilla::Array<Registers::RegisterContent, Registers::Total> GPRArray;
|
|
typedef mozilla::Array<FloatRegisters::RegisterContent, FloatRegisters::TotalPhys> FPUArray;
|
|
|
|
protected: // Silence Clang warning.
|
|
GPRArray regs_;
|
|
FPUArray fpregs_;
|
|
|
|
public:
|
|
static size_t offsetOfRegister(Register reg) {
|
|
return offsetof(RegisterDump, regs_) + reg.code() * sizeof(uintptr_t);
|
|
}
|
|
static size_t offsetOfRegister(FloatRegister reg) {
|
|
return offsetof(RegisterDump, fpregs_) + reg.getRegisterDumpOffsetInBytes();
|
|
}
|
|
};
|
|
|
|
// Information needed to recover machine register state. This records the
|
|
// location of spilled register and not the content of the spilled
|
|
// registers. Thus we can safely assume that this structure is unchanged, even
|
|
// if the GC pointers mapped by this structure are relocated.
|
|
class MachineState
|
|
{
|
|
mozilla::Array<Registers::RegisterContent*, Registers::Total> regs_;
|
|
mozilla::Array<FloatRegisters::RegisterContent*, FloatRegisters::Total> fpregs_;
|
|
|
|
public:
|
|
MachineState() {
|
|
#ifndef JS_CODEGEN_NONE
|
|
for (unsigned i = 0; i < Registers::Total; i++)
|
|
regs_[i] = reinterpret_cast<Registers::RegisterContent*>(i + 0x100);
|
|
for (unsigned i = 0; i < FloatRegisters::Total; i++)
|
|
fpregs_[i] = reinterpret_cast<FloatRegisters::RegisterContent*>(i + 0x200);
|
|
#endif
|
|
}
|
|
|
|
static MachineState FromBailout(RegisterDump::GPRArray& regs, RegisterDump::FPUArray& fpregs);
|
|
|
|
void setRegisterLocation(Register reg, uintptr_t* up) {
|
|
regs_[reg.code()] = (Registers::RegisterContent*) up;
|
|
}
|
|
void setRegisterLocation(FloatRegister reg, float* fp) {
|
|
MOZ_ASSERT(reg.isSingle());
|
|
fpregs_[reg.code()] = (FloatRegisters::RegisterContent*) fp;
|
|
}
|
|
void setRegisterLocation(FloatRegister reg, double* dp) {
|
|
fpregs_[reg.code()] = (FloatRegisters::RegisterContent*) dp;
|
|
}
|
|
void setRegisterLocation(FloatRegister reg, FloatRegisters::RegisterContent* rp) {
|
|
fpregs_[reg.code()] = rp;
|
|
}
|
|
|
|
bool has(Register reg) const {
|
|
return regs_[reg.code()] != nullptr;
|
|
}
|
|
bool has(FloatRegister reg) const {
|
|
return fpregs_[reg.code()] != nullptr;
|
|
}
|
|
uintptr_t read(Register reg) const {
|
|
return regs_[reg.code()]->r;
|
|
}
|
|
double read(FloatRegister reg) const {
|
|
return fpregs_[reg.code()]->d;
|
|
}
|
|
void write(Register reg, uintptr_t value) const {
|
|
regs_[reg.code()]->r = value;
|
|
}
|
|
const FloatRegisters::RegisterContent* address(FloatRegister reg) const {
|
|
return fpregs_[reg.code()];
|
|
}
|
|
};
|
|
|
|
class MacroAssembler;
|
|
|
|
// Declares a register as owned within the scope of the object.
|
|
// In debug mode, owned register state is tracked within the MacroAssembler,
|
|
// and an assert will fire if ownership is conflicting.
|
|
// In contrast to ARM64's UseScratchRegisterScope, this class has no overhead
|
|
// in non-debug builds.
|
|
template <class RegisterType>
|
|
struct AutoGenericRegisterScope : public RegisterType
|
|
{
|
|
// Prevent MacroAssembler templates from creating copies,
|
|
// which causes the destructor to fire more than once.
|
|
AutoGenericRegisterScope(const AutoGenericRegisterScope& other) = delete;
|
|
|
|
#ifdef DEBUG
|
|
MacroAssembler& masm_;
|
|
explicit AutoGenericRegisterScope(MacroAssembler& masm, RegisterType reg);
|
|
~AutoGenericRegisterScope();
|
|
#else
|
|
MOZ_CONSTEXPR explicit AutoGenericRegisterScope(MacroAssembler& masm, RegisterType reg)
|
|
: RegisterType(reg)
|
|
{ }
|
|
#endif
|
|
};
|
|
|
|
typedef AutoGenericRegisterScope<Register> AutoRegisterScope;
|
|
typedef AutoGenericRegisterScope<FloatRegister> AutoFloatRegisterScope;
|
|
|
|
} // namespace jit
|
|
} // namespace js
|
|
|
|
#endif /* jit_Registers_h */
|