wavm.cpp 3.9 KB
Newer Older
1
#include <eosio/chain/webassembly/wavm.hpp>
B
Bart Wyatt 已提交
2
#include <eosio/chain/wasm_eosio_constraints.hpp>
3
#include <eosio/chain/wasm_eosio_injection.hpp>
4
#include <eosio/chain/apply_context.hpp>
5
#include <eosio/chain/exceptions.hpp>
B
Bart Wyatt 已提交
6 7 8 9 10 11 12 13 14 15 16 17 18

#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;

19
namespace eosio { namespace chain { namespace webassembly { namespace wavm {
B
Bart Wyatt 已提交
20

21 22
running_instance_context the_running_instance_context;

23
class wavm_instantiated_module : public wasm_instantiated_module_interface {
24 25
   public:
      wavm_instantiated_module(ModuleInstance* instance, Module* module, std::vector<uint8_t> initial_mem) :
26
         _initial_memory(initial_mem),
27
         _instance(instance),
28
         _module(module)
29 30 31 32 33 34 35
      {}

      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);
B
Bart Wyatt 已提交
36 37
      }

38 39
      ~wavm_instantiated_module() {
         delete _module;
40
         //_instance is deleted via WAVM's object garbage collection when wavm_rutime is deleted
41
      }
42

43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
   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());
            }

64
            the_running_instance_context.memory = default_mem;
65
            the_running_instance_context.apply_ctx = &context;
66

67 68 69
            resetGlobalInstances(_instance);
            runInstanceStartFunc(_instance);
            Runtime::invokeFunction(call,args);
70
         } catch( const wasm_exit& e ) {
71 72
         } catch( const Runtime::Exception& e ) {
             FC_THROW_EXCEPTION(wasm_execution_error,
73 74 75
                         "cause: ${cause}\n${callstack}",
                         ("cause", string(describeExceptionCause(e.cause)))
                         ("callstack", e.callStack));
76 77
         } FC_CAPTURE_AND_RETHROW()
      }
78

79 80 81 82 83
      std::vector<uint8_t> _initial_memory;
      //naked pointers because ModuleInstance is opaque
      ModuleInstance*      _instance;
      Module*              _module;
};
B
Bart Wyatt 已提交
84

85 86 87
wavm_runtime::wavm_runtime() {
   Runtime::init();
}
B
Bart Wyatt 已提交
88

89 90
wavm_runtime::~wavm_runtime() {
   Runtime::freeUnreferencedObjects({});
B
Bart Wyatt 已提交
91
}
B
Bart Wyatt 已提交
92

93
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) {
B
Bart Wyatt 已提交
94
   Module* module = new Module();
95
   Serialization::MemoryInputStream stream((const U8 *)code_bytes, code_size);
96
   WASM::serialize(stream, *module);
B
Bart Wyatt 已提交
97

98
   eosio::chain::webassembly::common::root_resolver resolver;
B
Bart Wyatt 已提交
99 100 101
   LinkResult link_result = linkModule(*module, resolver);
   ModuleInstance *instance = instantiateModule(*module, std::move(link_result.resolvedImports));
   FC_ASSERT(instance != nullptr);
B
Bart Wyatt 已提交
102

103
   return std::make_unique<wavm_instantiated_module>(instance, module, initial_memory);
104 105
}

106
}}}}