summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/dfg/DFGGPRInfo.h
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/dfg/DFGGPRInfo.h')
-rw-r--r--Source/JavaScriptCore/dfg/DFGGPRInfo.h465
1 files changed, 465 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGGPRInfo.h b/Source/JavaScriptCore/dfg/DFGGPRInfo.h
new file mode 100644
index 000000000..2f779d645
--- /dev/null
+++ b/Source/JavaScriptCore/dfg/DFGGPRInfo.h
@@ -0,0 +1,465 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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.
+ */
+
+#ifndef DFGGPRInfo_h
+#define DFGGPRInfo_h
+
+#if ENABLE(DFG_JIT)
+
+#include <assembler/MacroAssembler.h>
+#include <dfg/DFGRegisterBank.h>
+
+namespace JSC { namespace DFG {
+
+typedef MacroAssembler::RegisterID GPRReg;
+#define InvalidGPRReg ((GPRReg)-1)
+
+#if USE(JSVALUE64)
+class JSValueRegs {
+public:
+ JSValueRegs()
+ : m_gpr(InvalidGPRReg)
+ {
+ }
+
+ explicit JSValueRegs(GPRReg gpr)
+ : m_gpr(gpr)
+ {
+ }
+
+ bool operator!() const { return m_gpr == InvalidGPRReg; }
+
+ GPRReg gpr() const { return m_gpr; }
+
+private:
+ GPRReg m_gpr;
+};
+
+class JSValueSource {
+public:
+ JSValueSource()
+ : m_offset(notAddress())
+ , m_base(InvalidGPRReg)
+ {
+ }
+
+ JSValueSource(JSValueRegs regs)
+ : m_offset(notAddress())
+ , m_base(regs.gpr())
+ {
+ }
+
+ explicit JSValueSource(GPRReg gpr)
+ : m_offset(notAddress())
+ , m_base(gpr)
+ {
+ }
+
+ JSValueSource(MacroAssembler::Address address)
+ : m_offset(address.offset)
+ , m_base(address.base)
+ {
+ ASSERT(m_offset != notAddress());
+ ASSERT(m_base != InvalidGPRReg);
+ }
+
+ static JSValueSource unboxedCell(GPRReg payloadGPR)
+ {
+ return JSValueSource(payloadGPR);
+ }
+
+ bool operator!() const { return m_base == InvalidGPRReg; }
+
+ bool isAddress() const { return m_offset != notAddress(); }
+
+ int32_t offset() const
+ {
+ ASSERT(isAddress());
+ return m_offset;
+ }
+
+ GPRReg base() const
+ {
+ ASSERT(isAddress());
+ return m_base;
+ }
+
+ GPRReg gpr() const
+ {
+ ASSERT(!isAddress());
+ return m_base;
+ }
+
+ MacroAssembler::Address asAddress() const { return MacroAssembler::Address(base(), offset()); }
+
+private:
+ static inline int32_t notAddress() { return 0x80000000; }
+
+ int32_t m_offset;
+ GPRReg m_base;
+};
+#endif
+
+#if USE(JSVALUE32_64)
+class JSValueRegs {
+public:
+ JSValueRegs()
+ : m_tagGPR(static_cast<int8_t>(InvalidGPRReg))
+ , m_payloadGPR(static_cast<int8_t>(InvalidGPRReg))
+ {
+ }
+
+ JSValueRegs(GPRReg tagGPR, GPRReg payloadGPR)
+ : m_tagGPR(tagGPR)
+ , m_payloadGPR(payloadGPR)
+ {
+ ASSERT((static_cast<GPRReg>(m_tagGPR) == InvalidGPRReg) == (static_cast<GPRReg>(payloadGPR) == InvalidGPRReg));
+ }
+
+ bool operator!() const { return static_cast<GPRReg>(m_tagGPR) == InvalidGPRReg; }
+
+ GPRReg tagGPR() const { return static_cast<GPRReg>(m_tagGPR); }
+ GPRReg payloadGPR() const { return static_cast<GPRReg>(m_payloadGPR); }
+
+private:
+ int8_t m_tagGPR;
+ int8_t m_payloadGPR;
+};
+
+class JSValueSource {
+public:
+ JSValueSource()
+ : m_offset(notAddress())
+ , m_baseOrTag(static_cast<int8_t>(InvalidGPRReg))
+ , m_payload(static_cast<int8_t>(InvalidGPRReg))
+ , m_tagType(0)
+ {
+ }
+
+ JSValueSource(JSValueRegs regs)
+ : m_offset(notAddress())
+ , m_baseOrTag(regs.tagGPR())
+ , m_payload(regs.payloadGPR())
+ , m_tagType(0)
+ {
+ }
+
+ JSValueSource(GPRReg tagGPR, GPRReg payloadGPR)
+ : m_offset(notAddress())
+ , m_baseOrTag(static_cast<int8_t>(tagGPR))
+ , m_payload(static_cast<int8_t>(payloadGPR))
+ , m_tagType(0)
+ {
+ }
+
+ JSValueSource(MacroAssembler::Address address)
+ : m_offset(address.offset)
+ , m_baseOrTag(static_cast<int8_t>(address.base))
+ , m_payload(static_cast<int8_t>(InvalidGPRReg))
+ , m_tagType(0)
+ {
+ ASSERT(m_offset != notAddress());
+ ASSERT(static_cast<GPRReg>(m_baseOrTag) != InvalidGPRReg);
+ }
+
+ static JSValueSource unboxedCell(GPRReg payloadGPR)
+ {
+ JSValueSource result;
+ result.m_offset = notAddress();
+ result.m_baseOrTag = static_cast<int8_t>(InvalidGPRReg);
+ result.m_payload = static_cast<int8_t>(payloadGPR);
+ result.m_tagType = static_cast<int8_t>(JSValue::CellTag);
+ return result;
+ }
+
+ bool operator!() const { return static_cast<GPRReg>(m_baseOrTag) == InvalidGPRReg && static_cast<GPRReg>(m_payload) == InvalidGPRReg; }
+
+ bool isAddress() const
+ {
+ ASSERT(!!*this);
+ return m_offset != notAddress();
+ }
+
+ int32_t offset() const
+ {
+ ASSERT(isAddress());
+ return m_offset;
+ }
+
+ GPRReg base() const
+ {
+ ASSERT(isAddress());
+ return static_cast<GPRReg>(m_baseOrTag);
+ }
+
+ GPRReg tagGPR() const
+ {
+ ASSERT(!isAddress() && m_baseOrTag != InvalidGPRReg);
+ return static_cast<GPRReg>(m_baseOrTag);
+ }
+
+ GPRReg payloadGPR() const
+ {
+ ASSERT(!isAddress());
+ return static_cast<GPRReg>(m_payload);
+ }
+
+ bool hasKnownTag() const
+ {
+ ASSERT(!!*this);
+ ASSERT(!isAddress());
+ return static_cast<GPRReg>(m_baseOrTag) == InvalidGPRReg;
+ }
+
+ uint32_t tag() const
+ {
+ return static_cast<int32_t>(m_tagType);
+ }
+
+ MacroAssembler::Address asAddress(unsigned additionalOffset = 0) const { return MacroAssembler::Address(base(), offset() + additionalOffset); }
+
+private:
+ static inline int32_t notAddress() { return 0x80000000; }
+
+ int32_t m_offset;
+ int8_t m_baseOrTag;
+ int8_t m_payload;
+ int8_t m_tagType; // Contains the low bits of the tag.
+};
+#endif
+
+#if CPU(X86)
+#define NUMBER_OF_ARGUMENT_REGISTERS 0
+
+class GPRInfo {
+public:
+ typedef GPRReg RegisterType;
+ static const unsigned numberOfRegisters = 5;
+
+ // Temporary registers.
+ static const GPRReg regT0 = X86Registers::eax;
+ static const GPRReg regT1 = X86Registers::edx;
+ static const GPRReg regT2 = X86Registers::ecx;
+ static const GPRReg regT3 = X86Registers::ebx;
+ static const GPRReg regT4 = X86Registers::esi;
+ // These registers match the baseline JIT.
+ static const GPRReg cachedResultRegister = regT0;
+ static const GPRReg cachedResultRegister2 = regT1;
+ static const GPRReg callFrameRegister = X86Registers::edi;
+ // These constants provide the names for the general purpose argument & return value registers.
+ static const GPRReg argumentGPR0 = X86Registers::ecx; // regT2
+ static const GPRReg argumentGPR1 = X86Registers::edx; // regT1
+ static const GPRReg returnValueGPR = X86Registers::eax; // regT0
+ static const GPRReg returnValueGPR2 = X86Registers::edx; // regT1
+ static const GPRReg nonPreservedNonReturnGPR = X86Registers::ecx;
+
+ static GPRReg toRegister(unsigned index)
+ {
+ ASSERT(index < numberOfRegisters);
+ static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4 };
+ return registerForIndex[index];
+ }
+
+ static unsigned toIndex(GPRReg reg)
+ {
+ ASSERT(reg != InvalidGPRReg);
+ ASSERT(reg < 8);
+ static const unsigned indexForRegister[8] = { 0, 2, 1, 3, InvalidIndex, InvalidIndex, 4, InvalidIndex };
+ unsigned result = indexForRegister[reg];
+ ASSERT(result != InvalidIndex);
+ return result;
+ }
+
+#ifndef NDEBUG
+ static const char* debugName(GPRReg reg)
+ {
+ ASSERT(reg != InvalidGPRReg);
+ ASSERT(reg < 8);
+ static const char* nameForRegister[8] = {
+ "eax", "ecx", "edx", "ebx",
+ "esp", "ebp", "esi", "edi",
+ };
+ return nameForRegister[reg];
+ }
+#endif
+private:
+
+ static const unsigned InvalidIndex = 0xffffffff;
+};
+
+#endif
+
+#if CPU(X86_64)
+#define NUMBER_OF_ARGUMENT_REGISTERS 6
+
+class GPRInfo {
+public:
+ typedef GPRReg RegisterType;
+ static const unsigned numberOfRegisters = 9;
+
+ // These registers match the baseline JIT.
+ static const GPRReg cachedResultRegister = X86Registers::eax;
+ static const GPRReg timeoutCheckRegister = X86Registers::r12;
+ static const GPRReg callFrameRegister = X86Registers::r13;
+ static const GPRReg tagTypeNumberRegister = X86Registers::r14;
+ static const GPRReg tagMaskRegister = X86Registers::r15;
+ // Temporary registers.
+ static const GPRReg regT0 = X86Registers::eax;
+ static const GPRReg regT1 = X86Registers::edx;
+ static const GPRReg regT2 = X86Registers::ecx;
+ static const GPRReg regT3 = X86Registers::ebx;
+ static const GPRReg regT4 = X86Registers::edi;
+ static const GPRReg regT5 = X86Registers::esi;
+ static const GPRReg regT6 = X86Registers::r8;
+ static const GPRReg regT7 = X86Registers::r9;
+ static const GPRReg regT8 = X86Registers::r10;
+ // These constants provide the names for the general purpose argument & return value registers.
+ static const GPRReg argumentGPR0 = X86Registers::edi; // regT4
+ static const GPRReg argumentGPR1 = X86Registers::esi; // regT5
+ static const GPRReg argumentGPR2 = X86Registers::edx; // regT1
+ static const GPRReg argumentGPR3 = X86Registers::ecx; // regT2
+ static const GPRReg argumentGPR4 = X86Registers::r8; // regT6
+ static const GPRReg argumentGPR5 = X86Registers::r9; // regT7
+ static const GPRReg returnValueGPR = X86Registers::eax; // regT0
+ static const GPRReg returnValueGPR2 = X86Registers::edx; // regT1
+ static const GPRReg nonPreservedNonReturnGPR = X86Registers::esi;
+
+ static GPRReg toRegister(unsigned index)
+ {
+ ASSERT(index < numberOfRegisters);
+ static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6, regT7, regT8 };
+ return registerForIndex[index];
+ }
+
+ static unsigned toIndex(GPRReg reg)
+ {
+ ASSERT(reg != InvalidGPRReg);
+ ASSERT(reg < 16);
+ static const unsigned indexForRegister[16] = { 0, 2, 1, 3, InvalidIndex, InvalidIndex, 5, 4, 6, 7, 8, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex };
+ unsigned result = indexForRegister[reg];
+ ASSERT(result != InvalidIndex);
+ return result;
+ }
+
+#ifndef NDEBUG
+ static const char* debugName(GPRReg reg)
+ {
+ ASSERT(reg != InvalidGPRReg);
+ ASSERT(reg < 16);
+ static const char* nameForRegister[16] = {
+ "rax", "rcx", "rdx", "rbx",
+ "rsp", "rbp", "rsi", "rdi",
+ "r8", "r9", "r10", "r11",
+ "r12", "r13", "r14", "r15"
+ };
+ return nameForRegister[reg];
+ }
+#endif
+private:
+
+ static const unsigned InvalidIndex = 0xffffffff;
+};
+
+#endif
+
+#if CPU(ARM_THUMB2)
+#define NUMBER_OF_ARGUMENT_REGISTERS 4
+
+class GPRInfo {
+public:
+ typedef GPRReg RegisterType;
+ static const unsigned numberOfRegisters = 9;
+
+ // Temporary registers.
+ static const GPRReg regT0 = ARMRegisters::r0;
+ static const GPRReg regT1 = ARMRegisters::r1;
+ static const GPRReg regT2 = ARMRegisters::r2;
+ static const GPRReg regT3 = ARMRegisters::r4;
+ static const GPRReg regT4 = ARMRegisters::r7;
+ static const GPRReg regT5 = ARMRegisters::r8;
+ static const GPRReg regT6 = ARMRegisters::r9;
+ static const GPRReg regT7 = ARMRegisters::r10;
+ static const GPRReg regT8 = ARMRegisters::r11;
+ // These registers match the baseline JIT.
+ static const GPRReg cachedResultRegister = regT0;
+ static const GPRReg cachedResultRegister2 = regT1;
+ static const GPRReg callFrameRegister = ARMRegisters::r5;
+ // These constants provide the names for the general purpose argument & return value registers.
+ static const GPRReg argumentGPR0 = ARMRegisters::r0; // regT0
+ static const GPRReg argumentGPR1 = ARMRegisters::r1; // regT1
+ static const GPRReg argumentGPR2 = ARMRegisters::r2; // regT2
+ // FIXME: r3 is currently used be the MacroAssembler as a temporary - it seems
+ // This could threoretically be a problem if theis is used in code generation
+ // between the arguments being set up, and the call being made. That said,
+ // any change introducing a problem here is likely to be immediately apparent!
+ static const GPRReg argumentGPR3 = ARMRegisters::r3; // FIXME!
+ static const GPRReg returnValueGPR = ARMRegisters::r0; // regT0
+ static const GPRReg returnValueGPR2 = ARMRegisters::r1; // regT1
+ static const GPRReg nonPreservedNonReturnGPR = ARMRegisters::r2;
+
+ static GPRReg toRegister(unsigned index)
+ {
+ ASSERT(index < numberOfRegisters);
+ static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6, regT7, regT8 };
+ return registerForIndex[index];
+ }
+
+ static unsigned toIndex(GPRReg reg)
+ {
+ ASSERT(reg != InvalidGPRReg);
+ ASSERT(reg < 16);
+ static const unsigned indexForRegister[16] = { 0, 1, 2, InvalidIndex, 3, InvalidIndex, InvalidIndex, 4, 5, 6, 7, 8, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex };
+ unsigned result = indexForRegister[reg];
+ ASSERT(result != InvalidIndex);
+ return result;
+ }
+
+#ifndef NDEBUG
+ static const char* debugName(GPRReg reg)
+ {
+ ASSERT(reg != InvalidGPRReg);
+ ASSERT(reg < 16);
+ static const char* nameForRegister[16] = {
+ "r0", "r1", "r2", "r3",
+ "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11",
+ "r12", "r13", "r14", "r15"
+ };
+ return nameForRegister[reg];
+ }
+#endif
+private:
+
+ static const unsigned InvalidIndex = 0xffffffff;
+};
+
+#endif
+
+typedef RegisterBank<GPRInfo>::iterator gpr_iterator;
+
+} } // namespace JSC::DFG
+
+#endif
+#endif