From 6941a1c78c066cdfcfbd44ee0b8d31c95fb35280 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 2 Mar 2015 11:14:57 +0100 Subject: [PATCH] Fix memory leaks --- evmjit/libevmjit/Array.cpp | 10 +++++++--- evmjit/libevmjit/Common.h | 4 +++- evmjit/libevmjit/Compiler.cpp | 23 ++++++++++++----------- evmjit/libevmjit/Runtime.cpp | 9 +++------ evmjit/libevmjit/RuntimeManager.cpp | 3 +-- evmjit/libevmjit/RuntimeManager.h | 5 +++-- evmjit/libevmjit/interface.cpp | 5 ----- 7 files changed, 29 insertions(+), 30 deletions(-) diff --git a/evmjit/libevmjit/Array.cpp b/evmjit/libevmjit/Array.cpp index 92ba6193d..3266038db 100644 --- a/evmjit/libevmjit/Array.cpp +++ b/evmjit/libevmjit/Array.cpp @@ -278,7 +278,11 @@ namespace ~AllocatedMemoryWatchdog() { if (!allocatedMemory.empty()) + { DLOG(mem) << allocatedMemory.size() << " MEM LEAKS!\n"; + for (auto&& leak : allocatedMemory) + DLOG(mem) << "\t" << leak << "\n"; + } } }; @@ -289,20 +293,20 @@ extern "C" { using namespace dev::eth::jit; - EXPORT void* ext_realloc(void* _data, size_t _size) + EXPORT void* ext_realloc(void* _data, size_t _size) noexcept { //std::cerr << "REALLOC: " << _data << " [" << _size << "]" << std::endl; auto newData = std::realloc(_data, _size); if (_data != newData) { - DLOG(mem) << "REALLOC: " << _data << " -> " << newData << " [" << _size << "]\n"; + DLOG(mem) << "REALLOC: " << newData << " <- " << _data << " [" << _size << "]\n"; watchdog.allocatedMemory.erase(_data); watchdog.allocatedMemory.insert(newData); } return newData; } - EXPORT void ext_free(void* _data) + EXPORT void ext_free(void* _data) noexcept { std::free(_data); if (_data) diff --git a/evmjit/libevmjit/Common.h b/evmjit/libevmjit/Common.h index 7e3380c2e..cbe60483d 100644 --- a/evmjit/libevmjit/Common.h +++ b/evmjit/libevmjit/Common.h @@ -4,7 +4,9 @@ #include #ifdef _MSC_VER -#define EXPORT __declspec(dllexport) +#define EXPORT __declspec(dllexport) +#define _ALLOW_KEYWORD_MACROS +#define noexcept throw() #else #define EXPORT #endif diff --git a/evmjit/libevmjit/Compiler.cpp b/evmjit/libevmjit/Compiler.cpp index ab95458e8..6fa82c870 100644 --- a/evmjit/libevmjit/Compiler.cpp +++ b/evmjit/libevmjit/Compiler.cpp @@ -132,6 +132,17 @@ std::unique_ptr Compiler::compile(code_iterator _begin, code_itera auto entryBlock = llvm::BasicBlock::Create(m_builder.getContext(), {}, m_mainFunc); m_builder.SetInsertPoint(entryBlock); + createBasicBlocks(_begin, _end); + + // Init runtime structures. + RuntimeManager runtimeManager(m_builder, _begin, _end); + GasMeter gasMeter(m_builder, runtimeManager); + Memory memory(runtimeManager, gasMeter); + Ext ext(runtimeManager, memory); + Stack stack(m_builder, runtimeManager); + runtimeManager.setStack(stack); // Runtime Manager will free stack memory + Arith256 arith(m_builder); + auto jmpBufWords = m_builder.CreateAlloca(Type::BytePtr, m_builder.getInt64(3), "jmpBuf.words"); auto frameaddress = llvm::Intrinsic::getDeclaration(module.get(), llvm::Intrinsic::frameaddress); auto fp = m_builder.CreateCall(frameaddress, m_builder.getInt32(0), "fp"); @@ -144,17 +155,7 @@ std::unique_ptr Compiler::compile(code_iterator _begin, code_itera auto jmpBuf = m_builder.CreateBitCast(jmpBufWords, Type::BytePtr, "jmpBuf"); auto r = m_builder.CreateCall(setjmp, jmpBuf); auto normalFlow = m_builder.CreateICmpEQ(r, m_builder.getInt32(0)); - - createBasicBlocks(_begin, _end); - - // Init runtime structures. - RuntimeManager runtimeManager(m_builder, jmpBuf, _begin, _end); - GasMeter gasMeter(m_builder, runtimeManager); - Memory memory(runtimeManager, gasMeter); - Ext ext(runtimeManager, memory); - Stack stack(m_builder, runtimeManager); - runtimeManager.setStack(stack); // Runtime Manager will free stack memory - Arith256 arith(m_builder); + runtimeManager.setJmpBuf(jmpBuf); // TODO: Create Stop basic block on demand m_stopBB = llvm::BasicBlock::Create(m_mainFunc->getContext(), "Stop", m_mainFunc); diff --git a/evmjit/libevmjit/Runtime.cpp b/evmjit/libevmjit/Runtime.cpp index 952ee2645..7e9a7d52e 100644 --- a/evmjit/libevmjit/Runtime.cpp +++ b/evmjit/libevmjit/Runtime.cpp @@ -1,7 +1,5 @@ #include "Runtime.h" -#include -#include #include namespace dev @@ -17,13 +15,12 @@ void Runtime::init(RuntimeData* _data, Env* _env) m_env = _env; } +extern "C" void ext_free(void* _data) noexcept; + Runtime::~Runtime() { if (m_memData) - { - std::cerr << "MEM: " << (size_t)m_memData << " [" << m_memSize << "]\n"; - std::free(m_memData); - } + ext_free(m_memData); // Use helper free to check memory leaks } bytes_ref Runtime::getReturnData() const diff --git a/evmjit/libevmjit/RuntimeManager.cpp b/evmjit/libevmjit/RuntimeManager.cpp index 87b47c057..d1ccaea8a 100644 --- a/evmjit/libevmjit/RuntimeManager.cpp +++ b/evmjit/libevmjit/RuntimeManager.cpp @@ -84,9 +84,8 @@ llvm::Twine getName(RuntimeData::Index _index) } } -RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder, llvm::Value* _jmpBuf, code_iterator _codeBegin, code_iterator _codeEnd): +RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder, code_iterator _codeBegin, code_iterator _codeEnd): CompilerHelper(_builder), - m_jmpBuf(_jmpBuf), m_codeBegin(_codeBegin), m_codeEnd(_codeEnd) { diff --git a/evmjit/libevmjit/RuntimeManager.h b/evmjit/libevmjit/RuntimeManager.h index 52298d1d0..eb8dadf6f 100644 --- a/evmjit/libevmjit/RuntimeManager.h +++ b/evmjit/libevmjit/RuntimeManager.h @@ -16,7 +16,7 @@ class Stack; class RuntimeManager: public CompilerHelper { public: - RuntimeManager(llvm::IRBuilder<>& _builder, llvm::Value* _jmpBuf, code_iterator _codeBegin, code_iterator _codeEnd); + RuntimeManager(llvm::IRBuilder<>& _builder, code_iterator _codeBegin, code_iterator _codeEnd); llvm::Value* getRuntimePtr(); llvm::Value* getDataPtr(); @@ -43,6 +43,7 @@ public: void abort(llvm::Value* _jmpBuf); void setStack(Stack& _stack) { m_stack = &_stack; } + void setJmpBuf(llvm::Value* _jmpBuf) { m_jmpBuf = _jmpBuf; } static llvm::StructType* getRuntimeType(); static llvm::StructType* getRuntimeDataType(); @@ -52,7 +53,7 @@ private: void set(RuntimeData::Index _index, llvm::Value* _value); llvm::Function* m_longjmp = nullptr; - llvm::Value* const m_jmpBuf; + llvm::Value* m_jmpBuf = nullptr; llvm::Value* m_dataPtr = nullptr; llvm::Value* m_gasPtr = nullptr; llvm::Value* m_memPtr = nullptr; diff --git a/evmjit/libevmjit/interface.cpp b/evmjit/libevmjit/interface.cpp index 645f3d150..01f743a2e 100644 --- a/evmjit/libevmjit/interface.cpp +++ b/evmjit/libevmjit/interface.cpp @@ -5,11 +5,6 @@ extern "C" using namespace dev::eth::jit; -#ifdef _MSC_VER -#define _ALLOW_KEYWORD_MACROS -#define noexcept throw() -#endif - EXPORT void* evmjit_create() noexcept { // TODO: Make sure ExecutionEngine constructor does not throw