123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 |
- #pragma once
- #ifdef __GNUC__
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wunused-parameter"
- #endif
- //===-- Speculation.h - Speculative Compilation --*- C++ -*-===//
- //
- // 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
- //
- //===----------------------------------------------------------------------===//
- //
- // Contains the definition to support speculative compilation when laziness is
- // enabled.
- //===----------------------------------------------------------------------===//
- #ifndef LLVM_EXECUTIONENGINE_ORC_SPECULATION_H
- #define LLVM_EXECUTIONENGINE_ORC_SPECULATION_H
- #include "llvm/ADT/DenseMap.h"
- #include "llvm/ADT/Optional.h"
- #include "llvm/ExecutionEngine/Orc/Core.h"
- #include "llvm/ExecutionEngine/Orc/DebugUtils.h"
- #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
- #include "llvm/Support/Debug.h"
- #include <mutex>
- #include <type_traits>
- #include <utility>
- namespace llvm {
- namespace orc {
- class Speculator;
- // Track the Impls (JITDylib,Symbols) of Symbols while lazy call through
- // trampolines are created. Operations are guarded by locks tp ensure that Imap
- // stays in consistent state after read/write
- class ImplSymbolMap {
- friend class Speculator;
- public:
- using AliaseeDetails = std::pair<SymbolStringPtr, JITDylib *>;
- using Alias = SymbolStringPtr;
- using ImapTy = DenseMap<Alias, AliaseeDetails>;
- void trackImpls(SymbolAliasMap ImplMaps, JITDylib *SrcJD);
- private:
- // FIX ME: find a right way to distinguish the pre-compile Symbols, and update
- // the callsite
- Optional<AliaseeDetails> getImplFor(const SymbolStringPtr &StubSymbol) {
- std::lock_guard<std::mutex> Lockit(ConcurrentAccess);
- auto Position = Maps.find(StubSymbol);
- if (Position != Maps.end())
- return Position->getSecond();
- else
- return None;
- }
- std::mutex ConcurrentAccess;
- ImapTy Maps;
- };
- // Defines Speculator Concept,
- class Speculator {
- public:
- using TargetFAddr = JITTargetAddress;
- using FunctionCandidatesMap = DenseMap<SymbolStringPtr, SymbolNameSet>;
- using StubAddrLikelies = DenseMap<TargetFAddr, SymbolNameSet>;
- private:
- void registerSymbolsWithAddr(TargetFAddr ImplAddr,
- SymbolNameSet likelySymbols) {
- std::lock_guard<std::mutex> Lockit(ConcurrentAccess);
- GlobalSpecMap.insert({ImplAddr, std::move(likelySymbols)});
- }
- void launchCompile(JITTargetAddress FAddr) {
- SymbolNameSet CandidateSet;
- // Copy CandidateSet is necessary, to avoid unsynchronized access to
- // the datastructure.
- {
- std::lock_guard<std::mutex> Lockit(ConcurrentAccess);
- auto It = GlobalSpecMap.find(FAddr);
- if (It == GlobalSpecMap.end())
- return;
- CandidateSet = It->getSecond();
- }
- SymbolDependenceMap SpeculativeLookUpImpls;
- for (auto &Callee : CandidateSet) {
- auto ImplSymbol = AliaseeImplTable.getImplFor(Callee);
- // try to distinguish already compiled & library symbols
- if (!ImplSymbol.hasValue())
- continue;
- const auto &ImplSymbolName = ImplSymbol.getPointer()->first;
- JITDylib *ImplJD = ImplSymbol.getPointer()->second;
- auto &SymbolsInJD = SpeculativeLookUpImpls[ImplJD];
- SymbolsInJD.insert(ImplSymbolName);
- }
- DEBUG_WITH_TYPE("orc", {
- for (auto &I : SpeculativeLookUpImpls) {
- llvm::dbgs() << "\n In " << I.first->getName() << " JITDylib ";
- for (auto &N : I.second)
- llvm::dbgs() << "\n Likely Symbol : " << N;
- }
- });
- // for a given symbol, there may be no symbol qualified for speculatively
- // compile try to fix this before jumping to this code if possible.
- for (auto &LookupPair : SpeculativeLookUpImpls)
- ES.lookup(
- LookupKind::Static,
- makeJITDylibSearchOrder(LookupPair.first,
- JITDylibLookupFlags::MatchAllSymbols),
- SymbolLookupSet(LookupPair.second), SymbolState::Ready,
- [this](Expected<SymbolMap> Result) {
- if (auto Err = Result.takeError())
- ES.reportError(std::move(Err));
- },
- NoDependenciesToRegister);
- }
- public:
- Speculator(ImplSymbolMap &Impl, ExecutionSession &ref)
- : AliaseeImplTable(Impl), ES(ref), GlobalSpecMap(0) {}
- Speculator(const Speculator &) = delete;
- Speculator(Speculator &&) = delete;
- Speculator &operator=(const Speculator &) = delete;
- Speculator &operator=(Speculator &&) = delete;
- /// Define symbols for this Speculator object (__orc_speculator) and the
- /// speculation runtime entry point symbol (__orc_speculate_for) in the
- /// given JITDylib.
- Error addSpeculationRuntime(JITDylib &JD, MangleAndInterner &Mangle);
- // Speculatively compile likely functions for the given Stub Address.
- // destination of __orc_speculate_for jump
- void speculateFor(TargetFAddr StubAddr) { launchCompile(StubAddr); }
- // FIXME : Register with Stub Address, after JITLink Fix.
- void registerSymbols(FunctionCandidatesMap Candidates, JITDylib *JD) {
- for (auto &SymPair : Candidates) {
- auto Target = SymPair.first;
- auto Likely = SymPair.second;
- auto OnReadyFixUp = [Likely, Target,
- this](Expected<SymbolMap> ReadySymbol) {
- if (ReadySymbol) {
- auto RAddr = (*ReadySymbol)[Target].getAddress();
- registerSymbolsWithAddr(RAddr, std::move(Likely));
- } else
- this->getES().reportError(ReadySymbol.takeError());
- };
- // Include non-exported symbols also.
- ES.lookup(
- LookupKind::Static,
- makeJITDylibSearchOrder(JD, JITDylibLookupFlags::MatchAllSymbols),
- SymbolLookupSet(Target, SymbolLookupFlags::WeaklyReferencedSymbol),
- SymbolState::Ready, OnReadyFixUp, NoDependenciesToRegister);
- }
- }
- ExecutionSession &getES() { return ES; }
- private:
- static void speculateForEntryPoint(Speculator *Ptr, uint64_t StubId);
- std::mutex ConcurrentAccess;
- ImplSymbolMap &AliaseeImplTable;
- ExecutionSession &ES;
- StubAddrLikelies GlobalSpecMap;
- };
- class IRSpeculationLayer : public IRLayer {
- public:
- using IRlikiesStrRef = Optional<DenseMap<StringRef, DenseSet<StringRef>>>;
- using ResultEval = std::function<IRlikiesStrRef(Function &)>;
- using TargetAndLikelies = DenseMap<SymbolStringPtr, SymbolNameSet>;
- IRSpeculationLayer(ExecutionSession &ES, IRCompileLayer &BaseLayer,
- Speculator &Spec, MangleAndInterner &Mangle,
- ResultEval Interpreter)
- : IRLayer(ES, BaseLayer.getManglingOptions()), NextLayer(BaseLayer),
- S(Spec), Mangle(Mangle), QueryAnalysis(Interpreter) {}
- void emit(std::unique_ptr<MaterializationResponsibility> R,
- ThreadSafeModule TSM) override;
- private:
- TargetAndLikelies
- internToJITSymbols(DenseMap<StringRef, DenseSet<StringRef>> IRNames) {
- assert(!IRNames.empty() && "No IRNames received to Intern?");
- TargetAndLikelies InternedNames;
- for (auto &NamePair : IRNames) {
- DenseSet<SymbolStringPtr> TargetJITNames;
- for (auto &TargetNames : NamePair.second)
- TargetJITNames.insert(Mangle(TargetNames));
- InternedNames[Mangle(NamePair.first)] = std::move(TargetJITNames);
- }
- return InternedNames;
- }
- IRCompileLayer &NextLayer;
- Speculator &S;
- MangleAndInterner &Mangle;
- ResultEval QueryAnalysis;
- };
- } // namespace orc
- } // namespace llvm
- #endif // LLVM_EXECUTIONENGINE_ORC_SPECULATION_H
- #ifdef __GNUC__
- #pragma GCC diagnostic pop
- #endif
|