Files
mercury/runtime/mercury_deep_profiling.h
Zoltan Somogyi 2d0bfc0674 The algorithm that decides whether the order independent state update
Estimated hours taken: 120
Branches: main

The algorithm that decides whether the order independent state update
transformation is applicable in a given module needs access to the list
of oisu pragmas in that module, and to information about the types
of variables in the procedures named in those pragmas. This diff
puts this information in Deep.procrep files, to make them available
to the autoparallelization feedback program, to which that algorithm
will later be added.

Compilers that have this diff will generate Deep.procrep files in a new,
slightly different format, but the deep profiler will be able to read
Deep.procrep files not just in the new format, but in the old format as well.

runtime/mercury_stack_layout.h:
	Add to module layout structures the fields holding the new information
	we want to put into Deep.procrep files. This means three things:

	- a bytecode array in module layout structures encoding the list
	  of oisu pragmas in the module;
	- additions to the bytecode arrays in procedure layout structures
	  mapping the procedure's variables to their types; and
	- a bytecode array containing the encoded versions of those types
	  themselves in the module layout structure. This allows us to
	  represent each type used in the module just once.

	Since there is now information in module layout structures that
	is needed only for deep profiling, as well as information that is
	needed only for debugging, the old arrangement that split a module's
	information between two structures, MR_ModuleLayout (debug specific
	info) and MR_ModuleCommonLayout (info used by both debugging and
	profiling), is no longer approriate. We could add a third structure
	containing profiling-specific info, but it is simpler to move
	all the info into just one structure, some of whose fields
	may not be used. This wastes only a few words of memory per module,
	but allows the runtime system to avoid unnecessary indirections.

runtime/mercury_types.h:
	Remove the type synonym for the deleted type.

runtime/mercury_grade.h:
	The change in mercury_stack_layout.h destroys binary compatibility
	with previous versions of Mercury for debug and deep profiling grades,
	so bump their grade-component-specific version numbers.

runtime/mercury_deep_profiling.c:
	Write out the information in the new fields in module layout
	structures, if they are filled in.

	Since this changes the format of the Deep.procrep file, bump
	its version number.

runtime/mercury_deep_profiling.h:
runtime/mercury_stack_layout.c:
	Conform to the change to mercury_stack_layout.h.

mdbcomp/program_representation.m:
	Add to module representations information about the oisu pragmas
	defined in that module, and the type table of the module.
	Optionally add to procedure representations a map mapping
	the variables of the procedure to their types.

	Rename the old var_table type to be the var_name_table type,
	since it contains just names. Make the var to type map separate,
	since it will be there only for selected procedures.

	Modify the predicates reading in module and procedure representations
	to allow them to read in the new representation, while still accepting
	the old one. Use the version number in the Deep.procrep file to decide
	which format to expect.

mdbcomp/rtti_access.m:
	Add functions to encode the data representations that this module
	also decodes.

	Conform to the changes above.

mdbcomp/feedback.automatic_parallelism.m:
	Conform the changes above.

mdbcomp/prim_data.m:
	Fix layout.

compiler/layout.m:
	Update the compiler's representation of layout structures
	to conform to the change to runtime/mercury_stack_layout.h.

compiler/layout_out.m:
	Output the new parts of module layout structures.

compiler/opt_debug.m:
	Allow the debugging of code referring to the new parts of
	module layout structures.

compiler/llds_out_file.m:
	Conform to the move to a single module layout structure.

compiler/prog_rep_tables.m:
	This new module provided mechanisms for building the string table
	and the type table components of module layouts. The string table
	part is old (it is moved here from stack_layout.m); the type table
	part is new.

	Putting this code in a module of its own allows us to remove
	a circular dependency between prog_rep.m and stack_layout.m;
	instead, both now just depend on prog_rep_tables.m.

compiler/ll_backend.m:
	Add the new module.

compiler/notes/compiler_design.html:
	Describe the new module.

