mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-16 22:35:41 +00:00
Estimated hours taken: 2 Branches: main The runtime had two different conventions for naming types. One convention, used mostly in the debugger-related modules, added underscores between capitalized words; example: MR_Label_Layout. The other convention, used in most modules, used capitalized words without underscores (e.g. MR_TypeInfo). This diff standardizes on the second convention. It has no algorithmic changes, only renames of types. runtime/*.[ch]: trace/*.[ch]: compiler/*.m: library/*.m: mdbcomp/*.m: Effect the change described above. The only substantive change is that runtime/mercury_stack_layout.h used to define *two* types for trace levels: MR_TraceLevel and MR_Trace_Level, and this diff standardizes on just one (they had equivalent definitions). runtime/mercury_bootstrap.h: Add a #define from the old name to the new for all the changed type names that the installed compiler can put into .c files. We can delete these #defines some time after this diff has bootstrapped. slice/.mgnuc_opts: Restore the --no-mercury-stdlib-dir option, without which the slice directory won't compile after this change (because it looks for type names in the installed runtime header files, which define the old versions of type names).
1692 lines
51 KiB
C
1692 lines
51 KiB
C
/*
|
|
** vim:sw=4 ts=4 expandtab
|
|
*/
|
|
/*
|
|
** Copyright (C) 2001-2006 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.
|
|
*/
|
|
|
|
/*
|
|
** Deep profiling module
|
|
**
|
|
** See ../deep_profiler/README for some pointers to documentation
|
|
** on deep profiling.
|
|
**
|
|
** Authors: conway, zs
|
|
*/
|
|
|
|
/* turn on assertions, to protect the integrity of the generated data files */
|
|
#define MR_DEEP_CHECKS
|
|
|
|
#include "mercury_imp.h"
|
|
#include "mercury_ho_call.h"
|
|
#include "mercury_stack_layout.h"
|
|
#include "mercury_timing.h"
|
|
#include "mercury_prof_time.h"
|
|
#include "mercury_runtime_util.h" /* for strerror() on some systems */
|
|
#include "mercury_deep_profiling.h"
|
|
#include "mercury_deep_profiling_hand.h"
|
|
|
|
#ifdef MR_DEEP_PROFILING
|
|
|
|
#include <stdio.h>
|
|
#include <errno.h>
|
|
|
|
#ifdef MR_EXEC_TRACE
|
|
MR_bool MR_disable_deep_profiling_in_debugger = MR_FALSE;
|
|
#endif
|
|
|
|
MR_CallSiteStatic MR_main_parent_call_site_statics[1] =
|
|
{
|
|
{ MR_callback, NULL, NULL, "Mercury runtime", 0, "" }
|
|
};
|
|
|
|
MR_ProcStatic MR_main_parent_proc_static =
|
|
{
|
|
"Mercury runtime",
|
|
0,
|
|
MR_TRUE,
|
|
1,
|
|
&MR_main_parent_call_site_statics[0],
|
|
#ifdef MR_USE_ACTIVATION_COUNTS
|
|
0,
|
|
#endif
|
|
NULL,
|
|
-1,
|
|
-1,
|
|
-1
|
|
};
|
|
|
|
MR_ProcLayoutUser MR_main_parent_proc_layout =
|
|
{
|
|
{ MR_do_not_reached, { MR_LONG_LVAL_TYPE_UNKNOWN }, -1, MR_DETISM_DET },
|
|
{ MR_PREDICATE, "Mercury runtime", "Mercury runtime",
|
|
"Mercury runtime", 0, 0 },
|
|
NULL,
|
|
&MR_main_parent_proc_static
|
|
};
|
|
|
|
MR_CallSiteDynamic *MR_main_parent_call_site_dynamics[1] =
|
|
{
|
|
NULL
|
|
};
|
|
|
|
MR_ProcDynamic MR_main_parent_proc_dynamic =
|
|
{
|
|
(MR_ProcLayout *) &MR_main_parent_proc_layout,
|
|
&MR_main_parent_call_site_dynamics[0]
|
|
};
|
|
|
|
MR_CallSiteDynamic MR_main_grandparent_call_site_dynamic =
|
|
{
|
|
&MR_main_parent_proc_dynamic,
|
|
{
|
|
#ifdef MR_DEEP_PROFILING_PORT_COUNTS
|
|
#ifdef MR_DEEP_PROFILING_EXPLICIT_CALL_COUNTS
|
|
1,
|
|
#else
|
|
/* the call count is computed from the other counts */
|
|
#endif
|
|
1, 0, 0, 0,
|
|
#endif
|
|
#ifdef MR_DEEP_PROFILING_TIMING
|
|
0,
|
|
#endif
|
|
#ifdef MR_DEEP_PROFILING_MEMORY
|
|
0, 0
|
|
#endif
|
|
},
|
|
0
|
|
};
|
|
|
|
MR_CallSiteDynamic *MR_current_call_site_dynamic =
|
|
&MR_main_grandparent_call_site_dynamic;
|
|
MR_CallSiteDynamic *MR_next_call_site_dynamic = NULL;
|
|
MR_CallSiteDynList **MR_current_callback_site = (MR_CallSiteDynList **)
|
|
&MR_main_parent_call_site_dynamics[0];
|
|
|
|
volatile MR_bool MR_inside_deep_profiling_code = MR_FALSE;
|
|
volatile unsigned MR_quanta_inside_deep_profiling_code = 0;
|
|
volatile unsigned MR_quanta_outside_deep_profiling_code = 0;
|
|
|
|
#ifdef MR_DEEP_PROFILING_CALL_SEQ
|
|
unsigned MR_deep_prof_cur_call_seq = 0;
|
|
#endif
|
|
|
|
#ifdef MR_DEEP_PROFILING_STATISTICS
|
|
|
|
int MR_deep_num_csd_nodes = 0;
|
|
int MR_deep_num_pd_nodes = 0;
|
|
int MR_deep_num_pd_array_slots = 0;
|
|
int MR_deep_num_dynlist_nodes = 0;
|
|
|
|
int MR_dictionary_search_lengths[MR_MAX_CLOSURE_LIST_LENGTH];
|
|
int MR_closure_search_lengths[MR_MAX_CLOSURE_LIST_LENGTH];
|
|
int MR_method_search_lengths[MR_MAX_CLOSURE_LIST_LENGTH];
|
|
|
|
int MR_deep_prof_prep_normal_new = 0;
|
|
int MR_deep_prof_prep_normal_old = 0;
|
|
int MR_deep_prof_prep_special_new = 0;
|
|
int MR_deep_prof_prep_special_old = 0;
|
|
int MR_deep_prof_prep_ho_new = 0;
|
|
int MR_deep_prof_prep_ho_old = 0;
|
|
int MR_deep_prof_prep_method_new = 0;
|
|
int MR_deep_prof_prep_method_old = 0;
|
|
int MR_deep_prof_prep_callback_new = 0;
|
|
int MR_deep_prof_prep_callback_old = 0;
|
|
int MR_deep_prof_prep_tail_old = 0;
|
|
int MR_deep_prof_prep_tail_new = 0;
|
|
|
|
int MR_deep_prof_call_new = 0;
|
|
int MR_deep_prof_call_rec = 0;
|
|
int MR_deep_prof_call_old = 0;
|
|
int MR_deep_prof_call_builtin_new = 0;
|
|
int MR_deep_prof_call_builtin_old = 0;
|
|
|
|
#endif /* MR_DEEP_PROFILING_STATISTICS */
|
|
|
|
#ifdef MR_DEEP_PROFILING_LOG
|
|
FILE *MR_deep_prof_log_file = NULL;
|
|
#endif
|
|
|
|
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)
|
|
{
|
|
char buf[1024];
|
|
char bufcsd[1024];
|
|
char bufps[1024];
|
|
|
|
if (csd != NULL) {
|
|
sprintf(bufcsd, ", csd %p\n", csd);
|
|
} else {
|
|
strcpy(bufcsd, "");
|
|
}
|
|
|
|
if (pl != NULL) {
|
|
sprintf(bufps, ", pl %p\n", pl);
|
|
} else {
|
|
strcpy(bufps, "");
|
|
}
|
|
|
|
if (ps != NULL) {
|
|
sprintf(bufps, ", ps %p\n", ps);
|
|
} else {
|
|
strcpy(bufps, "");
|
|
}
|
|
|
|
sprintf(buf, "Deep profiling assertion failed, %s:%d\n%s%s%s\n",
|
|
filename, linenumber, cond, bufcsd, bufps);
|
|
MR_fatal_error(buf);
|
|
}
|
|
|
|
void
|
|
MR_setup_callback(void *entry)
|
|
{
|
|
MR_CallSiteDynList *csd_list;
|
|
MR_CallSiteDynamic *csd;
|
|
|
|
MR_enter_instrumentation();
|
|
csd_list = *MR_current_callback_site;
|
|
while (csd_list != NULL)
|
|
{
|
|
if (csd_list->MR_csdlist_key == entry) {
|
|
MR_next_call_site_dynamic = csd_list->MR_csdlist_call_site;
|
|
#ifdef MR_DEEP_PROFILING_STATISTICS
|
|
MR_deep_prof_prep_callback_old++;
|
|
#endif
|
|
MR_leave_instrumentation();
|
|
return;
|
|
}
|
|
|
|
csd_list = csd_list->MR_csdlist_next;
|
|
}
|
|
|
|
#ifdef MR_DEEP_PROFILING_STATISTICS
|
|
MR_deep_prof_prep_callback_new++;
|
|
#endif
|
|
|
|
MR_new_call_site_dynamic(csd);
|
|
|
|
csd_list = MR_PROFILING_MALLOC(MR_CallSiteDynList);
|
|
csd_list->MR_csdlist_key = entry;
|
|
csd_list->MR_csdlist_call_site = csd;
|
|
csd_list->MR_csdlist_next = *MR_current_callback_site;
|
|
*MR_current_callback_site = csd_list;
|
|
|
|
MR_next_call_site_dynamic = csd;
|
|
MR_leave_instrumentation();
|
|
}
|
|
|
|
#ifdef MR_DEEP_PROFILING_STATISTICS
|
|
|
|
int MR_deep_prof_search_len;
|
|
|
|
void
|
|
MR_deep_profile_update_special_history(void)
|
|
{
|
|
if (MR_deep_prof_search_len < MR_MAX_CLOSURE_LIST_LENGTH) {
|
|
MR_dictionary_search_lengths[MR_deep_prof_search_len]++;
|
|
}
|
|
}
|
|
|
|
void
|
|
MR_deep_profile_update_closure_history()
|
|
{
|
|
if (MR_deep_prof_search_len < MR_MAX_CLOSURE_LIST_LENGTH) {
|
|
MR_closure_search_lengths[MR_deep_prof_search_len]++;
|
|
}
|
|
}
|
|
|
|
void
|
|
MR_deep_profile_update_method_history()
|
|
{
|
|
if (MR_deep_prof_search_len < MR_MAX_CLOSURE_LIST_LENGTH) {
|
|
MR_method_search_lengths[MR_deep_prof_search_len]++;
|
|
}
|
|
}
|
|
|
|
#endif /* MR_DEEP_PROFILING_STATISTICS */
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
/*
|
|
** Functions for writing out the data at the end of the execution.
|
|
*/
|
|
|
|
static void MR_deep_data_output_error(const char *msg);
|
|
static void MR_write_out_profiling_tree_check_unwritten(FILE *check_fp);
|
|
|
|
static void MR_write_out_id_string(FILE *fp);
|
|
|
|
static void MR_write_out_call_site_static(FILE *fp,
|
|
const MR_CallSiteStatic *css);
|
|
static void MR_write_out_call_site_dynamic(FILE *fp,
|
|
const MR_CallSiteDynamic *csd);
|
|
|
|
static void MR_write_out_proc_dynamic(FILE *fp, const MR_ProcDynamic *pd);
|
|
static void MR_write_out_ho_call_site_ptrs(FILE *fp,
|
|
const MR_ProcDynamic *pd,
|
|
const MR_CallSiteDynList *dynlist);
|
|
static void MR_write_out_ho_call_site_nodes(FILE *fp,
|
|
MR_CallSiteDynList *dynlist);
|
|
|
|
static void MR_unwritten_css_handler(FILE *fp, const void *css);
|
|
static void MR_unwritten_csd_handler(FILE *fp, const void *csd);
|
|
static void MR_unwritten_pl_handler(FILE *fp, const void *ps);
|
|
static void MR_unwritten_pd_handler(FILE *fp, const void *pd);
|
|
|
|
typedef enum node_kind {
|
|
kind_csd, kind_pd, kind_css, kind_ps
|
|
} MR_NodeKind;
|
|
|
|
/* must correspond to fixed_size_int_bytes in deep_profiler/read_profile.m */
|
|
#define MR_FIXED_SIZE_INT_BYTES 4
|
|
|
|
static void MR_write_csd_ptr(FILE *fp, const MR_CallSiteDynamic *csd);
|
|
static void MR_write_ptr(FILE *fp, MR_NodeKind kind, const int node_id);
|
|
static void MR_write_kind(FILE *fp, MR_CallSite_Kind kind);
|
|
static void MR_write_byte(FILE *fp, const char byte);
|
|
static void MR_write_num(FILE *fp, unsigned long num);
|
|
static void MR_write_fixed_size_int(FILE *fp, unsigned long num);
|
|
static void MR_write_string(FILE *fp, const char *ptr);
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
/*
|
|
** We need some hash tables, so here are the structures for handling them....
|
|
*/
|
|
|
|
typedef struct MR_Profiling_Hash_Node_Struct {
|
|
const void *item;
|
|
int id;
|
|
MR_bool written;
|
|
struct MR_Profiling_Hash_Node_Struct *next;
|
|
} MR_ProfilingHashNode;
|
|
|
|
typedef struct {
|
|
int last_id;
|
|
int length;
|
|
MR_ProfilingHashNode **nodes;
|
|
} MR_ProfilingHashTable;
|
|
|
|
static MR_ProfilingHashTable *MR_create_hash_table(int size);
|
|
|
|
static MR_bool MR_insert_proc_layout(
|
|
const MR_ProcLayout *pl, int *id,
|
|
MR_bool *already_written,
|
|
MR_bool init_written);
|
|
static MR_bool MR_insert_proc_dynamic(
|
|
const MR_ProcDynamic *pd, int *id,
|
|
MR_bool *already_written,
|
|
MR_bool init_written);
|
|
static MR_bool MR_insert_call_site_static(
|
|
const MR_CallSiteStatic *css, int *id,
|
|
MR_bool *already_written,
|
|
MR_bool init_written);
|
|
static MR_bool MR_insert_call_site_dynamic(
|
|
const MR_CallSiteDynamic *csd, int *id,
|
|
MR_bool *already_written,
|
|
MR_bool init_written);
|
|
|
|
static void MR_flag_written_proc_layout(
|
|
const MR_ProcLayout *pl);
|
|
static void MR_flag_written_proc_dynamic(
|
|
const MR_ProcDynamic *pd);
|
|
static void MR_flag_written_call_site_static(
|
|
const MR_CallSiteStatic *css);
|
|
static void MR_flag_written_call_site_dynamic(
|
|
const MR_CallSiteDynamic *csd);
|
|
|
|
static MR_ProfilingHashTable *MR_call_site_dynamic_table;
|
|
static MR_ProfilingHashTable *MR_call_site_static_table;
|
|
static MR_ProfilingHashTable *MR_proc_dynamic_table;
|
|
static MR_ProfilingHashTable *MR_proc_layout_table;
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
/*
|
|
** A convenient prime for the size of the node hash tables.
|
|
** The compiler contains nearly 10,000 preds, so a width of 10007
|
|
** (requiring about 40K of storage - not onerous compared to the
|
|
** size of the tree) will yield chain lengths of about 1 for the
|
|
** MR_needed_proc_statics table. For the MR_seen_nodes table, which
|
|
** stores all the MR_ProcDynamic nodes that have been seen, the average
|
|
** chain length will be longer - a typical run of the compiler can have
|
|
** as many as 50,000 nodes, so we don't want the table any narrower than this.
|
|
*/
|
|
|
|
static const int MR_hash_table_size = 10007;
|
|
|
|
#ifdef MR_DEEP_PROFILING_DEBUG
|
|
static FILE *debug_fp;
|
|
#endif
|
|
|
|
#define MR_MDPROF_DATAFILENAME "Deep.data"
|
|
|
|
void
|
|
MR_write_out_profiling_tree(void)
|
|
{
|
|
int i;
|
|
MR_ProfilingHashNode *n;
|
|
MR_ProcId *pid;
|
|
int root_pd_id;
|
|
FILE *fp;
|
|
int ticks_per_sec;
|
|
unsigned num_call_seqs;
|
|
FILE *check_fp;
|
|
|
|
fp = fopen(MR_MDPROF_DATAFILENAME, "wb+");
|
|
if (fp == NULL) {
|
|
MR_fatal_error("cannot open `%s' for writing: %s",
|
|
MR_MDPROF_DATAFILENAME, strerror(errno));
|
|
}
|
|
|
|
#ifdef MR_DEEP_PROFILING_DEBUG
|
|
if (MR_deep_prof_debug_file_flag) {
|
|
debug_fp = fopen("Deep.debug", "w");
|
|
if (debug_fp == NULL) {
|
|
debug_fp = stderr;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* We overwrite these zeros (and the id string) after the seek below. */
|
|
MR_write_out_id_string(fp);
|
|
MR_write_fixed_size_int(fp, 0);
|
|
MR_write_fixed_size_int(fp, 0);
|
|
MR_write_fixed_size_int(fp, 0);
|
|
MR_write_fixed_size_int(fp, 0);
|
|
|
|
#ifdef MR_CLOCK_TICKS_PER_SECOND
|
|
ticks_per_sec = MR_CLOCK_TICKS_PER_SECOND;
|
|
#else
|
|
ticks_per_sec = 0;
|
|
#endif
|
|
#ifdef MR_DEEP_PROFILING_CALL_SEQ
|
|
num_call_seqs = MR_deep_prof_cur_call_seq;
|
|
#else
|
|
num_call_seqs = 0;
|
|
#endif
|
|
|
|
MR_write_num(fp, ticks_per_sec);
|
|
MR_write_num(fp, MR_quanta_inside_deep_profiling_code);
|
|
MR_write_num(fp, MR_quanta_outside_deep_profiling_code);
|
|
MR_write_num(fp, num_call_seqs);
|
|
MR_write_byte(fp, sizeof(MR_Word));
|
|
MR_write_byte(fp, 0); /* the canonical flag is MR_FALSE = 0 */
|
|
|
|
MR_call_site_dynamic_table = MR_create_hash_table(MR_hash_table_size);
|
|
MR_call_site_static_table = MR_create_hash_table(MR_hash_table_size);
|
|
MR_proc_dynamic_table = MR_create_hash_table(MR_hash_table_size);
|
|
MR_proc_layout_table = MR_create_hash_table(MR_hash_table_size);
|
|
|
|
if (MR_insert_proc_dynamic(&MR_main_parent_proc_dynamic, &root_pd_id,
|
|
NULL, MR_FALSE))
|
|
{
|
|
MR_fatal_error("MR_write_out_profiling_tree: root seen before");
|
|
}
|
|
|
|
#ifdef MR_DEEP_PROFILING_DEBUG
|
|
if (debug_fp != NULL) {
|
|
fprintf(debug_fp, "root = %p, %d\n",
|
|
&MR_main_parent_proc_dynamic, root_pd_id);
|
|
}
|
|
#endif
|
|
|
|
MR_write_ptr(fp, kind_pd, root_pd_id);
|
|
|
|
MR_write_out_proc_dynamic(fp, &MR_main_parent_proc_dynamic);
|
|
|
|
MR_write_out_user_proc_static(fp, &MR_main_parent_proc_layout);
|
|
MR_deep_assert(NULL, NULL, NULL,
|
|
MR_address_of_write_out_proc_statics != NULL);
|
|
(*MR_address_of_write_out_proc_statics)(fp);
|
|
|
|
if (fseek(fp, 0L, SEEK_SET) != 0) {
|
|
MR_deep_data_output_error("cannot seek to start of");
|
|
}
|
|
|
|
MR_write_out_id_string(fp);
|
|
MR_write_fixed_size_int(fp, MR_call_site_dynamic_table->last_id);
|
|
MR_write_fixed_size_int(fp, MR_call_site_static_table->last_id);
|
|
MR_write_fixed_size_int(fp, MR_proc_dynamic_table->last_id);
|
|
MR_write_fixed_size_int(fp, MR_proc_layout_table->last_id);
|
|
|
|
if (fclose(fp) != 0) {
|
|
MR_deep_data_output_error("cannot close");
|
|
}
|
|
|
|
#ifdef MR_DEEP_PROFILING_STATISTICS
|
|
if (! MR_print_deep_profiling_statistics) {
|
|
return;
|
|
}
|
|
|
|
fprintf(stderr, "%-40s %10d\n",
|
|
"MR_deep_prof_prep_normal_new:",
|
|
MR_deep_prof_prep_normal_new);
|
|
fprintf(stderr, "%-40s %10d\n",
|
|
"MR_deep_prof_prep_normal_old:",
|
|
MR_deep_prof_prep_normal_old);
|
|
fprintf(stderr, "%-40s %10d\n",
|
|
"MR_deep_prof_prep_normal all:",
|
|
MR_deep_prof_prep_normal_new +
|
|
MR_deep_prof_prep_normal_old);
|
|
fprintf(stderr, "%-40s %10d\n",
|
|
"MR_deep_prof_prep_special_new:",
|
|
MR_deep_prof_prep_special_new);
|
|
fprintf(stderr, "%-40s %10d\n",
|
|
"MR_deep_prof_prep_special_old:",
|
|
MR_deep_prof_prep_special_old);
|
|
fprintf(stderr, "%-40s %10d\n",
|
|
"MR_deep_prof_prep_special all:",
|
|
MR_deep_prof_prep_special_new +
|
|
MR_deep_prof_prep_special_old);
|
|
fprintf(stderr, "%-40s %10d\n",
|
|
"MR_deep_prof_prep_ho_new:",
|
|
MR_deep_prof_prep_ho_new);
|
|
fprintf(stderr, "%-40s %10d\n",
|
|
"MR_deep_prof_prep_ho_old:",
|
|
MR_deep_prof_prep_ho_old);
|
|
fprintf(stderr, "%-40s %10d\n",
|
|
"MR_deep_prof_prep_ho all:",
|
|
MR_deep_prof_prep_ho_new +
|
|
MR_deep_prof_prep_ho_old);
|
|
fprintf(stderr, "%-40s %10d\n",
|
|
"MR_deep_prof_prep_method_new:",
|
|
MR_deep_prof_prep_method_new);
|
|
fprintf(stderr, "%-40s %10d\n",
|
|
"MR_deep_prof_prep_method_old:",
|
|
MR_deep_prof_prep_method_old);
|
|
fprintf(stderr, "%-40s %10d\n",
|
|
"MR_deep_prof_prep_method all:",
|
|
MR_deep_prof_prep_method_new +
|
|
MR_deep_prof_prep_method_old);
|
|
fprintf(stderr, "%-40s %10d\n",
|
|
"MR_deep_prof_prep_callback_new:",
|
|
MR_deep_prof_prep_callback_new);
|
|
fprintf(stderr, "%-40s %10d\n",
|
|
"MR_deep_prof_prep_callback_old:",
|
|
MR_deep_prof_prep_callback_old);
|
|
fprintf(stderr, "%-40s %10d\n",
|
|
"MR_deep_prof_prep_callback all:",
|
|
MR_deep_prof_prep_callback_new +
|
|
MR_deep_prof_prep_callback_old);
|
|
fprintf(stderr, "%-40s %10d\n",
|
|
"MR_deep_prof_prep_tail_new:",
|
|
MR_deep_prof_prep_tail_new);
|
|
fprintf(stderr, "%-40s %10d\n",
|
|
"MR_deep_prof_prep_tail_old:",
|
|
MR_deep_prof_prep_tail_old);
|
|
fprintf(stderr, "%-40s %10d\n",
|
|
"MR_deep_prof_prep_tail all:",
|
|
MR_deep_prof_prep_tail_new +
|
|
MR_deep_prof_prep_tail_old);
|
|
|
|
fprintf(stderr, "%-40s %10d\n",
|
|
"MR_deep_prof_call_new:",
|
|
MR_deep_prof_call_new);
|
|
fprintf(stderr, "%-40s %10d\n",
|
|
"MR_deep_prof_call_rec:",
|
|
MR_deep_prof_call_rec);
|
|
fprintf(stderr, "%-40s %10d\n",
|
|
"MR_deep_prof_call_old:",
|
|
MR_deep_prof_call_old);
|
|
fprintf(stderr, "%-40s %10d\n",
|
|
"MR_deep_prof_call all:",
|
|
MR_deep_prof_call_new +
|
|
MR_deep_prof_call_rec +
|
|
MR_deep_prof_call_old);
|
|
fprintf(stderr, "%-40s %10d\n",
|
|
"MR_deep_prof_call_builtin_new:",
|
|
MR_deep_prof_call_builtin_new);
|
|
fprintf(stderr, "%-40s %10d\n",
|
|
"MR_deep_prof_call_builtin_old:",
|
|
MR_deep_prof_call_builtin_old);
|
|
fprintf(stderr, "%-40s %10d\n",
|
|
"MR_deep_prof_call_builtin all:",
|
|
MR_deep_prof_call_builtin_new +
|
|
MR_deep_prof_call_builtin_old);
|
|
|
|
fprintf(stderr, "%-40s %10d\n",
|
|
"call prepare:",
|
|
MR_deep_prof_prep_normal_new +
|
|
MR_deep_prof_prep_normal_old +
|
|
MR_deep_prof_prep_special_new +
|
|
MR_deep_prof_prep_special_old +
|
|
MR_deep_prof_prep_ho_new +
|
|
MR_deep_prof_prep_ho_old +
|
|
MR_deep_prof_prep_method_new +
|
|
MR_deep_prof_prep_method_old +
|
|
MR_deep_prof_prep_callback_new +
|
|
MR_deep_prof_prep_callback_old +
|
|
MR_deep_prof_prep_tail_old +
|
|
MR_deep_prof_prep_tail_new);
|
|
fprintf(stderr, "%-40s %10d\n",
|
|
"call arrival:",
|
|
MR_deep_prof_prep_tail_old +
|
|
MR_deep_prof_prep_tail_new +
|
|
MR_deep_prof_call_new +
|
|
MR_deep_prof_call_rec +
|
|
MR_deep_prof_call_old +
|
|
MR_deep_prof_call_builtin_new +
|
|
MR_deep_prof_call_builtin_old);
|
|
|
|
fprintf(stderr, "\ntotal size of profiling tree: %10d bytes\n",
|
|
MR_deep_num_csd_nodes * sizeof(MR_CallSiteDynamic) +
|
|
MR_deep_num_pd_nodes * sizeof(MR_ProcDynamic) +
|
|
MR_deep_num_pd_array_slots * sizeof(MR_CallSiteDynamic *) +
|
|
MR_deep_num_dynlist_nodes * sizeof(MR_CallSiteDynList));
|
|
fprintf(stderr, "%10d CSD nodes at %4d bytes per node: %10d bytes\n",
|
|
MR_deep_num_csd_nodes,
|
|
sizeof(MR_CallSiteDynamic),
|
|
MR_deep_num_csd_nodes * sizeof(MR_CallSiteDynamic));
|
|
fprintf(stderr, "%10d PD nodes at %4d bytes per node: %10d bytes\n",
|
|
MR_deep_num_pd_nodes,
|
|
sizeof(MR_ProcDynamic),
|
|
MR_deep_num_pd_nodes * sizeof(MR_ProcDynamic));
|
|
fprintf(stderr, "%10d array slots at %4d bytes per node: %10d bytes\n",
|
|
MR_deep_num_pd_array_slots,
|
|
sizeof(MR_CallSiteDynamic *),
|
|
MR_deep_num_pd_array_slots * sizeof(MR_CallSiteDynamic *));
|
|
fprintf(stderr, "%10d list nodes at %4d bytes per node: %10d bytes\n",
|
|
MR_deep_num_dynlist_nodes,
|
|
sizeof(MR_CallSiteDynList),
|
|
MR_deep_num_dynlist_nodes * sizeof(MR_CallSiteDynList));
|
|
|
|
fprintf(stderr, "\nTypeInfo search length histogram:\n");
|
|
for (i = 0; i < MR_MAX_CLOSURE_LIST_LENGTH; i++) {
|
|
if (MR_dictionary_search_lengths[i] > 0) {
|
|
fprintf(stderr, "\t%3d: %12d\n", i,
|
|
MR_dictionary_search_lengths[i]);
|
|
}
|
|
}
|
|
|
|
fprintf(stderr, "\nClosure search length histogram:\n");
|
|
for (i = 0; i < MR_MAX_CLOSURE_LIST_LENGTH; i++) {
|
|
if (MR_closure_search_lengths[i] > 0) {
|
|
fprintf(stderr, "\t%3d: %12d\n", i, MR_closure_search_lengths[i]);
|
|
}
|
|
}
|
|
|
|
fprintf(stderr, "\nMethod search length histogram:\n");
|
|
for (i = 0; i < MR_MAX_CLOSURE_LIST_LENGTH; i++) {
|
|
if (MR_method_search_lengths[i] > 0) {
|
|
fprintf(stderr, "\t%3d: %12d\n", i, MR_method_search_lengths[i]);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifdef MR_DEEP_PROFILING_DEBUG
|
|
check_fp = debug_fp;
|
|
#else
|
|
check_fp = NULL;
|
|
#endif
|
|
|
|
MR_write_out_profiling_tree_check_unwritten(check_fp);
|
|
}
|
|
|
|
static void
|
|
MR_deep_data_output_error(const char *op)
|
|
{
|
|
MR_warning("%s %s: %s", op, MR_MDPROF_DATAFILENAME, strerror(errno));
|
|
|
|
/*
|
|
** An incomplete profiling data file is useless. Removing it
|
|
** prevents misunderstandings about that, and may also cure a
|
|
** disk-full condition, if the close failure was caused by
|
|
** that.
|
|
*/
|
|
|
|
if (remove(MR_MDPROF_DATAFILENAME) != 0) {
|
|
MR_warning("cannot remove %s: %s",
|
|
MR_MDPROF_DATAFILENAME, strerror(errno));
|
|
}
|
|
|
|
exit(1);
|
|
}
|
|
|
|
static void
|
|
MR_write_out_id_string(FILE *fp)
|
|
{
|
|
/* Must be the same as id_string in deep_profiler/read_profile.m */
|
|
const char *id_string = "Mercury deep profiler data version 3\n";
|
|
|
|
fputs(id_string, fp);
|
|
}
|
|
|
|
void
|
|
MR_write_out_user_proc_static(FILE *fp, const MR_ProcLayoutUser *proc_layout)
|
|
{
|
|
MR_write_out_proc_static(fp, (const MR_ProcLayout *) proc_layout);
|
|
}
|
|
|
|
void
|
|
MR_write_out_uci_proc_static(FILE *fp, const MR_ProcLayoutUCI *proc_layout)
|
|
{
|
|
MR_write_out_proc_static(fp, (const MR_ProcLayout *) proc_layout);
|
|
}
|
|
|
|
#ifdef MR_DEEP_PROFILING_LOG
|
|
MR_bool MR_deep_prof_doing_logging = MR_FALSE;
|
|
|
|
void
|
|
MR_deep_log_proc_statics(FILE *fp)
|
|
{
|
|
MR_deep_prof_doing_logging = MR_TRUE;
|
|
(*MR_address_of_write_out_proc_statics)(fp);
|
|
MR_deep_prof_doing_logging = MR_FALSE;
|
|
}
|
|
#endif /* MR_DEEP_PROFILING_LOG */
|
|
|
|
void
|
|
MR_write_out_proc_static(FILE *fp, const MR_ProcLayout *proc_layout)
|
|
{
|
|
const MR_ProcStatic *ps;
|
|
const MR_ProcId *procid;
|
|
int ps_id;
|
|
int css_id;
|
|
MR_bool already_written;
|
|
int i;
|
|
|
|
if (proc_layout == NULL) {
|
|
MR_fatal_error("MR_write_out_proc_static: null proc_layout");
|
|
}
|
|
|
|
if (! MR_PROC_LAYOUT_HAS_PROC_ID(proc_layout)) {
|
|
MR_fatal_error("MR_write_out_proc_static: no proc_id\n");
|
|
}
|
|
|
|
ps = proc_layout->MR_sle_proc_static;
|
|
|
|
#ifdef MR_DEEP_PROFILING_LOG
|
|
if (MR_deep_prof_doing_logging) {
|
|
procid = &proc_layout->MR_sle_proc_id;
|
|
if (MR_PROC_ID_IS_UCI(*procid)) {
|
|
fprintf(fp,
|
|
"proc_static_uci(%ld,\"%s\",\"%s\",\"%s\",\"%s\",%d,%d,[",
|
|
(long) proc_layout->MR_sle_proc_static,
|
|
procid->MR_proc_uci.MR_uci_type_name,
|
|
procid->MR_proc_uci.MR_uci_type_module,
|
|
procid->MR_proc_uci.MR_uci_def_module,
|
|
procid->MR_proc_uci.MR_uci_pred_name,
|
|
procid->MR_proc_uci.MR_uci_type_arity,
|
|
procid->MR_proc_uci.MR_uci_mode);
|
|
} else {
|
|
fprintf(fp,
|
|
"proc_static_user(%ld,%s,\"%s\",\"%s\",\"%s\",%d,%d,[",
|
|
(long) proc_layout->MR_sle_proc_static,
|
|
procid->MR_proc_user.MR_user_pred_or_func == MR_PREDICATE ?
|
|
"p" : "f",
|
|
procid->MR_proc_user.MR_user_decl_module,
|
|
procid->MR_proc_user.MR_user_def_module,
|
|
procid->MR_proc_user.MR_user_name,
|
|
procid->MR_proc_user.MR_user_arity,
|
|
procid->MR_proc_user.MR_user_mode);
|
|
}
|
|
|
|
for (i = 0; i < ps->MR_ps_num_call_sites; i++) {
|
|
if (i == 0) {
|
|
fputs("\n\t", fp);
|
|
} else {
|
|
fputs(",\n\t", fp);
|
|
}
|
|
|
|
switch (ps->MR_ps_call_sites[i].MR_css_kind) {
|
|
case MR_normal_call:
|
|
fprintf(fp, "css_normal(%ld, %ld)",
|
|
(long) &ps->MR_ps_call_sites[i],
|
|
(long) &ps->MR_ps_call_sites[i].
|
|
MR_css_callee_ptr_if_known->MR_sle_proc_static);
|
|
break;
|
|
|
|
case MR_special_call:
|
|
fprintf(fp, "css_special(%ld)",
|
|
(long) &ps->MR_ps_call_sites[i]);
|
|
break;
|
|
|
|
case MR_higher_order_call:
|
|
fprintf(fp, "css_higher_order(%ld)",
|
|
(long) &ps->MR_ps_call_sites[i]);
|
|
break;
|
|
|
|
case MR_method_call:
|
|
fprintf(fp, "css_method(%ld)",
|
|
(long) &ps->MR_ps_call_sites[i]);
|
|
break;
|
|
|
|
case MR_callback:
|
|
fprintf(fp, "css_callback(%ld)",
|
|
(long) &ps->MR_ps_call_sites[i]);
|
|
break;
|
|
|
|
default:
|
|
fprintf(fp, "css_unknown(%ld)",
|
|
(long) &ps->MR_ps_call_sites[i]);
|
|
break;
|
|
}
|
|
}
|
|
|
|
fprintf(fp, "]).\n");
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
if (ps == NULL) {
|
|
procid = &proc_layout->MR_sle_proc_id;
|
|
if (MR_PROC_ID_IS_UCI(*procid)) {
|
|
fprintf(stderr, "uci %s/%s/%s/%s/%d/%d\n",
|
|
procid->MR_proc_uci.MR_uci_type_name,
|
|
procid->MR_proc_uci.MR_uci_type_module,
|
|
procid->MR_proc_uci.MR_uci_def_module,
|
|
procid->MR_proc_uci.MR_uci_pred_name,
|
|
procid->MR_proc_uci.MR_uci_type_arity,
|
|
procid->MR_proc_uci.MR_uci_mode);
|
|
} else {
|
|
fprintf(stderr, "user %d/%s/%s/%s/%d/%d\n",
|
|
procid->MR_proc_user.MR_user_pred_or_func,
|
|
procid->MR_proc_user.MR_user_decl_module,
|
|
procid->MR_proc_user.MR_user_def_module,
|
|
procid->MR_proc_user.MR_user_name,
|
|
procid->MR_proc_user.MR_user_arity,
|
|
procid->MR_proc_user.MR_user_mode);
|
|
}
|
|
|
|
MR_fatal_error("MR_write_out_proc_static: null ps");
|
|
}
|
|
|
|
(void) MR_insert_proc_layout(proc_layout, &ps_id, &already_written,
|
|
MR_TRUE);
|
|
|
|
#ifdef MR_DEEP_PROFILING_DEBUG
|
|
if (debug_fp != NULL) {
|
|
fprintf(debug_fp, "proc_static %p/%p/%d\n", proc_layout, ps, ps_id);
|
|
fprintf(debug_fp, " filename \"%s\", linenumber %d, "
|
|
"interface %d, %d call sites\n",
|
|
ps->MR_ps_file_name, ps->MR_ps_line_number,
|
|
ps->MR_ps_is_in_interface, ps->MR_ps_num_call_sites);
|
|
}
|
|
#endif
|
|
|
|
if (already_written) {
|
|
MR_fatal_error("MR_write_out_proc_static: seen ps");
|
|
}
|
|
|
|
MR_flag_written_proc_layout(proc_layout);
|
|
|
|
MR_write_byte(fp, MR_deep_token_proc_static);
|
|
MR_write_ptr(fp, kind_ps, ps_id);
|
|
|
|
procid = &proc_layout->MR_sle_proc_id;
|
|
if (MR_PROC_ID_IS_UCI(*procid)) {
|
|
#ifdef MR_DEEP_PROFILING_DEBUG
|
|
if (debug_fp != NULL) {
|
|
fprintf(debug_fp, " uci %s/%s/%s/%s/%d/%d\n",
|
|
procid->MR_proc_uci.MR_uci_type_name,
|
|
procid->MR_proc_uci.MR_uci_type_module,
|
|
procid->MR_proc_uci.MR_uci_def_module,
|
|
procid->MR_proc_uci.MR_uci_pred_name,
|
|
procid->MR_proc_uci.MR_uci_type_arity,
|
|
procid->MR_proc_uci.MR_uci_mode);
|
|
}
|
|
#endif
|
|
|
|
MR_write_byte(fp, MR_deep_token_isa_uci_pred);
|
|
MR_write_string(fp, procid->MR_proc_uci.MR_uci_type_name);
|
|
MR_write_string(fp, procid->MR_proc_uci.MR_uci_type_module);
|
|
MR_write_string(fp, procid->MR_proc_uci.MR_uci_def_module);
|
|
MR_write_string(fp, procid->MR_proc_uci.MR_uci_pred_name);
|
|
MR_write_num(fp, procid->MR_proc_uci.MR_uci_type_arity);
|
|
MR_write_num(fp, procid->MR_proc_uci.MR_uci_mode);
|
|
} else {
|
|
#ifdef MR_DEEP_PROFILING_DEBUG
|
|
if (debug_fp != NULL) {
|
|
fprintf(debug_fp, " user %d/%s/%s/%s/%d/%d\n",
|
|
procid->MR_proc_user.MR_user_pred_or_func,
|
|
procid->MR_proc_user.MR_user_decl_module,
|
|
procid->MR_proc_user.MR_user_def_module,
|
|
procid->MR_proc_user.MR_user_name,
|
|
procid->MR_proc_user.MR_user_arity,
|
|
procid->MR_proc_user.MR_user_mode);
|
|
}
|
|
#endif
|
|
|
|
if (procid->MR_proc_user.MR_user_pred_or_func == MR_PREDICATE) {
|
|
MR_write_byte(fp, MR_deep_token_isa_predicate);
|
|
} else {
|
|
MR_write_byte(fp, MR_deep_token_isa_function);
|
|
}
|
|
|
|
MR_write_string(fp, procid->MR_proc_user.MR_user_decl_module);
|
|
MR_write_string(fp, procid->MR_proc_user.MR_user_def_module);
|
|
MR_write_string(fp, procid->MR_proc_user.MR_user_name);
|
|
MR_write_num(fp, procid->MR_proc_user.MR_user_arity);
|
|
MR_write_num(fp, procid->MR_proc_user.MR_user_mode);
|
|
}
|
|
|
|
MR_write_string(fp, ps->MR_ps_file_name);
|
|
MR_write_num(fp, ps->MR_ps_line_number);
|
|
MR_write_byte(fp, ps->MR_ps_is_in_interface);
|
|
MR_write_num(fp, ps->MR_ps_num_call_sites);
|
|
|
|
for (i = 0; i < ps->MR_ps_num_call_sites; i++) {
|
|
(void) MR_insert_call_site_static(&ps->MR_ps_call_sites[i], &css_id,
|
|
NULL, MR_FALSE);
|
|
|
|
#ifdef MR_DEEP_PROFILING_DEBUG
|
|
if (debug_fp != NULL) {
|
|
fprintf(debug_fp,
|
|
"call site id %d in proc_static %p/%p/%d -> %d\n",
|
|
i, proc_layout, ps, ps_id, css_id);
|
|
}
|
|
#endif
|
|
|
|
MR_write_ptr(fp, kind_css, css_id);
|
|
}
|
|
|
|
for (i = 0; i < ps->MR_ps_num_call_sites; i++) {
|
|
#ifdef MR_DEEP_PROFILING_DEBUG
|
|
if (debug_fp != NULL) {
|
|
fprintf(debug_fp, "in proc_static %p/%p/%d, call site %d\n",
|
|
proc_layout, ps, ps_id, i);
|
|
}
|
|
#endif
|
|
|
|
MR_write_out_call_site_static(fp, &ps->MR_ps_call_sites[i]);
|
|
}
|
|
}
|
|
|
|
static void
|
|
MR_write_out_call_site_static(FILE *fp, const MR_CallSiteStatic *css)
|
|
{
|
|
int css_id;
|
|
int ps_id;
|
|
MR_bool already_written;
|
|
|
|
if (css == NULL) {
|
|
MR_fatal_error("MR_write_out_call_site_static: null css");
|
|
}
|
|
|
|
(void) MR_insert_call_site_static(css, &css_id, &already_written, MR_TRUE);
|
|
|
|
if (already_written) {
|
|
MR_fatal_error("MR_write_out_call_site_static: seen css");
|
|
fflush(fp);
|
|
}
|
|
|
|
MR_flag_written_call_site_static(css);
|
|
|
|
#ifdef MR_DEEP_PROFILING_DEBUG
|
|
if (debug_fp != NULL) {
|
|
fprintf(debug_fp, "call_site_static %p/%d\n", css, css_id);
|
|
fprintf(debug_fp,
|
|
" filename \"%s\", linenum %d, goal path %s, kind %d\n",
|
|
css->MR_css_file_name, css->MR_css_line_number,
|
|
css->MR_css_goal_path, css->MR_css_kind);
|
|
}
|
|
#endif
|
|
|
|
MR_write_byte(fp, MR_deep_token_call_site_static);
|
|
MR_write_ptr(fp, kind_css, css_id);
|
|
MR_write_kind(fp, css->MR_css_kind);
|
|
if (css->MR_css_kind == MR_normal_call) {
|
|
(void) MR_insert_proc_layout(css->MR_css_callee_ptr_if_known, &ps_id,
|
|
NULL, MR_FALSE);
|
|
#ifdef MR_DEEP_PROFILING_DEBUG
|
|
if (debug_fp != NULL) {
|
|
fprintf(debug_fp, " callee %p/%d\n",
|
|
css->MR_css_callee_ptr_if_known, ps_id);
|
|
}
|
|
#endif
|
|
MR_write_num(fp, ps_id);
|
|
if (css->MR_css_type_subst_if_known != NULL) {
|
|
MR_write_string(fp, css->MR_css_type_subst_if_known);
|
|
} else {
|
|
MR_write_string(fp, "");
|
|
}
|
|
}
|
|
/* XXX MR_css_file_name */
|
|
MR_write_num(fp, css->MR_css_line_number);
|
|
MR_write_string(fp, css->MR_css_goal_path);
|
|
}
|
|
|
|
static void
|
|
MR_write_out_call_site_dynamic(FILE *fp, const MR_CallSiteDynamic *csd)
|
|
{
|
|
int bitmask = 0;
|
|
int csd_id;
|
|
int pd_id;
|
|
|
|
if (csd == NULL) {
|
|
return;
|
|
}
|
|
|
|
#ifdef MR_DEEP_PROFILING_STATISTICS
|
|
MR_deep_num_csd_nodes++;
|
|
#endif
|
|
|
|
MR_deep_assert(csd, NULL, NULL, csd->MR_csd_callee_ptr != NULL);
|
|
|
|
#ifdef MR_DEEP_PROFILING_DEBUG
|
|
if (debug_fp != NULL) {
|
|
fprintf(debug_fp, "call_site_dynamic %p: callee proc_dynamic %p\n",
|
|
csd, csd->MR_csd_callee_ptr);
|
|
}
|
|
#endif
|
|
|
|
MR_write_byte(fp, MR_deep_token_call_site_dynamic);
|
|
if (! MR_insert_call_site_dynamic(csd, &csd_id, NULL, MR_FALSE)) {
|
|
MR_fatal_error("MR_write_out_call_site_dynamic: insert succeeded");
|
|
}
|
|
|
|
MR_flag_written_call_site_dynamic(csd);
|
|
|
|
MR_write_ptr(fp, kind_csd, csd_id);
|
|
if (csd->MR_csd_callee_ptr == NULL) {
|
|
pd_id = 0;
|
|
} else {
|
|
(void) MR_insert_proc_dynamic(csd->MR_csd_callee_ptr, &pd_id, NULL,
|
|
MR_FALSE);
|
|
}
|
|
|
|
MR_write_ptr(fp, kind_pd, pd_id);
|
|
|
|
/*
|
|
** The masks here must exactly correspond with the masks in
|
|
** predicate read_profile in deep_profiler/read_profile.m.
|
|
*/
|
|
|
|
#ifdef MR_DEEP_PROFILING_PORT_COUNTS
|
|
#ifdef MR_DEEP_PROFILING_EXPLICIT_CALL_COUNTS
|
|
if (csd->MR_csd_own.MR_own_calls != 0) {
|
|
bitmask |= 0x0001;
|
|
}
|
|
#endif
|
|
if (csd->MR_csd_own.MR_own_exits != 0) {
|
|
bitmask |= 0x0002;
|
|
}
|
|
if (csd->MR_csd_own.MR_own_fails != 0) {
|
|
bitmask |= 0x0004;
|
|
}
|
|
if (csd->MR_csd_own.MR_own_redos != 0) {
|
|
bitmask |= 0x0040;
|
|
}
|
|
if (csd->MR_csd_own.MR_own_excps != 0) {
|
|
bitmask |= 0x0080;
|
|
}
|
|
#endif
|
|
#ifdef MR_DEEP_PROFILING_TIMING
|
|
if (csd->MR_csd_own.MR_own_quanta != 0) {
|
|
bitmask |= 0x0100;
|
|
}
|
|
#endif
|
|
#ifdef MR_DEEP_PROFILING_CALL_SEQ
|
|
if (csd->MR_csd_own.MR_own_call_seqs != 0) {
|
|
bitmask |= 0x0008;
|
|
}
|
|
#endif
|
|
#ifdef MR_DEEP_PROFILING_MEMORY
|
|
if (csd->MR_csd_own.MR_own_allocs != 0) {
|
|
bitmask |= 0x0010;
|
|
}
|
|
if (csd->MR_csd_own.MR_own_words != 0) {
|
|
bitmask |= 0x0020;
|
|
}
|
|
#endif
|
|
|
|
MR_write_num(fp, bitmask);
|
|
|
|
#ifdef MR_DEEP_PROFILING_PORT_COUNTS
|
|
#ifdef MR_DEEP_PROFILING_EXPLICIT_CALL_COUNTS
|
|
if (csd->MR_csd_own.MR_own_calls != 0) {
|
|
MR_write_num(fp, csd->MR_csd_own.MR_own_calls);
|
|
}
|
|
#endif
|
|
if (csd->MR_csd_own.MR_own_exits != 0) {
|
|
MR_write_num(fp, csd->MR_csd_own.MR_own_exits);
|
|
}
|
|
if (csd->MR_csd_own.MR_own_fails != 0) {
|
|
MR_write_num(fp, csd->MR_csd_own.MR_own_fails);
|
|
}
|
|
if (csd->MR_csd_own.MR_own_redos != 0) {
|
|
MR_write_num(fp, csd->MR_csd_own.MR_own_redos);
|
|
}
|
|
if (csd->MR_csd_own.MR_own_excps != 0) {
|
|
MR_write_num(fp, csd->MR_csd_own.MR_own_excps);
|
|
}
|
|
#endif
|
|
|
|
#ifdef MR_DEEP_PROFILING_TIMING
|
|
if (csd->MR_csd_own.MR_own_quanta != 0) {
|
|
MR_write_num(fp, csd->MR_csd_own.MR_own_quanta);
|
|
}
|
|
#endif
|
|
|
|
#ifdef MR_DEEP_PROFILING_CALL_SEQ
|
|
if (csd->MR_csd_own.MR_own_call_seqs != 0) {
|
|
MR_write_num(fp, csd->MR_csd_own.MR_own_call_seqs);
|
|
}
|
|
#endif
|
|
|
|
#ifdef MR_DEEP_PROFILING_MEMORY
|
|
if (csd->MR_csd_own.MR_own_allocs != 0) {
|
|
MR_write_num(fp, csd->MR_csd_own.MR_own_allocs);
|
|
}
|
|
if (csd->MR_csd_own.MR_own_words != 0) {
|
|
MR_write_num(fp, csd->MR_csd_own.MR_own_words);
|
|
}
|
|
#endif
|
|
|
|
MR_write_out_proc_dynamic(fp, csd->MR_csd_callee_ptr);
|
|
}
|
|
|
|
static void
|
|
MR_write_out_proc_dynamic(FILE *fp, const MR_ProcDynamic *pd)
|
|
{
|
|
const MR_ProcStatic *ps;
|
|
const MR_ProcLayout *pl;
|
|
int pd_id;
|
|
int ps_id;
|
|
MR_bool already_written;
|
|
int i;
|
|
|
|
if (pd == NULL) {
|
|
/*
|
|
** This shouldn't really happen except that we don't have
|
|
** correct handling of nondet pragma_foreign_code yet.
|
|
*/
|
|
|
|
return;
|
|
}
|
|
|
|
if (! MR_insert_proc_dynamic(pd, &pd_id, &already_written, MR_TRUE)) {
|
|
MR_fatal_error("MR_write_out_proc_dynamic: unseen pd");
|
|
}
|
|
|
|
if (already_written) {
|
|
return;
|
|
}
|
|
|
|
pl = pd->MR_pd_proc_layout;
|
|
ps = pl->MR_sle_proc_static;
|
|
|
|
MR_flag_written_proc_dynamic(pd);
|
|
(void) MR_insert_proc_layout(pl, &ps_id, NULL, MR_FALSE);
|
|
|
|
#ifdef MR_DEEP_PROFILING_STATISTICS
|
|
MR_deep_num_pd_nodes++;
|
|
MR_deep_num_pd_array_slots += ps->MR_ps_num_call_sites;
|
|
#endif
|
|
|
|
MR_write_byte(fp, MR_deep_token_proc_dynamic);
|
|
MR_write_ptr(fp, kind_pd, pd_id);
|
|
MR_write_ptr(fp, kind_ps, ps_id);
|
|
MR_write_num(fp, ps->MR_ps_num_call_sites);
|
|
|
|
#ifdef MR_DEEP_PROFILING_DEBUG
|
|
if (debug_fp != NULL) {
|
|
fprintf(debug_fp, "proc_dynamic %p/%d, proc_static %p/%p/%d\n",
|
|
pd, pd_id, pd->MR_pd_proc_layout, ps, ps_id);
|
|
}
|
|
#endif
|
|
|
|
for (i = 0; i < ps->MR_ps_num_call_sites; i++) {
|
|
MR_write_kind(fp, ps->MR_ps_call_sites[i].MR_css_kind);
|
|
switch (ps->MR_ps_call_sites[i].MR_css_kind)
|
|
{
|
|
case MR_normal_call:
|
|
#ifdef MR_DEEP_PROFILING_DEBUG
|
|
if (debug_fp != NULL) {
|
|
fprintf(debug_fp,
|
|
" normal call from pd %p to pd %p\n",
|
|
pd, pd->MR_pd_call_site_ptr_ptrs[i]);
|
|
}
|
|
#endif
|
|
MR_write_csd_ptr(fp, pd->MR_pd_call_site_ptr_ptrs[i]);
|
|
break;
|
|
|
|
case MR_special_call:
|
|
case MR_higher_order_call:
|
|
case MR_method_call:
|
|
case MR_callback:
|
|
MR_write_out_ho_call_site_ptrs(fp, pd,
|
|
(MR_CallSiteDynList *) pd->MR_pd_call_site_ptr_ptrs[i]);
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < ps->MR_ps_num_call_sites; i++) {
|
|
switch (ps->MR_ps_call_sites[i].MR_css_kind)
|
|
{
|
|
case MR_normal_call:
|
|
MR_write_out_call_site_dynamic(fp,
|
|
pd->MR_pd_call_site_ptr_ptrs[i]);
|
|
break;
|
|
|
|
case MR_special_call:
|
|
case MR_higher_order_call:
|
|
case MR_method_call:
|
|
case MR_callback:
|
|
MR_write_out_ho_call_site_nodes(fp,
|
|
(MR_CallSiteDynList *) pd->MR_pd_call_site_ptr_ptrs[i]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
MR_write_out_ho_call_site_ptrs(FILE *fp, const MR_ProcDynamic *pd,
|
|
const MR_CallSiteDynList *dynlist)
|
|
{
|
|
while (dynlist != NULL) {
|
|
#ifdef MR_DEEP_PROFILING_STATISTICS
|
|
MR_deep_num_dynlist_nodes++;
|
|
#endif
|
|
#ifdef MR_DEEP_PROFILING_DEBUG
|
|
if (debug_fp != NULL) {
|
|
fprintf(debug_fp, " multi call from pd %p to pd %p\n",
|
|
pd, dynlist->MR_csdlist_call_site);
|
|
}
|
|
#endif
|
|
MR_write_csd_ptr(fp, dynlist->MR_csdlist_call_site);
|
|
dynlist = dynlist->MR_csdlist_next;
|
|
}
|
|
MR_write_byte(fp, MR_deep_token_end);
|
|
}
|
|
|
|
static void
|
|
MR_write_out_ho_call_site_nodes(FILE *fp, MR_CallSiteDynList *dynlist)
|
|
{
|
|
while (dynlist != NULL) {
|
|
MR_write_out_call_site_dynamic(fp, dynlist->MR_csdlist_call_site);
|
|
dynlist = dynlist->MR_csdlist_next;
|
|
}
|
|
}
|
|
|
|
static void
|
|
MR_write_csd_ptr(FILE *fp, const MR_CallSiteDynamic *csd)
|
|
{
|
|
int csd_id;
|
|
|
|
if (csd == NULL) {
|
|
csd_id = 0;
|
|
} else {
|
|
(void) MR_insert_call_site_dynamic(csd, &csd_id, NULL, MR_FALSE);
|
|
}
|
|
|
|
MR_write_ptr(fp, kind_csd, csd_id);
|
|
}
|
|
|
|
static void
|
|
MR_write_ptr(FILE *fp, MR_NodeKind kind, int node_id)
|
|
{
|
|
#ifdef MR_DEEP_PROFILING_DETAIL_DEBUG
|
|
if (debug_fp != NULL) {
|
|
fprintf(debug_fp, "ptr: %d\n", node_id);
|
|
}
|
|
#endif
|
|
|
|
/* MR_write_byte(fp, (int) kind); */
|
|
MR_write_num(fp, node_id);
|
|
}
|
|
|
|
static void
|
|
MR_write_kind(FILE *fp, MR_CallSite_Kind kind)
|
|
{
|
|
int byte;
|
|
|
|
#ifdef MR_DEEP_PROFILING_DETAIL_DEBUG
|
|
if (debug_fp != NULL) {
|
|
fprintf(debug_fp, "call_site_kind: %d\n", (int) kind);
|
|
}
|
|
#endif
|
|
|
|
/* convert from a MR_CallSite_Kind to an MR_Profiling_Encoding_Token */
|
|
byte = (int) kind +
|
|
((int) MR_deep_token_normal_call - (int) MR_normal_call);
|
|
if (byte < MR_deep_token_normal_call || byte > MR_deep_token_callback) {
|
|
MR_fatal_error("MR_write_kind: bad kind %d %d\n", (int) kind, byte);
|
|
}
|
|
|
|
MR_write_byte(fp, byte);
|
|
}
|
|
|
|
static void
|
|
MR_write_byte(FILE *fp, const char byte)
|
|
{
|
|
#ifdef MR_DEEP_PROFILING_DETAIL_DEBUG
|
|
if (debug_fp != NULL) {
|
|
fprintf(debug_fp, "byte: %d\n", (int) byte);
|
|
}
|
|
#endif
|
|
putc(byte, fp);
|
|
}
|
|
|
|
/*
|
|
** Write out a (non-negative) integer. The format we use is a multibyte format
|
|
** which uses the least significant 7 bits as data bits and the most
|
|
** significant bit to indicate whether there are more bytes following.
|
|
** Numbers are written most significant byte first.
|
|
*/
|
|
|
|
static void
|
|
MR_write_num(FILE *fp, unsigned long num)
|
|
{
|
|
unsigned char pieces[sizeof(unsigned long) * 8 / 7 + 1];
|
|
int i;
|
|
|
|
#ifdef MR_DEEP_PROFILING_DETAIL_DEBUG
|
|
if (debug_fp != NULL) {
|
|
fprintf(debug_fp, "num: %ld\n", num);
|
|
}
|
|
#endif
|
|
|
|
MR_deep_assert(NULL, NULL, NULL, (int) num >= 0);
|
|
|
|
i = 0;
|
|
do {
|
|
pieces[i] = num & 0x7f;
|
|
num = num >> 7;
|
|
i++;
|
|
} while (num != 0);
|
|
|
|
i--;
|
|
|
|
while (i > 0) {
|
|
putc(pieces[i--] | 0x80, fp);
|
|
}
|
|
putc(pieces[0], fp);
|
|
}
|
|
|
|
static void
|
|
MR_write_fixed_size_int(FILE *fp, unsigned long num)
|
|
{
|
|
int i;
|
|
|
|
#ifdef MR_DEEP_PROFILING_DETAIL_DEBUG
|
|
if (debug_fp != NULL) {
|
|
fprintf(debug_fp, "fixed_size_int: %ld\n", num);
|
|
}
|
|
#endif
|
|
|
|
MR_deep_assert(NULL, NULL, NULL, (int) num >= 0);
|
|
|
|
for (i = 0; i < MR_FIXED_SIZE_INT_BYTES; i++) {
|
|
putc(num & ((1 << 8) - 1), fp);
|
|
num = num >> 8;
|
|
}
|
|
}
|
|
|
|
static void
|
|
MR_write_string(FILE *fp, const char *ptr)
|
|
{
|
|
int i;
|
|
int len;
|
|
|
|
#ifdef MR_DEEP_PROFILING_DETAIL_DEBUG
|
|
if (debug_fp != NULL) {
|
|
fprintf(debug_fp, "string: <%s>\n", ptr);
|
|
}
|
|
#endif
|
|
|
|
len = strlen(ptr);
|
|
MR_write_num(fp, len);
|
|
for (i = 0; i < len; i++) {
|
|
putc(ptr[i], fp);
|
|
}
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
/*
|
|
** This section of the file implements the hash tables that turn the addresses
|
|
** of ProcDynamic, ProcDynamic, and CallSiteDynamic nodes into node ids.
|
|
** We use our own routines instead of reusing the hash table routines in
|
|
** mercury_hash_table.c for efficiency. By writing our own code, we avoid
|
|
** several sources of overhead: higher order calls, separate calls to lookup
|
|
** a pointer and insert it if it isn't there, and the use of doubly-linked
|
|
** lists. Efficiency is reasonably important, since the tables can have
|
|
** millions of entries. Eventually, they should be implemented using
|
|
** dynamically sized hash tables (extendible hashing or linear hashing).
|
|
*/
|
|
|
|
static MR_ProfilingHashTable *
|
|
MR_create_hash_table(int size)
|
|
{
|
|
MR_ProfilingHashTable *ptr;
|
|
int i;
|
|
|
|
ptr = MR_NEW(MR_ProfilingHashTable);
|
|
ptr->length = size;
|
|
ptr->last_id = 0;
|
|
ptr->nodes = MR_NEW_ARRAY(MR_ProfilingHashNode *, size);
|
|
|
|
for (i = 0; i < size; i++) {
|
|
ptr->nodes[i] = NULL;
|
|
}
|
|
|
|
return ptr;
|
|
}
|
|
|
|
/****************************************************************************/
|
|
/*
|
|
** Type safe interfaces to the generic hash table routines.
|
|
**
|
|
** We declare those generic routines here to ensure that any calls to them
|
|
** from above this point get error messages from mgnuc.
|
|
*/
|
|
|
|
static MR_bool MR_hash_table_insert_INTERNAL(
|
|
MR_ProfilingHashTable *table,
|
|
const void *ptr, int *id,
|
|
MR_bool *already_written,
|
|
MR_bool init_written);
|
|
static void MR_hash_table_flag_written_INTERNAL(
|
|
MR_ProfilingHashTable *table,
|
|
const void *ptr);
|
|
static int MR_hash_table_check_all_written_INTERNAL(
|
|
FILE *fp, const char *type,
|
|
MR_ProfilingHashTable *table,
|
|
void write_func(FILE *fp, const void *));
|
|
|
|
static MR_bool
|
|
MR_insert_proc_layout(const MR_ProcLayout *pl, int *id,
|
|
MR_bool *already_written, MR_bool init_written)
|
|
{
|
|
return MR_hash_table_insert_INTERNAL(MR_proc_layout_table,
|
|
(const void *) pl, id, already_written, init_written);
|
|
}
|
|
|
|
static MR_bool
|
|
MR_insert_proc_dynamic(const MR_ProcDynamic *pd, int *id,
|
|
MR_bool *already_written, MR_bool init_written)
|
|
{
|
|
return MR_hash_table_insert_INTERNAL(MR_proc_dynamic_table,
|
|
(const void *) pd, id, already_written, init_written);
|
|
}
|
|
|
|
static MR_bool
|
|
MR_insert_call_site_static(const MR_CallSiteStatic *css, int *id,
|
|
MR_bool *already_written, MR_bool init_written)
|
|
{
|
|
return MR_hash_table_insert_INTERNAL(MR_call_site_static_table,
|
|
(const void *) css, id, already_written, init_written);
|
|
}
|
|
|
|
static MR_bool
|
|
MR_insert_call_site_dynamic(const MR_CallSiteDynamic *csd, int *id,
|
|
MR_bool *already_written, MR_bool init_written)
|
|
{
|
|
return MR_hash_table_insert_INTERNAL(MR_call_site_dynamic_table,
|
|
(const void *) csd, id, already_written, init_written);
|
|
}
|
|
|
|
static void
|
|
MR_flag_written_proc_layout(const MR_ProcLayout *pl)
|
|
{
|
|
MR_hash_table_flag_written_INTERNAL(MR_proc_layout_table,
|
|
(const void *) pl);
|
|
}
|
|
|
|
static void
|
|
MR_flag_written_proc_dynamic(const MR_ProcDynamic *pd)
|
|
{
|
|
MR_hash_table_flag_written_INTERNAL(MR_proc_dynamic_table,
|
|
(const void *) pd);
|
|
}
|
|
|
|
static void
|
|
MR_flag_written_call_site_static(const MR_CallSiteStatic *css)
|
|
{
|
|
MR_hash_table_flag_written_INTERNAL(MR_call_site_static_table,
|
|
(const void *) css);
|
|
}
|
|
|
|
static void
|
|
MR_flag_written_call_site_dynamic(const MR_CallSiteDynamic *csd)
|
|
{
|
|
MR_hash_table_flag_written_INTERNAL(MR_call_site_dynamic_table,
|
|
(const void *) csd);
|
|
}
|
|
|
|
#define MR_hash_ptr(ptr, table) (((MR_Unsigned) (ptr) >> 2) % (table)->length)
|
|
|
|
static MR_bool
|
|
MR_hash_table_insert_INTERNAL(MR_ProfilingHashTable *table, const void *ptr,
|
|
int *id, MR_bool *already_written, MR_bool init_written)
|
|
{
|
|
int hash;
|
|
MR_ProfilingHashNode *node;
|
|
|
|
if (ptr == NULL) {
|
|
MR_fatal_error("NULL ptr in MR_hash_table_insert");
|
|
}
|
|
|
|
hash = MR_hash_ptr(ptr, table);
|
|
node = table->nodes[hash];
|
|
while (node != NULL) {
|
|
if (node->item == ptr) {
|
|
*id = node->id;
|
|
if (already_written != NULL) {
|
|
*already_written = node->written;
|
|
}
|
|
return MR_TRUE;
|
|
}
|
|
node = node->next;
|
|
}
|
|
|
|
node = MR_NEW(MR_ProfilingHashNode);
|
|
node->item = ptr;
|
|
node->id = ++table->last_id;
|
|
node->written = init_written;
|
|
node->next = table->nodes[hash];
|
|
table->nodes[hash] = node;
|
|
|
|
*id = node->id;
|
|
if (already_written != NULL) {
|
|
*already_written = MR_FALSE;
|
|
}
|
|
|
|
return MR_FALSE;
|
|
}
|
|
|
|
static void
|
|
MR_hash_table_flag_written_INTERNAL(MR_ProfilingHashTable *table,
|
|
const void *ptr)
|
|
{
|
|
int hash;
|
|
MR_ProfilingHashNode *node;
|
|
|
|
if (ptr == NULL) {
|
|
MR_fatal_error("NULL ptr in MR_hash_table_flag_written");
|
|
}
|
|
|
|
hash = MR_hash_ptr(ptr, table);
|
|
node = table->nodes[hash];
|
|
while (node != NULL) {
|
|
if (node->item == ptr) {
|
|
node->written = MR_TRUE;
|
|
return;
|
|
}
|
|
node = node->next;
|
|
}
|
|
|
|
MR_fatal_error("MR_hash_table_flag_written: did not find node");
|
|
}
|
|
|
|
static void
|
|
MR_write_out_profiling_tree_check_unwritten(FILE *check_fp)
|
|
{
|
|
int unwritten_csd;
|
|
int unwritten_css;
|
|
int unwritten_pd;
|
|
int unwritten_ps;
|
|
int any_unwritten;
|
|
int iteration;
|
|
|
|
unwritten_ps = MR_hash_table_check_all_written_INTERNAL(check_fp,
|
|
"ProcLayout", MR_proc_layout_table,
|
|
MR_unwritten_pl_handler);
|
|
unwritten_pd = MR_hash_table_check_all_written_INTERNAL(check_fp,
|
|
"ProcDynamic", MR_proc_dynamic_table,
|
|
MR_unwritten_pd_handler);
|
|
unwritten_css = MR_hash_table_check_all_written_INTERNAL(check_fp,
|
|
"CallSiteStatic", MR_call_site_static_table,
|
|
MR_unwritten_css_handler);
|
|
unwritten_csd = MR_hash_table_check_all_written_INTERNAL(check_fp,
|
|
"CallSiteDynamic", MR_call_site_dynamic_table,
|
|
MR_unwritten_csd_handler);
|
|
any_unwritten = unwritten_ps + unwritten_pd +
|
|
unwritten_css + unwritten_csd;
|
|
|
|
if (unwritten_ps > 0 && check_fp != NULL) {
|
|
fprintf(check_fp, "%d unwritten proc statics\n",
|
|
unwritten_ps);
|
|
}
|
|
|
|
if (unwritten_pd > 0 && check_fp != NULL) {
|
|
fprintf(check_fp, "%d unwritten proc dynamics\n",
|
|
unwritten_pd);
|
|
}
|
|
|
|
if (unwritten_css > 0 && check_fp != NULL) {
|
|
fprintf(check_fp, "%d unwritten call site statics\n",
|
|
unwritten_css);
|
|
}
|
|
|
|
if (unwritten_csd > 0 && check_fp != NULL) {
|
|
fprintf(check_fp, "%d unwritten call site dynamics\n",
|
|
unwritten_csd);
|
|
}
|
|
|
|
if (any_unwritten > 0) {
|
|
MR_fatal_error("UNWRITTEN nodes: Deep.data file corrupted\n");
|
|
}
|
|
}
|
|
|
|
static void
|
|
MR_unwritten_css_handler(FILE *fp, const void *css)
|
|
{
|
|
fprintf(stderr, "UNWRITTEN call site static %p\n", css);
|
|
}
|
|
|
|
static void
|
|
MR_unwritten_csd_handler(FILE *fp, const void *csd)
|
|
{
|
|
fprintf(stderr, "UNWRITTEN call site dynamic %p\n", csd);
|
|
}
|
|
|
|
static void
|
|
MR_unwritten_pl_handler(FILE *fp, const void *pl)
|
|
{
|
|
const MR_ProcLayout *proc_layout;
|
|
const MR_ProcId *procid;
|
|
|
|
proc_layout = (const MR_ProcLayout *) pl;
|
|
|
|
if (! MR_PROC_LAYOUT_HAS_PROC_ID(proc_layout)) {
|
|
MR_fatal_error("MR_write_out_proc_layout_from_void: no proc_id\n");
|
|
}
|
|
|
|
procid = &proc_layout->MR_sle_proc_id;
|
|
if (MR_PROC_ID_IS_UCI(*procid)) {
|
|
fprintf(stderr, "uci %s/%s/%s/%s/%d/%d\n",
|
|
procid->MR_proc_uci.MR_uci_type_name,
|
|
procid->MR_proc_uci.MR_uci_type_module,
|
|
procid->MR_proc_uci.MR_uci_def_module,
|
|
procid->MR_proc_uci.MR_uci_pred_name,
|
|
procid->MR_proc_uci.MR_uci_type_arity,
|
|
procid->MR_proc_uci.MR_uci_mode);
|
|
} else {
|
|
fprintf(stderr, "user %d/%s/%s/%s/%d/%d\n",
|
|
procid->MR_proc_user.MR_user_pred_or_func,
|
|
procid->MR_proc_user.MR_user_decl_module,
|
|
procid->MR_proc_user.MR_user_def_module,
|
|
procid->MR_proc_user.MR_user_name,
|
|
procid->MR_proc_user.MR_user_arity,
|
|
procid->MR_proc_user.MR_user_mode);
|
|
}
|
|
|
|
fprintf(stderr, "UNWRITTEN proc layout %p\n", pl);
|
|
}
|
|
|
|
static void
|
|
MR_unwritten_pd_handler(FILE *fp, const void *pd)
|
|
{
|
|
fprintf(stderr, "UNWRITTEN proc dynamic %p\n", pd);
|
|
}
|
|
|
|
static int
|
|
MR_hash_table_check_all_written_INTERNAL(FILE *fp, const char *type,
|
|
MR_ProfilingHashTable *table, void write_func(FILE *, const void *))
|
|
{
|
|
int i;
|
|
int errors;
|
|
MR_ProfilingHashNode *node;
|
|
|
|
errors = 0;
|
|
for (i = 0; i < table->length ; i++) {
|
|
for (node = table->nodes[i]; node != NULL; node = node->next) {
|
|
if (! node->written) {
|
|
errors++;
|
|
if (fp != NULL) {
|
|
fprintf(fp, "unwritten %s %d at %p\n",
|
|
type, node->id, node->item);
|
|
fflush(fp);
|
|
(*write_func)(fp, node->item);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return errors;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
void
|
|
MR_deep_prof_init(void)
|
|
{
|
|
#ifdef MR_DEEP_PROFILING_TIMING
|
|
MR_init_time_profile_method();
|
|
#endif
|
|
}
|
|
|
|
static void MR_deep_tick_handler(int signum);
|
|
|
|
void
|
|
MR_deep_prof_turn_on_time_profiling(void)
|
|
{
|
|
#ifdef MR_DEEP_PROFILING_TIMING
|
|
MR_turn_on_time_profiling(MR_deep_tick_handler);
|
|
#endif
|
|
}
|
|
|
|
void
|
|
MR_deep_prof_turn_off_time_profiling(void)
|
|
{
|
|
#ifdef MR_DEEP_PROFILING_TIMING
|
|
MR_turn_off_time_profiling();
|
|
#endif
|
|
}
|
|
|
|
#ifdef MR_DEEP_PROFILING_TIMING
|
|
|
|
static void
|
|
MR_deep_tick_handler(/* unused */ int signum)
|
|
{
|
|
if (MR_inside_deep_profiling_code) {
|
|
MR_quanta_inside_deep_profiling_code++;
|
|
} else {
|
|
MR_quanta_outside_deep_profiling_code++;
|
|
MR_current_call_site_dynamic->MR_csd_own.MR_own_quanta++;
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif /* MR_DEEP_PROFILING */
|