void Disassembler::dumpHeader(PrintStream& out, LinkBuffer& linkBuffer) { out.print("Generated DFG JIT code for ", CodeBlockWithJITType(m_graph.m_codeBlock, JITCode::DFGJIT), ", instruction count = ", m_graph.m_codeBlock->instructionCount(), ":\n"); out.print(" Optimized with execution counter = ", m_graph.m_profiledBlock->jitExecuteCounter(), "\n"); out.print(" Source: ", m_graph.m_codeBlock->sourceCodeOnOneLine(), "\n"); out.print(" Code at [", RawPointer(linkBuffer.debugAddress()), ", ", RawPointer(static_cast<char*>(linkBuffer.debugAddress()) + linkBuffer.debugSize()), "):\n"); }
bool JITFinalizer::finalizeFunction() { RELEASE_ASSERT(!m_withArityCheck.isEmptyValue()); m_jitCode->initializeCodeRef( FINALIZE_DFG_CODE(*m_linkBuffer, ("DFG JIT code for %s", toCString(CodeBlockWithJITType(m_plan.codeBlock.get(), JITCode::DFGJIT)).data())), m_withArityCheck); m_plan.codeBlock->setJITCode(m_jitCode); finalizeCommon(); return true; }
bool JITFinalizer::finalize() { m_jitCode->initializeCodeRef( FINALIZE_DFG_CODE(*m_linkBuffer, ("DFG JIT code for %s", toCString(CodeBlockWithJITType(m_plan.codeBlock.get(), JITCode::DFGJIT)).data())), MacroAssemblerCodePtr()); m_plan.codeBlock->setJITCode(m_jitCode); finalizeCommon(); return true; }
void Disassembler::dump(PrintStream& out, LinkBuffer& linkBuffer) { m_graph.m_dominators.computeIfNecessary(m_graph); out.print("Generated DFG JIT code for ", CodeBlockWithJITType(m_graph.m_codeBlock, JITCode::DFGJIT), ", instruction count = ", m_graph.m_codeBlock->instructionCount(), ":\n"); out.print(" Code at [", RawPointer(linkBuffer.debugAddress()), ", ", RawPointer(static_cast<char*>(linkBuffer.debugAddress()) + linkBuffer.debugSize()), "):\n"); const char* prefix = " "; const char* disassemblyPrefix = " "; NodeIndex lastNodeIndex = NoNode; MacroAssembler::Label previousLabel = m_startOfCode; for (size_t blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) { BasicBlock* block = m_graph.m_blocks[blockIndex].get(); if (!block) continue; dumpDisassembly(out, disassemblyPrefix, linkBuffer, previousLabel, m_labelForBlockIndex[blockIndex], lastNodeIndex); m_graph.dumpBlockHeader(out, prefix, blockIndex, Graph::DumpLivePhisOnly); NodeIndex lastNodeIndexForDisassembly = block->at(0); for (size_t i = 0; i < block->size(); ++i) { if (!m_graph[block->at(i)].willHaveCodeGenOrOSR() && !Options::showAllDFGNodes()) continue; MacroAssembler::Label currentLabel; if (m_labelForNodeIndex[block->at(i)].isSet()) currentLabel = m_labelForNodeIndex[block->at(i)]; else { // Dump the last instruction by using the first label of the next block // as the end point. This case is hit either during peephole compare // optimizations (the Branch won't have its own label) or if we have a // forced OSR exit. if (blockIndex + 1 < m_graph.m_blocks.size()) currentLabel = m_labelForBlockIndex[blockIndex + 1]; else currentLabel = m_endOfMainPath; } dumpDisassembly(out, disassemblyPrefix, linkBuffer, previousLabel, currentLabel, lastNodeIndexForDisassembly); m_graph.dumpCodeOrigin(out, prefix, lastNodeIndex, block->at(i)); m_graph.dump(out, prefix, block->at(i)); lastNodeIndex = block->at(i); lastNodeIndexForDisassembly = block->at(i); } } dumpDisassembly(out, disassemblyPrefix, linkBuffer, previousLabel, m_endOfMainPath, lastNodeIndex); out.print(prefix, "(End Of Main Path)\n"); dumpDisassembly(out, disassemblyPrefix, linkBuffer, previousLabel, m_endOfCode, NoNode); }
void JITDisassembler::dump(PrintStream& out, LinkBuffer& linkBuffer) { out.print("Baseline JIT code for ", CodeBlockWithJITType(m_codeBlock, JITCode::BaselineJIT), ", instruction count = ", m_codeBlock->instructionCount(), "\n"); out.print(" Code at [", RawPointer(linkBuffer.debugAddress()), ", ", RawPointer(static_cast<char*>(linkBuffer.debugAddress()) + linkBuffer.debugSize()), "):\n"); dumpDisassembly(out, linkBuffer, m_startOfCode, m_labelForBytecodeIndexInMainPath[0]); MacroAssembler::Label firstSlowLabel; for (unsigned i = 0; i < m_labelForBytecodeIndexInSlowPath.size(); ++i) { if (m_labelForBytecodeIndexInSlowPath[i].isSet()) { firstSlowLabel = m_labelForBytecodeIndexInSlowPath[i]; break; } } dumpForInstructions(out, linkBuffer, " ", m_labelForBytecodeIndexInMainPath, firstSlowLabel.isSet() ? firstSlowLabel : m_endOfSlowPath); out.print(" (End Of Main Path)\n"); dumpForInstructions(out, linkBuffer, " (S) ", m_labelForBytecodeIndexInSlowPath, m_endOfSlowPath); out.print(" (End Of Slow Path)\n"); dumpDisassembly(out, linkBuffer, m_endOfSlowPath, m_endOfCode); }
void compile(State& state, Safepoint::Result& safepointResult) { char* error = 0; { GraphSafepoint safepoint(state.graph, safepointResult); LLVMMCJITCompilerOptions options; llvm->InitializeMCJITCompilerOptions(&options, sizeof(options)); options.OptLevel = Options::llvmBackendOptimizationLevel(); options.NoFramePointerElim = true; if (Options::useLLVMSmallCodeModel()) options.CodeModel = LLVMCodeModelSmall; options.EnableFastISel = Options::enableLLVMFastISel(); options.MCJMM = llvm->CreateSimpleMCJITMemoryManager( &state, mmAllocateCodeSection, mmAllocateDataSection, mmApplyPermissions, mmDestroy); LLVMExecutionEngineRef engine; if (isARM64()) #if OS(DARWIN) llvm->SetTarget(state.module, "arm64-apple-ios"); #elif OS(LINUX) llvm->SetTarget(state.module, "aarch64-linux-gnu"); #else #error "Unrecognized OS" #endif if (llvm->CreateMCJITCompilerForModule(&engine, state.module, &options, sizeof(options), &error)) { dataLog("FATAL: Could not create LLVM execution engine: ", error, "\n"); CRASH(); } // The data layout also has to be set in the module. Get the data layout from the MCJIT and apply // it to the module. LLVMTargetMachineRef targetMachine = llvm->GetExecutionEngineTargetMachine(engine); LLVMTargetDataRef targetData = llvm->GetExecutionEngineTargetData(engine); char* stringRepOfTargetData = llvm->CopyStringRepOfTargetData(targetData); llvm->SetDataLayout(state.module, stringRepOfTargetData); free(stringRepOfTargetData); LLVMPassManagerRef functionPasses = 0; LLVMPassManagerRef modulePasses; if (Options::llvmSimpleOpt()) { modulePasses = llvm->CreatePassManager(); llvm->AddTargetData(targetData, modulePasses); llvm->AddAnalysisPasses(targetMachine, modulePasses); llvm->AddPromoteMemoryToRegisterPass(modulePasses); llvm->AddGlobalOptimizerPass(modulePasses); llvm->AddFunctionInliningPass(modulePasses); llvm->AddPruneEHPass(modulePasses); llvm->AddGlobalDCEPass(modulePasses); llvm->AddConstantPropagationPass(modulePasses); llvm->AddAggressiveDCEPass(modulePasses); llvm->AddInstructionCombiningPass(modulePasses); // BEGIN - DO NOT CHANGE THE ORDER OF THE ALIAS ANALYSIS PASSES llvm->AddTypeBasedAliasAnalysisPass(modulePasses); llvm->AddBasicAliasAnalysisPass(modulePasses); // END - DO NOT CHANGE THE ORDER OF THE ALIAS ANALYSIS PASSES llvm->AddGVNPass(modulePasses); llvm->AddCFGSimplificationPass(modulePasses); llvm->AddDeadStoreEliminationPass(modulePasses); llvm->RunPassManager(modulePasses, state.module); } else { LLVMPassManagerBuilderRef passBuilder = llvm->PassManagerBuilderCreate(); llvm->PassManagerBuilderSetOptLevel(passBuilder, Options::llvmOptimizationLevel()); llvm->PassManagerBuilderUseInlinerWithThreshold(passBuilder, 275); llvm->PassManagerBuilderSetSizeLevel(passBuilder, Options::llvmSizeLevel()); functionPasses = llvm->CreateFunctionPassManagerForModule(state.module); modulePasses = llvm->CreatePassManager(); llvm->AddTargetData(llvm->GetExecutionEngineTargetData(engine), modulePasses); llvm->PassManagerBuilderPopulateFunctionPassManager(passBuilder, functionPasses); llvm->PassManagerBuilderPopulateModulePassManager(passBuilder, modulePasses); llvm->PassManagerBuilderDispose(passBuilder); llvm->InitializeFunctionPassManager(functionPasses); for (LValue function = llvm->GetFirstFunction(state.module); function; function = llvm->GetNextFunction(function)) llvm->RunFunctionPassManager(functionPasses, function); llvm->FinalizeFunctionPassManager(functionPasses); llvm->RunPassManager(modulePasses, state.module); } if (shouldShowDisassembly() || verboseCompilationEnabled()) state.dumpState("after optimization"); // FIXME: Need to add support for the case where JIT memory allocation failed. // https://bugs.webkit.org/show_bug.cgi?id=113620 state.generatedFunction = reinterpret_cast<GeneratedFunction>(llvm->GetPointerToGlobal(engine, state.function)); if (functionPasses) llvm->DisposePassManager(functionPasses); llvm->DisposePassManager(modulePasses); llvm->DisposeExecutionEngine(engine); } if (safepointResult.didGetCancelled()) return; RELEASE_ASSERT(!state.graph.m_vm.heap.isCollecting()); if (shouldShowDisassembly()) { for (unsigned i = 0; i < state.jitCode->handles().size(); ++i) { ExecutableMemoryHandle* handle = state.jitCode->handles()[i].get(); dataLog( "Generated LLVM code for ", CodeBlockWithJITType(state.graph.m_codeBlock, JITCode::FTLJIT), " #", i, ", ", state.codeSectionNames[i], ":\n"); disassemble( MacroAssemblerCodePtr(handle->start()), handle->sizeInBytes(), " ", WTF::dataFile(), LLVMSubset); } for (unsigned i = 0; i < state.jitCode->dataSections().size(); ++i) { DataSection* section = state.jitCode->dataSections()[i].get(); dataLog( "Generated LLVM data section for ", CodeBlockWithJITType(state.graph.m_codeBlock, JITCode::FTLJIT), " #", i, ", ", state.dataSectionNames[i], ":\n"); dumpDataSection(section, " "); } } bool didSeeUnwindInfo = state.jitCode->unwindInfo.parse( state.unwindDataSection, state.unwindDataSectionSize, state.generatedFunction); if (shouldShowDisassembly()) { dataLog("Unwind info for ", CodeBlockWithJITType(state.graph.m_codeBlock, JITCode::FTLJIT), ":\n"); if (didSeeUnwindInfo) dataLog(" ", state.jitCode->unwindInfo, "\n"); else dataLog(" <no unwind info>\n"); } if (state.stackmapsSection && state.stackmapsSection->size()) { if (shouldShowDisassembly()) { dataLog( "Generated LLVM stackmaps section for ", CodeBlockWithJITType(state.graph.m_codeBlock, JITCode::FTLJIT), ":\n"); dataLog(" Raw data:\n"); dumpDataSection(state.stackmapsSection.get(), " "); } RefPtr<DataView> stackmapsData = DataView::create( ArrayBuffer::create(state.stackmapsSection->base(), state.stackmapsSection->size())); state.jitCode->stackmaps.parse(stackmapsData.get()); if (shouldShowDisassembly()) { dataLog(" Structured data:\n"); state.jitCode->stackmaps.dumpMultiline(WTF::dataFile(), " "); } StackMaps::RecordMap recordMap = state.jitCode->stackmaps.computeRecordMap(); fixFunctionBasedOnStackMaps( state, state.graph.m_codeBlock, state.jitCode.get(), state.generatedFunction, recordMap, didSeeUnwindInfo); if (shouldShowDisassembly()) { for (unsigned i = 0; i < state.jitCode->handles().size(); ++i) { if (state.codeSectionNames[i] != SECTION_NAME("text")) continue; ExecutableMemoryHandle* handle = state.jitCode->handles()[i].get(); dataLog( "Generated LLVM code after stackmap-based fix-up for ", CodeBlockWithJITType(state.graph.m_codeBlock, JITCode::FTLJIT), " in ", state.graph.m_plan.mode, " #", i, ", ", state.codeSectionNames[i], ":\n"); disassemble( MacroAssemblerCodePtr(handle->start()), handle->sizeInBytes(), " ", WTF::dataFile(), LLVMSubset); } } } state.module = 0; // We no longer own the module. }
void JITDisassembler::dumpHeader(PrintStream& out, LinkBuffer& linkBuffer) { out.print("Generated Baseline JIT code for ", CodeBlockWithJITType(m_codeBlock, JITCode::BaselineJIT), ", instruction count = ", m_codeBlock->instructionCount(), "\n"); out.print(" Source: ", m_codeBlock->sourceCodeOnOneLine(), "\n"); out.print(" Code at [", RawPointer(linkBuffer.debugAddress()), ", ", RawPointer(static_cast<char*>(linkBuffer.debugAddress()) + linkBuffer.size()), "):\n"); }