compiler/prog_rep.m:
	When generating the representation of a module for deep profiling,
	include the information needed by the order independent state update
	analysis: the list of oisu pragmas in the module, if any, and
	information about the types of variables in selected procedures.

	To avoid having these additions increasing the size of the bytecode
	representation too much, convert some fixed 32 bit numbers in the
	bytecode to use variable sized numbers, which will usually be 8 or 16
	bits.

	Do not use predicates from bytecode_gen.m to encode numbers,
	since there is nothing keeping these in sync with the code that
	reads them in mdbcomp/program_representation.m. Instead, use
	new predicates in program_representation.m itself.

compiler/stack_layout.m:
	Generate the new parts of module layouts.

	Remove the code moved to prog_rep_tables.m.

compiler/continuation_info.m:
compiler/proc_gen.m:
	Make some more information available to stack_layout.m.

compiler/prog_data.m:
	Fix some formatting.

compiler/introduce_parallelism.m:
	Conform to the renaming of the var_table type.

compiler/follow_code.m:
	Fix the bug that used to cause the failure of the
	hard_coded/mode_check_clauses test case in deep profiling grades.

deep_profiler/program_representation_utils.m:
	Output the new parts of module and procedure representations,
	to allow the correctness of this change to be tested.

deep_profiler/mdprof_create_feedback.m:
	If we cannot read the Deep.procrep file, print a single error message
	and exit, instead of continuing with an analysis that will generate
	a whole bunch of error messages, one for each attempt to access
	a procedure's representation.

deep_profiler/mdprof_procrep.m:
	Give this program an option that specifies what file it is to
	look at; do not hardwire in "Deep.procrep" in the current directory.

deep_profiler/report.m:
	Add a report type that just prints the representation of a module.
	It returns the same information as mdprof_procrep, but from within
	the deep profiler, which can be more convenient.

deep_profiler/create_report.m:
deep_profiler/display_report.m:
	Respectively create and display the new report type.

deep_profiler/query.m:
	Recognize a query asking for the new report type.

deep_profiler/autopar_calc_overlap.m:
deep_profiler/autopar_find_best_par.m:
deep_profiler/autopar_reports.m:
deep_profiler/autopar_search_callgraph.m:
deep_profiler/autopar_search_goals.m:
deep_profiler/autopar_types.m:
deep_profiler/branch_and_bound.m:
deep_profiler/coverage.m:
deep_profiler/display.m:
deep_profiler/html_format.m:
deep_profiler/mdprof_test.m:
deep_profiler/measurements.m:
deep_profiler/query.m:
deep_profiler/read_profile.m:
deep_profiler/recursion_patterns.m:
deep_profiler/top_procs.m:
deep_profiler/top_procs.m:
	Conform to the changes above.

	Fix layout.

tests/debugger/declarative/dependency.exp2:
	Add this file as a possible expected output. It contains the new
	field added to module representations.
2012-10-24 04:59:55 +00:00

470 lines
14 KiB
C

