Author: chromatic
Date: Fri Jun 15 01:42:22 2007
New Revision: 19019

Modified:
   trunk/src/pmc/sub.pmc
   trunk/t/op/calling.t

Log:
[GC] Increase context refcount as necessary (RT #43006 and #42790, Bram Geron).

Modified: trunk/src/pmc/sub.pmc
==============================================================================
--- trunk/src/pmc/sub.pmc       (original)
+++ trunk/src/pmc/sub.pmc       Fri Jun 15 01:42:22 2007
@@ -279,11 +279,12 @@
         /* set context of the sub */
         sub->ctx = context;
 
-        if (PObj_get_FLAGS(SELF) & SUB_FLAG_IS_OUTER) {
-            /* don't destroy context */
+        /* don't destroy context */
+        if (PObj_get_FLAGS(SELF) & SUB_FLAG_IS_OUTER)
             ccont->vtable = interp->vtables[enum_class_Continuation];
-            context->ref_count++;
-        }
+
+        /* reference counting should work */
+        context->ref_count++;
 
         if (!PMC_IS_NULL(INTERP->current_object)) {
             context->current_object = INTERP->current_object;
@@ -320,7 +321,7 @@
                 PObj_get_FLAGS(ccont) &= ~SUB_FLAG_TAILCALL;
                 context->caller_ctx    = caller_ctx->caller_ctx;
 
-                Parrot_free_context(INTERP, caller_ctx, 1);
+                Parrot_free_context(INTERP, caller_ctx, 0);
             }
         }
 

Modified: trunk/t/op/calling.t
==============================================================================
--- trunk/t/op/calling.t        (original)
+++ trunk/t/op/calling.t        Fri Jun 15 01:42:22 2007
@@ -7,7 +7,7 @@
 use lib qw( . lib ../lib ../../lib );
 
 use Test::More;
-use Parrot::Test tests => 94;
+use Parrot::Test tests => 95;
 
 =head1 NAME
 
@@ -2408,6 +2408,45 @@
 Have bar: 2
 OUTPUT
 
+pir_output_is( <<'CODE', <<'OUTPUT', "Tail call without arguments should not 
free the context when a closure depends on it" );
+.sub main :main
+    $P0 = create_closure_and_run_it()
+.end
+
+.sub create_closure_and_run_it
+    P0 = new "Integer"
+    P0 = 3
+    .lex "val", P0
+    P2 = get_global "myclosure"
+    P1 = newclosure P2
+    # There is a closure depending on our current context, so this shouldn't
+    # free it.
+    .return P1()
+.end
+
+.sub myclosure :outer(create_closure_and_run_it)
+    P1 = find_lex "val"
+    say P1
+    donothing()
+    P1 = find_lex "val"
+    say P1
+    .return ()
+.end
+
+.sub donothing
+    P0 = new "Integer"
+    P0 = 5
+    # This creates a new binding that is not accessible by the
+    # caller (myclosure)
+    .lex "val", P0
+    P2 = null
+    P1 = null
+.end
+CODE
+3
+3
+OUTPUT
+
 # Local Variables:
 #   mode: cperl
 #   cperl-indent-level: 4

Reply via email to