[m-rev.] diff: Runtime changes to support tail recursion in loop control.

Paul Bone pbone at csse.unimelb.edu.au
Wed Oct 19 22:57:31 AEDT 2011


Hi Zoltan,

Here are the runtime changes I promised, they introduce two new macros:

    MR_lc_inc_worker_sp(lc, lcs, N)

        This macro increments the stack pointer by N slots of the context in
        the slot indicated by lcs within lc. 

    MR_lc_worker_sv(lc, lcs_idx, N)

        This macro allows you to access stack slots on the worker's stack.
        It is an lval so you should be able to assign to it or read from it
        like we do with the MR_sv and MR_parent_sv macros.

---

Runtime changes to support tail recursion in loop controlled code.

runtime/par_builtin.[ch]:
    Previously MR_lc_spawn_off setup context for loop control slots.  This code
    has been moved to MR_lc_wait_free_slot.

    Reset the stack pointer of a context in MR_lc_wait_free_slot since the
    stack pointer could have been left in a dirty state by a previous use -
    because of te way loop control will work.

    Also reset the stack pointer before releasing a context back to the free
    context pool.

    Provide new macros for manipulating the stack of a loop control worker
    context.

Index: runtime/mercury_par_builtin.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_par_builtin.c,v
retrieving revision 1.8
diff -u -p -b -r1.8 mercury_par_builtin.c
--- runtime/mercury_par_builtin.c	16 Oct 2011 03:34:39 -0000	1.8
+++ runtime/mercury_par_builtin.c	19 Oct 2011 11:52:39 -0000
@@ -116,15 +116,6 @@ MR_lc_spawn_off_func(MR_LoopControl *lc,
     fprintf(stderr, "lc_spawn_off(%p, %d, %p) sp: %p\n",
         lc, lcs_idx, code_ptr, MR_sp);
 #endif
-    if (lcs->MR_lcs_context == NULL) {
-        /*
-        ** Allocate a new context.
-        */
-        lcs->MR_lcs_context = MR_create_context("Loop control",
-            MR_CONTEXT_SIZE_FOR_LOOP_CONTROL_WORKER, NULL);
-        lcs->MR_lcs_context->MR_ctxt_thread_local_mutables =
-            MR_THREAD_LOCAL_MUTABLES;
-    }
 
     lcs->MR_lcs_context->MR_ctxt_resume = code_ptr;
     lcs->MR_lcs_context->MR_ctxt_parent_sp = MR_sp;
Index: runtime/mercury_par_builtin.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_par_builtin.h,v
retrieving revision 1.14
diff -u -p -b -r1.14 mercury_par_builtin.h
--- runtime/mercury_par_builtin.h	16 Oct 2011 03:34:40 -0000	1.14
+++ runtime/mercury_par_builtin.h	19 Oct 2011 11:52:39 -0000
@@ -423,7 +423,15 @@ extern MR_LoopControl   *MR_lc_create(un
                 ** saved in MR_join_and_terminate, which is important,      \
                 ** because if we did save it here we would write invalid    \
                 ** data into it.                                            \
+                **                                                          \
+                ** Reset the stack pointer, because loop control can some   \
+                ** times leave a stack frame on the stack, and the rest     \
+                ** of the runtime system will assume that the stack is      \
+                ** clean.                                                   \
                 */                                                          \
+                (lc)->MR_lc_slots[i].MR_lcs_context->MR_ctxt_sp =           \
+                    (lc)->MR_lc_slots[i].MR_lcs_context->                   \
+                    MR_ctxt_detstack_zone->MR_zone_min;                     \
                 MR_destroy_context((lc)->MR_lc_slots[i].MR_lcs_context);    \
             }                                                               \
         }                                                                   \
@@ -491,6 +499,24 @@ extern MR_Bool MR_lc_try_get_free_slot(M
             }                                                               \
         }                                                                   \
                                                                             \
+        if ((lc)->MR_lc_slots[i].MR_lcs_context == NULL) {                  \
+            /*                                                              \
+            ** Allocate a new context.                                      \
+            */                                                              \
+            (lc)->MR_lc_slots[i].MR_lcs_context =                           \
+                MR_create_context("Loop control",                           \
+                    MR_CONTEXT_SIZE_FOR_LOOP_CONTROL_WORKER, NULL);         \
+            (lc)->MR_lc_slots[i].MR_lcs_context->                           \
+                MR_ctxt_thread_local_mutables = MR_THREAD_LOCAL_MUTABLES;   \
+        }                                                                   \
+        /*                                                                  \
+        ** Reset the stack pointer of the context, it may have been left    \
+        ** in an inconsitent state.                                         \
+        */                                                                  \
+        (lc)->MR_lc_slots[i].MR_lcs_context->MR_ctxt_sp =                   \
+            (lc)->MR_lc_slots[i].MR_lcs_context->                           \
+            MR_ctxt_detstack_zone->MR_zone_min;                             \
+                                                                            \
         MR_IF_DEBUG_LOOP_CONTORL(                                           \
             fprintf(stderr, "lc_wait_free_slot returning %d, sp: %p\n",     \
                 (lcs_idx), MR_sp));                                         \
@@ -498,6 +524,23 @@ extern MR_Bool MR_lc_try_get_free_slot(M
     } while (0);
 
 /*
+** Add a frame to the stack of the worker context in the loop control slot.
+*/
+#define MR_lc_inc_worker_sp(lc, lcs_idx, N)                                 \
+    do {                                                                    \
+        MR_Context *ctxt;                                                   \
+                                                                            \
+        ctxt = (lc)->MR_lc_slots[lcs_idx].MR_lcs_context;                   \
+        MR_lcs_context->MR_ctxt_sp += N;                                    \
+    } while (0);
+
+/*
+** Access a slot on the stack of the worker context in the loop control slot.
+*/
+#define MR_lc_worker_sv(lc, lcs_idx, N)                                     \
+  MR_based_stackvar((lc)->MR_lc_slots[lc_idx].MR_lcs_context->MR_ctxt_sp, (N))
+
+/*
 ** Try to spawn off this code using the free slot.
 */
 #define MR_lc_spawn_off(lc, lcs_idx, label) \
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 490 bytes
Desc: Digital signature
URL: <http://lists.mercurylang.org/archives/reviews/attachments/20111019/fcd58097/attachment.sig>


More information about the reviews mailing list