Browse Source

Do not copy return data inside JIT

cl-refactor
Paweł Bylica 10 years ago
parent
commit
003ba383c3
  1. 2
      libevmjit-cpp/JitVM.cpp
  2. 1
      libevmjit/Common.h
  3. 5
      libevmjit/ExecutionEngine.cpp
  4. 8
      libevmjit/ExecutionEngine.h
  5. 6
      libevmjit/Runtime.cpp
  6. 9
      libevmjit/Runtime.h
  7. 6
      libevmjit/interface.cpp

2
libevmjit-cpp/JitVM.cpp

@ -50,7 +50,7 @@ bytesConstRef JitVM::go(ExtVMFace& _ext, OnOpFunc const&, uint64_t)
}
m_gas = llvm2eth(m_data.elems[RuntimeData::Gas]);
return {m_engine.returnData.data(), m_engine.returnData.size()}; // TODO: This all bytesConstRef is problematic, review.
return {std::get<0>(m_engine.returnData), std::get<1>(m_engine.returnData)};
}
}

1
libevmjit/Common.h

@ -12,6 +12,7 @@ namespace jit
using byte = uint8_t;
using bytes = std::vector<byte>;
using bytes_ref = std::tuple<byte const*, size_t>;
using u256 = boost::multiprecision::uint256_t;
using bigint = boost::multiprecision::cpp_int;

5
libevmjit/ExecutionEngine.cpp

@ -136,7 +136,10 @@ ReturnCode ExecutionEngine::run(bytes const& _code, RuntimeData* _data, Env* _en
auto returnCode = runEntryFunc(entryFuncPtr, &runtime);
if (returnCode == ReturnCode::Return)
this->returnData = runtime.getReturnData();
{
returnData = runtime.getReturnData(); // Save reference to return data
std::swap(m_memory, runtime.getMemory()); // Take ownership of memory
}
auto executionEndTime = std::chrono::high_resolution_clock::now();
clog(JIT) << " + " << std::chrono::duration_cast<std::chrono::milliseconds>(executionEndTime - executionStartTime).count() << " ms\n";

8
libevmjit/ExecutionEngine.h

@ -18,7 +18,13 @@ public:
ReturnCode run(bytes const& _code, RuntimeData* _data, Env* _env);
bytes returnData;
/// Reference to returned data (RETURN opcode used)
bytes_ref returnData;
private:
/// After execution, if RETURN used, memory is moved there
/// to allow client copy the returned data
bytes m_memory;
};
}

6
libevmjit/Runtime.cpp

@ -18,7 +18,7 @@ Runtime::Runtime(RuntimeData* _data, Env* _env) :
m_currJmpBuf(m_jmpBuf)
{}
bytes Runtime::getReturnData() const // FIXME: Reconsider returning by copy
bytes_ref Runtime::getReturnData() const
{
// TODO: Handle large indexes
auto offset = static_cast<size_t>(llvm2eth(m_data.elems[RuntimeData::ReturnDataOffset]));
@ -28,8 +28,8 @@ bytes Runtime::getReturnData() const // FIXME: Reconsider returning by copy
if (offset + size > m_memory.size())
return {};
auto dataBeg = m_memory.begin() + offset;
return {dataBeg, dataBeg + size};
auto dataBeg = m_memory.data() + offset;
return bytes_ref{dataBeg, size};
}
}

9
libevmjit/Runtime.h

@ -2,15 +2,8 @@
#pragma once
#include <csetjmp>
#include <vector>
#include "Instruction.h"
#include "CompilerHelper.h"
#include "Utils.h"
#include "Type.h"
#include "RuntimeData.h"
#ifdef _MSC_VER
#define EXPORT __declspec(dllexport)
#else
@ -40,7 +33,7 @@ public:
MemoryImpl& getMemory() { return m_memory; }
Env* getEnvPtr() { return &m_env; }
bytes getReturnData() const;
bytes_ref getReturnData() const;
jmp_buf_ref getJmpBuf() { return m_jmpBuf; }
private:

6
libevmjit/interface.cpp

@ -20,12 +20,12 @@ evmjit_result evmjit_run(void* _data, void* _env)
auto returnCode = engine.run(bytecode, data, static_cast<Env*>(_env));
evmjit_result result = {static_cast<int32_t>(returnCode), 0, nullptr};
if (returnCode == ReturnCode::Return && !engine.returnData.empty())
if (returnCode == ReturnCode::Return && std::get<0>(engine.returnData))
{
// TODO: Optimized returning data. Allocating memory on client side by callback function might be a good idea
result.returnDataSize = engine.returnData.size();
result.returnDataSize = std::get<1>(engine.returnData);
result.returnData = std::malloc(result.returnDataSize);
std::memcpy(result.returnData, engine.returnData.data(), result.returnDataSize);
std::memcpy(result.returnData, std::get<0>(engine.returnData), result.returnDataSize);
}
return result;

Loading…
Cancel
Save