提交 90ce83bd 编写于 作者: B Bart Wyatt

modularize sbrk

上级 4ed1d1ea
......@@ -9,13 +9,12 @@ using namespace eosio::chain::webassembly;
namespace eosio { namespace chain {
struct wasm_cache::entry {
entry(jit::entry&& jit, uint32_t default_sbrk_bytes)
: jit(std::forward<jit::entry>(jit)), default_sbrk_bytes(default_sbrk_bytes)
entry(jit::entry&& jit)
: jit(std::forward<jit::entry>(jit))
{
}
jit::entry jit;
uint32_t default_sbrk_bytes;
};
struct wasm_interface_impl {
......
......@@ -11,15 +11,13 @@ namespace eosio { namespace chain { namespace webassembly { namespace common {
using wasm_double = boost::multiprecision::cpp_dec_float_50;
struct wasm_context {
wasm_context(wasm_cache::entry &code, apply_context& ctx, uint32_t sbrk_bytes)
wasm_context(wasm_cache::entry &code, apply_context& ctx)
: code(code)
, context(ctx)
, sbrk_bytes(sbrk_bytes)
{
}
eosio::chain::wasm_cache::entry& code;
apply_context& context;
uint32_t sbrk_bytes;
};
class intrinsics_accessor {
......
......@@ -13,32 +13,39 @@ 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)
{
}
class entry {
public:
ModuleInstance* instance;
Module* module;
uint32_t sbrk_bytes;
ModuleInstance* instance;
Module* module;
void reset(const info& );
void reset(const info& );
void call(const string &entry_point, const vector <Value> &args, apply_context &context);
void call(const string &entry_point, const vector <Value> &args, apply_context &context);
void call_apply(apply_context&);
void call_error(apply_context&);
void call_apply(apply_context&);
void call_error(apply_context&);
int sbrk(int num_bytes);
static const entry& get(wasm_interface& wasm);
static const entry& get(wasm_interface& wasm);
static entry build(const char* wasm_binary, size_t wasm_binary_size);
private:
entry(ModuleInstance *instance, Module *module, uint32_t sbrk_bytes)
: instance(instance), module(module), sbrk_bytes(sbrk_bytes)
{
}
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);
default_sbrk_bytes = jit.sbrk_bytes;
if(current_memory) {
char *mem_ptr = &memoryRef<char>(current_memory, 0);
......@@ -53,9 +60,12 @@ struct info {
}
// a clean image of the memory used to sanitize things on checkin
size_t mem_start = 0;
size_t mem_end = 1<<16;
size_t mem_start = 0;
size_t mem_end = 1<<16;
vector<char> mem_image;
uint32_t default_sbrk_bytes = 0;
};
......
......@@ -174,11 +174,7 @@ namespace eosio { namespace chain {
// find or create a new entry
auto iter = _cache.emplace(code_id, code_info(std::move(*jit_info))).first;
/// 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>(std::move(*jit), default_sbrk_bytes));
iter->second.instances.emplace_back(std::make_unique<wasm_cache::entry>(std::move(*jit)));
pending_result = optional_entry_ref(*iter->second.instances.back().get());
});
}
......@@ -269,7 +265,7 @@ namespace eosio { namespace chain {
*/
struct scoped_context {
template<typename ...Args>
scoped_context(optional<wasm_context> &context, Args&... args)
scoped_context(optional<wasm_context> &context, Args&&... args)
:context(context)
{
context.emplace( std::forward<Args>(args)... );
......@@ -295,12 +291,12 @@ namespace eosio { namespace chain {
}
void wasm_interface::apply( wasm_cache::entry& code, apply_context& context ) {
auto context_guard = scoped_context(my->current_context, code, context, code.default_sbrk_bytes);
auto context_guard = scoped_context(my->current_context, code, context);
code.jit.call_apply(context);
}
void wasm_interface::error( wasm_cache::entry& code, apply_context& context ) {
auto context_guard = scoped_context(my->current_context, code, context, code.default_sbrk_bytes);
auto context_guard = scoped_context(my->current_context, code, context);
code.jit.call_error(context);
}
......@@ -320,12 +316,10 @@ namespace eosio { namespace chain {
class context_aware_api {
public:
context_aware_api(wasm_interface& wasm)
:context(intrinsics_accessor::get_context(wasm).context), code(intrinsics_accessor::get_context(wasm).code),
sbrk_bytes(intrinsics_accessor::get_context(wasm).sbrk_bytes)
:context(intrinsics_accessor::get_context(wasm).context), code(intrinsics_accessor::get_context(wasm).code)
{}
protected:
uint32_t& sbrk_bytes;
wasm_cache::entry& code;
apply_context& context;
};
......@@ -839,37 +833,7 @@ class memory_api : public context_aware_api {
}
uint32_t sbrk(int num_bytes) {
// TODO: omitted checktime function from previous version of sbrk, may need to be put back in at some point
constexpr uint32_t NBPPL2 = IR::numBytesPerPageLog2;
constexpr uint32_t MAX_MEM = 1024 * 1024;
MemoryInstance* default_mem = Runtime::getDefaultMemory(code.jit.instance);
if(!default_mem)
throw eosio::chain::page_memory_error();
const uint32_t num_pages = Runtime::getMemoryNumPages(default_mem);
const uint32_t min_bytes = (num_pages << NBPPL2) > UINT32_MAX ? UINT32_MAX : num_pages << NBPPL2;
const uint32_t prev_num_bytes = sbrk_bytes; //_num_bytes;
// round the absolute value of num_bytes to an alignment boundary
num_bytes = (num_bytes + 7) & ~7;
if ((num_bytes > 0) && (prev_num_bytes > (MAX_MEM - num_bytes))) // test if allocating too much memory (overflowed)
throw eosio::chain::page_memory_error();
else if ((num_bytes < 0) && (prev_num_bytes < (min_bytes - num_bytes))) // test for underflow
throw eosio::chain::page_memory_error();
// update the number of bytes allocated, and compute the number of pages needed
sbrk_bytes += num_bytes;
const uint32_t num_desired_pages = (sbrk_bytes + IR::numBytesPerPage - 1) >> NBPPL2;
// grow or shrink the memory to the desired number of pages
if (num_desired_pages > num_pages)
Runtime::growMemory(default_mem, num_desired_pages - num_pages);
else if (num_desired_pages < num_pages)
Runtime::shrinkMemory(default_mem, num_pages - num_desired_pages);
return prev_num_bytes;
return code.jit.sbrk(num_bytes);
}
};
......
......@@ -70,6 +70,40 @@ void entry::call_error(apply_context& context)
call("error", args, context);
}
int entry::sbrk(int num_bytes) {
// TODO: omitted checktime function from previous version of sbrk, may need to be put back in at some point
constexpr uint32_t NBPPL2 = IR::numBytesPerPageLog2;
constexpr uint32_t MAX_MEM = 1024 * 1024;
MemoryInstance* default_mem = Runtime::getDefaultMemory(instance);
if(!default_mem)
throw eosio::chain::page_memory_error();
const uint32_t num_pages = Runtime::getMemoryNumPages(default_mem);
const uint32_t min_bytes = (num_pages << NBPPL2) > UINT32_MAX ? UINT32_MAX : num_pages << NBPPL2;
const uint32_t prev_num_bytes = sbrk_bytes; //_num_bytes;
// round the absolute value of num_bytes to an alignment boundary
num_bytes = (num_bytes + 7) & ~7;
if ((num_bytes > 0) && (prev_num_bytes > (MAX_MEM - num_bytes))) // test if allocating too much memory (overflowed)
throw eosio::chain::page_memory_error();
else if ((num_bytes < 0) && (prev_num_bytes < (min_bytes - num_bytes))) // test for underflow
throw eosio::chain::page_memory_error();
// update the number of bytes allocated, and compute the number of pages needed
sbrk_bytes += num_bytes;
const uint32_t num_desired_pages = (sbrk_bytes + IR::numBytesPerPage - 1) >> NBPPL2;
// grow or shrink the memory to the desired number of pages
if (num_desired_pages > num_pages)
Runtime::growMemory(default_mem, num_desired_pages - num_pages);
else if (num_desired_pages < num_pages)
Runtime::shrinkMemory(default_mem, num_pages - num_desired_pages);
return prev_num_bytes;
}
void entry::reset(const info& base_info) {
if(getDefaultMemory(instance)) {
......@@ -78,6 +112,8 @@ void entry::reset(const info& base_info) {
memcpy( memstart, base_info.mem_image.data(), base_info.mem_end);
}
resetGlobalInstances(instance);
sbrk_bytes = base_info.default_sbrk_bytes;
}
......@@ -91,7 +127,15 @@ entry entry::build(const char* wasm_binary, size_t wasm_binary_size) {
LinkResult link_result = linkModule(*module, resolver);
ModuleInstance *instance = instantiateModule(*module, std::move(link_result.resolvedImports));
FC_ASSERT(instance != nullptr);
return entry(instance, module);
MemoryInstance* current_memory = Runtime::getDefaultMemory(instance);
uint32_t sbrk_bytes = 0;
if(current_memory) {
sbrk_bytes = Runtime::getMemoryNumPages(current_memory) << IR::numBytesPerPageLog2;
}
return entry(instance, module, sbrk_bytes);
};
}}}}
\ No newline at end of file
......@@ -93,12 +93,12 @@ namespace fc {
}
template<typename ...Args>
void emplace(Args... args) {
void emplace(Args&& ... args) {
if (_valid) {
reset();
}
new ((char*)ptr()) T( args... );
new ((char*)ptr()) T( fc::forward<Args>(args)... );
_valid = true;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册