⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jitinlinemethods.h

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 H
字号:
/* * Copyright (C) 2008 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 JITInlineMethods_h#define JITInlineMethods_h#include <wtf/Platform.h>#if ENABLE(JIT)#if PLATFORM(WIN)#undef FIELD_OFFSET // Fix conflict with winnt.h.#endif// FIELD_OFFSET: Like the C++ offsetof macro, but you can use it with classes.// The magic number 0x4000 is insignificant. We use it to avoid using NULL, since// NULL can cause compiler problems, especially in cases of multiple inheritance.#define FIELD_OFFSET(class, field) (reinterpret_cast<ptrdiff_t>(&(reinterpret_cast<class*>(0x4000)->field)) - 0x4000)namespace JSC {ALWAYS_INLINE void JIT::killLastResultRegister(){    m_lastResultBytecodeRegister = std::numeric_limits<int>::max();}// get arg puts an arg from the SF register array into a h/w registerALWAYS_INLINE void JIT::emitGetVirtualRegister(int src, RegisterID dst){    ASSERT(m_bytecodeIndex != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeIndex is set.    // TODO: we want to reuse values that are already in registers if we can - add a register allocator!    if (m_codeBlock->isConstantRegisterIndex(src)) {        JSValuePtr value = m_codeBlock->getConstant(src);        move(ImmPtr(JSValuePtr::encode(value)), dst);        killLastResultRegister();        return;    }    if (src == m_lastResultBytecodeRegister && m_codeBlock->isTemporaryRegisterIndex(src)) {        bool atJumpTarget = false;        while (m_jumpTargetsPosition < m_codeBlock->numberOfJumpTargets() && m_codeBlock->jumpTarget(m_jumpTargetsPosition) <= m_bytecodeIndex) {            if (m_codeBlock->jumpTarget(m_jumpTargetsPosition) == m_bytecodeIndex)                atJumpTarget = true;            ++m_jumpTargetsPosition;        }        if (!atJumpTarget) {            // The argument we want is already stored in eax            if (dst != cachedResultRegister)                move(cachedResultRegister, dst);            killLastResultRegister();            return;        }    }    loadPtr(Address(callFrameRegister, src * sizeof(Register)), dst);    killLastResultRegister();}ALWAYS_INLINE void JIT::emitGetVirtualRegisters(int src1, RegisterID dst1, int src2, RegisterID dst2){    if (src2 == m_lastResultBytecodeRegister) {        emitGetVirtualRegister(src2, dst2);        emitGetVirtualRegister(src1, dst1);    } else {        emitGetVirtualRegister(src1, dst1);        emitGetVirtualRegister(src2, dst2);    }}// puts an arg onto the stack, as an arg to a context threaded function.ALWAYS_INLINE void JIT::emitPutJITStubArg(RegisterID src, unsigned argumentNumber){    poke(src, argumentNumber);}ALWAYS_INLINE void JIT::emitPutJITStubArgConstant(unsigned value, unsigned argumentNumber){    poke(Imm32(value), argumentNumber);}ALWAYS_INLINE void JIT::emitPutJITStubArgConstant(void* value, unsigned argumentNumber){    poke(ImmPtr(value), argumentNumber);}ALWAYS_INLINE void JIT::emitGetJITStubArg(unsigned argumentNumber, RegisterID dst){    peek(dst, argumentNumber);}ALWAYS_INLINE JSValuePtr JIT::getConstantOperand(unsigned src){    ASSERT(m_codeBlock->isConstantRegisterIndex(src));    return m_codeBlock->getConstant(src);}ALWAYS_INLINE int32_t JIT::getConstantOperandImmediateInt(unsigned src){    return getConstantOperand(src).getInt32Fast();}ALWAYS_INLINE bool JIT::isOperandConstantImmediateInt(unsigned src){    return m_codeBlock->isConstantRegisterIndex(src) && getConstantOperand(src).isInt32Fast();}// get arg puts an arg from the SF register array onto the stack, as an arg to a context threaded function.ALWAYS_INLINE void JIT::emitPutJITStubArgFromVirtualRegister(unsigned src, unsigned argumentNumber, RegisterID scratch){    if (m_codeBlock->isConstantRegisterIndex(src)) {        JSValuePtr value = m_codeBlock->getConstant(src);        emitPutJITStubArgConstant(JSValuePtr::encode(value), argumentNumber);    } else {        loadPtr(Address(callFrameRegister, src * sizeof(Register)), scratch);        emitPutJITStubArg(scratch, argumentNumber);    }    killLastResultRegister();}ALWAYS_INLINE void JIT::emitPutCTIParam(void* value, unsigned name){    poke(ImmPtr(value), name);}ALWAYS_INLINE void JIT::emitPutCTIParam(RegisterID from, unsigned name){    poke(from, name);}ALWAYS_INLINE void JIT::emitGetCTIParam(unsigned name, RegisterID to){    peek(to, name);    killLastResultRegister();}ALWAYS_INLINE void JIT::emitPutToCallFrameHeader(RegisterID from, RegisterFile::CallFrameHeaderEntry entry){    storePtr(from, Address(callFrameRegister, entry * sizeof(Register)));}ALWAYS_INLINE void JIT::emitPutImmediateToCallFrameHeader(void* value, RegisterFile::CallFrameHeaderEntry entry){    storePtr(ImmPtr(value), Address(callFrameRegister, entry * sizeof(Register)));}ALWAYS_INLINE void JIT::emitGetFromCallFrameHeader(RegisterFile::CallFrameHeaderEntry entry, RegisterID to){    loadPtr(Address(callFrameRegister, entry * sizeof(Register)), to);    killLastResultRegister();}ALWAYS_INLINE void JIT::emitPutVirtualRegister(unsigned dst, RegisterID from){    storePtr(from, Address(callFrameRegister, dst * sizeof(Register)));    m_lastResultBytecodeRegister = (from == cachedResultRegister) ? dst : std::numeric_limits<int>::max();    // FIXME: #ifndef NDEBUG, Write the correct m_type to the register.}ALWAYS_INLINE void JIT::emitInitRegister(unsigned dst){    storePtr(ImmPtr(JSValuePtr::encode(jsUndefined())), Address(callFrameRegister, dst * sizeof(Register)));    // FIXME: #ifndef NDEBUG, Write the correct m_type to the register.}ALWAYS_INLINE JIT::Call JIT::emitNakedCall(void* function){    ASSERT(m_bytecodeIndex != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeIndex is set.    Call nakedCall = nearCall();    m_calls.append(CallRecord(nakedCall, m_bytecodeIndex, function));    return nakedCall;}#if USE(JIT_STUB_ARGUMENT_REGISTER)ALWAYS_INLINE void JIT::restoreArgumentReference(){    move(stackPointerRegister, firstArgumentRegister);    emitPutCTIParam(callFrameRegister, STUB_ARGS_callFrame);}ALWAYS_INLINE void JIT::restoreArgumentReferenceForTrampoline(){    // In the trampoline on x86-64, the first argument register is not overwritten.#if !PLATFORM(X86_64)    move(stackPointerRegister, firstArgumentRegister);    addPtr(Imm32(sizeof(void*)), firstArgumentRegister);#endif}#elif USE(JIT_STUB_ARGUMENT_STACK)ALWAYS_INLINE void JIT::restoreArgumentReference(){    poke(stackPointerRegister);    emitPutCTIParam(callFrameRegister, STUB_ARGS_callFrame);}ALWAYS_INLINE void JIT::restoreArgumentReferenceForTrampoline() {}#else // JIT_STUB_ARGUMENT_VA_LISTALWAYS_INLINE void JIT::restoreArgumentReference(){    emitPutCTIParam(callFrameRegister, STUB_ARGS_callFrame);}ALWAYS_INLINE void JIT::restoreArgumentReferenceForTrampoline() {}#endifALWAYS_INLINE JIT::Call JIT::emitCTICall_internal(void* helper){    ASSERT(m_bytecodeIndex != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeIndex is set.#if ENABLE(OPCODE_SAMPLING)    sampleInstruction(m_codeBlock->instructions().begin() + m_bytecodeIndex, true);#endif    restoreArgumentReference();    Call ctiCall = call();    m_calls.append(CallRecord(ctiCall, m_bytecodeIndex, helper));#if ENABLE(OPCODE_SAMPLING)    sampleInstruction(m_codeBlock->instructions().begin() + m_bytecodeIndex, false);#endif    killLastResultRegister();    return ctiCall;}ALWAYS_INLINE JIT::Jump JIT::checkStructure(RegisterID reg, Structure* structure){    return branchPtr(NotEqual, Address(reg, FIELD_OFFSET(JSCell, m_structure)), ImmPtr(structure));}ALWAYS_INLINE JIT::Jump JIT::emitJumpIfJSCell(RegisterID reg){#if USE(ALTERNATE_JSIMMEDIATE)    return branchTestPtr(Zero, reg, tagMaskRegister);#else    return branchTest32(Zero, reg, Imm32(JSImmediate::TagMask));#endif}ALWAYS_INLINE JIT::Jump JIT::emitJumpIfBothJSCells(RegisterID reg1, RegisterID reg2, RegisterID scratch){    move(reg1, scratch);    orPtr(reg2, scratch);    return emitJumpIfJSCell(scratch);}ALWAYS_INLINE void JIT::emitJumpSlowCaseIfJSCell(RegisterID reg){    addSlowCase(emitJumpIfJSCell(reg));}ALWAYS_INLINE JIT::Jump JIT::emitJumpIfNotJSCell(RegisterID reg){#if USE(ALTERNATE_JSIMMEDIATE)    return branchTestPtr(NonZero, reg, tagMaskRegister);#else    return branchTest32(NonZero, reg, Imm32(JSImmediate::TagMask));#endif}ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotJSCell(RegisterID reg){    addSlowCase(emitJumpIfNotJSCell(reg));}ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotJSCell(RegisterID reg, int vReg){    if (!m_codeBlock->isKnownNotImmediate(vReg))        emitJumpSlowCaseIfNotJSCell(reg);}ALWAYS_INLINE void JIT::linkSlowCaseIfNotJSCell(Vector<SlowCaseEntry>::iterator& iter, int vReg){    if (!m_codeBlock->isKnownNotImmediate(vReg))        linkSlowCase(iter);}#if USE(ALTERNATE_JSIMMEDIATE)ALWAYS_INLINE JIT::Jump JIT::emitJumpIfImmediateNumber(RegisterID reg){    return branchTestPtr(NonZero, reg, tagTypeNumberRegister);}ALWAYS_INLINE JIT::Jump JIT::emitJumpIfNotImmediateNumber(RegisterID reg){    return branchTestPtr(Zero, reg, tagTypeNumberRegister);}#endifALWAYS_INLINE JIT::Jump JIT::emitJumpIfImmediateInteger(RegisterID reg){#if USE(ALTERNATE_JSIMMEDIATE)    return branchPtr(AboveOrEqual, reg, tagTypeNumberRegister);#else    return branchTest32(NonZero, reg, Imm32(JSImmediate::TagTypeNumber));#endif}ALWAYS_INLINE JIT::Jump JIT::emitJumpIfNotImmediateInteger(RegisterID reg){#if USE(ALTERNATE_JSIMMEDIATE)    return branchPtr(Below, reg, tagTypeNumberRegister);#else    return branchTest32(Zero, reg, Imm32(JSImmediate::TagTypeNumber));#endif}ALWAYS_INLINE JIT::Jump JIT::emitJumpIfNotImmediateIntegers(RegisterID reg1, RegisterID reg2, RegisterID scratch){    move(reg1, scratch);    andPtr(reg2, scratch);    return emitJumpIfNotImmediateInteger(scratch);}ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotImmediateInteger(RegisterID reg){    addSlowCase(emitJumpIfNotImmediateInteger(reg));}ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotImmediateIntegers(RegisterID reg1, RegisterID reg2, RegisterID scratch){    addSlowCase(emitJumpIfNotImmediateIntegers(reg1, reg2, scratch));}#if !USE(ALTERNATE_JSIMMEDIATE)ALWAYS_INLINE void JIT::emitFastArithDeTagImmediate(RegisterID reg){    subPtr(Imm32(JSImmediate::TagTypeNumber), reg);}ALWAYS_INLINE JIT::Jump JIT::emitFastArithDeTagImmediateJumpIfZero(RegisterID reg){    return branchSubPtr(Zero, Imm32(JSImmediate::TagTypeNumber), reg);}#endifALWAYS_INLINE void JIT::emitFastArithReTagImmediate(RegisterID src, RegisterID dest){#if USE(ALTERNATE_JSIMMEDIATE)    emitFastArithIntToImmNoCheck(src, dest);#else    if (src != dest)        move(src, dest);    addPtr(Imm32(JSImmediate::TagTypeNumber), dest);#endif}ALWAYS_INLINE void JIT::emitFastArithImmToInt(RegisterID reg){#if USE(ALTERNATE_JSIMMEDIATE)    UNUSED_PARAM(reg);#else    rshiftPtr(Imm32(JSImmediate::IntegerPayloadShift), reg);#endif}// operand is int32_t, must have been zero-extended if register is 64-bit.ALWAYS_INLINE void JIT::emitFastArithIntToImmNoCheck(RegisterID src, RegisterID dest){#if USE(ALTERNATE_JSIMMEDIATE)    if (src != dest)        move(src, dest);    orPtr(tagTypeNumberRegister, dest);#else    signExtend32ToPtr(src, dest);    addPtr(dest, dest);    emitFastArithReTagImmediate(dest, dest);#endif}ALWAYS_INLINE void JIT::emitTagAsBoolImmediate(RegisterID reg){    lshift32(Imm32(JSImmediate::ExtendedPayloadShift), reg);    or32(Imm32(static_cast<int32_t>(JSImmediate::FullTagTypeBool)), reg);}ALWAYS_INLINE void JIT::addSlowCase(Jump jump){    ASSERT(m_bytecodeIndex != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeIndex is set.    m_slowCases.append(SlowCaseEntry(jump, m_bytecodeIndex));}ALWAYS_INLINE void JIT::addJump(Jump jump, int relativeOffset){    ASSERT(m_bytecodeIndex != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeIndex is set.    m_jmpTable.append(JumpTable(jump, m_bytecodeIndex + relativeOffset));}ALWAYS_INLINE void JIT::emitJumpSlowToHot(Jump jump, int relativeOffset){    ASSERT(m_bytecodeIndex != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeIndex is set.    jump.linkTo(m_labels[m_bytecodeIndex + relativeOffset], this);}}#endif // ENABLE(JIT)#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -