Files
mercury/runtime/mercury_deep_profiling.c
Zoltan Somogyi 455e1eea75 The runtime had two different conventions for naming types.
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).
2006-11-29 05:18:42 +00:00

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 */