Avoid redundant retains/releases by giving ts_stack_push move semantics
This commit is contained in:
parent
64fd5d0b4b
commit
ee995c3d6b
3 changed files with 56 additions and 58 deletions
|
|
@ -97,13 +97,13 @@ static bool parser__breakdown_top_of_stack(Parser *self, StackVersion version) {
|
|||
state = ts_language_next_state(self->language, state, child->symbol);
|
||||
}
|
||||
|
||||
ts_tree_retain(child);
|
||||
ts_stack_push(self->stack, slice.version, child, pending, state);
|
||||
}
|
||||
|
||||
for (uint32_t j = 1; j < slice.trees.size; j++) {
|
||||
Tree *tree = slice.trees.contents[j];
|
||||
ts_stack_push(self->stack, slice.version, tree, false, state);
|
||||
ts_tree_release(&self->tree_pool, tree);
|
||||
}
|
||||
|
||||
LOG("breakdown_top_of_stack tree:%s", SYM_NAME(parent->symbol));
|
||||
|
|
@ -638,7 +638,6 @@ static void parser__shift(Parser *self, StackVersion version, TSStateId state,
|
|||
self->stack, version, ts_tree_last_external_token(lookahead)
|
||||
);
|
||||
}
|
||||
ts_tree_release(&self->tree_pool, lookahead);
|
||||
}
|
||||
|
||||
static bool parser__replace_children(Parser *self, Tree *tree, Tree **children, uint32_t count) {
|
||||
|
|
@ -713,11 +712,9 @@ static StackPopResult parser__reduce(Parser *self, StackVersion version, TSSymbo
|
|||
// Push the parent node onto the stack, along with any extra tokens that
|
||||
// were previously on top of the stack.
|
||||
ts_stack_push(self->stack, slice.version, parent, false, next_state);
|
||||
ts_tree_release(&self->tree_pool, parent);
|
||||
for (uint32_t j = parent->child_count; j < slice.trees.size; j++) {
|
||||
Tree *tree = slice.trees.contents[j];
|
||||
ts_stack_push(self->stack, slice.version, tree, false, next_state);
|
||||
ts_tree_release(&self->tree_pool, tree);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -756,6 +753,7 @@ static void parser__accept(Parser *self, StackVersion version,
|
|||
Tree *lookahead) {
|
||||
lookahead->extra = true;
|
||||
assert(lookahead->symbol == ts_builtin_sym_end);
|
||||
ts_tree_retain(lookahead);
|
||||
ts_stack_push(self->stack, version, lookahead, false, 1);
|
||||
StackPopResult pop = ts_stack_pop_all(self->stack, version);
|
||||
|
||||
|
|
@ -769,8 +767,9 @@ static void parser__accept(Parser *self, StackVersion version,
|
|||
if (!child->extra) {
|
||||
root = ts_tree_make_copy(&self->tree_pool, child);
|
||||
root->child_count = 0;
|
||||
for (uint32_t k = 0; k < child->child_count; k++)
|
||||
for (uint32_t k = 0; k < child->child_count; k++) {
|
||||
ts_tree_retain(child->children[k]);
|
||||
}
|
||||
array_splice(&trees, j, 1, child->child_count, child->children);
|
||||
ts_tree_set_children(root, trees.size, trees.contents, self->language);
|
||||
ts_tree_release(&self->tree_pool, child);
|
||||
|
|
@ -920,7 +919,6 @@ static void parser__handle_error(Parser *self, StackVersion version, TSSymbol lo
|
|||
missing_tree, false,
|
||||
state_after_missing_symbol
|
||||
);
|
||||
ts_tree_release(&self->tree_pool, missing_tree);
|
||||
|
||||
if (parser__do_all_potential_reductions(
|
||||
self, version_with_missing_tree,
|
||||
|
|
@ -960,12 +958,10 @@ static void parser__halt_parse(Parser *self) {
|
|||
Tree *filler_node = ts_tree_make_error(&self->tree_pool, remaining_length, length_zero(), 0, self->language);
|
||||
filler_node->visible = false;
|
||||
ts_stack_push(self->stack, 0, filler_node, false, 0);
|
||||
ts_tree_release(&self->tree_pool, filler_node);
|
||||
|
||||
TreeArray children = array_new();
|
||||
Tree *root_error = ts_tree_make_error_node(&self->tree_pool, &children, self->language);
|
||||
ts_stack_push(self->stack, 0, root_error, false, 0);
|
||||
ts_tree_release(&self->tree_pool, root_error);
|
||||
|
||||
Tree *eof = ts_tree_make_leaf(&self->tree_pool, ts_builtin_sym_end, length_zero(), length_zero(), self->language);
|
||||
parser__accept(self, 0, eof);
|
||||
|
|
@ -1008,7 +1004,6 @@ static bool parser__recover_to_state(Parser *self, StackVersion version, unsigne
|
|||
Tree *error = ts_tree_make_error_node(&self->tree_pool, &slice.trees, self->language);
|
||||
error->extra = true;
|
||||
ts_stack_push(self->stack, slice.version, error, false, goal_state);
|
||||
ts_tree_release(&self->tree_pool, error);
|
||||
} else {
|
||||
array_delete(&slice.trees);
|
||||
}
|
||||
|
|
@ -1016,7 +1011,6 @@ static bool parser__recover_to_state(Parser *self, StackVersion version, unsigne
|
|||
for (unsigned j = 0; j < trailing_extras.size; j++) {
|
||||
Tree *tree = trailing_extras.contents[j];
|
||||
ts_stack_push(self->stack, slice.version, tree, false, goal_state);
|
||||
ts_tree_release(&self->tree_pool, tree);
|
||||
}
|
||||
|
||||
previous_version = slice.version;
|
||||
|
|
@ -1077,7 +1071,6 @@ static void parser__recover(Parser *self, StackVersion version, Tree *lookahead)
|
|||
TreeArray children = array_new();
|
||||
Tree *parent = ts_tree_make_error_node(&self->tree_pool, &children, self->language);
|
||||
ts_stack_push(self->stack, version, parent, false, 1);
|
||||
ts_tree_release(&self->tree_pool, parent);
|
||||
parser__accept(self, version, lookahead);
|
||||
return;
|
||||
}
|
||||
|
|
@ -1166,7 +1159,6 @@ static void parser__advance(Parser *self, StackVersion version, ReusableNode *re
|
|||
} else if (!parser__breakdown_top_of_stack(self, version)) {
|
||||
if (state == ERROR_STATE) {
|
||||
ts_stack_push(self->stack, version, lookahead, false, ERROR_STATE);
|
||||
ts_tree_release(&self->tree_pool, lookahead);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -128,7 +128,6 @@ static StackNode *stack_node_new(StackNode *previous_node, Tree *tree, bool is_p
|
|||
if (tree) {
|
||||
node->depth = previous_node->depth;
|
||||
if (!tree->extra) node->depth++;
|
||||
ts_tree_retain(tree);
|
||||
node->error_cost += tree->error_cost;
|
||||
node->position = length_add(node->position, ts_tree_total_size(tree));
|
||||
node->dynamic_precedence += tree->dynamic_precedence;
|
||||
|
|
|
|||
|
|
@ -100,6 +100,11 @@ describe("Stack", [&]() {
|
|||
AssertThat(record_alloc::outstanding_allocation_indices(), IsEmpty());
|
||||
});
|
||||
|
||||
auto push = [&](StackVersion version, Tree *tree, TSStateId state) {
|
||||
ts_tree_retain(tree);
|
||||
ts_stack_push(stack, version, tree, false, state);
|
||||
};
|
||||
|
||||
describe("push(version, tree, is_pending, state)", [&]() {
|
||||
it("adds entries to the given version of the stack", [&]() {
|
||||
AssertThat(ts_stack_version_count(stack), Equals<size_t>(1));
|
||||
|
|
@ -107,17 +112,17 @@ describe("Stack", [&]() {
|
|||
AssertThat(ts_stack_top_position(stack, 0), Equals(length_zero()));
|
||||
|
||||
// . <──0── A*
|
||||
ts_stack_push(stack, 0, trees[0], false, stateA);
|
||||
push(0, trees[0], stateA);
|
||||
AssertThat(ts_stack_top_state(stack, 0), Equals(stateA));
|
||||
AssertThat(ts_stack_top_position(stack, 0), Equals(tree_len));
|
||||
|
||||
// . <──0── A <──1── B*
|
||||
ts_stack_push(stack, 0, trees[1], false, stateB);
|
||||
push(0, trees[1], stateB);
|
||||
AssertThat(ts_stack_top_state(stack, 0), Equals(stateB));
|
||||
AssertThat(ts_stack_top_position(stack, 0), Equals(tree_len * 2));
|
||||
|
||||
// . <──0── A <──1── B <──2── C*
|
||||
ts_stack_push(stack, 0, trees[2], false, stateC);
|
||||
push(0, trees[2], stateC);
|
||||
AssertThat(ts_stack_top_state(stack, 0), Equals(stateC));
|
||||
AssertThat(ts_stack_top_position(stack, 0), Equals(tree_len * 3));
|
||||
|
||||
|
|
@ -135,7 +140,7 @@ describe("Stack", [&]() {
|
|||
// . <──0── A <─*
|
||||
// ↑
|
||||
// └───*
|
||||
ts_stack_push(stack, 0, trees[0], false, stateA);
|
||||
push(0, trees[0], stateA);
|
||||
ts_stack_copy_version(stack, 0);
|
||||
});
|
||||
|
||||
|
|
@ -143,10 +148,10 @@ describe("Stack", [&]() {
|
|||
// . <──0── A <──1── B <──3── D*
|
||||
// ↑
|
||||
// └───2─── C <──4── D*
|
||||
ts_stack_push(stack, 0, trees[1], false, stateB);
|
||||
ts_stack_push(stack, 1, trees[2], false, stateC);
|
||||
ts_stack_push(stack, 0, trees[3], false, stateD);
|
||||
ts_stack_push(stack, 1, trees[4], false, stateD);
|
||||
push(0, trees[1], stateB);
|
||||
push(1, trees[2], stateC);
|
||||
push(0, trees[3], stateD);
|
||||
push(1, trees[4], stateD);
|
||||
|
||||
// . <──0── A <──1── B <──3── D*
|
||||
// ↑ |
|
||||
|
|
@ -166,8 +171,8 @@ describe("Stack", [&]() {
|
|||
// . <──0── A <──1── B*
|
||||
// ↑
|
||||
// └───2─── C*
|
||||
ts_stack_push(stack, 0, trees[1], false, stateB);
|
||||
ts_stack_push(stack, 1, trees[2], false, stateC);
|
||||
push(0, trees[1], stateB);
|
||||
push(1, trees[2], stateC);
|
||||
|
||||
AssertThat(ts_stack_merge(stack, 0, 1), IsFalse());
|
||||
AssertThat(ts_stack_version_count(stack), Equals<size_t>(2));
|
||||
|
|
@ -178,10 +183,10 @@ describe("Stack", [&]() {
|
|||
// ↑
|
||||
// └───2─── C <──4── D*
|
||||
trees[3]->size = tree_len * 3;
|
||||
ts_stack_push(stack, 0, trees[1], false, stateB);
|
||||
ts_stack_push(stack, 1, trees[2], false, stateC);
|
||||
ts_stack_push(stack, 0, trees[3], false, stateD);
|
||||
ts_stack_push(stack, 1, trees[4], false, stateD);
|
||||
push(0, trees[1], stateB);
|
||||
push(1, trees[2], stateC);
|
||||
push(0, trees[3], stateD);
|
||||
push(1, trees[4], stateD);
|
||||
|
||||
AssertThat(ts_stack_merge(stack, 0, 1), IsFalse());
|
||||
AssertThat(ts_stack_version_count(stack), Equals<size_t>(2));
|
||||
|
|
@ -192,12 +197,12 @@ describe("Stack", [&]() {
|
|||
// . <──0── A <──1── B <──3── D <──5── E*
|
||||
// ↑
|
||||
// └───2─── C <──4── D <──5── E*
|
||||
ts_stack_push(stack, 0, trees[1], false, stateB);
|
||||
ts_stack_push(stack, 1, trees[2], false, stateC);
|
||||
ts_stack_push(stack, 0, trees[3], false, stateD);
|
||||
ts_stack_push(stack, 1, trees[4], false, stateD);
|
||||
ts_stack_push(stack, 0, trees[5], false, stateE);
|
||||
ts_stack_push(stack, 1, trees[5], false, stateE);
|
||||
push(0, trees[1], stateB);
|
||||
push(1, trees[2], stateC);
|
||||
push(0, trees[3], stateD);
|
||||
push(1, trees[4], stateD);
|
||||
push(0, trees[5], stateE);
|
||||
push(1, trees[5], stateE);
|
||||
|
||||
// . <──0── A <──1── B <──3── D <──5── E*
|
||||
// ↑ |
|
||||
|
|
@ -223,9 +228,9 @@ describe("Stack", [&]() {
|
|||
trees[2]->extra = true;
|
||||
trees[2]->size = tree_len * 0;
|
||||
|
||||
ts_stack_push(stack, 0, trees[1], false, stateB);
|
||||
ts_stack_push(stack, 1, trees[2], false, stateA);
|
||||
ts_stack_push(stack, 1, trees[1], false, stateB);
|
||||
push(0, trees[1], stateB);
|
||||
push(1, trees[2], stateA);
|
||||
push(1, trees[1], stateB);
|
||||
|
||||
// . <──0── A <──1── B*
|
||||
AssertThat(ts_stack_merge(stack, 0, 1), IsTrue());
|
||||
|
|
@ -242,9 +247,9 @@ describe("Stack", [&]() {
|
|||
describe("pop_count(version, count)", [&]() {
|
||||
before_each([&]() {
|
||||
// . <──0── A <──1── B <──2── C*
|
||||
ts_stack_push(stack, 0, trees[0], false, stateA);
|
||||
ts_stack_push(stack, 0, trees[1], false, stateB);
|
||||
ts_stack_push(stack, 0, trees[2], false, stateC);
|
||||
push(0, trees[0], stateA);
|
||||
push(0, trees[1], stateB);
|
||||
push(0, trees[2], stateC);
|
||||
});
|
||||
|
||||
it("creates a new version with the given number of entries removed", [&]() {
|
||||
|
|
@ -284,14 +289,14 @@ describe("Stack", [&]() {
|
|||
// . <──0── A <──1── B <──2── C <──3── D <──10── I*
|
||||
// ↑ |
|
||||
// └───4─── E <──5── F <──6───┘
|
||||
ts_stack_push(stack, 0, trees[3], false, stateD);
|
||||
push(0, trees[3], stateD);
|
||||
StackPopResult pop = ts_stack_pop_count(stack, 0, 3);
|
||||
free_slice_array(&pool,&pop.slices);
|
||||
ts_stack_push(stack, 1, trees[4], false, stateE);
|
||||
ts_stack_push(stack, 1, trees[5], false, stateF);
|
||||
ts_stack_push(stack, 1, trees[6], false, stateD);
|
||||
push(1, trees[4], stateE);
|
||||
push(1, trees[5], stateF);
|
||||
push(1, trees[6], stateD);
|
||||
ts_stack_merge(stack, 0, 1);
|
||||
ts_stack_push(stack, 0, trees[10], false, stateI);
|
||||
push(0, trees[10], stateI);
|
||||
|
||||
AssertThat(ts_stack_version_count(stack), Equals<size_t>(1));
|
||||
AssertThat(get_stack_entries(stack, 0), Equals(vector<StackEntry>({
|
||||
|
|
@ -407,10 +412,10 @@ describe("Stack", [&]() {
|
|||
// └───7─── G <──8── H <──9───┘
|
||||
StackPopResult pop = ts_stack_pop_count(stack, 0, 4);
|
||||
free_slice_array(&pool,&pop.slices);
|
||||
ts_stack_push(stack, 1, trees[7], false, stateG);
|
||||
ts_stack_push(stack, 1, trees[8], false, stateH);
|
||||
ts_stack_push(stack, 1, trees[9], false, stateD);
|
||||
ts_stack_push(stack, 1, trees[10], false, stateI);
|
||||
push(1, trees[7], stateG);
|
||||
push(1, trees[8], stateH);
|
||||
push(1, trees[9], stateD);
|
||||
push(1, trees[10], stateI);
|
||||
ts_stack_merge(stack, 0, 1);
|
||||
|
||||
AssertThat(ts_stack_version_count(stack), Equals<size_t>(1));
|
||||
|
|
@ -463,11 +468,12 @@ describe("Stack", [&]() {
|
|||
|
||||
describe("pop_pending(version)", [&]() {
|
||||
before_each([&]() {
|
||||
ts_stack_push(stack, 0, trees[0], false, stateA);
|
||||
push(0, trees[0], stateA);
|
||||
});
|
||||
|
||||
it("removes the top node from the stack if it was pushed in pending mode", [&]() {
|
||||
ts_stack_push(stack, 0, trees[1], true, stateB);
|
||||
ts_tree_retain(trees[1]);
|
||||
|
||||
StackPopResult pop = ts_stack_pop_pending(stack, 0);
|
||||
AssertThat(pop.slices.size, Equals<size_t>(1));
|
||||
|
|
@ -482,12 +488,13 @@ describe("Stack", [&]() {
|
|||
|
||||
it("skips entries whose trees are extra", [&]() {
|
||||
ts_stack_push(stack, 0, trees[1], true, stateB);
|
||||
ts_tree_retain(trees[1]);
|
||||
|
||||
trees[2]->extra = true;
|
||||
trees[3]->extra = true;
|
||||
|
||||
ts_stack_push(stack, 0, trees[2], false, stateB);
|
||||
ts_stack_push(stack, 0, trees[3], false, stateB);
|
||||
push(0, trees[2], stateB);
|
||||
push(0, trees[3], stateB);
|
||||
|
||||
StackPopResult pop = ts_stack_pop_pending(stack, 0);
|
||||
AssertThat(pop.slices.size, Equals<size_t>(1));
|
||||
|
|
@ -503,7 +510,7 @@ describe("Stack", [&]() {
|
|||
});
|
||||
|
||||
it("does nothing if the top node was not pushed in pending mode", [&]() {
|
||||
ts_stack_push(stack, 0, trees[1], false, stateB);
|
||||
push(0, trees[1], stateB);
|
||||
|
||||
StackPopResult pop = ts_stack_pop_pending(stack, 0);
|
||||
AssertThat(pop.slices.size, Equals<size_t>(0));
|
||||
|
|
@ -544,8 +551,8 @@ describe("Stack", [&]() {
|
|||
ts_external_token_state_init(&trees[2]->external_token_state, "ABCD", 2);
|
||||
|
||||
ts_stack_copy_version(stack, 0);
|
||||
ts_stack_push(stack, 0, trees[0], false, 5);
|
||||
ts_stack_push(stack, 1, trees[0], false, 5);
|
||||
push(0, trees[0], 5);
|
||||
push(1, trees[0], 5);
|
||||
|
||||
ts_stack_set_last_external_token(stack, 0, trees[1]);
|
||||
ts_stack_set_last_external_token(stack, 1, trees[2]);
|
||||
|
|
@ -558,8 +565,8 @@ describe("Stack", [&]() {
|
|||
ts_external_token_state_init(&trees[2]->external_token_state, "abcd", 2);
|
||||
|
||||
ts_stack_copy_version(stack, 0);
|
||||
ts_stack_push(stack, 0, trees[0], false, 5);
|
||||
ts_stack_push(stack, 1, trees[0], false, 5);
|
||||
push(0, trees[0], 5);
|
||||
push(1, trees[0], 5);
|
||||
|
||||
ts_stack_set_last_external_token(stack, 0, trees[1]);
|
||||
ts_stack_set_last_external_token(stack, 1, trees[2]);
|
||||
|
|
@ -569,8 +576,8 @@ describe("Stack", [&]() {
|
|||
|
||||
it("does not distinguish between an *empty* external token state and *no* external token state", [&]() {
|
||||
ts_stack_copy_version(stack, 0);
|
||||
ts_stack_push(stack, 0, trees[0], false, 5);
|
||||
ts_stack_push(stack, 1, trees[0], false, 5);
|
||||
push(0, trees[0], 5);
|
||||
push(1, trees[0], 5);
|
||||
|
||||
ts_stack_set_last_external_token(stack, 0, trees[1]);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue