[svn] r6158: nemerle/trunk/ncc: testsuite/positive/closures.n typing/TypedTree.n typing/Typer2.n

malekith svnadmin at nemerle.org
Mon Mar 13 08:29:41 CET 2006


Log:
Don't allow inlining of function with possibly needed closures. I guess this can cause performance hit in some cases, but it's hard-to-impossible to guess better here :/ Resolves #606.

Author: malekith
Date: Mon Mar 13 08:29:30 2006
New Revision: 6158

Modified:
   nemerle/trunk/ncc/testsuite/positive/closures.n
   nemerle/trunk/ncc/typing/TypedTree.n
   nemerle/trunk/ncc/typing/Typer2.n

Modified: nemerle/trunk/ncc/testsuite/positive/closures.n
==============================================================================
--- nemerle/trunk/ncc/testsuite/positive/closures.n	(original)
+++ nemerle/trunk/ncc/testsuite/positive/closures.n	Mon Mar 13 08:29:30 2006
@@ -10,6 +10,15 @@
 {
   static apply (f : void -> void) : void { f () }
 
+  public static Bug606 () : void
+  {
+    def d = Nemerle.Collections.Queue ();
+    foreach (x in [1..3])
+      d.Push (fun () { System.Console.WriteLine (x) });
+    while (!d.IsEmpty)
+      d.Take () ()
+  }
+
   public static Main () : void {
     def f2 (allow_ref) {
       when (allow_ref)
@@ -36,12 +45,15 @@
         ble: {
           def l = [1,2,3];
           foreach (x in l) {
-            _ = fun () { x }
+            // This cannot work in general...
+            // _ = fun () { x }
             when (x > 2) ble ();
           }
           System.Console.WriteLine ("oops");
         }
         System.Console.WriteLine ("qux");
+
+        Bug606 ();
   }
 
   public static Bug581 () : void
@@ -66,5 +78,8 @@
 foo
 4242
 qux
+1
+2
+3
 END-OUTPUT
 */

Modified: nemerle/trunk/ncc/typing/TypedTree.n
==============================================================================
--- nemerle/trunk/ncc/typing/TypedTree.n	(original)
+++ nemerle/trunk/ncc/typing/TypedTree.n	Mon Mar 13 08:29:30 2006
@@ -214,6 +214,8 @@
 
     public mutable usage : FunctionUsage;
     public mutable body : FunBody;
+    public mutable has_1st_class_child : bool;
+    public mutable cannot_inline : bool;
 
     /// local values defined in this function, which are closurised (used by children) 
     public mutable closure_vars : list [LocalValue] = [];

Modified: nemerle/trunk/ncc/typing/Typer2.n
==============================================================================
--- nemerle/trunk/ncc/typing/Typer2.n	(original)
+++ nemerle/trunk/ncc/typing/Typer2.n	Mon Mar 13 08:29:30 2006
@@ -441,9 +441,14 @@
             | _ => ()
           }
           v.InClosure = true;
-          v.DefinedIn.closure_vars = v :: v.DefinedIn.closure_vars;
+          v.DefinedIn.closure_vars ::= v;
         }
       }
+
+      // Message.Debug ($ "$(current_fun.name): $(current_fun.usage) $(current_fun.has_1st_class_child) $(current_fun.closure_vars)");
+
+      when (current_fun.has_1st_class_child && ! (current_fun.closure_vars is []))
+        current_fun.cannot_inline = true;
     }
 
 
@@ -754,10 +759,15 @@
                     // we may set just-once flag only if referencing
                     // from the outer function
                     if (decl.DefinedIn.id == current_fun.id &&
-                        (! hd.uses_try_block || ctx %&& Context.AllowTryAtFuncLev))
+                        (! hd.uses_try_block || ctx %&& Context.AllowTryAtFuncLev) &&
+                        !hd.cannot_inline) {
+                      //Message.Debug ($ "mark $(hd.name) just once");
                       hd.usage = FunctionUsage.UsedJustOnce
-                    else
+                    }
+                    else {
+                      //Message.Debug ($ "mark $(hd.name) used");
                       hd.usage = FunctionUsage.Used;
+                    }
                   | FunctionUsage.UsedJustOnce =>
                     hd.usage = FunctionUsage.Used
                   | FunctionUsage.Used | FunctionUsage.UsedAsFirstClass => ()
@@ -767,6 +777,12 @@
                 match (expr) {
                   | TExpr.LocalFunRef (_, []) =>
                     hd.usage = FunctionUsage.UsedAsFirstClass;
+                    def mark (fn) {
+                      fn.has_1st_class_child = true;
+                      unless (fn.decl == null)
+                        mark (fn.decl.DefinedIn)
+                    }
+                    mark (hd.decl.DefinedIn);
                     null
                   | TExpr.LocalFunRef as e =>
                     hd.usage = FunctionUsage.Used;



More information about the svn mailing list