The debugger relied on the environment stack. To fix it:

- absmi.c now tells who called the debugger, besides who it was calling
- this is used to control whether we allow a goal to be debugged.
- I have creep to start creeping immediately, and signal_creep to tell
  the next meta-call to creep what it executes!
- The debugger uses CalledFromTheDebugger to know if it is within the
debugger. If so, we do not need to creep on leaving.
This commit is contained in:
Vítor Santos Costa 2008-08-30 02:39:36 +01:00
parent d636450512
commit 1226b58d8e
14 changed files with 266 additions and 175 deletions

View File

@ -549,6 +549,24 @@ static inline Term rbig(MP_INT *big)
#include "arith2.h" #include "arith2.h"
/*
I can creep if I am not a prolog builtin that has been called
by a prolog builtin,
exception: meta-calls
*/
static PredEntry *
creep_allowed(PredEntry *p, PredEntry *p0)
{
if (p0 == PredMetaCall)
return p0;
if (!p0->ModuleOfPred &&
(!p->ModuleOfPred
||
p->PredFlags & StandardPredFlag))
return NULL;
return p;
}
#ifdef COROUTINING #ifdef COROUTINING
/* /*
Imagine we are interrupting the execution, say, because we have a spy Imagine we are interrupting the execution, say, because we have a spy
@ -2348,9 +2366,9 @@ Yap_absmi(int inp)
ENDOp(); ENDOp();
/* commit_b_x Xi */ /* commit_b_x Xi */
Op(commit_b_x, x); Op(commit_b_x, xp);
BEGD(d0); BEGD(d0);
d0 = XREG(PREG->u.x.x); d0 = XREG(PREG->u.xp.x);
#ifdef COROUTINING #ifdef COROUTINING
CACHE_Y_AS_ENV(YREG); CACHE_Y_AS_ENV(YREG);
check_stack(NoStackCommitX, H); check_stack(NoStackCommitX, H);
@ -2358,7 +2376,7 @@ Yap_absmi(int inp)
do_commit_b_x: do_commit_b_x:
#endif #endif
/* skip a void call and a label */ /* skip a void call and a label */
PREG = NEXTOP(NEXTOP(NEXTOP(PREG, x),sbpp),l); PREG = NEXTOP(NEXTOP(NEXTOP(PREG, xp),sbpp),l);
{ {
choiceptr pt0; choiceptr pt0;
#if defined(SBA) && defined(FROZEN_STACKS) #if defined(SBA) && defined(FROZEN_STACKS)
@ -2395,16 +2413,16 @@ Yap_absmi(int inp)
ENDOp(); ENDOp();
/* commit_b_y Yi */ /* commit_b_y Yi */
Op(commit_b_y, y); Op(commit_b_y, yp);
BEGD(d0); BEGD(d0);
d0 = YREG[PREG->u.y.y]; d0 = YREG[PREG->u.yp.y];
#ifdef COROUTINING #ifdef COROUTINING
CACHE_Y_AS_ENV(YREG); CACHE_Y_AS_ENV(YREG);
check_stack(NoStackCommitY, H); check_stack(NoStackCommitY, H);
ENDCACHE_Y_AS_ENV(); ENDCACHE_Y_AS_ENV();
do_commit_b_y: do_commit_b_y:
#endif #endif
PREG = NEXTOP(NEXTOP(NEXTOP(PREG, y),sbpp),l); PREG = NEXTOP(NEXTOP(NEXTOP(PREG, yp),sbpp),l);
{ {
choiceptr pt0; choiceptr pt0;
#if defined(SBA) && defined(FROZEN_STACKS) #if defined(SBA) && defined(FROZEN_STACKS)
@ -2488,6 +2506,7 @@ Yap_absmi(int inp)
NoStackExecute: NoStackExecute:
SREG = (CELL *) PREG->u.pp.p; SREG = (CELL *) PREG->u.pp.p;
PP = PREG->u.pp.p0;
if (ActiveSignals & YAP_CDOVF_SIGNAL) { if (ActiveSignals & YAP_CDOVF_SIGNAL) {
ASP = YREG+E_CB; ASP = YREG+E_CB;
if (ASP > (CELL *)PROTECT_FROZEN_B(B)) if (ASP > (CELL *)PROTECT_FROZEN_B(B))
@ -2629,48 +2648,12 @@ Yap_absmi(int inp)
ENDBOp(); ENDBOp();
NoStackCall: NoStackCall:
PP = PREG->u.sbpp.p0;
/* on X86 machines S will not actually be holding the pointer to pred */ /* on X86 machines S will not actually be holding the pointer to pred */
if (ActiveSignals & YAP_CREEP_SIGNAL) { if (ActiveSignals & YAP_CREEP_SIGNAL) {
PredEntry *ap = PREG->u.sbpp.p; PredEntry *ap = PREG->u.sbpp.p;
if (ap->PredFlags & HiddenPredFlag) { SREG = (CELL *) ap;
CACHE_Y_AS_ENV(YREG); goto creepc;
CACHE_A1();
ENV = ENV_YREG;
/* Try to preserve the environment */
ENV_YREG = (CELL *) (((char *) YREG) + PREG->u.sbpp.s);
CPREG = NEXTOP(PREG, sbpp);
ALWAYS_LOOKAHEAD(ap->OpcodeOfPred);
PREG = ap->CodeOfPred;
/* for profiler */
save_pc();
check_depth(DEPTH, ap);
#ifdef FROZEN_STACKS
{
choiceptr top_b = PROTECT_FROZEN_B(B);
#ifdef SBA
if (ENV_YREG > (CELL *) top_b || ENV_YREG < H) ENV_YREG = (CELL *) top_b;
#else
if (ENV_YREG > (CELL *) top_b) ENV_YREG = (CELL *) top_b;
#endif
}
#else
if (ENV_YREG > (CELL *) B) {
ENV_YREG = (CELL *) B;
}
#endif /* FROZEN_STACKS */
WRITEBACK_Y_AS_ENV();
/* setup GB */
ENV_YREG[E_CB] = (CELL) B;
#ifdef YAPOR
SCH_check_requests();
#endif /* YAPOR */
ALWAYS_GONext();
ALWAYS_END_PREFETCH();
ENDCACHE_Y_AS_ENV();
} else {
SREG = (CELL *) ap;
goto creepc;
}
} }
SREG = (CELL *) PREG->u.sbpp.p; SREG = (CELL *) PREG->u.sbpp.p;
if (ActiveSignals & YAP_CDOVF_SIGNAL) { if (ActiveSignals & YAP_CDOVF_SIGNAL) {
@ -2742,6 +2725,7 @@ Yap_absmi(int inp)
/* This is easier: I know there is an environment so I cannot do allocate */ /* This is easier: I know there is an environment so I cannot do allocate */
NoStackCommitY: NoStackCommitY:
PP = PREG->u.yp.p0;
/* find something to fool S */ /* find something to fool S */
if (!ActiveSignals || ActiveSignals & YAP_CDOVF_SIGNAL) { if (!ActiveSignals || ActiveSignals & YAP_CDOVF_SIGNAL) {
goto do_commit_b_y; goto do_commit_b_y;
@ -2757,6 +2741,7 @@ Yap_absmi(int inp)
/* Problem: have I got an environment or not? */ /* Problem: have I got an environment or not? */
NoStackCommitX: NoStackCommitX:
PP = PREG->u.xp.p0;
/* find something to fool S */ /* find something to fool S */
if (!ActiveSignals || ActiveSignals & YAP_CDOVF_SIGNAL) { if (!ActiveSignals || ActiveSignals & YAP_CDOVF_SIGNAL) {
goto do_commit_b_x; goto do_commit_b_x;
@ -2787,6 +2772,7 @@ Yap_absmi(int inp)
/* Problem: have I got an environment or not? */ /* Problem: have I got an environment or not? */
NoStackFail: NoStackFail:
PP = NULL;
/* find something to fool S */ /* find something to fool S */
if (!ActiveSignals || ActiveSignals & YAP_CDOVF_SIGNAL) { if (!ActiveSignals || ActiveSignals & YAP_CDOVF_SIGNAL) {
goto fail; goto fail;
@ -2800,6 +2786,7 @@ Yap_absmi(int inp)
/* don't forget I cannot creep at ; */ /* don't forget I cannot creep at ; */
NoStackEither: NoStackEither:
PP = PREG->u.sblp.p0;
if (ActiveSignals & YAP_CREEP_SIGNAL) { if (ActiveSignals & YAP_CREEP_SIGNAL) {
goto either_notest; goto either_notest;
} }
@ -2876,8 +2863,9 @@ Yap_absmi(int inp)
goto creep; goto creep;
NoStackDExecute: NoStackDExecute:
PP = PREG->u.pp.p0;
if (ActiveSignals & YAP_CREEP_SIGNAL) { if (ActiveSignals & YAP_CREEP_SIGNAL) {
PredEntry *ap = PREG->u.p.p; PredEntry *ap = PREG->u.pp.p;
if (ap->PredFlags & HiddenPredFlag) { if (ap->PredFlags & HiddenPredFlag) {
CACHE_Y_AS_ENV(YREG); CACHE_Y_AS_ENV(YREG);
@ -3014,6 +3002,10 @@ Yap_absmi(int inp)
#ifdef SHADOW_S #ifdef SHADOW_S
S = SREG; S = SREG;
#endif #endif
/* tell whether we can creep or not, this is hard because we will
lose the info RSN
*/
PP = creep_allowed((PredEntry*)SREG,PP);
BEGD(d0); BEGD(d0);
d0 = ((PredEntry *)(SREG))->ArityOfPE; d0 = ((PredEntry *)(SREG))->ArityOfPE;
if (d0 == 0) { if (d0 == 0) {
@ -3061,9 +3053,9 @@ Yap_absmi(int inp)
H += 2; H += 2;
LOCK(SignalLock); LOCK(SignalLock);
CreepFlag = CalculateStackGap();
#ifdef COROUTINING #ifdef COROUTINING
if (ActiveSignals & YAP_WAKEUP_SIGNAL) { if (ActiveSignals & YAP_WAKEUP_SIGNAL) {
CreepFlag = CalculateStackGap();
ActiveSignals &= ~YAP_WAKEUP_SIGNAL; ActiveSignals &= ~YAP_WAKEUP_SIGNAL;
UNLOCK(SignalLock); UNLOCK(SignalLock);
ARG2 = Yap_ListOfWokenGoals(); ARG2 = Yap_ListOfWokenGoals();
@ -3072,13 +3064,16 @@ Yap_absmi(int inp)
Yap_UpdateTimedVar(WokenGoals, TermNil); Yap_UpdateTimedVar(WokenGoals, TermNil);
} else } else
#endif #endif
SREG = (CELL *) CreepCode; {
CreepFlag = CalculateStackGap();
SREG = (CELL *) CreepCode;
}
UNLOCK(SignalLock); UNLOCK(SignalLock);
PREG = ((PredEntry *)SREG)->CodeOfPred;
#ifdef LOW_LEVEL_TRACER #ifdef LOW_LEVEL_TRACER
if (Yap_do_low_level_trace) if (Yap_do_low_level_trace)
low_level_trace(enter_pred,(PredEntry *)(SREG),XREGS+1); low_level_trace(enter_pred,(PredEntry *)(SREG),XREGS+1);
#endif /* LOW_LEVEL_TRACE */ #endif /* LOW_LEVEL_TRACE */
PREG = ((PredEntry *)(SREG))->CodeOfPred;
/* for profiler */ /* for profiler */
save_pc(); save_pc();
CACHE_A1(); CACHE_A1();
@ -13428,6 +13423,7 @@ Yap_absmi(int inp)
ENDD(d0); ENDD(d0);
NoStackPExecute2: NoStackPExecute2:
PP = PredMetaCall;
SREG = (CELL *) pen; SREG = (CELL *) pen;
ASP = ENV_YREG; ASP = ENV_YREG;
/* setup GB */ /* setup GB */
@ -13624,6 +13620,7 @@ Yap_absmi(int inp)
ENDD(d0); ENDD(d0);
NoStackPExecute: NoStackPExecute:
PP = PredMetaCall;
SREG = (CELL *) pen; SREG = (CELL *) pen;
ASP = ENV_YREG; ASP = ENV_YREG;
/* setup GB */ /* setup GB */
@ -13891,6 +13888,7 @@ Yap_absmi(int inp)
ENDD(d0); ENDD(d0);
ENDP(pt0); ENDP(pt0);
NoStackPTExecute: NoStackPTExecute:
PP = NULL;
WRITEBACK_Y_AS_ENV(); WRITEBACK_Y_AS_ENV();
SREG = (CELL *) pen; SREG = (CELL *) pen;
ASP = ENV_YREG; ASP = ENV_YREG;

View File

@ -553,6 +553,33 @@ a_v(op_numbers opcodex, op_numbers opcodey, yamop *code_p, int pass_no, struct P
return code_p; return code_p;
} }
inline static yamop *
a_vp(op_numbers opcodex, op_numbers opcodey, yamop *code_p, int pass_no, struct PSEUDO *cpc, clause_info *clinfo)
{
Ventry *ve = (Ventry *) cpc->rnd1;
OPREG var_offset;
int is_y_var = (ve->KindOfVE == PermVar);
var_offset = Var_Ref(ve, is_y_var);
if (is_y_var) {
if (pass_no) {
code_p->opc = emit_op(opcodey);
code_p->u.yp.y = emit_yreg(var_offset);
code_p->u.yp.p0 = clinfo->CurrentPred;
}
GONEXT(yp);
}
else {
if (pass_no) {
code_p->opc = emit_op(opcodex);
code_p->u.xp.x = emit_xreg(var_offset);
code_p->u.xp.p0 = clinfo->CurrentPred;
}
GONEXT(xp);
}
return code_p;
}
inline static yamop * inline static yamop *
a_uv(Ventry *ve, op_numbers opcodex, op_numbers opcodexw, op_numbers opcodey, op_numbers opcodeyw, yamop *code_p, int pass_no) a_uv(Ventry *ve, op_numbers opcodex, op_numbers opcodexw, op_numbers opcodey, op_numbers opcodeyw, yamop *code_p, int pass_no)
{ {
@ -3099,7 +3126,7 @@ do_pass(int pass_no, yamop **entry_codep, int assembling, int *clause_has_blobsp
code_p = a_v(_save_b_x, _save_b_y, code_p, pass_no, cip->cpc); code_p = a_v(_save_b_x, _save_b_y, code_p, pass_no, cip->cpc);
break; break;
case commit_b_op: case commit_b_op:
code_p = a_v(_commit_b_x, _commit_b_y, code_p, pass_no, cip->cpc); code_p = a_vp(_commit_b_x, _commit_b_y, code_p, pass_no, cip->cpc, &clinfo);
break; break;
case save_pair_op: case save_pair_op:
code_p = a_uv((Ventry *) cip->cpc->rnd1, _save_pair_x, _save_pair_x_write, _save_pair_y, _save_pair_y_write, code_p, pass_no); code_p = a_uv((Ventry *) cip->cpc->rnd1, _save_pair_x, _save_pair_x_write, _save_pair_y, _save_pair_y_write, code_p, pass_no);

View File

@ -3987,9 +3987,12 @@ ClauseInfoForCode(yamop *codeptr, CODEADDR *startp, CODEADDR *endp) {
#endif /* TABLING_INNER_CUTS */ #endif /* TABLING_INNER_CUTS */
pc = NEXTOP(pc,e); pc = NEXTOP(pc,e);
break; break;
/* instructions type xp */
case _commit_b_x:
pc = NEXTOP(pc,xp);
break;
/* instructions type x */ /* instructions type x */
case _save_b_x: case _save_b_x:
case _commit_b_x:
case _get_list: case _get_list:
case _put_list: case _put_list:
case _write_x_var: case _write_x_var:
@ -4011,9 +4014,12 @@ ClauseInfoForCode(yamop *codeptr, CODEADDR *startp, CODEADDR *endp) {
case _p_cut_by_x: case _p_cut_by_x:
pc = NEXTOP(pc,xl); pc = NEXTOP(pc,xl);
break; break;
/* instructions type yp */
case _commit_b_y:
pc = NEXTOP(pc,yp);
break;
/* instructions type y */ /* instructions type y */
case _save_b_y: case _save_b_y:
case _commit_b_y:
case _write_y_var: case _write_y_var:
case _write_y_val: case _write_y_val:
case _write_y_loc: case _write_y_loc:

View File

@ -383,6 +383,7 @@ EnterCreepMode(Term t, Term mod) {
return do_execute(ARG1, mod); return do_execute(ARG1, mod);
} }
} }
PP = PredMetaCall;
PredCreep = RepPredProp(PredPropByFunc(FunctorCreep,1)); PredCreep = RepPredProp(PredPropByFunc(FunctorCreep,1));
if (mod) { if (mod) {
ARG1 = MkPairTerm(mod,t); ARG1 = MkPairTerm(mod,t);
@ -623,6 +624,11 @@ p_execute_clause(void)
} else { } else {
code = Yap_ClauseFromTerm(clt)->ClCode; code = Yap_ClauseFromTerm(clt)->ClCode;
} }
LOCK(SignalLock);
if (ActiveSignals & YAP_CREEP_SIGNAL) {
Yap_signal(YAP_CREEP_SIGNAL);
}
UNLOCK(SignalLock);
return CallPredicate(RepPredProp(pe), cut_cp, code); return CallPredicate(RepPredProp(pe), cut_cp, code);
} }
@ -745,6 +751,11 @@ p_execute_nonstop(void)
} }
/* N = arity; */ /* N = arity; */
/* call may not define new system predicates!! */ /* call may not define new system predicates!! */
LOCK(SignalLock);
if (ActiveSignals & YAP_CREEP_SIGNAL) {
Yap_signal(YAP_CREEP_SIGNAL);
}
UNLOCK(SignalLock);
if (RepPredProp(pe)->PredFlags & SpiedPredFlag) { if (RepPredProp(pe)->PredFlags & SpiedPredFlag) {
return CallPredicate(RepPredProp(pe), B, RepPredProp(pe)->cs.p_code.TrueCodeOfPred); return CallPredicate(RepPredProp(pe), B, RepPredProp(pe)->cs.p_code.TrueCodeOfPred);
} else if ((RepPredProp(pe)->PredFlags & (AsmPredFlag|CPredFlag)) && } else if ((RepPredProp(pe)->PredFlags & (AsmPredFlag|CPredFlag)) &&
@ -2040,6 +2051,12 @@ p_uncaught_throw(void)
return out; return out;
} }
static Int
p_creep_allowed(void)
{
return (PP != NULL);
}
void void
Yap_InitExecFs(void) Yap_InitExecFs(void)
{ {
@ -2089,6 +2106,7 @@ Yap_InitExecFs(void)
Yap_InitCPred("$clean_ifcp", 1, p_clean_ifcp, SafePredFlag|HiddenPredFlag); Yap_InitCPred("$clean_ifcp", 1, p_clean_ifcp, SafePredFlag|HiddenPredFlag);
Yap_InitCPred("qpack_clean_up_to_disjunction", 0, p_cut_up_to_next_disjunction, SafePredFlag); Yap_InitCPred("qpack_clean_up_to_disjunction", 0, p_cut_up_to_next_disjunction, SafePredFlag);
Yap_InitCPred("$jump_env_and_store_ball", 1, p_jump_env, HiddenPredFlag); Yap_InitCPred("$jump_env_and_store_ball", 1, p_jump_env, HiddenPredFlag);
Yap_InitCPred("$creep_allowed", 0, p_creep_allowed, HiddenPredFlag);
Yap_InitCPred("$generate_pred_info", 4, p_generate_pred_info, HiddenPredFlag); Yap_InitCPred("$generate_pred_info", 4, p_generate_pred_info, HiddenPredFlag);
Yap_InitCPred("$uncaught_throw", 0, p_uncaught_throw, HiddenPredFlag); Yap_InitCPred("$uncaught_throw", 0, p_uncaught_throw, HiddenPredFlag);
} }

View File

@ -503,7 +503,7 @@ p_creep(void)
} }
static Int static Int
p_delayed_creep(void) p_signal_creep(void)
{ {
Atom at; Atom at;
PredEntry *pred; PredEntry *pred;
@ -511,13 +511,43 @@ p_delayed_creep(void)
at = Yap_FullLookupAtom("$creep"); at = Yap_FullLookupAtom("$creep");
pred = RepPredProp(PredPropByFunc(Yap_MkFunctor(at, 1),0)); pred = RepPredProp(PredPropByFunc(Yap_MkFunctor(at, 1),0));
CreepCode = pred; CreepCode = pred;
do_signal(YAP_CREEP_SIGNAL);
LOCK(SignalLock); LOCK(SignalLock);
CreepFlag = CalculateStackGap(); ActiveSignals |= YAP_CREEP_SIGNAL;
UNLOCK(SignalLock); UNLOCK(SignalLock);
return TRUE; return TRUE;
} }
static Int
p_disable_creep(void)
{
LOCK(SignalLock);
if (ActiveSignals & YAP_CREEP_SIGNAL) {
ActiveSignals &= ~YAP_CREEP_SIGNAL;
if (!ActiveSignals)
CreepFlag = CalculateStackGap();
UNLOCK(SignalLock);
return TRUE;
}
UNLOCK(SignalLock);
return FALSE;
}
/* never fails */
static Int
p_disable_docreep(void)
{
LOCK(SignalLock);
if (ActiveSignals & YAP_CREEP_SIGNAL) {
ActiveSignals &= ~YAP_CREEP_SIGNAL;
if (!ActiveSignals)
CreepFlag = CalculateStackGap();
UNLOCK(SignalLock);
} else {
UNLOCK(SignalLock);
}
return TRUE;
}
static Int static Int
p_stop_creep(void) p_stop_creep(void)
{ {
@ -3925,8 +3955,10 @@ Yap_InitCPreds(void)
/* basic predicates for the prolog machine tracer */ /* basic predicates for the prolog machine tracer */
/* they are defined in analyst.c */ /* they are defined in analyst.c */
/* Basic predicates for the debugger */ /* Basic predicates for the debugger */
Yap_InitCPred("$creep", 0, p_creep, SafePredFlag|SyncPredFlag|HiddenPredFlag); Yap_InitCPred("$creep", 0, p_creep, SafePredFlag|HiddenPredFlag);
Yap_InitCPred("$late_creep", 0, p_delayed_creep, SafePredFlag|SyncPredFlag|HiddenPredFlag); Yap_InitCPred("$signal_creep", 0, p_signal_creep, SafePredFlag|HiddenPredFlag);
Yap_InitCPred("$disable_creep", 0, p_disable_creep, SafePredFlag|HiddenPredFlag);
Yap_InitCPred("$disable_docreep", 0, p_disable_docreep, SafePredFlag|HiddenPredFlag);
Yap_InitCPred("$do_not_creep", 0, p_stop_creep, SafePredFlag|SyncPredFlag|HiddenPredFlag); Yap_InitCPred("$do_not_creep", 0, p_stop_creep, SafePredFlag|SyncPredFlag|HiddenPredFlag);
#ifdef DEBUG #ifdef DEBUG
Yap_InitCPred("$debug", 1, p_debug, SafePredFlag|SyncPredFlag|HiddenPredFlag); Yap_InitCPred("$debug", 1, p_debug, SafePredFlag|SyncPredFlag|HiddenPredFlag);

View File

@ -164,8 +164,6 @@ low_level_trace(yap_low_level_port port, PredEntry *pred, CELL *args)
LOCK(Yap_heap_regs->low_level_trace_lock); LOCK(Yap_heap_regs->low_level_trace_lock);
sc = Yap_heap_regs; sc = Yap_heap_regs;
vsc_count++; vsc_count++;
if (vsc_count < 82500)
return;
#ifdef THREADS #ifdef THREADS
Yap_heap_regs->thread_handle[worker_id].thread_inst_count++; Yap_heap_regs->thread_handle[worker_id].thread_inst_count++;
#endif #endif

View File

@ -117,8 +117,8 @@ typedef struct
choiceptr B_FZ_; choiceptr B_FZ_;
tr_fr_ptr TR_FZ_; tr_fr_ptr TR_FZ_;
#endif /* SBA || TABLING */ #endif /* SBA || TABLING */
#if defined(YAPOR) || defined(THREADS)
struct pred_entry *PP_; struct pred_entry *PP_;
#if defined(YAPOR) || defined(THREADS)
/* recursive write-locks for PredEntry */ /* recursive write-locks for PredEntry */
yamop **PREG_ADDR_; yamop **PREG_ADDR_;
unsigned int worker_id_; unsigned int worker_id_;
@ -699,9 +699,9 @@ EXTERN inline void restore_B(void) {
#define B_FZ Yap_REGS.B_FZ_ #define B_FZ Yap_REGS.B_FZ_
#define TR_FZ Yap_REGS.TR_FZ_ #define TR_FZ Yap_REGS.TR_FZ_
#endif /* SBA || TABLING */ #endif /* SBA || TABLING */
#define PP (Yap_REGS.PP_)
#if defined(YAPOR) || defined(THREADS) #if defined(YAPOR) || defined(THREADS)
#define worker_id (Yap_REGS.worker_id_) #define worker_id (Yap_REGS.worker_id_)
#define PP (Yap_REGS.PP_)
#define PREG_ADDR (Yap_REGS.PREG_ADDR_) #define PREG_ADDR (Yap_REGS.PREG_ADDR_)
#ifdef SBA #ifdef SBA
#define BSEG Yap_REGS.BSEG_ #define BSEG Yap_REGS.BSEG_

View File

@ -38,8 +38,8 @@
OPCODE(cut_e ,e), OPCODE(cut_e ,e),
OPCODE(save_b_x ,x), OPCODE(save_b_x ,x),
OPCODE(save_b_y ,y), OPCODE(save_b_y ,y),
OPCODE(commit_b_x ,x), OPCODE(commit_b_x ,xp),
OPCODE(commit_b_y ,y), OPCODE(commit_b_y ,yp),
OPCODE(execute ,pp), OPCODE(execute ,pp),
OPCODE(dexecute ,pp), OPCODE(dexecute ,pp),
OPCODE(fcall ,sbpp), OPCODE(fcall ,sbpp),

View File

@ -522,7 +522,12 @@ typedef struct yami {
} x; } x;
struct { struct {
wamreg x; wamreg x;
CELL c; struct pred_entry *p0;
CELL next;
} xp;
struct {
wamreg x;
CELL c;
CELL next; CELL next;
} xc; } xc;
struct { struct {
@ -591,6 +596,11 @@ typedef struct yami {
yslot y; yslot y;
CELL next; CELL next;
} y; } y;
struct {
yslot y;
struct pred_entry *p0;
CELL next;
} yp;
struct { struct {
yslot y; yslot y;
struct yami *F; struct yami *F;

View File

@ -480,7 +480,6 @@ restore_opcodes(yamop *pc)
pc = NEXTOP(pc,sssllp); pc = NEXTOP(pc,sssllp);
break; break;
/* instructions type x */ /* instructions type x */
case _commit_b_x:
case _get_list: case _get_list:
case _put_list: case _put_list:
case _save_b_x: case _save_b_x:
@ -554,6 +553,12 @@ restore_opcodes(yamop *pc)
pc->u.xllll.l4 = PtoOpAdjust(pc->u.xllll.l4); pc->u.xllll.l4 = PtoOpAdjust(pc->u.xllll.l4);
pc = NEXTOP(pc,xllll); pc = NEXTOP(pc,xllll);
break; break;
/* instructions type xp */
case _commit_b_x:
pc->u.xp.x = XAdjust(pc->u.xp.x);
pc->u.xp.p0 = PtoPredAdjust(pc->u.xp.p0);
pc = NEXTOP(pc,xp);
break;
/* instructions type xx */ /* instructions type xx */
case _get_x_val: case _get_x_val:
case _get_x_var: case _get_x_var:
@ -627,7 +632,6 @@ restore_opcodes(yamop *pc)
pc = NEXTOP(pc,xy); pc = NEXTOP(pc,xy);
break; break;
/* instructions type y */ /* instructions type y */
case _commit_b_y:
case _save_b_y: case _save_b_y:
case _write_y_loc: case _write_y_loc:
case _write_y_val: case _write_y_val:
@ -650,6 +654,12 @@ restore_opcodes(yamop *pc)
pc->u.yl.F = PtoOpAdjust(pc->u.yl.F); pc->u.yl.F = PtoOpAdjust(pc->u.yl.F);
pc = NEXTOP(pc,yl); pc = NEXTOP(pc,yl);
break; break;
/* instructions type yp */
case _commit_b_y:
pc->u.yp.y = YAdjust(pc->u.yp.y);
pc->u.yp.p0 = PtoPredAdjust(pc->u.yp.p0);
pc = NEXTOP(pc,yp);
break;
/* instructions type yx */ /* instructions type yx */
case _get_y_val: case _get_y_val:
case _get_y_var: case _get_y_var:

View File

@ -1164,3 +1164,9 @@ throw(Ball) :-
nb_setval('$system_mode',off), nb_setval('$system_mode',off),
( nb_getval('$trace',on) -> '$creep' ; true). ( nb_getval('$trace',on) -> '$creep' ; true).
'$donotrace'(G) :-
'$disable_creep', !,
'$execute'(G),
'$creep'.
'$donotrace'(G) :-
'$execute'(G).

View File

@ -275,10 +275,10 @@ debugging :-
% $spy may be called from user code, so be careful. % $spy may be called from user code, so be careful.
'$spy'([Mod|G]) :- '$spy'([Mod|G]) :-
nb_getval('$debug',off), !, nb_getval('$debug',off), !,
'$execute_nonstop'(G,Mod). '$execute'(G,Mod).
'$spy'([Mod|G]) :- '$spy'([Mod|G]) :-
nb_getval('$system_mode',on), !, nb_getval('$system_mode',on), !,
'$execute_nonstop'(G,Mod). '$execute'(G,Mod).
'$spy'([Mod|G]) :- '$spy'([Mod|G]) :-
CP is '$last_choice_pt', CP is '$last_choice_pt',
'$do_spy'(G, Mod, CP, yes). '$do_spy'(G, Mod, CP, yes).
@ -289,79 +289,79 @@ debugging :-
'$do_spy'('$cut_by'(M), _, _, _) :- !, '$$cut_by'(M). '$do_spy'('$cut_by'(M), _, _, _) :- !, '$$cut_by'(M).
'$do_spy'(true, _, _, _) :- !. '$do_spy'(true, _, _, _) :- !.
%'$do_spy'(fail, _, _, _) :- !, fail. %'$do_spy'(fail, _, _, _) :- !, fail.
'$do_spy'(M:G, _, CP, InControl) :- !, '$do_spy'(M:G, _, CP, CalledFromDebugger) :- !,
'$do_spy'(G, M, CP, InControl). '$do_spy'(G, M, CP, CalledFromDebugger).
'$do_spy'((A,B), M, CP, InControl) :- !, '$do_spy'((A,B), M, CP, CalledFromDebugger) :- !,
'$do_spy'(A, M, CP, yes), '$do_spy'(A, M, CP, yes),
'$do_spy'(B, M, CP, InControl). '$do_spy'(B, M, CP, CalledFromDebugger).
'$do_spy'((T->A;B), M, CP, InControl) :- !, '$do_spy'((T->A;B), M, CP, CalledFromDebugger) :- !,
( '$do_spy'(T, M, CP, yes) -> '$do_spy'(A, M, CP, yes) ( '$do_spy'(T, M, CP, yes) -> '$do_spy'(A, M, CP, yes)
; ;
'$do_spy'(B, M, CP, InControl) '$do_spy'(B, M, CP, CalledFromDebugger)
). ).
'$do_spy'((T->A|B), M, CP, InControl) :- !, '$do_spy'((T->A|B), M, CP, CalledFromDebugger) :- !,
( '$do_spy'(T, M, CP, yes) -> '$do_spy'(A, M, CP, yes) ( '$do_spy'(T, M, CP, yes) -> '$do_spy'(A, M, CP, yes)
; ;
'$do_spy'(B, M, CP, InControl) '$do_spy'(B, M, CP, CalledFromDebugger)
). ).
'$do_spy'((T->A), M, CP, _) :- !, '$do_spy'((T->A), M, CP, _) :- !,
( '$do_spy'(T, M, CP, yes) -> '$do_spy'(A, M, CP, yes) ). ( '$do_spy'(T, M, CP, yes) -> '$do_spy'(A, M, CP, yes) ).
'$do_spy'((A;B), M, CP, InControl) :- !, '$do_spy'((A;B), M, CP, CalledFromDebugger) :- !,
( (
'$do_spy'(A, M, CP, yes) '$do_spy'(A, M, CP, yes)
; ;
'$do_spy'(B, M, CP, InControl) '$do_spy'(B, M, CP, CalledFromDebugger)
). ).
'$do_spy'((A|B), M, CP, InControl) :- !, '$do_spy'((A|B), M, CP, CalledFromDebugger) :- !,
( (
'$do_spy'(A, M, CP, yes) '$do_spy'(A, M, CP, yes)
; ;
'$do_spy'(B, M, CP, InControl) '$do_spy'(B, M, CP, CalledFromDebugger)
). ).
'$do_spy'((\+G), M, CP, InControl) :- !, '$do_spy'((\+G), M, CP, CalledFromDebugger) :- !,
\+ '$do_spy'(G, M, CP, InControl). \+ '$do_spy'(G, M, CP, CalledFromDebugger).
'$do_spy'((not(G)), M, CP, InControl) :- !, '$do_spy'((not(G)), M, CP, CalledFromDebugger) :- !,
\+ '$do_spy'(G, M, CP, InControl). \+ '$do_spy'(G, M, CP, CalledFromDebugger).
'$do_spy'(G, Module, _, InControl) :- '$do_spy'(G, Module, _, CalledFromDebugger) :-
nb_getval('$spy_gn',L), /* get goal no. */ nb_getval('$spy_gn',L), /* get goal no. */
L1 is L+1, /* bump it */ L1 is L+1, /* bump it */
nb_setval('$spy_gn',L1), /* and save it globaly */ nb_setval('$spy_gn',L1), /* and save it globaly */
b_getval('$spy_glist',History), /* get goal list */ b_getval('$spy_glist',History), /* get goal list */
b_setval('$spy_glist',[info(L,Module,G,_Retry,_Det)|History]), /* and update it */ b_setval('$spy_glist',[info(L,Module,G,_Retry,_Det)|History]), /* and update it */
'$loop_spy'(L, G, Module, InControl). /* set creep on */ '$loop_spy'(L, G, Module, CalledFromDebugger). /* set creep on */
% we are skipping, so we can just call the goal, % we are skipping, so we can just call the goal,
% while leaving the minimal structure in place. % while leaving the minimal structure in place.
'$loop_spy'(GoalNumber, G, Module, InControl) :- '$loop_spy'(GoalNumber, G, Module, CalledFromDebugger) :-
yap_hacks:current_choice_point(CP), yap_hacks:current_choice_point(CP),
'$system_catch'('$loop_spy2'(GoalNumber, G, Module, InControl, CP), '$system_catch'('$loop_spy2'(GoalNumber, G, Module, CalledFromDebugger, CP),
Module, Event, Module, Event,
'$loop_spy_event'(Event, GoalNumber, G, Module, InControl)). '$loop_spy_event'(Event, GoalNumber, G, Module, CalledFromDebugger)).
% handle weird things happening in the debugger. % handle weird things happening in the debugger.
'$loop_spy_event'('$retry_spy'(G0), GoalNumber, G, Module, InControl) :- '$loop_spy_event'('$retry_spy'(G0), GoalNumber, G, Module, CalledFromDebugger) :-
G0 >= GoalNumber, !, G0 >= GoalNumber, !,
'$loop_spy'(GoalNumber, G, Module, InControl). '$loop_spy'(GoalNumber, G, Module, CalledFromDebugger).
'$loop_spy_event'('$retry_spy'(GoalNumber), _, _, _, _) :- !, '$loop_spy_event'('$retry_spy'(GoalNumber), _, _, _, _) :- !,
throw('$retry_spy'(GoalNumber)). throw('$retry_spy'(GoalNumber)).
'$loop_spy_event'('$fail_spy'(G0), GoalNumber, G, Module, InControl) :- '$loop_spy_event'('$fail_spy'(G0), GoalNumber, G, Module, CalledFromDebugger) :-
G0 >= GoalNumber, !, G0 >= GoalNumber, !,
'$loop_fail'(GoalNumber, G, Module, InControl). '$loop_fail'(GoalNumber, G, Module, CalledFromDebugger).
'$loop_spy_event'('$fail_spy'(GoalNumber), _, _, _, _) :- !, '$loop_spy_event'('$fail_spy'(GoalNumber), _, _, _, _) :- !,
throw('$fail_spy'(GoalNumber)). throw('$fail_spy'(GoalNumber)).
'$loop_spy_event'('$done_spy'(G0,G), GoalNumber, G, _, _) :- '$loop_spy_event'('$done_spy'(G0,G), GoalNumber, G, _, CalledFromDebugger) :-
G0 >= GoalNumber, !, G0 >= GoalNumber, !,
'$continue_debugging'. '$continue_debugging'(CalledFromDebugger).
'$loop_spy_event'('$done_spy'(GoalNumber), _, _, _, _) :- !, '$loop_spy_event'('$done_spy'(GoalNumber), _, _, _, _) :- !,
throw('$done_spy'(GoalNumber)). throw('$done_spy'(GoalNumber)).
'$loop_spy_event'(abort, _, _, _, _) :- !, '$loop_spy_event'(abort, _, _, _, _) :- !,
throw('$abort'). throw('$abort').
'$loop_spy_event'(Event, GoalNumber, G, Module, InControl) :- '$loop_spy_event'(Event, GoalNumber, G, Module, CalledFromDebugger) :-
'$debug_error'(Event), '$debug_error'(Event),
'$system_catch'( '$system_catch'(
('$trace'(exception,G,Module,GoalNumber,_),fail), ('$trace'(exception,G,Module,GoalNumber,_),fail),
Module,NewEvent, Module,NewEvent,
'$loop_spy_event'(NewEvent, GoalNumber, G, Module, InControl)). '$loop_spy_event'(NewEvent, GoalNumber, G, Module, CalledFromDebugger)).
'$debug_error'(Event) :- '$debug_error'(Event) :-
@ -371,18 +371,19 @@ debugging :-
% just fail here, don't really need to call debugger, the user knows what he % just fail here, don't really need to call debugger, the user knows what he
% wants to do % wants to do
'$loop_fail'(_GoalNumber, _G, _Module, _InControl) :- '$loop_fail'(_GoalNumber, _G, _Module, _CalledFromDebugger) :-
'$continue_debugging', '$continue_debugging'(CalledFromDebugger),
fail. fail.
% if we are in % if we are in
'$loop_spy2'(GoalNumber, G, Module, InControl, CP) :- '$loop_spy2'(GoalNumber, G, Module, CalledFromDebugger, CP) :-
/* the following choice point is where the predicate is called */ /* the following choice point is where the predicate is called */
b_getval('$spy_glist',[info(_,_,_,Retry,Det)|_]), /* get goal list */ b_getval('$spy_glist',[info(_,_,_,Retry,Det)|_]), /* get goal list */
( (
/* call port */ /* call port */
'$enter_goal'(GoalNumber, G, Module), '$enter_goal'(GoalNumber, G, Module),
'$spycall'(G, Module, InControl, Retry), '$spycall'(G, Module, CalledFromDebugger, Retry),
'$disable_docreep',
( (
'$debugger_deterministic_goal'(G) -> '$debugger_deterministic_goal'(G) ->
Det=true Det=true
@ -402,23 +403,23 @@ debugging :-
; ;
true true
), ),
'$continue_debugging' '$continue_debugging'(CalledFromDebugger)
; ;
/* backtracking from exit */ /* backtracking from exit */
/* we get here when we want to redo a goal */ /* we get here when we want to redo a goal */
/* redo port */ /* redo port */
'$show_trace'(redo,G,Module,GoalNumber,_), /* inform user_error */ '$disable_docreep',
'$continue_debugging'(InControl,G,Module), '$show_trace'(redo,G,Module,GoalNumber,_), /* inform user_error */
fail /* to backtrack to spycalls */ '$continue_debugging'(CalledFromDebugger),
fail /* to backtrack to spycalls */
) )
; ;
'$show_trace'(fail,G,Module,GoalNumber,_), /* inform at fail port */ '$show_trace'(fail,G,Module,GoalNumber,_), /* inform at fail port */
'$continue_debugging', '$continue_debugging'(CalledFromDebugger),
/* fail port */ /* fail port */
fail fail
). ).
'$enter_goal'(GoalNumber, G, Module) :- '$enter_goal'(GoalNumber, G, Module) :-
'$zip'(GoalNumber, G, Module), !. '$zip'(GoalNumber, G, Module), !.
'$enter_goal'(GoalNumber, G, Module) :- '$enter_goal'(GoalNumber, G, Module) :-
@ -449,47 +450,49 @@ debugging :-
). ).
% %
'$spycall'(G, M, _, _) :- '$spycall'(G, M, _, _) :-
nb_getval('$debug_run',StopPoint), nb_getval('$debug_run',StopPoint),
StopPoint \= off, StopPoint \= off,
!, !,
'$execute_nonstop'(G, M). '$execute'(M:G).
'$spycall'(G, M, _, _) :- '$spycall'(G, M, _, _) :-
'$system_predicate'(G,M), '$system_predicate'(G,M),
\+ '$is_metapredicate'(G,M), \+ '$is_metapredicate'(G,M),
!, '$execute'(M:G).
'$execute_nonstop'(G, M). '$spycall'(G, M, _, _) :-
'$spycall'(G, M, InControl, _) :-
'$tabled_predicate'(G,M), '$tabled_predicate'(G,M),
!, !,
'$continue_debugging'(InControl, G, M), '$continue_debugging'(no, '$execute_nonstop'(G,M)).
'$execute_nonstop'(G, M). '$spycall'(G, M, CalledFromDebugger, InRedo) :-
'$spycall'(G, M, InControl, InRedo) :-
'$flags'(G,M,F,F), '$flags'(G,M,F,F),
F /\ 0x18402000 =\= 0, !, % dynamic procedure, logical semantics, user-C, or source F /\ 0x18402000 =\= 0, !, % dynamic procedure, logical semantics, user-C, or source
% use the interpreter % use the interpreter
CP is '$last_choice_pt', CP is '$last_choice_pt',
'$clause'(G, M, Cl), '$clause'(G, M, Cl),
( '$do_spy'(Cl, M, CP, InControl) ; InRedo = true ). ( '$do_spy'(Cl, M, CP, CalledFromDebugger) ; InRedo = true ).
'$spycall'(G, M, InControl, InRedo) :- '$spycall'(G, M, CalledFromDebugger, InRedo) :-
'$undefined'(G, M), !, '$undefined'(G, M), !,
( (
recorded('$import','$import'(NM,M,Goal,G,_,_),_) recorded('$import','$import'(NM,M,Goal,G,_,_),_)
-> ->
'$spycall'(Goal, NM, InControl, InRedo) '$spycall'(Goal, NM, CalledFromDebugger, InRedo)
; ;
'$enter_undefp', '$enter_undefp',
'$find_undefp_handler'(G,M,Goal,NM) '$find_undefp_handler'(G,M,Goal,NM)
-> ->
'$spycall'(Goal, NM, InControl, InRedo) '$spycall'(Goal, NM, CalledFromDebugger, InRedo)
). ).
'$spycall'(G, M, InControl, InRedo) :- '$spycall'(G, M, _, InRedo) :-
% I lost control here. % I lost control here.
CP is '$last_choice_pt', CP is '$last_choice_pt',
'$static_clause'(G,M,_,R), '$static_clause'(G,M,_,R),
'$continue_debugging'(InControl, G, M), (
( '$execute_clause'(G, M, R, CP) ; InRedo = true ). '$continue_debugging'(no, '$execute_clause'(G, M, R, CP))
;
InRedo = true
).
'$tabled_predicate'(G,M) :- '$tabled_predicate'(G,M) :-
'$flags'(G,M,F,F), '$flags'(G,M,F,F),
@ -656,20 +659,34 @@ debugging :-
'$ilgl'(C), '$ilgl'(C),
fail. fail.
% if we are in the interpreter, don't need to care about forcing a trace, do we? '$continue_debugging'(yes).
'$continue_debugging'(no,_,_) :- !. % do not need to debug!
'$continue_debugging'(_,G,M) :- '$continue_debugging'(no) :-
'$system_predicate'(G,M), !,
'$late_creep'.
'$continue_debugging'(_,_,_) :-
'nb_getval'('$debug_run',Zip),
(Zip == nodebug ; number(Zip) ; Zip = spy(_) ), !.
'$continue_debugging'(_,_,_) :-
'$continue_debugging'.
'$continue_debugging' :-
'$creep'. '$creep'.
% if we are in the interpreter, don't need to care about forcing a trace, do we?
'$continue_debugging'(yes,G) :- !,
'$execute_dgoal'(G).
% do not need to debug!
'$continue_debugging'(_,G) :-
'nb_getval'('$debug_run',Zip),
(Zip == nodebug ; number(Zip) ; Zip = spy(_) ), !,
'$execute_dgoal'(G).
'$continue_debugging'(_,G) :-
'$execute_creep_dgoal'(G).
'$execute_dgoal'('$execute_nonstop'(G,M)) :-
'$execute_nonstop'(G,M).
'$execute_dgoal'('$execute_clause'(G, M, R, CP)) :-
'$execute_clause'(G, M, R, CP).
'$execute_creep_dgoal'('$execute_nonstop'(G,M)) :-
'$signal_creep',
'$execute_nonstop'(G,M).
'$execute_creep_dgoal'('$execute_clause'(G, M, R, CP)) :-
'$signal_creep',
'$execute_clause'(G, M, R, CP).
'$show_ancestors'(HowMany) :- '$show_ancestors'(HowMany) :-
b_getval('$spy_glist',[_|History]), b_getval('$spy_glist',[_|History]),
( (

View File

@ -984,4 +984,4 @@ current_key(A,K) :-
'$notrace'(G, Mod) :- '$notrace'(G, Mod) :-
\+ '$undefined'(G, Mod), \+ '$undefined'(G, Mod),
call(Mod:G). '$donotrace'(Mod:G).

View File

@ -31,8 +31,13 @@
% if more signals alive, set creep flag % if more signals alive, set creep flag
'$continue_signals', '$continue_signals',
'$wake_up_goal'(G, LG). '$wake_up_goal'(G, LG).
% never creep on entering system mode!!!
'$do_signal'(sig_creep, [M|G]) :- '$do_signal'(sig_creep, [M|G]) :-
'$creep_allowed', !,
'$start_creep'([M|G]). '$start_creep'([M|G]).
'$do_signal'(sig_creep, [M|G]) :-
'$signal_creep',
'$execute_nonstop'(G,M).
'$do_signal'(sig_delay_creep, [M|G]) :- '$do_signal'(sig_delay_creep, [M|G]) :-
'$execute'(M:G), '$execute'(M:G),
'$creep'. '$creep'.
@ -97,18 +102,13 @@
'$creep'. '$creep'.
'$start_creep'([Mod|G]) :- '$start_creep'([Mod|G]) :-
'$hidden_predicate'(G,Mod), !, '$hidden_predicate'(G,Mod), !,
'$creep', '$execute_nonstop'(G,Mod),
'$execute_nonstop'(G,Mod). '$creep'.
'$start_creep'([Mod|G]) :-
'$system_predicate'(G, Mod),
'$protected_env', !,
'$creep',
'$execute_nonstop'(G,Mod).
% do not debug if we are zipping through. % do not debug if we are zipping through.
'$start_creep'([Mod|G]) :- '$start_creep'([Mod|G]) :-
nb_getval('$debug_zip',on), nb_getval('$debug_zip',on),
'$zip'(-1, G, Mod), !, '$zip'(-1, G, Mod), !,
'$creep', '$signal_creep',
'$execute_nonstop'(G,Mod). '$execute_nonstop'(G,Mod).
'$start_creep'([Mod|G]) :- '$start_creep'([Mod|G]) :-
CP is '$last_choice_pt', CP is '$last_choice_pt',
@ -171,35 +171,4 @@ read_sig :-
read_sig. read_sig.
'$protected_env' :-
yap_hacks:current_continuations([Env|Envs]),
yap_hacks:continuation(Env,_,Addr,_),
%'$envs'(Envs, Addr),
'$skim_envs'(Envs,Addr,Mod,Name,Arity),
\+ '$external_call_seen'(Mod,Name,Arity).
'$envs'([Env|Envs], Addr0) :-
yap_hacks:cp_to_predicate(Addr0,Mod0,Name0,Arity0,ClId),
format(user_error,'~a:~w/~w ~d~n',[Mod0,Name0,Arity0,ClId]),
yap_hacks:continuation(Env,_,Addr,_),
'$envs'(Envs, Addr).
'$envs'([], _) :- format(user_error,'*****done*****~n',[]).
'$skim_envs'([Env|Envs],Addr0,Mod,Name,Arity) :-
yap_hacks:cp_to_predicate(Addr0, Mod0, Name0, Arity0, _ClId),
'$debugger_env'(Mod0,Name0,Arity0), !,
yap_hacks:continuation(Env,_,Addr,_),
'$skim_envs'(Envs,Addr,Mod,Name,Arity).
'$skim_envs'(_,Addr,Mod,Name,Arity) :-
yap_hacks:cp_to_predicate(Addr, Mod, Name, Arity, _ClId).
'$debugger_env'(prolog,'$start_creep',1).
'$external_call_seen'(prolog,Name,Arity) :- !,
'$allowed'(Name,Arity).
'$external_call_seen'(_,_,_).
'$allowed'('$spycall',4).
'$allowed'('$query',2).