first cut at call counter.

git-svn-id: https://yap.svn.sf.net/svnroot/yap/trunk@580 b08c6af1-5177-4d33-ba66-4b1c6b8b522a
This commit is contained in:
vsc
2002-09-03 14:28:09 +00:00
parent 89a188d5d7
commit 94e9529128
20 changed files with 459 additions and 16 deletions

123
C/absmi.c
View File

@@ -459,7 +459,7 @@ absmi(int inp)
GONext();
ENDOp();
/* profiled_enter_me Label,NArgs */
/* profiled_retry Label,NArgs */
Op(retry_profiled, l);
LOCK(((PredEntry *)(PREG->u.l.l))->StatisticsForPred.lock);
((PredEntry *)(PREG->u.l.l))->StatisticsForPred.NOfRetries++;
@@ -523,6 +523,111 @@ absmi(int inp)
GONext();
ENDOp();
/*****************************************************************
* Call count instructions *
*****************************************************************/
/* count_enter_me Label,NArgs */
Op(count_call, l);
ReductionsCounter--;
if (ReductionsCounter == 0 && ReductionsCounterOn) {
Error(CALL_COUNTER_UNDERFLOW,TermNil,"");
JMPNext();
}
PredEntriesCounter--;
if (PredEntriesCounter == 0 && PredEntriesCounterOn) {
Error(PRED_ENTRY_COUNTER_UNDERFLOW,TermNil,"");
JMPNext();
}
PREG = NEXTOP(PREG, l);
GONext();
ENDOp();
/* count_retry Label,NArgs */
Op(count_retry, l);
RetriesCounter--;
if (RetriesCounter == 0 && RetriesCounterOn) {
Error(RETRY_COUNTER_UNDERFLOW,TermNil,"");
JMPNext();
}
PredEntriesCounter--;
if (PredEntriesCounter == 0 && PredEntriesCounterOn) {
Error(PRED_ENTRY_COUNTER_UNDERFLOW,TermNil,"");
JMPNext();
}
PREG = NEXTOP(PREG, l);
GONext();
ENDOp();
/* count_retry_me Label,NArgs */
Op(count_retry_me, ld);
CACHE_Y(B);
/* After retry, cut should be pointing at the parent
* choicepoint for the current B */
RetriesCounter--;
if (RetriesCounter == 0 && RetriesCounterOn) {
Error(RETRY_COUNTER_UNDERFLOW,TermNil,"");
JMPNext();
}
PredEntriesCounter--;
if (PredEntriesCounter == 0 && PredEntriesCounterOn) {
Error(PRED_ENTRY_COUNTER_UNDERFLOW,TermNil,"");
JMPNext();
}
restore_yaam_regs(PREG->u.ld.d);
restore_args(PREG->u.ld.s);
#ifdef FROZEN_STACKS
S_Y = (CELL *)PROTECT_FROZEN_B(B_Y);
set_cut(S_Y, B->cp_b);
#else
set_cut(S_Y, B_Y->cp_b);
#endif /* FROZEN_STACKS */
SET_BB(B_Y);
ENDCACHE_Y();
PREG = NEXTOP(PREG, ld);
GONext();
ENDOp();
/* count_trust_me UnusedLabel,NArgs */
Op(count_trust_me, ld);
CACHE_Y(B);
#ifdef YAPOR
if (SCH_top_shared_cp(B)) {
SCH_last_alternative(PREG, B_Y);
restore_args(PREG->u.ld.s);
#ifdef FROZEN_STACKS
B_Y = PROTECT_FROZEN_B(B_Y);
#endif /* FROZEN_STACKS */
set_cut(S_Y, B->cp_b);
}
else
#endif /* YAPOR */
{
pop_yaam_regs();
pop_args(PREG->u.ld.s);
/* After trust, cut should be pointing at the new top
* choicepoint */
#ifdef FROZEN_STACKS
S_Y = (CELL *)PROTECT_FROZEN_B(B_Y);
#endif /* FROZEN_STACKS */
set_cut(S_Y, B);
}
SET_BB(B_Y);
ENDCACHE_Y();
RetriesCounter--;
if (RetriesCounter == 0) {
Error(RETRY_COUNTER_UNDERFLOW,TermNil,"");
JMPNext();
}
PredEntriesCounter--;
if (PredEntriesCounter == 0) {
Error(PRED_ENTRY_COUNTER_UNDERFLOW,TermNil,"");
JMPNext();
}
PREG = NEXTOP(PREG, ld);
GONext();
ENDOp();
/*****************************************************************
* Specialised try - retry - trust instructions *
*****************************************************************/
@@ -1071,6 +1176,21 @@ absmi(int inp)
ENDBOp();
BOp(count_retry_and_mark, ld);
RetriesCounter--;
if (RetriesCounter == 0) {
Error(RETRY_COUNTER_UNDERFLOW,TermNil,"");
JMPNext();
}
PredEntriesCounter--;
if (PredEntriesCounter == 0) {
Error(PRED_ENTRY_COUNTER_UNDERFLOW,TermNil,"");
JMPNext();
}
goto actual_retry_and_mark;
/* enter a retry dynamic */
ENDBOp();
BOp(profiled_retry_and_mark, ld);
LOCK(((PredEntry *)(PREG->u.ld.p))->StatisticsForPred.lock);
((PredEntry *)(PREG->u.ld.p))->StatisticsForPred.NOfRetries++;
@@ -1080,6 +1200,7 @@ absmi(int inp)
/* retry_and_mark Label,NArgs */
BOp(retry_and_mark, ld);
actual_retry_and_mark:
#ifdef YAPOR
CUT_wait_leftmost();
#endif /* YAPOR */

