[m-rev.] fix agc bug for semidet procs

Fergus Henderson fjh at cs.mu.OZ.AU
Fri Dec 19 01:47:39 AEDT 2003


Estimated hours taken: 10
Branches: main

runtime/mercury_accurate_gc.c:
	Fix a bug where we were trying to traverse registers holding
	output arguments from semidet procedures even when those
	procedures had failed.  For the top-most frame, if the
	procedure which just returned was semidet, the registers
	other than MR_r1 will be live only if MR_r1 is non-zero.

Workspace: /home/jupiter/fjh/ws-jupiter/mercury
Index: runtime/mercury_accurate_gc.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_accurate_gc.c,v
retrieving revision 1.33
diff -u -d -r1.33 mercury_accurate_gc.c
--- runtime/mercury_accurate_gc.c	17 Dec 2003 10:27:24 -0000	1.33
+++ runtime/mercury_accurate_gc.c	18 Dec 2003 10:48:36 -0000
@@ -55,26 +55,29 @@
   MR_define_extern_entry(mercury__garbage_collect_0_0);
 
   static void   MR_LLDS_garbage_collect(MR_Code *saved_success,
-                        MR_Word *stack_pointer,
+                        MR_bool callee_model_semi, MR_Word *stack_pointer,
                         MR_Word *max_frame, MR_Word *current_frame);
   static void   traverse_det_stack(const MR_Label_Layout *label_layout,
+                        MR_bool callee_model_semi,
                         MR_Word *stack_pointer, MR_Word *current_frame);
   static void   traverse_nondet_stack(const MR_Label_Layout *label_layout,
-                        MR_Word *stack_pointer,
+                        MR_bool callee_model_semi, MR_Word *stack_pointer,
                         MR_Word *max_frame, MR_Word *current_frame);
   static void   traverse_nondet_frame(void *user_data,
                         const MR_Label_Layout *label_layout,
                         MR_Word *stack_pointer, MR_Word *current_frame);
