changeset 692:09df0c85f306

Fix overzealous Marshalcheck; garbage-collect string-embedded closures when no dyns are active
author Adam Chlipala <adamc@hcoop.net>
date Sat, 04 Apr 2009 12:54:39 -0400
parents cc58941da3e2
children 655bcc9b77e0
files lib/js/urweb.js src/compiler.sig src/compiler.sml src/jscomp.sml src/marshalcheck.sml
diffstat 5 files changed, 79 insertions(+), 38 deletions(-) [+]
line wrap: on
line diff
--- a/lib/js/urweb.js	Sat Apr 04 11:46:24 2009 -0400
+++ b/lib/js/urweb.js	Sat Apr 04 12:54:39 2009 -0400
@@ -1,3 +1,5 @@
+// Lists
+
 function cons(v, ls) {
   return { next : ls, data : v };
 }
@@ -18,6 +20,43 @@
 }
 
 
+// Embedding closures in XML strings
+
+function cat(s1, s2) {
+  if (s1.length && s2.length)
+    return s1 + s2;
+  else
+    return {_1: s1, _2: s2};
+}
+
+var closures = [];
+
+function newClosure(f) {
+  var n = closures.length;
+  closures[n] = f;
+  return n;
+}
+
+function cr(n) {
+  return closures[n]();
+}
+
+function flatten(tr) {
+  if (tr.length)
+    return tr;
+  else if (tr._1)
+    return cs(tr._1) + cs(tr._2);
+  else
+    return "cr(" + newClosure(tr) + ")";
+}
+
+function clearClosures() {
+  closures = [];
+}
+
+
+// Dynamic tree management
+
 function populate(node) {
   var s = node.signal;
   var oldSources = node.sources;
@@ -85,7 +124,7 @@
 function runScripts(node) {
   var savedScript = thisScript;
 
-  var scripts = node.getElementsByTagName("script"), scriptsCopy = {};
+  var scripts = node.getElementsByTagName("script"), scriptsCopy = [];
   var len = scripts.length;
   for (var i = 0; i < len; ++i)
     scriptsCopy[i] = scripts[i];
@@ -98,12 +137,18 @@
 }
 
 
+// Dynamic tree entry points
+
+var dynDepth = 0;
+
 function dyn(s) {
   var x = document.createElement("span");
   x.dead = false;
   x.signal = s;
   x.sources = null;
   x.recreate = function(v) {
+    ++dynDepth;
+
     var spans = x.getElementsByTagName("span");
     for (var i = 0; i < spans.length; ++i) {
       var span = spans[i];
@@ -114,6 +159,9 @@
 
     x.innerHTML = v;
     runScripts(x);
+
+    if (--dynDepth == 0)
+      clearClosures();
   };
   populate(x);
   addNode(x);
@@ -131,6 +179,9 @@
   return x;
 }
 
+
+// Basic string operations
+
 function eh(x) {
   return x.split("&").join("&amp;").split("<").join("&lt;").split(">").join("&gt;");
 }
@@ -154,10 +205,17 @@
     throw "Can't parse float: " + s;
 }
 
-function cat(s1, s2) {
-  return s1 + s2;
+function uf(s) {
+  return escape(s).replace(new RegExp ("/", "g"), "%2F");
 }
 
+function uu(s) {
+  return unescape(s).replace(new RegExp ("\\+", "g"), " ");
+}
+
+
+// Error handling
+
 function whine(msg) {
   alert(msg);
   throw msg;
@@ -167,18 +225,8 @@
   whine("Pattern match failure");
 }
 
-var closures = [];
 
-function ca(f) {
-  var n = closures.length;
-  closures[n] = f;
-  return n;
-}
-
-function cr(n) {
-  return closures[n]();
-}
-
+// Remote calls
 
 var client_id = 0;
 var client_pass = 0;
@@ -364,11 +412,3 @@
     k(parse(msg))(null);
   }
 }
-
-function uf(s) {
-  return escape(s).replace(new RegExp ("/", "g"), "%2F");
-}
-
-function uu(s) {
-  return unescape(s).replace(new RegExp ("\\+", "g"), " ");
-}
--- a/src/compiler.sig	Sat Apr 04 11:46:24 2009 -0400
+++ b/src/compiler.sig	Sat Apr 04 12:54:39 2009 -0400
@@ -69,10 +69,10 @@
     val shake : (Core.file, Core.file) phase
     val rpcify : (Core.file, Core.file) phase
     val tag : (Core.file, Core.file) phase
