1
0
forked from GitHub/gf-core

fix all space leaks in PgfLRTableMaker

This commit is contained in:
Krasimir Angelov
2024-01-09 11:12:19 +01:00
parent dee0047ba6
commit f647f43274

View File

@@ -117,7 +117,8 @@ struct PgfLRTableMaker::Item {
}
void operator delete(void *p) {
free(p);
if (((Item *) p)->ref_cnt == 0)
free(p);
}
};
@@ -194,13 +195,11 @@ void PgfLRTableMaker::CCat::register_item(Item *item) {
PgfLRTableMaker::CCat::~CCat() {
for (Item *item : items) {
item->ref_cnt--;
if (item->ref_cnt == 0)
delete item;
delete item;
}
for (Item *item : suspended) {
item->ref_cnt--;
if (item->ref_cnt == 0)
delete item;
delete item;
}
for (Production *prod : prods) {
delete prod;
@@ -384,8 +383,8 @@ bool PgfLRTableMaker::CompareKey3::operator() (const Key3& k1, const Key3& k2) c
struct PgfLRTableMaker::State {
size_t id;
std::vector<Item*> items;
std::vector<Item*> completed;
std::vector<Item*> items; // The seed items for this state
std::vector<Item*> completed; // Completed items that will become reductions
std::map<Key1,State*,CompareKey1> ccats1;
std::map<Key2,State*,CompareKey2> ccats2;
std::map<Key3,State*,CompareKey3> tokens;
@@ -399,14 +398,12 @@ struct PgfLRTableMaker::State {
~State() {
for (Item *item : items) {
item->ref_cnt--;
if (item->ref_cnt == 0)
delete item;
delete item;
}
for (Item *item : completed) {
item->ref_cnt--;
if (item->ref_cnt == 0)
delete item;
delete item;
}
}
@@ -414,6 +411,12 @@ struct PgfLRTableMaker::State {
items.push_back(item); item->ref_cnt++;
push_heap(items.begin(), items.end(), compare_item);
}
Item *pop_item() {
Item *item = items.back(); items.pop_back();
item->ref_cnt--;
return item;
}
};
PgfLRTableMaker::PgfLRTableMaker(ref<PgfAbstr> abstr, ref<PgfConcr> concr)
@@ -709,38 +712,62 @@ void PgfLRTableMaker::symbol(State *state, Fold fold, Item *item, PgfSymbol sym)
item->ccat->register_item(item);
} else {
auto symkp = ref<PgfSymbolKP>::untagged(sym);
Item *new_item1 = NULL;
Item *new_item2 = NULL;
for (size_t i = 0; i < symkp->alts.len; i++) {
Item *new_item = new (item) Item; new_item->sym_idx++;
ref<PgfSequence> form = symkp->alts.data[i].form;
if (form->syms.len == 0) {
process(state, fold, new_item);
if (!new_item1) {
new_item1 = new (item) Item;
new_item1->sym_idx++;
}
process(state, fold, new_item1);
} else {
auto &next_state = state->tokens[Key3(form,0)];
if (next_state == NULL) {
next_state = new State;
}
new_item->stk_size++;
next_state->push_item(new_item);
if (!new_item2) {
new_item2 = new (item) Item;
new_item2->sym_idx++;
new_item2->stk_size++;
}
next_state->push_item(new_item2);
}
}
Item *new_item = new (item) Item; new_item->sym_idx++;
ref<PgfSequence> form = symkp->default_form;
if (form->syms.len == 0) {
process(state, fold, new_item);
if (!new_item1) {
new_item1 = new (item) Item;
new_item1->sym_idx++;
}
process(state, fold, new_item1);
} else {
auto &next_state = state->tokens[Key3(form,0)];
if (next_state == NULL) {
next_state = new State;
}
new_item->stk_size++;
next_state->push_item(new_item);
if (!new_item2) {
new_item2 = new (item) Item;
new_item2->sym_idx++;
new_item2->stk_size++;
}
next_state->push_item(new_item2);
}
// If the items are not owned by anyone, we must delete them
if (new_item1 != NULL)
delete new_item1;
if (new_item2 != NULL)
delete new_item2;
}
}
case PgfSymbolBIND::tag: {
if (fold != PROBE)
{
if (fold == PROBE) {
item->ccat->productive = true;
item->ccat->register_item(item);
} else {
if (state->bind_state == NULL) {
state->bind_state = new State;
}
@@ -753,33 +780,35 @@ void PgfLRTableMaker::symbol(State *state, Fold fold, Item *item, PgfSymbol sym)
}
case PgfSymbolSOFTBIND::tag:
case PgfSymbolSOFTSPACE::tag: {
if (fold != PROBE)
{
if (fold == PROBE) {
item->ccat->productive = true;
item->ccat->register_item(item);
} else {
// SOFT_BIND && SOFT_SPACE also allow a space
item = new (item) Item();
item->sym_idx++;
process(state,fold,item);
Item *new_item = new (item) Item();
new_item->sym_idx++;
process(state,fold,new_item);
delete new_item;
// Now we handle the case where there is no space
// Now we handle the case where there is no space.
if (state->bind_state == NULL) {
state->bind_state = new State;
}
item = new (item) Item();
item->stk_size++;
state->bind_state->push_item(item);
new_item = new (item) Item();
new_item->stk_size++;
state->bind_state->push_item(new_item);
delete new_item;
}
break;
}
case PgfSymbolCAPIT::tag:
case PgfSymbolALLCAPIT::tag: {
// We just ignore CAPIT && ALLCAPIT during parsing
item->sym_idx++;
item = new (item) Item(); item->sym_idx++;
process(state,fold,item);
delete item;
break;
}
default:
if (item->ref_cnt == 0)
delete item;
}
}
@@ -828,6 +857,8 @@ void PgfLRTableMaker::predict(State *state, Fold fold, Item *item, T cat,
predict(state, fold, new_item, cat, index);
delete new_item;
size_t i = n_terms;
while (i > 0) {
i--;
@@ -846,9 +877,6 @@ void PgfLRTableMaker::predict(State *state, Fold fold, Item *item, T cat,
break;
}
}
if (item->ref_cnt == 0)
delete item;
}
void PgfLRTableMaker::predict(State *state, Fold fold, Item *item, ref<PgfText> cat, size_t lin_idx)
@@ -871,6 +899,7 @@ void PgfLRTableMaker::predict(State *state, Fold fold, Item *item, ref<PgfText>
} else if (fold == PROBE && ccat->prods.size() > 0) {
Item *new_item = new(item,ccat) Item;
process(state,fold,new_item);
delete new_item;
}
if (fold == PROBE) {
@@ -896,6 +925,7 @@ void PgfLRTableMaker::predict(State *state, Fold fold, Item *item, ref<PgfText>
if (fold == INIT && ccat->prods.size() > 0) {
Item *new_item = new (item, ccat) Item;
process(state, fold, new_item);
delete new_item;
}
}
}
@@ -916,6 +946,7 @@ void PgfLRTableMaker::predict(State *state, Fold fold, Item *item, CCat *ccat, s
Production *prod = ccat->prods[i];
Item *item = new(new_ccat, prod, lin_idx) Item;
process(NULL, PROBE, item);
delete item;
}
}
@@ -926,13 +957,13 @@ void PgfLRTableMaker::predict(State *state, Fold fold, Item *item, CCat *ccat, s
}
} else {
if (new_ccat->productive) {
auto &new_state = state->ccats2[Key2(new_ccat,lin_idx)];
if (new_state == NULL) {
new_state = new State;
auto &next_state = state->ccats2[Key2(new_ccat,lin_idx)];
if (next_state == NULL) {
next_state = new State;
}
new_state->push_item(new(item,lin_idx) Item);
next_state->push_item(new(item,lin_idx) Item);
if (new_state->items.size() == 1) {
if (next_state->items.size() == 1) {
for (size_t i = 0; i < new_ccat->items.size(); i++) {
process(state, REPEAT, new_ccat->items[i]);
}
@@ -941,6 +972,7 @@ void PgfLRTableMaker::predict(State *state, Fold fold, Item *item, CCat *ccat, s
if (fold == INIT && new_ccat->prods.size() > 0) {
Item *new_item = new (item, new_ccat) Item;
process(state, fold, new_item);
delete new_item;
}
}
}
@@ -958,6 +990,7 @@ void PgfLRTableMaker::predict(ref<PgfAbsFun> absfun, CCat *ccat)
size_t seq_idx = n_fields * i + ccat->lin_idx;
Item *item = new(ccat, lin, seq_idx) Item;
process(NULL, PROBE, item);
delete item;
}
}
}
@@ -984,12 +1017,10 @@ void PgfLRTableMaker::complete(State *state, Fold fold, Item *item)
if (susp != NULL) {
Item *new_item = new (susp, item->ccat) Item;
process(state, PROBE, new_item);
delete new_item;
}
}
}
if (item->ref_cnt == 0)
delete item;
} else {
state->completed.push_back(item); item->ref_cnt++;
@@ -1045,7 +1076,7 @@ ref<PgfLRTable> PgfLRTableMaker::make()
#endif
while (!state->items.empty()) {
Item *item = state->items.back(); state->items.pop_back();
Item *item = state->pop_item();
#if defined(DEBUG_AUTOMATON) && !defined(DEBUG_STATE_CREATION)
// The order in which we process the items should not matter,
@@ -1055,9 +1086,8 @@ ref<PgfLRTable> PgfLRTableMaker::make()
#endif
process(state, INIT, item);
item->ref_cnt--;
if (item->ref_cnt == 0)
delete item;
delete item;
}
for (auto &i : state->ccats1) {