[m-rev.] accurate GC for type class methods

Fergus Henderson fjh at cs.mu.OZ.AU
Wed Aug 20 22:32:42 AEST 2003


Estimated hours taken: 24
Branches: main

Implement accurate GC for type class methods.
Accurate GC now supports the whole Mercury language.

compiler/ml_closure_gen.m:
	Generate GC tracing code for the type class method instance
	wrapper functions whose addresses get stored in typeclass_infos. 
	This code generates a closure layout for the method instance
	procedure, and then calls MR_materialize_closure_params(),
	passing it the typeclass_info and the closure layout.

runtime/mercury_layout_util.h:
runtime/mercury_layout_util.c:
	Add new routine MR_materialize_typeclass_info_params(), for use
	by the code generated by ml_closure_gen.m.
	This is similar to MR_materialize_closure_params() except that
	it works on a typeclass_info rather than an MR_Closure.

compiler/rtti_to_mlds.m:
	Update to reflect the changed interface to ml_gen_closure_wrapper.

compiler/ml_elim_nested.m:
	Update the accurate GC TODO list.

compiler/options.m:
doc/user_guide.texi:
	Document that accurate GC is now supported.

NEWS:
	Mention that we now support accurate GC.

Workspace: /home/ceres/fjh/mercury
Index: NEWS
===================================================================
RCS file: /home/mercury1/repository/mercury/NEWS,v
retrieving revision 1.318
diff -u -d -r1.318 NEWS
--- NEWS	18 Aug 2003 11:35:28 -0000	1.318
+++ NEWS	20 Aug 2003 12:30:43 -0000
@@ -15,6 +15,8 @@
   required to be defined in the same module as the type.
 
 Changes to the Mercury compiler:
+* We have added optional support for a new type-accurate garbage collector
+  as an alternative to using the Boehm et al conservative collector.
 * Better support for incremental program development:
   there's two new compiler options, `--allow-stubs' and `--no-warn-stubs',
   to support execution of incomplete programs.
@@ -198,6 +200,22 @@
 * Nothing yet.
 
 Changes to the Mercury compiler:
+
+* We have added optional support for a new type-accurate garbage collector
+  as an alternative to using the Boehm et al conservative collector.
+
+  The new collector is enabled by `--grade hlc.agc'.
+  For details about how it works, see the paper
+  "Accurate garbage collection in an uncooperative environment"
+  which is available via our web page.
+
+  Note that the new collector is a very naive copying collector, and still
+  has a number of serious limitations which may make it undesirable for
+  most applications.  It only works with `--high-level-code'.  The heap
+  size is fixed at program startup; the collector does not attempt to
+  resize the heap.  It does not do cheap heap reclamation on backtracking.
+  There is no support for passing terms on the Mercury heap to C code.
+  In most cases, the Boehm et all conservative collector will perform better.
 
 * There's a new warning option `--warn-dead-procs' which can be used
   for detecting unreachable code.
Index: compiler/ml_closure_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/ml_closure_gen.m,v
retrieving revision 1.18
diff -u -d -r1.18 ml_closure_gen.m
--- compiler/ml_closure_gen.m	26 May 2003 09:00:01 -0000	1.18
+++ compiler/ml_closure_gen.m	20 Aug 2003 11:49:57 -0000
@@ -48,17 +48,22 @@
 	% field in the ml_gen_info, and return the wrapper function's
 	% rval and type.
 	%
+	% The ClosureKind parameter specifies whether the closure is
+	% an ordinary closure, used for higher-order procedure calls,
+	% or a typeclass_info, used for class method calls.
 	% The NumClosuresArgs parameter specifies how many arguments
-	% to extract from the closure.  The Offset parameter specifies
-	% the offset to add to the argument number to get the field
-	% number within the closure.  (Argument numbers start from 1,
-	% and field numbers start from 0.)
+	% to extract from the closure.
 	%
-:- pred ml_gen_closure_wrapper(pred_id, proc_id, int, int, prog_context,
-		mlds__rval, mlds__type, ml_gen_info, ml_gen_info).
+:- pred ml_gen_closure_wrapper(pred_id, proc_id, closure_kind, int,
+		prog_context, mlds__rval, mlds__type,
+		ml_gen_info, ml_gen_info).
 :- mode ml_gen_closure_wrapper(in, in, in, in, in, out, out,
 		in, out) is det.
 
+:- type closure_kind
+	--->	higher_order_proc_closure
+	;	typeclass_info_closure.
+
 	% ml_gen_local_for_output_arg(VarName, Type, ArgNum, Context,
 	%	LocalVarDefn):
 	% Generate a declaration for a local variable with the specified
@@ -137,10 +142,9 @@
 	% it and will insert it before the mlds__defn for the current
 	% procedure.
 	%
