jq: Backport a bunch of commits in order to fix jq-1.6 terrible performance on startup
[feed/packages.git] / utils / jq / patches / 0003-Simplify-definition-of-block_bind_referenced.patch
diff --git a/utils/jq/patches/0003-Simplify-definition-of-block_bind_referenced.patch b/utils/jq/patches/0003-Simplify-definition-of-block_bind_referenced.patch
new file mode 100644 (file)
index 0000000..d710e4b
--- /dev/null
@@ -0,0 +1,78 @@
+From e6676ebbd2ab0a6283d96c797dbe93552c1a222c Mon Sep 17 00:00:00 2001
+From: Muh Muhten <muh.muhten@gmail.com>
+Date: Mon, 18 Feb 2019 21:00:59 -0500
+Subject: [PATCH 3/9] Simplify definition of block_bind_referenced
+
+---
+ src/compile.c | 49 ++++++++-----------------------------------------
+ 1 file changed, 8 insertions(+), 41 deletions(-)
+
+--- a/src/compile.c
++++ b/src/compile.c
+@@ -317,20 +317,6 @@ static int block_count_actuals(block b)
+   return args;
+ }
+-static int block_count_refs(block binder, block body) {
+-  int nrefs = 0;
+-  for (inst* i = body.first; i; i = i->next) {
+-    if (i != binder.first && i->bound_by == binder.first) {
+-      nrefs++;
+-    }
+-    // counting recurses into closures
+-    nrefs += block_count_refs(binder, i->subfn);
+-    // counting recurses into argument list
+-    nrefs += block_count_refs(binder, i->arglist);
+-  }
+-  return nrefs;
+-}
+-
+ static int block_bind_subblock_inner(int* any_unbound, block binder, block body, int bindflags, int break_distance) {
+   assert(block_is_single(binder));
+   assert((opcode_describe(binder.first->op)->flags & bindflags) == (bindflags & ~OP_BIND_WILDCARD));
+@@ -434,37 +420,18 @@ block block_bind_library(block binder, b
+   return body; // We don't return a join because we don't want those sticking around...
+ }
+-// Bind binder to body and throw away any defs in binder not referenced
+-// (directly or indirectly) from body.
++// Bind binder to body, then throw it away if not referenced.
+ block block_bind_referenced(block binder, block body, int bindflags) {
++  assert(block_is_single(binder));
+   assert(block_has_only_binders(binder, bindflags));
+   bindflags |= OP_HAS_BINDING;
+-  block refd = gen_noop();
+-  block unrefd = gen_noop();
+-  int nrefs;
+-  for (int last_kept = 0, kept = 0; ; ) {
+-    for (inst* curr; (curr = block_take(&binder));) {
+-      block b = inst_block(curr);
+-      nrefs = block_bind_each(b, body, bindflags);
+-      // Check if this binder is referenced from any of the ones we
+-      // already know are referenced by body.
+-      nrefs += block_count_refs(b, refd);
+-      nrefs += block_count_refs(b, body);
+-      if (nrefs) {
+-        refd = BLOCK(refd, b);
+-        kept++;
+-      } else {
+-        unrefd = BLOCK(unrefd, b);
+-      }
+-    }
+-    if (kept == last_kept)
+-      break;
+-    last_kept = kept;
+-    binder = unrefd;
+-    unrefd = gen_noop();
++
++  if (block_bind_subblock(binder, body, bindflags, 0) == 0) {
++    block_free(binder);
++  } else {
++    body = BLOCK(binder, body);
+   }
+-  block_free(unrefd);
+-  return block_join(refd, body);
++  return body;
+ }
+ static void block_mark_referenced(block body) {