summaryrefslogtreecommitdiffhomepage
path: root/src/vm.c
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2021-04-19 22:34:20 +0900
committerGitHub <[email protected]>2021-04-19 22:34:20 +0900
commitff366b65ebc866a6287002ece5121f6f25321e26 (patch)
treee754c81cdf798dc2b8ead74192154bc30a918e9f /src/vm.c
parent9d362f2c2732b15341f76d2d51bbd946b28e5974 (diff)
parent891e852286dabdc2dfda70b00d5325546a939a62 (diff)
downloadmruby-ff366b65ebc866a6287002ece5121f6f25321e26.tar.gz
mruby-ff366b65ebc866a6287002ece5121f6f25321e26.zip
Merge pull request #5415 from dearblue/unwind-mrb_protect
Introducing the `mrb_protect_raw()` API function
Diffstat (limited to 'src/vm.c')
-rw-r--r--src/vm.c43
1 files changed, 43 insertions, 0 deletions
diff --git a/src/vm.c b/src/vm.c
index d9a544714..0665634ed 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -306,6 +306,49 @@ cipop(mrb_state *mrb)
return c->ci;
}
+MRB_API mrb_value
+mrb_protect_raw(mrb_state *mrb, mrb_protect_raw_func *body, void *userdata, mrb_bool *error)
+{
+ struct mrb_jmpbuf *prev_jmp = mrb->jmp;
+ struct mrb_jmpbuf c_jmp;
+ mrb_value result = mrb_nil_value();
+ int ai = mrb_gc_arena_save(mrb);
+ const struct mrb_context *c = mrb->c;
+ int ci_index = c->ci - c->cibase;
+
+ if (error) { *error = FALSE; }
+
+ MRB_TRY(&c_jmp) {
+ mrb->jmp = &c_jmp;
+ result = body(mrb, userdata);
+ mrb->jmp = prev_jmp;
+ }
+ MRB_CATCH(&c_jmp) {
+ mrb->jmp = prev_jmp;
+ result = mrb_obj_value(mrb->exc);
+ mrb->exc = NULL;
+ if (error) { *error = TRUE; }
+ if (mrb->c == c) {
+ while (c->ci - c->cibase > ci_index) {
+ cipop(mrb);
+ }
+ }
+ else {
+ // It was probably switched by mrb_fiber_resume().
+ // Simply destroy all successive CI_ACC_DIRECTs once the fiber has been switched.
+ c = mrb->c;
+ while (c->ci > c->cibase && c->ci->acc == CI_ACC_DIRECT) {
+ cipop(mrb);
+ }
+ }
+ }
+ MRB_END_EXC(&c_jmp);
+
+ mrb_gc_arena_restore(mrb, ai);
+ mrb_gc_protect(mrb, result);
+ return result;
+}
+
void mrb_exc_set(mrb_state *mrb, mrb_value exc);
static mrb_value mrb_run(mrb_state *mrb, const struct RProc* proc, mrb_value self);