Skip to content
This repository has been archived by the owner on Aug 2, 2022. It is now read-only.

Commit

Permalink
Merge pull request #7176 from EOSIO/wavm_module_gc
Browse files Browse the repository at this point in the history
Destroy wavm module instances when deleting the wavm_instantiated_module
  • Loading branch information
arhag committed Apr 24, 2019
2 parents 1b797b2 + f60011b commit f83c5d5
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 31 deletions.
8 changes: 0 additions & 8 deletions libraries/chain/include/eosio/chain/webassembly/wavm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,6 @@ class wavm_runtime : public eosio::chain::wasm_runtime_interface {
std::unique_ptr<wasm_instantiated_module_interface> instantiate_module(const char* code_bytes, size_t code_size, std::vector<uint8_t> initial_memory) override;

void immediately_exit_currently_running_module() override;

struct runtime_guard {
runtime_guard();
~runtime_guard();
};

private:
std::shared_ptr<runtime_guard> _runtime_guard;
};

//This is a temporary hack for the single threaded implementation
Expand Down
66 changes: 43 additions & 23 deletions libraries/chain/webassembly/wavm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
#include "Runtime/Linker.h"
#include "Runtime/Intrinsics.h"

#include <mutex>
#include <vector>
#include <iterator>

using namespace IR;
using namespace Runtime;
Expand All @@ -21,11 +22,45 @@ namespace eosio { namespace chain { namespace webassembly { namespace wavm {

running_instance_context the_running_instance_context;

namespace detail {
struct wavm_runtime_initializer {
wavm_runtime_initializer() {
Runtime::init();
}
};

using live_module_ref = std::list<ObjectInstance*>::iterator;

struct wavm_live_modules {
live_module_ref add_live_module(ModuleInstance* module_instance) {
return live_modules.insert(live_modules.begin(), asObject(module_instance));
}

void remove_live_module(live_module_ref it) {
live_modules.erase(it);
run_wavm_garbage_collection();
}

void run_wavm_garbage_collection() {
//need to pass in a mutable list of root objects we want the garbage collector to retain
std::vector<ObjectInstance*> root;
std::copy(live_modules.begin(), live_modules.end(), std::back_inserter(root));
Runtime::freeUnreferencedObjects(std::move(root));
}

std::list<ObjectInstance*> live_modules;
};

static wavm_live_modules the_wavm_live_modules;

}

class wavm_instantiated_module : public wasm_instantiated_module_interface {
public:
wavm_instantiated_module(ModuleInstance* instance, std::unique_ptr<Module> module, std::vector<uint8_t> initial_mem) :
_initial_memory(initial_mem),
_instance(instance)
_instance(instance),
_module_ref(detail::the_wavm_live_modules.add_live_module(instance))
{
//The memory instance is reused across all wavm_instantiated_modules, but for wasm instances
// that didn't declare "memory", getDefaultMemory() won't see it. It would also be possible
Expand All @@ -34,6 +69,10 @@ class wavm_instantiated_module : public wasm_instantiated_module_interface {
_initial_memory_config = module->memories.defs.at(0).type;
}

~wavm_instantiated_module() {
detail::the_wavm_live_modules.remove_live_module(_module_ref);
}

void apply(apply_context& context) override {
vector<Value> args = {Value(uint64_t(context.get_receiver())),
Value(uint64_t(context.get_action().account)),
Expand Down Expand Up @@ -83,31 +122,12 @@ class wavm_instantiated_module : public wasm_instantiated_module_interface {
//naked pointer because ModuleInstance is opaque
//_instance is deleted via WAVM's object garbage collection when wavm_rutime is deleted
ModuleInstance* _instance;
detail::live_module_ref _module_ref;
MemoryType _initial_memory_config;
};


wavm_runtime::runtime_guard::runtime_guard() {
// TODO clean this up
//check_wasm_opcode_dispositions();
Runtime::init();
}

wavm_runtime::runtime_guard::~runtime_guard() {
Runtime::freeUnreferencedObjects({});
}

static weak_ptr<wavm_runtime::runtime_guard> __runtime_guard_ptr;
static std::mutex __runtime_guard_lock;

wavm_runtime::wavm_runtime() {
std::lock_guard<std::mutex> l(__runtime_guard_lock);
if (__runtime_guard_ptr.use_count() == 0) {
_runtime_guard = std::make_shared<runtime_guard>();
__runtime_guard_ptr = _runtime_guard;
} else {
_runtime_guard = __runtime_guard_ptr.lock();
}
static detail::wavm_runtime_initializer the_wavm_runtime_initializer;
}

wavm_runtime::~wavm_runtime() {
Expand Down

0 comments on commit f83c5d5

Please sign in to comment.