diff: typecheck.m performance bug fix

Fergus Henderson fjh at cs.mu.oz.au
Mon Jun 2 05:44:22 AEST 1997


Fix a performance bug that caused type inference to fail with a
det stack overflow for boyer.m.

compiler/typecheck.m:
	At the end of typechecking each predicate, recompute the
	typevarset, restricting it to only the type variables that
	actually occur in the final typing.  This avoids a problem
	where the typevarsets were expanding indefinitely.

Index: typecheck.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/typecheck.m,v
retrieving revision 1.205
diff -u -r1.205 typecheck.m
--- typecheck.m	1997/05/30 17:16:45	1.205
+++ typecheck.m	1997/06/01 19:29:11
@@ -359,8 +359,8 @@
 	    pred_info_typevarset(PredInfo0, TypeVarSet0),
 	    pred_info_clauses_info(PredInfo0, ClausesInfo0),
 	    pred_info_import_status(PredInfo0, Status),
-	    ClausesInfo0 = clauses_info(VarSet, VarTypes0, _,
-	    				HeadVars, Clauses0),
+	    ClausesInfo0 = clauses_info(VarSet, ExplicitVarTypes,
+				_OldInferredVarTypes, HeadVars, Clauses0),
 	    ( 
 		Clauses0 = [] 
 	    ->
@@ -390,25 +390,26 @@
 		bool(Inferring), % dummy pred call to avoid type ambiguity
 
 		typecheck_info_init(IOState1, ModuleInfo, PredId,
-				TypeVarSet0, VarSet, VarTypes0, HeadTypeParams,
-				Status, TypeCheckInfo1),
+				TypeVarSet0, VarSet, ExplicitVarTypes,
+				HeadTypeParams, Status, TypeCheckInfo1),
 		typecheck_clause_list(Clauses0, HeadVars, ArgTypes0, Clauses,
 				TypeCheckInfo1, TypeCheckInfo2),
 		typecheck_check_for_ambiguity(whole_pred, HeadVars,
 				TypeCheckInfo2, TypeCheckInfo3),
 		typecheck_info_get_final_info(TypeCheckInfo3, TypeVarSet, 
-				VarTypes1),
-		map__optimize(VarTypes1, VarTypes),
-		ClausesInfo = clauses_info(VarSet, VarTypes0, VarTypes,
-				HeadVars, Clauses),
+				InferredVarTypes0),
+		map__optimize(InferredVarTypes0, InferredVarTypes),
+		ClausesInfo = clauses_info(VarSet, ExplicitVarTypes,
+				InferredVarTypes, HeadVars, Clauses),
 		pred_info_set_clauses_info(PredInfo0, ClausesInfo, PredInfo1),
 		pred_info_set_typevarset(PredInfo1, TypeVarSet, PredInfo2),
 		( Inferring = no ->
 			PredInfo = PredInfo2,
 			Changed = no
 		;
-			map__apply_to_list(HeadVars, VarTypes, ArgTypes),
-			pred_info_set_arg_types(PredInfo1, TypeVarSet,
+			map__apply_to_list(HeadVars, InferredVarTypes,
+				ArgTypes),
+			pred_info_set_arg_types(PredInfo2, TypeVarSet,
 				ArgTypes, PredInfo),
 			( identical_up_to_renaming(ArgTypes0, ArgTypes) ->
 				Changed = no
@@ -2515,14 +2516,64 @@
 :- pred typecheck_info_get_final_info(typecheck_info, tvarset, map(var, type)).
 :- mode typecheck_info_get_final_info(in, out, out) is det.
 
-typecheck_info_get_final_info(TypeCheckInfo, TypeVarSet, VarTypes) :-
+typecheck_info_get_final_info(TypeCheckInfo, NewTypeVarSet, NewVarTypes) :-
 	typecheck_info_get_type_assign_set(TypeCheckInfo, TypeAssignSet),
 	( TypeAssignSet = [TypeAssign | _] ->
-		type_assign_get_typevarset(TypeAssign, TypeVarSet),
+		type_assign_get_typevarset(TypeAssign, OldTypeVarSet),
 		type_assign_get_var_types(TypeAssign, VarTypes0),
 		type_assign_get_type_bindings(TypeAssign, TypeBindings),
 		map__keys(VarTypes0, Vars),
-		expand_types(Vars, TypeBindings, VarTypes0, VarTypes)
+		expand_types(Vars, TypeBindings, VarTypes0, VarTypes),
+
+		%
+		% We used to just use the OldTypeVarSet that we got
+		% from the type assignment.
+		%
+		% However, that caused serious efficiency problems,
+		% because the typevarsets get bigger and bigger with each
+		% inference step.  Instead, we now construct a new
+		% typevarset NewTypeVarSet which contains only the
+		% variables we want, and we rename the type variables
+		% so that they fit into this new typevarset.
+		%
+
+		%
+		% First, find the set (sorted list) of type variables
+		% that we need.
+		%
+		map__values(VarTypes, Types),
+		term__vars_list(Types, TypeVars0),
+		list__sort_and_remove_dups(TypeVars0, TypeVars),
+		%
+		% Next, create a new typevarset with the same number of
+		% variables. 
+		%
+		list__length(TypeVars, NumTypeVars),
+		varset__init(NewTypeVarSet0),
+		varset__new_vars(NewTypeVarSet0, NumTypeVars, 
+			NewTypeVars0, NewTypeVarSet1),
+		%
+		% We need to sort the fresh variables, to
+		% ensure that the type substitution that we create below
+		% does not alter the relative ordering of the type variables
+		% (since that affects the order in which type_info
+		% parameters will be passed).
+		%
+		list__sort(NewTypeVars0, NewTypeVars),
+		%
+		% Copy the type variable names across from the old
+		% typevarset to the new typevarset.
+		%
+		varset__var_name_list(OldTypeVarSet, TypeVarNames),
+		map__from_corresponding_lists(TypeVars, NewTypeVars, TSubst),
+		copy_type_var_names(TypeVarNames, TSubst, NewTypeVarSet1,
+			NewTypeVarSet),
+		%
+		% Finally, rename the types to use the new typevarset
+		% type variables.
+		%
+		term__apply_variable_renaming_to_list(Types, TSubst, NewTypes),
+		map__from_corresponding_lists(Vars, NewTypes, NewVarTypes)
 	;
 		error("internal error in typecheck_info_get_vartypes")
 	).
@@ -2539,6 +2590,21 @@
 	term__apply_rec_substitution(Type0, TypeSubst, Type),
 	map__det_update(VarTypes0, Var, Type, VarTypes1),
 	expand_types(Vars, TypeSubst, VarTypes1, VarTypes).
+
+:- pred copy_type_var_names(assoc_list(tvar, string), map(tvar, tvar),
+				tvarset, tvarset).
+:- mode copy_type_var_names(in, in, in, out) is det.
+
+copy_type_var_names([], _TSubst, NewTypeVarSet, NewTypeVarSet).
+copy_type_var_names([OldTypeVar - Name | Rest], TypeSubst, NewTypeVarSet0,
+			NewTypeVarSet) :-
+	( map__search(TypeSubst, OldTypeVar, NewTypeVar) ->
+		varset__name_var(NewTypeVarSet0, NewTypeVar, Name,
+			NewTypeVarSet1)
+	;
+		NewTypeVarSet1 = NewTypeVarSet0
+	),
+	copy_type_var_names(Rest, TypeSubst, NewTypeVarSet1, NewTypeVarSet).
 
 %-----------------------------------------------------------------------------%
 

-- 
Fergus Henderson <fjh at cs.mu.oz.au>   |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>   |  of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3         |     -- the last words of T. S. Garp.



More information about the developers mailing list