protect ident lookups

These are global and may be accessed from different states,
so they need to be protected. Everything else generally lives
locally or is initialized upon startup.
This commit is contained in:
Daniel Kolesa 2022-04-20 04:31:24 +02:00
parent 41bae89472
commit f26979a69f
3 changed files with 56 additions and 22 deletions

View file

@ -44,15 +44,41 @@ static void *default_alloc(void *, void *p, size_t, size_t ns) {
return std::realloc(p, ns);
}
ident *internal_state::lookup_ident(std::size_t idx) {
std::lock_guard<std::mutex> l{ident_mtx};
return identmap[idx];
}
ident const *internal_state::lookup_ident(std::size_t idx) const {
std::lock_guard<std::mutex> l{ident_mtx};
return identmap[idx];
}
std::size_t internal_state::get_identnum() const {
std::lock_guard<std::mutex> l{ident_mtx};
return identmap.size();
}
void internal_state::foreach_ident(void (*f)(ident *, void *), void *data) {
auto nids = get_identnum();
for (std::size_t i = 0; i < nids; ++i) {
std::lock_guard<std::mutex> l{ident_mtx};
f(identmap[i], data);
}
}
ident *internal_state::add_ident(ident *id, ident_impl *impl) {
if (!id) {
return nullptr;
}
ident_p{*id}.impl(impl);
{
std::lock_guard<std::mutex> l{ident_mtx};
idents[id->name()] = id;
impl->p_index = int(identmap.size());
identmap.push_back(id);
return identmap.back();
}
}
ident &internal_state::new_ident(state &cs, std::string_view name, int flags) {
@ -72,6 +98,7 @@ ident &internal_state::new_ident(state &cs, std::string_view name, int flags) {
}
ident *internal_state::get_ident(std::string_view name) const {
std::lock_guard<std::mutex> l{ident_mtx};
auto id = idents.find(name);
if (id == idents.end()) {
return nullptr;
@ -315,7 +342,7 @@ LIBCUBESCRIPT_EXPORT void *state::alloc(void *ptr, size_t os, size_t ns) {
}
LIBCUBESCRIPT_EXPORT std::size_t state::ident_count() const {
return p_tstate->istate->identmap.size();
return p_tstate->istate->get_identnum();
}
LIBCUBESCRIPT_EXPORT std::optional<
@ -339,11 +366,11 @@ LIBCUBESCRIPT_EXPORT std::optional<
}
LIBCUBESCRIPT_EXPORT ident &state::get_ident(std::size_t index) {
return *p_tstate->istate->identmap[index];
return *p_tstate->istate->lookup_ident(index);
}
LIBCUBESCRIPT_EXPORT ident const &state::get_ident(std::size_t index) const {
return *p_tstate->istate->identmap[index];
return *p_tstate->istate->lookup_ident(index);
}
LIBCUBESCRIPT_EXPORT void state::clear_override(ident &id) {
@ -374,9 +401,9 @@ LIBCUBESCRIPT_EXPORT void state::clear_override(ident &id) {
}
LIBCUBESCRIPT_EXPORT void state::clear_overrides() {
for (auto &p: p_tstate->istate->idents) {
clear_override(*(p.second));
}
p_tstate->istate->foreach_ident([](ident *id, void *data) {
static_cast<state *>(data)->clear_override(*id);
}, this);
}
inline int var_flags(bool read_only, var_type vtp) {

View file

@ -6,6 +6,7 @@
#include <unordered_map>
#include <string>
#include <vector>
#include <mutex>
#include "cs_bcode.hh"
#include "cs_ident.hh"
@ -49,6 +50,7 @@ struct internal_state {
allocator_type
> idents;
std::vector<ident *, std_allocator<ident *>> identmap;
mutable std::mutex ident_mtx;
string_pool *strman;
empty_block *empty;
@ -69,6 +71,11 @@ struct internal_state {
~internal_state();
ident *lookup_ident(std::size_t idx);
ident const *lookup_ident(std::size_t idx) const;
std::size_t get_identnum() const;
void foreach_ident(void (*f)(ident *, void *), void *data);
ident *add_ident(ident *id, ident_impl *impl);
ident &new_ident(state &cs, std::string_view name, int flags);
ident *get_ident(std::string_view name) const;

View file

@ -133,7 +133,7 @@ any_value exec_alias(
std::size_t noff = ts.idstack.size();
for(std::size_t i = 0; i < callargs; i++) {
auto &ast = ts.get_astack(
static_cast<alias *>(ts.istate->identmap[i])
static_cast<alias *>(ts.istate->lookup_ident(i))
);
auto &st = ts.idstack.emplace_back();
ast.push(st);
@ -167,14 +167,14 @@ any_value exec_alias(
tss.ident_flags = oflags;
for (std::size_t i = 0; i < cargs; i++) {
tss.get_astack(
static_cast<alias *>(tss.istate->identmap[i])
static_cast<alias *>(tss.istate->lookup_ident(i))
).pop();
amask[i] = false;
}
for (; amask.any(); ++cargs) {
if (amask[cargs]) {
tss.get_astack(
static_cast<alias *>(tss.istate->identmap[cargs])
static_cast<alias *>(tss.istate->lookup_ident(cargs))
).pop();
amask[cargs] = false;
}
@ -202,7 +202,7 @@ any_value exec_code_with_args(thread_state &ts, bcode_ref const &body) {
for (std::size_t i = 0; mask.any(); ++i) {
if (mask[0]) {
auto &ast = ts.get_astack(
static_cast<alias *>(ts.istate->identmap[i])
static_cast<alias *>(ts.istate->lookup_ident(i))
);
auto &st = ts.idstack.emplace_back();
st.next = ast.node;
@ -229,7 +229,7 @@ any_value exec_code_with_args(thread_state &ts, bcode_ref const &body) {
for (std::size_t i = 0, nredo = 0; mask2.any(); ++i) {
if (mask2[0]) {
tss.get_astack(
static_cast<alias *>(tss.istate->identmap[i])
static_cast<alias *>(tss.istate->lookup_ident(i))
).node = tss.idstack[offn + nredo++].next;
}
mask2 >>= 1;
@ -552,7 +552,7 @@ std::uint32_t *vm_exec(
case BC_INST_IDENT: {
alias *a = static_cast<alias *>(
ts.istate->identmap[op >> 8]
ts.istate->lookup_ident(op >> 8)
);
if (a->is_arg() && !ident_is_used_arg(a, ts)) {
ts.get_astack(a).push(ts.idstack.emplace_back());
@ -583,7 +583,7 @@ std::uint32_t *vm_exec(
goto use_top;
case BC_INST_LOOKUP: {
ident *id = ts.istate->identmap[op >> 8];
ident *id = ts.istate->lookup_ident(op >> 8);
if (static_cast<alias *>(id)->is_arg()) {
auto &v = args.emplace_back();
if (ident_is_used_arg(id, ts)) {
@ -617,13 +617,13 @@ std::uint32_t *vm_exec(
case BC_INST_VAR:
args.emplace_back() = static_cast<builtin_var *>(
ts.istate->identmap[op >> 8]
ts.istate->lookup_ident(op >> 8)
)->value();
goto use_top;
case BC_INST_ALIAS: {
auto *a = static_cast<alias *>(
ts.istate->identmap[op >> 8]
ts.istate->lookup_ident(op >> 8)
);
auto &ast = ts.get_astack(a);
if (a->is_arg()) {
@ -645,7 +645,7 @@ std::uint32_t *vm_exec(
case BC_INST_CALL: {
result.force_none();
ident *id = ts.istate->identmap[op >> 8];
ident *id = ts.istate->lookup_ident(op >> 8);
std::size_t callargs = *code++;
std::size_t offset = args.size() - callargs;
auto *imp = static_cast<alias_impl *>(id);
@ -768,7 +768,7 @@ noid:
case BC_INST_COM: {
command_impl *id = static_cast<command_impl *>(
ts.istate->identmap[op >> 8]
ts.istate->lookup_ident(op >> 8)
);
std::size_t offset = args.size() - id->arg_count();
result.force_none();
@ -781,7 +781,7 @@ noid:
case BC_INST_COM_V: {
command_impl *id = static_cast<command_impl *>(
ts.istate->identmap[op >> 8]
ts.istate->lookup_ident(op >> 8)
);
std::size_t callargs = *code++;
std::size_t offset = args.size() - callargs;