Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
wasm_interface_private.hpp
Go to the documentation of this file.
1#pragma once
2
4#ifdef SYSIO_SYS_VM_OC_RUNTIME_ENABLED
6#else
7#define _REGISTER_SYSVMOC_INTRINSIC(CLS, MOD, METHOD, WASM_SIG, NAME, SIG)
8#endif
15#include <fc/scoped_exit.hpp>
16
17#include "IR/Module.h"
18#include "Runtime/Intrinsics.h"
19#include "Platform/Platform.h"
20#include "WAST/WAST.h"
21#include "IR/Validate.h"
22
24#include <sysio/vm/allocator.hpp>
25
26using namespace fc;
27using namespace sysio::chain::webassembly;
28using namespace IR;
29using namespace Runtime;
30
31using boost::multi_index_container;
32
33namespace sysio { namespace chain {
34
35 namespace eosvmoc { struct config; }
36
46 struct by_hash;
47 struct by_first_block_num;
48 struct by_last_block_num;
49
50#ifdef SYSIO_SYS_VM_OC_RUNTIME_ENABLED
51 struct eosvmoc_tier {
52 eosvmoc_tier(const boost::filesystem::path& d, const eosvmoc::config& c, const chainbase::database& db)
53 : cc(d, c, db), exec(cc),
54 mem(wasm_constraints::maximum_linear_memory/wasm_constraints::wasm_page_size) {}
58 };
59#endif
60
61 wasm_interface_impl(wasm_interface::vm_type vm, bool eosvmoc_tierup, const chainbase::database& d, const boost::filesystem::path data_dir, const eosvmoc::config& eosvmoc_config, bool profile) : db(d), wasm_runtime_time(vm) {
62#ifdef SYSIO_SYS_VM_RUNTIME_ENABLED
63 if(vm == wasm_interface::vm_type::eos_vm)
65#endif
66#ifdef SYSIO_SYS_VM_JIT_RUNTIME_ENABLED
67 if(vm == wasm_interface::vm_type::eos_vm_jit && profile) {
69 runtime_interface = std::make_unique<webassembly::eos_vm_runtime::eos_vm_profile_runtime>();
70 }
71 if(vm == wasm_interface::vm_type::eos_vm_jit && !profile)
73#endif
74#ifdef SYSIO_SYS_VM_OC_RUNTIME_ENABLED
75 if(vm == wasm_interface::vm_type::eos_vm_oc)
76 runtime_interface = std::make_unique<webassembly::eosvmoc::eosvmoc_runtime>(data_dir, eosvmoc_config, d);
77#endif
79 SYS_THROW(wasm_exception, "${r} wasm runtime not supported on this platform and/or configuration", ("r", vm));
80
81#ifdef SYSIO_SYS_VM_OC_RUNTIME_ENABLED
82 if(eosvmoc_tierup) {
83 SYS_ASSERT(vm != wasm_interface::vm_type::eos_vm_oc, wasm_exception, "You can't use SYS VM OC as the base runtime when tier up is activated");
84 eosvmoc.emplace(data_dir, eosvmoc_config, d);
85 }
86#endif
87 }
88
91 for(wasm_cache_index::iterator it = wasm_instantiation_cache.begin(); it != wasm_instantiation_cache.end(); ++it)
93 e.module.release()->fast_shutdown();
94 });
95 }
96
97 std::vector<uint8_t> parse_initial_memory(const Module& module) {
98 std::vector<uint8_t> mem_image;
99
100 for(const DataSegment& data_segment : module.dataSegments) {
101 SYS_ASSERT(data_segment.baseOffset.type == InitializerExpression::Type::i32_const, wasm_exception, "");
102 SYS_ASSERT(module.memories.defs.size(), wasm_exception, "");
103 const U32 base_offset = data_segment.baseOffset.i32;
104 const Uptr memory_size = (module.memories.defs[0].type.size.min << IR::numBytesPerPageLog2);
105 if(base_offset >= memory_size || base_offset + data_segment.data.size() > memory_size)
106 FC_THROW_EXCEPTION(wasm_execution_error, "WASM data segment outside of valid memory range");
107 if(base_offset + data_segment.data.size() > mem_image.size())
108 mem_image.resize(base_offset + data_segment.data.size(), 0x00);
109 memcpy(mem_image.data() + base_offset, data_segment.data.data(), data_segment.data.size());
110 }
111
112 return mem_image;
113 }
114
115 void code_block_num_last_used(const digest_type& code_hash, const uint8_t& vm_type, const uint8_t& vm_version, const uint32_t& block_num) {
116 wasm_cache_index::iterator it = wasm_instantiation_cache.find(boost::make_tuple(code_hash, vm_type, vm_version));
117 if(it != wasm_instantiation_cache.end())
118 wasm_instantiation_cache.modify(it, [block_num](wasm_cache_entry& e) {
119 e.last_block_num_used = block_num;
120 });
121 }
122
124 //anything last used before or on the LIB can be evicted
125 const auto first_it = wasm_instantiation_cache.get<by_last_block_num>().begin();
126 const auto last_it = wasm_instantiation_cache.get<by_last_block_num>().upper_bound(lib);
127#ifdef SYSIO_SYS_VM_OC_RUNTIME_ENABLED
128 if(eosvmoc) for(auto it = first_it; it != last_it; it++)
129 eosvmoc->cc.free_code(it->code_hash, it->vm_version);
130#endif
131 wasm_instantiation_cache.get<by_last_block_num>().erase(first_it, last_it);
132 }
133
134 const std::unique_ptr<wasm_instantiated_module_interface>& get_instantiated_module( const digest_type& code_hash, const uint8_t& vm_type,
135 const uint8_t& vm_version, transaction_context& trx_context )
136 {
137 wasm_cache_index::iterator it = wasm_instantiation_cache.find(
138 boost::make_tuple(code_hash, vm_type, vm_version) );
139 const code_object* codeobject = nullptr;
140 if(it == wasm_instantiation_cache.end()) {
141 codeobject = &db.get<code_object,by_code_hash>(boost::make_tuple(code_hash, vm_type, vm_version));
142
144 .code_hash = code_hash,
145 .first_block_num_used = codeobject->first_block_used,
146 .last_block_num_used = UINT32_MAX,
147 .module = nullptr,
148 .vm_type = vm_type,
149 .vm_version = vm_version
150 } ).first;
151 }
152
153 if(!it->module) {
154 if(!codeobject)
155 codeobject = &db.get<code_object,by_code_hash>(boost::make_tuple(code_hash, vm_type, vm_version));
156
157 auto timer_pause = fc::make_scoped_exit([&](){
158 trx_context.resume_billing_timer();
159 });
160 trx_context.pause_billing_timer();
162 std::vector<U8> bytes = {
163 (const U8*)codeobject->code.data(),
164 (const U8*)codeobject->code.data() + codeobject->code.size()};
165 try {
166 Serialization::MemoryInputStream stream((const U8*)bytes.data(),
167 bytes.size());
169 WASM::serialize(stream, module);
170 module.userSections.clear();
172 SYS_ASSERT(false, wasm_serialization_error, e.message.c_str());
173 } catch (const IR::ValidationException& e) {
174 SYS_ASSERT(false, wasm_serialization_error, e.message.c_str());
175 }
176
177 wasm_instantiation_cache.modify(it, [&](auto& c) {
178 c.module = runtime_interface->instantiate_module((const char*)bytes.data(), bytes.size(), parse_initial_memory(module), code_hash, vm_type, vm_version);
179 });
180 }
181 return it->module;
182 }
183
184 bool is_shutting_down = false;
185 std::unique_ptr<wasm_runtime_interface> runtime_interface;
186
187 typedef boost::multi_index_container<
189 indexed_by<
190 ordered_unique<tag<by_hash>,
191 composite_key< wasm_cache_entry,
192 member<wasm_cache_entry, digest_type, &wasm_cache_entry::code_hash>,
193 member<wasm_cache_entry, uint8_t, &wasm_cache_entry::vm_type>,
194 member<wasm_cache_entry, uint8_t, &wasm_cache_entry::vm_version>
195 >
196 >,
197 ordered_non_unique<tag<by_first_block_num>, member<wasm_cache_entry, uint32_t, &wasm_cache_entry::first_block_num_used>>,
198 ordered_non_unique<tag<by_last_block_num>, member<wasm_cache_entry, uint32_t, &wasm_cache_entry::last_block_num_used>>
199 >
202
205
206#ifdef SYSIO_SYS_VM_OC_RUNTIME_ENABLED
207 std::optional<eosvmoc_tier> eosvmoc;
208#endif
209 };
210
211} } // sysio::chain
uint32_t U32
Definition BasicTypes.h:9
uint8_t U8
Definition BasicTypes.h:5
PointerIntHelper< sizeof(size_t)>::UnsignedIntType Uptr
Definition BasicTypes.h:22
#define SYS_THROW(exc_type, FORMAT,...)
#define SYS_ASSERT(expr, exc_type, FORMAT,...)
Definition exceptions.hpp:7
const ObjectType & get(CompatibleKey &&key) const
#define FC_THROW_EXCEPTION(EXCEPTION, FORMAT,...)
void serialize(Stream &stream, U8 &i)
namespace sysio::chain
Definition authority.cpp:3
scoped_exit< Callback > make_scoped_exit(Callback &&c)
key Invalid authority Invalid transaction Invalid block ID Invalid packed transaction Invalid chain ID Invalid symbol Signature type is not a currently activated type Block can not be found Unlinkable block Block does not guarantee concurrent execution without conflicts Block exhausted allowed resources Block is from the future Block is not signed by expected producer Block includes an ill formed protocol feature activation extension Block includes an ill formed additional block signature extension Error decompressing transaction Transaction should have at least one required authority Expired Transaction Invalid Reference Block Duplicate deferred transaction The transaction can not be found Transaction is too big Invalid transaction extension Transaction includes disallowed Transaction exceeded transient resource limit Account name already exists sysio_assert_message assertion failure Action can not be found Attempt to use unaccessible API Inline Action exceeds maximum size limit sysio_assert_code assertion failure uses restricted error code value action return value size too big Permission Query Exception Contract Table Query Exception Database is an unknown or unsupported version Database usage is at unsafe levels wasm_exception
void set_profile_interval_us(uint32_t value)
Definition profile.hpp:271
wasm_interface::vm_type vm_type
unsigned int uint32_t
Definition stdint.h:126
#define UINT32_MAX
Definition stdint.h:188
unsigned char uint8_t
Definition stdint.h:124
std::vector< U8 > data
Definition Module.h:95
InitializerExpression baseOffset
Definition Module.h:94
std::unique_ptr< wasm_instantiated_module_interface > module
digest_type code_hash
uint8_t vm_version
uint32_t last_block_num_used
uint32_t first_block_num_used
const std::unique_ptr< wasm_instantiated_module_interface > & get_instantiated_module(const digest_type &code_hash, const uint8_t &vm_type, const uint8_t &vm_version, transaction_context &trx_context)
const wasm_interface::vm_type wasm_runtime_time
wasm_interface_impl(wasm_interface::vm_type vm, bool eosvmoc_tierup, const chainbase::database &d, const boost::filesystem::path data_dir, const eosvmoc::config &eosvmoc_config, bool profile)
void code_block_num_last_used(const digest_type &code_hash, const uint8_t &vm_type, const uint8_t &vm_version, const uint32_t &block_num)
boost::multi_index_container< wasm_cache_entry, indexed_by< ordered_unique< tag< by_hash >, composite_key< wasm_cache_entry, member< wasm_cache_entry, digest_type, &wasm_cache_entry::code_hash >, member< wasm_cache_entry, uint8_t, &wasm_cache_entry::vm_type >, member< wasm_cache_entry, uint8_t, &wasm_cache_entry::vm_version > > >, ordered_non_unique< tag< by_first_block_num >, member< wasm_cache_entry, uint32_t, &wasm_cache_entry::first_block_num_used > >, ordered_non_unique< tag< by_last_block_num >, member< wasm_cache_entry, uint32_t, &wasm_cache_entry::last_block_num_used > > > > wasm_cache_index
std::vector< uint8_t > parse_initial_memory(const Module &module)
std::unique_ptr< wasm_runtime_interface > runtime_interface
CK_ULONG d
memcpy((char *) pInfo->slotDescription, s, l)