mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-09 02:43:21 +00:00
Discussion of these changes can be found on the Mercury developers
mailing list archives from June 2018.
COPYING.LIB:
Add a special linking exception to the LGPL.
*:
Update references to COPYING.LIB.
Clean up some minor errors that have accumulated in copyright
messages.
460 lines
20 KiB
C
460 lines
20 KiB
C
// vim: ts=4 sw=4 expandtab ft=c
|
|
|
|
// Copyright (C) 2001-2004, 2006-2008, 2010 The University of Melbourne.
|
|
// Copyright (C) 2016, 2018 The Mercury team.
|
|
// This file is distributed under the terms specified in COPYING.LIB.
|
|
|
|
// 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 are
|
|
// 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
|