remove fixed-size argument stacks and reliance on argument ids
parent
9e82dc0d2f
commit
4154944726
|
@ -846,8 +846,8 @@ struct LIBCUBESCRIPT_EXPORT stacked_value: any_value {
|
|||
bool pop();
|
||||
|
||||
private:
|
||||
state &p_state;
|
||||
alias *p_a;
|
||||
ident_stack p_stack;
|
||||
bool p_pushed;
|
||||
};
|
||||
|
||||
|
|
|
@ -157,7 +157,7 @@ void alias_impl::set_arg(thread_state &ts, any_value &v) {
|
|||
p_val = std::move(v);
|
||||
clean_code();
|
||||
} else {
|
||||
push_arg(v, ts.callstack->argstack[get_index()], false);
|
||||
push_arg(v, ts.idstack.emplace_back(*ts.pstate), false);
|
||||
ts.callstack->usedargs[get_index()] = true;
|
||||
}
|
||||
}
|
||||
|
@ -196,6 +196,18 @@ command_impl::command_impl(
|
|||
p_cargs{args}, p_cb_cftv{std::move(f)}, p_numargs{nargs}
|
||||
{}
|
||||
|
||||
void command_impl::call(state &cs, std::span<any_value> args, any_value &ret) {
|
||||
auto &ts = *cs.thread_pointer();
|
||||
auto idstsz = ts.idstack.size();
|
||||
try {
|
||||
p_cb_cftv(cs, args, ret);
|
||||
} catch (...) {
|
||||
ts.idstack.resize(idstsz, ident_stack{cs});
|
||||
throw;
|
||||
}
|
||||
ts.idstack.resize(idstsz, ident_stack{cs});
|
||||
}
|
||||
|
||||
bool ident_is_used_arg(ident *id, thread_state &ts) {
|
||||
if (!ts.callstack) {
|
||||
return true;
|
||||
|
|
|
@ -19,7 +19,6 @@ enum {
|
|||
struct ident_link {
|
||||
ident *id;
|
||||
ident_link *next;
|
||||
ident_stack *argstack;
|
||||
std::bitset<MAX_ARGUMENTS> usedargs;
|
||||
};
|
||||
|
||||
|
@ -110,9 +109,7 @@ struct command_impl: ident_impl, command {
|
|||
string_ref name, string_ref args, int numargs, command_func func
|
||||
);
|
||||
|
||||
void call(state &cs, std::span<any_value> args, any_value &ret) {
|
||||
p_cb_cftv(cs, args, ret);
|
||||
}
|
||||
void call(state &cs, std::span<any_value> args, any_value &ret);
|
||||
|
||||
string_ref p_cargs;
|
||||
command_func p_cb_cftv;
|
||||
|
|
|
@ -28,30 +28,6 @@ inline void call_with_cleanup(F1 &&dof, F2 &&clf) {
|
|||
dof();
|
||||
}
|
||||
|
||||
/* a simple static array with elements constructed using ctor args */
|
||||
|
||||
template<typename T, std::size_t N>
|
||||
struct valarray {
|
||||
template<typename ...A>
|
||||
valarray(A &&...args) {
|
||||
for (std::size_t i = 0; i < N; ++i) {
|
||||
new (&stor[i]) T{std::forward<A>(args)...};
|
||||
}
|
||||
}
|
||||
|
||||
~valarray() {
|
||||
for (std::size_t i = 0; i < N; ++i) {
|
||||
std::launder(reinterpret_cast<T *>(&stor[i]))->~T();
|
||||
}
|
||||
}
|
||||
|
||||
T &operator[](std::size_t i) {
|
||||
return *std::launder(reinterpret_cast<T *>(&stor[i]));
|
||||
}
|
||||
|
||||
std::aligned_storage_t<sizeof(T), alignof(T)> stor[N];
|
||||
};
|
||||
|
||||
/* a value buffer */
|
||||
|
||||
template<typename T>
|
||||
|
|
|
@ -5,9 +5,10 @@
|
|||
namespace cubescript {
|
||||
|
||||
thread_state::thread_state(internal_state *cs):
|
||||
vmstack{cs}, errbuf{cs}
|
||||
vmstack{cs}, idstack{cs}, errbuf{cs}
|
||||
{
|
||||
vmstack.reserve(32);
|
||||
idstack.reserve(MAX_ARGUMENTS);
|
||||
}
|
||||
|
||||
hook_func thread_state::set_hook(hook_func f) {
|
||||
|
|
|
@ -21,8 +21,10 @@ struct thread_state {
|
|||
state *pstate{};
|
||||
/* current codegen state for diagnostics */
|
||||
codegen_state *cstate{};
|
||||
/* value stack for VM */
|
||||
/* VM stack */
|
||||
valbuf<any_value> vmstack;
|
||||
/* alias stack */
|
||||
valbuf<ident_stack> idstack;
|
||||
/* per-thread storage buffer for error messages */
|
||||
charbuf errbuf;
|
||||
/* we can attach a hook to vm events */
|
||||
|
|
|
@ -411,7 +411,7 @@ bool any_value::get_bool() const {
|
|||
/* stacked value for easy stack management */
|
||||
|
||||
stacked_value::stacked_value(state &cs, ident *id):
|
||||
any_value(cs), p_a(nullptr), p_stack{cs}, p_pushed(false)
|
||||
any_value{cs}, p_state{cs}, p_a{nullptr}, p_pushed{false}
|
||||
{
|
||||
set_alias(id);
|
||||
}
|
||||
|
@ -451,8 +451,11 @@ bool stacked_value::push() {
|
|||
if (!p_a) {
|
||||
return false;
|
||||
}
|
||||
auto &ts = *p_state.thread_pointer();
|
||||
if (!p_pushed) {
|
||||
static_cast<alias_impl *>(p_a)->push_arg(*this, p_stack);
|
||||
static_cast<alias_impl *>(p_a)->push_arg(
|
||||
*this, ts.idstack.emplace_back(p_state)
|
||||
);
|
||||
p_pushed = true;
|
||||
} else {
|
||||
static_cast<alias_impl *>(p_a)->p_val = std::move(
|
||||
|
|
27
src/cs_vm.cc
27
src/cs_vm.cc
|
@ -205,11 +205,11 @@ void exec_alias(
|
|||
integer_var *anargs = static_cast<integer_var *>(
|
||||
ts.istate->identmap[ID_IDX_NUMARGS]
|
||||
);
|
||||
valarray<ident_stack, MAX_ARGUMENTS> argstack{*ts.pstate};
|
||||
argset uargs{};
|
||||
std::size_t noff = ts.idstack.size();
|
||||
for(std::size_t i = 0; i < callargs; i++) {
|
||||
static_cast<alias_impl *>(ts.istate->identmap[i])->push_arg(
|
||||
args[offset + i], argstack[i], false
|
||||
args[offset + i], ts.idstack.emplace_back(*ts.pstate), false
|
||||
);
|
||||
uargs[i] = true;
|
||||
}
|
||||
|
@ -217,9 +217,7 @@ void exec_alias(
|
|||
anargs->set_value(callargs);
|
||||
int oldflags = ts.pstate->identflags;
|
||||
ts.pstate->identflags |= a->get_flags()&IDENT_FLAG_OVERRIDDEN;
|
||||
ident_link aliaslink = {
|
||||
a, ts.callstack, &argstack[0], uargs
|
||||
};
|
||||
ident_link aliaslink = {a, ts.callstack, uargs};
|
||||
ts.callstack = &aliaslink;
|
||||
std::uint32_t *codep = static_cast<
|
||||
alias_impl *
|
||||
|
@ -244,6 +242,7 @@ void exec_alias(
|
|||
amask[callargs] = false;
|
||||
}
|
||||
}
|
||||
ts.idstack.resize(noff, ident_stack{*ts.pstate});
|
||||
force_arg(result, op & BC_INST_RET_MASK);
|
||||
anargs->set_value(integer_type(oldargs));
|
||||
nargs = offset - skip;
|
||||
|
@ -513,9 +512,12 @@ std::uint32_t *vm_exec(
|
|||
case BC_INST_LOCAL: {
|
||||
std::size_t numlocals = op >> 8;
|
||||
std::size_t offset = args.size() - numlocals;
|
||||
valarray<ident_stack, MAX_ARGUMENTS> locals{cs};
|
||||
std::size_t idstsz = ts.idstack.size();
|
||||
for (std::size_t i = 0; i < numlocals; ++i) {
|
||||
push_alias(cs, args[offset + i].get_ident(), locals[i]);
|
||||
push_alias(
|
||||
cs, args[offset + i].get_ident(),
|
||||
ts.idstack.emplace_back(*ts.pstate)
|
||||
);
|
||||
}
|
||||
call_with_cleanup([&]() {
|
||||
code = vm_exec(ts, code, result);
|
||||
|
@ -523,6 +525,7 @@ std::uint32_t *vm_exec(
|
|||
for (std::size_t i = offset; i < args.size(); ++i) {
|
||||
pop_alias(args[i].get_ident());
|
||||
}
|
||||
ts.idstack.resize(idstsz, ident_stack{*ts.pstate});
|
||||
});
|
||||
return code;
|
||||
}
|
||||
|
@ -725,7 +728,7 @@ std::uint32_t *vm_exec(
|
|||
) {
|
||||
any_value nv{cs};
|
||||
static_cast<alias_impl *>(a)->push_arg(
|
||||
nv, ts.callstack->argstack[a->get_index()],
|
||||
nv, ts.idstack.emplace_back(*ts.pstate),
|
||||
false
|
||||
);
|
||||
ts.callstack->usedargs[a->get_index()] = true;
|
||||
|
@ -745,7 +748,7 @@ std::uint32_t *vm_exec(
|
|||
) {
|
||||
any_value nv{cs};
|
||||
static_cast<alias_impl *>(id)->push_arg(
|
||||
nv, ts.callstack->argstack[id->get_index()],
|
||||
nv, ts.idstack.emplace_back(*ts.pstate),
|
||||
false
|
||||
);
|
||||
ts.callstack->usedargs[id->get_index()] = true;
|
||||
|
@ -1131,10 +1134,11 @@ noid:
|
|||
args.resize(offset - 1, any_value{cs});
|
||||
continue;
|
||||
case ID_LOCAL: {
|
||||
valarray<ident_stack, MAX_ARGUMENTS> locals{cs};
|
||||
std::size_t idstsz = ts.idstack.size();
|
||||
for (size_t j = 0; j < size_t(callargs); ++j) {
|
||||
push_alias(
|
||||
cs, args[offset + j].force_ident(cs), locals[j]
|
||||
cs, args[offset + j].force_ident(cs),
|
||||
ts.idstack.emplace_back(*ts.pstate)
|
||||
);
|
||||
}
|
||||
call_with_cleanup([&]() {
|
||||
|
@ -1143,6 +1147,7 @@ noid:
|
|||
for (size_t j = 0; j < size_t(callargs); ++j) {
|
||||
pop_alias(args[offset + j].get_ident());
|
||||
}
|
||||
ts.idstack.resize(idstsz, ident_stack{*ts.pstate});
|
||||
});
|
||||
return code;
|
||||
}
|
||||
|
|
10
src/cs_vm.hh
10
src/cs_vm.hh
|
@ -47,12 +47,12 @@ static void call_with_args(thread_state &ts, F body) {
|
|||
body();
|
||||
return;
|
||||
}
|
||||
valarray<ident_stack, MAX_ARGUMENTS> argstack{*ts.pstate};
|
||||
auto mask = ts.callstack->usedargs;
|
||||
std::size_t noff = ts.idstack.size();
|
||||
for (std::size_t i = 0; mask.any(); ++i) {
|
||||
if (mask[0]) {
|
||||
static_cast<alias_impl *>(ts.istate->identmap[i])->undo_arg(
|
||||
argstack[i]
|
||||
ts.idstack.emplace_back(*ts.pstate)
|
||||
);
|
||||
}
|
||||
mask >>= 1;
|
||||
|
@ -60,7 +60,6 @@ static void call_with_args(thread_state &ts, F body) {
|
|||
ident_link *prevstack = ts.callstack->next;
|
||||
ident_link aliaslink = {
|
||||
ts.callstack->id, ts.callstack,
|
||||
prevstack ? prevstack->argstack : nullptr,
|
||||
prevstack ? prevstack->usedargs : argset{}
|
||||
};
|
||||
if (!prevstack) {
|
||||
|
@ -73,14 +72,15 @@ static void call_with_args(thread_state &ts, F body) {
|
|||
}
|
||||
ts.callstack = aliaslink.next;
|
||||
auto mask2 = ts.callstack->usedargs;
|
||||
for (std::size_t i = 0; mask2.any(); ++i) {
|
||||
for (std::size_t i = 0, nredo = 0; mask2.any(); ++i) {
|
||||
if (mask2[0]) {
|
||||
static_cast<alias_impl *>(ts.istate->identmap[i])->redo_arg(
|
||||
argstack[i]
|
||||
ts.idstack[noff + nredo++]
|
||||
);
|
||||
}
|
||||
mask2 >>= 1;
|
||||
}
|
||||
ts.idstack.resize(noff, ident_stack{*ts.pstate});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue