aboutsummaryrefslogtreecommitdiff
path: root/utils/jq/patches/0002-Reimplement-block_drop_unreferenced-in-linear-time.patch
blob: 3df0d00939f1ec9578a87713accd63214257cb1a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
From aab54373e9406ee2a154b8d6166b3045aa3484ee Mon Sep 17 00:00:00 2001
From: Muh Muhten <muh.muhten@gmail.com>
Date: Sat, 9 Feb 2019 17:24:18 -0500
Subject: [PATCH 2/9] Reimplement block_drop_unreferenced in linear time

---
 src/compile.c | 50 +++++++++++++++++++++++++++++---------------------
 1 file changed, 29 insertions(+), 21 deletions(-)

--- a/src/compile.c
+++ b/src/compile.c
@@ -53,6 +53,7 @@ struct inst {
   struct inst* bound_by;
   char* symbol;
   int any_unbound;
+  int referenced;
 
   int nformals;
   int nactuals;
@@ -75,6 +76,7 @@ static inst* inst_new(opcode op) {
   i->bound_by = 0;
   i->symbol = 0;
   i->any_unbound = 0;
+  i->referenced = 0;
   i->nformals = -1;
   i->nactuals = -1;
   i->subfn = gen_noop();
@@ -465,30 +467,36 @@ block block_bind_referenced(block binder
   return block_join(refd, body);
 }
 
+static void block_mark_referenced(block body) {
+  int saw_top = 0;
+  for (inst* i = body.last; i; i = i->prev) {
+    if (saw_top && i->bound_by == i && !i->referenced)
+      continue;
+    if (i->op == TOP) {
+      saw_top = 1;
+    }
+    if (i->bound_by) {
+      i->bound_by->referenced = 1;
+    }
+
+    block_mark_referenced(i->arglist);
+    block_mark_referenced(i->subfn);
+  }
+}
+
 block block_drop_unreferenced(block body) {
-  inst* curr;
+  block_mark_referenced(body);
+
   block refd = gen_noop();
-  block unrefd = gen_noop();
-  int drop;
-  do {
-    drop = 0;
-    while ((curr = block_take(&body)) && curr->op != TOP) {
-      block b = inst_block(curr);
-      if (block_count_refs(b,refd) + block_count_refs(b,body) == 0) {
-        unrefd = BLOCK(unrefd, b);
-        drop++;
-      } else {
-        refd = BLOCK(refd, b);
-      }
-    }
-    if (curr && curr->op == TOP) {
-      body = BLOCK(inst_block(curr),body);
+  inst* curr;
+  while ((curr = block_take(&body))) {
+    if (curr->bound_by == curr && !curr->referenced) {
+      inst_free(curr);
+    } else {
+      refd = BLOCK(inst_block(curr), refd);
     }
-    body = BLOCK(refd, body);
-    refd = gen_noop();
-  } while (drop != 0);
-  block_free(unrefd);
-  return body;
+  }
+  return refd;
 }
 
 jv block_take_imports(block* body) {