move cs thread call stack off real thread call stack

master
Daniel Kolesa 2021-05-14 23:14:48 +02:00
parent 203e0bd5e4
commit 72c3ecedb1
6 changed files with 60 additions and 56 deletions

View File

@ -11,16 +11,14 @@ namespace cubescript {
static typename error::stack_node *save_stack(state &cs) {
auto &ts = state_p{cs}.ts();
builtin_var *dalias = ts.istate->ivar_dbgalias;
auto dval = std::clamp(
auto dval = std::size_t(std::clamp(
dalias->value().get_integer(), integer_type(0), integer_type(1000)
);
));
if (!dval) {
return nullptr;
}
int total = 0, depth = 0;
for (ident_link *l = ts.callstack; l; l = l->next) {
total++;
}
std::size_t depth = 0;
std::size_t total = ts.callstack.size();
if (!total) {
return nullptr;
}
@ -29,21 +27,24 @@ static typename error::stack_node *save_stack(state &cs) {
);
typename error::stack_node *ret = st, *nd = st;
++st;
for (ident_link *l = ts.callstack; l; l = l->next) {
for (std::size_t i = total - 1;; --i) {
auto &lev = ts.callstack[i];
++depth;
if (depth < dval) {
nd->id = l->id;
nd->id = &lev.id;
nd->index = total - depth + 1;
if (!l->next) {
if (i == 0) {
nd->next = nullptr;
} else {
nd->next = st;
nd = st++;
break;
}
nd->next = st;
nd = st++;
} else if (!l->next) {
nd->id = l->id;
} else if (i == 0) {
nd->id = &lev.id;
nd->index = 1;
nd->next = nullptr;
break;
}
}
return ret;

View File

@ -114,10 +114,10 @@ void command_impl::call(
}
bool ident_is_used_arg(ident const *id, thread_state &ts) {
if (!ts.callstack) {
if (ts.callstack.empty()) {
return true;
}
return ts.callstack->usedargs[id->index()];
return ts.callstack.back().usedargs[id->index()];
}
void alias_stack::push(ident_stack &st) {
@ -134,7 +134,7 @@ void alias_stack::set_arg(alias *a, thread_state &ts, any_value &v) {
node->code = bcode_ref{};
} else {
push(ts.idstack.emplace_back());
ts.callstack->usedargs[a->index()] = true;
ts.callstack.back().usedargs[a->index()] = true;
}
node->val_s = std::move(v);
}

View File

@ -43,12 +43,6 @@ struct alias_stack {
void set_alias(alias *a, thread_state &ts, any_value &v);
};
struct ident_link {
ident const *id;
ident_link *next;
std::bitset<MAX_ARGUMENTS> usedargs;
};
struct ident_impl {
ident_impl() = delete;
ident_impl(ident_impl const &) = delete;

View File

@ -5,7 +5,7 @@
namespace cubescript {
thread_state::thread_state(internal_state *cs):
vmstack{cs}, idstack{cs}, astacks{cs}, errbuf{cs}
vmstack{cs}, idstack{cs}, callstack{cs}, astacks{cs}, errbuf{cs}
{
vmstack.reserve(32);
idstack.reserve(MAX_ARGUMENTS);

View File

@ -11,10 +11,15 @@
namespace cubescript {
struct ident_level {
ident &id;
std::bitset<MAX_ARGUMENTS> usedargs{};
ident_level(ident &i): id{i} {};
};
struct thread_state {
using astack_allocator = std_allocator<std::pair<int const, alias_stack>>;
/* thread call stack */
ident_link *callstack{};
/* the shared state pointer */
internal_state *istate{};
/* the public state interface */
@ -23,6 +28,8 @@ struct thread_state {
valbuf<any_value> vmstack;
/* ident stack */
valbuf<ident_stack> idstack;
/* call stack */
valbuf<ident_level> callstack;
/* per-alias stack pointer */
std::unordered_map<
int, alias_stack, std::hash<int>, std::equal_to<int>, astack_allocator

View File

@ -146,21 +146,24 @@ void exec_alias(
any_value cv;
cv.set_integer(integer_type(callargs));
anargs->set_raw_value(*ts.pstate, std::move(cv));
ident_link aliaslink = {a, ts.callstack, uargs};
ts.callstack = &aliaslink;
ts.callstack.emplace_back(*a);
if (!astack.node->code) {
gen_state gs{ts};
gs.gen_main(astack.node->val_s.get_string(*ts.pstate));
astack.node->code = gs.steal_ref();
try {
gen_state gs{ts};
gs.gen_main(astack.node->val_s.get_string(*ts.pstate));
astack.node->code = gs.steal_ref();
} catch (...) {
ts.callstack.pop_back();
throw;
}
}
bcode_ref coderef = astack.node->code;
auto cleanup = [](
auto &tss, auto &alink, std::size_t cargs,
std::size_t nids, auto oflags
auto &tss, std::size_t cargs, std::size_t nids, auto oflags
) {
tss.callstack = alink.next;
auto amask = tss.callstack.back().usedargs;
tss.callstack.pop_back();
tss.ident_flags = oflags;
auto amask = alink.usedargs;
for (std::size_t i = 0; i < cargs; i++) {
tss.get_astack(
static_cast<alias *>(tss.istate->identmap[i])
@ -180,21 +183,21 @@ void exec_alias(
try {
vm_exec(ts, bcode_p{coderef}.get()->raw(), result);
} catch (...) {
cleanup(ts, aliaslink, callargs, noff, oldflags);
cleanup(ts, callargs, noff, oldflags);
anargs->set_raw_value(*ts.pstate, std::move(oldargs));
nargs = offset - skip;
throw;
}
cleanup(ts, aliaslink, callargs, noff, oldflags);
cleanup(ts, callargs, noff, oldflags);
anargs->set_raw_value(*ts.pstate, std::move(oldargs));
nargs = offset - skip;
}
any_value exec_code_with_args(thread_state &ts, bcode_ref const &body) {
if (!ts.callstack) {
if (ts.callstack.empty()) {
return body.call(*ts.pstate);
}
auto mask = ts.callstack->usedargs;
auto mask = ts.callstack.back().usedargs;
std::size_t noff = ts.idstack.size();
for (std::size_t i = 0; mask.any(); ++i) {
if (mask[0]) {
@ -207,23 +210,22 @@ any_value exec_code_with_args(thread_state &ts, bcode_ref const &body) {
}
mask >>= 1;
}
ident_link *prevstack = ts.callstack->next;
ident_link aliaslink = {
ts.callstack->id, ts.callstack,
prevstack ? prevstack->usedargs : argset{}
};
if (!prevstack) {
aliaslink.usedargs.set();
ident_level *prevstack = nullptr;
if (ts.callstack.size() >= 2) {
prevstack = &ts.callstack[ts.callstack.size() - 2];
}
ts.callstack = &aliaslink;
auto cleanup = [](
auto &tss, ident_link *pstack, ident_link &alink, std::size_t offn
) {
auto &lev = ts.callstack.emplace_back(ts.callstack.back().id);
if (!prevstack) {
lev.usedargs.set();
} else {
lev.usedargs = prevstack->usedargs;
}
auto cleanup = [](auto &tss, ident_level *pstack, std::size_t offn) {
auto mask2 = tss.callstack.back().usedargs;
if (pstack) {
pstack->usedargs = alink.usedargs;
pstack->usedargs = mask2;
}
tss.callstack = alink.next;
auto mask2 = tss.callstack->usedargs;
tss.callstack.pop_back();
for (std::size_t i = 0, nredo = 0; mask2.any(); ++i) {
if (mask2[0]) {
tss.get_astack(
@ -237,11 +239,11 @@ any_value exec_code_with_args(thread_state &ts, bcode_ref const &body) {
try {
ret = body.call(*ts.pstate);
} catch (...) {
cleanup(ts, prevstack, aliaslink, noff);
cleanup(ts, prevstack, noff);
ts.idstack.resize(noff);
throw;
}
cleanup(ts, prevstack, aliaslink, noff);
cleanup(ts, prevstack, noff);
ts.idstack.resize(noff);
return ret;
}
@ -554,7 +556,7 @@ std::uint32_t *vm_exec(
);
if (a->is_arg() && !ident_is_used_arg(a, ts)) {
ts.get_astack(a).push(ts.idstack.emplace_back());
ts.callstack->usedargs[a->index()] = true;
ts.callstack.back().usedargs[a->index()] = true;
}
args.emplace_back().set_ident(*a);
continue;
@ -570,7 +572,7 @@ std::uint32_t *vm_exec(
alias *a = static_cast<alias *>(id);
if (a->is_arg() && !ident_is_used_arg(id, ts)) {
ts.get_astack(a).push(ts.idstack.emplace_back());
ts.callstack->usedargs[id->index()] = true;
ts.callstack.back().usedargs[id->index()] = true;
}
arg.set_ident(*id);
continue;