From ded54a3a1a068031a667739e83e4fd25393d90cb Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Sat, 1 Mar 2014 00:25:05 -0800 Subject: [PATCH] Fix some memory management bugs with trees --- Makefile | 2 +- include/tree_sitter/parser.h | 9 ++++---- include/tree_sitter/runtime.h | 4 ++-- spec/runtime/tree_spec.cpp | 8 +++---- src/runtime/tree.cpp | 41 +++++++++++++++++------------------ 5 files changed, 32 insertions(+), 32 deletions(-) diff --git a/Makefile b/Makefile index 48ccf960..d93cd51f 100644 --- a/Makefile +++ b/Makefile @@ -38,7 +38,7 @@ debug: $(TEST_BIN) gdb $< valgrind: $(TEST_BIN) - valgrind --track-origins=yes $(TEST_BIN) + valgrind --track-origins=yes --dsymutil=yes $(TEST_BIN) clean: $(RM) $(SRC_OBJECTS) $(TEST_OBJECTS) $(LIB_FILE) $(TEST_BIN) diff --git a/include/tree_sitter/parser.h b/include/tree_sitter/parser.h index 7dd1f017..995ba7bf 100644 --- a/include/tree_sitter/parser.h +++ b/include/tree_sitter/parser.h @@ -119,9 +119,9 @@ static void ts_parser_reduce(ts_parser *parser, ts_symbol symbol, int immediate_ } } - ts_parser_shrink_stack(parser, new_stack_size); parser->prev_lookahead_node = parser->lookahead_node; parser->lookahead_node = ts_tree_make_node(symbol, child_count, children); + ts_parser_shrink_stack(parser, new_stack_size); DEBUG_PARSE("reduce: %s, state: %u \n", ts_symbol_names[symbol], ts_parser_parse_state(parser)); } @@ -134,7 +134,7 @@ static void ts_parser_advance(ts_parser *parser, ts_state lex_state) { static void ts_parser_set_lookahead_sym(ts_parser *parser, ts_symbol symbol) { DEBUG_LEX("token: %s \n", ts_symbol_names[symbol]); - parser->lookahead_node = ts_tree_make_leaf(symbol); + parser->lookahead_node = ts_tree_make_leaf(symbol, 0, 0); } static ts_tree * ts_parser_tree(ts_parser *parser) { @@ -148,9 +148,10 @@ static void ts_parser_skip_whitespace(ts_parser *parser) { } static int ts_parser_handle_error(ts_parser *parser, size_t count, const ts_symbol *expected_symbols) { - ts_tree *error = ts_tree_make_error(ts_parser_lookahead_char(parser), count, expected_symbols); + ts_tree *error = ts_tree_make_error(ts_parser_lookahead_char(parser), count, expected_symbols, 0, 0); while (1) { + ts_tree_release(parser->lookahead_node); parser->lookahead_node = NULL; parser->lex_state = ts_lex_state_error; ts_lex(parser); @@ -199,7 +200,7 @@ next_state: #define START_LEXER() \ ts_parser_skip_whitespace(parser); \ if (!ts_parser_lookahead_char(parser)) { \ - parser->lookahead_node = ts_tree_make_leaf(ts_builtin_sym_end); \ + parser->lookahead_node = ts_tree_make_leaf(ts_builtin_sym_end, 0, 0); \ return; \ } \ next_state: diff --git a/include/tree_sitter/runtime.h b/include/tree_sitter/runtime.h index 4c8b70bf..6e3923f9 100644 --- a/include/tree_sitter/runtime.h +++ b/include/tree_sitter/runtime.h @@ -27,9 +27,9 @@ typedef struct ts_tree { } data; } ts_tree; -ts_tree * ts_tree_make_leaf(ts_symbol symbol); +ts_tree * ts_tree_make_leaf(ts_symbol symbol, size_t size, size_t offset); ts_tree * ts_tree_make_node(ts_symbol symbol, size_t child_count, ts_tree **children); -ts_tree * ts_tree_make_error(char lookahead_char, size_t expected_input_count, const ts_symbol *expected_inputs); +ts_tree * ts_tree_make_error(char lookahead_char, size_t expected_input_count, const ts_symbol *expected_inputs, size_t size, size_t offset); void ts_tree_retain(ts_tree *tree); void ts_tree_release(ts_tree *tree); int ts_tree_equals(const ts_tree *tree1, const ts_tree *tree2); diff --git a/spec/runtime/tree_spec.cpp b/spec/runtime/tree_spec.cpp index a40fac09..ca16a084 100644 --- a/spec/runtime/tree_spec.cpp +++ b/spec/runtime/tree_spec.cpp @@ -16,8 +16,8 @@ describe("trees", []() { ts_tree *tree1, *parent1; before_each([&]() { - tree1 = ts_tree_make_leaf(cat); - parent1 = ts_tree_make_node(dog, 1, &tree1); + tree1 = ts_tree_make_leaf(cat, 0, 0); + parent1 = ts_tree_make_node(dog, 1, tree_array({ tree1 })); }); after_each([&]() { @@ -27,7 +27,7 @@ describe("trees", []() { describe("equality", [&]() { it("returns true for identical trees", [&]() { - ts_tree *tree2 = ts_tree_make_leaf(cat); + ts_tree *tree2 = ts_tree_make_leaf(cat, 0, 0); AssertThat(ts_tree_equals(tree1, tree2), Equals(1)); ts_tree *parent2 = ts_tree_make_node(dog, 1, tree_array({ tree2 })); @@ -38,7 +38,7 @@ describe("trees", []() { }); it("returns false for different trees", [&]() { - ts_tree *different_tree = ts_tree_make_leaf(pig); + ts_tree *different_tree = ts_tree_make_leaf(pig, 0, 0); AssertThat(ts_tree_equals(tree1, different_tree), Equals(0)); ts_tree *different_parent = ts_tree_make_node(dog, 1, tree_array({ different_tree })); diff --git a/src/runtime/tree.cpp b/src/runtime/tree.cpp index 12d67f5c..dd4daf4c 100644 --- a/src/runtime/tree.cpp +++ b/src/runtime/tree.cpp @@ -5,36 +5,33 @@ using std::string; using std::to_string; -ts_tree * ts_tree_make_leaf(ts_symbol symbol) { - ts_tree *result = new ts_tree(); - result->ref_count = 0; +static ts_tree * ts_tree_make(ts_symbol symbol, size_t size, size_t offset) { + ts_tree *result = (ts_tree *)malloc(sizeof(ts_tree)); + result->ref_count = 1; result->symbol = symbol; - result->data.children = { - .count = 0, - .contents = NULL - }; + return result; +} + +ts_tree * ts_tree_make_leaf(ts_symbol symbol, size_t size, size_t offset) { + ts_tree *result = ts_tree_make(symbol, size, offset); + result->data.children = { .count = 0, .contents = NULL }; return result; } ts_tree * ts_tree_make_node(ts_symbol symbol, size_t child_count, ts_tree **children) { - ts_tree *result = new ts_tree(); - result->ref_count = 0; - result->symbol = symbol; - result->data.children = { - .count = child_count, - .contents = children - }; for (int i = 0; i < child_count; i++) ts_tree_retain(children[i]); + ts_tree *result = ts_tree_make(symbol, 0, 0); + result->data.children = { .count = child_count, .contents = children }; return result; } -ts_tree * ts_tree_make_error(char lookahead_char, size_t expected_input_count, const ts_symbol *expected_inputs) { - ts_tree *result = new ts_tree(); - result->symbol = ts_builtin_sym_error; +ts_tree * ts_tree_make_error(char lookahead_char, size_t expected_input_count, const ts_symbol *expected_inputs, size_t size, size_t offset) { + ts_tree *result = ts_tree_make(ts_builtin_sym_error, size, offset); result->data.error = { .lookahead_char = lookahead_char, .expected_input_count = expected_input_count, + .expected_inputs = expected_inputs }; return result; } @@ -46,10 +43,12 @@ void ts_tree_retain(ts_tree *tree) { void ts_tree_release(ts_tree *tree) { tree->ref_count--; if (tree->ref_count == 0) { - ts_tree **children = tree->data.children.contents; - for (int i = 0; i < ts_tree_child_count(tree); i++) - ts_tree_release(children[i]); - free(children); + ts_tree **children = ts_tree_children(tree); + if (children) { + for (int i = 0; i < ts_tree_child_count(tree); i++) + ts_tree_release(children[i]); + free(children); + } free(tree); } }