[m-rev.] for review: Re-factor the MR_join_and_continue macro.

Paul Bone pbone at csse.unimelb.edu.au
Mon Nov 23 14:09:01 AEDT 2009


For review by someone familiar with the low-level C backend, probably Zoltan.

 - Thanks, Paul.

Re-factor the MR_join_and_continue macro.

This change replaces the MR_join_and_continue macro with a Mercury C procedure.
This macro is used in the implementation of parallel conjunctions in the low
level C grades.  This means that this code will always be a procedure call
rather than always being in-lined.

This change also required changes to the compiler, namely in the hlds->llds
and llds->C transformations for parallel conjunctions.

runtime/mercury_context.h:
runtime/mercury_context.c:
    Created MR_do_join_and_continue procedure from old MR_join_and_continue
    macro.
    Created a new macro MR_join_and_continue that wraps the new procedure.
    Added additional comments to this procedure, describing how it works.

compiler/llds.m:
    Modified the LLDS data structure:
        Removed the synchronization term parameter from the join_and_continue
        instruction.
        Added a new memory reference, one can now address data on the parent
        context's stack.

compiler/par_conj_gen.m:
    Modified the generation of the join and continue code.  This now includes
    instructions for saving a pointer to the synchronization term into MR_r1,
    before calling MR_join_and_continue.
    Added an XXX: How to I tell the low-level backend that I will clobber MR_r1
    and MR_succip?  Could someone familiar with the low-level backend help me?

compiler/llds_out_data.m:
    Generate code for taking the address of something on the parent context's
    stack.

compiler/llds_out_instr.m:
    Alter the code generation for the join_and_continue instruction.

compiler/opt_util.m:
    Conform to changes in llds.m.
    Introduced an XXX: I don't know if join_and_continue use livevals.  Can
    someone familiar with this part of the compiler advise me?

compiler/code_util.m:
compiler/dupelim.m:
compiler/dupproc.m:
compiler/exprn_aux.m:
compiler/global_data.m:
compiler/jumpopt.m:
compiler/livemap.m:
compiler/llds_out_file.m:
compiler/llds_to_x86_64.m:
compiler/middle_rec.m:
compiler/opt_debug.m:
compiler/opt_util.m:
compiler/reassign.m:
compiler/use_local_vars.m:
compiler/var_locn.m:
    Conform to changes in llds.m
    In some cases code has been re-factored to factor out code common to a
    number of switch arms.

Index: compiler/code_util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/code_util.m,v
retrieving revision 1.186
diff -u -p -b -r1.186 code_util.m
--- compiler/code_util.m	30 Oct 2009 03:33:12 -0000	1.186
+++ compiler/code_util.m	20 Nov 2009 10:30:53 -0000
@@ -383,6 +383,7 @@ lvals_in_lval(global_var_ref(_)) = [].
 :- func lvals_in_mem_ref(mem_ref) = list(lval).
 
 lvals_in_mem_ref(stackvar_ref(Rval)) = lvals_in_rval(Rval).
+lvals_in_mem_ref(parent_stackvar_ref(Rval)) = lvals_in_rval(Rval).
 lvals_in_mem_ref(framevar_ref(Rval)) = lvals_in_rval(Rval).
 lvals_in_mem_ref(heap_ref(Rval1, _, Rval2)) =
     lvals_in_rval(Rval1) ++ lvals_in_rval(Rval2).
Index: compiler/dupelim.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/dupelim.m,v
retrieving revision 1.94
diff -u -p -b -r1.94 dupelim.m
--- compiler/dupelim.m	21 Oct 2009 06:36:18 -0000	1.94
+++ compiler/dupelim.m	22 Nov 2009 00:19:54 -0000
@@ -425,10 +425,6 @@ standardize_instr(Instr0, Instr) :-
         standardize_lval(Lval0, Lval),
         Instr = init_sync_term(Lval, N)
     ;
-        Instr0 = join_and_continue(Lval0, Label),
-        standardize_lval(Lval0, Lval),
-        Instr = join_and_continue(Lval, Label)
-    ;
         ( Instr0 = comment(_)
         ; Instr0 = livevals(_)
         ; Instr0 = block(_, _, _)
@@ -447,6 +443,7 @@ standardize_instr(Instr0, Instr) :-
         ; Instr0 = decr_sp_and_return(_)
         ; Instr0 = fork_new_child(_, _)
         ; Instr0 = foreign_proc_code(_, _, _, _, _, _, _, _, _, _)
+        ; Instr0 = join_and_continue(_)
         ),
         Instr = Instr0
     ).
