summaryrefslogtreecommitdiffstats
path: root/parser.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2019-10-21 19:45:40 -0700
committerKaz Kylheku <kaz@kylheku.com>2019-10-21 19:45:40 -0700
commit81da1829a7b79676d36e0684aed8b5b587fffc09 (patch)
treea5547403e9d15c31ef8480de062904c80813ba39 /parser.c
parent84e9903c27ede099e2361e15b16a05c6aa4dc819 (diff)
downloadtxr-81da1829a7b79676d36e0684aed8b5b587fffc09.tar.gz
txr-81da1829a7b79676d36e0684aed8b5b587fffc09.tar.bz2
txr-81da1829a7b79676d36e0684aed8b5b587fffc09.zip
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.
Diffstat (limited to 'parser.c')
-rw-r--r--parser.c19
1 files 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) {