-	{ Offset = ml_closure_arg_offset },
 	{ list__length(ArgVars, NumArgs) },
-	ml_gen_closure_wrapper(PredId, ProcId, Offset, NumArgs,
-		Context, WrapperFuncRval0, WrapperFuncType0),
+	ml_gen_closure_wrapper(PredId, ProcId, higher_order_proc_closure,
+		NumArgs, Context, WrapperFuncRval0, WrapperFuncType0),
 
 	%
 	% Compute the rval which holds the number of arguments
@@ -588,12 +592,24 @@
 	%		void *closure;
 	% #endif
 	%
-	% #ifdef MR_NATIVE_GC
+	% #if defined(MR_NATIVE_GC)
+	%		MR_Closure_Layout *closure_layout_ptr;
 	%		MR_TypeInfo *type_params;
 	%	#if 0 /* GC tracing code */
+	%	  #if CLOSURE_KIND == HIGHER_ORDER_PROC_CLOSURE
+	%		closure_layout_ptr =
+	%			((MR_Closure *)closure_arg)->MR_closure_layout;
 	%		type_params =
 	%			MR_materialize_closure_typeinfos(closure_arg);
-	%	#endif
+	%         #else /* CLOSURE_KIND == TYPECLASS_INFO_CLOSURE */
+	%		{
+	%		  static const MR_Closure_Layout closure_layout = ...;
+	%		  closure_layout_ptr = &closure_layout;
+	%		}
+	%		type_params =
+	%			MR_materialize_closure_typeinfos(closure_arg);
+	%	  #endif
+	%	#endif /* GC tracing code */
 	% #endif
 	%
 	%		/* declarations needed for converting output args */
@@ -603,18 +619,19 @@
 	%
 	%		/* declarations needed for by-value outputs */
 	%		RetType conv_retval;
-	% #ifdef MR_NATIVE_GC
+	% #if defined(MR_NATIVE_GC)
 	%   #if 0 /* GC tracing code */
 	%     {
 	%	MR_TypeInfo type_info;
 	%	MR_MemoryList allocated_memory_cells = NULL;
     	%	type_info = MR_make_type_info_maybe_existq(type_params,
-	%	    ((MR_Closure*)closure)->MR_closure_layout
-	%	    	->MR_closure_arg_pseudo_type_info[<arg number> - 1],
+	%	    closure_layout_ptr->MR_closure_arg_pseudo_type_info
+	%		[<arg number> - 1],
 	%           NULL, NULL, &allocated_memory_cells);
 	%	mercury__private_builtin__gc_trace_1_0(type_info, &conv_retval);
 	%       MR_deallocate(allocated_memory_cells);
 	%     }
+	%     #endif
 	%   #endif
 	% #endif
 	%
@@ -685,7 +702,7 @@
 	%			foo_1);
 	% #endif
 	%
