From db5f405fa420c0e1dfefb8636181e162a4610668 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Sun, 18 Jan 2015 16:54:06 +0100 Subject: [PATCH] Do not copy return data inside JIT --- evmjit/libevmjit-cpp/JitVM.cpp | 2 +- evmjit/libevmjit/Common.h | 1 + evmjit/libevmjit/ExecutionEngine.cpp | 5 ++++- evmjit/libevmjit/ExecutionEngine.h | 8 +++++++- evmjit/libevmjit/Runtime.cpp | 6 +++--- evmjit/libevmjit/Runtime.h | 9 +-------- evmjit/libevmjit/interface.cpp | 6 +++--- 7 files changed, 20 insertions(+), 17 deletions(-) diff --git a/evmjit/libevmjit-cpp/JitVM.cpp b/evmjit/libevmjit-cpp/JitVM.cpp index dda8133a8..f1bba9e7f 100644 --- a/evmjit/libevmjit-cpp/JitVM.cpp +++ b/evmjit/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)}; } } diff --git a/evmjit/libevmjit/Common.h b/evmjit/libevmjit/Common.h index 1d8451c74..2d35b21ac 100644 --- a/evmjit/libevmjit/Common.h +++ b/evmjit/libevmjit/Common.h @@ -12,6 +12,7 @@ namespace jit using byte = uint8_t; using bytes = std::vector; +using bytes_ref = std::tuple; using u256 = boost::multiprecision::uint256_t; using bigint = boost::multiprecision::cpp_int; diff --git a/evmjit/libevmjit/ExecutionEngine.cpp b/evmjit/libevmjit/ExecutionEngine.cpp index b6b140fd5..ee92a6ba9 100644 --- a/evmjit/libevmjit/ExecutionEngine.cpp +++ b/evmjit/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(executionEndTime - executionStartTime).count() << " ms\n"; diff --git a/evmjit/libevmjit/ExecutionEngine.h b/evmjit/libevmjit/ExecutionEngine.h index 559701bba..52e3b29fa 100644 --- a/evmjit/libevmjit/ExecutionEngine.h +++ b/evmjit/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; }; } diff --git a/evmjit/libevmjit/Runtime.cpp b/evmjit/libevmjit/Runtime.cpp index 911dc469d..443c19ba6 100644 --- a/evmjit/libevmjit/Runtime.cpp +++ b/evmjit/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(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}; } } diff --git a/evmjit/libevmjit/Runtime.h b/evmjit/libevmjit/Runtime.h index f97efa128..df1bde7fd 100644 --- a/evmjit/libevmjit/Runtime.h +++ b/evmjit/libevmjit/Runtime.h @@ -2,15 +2,8 @@ #pragma once #include -#include - -#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: diff --git a/evmjit/libevmjit/interface.cpp b/evmjit/libevmjit/interface.cpp index eef92d00f..7f334fa14 100644 --- a/evmjit/libevmjit/interface.cpp +++ b/evmjit/libevmjit/interface.cpp @@ -20,12 +20,12 @@ evmjit_result evmjit_run(void* _data, void* _env) auto returnCode = engine.run(bytecode, data, static_cast(_env)); evmjit_result result = {static_cast(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;