[m-rev.] for review: explicitly free dead cells

Peter Wang novalazy at gmail.com
Mon Sep 8 13:38:49 AEST 2008


On 2008-08-25, Peter Wang <novalazy at gmail.com> wrote:
> On 2008-08-25, Zoltan Somogyi <zs at csse.unimelb.edu.au> wrote:
> > On 21-Aug-2008, Peter Wang <novalazy at gmail.com> wrote:
> > > Zoltan, do you think it will be hard to solve the problem noted in
> > > unify_gen.m?
> > 
> > What problem noted in unify_gen.m?
> 
> Nevermind.  I thought there was a difficulty in freeing a dead cell,
> because some of its fields might not actually be extracted yet.  But of
> course the same problem would occur if we were to reuse the dead cell,
> so I can just reuse the code that handles that.

I've updated the patch so explicit frees work in LLDS grades as well.
Interdiff follows.  Post-commit review welcome.


Branches: main

Add the ability, when structure reuse is enabled, to free dead heap cells which
can't otherwise be reused.

Fix a bug where we might try to reuse static data in MLDS grades.  As with the
the LLDS grades, check at run-time that the cell to reuse is within the heap
range.

compiler/options.m:
	Add `--structure-reuse-free-cells' option (disabled by default).

compiler/structure_reuse.direct.choose_reuse.m:
	Fix a bug which caused the code to mark deconstructions with `can_cgc'
	to never be run.  Run the code if `--structure-reuse-free-cells'
	is enabled.

compiler/unify_gen.m:
	Generate `free_heap' instructions after deconstructions marked with
	`can_cgc'.  As in the case of cell reuse, we need to ensure that all
	the needed fields are available from other locations before freeing the
	cell.

compiler/code_info.m:
compiler/var_locn.m:
	Export the code which saves cell fields before the cell is reused
	or freed.

compiler/ml_unify_gen.m:
	Make the code which implements cell reuse generate code like this:

	    MR_assign_if_in_heap(Lval, Rval);
	    if (Lval) {
		/* assign fields */
	    } else {
		Lval = MR_new_object(...);
	    }

	where `MR_assign_if_in_heap' assigns NULL to Lval if Rval doesn't look
	like a dynamically allocated address.

	Strip tag bits off the argument to `delete_object' statements.

compiler/mlds.m:
	Add an MLDS statement `assign_if_in_heap'.

	Change `delete_object' to take an rval argument instead of an lval,
	for stripping tag bits.

compiler/mlds_to_c.m:
	Generate output for `assign_if_in_heap' and `delete_object'.

compiler/ml_elim_nested.m:
compiler/ml_optimize.m:
compiler/mlds_to_gcc.m:
compiler/mlds_to_il.m:
compiler/mlds_to_java.m:
	Conform to MLDS statement changes.

