clean up the call stack in a scoped way properly always
parent
e3310ce74f
commit
5674375614
|
@ -2,6 +2,8 @@
|
||||||
#define LIBCUBESCRIPT_CS_UTIL_HH
|
#define LIBCUBESCRIPT_CS_UTIL_HH
|
||||||
|
|
||||||
#include <ostd/string.hh>
|
#include <ostd/string.hh>
|
||||||
|
#include <ostd/utility.hh>
|
||||||
|
#include <ostd/type_traits.hh>
|
||||||
|
|
||||||
namespace cscript {
|
namespace cscript {
|
||||||
|
|
||||||
|
@ -13,6 +15,22 @@ CsFloat cs_parse_float(
|
||||||
ostd::ConstCharRange input, ostd::ConstCharRange *end = nullptr
|
ostd::ConstCharRange input, ostd::ConstCharRange *end = nullptr
|
||||||
);
|
);
|
||||||
|
|
||||||
|
template<typename F>
|
||||||
|
struct CsScopeExit {
|
||||||
|
template<typename FF>
|
||||||
|
CsScopeExit(FF &&f): func(ostd::forward<FF>(f)) {}
|
||||||
|
~CsScopeExit() {
|
||||||
|
func();
|
||||||
|
}
|
||||||
|
ostd::Decay<F> func;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename F1, typename F2>
|
||||||
|
inline void cs_do_and_cleanup(F1 &&dof, F2 &&clf) {
|
||||||
|
CsScopeExit<F2> cleanup(ostd::forward<F2>(clf));
|
||||||
|
dof();
|
||||||
|
}
|
||||||
|
|
||||||
} /* namespace cscript */
|
} /* namespace cscript */
|
||||||
|
|
||||||
#endif /* LIBCUBESCRIPT_CS_UTIL_HH */
|
#endif /* LIBCUBESCRIPT_CS_UTIL_HH */
|
||||||
|
|
61
src/cs_vm.cc
61
src/cs_vm.cc
|
@ -443,25 +443,28 @@ static inline void cs_call_alias(
|
||||||
CsAliasInternal::compile_code(a, cs)
|
CsAliasInternal::compile_code(a, cs)
|
||||||
);
|
);
|
||||||
bcode_incr(codep);
|
bcode_incr(codep);
|
||||||
runcode(cs, codep+1, result);
|
cs_do_and_cleanup([&]() {
|
||||||
bcode_decr(codep);
|
runcode(cs, codep+1, result);
|
||||||
cs.p_callstack = aliaslink.next;
|
}, [&]() {
|
||||||
cs.identflags = oldflags;
|
bcode_decr(codep);
|
||||||
for (int i = 0; i < callargs; i++) {
|
cs.p_callstack = aliaslink.next;
|
||||||
CsAliasInternal::pop_arg(static_cast<CsAlias *>(cs.identmap[i]));
|
cs.identflags = oldflags;
|
||||||
}
|
for (int i = 0; i < callargs; i++) {
|
||||||
int argmask = aliaslink.usedargs & (~0 << callargs);
|
CsAliasInternal::pop_arg(static_cast<CsAlias *>(cs.identmap[i]));
|
||||||
for (; argmask; ++callargs) {
|
|
||||||
if (argmask & (1 << callargs)) {
|
|
||||||
CsAliasInternal::pop_arg(static_cast<CsAlias *>(
|
|
||||||
cs.identmap[callargs])
|
|
||||||
);
|
|
||||||
argmask &= ~(1 << callargs);
|
|
||||||
}
|
}
|
||||||
}
|
int argmask = aliaslink.usedargs & (~0 << callargs);
|
||||||
force_arg(result, op & CsCodeRetMask);
|
for (; argmask; ++callargs) {
|
||||||
anargs->set_value(oldargs);
|
if (argmask & (1 << callargs)) {
|
||||||
nargs = offset - skip;
|
CsAliasInternal::pop_arg(static_cast<CsAlias *>(
|
||||||
|
cs.identmap[callargs])
|
||||||
|
);
|
||||||
|
argmask &= ~(1 << callargs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
force_arg(result, op & CsCodeRetMask);
|
||||||
|
anargs->set_value(oldargs);
|
||||||
|
nargs = offset - skip;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr int MaxRunDepth = 255;
|
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) {
|
for (int i = 0; i < numlocals; ++i) {
|
||||||
cs_push_alias(args[offset + i].get_ident(), locals[i]);
|
cs_push_alias(args[offset + i].get_ident(), locals[i]);
|
||||||
}
|
}
|
||||||
code = runcode(cs, code, result);
|
cs_do_and_cleanup([&]() {
|
||||||
for (int i = offset; i < numargs; i++) {
|
code = runcode(cs, code, result);
|
||||||
cs_pop_alias(args[i].get_ident());
|
}, [&]() {
|
||||||
}
|
for (int i = offset; i < numargs; i++) {
|
||||||
|
cs_pop_alias(args[i].get_ident());
|
||||||
|
}
|
||||||
|
});
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1448,10 +1454,13 @@ noid:
|
||||||
args[offset + j]
|
args[offset + j]
|
||||||
), locals[j]);
|
), locals[j]);
|
||||||
}
|
}
|
||||||
code = runcode(cs, code, result);
|
cs_do_and_cleanup([&]() {
|
||||||
for (ostd::Size j = 0; j < ostd::Size(callargs); ++j) {
|
code = runcode(cs, code, result);
|
||||||
cs_pop_alias(args[offset + j].get_ident());
|
}, [&]() {
|
||||||
}
|
for (ostd::Size j = 0; j < ostd::Size(callargs); ++j) {
|
||||||
|
cs_pop_alias(args[offset + j].get_ident());
|
||||||
|
}
|
||||||
|
});
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
case CsIdIvar:
|
case CsIdIvar:
|
||||||
|
|
23
src/cs_vm.hh
23
src/cs_vm.hh
|
@ -8,6 +8,8 @@
|
||||||
#include <ostd/array.hh>
|
#include <ostd/array.hh>
|
||||||
#include <ostd/vector.hh>
|
#include <ostd/vector.hh>
|
||||||
|
|
||||||
|
#include "cs_util.hh"
|
||||||
|
|
||||||
namespace cscript {
|
namespace cscript {
|
||||||
|
|
||||||
static constexpr int MaxArguments = 25;
|
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->id, cs.p_callstack, prevstack->usedargs, prevstack->argstack
|
||||||
};
|
};
|
||||||
cs.p_callstack = &aliaslink;
|
cs.p_callstack = &aliaslink;
|
||||||
body();
|
cs_do_and_cleanup(ostd::move(body), [&]() {
|
||||||
prevstack->usedargs = aliaslink.usedargs;
|
prevstack->usedargs = aliaslink.usedargs;
|
||||||
cs.p_callstack = aliaslink.next;
|
cs.p_callstack = aliaslink.next;
|
||||||
int argmask2 = cs.p_callstack->usedargs;
|
int argmask2 = cs.p_callstack->usedargs;
|
||||||
for (int i = 0; argmask2; argmask2 >>= 1, ++i) {
|
for (int i = 0; argmask2; argmask2 >>= 1, ++i) {
|
||||||
if (argmask2 & 1) {
|
if (argmask2 & 1) {
|
||||||
CsAliasInternal::redo_arg(
|
CsAliasInternal::redo_arg(
|
||||||
static_cast<CsAlias *>(cs.identmap[i]), argstack[i]
|
static_cast<CsAlias *>(cs.identmap[i]), argstack[i]
|
||||||
);
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
CsBytecode *cs_copy_code(CsBytecode *c);
|
CsBytecode *cs_copy_code(CsBytecode *c);
|
||||||
|
|
Loading…
Reference in New Issue