[m-rev.] diff: more fixes for MLDS->C accurate GC

Fergus Henderson fjh at cs.mu.OZ.AU
Sat Feb 2 09:00:50 AEDT 2002


Estimated hours taken: 8
Branches: main

Some more bug fixes for accurate GC with the MLDS->C back-end.

With these changes, and a few hacks (see http://www.cs.mu.oz.au/research/
mercury/mailing-lists/mercury-reviews/mercury-reviews.0201/0188.html),
I was able to run all of the programs in tests/benchmarks in grade hlc.agc,
even with MERCURY_OPTIONS set to "-r10000" so as to run them enough times to
force garbage collection.

compiler/ml_elim_nested.m:
	- Fix a bug where we were not saving/restoring the stack chain
	  pointer when doing commits (setjmp/longjmp).
	- Fix a bug where we were not calling GC_check() for the nested
	  functions used for continuations in nondeterministic procedures.
	- Remove the GC tracing annotations from function arguments
	  once they have been put into the GC tracing function,
	  to avoid cluttering the generated C code.
	- Update the TODO list for accurate GC.

compiler/ml_code_util.m:
	Allocate type_infos used for GC tracing on the stack,
	rather than on the heap.  This avoids a problem where
	we were running out of heap space during garbage collection,
	because the tracing routines were themselves allocating heap space.

runtime/mercury_accurate_gc.c:
	Delete a call to MR_reset_redzone() in the MR_garbage_collect()
	function, since the MLDS accurate garbage collector doesn't use
	redzones.
	Also update a comment to reflect the change to ml_code_util.m.

Workspace: /home/earth/fjh/ws-earth4/mercury
Index: compiler/ml_code_util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/ml_code_util.m,v
retrieving revision 1.52
diff -u -d -r1.52 ml_code_util.m
--- compiler/ml_code_util.m	30 Jan 2002 12:46:58 -0000	1.52
+++ compiler/ml_code_util.m	1 Feb 2002 18:50:47 -0000
@@ -779,7 +779,7 @@
 :- import_module ml_code_gen, ml_call_gen.
 :- import_module globals, options.
 
-:- import_module stack, string, require, set, term, varset.
+:- import_module counter, stack, string, require, set, term, varset.
 
 %-----------------------------------------------------------------------------%
 %
@@ -2159,7 +2159,19 @@
 	{ conj_list_to_goal(HLDS_TypeInfoGoals, GoalInfo, Conj) },
 
 	% Convert this HLDS code to MLDS
-	ml_gen_goal(model_det, Conj, MLDS_TypeInfoStatement),
+	ml_gen_goal(model_det, Conj, MLDS_TypeInfoStatement0),
+
+	% Replace all heap allocation (new_object instructions)
+	% with stack allocation (local variable declarations)
+	% in the code to construct type_infos.  This is safe
+	% because those type_infos will only be used in the
+	% immediately following call to gc_trace/1.
+	=(MLGenInfo),
+	{ ml_gen_info_get_module_info(MLGenInfo, ModuleInfo) },
+	{ module_info_name(ModuleInfo, ModuleName) },
+	{ fixup_newobj(MLDS_TypeInfoStatement0,
+		mercury_module_name_to_mlds(ModuleName),
+		MLDS_TypeInfoStatement, MLDS_NewobjLocals) },
 
 	% Build MLDS code to trace the variable
 	ml_gen_trace_var(VarName, DeclType, TypeInfoVar, Context,
@@ -2174,8 +2186,6 @@
 	% get put in the GC frame, rather than these declarations,
 	% which will get ignored.
 	% XXX This is not a very robust way of doing things...
-	=(MLGenInfo),
-	{ ml_gen_info_get_module_info(MLGenInfo, ModuleInfo) },
 	{ ml_gen_info_get_varset(MLGenInfo, VarSet) },
 	{ ml_gen_info_get_var_types(MLGenInfo, VarTypes) },
 	{ MLDS_Context = mlds__make_context(Context) },
@@ -2188,11 +2198,12 @@
 					LocalVarType),
 				no, MLDS_Context)
 		) },
