[wasm] gc.c: scan wasm locals and c stack to mark living objects

WebAssembly has function local infinite registers and stack values, but
there is no way to scan the values in a call stack for now.
This implementation uses Asyncify to spilling out wasm locals into
linear memory.
This commit is contained in:
Yuta Saito 2022-01-15 23:59:37 +09:00
Родитель e7fb1fa041
Коммит bf1c4d254b
1 изменённых файлов: 40 добавлений и 21 удалений

61
gc.c
Просмотреть файл

@ -30,6 +30,7 @@
#if defined(__wasm__) && !defined(__EMSCRIPTEN__)
# include "wasm/setjmp.h"
# include "wasm/machine.h"
#else
# include <setjmp.h>
#endif
@ -6504,7 +6505,45 @@ mark_const_tbl(rb_objspace_t *objspace, struct rb_id_table *tbl)
static void each_stack_location(rb_objspace_t *objspace, const rb_execution_context_t *ec,
const VALUE *stack_start, const VALUE *stack_end, void (*cb)(rb_objspace_t *, VALUE));
#ifndef __EMSCRIPTEN__
#if defined(__wasm__)
static VALUE *rb_stack_range_tmp[2];
static void
rb_mark_locations(void *begin, void *end)
{
rb_stack_range_tmp[0] = begin;
rb_stack_range_tmp[1] = end;
}
# if defined(__EMSCRIPTEN__)
static void
mark_current_machine_context(rb_objspace_t *objspace, rb_execution_context_t *ec)
{
emscripten_scan_stack(rb_mark_locations);
each_stack_location(objspace, ec, rb_stack_range_tmp[0], rb_stack_range_tmp[1], gc_mark_maybe);
emscripten_scan_registers(rb_mark_locations);
each_stack_location(objspace, ec, rb_stack_range_tmp[0], rb_stack_range_tmp[1], gc_mark_maybe);
}
# else // use Asyncify version
static void
mark_current_machine_context(rb_objspace_t *objspace, rb_execution_context_t *ec)
{
rb_wasm_scan_stack(rb_mark_locations);
each_stack_location(objspace, ec, rb_stack_range_tmp[0], rb_stack_range_tmp[1], gc_mark_maybe);
rb_wasm_scan_locals(rb_mark_locations);
each_stack_location(objspace, ec, rb_stack_range_tmp[0], rb_stack_range_tmp[1], gc_mark_maybe);
}
# endif
#else // !defined(__wasm__)
static void
mark_current_machine_context(rb_objspace_t *objspace, rb_execution_context_t *ec)
{
@ -6529,26 +6568,6 @@ mark_current_machine_context(rb_objspace_t *objspace, rb_execution_context_t *ec
each_stack_location(objspace, ec, stack_start, stack_end, gc_mark_maybe);
}
#else
static VALUE *rb_emscripten_stack_range_tmp[2];
static void
rb_emscripten_mark_locations(void *begin, void *end)
{
rb_emscripten_stack_range_tmp[0] = begin;
rb_emscripten_stack_range_tmp[1] = end;
}
static void
mark_current_machine_context(rb_objspace_t *objspace, rb_execution_context_t *ec)
{
emscripten_scan_stack(rb_emscripten_mark_locations);
each_stack_location(objspace, ec, rb_emscripten_stack_range_tmp[0], rb_emscripten_stack_range_tmp[1], gc_mark_maybe);
emscripten_scan_registers(rb_emscripten_mark_locations);
each_stack_location(objspace, ec, rb_emscripten_stack_range_tmp[0], rb_emscripten_stack_range_tmp[1], gc_mark_maybe);
}
#endif
static void