diff --git a/src/cs_util.hh b/src/cs_util.hh index c00345c..8dbe4ee 100644 --- a/src/cs_util.hh +++ b/src/cs_util.hh @@ -2,6 +2,8 @@ #define LIBCUBESCRIPT_CS_UTIL_HH #include +#include +#include namespace cscript { @@ -13,6 +15,22 @@ CsFloat cs_parse_float( ostd::ConstCharRange input, ostd::ConstCharRange *end = nullptr ); +template +struct CsScopeExit { + template + CsScopeExit(FF &&f): func(ostd::forward(f)) {} + ~CsScopeExit() { + func(); + } + ostd::Decay func; +}; + +template +inline void cs_do_and_cleanup(F1 &&dof, F2 &&clf) { + CsScopeExit cleanup(ostd::forward(clf)); + dof(); +} + } /* namespace cscript */ #endif /* LIBCUBESCRIPT_CS_UTIL_HH */ diff --git a/src/cs_vm.cc b/src/cs_vm.cc index be4741e..9bbfbcd 100644 --- a/src/cs_vm.cc +++ b/src/cs_vm.cc @@ -443,25 +443,28 @@ static inline void cs_call_alias( CsAliasInternal::compile_code(a, cs) ); bcode_incr(codep); - runcode(cs, codep+1, result); - bcode_decr(codep); - cs.p_callstack = aliaslink.next; - cs.identflags = oldflags; - for (int i = 0; i < callargs; i++) { - CsAliasInternal::pop_arg(static_cast(cs.identmap[i])); - } - int argmask = aliaslink.usedargs & (~0 << callargs); - for (; argmask; ++callargs) { - if (argmask & (1 << callargs)) { - CsAliasInternal::pop_arg(static_cast( - cs.identmap[callargs]) - ); - argmask &= ~(1 << callargs); + cs_do_and_cleanup([&]() { + runcode(cs, codep+1, result); + }, [&]() { + bcode_decr(codep); + cs.p_callstack = aliaslink.next; + cs.identflags = oldflags; + for (int i = 0; i < callargs; i++) { + CsAliasInternal::pop_arg(static_cast(cs.identmap[i])); } - } - force_arg(result, op & CsCodeRetMask); - anargs->set_value(oldargs); - nargs = offset - skip; + int argmask = aliaslink.usedargs & (~0 << callargs); + for (; argmask; ++callargs) { + if (argmask & (1 << callargs)) { + CsAliasInternal::pop_arg(static_cast( + cs.identmap[callargs]) + ); + argmask &= ~(1 << callargs); + } + } + force_arg(result, op & CsCodeRetMask); + anargs->set_value(oldargs); + nargs = offset - skip; + }); } static constexpr int MaxRunDepth = 255; @@ -631,10 +634,13 @@ static ostd::Uint32 *runcode(CsState &cs, ostd::Uint32 *code, CsValue &result) { for (int i = 0; i < numlocals; ++i) { cs_push_alias(args[offset + i].get_ident(), locals[i]); } - code = runcode(cs, code, result); - for (int i = offset; i < numargs; i++) { - cs_pop_alias(args[i].get_ident()); - } + cs_do_and_cleanup([&]() { + code = runcode(cs, code, result); + }, [&]() { + for (int i = offset; i < numargs; i++) { + cs_pop_alias(args[i].get_ident()); + } + }); goto exit; } @@ -1448,10 +1454,13 @@ noid: args[offset + j] ), locals[j]); } - code = runcode(cs, code, result); - for (ostd::Size j = 0; j < ostd::Size(callargs); ++j) { - cs_pop_alias(args[offset + j].get_ident()); - } + cs_do_and_cleanup([&]() { + code = runcode(cs, code, result); + }, [&]() { + for (ostd::Size j = 0; j < ostd::Size(callargs); ++j) { + cs_pop_alias(args[offset + j].get_ident()); + } + }); goto exit; } case CsIdIvar: diff --git a/src/cs_vm.hh b/src/cs_vm.hh index 154d077..9a1c54f 100644 --- a/src/cs_vm.hh +++ b/src/cs_vm.hh @@ -8,6 +8,8 @@ #include #include +#include "cs_util.hh" + namespace cscript { static constexpr int MaxArguments = 25; @@ -328,17 +330,18 @@ static void cs_do_args(CsState &cs, F body) { cs.p_callstack->id, cs.p_callstack, prevstack->usedargs, prevstack->argstack }; cs.p_callstack = &aliaslink; - body(); - prevstack->usedargs = aliaslink.usedargs; - cs.p_callstack = aliaslink.next; - int argmask2 = cs.p_callstack->usedargs; - for (int i = 0; argmask2; argmask2 >>= 1, ++i) { - if (argmask2 & 1) { - CsAliasInternal::redo_arg( - static_cast(cs.identmap[i]), argstack[i] - ); + cs_do_and_cleanup(ostd::move(body), [&]() { + prevstack->usedargs = aliaslink.usedargs; + cs.p_callstack = aliaslink.next; + int argmask2 = cs.p_callstack->usedargs; + for (int i = 0; argmask2; argmask2 >>= 1, ++i) { + if (argmask2 & 1) { + CsAliasInternal::redo_arg( + static_cast(cs.identmap[i]), argstack[i] + ); + } } - } + }); } CsBytecode *cs_copy_code(CsBytecode *c);