mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-22 04:36:42 +00:00
Do not compile LLVM module if machine code available in memory
This commit is contained in:
parent
2b31cba5d2
commit
3df5a125fa
5 changed files with 49 additions and 56 deletions
|
|
@ -132,7 +132,7 @@ int main(int argc, char** argv)
|
||||||
compilerOptions.rewriteSwitchToBranches = optimize || options.count("rewrite-switch") > 0;
|
compilerOptions.rewriteSwitchToBranches = optimize || options.count("rewrite-switch") > 0;
|
||||||
|
|
||||||
auto compiler = eth::jit::Compiler(compilerOptions);
|
auto compiler = eth::jit::Compiler(compilerOptions);
|
||||||
auto module = compiler.compile(bytecode);
|
auto module = compiler.compile(bytecode, "main");
|
||||||
|
|
||||||
auto compilationEndTime = std::chrono::high_resolution_clock::now();
|
auto compilationEndTime = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
|
|
@ -201,7 +201,8 @@ int main(int argc, char** argv)
|
||||||
data.code = bytecode.data();
|
data.code = bytecode.data();
|
||||||
|
|
||||||
// BROKEN: env_* functions must be implemented & RuntimeData struct created
|
// BROKEN: env_* functions must be implemented & RuntimeData struct created
|
||||||
auto result = engine.run(std::move(module), &data, nullptr, bytecode);
|
// TODO: Do not compile module again
|
||||||
|
auto result = engine.run(bytecode, &data, nullptr);
|
||||||
return static_cast<int>(result);
|
return static_cast<int>(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -152,19 +152,14 @@ void Compiler::createBasicBlocks(bytes const& _bytecode)
|
||||||
m_indirectJumpTargets.push_back(&basicBlocks.find(*it)->second);
|
m_indirectJumpTargets.push_back(&basicBlocks.find(*it)->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<llvm::Module> Compiler::compile(bytes const& _bytecode)
|
std::unique_ptr<llvm::Module> Compiler::compile(bytes const& _bytecode, std::string const& _id)
|
||||||
{
|
{
|
||||||
// TODO: Better hash of code needed, probably SHA3
|
|
||||||
std::string code{reinterpret_cast<char const*>(_bytecode.data()), _bytecode.size()};
|
|
||||||
auto hash = std::hash<std::string>{}(code);
|
|
||||||
auto strHash = std::to_string(hash);
|
|
||||||
|
|
||||||
auto compilationStartTime = std::chrono::high_resolution_clock::now();
|
auto compilationStartTime = std::chrono::high_resolution_clock::now();
|
||||||
auto module = std::unique_ptr<llvm::Module>(new llvm::Module(strHash, m_builder.getContext()));
|
auto module = std::unique_ptr<llvm::Module>(new llvm::Module(_id, m_builder.getContext()));
|
||||||
|
|
||||||
// Create main function
|
// Create main function
|
||||||
auto mainFuncType = llvm::FunctionType::get(Type::MainReturn, Type::RuntimePtr, false);
|
auto mainFuncType = llvm::FunctionType::get(Type::MainReturn, Type::RuntimePtr, false);
|
||||||
m_mainFunc = llvm::Function::Create(mainFuncType, llvm::Function::ExternalLinkage, strHash, module.get());
|
m_mainFunc = llvm::Function::Create(mainFuncType, llvm::Function::ExternalLinkage, _id, module.get());
|
||||||
m_mainFunc->getArgumentList().front().setName("rt");
|
m_mainFunc->getArgumentList().front().setName("rt");
|
||||||
|
|
||||||
// Create the basic blocks.
|
// Create the basic blocks.
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ public:
|
||||||
|
|
||||||
Compiler(Options const& _options);
|
Compiler(Options const& _options);
|
||||||
|
|
||||||
std::unique_ptr<llvm::Module> compile(bytes const& _bytecode);
|
std::unique_ptr<llvm::Module> compile(bytes const& _bytecode, std::string const& _id);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,13 +21,6 @@ namespace eth
|
||||||
namespace jit
|
namespace jit
|
||||||
{
|
{
|
||||||
|
|
||||||
ReturnCode ExecutionEngine::run(bytes const& _code, RuntimeData* _data, Env* _env)
|
|
||||||
{
|
|
||||||
auto module = Compiler({}).compile(_code);
|
|
||||||
//module->dump();
|
|
||||||
return run(std::move(module), _data, _env, _code);
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
typedef ReturnCode(*EntryFuncPtr)(Runtime*);
|
typedef ReturnCode(*EntryFuncPtr)(Runtime*);
|
||||||
|
|
@ -48,50 +41,61 @@ ReturnCode runEntryFunc(EntryFuncPtr _mainFunc, Runtime* _runtime)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnCode ExecutionEngine::run(std::unique_ptr<llvm::Module> _module, RuntimeData* _data, Env* _env, bytes const& _code)
|
ReturnCode ExecutionEngine::run(bytes const& _code, RuntimeData* _data, Env* _env)
|
||||||
{
|
{
|
||||||
static std::unique_ptr<llvm::ExecutionEngine> ee; // TODO: Use Managed Objects from LLVM?
|
static std::unique_ptr<llvm::ExecutionEngine> ee; // TODO: Use Managed Objects from LLVM?
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: Better hash of code needed, probably SHA3
|
||||||
|
std::string code{reinterpret_cast<char const*>(_code.data()), _code.size()};
|
||||||
|
auto hash = std::hash<std::string>{}(code);
|
||||||
|
auto mainFuncName = std::to_string(hash);
|
||||||
|
|
||||||
EntryFuncPtr entryFuncPtr{};
|
EntryFuncPtr entryFuncPtr{};
|
||||||
auto&& mainFuncName = _module->getModuleIdentifier();
|
|
||||||
Runtime runtime(_data, _env); // TODO: I don't know why but it must be created before getFunctionAddress() calls
|
Runtime runtime(_data, _env); // TODO: I don't know why but it must be created before getFunctionAddress() calls
|
||||||
|
|
||||||
if (!ee)
|
if (ee && (entryFuncPtr = (EntryFuncPtr)ee->getFunctionAddress(mainFuncName)))
|
||||||
{
|
{
|
||||||
llvm::InitializeNativeTarget();
|
|
||||||
llvm::InitializeNativeTargetAsmPrinter();
|
|
||||||
|
|
||||||
llvm::EngineBuilder builder(_module.get());
|
|
||||||
builder.setEngineKind(llvm::EngineKind::JIT);
|
|
||||||
builder.setUseMCJIT(true);
|
|
||||||
std::unique_ptr<llvm::SectionMemoryManager> memoryManager(new llvm::SectionMemoryManager);
|
|
||||||
builder.setMCJITMemoryManager(memoryManager.get());
|
|
||||||
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
|
|
||||||
memoryManager.release(); // and memory manager
|
|
||||||
|
|
||||||
//ee->setObjectCache(Cache::getObjectCache());
|
|
||||||
entryFuncPtr = (EntryFuncPtr)ee->getFunctionAddress(mainFuncName);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
entryFuncPtr = (EntryFuncPtr)ee->getFunctionAddress(mainFuncName);
|
auto module = Compiler({}).compile(_code, mainFuncName);
|
||||||
if (!entryFuncPtr)
|
if (!ee)
|
||||||
{
|
{
|
||||||
ee->addModule(_module.get());
|
llvm::InitializeNativeTarget();
|
||||||
_module.release();
|
llvm::InitializeNativeTargetAsmPrinter();
|
||||||
|
|
||||||
|
llvm::EngineBuilder builder(module.get());
|
||||||
|
builder.setEngineKind(llvm::EngineKind::JIT);
|
||||||
|
builder.setUseMCJIT(true);
|
||||||
|
std::unique_ptr<llvm::SectionMemoryManager> memoryManager(new llvm::SectionMemoryManager);
|
||||||
|
builder.setMCJITMemoryManager(memoryManager.get());
|
||||||
|
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
|
||||||
|
memoryManager.release(); // and memory manager
|
||||||
|
|
||||||
|
//ee->setObjectCache(Cache::getObjectCache());
|
||||||
entryFuncPtr = (EntryFuncPtr)ee->getFunctionAddress(mainFuncName);
|
entryFuncPtr = (EntryFuncPtr)ee->getFunctionAddress(mainFuncName);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!entryFuncPtr)
|
||||||
|
{
|
||||||
|
ee->addModule(module.get());
|
||||||
|
module.release();
|
||||||
|
entryFuncPtr = (EntryFuncPtr)ee->getFunctionAddress(mainFuncName);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
assert(entryFuncPtr);
|
assert(entryFuncPtr);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
namespace llvm
|
|
||||||
{
|
|
||||||
class Module;
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "RuntimeData.h"
|
#include "RuntimeData.h"
|
||||||
|
|
||||||
namespace dev
|
namespace dev
|
||||||
|
|
@ -13,7 +8,6 @@ namespace eth
|
||||||
{
|
{
|
||||||
namespace jit
|
namespace jit
|
||||||
{
|
{
|
||||||
class ExecBundle;
|
|
||||||
|
|
||||||
class ExecutionEngine
|
class ExecutionEngine
|
||||||
{
|
{
|
||||||
|
|
@ -23,7 +17,6 @@ public:
|
||||||
void operator=(ExecutionEngine) = delete;
|
void operator=(ExecutionEngine) = delete;
|
||||||
|
|
||||||
ReturnCode run(bytes const& _code, RuntimeData* _data, Env* _env);
|
ReturnCode run(bytes const& _code, RuntimeData* _data, Env* _env);
|
||||||
ReturnCode run(std::unique_ptr<llvm::Module> module, RuntimeData* _data, Env* _env, bytes const& _code);
|
|
||||||
|
|
||||||
bytes returnData;
|
bytes returnData;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue