tabling I/O for retry

Fergus Henderson fjh at cs.mu.OZ.AU
Tue Mar 2 09:45:13 AEDT 1999


This is just proof-of-concept at the moment.
I won't commit it until I've fixed the XXXs below.

--------------------

Estimated hours taken: 4

A first go at implementing "retry" in mdb for procedures that do I/O
by memoizing the results of all the I/O operations.
XXX This should all be enabled by an option; it should not be the default.
XXX The option should be part of the mangled grade.

compiler/trace.m:
	Ensure that old clobbered values of the io__state are retained
	if tracing is enabled, so that we can do `retry' in IO code.

runtime/mercury_wrapper.h:
runtime/mercury_wrapper.c:
	Declare & define a new variable MR_io_counter.

compiler/export.m:
	Initialize the io__state on entry to Mercury code,
	by incrementing the MR_io_counter.

compiler/pragma_c_gen.m:
	Update the io__state at every call to C code.
	by incrementing the MR_io_counter.

compiler/table_gen.m:
	Table all pragma_c_code procedures that do I/O,
	so that doing `retry' in IO code actually works.
	Ensure that io__state values are tabled
	as if they were ints (since they are, now).
	[Hmm, would it be better to just change the
	definition of `io__state' in library/io.m?

Index: compiler/export.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/export.m,v
retrieving revision 1.26
diff -u -r1.26 export.m
--- export.m	1998/11/20 04:07:35	1.26
+++ export.m	1999/03/01 20:45:21
@@ -94,7 +94,7 @@
 	E = pragma_exported_proc(PredId, ProcId, C_Function),
 	get_export_info(Preds, PredId, ProcId, C_RetType,
 		_DeclareReturnVal, _FailureAction, _SuccessAction,
-		HeadArgInfoTypes),
+		HeadArgInfoTypes, _ExcludedHeadArgInfoTypes),
 	get_argument_declarations(HeadArgInfoTypes, no, ArgDecls),
 	C_ExportDecl = c_export_decl(C_RetType, C_Function, ArgDecls),
 	export__get_c_export_decls_2(Preds, ExportedProcs, C_ExportDecls0),
@@ -173,12 +173,13 @@
 	E = pragma_exported_proc(PredId, ProcId, C_Function),
 	get_export_info(Preds, PredId, ProcId,
 		C_RetType, MaybeDeclareRetval, MaybeFail, MaybeSucceed,
-		ArgInfoTypes),
+		ArgInfoTypes, ExcludedArgInfoTypes),
 	get_argument_declarations(ArgInfoTypes, yes, ArgDecls),
 
 		% work out which arguments are input, and which are output,
 		% and copy to/from the mercury registers.
 	get_input_args(ArgInfoTypes, 0, InputArgs),
+	get_excluded_input_args(ExcludedArgInfoTypes, ExcludedInputArgs),
 	copy_output_args(ArgInfoTypes, 0, OutputArgs),
 	
 	code_util__make_proc_label(Module, PredId, ProcId, ProcLabel),
@@ -195,6 +196,7 @@
 				"\tsave_regs_to_mem(c_regs);\n", 
 				"\trestore_registers();\n", 
 				InputArgs,
+				ExcludedInputArgs,
 				"\tsave_transient_registers();\n",
 				"\t{\n\tDeclare_entry(",
 				ProcLabelString,
@@ -222,11 +224,12 @@
 	%	for a given procedure.
 :- pred get_export_info(pred_table, pred_id, proc_id,
 			string, string, string, string,
-			assoc_list(arg_info, type)).
-:- mode get_export_info(in, in, in, out, out, out, out, out) is det.
+			assoc_list(arg_info, type), assoc_list(arg_info, type)).
+:- mode get_export_info(in, in, in, out, out, out, out, out, out) is det.
 
 get_export_info(Preds, PredId, ProcId, C_RetType,
-		MaybeDeclareRetval, MaybeFail, MaybeSucceed, ArgInfoTypes) :-
+		MaybeDeclareRetval, MaybeFail, MaybeSucceed,
+		ArgInfoTypes, ExcludedArgInfoTypes) :-
 	map__lookup(Preds, PredId, PredInfo),
 	pred_info_get_is_pred_or_func(PredInfo, PredOrFunc),
 	pred_info_procedures(PredInfo, ProcTable),
@@ -290,7 +293,8 @@
 		MaybeSucceed = "",
 		ArgInfoTypes2 = ArgInfoTypes0
 	),
-	list__filter(export__include_arg, ArgInfoTypes2, ArgInfoTypes).
+	list__filter(export__include_arg, ArgInfoTypes2, ArgInfoTypes,
+		ExcludedArgInfoTypes).
 
 	% export__include_arg(ArgInfoType):
 	%	Succeeds iff the specified argument should be included in
@@ -379,6 +383,29 @@
 		InputArg = ""
 	),
 	get_input_args(ATs, Num, TheRest),
+	string__append(InputArg, TheRest, Result).
+
+:- pred get_excluded_input_args(assoc_list(arg_info, type), string).
+:- mode get_excluded_input_args(in, out) is det.
+
+get_excluded_input_args([], "").
+get_excluded_input_args([AT|ATs], Result) :-
+	AT = ArgInfo - _Type,
+	ArgInfo = arg_info(ArgLoc, Mode),
+	(
+		Mode = top_in,
+		argloc_to_string(ArgLoc, ArgLocString),
+		string__append_list(
+			["\t", ArgLocString, " = ++MR_io_counter;\n" ],
+			InputArg)
+	;
+		Mode = top_out,
+		InputArg = ""
+	;
+		Mode = top_unused,
+		InputArg = ""
+	),
+	get_excluded_input_args(ATs, TheRest),
 	string__append(InputArg, TheRest, Result).
 
 :- pred copy_output_args(assoc_list(arg_info, type), int, string).
Index: compiler/pragma_c_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/pragma_c_gen.m,v
retrieving revision 1.26
diff -u -r1.26 pragma_c_gen.m
--- pragma_c_gen.m	1999/01/27 08:34:30	1.26
+++ pragma_c_gen.m	1999/03/01 20:47:01
@@ -39,6 +39,8 @@
 :- implementation.
 
 :- import_module hlds_module, hlds_pred, call_gen, llds_out, trace, tree.
+:- import_module export.
+
 :- import_module options, globals.
 :- import_module bool, string, int, assoc_list, set, map, require.
 
@@ -1002,6 +1004,10 @@
 	code_info__release_reg(Reg),
 	code_info__set_var_location(Var, Reg),
 	{
+		export__exclude_argument_type(OrigType)
+	->
+		Outputs = [pragma_c_output(Reg, OrigType, "(++MR_io_counter)")]
+	;
 		var_is_not_singleton(MaybeName, Name)
 	->
 		Outputs = [pragma_c_output(Reg, OrigType, Name) | Outputs0]
Index: compiler/table_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/table_gen.m,v
retrieving revision 1.6
diff -u -r1.6 table_gen.m
--- table_gen.m	1998/11/24 03:57:20	1.6
+++ table_gen.m	1999/03/01 22:41:10
@@ -172,6 +172,8 @@
 :- import_module hlds_module, hlds_goal, hlds_data, (inst), inst_match.
 :- import_module globals, options, passes_aux, prog_data, mode_util, type_util.
 :- import_module code_util, quantification, modes, purity, prog_util.
+:- import_module export.
+
 :- import_module term, varset.
 :- import_module bool, list, set, map, require, std_util, int.
 :- import_module assoc_list, string, llds.
@@ -214,7 +216,23 @@
 	pred_info_procedures(PredInfo, ProcTable),
 	map__lookup(ProcTable, ProcId, ProcInfo),
 
-	proc_info_eval_method(ProcInfo, EvalMethod),
+	proc_info_eval_method(ProcInfo, EvalMethod0),
+	(
+		EvalMethod0 = eval_normal,
+		proc_info_goal(ProcInfo, Goal),
+		% XXX the following check is not robust
+		Goal = pragma_c_code(_, _, _, _, _, _, _) - _,
+		% XXX check debugging enabled
+		pred_info_arg_types(PredInfo, ArgTypes),
+		some [Type] (
+			list__member(Type, ArgTypes),
+			export__exclude_argument_type(Type)
+		)
+	->
+		EvalMethod = eval_memo
+	;
+		EvalMethod = EvalMethod0
+	),
 
 	(
 		EvalMethod \= eval_normal
@@ -707,7 +725,7 @@
 		VarTypes, VarSet0, VarSet, [Goal|RestGoals]) :-
 	map__lookup(VarTypes0, Var, VarType),
 
-	classify_type(VarType, Module, TypeCat),
+	table_gen_classify_type(VarType, Module, TypeCat),
 	gen_lookup_call_for_type(TypeCat, VarType, TableVar0, Var,
 		Module, VarTypes0, VarTypes1, VarSet0, VarSet1, TableVar1,
 		Goal),
@@ -897,7 +915,7 @@
 		VarSet0, VarSet1, OffsetVar, OffsetUnifyGoal),
 
 	map__lookup(VarTypes1, Var, VarType),
-	classify_type(VarType, Module, TypeCat),
+	table_gen_classify_type(VarType, Module, TypeCat),
 
 	gen_save_call_for_type(TypeCat, VarType, TableVar, Var, OffsetVar,
 		Module, CallGoal),
@@ -910,7 +928,7 @@
 		prog_var, module_info, hlds_goal).
 :- mode gen_save_call_for_type(in, in, in, in, in, in, out) is det.
 
-gen_save_call_for_type(TypeCat, _Type, TableVar, Var, OffsetVar, Module,
+gen_save_call_for_type(TypeCat, Type, TableVar, Var, OffsetVar, Module,
 		Goal) :-
 	(
 		not_builtin_type(TypeCat)
@@ -988,7 +1006,7 @@
 		VarSet0, VarSet1, OffsetVar, OffsetUnifyGoal),
 
 	map__lookup(VarTypes1, Var, VarType),
-	classify_type(VarType, Module, TypeCat),
+	table_gen_classify_type(VarType, Module, TypeCat),
 
 	gen_restore_call_for_type(TypeCat, VarType, TableVar, Var, OffsetVar,
 		Module, CallGoal),
@@ -1001,7 +1019,7 @@
 		prog_var, module_info, hlds_goal).
 :- mode gen_restore_call_for_type(in, in, in, in, in, in, out) is det.
 
-gen_restore_call_for_type(TypeCat, _Type, TableVar, Var, OffsetVar, Module,
+gen_restore_call_for_type(TypeCat, Type, TableVar, Var, OffsetVar, Module,
 		Goal) :-
 	(
 		not_builtin_type(TypeCat)
@@ -1247,6 +1265,15 @@
 	goal_info_get_instmap_delta(GoalInfo, IMD0),
 	create_instmap_delta(Rest, IMD1),
 	instmap_delta_apply_instmap_delta(IMD0, IMD1, IMD).
+
+:- pred table_gen_classify_type(type, module_info, builtin_type).
+table_gen_classify_type(VarType, ModuleInfo, TypeCat) :-
+	% treat io__state etc. the same as int
+	( export__exclude_argument_type(VarType) ->
+		TypeCat = int_type
+	;
+		classify_type(VarType, ModuleInfo, TypeCat)
+	).
 
 :- pred not_builtin_type(builtin_type).
 :- mode not_builtin_type(in) is semidet.
Index: compiler/trace.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/trace.m,v
retrieving revision 1.18
diff -u -r1.18 trace.m
--- trace.m	1998/12/14 16:05:10	1.18
+++ trace.m	1999/03/01 22:04:40
@@ -143,7 +143,7 @@
 :- implementation.
 
 :- import_module continuation_info, type_util, llds_out, tree, varset.
-:- import_module (inst), instmap, inst_match, mode_util, options.
+:- import_module (inst), instmap, inst_match, mode_util, options, export.
 :- import_module list, bool, int, string, map, std_util, require.
 
 	% The redo port is not included in this type; see the comment
@@ -199,10 +199,11 @@
 	proc_info_headvars(ProcInfo, HeadVars),
 	proc_info_argmodes(ProcInfo, Modes),
 	proc_info_arg_info(ProcInfo, ArgInfos),
+	proc_info_vartypes(ProcInfo, VarTypes),
 	mode_list_get_final_insts(Modes, ModuleInfo, Insts),
 	(
 		trace__build_fail_vars(HeadVars, Insts, ArgInfos,
-			ModuleInfo, FailVarsList)
+			VarTypes, ModuleInfo, FailVarsList)
 	->
 		set__list_to_set(FailVarsList, FailVars)
 	;
@@ -579,16 +580,23 @@
 %-----------------------------------------------------------------------------%
 
 :- pred trace__build_fail_vars(list(prog_var)::in, list(inst)::in,
-	list(arg_info)::in, module_info::in, list(prog_var)::out) is semidet.
+	list(arg_info)::in, map(prog_var, type)::in, module_info::in,
+	list(prog_var)::out) is semidet.
 
-trace__build_fail_vars([], [], [], _, []).
+trace__build_fail_vars([], [], [], _, _, []).
 trace__build_fail_vars([Var | Vars], [Inst | Insts], [Info | Infos],
-		ModuleInfo, FailVars) :-
-	trace__build_fail_vars(Vars, Insts, Infos, ModuleInfo, FailVars0),
+		VarTypes, ModuleInfo, FailVars) :-
+	trace__build_fail_vars(Vars, Insts, Infos, VarTypes, ModuleInfo,
+		FailVars0),
 	Info = arg_info(_Loc, ArgMode),
 	(
 		ArgMode = top_in,
-		\+ inst_is_clobbered(ModuleInfo, Inst)
+		( inst_is_clobbered(ModuleInfo, Inst) ->
+			map__lookup(VarTypes, Var, Type),
+			export__exclude_argument_type(Type)
+		;
+			true
+		)
 	->
 		FailVars = [Var | FailVars0]
 	;
Index: runtime/mercury_wrapper.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_wrapper.c,v
retrieving revision 1.31
diff -u -r1.31 mercury_wrapper.c
--- mercury_wrapper.c	1999/02/04 10:53:00	1.31
+++ mercury_wrapper.c	1999/03/01 21:06:13
@@ -106,6 +106,8 @@
 
 bool		MR_profiling = TRUE;
 
+Word		MR_io_counter = 1000;
+
 /*
 ** EXTERNAL DEPENDENCIES
 **
Index: runtime/mercury_wrapper.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_wrapper.h,v
retrieving revision 1.17
diff -u -r1.17 mercury_wrapper.h
--- mercury_wrapper.h	1999/02/04 10:52:58	1.17
+++ mercury_wrapper.h	1999/03/01 21:05:39
@@ -140,4 +140,6 @@
 
 extern  bool MR_profiling;
 
+extern  Word MR_io_counter;
+
 #endif /* not MERCURY_WRAPPER_H */
-- 
Fergus Henderson <fjh at cs.mu.oz.au>  |  "Binaries may die
WWW: <http://www.cs.mu.oz.au/~fjh>  |   but source code lives forever"
PGP: finger fjh at 128.250.37.3        |     -- leaked Microsoft memo.



More information about the developers mailing list