-ml_gen_closure_wrapper(PredId, ProcId, Offset, NumClosureArgs,
+ml_gen_closure_wrapper(PredId, ProcId, ClosureKind, NumClosureArgs,
 		Context, WrapperFuncRval, WrapperFuncType) -->
 	%
 	% grab the relevant information about the called procedure
@@ -694,8 +711,8 @@
 	{ ml_gen_info_get_module_info(Info, ModuleInfo) },
 	{ module_info_pred_proc_info(ModuleInfo, PredId, ProcId,
 		PredInfo, ProcInfo) },
-	{ pred_info_get_purity(PredInfo, Purity) },
-	{ pred_info_arg_types(PredInfo, ProcArgTypes) },
+	%{ pred_info_purity(PredInfo, Purity) },
+	%{ pred_info_arg_types(PredInfo, ProcArgTypes) },
 	{ pred_info_get_is_pred_or_func(PredInfo, PredOrFunc) },
 	{ proc_info_headvars(ProcInfo, ProcHeadVars) },
 	{ proc_info_argmodes(ProcInfo, ProcArgModes) },
@@ -721,13 +738,13 @@
 	{ 
 		list__drop(NumClosureArgs, ProcHeadVars, WrapperHeadVars0),
 		list__drop(NumClosureArgs, ProcArgModes, WrapperArgModes0),
-		list__drop(NumClosureArgs, ProcArgTypes, WrapperArgTypes0),
+		%list__drop(NumClosureArgs, ProcArgTypes, WrapperArgTypes0),
 		list__drop(NumClosureArgs, ProcBoxedArgTypes,
 			WrapperBoxedArgTypes0)
 	->
 		WrapperHeadVars = WrapperHeadVars0,
 		WrapperArgModes = WrapperArgModes0,
-		WrapperArgTypes = WrapperArgTypes0,
+		%WrapperArgTypes = WrapperArgTypes0,
 		WrapperBoxedArgTypes = WrapperBoxedArgTypes0
 	;
 		unexpected(this_file,
@@ -752,20 +769,23 @@
 
 	% then insert the `closure_arg' parameter
 	{ ClosureArgType = mlds__generic_type },
-	{ ClosureArgDeclType = list__det_head(ml_make_boxed_types(1)) },
-	{ ClosureArgName = var_name("closure_arg", no) },
-	% We can't use WrapperArgTypes here,
-	% because we don't have type_infos for the type variables in
-	% WrapperArgTypes; those type variables come from the callee.
-	% But when copying closures, we don't care what the types of the
-	% not-yet-applied arguments are.  So we can just use dummy values here.
-	{ HigherOrderArgTypes = list__duplicate(list__length(WrapperArgTypes),
-		c_pointer_type) },
-	{ LambdaEvalMethod = normal },
-	{ construct_higher_order_type(Purity, PredOrFunc, LambdaEvalMethod,
-		HigherOrderArgTypes, ClosureActualType) },
-	ml_gen_maybe_gc_trace_code(ClosureArgName, ClosureArgDeclType,
-		ClosureActualType, Context, ClosureArgGCTraceCode),
+	{ ClosureArgName = mlds__var_name("closure_arg", no) },
+	% If we were to generate GC tracing code for the closure arg,
+	% it would look like this:
+	%	{ ClosureArgDeclType = list__det_head(ml_make_boxed_types(1)) },
+	%	{ gen_closure_gc_trace_code(ClosureArgName, ClosureArgDeclType,
+	% 		ClosureKind, WrapperArgTypes, Purity, PredOrFunc,
+	%		ClosureArgGCTraceCode) },
+	% But we don't need any GC tracing code for the closure arg,
+	% because it won't be live across an allocation.
+	% However, we do need to give it a yes(_) GC tracing code,
+	% because it is referred to from other GC tracing code;
+	% without this, ml_elim_nested.m won't put it into the GC stack frame
+	% struct, and then those other references will be dangling.
+	% (XXX Maybe ml_elim_nested should be smarter about that.)
+	{ MLDS_Context = mlds__make_context(Context) },
+	{ ClosureArgGCTraceCode = yes(mlds__statement(block([],[]),
+					MLDS_Context)) },
 	{ ClosureArg = mlds__argument(
 		data(var(ClosureArgName)),
 		ClosureArgType,
@@ -793,14 +813,14 @@
 	%	closure = closure_arg;
 	%
 	{ ClosureName = mlds__var_name("closure", no) },
-	{ ClosureArgName = mlds__var_name("closure_arg", no) },
 	{ ClosureType = mlds__generic_type },
-	{ ClosureDeclType = list__det_head(ml_make_boxed_types(1)) },
 	% The GC tracing code for `closure' is essentially the same as
-	% for `closure_arg' (see above)
-	ml_gen_maybe_gc_trace_code(ClosureName, ClosureDeclType,
-		ClosureActualType, Context, ClosureGCTraceCode),
-	{ MLDS_Context = mlds__make_context(Context) },
+	% for `closure_arg' (see above).
+	% { ClosureDeclType = list__det_head(ml_make_boxed_types(1)) },
+	% { gen_closure_gc_trace_code(ClosureName, ClosureDeclType,
+	% 	ClosureKind, WrapperArgTypes, ClosureGCTraceCode) },
+	{ ClosureGCTraceCode = yes(mlds__statement(block([],[]),
+		MLDS_Context)) },
 	{ ClosureDecl = ml_gen_mlds_var_decl(var(ClosureName),
 		ClosureType, ClosureGCTraceCode, MLDS_Context) },
 	ml_gen_var_lval(ClosureName, ClosureType, ClosureLval),
@@ -834,7 +854,7 @@
 		[]
 	),
 
-	% prepare to generate code to call the function:
+	% generate code to call the function:
 	% XXX currently we're using a low-level data representation
 	% in the closure
 	%
@@ -849,6 +869,16 @@
 	%		unbox(wrapper_arg1), &conv_arg2, wrapper_arg3, ...
 	%	);
 	%
+	% `Offset' specifies the offset to add to the argument number to
+	% get the field number within the closure.  (Argument numbers start
+	% from 1, and field numbers start from 0.)
+	{
+		ClosureKind = higher_order_proc_closure,
+		Offset = ml_closure_arg_offset
+	;
+		ClosureKind = typeclass_info_closure,
+		Offset = ml_typeclass_info_arg_offset
+	},
 	ml_gen_closure_field_lvals(ClosureLval, Offset, 1, NumClosureArgs,
 		ClosureArgLvals),
 	{ CallLvals = list__append(ClosureArgLvals, WrapperHeadVarLvals) },
@@ -880,8 +910,8 @@
 	%
 	{ module_info_globals(ModuleInfo, Globals) },
 	( { globals__get_gc_method(Globals, accurate) } ->
-		ml_gen_closure_wrapper_gc_decls(ClosureArgName,
-			ClosureArgType, MLDS_Context, GC_Decls)
+		ml_gen_closure_wrapper_gc_decls(ClosureKind, ClosureArgName,
+			ClosureArgType, PredId, ProcId, Context, GC_Decls)
 	;
 		{ GC_Decls = [] }
 	),
@@ -919,6 +949,36 @@
 	Argument0 = mlds__argument(Name, Type, _GCTraceCode),
 	Argument = mlds__argument(Name, Type, no).
 
+	% generate the GC tracing code for `closure_arg' or `closure'
+	% (see ml_gen_closure_wrapper above).
+:- pred gen_closure_gc_trace_code(mlds__var_name, prog_type, closure_kind,
+	list(mlds__type), purity, pred_or_func, prog_context,
+	mlds__maybe_gc_trace_code, ml_gen_info, ml_gen_info) is det.
+:- mode gen_closure_gc_trace_code(in, in, in, in, in, in, in, out, in, out)
+	is det.
+gen_closure_gc_trace_code(ClosureName, ClosureDeclType,
+		ClosureKind, WrapperArgTypes, Purity, PredOrFunc,
+		Context, ClosureGCTraceCode) -->
+	% We can't use WrapperArgTypes here,
+	% because we don't have type_infos for the type variables in
+	% WrapperArgTypes; those type variables come from the callee.
+	% But when copying closures, we don't care what the types of the
+	% not-yet-applied arguments are.  So we can just use dummy values here.
+	{ HigherOrderArgTypes = list__duplicate(list__length(WrapperArgTypes),
+		c_pointer_type) },
+	(
+		{ ClosureKind = higher_order_proc_closure },
+		{ LambdaEvalMethod = normal },
+		{ construct_higher_order_type(Purity, PredOrFunc,
+			LambdaEvalMethod, HigherOrderArgTypes,
+			ClosureActualType) }
+	;
+		{ ClosureKind = typeclass_info_closure },
+		{ ClosureActualType = sample_typeclass_info_type }
+	),
+	ml_gen_maybe_gc_trace_code(ClosureName, ClosureDeclType,
+		ClosureActualType, Context, ClosureGCTraceCode).
+
 :- pred ml_gen_wrapper_func(ml_label_func, mlds__func_params, prog_context,
 		mlds__statement, mlds__defn, ml_gen_info, ml_gen_info).
 :- mode ml_gen_wrapper_func(in, in, in, in, out, in, out) is det.
@@ -1035,34 +1095,97 @@
 	).
 
 	% This is used for accurate GC with the MLDS->C back-end.
