summaryrefslogtreecommitdiff
path: root/js/src/jit/Registers.h
diff options
context:
space:
mode:
authorMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
committerMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
commit5f8de423f190bbb79a62f804151bc24824fa32d8 (patch)
tree10027f336435511475e392454359edea8e25895d /js/src/jit/Registers.h
parent49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff)
downloaduxp-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz
Add m-esr52 at 52.6.0
Diffstat (limited to 'js/src/jit/Registers.h')
-rw-r--r--js/src/jit/Registers.h250
1 files changed, 250 insertions, 0 deletions
diff --git a/js/src/jit/Registers.h b/js/src/jit/Registers.h
new file mode 100644
index 0000000000..4ecf3ae9cc
--- /dev/null
+++ b/js/src/jit/Registers.h
@@ -0,0 +1,250 @@
+/* -*- 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_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;
+ }
+ static Register Invalid() {
+ Register r = { Encoding(Codes::Invalid) };
+ return r;
+ }
+ 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);
+ }
+};
+
+#if defined(JS_NUNBOX32)
+static const uint32_t INT64LOW_OFFSET = 0 * sizeof(int32_t);
+static const uint32_t INT64HIGH_OFFSET = 1 * sizeof(int32_t);
+#endif
+
+struct Register64
+{
+#ifdef JS_PUNBOX64
+ Register reg;
+#else
+ Register high;
+ Register low;
+#endif
+
+#ifdef JS_PUNBOX64
+ explicit constexpr Register64(Register r)
+ : reg(r)
+ {}
+ bool operator ==(Register64 other) const {
+ return reg == other.reg;
+ }
+ bool operator !=(Register64 other) const {
+ return reg != other.reg;
+ }
+ static Register64 Invalid() {
+ return Register64(Register::Invalid());
+ }
+#else
+ constexpr Register64(Register h, Register l)
+ : high(h), low(l)
+ {}
+ bool operator ==(Register64 other) const {
+ return high == other.high && low == other.low;
+ }
+ bool operator !=(Register64 other) const {
+ return high != other.high || low != other.low;
+ }
+ static Register64 Invalid() {
+ return Register64(Register::Invalid(), Register::Invalid());
+ }
+#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 (uintptr_t i = 0; i < Registers::Total; i++)
+ regs_[i] = reinterpret_cast<Registers::RegisterContent*>(i + 0x100);
+ for (uintptr_t 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
+ 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 */