#include #include #include #include #include #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 initial_mem) : _initial_memory(initial_mem), _instance(instance), _module(module) {} void apply(apply_context& context) override { vector 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 &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(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 _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 wavm_runtime::instantiate_module(const char* code_bytes, size_t code_size, std::vector 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(instance, module, initial_memory); } }}}}