提交 9a614ead 编写于 作者: B Bart Wyatt

more modularization

上级 7ea3f14c
......@@ -27,6 +27,7 @@ add_library( eosio_chain
contracts/genesis_state.cpp
contracts/abi_serializer.cpp
webassembly/jit.cpp
${HEADERS}
transaction_metadata.cpp)
......
......@@ -12,6 +12,7 @@ using namespace eosio::chain::webassembly::common;
namespace eosio { namespace chain { namespace webassembly { namespace jit {
struct info;
struct entry {
entry(ModuleInstance *instance, Module *module)
: instance(instance), module(module)
......@@ -20,10 +21,39 @@ struct entry {
ModuleInstance* instance;
Module* module;
void reset(const info& );
static const entry& get(wasm_interface& wasm);
static entry build(const char* wasm_binary, size_t wasm_binary_size);
};
struct info {
info( const entry &jit )
{
MemoryInstance* current_memory = Runtime::getDefaultMemory(jit.instance);
if(current_memory) {
char *mem_ptr = &memoryRef<char>(current_memory, 0);
const auto allocated_memory = Runtime::getDefaultMemorySize(jit.instance);
for (uint64_t i = 0; i < allocated_memory; ++i) {
if (mem_ptr[i])
mem_end = i + 1;
}
mem_image.resize(mem_end);
memcpy(mem_image.data(), mem_ptr, mem_end);
}
}
// a clean image of the memory used to sanitize things on checkin
size_t mem_start = 0;
size_t mem_end = 1<<16;
vector<char> mem_image;
};
/**
* class to represent an in-wasm-memory array
* it is a hint to the transcriber that the next parameter will
......@@ -32,7 +62,7 @@ struct entry {
* @tparam T
*/
template<typename T>
array_ptr<T> array_ptr_impl (wasm_interface& wasm, U32 ptr, size_t length)
inline array_ptr<T> array_ptr_impl (wasm_interface& wasm, U32 ptr, size_t length)
{
auto mem = getDefaultMemory(entry::get(wasm).instance);
if(!mem || ptr + length > IR::numBytesPerPage*Runtime::getMemoryNumPages(mem))
......@@ -44,7 +74,7 @@ array_ptr<T> array_ptr_impl (wasm_interface& wasm, U32 ptr, size_t length)
/**
* class to represent an in-wasm-memory char array that must be null terminated
*/
null_terminated_ptr null_terminated_ptr_impl(wasm_interface& wasm, U32 ptr)
inline null_terminated_ptr null_terminated_ptr_impl(wasm_interface& wasm, U32 ptr)
{
auto mem = getDefaultMemory(entry::get(wasm).instance);
if(!mem)
......@@ -128,19 +158,19 @@ template<typename T>
using native_to_wasm_t = typename native_to_wasm<T>::type;
template<typename T>
auto convert_native_to_wasm(const wasm_interface &wasm, T val) {
inline auto convert_native_to_wasm(const wasm_interface &wasm, T val) {
return native_to_wasm_t<T>(val);
}
auto convert_native_to_wasm(const wasm_interface &wasm, const name &val) {
inline auto convert_native_to_wasm(const wasm_interface &wasm, const name &val) {
return native_to_wasm_t<const name &>(val.value);
}
auto convert_native_to_wasm(const wasm_interface &wasm, const fc::time_point_sec &val) {
inline auto convert_native_to_wasm(const wasm_interface &wasm, const fc::time_point_sec &val) {
return native_to_wasm_t<const fc::time_point_sec &>(val.sec_since_epoch());
}
auto convert_native_to_wasm(wasm_interface &wasm, char* ptr) {
inline auto convert_native_to_wasm(wasm_interface &wasm, char* ptr) {
auto mem = getDefaultMemory(entry::get(wasm).instance);
if(!mem)
Runtime::causeException(Exception::Cause::accessViolation);
......@@ -152,12 +182,12 @@ auto convert_native_to_wasm(wasm_interface &wasm, char* ptr) {
}
template<typename T>
auto convert_wasm_to_native(native_to_wasm_t<T> val) {
inline auto convert_wasm_to_native(native_to_wasm_t<T> val) {
return T(val);
}
template<>
auto convert_wasm_to_native<wasm_double>(I64 val) {
inline auto convert_wasm_to_native<wasm_double>(I64 val) {
return wasm_double(*reinterpret_cast<wasm_double *>(&val));
}
......
......@@ -4,7 +4,6 @@
#include <eosio/chain/exceptions.hpp>
#include <boost/core/ignore_unused.hpp>
#include <eosio/chain/wasm_interface_private.hpp>
#include <eosio/chain/wasm_eosio_constraints.hpp>
#include <fc/exception/exception.hpp>
#include <fc/crypto/sha1.hpp>
#include <fc/io/raw.hpp>
......@@ -72,26 +71,6 @@ namespace eosio { namespace chain {
using namespace webassembly;
using namespace webassembly::common;
/**
* Integration with the WASM Linker to resolve our intrinsics
*/
struct root_resolver : Runtime::Resolver
{
bool resolve(const string& mod_name,
const string& export_name,
ObjectType type,
ObjectInstance*& out) override
{ try {
// Try to resolve an intrinsic first.
if(IntrinsicResolver::singleton.resolve(mod_name,export_name,type, out)) {
return true;
}
FC_ASSERT( !"unresolvable", "${module}.${export}", ("module",mod_name)("export",export_name) );
return false;
} FC_CAPTURE_AND_RETHROW( (mod_name)(export_name) ) }
};
/**
* Implementation class for the wasm cache
* it is responsible for compiling and storing instances of wasm code for use
......@@ -127,14 +106,8 @@ namespace eosio { namespace chain {
* the instance handed out to other threads
*/
struct code_info {
code_info( size_t mem_end, vector<char>&& mem_image )
:mem_end(mem_end),mem_image(std::forward<vector<char>>(mem_image))
{}
// a clean image of the memory used to sanitize things on checkin
size_t mem_start = 0;
size_t mem_end = 1<<16;
vector<char> mem_image;
explicit code_info(jit::info&& jit_info) :jit_info(jit_info) {}
jit::info jit_info;
// all existing instances of this code
vector<unique_ptr<wasm_cache::entry>> instances;
......@@ -215,33 +188,14 @@ namespace eosio { namespace chain {
if (!pending_result) {
// time to compile a brand new (maybe first) copy of this code
Module* module = new Module();
ModuleInstance* instance = nullptr;
size_t mem_end = 0;
vector<char> mem_image;
fc::optional<jit::entry> jit;
fc::optional<jit::info> jit_info;
try {
Serialization::MemoryInputStream stream((const U8 *) wasm_binary, wasm_binary_size);
WASM::serializeWithInjection(stream, *module);
validate_eosio_wasm_constraints(*module);
root_resolver resolver;
LinkResult link_result = linkModule(*module, resolver);
instance = instantiateModule(*module, std::move(link_result.resolvedImports));
FC_ASSERT(instance != nullptr);
MemoryInstance* current_memory = Runtime::getDefaultMemory(instance);
if(current_memory) {
char *mem_ptr = &memoryRef<char>(current_memory, 0);
const auto allocated_memory = Runtime::getDefaultMemorySize(instance);
for (uint64_t i = 0; i < allocated_memory; ++i) {
if (mem_ptr[i])
mem_end = i + 1;
}
mem_image.resize(mem_end);
memcpy(mem_image.data(), mem_ptr, mem_end);
}
/// TODO: make validation generic
jit = jit::entry::build(wasm_binary, wasm_binary_size);
jit_info.emplace(*jit);
} catch (...) {
pending_error = std::current_exception();
......@@ -251,12 +205,13 @@ namespace eosio { namespace chain {
// grab the lock and put this in the cache as unavailble
with_lock(_cache_lock, [&,this]() {
// find or create a new entry
auto iter = _cache.emplace(code_id, code_info(mem_end, std::move(mem_image))).first;
auto iter = _cache.emplace(code_id, code_info(std::move(*jit_info))).first;
MemoryInstance* default_mem = Runtime::getDefaultMemory(instance);
/// TODO: make sbrk bytes generic
MemoryInstance* default_mem = Runtime::getDefaultMemory(jit->instance);
uint32_t default_sbrk_bytes = default_mem ? Runtime::getMemoryNumPages(default_mem) << IR::numBytesPerPageLog2 : 0;
iter->second.instances.emplace_back(std::make_unique<wasm_cache::entry>(jit::entry{instance, module}, default_sbrk_bytes));
iter->second.instances.emplace_back(std::make_unique<wasm_cache::entry>(std::move(*jit), default_sbrk_bytes));
pending_result = optional_entry_ref(*iter->second.instances.back().get());
});
}
......@@ -291,12 +246,7 @@ namespace eosio { namespace chain {
void return_entry(const digest_type& code_id, wasm_cache::entry& entry) {
// sanitize by reseting the memory that may now be dirty
auto& info = (*fetch_info(code_id)).get();
if(getDefaultMemory(entry.jit.instance)) {
char* memstart = &memoryRef<char>( getDefaultMemory(entry.jit.instance), 0 );
memset( memstart + info.mem_end, 0, ((1<<16) - info.mem_end) );
memcpy( memstart, info.mem_image.data(), info.mem_end);
}
resetGlobalInstances(entry.jit.instance);
entry.jit.reset(info.jit_info);
// under a lock, put this entry back in the available instances side of the instances vector
with_lock(_cache_lock, [&,this](){
......
#include <eosio/chain/webassembly/jit.hpp>
#include <eosio/chain/wasm_eosio_constraints.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 jit {
/**
* Integration with the WASM Linker to resolve our intrinsics
*/
struct root_resolver : Runtime::Resolver
{
bool resolve(const string& mod_name,
const string& export_name,
ObjectType type,
ObjectInstance*& out) override
{ try {
// Try to resolve an intrinsic first.
if(IntrinsicResolver::singleton.resolve(mod_name,export_name,type, out)) {
return true;
}
FC_ASSERT( !"unresolvable", "${module}.${export}", ("module",mod_name)("export",export_name) );
return false;
} FC_CAPTURE_AND_RETHROW( (mod_name)(export_name) ) }
};
void entry::reset(const info& base_info) {
if(getDefaultMemory(instance)) {
char* memstart = &memoryRef<char>( getDefaultMemory(instance), 0 );
memset( memstart + base_info.mem_end, 0, ((1<<16) - base_info.mem_end) );
memcpy( memstart, base_info.mem_image.data(), base_info.mem_end);
}
resetGlobalInstances(instance);
}
entry entry::build(const char* wasm_binary, size_t wasm_binary_size) {
Module* module = new Module();
Serialization::MemoryInputStream stream((const U8 *) wasm_binary, wasm_binary_size);
WASM::serializeWithInjection(stream, *module);
validate_eosio_wasm_constraints(*module);
root_resolver resolver;
LinkResult link_result = linkModule(*module, resolver);
ModuleInstance *instance = instantiateModule(*module, std::move(link_result.resolvedImports));
FC_ASSERT(instance != nullptr);
return entry(instance, module);
};
}}}}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册