-	{ set__to_sorted_list(NonLocals, VarList) },
-	{ MLDS_VarDecls = list__map(GenLocalVarDecl, VarList) },
+	{ set__to_sorted_list(NonLocals, NonLocalVarList) },
+	{ MLDS_NonLocalVarDecls = list__map(GenLocalVarDecl, NonLocalVarList) },
 
 	% Combine the MLDS code fragments together.
-	{ GC_TraceCode = ml_gen_block(MLDS_VarDecls,
+	{ GC_TraceCode = ml_gen_block(
+		MLDS_NewobjLocals ++ MLDS_NonLocalVarDecls,
 		[MLDS_TypeInfoStatement] ++ [MLDS_TraceStatement],
 		Context) }.
 
@@ -2276,6 +2287,198 @@
 	MLGenInfo = (((MLGenInfo0 ^ module_info := ModuleInfo)
 				  ^ varset := VarSet)
 				  ^ var_types := VarTypes).
+
+%-----------------------------------------------------------------------------%
+
+:- type fixup_newobj_info
+	---> fixup_newobj_info(
+		module_name :: mlds_module_name,% the current module
+		context :: mlds__context,	% the current context
+		locals :: mlds__defns,	% the local variable declarations
+					% accumulated so far
+		next_id :: counter	% a counter used to allocate
+					% variable names
+	).
+
+	% Replace all heap allocation (new_object instructions)
+	% with stack allocation (local variable declarations)
+	% in the specified statement, returning the local
+	% variable declarations needed for the stack allocation.
+	%
+:- pred fixup_newobj(mlds__statement::in, mlds_module_name::in,
+	 mlds__statement::out, mlds__defns::out) is det.
+
+fixup_newobj(Statement0, ModuleName, Statement, Defns) :-
+	Statement0 = mlds__statement(Stmt0, Context),
+	Info0 = fixup_newobj_info(ModuleName, Context, [], counter__init(0)),
+	fixup_newobj_in_stmt(Stmt0, Stmt, Info0, Info),
+	Statement = mlds__statement(Stmt, Context),
+	Defns = Info^locals.
+
+:- pred fixup_newobj_in_statement(mlds__statement::in, mlds__statement::out,
+		fixup_newobj_info::in, fixup_newobj_info::out) is det.
+fixup_newobj_in_statement(MLDS_Statement0, MLDS_Statement) -->
+	{ MLDS_Statement0 = mlds__statement(MLDS_Stmt0, Context) },
+	^context := Context,
+	fixup_newobj_in_stmt(MLDS_Stmt0, MLDS_Stmt),
+	{ MLDS_Statement = mlds__statement(MLDS_Stmt, Context) }.
+
+:- pred fixup_newobj_in_stmt(mlds__stmt::in, mlds__stmt::out,
+		fixup_newobj_info::in, fixup_newobj_info::out) is det.
+
+fixup_newobj_in_stmt(Stmt0, Stmt) -->
+	(
+		{ Stmt0 = block(Defns, Statements0) },
+		list__map_foldl(fixup_newobj_in_statement,
+			Statements0, Statements),
+		{ Stmt = block(Defns, Statements) }
+	;
+		{ Stmt0 = while(Rval, Statement0, Once) },
+		fixup_newobj_in_statement(Statement0, Statement),
+		{ Stmt = while(Rval, Statement, Once) }
+	;
+		{ Stmt0 = if_then_else(Cond, Then0, MaybeElse0) },
+		fixup_newobj_in_statement(Then0, Then),
+		fixup_newobj_in_maybe_statement(MaybeElse0, MaybeElse),
+		{ Stmt = if_then_else(Cond, Then, MaybeElse) }
+	;
+		{ Stmt0 = switch(Type, Val, Range, Cases0, Default0) },
+		list__map_foldl(fixup_newobj_in_case, Cases0, Cases),
+		fixup_newobj_in_default(Default0, Default),
+		{ Stmt = switch(Type, Val, Range, Cases, Default) }
+	;
+		{ Stmt0 = label(_) },
+		{ Stmt = Stmt0 }
+	;
+		{ Stmt0 = goto(_) },
+		{ Stmt = Stmt0 }
+	;
+		{ Stmt0 = computed_goto(Rval, Labels) },
+		{ Stmt = computed_goto(Rval, Labels) }
+	;
+		{ Stmt0 = call(_Sig, _Func, _Obj, _Args, _RetLvals,
+			_TailCall) },
+		{ Stmt = Stmt0 }
+	;
+		{ Stmt0 = return(_Rvals) },
+		{ Stmt = Stmt0 }
+	;
+		{ Stmt0 = do_commit(_Ref) },
+		{ Stmt = Stmt0 }
+	;
+		{ Stmt0 = try_commit(Ref, Statement0, Handler0) },
+		fixup_newobj_in_statement(Statement0, Statement),
+		fixup_newobj_in_statement(Handler0, Handler),
+		{ Stmt = try_commit(Ref, Statement, Handler) }
+	;
+		{ Stmt0 = atomic(AtomicStmt0) },
+		fixup_newobj_in_atomic_statement(AtomicStmt0, Stmt)
+	).
+
+:- pred fixup_newobj_in_case(mlds__switch_case, mlds__switch_case,
+		fixup_newobj_info, fixup_newobj_info).
+:- mode fixup_newobj_in_case(in, out, in, out) is det.
+
+fixup_newobj_in_case(Conds - Statement0, Conds - Statement) -->
+	fixup_newobj_in_statement(Statement0, Statement).
+
+:- pred fixup_newobj_in_maybe_statement(maybe(mlds__statement),
+		maybe(mlds__statement), fixup_newobj_info, fixup_newobj_info).
+:- mode fixup_newobj_in_maybe_statement(in, out, in, out) is det.
+
+fixup_newobj_in_maybe_statement(no, no) --> [].
+fixup_newobj_in_maybe_statement(yes(Statement0), yes(Statement)) -->
+	fixup_newobj_in_statement(Statement0, Statement).
+
+:- pred fixup_newobj_in_default(mlds__switch_default, mlds__switch_default,
+		fixup_newobj_info, fixup_newobj_info).
+:- mode fixup_newobj_in_default(in, out, in, out) is det.
+
+fixup_newobj_in_default(default_is_unreachable, default_is_unreachable) --> [].
+fixup_newobj_in_default(default_do_nothing, default_do_nothing) --> [].
+fixup_newobj_in_default(default_case(Statement0), default_case(Statement)) -->
+	fixup_newobj_in_statement(Statement0, Statement).
+
+:- pred fixup_newobj_in_atomic_statement(mlds__atomic_statement::in,
+		mlds__stmt::out, fixup_newobj_info::in,
+		fixup_newobj_info::out) is det.
+fixup_newobj_in_atomic_statement(AtomicStatement0, Stmt, Info0, Info) :-
+	(
+		AtomicStatement0 = new_object(Lval, MaybeTag, _HasSecTag,
+			PointerType, _MaybeSizeInWordsRval, _MaybeCtorName,
+			ArgRvals, _ArgTypes)
+	->
+		%
+		% generate the declaration of the new local variable
+		%
+		% XXX Using array(generic_type) is wrong for
+		% --high-level-data.
+		%
+		% We need to specify an initializer to tell the
+		% C back-end what the length of the array is.
+		% We initialize it with null pointers and then
+		% later generate assignment statements to fill
+		% in the values properly (see below).
+		%
+		counter__allocate(Id, Info0 ^ next_id, NextId),
+		VarName = var_name("new_obj", yes(Id)),
+		VarType = mlds__array_type(mlds__generic_type),
+		NullPointers = list__duplicate(list__length(ArgRvals),
+			init_obj(const(mlds__null(mlds__generic_type)))),
+		Initializer = init_array(NullPointers),
+		% this is used for the type_infos allocated during tracing,
+		% and we don't need to trace them
+		MaybeGCTraceCode = no,
+		Context = Info0 ^ context,
+		VarDecl = ml_gen_mlds_var_decl(var(VarName),
+			VarType, Initializer, MaybeGCTraceCode, Context),
+		Info1 = Info0 ^ next_id := NextId,
+		Info = Info1 ^ locals := Info1 ^ locals ++ [VarDecl],
+		%
+		% Generate code to initialize the variable.
+		%
+		% Note that we need to use assignment statements,
+		% rather than an initializer, to initialize the
+		% local variable, because the initialization code
+		% needs to occur at exactly the point where the
+		% atomic_statement occurs, rather than at the
+		% local variable declaration.
+		%
+		VarLval = mlds__var(qual(Info ^ module_name, VarName),
+			VarType),
+		PtrRval = mlds__unop(cast(PointerType), mem_addr(VarLval)),
+		list__map_foldl(
+			init_field_n(PointerType, PtrRval, Context),
+			ArgRvals, ArgInitStatements, 0, _NumFields),
+		%
+		% generate code to assign the address of the new local
+		% variable to the Lval
+		%
+		TaggedPtrRval = maybe_tag_rval(MaybeTag, PointerType, PtrRval),
+		AssignStmt = atomic(assign(Lval, TaggedPtrRval)),
+		AssignStatement = mlds__statement(AssignStmt, Context),
+		Stmt = block([], ArgInitStatements ++ [AssignStatement])
+	;
+		Stmt = atomic(AtomicStatement0),
+		Info = Info0
+	).
+
+:- pred init_field_n(mlds__type::in, mlds__rval::in,
+		mlds__context::in, mlds__rval::in, mlds__statement::out,
+		int::in, int::out) is det.
+init_field_n(PointerType, PointerRval, Context, ArgRval, Statement,
+		FieldNum, FieldNum + 1) :-
+	FieldId = offset(const(int_const(FieldNum))),
+	% XXX FieldType is wrong for --high-level-data
+	FieldType = mlds__generic_type,
+	MaybeTag = yes(0),
+	Field = field(MaybeTag, PointerRval, FieldId, FieldType, PointerType),
+	AssignStmt = atomic(assign(Field, ArgRval)),
+	Statement = mlds__statement(AssignStmt, Context).
+
+:- func maybe_tag_rval(maybe(mlds__tag), mlds__type, mlds__rval) = mlds__rval.
+maybe_tag_rval(no, _Type, Rval) = Rval.
+maybe_tag_rval(yes(Tag), Type, Rval) = unop(cast(Type), mkword(Tag, Rval)).
 
 %-----------------------------------------------------------------------------%
 %
Index: compiler/ml_elim_nested.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/ml_elim_nested.m,v
retrieving revision 1.47
diff -u -d -r1.47 ml_elim_nested.m
--- compiler/ml_elim_nested.m	28 Jan 2002 05:30:23 -0000	1.47
+++ compiler/ml_elim_nested.m	1 Feb 2002 21:44:03 -0000
@@ -152,12 +152,16 @@
 % XXX Accurate GC is still not yet fully implemented.
 % TODO:
 %	- fix problem with undeclared local vars for some test cases
-%	  (e.g. tests/valid/agc_unbound_typevars*).
-%	- fix problem with type classes & `constraint(...)' types
-%	  (the compiler goes into an infinite loop and runs out of
-%	  stack space for test cases using type classes)
+%	  (this seems to be due to the problems with higher-order code)
 %	- handle `pragma export'
 %	- support higher-order code: fix problems with tracing closures
+%	  (the MLDS back-end doesn't generate closure layouts)
+%	  and with tracing the wrapper functions generated for
+%	  higher-order code.
+%	- support type classes: same issues as for higher-order code, I think
+%	- support --nondet-copy-out (see comment in flatten_nested_defn)
+%	- support --high-level-data (fixup_newobj_in_atomic_statement
+%	  gets the types wrong; see comment in ml_code_util.m)
 %
 % There are also some things that could be done to improve efficiency,
 % e.g.
@@ -393,8 +397,10 @@
 ml_elim_nested_defns(Action, ModuleName, Globals, OuterVars, Defn0)
 		= Defns :-
 	Defn0 = mlds__defn(Name, Context, Flags, DefnBody0),
-	( DefnBody0 = mlds__function(PredProcId, Params0,
-			defined_here(FuncBody0), Attributes) ->
+	(
+		DefnBody0 = mlds__function(PredProcId, Params0,
+			defined_here(FuncBody0), Attributes)
+	->
 		EnvName = ml_env_name(Name, Action),
 		EnvTypeName = ml_create_env_type_name(EnvName,
 			 ModuleName, Globals),
@@ -408,15 +414,17 @@
 		% structure (e.g. because they occur in nested functions,
 		% or to make them visible to the garbage collector)
 		%
+		% Also, for accurate GC, add code to save and restore the
+		% stack chain pointer at any `try_commit' statements.
+		%
 		ElimInfo0 = elim_info_init(Action, ModuleName,
 			OuterVars, EnvTypeName, EnvPtrTypeName),
 		Params0 = mlds__func_params(Arguments0, RetValues),
 		ml_maybe_add_args(Arguments0, FuncBody0, ModuleName,
 			Context, ElimInfo0, ElimInfo1),
-		flatten_arguments(Arguments0, Arguments, ElimInfo1, ElimInfo2),
+		flatten_arguments(Arguments0, Arguments1, ElimInfo1, ElimInfo2),
 		flatten_statement(FuncBody0, FuncBody1, ElimInfo2, ElimInfo),
 		elim_info_finish(ElimInfo, NestedFuncs0, Locals),
-		Params = mlds__func_params(Arguments, RetValues),
 
 		%
 		% Split the locals that we need to process
@@ -496,7 +504,7 @@
 				% variables in the environment
 				% structure.
 				%
-				ml_maybe_copy_args(Arguments, FuncBody0,
+				ml_maybe_copy_args(Arguments1, FuncBody0,
 					ElimInfo, EnvTypeName, EnvPtrTypeName,
 					Context, _ArgsToCopy, CodeToCopyArgs),
 
@@ -577,6 +585,20 @@
 				HoistedDefns = [EnvTypeDefn | HoistedDefns0]
 			)
 		),
+		(	
+			Action = chain_gc_stack_frames,
+			% This pass will have put the GC tracing code for the
+			% arguments in the GC tracing function.  So we don't
+			% need the GC tracing code annotation on the arguments
+			% anymore.  We delete them here, because otherwise
+			% the `#if 0 ... #endif' blocks output for the
+			% annotations clutter up the generated C files.
+			Arguments = list__map(strip_gc_trace_code, Arguments1)
+		;
+			Action = hoist_nested_funcs,
+			Arguments = Arguments1
+		),
+		Params = mlds__func_params(Arguments, RetValues),
 		DefnBody = mlds__function(PredProcId, Params,
 			defined_here(FuncBody), Attributes),
 		Defn = mlds__defn(Name, Context, Flags, DefnBody),
@@ -586,6 +608,11 @@
 		Defns = [Defn0]
 	).
 
+:- func strip_gc_trace_code(mlds__argument) = mlds__argument.
+strip_gc_trace_code(Argument0) = Argument :-
+	Argument0 = mlds__argument(Name, Type, _MaybeGCTraceCode),
+	Argument = mlds__argument(Name, Type, no).
+
 	%
 	% Add any arguments which are used in nested functions
 	% to the local_data field in the elim_info.
@@ -848,7 +875,7 @@
 	%
 	PrevFieldName = data(var(var_name("prev", no))),
 	PrevFieldFlags = ml_gen_public_field_decl_flags,
-	PrevFieldType = mlds__generic_env_ptr_type,
+	PrevFieldType = ml_stack_chain_type,
 	PrevFieldDefnBody = mlds__data(PrevFieldType,
 		no_initializer, no),
 	PrevFieldDecl = mlds__defn(PrevFieldName, Context,
@@ -1158,7 +1185,11 @@
 	mercury_private_builtin_module(PrivateBuiltin),
 	MLDS_Module = mercury_module_name_to_mlds(PrivateBuiltin),
 	StackChain = var(qual(MLDS_Module, var_name("stack_chain", no)),
-		mlds__generic_env_ptr_type).
+		ml_stack_chain_type).
+
+	% the type of the `stack_chain' pointer, i.e. `void *'.
+:- func ml_stack_chain_type = mlds__type.
+ml_stack_chain_type = mlds__generic_env_ptr_type.
 
 %-----------------------------------------------------------------------------%
 %
@@ -1250,6 +1281,9 @@
 %	for every definition they contain (e.g. definitions of local
 %	variables and nested functions).
 %
+%	Also, for Action = chain_gc_stack_frames, add code to save and
+%	restore the stack chain pointer at any `try_commit' statements.
+%
 
 :- pred flatten_arguments(mlds__arguments, mlds__arguments,
 		elim_info, elim_info).
@@ -1353,9 +1387,32 @@
 	;
 		{ Stmt0 = try_commit(Ref0, Statement0, Handler0) },
 		fixup_lval(Ref0, Ref),
-		flatten_statement(Statement0, Statement),
-		flatten_statement(Handler0, Handler),
-		{ Stmt = try_commit(Ref, Statement, Handler) }
+		flatten_statement(Statement0, Statement1),
+		flatten_statement(Handler0, Handler1),
+		%
+		% add code to save/restore the stack chain pointer
+		%
+		Action =^ action,
+		ModuleName =^ module_name,
+		{ Action = chain_gc_stack_frames ->
+			Statement1 = mlds__statement(_, StatementContext),
+			Handler1 = mlds__statement(_, HandlerContext),
+			Handler = mlds__statement(
+				block(
+				    [],
+				    [gen_restore_stack_chain_var(ModuleName,
+						HandlerContext),
+				     Handler1]
+				),
+				HandlerContext),
+			TryCommit = try_commit(Ref, Statement1, Handler),
+			Stmt = block(
+				[gen_saved_stack_chain_var(StatementContext)],
+				[mlds__statement(TryCommit, StatementContext)]
+			)
+		;
+			Stmt = try_commit(Ref, Statement1, Handler1)
+		}
 	;
 		{ Stmt0 = atomic(AtomicStmt0) },
 		fixup_atomic_stmt(AtomicStmt0, AtomicStmt),
@@ -1411,7 +1468,41 @@
 		%
 		% recursively flatten the nested function
 		%
-		flatten_function_body(FuncBody0, FuncBody),
+		flatten_function_body(FuncBody0, FuncBody1),
+
+		%
+		% for accurate GC,
+		% add a call to GC_check() at start of every
+		% nested function that might allocate memory
+		%
+		% (XXX we could perhaps reduce the overhead of
+		% this slightly by only doing it for
+		% possibly-recursive functions, i.e.
+		% by not doing it for leaf functions).
+		%
+		% XXX This won't work properly with --nondet-copy-out:
+		% we'd need to check out to come after
+		% we copy the arguments to the GC frame struct.
+		% In fact, do we even copy the arguments of
+		% nested functions to the GC frame struct?
+		% 
+		{
+			FuncBody1 = defined_here(FuncBody2),
+			Action = chain_gc_stack_frames,
+			some [NewObjectStmt] (
+				statement_contains_statement(FuncBody2,
+					NewObjectStmt),
+				NewObjectStmt = mlds__statement(atomic(
+				    new_object(_, _, _, _, _, _, _, _)
+				    ), _)
+			)
+		->
+			GC_Check = mlds__statement(atomic(gc_check), Context),
+			FuncBody = defined_here(mlds__statement(
+				block([], [GC_Check, FuncBody2]), Context))
+		;
+			FuncBody = FuncBody1
+		},
 
 		%
 		% mark the function as private / one_copy,
@@ -2204,6 +2295,8 @@
 
 %-----------------------------------------------------------------------------%
 
+% Add code to unlink the stack chain before any explicit returns or tail calls.
+
 :- pred add_unchain_stack_to_maybe_statement(maybe(mlds__statement),
 		maybe(mlds__statement), elim_info, elim_info).
 :- mode add_unchain_stack_to_maybe_statement(in, out, in, out) is det.
@@ -2347,6 +2440,34 @@
 		PrevFieldType, EnvPtrTypeName)),
 	Assignment = assign(StackChain, PrevFieldRval),
 	UnchainFrame = mlds__statement(atomic(Assignment), Context).
+
+	% Generate a local variable declaration
+	% to save the stack chain pointer:
+	%	void *saved_stack_chain = stack_chain;
+:- func gen_saved_stack_chain_var(mlds__context) = mlds__defn.
+gen_saved_stack_chain_var(Context) = Defn :-
+	Name = data(var(ml_saved_stack_chain_name)),
+	Flags = ml_gen_local_var_decl_flags,
+	Type = ml_stack_chain_type,
+	Initializer = init_obj(lval(ml_stack_chain_var)),
+	% The saved stack chain never needs to be traced by the GC,
+	% since it will always point to the stack, not into the heap.
+	GCTraceCode = no,
+	DefnBody = mlds__data(Type, Initializer, GCTraceCode),
+	Defn = mlds__defn(Name, Context, Flags, DefnBody).
+
+	% Generate a statement to restore the stack chain pointer:
+	%	stack_chain = saved_stack_chain;
+:- func gen_restore_stack_chain_var(mlds_module_name, mlds__context) =
+	mlds__statement.
+gen_restore_stack_chain_var(MLDS_Module, Context) = RestoreStatement :-
+	SavedStackChain = var(qual(MLDS_Module,
+		ml_saved_stack_chain_name), ml_stack_chain_type),
+	Assignment = assign(ml_stack_chain_var, lval(SavedStackChain)),
+	RestoreStatement = mlds__statement(atomic(Assignment), Context).
+
+:- func ml_saved_stack_chain_name = mlds__var_name.
+ml_saved_stack_chain_name = var_name("saved_stack_chain", no).
 
 %-----------------------------------------------------------------------------%
 
Index: runtime/mercury_accurate_gc.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_accurate_gc.c,v
retrieving revision 1.13
diff -u -d -r1.13 mercury_accurate_gc.c
--- runtime/mercury_accurate_gc.c	28 Jan 2002 05:30:32 -0000	1.13
+++ runtime/mercury_accurate_gc.c	1 Feb 2002 21:03:59 -0000
@@ -156,9 +156,6 @@
 
 #endif
 
-    /* Reset the redzone on the old heap */
-    MR_reset_redzone(old_heap);
-
 #ifdef MR_DEBUG_AGC_COLLECTION
     fprintf(stderr, "garbage_collect() done.\n\n");
 #endif
@@ -168,10 +165,8 @@
 traverse_stack(struct MR_StackChain *stack_chain)
 {
 	/*
-	** The trace() routines may themselves allocate heap space.
-	** However, the space that they allocate is only used transiently.
-	** XXX We ought to therefore reset the heap pointer
-	** after each iteration of this loop.
+	** The trace() routines themselves should not allocate heap space;
+	** they should use stack allocation.
 	*/
 	while (stack_chain != NULL) {
 		(*stack_chain->trace)(stack_chain);

-- 
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