refactor vm scope guard
parent
36fb06425b
commit
8b04bd1488
|
@ -358,14 +358,19 @@ LIBCUBESCRIPT_EXPORT any_value command::call(
|
||||||
auto nargs = args.size();
|
auto nargs = args.size();
|
||||||
auto &ts = state_p{cs}.ts();
|
auto &ts = state_p{cs}.ts();
|
||||||
if (nargs < std::size_t(cimpl.arg_count())) {
|
if (nargs < std::size_t(cimpl.arg_count())) {
|
||||||
stack_guard s{ts}; /* restore after call */
|
|
||||||
auto &targs = ts.vmstack;
|
auto &targs = ts.vmstack;
|
||||||
auto osz = targs.size();
|
auto osz = targs.size();
|
||||||
targs.resize(osz + cimpl.arg_count());
|
targs.resize(osz + cimpl.arg_count());
|
||||||
for (std::size_t i = 0; i < nargs; ++i) {
|
try {
|
||||||
targs[osz + i] = args[i];
|
for (std::size_t i = 0; i < nargs; ++i) {
|
||||||
|
targs[osz + i] = args[i];
|
||||||
|
}
|
||||||
|
exec_command(ts, &cimpl, this, &targs[osz], ret, nargs, false);
|
||||||
|
} catch (...) {
|
||||||
|
targs.resize(osz);
|
||||||
|
throw;
|
||||||
}
|
}
|
||||||
exec_command(ts, &cimpl, this, &targs[osz], ret, nargs, false);
|
targs.resize(osz);
|
||||||
} else {
|
} else {
|
||||||
exec_command(ts, &cimpl, this, &args[0], ret, nargs, false);
|
exec_command(ts, &cimpl, this, &args[0], ret, nargs, false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -517,16 +517,19 @@ LIBCUBESCRIPT_EXPORT any_value state::lookup_value(std::string_view name) {
|
||||||
return static_cast<builtin_var *>(id)->value();
|
return static_cast<builtin_var *>(id)->value();
|
||||||
case ident_type::COMMAND: {
|
case ident_type::COMMAND: {
|
||||||
any_value val{};
|
any_value val{};
|
||||||
/* make sure value stack gets restored */
|
|
||||||
stack_guard s{*p_tstate};
|
|
||||||
auto *cimpl = static_cast<command_impl *>(id);
|
auto *cimpl = static_cast<command_impl *>(id);
|
||||||
auto &args = p_tstate->vmstack;
|
auto &args = p_tstate->vmstack;
|
||||||
auto osz = args.size();
|
auto osz = args.size();
|
||||||
/* pad with as many empty values as we need */
|
/* pad with as many empty values as we need */
|
||||||
args.resize(osz + cimpl->arg_count());
|
args.resize(osz + cimpl->arg_count());
|
||||||
exec_command(
|
try {
|
||||||
*p_tstate, cimpl, cimpl, &args[osz], val, 0, true
|
exec_command(
|
||||||
);
|
*p_tstate, cimpl, cimpl, &args[osz], val, 0, true
|
||||||
|
);
|
||||||
|
} catch (...) {
|
||||||
|
args.resize(osz);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
args.resize(osz);
|
args.resize(osz);
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
29
src/cs_vm.cc
29
src/cs_vm.cc
|
@ -216,15 +216,6 @@ bool exec_alias(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
call_depth_guard::call_depth_guard(thread_state &ts): tsp(&ts) {
|
|
||||||
if (ts.max_call_depth && (ts.call_depth >= ts.max_call_depth)) {
|
|
||||||
throw error{*ts.pstate, "exceeded recursion limit"};
|
|
||||||
}
|
|
||||||
++ts.call_depth;
|
|
||||||
}
|
|
||||||
|
|
||||||
call_depth_guard::~call_depth_guard() { --tsp->call_depth; }
|
|
||||||
|
|
||||||
static inline alias *get_lookup_id(
|
static inline alias *get_lookup_id(
|
||||||
thread_state &ts, std::uint32_t op, alias_stack *&ast
|
thread_state &ts, std::uint32_t op, alias_stack *&ast
|
||||||
) {
|
) {
|
||||||
|
@ -247,13 +238,29 @@ static inline alias *get_lookup_id(
|
||||||
return static_cast<alias *>(id);
|
return static_cast<alias *>(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct vm_guard {
|
||||||
|
vm_guard(thread_state &s): ts{s}, oldtop{s.vmstack.size()} {
|
||||||
|
if (s.max_call_depth && (s.call_depth >= s.max_call_depth)) {
|
||||||
|
throw error{*s.pstate, "exceeded recursion limit"};
|
||||||
|
}
|
||||||
|
++s.call_depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
~vm_guard() {
|
||||||
|
--ts.call_depth;
|
||||||
|
ts.vmstack.resize(oldtop);
|
||||||
|
}
|
||||||
|
|
||||||
|
thread_state &ts;
|
||||||
|
std::size_t oldtop;
|
||||||
|
};
|
||||||
|
|
||||||
std::uint32_t *vm_exec(
|
std::uint32_t *vm_exec(
|
||||||
thread_state &ts, std::uint32_t *code, any_value &result
|
thread_state &ts, std::uint32_t *code, any_value &result
|
||||||
) {
|
) {
|
||||||
result.set_none();
|
result.set_none();
|
||||||
auto &cs = *ts.pstate;
|
auto &cs = *ts.pstate;
|
||||||
call_depth_guard level{ts}; /* incr and decr on scope exit */
|
vm_guard scope{ts}; /* keep track of recursion depth + manage stack */
|
||||||
stack_guard guard{ts}; /* resize back to original */
|
|
||||||
auto &args = ts.vmstack;
|
auto &args = ts.vmstack;
|
||||||
auto &chook = cs.call_hook();
|
auto &chook = cs.call_hook();
|
||||||
if (chook) {
|
if (chook) {
|
||||||
|
|
27
src/cs_vm.hh
27
src/cs_vm.hh
|
@ -17,33 +17,6 @@ struct break_exception {
|
||||||
struct continue_exception {
|
struct continue_exception {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct call_depth_guard {
|
|
||||||
call_depth_guard() = delete;
|
|
||||||
call_depth_guard(thread_state &ts);
|
|
||||||
call_depth_guard(call_depth_guard const &) = delete;
|
|
||||||
call_depth_guard(call_depth_guard &&) = delete;
|
|
||||||
~call_depth_guard();
|
|
||||||
|
|
||||||
thread_state *tsp;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct stack_guard {
|
|
||||||
thread_state *tsp;
|
|
||||||
std::size_t oldtop;
|
|
||||||
|
|
||||||
stack_guard() = delete;
|
|
||||||
stack_guard(thread_state &ts):
|
|
||||||
tsp{&ts}, oldtop{ts.vmstack.size()}
|
|
||||||
{}
|
|
||||||
|
|
||||||
~stack_guard() {
|
|
||||||
tsp->vmstack.resize(oldtop);
|
|
||||||
}
|
|
||||||
|
|
||||||
stack_guard(stack_guard const &) = delete;
|
|
||||||
stack_guard(stack_guard &&) = delete;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename F, typename ...A>
|
template<typename F, typename ...A>
|
||||||
static void call_with_args(thread_state &ts, F body, A &&...args) {
|
static void call_with_args(thread_state &ts, F body, A &&...args) {
|
||||||
if (!ts.callstack) {
|
if (!ts.callstack) {
|
||||||
|
|
Loading…
Reference in New Issue