From 81da1829a7b79676d36e0684aed8b5b587fffc09 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Mon, 21 Oct 2019 19:45:40 -0700 Subject: circle notation: some backpatching optimizations. * parser.c (circ_backpatch): For hashes and trees, if the count has not changed while traversing the elements, then it means nothing was backpatched: there is no need to do the extra expensive step of rebuilding the hash or tree. --- parser.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/parser.c b/parser.c index b05892bb..a849e980 100644 --- a/parser.c +++ b/parser.c @@ -366,12 +366,14 @@ tail: if (hashp(obj)) { val u = get_hash_userdata(obj); val ru = patch_ref(p, u); + cnum old_circ_count = p->circ_count; + if (ru) set_hash_userdata(obj, ru); else circ_backpatch(p, &cs, u); - if (p->circ_count) { + if (old_circ_count > 0) { val iter = hash_begin(obj); val cell; val pairs = nil; @@ -381,11 +383,13 @@ tail: push(cell, &pairs); } - clearhash(obj); + if (old_circ_count != p->circ_count) { + clearhash(obj); - while (pairs) { - val cell = pop(&pairs); - sethash(obj, us_car(cell), us_cdr(cell)); + while (pairs) { + val cell = pop(&pairs); + sethash(obj, us_car(cell), us_cdr(cell)); + } } } } else if (structp(obj)) { @@ -400,11 +404,14 @@ tail: slotset(obj, sn, rsv); else circ_backpatch(p, &cs, sv); + if (p->circ_count <= 0) + break; } } else if (treep(obj)) { val iter = tree_begin(obj); val node; val nodes = nil; + cnum old_circ_count = p->circ_count; while ((node = tree_next(iter))) { val k = node->tn.key; @@ -416,7 +423,7 @@ tail: push(node, &nodes); } - if (nodes) { + if (nodes && old_circ_count != p->circ_count) { tree_clear(obj); while (nodes) { -- cgit v1.2.3