-    val marshalcheck : (Core.file, Core.file) phase
     val reduce : (Core.file, Core.file) phase
     val unpoly : (Core.file, Core.file) phase
     val specialize : (Core.file, Core.file) phase
+    val marshalcheck : (Core.file, Core.file) phase
     val monoize : (Core.file, Mono.file) phase
     val mono_opt : (Mono.file, Mono.file) phase
     val untangle : (Mono.file, Mono.file) phase
@@ -100,11 +100,11 @@
     val toCore_untangle2 : (string, Core.file) transform
     val toShake2 : (string, Core.file) transform
     val toTag : (string, Core.file) transform
-    val toMarshalcheck : (string, Core.file) transform
     val toReduce : (string, Core.file) transform
     val toUnpoly : (string, Core.file) transform 
     val toSpecialize : (string, Core.file) transform 
     val toShake3 : (string, Core.file) transform
+    val toMarshalcheck : (string, Core.file) transform
     val toMonoize : (string, Mono.file) transform
     val toMono_opt1 : (string, Mono.file) transform
     val toUntangle : (string, Mono.file) transform
--- a/src/compiler.sml	Sat Apr 04 11:46:24 2009 -0400
+++ b/src/compiler.sml	Sat Apr 04 12:54:39 2009 -0400
@@ -475,19 +475,12 @@
 
 val toTag = transform tag "tag" o toCore_untangle2
 
-val marshalcheck = {
-    func = (fn file => (MarshalCheck.check file; file)),
-    print = CorePrint.p_file CoreEnv.empty
-}
-
-val toMarshalcheck = transform marshalcheck "marshalcheck" o toTag
-
 val reduce = {
     func = Reduce.reduce,
     print = CorePrint.p_file CoreEnv.empty
 }
 
-val toReduce = transform reduce "reduce" o toMarshalcheck
+val toReduce = transform reduce "reduce" o toTag
 
 val unpoly = {
     func = Unpoly.unpoly,
@@ -505,12 +498,19 @@
 
 val toShake3 = transform shake "shake3" o toSpecialize
 
+val marshalcheck = {
+    func = (fn file => (MarshalCheck.check file; file)),
+    print = CorePrint.p_file CoreEnv.empty
+}
+
+val toMarshalcheck = transform marshalcheck "marshalcheck" o toShake3
+
 val monoize = {
     func = Monoize.monoize CoreEnv.empty,
     print = MonoPrint.p_file MonoEnv.empty
 }
 
-val toMonoize = transform monoize "monoize" o toShake3
+val toMonoize = transform monoize "monoize" o toMarshalcheck
 
 val mono_opt = {
     func = MonoOpt.optimize,
--- a/src/jscomp.sml	Sat Apr 04 11:46:24 2009 -0400
+++ b/src/jscomp.sml	Sat Apr 04 12:54:39 2009 -0400
@@ -891,9 +891,9 @@
 
                           | EJavaScript (Source _, _, SOME _) => (e, st)
                           | EJavaScript (_, _, SOME e) =>
-                            (strcat [str "\"cr(\"+ca(function(){return ",
+                            (strcat [str "function(){return ",
                                      e,
-                                     str "})+\")\""],
+                                     str "}"],
                              st)
 
                           | EClosure _ => unsupported "EClosure"
@@ -905,9 +905,9 @@
                             let
                                 val (e, st) = jsE inner (e, st)
                             in
-                                (strcat [str "\"cr(\"+ca(function(){return ",
+                                (strcat [str "function(){return ",
                                          e,
-                                         str "})+\")\""],
+                                         str "}"],
                                  st)
                             end
 
--- a/src/marshalcheck.sml	Sat Apr 04 11:46:24 2009 -0400
+++ b/src/marshalcheck.sml	Sat Apr 04 12:54:39 2009 -0400
@@ -58,7 +58,8 @@
                       ("Basis", "string"),
                       ("Basis", "time"),
                       ("Basis", "unit"),
-                      ("Basis", "option")]
+                      ("Basis", "option"),
+                      ("Basis", "bool")]
 
 val clientToServer = PS.addList (PS.empty, clientToServer)