/*
** Copyright (C) 2001-2004, 2006-2008, 2010 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.
*/
/*
** mercury_deep_profiling.h -- definitions for deep profiling.
**
** See ../deep_profiler/README for some pointers to documentation on
** deep profiling.
*/
#ifndef MERCURY_DEEP_PROFILING_H
#define MERCURY_DEEP_PROFILING_H
#include "mercury_types.h" /* for MR_ConstString etc */
#include "mercury_ho_call.h"
#include <stdio.h>
typedef enum {
MR_callsite_normal_call,
MR_callsite_special_call,
MR_callsite_higher_order_call,
MR_callsite_method_call,
MR_callsite_callback
} MR_CallSiteKind;
struct MR_ProfilingMetrics_Struct {
#ifdef MR_DEEP_PROFILING_PORT_COUNTS
#ifdef MR_DEEP_PROFILING_EXPLICIT_CALL_COUNTS
unsigned MR_own_calls;
#else
/* calls are computed from the other fields */
#endif
unsigned MR_own_exits;
unsigned MR_own_fails;
unsigned MR_own_redos;
unsigned MR_own_excps;
#endif
#ifdef MR_DEEP_PROFILING_TIMING
volatile unsigned MR_own_quanta;
#endif
#ifdef MR_DEEP_PROFILING_CALL_SEQ
unsigned MR_own_call_seqs;
#endif
#ifdef MR_DEEP_PROFILING_MEMORY
unsigned MR_own_allocs;
unsigned MR_own_words;
#endif
/* ANSI/ISO C requires non-empty structs */
#if !defined(MR_DEEP_PROFILING_PORT_COUNTS) && \
!defined(MR_DEEP_PROFILING_TIMING) && \
!defined(MR_DEEP_PROFILING_MEMORY)
unsigned dummy;
#endif
};
/*
** The coverage point types. Please update the enum and type within
** mdbcomp/program_representation.m when updating this structure.
*/
typedef enum {
MR_cp_type_coverage_after,
MR_cp_type_branch_arm
} MR_CPType;
typedef struct {
const char *MR_cp_goal_path;
const MR_CPType MR_cp_type;
} MR_CoveragePointStatic;
struct MR_CallSiteStatic_Struct {
MR_CallSiteKind MR_css_kind;
MR_ProcLayout *MR_css_callee_ptr_if_known;
MR_ConstString MR_css_type_subst_if_known;
MR_ConstString MR_css_file_name;
int MR_css_line_number;
MR_ConstString MR_css_goal_path;
};
struct MR_ProcStatic_Struct {
MR_ConstString MR_ps_file_name;
int MR_ps_line_number;
int MR_ps_is_in_interface;
int MR_ps_num_call_sites;
const MR_CallSiteStatic *MR_ps_call_sites;
#ifdef MR_USE_ACTIVATION_COUNTS
int MR_ps_activation_count;
#endif
MR_ProcDynamic *MR_ps_outermost_activation_ptr;
int MR_ps_cur_csd_stack_slot;
int MR_ps_next_csd_stack_slot;
int MR_ps_old_outermost_stack_slot;
#ifdef MR_DEEP_PROFILING_COVERAGE
/*
** The number of coverage points in a procedure and static information
** about them are fixed at compile time, so they are associated with
** proc statics rather than proc dynamics.
*/
const MR_Unsigned MR_ps_num_coverage_points;
const MR_CoveragePointStatic * const MR_ps_coverage_points_static;
#ifdef MR_DEEP_PROFILING_COVERAGE_STATIC
/*
** Coverage data is kept in the ProcStatic structure if we're
** collecting it statically. See also MR_dyn_coverage_points
*/
MR_Unsigned * const MR_ps_coverage_points;
#endif
#endif
};
struct MR_CallSiteDynamic_Struct {
MR_ProcDynamic *MR_csd_callee_ptr;
MR_ProfilingMetrics MR_csd_own;
unsigned MR_csd_depth_count;
};
struct MR_ProcDynamic_Struct {
const MR_ProcLayout *MR_pd_proc_layout;
MR_CallSiteDynamic **MR_pd_call_site_ptr_ptrs;
#ifdef MR_DEEP_PROFILING_COVERAGE_DYNAMIC
/*
** Coverage data is kept in the ProcStatic structure initially, at a
** later stage more fine-grained coverage data may be associated with
** ProcDynamic if performance is not affected too much.
*/
MR_Unsigned *MR_pd_coverage_points;
#endif
};
struct MR_CallSiteDynList_Struct {
MR_CallSiteDynamic *MR_csdlist_call_site;
const void *MR_csdlist_key;
MR_CallSiteDynList *MR_csdlist_next;
};
typedef enum {
MR_deep_item_end = 0,
MR_deep_item_call_site_static,
MR_deep_item_call_site_dynamic,
MR_deep_item_proc_static,
MR_deep_item_proc_dynamic
} MR_DeepProfNextItem;
typedef enum {
MR_no_more_modules,
MR_next_module
} MR_MoreModules;
typedef enum {
MR_no_more_procs,
MR_next_proc
} MR_MoreProcs;
/*
** The definition of this type should be kept in sync with the code of
** the string_proclabel_kind_* functions in compiler/prog_rep.m.
*/
typedef enum {
MR_proclabel_user_predicate,
MR_proclabel_user_function,
MR_proclabel_special
} MR_ProcLabelToken;
#define MR_enter_instrumentation() \
do { MR_inside_deep_profiling_code = MR_TRUE; } while (0)
#define MR_leave_instrumentation() \
do { MR_inside_deep_profiling_code = MR_FALSE; } while (0)
#ifdef MR_DEEP_PROFILING_EXPLICIT_CALL_COUNTS
#define MR_init_own_call_port(csd) \
do { \
(csd)->MR_csd_own.MR_own_calls = 0; \
} while (0)
#else
#define MR_init_own_call_port(csd) \
((void) 0)
#endif
#ifdef MR_DEEP_PROFILING_PORT_COUNTS
#define MR_init_own_ports(csd) \
do { \
MR_init_own_call_port(csd); \
(csd)->MR_csd_own.MR_own_exits = 0; \
(csd)->MR_csd_own.MR_own_fails = 0; \
(csd)->MR_csd_own.MR_own_redos = 0; \
(csd)->MR_csd_own.MR_own_excps = 0; \
} while (0)
#else
#define MR_init_own_ports(csd) \
((void) 0)
#endif
#ifdef MR_DEEP_PROFILING_TIMING
#define MR_init_own_quanta(csd) \
do { \
(csd)->MR_csd_own.MR_own_quanta = 0; \
} while (0)
#else
#define MR_init_own_quanta(csd) \
((void) 0)
#endif
#ifdef MR_DEEP_PROFILING_CALL_SEQ
#define MR_init_own_call_seqs(csd) \
do { \
(csd)->MR_csd_own.MR_own_call_seqs = 0; \
} while (0)
#else
#define MR_init_own_call_seqs(csd) \
((void) 0)
#endif
#ifdef MR_DEEP_PROFILING_MEMORY
#define MR_init_own_memory(csd) \
do { \
(csd)->MR_csd_own.MR_own_allocs = 0; \
(csd)->MR_csd_own.MR_own_words = 0; \
} while (0)
#else
#define MR_init_own_memory(csd) \
((void) 0)
#endif
#ifdef MR_DEEP_PROFILING_TAIL_RECURSION
#define MR_init_depth_count(csd) \
do { \
(csd)->MR_csd_depth_count = 0; \
} while (0)
#else
#define MR_init_depth_count(csd) \
((void) 0)
#endif
#define MR_new_call_site_dynamic(newcsd) \
do { \
newcsd = MR_PROFILING_NEW(MR_CallSiteDynamic); \
\
newcsd->MR_csd_callee_ptr = NULL; \
MR_init_own_ports(newcsd); \
MR_init_own_quanta(newcsd); \
MR_init_own_call_seqs(newcsd); \
MR_init_own_memory(newcsd); \
MR_init_depth_count(newcsd); \
} while (0)
#ifdef MR_DEEP_PROFILING_COVERAGE_DYNAMIC
#define MR_pd_init_coverage_points(pd, ps) \
do { \
int num_cps; \
int cp_i; \
\
num_cps = (ps)->MR_ps_num_coverage_points; \
if (num_cps) { \
(pd)->MR_pd_coverage_points = \
MR_PROFILING_NEW_ARRAY(MR_Unsigned, num_cps); \
for (cp_i = 0; cp_i < num_cps; cp_i++) { \
(pd)->MR_pd_coverage_points[cp_i] = 0; \
} \
} \
} while (0)
#else
#define MR_pd_init_coverage_points(pd, ps) \
((void) 0)
#endif
/*
** TODO: Consider merging these mallocs into one, this should improve
** efficiency.
*/
#define MR_new_proc_dynamic(pd, pl) \
do { \
MR_ProcStatic *psl; \
int npdi; \
\
(pd) = MR_PROFILING_NEW(MR_ProcDynamic); \
(pd)->MR_pd_proc_layout = (pl); \
psl = (pl)->MR_sle_proc_static; \
(pd)->MR_pd_call_site_ptr_ptrs = \
MR_PROFILING_NEW_ARRAY(MR_CallSiteDynamic *, \
psl->MR_ps_num_call_sites); \
\
for (npdi = 0; npdi < psl->MR_ps_num_call_sites; npdi++) { \
(pd)->MR_pd_call_site_ptr_ptrs[npdi] = NULL; \
} \
MR_pd_init_coverage_points(pd, psl); \
} while (0)
#ifdef MR_DEEP_PROFILING_STATISTICS
extern int MR_deep_prof_search_len;
extern void MR_deep_profile_update_special_history(void);
extern void MR_deep_profile_update_closure_history(void);
extern void MR_deep_profile_update_method_history(void);
#define MR_maybe_init_search_len() \
do { MR_deep_prof_search_len = 0; } while(0)
#define MR_maybe_increment_search_len() \
do { MR_deep_prof_search_len++; } while (0)
#define MR_maybe_deep_profile_update_special_history() \
MR_deep_profile_update_special_history()
#define MR_maybe_deep_profile_update_closure_history() \
MR_deep_profile_update_closure_history()
#define MR_maybe_deep_profile_update_method_history() \
MR_deep_profile_update_method_history()
#else
#define MR_maybe_init_search_len() \
((void) 0)
#define MR_maybe_increment_search_len() \
((void) 0)
#define MR_maybe_deep_profile_update_special_history() \
((void) 0)
#define MR_maybe_deep_profile_update_closure_history() \
((void) 0)
#define MR_maybe_deep_profile_update_method_history() \
((void) 0)
#endif
#ifdef MR_DEEP_PROFILING_MOVE_TO_FRONT_LISTS
#define MR_maybe_update_prev(csdlist, prev) \
do { (prev) = (csdlist); } while (0)
#define MR_maybe_move_to_front(csdlist, prev, pd, csn) \
do { \
if (prev != NULL) { \
prev->MR_csdlist_next = csdlist->MR_csdlist_next;\
csdlist->MR_csdlist_next = (MR_CallSiteDynList *)\
pd->MR_pd_call_site_ptr_ptrs[(csn)]; \
pd->MR_pd_call_site_ptr_ptrs[(csn)] = \
(MR_CallSiteDynamic *) csdlist; \
} \
} while (0)
#else
#define MR_maybe_update_prev(csdlist, prev) \
((void) 0)
#define MR_maybe_move_to_front(csdlist, prev, pd, csn) \
((void) 0)
#endif
#define MR_search_csdlist(csdlist, prev, pd, csn, void_key) \
do { \
(csdlist) = (MR_CallSiteDynList *) (pd)-> \
MR_pd_call_site_ptr_ptrs[(csn)]; \
MR_maybe_init_search_len(); \
while ((csdlist) != NULL) { \
MR_maybe_increment_search_len(); \
if ((csdlist)->MR_csdlist_key == (void_key)) { \
MR_maybe_move_to_front((csdlist), (prev),\
(pd), (csn)); \
break; \
} \
MR_maybe_update_prev((csdlist), (prev)); \
(csdlist) = (csdlist)->MR_csdlist_next; \
} \
} while (0)
#define MR_make_and_link_csdlist(csdlist, newcsd, pd, csn, void_key) \
do { \
(csdlist) = MR_PROFILING_NEW(MR_CallSiteDynList); \
(csdlist)->MR_csdlist_key = (void_key); \
(csdlist)->MR_csdlist_call_site = (newcsd); \
(csdlist)->MR_csdlist_next = (MR_CallSiteDynList *) \
(pd)->MR_pd_call_site_ptr_ptrs[(csn)]; \
pd->MR_pd_call_site_ptr_ptrs[(csn)] \
= (MR_CallSiteDynamic *) (csdlist); \
} while (0)
#define MR_make_and_link_csdlist_callback(csdlist, newcsd, void_key) \
do { \
(csdlist) = MR_PROFILING_NEW(MR_CallSiteDynList); \
(csdlist)->MR_csdlist_key = (void_key); \
(csdlist)->MR_csdlist_call_site = (newcsd); \
(csdlist)->MR_csdlist_next = *MR_current_callback_site; \
*MR_current_callback_site = (csdlist); \
} while (0)
#ifdef MR_DEEP_CHECKS
#define MR_deep_assert(csd, pl, ps, cond) \
do { \
if (!(cond)) { \
MR_deep_assert_failed(csd, pl, ps, \
MR_STRINGIFY(cond), __FILE__, __LINE__); \
} \
} while (0)
#else
#define MR_deep_assert(csd, pl, ps, cond) \
((void) 0)
#endif
#if defined(MR_DEEP_PROFILING) && defined(MR_EXEC_TRACE)
extern MR_bool MR_disable_deep_profiling_in_debugger;
#endif
extern MR_CallSiteDynamic *MR_current_call_site_dynamic;
extern MR_CallSiteDynamic *MR_next_call_site_dynamic;
extern MR_CallSiteDynList **MR_current_callback_site;
extern MR_CallSiteDynamic *MR_root_call_sites[];
extern volatile MR_bool MR_inside_deep_profiling_code;
extern volatile unsigned MR_quanta_inside_deep_profiling_code;
extern volatile unsigned MR_quanta_outside_deep_profiling_code;
#ifdef MR_DEEP_PROFILING_CALL_SEQ
extern unsigned MR_deep_prof_cur_call_seq;
#endif
#ifdef MR_DEEP_PROFILING_STATISTICS
#define MR_MAX_CLOSURE_LIST_LENGTH 256
extern int MR_deep_prof_prep_normal_new;
extern int MR_deep_prof_prep_normal_old;
extern int MR_deep_prof_prep_special_new;
extern int MR_deep_prof_prep_special_old;
extern int MR_deep_prof_prep_ho_new;
extern int MR_deep_prof_prep_ho_old;
extern int MR_deep_prof_prep_method_new;
extern int MR_deep_prof_prep_method_old;
extern int MR_deep_prof_prep_callback_new;
extern int MR_deep_prof_prep_callback_old;
extern int MR_deep_prof_prep_tail_new;
extern int MR_deep_prof_prep_tail_old;
extern int MR_deep_prof_call_new;
extern int MR_deep_prof_call_rec;
extern int MR_deep_prof_call_old;
extern int MR_deep_prof_call_builtin_new;
extern int MR_deep_prof_call_builtin_old;
#endif /* MR_DEEP_PROFILING_STATISTICS */
#ifdef MR_DEEP_PROFILING_LOG
extern FILE *MR_deep_prof_log_file;
extern void MR_deep_log_proc_statics(FILE *fp);
#endif
extern void MR_deep_assert_failed(const MR_CallSiteDynamic *csd,
const MR_ProcLayout *pl, const MR_ProcStatic *ps,
const char *cond, const char *filename,
int linenumber);
extern void MR_setup_callback(void *entry);
extern void MR_write_out_str_proc_label(FILE *deep_fp,
const MR_ProcId *procid);
extern void MR_write_out_user_proc_static(FILE *deep_fp, FILE *procrep_fp,
const MR_ProcLayoutUser *proc_layout);
extern void MR_write_out_uci_proc_static(FILE *deep_fp, FILE *procrep_fp,
const MR_ProcLayoutUCI *proc_layout);
extern void MR_write_out_proc_static(FILE *deep_fp, FILE *procrep_fp,
const MR_ProcLayout *proc_layout);
extern void MR_write_out_module_proc_reps_start(FILE *procrep_fp,
const MR_ModuleLayout *module_layout);
extern void MR_write_out_module_proc_reps_end(FILE *procrep_fp);
extern void MR_write_out_profiling_tree(void);
extern void MR_deep_prof_init(void);
extern void MR_deep_prof_turn_on_time_profiling(void);
extern void MR_deep_prof_turn_off_time_profiling(void);
#define MR_PROFILING_MALLOC(size) MR_GC_malloc(size)
#define MR_PROFILING_NEW(type) MR_NEW(type)
#define MR_PROFILING_NEW_ARRAY(type, nelems) MR_NEW_ARRAY(type, nelems)
#endif /* not MERCURY_DEEP_PROFILING_H */