[m-rev.] diff: more minimal model improvements
Zoltan Somogyi
zs at cs.mu.OZ.AU
Fri Mar 12 17:01:30 AEDT 2004
More improvements for minimal model tabling.
runtime/mercury_engine.[ch]:
Provide a debug flag to control the printing of debug stack slots
in nondet stack dumps.
runtime/mercury_stack_trace.[ch]:
Provide a mechanism that allows a dump of the nondet stack to print
the principal debugging stack slots of the stack frames of procedures
that were compiled with debugging, to help debug problems where
these are overwritten during stack segment saves/restores.
Add a mechanism for limiting the output of a nondet stack trace
to a segment of the nondet stack.
runtime/mercury_minimal_model.[ch]:
Limit the output of a diagnostic nondet stack trace to just the
segment being saved or restored.
Provide a label layout structure for the entry point of the suspend
predicate, since this is necessary for correct nondet stack traces
at suspensions and resumptions.
Store the layout structure of the top nondet stack frame with each
saved state, to allow the saved nondet stack segment to be dumped
at resumptions as well as suspensions.
Fix an old bug: when extending a saved stack segment, use the same
algorithm for determining its lower bound as when the stack segment
was created in the first place.
Factor out some repeated definitions.
Note problems to be fixed later.
Improve debugging output.
runtime/mercury_stacks.[ch]:
Move the documentation of the generator stack, the cut stack and the
pneg stack from the source file to the header file, and expand it
considerably.
Make the routines for printing entries of these stacks generate more
consistently formatted output.
Simplify some code.
runtime/mercury_stack_layout.h:
Provide a macro for use by mercury_minimal_model.c.
runtime/mercury_trace_base.[ch]:
Save and restore the global variables holding event numbers,
call sequence numbers and call depths across debugging Mercury code.
We already used to do this for Mercury code invoked by the debugger,
but now that we can invoke Mercury code to print the values of
variables as diagnostics from within the suspend and resume predicates
*outside* the debugger, we need to do it more generally.
trace/mercury_trace.c:
Fix a bug: provide the layout structure of the current procedure
to the diagnostic routines for minimal model tabling even if the
debugger doesn't stop at that procedure.
trace/mercury_trace_internal.c:
Add two new mdb commands to help debug minimal model tabling.
The "mm_stack" command has the same effect as the existing commands
"gen_stack", "cut_stack" and "pneg_stack" executed in sequence.
The "debug_vars" command prints the counters for event numbers,
call sequence numbers and call depths, both from their global variables
and their saved copies, for debugging problems where they are
overwritten, such as the one fixed by the changes to
mercury_trace_base.[ch] above.
Reorder some code for consistency.
trace/mercury_trace_util.[ch]:
Add a function to implement the "debug_vars" command.
doc/user_guide.texi:
Document the new mdb commands.
doc/mdb_categories:
Add the new mdb commands to the list of developer commands, as well
some others previously left out.
tests/debugger/mdb_command_test.inp:
Test the documentation of the new mdb commands.
tests/tabling/combine.m:
Change the code of this test case to what was intended, so that it now
matches the old expected output.
tests/tabling/completed_consumer_in_solutions.{m,exp}:
New test case, an easier version of consumer_in_solutions.
tests/tabling/consumer_in_commit.{m,exp}:
Extend this test case and update the expected output; we can execute
both the original code and the extension without runtime exceptions.
tests/tabling/seq2.m:
Fix Kostis's new test case.
tests/tabling/seq4.exp:
Fix the expected output of Kostis's new test case.
tests/tabling/Mmakefile:
Enable the new test cases, and some old test cases that we now pass.
Zoltan.
cvs diff: Diffing .
cvs diff: Diffing analysis
cvs diff: Diffing bindist
cvs diff: Diffing boehm_gc
cvs diff: Diffing boehm_gc/Mac_files
cvs diff: Diffing boehm_gc/cord
cvs diff: Diffing boehm_gc/cord/private
cvs diff: Diffing boehm_gc/doc
cvs diff: Diffing boehm_gc/include
cvs diff: Diffing boehm_gc/include/private
cvs diff: Diffing boehm_gc/tests
cvs diff: Diffing browser
cvs diff: Diffing bytecode
cvs diff: Diffing compiler
cvs diff: Diffing compiler/notes
cvs diff: Diffing debian
cvs diff: Diffing deep_profiler
cvs diff: Diffing deep_profiler/notes
cvs diff: Diffing doc
Index: doc/mdb_categories
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/doc/mdb_categories,v
retrieving revision 1.18
diff -u -b -r1.18 mdb_categories
--- doc/mdb_categories 7 Nov 2003 04:33:19 -0000 1.18
+++ doc/mdb_categories 12 Mar 2004 02:17:58 -0000
@@ -67,9 +67,10 @@
document_category 1100 developer
developer - Commands that are intended to be of use only to developers
of the Mercury implementation. The developer commands are
- `nondet_stack', `stack_regs', `all_regs', `proc_stats',
- `label_stats', `print_optionals', `unhide_events', `dd_dd',
- `table', `type_ctor', `class_decl', `all_type_ctors' and
- `all_class_decls'.
+ `flag', `subgoal', `consumer', `gen_stack', `cut_stack,
+ `pneg_stack', `mm_stacks', `nondet_stack', `stack_regs',
+ `all_regs', `debug_vars', `proc_stats', `label_stats',
+ `print_optionals', `unhide_events', `dd_dd', `table',
+ `type_ctor', `class_decl', `all_type_ctors' and `all_class_decls'.
end
Index: doc/user_guide.texi
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/doc/user_guide.texi,v
retrieving revision 1.381
diff -u -b -r1.381 user_guide.texi
--- doc/user_guide.texi 19 Feb 2004 00:18:20 -0000 1.381
+++ doc/user_guide.texi 11 Mar 2004 16:33:35 -0000
@@ -3268,6 +3268,13 @@
prints the contents of the frames on the possible negated context stack.
In other grades, it reports an error.
@sp 1
+ at item mm_stacks
+ at kindex mm_stacks (mdb command)
+In minimal model grades,
+prints the contents of the frames on the generator stack,
+the cut stack and the possible negated context stack.
+In other grades, it reports an error.
+ at sp 1
@item nondet_stack [-d] [@var{num}]
@kindex nondet_stack (mdb command)
Prints the contents of the frames on the nondet stack.
@@ -3286,6 +3293,11 @@
@item all_regs
@kindex all_regs (mdb command)
Prints the contents of all the virtual machine registers.
+ at sp 1
+ at item debug_vars
+ at kindex debug_vars (mdb command)
+Prints the values of the variables used by the debugger
+to record event numbers, call sequence numbers and call depths.
@sp 1
@item proc_stats
@kindex proc_stats (mdb command)
cvs diff: Diffing extras
cvs diff: Diffing extras/aditi
cvs diff: Diffing extras/cgi
cvs diff: Diffing extras/complex_numbers
cvs diff: Diffing extras/complex_numbers/samples
cvs diff: Diffing extras/complex_numbers/tests
cvs diff: Diffing extras/concurrency
cvs diff: Diffing extras/curs
cvs diff: Diffing extras/curs/samples
cvs diff: Diffing extras/curses
cvs diff: Diffing extras/curses/sample
cvs diff: Diffing extras/dynamic_linking
cvs diff: Diffing extras/error
cvs diff: Diffing extras/graphics
cvs diff: Diffing extras/graphics/mercury_opengl
cvs diff: Diffing extras/graphics/mercury_tcltk
cvs diff: Diffing extras/graphics/samples
cvs diff: Diffing extras/graphics/samples/calc
cvs diff: Diffing extras/graphics/samples/maze
cvs diff: Diffing extras/graphics/samples/pent
cvs diff: Diffing extras/lazy_evaluation
cvs diff: Diffing extras/lex
cvs diff: Diffing extras/lex/samples
cvs diff: Diffing extras/lex/tests
cvs diff: Diffing extras/logged_output
cvs diff: Diffing extras/moose
cvs diff: Diffing extras/moose/samples
cvs diff: Diffing extras/moose/tests
cvs diff: Diffing extras/morphine
cvs diff: Diffing extras/morphine/non-regression-tests
cvs diff: Diffing extras/morphine/scripts
cvs diff: Diffing extras/morphine/source
cvs diff: Diffing extras/odbc
cvs diff: Diffing extras/posix
cvs diff: Diffing extras/quickcheck
cvs diff: Diffing extras/quickcheck/tutes
cvs diff: Diffing extras/references
cvs diff: Diffing extras/references/samples
cvs diff: Diffing extras/references/tests
cvs diff: Diffing extras/stream
cvs diff: Diffing extras/trailed_update
cvs diff: Diffing extras/trailed_update/samples
cvs diff: Diffing extras/trailed_update/tests
cvs diff: Diffing extras/xml
cvs diff: Diffing extras/xml/samples
cvs diff: Diffing java
cvs diff: Diffing java/library
cvs diff: Diffing java/runtime
cvs diff: Diffing library
cvs diff: Diffing profiler
cvs diff: Diffing robdd
cvs diff: Diffing runtime
Index: runtime/mercury_engine.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_engine.c,v
retrieving revision 1.45
diff -u -b -r1.45 mercury_engine.c
--- runtime/mercury_engine.c 24 Oct 2003 03:09:51 -0000 1.45
+++ runtime/mercury_engine.c 11 Mar 2004 16:27:25 -0000
@@ -62,6 +62,7 @@
{ "printlocn", MR_PRINT_LOCN_FLAG },
{ "enabled", MR_LLD_DEBUG_ENABLED_FLAG },
{ "notnearest", MR_NOT_NEAREST_FLAG },
+ { "debugslots", MR_DEBUG_SLOTS_FLAG },
{ "detail", MR_DETAILFLAG }
};
Index: runtime/mercury_engine.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_engine.h,v
retrieving revision 1.32
diff -u -b -r1.32 mercury_engine.h
--- runtime/mercury_engine.h 1 Jun 2003 06:52:35 -0000 1.32
+++ runtime/mercury_engine.h 11 Mar 2004 16:27:25 -0000
@@ -63,8 +63,9 @@
#define MR_PRINT_LOCN_FLAG 17
#define MR_LLD_DEBUG_ENABLED_FLAG 18
#define MR_NOT_NEAREST_FLAG 19
-#define MR_DETAILFLAG 20
-#define MR_MAXFLAG 21
+#define MR_DEBUG_SLOTS_FLAG 20
+#define MR_DETAILFLAG 21
+#define MR_MAXFLAG 22
/* MR_DETAILFLAG should be the last real flag */
/*
@@ -125,6 +126,10 @@
** MR_not_nearest_flag, if set, tells minimal model tabling to save stack
** segments only to the nearest generator, not to the nearest common ancestor
** of the consumer being suspended and its generator.
+**
+** MR_debug_slots_flag controls whether dumps of nondet stack frames will
+** print the values of the fixed stack slots used by the debugger, in the
+** stack frames of procedures compiled with debugging.
*/
#define MR_progdebug MR_debugflag[MR_PROGFLAG]
@@ -147,6 +152,7 @@
#define MR_printlocndebug MR_debugflag[MR_PRINT_LOCN_FLAG]
#define MR_lld_debug_enabled MR_debugflag[MR_LLD_DEBUG_ENABLED_FLAG]
#define MR_not_nearest_flag MR_debugflag[MR_NOT_NEAREST_FLAG]
+#define MR_debug_slots_flag MR_debugflag[MR_DEBUG_SLOTS_FLAG]
#define MR_detaildebug MR_debugflag[MR_DETAILFLAG]
typedef struct {
Index: runtime/mercury_minimal_model.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_minimal_model.c,v
retrieving revision 1.5
diff -u -b -r1.5 mercury_minimal_model.c
--- runtime/mercury_minimal_model.c 10 Mar 2004 04:30:38 -0000 1.5
+++ runtime/mercury_minimal_model.c 12 Mar 2004 04:03:07 -0000
@@ -24,7 +24,7 @@
static MR_Word *nearest_common_ancestor(MR_Word *fr1, MR_Word *fr2);
static void save_state(MR_SavedState *saved_state, MR_Word *generator_fr,
const char *who, const char *what,
- MR_bool can_print_stack_detail);
+ const MR_Label_Layout *top_layout);
static void restore_state(MR_SavedState *saved_state, const char *who,
const char *what);
static void extend_consumer_stacks(MR_Subgoal *leader,
@@ -407,6 +407,7 @@
** suspensions and resumptions of derivations.
*/
+#define SUSPEND_LABEL(name) MR_PASTE3(MR_SUSPEND_ENTRY, _, name)
#define RESUME_LABEL(name) MR_PASTE3(MR_RESUME_ENTRY, _, name)
/*
@@ -458,7 +459,7 @@
static void
save_state(MR_SavedState *saved_state, MR_Word *generator_fr,
- const char *who, const char *what, MR_bool can_print_stack_detail)
+ const char *who, const char *what, const MR_Label_Layout *top_layout)
{
MR_Word *common_ancestor_fr;
MR_Word *start_non;
@@ -467,6 +468,11 @@
MR_restore_transient_registers();
if (MR_not_nearest_flag) {
+ /*
+ ** This can yield incorrect results, as documented in mday_sld.tex
+ ** in papers/tabling2. It is included here only to allow demonstrations
+ ** of *why* this is incorrect.
+ */
common_ancestor_fr = generator_fr;
} else {
common_ancestor_fr = nearest_common_ancestor(MR_curfr, generator_fr);
@@ -479,6 +485,7 @@
saved_state->MR_ss_cur_fr = MR_curfr;
saved_state->MR_ss_max_fr = MR_maxfr;
saved_state->MR_ss_common_ancestor_fr = common_ancestor_fr;
+ saved_state->MR_ss_top_layout = top_layout;
/* we copy from start_non to MR_maxfr, both inclusive */
saved_state->MR_ss_non_stack_real_start = start_non;
@@ -533,12 +540,8 @@
}
if (MR_tablestackdebug) {
- if (can_print_stack_detail) {
- MR_dump_nondet_stack_from_layout(stdout, 0, MR_maxfr,
- MR_subgoal_debug_cur_proc->MR_sle_call_label, MR_sp, MR_curfr);
- } else {
- MR_dump_nondet_stack(stdout, 0, MR_maxfr);
- }
+ MR_dump_nondet_stack_from_layout(stdout, start_non, 0, MR_maxfr,
+ top_layout, MR_sp, MR_curfr);
}
#endif /* MR_TABLE_DEBUG */
@@ -589,8 +592,9 @@
}
if (MR_tablestackdebug) {
- MR_dump_nondet_stack_from_layout(stdout, 0, MR_maxfr, NULL,
- MR_sp, MR_curfr);
+ MR_dump_nondet_stack_from_layout(stdout,
+ saved_state->MR_ss_non_stack_real_start, 0, MR_maxfr,
+ saved_state->MR_ss_top_layout, MR_sp, MR_curfr);
}
#endif /* MR_TABLE_DEBUG */
@@ -604,8 +608,9 @@
** When A becomes a follower of another subgoal B, the responsibility for
** scheduling A's consumers passes to B's generator. Since by definition
** B's nondet stack frame is lower in the stack than A's generator's,
-** we need to extend the stack segments of A's consumers to also include
-** the parts of the stacks between the generator of B and the generator of A.
+** nca(consumer, B) will in general be lower than nca(consumer, A)
+** (where nca = nearest common ancestor). The consumer's saved state
+** goes down to nca(consumer, A); we need to extend it to nca(consumer, B).
*/
static void
@@ -615,6 +620,7 @@
MR_Word *arena_start;
MR_Word arena_size;
MR_Word extension_size;
+ MR_Word *old_common_ancestor_fr;
MR_Word *new_common_ancestor_fr;
MR_Word *saved_fr;
MR_Word *real_fr;
@@ -624,30 +630,50 @@
cons_saved_state = &consumer->MR_cns_saved_state;
+ old_common_ancestor_fr = cons_saved_state->MR_ss_common_ancestor_fr;
+ new_common_ancestor_fr = nearest_common_ancestor(old_common_ancestor_fr,
+ leader->MR_sg_generator_fr);
+
#ifdef MR_TABLE_DEBUG
- if (MR_tablestackdebug) {
- printf("\nextending saved consumer stacks\n");
+ if (MR_tabledebug) {
+ printf("extending saved state of consumer %s for %s\n",
+ MR_consumer_addr_name(consumer), MR_subgoal_addr_name(leader));
+ printf("common ancestors: old ");
+ MR_printnondstackptr(old_common_ancestor_fr);
+ printf(", new ");
+ MR_printnondstackptr(new_common_ancestor_fr);
+ printf("\nold saved state:\n");
print_saved_state(stdout, cons_saved_state);
}
#endif /* MR_TABLE_DEBUG */
- new_common_ancestor_fr = nearest_common_ancestor(
- cons_saved_state->MR_ss_common_ancestor_fr,
- leader->MR_sg_generator_fr);
cons_saved_state->MR_ss_common_ancestor_fr = new_common_ancestor_fr;
- arena_start = MR_table_detfr_slot(leader->MR_sg_generator_fr) + 1;
+ arena_start = MR_table_detfr_slot(new_common_ancestor_fr) + 1;
extension_size = cons_saved_state->MR_ss_det_stack_real_start
- arena_start;
+
+ if (extension_size > 0) {
arena_size = extension_size
+ cons_saved_state->MR_ss_det_stack_block_size;
-#if 0
- if (arena_size != 0) {
- assert(arena_start + arena_size == cons_saved_state->MR_ss_s_p - 1);
+#ifdef MR_TABLE_DEBUG
+ if (MR_tabledebug) {
+ printf("assert: det arena_start ");
+ MR_printdetstackptr(arena_start);
+ printf(" + %d = ", arena_size);
+ MR_printdetstackptr(cons_saved_state->MR_ss_s_p);
+ printf(" + 1: diff %d\n",
+ (arena_start + arena_size)
+ - (cons_saved_state->MR_ss_s_p + 1));
}
#endif
+ if (arena_size != 0) {
+ assert(arena_start + arena_size
+ == cons_saved_state->MR_ss_s_p + 1);
+ }
+
arena_block = MR_table_allocate_words(arena_size);
MR_table_copy_words(arena_block, arena_start, extension_size);
@@ -671,17 +697,32 @@
cons_saved_state->MR_ss_det_stack_saved_block = arena_block;
cons_saved_state->MR_ss_det_stack_block_size = arena_size;
cons_saved_state->MR_ss_det_stack_real_start = arena_start;
+ }
- arena_start = leader->MR_sg_generator_fr + 1;
+ arena_start = MR_prevfr_slot(new_common_ancestor_fr) + 1;
extension_size = cons_saved_state->MR_ss_non_stack_real_start
- arena_start;
+ if (extension_size > 0) {
arena_size = extension_size
+ cons_saved_state->MR_ss_non_stack_block_size;
-#if 0
- assert(arena_start + arena_size == cons_saved_state->MR_max_fr);
+#ifdef MR_TABLE_DEBUG
+ if (MR_tabledebug) {
+ printf("assert: non arena_start ");
+ MR_printnondstackptr(arena_start);
+ printf(" + %d = ", arena_size);
+ MR_printnondstackptr(cons_saved_state->MR_ss_max_fr);
+ printf(" + 1: diff %d\n",
+ (arena_start + arena_size)
+ - (cons_saved_state->MR_ss_max_fr + 1));
+ }
#endif
+ if (arena_size != 0) {
+ assert(arena_start + arena_size
+ == cons_saved_state->MR_ss_max_fr + 1);
+ }
+
arena_block = MR_table_allocate_words(arena_size);
MR_table_copy_words(arena_block, arena_start, extension_size);
@@ -705,6 +746,7 @@
cons_saved_state->MR_ss_non_stack_saved_block = arena_block;
cons_saved_state->MR_ss_non_stack_block_size = arena_size;
cons_saved_state->MR_ss_non_stack_real_start = arena_start;
+ }
#ifdef MR_TABLE_DEBUG
if (MR_tablestackdebug) {
@@ -713,6 +755,7 @@
}
#endif /* MR_TABLE_DEBUG */
+ /* XXX we should be doing this only for the newly added segment */
saved_fr = cons_saved_state->MR_ss_non_stack_saved_block +
cons_saved_state->MR_ss_non_stack_block_size - 1;
real_fr = cons_saved_state->MR_ss_non_stack_real_start +
@@ -775,9 +818,8 @@
#ifdef MR_TABLE_DEBUG
if (MR_tabledebug) {
- printf("making %s follow %s\n",
- MR_subgoal_addr_name(this_follower),
- MR_subgoal_addr_name(leader));
+ printf("\nmaking %s follow %s\n",
+ MR_subgoal_addr_name(this_follower), MR_subgoal_addr_name(leader));
}
#endif /* MR_TABLE_DEBUG */
@@ -936,15 +978,16 @@
#else /* ! MR_HIGHLEVEL_CODE */
-#ifndef MR_USE_MINIMAL_MODEL
-
MR_define_extern_entry(MR_SUSPEND_ENTRY);
MR_define_extern_entry(MR_RESUME_ENTRY);
+
MR_MAKE_PROC_LAYOUT(MR_SUSPEND_ENTRY, MR_DETISM_NON, 0, -1,
MR_PREDICATE, "table_builtin", "table_nondet_suspend", 2, 0);
MR_MAKE_PROC_LAYOUT(MR_RESUME_ENTRY, MR_DETISM_NON, 0, -1,
MR_PREDICATE, "table_builtin", "table_nondet_resume", 1, 0);
+#ifndef MR_USE_MINIMAL_MODEL
+
MR_BEGIN_MODULE(table_nondet_suspend_resume_module)
MR_init_entry_sl(MR_SUSPEND_ENTRY);
MR_init_entry_sl(MR_RESUME_ENTRY);
@@ -965,12 +1008,11 @@
MR_Subgoal *MR_cur_leader;
+MR_define_extern_entry(MR_table_nondet_commit);
+
MR_declare_entry(MR_do_trace_redo_fail);
MR_declare_entry(MR_table_nondet_commit);
-MR_define_extern_entry(MR_SUSPEND_ENTRY);
-
-MR_define_extern_entry(MR_RESUME_ENTRY);
MR_declare_label(RESUME_LABEL(ChangeLoop));
MR_declare_label(RESUME_LABEL(ReachedFixpoint));
MR_declare_label(RESUME_LABEL(LoopOverSubgoals));
@@ -979,13 +1021,8 @@
MR_declare_label(RESUME_LABEL(RedoPoint));
MR_declare_label(RESUME_LABEL(RestartPoint));
-MR_define_extern_entry(MR_table_nondet_commit);
-
-MR_MAKE_PROC_LAYOUT(MR_SUSPEND_ENTRY, MR_DETISM_NON, 0, -1,
- MR_PREDICATE, "table_builtin", "table_nondet_suspend", 2, 0);
-
-MR_MAKE_PROC_LAYOUT(MR_RESUME_ENTRY, MR_DETISM_NON, 0, -1,
- MR_PREDICATE, "table_builtin", "table_nondet_resume", 1, 0);
+MR_MAKE_INTERNAL_LAYOUT_WITH_ENTRY(
+ SUSPEND_LABEL(Call), MR_SUSPEND_ENTRY);
MR_MAKE_INTERNAL_LAYOUT_WITH_ENTRY(
RESUME_LABEL(ChangeLoop), MR_RESUME_ENTRY);
MR_MAKE_INTERNAL_LAYOUT_WITH_ENTRY(
@@ -1004,6 +1041,7 @@
MR_BEGIN_MODULE(table_nondet_suspend_resume_module)
MR_init_entry_sl(MR_SUSPEND_ENTRY);
MR_INIT_PROC_LAYOUT_ADDR(MR_SUSPEND_ENTRY);
+ MR_init_label_sl(SUSPEND_LABEL(Call));
MR_init_entry_sl(MR_RESUME_ENTRY);
MR_INIT_PROC_LAYOUT_ADDR(MR_RESUME_ENTRY);
@@ -1035,6 +1073,16 @@
** answers is in table_nondet_resume.
*/
+ /*
+ ** This frame is not used in table_nondet_suspend, but it is copied
+ ** to the suspend list as part of the saved nondet stack fragment,
+ ** and it *will* be used when table_nondet_resume copies back the
+ ** nondet stack fragment. The framevar slot is for use by
+ ** table_nondet_resume.
+ */
+ MR_mkframe(MR_STRINGIFY(MR_SUSPEND_ENTRY), 1, MR_ENTRY(MR_do_fail));
+
+MR_define_label(SUSPEND_LABEL(Call));
{
MR_SubgoalPtr subgoal;
MR_Consumer *consumer;
@@ -1048,15 +1096,6 @@
MR_Word offset;
MR_Word *clobber_addr;
- /*
- ** This frame is not used in table_nondet_suspend, but it is copied
- ** to the suspend list as part of the saved nondet stack fragment,
- ** and it *will* be used when table_nondet_resume copies back the
- ** nondet stack fragment. The framevar slot is for use by
- ** table_nondet_resume.
- */
- MR_mkframe(MR_STRINGIFY(MR_SUSPEND_ENTRY), 1, MR_ENTRY(MR_do_fail));
-
subgoal = (MR_SubgoalPtr) MR_r1;
MR_register_suspension(subgoal);
consumer = MR_table_allocate_struct(MR_Consumer);
@@ -1073,7 +1112,8 @@
MR_save_transient_registers();
save_state(&(consumer->MR_cns_saved_state), subgoal->MR_sg_generator_fr,
- "suspension", "consumer", MR_TRUE);
+ "suspension", "consumer",
+ (const MR_Label_Layout *) &MR_LAYOUT_FROM_LABEL(SUSPEND_LABEL(Call)));
MR_restore_transient_registers();
cur_gen = MR_gen_next - 1;
@@ -1101,27 +1141,39 @@
** generator corresponding to this consumer.
*/
- *clobber_addr = (MR_Word) MR_ENTRY(MR_RESUME_ENTRY);
#ifdef MR_TABLE_DEBUG
if (MR_tablestackdebug) {
printf("completing redoip of frame at ");
MR_printnondstackptr(fr);
printf(" (in saved copy)\n");
+ printf(" old contents was %p\n",
+ (MR_Word *) *clobber_addr);
}
#endif /* MR_TABLE_DEBUG */
+ *clobber_addr = (MR_Word) MR_ENTRY(MR_RESUME_ENTRY);
- consumer->MR_cns_saved_state.MR_ss_gen_next = cur_gen + 1;
#ifdef MR_TABLE_DEBUG
if (MR_tabledebug) {
- printf("saved gen_next set to %d\n", cur_gen + 1);
+ printf("saved gen_next set to %d from %d\n",
+ cur_gen + 1,
+ consumer->MR_cns_saved_state.MR_ss_gen_next);
+ /* XXX if next assignment is not idempotent */
+ if (consumer->MR_cns_saved_state.MR_ss_gen_next
+ != cur_gen + 1)
+ {
+ MR_print_gen_stack(stdout);
+ MR_print_cut_stack(stdout);
+ }
}
#endif /* MR_TABLE_DEBUG */
+ consumer->MR_cns_saved_state.MR_ss_gen_next = cur_gen + 1;
} else {
/*
** This is the nondet stack frame of some other generator.
*/
#if 0
+ /* reenable XXX */
assert(MR_prevfr_slot(fr) != (stop_addr - 1));
#endif
@@ -1261,7 +1313,7 @@
MR_save_transient_registers();
save_state(&(MR_cur_leader->MR_sg_resume_info->MR_ri_leader_state),
MR_cur_leader->MR_sg_generator_fr, "resumption", "generator",
- MR_FALSE);
+ NULL);
MR_restore_transient_registers();
#ifdef MR_TABLE_DEBUG
Index: runtime/mercury_minimal_model.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_minimal_model.h,v
retrieving revision 1.3
diff -u -b -r1.3 mercury_minimal_model.h
--- runtime/mercury_minimal_model.h 2 May 2003 21:44:16 -0000 1.3
+++ runtime/mercury_minimal_model.h 11 Mar 2004 08:32:52 -0000
@@ -79,6 +79,9 @@
MR_Integer MR_ss_pneg_next;
MR_PNegStackFrame *MR_ss_pneg_stack_saved_block;
+
+ /* to make it possible to generate more detailed debugging output */
+ const MR_Label_Layout *MR_ss_top_layout;
} MR_SavedState;
/* The state of a consumer subgoal */
Index: runtime/mercury_stack_layout.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_stack_layout.h,v
retrieving revision 1.74
diff -u -b -r1.74 mercury_stack_layout.h
--- runtime/mercury_stack_layout.h 20 Oct 2003 07:29:32 -0000 1.74
+++ runtime/mercury_stack_layout.h 11 Mar 2004 04:43:01 -0000
@@ -398,9 +398,12 @@
** live value information as well to these macros.
*/
+#define MR_LAYOUT_FROM_LABEL(label) \
+ MR_PASTE2(mercury_data__label_layout__, label)
+
#define MR_MAKE_INTERNAL_LAYOUT_WITH_ENTRY(label, entry) \
MR_Label_Layout_No_Var_Info \
- MR_PASTE2(mercury_data__label_layout__, label) = { \
+ MR_LAYOUT_FROM_LABEL(label) = { \
(MR_Proc_Layout *) & \
MR_PASTE2(mercury_data__proc_layout__, entry), \
-1, \
Index: runtime/mercury_stack_trace.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_stack_trace.c,v
retrieving revision 1.61
diff -u -b -r1.61 mercury_stack_trace.c
--- runtime/mercury_stack_trace.c 10 Mar 2004 04:30:39 -0000 1.61
+++ runtime/mercury_stack_trace.c 12 Mar 2004 01:58:41 -0000
@@ -302,11 +302,13 @@
/**************************************************************************/
void
-MR_dump_nondet_stack(FILE *fp, int limit, MR_Word *base_maxfr)
+MR_dump_nondet_stack(FILE *fp, MR_Word *limit_addr, int limit,
+ MR_Word *base_maxfr)
{
#ifndef MR_HIGHLEVEL_CODE
- MR_dump_nondet_stack_from_layout(fp, limit, base_maxfr, NULL, NULL, NULL);
+ MR_dump_nondet_stack_from_layout(fp, limit_addr, limit, base_maxfr,
+ NULL, NULL, NULL);
#else /* !MR_HIGHLEVEL_CODE */
@@ -318,8 +320,9 @@
#ifdef MR_HIGHLEVEL_CODE
void
-MR_dump_nondet_stack_from_layout(FILE *fp, int limit, MR_Word *base_maxfr,
- const MR_Label_Layout *top_layout, MR_Word *base_sp, MR_Word *base_curfr)
+MR_dump_nondet_stack_from_layout(FILE *fp, MR_Word *limit_addr, int limit,
+ MR_Word *base_maxfr, const MR_Label_Layout *top_layout,
+ MR_Word *base_sp, MR_Word *base_curfr)
{
MR_fatal_error("MR_dump_nondet_stack_from_layout in high level grade");
}
@@ -392,8 +395,9 @@
#define MR_INIT_NONDET_BRANCH_ARRAY_SIZE 10
void
-MR_dump_nondet_stack_from_layout(FILE *fp, int limit, MR_Word *base_maxfr,
- const MR_Label_Layout *top_layout, MR_Word *base_sp, MR_Word *base_curfr)
+MR_dump_nondet_stack_from_layout(FILE *fp, MR_Word *limit_addr, int limit,
+ MR_Word *base_maxfr, const MR_Label_Layout *top_layout,
+ MR_Word *base_sp, MR_Word *base_curfr)
{
int frame_size;
int level_number;
@@ -401,6 +405,8 @@
const char *problem;
int frames_traversed_so_far;
int branch;
+ const MR_Label_Layout *label_layout;
+ const MR_Proc_Layout *proc_layout;
MR_do_init_modules();
@@ -431,6 +437,11 @@
return;
}
+ if (limit_addr != NULL && base_maxfr < limit_addr) {
+ fprintf(fp, "<reached limit of dumped region>\n");
+ return;
+ }
+
frame_size = base_maxfr - MR_prevfr_slot(base_maxfr);
if (frame_size == MR_NONDET_TEMP_SIZE) {
MR_print_nondstackptr(fp, base_maxfr);
@@ -459,8 +470,6 @@
MR_print_nondstackptr(fp, base_maxfr);
fprintf(fp, ": ordinary, %d words", frame_size);
if (print_vars && MR_find_matching_branch(base_maxfr, &branch)) {
- const MR_Label_Layout *label_layout;
-
fprintf(fp, ", ");
label_layout = MR_nondet_branch_infos[branch].branch_layout;
MR_print_proc_id(fp, label_layout->MR_sll_entry);
@@ -482,6 +491,30 @@
MR_print_detstackptr(fp, MR_table_detfr_slot(base_maxfr));
fprintf(fp, "\n");
#endif
+ if (print_vars && MR_find_matching_branch(base_maxfr, &branch)) {
+ label_layout = MR_nondet_branch_infos[branch].branch_layout;
+ proc_layout = label_layout->MR_sll_entry;
+ if (MR_PROC_LAYOUT_HAS_EXEC_TRACE(proc_layout)
+ && MR_debug_slots_flag)
+ {
+ fprintf(fp, " debug: ");
+ fprintf(fp, "call event ");
+ MR_print_nondstackptr(fp,
+ &MR_event_num_framevar(base_maxfr));
+ fprintf(fp, " => %d, ",
+ MR_event_num_framevar(base_maxfr) + 1);
+ fprintf(fp, "call seq ");
+ MR_print_nondstackptr(fp,
+ &MR_call_num_framevar(base_maxfr));
+ fprintf(fp, " => %d, ",
+ MR_call_num_framevar(base_maxfr)),
+ fprintf(fp, "depth ");
+ MR_print_nondstackptr(fp,
+ &MR_call_depth_framevar(base_maxfr));
+ fprintf(fp, " => %d\n",
+ MR_call_depth_framevar(base_maxfr));
+ }
+ }
level_number++;
if (print_vars && base_maxfr > MR_nondet_stack_trace_bottom) {
@@ -539,7 +572,7 @@
MR_SavedDebugState saved_debug_state;
- MR_turn_off_debug(&saved_debug_state);
+ MR_turn_off_debug(&saved_debug_state, MR_TRUE);
/* XXX we ignore the return value */
(*MR_address_of_trace_browse_all_on_level) (dump_fp, top_layout,
base_sp, base_curfr, level_number, MR_TRUE);
@@ -1124,9 +1157,15 @@
{
MR_bool print_details;
- if (base_sp == NULL || base_curfr == NULL) {
+ if (MR_DETISM_DET_STACK(entry->MR_sle_detism)) {
+ if (base_sp == NULL) {
+ return;
+ }
+ } else {
+ if (base_curfr == NULL) {
return;
}
+ }
if (MR_PROC_LAYOUT_HAS_EXEC_TRACE(entry)) {
MR_Integer maybe_from_full = entry->MR_sle_maybe_from_full;
@@ -1166,7 +1205,6 @@
event_num = MR_event_num_framevar(base_curfr) + 1;
call_num = MR_call_num_framevar(base_curfr);
depth = MR_call_depth_framevar(base_curfr);
-
}
if (MR_standardize_event_details) {
Index: runtime/mercury_stack_trace.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_stack_trace.h,v
retrieving revision 1.31
diff -u -b -r1.31 mercury_stack_trace.h
--- runtime/mercury_stack_trace.h 18 Nov 2003 07:02:28 -0000 1.31
+++ runtime/mercury_stack_trace.h 11 Mar 2004 08:25:41 -0000
@@ -77,21 +77,25 @@
/*
** MR_dump_nondet_stack:
** This function dumps the control slots of the nondet stack.
+** If limit_addr is nonnull, dumps only frames above limit_addr.
** If limit is nonzero, dumps at most limit frames.
** The output format is not meant to be intelligible to non-implementors.
*/
-extern void MR_dump_nondet_stack(FILE *fp, int limit, MR_Word *maxfr);
+extern void MR_dump_nondet_stack(FILE *fp, MR_Word *limit_addr, int limit,
+ MR_Word *maxfr);
/*
** MR_dump_nondet_stack_from_layout:
** This function dumps the nondet stack.
+** If limit_addr is nonnull, dumps only frames above limit_addr.
** If limit is nonzero, dumps at most limit frames.
** The output format is not meant to be intelligible to non-implementors.
*/
-extern void MR_dump_nondet_stack_from_layout(FILE *fp, int limit,
- MR_Word *maxfr, const MR_Label_Layout *label_layout,
+extern void MR_dump_nondet_stack_from_layout(FILE *fp,
+ MR_Word *limit_addr, int limit, MR_Word *maxfr,
+ const MR_Label_Layout *label_layout,
MR_Word *base_sp, MR_Word *base_curfr);
/*
Index: runtime/mercury_stacks.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_stacks.c,v
retrieving revision 1.10
diff -u -b -r1.10 mercury_stacks.c
--- runtime/mercury_stacks.c 2 May 2003 21:44:16 -0000 1.10
+++ runtime/mercury_stacks.c 11 Mar 2004 06:10:00 -0000
@@ -6,7 +6,7 @@
/*
** This file contains code for printing statistics about stack frame sizes,
-** and for manipulating the generator stack and the cut stack.
+** and for manipulating the generator stack, the cut stack and the pneg stack.
**
** The generator stack has one entry for each call to a minimal model tabled
** procedure that is (a) acting as the generator for its subgoal and (b) is
@@ -131,6 +131,11 @@
/***************************************************************************/
+/*
+** Record that the nondet stack frame at address frame_addr is now the
+** generator for subgoal.
+*/
+
void
MR_push_generator(MR_Word *frame_addr, MR_SubgoalPtr subgoal)
{
@@ -147,6 +152,10 @@
#endif
}
+/*
+** Return the subgoal of the topmost generator on the nondet stack.
+*/
+
MR_Subgoal *
MR_top_generator_table(void)
{
@@ -161,6 +170,10 @@
return MR_gen_stack[MR_gen_next - 1].MR_gen_subgoal;
}
+/*
+** Record the deletion of the topmost generator on the nondet stack.
+*/
+
void
MR_pop_generator(void)
{
@@ -187,7 +200,7 @@
{
MR_Integer i;
- fprintf(fp, "gen stack size: %d:\n", (int) gen_next);
+ fprintf(fp, "gen stack size: %d\n", (int) gen_next);
for (i = gen_next - 1; i >= 0; i--) {
MR_print_gen_stack_entry(fp, i, &MR_gen_stack[i]);
}
@@ -206,6 +219,10 @@
/***************************************************************************/
+/*
+** Record the entering of a committed choice context.
+*/
+
void
MR_commit_mark(void)
{
@@ -227,6 +244,15 @@
MR_save_transient_registers();
}
+/*
+** Record the leaving of a committed choice context, and clean up the
+** generators that were created within the context that are still active.
+** We need to clean them up because otherwise, consumers will be depend on this
+** generator to find all the answers to the generator's subgoal, but the
+** generation will never compute any more answers, since it will never be
+** backtracked into.
+*/
+
void
MR_commit_cut(void)
{
@@ -243,13 +269,9 @@
(long) MR_cut_stack[MR_cut_next].MR_cut_gen_next,
(long) MR_gen_next);
- if (MR_gen_next != MR_cut_stack[MR_cut_next].MR_cut_gen_next) {
- if (MR_gen_next <=
- MR_cut_stack[MR_cut_next].MR_cut_gen_next)
- {
+ if (MR_gen_next < MR_cut_stack[MR_cut_next].MR_cut_gen_next) {
printf("MR_gen_next %ld, MR_cut_next %ld, "
- "MR_cut_stack[MR_cut_next].gen_next "
- "%ld\n",
+ "MR_cut_stack[MR_cut_next].gen_next %ld\n",
(long) MR_gen_next,
(long) MR_cut_next,
(long) MR_cut_stack[MR_cut_next].
@@ -257,7 +279,6 @@
MR_fatal_error("GEN_NEXT ASSERTION FAILURE");
}
}
- }
#endif
for (g = MR_cut_stack[MR_cut_next].MR_cut_generators; g != NULL;
@@ -270,6 +291,11 @@
MR_gen_next = MR_cut_stack[MR_cut_next].MR_cut_gen_next;
}
+/*
+** Record the creation of a generator, for possible cleanup later by
+** MR_commit_cut.
+*/
+
void
MR_register_generator_ptr(MR_SubgoalPtr subgoal)
{
@@ -333,7 +359,7 @@
{
MR_Integer i;
- fprintf(fp, "cut stack size: %d:\n", (int) cut_next);
+ fprintf(fp, "cut stack size: %d\n", (int) cut_next);
for (i = cut_next - 1; i >= 0; i--) {
MR_print_cut_stack_entry(fp, i, &cut_block[i]);
}
@@ -347,9 +373,14 @@
fprintf(fp, "cut %ld = <", (long) i);
MR_print_nondstackptr(fp, p->MR_cut_frame);
- fprintf(fp, ", %d>:", p->MR_cut_gen_next);
+ fprintf(fp, ">, cut_gen_next %d, ", (int) p->MR_cut_gen_next);
+ fprintf(fp, "pneg+cut stack depth %d\n", (int) p->MR_cut_depth);
+ fprintf(fp, "registered generators:");
gen_list = p->MR_cut_generators;
+ if (gen_list == NULL) {
+ fprintf(fp, " none");
+ } else {
while (gen_list != NULL) {
if (gen_list->MR_cut_generator_ptr == NULL) {
fprintf(fp, " <NULL>");
@@ -362,6 +393,7 @@
gen_list = gen_list->MR_cut_next_generator;
}
+ }
fprintf(fp, "\n");
}
@@ -471,7 +503,7 @@
void
MR_print_pneg_stack(FILE *fp)
{
- MR_print_pneg_stack_entry(fp, MR_pneg_next, MR_pneg_stack);
+ MR_print_any_pneg_stack(fp, MR_pneg_next, MR_pneg_stack);
}
void
@@ -480,7 +512,7 @@
{
MR_Integer i;
- fprintf(fp, "pneg stack size: %d:\n", (int) pneg_next);
+ fprintf(fp, "pneg stack size: %d\n", (int) pneg_next);
for (i = MR_pneg_next - 1; i >= 0; i--) {
MR_print_pneg_stack_entry(fp, i, &pneg_block[i]);
}
@@ -491,24 +523,26 @@
{
MR_PNegConsumerList l;
- fprintf(fp, "pneg stack entry %d:\n", (int) i);
- fprintf(fp, "gen next: %d\n", (int) p->MR_pneg_gen_next);
- fprintf(fp, "frame: ");
+ fprintf(fp, "pneg %d = <", (int) i);
MR_print_nondstackptr(fp, p->MR_pneg_frame);
- fprintf(fp, "\npneg+cut stack depth %d:\n", (int) p->MR_pneg_depth);
+ fprintf(fp, ">, pneg_gen_next %d, ", (int) p->MR_pneg_gen_next);
+ fprintf(fp, "pneg+cut stack depth %d\n", (int) p->MR_pneg_depth);
+ fprintf(fp, "registered consumers: ");
if (p->MR_pneg_consumers == NULL) {
- fprintf(fp, "no consumers\n");
+ fprintf(fp, " none");
} else {
int n;
for (n = 1, l = p->MR_pneg_consumers; l != NULL;
l = l->MR_pneg_next_consumer, n++)
{
- fprintf(fp, "consumer %d: %s\n", n,
+ fprintf(fp, " <%d: %s>", n,
MR_subgoal_addr_name(l->MR_pneg_consumer_ptr));
}
}
+
+ fprintf(fp, "\n");
}
/***************************************************************************/
Index: runtime/mercury_stacks.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_stacks.h,v
retrieving revision 1.41
diff -u -b -r1.41 mercury_stacks.h
--- runtime/mercury_stacks.h 5 Nov 2003 08:51:20 -0000 1.41
+++ runtime/mercury_stacks.h 11 Mar 2004 05:56:38 -0000
@@ -468,6 +468,21 @@
/* DEFINITIONS FOR GENERATOR STACK FRAMES */
+/*
+** The generator stack has one entry for each call to a minimal model tabled
+** procedure that is (a) acting as the generator for its subgoal and (b) is
+** in the active state. The MR_gen_frame field points to the home nondet stack
+** frame of the generator, and the MR_gen_subgoal field points to the
+** generator's data structure.
+**
+** In systems such as XSB, each choice point has a flag saying whether it is
+** an active generator or not, and if yes, where its subgoal's tabling
+** information is stored. In Mercury, the equivalent test checks whether
+** the generator stack has an entry whose MR_gen_frame field matches the
+** address of the nondet stack frame. This approach that minimizes the
+** performance impact of minimal model evaluation on non-tabled procedures.
+*/
+
struct MR_GenStackFrameStruct {
MR_Word *MR_gen_frame;
MR_SubgoalPtr MR_gen_subgoal;
@@ -484,6 +499,35 @@
/* DEFINITIONS FOR CUT STACK FRAMES */
+/*
+** The cut stack has one entry for each commit goal currently active.
+** (A commit goal is an existential quantification that has a different
+** determinism than the goal being quantified over.) We use the cut stack
+** to prevent generators in the quantified being left active but incomplete
+** when the commit goal succeeds. We need to clean up any such generators
+** because otherwise, consumers will be depend on the generator to find all
+** the answers to the generator's subgoal, but the generator will never
+** compute any more answers, since it will never be backtracked into.
+** The MR_cut_generators field of a cut stack entry contains the list of
+** generators that are inside the corresponding commit and not inside
+** some nested commit.
+**
+** The MR_cut_frame field specifies the address of the nondet stack frame
+** (it should be a temp frame) used by the commit to get control on the
+** failure of the quantified goal. The MR_cut_gen_next field records
+** the value of MR_gen_next (the size of the generator stack) when the
+** commit goal started. When the quantified goal succeeds, the commit cuts
+** away the nondet stack frame at and above MR_cut_frame; we must also throw
+** away the generator stack entries that act as markers on the discarded nondet
+** stack frames. This means the generator stack entries at index
+** MR_cut_gen_next and above.
+**
+** The MR_cut_depth field records the depth of the cut stack entry in
+** the interleaving of the cut stack and pneg stack entries dictated by
+** the nesting of committed choice and possibly negated contexts currently
+** active.
+*/
+
typedef struct MR_CutGeneratorListNode *MR_CutGeneratorList;
struct MR_CutGeneratorListNode {
MR_SubgoalPtr MR_cut_generator_ptr;
@@ -507,6 +551,30 @@
MR_CutStackFrame *cut_block);
/* DEFINITIONS FOR PNEG STACK FRAMES */
+
+/*
+** The pneg stack has one entry for each possibly negated context currently
+** active. (Possibly negated contexts include the conditions of if-then-elses
+** as well negated goals.) The MR_pneg_consumers field of a pneg stack entry
+** records all the consumers that are inside the corresponding possibly negated
+** context and not inside any nested possibly negated context. When the goal
+** in the possibly negated context fails, we check whether any of these
+** consumers are waiting for more answers from their generator. If yes,
+** then the failure is an artifact of the tabling implementation, and
+** committing to the else branch of the if-then-else or continuing after the
+** negated goal would be incorrect, so we abort the program.
+**
+** The MR_pneg_frame field specifies the address of the nondet stack frame
+** (it should be a temp frame) used by the negation or if-then-else to get
+** control on the failure of the possibly negated goal. The MR_pneg_gen_next
+** field records the value of MR_gen_next (the size of the generator stack)
+** when the possibly negated goal started. Currently, neither field is used.
+**
+** The MR_pneg_depth field records the depth of the pneg stack entry in
+** the interleaving of the cut stack and pneg stack entries dictated by
+** the nesting of committed choice and possibly negated contexts currently
+** active.
+*/
struct MR_PNegConsumerListNodeStruct {
MR_Subgoal *MR_pneg_consumer_ptr;
Index: runtime/mercury_trace_base.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_trace_base.c,v
retrieving revision 1.55
diff -u -b -r1.55 mercury_trace_base.c
--- runtime/mercury_trace_base.c 10 Mar 2004 04:30:39 -0000 1.55
+++ runtime/mercury_trace_base.c 12 Mar 2004 01:58:20 -0000
@@ -466,7 +466,8 @@
}
void
-MR_turn_off_debug(MR_SavedDebugState *saved_state)
+MR_turn_off_debug(MR_SavedDebugState *saved_state,
+ MR_bool include_counter_vars)
{
int i;
@@ -479,6 +480,11 @@
saved_state->MR_sds_debugflags[i] = MR_debugflag[i];
MR_debugflag[i] = MR_FALSE;
}
+
+ saved_state->MR_sds_include_counter_vars = include_counter_vars;
+ saved_state->MR_sds_trace_call_seqno = MR_trace_call_seqno;
+ saved_state->MR_sds_trace_call_depth = MR_trace_call_depth;
+ saved_state->MR_sds_trace_event_number = MR_trace_event_number;
}
void
@@ -491,6 +497,12 @@
for (i = 0; i < MR_MAXFLAG ; i++) {
MR_debugflag[i] = saved_state->MR_sds_debugflags[i];
+ }
+
+ if (saved_state->MR_sds_include_counter_vars) {
+ MR_trace_call_seqno = saved_state->MR_sds_trace_call_seqno;
+ MR_trace_call_depth = saved_state->MR_sds_trace_call_depth;
+ MR_trace_event_number = saved_state->MR_sds_trace_event_number;
}
}
Index: runtime/mercury_trace_base.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_trace_base.h,v
retrieving revision 1.37
diff -u -b -r1.37 mercury_trace_base.h
--- runtime/mercury_trace_base.h 10 Mar 2004 04:30:39 -0000 1.37
+++ runtime/mercury_trace_base.h 12 Mar 2004 01:56:44 -0000
@@ -333,16 +333,23 @@
** MR_turn_off_debug saves the current values of the variables controlling
** debugging (execution tracing and diagnostics) in the structure provided by
** the caller, and then turns them off. MR_turn_debug_back_on restores the
-** saved values from the structure.
+** saved values from the structure. If include_counter_vars is set, they also
+** save and restore the global variables containing the event and sequence
+** number counters and the call depth.
*/
typedef struct {
MR_bool MR_sds_trace_enabled;
MR_bool MR_sds_io_tabling_enabled;
MR_bool MR_sds_debugflags[MR_MAXFLAG];
+ MR_bool MR_sds_include_counter_vars;
+ MR_Unsigned MR_sds_trace_call_seqno;
+ MR_Unsigned MR_sds_trace_call_depth;
+ MR_Unsigned MR_sds_trace_event_number;
} MR_SavedDebugState;
-extern void MR_turn_off_debug(MR_SavedDebugState *saved_state);
+extern void MR_turn_off_debug(MR_SavedDebugState *saved_state,
+ MR_bool include_counter_vars);
extern void MR_turn_debug_back_on(MR_SavedDebugState *saved_state);
/*
cvs diff: Diffing runtime/GETOPT
cvs diff: Diffing runtime/machdeps
cvs diff: Diffing samples
cvs diff: Diffing samples/c_interface
cvs diff: Diffing samples/c_interface/c_calls_mercury
cvs diff: Diffing samples/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/c_interface/mercury_calls_c
cvs diff: Diffing samples/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/diff
cvs diff: Diffing samples/muz
cvs diff: Diffing samples/rot13
cvs diff: Diffing samples/solutions
cvs diff: Diffing samples/tests
cvs diff: Diffing samples/tests/c_interface
cvs diff: Diffing samples/tests/c_interface/c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/tests/c_interface/mercury_calls_c
cvs diff: Diffing samples/tests/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/tests/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/tests/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/tests/diff
cvs diff: Diffing samples/tests/muz
cvs diff: Diffing samples/tests/rot13
cvs diff: Diffing samples/tests/solutions
cvs diff: Diffing samples/tests/toplevel
cvs diff: Diffing scripts
cvs diff: Diffing tests
cvs diff: Diffing tests/benchmarks
cvs diff: Diffing tests/debugger
Index: tests/debugger/mdb_command_test.inp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/mdb_command_test.inp,v
retrieving revision 1.25
diff -u -b -r1.25 mdb_command_test.inp
--- tests/debugger/mdb_command_test.inp 23 Oct 2003 02:02:41 -0000 1.25
+++ tests/debugger/mdb_command_test.inp 12 Mar 2004 05:12:46 -0000
@@ -51,9 +51,11 @@
gen_stack xyzzy xyzzy xyzzy xyzzy xyzzy
cut_stack xyzzy xyzzy xyzzy xyzzy xyzzy
pneg_stack xyzzy xyzzy xyzzy xyzzy xyzzy
+mm_stacks xyzzy xyzzy xyzzy xyzzy xyzzy
nondet_stack xyzzy xyzzy xyzzy xyzzy xyzzy
stack_regs xyzzy xyzzy xyzzy xyzzy xyzzy
all_regs xyzzy xyzzy xyzzy xyzzy xyzzy
+debug_vars xyzzy xyzzy xyzzy xyzzy xyzzy
proc_stats xyzzy xyzzy xyzzy xyzzy xyzzy
label_stats xyzzy xyzzy xyzzy xyzzy xyzzy
print_optionals xyzzy xyzzy xyzzy xyzzy xyzzy
cvs diff: Diffing tests/debugger/declarative
cvs diff: Diffing tests/dppd
cvs diff: Diffing tests/general
cvs diff: Diffing tests/general/accumulator
cvs diff: Diffing tests/general/string_format
cvs diff: Diffing tests/general/structure_reuse
cvs diff: Diffing tests/grade_subdirs
cvs diff: Diffing tests/hard_coded
cvs diff: Diffing tests/hard_coded/exceptions
cvs diff: Diffing tests/hard_coded/purity
cvs diff: Diffing tests/hard_coded/sub-modules
cvs diff: Diffing tests/hard_coded/typeclasses
cvs diff: Diffing tests/invalid
cvs diff: Diffing tests/invalid/purity
cvs diff: Diffing tests/misc_tests
cvs diff: Diffing tests/mmc_make
cvs diff: Diffing tests/mmc_make/lib
cvs diff: Diffing tests/recompilation
cvs diff: Diffing tests/tabling
Index: tests/tabling/Mmakefile
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/tabling/Mmakefile,v
retrieving revision 1.22
diff -u -b -r1.22 Mmakefile
--- tests/tabling/Mmakefile 12 Mar 2004 03:01:20 -0000 1.22
+++ tests/tabling/Mmakefile 12 Mar 2004 03:46:10 -0000
@@ -19,6 +19,9 @@
unused_args
NONDET_PROGS = \
+ combine \
+ completed_consumer_in_solutions \
+ consumer_in_commit \
coup \
coup_det_frame \
coup_no_commit \
@@ -29,19 +32,20 @@
seq \
seq2 \
seq3 \
+ seq4 \
sg \
tc_loop \
tc_minimal
# We don't yet pass the following minimal model tests. The reason is that
# they contain interactions between tabling and constructs that function
-# as commited or negated contexts.
+# as committed or negated contexts.
#
-# consumer_in_commit
# consumer_in_solutions
-# combine
+#
+# We don't yet pass the following minimal model tests for undetermined reasons.
+#
# coup2
-# seq4
# Tabling does not yet work in .rt grades
ifneq "$(findstring .gc,$(GRADE))" ""
Index: tests/tabling/combine.m
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/tabling/combine.m,v
retrieving revision 1.1
diff -u -b -r1.1 combine.m
--- tests/tabling/combine.m 30 Oct 2002 01:42:18 -0000 1.1
+++ tests/tabling/combine.m 11 Mar 2004 06:57:07 -0000
@@ -19,16 +19,20 @@
:- pred b(int::out) is multi.
:- pred c(int::out) is multi.
:- pred d(int::out) is nondet.
+:- pred e(int::out) is nondet.
:- pragma minimal_model(d/1).
+:- pragma minimal_model(e/1).
a(A) :-
d(B),
- d(C),
+ e(C),
A = B * 10 + C.
d(A) :-
- b(A),
+ b(A).
+
+e(A) :-
c(A).
b(3).
Index: tests/tabling/completed_consumer_in_solutions.exp
===================================================================
RCS file: tests/tabling/completed_consumer_in_solutions.exp
diff -N tests/tabling/completed_consumer_in_solutions.exp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/tabling/completed_consumer_in_solutions.exp 11 Mar 2004 07:24:43 -0000
@@ -0,0 +1,2 @@
+[1, 2, 3]
+[1, 2, 3]
Index: tests/tabling/completed_consumer_in_solutions.m
===================================================================
RCS file: tests/tabling/completed_consumer_in_solutions.m
diff -N tests/tabling/completed_consumer_in_solutions.m
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/tabling/completed_consumer_in_solutions.m 11 Mar 2004 07:28:11 -0000
@@ -0,0 +1,36 @@
+% This test case checks whether we get incorrect answers
+% when a consumer accesses a completed generator inside solutions.
+% The first call to solutions completes the generator for p,
+% the second call accesses the completed generator.
+
+:- module completed_consumer_in_solutions.
+
+:- interface.
+:- import_module io.
+
+:- pred main(io__state::di, io__state::uo) is det.
+
+:- implementation.
+
+:- import_module int, list.
+:- import_module std_util.
+
+main -->
+ { q(Solns1, Solns2) },
+ io__write(Solns1),
+ io__write_string("\n"),
+ io__write(Solns2),
+ io__write_string("\n").
+
+:- pred q(list(int)::out, list(int)::out) is det.
+
+q(L1, L2) :-
+ solutions(p, L1),
+ solutions(p, L2).
+
+:- pragma minimal_model(p/1).
+:- pred p(int::out) is nondet.
+
+p(1).
+p(2).
+p(3).
Index: tests/tabling/consumer_in_commit.exp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/tabling/consumer_in_commit.exp,v
retrieving revision 1.1
diff -u -b -r1.1 consumer_in_commit.exp
--- tests/tabling/consumer_in_commit.exp 20 Apr 1999 11:48:37 -0000 1.1
+++ tests/tabling/consumer_in_commit.exp 11 Mar 2004 07:05:27 -0000
@@ -1,2 +1,2 @@
-Mercury runtime: Sorry, not implemented:
-committing across a suspended call to a tabled predicate
+[1, 2, 3, 4]
+[1, 2, 3, 4, 5, 6, 7, 8, 9]
Index: tests/tabling/consumer_in_commit.m
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/tabling/consumer_in_commit.m,v
retrieving revision 1.1
diff -u -b -r1.1 consumer_in_commit.m
--- tests/tabling/consumer_in_commit.m 20 Apr 1999 11:48:38 -0000 1.1
+++ tests/tabling/consumer_in_commit.m 11 Mar 2004 07:03:53 -0000
@@ -14,8 +14,11 @@
:- import_module std_util.
main -->
- { solutions(p, Solns) },
- io__write(Solns),
+ { solutions(p, SolnsP) },
+ io__write(SolnsP),
+ io__write_string("\n"),
+ { solutions(q, SolnsQ) },
+ io__write(SolnsQ),
io__write_string("\n").
:- pred p(int).
Index: tests/tabling/seq2.m
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/tabling/seq2.m,v
retrieving revision 1.1
diff -u -b -r1.1 seq2.m
--- tests/tabling/seq2.m 11 Mar 2004 07:32:21 -0000 1.1
+++ tests/tabling/seq2.m 11 Mar 2004 07:43:43 -0000
@@ -20,20 +20,25 @@
io__write(Solns),
io__write_string("\n").
-:- pred p(int).
-:- mode p(out) is nondet.
+:- pred p(int::out) is nondet.
:- pragma minimal_model(p/1).
p(X) :-
(
p(Y),
- 0 =< Y, Y < 10,
- X is -Y - 1
+ between(0, Y, 9),
+ X = -Y - 1
;
p(Y),
- -10 < Y, Y =< 10,
- X is -Y + 1
+ between(-9, Y, 0),
+ X = -Y + 1
;
X = 0
).
+
+:- pred between(int::in, int::in, int::in) is semidet.
+
+between(A, B, C) :-
+ A =< B,
+ B =< C.
Index: tests/tabling/seq4.exp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/tabling/seq4.exp,v
retrieving revision 1.1
diff -u -b -r1.1 seq4.exp
--- tests/tabling/seq4.exp 12 Mar 2004 03:01:21 -0000 1.1
+++ tests/tabling/seq4.exp 12 Mar 2004 03:46:21 -0000
@@ -1,2 +1,2 @@
P = [1, 2, 3, 4, 6, 8, 9, 12, 16, 18]
-Q = [1, 2, 4, 6, 8, 12, 16, 16]
+Q = [1, 2, 4, 8, 16]
cvs diff: Diffing tests/term
cvs diff: Diffing tests/valid
cvs diff: Diffing tests/warnings
cvs diff: Diffing tools
cvs diff: Diffing trace
Index: trace/mercury_trace.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/trace/mercury_trace.c,v
retrieving revision 1.66
diff -u -b -r1.66 mercury_trace.c
--- trace/mercury_trace.c 10 Mar 2004 01:08:38 -0000 1.66
+++ trace/mercury_trace.c 11 Mar 2004 03:46:29 -0000
@@ -148,6 +148,12 @@
depth = (MR_Unsigned) MR_call_depth_framevar(MR_curfr);
}
+#if defined(MR_USE_MINIMAL_MODEL) && defined(MR_TABLE_DEBUG)
+ if ((MR_Trace_Port) layout->MR_sll_port == MR_PORT_CALL) {
+ MR_subgoal_debug_cur_proc = layout->MR_sll_entry;
+ }
+#endif
+
if (layout->MR_sll_hidden && !MR_trace_unhide_events) {
return NULL;
}
@@ -441,12 +447,6 @@
MR_compute_max_mr_num(event_info.MR_max_mr_num, layout);
/* This also saves the regs in MR_fake_regs. */
MR_copy_regs_to_saved_regs(event_info.MR_max_mr_num, saved_regs);
-
-#if defined(MR_USE_MINIMAL_MODEL) && defined(MR_TABLE_DEBUG)
- if (port == MR_PORT_CALL) {
- MR_subgoal_debug_cur_proc = layout->MR_sll_entry;
- }
-#endif
#ifdef MR_USE_EXTERNAL_DEBUGGER
if (MR_trace_handler == MR_TRACE_EXTERNAL) {
Index: trace/mercury_trace_external.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/trace/mercury_trace_external.c,v
retrieving revision 1.72
diff -u -b -r1.72 mercury_trace_external.c
--- trace/mercury_trace_external.c 26 Jan 2004 21:09:47 -0000 1.72
+++ trace/mercury_trace_external.c 11 Mar 2004 15:55:30 -0000
@@ -670,7 +670,7 @@
** MR_dump_nondet_stack() (as we do
** with MR_dump_stack_record_print()).
*/
- MR_dump_nondet_stack(stdout, 0,
+ MR_dump_nondet_stack(stdout, NULL, 0,
MR_saved_maxfr(saved_regs));
MR_send_message_to_socket("ok");
break;
Index: trace/mercury_trace_internal.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/trace/mercury_trace_internal.c,v
retrieving revision 1.168
diff -u -b -r1.168 mercury_trace_internal.c
--- trace/mercury_trace_internal.c 10 Mar 2004 04:31:06 -0000 1.168
+++ trace/mercury_trace_internal.c 12 Mar 2004 01:57:16 -0000
@@ -439,9 +439,11 @@
static MR_TraceCmdFunc MR_trace_cmd_gen_stack;
static MR_TraceCmdFunc MR_trace_cmd_cut_stack;
static MR_TraceCmdFunc MR_trace_cmd_pneg_stack;
+static MR_TraceCmdFunc MR_trace_cmd_mm_stacks;
static MR_TraceCmdFunc MR_trace_cmd_nondet_stack;
static MR_TraceCmdFunc MR_trace_cmd_stack_regs;
static MR_TraceCmdFunc MR_trace_cmd_all_regs;
+static MR_TraceCmdFunc MR_trace_cmd_debug_vars;
static MR_TraceCmdFunc MR_trace_cmd_table_io;
static MR_TraceCmdFunc MR_trace_cmd_proc_stats;
static MR_TraceCmdFunc MR_trace_cmd_label_stats;
@@ -659,7 +661,7 @@
** do any I/O tabling.
*/
- MR_turn_off_debug(&MR_saved_debug_state);
+ MR_turn_off_debug(&MR_saved_debug_state, MR_FALSE);
MR_trace_internal_ensure_init();
@@ -674,9 +676,9 @@
** to allow them to be modified by MR_trace_retry().
*/
+ event_details.MR_event_number = MR_trace_event_number;
event_details.MR_call_seqno = MR_trace_call_seqno;
event_details.MR_call_depth = MR_trace_call_depth;
- event_details.MR_event_number = MR_trace_event_number;
MR_trace_init_point_vars(event_info->MR_event_sll,
event_info->MR_saved_regs, event_info->MR_trace_port,
@@ -3463,6 +3465,39 @@
}
static MR_Next
+MR_trace_cmd_mm_stacks(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+ MR_Event_Info *event_info, MR_Event_Details *event_details,
+ MR_Code **jumpaddr)
+{
+#ifdef MR_USE_MINIMAL_MODEL
+
+ if (word_count == 1) {
+ MR_bool saved_tabledebug;
+
+ MR_trace_init_modules();
+ saved_tabledebug = MR_tabledebug;
+ MR_tabledebug = MR_TRUE;
+ MR_print_gen_stack(MR_mdb_out);
+ fprintf(MR_mdb_out, "\n");
+ MR_print_cut_stack(MR_mdb_out);
+ fprintf(MR_mdb_out, "\n");
+ MR_print_pneg_stack(MR_mdb_out);
+ MR_tabledebug = saved_tabledebug;
+ } else {
+ MR_trace_usage("developer", "pneg_stack");
+ }
+
+#else /* MR_USE_MINIMAL_MODEL */
+
+ fprintf(MR_mdb_out, "mdb: the `pneg_stack' command is available "
+ "only in minimal model grades.\n");
+
+#endif /* MR_USE_MINIMAL_MODEL */
+
+ return KEEP_INTERACTING;
+}
+
+static MR_Next
MR_trace_cmd_nondet_stack(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
MR_Event_Info *event_info, MR_Event_Details *event_details,
MR_Code **jumpaddr)
@@ -3503,12 +3538,12 @@
int saved_level;
saved_level = MR_trace_current_level();
- MR_dump_nondet_stack_from_layout(MR_mdb_out, limit,
+ MR_dump_nondet_stack_from_layout(MR_mdb_out, NULL, limit,
MR_saved_maxfr(saved_regs), layout,
MR_saved_sp(saved_regs), MR_saved_curfr(saved_regs));
MR_trace_set_level(saved_level, MR_print_optionals);
} else {
- MR_dump_nondet_stack(MR_mdb_out, limit,
+ MR_dump_nondet_stack(MR_mdb_out, NULL, limit,
MR_saved_maxfr(saved_regs));
}
}
@@ -3557,6 +3592,20 @@
}
static MR_Next
+MR_trace_cmd_debug_vars(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+ MR_Event_Info *event_info, MR_Event_Details *event_details,
+ MR_Code **jumpaddr)
+{
+ if (word_count == 1) {
+ MR_print_debug_vars(MR_mdb_out, event_details);
+ } else {
+ MR_trace_usage("developer", "debug_vars");
+ }
+
+ return KEEP_INTERACTING;
+}
+
+static MR_Next
MR_trace_cmd_table_io(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
MR_Event_Info *event_info, MR_Event_Details *event_details,
MR_Code **jumpaddr)
@@ -6927,11 +6976,15 @@
NULL, MR_trace_null_completer },
{ "developer", "pneg_stack", MR_trace_cmd_pneg_stack,
NULL, MR_trace_null_completer },
+ { "developer", "mm_stacks", MR_trace_cmd_mm_stacks,
+ NULL, MR_trace_null_completer },
{ "developer", "nondet_stack", MR_trace_cmd_nondet_stack,
MR_trace_stack_cmd_args, MR_trace_null_completer },
{ "developer", "stack_regs", MR_trace_cmd_stack_regs,
NULL, MR_trace_null_completer },
{ "developer", "all_regs", MR_trace_cmd_all_regs,
+ NULL, MR_trace_null_completer },
+ { "developer", "debug_vars", MR_trace_cmd_debug_vars,
NULL, MR_trace_null_completer },
{ "developer", "proc_stats", MR_trace_cmd_proc_stats,
NULL, MR_trace_filename_completer },
Index: trace/mercury_trace_util.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/trace/mercury_trace_util.c,v
retrieving revision 1.10
diff -u -b -r1.10 mercury_trace_util.c
--- trace/mercury_trace_util.c 21 Nov 2002 08:00:58 -0000 1.10
+++ trace/mercury_trace_util.c 11 Mar 2004 04:59:46 -0000
@@ -149,3 +149,20 @@
(long) MR_saved_reg(saved_regs, 5));
#endif
}
+
+void
+MR_print_debug_vars(FILE *fp, MR_Event_Details *event_details)
+{
+#ifndef MR_HIGHLEVEL_CODE
+ fprintf(fp, "from event details:\n");
+ fprintf(fp, "call event %d, call seq %d, depth %d\n",
+ event_details->MR_event_number,
+ event_details->MR_call_seqno,
+ event_details->MR_call_depth);
+ fprintf(fp, "from global vars:\n");
+ fprintf(fp, "call event %d, call seq %d, depth %d\n",
+ MR_trace_event_number,
+ MR_trace_call_seqno,
+ MR_trace_call_depth);
+#endif
+}
Index: trace/mercury_trace_util.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/trace/mercury_trace_util.h,v
retrieving revision 1.9
diff -u -b -r1.9 mercury_trace_util.h
--- trace/mercury_trace_util.h 15 Nov 2002 04:50:49 -0000 1.9
+++ trace/mercury_trace_util.h 11 Mar 2004 04:56:56 -0000
@@ -20,6 +20,7 @@
#include "mercury_types.h" /* for MR_Word etc */
#include "mercury_library_types.h" /* for MercuryFile */
#include <stdio.h> /* for FILE */
+#include "mercury_trace.h" /* for MR_Event_Details */
/*
** When using the heap pointer, we need to restore it, in case it is
@@ -90,5 +91,6 @@
extern void MR_print_tabling_regs(FILE *fp, MR_Word *saved_regs);
extern void MR_print_succip_reg(FILE *fp, MR_Word *saved_regs);
extern void MR_print_r_regs(FILE *fp, MR_Word *saved_regs);
+extern void MR_print_debug_vars(FILE *fp, MR_Event_Details *event_details);
#endif /* MERCURY_TRACE_UTIL_H */
cvs diff: Diffing util
cvs diff: Diffing vim
cvs diff: Diffing vim/after
cvs diff: Diffing vim/ftplugin
cvs diff: Diffing vim/syntax
--------------------------------------------------------------------------
mercury-reviews mailing list
post: mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------
More information about the reviews
mailing list