runtime/mercury_heap.h:
	Make `MR_free_heap' macro test that its argument is the heap range
	before calling `GC_FREE', so we don't try to free static data.

	Add `MR_assign_if_in_heap'.

diff --git a/compiler/code_info.m b/compiler/code_info.m
index f9ef9be..ba0eeea 100644
--- a/compiler/code_info.m
+++ b/compiler/code_info.m
@@ -3617,6 +3617,9 @@ should_add_region_ops(CodeInfo, _GoalInfo) = AddRegionOps :-
     list(int)::in, string::in, may_use_atomic_alloc::in, code_tree::out,
     code_info::in, code_info::out) is det.
 
+:- pred save_reused_cell_fields(prog_var::in, lval::in, code_tree::out,
+    list(lval)::out, code_info::in, code_info::out) is det.
+
 :- pred place_var(prog_var::in, lval::in, code_tree::out,
     code_info::in, code_info::out) is det.
 
@@ -3768,6 +3771,13 @@ assign_cell_to_var(Var, ReserveWordAtStart, Ptag, MaybeRvals, HowToConstruct,
     set_static_cell_info(StaticCellInfo, !CI),
     set_var_locn_info(VarLocnInfo, !CI).
 
+save_reused_cell_fields(Var, Lval, Code, Regs, !CI) :-
+    get_var_locn_info(!.CI, VarLocnInfo0),
+    get_module_info(!.CI, ModuleInfo),
+    var_locn_save_cell_fields(ModuleInfo, Var, Lval, Code, Regs,
+        VarLocnInfo0, VarLocnInfo),
+    set_var_locn_info(VarLocnInfo, !CI).
+
 place_var(Var, Lval, Code, !CI) :-
     get_var_locn_info(!.CI, VarLocnInfo0),
     get_module_info(!.CI, ModuleInfo),

diff --git a/compiler/unify_gen.m b/compiler/unify_gen.m
index 518dcb1..8b833b6 100644
--- a/compiler/unify_gen.m
+++ b/compiler/unify_gen.m
@@ -143,20 +143,21 @@ generate_unification(CodeModel, Uni, GoalInfo, Code, !CI) :-
         ),
         (
             CanCGC = can_cgc,
-            % XXX we can't free the cell yet.
-            % Any live variables which are only reachable via Var (or its
-            % aliases?) must be produced beforehand.
-            %
-            % XXX avoid strip_tag when we know what tag it will have
-            % VarName = variable_name(!.CI, Var),
-            % FreeVar = node([
-            %     llds_instr(free_heap(unop(strip_tag, VarRval)),
-            %         "Free " ++ VarName)
-            % ]),
-            ProduceArgs = empty,
-            ProduceVar = empty,
-            FreeVar = empty,
-            Code = tree_list([Code0, ProduceArgs, ProduceVar, FreeVar])
+            VarName = variable_name(!.CI, Var),
+            produce_variable(Var, ProduceVar, VarRval, !CI),
+            ( VarRval = lval(VarLval) ->
+                save_reused_cell_fields(Var, VarLval, SaveArgs, Regs, !CI),
+                % This seems to be fine.
+                list.foldl(release_reg, Regs, !CI),
+                % XXX avoid strip_tag when we know what tag it will have
+                FreeVar = node([
+                    llds_instr(free_heap(unop(strip_tag, VarRval)),
+                        "Free " ++ VarName)
+                ]),
+                Code = tree_list([Code0, ProduceVar, SaveArgs, FreeVar])
+            ;
+                Code = Code0
+            )
         ;
             CanCGC = cannot_cgc,
             Code = Code0
diff --git a/compiler/var_locn.m b/compiler/var_locn.m
index 18f7696..3adbb13 100644
--- a/compiler/var_locn.m
+++ b/compiler/var_locn.m
@@ -187,6 +187,16 @@
     static_cell_info::in, static_cell_info::out,
     var_locn_info::in, var_locn_info::out) is det.
 
+    % var_locn_save_cell_fields(ModuleInfo, Var, VarLval, Code,
+    %   TempRegs, !VarLocnInfo)
+    %
+    % Save any variables which depend on the ReuseLval into temporary
+    % registers so that they are available after ReuseLval is clobbered.
+    %
+:- pred var_locn_save_cell_fields(module_info::in, prog_var::in, lval::in,
+    code_tree::out, list(lval)::out, var_locn_info::in, var_locn_info::out)
+    is det.
+
     % var_locn_place_var(ModuleInfo, Var, Lval, Code, !VarLocnInfo):
     %
     % Produces Code to place the value of Var in Lval, and update !VarLocnInfo
@@ -879,8 +889,8 @@ var_locn_assign_dynamic_cell_to_var(ModuleInfo, Var, ReserveWordAtStart, Ptag,
         MaybeOffset = no,
         StartOffset = 0
     ),
-    % This must appear before the call to `save_reused_cell_fields' in the
-    % reused_cell case, otherwise `save_reused_cell_fields' won't know not to
+    % This must appear before the call to `var_locn_save_cell_fields' in the
+    % reused_cell case, otherwise `var_locn_save_cell_fields' won't know not to
     % use Lval as a temporary register (if Lval is a register).
     var_locn_set_magic_var_location(Var, Lval, !VLI),
     (
@@ -953,7 +963,7 @@ assign_reused_cell_to_var(ModuleInfo, Lval, Ptag, Vector, CellToReuse,
 
     % Save any variables which are available only in the reused cell into
     % temporary registers.
-    save_reused_cell_fields(ModuleInfo, ReuseVar, ReuseLval, SaveArgsCode,
+    var_locn_save_cell_fields(ModuleInfo, ReuseVar, ReuseLval, SaveArgsCode,
         TempRegs0, !VLI),
     SetupReuseCode = tree(ReuseVarCode, SaveArgsCode),
 
@@ -1102,27 +1112,20 @@ assign_cell_arg(ModuleInfo, Rval0, Ptag, Base, Offset, Code, !VLI) :-
     ),
     Code = tree(EvalCode, AssignCode).
 
-    % Save any variables which depend on the ReuseLval into temporary
-    % registers so that they are available after ReuseLval is clobbered.
-    %
-:- pred save_reused_cell_fields(module_info::in, prog_var::in, lval::in,
-    code_tree::out, list(lval)::out, var_locn_info::in, var_locn_info::out)
-    is det.
-
-save_reused_cell_fields(ModuleInfo, ReuseVar, ReuseLval, Code, Regs, !VLI) :-
+var_locn_save_cell_fields(ModuleInfo, ReuseVar, ReuseLval, Code, Regs, !VLI) :-
     var_locn_get_var_state_map(!.VLI, VarStateMap),
     map.lookup(VarStateMap, ReuseVar, ReuseVarState0),
     DepVarsSet = ReuseVarState0 ^ using_vars,
     DepVars = set.to_sorted_list(DepVarsSet),
-    list.map_foldl2(save_reused_cell_fields_2(ModuleInfo, ReuseLval),
+    list.map_foldl2(var_locn_save_cell_fields_2(ModuleInfo, ReuseLval),
         DepVars, SaveArgsCode, [], Regs, !VLI),
     Code = tree_list(SaveArgsCode).
 
-:- pred save_reused_cell_fields_2(module_info::in, lval::in, prog_var::in,
+:- pred var_locn_save_cell_fields_2(module_info::in, lval::in, prog_var::in,
     code_tree::out, list(lval)::in, list(lval)::out,
     var_locn_info::in, var_locn_info::out) is det.
 
-save_reused_cell_fields_2(ModuleInfo, ReuseLval, DepVar, SaveDepVarCode,
+var_locn_save_cell_fields_2(ModuleInfo, ReuseLval, DepVar, SaveDepVarCode,
         !Regs, !VLI) :-
     find_var_availability(!.VLI, DepVar, no, Avail),
     (


--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to:       mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions:          mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the reviews mailing list