[m-rev.] for review: higher order calling convention

Zoltan Somogyi zs at cs.mu.OZ.AU
Tue Oct 28 13:25:03 AEDT 2003


For review by Fergus.

Change the calling convention for higher order calls, to make such calls
faster.

The change to mercury_ho_call.c will be committed first. The change to the
compiler will be committed later, after people had a chance to do a "cvs
update" of the change of the runtime. This will avoid installed compilers
generating calls to labels that do not exist in the runtime directories of
workspaces.

runtime/mercury_ho_call.c:
	Add versions of mercury_do_call_closure/mercury_do_call_class_method
	that do not expect the argument giving the number of output arguments,
	since the code does not and will not need this information.
	
compiler/call_gen.m:
	Do not generate the argument giving the number of output arguments,
	and start placing user-specified arguments into the freed-up register.

compiler/llds_out.m:
	Generate code that calls the compact versions of the labels in
	mercury_ho_call.c.

cvs diff: Diffing .
cvs diff: Diffing analysis
cvs diff: Diffing bindist
cvs diff: Diffing boehm_gc
cvs diff: Diffing boehm_gc/Mac_files
cvs diff: Diffing boehm_gc/cord
cvs diff: Diffing boehm_gc/cord/private
cvs diff: Diffing boehm_gc/doc
cvs diff: Diffing boehm_gc/include
cvs diff: Diffing boehm_gc/include/private
cvs diff: Diffing boehm_gc/tests
cvs diff: Diffing browser
cvs diff: Diffing bytecode
cvs diff: Diffing compiler
Index: compiler/call_gen.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/call_gen.m,v
retrieving revision 1.157
diff -u -r1.157 call_gen.m
--- compiler/call_gen.m	27 Oct 2003 05:42:35 -0000	1.157
+++ compiler/call_gen.m	27 Oct 2003 06:35:08 -0000
@@ -264,9 +264,9 @@
 	).
 
 call_gen__generic_call_info(_, higher_order(PredVar, _, _, _),
-		do_call_closure, [PredVar - arg_info(1, top_in)], 4).
+		do_call_closure, [PredVar - arg_info(1, top_in)], 3).
 call_gen__generic_call_info(_, class_method(TCVar, _, _, _),
-		do_call_class_method, [TCVar - arg_info(1, top_in)], 5).
+		do_call_class_method, [TCVar - arg_info(1, top_in)], 4).
 	% Casts are generated inline.
 call_gen__generic_call_info(_, unsafe_cast, do_not_reached, [], 1).
 call_gen__generic_call_info(_, aditi_builtin(_, _), _, _, _) :-
@@ -291,27 +291,21 @@
 
 call_gen__generic_call_nonvar_setup(higher_order(_, _, _, _),
 		InVars, OutVars, Code, !CI) :-
-	code_info__clobber_regs([reg(r, 2), reg(r, 3)], !CI),
+	code_info__clobber_regs([reg(r, 2)], !CI),
 	list__length(InVars, NInVars),
-	list__length(OutVars, NOutVars),
 	Code = node([
 		assign(reg(r, 2), const(int_const(NInVars))) -
-			"Assign number of immediate input arguments",
-		assign(reg(r, 3), const(int_const(NOutVars))) -
-			"Assign number of output arguments"
+			"Assign number of immediate input arguments"
 	]).
 call_gen__generic_call_nonvar_setup(class_method(_, Method, _, _),
 		InVars, OutVars, Code, !CI) :-
-	code_info__clobber_regs([reg(r, 2), reg(r, 3), reg(r, 4)], !CI),
+	code_info__clobber_regs([reg(r, 2), reg(r, 3)], !CI),
 	list__length(InVars, NInVars),
-	list__length(OutVars, NOutVars),
 	Code = node([
 		assign(reg(r, 2), const(int_const(Method))) -
 			"Index of class method in typeclass info",
 		assign(reg(r, 3), const(int_const(NInVars))) -
-			"Assign number of immediate input arguments",
-		assign(reg(r, 4), const(int_const(NOutVars))) -
-			"Assign number of output arguments"
+			"Assign number of immediate input arguments"
 	]).
 call_gen__generic_call_nonvar_setup(unsafe_cast, _, _, _, !CI) :-
 	error("call_gen__generic_call_nonvar_setup: unsafe_cast").