@@ -836,7 +833,7 @@ most_specific_instr(InstrA, InstrB, Mayb
         ; InstrA = foreign_proc_code(_, _, _, _, _, _, _, _, _, _)
         ; InstrA = fork_new_child(_, _)
         ; InstrA = init_sync_term(_, _)
-        ; InstrA = join_and_continue(_, _)
+        ; InstrA = join_and_continue(_)
         ),
         ( InstrA = InstrB ->
             MaybeInstr = yes(InstrA)
Index: compiler/dupproc.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/dupproc.m,v
retrieving revision 1.25
diff -u -p -b -r1.25 dupproc.m
--- compiler/dupproc.m	21 Oct 2009 06:36:18 -0000	1.25
+++ compiler/dupproc.m	22 Nov 2009 00:20:38 -0000
@@ -226,9 +226,9 @@ standardize_instr(Instr, StdInstr, DupPr
         standardize_label(Child, StdChild, DupProcMap),
         StdInstr = fork_new_child(Lval, StdChild)
     ;
-        Instr = join_and_continue(Lval, Label),
+        Instr = join_and_continue(Label),
         standardize_label(Label, StdLabel, DupProcMap),
-        StdInstr = join_and_continue(Lval, StdLabel)
+        StdInstr = join_and_continue(StdLabel)
     ;
         % The labels occurring in foreign_proc_code instructions
         % cannot be substituted.
Index: compiler/exprn_aux.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/exprn_aux.m,v
retrieving revision 1.90
diff -u -p -b -r1.90 exprn_aux.m
--- compiler/exprn_aux.m	30 Oct 2009 03:33:13 -0000	1.90
+++ compiler/exprn_aux.m	22 Nov 2009 00:21:31 -0000
@@ -234,6 +234,8 @@ vars_in_lval(lvar(Var), [Var]).
 
 vars_in_mem_ref(stackvar_ref(Rval), Vars) :-
     vars_in_rval(Rval, Vars).
+vars_in_mem_ref(parent_stackvar_ref(Rval), Vars) :-
+    vars_in_rval(Rval, Vars).
 vars_in_mem_ref(framevar_ref(Rval), Vars) :-
     vars_in_rval(Rval, Vars).
 vars_in_mem_ref(heap_ref(BaseRval, _Tag, FieldRval), BaseVars ++ FieldVars) :-
@@ -263,6 +265,7 @@ transform_lval_in_uinstr(Transform, Uins
         ; Uinstr0 = decr_sp(_)
         ; Uinstr0 = decr_sp_and_return(_)
         ; Uinstr0 = fork_new_child(_, _)
+        ; Uinstr0 = join_and_continue(_)
         ),
         Uinstr = Uinstr0
     ;
@@ -404,10 +407,6 @@ transform_lval_in_uinstr(Transform, Uins
         Uinstr0 = init_sync_term(Lval0, BranchCount),
         Transform(Lval0, Lval, !Acc),
         Uinstr = init_sync_term(Lval, BranchCount)
-    ;
-        Uinstr0 = join_and_continue(Lval0, Label),
-        Transform(Lval0, Lval, !Acc),
-        Uinstr = join_and_continue(Lval, Label)
     ).
 
 :- pred transform_lval_in_component(transform_lval(T)::in(transform_lval),
@@ -514,6 +513,10 @@ transform_lval_in_mem_ref(Transform, Mem
         transform_lval_in_rval(Transform, Rval0, Rval, !Acc),
         MemRef = stackvar_ref(Rval)
     ;
+        MemRef0 = parent_stackvar_ref(Rval0),
+        transform_lval_in_rval(Transform, Rval0, Rval, !Acc),
+        MemRef = parent_stackvar_ref(Rval)
+    ;
         MemRef0 = framevar_ref(Rval0),
         transform_lval_in_rval(Transform, Rval0, Rval, !Acc),
         MemRef = framevar_ref(Rval)
@@ -643,6 +646,9 @@ substitute_rval_in_mem_ref(OldRval, NewR
         MemRef0 = stackvar_ref(N),
         MemRef = stackvar_ref(N)
     ;
+        MemRef0 = parent_stackvar_ref(N),
+        MemRef = parent_stackvar_ref(N)
+    ;
         MemRef0 = framevar_ref(N),
         MemRef = framevar_ref(N)
     ;
@@ -870,6 +876,7 @@ lval_list_addrs([Lval | Lvals], CodeAddr
     list(code_addr)::out, list(data_id)::out) is det.
 
 mem_ref_addrs(stackvar_ref(_SlotNum), [], []).
+mem_ref_addrs(parent_stackvar_ref(_SlotNum), [], []).
 mem_ref_addrs(framevar_ref(_SlotNum), [], []).
 mem_ref_addrs(heap_ref(Rval, _Tag, _FieldNum), CodeAddrs, DataIds) :-
     rval_addrs(Rval, CodeAddrs, DataIds).
Index: compiler/global_data.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/global_data.m,v
retrieving revision 1.43
diff -u -p -b -r1.43 global_data.m
--- compiler/global_data.m	30 Oct 2009 03:33:13 -0000	1.43
+++ compiler/global_data.m	22 Nov 2009 00:22:11 -0000
@@ -1020,10 +1020,6 @@ remap_instr(Remap, Instr0, Instr) :-
         remap_lval(Remap, Lval0, Lval),
         Instr = init_sync_term(Lval, NumJoins)
     ;
-        Instr0 = join_and_continue(Lval0, Label),
-        remap_lval(Remap, Lval0, Lval),
-        Instr = join_and_continue(Lval, Label)
-    ;
         ( Instr0 = comment(_)
         ; Instr0 = livevals(_)
         ; Instr0 = llcall(_, _, _, _, _, _)
@@ -1037,6 +1033,7 @@ remap_instr(Remap, Instr0, Instr) :-
         ; Instr0 = decr_sp(_)
         ; Instr0 = decr_sp_and_return(_)
         ; Instr0 = fork_new_child(_, _)
+        ; Instr0 = join_and_continue(_)
         ),
         Instr = Instr0
     ).
@@ -1196,6 +1193,7 @@ remap_rval_const(Remap, Const0, Const) :
 remap_mem_ref(Remap, MemRef0, MemRef) :-
     (
         ( MemRef0 = stackvar_ref(_)
+        ; MemRef0 = parent_stackvar_ref(_)
         ; MemRef0 = framevar_ref(_)
         ),
         MemRef = MemRef0
Index: compiler/jumpopt.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/jumpopt.m,v
retrieving revision 1.112
diff -u -p -b -r1.112 jumpopt.m
--- compiler/jumpopt.m	21 Oct 2009 06:36:19 -0000	1.112
+++ compiler/jumpopt.m	22 Nov 2009 00:23:22 -0000
@@ -798,12 +798,12 @@ jump_opt_instr_list([Instr0 | Instrs0], 
             NewRemain = specified([Instr], Instrs0)
         )
     ;
-        Uinstr0 = join_and_continue(SyncTerm, Label0),
+        Uinstr0 = join_and_continue(Label0),
         short_label(Instrmap, Label0, Label),
         ( Label = Label0 ->
             NewRemain = usual_case
         ;
-            Uinstr = join_and_continue(SyncTerm, Label),
+            Uinstr = join_and_continue(Label),
             Comment = Comment0 ++ " (redirect)",
             Instr = llds_instr(Uinstr, Comment),
             NewRemain = specified([Instr], Instrs0)
Index: compiler/livemap.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/livemap.m,v
retrieving revision 1.93
diff -u -p -b -r1.93 livemap.m
--- compiler/livemap.m	21 Oct 2009 06:36:19 -0000	1.93
+++ compiler/livemap.m	22 Nov 2009 00:27:54 -0000
@@ -350,7 +350,7 @@ livemap_do_build_instr(Instr0, !Instrs, 
     ;
         Uinstr0 = fork_new_child(_, _)
     ;
-        Uinstr0 = join_and_continue(_, _)
+        Uinstr0 = join_and_continue(_)
     ;
         Uinstr0 = arbitrary_c_code(AffectsLiveness, LiveLvalInfo, Code),
         build_live_lval_info(AffectsLiveness, LiveLvalInfo, Code,
@@ -523,6 +523,8 @@ make_live_in_rval(mem_addr(MemRef), !Liv
 
 make_live_in_mem_ref(stackvar_ref(Rval), !Live) :-
     make_live_in_rval(Rval, !Live).
+make_live_in_mem_ref(parent_stackvar_ref(Rval), !Live) :-
+    make_live_in_rval(Rval, !Live).
 make_live_in_mem_ref(framevar_ref(Rval), !Live) :-
     make_live_in_rval(Rval, !Live).
 make_live_in_mem_ref(heap_ref(Rval1, _, Rval2), !Live) :-
Index: compiler/llds.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/llds.m,v
retrieving revision 1.365
diff -u -p -b -r1.365 llds.m
--- compiler/llds.m	30 Oct 2009 03:33:14 -0000	1.365
+++ compiler/llds.m	22 Nov 2009 10:33:18 -0000
@@ -621,13 +621,15 @@
             % the synchronisation term. Control continues at the next
             % instruction.
 
-    ;       join_and_continue(lval, label).
+    ;       join_and_continue(label).
             % Signal that this thread of execution has finished in the current
             % parallel conjunct. For details of how we at the end of a parallel
-            % conjunct see runtime/mercury_context.{c,h}.
-            % The synchronisation term is specified by the given lval.
-            % The label gives the address of the code following the parallel
-            % conjunction. 
+            % conjunct see runtime/mercury_context.{c,h}.  The value in MR_r1
+            % points to The synchronisation term.  The label gives the address
+            % of the code following the parallel conjunction.  The
+            % MR_join_and_continue macro loads the address of the label into
+            % MR_succip before jumping to the implementation of
+            % MR_do_join_and_continue. 
 
 :- type stack_incr_kind
     --->    stack_incr_leaf         % The incr_sp creates the stack frame
@@ -1129,8 +1131,9 @@
             % stack.
 
 :- type mem_ref
-    --->    stackvar_ref(rval)          % Stack slot number.
-    ;       framevar_ref(rval)          % Stack slot number.
+    --->    stackvar_ref(rval)          % Det stack slot number.
+    ;       parent_stackvar_ref(rval)   % Parent's det stack slot number.
+    ;       framevar_ref(rval)          % Nondet stack slot number.
     ;       heap_ref(rval, int, rval).  % The cell pointer, the tag to
                                         % subtract, and the field number.
 
Index: compiler/llds_out_data.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/llds_out_data.m,v
retrieving revision 1.1
diff -u -p -b -r1.1 llds_out_data.m
--- compiler/llds_out_data.m	4 Nov 2009 03:44:48 -0000	1.1
+++ compiler/llds_out_data.m	20 Nov 2009 10:52:12 -0000
@@ -756,6 +756,7 @@ output_record_mem_ref_decls_format(Info,
         !N, !DeclSet, !IO) :-
     (
         ( MemRef = stackvar_ref(Rval)
+        ; MemRef = parent_stackvar_ref(Rval)
         ; MemRef = framevar_ref(Rval)
         ),
         output_record_rval_decls_format(Info, Rval,
@@ -957,18 +958,16 @@ output_rval(Info, Rval, !IO) :-
     ;
         Rval = mem_addr(MemRef),
         (
+            (
             MemRef = stackvar_ref(SubRval),
-            io.write_string("&MR_sv(", !IO),
-            % Don't clutter the output with unnecessary casts.
-            ( SubRval = const(llconst_int(SlotNum)) ->
-                io.write_int(SlotNum, !IO)
+                io.write_string("&MR_sv(", !IO)
             ;
-                output_rval_as_type(Info, SubRval, lt_integer, !IO)
-            ),
-            io.write_string(")", !IO)
+                MemRef = parent_stackvar_ref(SubRval),
+                io.write_string("&MR_parent_sv(", !IO)
         ;
             MemRef = framevar_ref(SubRval),
-            io.write_string("&MR_fv(", !IO),
+                io.write_string("&MR_fv(", !IO)
+            ),
             % Don't clutter the output with unnecessary casts.
             ( SubRval = const(llconst_int(SlotNum)) ->
                 io.write_int(SlotNum, !IO)
Index: compiler/llds_out_file.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/llds_out_file.m,v
retrieving revision 1.1
diff -u -p -b -r1.1 llds_out_file.m
--- compiler/llds_out_file.m	4 Nov 2009 03:44:48 -0000	1.1
+++ compiler/llds_out_file.m	22 Nov 2009 00:28:30 -0000
@@ -1134,7 +1134,7 @@ find_cont_labels([Instr | Instrs], !Cont
         ;
             Uinstr = mkframe(_, yes(code_label(ContLabel)))
         ;
-            Uinstr = join_and_continue(_, ContLabel)
+            Uinstr = join_and_continue(ContLabel)
         ;
             Uinstr = assign(redoip_slot(_), const(Const)),
             Const = llconst_code_addr(code_label(ContLabel))
Index: compiler/llds_out_instr.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/llds_out_instr.m,v
retrieving revision 1.1
diff -u -p -b -r1.1 llds_out_instr.m
--- compiler/llds_out_instr.m	4 Nov 2009 03:44:48 -0000	1.1
+++ compiler/llds_out_instr.m	22 Nov 2009 00:38:03 -0000
@@ -233,8 +233,7 @@ output_record_instr_decls(Info, Instr, !
         output_record_lval_decls(Info, Lval, !DeclSet, !IO),
         output_record_code_addr_decls(Info, code_label(Child), !DeclSet, !IO)
     ;
-        Instr = join_and_continue(Lval, Label),
-        output_record_lval_decls(Info, Lval, !DeclSet, !IO),
+        Instr = join_and_continue(Label),
         output_record_code_addr_decls(Info, code_label(Label), !DeclSet, !IO)
     ).
 
@@ -905,10 +904,8 @@ output_instruction(Info, Instr, ProfInfo
         output_label_as_code_addr(Child, !IO),
         io.write_string(");\n", !IO)
     ;
-        Instr = join_and_continue(Lval, Label),
+        Instr = join_and_continue(Label),
         io.write_string("\tMR_join_and_continue(", !IO),
-        output_lval(Info, Lval, !IO),
-        io.write_string(", ", !IO),
         output_label_as_code_addr(Label, !IO),
         io.write_string(");\n", !IO)
     ).
Index: compiler/llds_to_x86_64.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/llds_to_x86_64.m,v
retrieving revision 1.13
diff -u -p -b -r1.13 llds_to_x86_64.m
--- compiler/llds_to_x86_64.m	4 Nov 2009 03:44:48 -0000	1.13
+++ compiler/llds_to_x86_64.m	22 Nov 2009 00:29:49 -0000
@@ -438,7 +438,7 @@ instr_to_x86_64(!RegMap, init_sync_term(
     Instr = [x86_64_comment("<<init_sync_term>>")].
 instr_to_x86_64(!RegMap, fork_new_child(_, _), Instr) :-
     Instr = [x86_64_comment("<<fork_new_child>>")].
-instr_to_x86_64(!RegMap, join_and_continue(_, _), Instr) :-
+instr_to_x86_64(!RegMap, join_and_continue(_), Instr) :-
     Instr = [x86_64_comment("<<join_and_continue>>")].
 
     % Transform lval into either an x86_64 operand or x86_64 instructions.
@@ -700,6 +700,8 @@ transform_rval(!RegMap, binop(Op, Rval1,
     ).
 transform_rval(!RegMap, mem_addr(stackvar_ref(Rval)), Op, no) :-
     transform_rval(!RegMap, Rval, Op, _).
+transform_rval(!RegMap, mem_addr(parent_stackvar_ref(Rval)), Op, no) :-
+    transform_rval(!RegMap, Rval, Op, _).
 transform_rval(!RegMap, mem_addr(framevar_ref(Rval)), Op, no) :-
     transform_rval(!RegMap, Rval, Op, _).
 transform_rval(!RegMap, mem_addr(heap_ref(Rval1, Tag, Rval2)), no, Instrs) :-
Index: compiler/middle_rec.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/middle_rec.m,v
retrieving revision 1.139
diff -u -p -b -r1.139 middle_rec.m
--- compiler/middle_rec.m	21 Oct 2009 06:36:20 -0000	1.139
+++ compiler/middle_rec.m	22 Nov 2009 00:33:02 -0000
@@ -529,6 +529,7 @@ find_used_registers_instr(Uinstr, !Used)
         ; Uinstr = incr_sp(_, _, _)
         ; Uinstr = decr_sp(_)
         ; Uinstr = decr_sp_and_return(_)
+        ; Uinstr = join_and_continue(_)
         )
     ;
         Uinstr = livevals(LvalSet),
@@ -595,7 +596,6 @@ find_used_registers_instr(Uinstr, !Used)
         ; Uinstr = mark_ticket_stack(Lval)
         ; Uinstr = init_sync_term(Lval, _)
         ; Uinstr = fork_new_child(Lval, _)
-        ; Uinstr = join_and_continue(Lval, _)
         ),
         find_used_registers_lval(Lval, !Used)
     ).
@@ -676,6 +676,8 @@ find_used_registers_rval(Rval, !Used) :-
 
 find_used_registers_mem_ref(stackvar_ref(Rval), !Used) :-
     find_used_registers_rval(Rval, !Used).
+find_used_registers_mem_ref(parent_stackvar_ref(Rval), !Used) :-
+    find_used_registers_rval(Rval, !Used).
 find_used_registers_mem_ref(framevar_ref(Rval), !Used) :-
     find_used_registers_rval(Rval, !Used).
 find_used_registers_mem_ref(heap_ref(Rval1, _, Rval2), !Used) :-
Index: compiler/opt_debug.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/opt_debug.m,v
retrieving revision 1.214
diff -u -p -b -r1.214 opt_debug.m
--- compiler/opt_debug.m	4 Nov 2009 03:44:49 -0000	1.214
+++ compiler/opt_debug.m	22 Nov 2009 00:24:23 -0000
@@ -354,6 +354,8 @@ dump_rvals(MaybeProcLabel, [Rval | Rvals
 
 dump_mem_ref(MaybeProcLabel, stackvar_ref(N)) =
     "stackvar_ref(" ++ dump_rval(MaybeProcLabel, N) ++ ")".
+dump_mem_ref(MaybeProcLabel, parent_stackvar_ref(N)) =
+    "parent_stackvar_ref(" ++ dump_rval(MaybeProcLabel, N) ++ ")".
 dump_mem_ref(MaybeProcLabel, framevar_ref(N)) =
     "framevar_ref(" ++ dump_rval(MaybeProcLabel, N) ++ ")".
 dump_mem_ref(MaybeProcLabel, heap_ref(R, T, N)) =
@@ -1027,9 +1029,8 @@ dump_instr(MaybeProcLabel, AutoComments,
         Str = "fork_new_child(" ++ dump_lval(MaybeProcLabel, Lval)
             ++ dump_label(MaybeProcLabel, Child) ++ ", " ++ ")"
     ;
-        Instr = join_and_continue(Lval, Label),
-        Str = "join_and_continue(" ++ dump_lval(MaybeProcLabel, Lval) ++ ", "
-            ++ dump_label(MaybeProcLabel, Label) ++ ")"
+        Instr = join_and_continue(Label),
+        Str = "join_and_continue(" ++ dump_label(MaybeProcLabel, Label) ++ ")"
     ;
         Instr = foreign_proc_code(Decls, Comps, MCM, MFNL, MFL, MFOL, MNF, MDL,
             SSR, MD),
Index: compiler/opt_util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/opt_util.m,v
retrieving revision 1.171
diff -u -p -b -r1.171 opt_util.m
--- compiler/opt_util.m	21 Oct 2009 06:36:21 -0000	1.171
+++ compiler/opt_util.m	22 Nov 2009 10:35:36 -0000
@@ -736,6 +736,7 @@ lval_refers_stackvars(global_var_ref(_))
 :- func mem_ref_refers_stackvars(mem_ref) = bool.
 
 mem_ref_refers_stackvars(stackvar_ref(_)) = yes.
+mem_ref_refers_stackvars(parent_stackvar_ref(_)) = yes.
 mem_ref_refers_stackvars(framevar_ref(_)) = yes.
 mem_ref_refers_stackvars(heap_ref(Rval1, _, Rval2)) =
     bool.or(rval_refers_stackvars(Rval1), rval_refers_stackvars(Rval2)).
@@ -887,7 +888,7 @@ instr_refers_to_stack(llds_instr(Uinstr,
         ; Uinstr = decr_sp_and_return(_)
         ; Uinstr = init_sync_term(_, _)
         ; Uinstr = fork_new_child(_, _)
-        ; Uinstr = join_and_continue(_, _)
+        ; Uinstr = join_and_continue(_)
         ),
         Refers = yes
     ;
@@ -1111,7 +1112,7 @@ can_instr_branch_away(decr_sp(_)) = no.
 can_instr_branch_away(decr_sp_and_return(_)) = yes.
 can_instr_branch_away(init_sync_term(_, _)) = no.
 can_instr_branch_away(fork_new_child(_, _)) = no.
-can_instr_branch_away(join_and_continue(_, _)) = yes.
+can_instr_branch_away(join_and_continue(_)) = yes.
 can_instr_branch_away(foreign_proc_code(_, Comps, _, _, _, _, _, _, _, _)) =
     can_components_branch_away(Comps).
 
@@ -1190,7 +1191,7 @@ can_instr_fall_through(decr_sp(_)) = yes
 can_instr_fall_through(decr_sp_and_return(_)) = no.
 can_instr_fall_through(init_sync_term(_, _)) = yes.
 can_instr_fall_through(fork_new_child(_, _)) = yes.
-can_instr_fall_through(join_and_continue(_, _)) = no.
+can_instr_fall_through(join_and_continue(_)) = no.
 can_instr_fall_through(foreign_proc_code(_, _, _, _, _, _, _, _, _, _)) = yes.
 
     % Check whether an instruction sequence can possibly fall through
@@ -1241,7 +1242,9 @@ can_use_livevals(decr_sp(_), no).
 can_use_livevals(decr_sp_and_return(_), yes).
 can_use_livevals(init_sync_term(_, _), no).
 can_use_livevals(fork_new_child(_, _), no).
-can_use_livevals(join_and_continue(_, _), no).
+% XXX: Is the synchronization term (now in R1) a liveval?, I don't want the
+% move to be optimized away. -pbone
+can_use_livevals(join_and_continue(_), no).
 can_use_livevals(foreign_proc_code(_, _, _, _, _, _, _, _, _, _), no).
 
 instr_labels(Instr, Labels, CodeAddrs) :-
@@ -1314,7 +1317,7 @@ instr_labels_2(Uinstr, Labels, CodeAddrs
         Labels = [Child],
         CodeAddrs = []
     ;
-        Uinstr = join_and_continue(_, Label),
+        Uinstr = join_and_continue(Label),
         Labels = [Label],
         CodeAddrs = []
     ;
@@ -1404,7 +1407,7 @@ possible_targets(Uinstr, Labels, CodeAdd
         % XXX see the comment in instr_labels_2.
         unexpected(this_file, "possible_targets: decr_sp_and_return")
     ;
-        Uinstr = join_and_continue(_, Label),
+        Uinstr = join_and_continue(Label),
         Labels = [Label],
         CodeAddrs = []
     ;
@@ -1544,7 +1547,7 @@ instr_rvals_and_lvals(decr_sp(_), [], []
 instr_rvals_and_lvals(decr_sp_and_return(_), [], []).
 instr_rvals_and_lvals(init_sync_term(Lval, _), [], [Lval]).
 instr_rvals_and_lvals(fork_new_child(Lval, _), [], [Lval]).
-instr_rvals_and_lvals(join_and_continue(Lval, _), [], [Lval]).
+instr_rvals_and_lvals(join_and_continue(_), [], []).
 instr_rvals_and_lvals(foreign_proc_code(_, Cs, _, _, _, _, _, _, _, _),
         Rvals, Lvals) :-
     foreign_proc_components_get_rvals_and_lvals(Cs, Rvals, Lvals).
@@ -1724,8 +1727,7 @@ count_temps_instr(init_sync_term(Lval, _
     count_temps_lval(Lval, !R, !F).
 count_temps_instr(fork_new_child(Lval, _), !R, !F) :-
     count_temps_lval(Lval, !R, !F).
-count_temps_instr(join_and_continue(Lval, _), !R, !F) :-
-    count_temps_lval(Lval, !R, !F).
+count_temps_instr(join_and_continue(_), !R, !F).
 count_temps_instr(foreign_proc_code(_, Comps, _, _, _, _, _, _, _, _),
         !R, !F) :-
     count_temps_components(Comps, !R, !F).
@@ -1855,6 +1857,7 @@ count_temps_rval(Rval, !R, !F) :-
 count_temps_mem_ref(MemRef, !R, !F) :-
     (
         ( MemRef = stackvar_ref(Rval)
+        ; MemRef = parent_stackvar_ref(Rval)
         ; MemRef = framevar_ref(Rval)
         ),
         count_temps_rval(Rval, !R, !F)
@@ -1933,7 +1936,7 @@ touches_nondet_ctrl_instr(Uinstr) = Touc
         ; Uinstr = restore_maxfr(_)
         ; Uinstr = init_sync_term(_, _)     % This is a safe approximation.
         ; Uinstr = fork_new_child(_, _)     % This is a safe approximation.
-        ; Uinstr = join_and_continue(_, _)  % This is a safe approximation.
+        ; Uinstr = join_and_continue(_)     % This is a safe approximation.
         ),
         Touch = yes
     ;
@@ -2064,6 +2067,7 @@ touches_nondet_ctrl_rval(mem_addr(MemRef
 :- func touches_nondet_ctrl_mem_ref(mem_ref) = bool.
 
 touches_nondet_ctrl_mem_ref(stackvar_ref(_)) = no.
+touches_nondet_ctrl_mem_ref(parent_stackvar_ref(_)) = no.
 touches_nondet_ctrl_mem_ref(framevar_ref(_)) = no.
 touches_nondet_ctrl_mem_ref(heap_ref(Rval, _, _)) =
     touches_nondet_ctrl_rval(Rval).
@@ -2497,10 +2501,9 @@ replace_labels_instr(Uinstr0, Uinstr, Re
         replace_labels_label(Child0, Child, ReplMap),
         Uinstr = fork_new_child(Lval, Child)
     ;
-        Uinstr0 = join_and_continue(Lval0, Label0),
+        Uinstr0 = join_and_continue(Label0),
         replace_labels_label(Label0, Label, ReplMap),
-        replace_labels_lval(Lval0, Lval, ReplMap),
-        Uinstr = join_and_continue(Lval, Label)
+        Uinstr = join_and_continue(Label)
     ;
         Uinstr0 = foreign_proc_code(Decls, Comps0, MayCallMercury,
             MaybeFix, MaybeLayout, MaybeOnlyLayout, MaybeSub0, MaybeDef,
@@ -2693,6 +2696,7 @@ replace_labels_rval(Rval0, Rval, ReplMap
 replace_labels_mem_ref(MemRef0, MemRef, ReplMap) :-
     (
         ( MemRef0 = stackvar_ref(_)
+        ; MemRef0 = parent_stackvar_ref(_)
         ; MemRef0 = framevar_ref(_)
         ),
         MemRef = MemRef0
Index: compiler/par_conj_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/par_conj_gen.m,v
retrieving revision 1.40
diff -u -p -b -r1.40 par_conj_gen.m
--- compiler/par_conj_gen.m	3 Sep 2009 23:07:28 -0000	1.40
+++ compiler/par_conj_gen.m	23 Nov 2009 03:05:41 -0000
@@ -186,11 +186,11 @@ generate_par_conj(Goals, GoalInfo, CodeM
     (
         % The highest numbered slot has the lowest address.
         list.last(SyncTermSlots, SyncTermBaseSlotPrime),
-        SyncTermBaseSlotPrime = stackvar(SlotNum),
+        SyncTermBaseSlotPrime = stackvar(SlotNumPrime),
         StackId = det_stack
     ->
         SyncTermBaseSlot = SyncTermBaseSlotPrime,
-        ParentSyncTermBaseSlot = parent_stackvar(SlotNum)
+        SlotNum = SlotNumPrime
     ;
         unexpected(this_file, "generate_par_conj")
     ),
@@ -204,8 +204,8 @@ generate_par_conj(Goals, GoalInfo, CodeM
     set_par_conj_depth(Depth+1, !CI),
     get_next_label(EndLabel, !CI),
     clear_all_registers(no, !CI),
-    generate_det_par_conj_2(Goals, ParentSyncTermBaseSlot, EndLabel, Initial,
-        no, GoalCode, !CI),
+    generate_det_par_conj_2(Goals, SlotNum, EndLabel, Initial, no, GoalCode,
+        !CI),
     set_par_conj_depth(Depth, !CI),
 
     EndLabelCode = singleton(
@@ -252,12 +252,12 @@ generate_par_conj(Goals, GoalInfo, CodeM
     place_all_outputs(Outputs, !CI).
 
 :- pred generate_det_par_conj_2(list(hlds_goal)::in,
-    lval::in, label::in, instmap::in, branch_end::in, llds_code::out,
+    int::in, label::in, instmap::in, branch_end::in, llds_code::out,
     code_info::in, code_info::out) is det.
 
-generate_det_par_conj_2([], _ParentSyncTermBaseSlot, _EndLabel,
+generate_det_par_conj_2([], _ParentSyncTermBaseSlotNum, _EndLabel,
         _Initial, _, empty, !CI).
-generate_det_par_conj_2([Goal | Goals], ParentSyncTermBaseSlot, EndLabel,
+generate_det_par_conj_2([Goal | Goals], ParentSyncTermBaseSlotNum, EndLabel,
         Initial, MaybeEnd0, Code, !CI) :-
     remember_position(!.CI, StartPos),
     code_gen.generate_goal(model_det, Goal, ThisGoalCode0, !CI),
@@ -271,6 +271,18 @@ generate_det_par_conj_2([Goal | Goals], 
     generate_branch_end(StoreMap, MaybeEnd0, MaybeEnd, SaveCode0, !CI),
     replace_stack_vars_by_parent_sv(SaveCode0, SaveCode),
 
+    ParentSyncTermBaseSlot = parent_stackvar(ParentSyncTermBaseSlotNum),
+    SyncTermPointer = mem_addr(parent_stackvar_ref(
+        const(llconst_int(ParentSyncTermBaseSlotNum)))),
+    % The move instruction clobbers MR_r1,
+    % The join_and_continue instruction clobbers MR_succip.
+    % XXX: How do I tell the low-level backend that I want to use these
+    % registers and arrange for anything important to be saved? -pbone
+    JoinInstructions = [
+        llds_instr(assign(reg(reg_r, 1), SyncTermPointer),
+            "Put the address of the sync term in r1"),
+        llds_instr(join_and_continue(EndLabel),
+            "Join after parallel execution")],
     (
         Goals = [_ | _],
         get_next_label(NextConjunct, !CI),
@@ -279,22 +291,17 @@ generate_det_par_conj_2([Goal | Goals], 
             llds_instr(fork_new_child(ParentSyncTermBaseSlot, NextConjunct),
                 "fork off a child")
         ),
-        JoinCode = from_list([
-            llds_instr(join_and_continue(ParentSyncTermBaseSlot, EndLabel),
-                "finish"),
-            llds_instr(label(NextConjunct),
-                "start of the next conjunct")
-        ])
+        JoinCode = from_list( JoinInstructions ++ 
+                [llds_instr(label(NextConjunct),
+            "start of the next conjunct")]
+        )
     ;
         Goals = [],
         ForkCode = empty,
-        JoinCode = singleton(
-            llds_instr(join_and_continue(ParentSyncTermBaseSlot, EndLabel),
-                "finish")
-        )
+        JoinCode = from_list(JoinInstructions)
     ),
     ThisCode = ForkCode ++ ThisGoalCode ++ SaveCode ++ JoinCode,
-    generate_det_par_conj_2(Goals, ParentSyncTermBaseSlot, EndLabel, Initial,
+    generate_det_par_conj_2(Goals, ParentSyncTermBaseSlotNum, EndLabel, Initial,
         MaybeEnd, RestCode, !CI),
     Code = ThisCode ++ RestCode.
 
Index: compiler/reassign.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/reassign.m,v
retrieving revision 1.30
diff -u -p -b -r1.30 reassign.m
--- compiler/reassign.m	21 Oct 2009 06:36:21 -0000	1.30
+++ compiler/reassign.m	22 Nov 2009 00:24:53 -0000
@@ -320,7 +320,7 @@ remove_reassign_loop([Instr0 | Instrs0],
         !:KnownContentsMap = map.init,
         !:DepLvalMap = map.init
     ;
-        Uinstr0 = join_and_continue(_, _),
+        Uinstr0 = join_and_continue(_),
         !:RevInstrs = [Instr0 | !.RevInstrs],
         % Other threads may modify any lval.
         !:KnownContentsMap = map.init,
Index: compiler/use_local_vars.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/use_local_vars.m,v
retrieving revision 1.40
diff -u -p -b -r1.40 use_local_vars.m
--- compiler/use_local_vars.m	21 Oct 2009 06:36:22 -0000	1.40
+++ compiler/use_local_vars.m	22 Nov 2009 00:25:11 -0000
@@ -690,7 +690,7 @@ substitute_lval_in_instr_until_defn_2(Ol
         ; Uinstr0 = decr_sp_and_return(_)
         ; Uinstr0 = init_sync_term(_, _)
         ; Uinstr0 = fork_new_child(_, _)
-        ; Uinstr0 = join_and_continue(_, _)
+        ; Uinstr0 = join_and_continue(_)
         ; Uinstr0 = arbitrary_c_code(_, _, _)
         )
     ).
Index: compiler/var_locn.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/var_locn.m,v
retrieving revision 1.68
diff -u -p -b -r1.68 var_locn.m
--- compiler/var_locn.m	2 Sep 2009 00:30:24 -0000	1.68
+++ compiler/var_locn.m	20 Nov 2009 21:52:41 -0000
@@ -2270,11 +2270,9 @@ var_locn_materialize_vars_in_rval_avoid(
 var_locn_materialize_vars_in_mem_ref_avoid(ModuleInfo, MemRef0, MemRef, Avoid,
         Code, !VLI) :-
     (
-        MemRef0 = stackvar_ref(_),
-        MemRef = MemRef0,
-        Code = empty
-    ;
-        MemRef0 = framevar_ref(_),
+        ( MemRef0 = stackvar_ref(_)
+        ; MemRef0 = parent_stackvar_ref(_)
+        ; MemRef0 = framevar_ref(_) ),
         MemRef = MemRef0,
         Code = empty
     ;
Index: runtime/mercury_context.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_context.c,v
retrieving revision 1.70
diff -u -p -b -r1.70 mercury_context.c
--- runtime/mercury_context.c	6 Nov 2009 05:40:24 -0000	1.70
+++ runtime/mercury_context.c	23 Nov 2009 02:56:02 -0000
@@ -811,9 +811,10 @@ MR_schedule_spark_globally(const MR_Spar
 
 #ifndef MR_HIGHLEVEL_CODE
 
+
 MR_define_extern_entry(MR_do_runnext);
 
-MR_BEGIN_MODULE(scheduler_module)
+MR_BEGIN_MODULE(scheduler_module_do_runnext)
     MR_init_entry_an(MR_do_runnext);
 MR_BEGIN_CODE
 
@@ -983,6 +984,133 @@ MR_define_entry(MR_do_runnext);
 
 MR_END_MODULE
 
+#if defined(MR_THREAD_SAFE) && defined(MR_LL_PARALLEL_CONJ) 
+MR_define_extern_entry(MR_do_join_and_continue);
+
+MR_BEGIN_MODULE(scheduler_module_do_join_and_continue)
+    MR_init_entry_an(MR_do_join_and_continue);
+MR_BEGIN_CODE
+
+MR_define_entry(MR_do_join_and_continue);
+{
+    MR_SyncTerm *jnc_st = (MR_SyncTerm *) MR_r1;
+
+    if (!jnc_st->MR_st_is_shared) {
+        /* This parallel conjunction has only executed sequentially. */
+        if (--jnc_st->MR_st_count == 0) {
+            /*
+            ** It has finished executing, continue execution from the join
+            ** label.
+            */
+            MR_proceed();
+        } else {
+            /*
+            ** It has not finished executing.  Try to finish it by executing
+            ** our sparks.
+            ** This code was formerly MR_join_and_continue_1() 
+            */
+            MR_Context  *jnc_ctxt;
+            MR_bool     jnc_popped;
+            MR_Spark    jnc_spark;
+
+            jnc_ctxt = MR_ENGINE(MR_eng_this_context);
+            jnc_popped = MR_wsdeque_pop_bottom(&jnc_ctxt->MR_ctxt_spark_deque,
+                &jnc_spark);
+            if (jnc_popped) {
+                MR_atomic_dec_int(&MR_num_outstanding_contexts_and_all_sparks);
+                MR_GOTO(jnc_spark.MR_spark_resume);
+            } else {
+                /*
+                ** Someone's stolen our sparks, we should try to execute
+                ** something that's been scheduled globally.
+                */
+                MR_runnext();
+            }
+        }
+    } else {
+        /* This parallel conjunction may be executing in parallel. */
+        MR_LOCK(&MR_sync_term_lock, "continue");
+        if (--jnc_st->MR_st_count == 0) {
+            /* This parallel conjunction has finished. */
+            if (MR_ENGINE(MR_eng_this_context) == jnc_st->MR_st_orig_context) {
+                /*
+                ** This context originated this parallel conjunction and all
+                ** the branches have finished so jump to the join label.
+                */
+                MR_UNLOCK(&MR_sync_term_lock, "continue i");
+                MR_proceed();
+            } else {
+                /*
+                ** This context didn't originate this parallel conjunction and
+                ** we're the last branch to finish.  The originating context
+                ** should be suspended waiting for us to finish, so wake it up.
+                */
+                jnc_st->MR_st_orig_context->MR_ctxt_resume = (MR_Code*)MR_succip;
+                MR_schedule_context(jnc_st->MR_st_orig_context);
+                MR_UNLOCK(&MR_sync_term_lock, "continue ii");
+                MR_runnext();
+            }
+        } else {
+            /*
+            ** The parallel conjunction is being executed in parallel but it is
+            ** not yet finished.  This code was Formerly
+            ** MR_join_and_continue_2() 
+            */
+            MR_Context  *jnc_ctxt;
+            MR_bool     jnc_popped;
+            MR_Spark    jnc_spark;
+
+            jnc_ctxt = MR_ENGINE(MR_eng_this_context);
+            jnc_popped = MR_wsdeque_pop_bottom(&jnc_ctxt->MR_ctxt_spark_deque,
+                &jnc_spark);
+            if (jnc_popped && (jnc_spark.MR_spark_parent_sp == MR_parent_sp)) {
+                /*
+                ** The spark at the top of the stack is from to the same parallel
+                ** conjunction that we've just been executing. We can immediately
+                ** execute the next branch of the same parallel conjunction in
+                ** the current context.
+                */
+                MR_UNLOCK(&MR_sync_term_lock, "continue_2 i");
+                MR_atomic_dec_int(&MR_num_outstanding_contexts_and_all_sparks);
+                MR_GOTO(jnc_spark.MR_spark_resume);
+            } else {
+                /*
+                ** The spark stack is empty or the next spark is from a different
+                ** parallel conjunction to the one we've been executing.  Either
+                ** way, there's nothing more we can do with this context right
+                ** now.  Put back the spark we won't be using.
+                */
+                if (jnc_popped) {
+                    MR_wsdeque_putback_bottom(&jnc_ctxt->MR_ctxt_spark_deque,
+                        &jnc_spark);
+                }
+                /*
+                ** If this context originated the parallel conjunction we've been
+                ** executing, the rest of the parallel conjunction must have been
+                ** put on the global spark queue to be executed in other
+                ** contexts.  This context will need to be resumed once the
+                ** parallel conjunction is completed, so suspend the context.
+                **
+                ** What if the other conjuncts where put on the global queue
+                ** but haven't yet been taken by other threads?  Then this step
+                ** is redundant.  It's not worth fixing, this problem will go
+                ** away once we enable work-stealing. - pbone. 
+                */
+                if (jnc_ctxt == jnc_st->MR_st_orig_context) {
+                    MR_save_context(jnc_ctxt);
+                    MR_ENGINE(MR_eng_this_context) = NULL;
+                }
+                /* Finally look for other work. */
+                MR_UNLOCK(&MR_sync_term_lock, "continue_2 ii");
+                MR_runnext();
+            }
+        }
+    }
+}
+MR_END_MODULE
+
+#endif /* defined(MR_THREAD_SAFE) && defined(MR_LL_PARALLEL_CONJ) */ 
+
 #endif /* !MR_HIGHLEVEL_CODE */
 
 #ifdef MR_LL_PARALLEL_CONJ
@@ -1051,7 +1179,10 @@ void mercury_sys_init_scheduler_wrapper_
 void mercury_sys_init_scheduler_wrapper_init(void)
 {
 #ifndef MR_HIGHLEVEL_CODE
-    scheduler_module();
+    scheduler_module_do_runnext();
+#if defined(MR_THREAD_SAFE) && defined(MR_LL_PARALLEL_CONJ) 
+    scheduler_module_do_join_and_continue();
+#endif
 #endif
 }
 
Index: runtime/mercury_context.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_context.h,v
retrieving revision 1.55
diff -u -p -b -r1.55 mercury_context.h
--- runtime/mercury_context.h	17 Nov 2009 06:30:26 -0000	1.55
+++ runtime/mercury_context.h	22 Nov 2009 06:33:40 -0000
@@ -811,111 +811,19 @@ extern  void        MR_schedule_context(
         MR_atomic_inc_int(&MR_num_outstanding_contexts_and_all_sparks);       \
     } while (0)
 
-  #define MR_join_and_continue(sync_term, join_label)                         \
-    do {                                                                      \
-        MR_SyncTerm *jnc_st = (MR_SyncTerm *) &sync_term;                     \
-                                                                              \
-        if (!jnc_st->MR_st_is_shared) {                                       \
-            /* This parallel conjunction has only executed sequentially. */   \
-            if (--jnc_st->MR_st_count == 0) {                                 \
-                MR_GOTO(join_label);                                          \
-            } else {                                                          \
-                MR_join_and_continue_1();                                     \
-            }                                                                 \
-        } else {                                                              \
-            /* This parallel conjunction may be executing in parallel. */     \
-            MR_LOCK(&MR_sync_term_lock, "continue");                          \
-            if (--jnc_st->MR_st_count == 0) {                                 \
-                if (MR_ENGINE(MR_eng_this_context)                            \
-                    == jnc_st->MR_st_orig_context)                            \
-                {                                                             \
-                    /*                                                        \
-                    ** This context originated this parallel conjunction and  \
-                    ** all the branches have finished so jump to the join     \
-                    ** label.                                                 \
-                    */                                                        \
-                    MR_UNLOCK(&MR_sync_term_lock, "continue i");              \
-                    MR_GOTO(join_label);                                      \
-                } else {                                                      \
-                    /*                                                        \
-                    ** This context didn't originate this parallel            \
-                    ** conjunction and we're the last branch to finish.  The  \
-                    ** originating context should be suspended waiting for us \
-                    ** to finish, so wake it up.                              \
-                    */                                                        \
-                    jnc_st->MR_st_orig_context->MR_ctxt_resume = join_label;  \
-                    MR_schedule_context(jnc_st->MR_st_orig_context);          \
-                    MR_UNLOCK(&MR_sync_term_lock, "continue ii");             \
-                    MR_runnext();                                             \
-                }                                                             \
-            } else {                                                          \
-                MR_join_and_continue_2();                                     \
-            }                                                                 \
-        }                                                                     \
-    } while (0)
-
-  #define MR_join_and_continue_1()                                            \
-    do {                                                                      \
-        MR_Context  *jnc_ctxt;                                                \
-        MR_bool     jnc_popped;                                               \
-        MR_Spark    jnc_spark;                                                \
-                                                                              \
-        jnc_ctxt = MR_ENGINE(MR_eng_this_context);                            \
-        jnc_popped = MR_wsdeque_pop_bottom(&jnc_ctxt->MR_ctxt_spark_deque,    \
-            &jnc_spark);                                                      \
-        if (jnc_popped) {                                                     \
-            MR_atomic_dec_int(&MR_num_outstanding_contexts_and_all_sparks);   \
-            MR_GOTO(jnc_spark.MR_spark_resume);                               \
-        } else {                                                              \
-            MR_runnext();                                                     \
-        }                                                                     \
-    } while (0)
-
-  #define MR_join_and_continue_2()                                            \
+  /*
+  ** At the end of a parallel conjunct this is called, depending on which
+  ** context calls this the context may block, jump to the join label or look
+  ** for other parallel work.
+  ** The arguments are:
+  ** MR_r1 - sync term pointer.
+  ** MR_succip - join label.
+  */
+  MR_declare_entry(MR_do_join_and_continue);
+  #define MR_join_and_continue(label) \
     do {                                                                      \
-        MR_Context  *jnc_ctxt;                                                \
-        MR_bool     jnc_popped;                                               \
-        MR_Spark    jnc_spark;                                                \
-                                                                              \
-        jnc_ctxt = MR_ENGINE(MR_eng_this_context);                            \
-        jnc_popped = MR_wsdeque_pop_bottom(&jnc_ctxt->MR_ctxt_spark_deque,    \
-            &jnc_spark);                                                      \
-        if (jnc_popped && (jnc_spark.MR_spark_parent_sp == MR_parent_sp)) {   \
-            /*                                                                \
-            ** The spark at the top of the stack is due to the same parallel  \
-            ** conjunction that we've just been executing. We can immediately \
-            ** execute the next branch of the same parallel conjunction in    \
-            ** the current context.                                           \
-            */                                                                \
-            MR_UNLOCK(&MR_sync_term_lock, "continue_2 i");                    \
-            MR_atomic_dec_int(&MR_num_outstanding_contexts_and_all_sparks);   \
-            MR_GOTO(jnc_spark.MR_spark_resume);                               \
-        } else {                                                              \
-            /*                                                                \
-            ** The spark stack is empty or the next spark is from a different \
-            ** parallel conjunction to the one we've been executing.  Either  \
-            ** way, there's nothing more we can do with this context right    \
-            ** now.  Put back the spark we won't be using.                    \
-            */                                                                \
-            if (jnc_popped) {                                                 \
-                MR_wsdeque_putback_bottom(&jnc_ctxt->MR_ctxt_spark_deque,     \
-                    &jnc_spark);                                              \
-            }                                                                 \
-            /*                                                                \
-            ** If this context originated the parallel conjunction we've been \
-            ** executing, the rest of the parallel conjunction must have been \
-            ** put on the global spark queue to be executed in other          \
-            ** contexts.  This context will need to be resumed once the       \
-            ** parallel conjunction is completed, so suspend the context.     \
-            */                                                                \
-            if (jnc_ctxt == jnc_st->MR_st_orig_context) {                     \
-                MR_save_context(jnc_ctxt);                                    \
-                MR_ENGINE(MR_eng_this_context) = NULL;                        \
-            }                                                                 \
-            /* Finally look for other work. */                                \
-            MR_UNLOCK(&MR_sync_term_lock, "continue_2 ii");                   \
-            MR_runnext();                                                     \
-        }                                                                     \
+        MR_succip_word = label; \
+        MR_GOTO(MR_ENTRY(MR_do_join_and_continue)); \
     } while (0)
 
   /* This needs to come after the definition of MR_SparkDeque_Struct. */
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 489 bytes
Desc: Digital signature
URL: <http://lists.mercurylang.org/archives/reviews/attachments/20091123/7b49eb75/attachment.sig>


More information about the reviews mailing list