From c95c1c81f43b42d536f15ec56ee53043e2701d3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 11 Feb 2015 17:06:35 +0100 Subject: [PATCH] Cleanup ExecutionEngine creation --- evmjit/libevmjit/Arith256.cpp | 1 - evmjit/libevmjit/ExecutionEngine.cpp | 96 +++++++++++----------------- evmjit/libevmjit/Runtime.h | 1 - 3 files changed, 39 insertions(+), 59 deletions(-) diff --git a/evmjit/libevmjit/Arith256.cpp b/evmjit/libevmjit/Arith256.cpp index 21a2f83cb..8e1ceb748 100644 --- a/evmjit/libevmjit/Arith256.cpp +++ b/evmjit/libevmjit/Arith256.cpp @@ -1,5 +1,4 @@ #include "Arith256.h" -#include "Runtime.h" #include "Type.h" #include "Endianness.h" diff --git a/evmjit/libevmjit/ExecutionEngine.cpp b/evmjit/libevmjit/ExecutionEngine.cpp index 30df7f26a..c4c03233c 100644 --- a/evmjit/libevmjit/ExecutionEngine.cpp +++ b/evmjit/libevmjit/ExecutionEngine.cpp @@ -68,81 +68,63 @@ bool showInfo() ReturnCode ExecutionEngine::run(RuntimeData* _data, Env* _env) { - static std::unique_ptr ee; // TODO: Use Managed Objects from LLVM? static auto debugDumpModule = getEnvOption("EVMJIT_DUMP", false); static auto objectCacheEnabled = getEnvOption("EVMJIT_CACHE", true); static auto statsCollectingEnabled = getEnvOption("EVMJIT_STATS", false); static auto infoShown = showInfo(); (void) infoShown; - static StatsCollector statsCollector; - std::unique_ptr listener{new ExecStats}; listener->stateChanged(ExecState::Started); - auto codeBegin = _data->code; - auto codeEnd = codeBegin + _data->codeSize; - assert(codeBegin || !codeEnd); //TODO: Is it good idea to execute empty code? - auto mainFuncName = codeHash(_data->codeHash); - EntryFuncPtr entryFuncPtr{}; - Runtime runtime(_data, _env); // TODO: I don't know why but it must be created before getFunctionAddress() calls + auto objectCache = objectCacheEnabled ? Cache::getObjectCache(listener.get()) : nullptr; - if (ee && (entryFuncPtr = (EntryFuncPtr)ee->getFunctionAddress(mainFuncName))) + static std::unique_ptr ee; + if (!ee) { + llvm::InitializeNativeTarget(); + llvm::InitializeNativeTargetAsmPrinter(); + + auto module = std::unique_ptr(new llvm::Module({}, llvm::getGlobalContext())); + llvm::EngineBuilder builder(module.get()); + builder.setEngineKind(llvm::EngineKind::JIT); + builder.setUseMCJIT(true); + builder.setOptLevel(llvm::CodeGenOpt::None); + + auto triple = llvm::Triple(llvm::sys::getProcessTriple()); + if (triple.getOS() == llvm::Triple::OSType::Win32) + triple.setObjectFormat(llvm::Triple::ObjectFormatType::ELF); // MCJIT does not support COFF format + module->setTargetTriple(triple.str()); + + ee.reset(builder.create()); + if (!ee) + return ReturnCode::LLVMConfigError; + module.release(); // Successfully created llvm::ExecutionEngine takes ownership of the module + ee->setObjectCache(objectCache); } - else - { - auto objectCache = objectCacheEnabled ? Cache::getObjectCache(listener.get()) : nullptr; - std::unique_ptr module; - if (objectCache) - module = Cache::getObject(mainFuncName); + + static StatsCollector statsCollector; + + auto mainFuncName = codeHash(_data->codeHash); + Runtime runtime(_data, _env); // TODO: I don't know why but it must be created before getFunctionAddress() calls + + auto entryFuncPtr = (EntryFuncPtr)ee->getFunctionAddress(mainFuncName); + if (!entryFuncPtr) + { + auto module = objectCache ? Cache::getObject(mainFuncName) : nullptr; if (!module) { listener->stateChanged(ExecState::Compilation); - module = Compiler({}).compile(codeBegin, codeEnd, mainFuncName); + assert(_data->code || !_data->codeSize); //TODO: Is it good idea to execute empty code? + module = Compiler({}).compile(_data->code, _data->code + _data->codeSize, mainFuncName); } if (debugDumpModule) module->dump(); - if (!ee) - { - llvm::InitializeNativeTarget(); - llvm::InitializeNativeTargetAsmPrinter(); - - llvm::EngineBuilder builder(module.get()); - builder.setEngineKind(llvm::EngineKind::JIT); - builder.setUseMCJIT(true); - std::unique_ptr memoryManager(new llvm::SectionMemoryManager); - builder.setMCJITMemoryManager(memoryManager.get()); - builder.setOptLevel(llvm::CodeGenOpt::None); - builder.setVerifyModules(true); - - auto triple = llvm::Triple(llvm::sys::getProcessTriple()); - if (triple.getOS() == llvm::Triple::OSType::Win32) - triple.setObjectFormat(llvm::Triple::ObjectFormatType::ELF); // MCJIT does not support COFF format - module->setTargetTriple(triple.str()); - - ee.reset(builder.create()); - if (!ee) - return ReturnCode::LLVMConfigError; - - module.release(); // Successfully created llvm::ExecutionEngine takes ownership of the module - memoryManager.release(); // and memory manager - - if (objectCache) - ee->setObjectCache(objectCache); - listener->stateChanged(ExecState::CodeGen); - entryFuncPtr = (EntryFuncPtr)ee->getFunctionAddress(mainFuncName); - } - else - { - if (!entryFuncPtr) - { - ee->addModule(module.get()); - module.release(); - listener->stateChanged(ExecState::CodeGen); - entryFuncPtr = (EntryFuncPtr)ee->getFunctionAddress(mainFuncName); - } - } + + ee->addModule(module.get()); + module.release(); + listener->stateChanged(ExecState::CodeGen); + entryFuncPtr = (EntryFuncPtr)ee->getFunctionAddress(mainFuncName); } assert(entryFuncPtr); //TODO: Replace it with safe exception diff --git a/evmjit/libevmjit/Runtime.h b/evmjit/libevmjit/Runtime.h index a24d822e1..9ea3039a0 100644 --- a/evmjit/libevmjit/Runtime.h +++ b/evmjit/libevmjit/Runtime.h @@ -21,7 +21,6 @@ public: StackImpl& getStack() { return m_stack; } MemoryImpl& getMemory() { return m_memory; } - Env* getEnvPtr() { return &m_env; } bytes_ref getReturnData() const;