X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/93a3786624b2768d89bfa27e46598dc64e2fb70a..refs/heads/master:/assembler/LinkBuffer.cpp?ds=sidebyside diff --git a/assembler/LinkBuffer.cpp b/assembler/LinkBuffer.cpp index e4bc958..d53ef45 100644 --- a/assembler/LinkBuffer.cpp +++ b/assembler/LinkBuffer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Apple Inc. All rights reserved. + * Copyright (C) 2012-2015 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,52 +28,86 @@ #if ENABLE(ASSEMBLER) +#include "CodeBlock.h" +#include "JITCode.h" +#include "JSCInlines.h" #include "Options.h" +#include "VM.h" +#include namespace JSC { +bool shouldShowDisassemblyFor(CodeBlock* codeBlock) +{ + if (JITCode::isOptimizingJIT(codeBlock->jitType()) && Options::showDFGDisassembly()) + return true; + return Options::showDisassembly(); +} + LinkBuffer::CodeRef LinkBuffer::finalizeCodeWithoutDisassembly() { performFinalization(); - return CodeRef(m_executableMemory); + ASSERT(m_didAllocate); + if (m_executableMemory) + return CodeRef(m_executableMemory); + + return CodeRef::createSelfManagedCodeRef(MacroAssemblerCodePtr(m_code)); } LinkBuffer::CodeRef LinkBuffer::finalizeCodeWithDisassembly(const char* format, ...) { - ASSERT(Options::showDisassembly() || Options::showDFGDisassembly()); - CodeRef result = finalizeCodeWithoutDisassembly(); + + if (m_alreadyDisassembled) + return result; - dataLogF("Generated JIT code for "); + StringPrintStream out; + out.printf("Generated JIT code for "); va_list argList; va_start(argList, format); - WTF::dataLogFV(format, argList); + out.vprintf(format, argList); va_end(argList); - dataLogF(":\n"); + out.printf(":\n"); + + out.printf(" Code at [%p, %p):\n", result.code().executableAddress(), static_cast(result.code().executableAddress()) + result.size()); + + CString header = out.toCString(); + + if (Options::asyncDisassembly()) { + disassembleAsynchronously(header, result, m_size, " "); + return result; + } - dataLogF(" Code at [%p, %p):\n", result.code().executableAddress(), static_cast(result.code().executableAddress()) + result.size()); + dataLog(header); disassemble(result.code(), m_size, " ", WTF::dataFile()); return result; } #if ENABLE(BRANCH_COMPACTION) +static ALWAYS_INLINE void recordLinkOffsets(AssemblerData& assemblerData, int32_t regionStart, int32_t regionEnd, int32_t offset) +{ + int32_t ptr = regionStart / sizeof(int32_t); + const int32_t end = regionEnd / sizeof(int32_t); + int32_t* offsets = reinterpret_cast(assemblerData.buffer()); + while (ptr < end) + offsets[ptr++] = offset; +} + template -void LinkBuffer::copyCompactAndLinkCode(void* ownerUID, JITCompilationEffort effort) +void LinkBuffer::copyCompactAndLinkCode(MacroAssembler& macroAssembler, void* ownerUID, JITCompilationEffort effort) { - m_initialSize = m_assembler->m_assembler.codeSize(); - m_executableMemory = m_vm->executableAllocator.allocate(*m_vm, m_initialSize, ownerUID, effort); - if (!m_executableMemory) + m_initialSize = macroAssembler.m_assembler.codeSize(); + allocate(m_initialSize, ownerUID, effort); + if (didFailToAllocate()) return; - m_code = (uint8_t*)m_executableMemory->start(); - ASSERT(m_code); - ExecutableAllocator::makeWritable(m_code, m_initialSize); - uint8_t* inData = (uint8_t*)m_assembler->unlinkedCode(); + Vector& jumpsToLink = macroAssembler.jumpsToLink(); + m_assemblerStorage = macroAssembler.m_assembler.buffer().releaseAssemblerData(); + uint8_t* inData = reinterpret_cast(m_assemblerStorage.buffer()); uint8_t* outData = reinterpret_cast(m_code); int readPtr = 0; int writePtr = 0; - Vector& jumpsToLink = m_assembler->jumpsToLink(); unsigned jumpCount = jumpsToLink.size(); for (unsigned i = 0; i < jumpCount; ++i) { int offset = readPtr - writePtr; @@ -89,7 +123,7 @@ void LinkBuffer::copyCompactAndLinkCode(void* ownerUID, JITCompilationEffort eff ASSERT(!(writePtr % 2)); while (copySource != copyEnd) *copyDst++ = *copySource++; - m_assembler->recordLinkOffsets(readPtr, jumpsToLink[i].from(), offset); + recordLinkOffsets(m_assemblerStorage, readPtr, jumpsToLink[i].from(), offset); readPtr += regionSize; writePtr += regionSize; @@ -99,33 +133,32 @@ void LinkBuffer::copyCompactAndLinkCode(void* ownerUID, JITCompilationEffort eff if (jumpsToLink[i].to() >= jumpsToLink[i].from()) target = outData + jumpsToLink[i].to() - offset; // Compensate for what we have collapsed so far else - target = outData + jumpsToLink[i].to() - m_assembler->executableOffsetFor(jumpsToLink[i].to()); + target = outData + jumpsToLink[i].to() - executableOffsetFor(jumpsToLink[i].to()); - JumpLinkType jumpLinkType = m_assembler->computeJumpType(jumpsToLink[i], outData + writePtr, target); + JumpLinkType jumpLinkType = MacroAssembler::computeJumpType(jumpsToLink[i], outData + writePtr, target); // Compact branch if we can... - if (m_assembler->canCompact(jumpsToLink[i].type())) { + if (MacroAssembler::canCompact(jumpsToLink[i].type())) { // Step back in the write stream - int32_t delta = m_assembler->jumpSizeDelta(jumpsToLink[i].type(), jumpLinkType); + int32_t delta = MacroAssembler::jumpSizeDelta(jumpsToLink[i].type(), jumpLinkType); if (delta) { writePtr -= delta; - m_assembler->recordLinkOffsets(jumpsToLink[i].from() - delta, readPtr, readPtr - writePtr); + recordLinkOffsets(m_assemblerStorage, jumpsToLink[i].from() - delta, readPtr, readPtr - writePtr); } } jumpsToLink[i].setFrom(writePtr); } // Copy everything after the last jump memcpy(outData + writePtr, inData + readPtr, m_initialSize - readPtr); - m_assembler->recordLinkOffsets(readPtr, m_initialSize, readPtr - writePtr); + recordLinkOffsets(m_assemblerStorage, readPtr, m_initialSize, readPtr - writePtr); for (unsigned i = 0; i < jumpCount; ++i) { uint8_t* location = outData + jumpsToLink[i].from(); - uint8_t* target = outData + jumpsToLink[i].to() - m_assembler->executableOffsetFor(jumpsToLink[i].to()); - m_assembler->link(jumpsToLink[i], location, target); + uint8_t* target = outData + jumpsToLink[i].to() - executableOffsetFor(jumpsToLink[i].to()); + MacroAssembler::link(jumpsToLink[i], location, target); } jumpsToLink.clear(); - m_size = writePtr + m_initialSize - readPtr; - m_executableMemory->shrink(m_size); + shrink(writePtr + m_initialSize - readPtr); #if DUMP_LINK_STATISTICS dumpLinkStatistics(m_code, m_initialSize, m_size); @@ -137,26 +170,63 @@ void LinkBuffer::copyCompactAndLinkCode(void* ownerUID, JITCompilationEffort eff #endif -void LinkBuffer::linkCode(void* ownerUID, JITCompilationEffort effort) +void LinkBuffer::linkCode(MacroAssembler& macroAssembler, void* ownerUID, JITCompilationEffort effort) { - ASSERT(!m_code); #if !ENABLE(BRANCH_COMPACTION) - m_executableMemory = m_assembler->m_assembler.executableCopy(*m_vm, ownerUID, effort); - if (!m_executableMemory) +#if defined(ASSEMBLER_HAS_CONSTANT_POOL) && ASSEMBLER_HAS_CONSTANT_POOL + macroAssembler.m_assembler.buffer().flushConstantPool(false); +#endif + AssemblerBuffer& buffer = macroAssembler.m_assembler.buffer(); + allocate(buffer.codeSize(), ownerUID, effort); + if (!m_didAllocate) return; - m_code = m_executableMemory->start(); - m_size = m_assembler->m_assembler.codeSize(); ASSERT(m_code); +#if CPU(ARM_TRADITIONAL) + macroAssembler.m_assembler.prepareExecutableCopy(m_code); +#endif + memcpy(m_code, buffer.data(), buffer.codeSize()); +#if CPU(MIPS) + macroAssembler.m_assembler.relocateJumps(buffer.data(), m_code); +#endif #elif CPU(ARM_THUMB2) - copyCompactAndLinkCode(ownerUID, effort); + copyCompactAndLinkCode(macroAssembler, ownerUID, effort); #elif CPU(ARM64) - copyCompactAndLinkCode(ownerUID, effort); + copyCompactAndLinkCode(macroAssembler, ownerUID, effort); #endif } +void LinkBuffer::allocate(size_t initialSize, void* ownerUID, JITCompilationEffort effort) +{ + if (m_code) { + if (initialSize > m_size) + return; + + m_didAllocate = true; + m_size = initialSize; + return; + } + + m_executableMemory = m_vm->executableAllocator.allocate(*m_vm, initialSize, ownerUID, effort); + if (!m_executableMemory) + return; + ExecutableAllocator::makeWritable(m_executableMemory->start(), m_executableMemory->sizeInBytes()); + m_code = m_executableMemory->start(); + m_size = initialSize; + m_didAllocate = true; +} + +void LinkBuffer::shrink(size_t newSize) +{ + if (!m_executableMemory) + return; + m_size = newSize; + m_executableMemory->shrink(m_size); +} + void LinkBuffer::performFinalization() { #ifndef NDEBUG + ASSERT(!isCompilationThread()); ASSERT(!m_completed); ASSERT(isValid()); m_completed = true;