/* * Copyright (C) 2011, 2013 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 GPRInfo_h #define GPRInfo_h #include "MacroAssembler.h" #include namespace JSC { typedef MacroAssembler::RegisterID GPRReg; #define InvalidGPRReg ((::JSC::GPRReg)-1) #if ENABLE(JIT) #if USE(JSVALUE64) class JSValueRegs { public: JSValueRegs() : m_gpr(InvalidGPRReg) { } explicit JSValueRegs(GPRReg gpr) : m_gpr(gpr) { } static JSValueRegs payloadOnly(GPRReg gpr) { return JSValueRegs(gpr); } bool operator!() const { return m_gpr == InvalidGPRReg; } GPRReg gpr() const { return m_gpr; } GPRReg tagGPR() const { return InvalidGPRReg; } GPRReg payloadGPR() 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 // USE(JSVALUE64) #if USE(JSVALUE32_64) class JSValueRegs { public: JSValueRegs() : m_tagGPR(static_cast(InvalidGPRReg)) , m_payloadGPR(static_cast(InvalidGPRReg)) { } JSValueRegs(GPRReg tagGPR, GPRReg payloadGPR) : m_tagGPR(tagGPR) , m_payloadGPR(payloadGPR) { } static JSValueRegs payloadOnly(GPRReg gpr) { return JSValueRegs(InvalidGPRReg, gpr); } bool operator!() const { return static_cast(m_tagGPR) == InvalidGPRReg && static_cast(m_payloadGPR) == InvalidGPRReg; } GPRReg tagGPR() const { return static_cast(m_tagGPR); } GPRReg payloadGPR() const { return static_cast(m_payloadGPR); } GPRReg gpr(WhichValueWord which) const { switch (which) { case TagWord: return tagGPR(); case PayloadWord: return payloadGPR(); } ASSERT_NOT_REACHED(); return tagGPR(); } private: int8_t m_tagGPR; int8_t m_payloadGPR; }; class JSValueSource { public: JSValueSource() : m_offset(notAddress()) , m_baseOrTag(static_cast(InvalidGPRReg)) , m_payload(static_cast(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(tagGPR)) , m_payload(static_cast(payloadGPR)) , m_tagType(0) { } JSValueSource(MacroAssembler::Address address) : m_offset(address.offset) , m_baseOrTag(static_cast(address.base)) , m_payload(static_cast(InvalidGPRReg)) , m_tagType(0) { ASSERT(m_offset != notAddress()); ASSERT(static_cast(m_baseOrTag) != InvalidGPRReg); } static JSValueSource unboxedCell(GPRReg payloadGPR) { JSValueSource result; result.m_offset = notAddress(); result.m_baseOrTag = static_cast(InvalidGPRReg); result.m_payload = static_cast(payloadGPR); result.m_tagType = static_cast(JSValue::CellTag); return result; } bool operator!() const { return static_cast(m_baseOrTag) == InvalidGPRReg && static_cast(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(m_baseOrTag); } GPRReg tagGPR() const { ASSERT(!isAddress() && static_cast(m_baseOrTag) != InvalidGPRReg); return static_cast(m_baseOrTag); } GPRReg payloadGPR() const { ASSERT(!isAddress()); return static_cast(m_payload); } bool hasKnownTag() const { ASSERT(!!*this); ASSERT(!isAddress()); return static_cast(m_baseOrTag) == InvalidGPRReg; } uint32_t tag() const { return static_cast(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 // USE(JSVALUE32_64) // The baseline JIT requires that regT3 be callee-preserved. #if CPU(X86) #define NUMBER_OF_ARGUMENT_REGISTERS 0u class GPRInfo { public: typedef GPRReg RegisterType; static const unsigned numberOfRegisters = 6; static const unsigned numberOfArgumentRegisters = NUMBER_OF_ARGUMENT_REGISTERS; // Note: regT3 is required to be callee-preserved. // 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; // These registers match the baseline JIT. static const GPRReg cachedResultRegister = regT0; static const GPRReg cachedResultRegister2 = regT1; static const GPRReg callFrameRegister = X86Registers::ebp; // 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 nonArgGPR0 = X86Registers::esi; // regT4 static const GPRReg nonArgGPR1 = X86Registers::eax; // regT0 static const GPRReg nonArgGPR2 = X86Registers::ebx; // regT3 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 (reg) (reg) (reg) (reg) (reg) (reg) (reg) != InvalidGPRReg); ASSERT(static_cast(reg)