-	% It generates the following variable declaration:
+	% It generates the following variable declarations:
+	%	MR_Closure_Layout *closure_layout_ptr;
 	%	MR_TypeInfo *type_params;
-	% and code to initialize it
+	% and code to initialize them: either
+	%	closure_layout_ptr =
+	%		((MR_Closure *)closure_arg)->MR_closure_layout;
 	%	type_params = MR_materialize_closure_typeinfos(closure_arg);
-:- pred ml_gen_closure_wrapper_gc_decls(mlds__var_name, mlds__type,
-		mlds__context, mlds__defns, ml_gen_info, ml_gen_info).
-:- mode ml_gen_closure_wrapper_gc_decls(in, in, in, out, in, out) is det.
+	% or
+	%	{
+	%	  static const MR_Closure_Layout closure_layout = { ... }
+	%	  closure_layout_ptr = &closure_layout;
+	%	}
+	%	type_params = MR_materialize_typeclass_info_typeinfos(
+	%			closure_arg, closure_layout);
+	%
+:- pred ml_gen_closure_wrapper_gc_decls(closure_kind, mlds__var_name,
+		mlds__type, pred_id, proc_id, prog_context, mlds__defns,
+		ml_gen_info, ml_gen_info).
+:- mode ml_gen_closure_wrapper_gc_decls(in, in, in, in, in, in, out, in, out)
+	is det.
+
+ml_gen_closure_wrapper_gc_decls(ClosureKind, ClosureArgName, ClosureArgType,
+		PredId, ProcId, Context, GC_Decls) -->
+	{ MLDS_Context = mlds__make_context(Context) },
 
-ml_gen_closure_wrapper_gc_decls(ClosureArgName, ClosureArgType, Context,
-		GC_Decls) -->
 	ml_gen_var_lval(ClosureArgName, ClosureArgType, ClosureArgLval),
