text: #include <eosio/chain/webassembly/wavm.hpp>
  #include <eosio/chain/wasm_eosio_constraints.hpp>
  #include <eosio/chain/wasm_eosio_injection.hpp>
  #include <eosio/chain/apply_context.hpp>
  #include <eosio/chain/exceptions.hpp>
  
  #include "IR/Module.h"
  #include "Platform/Platform.h"
  #include "WAST/WAST.h"
  #include "IR/Operators.h"
  #include "IR/Validate.h"
  #include "Runtime/Linker.h"
  #include "Runtime/Intrinsics.h"
  
  
  using namespace IR;
  using namespace Runtime;
  
  namespace eosio { namespace chain { namespace webassembly { namespace wavm {
  
  running_instance_context the_running_instance_context;
  
  class wavm_instantiated_module : public wasm_instantiated_module_interface {
     public:
        wavm_instantiated_module(ModuleInstance* instance, Module* module, std::vector<uint8_t> initial_mem) :
           _initial_memory(initial_mem),
           _instance(instance),
           _module(module)
        {}
  
        void apply(apply_context& context) override {
           vector<Value> args = {Value(uint64_t(context.act.account)),
                                 Value(uint64_t(context.act.name))};
  
           call("apply", args, context);
        }
  
        ~wavm_instantiated_module() {
           delete _module;
           //_instance is deleted via WAVM's object garbage collection when wavm_rutime is deleted
        }
  
     private:
        void call(const string &entry_point, const vector <Value> &args, apply_context &context) {
           try {
              FunctionInstance* call = asFunctionNullable(getInstanceExport(_instance,entry_point));
              if( !call )
                 return;
  
              FC_ASSERT( getFunctionType(call)->parameters.size() == args.size() );
  
              //The memory instance is reused across all wavm_instantiated_modules, but for wasm instances
              // that didn't declare "memory", getDefaultMemory() won't see it
              MemoryInstance* default_mem = getDefaultMemory(_instance);
              if(default_mem) {
                 //reset memory resizes the sandbox'ed memory to the module's init memory size and then
                 // (effectively) memzeros it all
                 resetMemory(default_mem, _module->memories.defs[0].type);
  
                 char* memstart = &memoryRef<char>(getDefaultMemory(_instance), 0);
                 memcpy(memstart, _initial_memory.data(), _initial_memory.size());
              }
  
              the_running_instance_context.memory = default_mem;
              the_running_instance_context.apply_ctx = &context;
  
              resetGlobalInstances(_instance);
              runInstanceStartFunc(_instance);
              Runtime::invokeFunction(call,args);
           } catch( const wasm_exit& e ) {
           } catch( const Runtime::Exception& e ) {
               FC_THROW_EXCEPTION(wasm_execution_error,
                           "cause: ${cause}\n${callstack}",
                           ("cause", string(describeExceptionCause(e.cause)))
                           ("callstack", e.callStack));
           } FC_CAPTURE_AND_RETHROW()
        }
  
        std::vector<uint8_t> _initial_memory;
        //naked pointers because ModuleInstance is opaque
        ModuleInstance*      _instance;
        Module*              _module;
  };
  
  wavm_runtime::wavm_runtime() {
     Runtime::init();
  }
  
  wavm_runtime::~wavm_runtime() {
     Runtime::freeUnreferencedObjects({});
  }
  
  std::unique_ptr<wasm_instantiated_module_interface> wavm_runtime::instantiate_module(const char* code_bytes, size_t code_size, std::vector<uint8_t> initial_memory) {
     Module* module = new Module();
     Serialization::MemoryInputStream stream((const U8 *)code_bytes, code_size);
     WASM::serialize(stream, *module);
  
     eosio::chain::webassembly::common::root_resolver resolver;
     LinkResult link_result = linkModule(*module, resolver);
     ModuleInstance *instance = instantiateModule(*module, std::move(link_result.resolvedImports));
     FC_ASSERT(instance != nullptr);
  
     return std::make_unique<wavm_instantiated_module>(instance, module, initial_memory);
  }
  
  }}}}
  