X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/ba379fdc102753d6be2c4d937058fe40257329fe..93a3786624b2768d89bfa27e46598dc64e2fb70a:/assembler/AssemblerBufferWithConstantPool.h diff --git a/assembler/AssemblerBufferWithConstantPool.h b/assembler/AssemblerBufferWithConstantPool.h index f15b7f3..852f86d 100644 --- a/assembler/AssemblerBufferWithConstantPool.h +++ b/assembler/AssemblerBufferWithConstantPool.h @@ -27,13 +27,13 @@ #ifndef AssemblerBufferWithConstantPool_h #define AssemblerBufferWithConstantPool_h -#include - #if ENABLE(ASSEMBLER) #include "AssemblerBuffer.h" #include +#define ASSEMBLER_HAS_CONSTANT_POOL 1 + namespace JSC { /* @@ -83,9 +83,16 @@ namespace JSC { */ template -class AssemblerBufferWithConstantPool: public AssemblerBuffer { - typedef WTF::SegmentedVector LoadOffsets; +class AssemblerBufferWithConstantPool : public AssemblerBuffer { + typedef SegmentedVector LoadOffsets; + using AssemblerBuffer::putIntegral; + using AssemblerBuffer::putIntegralUnchecked; public: + typedef struct { + short high; + short low; + } TwoShorts; + enum { UniqueConst, ReusableConst, @@ -120,6 +127,11 @@ public: AssemblerBuffer::ensureSpace(insnSpace); } + void ensureSpaceForAnyInstruction(int amount = 1) + { + flushIfNoSpaceFor(amount * maxInstructionSize, amount * sizeof(uint64_t)); + } + bool isAligned(int alignment) { flushIfNoSpaceFor(alignment); @@ -171,46 +183,39 @@ public: correctDeltas(8); } - int size() + void putIntegral(TwoShorts value) { - flushIfNoSpaceFor(maxInstructionSize, sizeof(uint64_t)); - return AssemblerBuffer::size(); + putIntegral(value.high); + putIntegral(value.low); } - void* executableCopy(ExecutablePool* allocator) + void putIntegralUnchecked(TwoShorts value) { - flushConstantPool(false); - return AssemblerBuffer::executableCopy(allocator); + putIntegralUnchecked(value.high); + putIntegralUnchecked(value.low); } - void putIntWithConstantInt(uint32_t insn, uint32_t constant, bool isReusable = false) + PassRefPtr executableCopy(VM& vm, void* ownerUID, JITCompilationEffort effort) { - flushIfNoSpaceFor(4, 4); - - m_loadOffsets.append(AssemblerBuffer::size()); - if (isReusable) - for (int i = 0; i < m_numConsts; ++i) { - if (m_mask[i] == ReusableConst && m_pool[i] == constant) { - AssemblerBuffer::putInt(AssemblerType::patchConstantPoolLoad(insn, i)); - correctDeltas(4); - return; - } - } - - m_pool[m_numConsts] = constant; - m_mask[m_numConsts] = static_cast(isReusable ? ReusableConst : UniqueConst); + flushConstantPool(false); + return AssemblerBuffer::executableCopy(vm, ownerUID, effort); + } - AssemblerBuffer::putInt(AssemblerType::patchConstantPoolLoad(insn, m_numConsts)); - ++m_numConsts; + void putShortWithConstantInt(uint16_t insn, uint32_t constant, bool isReusable = false) + { + putIntegralWithConstantInt(insn, constant, isReusable); + } - correctDeltas(4, 4); + void putIntWithConstantInt(uint32_t insn, uint32_t constant, bool isReusable = false) + { + putIntegralWithConstantInt(insn, constant, isReusable); } // This flushing mechanism can be called after any unconditional jumps. - void flushWithoutBarrier() + void flushWithoutBarrier(bool isForced = false) { // Flush if constant pool is more than 60% full to avoid overuse of this function. - if (5 * m_numConsts > 3 * maxPoolSize / sizeof(uint32_t)) + if (isForced || 5 * static_cast(m_numConsts) > 3 * maxPoolSize / sizeof(uint32_t)) flushConstantPool(false); } @@ -219,6 +224,11 @@ public: return m_pool; } + int sizeOfConstantPool() + { + return m_numConsts; + } + private: void correctDeltas(int insnSize) { @@ -236,18 +246,45 @@ private: m_lastConstDelta = constSize; } + template + void putIntegralWithConstantInt(IntegralType insn, uint32_t constant, bool isReusable) + { + if (!m_numConsts) + m_maxDistance = maxPoolSize; + flushIfNoSpaceFor(sizeof(IntegralType), 4); + + m_loadOffsets.append(codeSize()); + if (isReusable) { + for (int i = 0; i < m_numConsts; ++i) { + if (m_mask[i] == ReusableConst && m_pool[i] == constant) { + putIntegral(static_cast(AssemblerType::patchConstantPoolLoad(insn, i))); + correctDeltas(sizeof(IntegralType)); + return; + } + } + } + + m_pool[m_numConsts] = constant; + m_mask[m_numConsts] = static_cast(isReusable ? ReusableConst : UniqueConst); + + putIntegral(static_cast(AssemblerType::patchConstantPoolLoad(insn, m_numConsts))); + ++m_numConsts; + + correctDeltas(sizeof(IntegralType), 4); + } + void flushConstantPool(bool useBarrier = true) { if (m_numConsts == 0) return; - int alignPool = (AssemblerBuffer::size() + (useBarrier ? barrierSize : 0)) & (sizeof(uint64_t) - 1); + int alignPool = (codeSize() + (useBarrier ? barrierSize : 0)) & (sizeof(uint64_t) - 1); if (alignPool) alignPool = sizeof(uint64_t) - alignPool; // Callback to protect the constant pool from execution if (useBarrier) - AssemblerBuffer::putInt(AssemblerType::placeConstantPoolBarrier(m_numConsts * sizeof(uint32_t) + alignPool)); + putIntegral(AssemblerType::placeConstantPoolBarrier(m_numConsts * sizeof(uint32_t) + alignPool)); if (alignPool) { if (alignPool & 1) @@ -258,25 +295,25 @@ private: AssemblerBuffer::putInt(AssemblerType::padForAlign32); } - int constPoolOffset = AssemblerBuffer::size(); + int constPoolOffset = codeSize(); append(reinterpret_cast(m_pool), m_numConsts * sizeof(uint32_t)); // Patch each PC relative load for (LoadOffsets::Iterator iter = m_loadOffsets.begin(); iter != m_loadOffsets.end(); ++iter) { - void* loadAddr = reinterpret_cast(m_buffer + *iter); - AssemblerType::patchConstantPoolLoad(loadAddr, reinterpret_cast(m_buffer + constPoolOffset)); + void* loadAddr = reinterpret_cast(data()) + *iter; + AssemblerType::patchConstantPoolLoad(loadAddr, reinterpret_cast(data()) + constPoolOffset); } m_loadOffsets.clear(); m_numConsts = 0; - m_maxDistance = maxPoolSize; } void flushIfNoSpaceFor(int nextInsnSize) { if (m_numConsts == 0) return; - if ((m_maxDistance < nextInsnSize + m_lastConstDelta + barrierSize + (int)sizeof(uint32_t))) + int lastConstDelta = m_lastConstDelta > nextInsnSize ? m_lastConstDelta - nextInsnSize : 0; + if ((m_maxDistance < nextInsnSize + lastConstDelta + barrierSize + (int)sizeof(uint32_t))) flushConstantPool(); } @@ -284,8 +321,8 @@ private: { if (m_numConsts == 0) return; - if ((m_maxDistance < nextInsnSize + m_lastConstDelta + barrierSize + (int)sizeof(uint32_t)) || - (m_numConsts + nextConstSize / sizeof(uint32_t) >= maxPoolSize)) + if ((m_maxDistance < nextInsnSize + m_lastConstDelta + nextConstSize + barrierSize + (int)sizeof(uint32_t)) || + (m_numConsts * sizeof(uint32_t) + nextConstSize >= maxPoolSize)) flushConstantPool(); }