-  static void   traverse_frame(MR_bool is_first_frame,
+  static MR_bool are_registers_live(MR_bool is_first_frame,
+                        MR_bool callee_model_semi);
+  static void   traverse_frame(MR_bool registers_live,
                         const MR_Label_Layout *label_layout,
                         MR_Word *stack_pointer, MR_Word *current_frame);
   static void   resize_and_reset_redzone(MR_MemoryZone *old_heap,
                         MR_MemoryZone *new_heap);
   static void   copy_long_value(MR_Long_Lval locn, MR_TypeInfo type_info, 
-                        MR_bool is_first_frame, MR_Word *stack_pointer,
+                        MR_bool registers_live, MR_Word *stack_pointer,
                         MR_Word *current_frame);
   static void   copy_short_value(MR_Short_Lval locn, MR_TypeInfo type_info,
-                        MR_bool is_first_frame, MR_Word *stack_pointer,
+                        MR_bool registers_live, MR_Word *stack_pointer,
                         MR_Word *current_frame);
 
 #endif
@@ -97,6 +100,7 @@
 #ifndef MR_HIGHLEVEL_CODE
 static MR_Code  *saved_success = NULL;
 static MR_Code **saved_success_location = NULL;
+static MR_bool  callee_was_model_semi = MR_FALSE;
 static MR_bool  gc_scheduled = MR_FALSE;
 static MR_bool  gc_running = MR_FALSE;
 #endif
@@ -351,6 +355,7 @@
     type = MR_LONG_LVAL_TYPE(location);
     number = MR_LONG_LVAL_NUMBER(location);
     if (MR_DETISM_DET_STACK(determinism)) {
+        callee_was_model_semi = MR_DETISM_CAN_FAIL(determinism);
 
         if (type != MR_LONG_LVAL_TYPE_STACKVAR) {
             MR_fatal_error("can only handle stackvars");
@@ -363,6 +368,7 @@
                 & MR_based_stackvar(sp_at_signal, number);
         saved_success = *saved_success_location;
     } else {
+        callee_was_model_semi = MR_FALSE;
         /*
         ** XXX we ought to also overwrite the redoip,
         **     otherwise we might miss failure-driven loops
@@ -414,7 +420,8 @@
     gc_running = MR_TRUE;
 
     MR_save_registers();
-    MR_LLDS_garbage_collect(saved_success, MR_sp, MR_maxfr, MR_curfr);
+    MR_LLDS_garbage_collect(saved_success, callee_was_model_semi,
+        MR_sp, MR_maxfr, MR_curfr);
     MR_restore_registers();
     gc_scheduled = MR_FALSE;
     gc_running = MR_FALSE;
@@ -434,8 +441,8 @@
 ** code duplication with the version for the MLDS back-end, which is above.
 */
 static void
-MR_LLDS_garbage_collect(MR_Code *success_ip, MR_Word *stack_pointer, 
-        MR_Word *max_frame, MR_Word *current_frame)
+MR_LLDS_garbage_collect(MR_Code *success_ip, MR_bool callee_model_semi,
+        MR_Word *stack_pointer, MR_Word *max_frame, MR_Word *current_frame)
 {
     MR_MemoryZone                   *old_heap, *new_heap;
     MR_Word                         *old_hp;
@@ -489,9 +496,10 @@
     ** Traverse the stacks, copying the live data in the old heap to the
     ** new heap.
     */
-    traverse_det_stack(label_layout, stack_pointer, current_frame);
-    traverse_nondet_stack(label_layout, stack_pointer, max_frame,
-        current_frame);
+    traverse_det_stack(label_layout, callee_model_semi,
+        stack_pointer, current_frame);
+    traverse_nondet_stack(label_layout, callee_model_semi,
+        stack_pointer, max_frame, current_frame);
 
     /*
     ** Copy any roots that are not on the stack.
@@ -542,7 +550,7 @@
 */
 static void
 traverse_det_stack(const MR_Label_Layout *label_layout,
-    MR_Word *stack_pointer, MR_Word *current_frame)
+    MR_bool callee_model_semi, MR_Word *stack_pointer, MR_Word *current_frame)
 {
     /*
     ** Record whether this is the first frame on the call stack.
@@ -564,7 +572,9 @@
         */
         proc_layout = label_layout->MR_sll_entry;
         if (MR_DETISM_DET_STACK(proc_layout->MR_sle_detism)) {
-            traverse_frame(is_first_frame, label_layout, stack_pointer,
+            MR_bool registers_live = are_registers_live(is_first_frame,
+                callee_model_semi);
+            traverse_frame(registers_live, label_layout, stack_pointer,
                 current_frame);
         }
 
@@ -582,6 +592,23 @@
     } while (label_layout != NULL); /* end for each stack frame... */
 }
 
+static MR_bool
+are_registers_live(MR_bool is_first_frame, MR_bool callee_model_semi)
+{
+    /*
+    ** The registers are live if this is the first (top) frame.
+    ** However, as an exception, if the called procedure was
+    ** semidet, and the success indicator (MR_r1) is false,
+    ** then the registers are not live (only MR_r1 is live,
+    ** and we don't need to traverse that).
+    */
+    MR_bool registers_live = is_first_frame;
+    if (callee_model_semi && !MR_virtual_reg(1)) {
+        registers_live = MR_FALSE;
+    }
+    return registers_live;
+}
+
 /*
 ** Traverse the whole of the nondet stack.
 */ 
@@ -589,15 +616,18 @@
 struct first_frame_data {
     const MR_Label_Layout *first_frame_layout;
     MR_Word *first_frame_curfr;
+    MR_bool first_frame_callee_model_semi;
 };
     
 static void
 traverse_nondet_stack(const MR_Label_Layout *first_frame_layout,
+        MR_bool callee_model_semi,
         MR_Word *stack_pointer, MR_Word *max_frame, MR_Word *current_frame)
 {
     struct first_frame_data data;
     data.first_frame_layout = first_frame_layout;
     data.first_frame_curfr = current_frame;
+    data.first_frame_callee_model_semi = callee_model_semi;
     MR_traverse_nondet_stack_from_layout(max_frame, first_frame_layout,
             stack_pointer, current_frame, traverse_nondet_frame,
             &data);
@@ -609,6 +639,7 @@
         MR_Word *current_frame)
 {   
     MR_bool is_first_frame;
+    MR_bool registers_live;
     struct first_frame_data *data = user_data;
     
     /*
@@ -620,14 +651,17 @@
         && !MR_DETISM_DET_STACK(
             data->first_frame_layout->MR_sll_entry->MR_sle_detism));
 
-    traverse_frame(is_first_frame, label_layout, stack_pointer, current_frame);
+    registers_live = are_registers_live(is_first_frame, 
+        data->first_frame_callee_model_semi);
+
+    traverse_frame(registers_live, label_layout, stack_pointer, current_frame);
 }
 
 /*
 ** Traverse a stack frame (it could be either a det frame or a nondet frame).
 */
 static void
-traverse_frame(MR_bool is_first_frame, const MR_Label_Layout *label_layout,
+traverse_frame(MR_bool registers_live, const MR_Label_Layout *label_layout,
         MR_Word *stack_pointer, MR_Word *current_frame)
 {
     int                             short_var_count, long_var_count;
@@ -658,8 +692,14 @@
     ** will be stored in registers across a call, since we have no
     ** caller-save registers (they are all callee-save).
     */
+    /*
+    ** XXX this won't handle calls to semidet existentially typed procedures:
+    **      we will try to dereference the type_infos for the
+    **      existential type vars here, even if the success
+    **      indicator is false and hence the registers are not live.
+    */
     type_params = MR_materialize_type_params_base(label_layout,
-            (is_first_frame ? MR_fake_reg : NULL),
+            (registers_live ? MR_fake_reg : NULL),
             stack_pointer, current_frame);
     
     /* Copy each live variable */
@@ -670,7 +710,7 @@
 
         type_info = MR_make_type_info(type_params, pseudo_type_info,
                 &allocated_memory_cells);
-        copy_long_value(locn, type_info, is_first_frame,
+        copy_long_value(locn, type_info, registers_live,
                 stack_pointer, current_frame);
         MR_deallocate(allocated_memory_cells);
         allocated_memory_cells = NULL;
@@ -682,7 +722,7 @@
 
         type_info = MR_make_type_info(type_params, pseudo_type_info,
                 &allocated_memory_cells);
-        copy_short_value(locn, type_info, is_first_frame,
+        copy_short_value(locn, type_info, registers_live,
                 stack_pointer, current_frame);
         MR_deallocate(allocated_memory_cells);
         allocated_memory_cells = NULL;
@@ -704,14 +744,14 @@
 
 static void
 copy_long_value(MR_Long_Lval locn, MR_TypeInfo type_info,
-        MR_bool is_first_frame, MR_Word *stack_pointer, MR_Word *current_frame)
+        MR_bool registers_live, MR_Word *stack_pointer, MR_Word *current_frame)
 {
     int locn_num;
 
     locn_num = MR_LONG_LVAL_NUMBER(locn);
     switch (MR_LONG_LVAL_TYPE(locn)) {
     case MR_LONG_LVAL_TYPE_R:
-        if (is_first_frame) {
+        if (registers_live) {
             MR_virtual_reg(locn_num) = MR_agc_deep_copy(
                     MR_virtual_reg(locn_num), type_info,
                     MR_ENGINE(MR_eng_heap_zone2->min),
@@ -778,14 +818,14 @@
 
 static void
 copy_short_value(MR_Short_Lval locn, MR_TypeInfo type_info,
-                 MR_bool is_first_frame, MR_Word *stack_pointer,
+                 MR_bool registers_live, MR_Word *stack_pointer,
                  MR_Word *current_frame)
 {
     int locn_num;
 
     switch (MR_SHORT_LVAL_TYPE(locn)) {
     case MR_SHORT_LVAL_TYPE_R:
-        if (is_first_frame) {
+        if (registers_live) {
             locn_num = MR_SHORT_LVAL_NUMBER(locn);
             MR_virtual_reg(locn_num) =
                     MR_agc_deep_copy(

-- 
Fergus Henderson <fjh at cs.mu.oz.au>  |  "I have always known that the pursuit
The University of Melbourne         |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.
--------------------------------------------------------------------------
mercury-reviews mailing list
post:  mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the reviews mailing list