+
+	{ ClosureLayoutPtrName = var_name("closure_layout_ptr", no) },
+	% This type is really `const MR_Closure_Layout *', but there's no easy
+	% way to represent that in the MLDS; using MR_Box instead works fine.
+	{ ClosureLayoutPtrType = mlds__generic_type },
+	{ ClosureLayoutPtrDecl = ml_gen_mlds_var_decl(var(ClosureLayoutPtrName),
+		ClosureLayoutPtrType, yes(ClosureLayoutPtrGCInit),
+		MLDS_Context) },
+	ml_gen_var_lval(ClosureLayoutPtrName, ClosureLayoutPtrType,
+		ClosureLayoutPtrLval),
+
 	{ TypeParamsName = var_name("type_params", no) },
 	% This type is really MR_TypeInfoParams, but there's no easy way to
 	% represent that in the MLDS; using MR_Box instead works fine.
 	{ TypeParamsType = mlds__generic_type },
 	{ TypeParamsDecl = ml_gen_mlds_var_decl(var(TypeParamsName),
-		TypeParamsType, yes(GC_Init), Context) },
+		TypeParamsType, yes(TypeParamsGCInit), MLDS_Context) },
 	ml_gen_var_lval(TypeParamsName, TypeParamsType, TypeParamsLval),
-	{ GC_Decls = [TypeParamsDecl] },
-	{ GC_Init = mlds__statement(atomic(inline_target_code(lang_C, [
-		% MR_TypeInfo *type_params =
-		%	MR_materialize_closure_typeinfos(closure);
-		target_code_output(TypeParamsLval),
-		raw_target_code(
-		    " = (MR_Box) MR_materialize_closure_type_params(\n", []),
-		target_code_input(lval(ClosureArgLval)),
-		raw_target_code(");\n", [])
-	])), Context) }.
+
+	(
+		{ ClosureKind = higher_order_proc_closure },
+		{ ClosureLayoutPtrGCInitFragments = [
+			target_code_output(ClosureLayoutPtrLval),
+			raw_target_code(" = (MR_Box) ((MR_Closure *)\n", []),
+			target_code_input(lval(ClosureArgLval)),
+			raw_target_code("->MR_closure_layout);\n", [])
+		] },
+		{ ClosureLayoutPtrGCInit = mlds__statement(atomic(
+			inline_target_code(lang_C,
+			ClosureLayoutPtrGCInitFragments)), MLDS_Context) },
+		{ TypeParamsGCInitFragments = [
+			target_code_output(TypeParamsLval),
+			raw_target_code(" = (MR_Box) " ++
+			  "MR_materialize_closure_type_params(\n", []),
+			target_code_input(lval(ClosureArgLval)),
+			raw_target_code(");\n", [])
+		] }
+	;
+		{ ClosureKind = typeclass_info_closure },
+		ml_gen_closure_layout(PredId, ProcId, Context,
+				ClosureLayoutRval, ClosureLayoutType,
+				ClosureLayoutDefns),
+		{ ClosureLayoutPtrGCInit = mlds__statement(
+			mlds__block(
+				ClosureLayoutDefns,
+				[mlds__statement(atomic(
+					assign(ClosureLayoutPtrLval,
+					unop(box(ClosureLayoutType),
+						ClosureLayoutRval)
+				)), MLDS_Context)]
+			), MLDS_Context) },
+		{ TypeParamsGCInitFragments = [
+			target_code_output(TypeParamsLval),
+			raw_target_code(" = (MR_Box) " ++
+			  "MR_materialize_typeclass_info_type_params(\n" ++
+			  "(MR_Word) ", []),
+			target_code_input(lval(ClosureArgLval)),
+			raw_target_code(", (MR_Closure_Layout *) ", []),
+			target_code_input(lval(ClosureLayoutPtrLval)),
+			raw_target_code(");\n", [])
+		] }
+	),
+	{ TypeParamsGCInit = mlds__statement(atomic(inline_target_code(
+		lang_C, TypeParamsGCInitFragments)), MLDS_Context) },
+	{ GC_Decls = [ClosureLayoutPtrDecl, TypeParamsDecl] }.
 
 ml_gen_local_for_output_arg(VarName, Type, ArgNum, Context, LocalVarDefn) -->
 	%
@@ -1083,16 +1206,19 @@
 	%
 	{ MLDS_Context = mlds__make_context(Context) },
 
+	{ ClosureLayoutPtrName = var_name("closure_layout_ptr", no) },
+	% This type is really `const MR_Closure_Layout *', but there's no easy
+	% way to represent that in the MLDS; using MR_Box instead works fine.
+	{ ClosureLayoutPtrType = mlds__generic_type },
+	ml_gen_var_lval(ClosureLayoutPtrName, ClosureLayoutPtrType,
+		ClosureLayoutPtrLval),
+
 	{ TypeParamsName = var_name("type_params", no) },
 	% This type is really MR_TypeInfoParams, but there's no easy way to
 	% represent that in the MLDS; using MR_Box instead works fine.
 	{ TypeParamsType = mlds__generic_type },
 	ml_gen_var_lval(TypeParamsName, TypeParamsType, TypeParamsLval),
 
