|
@ -19,6 +19,7 @@ |
|
|
#include "Runtime.h" |
|
|
#include "Runtime.h" |
|
|
#include "Compiler.h" |
|
|
#include "Compiler.h" |
|
|
#include "Cache.h" |
|
|
#include "Cache.h" |
|
|
|
|
|
#include "ExecStats.h" |
|
|
#include "BuildInfo.gen.h" |
|
|
#include "BuildInfo.gen.h" |
|
|
|
|
|
|
|
|
#include <iostream> |
|
|
#include <iostream> |
|
@ -83,50 +84,6 @@ bool showInfo() |
|
|
return show; |
|
|
return show; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
class StatsCollector |
|
|
|
|
|
{ |
|
|
|
|
|
public: |
|
|
|
|
|
std::vector<std::unique_ptr<ExecStats>> stats; |
|
|
|
|
|
|
|
|
|
|
|
~StatsCollector() |
|
|
|
|
|
{ |
|
|
|
|
|
if (stats.empty()) |
|
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
using d = decltype(ExecStats{}.execTime); |
|
|
|
|
|
d total = d::zero(); |
|
|
|
|
|
d max = d::zero(); |
|
|
|
|
|
d min = d::max(); |
|
|
|
|
|
|
|
|
|
|
|
for (auto&& s : stats) |
|
|
|
|
|
{ |
|
|
|
|
|
auto t = s->execTime; |
|
|
|
|
|
total += t; |
|
|
|
|
|
if (t < min) |
|
|
|
|
|
min = t; |
|
|
|
|
|
if (t > max) |
|
|
|
|
|
max = t; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
using u = std::chrono::microseconds; |
|
|
|
|
|
auto nTotal = std::chrono::duration_cast<u>(total).count(); |
|
|
|
|
|
auto nAverage = std::chrono::duration_cast<u>(total / stats.size()).count(); |
|
|
|
|
|
auto nMax = std::chrono::duration_cast<u>(max).count(); |
|
|
|
|
|
auto nMin = std::chrono::duration_cast<u>(min).count(); |
|
|
|
|
|
|
|
|
|
|
|
std::cout << "Total exec time: " << nTotal << " us" << std::endl |
|
|
|
|
|
<< "Averge exec time: " << nAverage << " us" << std::endl |
|
|
|
|
|
<< "Min exec time: " << nMin << " us" << std::endl |
|
|
|
|
|
<< "Max exec time: " << nMax << " us" << std::endl; |
|
|
|
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void ExecutionEngine::collectStats() |
|
|
|
|
|
{ |
|
|
|
|
|
if (!m_stats) |
|
|
|
|
|
m_stats.reset(new ExecStats); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
ReturnCode ExecutionEngine::run(RuntimeData* _data, Env* _env) |
|
|
ReturnCode ExecutionEngine::run(RuntimeData* _data, Env* _env) |
|
@ -140,8 +97,8 @@ ReturnCode ExecutionEngine::run(RuntimeData* _data, Env* _env) |
|
|
|
|
|
|
|
|
static StatsCollector statsCollector; |
|
|
static StatsCollector statsCollector; |
|
|
|
|
|
|
|
|
if (statsCollectingEnabled) |
|
|
std::unique_ptr<ExecStats> listener{new ExecStats}; |
|
|
collectStats(); |
|
|
listener->stateChanged(ExecState::Started); |
|
|
|
|
|
|
|
|
auto codeBegin = _data->code; |
|
|
auto codeBegin = _data->code; |
|
|
auto codeEnd = codeBegin + _data->codeSize; |
|
|
auto codeEnd = codeBegin + _data->codeSize; |
|
@ -155,12 +112,15 @@ ReturnCode ExecutionEngine::run(RuntimeData* _data, Env* _env) |
|
|
} |
|
|
} |
|
|
else |
|
|
else |
|
|
{ |
|
|
{ |
|
|
auto objectCache = objectCacheEnabled ? Cache::getObjectCache() : nullptr; |
|
|
auto objectCache = objectCacheEnabled ? Cache::getObjectCache(listener.get()) : nullptr; |
|
|
std::unique_ptr<llvm::Module> module; |
|
|
std::unique_ptr<llvm::Module> module; |
|
|
if (objectCache) |
|
|
if (objectCache) |
|
|
module = Cache::getObject(mainFuncName); |
|
|
module = Cache::getObject(mainFuncName); |
|
|
if (!module) |
|
|
if (!module) |
|
|
|
|
|
{ |
|
|
|
|
|
listener->stateChanged(ExecState::Compilation); |
|
|
module = Compiler({}).compile(codeBegin, codeEnd, mainFuncName); |
|
|
module = Compiler({}).compile(codeBegin, codeEnd, mainFuncName); |
|
|
|
|
|
} |
|
|
if (debugDumpModule) |
|
|
if (debugDumpModule) |
|
|
module->dump(); |
|
|
module->dump(); |
|
|
if (!ee) |
|
|
if (!ee) |
|
@ -190,6 +150,7 @@ ReturnCode ExecutionEngine::run(RuntimeData* _data, Env* _env) |
|
|
|
|
|
|
|
|
if (objectCache) |
|
|
if (objectCache) |
|
|
ee->setObjectCache(objectCache); |
|
|
ee->setObjectCache(objectCache); |
|
|
|
|
|
listener->stateChanged(ExecState::CodeGen); |
|
|
entryFuncPtr = (EntryFuncPtr)ee->getFunctionAddress(mainFuncName); |
|
|
entryFuncPtr = (EntryFuncPtr)ee->getFunctionAddress(mainFuncName); |
|
|
} |
|
|
} |
|
|
else |
|
|
else |
|
@ -198,28 +159,26 @@ ReturnCode ExecutionEngine::run(RuntimeData* _data, Env* _env) |
|
|
{ |
|
|
{ |
|
|
ee->addModule(module.get()); |
|
|
ee->addModule(module.get()); |
|
|
module.release(); |
|
|
module.release(); |
|
|
|
|
|
listener->stateChanged(ExecState::CodeGen); |
|
|
entryFuncPtr = (EntryFuncPtr)ee->getFunctionAddress(mainFuncName); |
|
|
entryFuncPtr = (EntryFuncPtr)ee->getFunctionAddress(mainFuncName); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
assert(entryFuncPtr); |
|
|
assert(entryFuncPtr); |
|
|
|
|
|
|
|
|
if (m_stats) |
|
|
listener->stateChanged(ExecState::Execution); |
|
|
m_stats->execStarted(); |
|
|
|
|
|
|
|
|
|
|
|
auto returnCode = runEntryFunc(entryFuncPtr, &runtime); |
|
|
auto returnCode = runEntryFunc(entryFuncPtr, &runtime); |
|
|
|
|
|
listener->stateChanged(ExecState::Return); |
|
|
if (m_stats) |
|
|
|
|
|
m_stats->execEnded(); |
|
|
|
|
|
|
|
|
|
|
|
if (returnCode == ReturnCode::Return) |
|
|
if (returnCode == ReturnCode::Return) |
|
|
{ |
|
|
{ |
|
|
returnData = runtime.getReturnData(); // Save reference to return data
|
|
|
returnData = runtime.getReturnData(); // Save reference to return data
|
|
|
std::swap(m_memory, runtime.getMemory()); // Take ownership of memory
|
|
|
std::swap(m_memory, runtime.getMemory()); // Take ownership of memory
|
|
|
} |
|
|
} |
|
|
|
|
|
listener->stateChanged(ExecState::Finished); |
|
|
|
|
|
|
|
|
if (statsCollectingEnabled) |
|
|
if (statsCollectingEnabled) |
|
|
statsCollector.stats.push_back(std::move(m_stats)); |
|
|
statsCollector.stats.push_back(std::move(listener)); |
|
|
|
|
|
|
|
|
return returnCode; |
|
|
return returnCode; |
|
|
} |
|
|
} |
|
|