[m-dev.] Re: for review: minimal model tabling

Zoltan Somogyi zs at cs.mu.OZ.AU
Sun Mar 21 21:27:29 AEDT 1999


I made all the trivial changes Fergus requested. Here are my responses
to the nontrivial ones.

> A comment here explaining why we need to call MR_commit_mark()
> if --use-minimal-model is set would be helpful.

% If the code we are committing across starts but
% does not complete the evaluation of a tabled subgoal,
% the cut will remove the generator's choice point,
% so that the evaluation of the subgoal will never
% be completed. We handle such "dangling" generators
% by removing them from the subgoal trie of the
% tabled procedure. This requires knowing what
% tabled subgoals are started inside commits,
% which is why we wrap the goal being committed across
% inside MR_commit_{mark,cut}.

> > +	if (c->cutstack_zone != NULL) {
> > +		reset_redzone(c->cutstack_zone);
> > +	} else {
> > +		c->cutstack_zone = create_zone("cutstack", 0,
> > +			cutstack_size, next_offset(),
> > +			cutstack_zone_size, default_handler);
> > +	}
> > +	c->context_cut_sp = 0;
> 
> I think all that code should be inside "#ifdef MR_USE_MINIMAL_MODEL"
> or something like that.
> 
> Likewise for all the other new code added to mercury_context.h,
> mercury_context.c, mercury_memory.c, mercury_stacks.c,
> and mercury_tabling.c.  Also for the code in
> trace/mercury_trace_internal.h.

OK, since I see your point that the new stuff is not necessary
only if you use minimal model tabling. However, the price of this is that
people who don't enable -DMR_USE_MINIMAL_MODEL and --use-minimal-model
will not be warned by bootcheck if their changes break minimal model tabling,
since the test cases for minimal model will have to be disabled then.

> > +#include "mercury_regs.h"	/* must be before prototypes */
> 
> I don't understand the comment here.  Why must "mercury_regs.h"
> be #included before the function prototypes?

That is documented in mercury_regs.h itself.

> > +save_state(MR_SavedState *saved_state,
> > +	Word *generator_maxfr, Word *generator_sp,
> > +	const char *who, const char *what)
> 
> A comment explaining what this function is supposed to do
> would be helpful.

/*
** Save the current state of the Mercury abstract machine, so that the
** current computation may be suspended for a while, and restored later.
** The generator_{maxfr,sp} arguments give the points from which we need
** to copy the nondet and the det stacks. The parts of those stacks below
** the given points will not change between the suspension and the resumption
** of this state, or if they do, the stack segments in the saved state
** will be extended (via extend_consumer_stacks).
*/

> > +	table_copy_bytes(saved_state->generator_stack_block,
> > +		(char *) MR_gen_stack,
> > +		MR_gen_sp * sizeof(MR_GeneratorStackFrame));
> 
> If MR_gen_sp is a pointer, then the above code is buggy.
> If MR_gen_sp is actually an array index, rather than a pointer,
> then I think perhaps `MR_gen_sp' is a misleading name.

It is an index, but it still "points" to a stack slot.

I have renamed MR_gen_sp as MR_gen_next, and similarly for MR_cut_sp.

> Why the cast to `char *' here?

Because MR_gen_stack is a pointer to an array of generator stack frame
structures, not chars.

> > +	table_copy_bytes(saved_state->cut_stack_block,
> > +		(char *) MR_cut_stack,
> > +		(MR_cut_sp + 1) * sizeof(MR_CutStackFrame));
> 
> Why the cast to `char *' here?

Similar reason.

> > +static void
> > +extend_consumer_stacks(MR_Subgoal *leader, MR_Consumer *suspension)
> 
> A comment explaining what this function is supposed to do would be
> helpful.

/*
** The saved state of a consumer for a subgoal (say subgoal A) includes
** the stack segments between the tops of the stack at the time that
** A's generator was entered and the time that A's consumer was entered.
** 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.
*/

> > +static void
> > +make_subgoal_follow_leader(MR_Subgoal *this_follower, MR_Subgoal *leader)
> 
> Likewise here.

/*
** When we discover that two subgoals depend on each other, neither can be
** completed alone. We therefore pass responsibility for completing all
** the subgoals in an SCC to the subgoal whose nondet stack frame is
** lowest in the nondet stack.
*/

> > +/* virtual machine registers that we don't even try to make real ones */
> > +Integer			MR_gen_sp = 0;
> > +Integer			MR_cut_sp = 0;
> > +MR_GeneratorStackFrame	*MR_gen_stack = NULL;
> > +MR_CutStackFrame	*MR_cut_stack = NULL;
> 
> Hmm, shouldn't they go in the MR_Engine data structure?

They *are* in the MR_Engine data structure (specifically, the MR_Context part).
That is where they live in non-active threads. These global vars are for the
active thread. (maxfr, curfr, sp etc are not in MR_Engine either.) The thread
activation/suspension routines handle the rest.

> If tabling is not supposed to work in conjunction with multithreading,
> then that should be documented, with appropriate XXX comments,
> calls to fatal_error("sorry, not implemented: ...") and/or
> compile-time `#ifdef ... #error ... #endif' tests.

OK.

> > :- type ml_table == c_pointer.
> > :- type ml_subgoal_table_node == c_pointer.
> > :- type ml_answer_table_node == c_pointer.
> > :- type ml_answer_slot == c_pointer.
> > :- type ml_answer_block == c_pointer.
> 
> I think it would be clearer to write those as
> 
> 	:- type ml_subgoal_table_node == ml_table.
> 	:- type ml_answer_table_node == ml_table.
> 	:- type ml_answer_slot == ml_table.
> 	:- type ml_answer_block == ml_table.

OK.

> And is there any reason why the `type ml_table == c_pointer' equivalence
> is exported?

No. Only the fact that ml_* are equivalent to ml_table needs to be.

> > :- pragma c_code("
> > BEGIN_MODULE(private_builtin_module_XXX)
> 
> What's the XXX for?

The comment just above the stuff you quote explains that.

Zoltan.



More information about the developers mailing list