415 lines
9.9 KiB
C
415 lines
9.9 KiB
C
/*****************************************************************
|
||
* Failure *
|
||
*****************************************************************/
|
||
|
||
#ifdef INDENT_CODE
|
||
{
|
||
{
|
||
{
|
||
#endif /* INDENT_CODE */
|
||
|
||
/* trust_fail */
|
||
BOp(trust_fail, e);
|
||
{
|
||
while (POP_CHOICE_POINT(B->cp_b))
|
||
{
|
||
POP_EXECUTE();
|
||
}
|
||
}
|
||
#ifdef YAPOR
|
||
{
|
||
choiceptr cut_pt;
|
||
cut_pt = B->cp_b;
|
||
CUT_prune_to(cut_pt);
|
||
B = cut_pt;
|
||
}
|
||
#else
|
||
B = B->cp_b;
|
||
#endif /* YAPOR */
|
||
goto fail;
|
||
ENDBOp();
|
||
|
||
#ifdef YAPOR
|
||
shared_fail:
|
||
B = Get_LOCAL_top_cp();
|
||
SET_BB(PROTECT_FROZEN_B(B));
|
||
goto fail;
|
||
#endif /* YAPOR */
|
||
|
||
/* fail */
|
||
PBOp(op_fail, e);
|
||
|
||
if (PP) {
|
||
UNLOCK(PP->PELock);
|
||
PP = NULL;
|
||
}
|
||
#ifdef COROUTINING
|
||
CACHE_Y_AS_ENV(YREG);
|
||
check_stack(NoStackFail, HR);
|
||
ENDCACHE_Y_AS_ENV();
|
||
#endif
|
||
|
||
fail:
|
||
{
|
||
register tr_fr_ptr pt0 = TR;
|
||
#if defined(YAPOR) || defined(THREADS)
|
||
if (PP) {
|
||
UNLOCK(PP->PELock);
|
||
PP = NULL;
|
||
}
|
||
#endif
|
||
PREG = B->cp_ap;
|
||
save_pc();
|
||
CACHE_TR(B->cp_tr);
|
||
PREFETCH_OP(PREG);
|
||
failloop:
|
||
if (pt0 == S_TR) {
|
||
SP = SP0;
|
||
#ifdef LOW_LEVEL_TRACER
|
||
if (Yap_do_low_level_trace) {
|
||
int go_on = true;
|
||
yamop *ipc = PREG;
|
||
|
||
while (go_on) {
|
||
op_numbers opnum = Yap_op_from_opcode(ipc->opc);
|
||
|
||
go_on = false;
|
||
switch (opnum) {
|
||
#ifdef TABLING
|
||
case _table_load_answer:
|
||
low_level_trace(retry_table_loader, LOAD_CP(B)->cp_pred_entry, NULL);
|
||
break;
|
||
case _table_try_answer:
|
||
case _table_retry_me:
|
||
case _table_trust_me:
|
||
case _table_retry:
|
||
case _table_trust:
|
||
case _table_completion:
|
||
#ifdef THREADS_CONSUMER_SHARING
|
||
case _table_answer_resolution_completion:
|
||
#endif /* THREADS_CONSUMER_SHARING */
|
||
#ifdef DETERMINISTIC_TABLING
|
||
if (IS_DET_GEN_CP(B))
|
||
low_level_trace(retry_table_generator, DET_GEN_CP(B)->cp_pred_entry, NULL);
|
||
else
|
||
#endif /* DETERMINISTIC_TABLING */
|
||
low_level_trace(retry_table_generator, GEN_CP(B)->cp_pred_entry, (CELL *)(GEN_CP(B) + 1));
|
||
break;
|
||
case _table_answer_resolution:
|
||
low_level_trace(retry_table_consumer, CONS_CP(B)->cp_pred_entry, NULL);
|
||
break;
|
||
case _trie_trust_var:
|
||
case _trie_retry_var:
|
||
case _trie_trust_var_in_pair:
|
||
case _trie_retry_var_in_pair:
|
||
case _trie_trust_val:
|
||
case _trie_retry_val:
|
||
case _trie_trust_val_in_pair:
|
||
case _trie_retry_val_in_pair:
|
||
case _trie_trust_atom:
|
||
case _trie_retry_atom:
|
||
case _trie_trust_atom_in_pair:
|
||
case _trie_retry_atom_in_pair:
|
||
case _trie_trust_null:
|
||
case _trie_retry_null:
|
||
case _trie_trust_null_in_pair:
|
||
case _trie_retry_null_in_pair:
|
||
case _trie_trust_pair:
|
||
case _trie_retry_pair:
|
||
case _trie_trust_appl:
|
||
case _trie_retry_appl:
|
||
case _trie_trust_appl_in_pair:
|
||
case _trie_retry_appl_in_pair:
|
||
case _trie_trust_extension:
|
||
case _trie_retry_extension:
|
||
case _trie_trust_double:
|
||
case _trie_retry_double:
|
||
case _trie_trust_longint:
|
||
case _trie_retry_longint:
|
||
case _trie_trust_gterm:
|
||
case _trie_retry_gterm:
|
||
low_level_trace(retry_table_loader, UndefCode, NULL);
|
||
break;
|
||
#endif /* TABLING */
|
||
case _or_else:
|
||
case _or_last:
|
||
low_level_trace(retry_or, NULL, NULL);
|
||
break;
|
||
case _retry2:
|
||
case _retry3:
|
||
case _retry4:
|
||
ipc = NEXTOP(ipc,l);
|
||
go_on = true;
|
||
break;
|
||
case _jump:
|
||
ipc = ipc->y_u.l.l;
|
||
go_on = true;
|
||
break;
|
||
case _retry_c:
|
||
case _retry_userc:
|
||
low_level_trace(retry_pred, ipc->y_u.OtapFs.p, B->cp_args);
|
||
break;
|
||
case _retry_profiled:
|
||
case _count_retry:
|
||
ipc = NEXTOP(ipc,p);
|
||
go_on = true;
|
||
break;
|
||
case _retry_me:
|
||
case _trust_me:
|
||
case _count_retry_me:
|
||
case _count_trust_me:
|
||
case _profiled_retry_me:
|
||
case _profiled_trust_me:
|
||
case _retry_and_mark:
|
||
case _profiled_retry_and_mark:
|
||
case _retry:
|
||
case _trust:
|
||
low_level_trace(retry_pred, ipc->y_u.Otapl.p, B->cp_args);
|
||
break;
|
||
case _try_logical:
|
||
case _retry_logical:
|
||
case _profiled_retry_logical:
|
||
case _count_retry_logical:
|
||
case _trust_logical:
|
||
case _profiled_trust_logical:
|
||
case _count_trust_logical:
|
||
low_level_trace(retry_pred, ipc->y_u.OtILl.d->ClPred, B->cp_args);
|
||
break;
|
||
case _Nstop:
|
||
case _Ystop:
|
||
low_level_trace(retry_pred, NULL, B->cp_args);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
#endif /* LOW_LEVEL_TRACER */
|
||
#ifdef FROZEN_STACKS
|
||
#ifdef YAPOR_SBA
|
||
if (pt0 < TR_FZ || pt0 > (ADDR)CurrentTrailTop+MinTrailGap)
|
||
#else
|
||
if (pt0 < TR_FZ)
|
||
#endif /* YAPOR_SBA */
|
||
{
|
||
TR = TR_FZ;
|
||
TRAIL_LINK(pt0);
|
||
} else
|
||
#endif /* FROZEN_STACKS */
|
||
RESTORE_TR();
|
||
GONext();
|
||
}
|
||
BEGD(d1);
|
||
d1 = TrailTerm(pt0-1);
|
||
pt0--;
|
||
if (IsVarTerm(d1)) {
|
||
#if defined(YAPOR_SBA) && defined(YAPOR)
|
||
/* clean up the trail when we backtrack */
|
||
if (Unsigned((Int)(d1)-(Int)(H_FZ)) >
|
||
Unsigned((Int)(B_FZ)-(Int)(H_FZ))) {
|
||
RESET_VARIABLE(STACK_TO_SBA(d1));
|
||
} else
|
||
#endif
|
||
/* normal variable */
|
||
RESET_VARIABLE(d1);
|
||
goto failloop;
|
||
}
|
||
/* pointer to code space */
|
||
/* or updatable variable */
|
||
#if defined(TERM_EXTENSIONS) || defined(FROZEN_STACKS) || defined(MULTI_ASSIGNMENT_VARIABLES)
|
||
if (IsPairTerm(d1))
|
||
#endif /* TERM_EXTENSIONS || FROZEN_STACKS || MULTI_ASSIGNMENT_VARIABLES */
|
||
{
|
||
register CELL flags;
|
||
CELL *pt1 = RepPair(d1);
|
||
#ifdef LIMIT_TABLING
|
||
if ((ADDR) pt1 == LOCAL_TrailBase) {
|
||
sg_fr_ptr sg_fr = (sg_fr_ptr) TrailVal(pt0);
|
||
TrailTerm(pt0) = AbsPair((CELL *)(pt0 - 1));
|
||
SgFr_state(sg_fr)--; /* complete_in_use --> complete : compiled_in_use --> compiled */
|
||
insert_into_global_sg_fr_list(sg_fr);
|
||
goto failloop;
|
||
}
|
||
#endif /* LIMIT_TABLING */
|
||
#ifdef FROZEN_STACKS /* TRAIL */
|
||
/* avoid frozen segments */
|
||
if (
|
||
#ifdef YAPOR_SBA
|
||
(ADDR) pt1 >= HeapTop
|
||
#else
|
||
IN_BETWEEN(LOCAL_TrailBase, pt1, (ADDR)CurrentTrailTop+MinTrailGap)
|
||
#endif /* YAPOR_SBA */
|
||
)
|
||
{
|
||
pt0 = (tr_fr_ptr) pt1;
|
||
goto failloop;
|
||
} else
|
||
#endif /* FROZEN_STACKS */
|
||
if (IN_BETWEEN(H0,pt1,HR)) {
|
||
if (IsAttVar(pt1)) {
|
||
goto failloop;
|
||
} else if (*pt1 == (CELL)FunctorBigInt) {
|
||
Yap_CleanOpaqueVariable(pt1);
|
||
goto failloop;
|
||
}
|
||
}
|
||
#ifdef FROZEN_STACKS /* TRAIL */
|
||
/* don't reset frozen variables */
|
||
if (pt0 < TR_FZ)
|
||
goto failloop;
|
||
#endif
|
||
flags = *pt1;
|
||
#if MULTIPLE_STACKS
|
||
if (FlagOn(DBClMask, flags)) {
|
||
DBRef dbr = DBStructFlagsToDBStruct(pt1);
|
||
int erase;
|
||
|
||
LOCK(dbr->lock);
|
||
DEC_DBREF_COUNT(dbr);
|
||
erase = (dbr->Flags & ErasedMask) && (dbr->ref_count == 0);
|
||
UNLOCK(dbr->lock);
|
||
if (erase) {
|
||
saveregs();
|
||
Yap_ErDBE(dbr);
|
||
setregs();
|
||
}
|
||
} else {
|
||
if (flags & LogUpdMask) {
|
||
if (flags & IndexMask) {
|
||
LogUpdIndex *cl = ClauseFlagsToLogUpdIndex(pt1);
|
||
int erase;
|
||
#if PARALLEL_YAP
|
||
PredEntry *ap = cl->ClPred;
|
||
#endif
|
||
|
||
PELOCK(8,ap);
|
||
DEC_CLREF_COUNT(cl);
|
||
erase = (cl->ClFlags & ErasedMask) && !(cl->ClRefCount);
|
||
if (erase) {
|
||
saveregs();
|
||
/* at this point,
|
||
we are the only ones accessing the clause,
|
||
hence we don't need to have a lock it */
|
||
Yap_ErLogUpdIndex(cl);
|
||
setregs();
|
||
} else if (cl->ClFlags & DirtyMask) {
|
||
saveregs();
|
||
/* at this point,
|
||
we are the only ones accessing the clause,
|
||
hence we don't need to have a lock it */
|
||
Yap_CleanUpIndex(cl);
|
||
setregs();
|
||
}
|
||
UNLOCK(ap->PELock);
|
||
} else {
|
||
LogUpdClause *cl = ClauseFlagsToLogUpdClause(pt1);
|
||
int erase;
|
||
#if PARALLEL_YAP
|
||
PredEntry *ap = cl->ClPred;
|
||
#endif
|
||
/* BB support */
|
||
if (ap) {
|
||
|
||
PELOCK(9,ap);
|
||
DEC_CLREF_COUNT(cl);
|
||
erase = (cl->ClFlags & ErasedMask) && !(cl->ClRefCount);
|
||
if (erase) {
|
||
saveregs();
|
||
/* at this point,
|
||
we are the only ones accessing the clause,
|
||
hence we don't need to have a lock it */
|
||
Yap_ErLogUpdCl(cl);
|
||
setregs();
|
||
}
|
||
UNLOCK(ap->PELock);
|
||
}
|
||
}
|
||
} else {
|
||
DynamicClause *cl = ClauseFlagsToDynamicClause(pt1);
|
||
int erase;
|
||
|
||
LOCK(cl->ClLock);
|
||
DEC_CLREF_COUNT(cl);
|
||
erase = (cl->ClFlags & ErasedMask) && !(cl->ClRefCount);
|
||
UNLOCK(cl->ClLock);
|
||
if (erase) {
|
||
saveregs();
|
||
/* at this point,
|
||
we are the only ones accessing the clause,
|
||
hence we don't need to have a lock it */
|
||
Yap_ErCl(cl);
|
||
setregs();
|
||
}
|
||
}
|
||
}
|
||
#else
|
||
ResetFlag(InUseMask, flags);
|
||
*pt1 = flags;
|
||
if (FlagOn((ErasedMask|DirtyMask), flags)) {
|
||
if (FlagOn(DBClMask, flags)) {
|
||
saveregs();
|
||
Yap_ErDBE(DBStructFlagsToDBStruct(pt1));
|
||
setregs();
|
||
} else {
|
||
saveregs();
|
||
if (flags & LogUpdMask) {
|
||
if (flags & IndexMask) {
|
||
if (FlagOn(ErasedMask, flags)) {
|
||
Yap_ErLogUpdIndex(ClauseFlagsToLogUpdIndex(pt1));
|
||
} else {
|
||
Yap_CleanUpIndex(ClauseFlagsToLogUpdIndex(pt1));
|
||
}
|
||
} else {
|
||
Yap_ErLogUpdCl(ClauseFlagsToLogUpdClause(pt1));
|
||
}
|
||
} else {
|
||
Yap_ErCl(ClauseFlagsToDynamicClause(pt1));
|
||
}
|
||
setregs();
|
||
}
|
||
}
|
||
#endif
|
||
goto failloop;
|
||
}
|
||
#ifdef MULTI_ASSIGNMENT_VARIABLES
|
||
else /* if (IsApplTerm(d1)) */ {
|
||
CELL *pt = RepAppl(d1);
|
||
/* AbsAppl means */
|
||
/* multi-assignment variable */
|
||
/* so the next cell is the old value */
|
||
#ifdef FROZEN_STACKS
|
||
--pt0;
|
||
pt[0] = TrailVal(pt0);
|
||
#else
|
||
pt[0] = TrailTerm(pt0-1);
|
||
pt0 -= 2;
|
||
#endif /* FROZEN_STACKS */
|
||
goto failloop;
|
||
}
|
||
#endif
|
||
ENDD(d1);
|
||
ENDCACHE_TR();
|
||
}
|
||
|
||
#ifdef COROUTINING
|
||
NoStackFail:
|
||
BEGD(d0);
|
||
#ifdef SHADOW_S
|
||
Yap_REGS.S_ = SREG;
|
||
#endif
|
||
saveregs();
|
||
d0 = interrupt_fail( PASS_REGS1 );
|
||
setregs();
|
||
#ifdef SHADOW_S
|
||
SREG = Yap_REGS.S_;
|
||
#endif
|
||
if (!d0) FAIL();
|
||
JMPNext();
|
||
ENDD(d0);
|
||
|
||
#endif /* COROUTINING */
|
||
ENDPBOp();
|
||
|
||
|
||
|