mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-12 12:26:29 +00:00
Estimated hours taken: 120
Branches: main
The following change is only 98% complete, not 100%. I am committing it in
this state because (1) we pass many more test cases in deep profiling grade
with it than without it, and (2) the double maintanance involved in fixing
CVS conflicts is preventing me from doing the last 2%.
Get the deep profiler to work for code that sets up to catch exceptions,
which for the last year or more has included the compiler, and to get it
almost working for code that actually catching exceptions.
The basic problem is that code that throws exceptions will in general cause
several calls to "return" without executing the exit or fail port codes that
the deep profiling transformation inserted into their bodies, and this leaves
the data structure being built by the deep profiling inconsistent. The solution
uses the same approach as we have adopted for the debugger: have the code that
handles the throwing of exceptions simulate a return from each call between
the throw and the catch, updating the deep profiling data structures as needed.
This requires us to be able to walk the stack at runtime not just in debugging
grades but also in deep profiling grades. Since the debugger already has the
mechanisms required for this, we reuse them. The procedure layouts used by the
debugger were designed to have three segments: the procedure stack walk
information, the procedure id, and the execution tracing information. We now
modify this design to make the third segment contain two pointers: to the
execution tracing information (for use by the debugger), and to the procedure's
proc_static structure (for use by deep profiling). Each pointer will be null
unless the pointed-to structure is required by compile-time options.
This common use by the debugger and by deep profiling of the stack-walk
structure and the procedure id structure (which deep profiling used to
generate independently and possibly redundantly) required some rearrangement
of the compiler's version of these data structures.
To make this rearrangement simpler, this diff removes a capability that
we theoretically supported but never used: turning on stack traces without
turning on execution tracing and vice versa. After this diff, stack tracing
is enabled if and only if either execution tracing or deep profiling is
enabled.
The diff also includes improvements in the debugging infrastructure for
debugging deep profiling, which were necessary for the implementation of the
rest of the changes.
compiler/deep_profiling.m:
The code in exception.m needs to know the locations of the variables
that we would pass to the exit or fail port code, so it can simulate
leaving the procedure invocation through the exception port. Without
this information, throwing an exception leaves the deep profiling
data structures of the procedure invocations between throw and catch
in an inconsistent state.
Deep_profiling.m creates these variables, but it doesn't know where
they will be at runtime, so it records their identities; the code
generator will allocate them stack slots and record the numbers of
these stack slots for placement in the now expanded proc layout
structures. Deep profiling used to generate static data structures
separately from the HLDS, but since the code generator now needs
access to them, we store their information in proc_infos in the HLDS.
Instead of passing the addresses of proc_static structures to the deep
profiling port procedures, pass the address of proc_layout structures,
since the information about the identities of procedures are now stored
not in the proc_static structure, but in the proc_layout structure
that points to the proc_static structure.
compiler/hlds_pred.m:
compiler/layout.m:
Move the definitions of the static data structures generated by deep
profiling from layout.m to hlds_pred.m, to allow deep_profiling.m
to store them in proc_infos.
compiler/hlds_pred.m:
compiler/rtti.m:
Move the definition of rtti_proc_label from rtti.m to hlds_pred.m,
since some of the new data structures in hlds_pred.m need it. Despite
its name, the rtti_proc_label type doesn't contain any info that
doesn't belong in the HLDS.
Add some information to the rtti_proc_label type that is now needed
by deep profiling, e.g. record determinisms instead of just code
models. Record explicitly the outcome of some tests that used to be
duplicated in more than one place in the compiler, e.g. for whether
the procedure (as opposed to the predicate) is imported. Change some
of the field names to be more precise about the field's meaning.
compiler/code_gen.m:
Transmit the contents of the deep profiling data structures stored in
the proc_info by deep_profiling.m to continuation_info.m, together
with the layout structures created for execution tracing and the
identities of the variables needed for handling exceptions,
when code generation for a procedure is complete.
After the goal that generates these variables, save them to stack
for use by the exception handler.
compiler/hlds_goal.m:
Add a feature to mark the goal that generates the deep profiling
variables needed by the exception handler.
compiler/hlds_llds.m:
Add a utility predicate for new code in code_gen.m
compiler/continuation_info.m:
Hold the deep profiling information computed by code_gen.m for use by
stack_layout.m.
compiler/layout.m:
compiler/layout_out.m:
Update the definitions of the data structures describing procedure
layouts, and the code writing them out, to reflect the use of some
parts of procedure layouts by deep profiling as well as debugging.
Change the layout structures generated by deep profiling to use
rtti_proc_labels, which are backend independent, instead of
proc_labels, which are specific to the LLDS backend.
Conform to the changes in runtime/mercury_stack_layout.h.
compiler/stack_layout.m:
Generate the updated version of proc_layout structures.
compiler/mercury_compile.m:
compiler/global_data.m:
Conform to the fact that deep profiling no longer generates layout
structures separate from proc_infos.
compiler/llds_out.m:
Register proc_layout structures instead of proc_static structures
for use by runtime/mercury_deep_profiling.c.
compiler/options.m:
compiler/handle_options.m:
Rename the require_tracing option as exec_trace, since this more
directly reflects its meaning.
Instead of having --debug set both require_tracing and stack_trace,
make it set (be the user-visible name of) just exec_trace;
the value of stack_trace is implied.
Turn off the specialization of deep profiling for self-tail-recursive
procedures for now. Due to the changes made by this diff in the data
structures involved in debugging, it cannot be debugged until this
change has been installed. Handling the full language is more important
than a specialization that reduces only stack space overheads, not
runtime overheads.
compiler/compile_target_code.m:
Conform to the changes in options.m and runtime/mercury_grade.h.
compiler/hlds_data.m:
Replace the deep_profiling_proc_static cons_id, and its associated tag,
to deep_profiling_proc_layout, since we now generate addresses of proc
layout structures, not of proc_static structures.
compiler/code_util.m:
Simplify some code based on the new info in rtti_proc_labels.
compiler/bytecode_gen.m:
compiler/dependency_graph.m:
compiler/higher_order.m:
compiler/hlds_out.m:
compiler/mercury_to_mercury.m:
compiler/ml_code_util.m:
compiler/ml_unify_gen.m:
compiler/opt_debug.m:
compiler/proc_label.m:
compiler/prog_rep.m:
compiler/rl_exprn.m:
compiler/rtti_out.m:
compiler/rtti_to_mlds.m:
compiler/saved_vars.m:
compiler/switch_util.m:
compiler/unify_gen.m:
Minor changes to conform to the change from deep_profiling_proc_static
to deep_profiling_proc_layout, to the change in the structure of
rtti_proc_labels, to the changes in types of layout.m, and/or to the
new goal feature.
deep_profiler/measurements.m:
Reserve space for exception counts.
deep_profiler/html_format.m:
Add a column for exception counts.
deep_profiler/profile.m:
deep_profiler/read_profile.m:
Rename the data structures referring to compiler generated unify,
compare and index predicates to avoid misleading names: they are
not the only compiler generated predicates.
deep_profiler/read_profile.m:
runtime/mercury_deep_profiling.c:
Update the string that identifies deep profiling data files.
This is necessary because the format has changed: it now includes
information about exception port counts.
library/exception.m:
In deep profiling grades, execute the exception port code for every
procedure invocation between a throw and a catch, using the procedure
layout structures now generated by the compiler for every procedure.
Rename the function involved to reflect its new, more general purpose.
Update the definitions of the hand-written proc_static and proc_layout
structures for the procedures implemented via hand-written C code.
Indent C preprocessor directives and foreign_procs according to our
coding standards.
library/profiling_builtin.m:
Change the parameters of the call port code procedures from proc_static
to proc_layout. Reach the proc_static structure from the proc_layout
structure when needed. Include the proc_layout structure in any
messages from assertion failures.
Add some conditionally compiled debugging code.
Give some variables better names.
runtime/mercury_type_info.h:
runtime/mercury_builtin_types.c:
Move the macros required to create the proc_static structures
of unify and compare predicates from mercury_type_info.h
to mercury_builtin_types.c, since the latter is the only file
that needs them.
Use the same macros for creating the proc_static structures
of hand-written unify, compare and compare_reprentation predicates
as for user defined predicates. This required changing their naming
scheme.
runtime/mercury_unify_compare_body.h:
Conform to the new naming scheme.
runtime/mercury_ho_call.c:
Provide the mechanism for mercury_unify_compare_body.h to conform
to the new naming scheme.
Remove the definitions of the proc_static structures for
hand-written unify, compare and compare_reprentation predicates,
since these now have to be defined together with the corresponding
proc_layout structures in mercury_builtin_types.c.
runtime/mercury_builtin_types.[ch]:
Update the definitions of the hand-written proc_static and proc_layout
structures for the procedures implemented via hand-written C code,
and add the required declarations first.
Handle deep profiling of compare_representation as well as unify
and compare predicates on builtin types.
Handle deep profiling of compare_representation on user-defined types,
since this is done entirely in the runtime, not by compiler generated
predicates.
runtime/mercury_builtin_types_proc_layouts.h:
New header file containing the declarations of the proc layout
structures of the unify, compare and index predicates of builtin types.
Logically, these declarations belong in mercury_builtin_types.h,
but putting them there causes problems for the linker; the details
are explained in the file itself.
runtime/Mmakefile:
Add the new header file.
runtime/mercury_minimal_model.[ch]:
Update the definitions of the hand-written proc_static and proc_layout
structures for the procedures implemented via hand-written C code,
and add the required declarations first.
runtime/mercury_grade.h:
Replace the MR_REQUIRE_TRACING grade option with MR_EXEC_TRACING.
Besides being better named, the MR_EXEC_TRACING option implies
MR_STACK_TRACE.
Besides the overall binary compatibility version number, add subsidiary
version numbers for binary compatibility in deep profiling and
debugging grades. These will make it easier to bootstrap changes
(such as this) that affect binary compatibility only in such grades.
runtime/mercury_trace_base.c:
trace/mercury_trace.c:
Conform to the new names of the configuration parameters.
runtime/mercury_hand_compare_body.h:
runtime/mercury_hand_unify_body.h:
runtime/mercury_hand_unify_compare_body.h:
runtime/mercury_ho_call.c:
tools/make_port_code:
Pass proc_layout structures instead of proc_static structures
to deep profiling port routines.
runtime/mercury_conf_param.h:
Make MR_DEEP_PROFILING as well as MR_EXEC_TRACING imply MR_STACK_TRACE,
since deep profiling now needs stack tracing. (MR_STACK_TRACE needs
to be set in this file, because tests in this file depend on knowing
its value, and this file is among the first files included (in this
case indirectly) in mercury_imp.h.)
Document the macros controlling the debugging of deep profiling.
Enable printing of label names when the relevant deep profiling
debugging macro is set.
runtime/mercury_debug.c:
runtime/mercury_deep_rec_depth_actions.h:
runtime/mercury_deep_rec_depth_body.h:
runtime/mercury_exception_catch_body.h:
Get to proc_statics via proc_layouts.
runtime/mercury_deep_call_port_body.c:
runtime/mercury_deep_leave_port_body.c:
Get to proc_statics via proc_layouts.
Allow the debugger to disable deep profiling in Mercury code that is
part of the debugger, not of the user program being executed.
Add some more assertions.
runtime/mercury_engine.[ch]:
Add a new debugging flag that controls at runtime whether we generate
a human readable Deep.debug equivalent to the binary Deep.data files.
(We already had a mechanism for controlling this at compile time,
but this isn't flexible enough.)
runtime/mercury_wrapper.c:
Allow this new debugging flag to be set from MERCURY_OPTIONS.
runtime/mercury_deep_profiling.[ch]:
Respect this new debugging flag.
Update the hand-written proc_static structures representing the runtime
system.
Print out addresses of proc_layout as well as proc_static structures
when assertions fail.
Add a field to the measurement structure for exception port counts,
and write out this field with the other port counts.
Remove procedure id information from proc_static structures,
deep profiling now uses the procedure id in the proc_layout structure.
Add to proc_static structures fields that specify where, if anywhere,
the variables needed by exception.m to executed the exception port code
are in the procedure's stack frame.
Define a global flag that allows the debugger to disable deep
profiling in Mercury code that is part of the debugger, not of the
user program being executed.
Increase type safety by providing two versions of the function
for registering proc_layouts, one for the proc_layout structures
of user-defined predicates and one for unify, compare and index
predicates.
Fix a bug that occurs only if MR_DEEP_PROFILING_EXPLICIT_CALL_COUNTS is
defined (which it usually isn't): the initial call count was wrong.
runtime/mercury_deep_profiling_hand.h:
Fix a bug: the handwritten code saving deep profiling variables was
saving them in slots that didn't belong to the relevant stack frame.
Update to conform to the modified definitions of proc_static structures
and the fact that we now reach them via proc_layout structures.
runtime/mercury_exception_catch_body.h:
runtime/mercury_stacks.h:
Fix the other side of the bug in mercury_deep_profiling_hand.h
by reserving the right number of stack slots in the stack frames
of the various modes of exception__catch. Make it harder to make
the same bug in the future by getting the needed info from the
place in mercury_stacks.h that defines the structure of the relevant
stack frame.
runtime/mercury_proc_id.h:
Rename the procedure id structure fields referring to compiler
generated unify, compare and index predicates: they are not the only
compiler-generated predicates.
runtime/mercury_stack_layout.h:
Change procedure layout structures to allow them to be used for deep
profiling as well as for debugging, as described in the prologue above.
We don't need the capability to support label layout structures with
links to misnamed proc layout structures, and supporting it is
inconvenient, so delete the capability.
runtime/mercury_debug.c:
runtime/mercury_deep_profiling_hand.h:
runtime/mercury_layout_util.c:
runtime/mercury_ml_expand_body.h:
runtime/mercury_stack_trace.c:
runtime/mercury_types.h:
trace/mercury_trace_external.c:
Conform to the new names of the procedure id structure fields.
runtime/mercury_std.h:
Add some more arities for MR_PASTE for use in some of the modified
modules in the runtime.
trace/mercury_trace_internal.c:
Disable deep profiling actions in Mercury code that is part of the
debugger, not of the program being debugged.
scripts/init_grade_options.sh-subr:
scripts/parse_grade_options.sh-subr:
Make changes parallel to the ones in runtime/mercury_grade.h: delete
--stack-trace as an independent option, and make --debug set its
own option, not --require-tracing.
scripts/canonical_grade.sh-subr:
scripts/final_grade_options.sh-subr:
scripts/c2init.in:
scripts/mgnuc.in:
scripts/ml.in:
Conform to the changes in grade options for debugging and for deep
profiling.
tools/bootcheck:
If Mmake.stage.{browser,deep,library,runtime,trace}.params exist,
copy them to become the file Mmake.$dir.params in stage2/$dir
(where dir is derived from the name of the original file in the obvious
way). This allows more flexibility in the creation of the stage2;
for example, it allows some directories (e.g. runtime or library)
to be compiled with more debugging than other directories (e.g.
compiler). This may be required because compiling all directories
with lots of debugging may cause the linker to thrash.
Add an option, --disable-debug-libs, that clobbers the libraries
that should be linked in only in debugging grades.
To conserve disk space, remove Deep.data files created by the bootcheck
by default. Add an option, --keep-deep-data, to preserve these files.
Use a consistent mechanism (test -f) for testing the existence of
all files whose existence is tested.
When recording modification times, record the modification times
of some more files.
tests/hard_coded/Mmakefile:
In deep profiling grades, disable the test cases that we don't now
pass in such grades, and document the reasons for their failure.
Fix the misclassification of the write_binary test case.
140 lines
3.9 KiB
C
140 lines
3.9 KiB
C
/*
|
|
** Copyright (C) 2001-2002, 2004 The University of Melbourne.
|
|
** This file may only be copied under the terms of the GNU Library General
|
|
** Public License - see the file COPYING.LIB in the Mercury distribution.
|
|
*/
|
|
|
|
/*
|
|
** The internals of exception:builtin_catch.
|
|
**
|
|
** The versions of builtin_catch for the various determinisms should define
|
|
** the following macros:
|
|
**
|
|
** proc_label
|
|
** proc_layout
|
|
** model
|
|
** excp_handler
|
|
** handle_ticket_on_exit
|
|
**
|
|
** For the model_non versions, it should also define
|
|
**
|
|
** version_model_non
|
|
** handle_ticket_on_fail
|
|
*/
|
|
|
|
/*
|
|
** Each procedure defines several local labels. The local label numbers are
|
|
** allocated as follows. Note that not all procedures use all of these labels.
|
|
*/
|
|
|
|
#define CALL_PORT_RETURN_LABEL(pl) MR_label_name(pl, 1)
|
|
#define CLOSURE_RETURN_LABEL(pl) MR_label_name(pl, 2)
|
|
#define EXIT_PORT_RETURN_LABEL(pl) MR_label_name(pl, 3)
|
|
#define REDO_REDOIP_LABEL(pl) MR_label_name(pl, 4)
|
|
#define REDO_PORT_RETURN_LABEL(pl) MR_label_name(pl, 5)
|
|
#define FAIL_REDOIP_LABEL(pl) MR_label_name(pl, 6)
|
|
#define FAIL_PORT_RETURN_LABEL(pl) MR_label_name(pl, 7)
|
|
#define PREPARE_RETURN_LABEL(pl) MR_label_name(pl, 8)
|
|
|
|
#if defined(version_model_non) && \
|
|
(defined(MR_USE_TRAIL) || defined(MR_DEEP_PROFILING))
|
|
#define excp_catch_redoip(pl) MR_LABEL(FAIL_REDOIP_LABEL(pl))
|
|
#else
|
|
#define excp_catch_redoip(pl) MR_ENTRY(MR_do_fail);
|
|
#endif
|
|
|
|
/*****************************************************************************/
|
|
|
|
MR_define_entry(proc_label);
|
|
|
|
/*
|
|
** Create an exception handler entry on the nondet stack.
|
|
** (Register MR_r3 holds the Handler closure.)
|
|
*/
|
|
MR_create_exception_handler("builtin_catch/3" model,
|
|
excp_handler, MR_r3, excp_catch_redoip(proc_label));
|
|
|
|
#if defined(version_model_non) && defined(MR_DEEP_PROFILING)
|
|
/*
|
|
** Give the deep profiler control when execution backtracks into
|
|
** the closure.
|
|
*/
|
|
MR_mktempframe(MR_LABEL(REDO_REDOIP_LABEL(proc_label)));
|
|
#endif
|
|
|
|
#ifdef MR_DEEP_PROFILING
|
|
MR_framevar(1) = MR_r2;
|
|
MR_deep_non_call(proc_label, proc_layout,
|
|
MR_EXCEPTION_FIRST_DEEP_SLOT,
|
|
CALL_PORT_RETURN_LABEL(proc_label));
|
|
MR_deep_prepare_ho_call(proc_label, MR_EXCEPTION_FIRST_DEEP_SLOT,
|
|
PREPARE_RETURN_LABEL(proc_label), 0, MR_framevar(1));
|
|
MR_r1 = MR_framevar(1); /* The Goal to call */
|
|
#else
|
|
MR_r1 = MR_r2; /* The Goal to call */
|
|
#endif
|
|
MR_r2 = 0; /* Zero additional input arguments */
|
|
/*
|
|
** Now call `Goal(Result)'.
|
|
*/
|
|
MR_call(MR_ENTRY(mercury__do_call_closure_compact),
|
|
MR_LABEL(CLOSURE_RETURN_LABEL(proc_label)),
|
|
MR_ENTRY(proc_label));
|
|
|
|
MR_define_label(CLOSURE_RETURN_LABEL(proc_label));
|
|
MR_update_prof_current_proc(MR_LABEL(proc_label));
|
|
|
|
#ifdef MR_DEEP_PROFILING
|
|
save_results();
|
|
MR_deep_non_exit(proc_layout, MR_EXCEPTION_FIRST_DEEP_SLOT,
|
|
EXIT_PORT_RETURN_LABEL(proc_label));
|
|
restore_results();
|
|
#endif
|
|
|
|
#ifdef MR_USE_TRAIL
|
|
handle_ticket_on_exit();
|
|
#endif
|
|
|
|
#ifdef version_model_non
|
|
MR_succeed();
|
|
#else
|
|
MR_succeed_discard();
|
|
#endif
|
|
|
|
#if defined(version_model_non) && defined(MR_DEEP_PROFILING)
|
|
MR_define_label(REDO_REDOIP_LABEL(proc_label));
|
|
MR_deep_non_redo(proc_layout, MR_EXCEPTION_FIRST_DEEP_SLOT,
|
|
REDO_PORT_RETURN_LABEL(proc_label));
|
|
/* non_redo_port_code executes *semidet* failure */
|
|
MR_fail();
|
|
#endif
|
|
|
|
#if defined(version_model_non) && \
|
|
(defined(MR_USE_TRAIL) || defined(MR_DEEP_PROFILING))
|
|
|
|
MR_define_label(FAIL_REDOIP_LABEL(proc_label));
|
|
|
|
#ifdef MR_USE_TRAIL
|
|
handle_ticket_on_fail();
|
|
#endif
|
|
|
|
#ifdef MR_DEEP_PROFILING
|
|
MR_deep_non_fail(proc_layout, MR_EXCEPTION_FIRST_DEEP_SLOT,
|
|
FAIL_PORT_RETURN_LABEL(proc_label));
|
|
/* non_redo_port_code executes *semidet* failure */
|
|
#endif
|
|
MR_fail();
|
|
|
|
#endif /* defined(version_model_non) && \
|
|
(defined(MR_USE_TRAIL) || defined(MR_DEEP_PROFILING)) */
|
|
|
|
#undef CALL_PORT_RETURN_LABEL
|
|
#undef CLOSURE_RETURN_LABEL
|
|
#undef EXIT_PORT_RETURN_LABEL
|
|
#undef REDO_REDOIP_LABEL
|
|
#undef REDO_PORT_RETURN_LABEL
|
|
#undef FAIL_REDOIP_LABEL
|
|
#undef FAIL_PORT_RETURN_LABEL
|
|
|
|
#undef excp_catch_redoip
|