Don't make sandbox_malloc into a coroutine

Okay, the coroutine implementation of `sandbox_malloc` is clearly
broken. It would be working if Asyncify instrumented the `memory.grow`
WebAssembly instruction, but it doesn't instrument it.

This commit reverts commit 42c4ff9497 and
also increases the default VM memory allocation from 64 MiB to 96 MiB to
account for the lack of ability to increase the memory allocation at run
time. I'll find some new way to implement increasing the memory
allocation later.
This commit is contained in:
刘皓 2025-03-18 13:49:41 -04:00
parent 7ce7fdb3e0
commit eeef9ff943
No known key found for this signature in database
GPG key ID: 7901753DB465B711
19 changed files with 156 additions and 318 deletions

View file

@ -67,7 +67,7 @@ uint8_t *binding_base::operator*() const noexcept {
return get();
}
wasm_ptr_t binding_base::_sandbox_malloc(wasm_size_t size) {
wasm_ptr_t binding_base::sandbox_malloc(wasm_size_t size) {
wasm_ptr_t buf = w2c_ruby_mkxp_sandbox_malloc(&instance(), size);
// Verify that the entire allocated buffer is in valid memory

View file

@ -80,7 +80,7 @@ namespace mkxp_sandbox {
struct w2c_ruby &instance() const noexcept;
uint8_t *get() const noexcept;
uint8_t *operator*() const noexcept;
wasm_ptr_t _sandbox_malloc(wasm_size_t);
wasm_ptr_t sandbox_malloc(wasm_size_t);
void sandbox_free(wasm_ptr_t ptr);
wasm_ptr_t rtypeddata_data(VALUE obj) const noexcept;
void rtypeddata_dmark(wasm_ptr_t data, wasm_ptr_t ptr);

View file

@ -41,6 +41,21 @@
return mkxp_sandbox::sb()->bind<struct alloc>()()(_klass); \
}
#define SANDBOX_DEF_ALLOC_WITH_INIT(rbtype, initializer) \
static VALUE alloc(VALUE _klass) { \
SANDBOX_COROUTINE(alloc, \
VALUE _obj; \
VALUE operator()(VALUE _klass) { \
BOOST_ASIO_CORO_REENTER (this) { \
SANDBOX_AWAIT_AND_SET(_obj, mkxp_sandbox::rb_data_typed_object_wrap, _klass, 0, rbtype); \
mkxp_sandbox::set_private_data(_obj, initializer); /* TODO: free when sandbox is deallocated */ \
} \
return _obj; \
} \
) \
return mkxp_sandbox::sb()->bind<struct alloc>()()(_klass); \
}
#define SANDBOX_DEF_DFREE(T) \
static void dfree(wasm_ptr_t _buf) { \
delete *(T **)(**mkxp_sandbox::sb() + _buf); \
@ -48,46 +63,28 @@
#define SANDBOX_DEF_LOAD(T) \
static VALUE load(VALUE _self, VALUE _serialized) { \
return mkxp_sandbox::sb()->bind<struct _load_inner<T>>()()(_self, _serialized); \
SANDBOX_COROUTINE(load, \
struct mkxp_sandbox::_load::load_struct _data; \
VALUE operator()(VALUE _self, VALUE _serialized) { \
BOOST_ASIO_CORO_REENTER (this) { \
SANDBOX_AWAIT_AND_SET(_data, mkxp_sandbox::_load::load_inner, _self, _serialized); \
set_private_data(_data.obj, T::deserialize((const char *)(**mkxp_sandbox::sb() + _data.ptr), _data.len)); /* TODO: free when sandbox is deallocated */ \
} \
return _data.obj; \
} \
) \
return mkxp_sandbox::sb()->bind<struct load>()()(_self, _serialized); \
}
namespace mkxp_sandbox {
// Given Ruby typed data `obj`, stores `ptr` into the private data field of `obj`.
void set_private_data(VALUE obj, void *ptr);
// Given Ruby typed data `obj`, retrieves the private data field of `obj`.
template <typename T> inline T *get_private_data(VALUE obj) {
return *(T **)(**sb() + *(wasm_ptr_t *)(**sb() + sb()->rtypeddata_data(obj)));
}
// Given Ruby typed data `obj`, stores `ptr` into the private data field of `obj`.
SANDBOX_COROUTINE(set_private_data,
wasm_ptr_t data;
wasm_ptr_t buf;
void operator()(VALUE obj, void *ptr) {
BOOST_ASIO_CORO_REENTER (this) {
/* RGSS's behavior is to just leak memory if a disposable is reinitialized,
* with the original disposable being left permanently instantiated,
* but that's (1) bad, and (2) would currently cause memory access issues
* when things like a sprite's src_rect inevitably get GC'd, so we're not
* copying that. */
data = sb()->rtypeddata_data(obj);
// Free the old value if it already exists (initialize called twice?)
if (*(wasm_ptr_t *)(**sb() + data) != 0 && *(void **)(**sb() + *(wasm_ptr_t *)(**sb() + data)) != ptr) {
sb()->rtypeddata_dfree(obj, *(wasm_ptr_t *)(**sb() + data));
sb()->sandbox_free(*(wasm_ptr_t *)(**sb() + data));
*(wasm_ptr_t *)(**sb() + data) = 0;
}
if (*(wasm_ptr_t *)(**sb() + data) == 0) {
SANDBOX_AWAIT_AND_SET(buf, sandbox_malloc, sizeof(void *));
*(void **)(**sb() + buf) = ptr;
*(wasm_ptr_t *)(**sb() + data) = buf;
}
}
}
)
// Gets the length of a Ruby object.
SANDBOX_COROUTINE(get_length,
ID id;
@ -105,23 +102,28 @@ namespace mkxp_sandbox {
}
)
// Internal-use utility coroutine for the `SANDBOX_DEF_LOAD` macro.
template <typename T> SANDBOX_COROUTINE(_load_inner,
VALUE obj;
wasm_ptr_t ptr;
wasm_size_t len;
namespace _load {
struct load_struct {
VALUE obj;
wasm_ptr_t ptr;
wasm_size_t len;
};
VALUE operator()(VALUE self, VALUE serialized) {
BOOST_ASIO_CORO_REENTER (this) {
SANDBOX_AWAIT_AND_SET(obj, rb_obj_alloc, self);
SANDBOX_AWAIT_AND_SET(ptr, rb_string_value_ptr, &serialized);
SANDBOX_AWAIT_AND_SET(len, get_length, serialized);
SANDBOX_AWAIT(set_private_data, obj, T::deserialize((const char *)(**sb() + ptr), len)); // TODO: free when sandbox is deallocated
// Internal-use utility coroutine for the `SANDBOX_DEF_LOAD` macro.
SANDBOX_COROUTINE(load_inner,
struct load_struct data;
struct load_struct operator()(VALUE self, VALUE serialized) {
BOOST_ASIO_CORO_REENTER (this) {
SANDBOX_AWAIT_AND_SET(data.obj, rb_obj_alloc, self);
SANDBOX_AWAIT_AND_SET(data.ptr, rb_string_value_ptr, &serialized);
SANDBOX_AWAIT_AND_SET(data.len, get_length, serialized);
}
return data;
}
return obj;
}
)
)
}
// Prints the backtrace of a Ruby exception to the log.
SANDBOX_COROUTINE(log_backtrace,

View file

@ -66,7 +66,7 @@ namespace mkxp_sandbox {
GFX_GUARD_EXC(bitmap = new Bitmap(width, height);)
}
SANDBOX_AWAIT(set_private_data, self, bitmap);
set_private_data(self, bitmap);
SANDBOX_AWAIT(init_props, bitmap, self);
}
@ -96,7 +96,7 @@ namespace mkxp_sandbox {
SANDBOX_AWAIT(init_props, bitmap, self);
// TODO: set font
SANDBOX_AWAIT(set_private_data, self, bitmap);
set_private_data(self, bitmap);
}
return self;
@ -138,7 +138,7 @@ namespace mkxp_sandbox {
SANDBOX_AWAIT_AND_SET(id, rb_intern, "Rect");
SANDBOX_AWAIT_AND_SET(klass, rb_const_get, sb()->rb_cObject(), id);
SANDBOX_AWAIT_AND_SET(obj, rb_obj_alloc, klass);
SANDBOX_AWAIT(set_private_data, obj, new Rect(get_private_data<Bitmap>(self)->rect()));
set_private_data(obj, new Rect(get_private_data<Bitmap>(self)->rect()));
}
return obj;
@ -284,7 +284,7 @@ namespace mkxp_sandbox {
SANDBOX_AWAIT_AND_SET(id, rb_intern, "Color");
SANDBOX_AWAIT_AND_SET(klass, rb_const_get, sb()->rb_cObject(), id);
SANDBOX_AWAIT_AND_SET(obj, rb_obj_alloc, klass);
SANDBOX_AWAIT(set_private_data, obj, color);
set_private_data(obj, color);
}
return obj;
@ -402,7 +402,7 @@ namespace mkxp_sandbox {
SANDBOX_AWAIT_AND_SET(id, rb_intern, "Rect");
SANDBOX_AWAIT_AND_SET(klass, rb_const_get, sb()->rb_cObject(), id);
SANDBOX_AWAIT_AND_SET(obj, rb_obj_alloc, klass);
SANDBOX_AWAIT(set_private_data, obj, new Rect(get_private_data<Bitmap>(self)->textSize((const char *)(**sb() + str))));
set_private_data(obj, new Rect(get_private_data<Bitmap>(self)->textSize((const char *)(**sb() + str))));
}
return obj;
@ -416,7 +416,7 @@ namespace mkxp_sandbox {
void operator()() {
BOOST_ASIO_CORO_REENTER (this) {
SANDBOX_AWAIT_AND_SET(bitmap_type, new_rb_data_type, "Bitmap", NULL, dfree, NULL, NULL, 0, 0, 0);
bitmap_type = sb()->rb_data_type("Bitmap", NULL, dfree, NULL, NULL, 0, 0, 0);
SANDBOX_AWAIT_AND_SET(klass, rb_define_class, "Bitmap", sb()->rb_cObject());
SANDBOX_AWAIT(rb_define_alloc_func, klass, alloc);
SANDBOX_AWAIT(rb_define_method, klass, "initialize", (VALUE (*)(ANYARGS))initialize, -1);

View file

@ -33,26 +33,10 @@ namespace mkxp_sandbox {
SANDBOX_COROUTINE(etc_binding_init,
SANDBOX_COROUTINE(color_binding_init,
SANDBOX_DEF_ALLOC_WITH_INIT(color_type, new Color)
SANDBOX_DEF_DFREE(Color)
SANDBOX_DEF_LOAD(Color)
static VALUE alloc(VALUE klass) {
SANDBOX_COROUTINE(coro,
VALUE obj;
VALUE operator()(VALUE klass) {
BOOST_ASIO_CORO_REENTER (this) {
SANDBOX_AWAIT_AND_SET(obj, mkxp_sandbox::rb_data_typed_object_wrap, klass, 0, color_type);
SANDBOX_AWAIT(set_private_data, obj, new Color);
}
return obj;
}
)
return mkxp_sandbox::sb()->bind<struct coro>()()(klass);
}
static VALUE initialize(int32_t argc, wasm_ptr_t argv, VALUE self) {
SANDBOX_COROUTINE(coro,
Color *color;
@ -64,7 +48,7 @@ namespace mkxp_sandbox {
VALUE operator()(int32_t argc, wasm_ptr_t argv, VALUE self) {
BOOST_ASIO_CORO_REENTER (this) {
if (argc == 0) {
color = new Color;
color = new Color();
} else {
SANDBOX_AWAIT_AND_SET(red, rb_num2dbl, ((VALUE *)(**sb() + argv))[0]);
SANDBOX_AWAIT_AND_SET(green, rb_num2dbl, ((VALUE *)(**sb() + argv))[1]);
@ -77,7 +61,7 @@ namespace mkxp_sandbox {
}
}
SANDBOX_AWAIT(set_private_data, self, color);
set_private_data(self, color);
}
return SANDBOX_NIL;
@ -206,7 +190,7 @@ namespace mkxp_sandbox {
void operator()() {
BOOST_ASIO_CORO_REENTER (this) {
SANDBOX_AWAIT_AND_SET(color_type, new_rb_data_type, "Color", NULL, dfree, NULL, NULL, 0, 0, 0);
color_type = sb()->rb_data_type("Color", NULL, dfree, NULL, NULL, 0, 0, 0);
SANDBOX_AWAIT_AND_SET(klass, rb_define_class, "Color", sb()->rb_cObject());
SANDBOX_AWAIT(rb_define_alloc_func, klass, alloc);
SANDBOX_AWAIT(rb_define_singleton_method, klass, "_load", (VALUE (*)(ANYARGS))load, 1);
@ -225,26 +209,10 @@ namespace mkxp_sandbox {
)
SANDBOX_COROUTINE(tone_binding_init,
SANDBOX_DEF_ALLOC_WITH_INIT(tone_type, new Tone)
SANDBOX_DEF_DFREE(Tone)
SANDBOX_DEF_LOAD(Tone)
static VALUE alloc(VALUE klass) {
SANDBOX_COROUTINE(coro,
VALUE obj;
VALUE operator()(VALUE klass) {
BOOST_ASIO_CORO_REENTER (this) {
SANDBOX_AWAIT_AND_SET(obj, mkxp_sandbox::rb_data_typed_object_wrap, klass, 0, tone_type);
SANDBOX_AWAIT(set_private_data, obj, new Tone);
}
return obj;
}
)
return mkxp_sandbox::sb()->bind<struct coro>()()(klass);
}
static VALUE initialize(int32_t argc, wasm_ptr_t argv, VALUE self) {
SANDBOX_COROUTINE(coro,
Tone *tone;
@ -256,7 +224,7 @@ namespace mkxp_sandbox {
VALUE operator()(int32_t argc, wasm_ptr_t argv, VALUE self) {
BOOST_ASIO_CORO_REENTER (this) {
if (argc == 0) {
tone = new Tone;
tone = new Tone();
} else {
SANDBOX_AWAIT_AND_SET(red, rb_num2dbl, ((VALUE *)(**sb() + argv))[0]);
SANDBOX_AWAIT_AND_SET(green, rb_num2dbl, ((VALUE *)(**sb() + argv))[1]);
@ -269,7 +237,7 @@ namespace mkxp_sandbox {
}
}
SANDBOX_AWAIT(set_private_data, self, tone);
set_private_data(self, tone);
}
return SANDBOX_NIL;
@ -398,7 +366,7 @@ namespace mkxp_sandbox {
void operator()() {
BOOST_ASIO_CORO_REENTER (this) {
SANDBOX_AWAIT_AND_SET(tone_type, new_rb_data_type, "Tone", NULL, dfree, NULL, NULL, 0, 0, 0);
tone_type = sb()->rb_data_type("Tone", NULL, dfree, NULL, NULL, 0, 0, 0);
SANDBOX_AWAIT_AND_SET(klass, rb_define_class, "Tone", sb()->rb_cObject());
SANDBOX_AWAIT(rb_define_alloc_func, klass, alloc);
SANDBOX_AWAIT(rb_define_singleton_method, klass, "_load", (VALUE (*)(ANYARGS))load, 1);
@ -417,26 +385,10 @@ namespace mkxp_sandbox {
)
SANDBOX_COROUTINE(rect_binding_init,
SANDBOX_DEF_ALLOC_WITH_INIT(rect_type, new Rect)
SANDBOX_DEF_DFREE(Rect)
SANDBOX_DEF_LOAD(Rect)
static VALUE alloc(VALUE klass) {
SANDBOX_COROUTINE(coro,
VALUE obj;
VALUE operator()(VALUE klass) {
BOOST_ASIO_CORO_REENTER (this) {
SANDBOX_AWAIT_AND_SET(obj, mkxp_sandbox::rb_data_typed_object_wrap, klass, 0, rect_type);
SANDBOX_AWAIT(set_private_data, obj, new Rect);
}
return obj;
}
)
return mkxp_sandbox::sb()->bind<struct coro>()()(klass);
}
static VALUE initialize(int32_t argc, wasm_ptr_t argv, VALUE self) {
SANDBOX_COROUTINE(coro,
Rect *rect;
@ -448,7 +400,7 @@ namespace mkxp_sandbox {
VALUE operator()(int32_t argc, wasm_ptr_t argv, VALUE self) {
BOOST_ASIO_CORO_REENTER (this) {
if (argc == 0) {
rect = new Rect;
rect = new Rect();
} else {
SANDBOX_AWAIT_AND_SET(x, rb_num2int, ((VALUE *)(**sb() + argv))[0]);
SANDBOX_AWAIT_AND_SET(y, rb_num2int, ((VALUE *)(**sb() + argv))[1]);
@ -457,7 +409,7 @@ namespace mkxp_sandbox {
rect = new Rect(x, y, width, height);
}
SANDBOX_AWAIT(set_private_data, self, rect);
set_private_data(self, rect);
}
return SANDBOX_NIL;
@ -587,7 +539,7 @@ namespace mkxp_sandbox {
void operator()() {
BOOST_ASIO_CORO_REENTER (this) {
SANDBOX_AWAIT_AND_SET(rect_type, new_rb_data_type, "Rect", NULL, dfree, NULL, NULL, 0, 0, 0);
rect_type = sb()->rb_data_type("Rect", NULL, dfree, NULL, NULL, 0, 0, 0);
SANDBOX_AWAIT_AND_SET(klass, rb_define_class, "Rect", sb()->rb_cObject());
SANDBOX_AWAIT(rb_define_alloc_func, klass, alloc);
SANDBOX_AWAIT(rb_define_singleton_method, klass, "_load", (VALUE (*)(ANYARGS))load, 1);

View file

@ -41,9 +41,8 @@ namespace mkxp_sandbox {
SANDBOX_AWAIT_AND_SET(id, rb_intern, "Color");
SANDBOX_AWAIT_AND_SET(klass, rb_const_get, sb()->rb_cObject(), id);
SANDBOX_AWAIT_AND_SET(obj, rb_obj_alloc, klass);
SANDBOX_AWAIT(set_private_data, obj, new Color);
set_private_data(obj, new Color());
SANDBOX_AWAIT(rb_iv_set, self, "color", obj);
SANDBOX_AWAIT_AND_SET(obj, rb_iv_get, self, "color");
}
return SANDBOX_NIL;

View file

@ -62,20 +62,20 @@ namespace mkxp_sandbox {
GFX_LOCK
plane = new Plane(viewport);
SANDBOX_AWAIT(set_private_data, self, plane);
set_private_data(self, plane);
plane->initDynAttribs();
SANDBOX_AWAIT_AND_SET(id, rb_intern, "Color");
SANDBOX_AWAIT_AND_SET(klass, rb_const_get, sb()->rb_cObject(), id);
SANDBOX_AWAIT_AND_SET(obj, rb_obj_alloc, klass);
SANDBOX_AWAIT(set_private_data, obj, &plane->getColor());
set_private_data(obj, &plane->getColor());
SANDBOX_AWAIT(rb_iv_set, self, "color", obj);
SANDBOX_AWAIT_AND_SET(id, rb_intern, "Tone");
SANDBOX_AWAIT_AND_SET(klass, rb_const_get, sb()->rb_cObject(), id);
SANDBOX_AWAIT_AND_SET(obj, rb_obj_alloc, klass);
SANDBOX_AWAIT(set_private_data, obj, &plane->getTone());
set_private_data(obj, &plane->getTone());
SANDBOX_AWAIT(rb_iv_set, self, "tone", obj);
GFX_UNLOCK
@ -316,7 +316,7 @@ namespace mkxp_sandbox {
void operator()() {
BOOST_ASIO_CORO_REENTER (this) {
SANDBOX_AWAIT_AND_SET(plane_type, new_rb_data_type, "Plane", NULL, dfree, NULL, NULL, 0, 0, 0);
plane_type = sb()->rb_data_type("Plane", NULL, dfree, NULL, NULL, 0, 0, 0);
SANDBOX_AWAIT_AND_SET(klass, rb_define_class, "Plane", sb()->rb_cObject());
SANDBOX_AWAIT(rb_define_alloc_func, klass, alloc);
SANDBOX_AWAIT(rb_define_method, klass, "initialize", (VALUE (*)(ANYARGS))initialize, -1);

View file

@ -43,7 +43,6 @@ using namespace mkxp_sandbox;
usize sandbox::sandbox_malloc(usize size) {
usize buf = w2c_ruby_mkxp_sandbox_malloc(RB, size);
assert(w2c_ruby_asyncify_get_state(RB) == 0);
// Verify that the returned pointer is non-null and the entire allocated buffer is in valid memory
usize buf_end;
@ -58,7 +57,7 @@ void sandbox::sandbox_free(usize ptr) {
w2c_ruby_mkxp_sandbox_free(RB, ptr);
}
sandbox::sandbox() : ruby(new struct w2c_ruby), wasi(new wasi_t(ruby)), bindings(ruby), yielding(false), realloc_size(0) {
sandbox::sandbox() : ruby(new struct w2c_ruby), wasi(new wasi_t(ruby)), bindings(ruby), yielding(false) {
try {
// Initialize the sandbox
wasm2c_ruby_instantiate(RB, wasi.get());
@ -82,8 +81,6 @@ sandbox::sandbox() : ruby(new struct w2c_ruby), wasi(new wasi_t(ruby)), bindings
args.push_back("--yjit");
}
usize state_buf = sandbox_malloc(sizeof(usize));
// Copy all the command-line arguments into the sandbox (sandboxed code can't access memory that's outside the sandbox!)
usize argv_buf = sandbox_malloc(args.size() * sizeof(usize));
for (usize i = 0; i < args.size(); ++i) {
@ -101,6 +98,7 @@ sandbox::sandbox() : ruby(new struct w2c_ruby), wasi(new wasi_t(ruby)), bindings
// Start up Ruby executable node
bool valid;
u32 state;
usize state_buf = sandbox_malloc(sizeof(usize));
AWAIT(valid = w2c_ruby_ruby_executable_node(RB, node, state_buf));
if (valid) {
AWAIT(state = w2c_ruby_ruby_exec_node(RB, node));
@ -124,7 +122,7 @@ sandbox::sandbox() : ruby(new struct w2c_ruby), wasi(new wasi_t(ruby)), bindings
}
sandbox::~sandbox() {
if (yielding || realloc_size != 0) {
if (yielding) {
w2c_ruby_asyncify_stop_unwind(ruby.get());
}
bindings.reset(); // Destroy the bindings before destroying the runtime since the bindings destructor requires the runtime to be alive

View file

@ -22,7 +22,6 @@
#ifndef MKXPZ_SANDBOX_H
#define MKXPZ_SANDBOX_H
#include <cstring>
#include <memory>
#include <boost/optional.hpp>
#include <mkxp-sandbox-bindgen.h>
@ -79,8 +78,6 @@ namespace mkxp_sandbox {
std::unique_ptr<struct w2c_wasi__snapshot__preview1> wasi;
boost::optional<struct mkxp_sandbox::bindings> bindings;
bool yielding;
size_t realloc_size;
bool realloc_succeeded;
usize sandbox_malloc(usize size);
void sandbox_free(usize ptr);
@ -101,20 +98,6 @@ namespace mkxp_sandbox {
w2c_ruby_asyncify_stop_rewind(ruby.get());
}
inline void _begin_realloc(size_t size) {
realloc_size = size;
w2c_ruby_asyncify_start_unwind(ruby.get(), ruby->w2c_mkxp_sandbox_async_buf);
}
inline bool _end_realloc() {
w2c_ruby_asyncify_stop_rewind(ruby.get());
return realloc_succeeded;
}
inline bool _rewinding() {
return w2c_ruby_asyncify_get_state(ruby.get()) == 2;
}
// Executes the given coroutine as the top-level coroutine. Don't call this from inside of another coroutine; use `sb()->bind<T>()` instead.
// Returns whether or not the coroutine completed execution.
template <typename T> inline bool run() {
@ -128,16 +111,7 @@ namespace mkxp_sandbox {
frame()();
if (yielding || frame().is_complete()) break;
}
if (realloc_size != 0) {
w2c_ruby_asyncify_start_rewind(ruby.get(), ruby->w2c_mkxp_sandbox_async_buf);
uint8_t *new_data = (uint8_t *)std::realloc(ruby->w2c_memory.data, realloc_size);
if ((realloc_succeeded = new_data != NULL)) {
ruby->w2c_memory.private_data = new_data;
}
realloc_size = 0;
} else {
w2c_ruby_mkxp_sandbox_yield(ruby.get());
}
w2c_ruby_mkxp_sandbox_yield(ruby.get());
}
return !yielding;
}

View file

@ -58,25 +58,25 @@ namespace mkxp_sandbox {
sprite = new Sprite(viewport);
SANDBOX_AWAIT(rb_iv_set, self, "viewport", viewport_obj);
SANDBOX_AWAIT(set_private_data, self, sprite);
set_private_data(self, sprite);
sprite->initDynAttribs();
SANDBOX_AWAIT_AND_SET(id, rb_intern, "Rect");
SANDBOX_AWAIT_AND_SET(klass, rb_const_get, sb()->rb_cObject(), id);
SANDBOX_AWAIT_AND_SET(obj, rb_obj_alloc, klass);
SANDBOX_AWAIT(set_private_data, obj, &sprite->getSrcRect());
set_private_data(obj, &sprite->getSrcRect());
SANDBOX_AWAIT(rb_iv_set, self, "src_rect", obj);
SANDBOX_AWAIT_AND_SET(id, rb_intern, "Color");
SANDBOX_AWAIT_AND_SET(klass, rb_const_get, sb()->rb_cObject(), id);
SANDBOX_AWAIT_AND_SET(obj, rb_obj_alloc, klass);
SANDBOX_AWAIT(set_private_data, obj, &sprite->getColor());
set_private_data(obj, &sprite->getColor());
SANDBOX_AWAIT(rb_iv_set, self, "color", obj);
SANDBOX_AWAIT_AND_SET(id, rb_intern, "Tone");
SANDBOX_AWAIT_AND_SET(klass, rb_const_get, sb()->rb_cObject(), id);
SANDBOX_AWAIT_AND_SET(obj, rb_obj_alloc, klass);
SANDBOX_AWAIT(set_private_data, obj, &sprite->getTone());
set_private_data(obj, &sprite->getTone());
SANDBOX_AWAIT(rb_iv_set, self, "tone", obj);
GFX_UNLOCK
@ -460,7 +460,7 @@ namespace mkxp_sandbox {
void operator()() {
BOOST_ASIO_CORO_REENTER (this) {
SANDBOX_AWAIT_AND_SET(sprite_type, new_rb_data_type, "Sprite", NULL, dfree, NULL, NULL, 0, 0, 0);
sprite_type = sb()->rb_data_type("Sprite", NULL, dfree, NULL, NULL, 0, 0, 0);
SANDBOX_AWAIT_AND_SET(klass, rb_define_class, "Sprite", sb()->rb_cObject());
SANDBOX_AWAIT(rb_define_alloc_func, klass, alloc);
SANDBOX_AWAIT(rb_define_method, klass, "initialize", (VALUE (*)(ANYARGS))initialize, -1);

View file

@ -31,27 +31,10 @@ namespace mkxp_sandbox {
static struct mkxp_sandbox::bindings::rb_data_type table_type;
SANDBOX_COROUTINE(table_binding_init,
SANDBOX_DEF_ALLOC_WITH_INIT(table_type, new Table(0, 0, 0))
SANDBOX_DEF_DFREE(Table)
SANDBOX_DEF_LOAD(Table)
static VALUE alloc(VALUE klass) {
SANDBOX_COROUTINE(coro,
VALUE obj;
VALUE operator()(VALUE klass) {
BOOST_ASIO_CORO_REENTER (this) {
SANDBOX_AWAIT_AND_SET(obj, mkxp_sandbox::rb_data_typed_object_wrap, klass, 0, table_type);
SANDBOX_AWAIT(set_private_data, obj, new Table(0, 0, 0));
}
return obj;
}
)
return mkxp_sandbox::sb()->bind<struct coro>()()(klass);
}
static VALUE get(int32_t argc, wasm_ptr_t argv, VALUE self) {
SANDBOX_COROUTINE(coro,
Table *table;
@ -128,7 +111,7 @@ namespace mkxp_sandbox {
void operator()() {
BOOST_ASIO_CORO_REENTER (this) {
SANDBOX_AWAIT_AND_SET(table_type, new_rb_data_type, "Table", NULL, dfree, NULL, NULL, 0, 0, 0);
table_type = sb()->rb_data_type("Table", NULL, dfree, NULL, NULL, 0, 0, 0);
SANDBOX_AWAIT_AND_SET(klass, rb_define_class, "Table", sb()->rb_cObject());
SANDBOX_AWAIT(rb_define_alloc_func, klass, alloc);
SANDBOX_AWAIT(rb_define_singleton_method, klass, "_load", (VALUE (*)(ANYARGS))load, 1);

View file

@ -90,7 +90,7 @@ namespace mkxp_sandbox {
void operator()() {
BOOST_ASIO_CORO_REENTER (this) {
SANDBOX_AWAIT_AND_SET(tilemap_autotiles_type, new_rb_data_type, "TilemapAutotiles", NULL, NULL, NULL, NULL, 0, 0, 0);
tilemap_autotiles_type = sb()->rb_data_type("TilemapAutotiles", NULL, NULL, NULL, NULL, 0, 0, 0);
SANDBOX_AWAIT_AND_SET(klass, rb_define_class, "TilemapAutotiles", sb()->rb_cObject());
SANDBOX_AWAIT(rb_define_alloc_func, klass, alloc);
SANDBOX_AWAIT(rb_define_method, klass, "[]", (VALUE (*)(ANYARGS))get, 1);
@ -131,7 +131,7 @@ namespace mkxp_sandbox {
GFX_LOCK
tilemap = new Tilemap(viewport);
SANDBOX_AWAIT(set_private_data, self, tilemap);
set_private_data(self, tilemap);
tilemap->initDynAttribs();
@ -139,25 +139,25 @@ namespace mkxp_sandbox {
* See the comment in setPrivateData for more info. */
SANDBOX_AWAIT_AND_SET(obj, rb_iv_get, self, "autotiles");
if (obj != SANDBOX_NIL) {
SANDBOX_AWAIT(set_private_data, obj, NULL);
set_private_data(obj, NULL);
}
SANDBOX_AWAIT_AND_SET(id, rb_intern, "TilemapAutotiles");
SANDBOX_AWAIT_AND_SET(klass, rb_const_get, sb()->rb_cObject(), id);
SANDBOX_AWAIT_AND_SET(obj, rb_obj_alloc, klass);
SANDBOX_AWAIT(set_private_data, obj, &tilemap->getAutotiles());
set_private_data(obj, &tilemap->getAutotiles());
SANDBOX_AWAIT(rb_iv_set, self, "autotiles", obj);
SANDBOX_AWAIT_AND_SET(id, rb_intern, "Color");
SANDBOX_AWAIT_AND_SET(klass, rb_const_get, sb()->rb_cObject(), id);
SANDBOX_AWAIT_AND_SET(obj, rb_obj_alloc, klass);
SANDBOX_AWAIT(set_private_data, obj, &tilemap->getColor());
set_private_data(obj, &tilemap->getColor());
SANDBOX_AWAIT(rb_iv_set, self, "color", obj);
SANDBOX_AWAIT_AND_SET(id, rb_intern, "Tone");
SANDBOX_AWAIT_AND_SET(klass, rb_const_get, sb()->rb_cObject(), id);
SANDBOX_AWAIT_AND_SET(obj, rb_obj_alloc, klass);
SANDBOX_AWAIT(set_private_data, obj, &tilemap->getTone());
set_private_data(obj, &tilemap->getTone());
SANDBOX_AWAIT(rb_iv_set, self, "tone", obj);
SANDBOX_AWAIT_AND_SET(obj, rb_iv_get, self, "autotiles");
@ -418,7 +418,7 @@ namespace mkxp_sandbox {
BOOST_ASIO_CORO_REENTER (this) {
SANDBOX_AWAIT(tilemap_autotiles_binding_init);
SANDBOX_AWAIT_AND_SET(tilemap_type, new_rb_data_type, "Tilemap", NULL, dfree, NULL, NULL, 0, 0, 0);
tilemap_type = sb()->rb_data_type("Tilemap", NULL, dfree, NULL, NULL, 0, 0, 0);
SANDBOX_AWAIT_AND_SET(klass, rb_define_class, "Tilemap", sb()->rb_cObject());
SANDBOX_AWAIT(rb_define_alloc_func, klass, alloc);
SANDBOX_AWAIT(rb_define_method, klass, "initialize", (VALUE (*)(ANYARGS))initialize, -1);

View file

@ -59,26 +59,26 @@ namespace mkxp_sandbox {
viewport = new Viewport(x, y, w, h);
}
SANDBOX_AWAIT(set_private_data, self, viewport);
set_private_data(self, viewport);
viewport->initDynAttribs();
SANDBOX_AWAIT_AND_SET(id, rb_intern, "Rect");
SANDBOX_AWAIT_AND_SET(klass, rb_const_get, sb()->rb_cObject(), id);
SANDBOX_AWAIT_AND_SET(obj, rb_obj_alloc, klass);
SANDBOX_AWAIT(set_private_data, obj, &viewport->getRect());
set_private_data(obj, &viewport->getRect());
SANDBOX_AWAIT(rb_iv_set, self, "rect", obj);
SANDBOX_AWAIT_AND_SET(id, rb_intern, "Color");
SANDBOX_AWAIT_AND_SET(klass, rb_const_get, sb()->rb_cObject(), id);
SANDBOX_AWAIT_AND_SET(obj, rb_obj_alloc, klass);
SANDBOX_AWAIT(set_private_data, obj, &viewport->getColor());
set_private_data(obj, &viewport->getColor());
SANDBOX_AWAIT(rb_iv_set, self, "color", obj);
SANDBOX_AWAIT_AND_SET(id, rb_intern, "Tone");
SANDBOX_AWAIT_AND_SET(klass, rb_const_get, sb()->rb_cObject(), id);
SANDBOX_AWAIT_AND_SET(obj, rb_obj_alloc, klass);
SANDBOX_AWAIT(set_private_data, obj, &viewport->getTone());
set_private_data(obj, &viewport->getTone());
SANDBOX_AWAIT(rb_iv_set, self, "tone", obj);
GFX_UNLOCK
@ -232,7 +232,7 @@ namespace mkxp_sandbox {
void operator()() {
BOOST_ASIO_CORO_REENTER (this) {
SANDBOX_AWAIT_AND_SET(viewport_type, new_rb_data_type, "Viewport", NULL, dfree, NULL, NULL, 0, 0, 0);
viewport_type = sb()->rb_data_type("Viewport", NULL, dfree, NULL, NULL, 0, 0, 0);
SANDBOX_AWAIT_AND_SET(klass, rb_define_class, "Viewport", sb()->rb_cObject());
SANDBOX_AWAIT(rb_define_alloc_func, klass, alloc);
SANDBOX_AWAIT(rb_define_method, klass, "initialize", (VALUE (*)(ANYARGS))initialize, -1);

View file

@ -27,7 +27,7 @@
#define WASM_PAGE_SIZE ((uint64_t)65536U)
#define WASM_MIN_PAGES ((uint32_t)1024U) // tentative
#define WASM_MIN_PAGES ((uint32_t)1536U)
extern "C" bool wasm_rt_is_initialized(void) {
return true;
@ -94,15 +94,8 @@ extern "C" uint32_t wasm_rt_grow_memory(wasm_rt_memory_t *memory, uint32_t pages
return -1;
}
if (!mkxp_retro::sandbox.has_value()) {
assert(new_pages <= WASM_MIN_PAGES);
} else if (mkxp_retro::sandbox->_rewinding()) {
if (!mkxp_retro::sandbox->_end_realloc()) {
return -1;
}
} else if (new_pages > WASM_MIN_PAGES) {
mkxp_retro::sandbox->_begin_realloc((size_t)new_size);
return -1; // Arbitrary value that never gets read
if (new_pages > WASM_MIN_PAGES) {
mkxp_retro::log_printf(RETRO_LOG_ERROR, "Sandbox memory growth is not implemented yet");
}
#ifdef MKXPZ_BIG_ENDIAN

View file

@ -57,25 +57,25 @@ namespace mkxp_sandbox {
window = new Window(viewport);
SANDBOX_AWAIT(rb_iv_set, self, "viewport", viewport_obj);
SANDBOX_AWAIT(set_private_data, self, window);
set_private_data(self, window);
window->initDynAttribs();
SANDBOX_AWAIT_AND_SET(id, rb_intern, "Bitmap");
SANDBOX_AWAIT_AND_SET(klass, rb_const_get, sb()->rb_cObject(), id);
SANDBOX_AWAIT_AND_SET(obj, rb_obj_alloc, klass);
SANDBOX_AWAIT(set_private_data, obj, window->getWindowskin());
set_private_data(obj, window->getWindowskin());
SANDBOX_AWAIT(rb_iv_set, self, "windowskin", obj);
SANDBOX_AWAIT_AND_SET(id, rb_intern, "Bitmap");
SANDBOX_AWAIT_AND_SET(klass, rb_const_get, sb()->rb_cObject(), id);
SANDBOX_AWAIT_AND_SET(obj, rb_obj_alloc, klass);
SANDBOX_AWAIT(set_private_data, obj, window->getContents());
set_private_data(obj, window->getContents());
SANDBOX_AWAIT(rb_iv_set, self, "contents", obj);
SANDBOX_AWAIT_AND_SET(id, rb_intern, "Rect");
SANDBOX_AWAIT_AND_SET(klass, rb_const_get, sb()->rb_cObject(), id);
SANDBOX_AWAIT_AND_SET(obj, rb_obj_alloc, klass);
SANDBOX_AWAIT(set_private_data, obj, &window->getCursorRect());
set_private_data(obj, &window->getCursorRect());
SANDBOX_AWAIT(rb_iv_set, self, "cursor_rect", obj);
GFX_UNLOCK
@ -416,7 +416,7 @@ namespace mkxp_sandbox {
void operator()() {
BOOST_ASIO_CORO_REENTER (this) {
SANDBOX_AWAIT_AND_SET(window_type, new_rb_data_type, "Window", NULL, dfree, NULL, NULL, 0, 0, 0);
window_type = sb()->rb_data_type("Window", NULL, dfree, NULL, NULL, 0, 0, 0);
SANDBOX_AWAIT_AND_SET(klass, rb_define_class, "Window", sb()->rb_cObject());
SANDBOX_AWAIT(rb_define_alloc_func, klass, alloc);
SANDBOX_AWAIT(rb_define_method, klass, "initialize", (VALUE (*)(ANYARGS))initialize, -1);

View file

@ -41,7 +41,7 @@ MKXP_SANDBOX_API void *mkxp_sandbox_fiber_arg1 = NULL;
/* This function should be called immediately after initializing the sandbox to perform initialization, before calling any other functions. */
MKXP_SANDBOX_API void mkxp_sandbox_init(void) {
void __wasm_call_ctors(void); /* Defined by wasi-libc from the WASI SDK */
void __wasm_call_ctors(void); /* Defined by the LLVM linker */
__wasm_call_ctors();
void async_buf_init(struct __rb_wasm_asyncify_jmp_buf *); /* Defined in wasm/setjmp.c in Ruby source code */

View file

@ -218,7 +218,6 @@ HEADER_START = <<~HEREDOC
struct rb_data_type {
friend struct bindings;
friend struct new_rb_data_type;
rb_data_type();
wasm_ptr_t get() const;
private:
@ -226,6 +225,8 @@ HEADER_START = <<~HEREDOC
rb_data_type(wasm_ptr_t ptr);
};
struct rb_data_type rb_data_type(const char *wrap_struct_name, void (*dmark)(wasm_ptr_t), void (*dfree)(wasm_ptr_t), wasm_size_t (*dsize)(wasm_ptr_t), void (*dcompact)(wasm_ptr_t), wasm_ptr_t parent, wasm_ptr_t data, wasm_size_t flags);
HEREDOC
HEADER_END = <<~HEREDOC
@ -302,84 +303,58 @@ HEREDOC
POSTSCRIPT = <<~HEREDOC
sandbox_malloc::sandbox_malloc(struct binding_base &b) : bind(b) {}
wasm_ptr_t sandbox_malloc::operator()(wasm_size_t size) {
BOOST_ASIO_CORO_REENTER (this) {
for (;;) {
{
wasm_ptr_t buf = bind._sandbox_malloc(size);
if (w2c_#{MODULE_NAME}_asyncify_get_state(&bind.instance()) != 1) return buf;
}
BOOST_ASIO_CORO_YIELD;
}
struct bindings::rb_data_type bindings::rb_data_type(const char *wrap_struct_name, void (*dmark)(wasm_ptr_t), void (*dfree)(wasm_ptr_t), wasm_size_t (*dsize)(wasm_ptr_t), void (*dcompact)(wasm_ptr_t), wasm_ptr_t parent, wasm_ptr_t data, wasm_size_t flags) {
wasm_ptr_t buf;
wasm_ptr_t str;
buf = sandbox_malloc(9 * sizeof(wasm_ptr_t));
if (buf == 0) {
throw SandboxOutOfMemoryException();
}
str = sandbox_malloc(std::strlen(wrap_struct_name) + 1);
if (str == 0) {
sandbox_free(buf);
throw SandboxOutOfMemoryException();
}
return 0;
}
std::strcpy((char *)(**this + str), wrap_struct_name);
((wasm_ptr_t *)(**this + buf))[0] = SERIALIZE_VALUE(str);
new_rb_data_type::new_rb_data_type(struct binding_base &b) : bind(b), buf(0), str(0) {}
struct bindings::rb_data_type new_rb_data_type::operator()(const char *wrap_struct_name, void (*dmark)(wasm_ptr_t), void (*dfree)(wasm_ptr_t), wasm_size_t (*dsize)(wasm_ptr_t), void (*dcompact)(wasm_ptr_t), wasm_ptr_t parent, wasm_ptr_t data, wasm_size_t flags) {
BOOST_ASIO_CORO_REENTER (this) {
for (;;) {
buf = bind._sandbox_malloc(9 * sizeof(wasm_ptr_t));
if (w2c_#{MODULE_NAME}_asyncify_get_state(&bind.instance()) != 1) break;
BOOST_ASIO_CORO_YIELD;
}
if (buf == 0) {
throw SandboxOutOfMemoryException();
}
((wasm_ptr_t *)(**this + buf))[1] = dmark == NULL ? 0 : SERIALIZE_VALUE(wasm_rt_push_funcref(&instance().w2c_T0, wasm_rt_funcref_t {
.func_type = wasm2c_#{MODULE_NAME}_get_func_type(1, 0, #{FUNC_TYPE_TABLE[:ptr]}),
.func = (wasm_rt_function_ptr_t)_sbindgen_call_#{call_type_hash([:void, [:value]])},
.func_tailcallee = {.fn = NULL},
.module_instance = (void *)dmark,
}));
for (;;) {
str = bind._sandbox_malloc(std::strlen(wrap_struct_name) + 1);
if (w2c_#{MODULE_NAME}_asyncify_get_state(&bind.instance()) != 1) break;
BOOST_ASIO_CORO_YIELD;
}
if (str == 0) {
throw SandboxOutOfMemoryException();
}
((wasm_ptr_t *)(**this + buf))[2] = dfree == NULL ? 0 : SERIALIZE_VALUE(wasm_rt_push_funcref(&instance().w2c_T0, wasm_rt_funcref_t {
.func_type = wasm2c_#{MODULE_NAME}_get_func_type(1, 0, #{FUNC_TYPE_TABLE[:ptr]}),
.func = (wasm_rt_function_ptr_t)_sbindgen_call_#{call_type_hash([:void, [:value]])},
.func_tailcallee = {.fn = NULL},
.module_instance = (void *)dfree,
}));
std::strcpy((char *)(*bind + str), wrap_struct_name);
((wasm_ptr_t *)(*bind + buf))[0] = SERIALIZE_VALUE(str);
((wasm_ptr_t *)(**this + buf))[3] = dsize == NULL ? 0 : SERIALIZE_VALUE(wasm_rt_push_funcref(&instance().w2c_T0, wasm_rt_funcref_t {
.func_type = wasm2c_#{MODULE_NAME}_get_func_type(1, 0, #{FUNC_TYPE_TABLE[:ptr]}, #{FUNC_TYPE_TABLE[:size]}),
.func = (wasm_rt_function_ptr_t)_sbindgen_call_#{call_type_hash([:size, [:value]])},
.func_tailcallee = {.fn = NULL},
.module_instance = (void *)dsize,
}));
((wasm_ptr_t *)(*bind + buf))[1] = dmark == NULL ? 0 : SERIALIZE_VALUE(wasm_rt_push_funcref(&bind.instance().w2c_T0, wasm_rt_funcref_t {
.func_type = wasm2c_#{MODULE_NAME}_get_func_type(1, 0, #{FUNC_TYPE_TABLE[:ptr]}),
.func = (wasm_rt_function_ptr_t)_sbindgen_call_#{call_type_hash([:void, [:value]])},
.func_tailcallee = {.fn = NULL},
.module_instance = (void *)dmark,
}));
((wasm_ptr_t *)(**this + buf))[4] = dcompact == NULL ? 0 : SERIALIZE_VALUE(wasm_rt_push_funcref(&instance().w2c_T0, wasm_rt_funcref_t {
.func_type = wasm2c_#{MODULE_NAME}_get_func_type(1, 0, #{FUNC_TYPE_TABLE[:ptr]}),
.func = (wasm_rt_function_ptr_t)_sbindgen_call_#{call_type_hash([:void, [:value]])},
.func_tailcallee = {.fn = NULL},
.module_instance = (void *)dcompact,
}));
((wasm_ptr_t *)(*bind + buf))[2] = dfree == NULL ? 0 : SERIALIZE_VALUE(wasm_rt_push_funcref(&bind.instance().w2c_T0, wasm_rt_funcref_t {
.func_type = wasm2c_#{MODULE_NAME}_get_func_type(1, 0, #{FUNC_TYPE_TABLE[:ptr]}),
.func = (wasm_rt_function_ptr_t)_sbindgen_call_#{call_type_hash([:void, [:value]])},
.func_tailcallee = {.fn = NULL},
.module_instance = (void *)dfree,
}));
((wasm_ptr_t *)(*bind + buf))[3] = dsize == NULL ? 0 : SERIALIZE_VALUE(wasm_rt_push_funcref(&bind.instance().w2c_T0, wasm_rt_funcref_t {
.func_type = wasm2c_#{MODULE_NAME}_get_func_type(1, 0, #{FUNC_TYPE_TABLE[:ptr]}, #{FUNC_TYPE_TABLE[:size]}),
.func = (wasm_rt_function_ptr_t)_sbindgen_call_#{call_type_hash([:size, [:value]])},
.func_tailcallee = {.fn = NULL},
.module_instance = (void *)dsize,
}));
((wasm_ptr_t *)(*bind + buf))[4] = dcompact == NULL ? 0 : SERIALIZE_VALUE(wasm_rt_push_funcref(&bind.instance().w2c_T0, wasm_rt_funcref_t {
.func_type = wasm2c_#{MODULE_NAME}_get_func_type(1, 0, #{FUNC_TYPE_TABLE[:ptr]}),
.func = (wasm_rt_function_ptr_t)_sbindgen_call_#{call_type_hash([:void, [:value]])},
.func_tailcallee = {.fn = NULL},
.module_instance = (void *)dcompact,
}));
((wasm_ptr_t *)(*bind + buf))[5] = 0;
((wasm_ptr_t *)(*bind + buf))[6] = SERIALIZE_VALUE(parent);
((wasm_ptr_t *)(*bind + buf))[7] = SERIALIZE_VALUE(data);
((wasm_ptr_t *)(*bind + buf))[8] = SERIALIZE_VALUE(flags);
}
((wasm_ptr_t *)(**this + buf))[5] = 0;
((wasm_ptr_t *)(**this + buf))[6] = SERIALIZE_VALUE(parent);
((wasm_ptr_t *)(**this + buf))[7] = SERIALIZE_VALUE(data);
((wasm_ptr_t *)(**this + buf))[8] = SERIALIZE_VALUE(flags);
return buf;
}
new_rb_data_type::~new_rb_data_type() {
if (str == 0 && buf != 0) bind.sandbox_free(buf);
}
//////////////////////////////////////////////////////////////////////////////
@ -519,11 +494,7 @@ File.readlines('tags', chomp: true).each do |line|
transformed_args.add(i)
elsif !handler[:buf_size].nil?
coroutine_initializer += <<~HEREDOC
for (;;) {
f#{i} = bind._sandbox_malloc(#{handler[:buf_size].gsub('PREV_ARG', "a#{i - 1}").gsub('ARG', "a#{i}")});
if (w2c_#{MODULE_NAME}_asyncify_get_state(&bind.instance()) != 1) break;
BOOST_ASIO_CORO_YIELD;
}
f#{i} = bind.sandbox_malloc(#{handler[:buf_size].gsub('PREV_ARG', "a#{i - 1}").gsub('ARG', "a#{i}")});
if (f#{i} == 0) throw SandboxOutOfMemoryException();
HEREDOC
coroutine_initializer += handler[:serialize].gsub('PREV_ARG', "a#{i - 1}").gsub('ARG', "a#{i}").gsub('BUF', "f#{i}")
@ -542,11 +513,7 @@ File.readlines('tags', chomp: true).each do |line|
case func_name
when 'rb_funcall'
coroutine_initializer += <<~HEREDOC
for (;;) {
f#{args.length - 1} = bind._sandbox_malloc(a#{args.length - 2} * sizeof(VALUE));
if (w2c_#{MODULE_NAME}_asyncify_get_state(&bind.instance()) != 1) break;
BOOST_ASIO_CORO_YIELD;
}
f#{args.length - 1} = bind.sandbox_malloc(a#{args.length - 2} * sizeof(VALUE));
if (f#{args.length - 1} == 0) throw SandboxOutOfMemoryException();
std::va_list a;
va_start(a, a#{args.length - 2});
@ -566,11 +533,7 @@ File.readlines('tags', chomp: true).each do |line|
n = 0;
do ++n; while (va_arg(b, VALUE));
va_end(b);
for (;;) {
f#{args.length - 1} = bind._sandbox_malloc(n * sizeof(VALUE));
if (w2c_#{MODULE_NAME}_asyncify_get_state(&bind.instance()) != 1) break;
BOOST_ASIO_CORO_YIELD;
}
f#{args.length - 1} = bind.sandbox_malloc(n * sizeof(VALUE));
if (f#{args.length - 1} == 0) {
va_end(a);
throw SandboxOutOfMemoryException();
@ -654,32 +617,7 @@ File.open('mkxp-sandbox-bindgen.h', 'w') do |file|
for global_name in globals
file.write(" inline VALUE #{global_name}() const noexcept { return *(VALUE *)(**this + instance().w2c_#{global_name}); }\n")
end
file.write(" };\n\n")
declaration = <<~HEREDOC
struct sandbox_malloc : boost::asio::coroutine {
friend struct bindings::stack_frame_guard<struct sandbox_malloc>;
BOOST_TYPE_INDEX_REGISTER_CLASS
wasm_ptr_t operator()(wasm_size_t size);
private:
struct binding_base &bind;
sandbox_malloc(struct binding_base &b);
};
struct new_rb_data_type : boost::asio::coroutine {
friend struct bindings::stack_frame_guard<struct new_rb_data_type>;
BOOST_TYPE_INDEX_REGISTER_CLASS
struct bindings::rb_data_type operator()(const char *wrap_struct_name, void (*dmark)(wasm_ptr_t), void (*dfree)(wasm_ptr_t), wasm_size_t (*dsize)(wasm_ptr_t), void (*dcompact)(wasm_ptr_t), wasm_ptr_t parent, wasm_ptr_t data, wasm_size_t flags);
~new_rb_data_type();
private:
struct binding_base &bind;
new_rb_data_type(struct binding_base &b);
wasm_ptr_t buf;
wasm_ptr_t str;
};
HEREDOC
for line in declaration.split("\n")
file.write(" #{line}".rstrip + "\n")
end
file.write(" };")
for declaration in declarations
file.write("\n\n" + declaration.split("\n").map { |line| " #{line}" }.join("\n").rstrip)
end

View file

@ -115,8 +115,6 @@ if is_libretro
'-DSHARED_FLUID',
'-D_FILE_OFFSET_BITS=64',
'-DMPG123_NO_LARGENAME',
'-DPGL_PREFIX_TYPES',
'-DPGL_PREFIX_GLSL',
'-DGL_GLES_PROTOTYPES=0',
]
@ -646,6 +644,7 @@ if is_libretro
'src/filesystem/filesystem.cpp',
'src/input/input-retro.cpp',
'binding-sandbox/binding-base.cpp',
'binding-sandbox/binding-util.cpp',
'binding-sandbox/sandbox.cpp',
'binding-sandbox/wasi.cpp',
'binding-sandbox/wasm-rt.cpp',

View file

@ -257,7 +257,7 @@ static bool init_sandbox() {
return std::calloc(1, sizeof(long));
},
.fread = [](void *buf, int count, void *handle) {
assert(*(long *)handle + count < mkxp_gmgsx_sf2_len);
assert((size_t)(*(long *)handle + count) < mkxp_gmgsx_sf2_len);
std::memcpy(buf, mkxp_gmgsx_sf2 + *(long *)handle, count);
*(long *)handle += count;
return (int)FLUID_OK;