diff options
author | Lang Hames <lhames@gmail.com> | 2018-09-06 19:39:26 +0000 |
---|---|---|
committer | Lang Hames <lhames@gmail.com> | 2018-09-06 19:39:26 +0000 |
commit | bf985258b9af0de0c95370c696fbdbc03d0713cf (patch) | |
tree | abbb4f006298f2a4d5988030b54c0ec8432234ac | |
parent | a5f33c86942e49ea3e1d06bb33909ce7bb806be5 (diff) | |
download | bcm5719-llvm-bf985258b9af0de0c95370c696fbdbc03d0713cf.tar.gz bcm5719-llvm-bf985258b9af0de0c95370c696fbdbc03d0713cf.zip |
[ORC] Make RuntimeDyldObjectLinkingLayer2 take memory managers by unique_ptr.
The existing memory manager API can not be shared between objects when linking
concurrently (since there is no way to know which concurrent allocations were
performed on behalf of which object, and hence which allocations would be safe
to finalize when finalizeMemory is called). For now, we can work around this by
requiring a new memory manager for each object.
This change only affects the concurrent version of the ORC APIs.
llvm-svn: 341579
4 files changed, 8 insertions, 188 deletions
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h b/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h index 6e2ac85eab9..aced03f3035 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h @@ -91,7 +91,7 @@ protected: LLJIT(std::unique_ptr<ExecutionSession> ES, std::unique_ptr<TargetMachine> TM, DataLayout DL); - std::shared_ptr<RuntimeDyld::MemoryManager> getMemoryManager(VModuleKey K); + std::unique_ptr<RuntimeDyld::MemoryManager> getMemoryManager(VModuleKey K); std::string mangle(StringRef UnmangledName); diff --git a/llvm/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h b/llvm/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h index f4a4703363e..532c8337ec3 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h @@ -47,7 +47,7 @@ public: using NotifyEmittedFunction = std::function<void(VModuleKey)>; using GetMemoryManagerFunction = - std::function<std::shared_ptr<RuntimeDyld::MemoryManager>(VModuleKey)>; + std::function<std::unique_ptr<RuntimeDyld::MemoryManager>(VModuleKey)>; /// Construct an ObjectLinkingLayer with the given NotifyLoaded, /// and NotifyEmitted functors. diff --git a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp index f9cc763f802..b463771c730 100644 --- a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp +++ b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp @@ -59,7 +59,7 @@ LLJIT::LLJIT(std::unique_ptr<ExecutionSession> ES, CompileLayer(*this->ES, ObjLinkingLayer, SimpleCompiler(*this->TM)), CtorRunner(Main), DtorRunner(Main) {} -std::shared_ptr<RuntimeDyld::MemoryManager> +std::unique_ptr<RuntimeDyld::MemoryManager> LLJIT::getMemoryManager(VModuleKey K) { return llvm::make_unique<SectionMemoryManager>(); } diff --git a/llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayer2Test.cpp b/llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayer2Test.cpp index 30cd923b54a..b99fc494880 100644 --- a/llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayer2Test.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayer2Test.cpp @@ -28,22 +28,6 @@ namespace { class RTDyldObjectLinkingLayer2ExecutionTest : public testing::Test, public OrcExecutionTest {}; -class SectionMemoryManagerWrapper : public SectionMemoryManager { -public: - int FinalizationCount = 0; - int NeedsToReserveAllocationSpaceCount = 0; - - bool needsToReserveAllocationSpace() override { - ++NeedsToReserveAllocationSpaceCount; - return SectionMemoryManager::needsToReserveAllocationSpace(); - } - - bool finalizeMemory(std::string *ErrMsg = nullptr) override { - ++FinalizationCount; - return SectionMemoryManager::finalizeMemory(ErrMsg); - } -}; - // Adds an object with a debug section to RuntimeDyld and then returns whether // the debug section was passed to the memory manager. static bool testSetProcessAllSections(std::unique_ptr<MemoryBuffer> Obj, @@ -65,13 +49,14 @@ static bool testSetProcessAllSections(std::unique_ptr<MemoryBuffer> Obj, }; bool DebugSectionSeen = false; - auto MM = std::make_shared<MemoryManagerWrapper>(DebugSectionSeen); ExecutionSession ES; auto &JD = ES.createJITDylib("main"); auto Foo = ES.getSymbolStringPool().intern("foo"); - RTDyldObjectLinkingLayer2 ObjLayer(ES, [&MM](VModuleKey) { return MM; }); + RTDyldObjectLinkingLayer2 ObjLayer(ES, [&DebugSectionSeen](VModuleKey) { + return llvm::make_unique<MemoryManagerWrapper>(DebugSectionSeen); + }); auto OnResolveDoNothing = [](Expected<SymbolMap> R) { cantFail(std::move(R)); @@ -165,7 +150,7 @@ TEST(RTDyldObjectLinkingLayer2Test, TestOverrideObjectFlags) { auto &JD = ES.createJITDylib("main"); auto Foo = ES.getSymbolStringPool().intern("foo"); RTDyldObjectLinkingLayer2 ObjLayer( - ES, [](VModuleKey) { return std::make_shared<SectionMemoryManager>(); }); + ES, [](VModuleKey) { return llvm::make_unique<SectionMemoryManager>(); }); IRCompileLayer2 CompileLayer(ES, ObjLayer, FunkySimpleCompiler(*TM)); ObjLayer.setOverrideObjectFlagsWithResponsibilityFlags(true); @@ -226,7 +211,7 @@ TEST(RTDyldObjectLinkingLayer2Test, TestAutoClaimResponsibilityForSymbols) { auto &JD = ES.createJITDylib("main"); auto Foo = ES.getSymbolStringPool().intern("foo"); RTDyldObjectLinkingLayer2 ObjLayer( - ES, [](VModuleKey) { return std::make_shared<SectionMemoryManager>(); }); + ES, [](VModuleKey) { return llvm::make_unique<SectionMemoryManager>(); }); IRCompileLayer2 CompileLayer(ES, ObjLayer, FunkySimpleCompiler(*TM)); ObjLayer.setAutoClaimResponsibilityForObjectSymbols(true); @@ -237,169 +222,4 @@ TEST(RTDyldObjectLinkingLayer2Test, TestAutoClaimResponsibilityForSymbols) { NoDependenciesToRegister); } -TEST(RTDyldObjectLinkingLayer2Test, NoDuplicateFinalization) { - // Create a pair of modules that will trigger recursive finalization: - // Module 1: - // int bar() { return 42; } - // Module 2: - // int bar(); - // int foo() { return bar(); } - // - // Verify that the memory manager is only finalized once (for Module 2). - // Failure suggests that finalize is being called on the inner RTDyld - // instance (for Module 1) which is unsafe, as it will prevent relocation of - // Module 2. - - // Initialize the native target in case this is the first unit test - // to try to build a TM. - OrcNativeTarget::initialize(); - std::unique_ptr<TargetMachine> TM( - EngineBuilder().selectTarget(Triple("x86_64-unknown-linux-gnu"), "", "", - SmallVector<std::string, 1>())); - - if (!TM) - return; - - LLVMContext Context; - ExecutionSession ES; - auto &JD = ES.createJITDylib("main"); - - auto Foo = ES.getSymbolStringPool().intern("foo"); - - auto MM = std::make_shared<SectionMemoryManagerWrapper>(); - - RTDyldObjectLinkingLayer2 ObjLayer(ES, [&](VModuleKey K) { return MM; }); - - SimpleCompiler Compile(*TM); - - ModuleBuilder MB1(Context, TM->getTargetTriple().str(), "dummy"); - { - MB1.getModule()->setDataLayout(TM->createDataLayout()); - Function *BarImpl = MB1.createFunctionDecl<int32_t(void)>("bar"); - BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl); - IRBuilder<> Builder(BarEntry); - IntegerType *Int32Ty = IntegerType::get(Context, 32); - Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42); - Builder.CreateRet(FourtyTwo); - } - - auto Obj1 = Compile(*MB1.getModule()); - - ModuleBuilder MB2(Context, TM->getTargetTriple().str(), "dummy"); - { - MB2.getModule()->setDataLayout(TM->createDataLayout()); - Function *BarDecl = MB2.createFunctionDecl<int32_t(void)>("bar"); - Function *FooImpl = MB2.createFunctionDecl<int32_t(void)>("foo"); - BasicBlock *FooEntry = BasicBlock::Create(Context, "entry", FooImpl); - IRBuilder<> Builder(FooEntry); - Builder.CreateRet(Builder.CreateCall(BarDecl)); - } - auto Obj2 = Compile(*MB2.getModule()); - - auto K1 = ES.allocateVModule(); - cantFail(ObjLayer.add(JD, K1, std::move(Obj1))); - - auto K2 = ES.allocateVModule(); - cantFail(ObjLayer.add(JD, K2, std::move(Obj2))); - - auto OnResolve = [](Expected<SymbolMap> Symbols) { - cantFail(std::move(Symbols)); - }; - auto OnReady = [](Error Err) { cantFail(std::move(Err)); }; - - ES.lookup({&JD}, {Foo}, OnResolve, OnReady, NoDependenciesToRegister); - - // Finalization of module 2 should trigger finalization of module 1. - // Verify that finalize on SMMW is only called once. - EXPECT_EQ(MM->FinalizationCount, 1) << "Extra call to finalize"; -} - -TEST(RTDyldObjectLinkingLayer2Test, NoPrematureAllocation) { - // Create a pair of unrelated modules: - // - // Module 1: - // int foo() { return 42; } - // Module 2: - // int bar() { return 7; } - // - // Both modules will share a memory manager. We want to verify that the - // second object is not loaded before the first one is finalized. To do this - // in a portable way, we abuse the - // RuntimeDyld::MemoryManager::needsToReserveAllocationSpace hook, which is - // called once per object before any sections are allocated. - - // Initialize the native target in case this is the first unit test - // to try to build a TM. - OrcNativeTarget::initialize(); - std::unique_ptr<TargetMachine> TM( - EngineBuilder().selectTarget(Triple("x86_64-unknown-linux-gnu"), "", "", - SmallVector<std::string, 1>())); - - if (!TM) - return; - - ExecutionSession ES; - auto &JD = ES.createJITDylib("main"); - - auto Foo = ES.getSymbolStringPool().intern("foo"); - - auto MM = std::make_shared<SectionMemoryManagerWrapper>(); - - RTDyldObjectLinkingLayer2 ObjLayer(ES, [&MM](VModuleKey K) { return MM; }); - SimpleCompiler Compile(*TM); - - LLVMContext Context; - ModuleBuilder MB1(Context, TM->getTargetTriple().str(), "dummy"); - { - MB1.getModule()->setDataLayout(TM->createDataLayout()); - Function *BarImpl = MB1.createFunctionDecl<int32_t(void)>("foo"); - BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl); - IRBuilder<> Builder(BarEntry); - IntegerType *Int32Ty = IntegerType::get(Context, 32); - Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42); - Builder.CreateRet(FourtyTwo); - } - - auto Obj1 = Compile(*MB1.getModule()); - - ModuleBuilder MB2(Context, TM->getTargetTriple().str(), "dummy"); - { - MB2.getModule()->setDataLayout(TM->createDataLayout()); - Function *BarImpl = MB2.createFunctionDecl<int32_t(void)>("bar"); - BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl); - IRBuilder<> Builder(BarEntry); - IntegerType *Int32Ty = IntegerType::get(Context, 32); - Value *Seven = ConstantInt::getSigned(Int32Ty, 7); - Builder.CreateRet(Seven); - } - auto Obj2 = Compile(*MB2.getModule()); - - cantFail(ObjLayer.add(JD, ES.allocateVModule(), std::move(Obj1))); - cantFail(ObjLayer.add(JD, ES.allocateVModule(), std::move(Obj2))); - - auto OnResolve = [](Expected<SymbolMap> Result) { - cantFail(std::move(Result)); - }; - - auto OnReady = [](Error Err) { cantFail(std::move(Err)); }; - - ES.lookup({&JD}, {Foo}, OnResolve, OnReady, NoDependenciesToRegister); - - // Only one call to needsToReserveAllocationSpace should have been made. - EXPECT_EQ(MM->NeedsToReserveAllocationSpaceCount, 1) - << "More than one call to needsToReserveAllocationSpace " - "(multiple unrelated objects loaded prior to finalization)"; -} - -TEST(RTDyldObjectLinkingLayer2Test, TestNotifyLoadedSignature) { - ExecutionSession ES; - RTDyldObjectLinkingLayer2 ObjLayer( - ES, - [](VModuleKey) -> std::shared_ptr<RuntimeDyld::MemoryManager> { - return nullptr; - }, - [](VModuleKey, const object::ObjectFile &obj, - const RuntimeDyld::LoadedObjectInfo &info) {}); -} - } // end anonymous namespace |