View File

@@ -2532,6 +2532,12 @@ do_pass(void)
case retry_profiled_op:
a_pl(_retry_profiled, (PredEntry *)(cpc->rnd1));
break;
case count_call_op:
a_pl(_count_call, (PredEntry *)(cpc->rnd1));
break;
case count_retry_op:
a_pl(_count_retry, (PredEntry *)(cpc->rnd1));
break;
case fetch_args_for_bccall:
if (cpc->nextInst->op != bccall_op) {
Error(SYSTEM_ERROR, TermNil, "compiling binary test", (int) cpc->op);

112
C/cdmgr.c
View File

@@ -74,6 +74,10 @@ STATIC_PROTO(Int p_compile_mode, (void));
STATIC_PROTO(Int p_is_profiled, (void));
STATIC_PROTO(Int p_profile_info, (void));
STATIC_PROTO(Int p_profile_reset, (void));
STATIC_PROTO(Int p_is_call_counted, (void));
STATIC_PROTO(Int p_call_count_info, (void));
STATIC_PROTO(Int p_call_count_set, (void));
STATIC_PROTO(Int p_call_count_reset, (void));
STATIC_PROTO(Int p_toggle_static_predicates_in_use, (void));
#ifdef DEBUG
STATIC_PROTO(void list_all_predicates_in_use, (void));
@@ -380,6 +384,8 @@ retract_all(PredEntry *p, int in_use)
p->OpcodeOfPred = cpt->opc;
if (p->PredFlags & ProfiledPredFlag) {
((yamop *)lclause)->opc = opcode(_profiled_trust_me);
} else if (p->PredFlags & CountPredFlag) {
((yamop *)lclause)->opc = opcode(_count_trust_me);
} else {
((yamop *)lclause)->opc = opcode(TRYCODE(_trust_me, _trust_me0, PredArity(p)));
}
@@ -520,6 +526,8 @@ add_first_dynamic(PredEntry *p, CODEADDR cp, int spy_flag)
* backtrack to the previous block */
if (p->PredFlags & ProfiledPredFlag)
((yamop *)cp)->opc = opcode(_profiled_retry_and_mark);
else if (p->PredFlags & CountPredFlag)
((yamop *)cp)->opc = opcode(_count_retry_and_mark);
else
((yamop *)cp)->opc = opcode(_retry_and_mark);
((yamop *)cp)->u.ld.s = p->ArityOfPE;
@@ -567,6 +575,11 @@ asserta_stat_clause(PredEntry *p, CODEADDR cp, int spy_flag)
q->opc = opcode(_profiled_trust_me);
else
q->opc = opcode(_profiled_retry_me);
} else if (p->PredFlags & CountPredFlag) {
if (p->FirstClause == p->LastClause)
q->opc = opcode(_count_trust_me);
else
q->opc = opcode(_count_retry_me);
} else {
if (p->FirstClause == p->LastClause) {
#ifdef TABLING
@@ -606,9 +619,11 @@ asserta_dynam_clause(PredEntry *p, CODEADDR cp)
q->u.ld.s = p->ArityOfPE;
q->u.ld.p = p;
if (p->PredFlags & ProfiledPredFlag)
((yamop *)cp)->opc = opcode(_retry_and_mark);
else
((yamop *)cp)->opc = opcode(_profiled_retry_and_mark);
else if (p->PredFlags & CountPredFlag)
((yamop *)cp)->opc = opcode(_count_retry_and_mark);
else
((yamop *)cp)->opc = opcode(_retry_and_mark);
((yamop *)cp)->u.ld.s = p->ArityOfPE;
((yamop *)cp)->u.ld.p = p;
p->FirstClause = cp;
@@ -630,6 +645,12 @@ assertz_stat_clause(PredEntry *p, CODEADDR cp, int spy_flag)
p->TrueCodeOfPred = p->FirstClause;
} else
pt->opc = opcode(_profiled_retry_me);
} else if (p->PredFlags & CountPredFlag) {
if (p->FirstClause == p->LastClause) {
pt->opc = opcode(TRYCODE(_try_me, _try_me0, PredArity(p)));
p->TrueCodeOfPred = p->FirstClause;
} else
pt->opc = opcode(_count_retry_me);
} else {
if (p->FirstClause == p->LastClause) {
#ifdef TABLING
@@ -653,6 +674,8 @@ assertz_stat_clause(PredEntry *p, CODEADDR cp, int spy_flag)
pt = (yamop *)cp;
if (p->PredFlags & ProfiledPredFlag) {
pt->opc = opcode(_profiled_trust_me);
} else if (p->PredFlags & CountPredFlag) {
pt->opc = opcode(_count_trust_me);
} else {
#ifdef TABLING
if (is_tabled(p))
@@ -693,6 +716,8 @@ assertz_dynam_clause(PredEntry *p, CODEADDR cp)
q = (yamop *)cp;
if (p->PredFlags & ProfiledPredFlag)
q->opc = opcode(_profiled_retry_and_mark);
else if (p->PredFlags & CountPredFlag)
q->opc = opcode(_count_retry_and_mark);
else
q->opc = opcode(_retry_and_mark);
q->u.ld.d = p->CodeOfPred;
@@ -1779,6 +1804,9 @@ search_for_static_predicate_in_use(PredEntry *p, int check_everything)
case _retry_profiled:
opnum = op_from_opcode(NEXTOP(b_ptr->cp_ap,l)->opc);
goto restart_cp;
case _count_retry:
opnum = op_from_opcode(NEXTOP(b_ptr->cp_ap,l)->opc);
goto restart_cp;
default:
pe = (PredEntry *)(b_ptr->cp_ap->u.ld.p);
}
@@ -1829,7 +1857,6 @@ static char *op_names[_std_top + 1] =
#endif
static void
list_all_predicates_in_use(void)
{
@@ -1865,6 +1892,7 @@ list_all_predicates_in_use(void)
case _retry_userc:
case _trust_logical_pred:
case _retry_profiled:
case _count_retry:
{
Atom at;
Int arity;
@@ -1890,7 +1918,7 @@ list_all_predicates_in_use(void)
YP_fprintf(YP_stderr,"CP %p %d (%s)\n", b_ptr, RepAtom((Atom)(pe->FunctorOfPred))->StrOfAE, op_names[opnum]);
}
}
if (opnum == _retry_profiled) {
if (opnum == _retry_profiled || opnum == _count_retry) {
opnum = op_from_opcode(NEXTOP(b_ptr->cp_ap,l)->opc);
goto restart_cp;
}
@@ -1958,6 +1986,9 @@ do_toggle_static_predicates_in_use(int mask)
case _retry_profiled:
opnum = op_from_opcode(NEXTOP(b_ptr->cp_ap,l)->opc);
goto restart_cp;
case _count_retry:
opnum = op_from_opcode(NEXTOP(b_ptr->cp_ap,l)->opc);
goto restart_cp;
default:
pe = (PredEntry *)(b_ptr->cp_ap->u.ld.p);
}
@@ -2171,6 +2202,75 @@ p_profile_reset(void)
return(TRUE);
}
static Int
p_is_call_counted(void)
{
Term t = Deref(ARG1);
char *s;
if (IsVarTerm(t)) {
Term ta;
if (CALL_COUNTING) ta = MkAtomTerm(LookupAtom("on"));
else ta = MkAtomTerm(LookupAtom("off"));
BIND((CELL *)t,ta,bind_is_call_counted);
#ifdef COROUTINING
DO_TRAIL(CellPtr(t), ta);
if (CellPtr(t) < H0) WakeUp((CELL *)t);
bind_is_call_counted:
#endif
return(TRUE);
} else if (!IsAtomTerm(t)) return(FALSE);
s = RepAtom(AtomOfTerm(t))->StrOfAE;
if (strcmp(s,"on") == 0) {
CALL_COUNTING = TRUE;
return(TRUE);
} else if (strcmp(s,"off") == 0) {
CALL_COUNTING = FALSE;
return(TRUE);
}
return(FALSE);
}
static Int
p_call_count_info(void)
{
return(unify(MkIntegerTerm(ReductionsCounter),ARG1) &&
unify(MkIntegerTerm(PredEntriesCounter),ARG2) &&
unify(MkIntegerTerm(PredEntriesCounter),ARG3));
}
static Int
p_call_count_reset(void)
{
ReductionsCounter = 0;
ReductionsCounterOn = FALSE;
PredEntriesCounter = 0;
PredEntriesCounterOn = FALSE;
RetriesCounter = 0;
RetriesCounterOn = FALSE;
return(TRUE);
}
static Int
p_call_count_set(void)
{
int do_calls = IntOfTerm(ARG2);
int do_retries = IntOfTerm(ARG4);
int do_entries = IntOfTerm(ARG6);
if (do_calls)
ReductionsCounter = IntegerOfTerm(Deref(ARG1));
ReductionsCounterOn = do_calls;
if (do_retries)
RetriesCounter = IntegerOfTerm(Deref(ARG3));
RetriesCounterOn = do_retries;
if (do_entries)
PredEntriesCounter = IntegerOfTerm(Deref(ARG5));
PredEntriesCounterOn = do_entries;
return(TRUE);
}
static Int
p_clean_up_dead_clauses(void)
{
@@ -2393,6 +2493,10 @@ InitCdMgr(void)
InitCPred("$is_profiled", 1, p_is_profiled, SafePredFlag|SyncPredFlag);
InitCPred("$profile_info", 3, p_profile_info, SafePredFlag|SyncPredFlag);
InitCPred("$profile_reset", 2, p_profile_reset, SafePredFlag|SyncPredFlag);
InitCPred("$is_call_counted", 1, p_is_call_counted, SafePredFlag|SyncPredFlag);
InitCPred("$call_count_info", 3, p_call_count_info, SafePredFlag|SyncPredFlag);
InitCPred("$call_count_set", 6, p_call_count_set, SafePredFlag|SyncPredFlag);
InitCPred("$call_count_reset", 0, p_call_count_reset, SafePredFlag|SyncPredFlag);
InitCPred("$toggle_static_predicates_in_use", 0, p_toggle_static_predicates_in_use, SafePredFlag|SyncPredFlag);
InitCPred("$set_pred_module", 2, p_set_pred_module, SafePredFlag);
InitCPred("$parent_pred", 3, p_parent_pred, SafePredFlag);

View File

@@ -73,7 +73,7 @@ static Ventry *vtable;
CExpEntry *common_exps;
int n_common_exps, profiling;
int n_common_exps, profiling, call_counting;
static int goalno, level, onlast, onhead, onbranch, cur_branch;
@@ -1097,6 +1097,8 @@ c_functor(Term Goal, int mod)
Prop p0 = PredPropByFunc(f, mod);
if (profiling)
emit(enter_profiling_op, (CELL)RepPredProp(p0), Zero);
else if (call_counting)
emit(count_call_op, (CELL)RepPredProp(p0), Zero);
c_args(Goal);
emit(safe_call_op, (CELL)p0 , Zero);
emit(empty_call_op, Zero, Zero);
@@ -1177,6 +1179,8 @@ c_goal(Term Goal, int mod)
if (profiling)
emit(enter_profiling_op, (CELL)RepPredProp(PredPropByAtom(AtomCut,0)), Zero);
else if (call_counting)
emit(count_call_op, (CELL)RepPredProp(PredPropByAtom(AtomCut,0)), Zero);
if (onlast) {
/* never a problem here with a -> b, !, c ; d */
emit(deallocate_op, Zero, Zero);
@@ -1208,6 +1212,8 @@ c_goal(Term Goal, int mod)
if (profiling)
emit(enter_profiling_op, (CELL)RepPredProp(PredPropByAtom(AtomRepeat,0)), Zero);
else if (call_counting)
emit(count_call_op, (CELL)RepPredProp(PredPropByAtom(AtomRepeat,0)), Zero);
or_found = 1;
push_branch(onbranch, TermNil);
cur_branch++;
@@ -1245,6 +1251,8 @@ c_goal(Term Goal, int mod)
/* if we are profiling, make sure we register we entered this predicate */
if (profiling)
emit(enter_profiling_op, (CELL)p, Zero);
if (call_counting)
emit(count_call_op, (CELL)p, Zero);
}
else {
f = FunctorOfTerm(Goal);
@@ -1438,6 +1446,8 @@ c_goal(Term Goal, int mod)
} else if (f == FunctorEq) {
if (profiling)
emit(enter_profiling_op, (CELL)p, Zero);
else if (call_counting)
emit(count_call_op, (CELL)p, Zero);
c_eq(ArgOfTerm(1, Goal), ArgOfTerm(2, Goal));
if (onlast) {
emit(deallocate_op, Zero, Zero);
@@ -1457,6 +1467,8 @@ c_goal(Term Goal, int mod)
int op = p->PredFlags & 0x7f;
if (profiling)
emit(enter_profiling_op, (CELL)p, Zero);
else if (call_counting)
emit(count_call_op, (CELL)p, Zero);
if (op >= _atom && op <= _primitive) {
c_test(op, ArgOfTerm(1, Goal));
if (onlast) {
@@ -1574,6 +1586,8 @@ c_goal(Term Goal, int mod)
} else {
if (profiling)
emit(enter_profiling_op, (CELL)p, Zero);
else if (call_counting)
emit(count_call_op, (CELL)p, Zero);
c_args(Goal);
}
}
@@ -2820,10 +2834,17 @@ cclause(Term inp_clause, int NOfArgs, int mod)
/* insert extra instructions to count calls */
READ_LOCK(CurrentPred->PRWLock);
if ((CurrentPred->PredFlags & ProfiledPredFlag) ||
(PROFILING && (CurrentPred->FirstClause == NIL)))
(PROFILING && (CurrentPred->FirstClause == NIL))) {
profiling = TRUE;
else
call_counting = FALSE;
} else if ((CurrentPred->PredFlags & CountPredFlag) ||
(CALL_COUNTING && (CurrentPred->FirstClause == NIL))) {
call_counting = TRUE;
profiling = FALSE;
} else {
profiling = FALSE;
call_counting = FALSE;
}
READ_UNLOCK(CurrentPred->PRWLock);
}
/* phase 1 : produce skeleton code and variable information */

View File

@@ -604,6 +604,8 @@ static char *opformat[] =
"function_to_al\t%v,%B",
"enter_profiling\t\t%g",
"retry_profiled\t\t%g",
"count_call_op\t\t%g",
"count_retry_op\t\t%g",
"restore_temps\t\t%l",
"restore_temps_and_skip\t\t%l",
"empty_call\t\t%l,%d",

View File

@@ -157,6 +157,9 @@ DumpActiveGoals (void)
case _retry_profiled:
opnum = op_from_opcode(NEXTOP(b_ptr->cp_ap,l)->opc);
goto restart_cp;
case _count_retry_me:
opnum = op_from_opcode(NEXTOP(b_ptr->cp_ap,l)->opc);
goto restart_cp;
default:
pe = (PredEntry *)(b_ptr->cp_ap->u.ld.p);
}
@@ -417,6 +420,26 @@ Error (yap_error_number type, Term where, char *format,...)
fun = MkFunctor(LookupAtom("abort"),2);
serious = TRUE;
break;
case CALL_COUNTER_UNDERFLOW:
/* Do a long jump */
PredEntriesCounter--;
JumpToEnv(MkAtomTerm(LookupAtom("call_counter")));
P = (yamop *)FAILCODE;
PrologMode &= ~InErrorMode;
return(P);
case PRED_ENTRY_COUNTER_UNDERFLOW:
/* Do a long jump */
JumpToEnv(MkAtomTerm(LookupAtom("call_and_retry_counter")));
P = (yamop *)FAILCODE;
PrologMode &= ~InErrorMode;
return(P);
case RETRY_COUNTER_UNDERFLOW:
/* Do a long jump */
PredEntriesCounter--;
JumpToEnv(MkAtomTerm(LookupAtom("retry_counter")));
P = (yamop *)FAILCODE;
PrologMode &= ~InErrorMode;
return(P);
case DOMAIN_ERROR_ARRAY_OVERFLOW:
{
int i;

View File

@@ -1462,6 +1462,7 @@ mark_choicepoints(register choiceptr gc_B, tr_fr_ptr saved_TR, int very_verbose)
case _retry_userc:
case _trust_logical_pred:
case _retry_profiled:
case _count_retry:
{
Atom at;
Int arity;
@@ -1594,6 +1595,7 @@ mark_choicepoints(register choiceptr gc_B, tr_fr_ptr saved_TR, int very_verbose)
break;
case _trust_logical_pred:
case _retry_profiled:
case _count_retry:
rtp = NEXTOP(rtp,l);
op = rtp->opc;
opnum = op_from_opcode(op);
@@ -1706,6 +1708,8 @@ mark_choicepoints(register choiceptr gc_B, tr_fr_ptr saved_TR, int very_verbose)
case _trust_me:
case _profiled_retry_me:
case _profiled_trust_me:
case _count_retry_me:
case _count_trust_me:
case _retry_me0:
case _trust_me0:
case _retry_me1:
@@ -1718,6 +1722,7 @@ mark_choicepoints(register choiceptr gc_B, tr_fr_ptr saved_TR, int very_verbose)
case _trust_me4:
case _retry_and_mark:
case _profiled_retry_and_mark:
case _count_retry_and_mark:
case _retry:
case _trust_in:
case _trust:
@@ -2201,6 +2206,7 @@ sweep_choicepoints(choiceptr gc_B)
break;
case _trust_logical_pred:
case _retry_profiled:
case _count_retry:
rtp = NEXTOP(rtp,l);
op = rtp->opc;
opnum = op_from_opcode(op);

View File

@@ -252,6 +252,8 @@ emit_cp_inst(compiler_vm_op op, yamop * Address, int Flag, int NClausesAfter)
indexed_code_for_cut = NIL;
if (op != try_op && profiling)
emit(retry_profiled_op, Unsigned(CurrentPred), Zero);
else if (op != try_op && call_counting)
emit(count_retry_op, Unsigned(CurrentPred), Zero);
if (NGroups == 1)
Flag = Flag | LoneGroup;
else if (Flag & LastGroup) {
@@ -1335,6 +1337,8 @@ PredIsIndexable(PredEntry *ap)
CurrentPred = ap;
if (CurrentPred->PredFlags & ProfiledPredFlag)
profiling = TRUE;
else if (CurrentPred->PredFlags & CountPredFlag)
call_counting = TRUE;
else
profiling = FALSE;
IPredArity = ap->ArityOfPE;

View File

@@ -852,6 +852,7 @@ InitCodes(void)
}
heap_regs->consultcapacity = InitialConsultCapacity;
heap_regs->profiling = FALSE;
heap_regs->call_counting = FALSE;
heap_regs->update_mode = 0;
heap_regs->consultbase = heap_regs->consultsp =
heap_regs->consultlow + heap_regs->consultcapacity;