27#include "wasm/asyncify.h"
28#include "wasm/machine.h"
29#include "wasm/setjmp.h"
31#ifdef RB_WASM_ENABLE_DEBUG_LOG
39# define RB_WASM_DEBUG_LOG_INTERNAL(msg) do { \
40 const uint8_t *msg_start = (uint8_t *)msg; \
41 const uint8_t *msg_end = msg_start; \
42 for (; *msg_end != '\0'; msg_end++) {} \
43 __wasi_ciovec_t iov = {.buf = msg_start, .buf_len = msg_end - msg_start}; \
45 __wasi_fd_write(STDERR_FILENO, &iov, 1, &nwritten); \
47# define RB_WASM_DEBUG_LOG(msg) \
48 RB_WASM_DEBUG_LOG_INTERNAL(__FILE__ ":" STRINGIZE(__LINE__) ": " msg "\n")
50# define RB_WASM_DEBUG_LOG(msg)
53enum rb_wasm_jmp_buf_state {
55 JMP_BUF_STATE_INITIALIZED = 0,
58 JMP_BUF_STATE_CAPTURING = 1,
60 JMP_BUF_STATE_CAPTURED = 2,
63 JMP_BUF_STATE_RETURNING = 3,
69 buf->top = &buf->buffer[0];
70 buf->end = &buf->buffer[WASM_SETJMP_STACK_BUFFER_SIZE];
75void *rb_asyncify_unwind_buf;
81 RB_WASM_DEBUG_LOG(
"enter _rb_wasm_setjmp_internal");
83 case JMP_BUF_STATE_INITIALIZED: {
84 RB_WASM_DEBUG_LOG(
" JMP_BUF_STATE_INITIALIZED");
85 env->state = JMP_BUF_STATE_CAPTURING;
87 env->longjmp_buf_ptr = NULL;
88 _rb_wasm_active_jmpbuf = env;
89 async_buf_init(&env->setjmp_buf);
90 asyncify_start_unwind(&env->setjmp_buf);
93 case JMP_BUF_STATE_CAPTURING: {
94 asyncify_stop_rewind();
95 RB_WASM_DEBUG_LOG(
" JMP_BUF_STATE_CAPTURING");
96 env->state = JMP_BUF_STATE_CAPTURED;
97 _rb_wasm_active_jmpbuf = NULL;
100 case JMP_BUF_STATE_RETURNING: {
101 asyncify_stop_rewind();
102 RB_WASM_DEBUG_LOG(
" JMP_BUF_STATE_RETURNING");
103 env->state = JMP_BUF_STATE_CAPTURED;
104 _rb_wasm_active_jmpbuf = NULL;
108 assert(0 &&
"unexpected state");
116 RB_WASM_DEBUG_LOG(
"enter _rb_wasm_longjmp");
117 assert(env->state == JMP_BUF_STATE_CAPTURED);
119 env->state = JMP_BUF_STATE_RETURNING;
120 env->payload = value;
124 env->longjmp_buf_ptr = &tmp_longjmp_buf;
125 _rb_wasm_active_jmpbuf = env;
126 async_buf_init(env->longjmp_buf_ptr);
127 asyncify_start_unwind(env->longjmp_buf_ptr);
131enum try_catch_phase {
132 TRY_CATCH_PHASE_MAIN = 0,
133 TRY_CATCH_PHASE_RESCUE = 1,
138 rb_wasm_try_catch_func_t try_f,
139 rb_wasm_try_catch_func_t catch_f,
142 try_catch->state = TRY_CATCH_PHASE_MAIN;
143 try_catch->try_f = try_f;
144 try_catch->catch_f = catch_f;
145 try_catch->context = context;
152 extern void *rb_asyncify_unwind_buf;
155 target->state = JMP_BUF_STATE_CAPTURED;
157 switch ((
enum try_catch_phase)try_catch->state) {
158 case TRY_CATCH_PHASE_MAIN:
160 try_catch->try_f(try_catch->context);
162 case TRY_CATCH_PHASE_RESCUE:
163 if (try_catch->catch_f) {
165 try_catch->catch_f(try_catch->context);
172 while (rb_asyncify_unwind_buf && _rb_wasm_active_jmpbuf == target) {
177 asyncify_stop_rewind();
179 _rb_wasm_active_jmpbuf = NULL;
181 target->state = JMP_BUF_STATE_CAPTURED;
183 try_catch->state = TRY_CATCH_PHASE_RESCUE;
184 if (try_catch->catch_f) {
185 try_catch->catch_f(try_catch->context);
193rb_wasm_handle_jmp_unwind(
void)
195 RB_WASM_DEBUG_LOG(
"enter rb_wasm_handle_jmp_unwind");
196 if (!_rb_wasm_active_jmpbuf) {
200 switch (_rb_wasm_active_jmpbuf->state) {
201 case JMP_BUF_STATE_CAPTURING:
202 RB_WASM_DEBUG_LOG(
" JMP_BUF_STATE_CAPTURING");
204 _rb_wasm_active_jmpbuf->dst_buf_top = _rb_wasm_active_jmpbuf->setjmp_buf.top;
206 case JMP_BUF_STATE_RETURNING:
207 RB_WASM_DEBUG_LOG(
" JMP_BUF_STATE_RETURNING");
209 _rb_wasm_active_jmpbuf->setjmp_buf.top = _rb_wasm_active_jmpbuf->dst_buf_top;
212 assert(0 &&
"unexpected state");
214 return &_rb_wasm_active_jmpbuf->setjmp_buf;