Index: compiler/llds_out.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/llds_out.m,v
retrieving revision 1.218
diff -u -r1.218 llds_out.m
--- compiler/llds_out.m	24 Oct 2003 06:17:40 -0000	1.218
+++ compiler/llds_out.m	24 Oct 2003 06:31:21 -0000
@@ -2637,9 +2637,11 @@
 output_code_addr_decls(do_trace_redo_fail_deep) -->
 	io__write_string("MR_declare_entry(MR_do_trace_redo_fail_deep);\n").
 output_code_addr_decls(do_call_closure) -->
-	io__write_string("MR_declare_entry(mercury__do_call_closure);\n").
+	io__write_string(
+		"MR_declare_entry(mercury__do_call_closure_compact);\n").
 output_code_addr_decls(do_call_class_method) -->
-	io__write_string("MR_declare_entry(mercury__do_call_class_method);\n").
+	io__write_string(
+		"MR_declare_entry(mercury__do_call_class_method_compact);\n").
 output_code_addr_decls(do_not_reached) -->
 	io__write_string("MR_declare_entry(MR_do_not_reached);\n").
 
@@ -2881,14 +2883,14 @@
 	output_label_as_code_addr(CallerLabel),
 	io__write_string(");\n\t\t"),
 	io__write_string(
-		"MR_noprof_tailcall(MR_ENTRY(mercury__do_call_closure));\n").
+		"MR_noprof_tailcall(MR_ENTRY(mercury__do_call_closure_compact));\n").
 output_goto(do_call_class_method, CallerLabel) -->
 	% see comment in output_call for why we use `noprof_' etc. here
 	io__write_string("MR_set_prof_ho_caller_proc("),
 	output_label_as_code_addr(CallerLabel),
 	io__write_string(");\n\t\t"),
 	io__write_string(
-		"MR_noprof_tailcall(MR_ENTRY(mercury__do_call_class_method));\n").
+		"MR_noprof_tailcall(MR_ENTRY(mercury__do_call_class_method_compact));\n").
 output_goto(do_not_reached, CallerLabel) -->
 	io__write_string("MR_tailcall(MR_ENTRY(MR_do_not_reached),\n\t\t"),
 	output_label_as_code_addr(CallerLabel),
@@ -2984,9 +2986,9 @@
 output_code_addr(do_trace_redo_fail_deep) -->
 	io__write_string("MR_ENTRY(MR_do_trace_redo_fail_deep)").
 output_code_addr(do_call_closure) -->
-	io__write_string("MR_ENTRY(mercury__do_call_closure)").
+	io__write_string("MR_ENTRY(mercury__do_call_closure_compact)").
 output_code_addr(do_call_class_method) -->
-	io__write_string("MR_ENTRY(mercury__do_call_class_method)").
+	io__write_string("MR_ENTRY(mercury__do_call_class_method_compact)").
 output_code_addr(do_not_reached) -->
 	io__write_string("MR_ENTRY(MR_do_not_reached)").
 
cvs diff: Diffing compiler/notes
cvs diff: Diffing debian
cvs diff: Diffing deep_profiler
cvs diff: Diffing deep_profiler/notes
cvs diff: Diffing doc
cvs diff: Diffing extras
cvs diff: Diffing extras/aditi
cvs diff: Diffing extras/cgi
cvs diff: Diffing extras/complex_numbers
cvs diff: Diffing extras/complex_numbers/samples
cvs diff: Diffing extras/complex_numbers/tests
cvs diff: Diffing extras/concurrency
cvs diff: Diffing extras/curs
cvs diff: Diffing extras/curs/samples
cvs diff: Diffing extras/curses
cvs diff: Diffing extras/curses/sample
cvs diff: Diffing extras/dynamic_linking
cvs diff: Diffing extras/error
cvs diff: Diffing extras/graphics
cvs diff: Diffing extras/graphics/mercury_opengl
cvs diff: Diffing extras/graphics/mercury_tcltk
cvs diff: Diffing extras/graphics/samples
cvs diff: Diffing extras/graphics/samples/calc
cvs diff: Diffing extras/graphics/samples/maze
cvs diff: Diffing extras/graphics/samples/pent
cvs diff: Diffing extras/lazy_evaluation
cvs diff: Diffing extras/lex
cvs diff: Diffing extras/lex/samples
cvs diff: Diffing extras/lex/tests
cvs diff: Diffing extras/logged_output
cvs diff: Diffing extras/moose
cvs diff: Diffing extras/moose/samples
cvs diff: Diffing extras/morphine
cvs diff: Diffing extras/morphine/non-regression-tests
cvs diff: Diffing extras/morphine/scripts
cvs diff: Diffing extras/morphine/source
cvs diff: Diffing extras/odbc
cvs diff: Diffing extras/posix
cvs diff: Diffing extras/quickcheck
cvs diff: Diffing extras/quickcheck/tutes
cvs diff: Diffing extras/references
cvs diff: Diffing extras/references/samples
cvs diff: Diffing extras/references/tests
cvs diff: Diffing extras/stream
cvs diff: Diffing extras/trailed_update
cvs diff: Diffing extras/trailed_update/samples
cvs diff: Diffing extras/trailed_update/tests
cvs diff: Diffing extras/xml
cvs diff: Diffing extras/xml/samples
cvs diff: Diffing java
cvs diff: Diffing java/library
cvs diff: Diffing java/runtime
cvs diff: Diffing library
cvs diff: Diffing profiler
cvs diff: Diffing robdd
cvs diff: Diffing runtime
Index: runtime/mercury_ho_call.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_ho_call.c,v
retrieving revision 1.66
diff -u -r1.66 mercury_ho_call.c
--- runtime/mercury_ho_call.c	20 Oct 2003 07:29:32 -0000	1.66
+++ runtime/mercury_ho_call.c	20 Oct 2003 07:38:20 -0000
@@ -343,7 +343,7 @@
 ** provided by the higher-order call may be input or output, and may appear
 ** in any order.
 **
-** The input arguments to do_call_*_closure are the closure in MR_r1,
+** The input arguments to do_call_closure are the closure in MR_r1,
 ** the number of additional input arguments in MR_r2, the number of output
 ** arguments to expect in MR_r3, and the additional input arguments themselves
 ** in MR_r4, MR_r5, etc. The output arguments are returned in registers MR_r1,
@@ -353,6 +353,19 @@
 ** The placement of the extra input arguments into MR_r4, MR_r5 etc is done by
 ** the code generator, as is the movement of the output arguments to their
 ** eventual destinations.
+**
+** do_call_closure_compact is like do_call_closure, but it doesn't use MR_r3
+** for the number of output arguments. Instead, the extra input arguments start
+** in MR_r3, not MR_r4. The code generator now calls do_call_closure_compact;
+** do_call_closure is for backward compatibility.
+** 
+** do_call_class_method_compact has the equivalent relationship to
+** do_call_class_method.
+**
+** After bootstrapping is complete, we should delete the existing
+** implementations of do_call_closure and do_call_class_method, and
+** rename do_call_closure_compact as do_call_closure and
+** do_call_class_method_compact as do_call_class_method.
 */
 
 	/*
@@ -362,6 +375,7 @@
 	** MR_r3 -> number of output arguments (unused).
 	*/
 #define MR_HO_CALL_INPUTS		3
+#define MR_HO_CALL_INPUTS_COMPACT	2
 
 	/*
 	** Number of input arguments to do_call_*_class_method,
@@ -370,7 +384,8 @@
 	** MR_r3 -> number of immediate input arguments.
 	** MR_r4 -> number of output arguments (unused).
 	*/
-#define MR_CLASS_METHOD_CALL_INPUTS	4
+#define MR_CLASS_METHOD_CALL_INPUTS		4
+#define MR_CLASS_METHOD_CALL_INPUTS_COMPACT	3
 
 /*
 ** These are the real implementations of higher order calls and method calls.
@@ -378,6 +393,8 @@
 
 MR_define_extern_entry(mercury__do_call_closure);
 MR_define_extern_entry(mercury__do_call_class_method);
+MR_define_extern_entry(mercury__do_call_closure_compact);
+MR_define_extern_entry(mercury__do_call_class_method_compact);
 
 /*
 ** These are the real implementations of unify and compare.
@@ -393,7 +410,9 @@
 
 MR_BEGIN_MODULE(call_module)
 	MR_init_entry_an(mercury__do_call_closure);
+	MR_init_entry_an(mercury__do_call_closure_compact);
 	MR_init_entry_an(mercury__do_call_class_method);
+	MR_init_entry_an(mercury__do_call_class_method_compact);
 
 	MR_init_entry_an(mercury__builtin__unify_2_0);
 	MR_init_entry_an(mercury__builtin__compare_3_0);
@@ -456,6 +475,59 @@
 	MR_tailcall(closure->MR_closure_code, MR_prof_ho_caller_proc);
 }
 
+/*
+** Note: this routine gets ignored for profiling.
+** That means it should be called using noprof_call()
+** rather than call().  See comment in output_call in
+** compiler/llds_out for explanation.
+*/
+MR_define_entry(mercury__do_call_closure_compact);
+{
+	MR_Closure	*closure;
+	int		num_extra_args;	/* # of args provided by our caller */
+	int		num_hidden_args;/* # of args hidden in the closure  */
+	int		i;
+
+	/*
+	** These assignments to local variables allow the values
+	** of the relevant registers to be printed in gdb without
+	** worrying about which machine registers, if any, hold them.
+	*/
+
+	closure = (MR_Closure *) MR_r1;
+	num_extra_args = MR_r2;
+	num_hidden_args = closure->MR_closure_num_hidden_args;
+
+	MR_save_registers();
+
+	if (num_hidden_args < MR_HO_CALL_INPUTS_COMPACT) {
+		/* copy to the left, from the left */
+		for (i = 1; i <= num_extra_args; i++) {
+			MR_virtual_reg(i + num_hidden_args) =
+				MR_virtual_reg(i + MR_HO_CALL_INPUTS_COMPACT);
+		}
+	} else if (num_hidden_args > MR_HO_CALL_INPUTS_COMPACT) {
+		/* copy to the right, from the right */
+		for (i = num_extra_args; i > 0; i--) {
+			MR_virtual_reg(i + num_hidden_args) =
+				MR_virtual_reg(i + MR_HO_CALL_INPUTS_COMPACT);
+		}
+	} /* else the new args are in the right place */
+
+	for (i = 1; i <= num_hidden_args; i++) {
+		MR_virtual_reg(i) = closure->MR_closure_hidden_args(i);
+	}
+
+	MR_restore_registers();
+
+	/*
+	** Note that we pass MR_prof_ho_caller_proc rather than
+	** MR_LABEL(mercury__do_call_closure), so that the call gets recorded
+	** as having come from our caller.
+	*/
+	MR_tailcall(closure->MR_closure_code, MR_prof_ho_caller_proc);
+}
+
 	/*
 	** MR_r1: the typeclass_info
 	** MR_r2: index of class method
@@ -509,6 +581,79 @@
 			MR_virtual_reg(i + num_extra_instance_args) =
 				MR_virtual_reg(i +
 					MR_CLASS_METHOD_CALL_INPUTS);
+		}
+	} /* else the new args are in the right place */
+
+	for (i = num_extra_instance_args; i > 0; i--) {
+		MR_virtual_reg(i) = 
+			MR_typeclass_info_arg_typeclass_info(MR_virtual_reg(1),
+				i);
+	}
+
+	MR_restore_registers();
+
+	/*
+	** Note that we pass MR_prof_ho_caller_proc rather than
+	** MR_LABEL(mercury__do_call_class_method), so that the call gets
+	** recorded as having come from our caller.
+	*/
+	MR_tailcall(destination, MR_prof_ho_caller_proc);
+}
+
+	/*
+	** MR_r1: the typeclass_info
+	** MR_r2: index of class method
+	** MR_r3: number of immediate input arguments
+	** MR_r4+:input args
+	*/
+
+/*
+** Note: this routine gets ignored for profiling.
+** That means it should be called using noprof_call()
+** rather than call().  See comment in output_call in
+** compiler/llds_out for explanation.
+*/
+MR_define_entry(mercury__do_call_class_method_compact);
+{
+	MR_Word		type_class_info;
+	MR_Integer	method_index;
+	MR_Integer	num_input_args;
+	MR_Code 	*destination;
+	MR_Integer	num_extra_instance_args;
+	int		i;
+
+	/*
+	** These assignments to local variables allow the values
+	** of the relevant registers to be printed in gdb without
+	** worrying about which machine registers, if any, hold them.
+	*/
+
+	type_class_info = MR_r1;
+	method_index = (MR_Integer) MR_r2;
+	num_input_args = MR_r3;
+
+	destination = MR_typeclass_info_class_method(type_class_info,
+		method_index);
+	num_extra_instance_args = (MR_Integer)
+		MR_typeclass_info_num_extra_instance_args(type_class_info);
+
+	MR_save_registers();
+
+	if (num_extra_instance_args < MR_CLASS_METHOD_CALL_INPUTS_COMPACT) {
+		/* copy to the left, from the left */
+		for (i = 1; i <= num_input_args; i++) {
+			MR_virtual_reg(i + num_extra_instance_args) =
+				MR_virtual_reg(i +
+					MR_CLASS_METHOD_CALL_INPUTS_COMPACT);
+		}
+	} else if (num_extra_instance_args >
+			MR_CLASS_METHOD_CALL_INPUTS_COMPACT)
+	{
+		/* copy to the right, from the right */
+		for (i = num_input_args; i > 0; i--) {
+			MR_virtual_reg(i + num_extra_instance_args) =
+				MR_virtual_reg(i +
+					MR_CLASS_METHOD_CALL_INPUTS_COMPACT);
 		}
 	} /* else the new args are in the right place */
 
cvs diff: Diffing runtime/GETOPT
cvs diff: Diffing runtime/machdeps
cvs diff: Diffing samples
cvs diff: Diffing samples/c_interface
cvs diff: Diffing samples/c_interface/c_calls_mercury
cvs diff: Diffing samples/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/c_interface/mercury_calls_c
cvs diff: Diffing samples/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/diff
cvs diff: Diffing samples/muz
cvs diff: Diffing samples/rot13
cvs diff: Diffing samples/solutions
cvs diff: Diffing samples/tests
cvs diff: Diffing samples/tests/c_interface
cvs diff: Diffing samples/tests/c_interface/c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/tests/c_interface/mercury_calls_c
cvs diff: Diffing samples/tests/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/tests/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/tests/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/tests/diff
cvs diff: Diffing samples/tests/muz
cvs diff: Diffing samples/tests/rot13
cvs diff: Diffing samples/tests/solutions
cvs diff: Diffing samples/tests/toplevel
cvs diff: Diffing scripts
cvs diff: Diffing tests
cvs diff: Diffing tests/benchmarks
cvs diff: Diffing tests/debugger
cvs diff: Diffing tests/debugger/declarative
cvs diff: Diffing tests/dppd
cvs diff: Diffing tests/general
cvs diff: Diffing tests/general/accumulator
cvs diff: Diffing tests/general/string_format
cvs diff: Diffing tests/general/structure_reuse
cvs diff: Diffing tests/grade_subdirs
cvs diff: Diffing tests/hard_coded
cvs diff: Diffing tests/hard_coded/exceptions
cvs diff: Diffing tests/hard_coded/purity
cvs diff: Diffing tests/hard_coded/sub-modules
cvs diff: Diffing tests/hard_coded/typeclasses
cvs diff: Diffing tests/invalid
cvs diff: Diffing tests/invalid/purity
cvs diff: Diffing tests/misc_tests
cvs diff: Diffing tests/mmc_make
cvs diff: Diffing tests/mmc_make/lib
cvs diff: Diffing tests/recompilation
cvs diff: Diffing tests/tabling
cvs diff: Diffing tests/term
cvs diff: Diffing tests/valid
cvs diff: Diffing tests/warnings
cvs diff: Diffing tools
cvs diff: Diffing trace
cvs diff: Diffing util
cvs diff: Diffing vim
cvs diff: Diffing vim/after
cvs diff: Diffing vim/ftplugin
cvs diff: Diffing vim/syntax
--------------------------------------------------------------------------
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