lock-free argument lookup

Since we know these ids are always early and up to a fixed index,
we can have a separate, fixed mapping for them, which is only
initialized once during state creation, and never changes.
This commit is contained in:
Daniel Kolesa 2022-04-20 05:00:05 +02:00
parent 4627321e23
commit 2406324a96
3 changed files with 13 additions and 6 deletions

View file

@ -45,11 +45,17 @@ static void *default_alloc(void *, void *p, size_t, size_t ns) {
} }
ident *internal_state::lookup_ident(std::size_t idx) { ident *internal_state::lookup_ident(std::size_t idx) {
if (idx < MAX_ARGUMENTS) {
return argmap[idx];
}
std::lock_guard<std::mutex> l{ident_mtx}; std::lock_guard<std::mutex> l{ident_mtx};
return identmap[idx]; return identmap[idx];
} }
ident const *internal_state::lookup_ident(std::size_t idx) const { ident const *internal_state::lookup_ident(std::size_t idx) const {
if (idx < MAX_ARGUMENTS) {
return argmap[idx];
}
std::lock_guard<std::mutex> l{ident_mtx}; std::lock_guard<std::mutex> l{ident_mtx};
return identmap[idx]; return identmap[idx];
} }
@ -141,7 +147,7 @@ state::state(alloc_func func, void *data) {
for (std::size_t i = 0; i < MAX_ARGUMENTS; ++i) { for (std::size_t i = 0; i < MAX_ARGUMENTS; ++i) {
char buf[16]; char buf[16];
snprintf(buf, sizeof(buf), "arg%zu", i + 1); snprintf(buf, sizeof(buf), "arg%zu", i + 1);
statep->new_ident( statep->argmap[i] = &statep->new_ident(
*this, static_cast<char const *>(buf), IDENT_FLAG_ARG *this, static_cast<char const *>(buf), IDENT_FLAG_ARG
); );
} }

View file

@ -50,6 +50,7 @@ struct internal_state {
allocator_type allocator_type
> idents; > idents;
std::vector<ident *, std_allocator<ident *>> identmap; std::vector<ident *, std_allocator<ident *>> identmap;
std::array<ident *, MAX_ARGUMENTS> argmap;
mutable std::mutex ident_mtx; mutable std::mutex ident_mtx;
string_pool *strman; string_pool *strman;

View file

@ -133,7 +133,7 @@ any_value exec_alias(
std::size_t noff = ts.idstack.size(); std::size_t noff = ts.idstack.size();
for(std::size_t i = 0; i < callargs; i++) { for(std::size_t i = 0; i < callargs; i++) {
auto &ast = ts.get_astack( auto &ast = ts.get_astack(
static_cast<alias *>(ts.istate->lookup_ident(i)) static_cast<alias *>(ts.istate->argmap[i])
); );
auto &st = ts.idstack.emplace_back(); auto &st = ts.idstack.emplace_back();
ast.push(st); ast.push(st);
@ -167,14 +167,14 @@ any_value exec_alias(
tss.ident_flags = oflags; tss.ident_flags = oflags;
for (std::size_t i = 0; i < cargs; i++) { for (std::size_t i = 0; i < cargs; i++) {
tss.get_astack( tss.get_astack(
static_cast<alias *>(tss.istate->lookup_ident(i)) static_cast<alias *>(tss.istate->argmap[i])
).pop(); ).pop();
amask[i] = false; amask[i] = false;
} }
for (; amask.any(); ++cargs) { for (; amask.any(); ++cargs) {
if (amask[cargs]) { if (amask[cargs]) {
tss.get_astack( tss.get_astack(
static_cast<alias *>(tss.istate->lookup_ident(cargs)) static_cast<alias *>(tss.istate->argmap[cargs])
).pop(); ).pop();
amask[cargs] = false; 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) { for (std::size_t i = 0; mask.any(); ++i) {
if (mask[0]) { if (mask[0]) {
auto &ast = ts.get_astack( auto &ast = ts.get_astack(
static_cast<alias *>(ts.istate->lookup_ident(i)) static_cast<alias *>(ts.istate->argmap[i])
); );
auto &st = ts.idstack.emplace_back(); auto &st = ts.idstack.emplace_back();
st.next = ast.node; 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) { for (std::size_t i = 0, nredo = 0; mask2.any(); ++i) {
if (mask2[0]) { if (mask2[0]) {
tss.get_astack( tss.get_astack(
static_cast<alias *>(tss.istate->lookup_ident(i)) static_cast<alias *>(tss.istate->argmap[i])
).node = tss.idstack[offn + nredo++].next; ).node = tss.idstack[offn + nredo++].next;
} }
mask2 >>= 1; mask2 >>= 1;