|  | //===-- llvm-jitlink-statistics.cpp -- gathers/reports JIT-linking stats --===// | 
|  | // | 
|  | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
|  | // See https://llvm.org/LICENSE.txt for license information. | 
|  | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | // | 
|  | // This file contains the code for enabling, gathering and reporting | 
|  | // llvm-jitlink statistics. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "llvm-jitlink.h" | 
|  | #include "llvm/Support/CommandLine.h" | 
|  |  | 
|  | #define DEBUG_TYPE "llvm_jitlink" | 
|  |  | 
|  | using namespace llvm; | 
|  | using namespace llvm::jitlink; | 
|  | using namespace llvm::orc; | 
|  |  | 
|  | static cl::opt<bool> ShowPrePruneTotalBlockSize( | 
|  | "pre-prune-total-block-size", | 
|  | cl::desc("Total size of all blocks (including zero-fill) in all " | 
|  | "graphs (pre-pruning)"), | 
|  | cl::init(false)); | 
|  |  | 
|  | static cl::opt<bool> ShowPostFixupTotalBlockSize( | 
|  | "post-fixup-total-block-size", | 
|  | cl::desc("Total size of all blocks (including zero-fill) in all " | 
|  | "graphs (post-fixup)"), | 
|  | cl::init(false)); | 
|  |  | 
|  | class StatsPlugin : public ObjectLinkingLayer::Plugin { | 
|  | public: | 
|  | static void enableIfNeeded(Session &S, bool UsingOrcRuntime) { | 
|  | std::unique_ptr<StatsPlugin> Instance; | 
|  | auto GetStats = [&]() -> StatsPlugin & { | 
|  | if (!Instance) | 
|  | Instance.reset(new StatsPlugin(UsingOrcRuntime)); | 
|  | return *Instance; | 
|  | }; | 
|  |  | 
|  | if (ShowPrePruneTotalBlockSize) | 
|  | GetStats().PrePruneTotalBlockSize = 0; | 
|  |  | 
|  | if (ShowPostFixupTotalBlockSize) | 
|  | GetStats().PostFixupTotalBlockSize = 0; | 
|  |  | 
|  | if (Instance) | 
|  | S.ObjLayer.addPlugin(std::move(Instance)); | 
|  | } | 
|  |  | 
|  | ~StatsPlugin() { publish(dbgs()); } | 
|  |  | 
|  | void publish(raw_ostream &OS); | 
|  |  | 
|  | void modifyPassConfig(MaterializationResponsibility &MR, LinkGraph &G, | 
|  | PassConfiguration &PassConfig) override { | 
|  | PassConfig.PrePrunePasses.push_back( | 
|  | [this](LinkGraph &G) { return recordPrePruneStats(G); }); | 
|  | PassConfig.PostFixupPasses.push_back( | 
|  | [this](LinkGraph &G) { return recordPostFixupStats(G); }); | 
|  | } | 
|  |  | 
|  | Error notifyFailed(MaterializationResponsibility &MR) override { | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override { | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey, | 
|  | ResourceKey SrcKey) override {} | 
|  |  | 
|  | private: | 
|  | StatsPlugin(bool UsingOrcRuntime) : UsingOrcRuntime(UsingOrcRuntime) {} | 
|  | Error recordPrePruneStats(jitlink::LinkGraph &G); | 
|  | Error recordPostFixupStats(jitlink::LinkGraph &G); | 
|  |  | 
|  | bool UsingOrcRuntime; | 
|  |  | 
|  | std::mutex M; | 
|  | std::optional<uint64_t> PrePruneTotalBlockSize; | 
|  | std::optional<uint64_t> PostFixupTotalBlockSize; | 
|  | std::optional<DenseMap<size_t, size_t>> EdgeCountDetails; | 
|  | }; | 
|  |  | 
|  | void StatsPlugin::publish(raw_ostream &OS) { | 
|  |  | 
|  | if (UsingOrcRuntime) | 
|  | OS << "Note: Session stats include runtime and entry point lookup, but " | 
|  | "not JITDylib initialization/deinitialization.\n"; | 
|  |  | 
|  | OS << "Statistics:\n"; | 
|  | if (PrePruneTotalBlockSize) | 
|  | OS << "  Total size of all blocks before pruning: " | 
|  | << *PrePruneTotalBlockSize << "\n"; | 
|  |  | 
|  | if (PostFixupTotalBlockSize) | 
|  | OS << "  Total size of all blocks after fixups: " | 
|  | << *PostFixupTotalBlockSize << "\n"; | 
|  | } | 
|  |  | 
|  | static uint64_t computeTotalBlockSizes(LinkGraph &G) { | 
|  | uint64_t TotalSize = 0; | 
|  | for (auto *B : G.blocks()) | 
|  | TotalSize += B->getSize(); | 
|  | return TotalSize; | 
|  | } | 
|  |  | 
|  | Error StatsPlugin::recordPrePruneStats(LinkGraph &G) { | 
|  | std::lock_guard<std::mutex> Lock(M); | 
|  |  | 
|  | if (PrePruneTotalBlockSize) | 
|  | *PrePruneTotalBlockSize += computeTotalBlockSizes(G); | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error StatsPlugin::recordPostFixupStats(LinkGraph &G) { | 
|  | std::lock_guard<std::mutex> Lock(M); | 
|  |  | 
|  | if (PostFixupTotalBlockSize) | 
|  | *PostFixupTotalBlockSize += computeTotalBlockSizes(G); | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | namespace llvm { | 
|  | void enableStatistics(Session &S, bool UsingOrcRuntime) { | 
|  | StatsPlugin::enableIfNeeded(S, UsingOrcRuntime); | 
|  | } | 
|  | } // namespace llvm |