X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/4e4e5a6f2694187498445a6ac6f1634ce8141119..ed1e77d3adeb83d26fd1dfb16dd84cabdcefd250:/assembler/AssemblerBufferWithConstantPool.h diff --git a/assembler/AssemblerBufferWithConstantPool.h b/assembler/AssemblerBufferWithConstantPool.h index b1c537e..053884b 100644 --- a/assembler/AssemblerBufferWithConstantPool.h +++ b/assembler/AssemblerBufferWithConstantPool.h @@ -83,9 +83,16 @@ namespace JSC { */ template -class AssemblerBufferWithConstantPool: public AssemblerBuffer { +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,51 +183,33 @@ public: correctDeltas(8); } - int size() + void putIntegral(TwoShorts value) { - flushIfNoSpaceFor(maxInstructionSize, sizeof(uint64_t)); - return AssemblerBuffer::size(); + putIntegral(value.high); + putIntegral(value.low); } - int uncheckedSize() + void putIntegralUnchecked(TwoShorts value) { - return AssemblerBuffer::size(); + putIntegralUnchecked(value.high); + putIntegralUnchecked(value.low); } - void* executableCopy(ExecutablePool* allocator) + void putShortWithConstantInt(uint16_t insn, uint32_t constant, bool isReusable = false) { - flushConstantPool(false); - return AssemblerBuffer::executableCopy(allocator); + putIntegralWithConstantInt(insn, constant, isReusable); } void putIntWithConstantInt(uint32_t insn, uint32_t constant, bool isReusable = false) { - 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); - - AssemblerBuffer::putInt(AssemblerType::patchConstantPoolLoad(insn, m_numConsts)); - ++m_numConsts; - - correctDeltas(4, 4); + putIntegralWithConstantInt(insn, constant, isReusable); } // This flushing mechanism can be called after any unconditional jumps. void flushWithoutBarrier(bool isForced = false) { // Flush if constant pool is more than 60% full to avoid overuse of this function. - if (isForced || 5 * m_numConsts > 3 * maxPoolSize / sizeof(uint32_t)) + if (isForced || 5 * static_cast(m_numConsts) > 3 * maxPoolSize / sizeof(uint32_t)) flushConstantPool(false); } @@ -229,35 +223,18 @@ public: return m_numConsts; } -private: - void correctDeltas(int insnSize) - { - m_maxDistance -= insnSize; - m_lastConstDelta -= insnSize; - if (m_lastConstDelta < 0) - m_lastConstDelta = 0; - } - - void correctDeltas(int insnSize, int constSize) - { - correctDeltas(insnSize); - - m_maxDistance -= m_lastConstDelta; - m_lastConstDelta = constSize; - } - void flushConstantPool(bool useBarrier = true) { - if (m_numConsts == 0) + if (!m_numConsts) 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) @@ -268,18 +245,61 @@ 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; + } + +private: + void correctDeltas(int insnSize) + { + m_maxDistance -= insnSize; + m_lastConstDelta -= insnSize; + if (m_lastConstDelta < 0) + m_lastConstDelta = 0; + } + + void correctDeltas(int insnSize, int constSize) + { + correctDeltas(insnSize); + + m_maxDistance -= m_lastConstDelta; + 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 flushIfNoSpaceFor(int nextInsnSize)