mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-13 12:53:53 +00:00
runtime/mercury_ml_expand_body.h: Fix another spot where we are incorrectly assuming that the machine word size is <= sizeof(long). runtime/mercury_debug.c: runtime/mercury_memory_zones.c: runtime/mercury_wrapper.c: s/MR_WORD_TYPE/MR_Integer/ in my last change.
1315 lines
33 KiB
C
1315 lines
33 KiB
C
/*
|
|
** vim: ts=4 sw=4 expandtab
|
|
*/
|
|
/*
|
|
** Copyright (C) 1996-2007, 2010 The University of Melbourne.
|
|
** This file may only be copied under the terms of the GNU Library General
|
|
** Public License - see the file COPYING.LIB in the Mercury distribution.
|
|
*/
|
|
|
|
#include "mercury_imp.h"
|
|
#include "mercury_dlist.h"
|
|
#include "mercury_regs.h"
|
|
#include "mercury_trace_base.h"
|
|
#include "mercury_label.h"
|
|
#include "mercury_debug.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
|
|
static MR_bool MR_find_zone_for_det_ptr_in_context(const MR_Word *ptr,
|
|
MR_Context *ctxt,
|
|
MR_MemoryZone **zone_ptr, int *zone_num_ptr);
|
|
static MR_bool MR_find_zone_for_nondet_ptr_in_context(const MR_Word *ptr,
|
|
MR_Context *ctxt,
|
|
MR_MemoryZone **zone_ptr, int *zone_num_ptr);
|
|
static MR_bool MR_find_zone_for_det_ptr(const MR_Word *ptr,
|
|
MR_Context **ctxt_ptr,
|
|
MR_MemoryZone **zone_ptr, int *zone_num_ptr);
|
|
static MR_bool MR_find_zone_for_nondet_ptr(const MR_Word *ptr,
|
|
MR_Context **ctxt_ptr,
|
|
MR_MemoryZone **zone_ptr, int *zone_num_ptr);
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
|
|
#ifdef MR_DEEP_PROFILING
|
|
static void MR_check_watch_csd_start(MR_Code *proc);
|
|
static MR_bool MR_csds_are_different(const MR_CallSiteDynamic *csd1,
|
|
const MR_CallSiteDynamic *csd2);
|
|
static void MR_assign_csd(MR_CallSiteDynamic *csd1,
|
|
const MR_CallSiteDynamic *csd2);
|
|
#endif
|
|
|
|
static void MR_count_call(FILE *fp, const MR_Code *proc);
|
|
static void MR_print_ordinary_regs(FILE *fp);
|
|
static void MR_do_watches(FILE *fp);
|
|
static MR_bool MR_proc_matches_name(const MR_Code *proc, const char *name);
|
|
|
|
#ifdef MR_LOWLEVEL_ADDR_DEBUG
|
|
#define MR_PRINT_RAW_ADDRS MR_TRUE
|
|
#else
|
|
#define MR_PRINT_RAW_ADDRS MR_FALSE
|
|
#endif
|
|
|
|
static MR_bool MR_print_raw_addrs = MR_PRINT_RAW_ADDRS;
|
|
|
|
/* debugging messages */
|
|
|
|
#ifdef MR_DEBUG_HEAP_ALLOC
|
|
|
|
void
|
|
MR_unravel_univ_msg(FILE *fp, MR_Word univ, MR_TypeInfo type_info,
|
|
MR_Word value)
|
|
{
|
|
if (MR_lld_print_enabled && MR_heapdebug) {
|
|
fprintf(fp, "unravel univ %p: typeinfo %p, value %p\n",
|
|
(void *) univ, (void *) type_info, (void *) value);
|
|
fflush(fp);
|
|
}
|
|
}
|
|
|
|
void
|
|
MR_new_univ_on_hp_msg(FILE *fp, MR_Word univ, MR_TypeInfo type_info,
|
|
MR_Word value)
|
|
{
|
|
if (MR_lld_print_enabled && MR_heapdebug) {
|
|
fprintf(fp"new univ on hp: typeinfo %p, value %p => %p\n",
|
|
(void *) type_info, (void *) value, (void *) univ);
|
|
fflush(fp);
|
|
}
|
|
}
|
|
|
|
void
|
|
MR_debug_tag_offset_incr_hp_base_msg(FILE *fp, MR_Word ptr,
|
|
int tag, int offset, int count, int is_atomic)
|
|
{
|
|
if (MR_lld_print_enabled && MR_heapdebug) {
|
|
fprintf(fp, "tag_offset_incr_hp: "
|
|
"tag %d, offset %d, count %d%s => %p\n",
|
|
tag, offset, count, (is_atomic ? ", atomic" : ""), (void *) ptr);
|
|
fflush(fp);
|
|
}
|
|
}
|
|
|
|
#endif /* MR_DEBUG_HEAP_ALLOC */
|
|
|
|
#ifdef MR_LOWLEVEL_DEBUG
|
|
|
|
void
|
|
MR_mkframe_msg(FILE *fp, const char *predname)
|
|
{
|
|
MR_restore_transient_registers();
|
|
|
|
if (!MR_lld_print_enabled) {
|
|
return;
|
|
}
|
|
|
|
fprintf(fp, "\nnew choice point for procedure %s\n", predname);
|
|
fprintf(fp, "new fr: ");
|
|
MR_printnondetstack(fp, MR_curfr);
|
|
fprintf(fp, "prev fr: ");
|
|
MR_printnondetstack(fp, MR_prevfr_slot(MR_curfr));
|
|
fprintf(fp, "succ fr: ");
|
|
MR_printnondetstack(fp, MR_succfr_slot(MR_curfr));
|
|
fprintf(fp, "succ ip: ");
|
|
MR_printlabel(fp, MR_succip_slot(MR_curfr));
|
|
fprintf(fp, "redo fr: ");
|
|
MR_printnondetstack(fp, MR_redofr_slot(MR_curfr));
|
|
fprintf(fp, "redo ip: ");
|
|
MR_printlabel(fp, MR_redoip_slot(MR_curfr));
|
|
#ifdef MR_USE_MINIMAL_MODEL_OWN_STACKS
|
|
fprintf(fp, "det fr: ");
|
|
MR_printdetstack(fp, MR_table_detfr_slot(MR_curfr));
|
|
#endif
|
|
|
|
if (MR_detaildebug) {
|
|
MR_dumpnondetstack(fp);
|
|
}
|
|
}
|
|
|
|
void
|
|
MR_mktempframe_msg(FILE *fp)
|
|
{
|
|
MR_restore_transient_registers();
|
|
|
|
if (!MR_lld_print_enabled) {
|
|
return;
|
|
}
|
|
|
|
fprintf(fp, "\nnew temp nondet frame\n");
|
|
fprintf(fp, "new fr: ");
|
|
MR_printnondetstack(fp, MR_maxfr);
|
|
fprintf(fp, "prev fr: ");
|
|
MR_printnondetstack(fp, MR_prevfr_slot(MR_maxfr));
|
|
fprintf(fp, "redo fr: ");
|
|
MR_printnondetstack(fp, MR_redofr_slot(MR_maxfr));
|
|
fprintf(fp, "redo ip: ");
|
|
MR_printlabel(fp, MR_redoip_slot(MR_maxfr));
|
|
|
|
if (MR_detaildebug) {
|
|
MR_dumpnondetstack(fp);
|
|
}
|
|
}
|
|
|
|
void
|
|
MR_mkdettempframe_msg(FILE *fp)
|
|
{
|
|
MR_restore_transient_registers();
|
|
|
|
if (!MR_lld_print_enabled) {
|
|
return;
|
|
}
|
|
|
|
fprintf(fp, "\nnew det temp nondet frame\n");
|
|
fprintf(fp, "new fr: ");
|
|
MR_printnondetstack(fp, MR_maxfr);
|
|
fprintf(fp, "prev fr: ");
|
|
MR_printnondetstack(fp, MR_prevfr_slot(MR_maxfr));
|
|
fprintf(fp, "redo fr: ");
|
|
MR_printnondetstack(fp, MR_redofr_slot(MR_maxfr));
|
|
fprintf(fp, "redo ip: ");
|
|
MR_printlabel(fp, MR_redoip_slot(MR_maxfr));
|
|
fprintf(fp, "det fr: ");
|
|
MR_printdetstack(fp, MR_tmp_detfr_slot(MR_maxfr));
|
|
|
|
if (MR_detaildebug) {
|
|
MR_dumpnondetstack(fp);
|
|
}
|
|
}
|
|
|
|
void
|
|
MR_succeed_msg(FILE *fp)
|
|
{
|
|
MR_restore_transient_registers();
|
|
|
|
MR_do_watches(fp);
|
|
|
|
if (!MR_lld_print_enabled) {
|
|
return;
|
|
}
|
|
|
|
fprintf(fp, "\nsucceeding from procedure\n");
|
|
fprintf(fp, "curr fr: ");
|
|
MR_printnondetstack(fp, MR_curfr);
|
|
fprintf(fp, "succ fr: ");
|
|
MR_printnondetstack(fp, MR_succfr_slot(MR_curfr));
|
|
fprintf(fp, "succ ip: ");
|
|
MR_printlabel(fp, MR_succip_slot(MR_curfr));
|
|
|
|
if (MR_detaildebug) {
|
|
MR_printregs(fp, "registers at success");
|
|
}
|
|
}
|
|
|
|
void
|
|
MR_succeeddiscard_msg(FILE *fp)
|
|
{
|
|
MR_restore_transient_registers();
|
|
|
|
MR_do_watches(fp);
|
|
|
|
if (!MR_lld_print_enabled) {
|
|
return;
|
|
}
|
|
|
|
fprintf(fp, "\nsucceeding from procedure\n");
|
|
fprintf(fp, "curr fr: ");
|
|
MR_printnondetstack(fp, MR_curfr);
|
|
fprintf(fp, "succ fr: ");
|
|
MR_printnondetstack(fp, MR_succfr_slot(MR_curfr));
|
|
fprintf(fp, "succ ip: ");
|
|
MR_printlabel(fp, MR_succip_slot(MR_curfr));
|
|
|
|
if (MR_detaildebug) {
|
|
MR_printregs(fp, "registers at success");
|
|
}
|
|
}
|
|
|
|
void
|
|
MR_fail_msg(FILE *fp)
|
|
{
|
|
MR_restore_transient_registers();
|
|
|
|
MR_do_watches(fp);
|
|
|
|
if (!MR_lld_print_enabled) {
|
|
return;
|
|
}
|
|
|
|
fprintf(fp, "\nfailing from procedure\n");
|
|
fprintf(fp, "curr fr: ");
|
|
MR_printnondetstack(fp, MR_curfr);
|
|
fprintf(fp, "fail fr: ");
|
|
MR_printnondetstack(fp, MR_prevfr_slot(MR_curfr));
|
|
fprintf(fp, "fail ip: ");
|
|
MR_printlabel(fp, MR_redoip_slot(MR_prevfr_slot(MR_curfr)));
|
|
}
|
|
|
|
void
|
|
MR_redo_msg(FILE *fp)
|
|
{
|
|
MR_restore_transient_registers();
|
|
|
|
MR_do_watches(fp);
|
|
|
|
if (!MR_lld_print_enabled) {
|
|
return;
|
|
}
|
|
|
|
fprintf(fp, "\nredo from procedure\n");
|
|
fprintf(fp, "curr fr: ");
|
|
MR_printnondetstack(fp, MR_curfr);
|
|
fprintf(fp, "redo fr: ");
|
|
MR_printnondetstack(fp, MR_maxfr);
|
|
fprintf(fp, "redo ip: ");
|
|
MR_printlabel(fp, MR_redoip_slot(MR_maxfr));
|
|
}
|
|
|
|
void
|
|
MR_call_msg(FILE *fp, const MR_Code *proc, const MR_Code *succ_cont)
|
|
{
|
|
MR_count_call(fp, proc);
|
|
|
|
#ifdef MR_DEEP_PROFILING
|
|
MR_check_watch_csd_start(proc);
|
|
#endif /* MR_DEEP_PROFILING */
|
|
|
|
MR_do_watches(fp);
|
|
|
|
if (!MR_lld_print_enabled) {
|
|
return;
|
|
}
|
|
|
|
fprintf(fp, "\ncall %lu: ", MR_lld_cur_call);
|
|
MR_printlabel(fp, proc);
|
|
fprintf(fp, "cont ");
|
|
MR_printlabel(fp, succ_cont);
|
|
|
|
if (MR_anyregdebug) {
|
|
MR_printregs(fp, "at call:");
|
|
}
|
|
|
|
#ifdef MR_DEEP_PROFILING
|
|
MR_print_deep_prof_vars(fp, "MR_call_msg");
|
|
#endif
|
|
}
|
|
|
|
void
|
|
MR_tailcall_msg(FILE *fp, const MR_Code *proc)
|
|
{
|
|
MR_restore_transient_registers();
|
|
|
|
MR_count_call(fp, proc);
|
|
|
|
#ifdef MR_DEEP_PROFILING
|
|
MR_check_watch_csd_start(proc);
|
|
#endif /* MR_DEEP_PROFILING */
|
|
|
|
MR_do_watches(fp);
|
|
|
|
if (!MR_lld_print_enabled) {
|
|
return;
|
|
}
|
|
|
|
fprintf(fp, "\ntail call %lu: ", MR_lld_cur_call);
|
|
MR_printlabel(fp, proc);
|
|
fprintf(fp, "cont ");
|
|
MR_printlabel(fp, MR_succip);
|
|
|
|
if (MR_anyregdebug) {
|
|
MR_printregs(fp, "at tailcall:");
|
|
}
|
|
|
|
#ifdef MR_DEEP_PROFILING
|
|
MR_print_deep_prof_vars(fp, "MR_tailcall_msg");
|
|
#endif
|
|
}
|
|
|
|
void
|
|
MR_proceed_msg(FILE *fp)
|
|
{
|
|
MR_do_watches(fp);
|
|
|
|
if (!MR_lld_print_enabled) {
|
|
return;
|
|
}
|
|
|
|
fprintf(fp, "\nreturning from determinate procedure\n");
|
|
if (MR_anyregdebug) {
|
|
MR_printregs(fp, "at proceed:");
|
|
}
|
|
|
|
#ifdef MR_DEEP_PROFILING
|
|
MR_print_deep_prof_vars(fp, "MR_proceed_msg");
|
|
#endif
|
|
}
|
|
|
|
void
|
|
MR_cr1_msg(FILE *fp, const MR_Word *addr)
|
|
{
|
|
if (!MR_lld_print_enabled) {
|
|
return;
|
|
}
|
|
|
|
#ifdef MR_RECORD_TERM_SIZES
|
|
fprintf(fp, "create1: put size %ld, value %9lx at ",
|
|
(long) (MR_Integer) addr[-2],
|
|
(long) (MR_Integer) addr[-1]);
|
|
#else
|
|
fprintf(fp, "create1: put value %9lx at ",
|
|
(long) (MR_Integer) addr[-1]);
|
|
#endif
|
|
MR_printheap(fp, addr);
|
|
}
|
|
|
|
void
|
|
MR_cr2_msg(FILE *fp, const MR_Word *addr)
|
|
{
|
|
if (!MR_lld_print_enabled) {
|
|
return;
|
|
}
|
|
|
|
#ifdef MR_RECORD_TERM_SIZES
|
|
fprintf(fp, "create2: put size %ld, values %9lx,%9lx at ",
|
|
(long) (MR_Integer) addr[-3],
|
|
(long) (MR_Integer) addr[-2],
|
|
(long) (MR_Integer) addr[-1]);
|
|
#else
|
|
fprintf(fp, "create2: put values %9lx,%9lx at ",
|
|
(long) (MR_Integer) addr[-2],
|
|
(long) (MR_Integer) addr[-1]);
|
|
#endif
|
|
MR_printheap(fp, addr);
|
|
}
|
|
|
|
void
|
|
MR_cr3_msg(FILE *fp, const MR_Word *addr)
|
|
{
|
|
if (!MR_lld_print_enabled) {
|
|
return;
|
|
}
|
|
|
|
#ifdef MR_RECORD_TERM_SIZES
|
|
fprintf(fp, "create3: put size %ld, values %9lx,%9lx,%9lx at ",
|
|
(long) (MR_Integer) addr[-4],
|
|
(long) (MR_Integer) addr[-3],
|
|
(long) (MR_Integer) addr[-2],
|
|
(long) (MR_Integer) addr[-1]);
|
|
#else
|
|
fprintf(fp, "create3: put values %9lx,%9lx,%9lx at ",
|
|
(long) (MR_Integer) addr[-3],
|
|
(long) (MR_Integer) addr[-2],
|
|
(long) (MR_Integer) addr[-1]);
|
|
#endif
|
|
MR_printheap(fp, addr);
|
|
}
|
|
|
|
void
|
|
MR_incr_hp_debug_msg(FILE *fp, MR_Word val, const MR_Word *addr)
|
|
{
|
|
if (!MR_lld_print_enabled) {
|
|
return;
|
|
}
|
|
|
|
#ifdef MR_CONSERVATIVE_GC
|
|
fprintf(fp, "allocated %ld words at %p\n", (long) val, addr);
|
|
#else
|
|
fprintf(fp, "increment hp by %ld from ", (long) (MR_Integer) val);
|
|
MR_printheap(fp, addr);
|
|
#endif
|
|
}
|
|
|
|
void
|
|
MR_incr_sp_msg(FILE *fp, MR_Word val, const MR_Word *addr)
|
|
{
|
|
if (!MR_lld_print_enabled) {
|
|
return;
|
|
}
|
|
|
|
fprintf(fp, "increment sp by %ld from ", (long) (MR_Integer) val);
|
|
MR_printdetstack(fp, addr);
|
|
}
|
|
|
|
void
|
|
MR_decr_sp_msg(FILE *fp, MR_Word val, const MR_Word *addr)
|
|
{
|
|
if (!MR_lld_print_enabled) {
|
|
return;
|
|
}
|
|
|
|
fprintf(fp, "decrement sp by %ld from ", (long) (MR_Integer) val);
|
|
MR_printdetstack(fp, addr);
|
|
}
|
|
|
|
#endif /* defined(MR_LOWLEVEL_DEBUG) */
|
|
|
|
#ifdef MR_DEBUG_GOTOS
|
|
|
|
void
|
|
MR_goto_msg(FILE *fp, const MR_Code *addr)
|
|
{
|
|
if (!MR_lld_print_enabled) {
|
|
return;
|
|
}
|
|
|
|
if (addr == NULL) {
|
|
fprintf(fp, "\ngoto NULL\n");
|
|
MR_fatal_error("MR_goto_msg: NULL");
|
|
}
|
|
|
|
fprintf(fp, "\ngoto ");
|
|
MR_printlabel(fp, addr);
|
|
}
|
|
|
|
void
|
|
MR_reg_msg(FILE *fp)
|
|
{
|
|
int i;
|
|
MR_Integer x;
|
|
|
|
if (!MR_lld_print_enabled) {
|
|
return;
|
|
}
|
|
|
|
for(i=1; i<=8; i++) {
|
|
x = (MR_Integer) MR_get_reg(i);
|
|
#ifndef MR_CONSERVATIVE_GC
|
|
if ((MR_Integer) MR_ENGINE(MR_eng_heap_zone)->MR_zone_min <= x
|
|
&& x < (MR_Integer) MR_ENGINE(MR_eng_heap_zone)->MR_zone_top)
|
|
{
|
|
x -= (MR_Integer) MR_ENGINE(MR_eng_heap_zone)->MR_zone_min;
|
|
}
|
|
#endif
|
|
fprintf(fp, "%8lx ", (long) x);
|
|
}
|
|
fprintf(fp, "\n");
|
|
}
|
|
|
|
#endif /* defined(MR_DEBUG_GOTOS) */
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
|
|
#ifdef MR_LOWLEVEL_DEBUG
|
|
|
|
/* debugging printing tools */
|
|
|
|
static void
|
|
MR_count_call(FILE *fp, const MR_Code *proc)
|
|
{
|
|
MR_lld_cur_call++;
|
|
if (!MR_lld_print_region_enabled) {
|
|
if (MR_lld_cur_call == MR_lld_print_min) {
|
|
MR_lld_print_region_enabled = MR_TRUE;
|
|
fprintf(fp, "entering printed region\n");
|
|
fprintf(fp, "min %lu, max %lu, more <%s>\n",
|
|
MR_lld_print_min, MR_lld_print_max,
|
|
MR_lld_print_more_min_max);
|
|
}
|
|
} else {
|
|
if (MR_lld_cur_call == MR_lld_print_max) {
|
|
MR_lld_print_region_enabled = MR_FALSE;
|
|
MR_setup_call_intervals(&MR_lld_print_more_min_max,
|
|
&MR_lld_print_min, &MR_lld_print_max);
|
|
fprintf(fp, "leaving printed region\n");
|
|
fprintf(fp, "min %lu, max %lu, more <%s>\n",
|
|
MR_lld_print_min, MR_lld_print_max,
|
|
MR_lld_print_more_min_max);
|
|
}
|
|
}
|
|
|
|
if (MR_proc_matches_name(proc, MR_lld_start_name)) {
|
|
MR_lld_print_name_enabled = MR_TRUE;
|
|
MR_lld_start_until = MR_lld_cur_call + MR_lld_start_block;
|
|
fprintf(fp, "entering printed name block %s\n", MR_lld_start_name);
|
|
} else if (MR_lld_cur_call == MR_lld_start_until) {
|
|
MR_lld_print_name_enabled = MR_FALSE;
|
|
fprintf(fp, "leaving printed name block\n");
|
|
}
|
|
|
|
#ifdef MR_DEEP_PROFILING
|
|
if (MR_watch_csd_addr == MR_next_call_site_dynamic
|
|
&& MR_watch_csd_addr != NULL)
|
|
{
|
|
MR_lld_print_csd_enabled = MR_TRUE;
|
|
MR_lld_csd_until = MR_lld_cur_call + MR_lld_start_block;
|
|
MR_watch_csd_started = MR_TRUE;
|
|
fprintf(fp, "entering printed csd block %p\n", MR_watch_csd_addr);
|
|
} else if (MR_lld_cur_call == MR_lld_csd_until) {
|
|
MR_lld_print_csd_enabled = MR_FALSE;
|
|
fprintf(fp, "leaving printed csd block\n");
|
|
}
|
|
#endif
|
|
|
|
/* the bitwise ORs implement logical OR */
|
|
MR_lld_print_enabled = MR_lld_print_region_enabled
|
|
| MR_lld_print_name_enabled | MR_lld_print_csd_enabled
|
|
| MR_lld_debug_enabled;
|
|
}
|
|
|
|
void
|
|
MR_printint(FILE *fp, MR_Word n)
|
|
{
|
|
fprintf(fp, "int %ld\n", (long) (MR_Integer) n);
|
|
}
|
|
|
|
void
|
|
MR_printstring(FILE *fp, const char *s)
|
|
{
|
|
if (MR_print_raw_addrs) {
|
|
fprintf(fp, "string %p %s\n", (const void *) s, s);
|
|
} else {
|
|
fprintf(fp, "string %s\n", s);
|
|
}
|
|
}
|
|
|
|
void
|
|
MR_printheap(FILE *fp, const MR_Word *h)
|
|
{
|
|
#ifndef MR_CONSERVATIVE_GC
|
|
if (MR_print_raw_addrs) {
|
|
fprintf(fp, "ptr %p, ", (const void *) h);
|
|
}
|
|
|
|
fprintf(fp, "offset %3ld words\n",
|
|
(long) (MR_Integer) (h - MR_ENGINE(MR_eng_heap_zone)->min));
|
|
#else
|
|
fprintf(fp, "ptr %p\n", (const void *) h);
|
|
#endif
|
|
}
|
|
|
|
void
|
|
MR_dumpframe(FILE *fp, const MR_Word *fr)
|
|
{
|
|
int i;
|
|
|
|
fprintf(fp, "frame at ");
|
|
MR_printnondetstack(fp, fr),
|
|
fprintf(fp, "\n");
|
|
fprintf(fp, "\t succip ");
|
|
MR_printlabel(fp, MR_succip_slot(fr));
|
|
fprintf(fp, "\t redoip ");
|
|
MR_printlabel(fp, MR_redoip_slot(fr));
|
|
fprintf(fp, "\t succfr ");
|
|
MR_printnondetstack(fp, MR_succfr_slot(fr));
|
|
fprintf(fp, "\t prevfr ");
|
|
MR_printnondetstack(fp, MR_prevfr_slot(fr));
|
|
|
|
for (i = 1; &MR_based_framevar(fr,i) > MR_prevfr_slot(fr); i++) {
|
|
fprintf(fp, "\t framevar(%d) %ld 0x%lx\n",
|
|
i, (long) (MR_Integer) MR_based_framevar(fr,i),
|
|
(unsigned long) MR_based_framevar(fr,i));
|
|
}
|
|
}
|
|
|
|
void
|
|
MR_dumpnondetstack(FILE *fp)
|
|
{
|
|
MR_Word *fr;
|
|
|
|
fprintf(fp, "\nnondetstack dump\n");
|
|
for (fr = MR_maxfr; fr > MR_nondet_stack_trace_bottom;
|
|
fr = MR_prevfr_slot(fr))
|
|
{
|
|
MR_dumpframe(fp, fr);
|
|
}
|
|
}
|
|
|
|
void
|
|
MR_printframe(FILE *fp, const char *msg)
|
|
{
|
|
fprintf(fp, "\n%s\n", msg);
|
|
MR_dumpframe(fp, MR_curfr);
|
|
|
|
MR_print_ordinary_regs(fp);
|
|
}
|
|
|
|
void
|
|
MR_printregs(FILE *fp, const char *msg)
|
|
{
|
|
MR_restore_transient_registers();
|
|
|
|
fprintf(fp, "\n%s\n", msg);
|
|
|
|
if (MR_sregdebug) {
|
|
fprintf(fp, "%-9s", "succip:");
|
|
MR_printlabel(fp, MR_succip);
|
|
fprintf(fp, "%-9s", "curfr:");
|
|
MR_printnondetstack(fp, MR_curfr);
|
|
fprintf(fp, "%-9s", "maxfr:");
|
|
MR_printnondetstack(fp, MR_maxfr);
|
|
fprintf(fp, "%-9s", "hp:");
|
|
MR_printheap(fp, MR_hp);
|
|
fprintf(fp, "%-9s", "sp:");
|
|
MR_printdetstack(fp, MR_sp);
|
|
}
|
|
|
|
if (MR_ordregdebug) {
|
|
MR_print_ordinary_regs(fp);
|
|
}
|
|
}
|
|
|
|
static void
|
|
MR_print_ordinary_regs(FILE *fp)
|
|
{
|
|
int i;
|
|
MR_Integer value;
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
fprintf(fp, "r%d: ", i + 1);
|
|
value = (MR_Integer) MR_get_reg(i+1);
|
|
|
|
#ifndef MR_CONSERVATIVE_GC
|
|
if ((MR_Integer) MR_ENGINE(MR_eng_heap_zone)->min <= value
|
|
&& value < (MR_Integer) MR_ENGINE(MR_eng_heap_zone)->top)
|
|
{
|
|
fprintf(fp, "(heap) ");
|
|
}
|
|
#endif
|
|
|
|
fprintf(fp, "%ld %lx\n", (long) value, (long) value);
|
|
}
|
|
}
|
|
|
|
#ifdef MR_DEEP_PROFILING
|
|
|
|
static struct MR_CallSiteDynamic_Struct MR_watched_csd_last_value =
|
|
{
|
|
/* MR_csd_callee_ptr */ NULL,
|
|
{
|
|
#ifdef MR_DEEP_PROFILING_PORT_COUNTS
|
|
#ifdef MR_DEEP_PROFILING_EXPLICIT_CALL_COUNTS
|
|
/* MR_own_calls */ 0,
|
|
#else
|
|
/* calls are computed from the other fields */
|
|
#endif
|
|
/* MR_own_exits */ 0,
|
|
/* MR_own_fails */ 0,
|
|
/* MR_own_redos */ 0,
|
|
#endif
|
|
#ifdef MR_DEEP_PROFILING_TIMING
|
|
/* MR_own_quanta */ 0,
|
|
#endif
|
|
#ifdef MR_DEEP_PROFILING_CALL_SEQ
|
|
/* MR_own_call_seqs */ 0,
|
|
#endif
|
|
#ifdef MR_DEEP_PROFILING_MEMORY
|
|
/* MR_own_allocs */ 0,
|
|
/* MR_own_words */ 0,
|
|
#endif
|
|
},
|
|
/* MR_csd_depth_count */ 0
|
|
};
|
|
|
|
static void
|
|
MR_check_watch_csd_start(MR_Code *proc)
|
|
{
|
|
#if 0
|
|
if (MR_watch_csd_start_name == NULL) {
|
|
return;
|
|
}
|
|
|
|
if (MR_proc_matches_name(proc, MR_watch_csd_start_name)) {
|
|
if (MR_watch_csd_addr == MR_next_call_site_dynamic) {
|
|
/*
|
|
** Optimize future checks and make MR_watch_csd_addr static.
|
|
*/
|
|
MR_watch_csd_started = MR_TRUE;
|
|
MR_watch_csd_start_name = NULL;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static MR_bool
|
|
MR_csds_are_different(const MR_CallSiteDynamic *csd1,
|
|
const MR_CallSiteDynamic *csd2)
|
|
{
|
|
const MR_ProfilingMetrics *pm1;
|
|
const MR_ProfilingMetrics *pm2;
|
|
|
|
if (csd1->MR_csd_callee_ptr != csd2->MR_csd_callee_ptr) {
|
|
return MR_TRUE;
|
|
}
|
|
|
|
pm1 = &csd1->MR_csd_own;
|
|
pm2 = &csd2->MR_csd_own;
|
|
|
|
#ifdef MR_DEEP_PROFILING_PORT_COUNTS
|
|
#ifdef MR_DEEP_PROFILING_EXPLICIT_CALL_COUNTS
|
|
if (pm1->MR_own_calls != pm2->MR_own_calls) {
|
|
return MR_TRUE;
|
|
}
|
|
#endif
|
|
if (pm1->MR_own_exits != pm2->MR_own_exits) {
|
|
return MR_TRUE;
|
|
}
|
|
if (pm1->MR_own_fails != pm2->MR_own_fails) {
|
|
return MR_TRUE;
|
|
}
|
|
if (pm1->MR_own_redos != pm2->MR_own_redos) {
|
|
return MR_TRUE;
|
|
}
|
|
#endif
|
|
#ifdef MR_DEEP_PROFILING_TIMING
|
|
if (pm1->MR_own_quanta != pm2->MR_own_quanta) {
|
|
return MR_TRUE;
|
|
}
|
|
#endif
|
|
#ifdef MR_DEEP_PROFILING_CALL_SEQ
|
|
if (pm1->MR_own_call_seqs != pm2->MR_own_call_seqs) {
|
|
return MR_TRUE;
|
|
}
|
|
#endif
|
|
#ifdef MR_DEEP_PROFILING_MEMORY
|
|
if (pm1->MR_own_allocs != pm2->MR_own_allocs) {
|
|
return MR_TRUE;
|
|
}
|
|
if (pm1->MR_own_words != pm2->MR_own_words) {
|
|
return MR_TRUE;
|
|
}
|
|
#endif
|
|
|
|
if (csd1->MR_csd_depth_count != csd2->MR_csd_depth_count) {
|
|
return MR_TRUE;
|
|
}
|
|
|
|
return MR_FALSE;
|
|
};
|
|
|
|
static void
|
|
MR_assign_csd(MR_CallSiteDynamic *csd1, const MR_CallSiteDynamic *csd2)
|
|
{
|
|
csd1->MR_csd_callee_ptr = csd2->MR_csd_callee_ptr;
|
|
|
|
#ifdef MR_DEEP_PROFILING_PORT_COUNTS
|
|
#ifdef MR_DEEP_PROFILING_EXPLICIT_CALL_COUNTS
|
|
csd1->MR_csd_own.MR_own_calls = csd2->MR_csd_own.MR_own_calls;
|
|
#endif
|
|
csd1->MR_csd_own.MR_own_exits = csd2->MR_csd_own.MR_own_exits;
|
|
csd1->MR_csd_own.MR_own_fails = csd2->MR_csd_own.MR_own_fails;
|
|
csd1->MR_csd_own.MR_own_redos = csd2->MR_csd_own.MR_own_redos;
|
|
#endif
|
|
#ifdef MR_DEEP_PROFILING_TIMING
|
|
csd1->MR_csd_own.MR_own_quanta = csd2->MR_csd_own.MR_own_quanta;
|
|
#endif
|
|
#ifdef MR_DEEP_PROFILING_CALL_SEQ
|
|
csd1->MR_csd_own.MR_own_call_seqs = csd2->MR_csd_own.MR_own_call_seqs;
|
|
#endif
|
|
#ifdef MR_DEEP_PROFILING_MEMORY
|
|
csd1->MR_csd_own.MR_own_allocs = csd2->MR_csd_own.MR_own_allocs;
|
|
csd1->MR_csd_own.MR_own_words = csd2->MR_csd_own.MR_own_words;
|
|
#endif
|
|
|
|
csd1->MR_csd_depth_count = csd2->MR_csd_depth_count;
|
|
};
|
|
|
|
#endif /* MR_DEEP_PROFILING */
|
|
|
|
static void
|
|
MR_do_watches(FILE *fp)
|
|
{
|
|
if (MR_watch_addr != NULL) {
|
|
fprintf(fp, "watch addr %p: 0x%lx %ld\n", MR_watch_addr,
|
|
(long) *MR_watch_addr, (long) *MR_watch_addr);
|
|
}
|
|
|
|
#ifdef MR_DEEP_PROFILING
|
|
if (MR_watch_csd_addr != NULL) {
|
|
if (MR_watch_csd_started) {
|
|
if (MR_csds_are_different(&MR_watched_csd_last_value,
|
|
MR_watch_csd_addr))
|
|
{
|
|
MR_assign_csd(&MR_watched_csd_last_value, MR_watch_csd_addr);
|
|
fprintf(fp, "current call: %lu\n", MR_lld_cur_call);
|
|
MR_print_deep_prof_var(fp, "watch_csd", MR_watch_csd_addr);
|
|
}
|
|
}
|
|
}
|
|
#endif /* MR_DEEP_PROFILING */
|
|
}
|
|
|
|
static MR_bool
|
|
MR_proc_matches_name(const MR_Code *proc, const char *name)
|
|
{
|
|
#ifdef MR_NEED_ENTRY_LABEL_ARRAY
|
|
MR_Entry *entry;
|
|
|
|
entry = MR_prev_entry_by_addr(proc);
|
|
if (entry != NULL && entry->MR_entry_addr == proc
|
|
&& entry->MR_entry_name != NULL)
|
|
{
|
|
if (MR_streq(entry->MR_entry_name, name)) {
|
|
return MR_TRUE;
|
|
}
|
|
}
|
|
|
|
#endif /* MR_NEED_ENTRY_LABEL_ARRAY */
|
|
return MR_FALSE;
|
|
}
|
|
|
|
#endif /* defined(MR_DEBUG_GOTOS) */
|
|
|
|
#ifndef MR_HIGHLEVEL_CODE
|
|
|
|
void
|
|
MR_print_detstackptr(FILE *fp, const MR_Word *s)
|
|
{
|
|
MR_MemoryZone *zone;
|
|
int zone_num;
|
|
|
|
if (MR_find_zone_for_det_ptr(s, NULL, &zone, &zone_num)) {
|
|
if (zone_num == 0) {
|
|
fprintf(fp, "det %3ld",
|
|
(long) (MR_Integer) (s - zone->MR_zone_min));
|
|
} else {
|
|
fprintf(fp, "det %3ld, segment %d",
|
|
(long) (MR_Integer) (s - zone->MR_zone_min), zone_num);
|
|
}
|
|
|
|
if (MR_print_raw_addrs) {
|
|
fprintf(fp, " (%p)", (const void *) s);
|
|
}
|
|
} else {
|
|
fprintf(fp, "det raw %p", (const void *) s);
|
|
}
|
|
}
|
|
|
|
void
|
|
MR_printdetstack(FILE *fp, const MR_Word *s)
|
|
{
|
|
MR_MemoryZone *zone;
|
|
int zone_num;
|
|
|
|
if (MR_find_zone_for_det_ptr(s, NULL, &zone, &zone_num)) {
|
|
if (MR_print_raw_addrs) {
|
|
fprintf(fp, "ptr %p, ", (const void *) s);
|
|
}
|
|
|
|
if (zone_num == 0) {
|
|
fprintf(fp, "offset %3ld words",
|
|
(long) (MR_Integer) (s - zone->MR_zone_min));
|
|
} else {
|
|
fprintf(fp, "offset %3ld words in segment %d",
|
|
(long) (MR_Integer) (s - zone->MR_zone_min), zone_num);
|
|
}
|
|
} else {
|
|
fprintf(fp, "raw ptr %p", (const void *) s);
|
|
}
|
|
}
|
|
|
|
void
|
|
MR_print_nondetstackptr(FILE *fp, const MR_Word *s)
|
|
{
|
|
MR_MemoryZone *zone;
|
|
int zone_num;
|
|
|
|
if (MR_find_zone_for_nondet_ptr(s, NULL, &zone, &zone_num)) {
|
|
if (zone_num == 0) {
|
|
fprintf(fp, "non %3ld",
|
|
(long) (MR_Integer) (s - zone->MR_zone_min));
|
|
} else {
|
|
fprintf(fp, "non %3ld, segment %d",
|
|
(long) (MR_Integer) (s - zone->MR_zone_min), zone_num);
|
|
}
|
|
|
|
if (MR_print_raw_addrs) {
|
|
fprintf(fp, " (%p)", (const void *) s);
|
|
}
|
|
} else {
|
|
fprintf(fp, "non raw %p", (const void *) s);
|
|
}
|
|
}
|
|
|
|
void
|
|
MR_printnondetstack(FILE *fp, const MR_Word *s)
|
|
{
|
|
MR_MemoryZone *zone;
|
|
int zone_num;
|
|
|
|
if (MR_find_zone_for_nondet_ptr(s, NULL, &zone, &zone_num)) {
|
|
if (MR_print_raw_addrs) {
|
|
fprintf(fp, "ptr %p, ", (const void *) s);
|
|
}
|
|
|
|
if (zone_num == 0) {
|
|
fprintf(fp, "offset %3ld words",
|
|
(long) (MR_Integer) (s - zone->MR_zone_min));
|
|
} else {
|
|
fprintf(fp, "offset %3ld words in segment %d",
|
|
(long) (MR_Integer) (s - zone->MR_zone_min), zone_num);
|
|
}
|
|
} else {
|
|
fprintf(fp, "raw ptr %p", (const void *) s);
|
|
}
|
|
}
|
|
|
|
#endif /* !MR_HIGHLEVEL_CODE */
|
|
|
|
void
|
|
MR_print_heapptr(FILE *fp, const MR_Word *s)
|
|
{
|
|
#ifdef MR_CONSERVATIVE_GC
|
|
fprintf(fp, "heap %" MR_INTEGER_LENGTH_MODIFIER "d", (MR_Integer) s);
|
|
#else
|
|
fprintf(fp, "heap %3ld",
|
|
(long) (MR_Integer) (s - MR_ENGINE(MR_eng_heap_zone)->MR_zone_min));
|
|
#endif
|
|
|
|
if (MR_print_raw_addrs) {
|
|
fprintf(fp, " (%p)", (const void *) s);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** The code of MR_print_label is similar to, but significantly more powerful
|
|
** than, MR_lookup_entry_or_internal in mercury_label.c, since it does not
|
|
** have to return a single short constant string.
|
|
*/
|
|
|
|
void
|
|
MR_print_label(FILE *fp, const MR_Code *w)
|
|
{
|
|
MR_Internal *internal;
|
|
|
|
internal = MR_lookup_internal_by_addr(w);
|
|
if (internal != NULL) {
|
|
if (internal->MR_internal_name != NULL) {
|
|
fprintf(fp, "label %s", internal->MR_internal_name);
|
|
} else {
|
|
fprintf(fp, "unnamed label %p", internal->MR_internal_addr);
|
|
}
|
|
#ifdef MR_DEBUG_LABEL_GOAL_PATHS
|
|
if (internal->MR_internal_layout != NULL) {
|
|
fprintf(fp, " <%s>",
|
|
MR_label_goal_path(internal->MR_internal_layout));
|
|
}
|
|
#endif
|
|
} else {
|
|
MR_Entry *entry;
|
|
|
|
entry = MR_prev_entry_by_addr(w);
|
|
if (entry != NULL && entry->MR_entry_addr == w) {
|
|
if (entry->MR_entry_name != NULL) {
|
|
fprintf(fp, "entry label %s", entry->MR_entry_name);
|
|
} else {
|
|
fprintf(fp, "unnamed entry label %p", entry->MR_entry_addr);
|
|
}
|
|
} else {
|
|
fprintf(fp, "label UNKNOWN %p", w);
|
|
}
|
|
}
|
|
|
|
if (MR_print_raw_addrs) {
|
|
fprintf(fp, " (%p)", w);
|
|
}
|
|
}
|
|
|
|
void
|
|
MR_printlabel(FILE *fp, const MR_Code *w)
|
|
{
|
|
MR_print_label(fp, w);
|
|
fprintf(fp, "\n");
|
|
}
|
|
|
|
void
|
|
MR_print_deep_prof_var(FILE *fp, const char *name, MR_CallSiteDynamic *csd)
|
|
{
|
|
#ifdef MR_DEEP_PROFILING
|
|
fprintf(fp, "%s: %p", name, csd);
|
|
|
|
if (csd == NULL) {
|
|
fprintf(fp, "\n");
|
|
} else {
|
|
const MR_ProcDynamic *pd;
|
|
const MR_ProcLayout *pl;
|
|
const MR_ProcStatic *ps;
|
|
const MR_ProcId *proc_id;
|
|
|
|
fprintf(fp, ", depth %d,", csd->MR_csd_depth_count);
|
|
|
|
#ifdef MR_DEEP_PROFILING_EXPLICIT_CALL_COUNTS
|
|
fprintf(fp, " calls %d,",
|
|
csd->MR_csd_own.MR_own_calls);
|
|
#endif
|
|
fprintf(fp, " exits %d, fails %d, redos %d\n",
|
|
csd->MR_csd_own.MR_own_exits,
|
|
csd->MR_csd_own.MR_own_fails,
|
|
csd->MR_csd_own.MR_own_redos);
|
|
|
|
pd = csd->MR_csd_callee_ptr;
|
|
fprintf(fp, " pd: %p", pd);
|
|
if (pd == NULL) {
|
|
fprintf(fp, "\n");
|
|
} else if (pd->MR_pd_proc_layout == NULL) {
|
|
fprintf(fp, ", pl is NULL\n");
|
|
} else {
|
|
pl = pd->MR_pd_proc_layout;
|
|
ps = pl->MR_sle_proc_static;
|
|
fprintf(fp, ", pl: %p, ps: %p\n", pl, ps);
|
|
proc_id = &pl->MR_sle_proc_id;
|
|
if (MR_PROC_ID_IS_UCI(*proc_id)) {
|
|
fprintf(fp, " %s:%s %s/%d-%d\n ",
|
|
proc_id->MR_proc_uci.MR_uci_type_module,
|
|
proc_id->MR_proc_uci.MR_uci_type_name,
|
|
proc_id->MR_proc_uci.MR_uci_pred_name,
|
|
proc_id->MR_proc_uci.MR_uci_type_arity,
|
|
proc_id->MR_proc_uci.MR_uci_mode);
|
|
} else {
|
|
fprintf(fp, " %s.%s/%d-%d\n ",
|
|
proc_id->MR_proc_user.MR_user_decl_module,
|
|
proc_id->MR_proc_user.MR_user_name,
|
|
proc_id->MR_proc_user.MR_user_arity,
|
|
proc_id->MR_proc_user.MR_user_mode);
|
|
}
|
|
|
|
#ifdef MR_USE_ACTIVATION_COUNTS
|
|
fprintf(fp, "active %d, ", ps->MR_ps_activation_count);
|
|
#endif
|
|
fprintf(fp, "outermost %p, array %d\n",
|
|
ps->MR_ps_outermost_activation_ptr, ps->MR_ps_num_call_sites);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/* auxiliary routines for the code that prints debugging messages */
|
|
|
|
static MR_bool
|
|
MR_find_zone_for_det_ptr_in_context(const MR_Word *ptr, MR_Context *ctxt,
|
|
MR_MemoryZone **zone_ptr, int *zone_num_ptr)
|
|
{
|
|
#ifdef MR_HIGHLEVEL_CODE
|
|
return MR_FALSE;
|
|
#else /* !MR_HIGHLEVEL_CODE */
|
|
int segment_number;
|
|
MR_MemoryZones *remaining_zones;
|
|
MR_MemoryZone *cur_zone;
|
|
|
|
remaining_zones = ctxt->MR_ctxt_prev_detstack_zones;
|
|
if (MR_in_zone(ptr, ctxt->MR_ctxt_detstack_zone)) {
|
|
if (zone_ptr != NULL) {
|
|
*zone_ptr = ctxt->MR_ctxt_detstack_zone;
|
|
}
|
|
} else {
|
|
while (remaining_zones != NULL) {
|
|
cur_zone = remaining_zones->MR_zones_head;
|
|
if (MR_in_zone(ptr, cur_zone)) {
|
|
if (zone_ptr != NULL) {
|
|
*zone_ptr = cur_zone;
|
|
}
|
|
|
|
remaining_zones = remaining_zones->MR_zones_tail;
|
|
break;
|
|
}
|
|
|
|
remaining_zones = remaining_zones->MR_zones_tail;
|
|
}
|
|
|
|
return MR_FALSE;
|
|
}
|
|
|
|
if (zone_num_ptr != NULL) {
|
|
segment_number = 0;
|
|
while (remaining_zones != NULL) {
|
|
segment_number++;
|
|
remaining_zones = remaining_zones->MR_zones_tail;
|
|
}
|
|
|
|
*zone_num_ptr = segment_number;
|
|
}
|
|
|
|
return MR_TRUE;
|
|
#endif /* !MR_HIGHLEVEL_CODE */
|
|
}
|
|
|
|
static MR_bool
|
|
MR_find_zone_for_nondet_ptr_in_context(const MR_Word *ptr, MR_Context *ctxt,
|
|
MR_MemoryZone **zone_ptr, int *zone_num_ptr)
|
|
{
|
|
#ifdef MR_HIGHLEVEL_CODE
|
|
return MR_FALSE;
|
|
#else /* !MR_HIGHLEVEL_CODE */
|
|
int segment_number;
|
|
MR_MemoryZones *remaining_zones;
|
|
MR_MemoryZone *cur_zone;
|
|
|
|
remaining_zones = ctxt->MR_ctxt_prev_nondetstack_zones;
|
|
if (MR_in_zone(ptr, ctxt->MR_ctxt_nondetstack_zone)) {
|
|
if (zone_ptr != NULL) {
|
|
*zone_ptr = ctxt->MR_ctxt_nondetstack_zone;
|
|
}
|
|
} else {
|
|
while (remaining_zones != NULL) {
|
|
cur_zone = remaining_zones->MR_zones_head;
|
|
if (MR_in_zone(ptr, cur_zone)) {
|
|
if (zone_ptr != NULL) {
|
|
*zone_ptr = cur_zone;
|
|
}
|
|
|
|
remaining_zones = remaining_zones->MR_zones_tail;
|
|
break;
|
|
}
|
|
|
|
remaining_zones = remaining_zones->MR_zones_tail;
|
|
}
|
|
|
|
return MR_FALSE;
|
|
}
|
|
|
|
if (zone_num_ptr != NULL) {
|
|
segment_number = 0;
|
|
while (remaining_zones != NULL) {
|
|
segment_number++;
|
|
remaining_zones = remaining_zones->MR_zones_tail;
|
|
}
|
|
|
|
*zone_num_ptr = segment_number;
|
|
}
|
|
|
|
return MR_TRUE;
|
|
#endif /* !MR_HIGHLEVEL_CODE */
|
|
}
|
|
|
|
static MR_bool
|
|
MR_find_zone_for_det_ptr(const MR_Word *ptr, MR_Context **ctxt_ptr,
|
|
MR_MemoryZone **zone_ptr, int *zone_num_ptr)
|
|
{
|
|
#ifdef MR_USE_MINIMAL_MODEL_OWN_STACKS
|
|
|
|
const MR_Dlist *item;
|
|
MR_Context *ctxt;
|
|
|
|
if (MR_find_zone_for_det_ptr_in_context(ptr,
|
|
MR_ENGINE(MR_eng_main_context), zone_ptr, zone_num_ptr))
|
|
{
|
|
if (ctxt_ptr != NULL) {
|
|
*ctxt_ptr = MR_ENGINE(MR_eng_main_context);
|
|
}
|
|
|
|
return MR_TRUE;
|
|
}
|
|
|
|
MR_for_dlist(item, MR_ENGINE(MR_eng_gen_contexts)) {
|
|
ctxt = (MR_Context *) MR_dlist_data(item);
|
|
if (MR_find_zone_for_det_ptr_in_context(ptr, ctxt,
|
|
zone_ptr, zone_num_ptr))
|
|
{
|
|
if (ctxt_ptr != NULL) {
|
|
*ctxt_ptr = ctxt;
|
|
}
|
|
|
|
return MR_TRUE;
|
|
}
|
|
}
|
|
|
|
#else /* !MR_USE_MINIMAL_MODEL_OWN_STACKS */
|
|
|
|
if (MR_find_zone_for_det_ptr_in_context(ptr, &MR_ENGINE(MR_eng_context),
|
|
zone_ptr, zone_num_ptr))
|
|
{
|
|
if (ctxt_ptr != NULL) {
|
|
*ctxt_ptr = &MR_ENGINE(MR_eng_context);
|
|
}
|
|
|
|
return MR_TRUE;
|
|
}
|
|
|
|
#endif /* MR_USE_MINIMAL_MODEL_OWN_STACKS */
|
|
|
|
return MR_FALSE;
|
|
}
|
|
|
|
static MR_bool
|
|
MR_find_zone_for_nondet_ptr(const MR_Word *ptr, MR_Context **ctxt_ptr,
|
|
MR_MemoryZone **zone_ptr, int *zone_num_ptr)
|
|
{
|
|
#ifdef MR_USE_MINIMAL_MODEL_OWN_STACKS
|
|
|
|
const MR_Dlist *item;
|
|
MR_Context *ctxt;
|
|
|
|
if (MR_find_zone_for_nondet_ptr_in_context(ptr,
|
|
MR_ENGINE(MR_eng_main_context), zone_ptr, zone_num_ptr))
|
|
{
|
|
if (ctxt_ptr != NULL) {
|
|
*ctxt_ptr = MR_ENGINE(MR_eng_main_context);
|
|
}
|
|
|
|
return MR_TRUE;
|
|
}
|
|
|
|
MR_for_dlist(item, MR_ENGINE(MR_eng_gen_contexts)) {
|
|
ctxt = (MR_Context *) MR_dlist_data(item);
|
|
if (MR_find_zone_for_nondet_ptr_in_context(ptr, ctxt,
|
|
zone_ptr, zone_num_ptr))
|
|
{
|
|
if (ctxt_ptr != NULL) {
|
|
*ctxt_ptr = ctxt;
|
|
}
|
|
|
|
return MR_TRUE;
|
|
}
|
|
}
|
|
|
|
#else /* !MR_USE_MINIMAL_MODEL_OWN_STACKS */
|
|
|
|
if (MR_find_zone_for_nondet_ptr_in_context(ptr, &MR_ENGINE(MR_eng_context),
|
|
zone_ptr, zone_num_ptr))
|
|
{
|
|
if (ctxt_ptr != NULL) {
|
|
*ctxt_ptr = &MR_ENGINE(MR_eng_context);
|
|
}
|
|
|
|
return MR_TRUE;
|
|
}
|
|
|
|
#endif /* MR_USE_MINIMAL_MODEL_OWN_STACKS */
|
|
|
|
return MR_FALSE;
|
|
}
|
|
|
|
void
|
|
MR_debug_log_message(const char *format, ...) {
|
|
char *buffer;
|
|
int len, result;
|
|
va_list args;
|
|
|
|
/*
|
|
** This should be a reasonable estimate of the size of the buffer that we
|
|
** need. At least twice the size of the format string or 128 bytes.
|
|
*/
|
|
len = strlen(format);
|
|
len = len*2;
|
|
len = len<128 ? 128 : len;
|
|
|
|
buffer = MR_GC_malloc(len);
|
|
while (1) {
|
|
va_start(args, format);
|
|
#ifdef MR_HAVE_VSNPRINTF
|
|
result = vsnprintf(buffer, len, format, args);
|
|
#elif MR_HAVE__VSNPRINTF
|
|
result = _vsnprintf(buffer, len, formst, args);
|
|
#else
|
|
MR_fatal_error(
|
|
"MR_debug_log_message: Don't have vsnprintf or _vsnprintf\n");
|
|
#endif
|
|
va_end(args);
|
|
if (result < len) {
|
|
break;
|
|
}
|
|
|
|
/* Make the buffer bigger. */
|
|
len = len*2;
|
|
buffer = MR_GC_realloc(buffer, len);
|
|
}
|
|
|
|
#if defined(MR_THREADSCOPE) && defined(MR_THREAD_SAFE)
|
|
MR_threadscope_post_log_msg(buffer);
|
|
#elif defined(MR_THREADSCOPE)
|
|
printf("Eng %p: %s\n", MR_thread_engine_base, buffer);
|
|
#else
|
|
printf("%s\n", buffer);
|
|
#endif
|
|
}
|
|
|