-	{ ClosureArgName = var_name("closure_arg", no) },
-	{ ClosureArgType = mlds__generic_type },
-	ml_gen_var_lval(ClosureArgName, ClosureArgType, ClosureArgLval),
-
 	{ TypeInfoName = var_name("type_info", no) },
 	% the type for this should match the type of the first argument
 	% of private_builtin__gc_trace/1, i.e. `mutvar(T)', which is
@@ -1119,10 +1245,9 @@
 			    " = (MR_C_Pointer) " ++
 			    "MR_make_type_info_maybe_existq(\n\t", []),
 			target_code_input(lval(TypeParamsLval)),
-			raw_target_code(", ((MR_Closure *)\n\t", []),
-			target_code_input(lval(ClosureArgLval)),
-			raw_target_code(string__format(
-			    ")->MR_closure_layout->" ++
+			raw_target_code(", ((MR_Closure_Layout *)\n\t", []),
+			target_code_input(lval(ClosureLayoutPtrLval)),
+			raw_target_code(string__format(")->" ++
 			    "MR_closure_arg_pseudo_type_info[%d - 1],\n\t" ++
 			    "NULL, NULL, &allocated_mem);\n",
 				[i(ArgNum)]), [])
Index: compiler/ml_elim_nested.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/ml_elim_nested.m,v
retrieving revision 1.62
diff -u -d -r1.62 ml_elim_nested.m
--- compiler/ml_elim_nested.m	28 Mar 2003 06:42:48 -0000	1.62
+++ compiler/ml_elim_nested.m	20 Aug 2003 12:00:25 -0000
@@ -154,13 +154,15 @@
 %	"Accurate garbage collection in an uncooperative environment".
 %	International Symposium on Memory Management, Berlin, Germany, 2002.
 %
-% XXX Accurate GC is still not yet fully implemented.
+% In theory accurate GC is now fully implemented,
+% i.e. it should support the whole Mercury language,
+% modulo the caveats below.
 % TODO:
-%	- Support type classes: currently we generate code for type class
-%	  method wrappers which calls MR_materialize_closure_type_params(),
-%	  which only works for closures, not for typeclass_infos.
+%	- XXX Need to test the GC tracing code for type class methods.
+%	  This code in theory ought to work, I think, but it has not
+%	  really been tested.
 %
-%	- The garbage collector should resize the heap if/when it fills up.
+%	- XXX The garbage collector should resize the heap if/when it fills up.
 %         We should allocate a large amount of virtual memory for each heap,
 %         but we should collect when we've allocated a small part of it.
 %
@@ -203,7 +205,7 @@
 %	  and MR_deep_copy() needs to call MR_GC_check() before each
 %	  heap allocation.
 %
-%	- We need to handle `pragma export'.
+%	- XXX We need to handle `pragma export'.
 %
 %	  The C interface in general is a bit problematic for GC.
 %	  But for code which does not call back to Mercury, 
@@ -223,7 +225,7 @@
 %	  But if Mercury code calls C code which calls back to Mercury
 %	  code, and the C code uses pointers to the Mercury heap,
 %	  then there could be serious problems (i.e. dangling pointers).
-%	  Even you just use `pragma export' to export a procedure
+%	  Even if you just use `pragma export' to export a procedure
 %	  and `pragma import' to import it back again, there may be
 %	  trouble.
 %         The code generated for the exported functions can include
Index: compiler/options.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/options.m,v
retrieving revision 1.416
diff -u -d -r1.416 options.m
--- compiler/options.m	6 Aug 2003 12:38:11 -0000	1.416
+++ compiler/options.m	20 Aug 2003 12:15:10 -0000
@@ -3061,9 +3061,11 @@
 		"\t\t\t\t`.mps' grades use `--gc mps',",
 		"\t\t\t\tother grades use `--gc none'.)",
 		"\tSpecify which method of garbage collection to use",
-		"\t(default: boehm).  `accurate' GC is not yet supported.",
+		"\t(default: boehm).",
 		"\t`conservative' or `boehm' is Hans Boehm et al's conservative",
 		"\tcollector.",
+		"\t`accurate' is our own type-accurate copying GC;",
+		"\tit requires `--high-level-code'.",
 		"\t`mps' is a different conservative collector, based on",
 		"\tRavenbrook Limited's MPS (Memory Pool System) kit.",
 		"\tThis option is ignored for the IL and Java back-ends,",
