git » jacl.git » commit 2b58c6a

WIP static tagbody optimization

author Alan Dipert
2020-04-11 14:59:59 UTC
committer Alan Dipert
2020-04-11 14:59:59 UTC
parent e7b5725c4fbc302529ff083e60ac1a242018b904

WIP static tagbody optimization

jacl.js +26 -13

diff --git a/jacl.js b/jacl.js
index 75b705e..c64329d 100644
--- a/jacl.js
+++ b/jacl.js
@@ -1567,35 +1567,48 @@ const analyze = (env, parent, form) => {
   }
 };
 
-const findNodesByName = (root, op) => {
+// TODO Consider turning this into an iterator function.
+const findNodes = (root, pred) => {
   let found = [];
-  if (root.op === op) found.push(root);
-  for (const child of root.children) {
-    found = [...found, ...findNodesByName(child, op)];
+  if (pred(root))
+    found.push(root);
+  for (const x of root.children) {
+    found = [...found, ...findNodes(x, pred)];
   }
   return found;
 };
 
-const optimizeTagbody = node => {
-  gos: for (const go of findNodesByName(node, 'go')) {
+const optimizeGo = node => {
+  const gos = findNodes(node, x => {
+    return x.op === 'go' && x.context !== 'expr';
+  });
+  next: for (const go of gos) {
     let parent = go.parent;
     while (parent) {
       if (parent.op === 'tagbody' && go.tagbodyId === parent.id) {
         go.op = 'go-continue';
-        continue gos;
-      }
-      if (parent.op === 'lambda') {
-        continue gos;
+        continue next;
       }
+      if (parent.op === 'lambda')
+        continue next;
       parent = parent.parent;
     }
   }
 };
 
+const optimizeTagbody = node => {
+  const tbs = findNodes(node, x => x.op === 'tagbody');
+  next: for (const tb of tbs) {
+    const gos = findNodes(tb, x => x.op === 'go' && x.tagbodyId === tb.id);
+    // If gos is empty, tb has no GOs that will throw exceptions.
+    if (!gos.length)
+      tb.op = 'tagbody-static';
+  }
+};
+
 const optimize = node => {
-  optimizeTagbody(node);
-  // TODO Consider optimize TAGBODYs for size consisting only of local
-  // GOs
+  optimizeGo(node);
+  // TODO: optimizeTagbody(node);
   return node;
 };