Index: compiler/rtti_to_mlds.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/rtti_to_mlds.m,v
retrieving revision 1.40
diff -u -d -r1.40 rtti_to_mlds.m
--- compiler/rtti_to_mlds.m	14 May 2003 00:10:03 -0000	1.40
+++ compiler/rtti_to_mlds.m	20 Aug 2003 08:08:54 -0000
@@ -1007,10 +1007,9 @@
 	%
 	% Now we can safely go ahead and generate the wrapper function
 	%
-	Offset = ml_typeclass_info_arg_offset,
 	term__context_init(Context),
-	ml_gen_closure_wrapper(PredId, ProcId, Offset, NumExtra,
-		Context, WrapperFuncRval, WrapperFuncType,
+	ml_gen_closure_wrapper(PredId, ProcId, typeclass_info_closure,
+		NumExtra, Context, WrapperFuncRval, WrapperFuncType,
 		MLGenInfo1, MLGenInfo),
 	ml_gen_info_get_extra_defns(MLGenInfo, ExtraDefns1),
 	ExtraDefns = list__append(ExtraDefns1, ExtraDefns0),
Index: doc/user_guide.texi
===================================================================
RCS file: /home/mercury1/repository/mercury/doc/user_guide.texi,v
retrieving revision 1.374
diff -u -d -r1.374 user_guide.texi
--- doc/user_guide.texi	6 Aug 2003 12:38:13 -0000	1.374
+++ doc/user_guide.texi	20 Aug 2003 12:17:01 -0000
@@ -5390,9 +5390,10 @@
 Grades containing @samp{.gc} use @samp{--gc boehm},
 grades containing @samp{.mps} use @samp{--gc mps},
 other grades use @samp{--gc none}.
- at samp{accurate} is not yet implemented.
 @samp{conservative} or @samp{boehm} is Hans Boehm et al's conservative
 garbage collector.
+ at samp{accurate} is our own type-accurate copying collector.
+It requires @samp{--high-level-code}.
 @samp{mps} is another conservative collector based on Ravenbrook Limited's 
 MPS (Memory Pool System) kit.
 This option is ignored by the IL and Java back-ends, which always use
Index: runtime/mercury_layout_util.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_layout_util.c,v
retrieving revision 1.30
diff -u -d -r1.30 mercury_layout_util.c
--- runtime/mercury_layout_util.c	2 Apr 2003 23:01:39 -0000	1.30
+++ runtime/mercury_layout_util.c	20 Aug 2003 10:14:32 -0000
@@ -17,6 +17,8 @@
 
 static MR_Word MR_lookup_closure_long_lval(MR_Long_Lval locn,
 	MR_Closure *closure, MR_bool *succeeded);
+static MR_Word MR_lookup_typeclass_info_long_lval(MR_Long_Lval locn,
+	MR_Word typeclass_info, MR_bool *succeeded);
 static MR_Word MR_lookup_answer_block_long_lval(MR_Long_Lval locn,
 	MR_Word *answer_block, int block_size, MR_bool *succeeded);
 
@@ -154,6 +156,44 @@
 }
 
 MR_TypeInfoParams
+MR_materialize_typeclass_info_params(MR_Word typeclass_info,
+	MR_Closure_Layout *closure_layout)
+{
+	const MR_Type_Param_Locns *tvar_locns;
+
+	tvar_locns = closure_layout->MR_closure_type_params;
+	if (tvar_locns != NULL) {
+		MR_TypeInfoParams	type_params;
+		MR_bool			succeeded;
+		MR_Integer		count;
+		int			i;
+
+		count = tvar_locns->MR_tp_param_count;
+		type_params = (MR_TypeInfoParams)
+			MR_NEW_ARRAY(MR_Word, count + 1);
+
+		for (i = 0; i < count; i++) {
+			if (tvar_locns->MR_tp_param_locns[i] != 0)
+			{
+				type_params[i + 1] = (MR_TypeInfo)
+					MR_lookup_typeclass_info_long_lval(
+						tvar_locns->
+							MR_tp_param_locns[i],
+						typeclass_info, &succeeded);
+				if (! succeeded) {
+					MR_fatal_error("missing type param in "
+				  "MR_materialize_typeclass_info_type_params");
+				}
+			}
+		}
+
+		return type_params;
+	} else {
+		return NULL;
+	}
+}
+
+MR_TypeInfoParams
 MR_materialize_answer_block_type_params(const MR_Type_Param_Locns *tvar_locns,
 	MR_Word *answer_block, int block_size)
 {
@@ -321,6 +361,114 @@
 		default:
 			if (MR_print_locn) {
 				printf("closure DEFAULT\n");
+			}
+			break;
+	}
+
+	return value;
+}
+
+static MR_Word
+MR_lookup_typeclass_info_long_lval(MR_Long_Lval locn, MR_Word typeclass_info,
+	MR_bool *succeeded)
+{
+	int	locn_num;
+	int	offset;
+	MR_Word	value;
+	MR_Word	baseaddr;
+	MR_Word	sublocn;
+
+	*succeeded = MR_FALSE;
+	value = 0;
+
+	locn_num = (int) MR_LONG_LVAL_NUMBER(locn);
+	switch (MR_LONG_LVAL_TYPE(locn)) {
+		case MR_LONG_LVAL_TYPE_R:
+			if (MR_print_locn) {
+				printf("typeclassinfo r%d\n", locn_num);
+			}
+			if (locn_num <= 
+				MR_typeclass_info_num_extra_instance_args(
+					typeclass_info))
+			{
+				value = MR_typeclass_info_arg_typeclass_info(
+					typeclass_info, locn_num);
+				*succeeded = MR_TRUE;
+			}
+			break;
+
+		case MR_LONG_LVAL_TYPE_F:
+			if (MR_print_locn) {
+				printf("typeclassinfo f%d\n", locn_num);
+			}
+			break;
+
+		case MR_LONG_LVAL_TYPE_STACKVAR:
+			if (MR_print_locn) {
+				printf("typeclassinfo stackvar%d\n", locn_num);
+			}
+			break;
+
+		case MR_LONG_LVAL_TYPE_FRAMEVAR:
+			if (MR_print_locn) {
+				printf("typeclassinfo framevar%d\n", locn_num);
+			}
+			break;
+
+		case MR_LONG_LVAL_TYPE_SUCCIP:
+			if (MR_print_locn) {
+				printf("typeclassinfo succip\n");
+			}
+			break;
+
+		case MR_LONG_LVAL_TYPE_MAXFR:
+			if (MR_print_locn) {
+				printf("typeclassinfo maxfr\n");
+			}
+			break;
+
+		case MR_LONG_LVAL_TYPE_CURFR:
+			if (MR_print_locn) {
+				printf("typeclassinfo curfr\n");
+			}
+			break;
+
+		case MR_LONG_LVAL_TYPE_HP:
+			if (MR_print_locn) {
+				printf("typeclassinfo hp\n");
+			}
+			break;
+
+		case MR_LONG_LVAL_TYPE_SP:
+			if (MR_print_locn) {
+				printf("typeclassinfo sp\n");
+			}
+			break;
+
+		case MR_LONG_LVAL_TYPE_INDIRECT:
+			offset = MR_LONG_LVAL_INDIRECT_OFFSET(locn_num);
+			sublocn = MR_LONG_LVAL_INDIRECT_BASE_LVAL(locn_num);
+			if (MR_print_locn) {
+				printf("typeclassinfo offset %d from ", offset);
+			}
+			baseaddr = MR_lookup_typeclass_info_long_lval(sublocn,
+					typeclass_info, succeeded);
+			if (! *succeeded) {
+				break;
+			}
+			value = MR_typeclass_info_type_info(baseaddr, offset);
+			*succeeded = MR_TRUE;
+			break;
+
+		case MR_LONG_LVAL_TYPE_UNKNOWN:
+			if (MR_print_locn) {
+				printf("typeclassinfo unknown\n");
+			}
+			break;
+
+		default:
+			if (MR_print_locn) {
+				printf("typeclassinfo DEFAULT\n");
 			}
 			break;
 	}
Index: runtime/mercury_layout_util.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_layout_util.h,v
retrieving revision 1.21
diff -u -d -r1.21 mercury_layout_util.h
--- runtime/mercury_layout_util.h	2 Apr 2003 23:01:39 -0000	1.21
+++ runtime/mercury_layout_util.h	20 Aug 2003 10:13:05 -0000
@@ -52,6 +52,11 @@
 ** it takes an MR_Closure rather than an MR_Label_Layout,
 ** and it gets the type_infos from a closure using the closure_layout,
 ** rather than getting them from the registers/stacks using a label_layout.
+**
+** MR_materialize_typeclass_info_type_params is the same as
+** MR_materialize_closure_type_params except that it takes
+** a typeclass_info and a closure layout (for the type class method)
+** and it gets the type_infos from the typeclass_info.
 */ 
 
 extern	MR_TypeInfoParams	MR_materialize_type_params(
@@ -63,6 +68,9 @@
 					MR_Word *base_sp, MR_Word *base_curfr);
 extern	MR_TypeInfoParams	MR_materialize_closure_type_params(
 					MR_Closure *closure);
+extern	MR_TypeInfoParams	MR_materialize_typeclass_info_type_params(
+					MR_Word typeclass_info,
+					MR_Closure_Layout *closure_layout);
 extern	MR_TypeInfoParams	MR_materialize_answer_block_type_params(
 					const MR_Type_Param_Locns *tvar_locns,
 					MR_Word *answer_block, int block_size);
-- 
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