diff --git a/C/alloc.c b/C/alloc.c index 20fbc91a5..b172e01c7 100644 --- a/C/alloc.c +++ b/C/alloc.c @@ -12,7 +12,7 @@ * Last rev: * * mods: * * comments: allocating space * -* version:$Id: alloc.c,v 1.94 2008-04-06 12:06:48 vsc Exp $ * +* version:$Id: alloc.c,v 1.95 2008-05-10 23:24:11 vsc Exp $ * *************************************************************************/ #ifdef SCCS static char SccsId[] = "%W% %G%"; @@ -208,7 +208,7 @@ struct various_codes *Yap_heap_regs; static void InitHeap(void) { - Yap_heap_regs = (struct various_codes *)malloc(sizeof(struct various_codes)); + Yap_heap_regs = (struct various_codes *)calloc(1, sizeof(struct various_codes)); } void @@ -265,14 +265,14 @@ Yap_InitExStacks(int Trail, int Stack) InitExStacks(Trail, Stack); } -#if defined(YAPOR) || defined(THREADS) +#if defined(THREADS) void Yap_KillStacks(int wid) { - ADDR gb = Yap_thread_gl[wid].global_base; + ADDR gb = ThreadHandle[wid].stack_address; if (gb) { free(gb); - Yap_thread_gl[wid].global_base = NULL; + ThreadHandle[wid].stack_address = NULL; } } #else @@ -300,6 +300,9 @@ Yap_ExtendWorkSpace(Int s) nbp = realloc(basebp, s+s0); if (nbp == NULL) return FALSE; +#if defined(THREADS) + ThreadHandle[worker_id].stack_address = (char *)nbp; +#endif Yap_GlobalBase = (char *)nbp; return TRUE; } diff --git a/C/arith1.c b/C/arith1.c index 116e9cde6..8a694c12b 100644 --- a/C/arith1.c +++ b/C/arith1.c @@ -234,6 +234,7 @@ p_uminus(Term t E_ARGS) #ifdef USE_GMP case big_int_e: mpz_neg(v.big, v.big); + fprintf(stderr,"Here I am %p\n", v.big); RBIG(v.big); #endif default: diff --git a/C/dbase.c b/C/dbase.c index f7564842e..59d364a3b 100644 --- a/C/dbase.c +++ b/C/dbase.c @@ -240,19 +240,11 @@ STATIC_PROTO(PredEntry *new_lu_int_key, (Int)); STATIC_PROTO(PredEntry *find_lu_entry, (Term)); STATIC_PROTO(DBProp find_int_key, (Int)); -#if USE_SYSTEM_MALLOC #define db_check_trail(x) { \ if (Unsigned(dbg->tofref) == Unsigned(x)) { \ goto error_tr_overflow; \ } \ } -#else -#define db_check_trail(x) { \ - if (Unsigned(dbg->tofref) == Unsigned(x)) { \ - goto error_tr_overflow; \ - } \ -} -#endif static UInt new_trail_size(void) { @@ -3689,7 +3681,7 @@ index_sz(LogUpdIndex *x) if (op == _enter_lu_pred) { PredEntry *ap = x->ClPred; OPCODE endop, op1; - UInt count = 0, count0 = start->u.Ill.s, dead=0; + UInt count = 0, dead=0; if (ap->PredFlags & CountPredFlag) endop = Yap_opcode(_count_trust_logical); @@ -3706,12 +3698,6 @@ index_sz(LogUpdIndex *x) dead++; start = start->u.lld.n; } while (op1 != endop); - if (x->ClFlags & InUseMask) - fprintf(stderr,"Inuse -- %p(%p)\n",ap,x); - if (x->ClFlags & DirtyMask) - fprintf(stderr,"Dirty -- %p(%p)\n",ap,x); - if (count > 200) - fprintf(stderr,"%lu/%lu/%lu -- %p(%p)\n",(unsigned long int)count,(unsigned long int)count0,(unsigned long int)dead,ap,x); } x = x->ChildIndex; while (x != NULL) { diff --git a/C/grow.c b/C/grow.c index b588a5a3f..483c8d281 100644 --- a/C/grow.c +++ b/C/grow.c @@ -433,51 +433,51 @@ AdjustGlobal(long sz) cpt = pt; reg = *pt; if (IsVarTerm(reg)) { - if (IsOldGlobal(reg)) - *pt = GlobalAdjust(reg); - else if (IsOldLocal(reg)) - *pt = LocalAdjust(reg); - else if (IsOldCode(reg)) { - Functor f; - f = (Functor)reg; - /* skip bitmaps */ - switch((CELL)f) { - case (CELL)FunctorDouble: + if (IsOldGlobal(reg)) + *pt = GlobalAdjust(reg); + else if (IsOldLocal(reg)) + *pt = LocalAdjust(reg); + else if (IsOldCode(reg)) { + Functor f; + f = (Functor)reg; + /* skip bitmaps */ + switch((CELL)f) { + case (CELL)FunctorDouble: #if SIZEOF_DOUBLE == 2*SIZEOF_LONG_INT - pt += 3; + pt += 3; #else - pt += 2; + pt += 2; #endif - break; + break; #if USE_GMP - case (CELL)FunctorBigInt: - { - Int sz = 1+ - (sizeof(MP_INT)+ - (((MP_INT *)(pt+1))->_mp_alloc*sizeof(mp_limb_t)))/CellSize; - pt += sz; - } - break; -#endif - case (CELL)0L: - break; - case (CELL)FunctorLongInt: - pt += 2; - break; - default: - *pt = CodeAdjust(reg); + case (CELL)FunctorBigInt: + { + Int sz = 1+ + (sizeof(MP_INT)+ + (((MP_INT *)(pt+1))->_mp_alloc*sizeof(mp_limb_t)))/CellSize; + pt += sz; } - } -#ifdef MULTI_ASSIGNMENT_VARIABLES - else if (IsOldTrail(reg)) - *pt = TrailAdjust(reg); + break; #endif - } else if (IsApplTerm(reg)) - *pt = AdjustAppl(reg); - else if (IsPairTerm(reg)) - *pt = AdjustPair(reg); - else if (IsAtomTerm(reg)) - *pt = AtomTermAdjust(reg); + case (CELL)0L: + break; + case (CELL)FunctorLongInt: + pt += 2; + break; + default: + *pt = CodeAdjust(reg); + } + } +#ifdef MULTI_ASSIGNMENT_VARIABLES + else if (IsOldTrail(reg)) + *pt = TrailAdjust(reg); +#endif + } else if (IsApplTerm(reg)) + *pt = AdjustAppl(reg); + else if (IsPairTerm(reg)) + *pt = AdjustPair(reg); + else if (IsAtomTerm(reg)) + *pt = AtomTermAdjust(reg); pt++; } } diff --git a/C/index.c b/C/index.c index 346f8a03f..099797bdc 100644 --- a/C/index.c +++ b/C/index.c @@ -11,8 +11,12 @@ * File: index.c * * comments: Indexing a Prolog predicate * * * -* Last rev: $Date: 2008-04-16 17:16:47 $,$Author: vsc $ * +* Last rev: $Date: 2008-05-10 23:24:11 $,$Author: vsc $ * * $Log: not supported by cvs2svn $ +* Revision 1.200 2008/04/16 17:16:47 vsc +* make static_clause only commit to a lause if it is sure that is the true +* clause. Otherwise, search for the clause. +* * Revision 1.199 2008/04/14 21:20:35 vsc * fixed a bug in static_clause (thanks to Jose Santos) * @@ -3839,7 +3843,11 @@ emit_single_switch_case(ClauseDef *min, struct intermediates *cint, int first, i } } #endif /* TABLING */ - return (UInt)(min->CurrentCode); + if (cint->CurrentPred->PredFlags & LogUpdatePredFlag) { + return (UInt)(min->Code); + } else { + return (UInt)(min->CurrentCode); + } } static UInt @@ -4120,7 +4128,11 @@ do_pair(GroupDef *grp, Term t, struct intermediates *cint, UInt argno, int first grp->FirstClause = max+1; if (min == max) { /* single clause, no need to do indexing, but we do know it is a list */ - return (UInt)(min->CurrentCode); + if (cint->CurrentPred->PredFlags & LogUpdatePredFlag) { + return (UInt)(min->Code); + } else { + return (UInt)(min->CurrentCode); + } } if (min != max && !IsPairTerm(t)) { if (yap_flags[INDEXING_MODE_FLAG] == INDEX_MODE_SINGLE) { @@ -6491,19 +6503,13 @@ expandz_block(path_stack_entry *sp, PredEntry *ap, ClauseDef *cls, int group1, y } static LogUpdClause * -lu_clause(yamop *ipc) +lu_clause(yamop *ipc, PredEntry *ap) { - LogUpdClause *c; - CELL *p = (CELL *)ipc; - if (ipc == FAILCODE) return NULL; - while ((c = ClauseCodeToLogUpdClause(p))->Id != FunctorDBRef || - !(c->ClFlags & LogUpdMask) || - (c->ClFlags & (IndexMask|DynamicMask|SwitchTableMask|SwitchRootMask))) { - p--; - } - return c; + if (ipc == (yamop *)(&(ap->OpcodeOfPred))) + return NULL; + return ClauseCodeToLogUpdClause(ipc); } static StaticClause * @@ -6526,6 +6532,8 @@ static_clause(yamop *ipc, PredEntry *ap, int trust) if (ipc == FAILCODE) return NULL; + if (ipc == (yamop*)(&(ap->OpcodeOfPred))) + return NULL; if (ap->PredFlags & MegaClausePredFlag) return (StaticClause *)ipc; if (ap->PredFlags & TabledPredFlag) @@ -6572,8 +6580,10 @@ static_clause(yamop *ipc, PredEntry *ap, int trust) } static StaticClause * -simple_static_clause(yamop *ipc) +simple_static_clause(yamop *ipc, PredEntry *ap) { + if (ipc == (yamop*)(&(ap->OpcodeOfPred))) + return NULL; if (ipc == FAILCODE) return NULL; return ClauseCodeToStaticClause(ipc); @@ -6598,7 +6608,7 @@ kill_unsafe_block(path_stack_entry *sp, op_numbers op, PredEntry *ap, int first, } if (ap->PredFlags & LogUpdatePredFlag) { struct intermediates intrs; - LogUpdClause *lc = lu_clause(ipc); + LogUpdClause *lc = lu_clause(ipc, ap); if (first) { cld[0].Code = cls[0].Code; @@ -6956,7 +6966,11 @@ add_to_index(struct intermediates *cint, int first, path_stack_entry *sp, Clause move_next(cls, 1); if (nipc == FAILCODE) { /* jump straight to clause */ - ipc->u.llll.l1 = cls->CurrentCode; + if (ap->PredFlags & LogUpdatePredFlag) { + ipc->u.llll.l1 = cls->Code; + } else { + ipc->u.llll.l1 = cls->CurrentCode; + } ipc = pop_path(&sp, cls, ap); } else { /* go on */ @@ -7010,7 +7024,11 @@ add_to_index(struct intermediates *cint, int first, path_stack_entry *sp, Clause move_next(cls, Yap_regtoregno(ipc->u.xllll.x)); if (nipc == FAILCODE) { /* jump straight to clause */ - ipc->u.xllll.l1 = cls->CurrentCode; + if (ap->PredFlags & LogUpdatePredFlag) { + ipc->u.xllll.l1 = cls->Code; + } else { + ipc->u.xllll.l1 = cls->CurrentCode; + } ipc = pop_path(&sp, cls, ap); } else { /* go on */ @@ -7059,7 +7077,11 @@ add_to_index(struct intermediates *cint, int first, path_stack_entry *sp, Clause } if (nipc == FAILCODE) { /* jump straight to clause */ - ipc->u.sllll.l1 = cls->CurrentCode; + if (ap->PredFlags & LogUpdatePredFlag) { + ipc->u.sllll.l1 = cls->Code; + } else { + ipc->u.sllll.l1 = cls->CurrentCode; + } ipc = pop_path(&sp, cls, ap); } else { /* go on */ @@ -7141,7 +7163,11 @@ add_to_index(struct intermediates *cint, int first, path_stack_entry *sp, Clause fe->Tag = f; ipc->u.sssl.e++; } - fe->u.labp = cls->CurrentCode; + if (ap->PredFlags & LogUpdatePredFlag) { + fe->u.labp = cls->Code; + } else { + fe->u.labp = cls->CurrentCode; + } ipc = pop_path(&sp, cls, ap); } else { yamop *newpc = fe->u.labp; @@ -7193,7 +7219,11 @@ add_to_index(struct intermediates *cint, int first, path_stack_entry *sp, Clause ae->Tag = at; ipc->u.sssl.e++; } - ae->u.labp = cls->CurrentCode; + if (ap->PredFlags & LogUpdatePredFlag) { + ae->u.labp = cls->Code; + } else { + ae->u.labp = cls->CurrentCode; + } ipc = pop_path(&sp, cls, ap); } else { yamop *newpc = ae->u.labp; @@ -7696,9 +7726,6 @@ remove_from_index(PredEntry *ap, path_stack_entry *sp, ClauseDef *cls, yamop *bg case _lock_lu: ipc = NEXTOP(ipc,p); break; - case _unlock_lu: - ipc = NEXTOP(ipc,e); - break; default: if (IN_BETWEEN(bg,ipc,lt)) { sp = kill_unsafe_block(sp, op, ap, TRUE, TRUE, cls); @@ -7867,11 +7894,11 @@ static LogUpdClause * to_clause(yamop *ipc, PredEntry *ap) { if (ap->PredFlags & LogUpdatePredFlag) - return lu_clause(ipc); + return lu_clause(ipc, ap); else if (ap->PredFlags & MegaClausePredFlag) return (LogUpdClause *)ipc; else - return (LogUpdClause *)simple_static_clause(ipc); + return (LogUpdClause *)simple_static_clause(ipc, ap); } LogUpdClause * @@ -7902,7 +7929,7 @@ Yap_FollowIndexingCode(PredEntry *ap, yamop *ipc, Term Terms[3], yamop *ap_pc, y case _try_in: update_clause_choice_point(NEXTOP(ipc,l), ap_pc); if (lu_pred) - return lu_clause(ipc->u.l.l); + return lu_clause(ipc->u.l.l, ap); else return (LogUpdClause *)static_clause(ipc->u.l.l, ap, unbounded); break; @@ -7918,7 +7945,7 @@ Yap_FollowIndexingCode(PredEntry *ap, yamop *ipc, Term Terms[3], yamop *ap_pc, y update_clause_choice_point(NEXTOP(ipc,ld), ap_pc); } if (lu_pred) - return lu_clause(ipc->u.ld.d); + return lu_clause(ipc->u.ld.d, ap); else return (LogUpdClause *)static_clause(ipc->u.ld.d, ap, unbounded); case _try_clause2: @@ -7932,7 +7959,7 @@ Yap_FollowIndexingCode(PredEntry *ap, yamop *ipc, Term Terms[3], yamop *ap_pc, y update_clause_choice_point(NEXTOP(ipc,l), ap_pc); } if (lu_pred) - return lu_clause(ipc->u.l.l); + return lu_clause(ipc->u.l.l, ap); else return (LogUpdClause *)static_clause(ipc->u.l.l, ap, unbounded); case _try_me: @@ -7958,7 +7985,7 @@ Yap_FollowIndexingCode(PredEntry *ap, yamop *ipc, Term Terms[3], yamop *ap_pc, y #endif update_clause_choice_point(NEXTOP(ipc,ld),ap_pc); if (lu_pred) - return lu_clause(ipc->u.ld.d); + return lu_clause(ipc->u.ld.d, ap); else return (LogUpdClause *)static_clause(ipc->u.ld.d, ap, TRUE); case _retry2: @@ -7966,7 +7993,7 @@ Yap_FollowIndexingCode(PredEntry *ap, yamop *ipc, Term Terms[3], yamop *ap_pc, y case _retry4: update_clause_choice_point(NEXTOP(ipc,l),ap_pc); if (lu_pred) - return lu_clause(ipc->u.l.l); + return lu_clause(ipc->u.l.l, ap); else return (LogUpdClause *)static_clause(ipc->u.l.l, ap, TRUE); case _retry_me: @@ -7997,7 +8024,7 @@ Yap_FollowIndexingCode(PredEntry *ap, yamop *ipc, Term Terms[3], yamop *ap_pc, y #endif /* YAPOR */ b0 = B; if (lu_pred) - return lu_clause(ipc->u.ld.d); + return lu_clause(ipc->u.ld.d, ap); else return (LogUpdClause *)static_clause(ipc->u.ld.d, ap, TRUE); case _profiled_trust_me: @@ -8352,9 +8379,6 @@ Yap_FollowIndexingCode(PredEntry *ap, yamop *ipc, Term Terms[3], yamop *ap_pc, y case _lock_lu: ipc = NEXTOP(ipc,p); break; - case _unlock_lu: - ipc = NEXTOP(ipc,e); - break; #if THREADS case _thread_local: ap = Yap_GetThreadPred(ap); @@ -8410,7 +8434,7 @@ Yap_FollowIndexingCode(PredEntry *ap, yamop *ipc, Term Terms[3], yamop *ap_pc, y if (op == _op_fail) return NULL; if (lu_pred) - return lu_clause(ipc); + return lu_clause(ipc, ap); else return (LogUpdClause *)static_clause(ipc, ap, unbounded); } diff --git a/C/init.c b/C/init.c index 8fe5634b7..64c50df9f 100644 --- a/C/init.c +++ b/C/init.c @@ -972,6 +972,9 @@ InitCodes(void) Yap_heap_regs->thread_handle[i].in_use = FALSE; Yap_heap_regs->thread_handle[i].zombie = FALSE; Yap_heap_regs->thread_handle[i].local_preds = NULL; +#ifdef LOW_LEVEL_TRACER + Yap_heap_regs->thread_handle[i].thread_inst_count = 0LL; +#endif pthread_mutex_init(&Yap_heap_regs->thread_handle[i].tlock, NULL); } } diff --git a/C/threads.c b/C/threads.c index d27f98ff7..7c89730e5 100644 --- a/C/threads.c +++ b/C/threads.c @@ -100,6 +100,7 @@ kill_thread_engine (int wid) } Yap_KillStacks(wid); Yap_FreeCodeSpace((ADDR)(ThreadHandle[wid].tgoal)); + ThreadHandle[wid].tgoal = NULL; Yap_heap_regs->wl[wid].active_signals = 0L; free(Yap_heap_regs->wl[wid].scratchpad.ptr); free(ThreadHandle[wid].default_yaam_regs); @@ -131,12 +132,12 @@ setup_engine(int myworker_id) { REGSTORE *standard_regs; - standard_regs = (REGSTORE *)malloc(sizeof(REGSTORE)); + standard_regs = (REGSTORE *)calloc(1,sizeof(REGSTORE)); /* create the YAAM descriptor */ ThreadHandle[myworker_id].default_yaam_regs = standard_regs; pthread_setspecific(Yap_yaamregs_key, (void *)standard_regs); worker_id = myworker_id; - Yap_InitExStacks(ThreadHandle[myworker_id].ssize, ThreadHandle[myworker_id].tsize); + Yap_InitExStacks(ThreadHandle[myworker_id].tsize, ThreadHandle[myworker_id].ssize); CurrentModule = ThreadHandle[myworker_id].cmod; Yap_InitTime(); Yap_InitYaamRegs(); @@ -419,7 +420,6 @@ static Int p_thread_exit(void) { thread_die(worker_id, FALSE); - fprintf(stderr,"2 the end of worker_id=%d\n",worker_id); pthread_exit(NULL); return TRUE; } diff --git a/C/tracer.c b/C/tracer.c index 2aa63148b..304c5c019 100644 --- a/C/tracer.c +++ b/C/tracer.c @@ -164,6 +164,11 @@ low_level_trace(yap_low_level_port port, PredEntry *pred, CELL *args) LOCK(Yap_heap_regs->low_level_trace_lock); sc = Yap_heap_regs; vsc_count++; +#ifdef THREADS + Yap_heap_regs->thread_handle[worker_id].thread_inst_count++; +#endif + UNLOCK(Yap_heap_regs->low_level_trace_lock); + return; #ifdef COMMENTED //*(H0+(0xb65f2850-0xb64b2008)/sizeof(CELL))==0xc || //0x4fd4d diff --git a/C/utilpreds.c b/C/utilpreds.c index e32f4eede..18b54f768 100644 --- a/C/utilpreds.c +++ b/C/utilpreds.c @@ -19,7 +19,7 @@ static char SccsId[] = "@(#)utilpreds.c 1.3"; #endif #include "Yap.h" -#include "Yatom.h" +#include "clause.h" #include "Heap.h" #include "yapio.h" #include "eval.h" @@ -155,9 +155,22 @@ copy_complex_term(CELL *pt0, CELL *pt0_end, int share, int newattvs, CELL *ptf, f = (Functor)(*ap2); if (IsExtensionFunctor(f)) { - { - *ptf++ = d0; /* you can just copy other extensions. */ +#if defined(YAPOR) || defined(THREADS) + if (f == FunctorDBRef) { + DBRef entryref = DBRefOfTerm(d0); + if (entryref->Flags & LogUpdMask) { + LogUpdClause *luclause = (LogUpdClause *)entryref; + LOCK(luclause->ClPred->PELock); + UNLOCK(luclause->ClPred->PELock); + } else { + LOCK(entryref->lock); + TRAIL_REF(entryref); /* So that fail will erase it */ + INC_DBREF_COUNT(entryref); + UNLOCK(entryref->lock); } + } +#endif + *ptf++ = d0; /* you can just copy other extensions. */ continue; } *ptf = AbsAppl(H); @@ -545,7 +558,6 @@ static Term vars_in_complex_term(register CELL *pt0, register CELL *pt0_end, Ter /* store the terms to visit */ ap2 = RepAppl(d0); f = (Functor)(*ap2); - if (IsExtensionFunctor(f)) { continue; } diff --git a/H/Heap.h b/H/Heap.h index 39c8ead82..2cb3eac1e 100644 --- a/H/Heap.h +++ b/H/Heap.h @@ -10,7 +10,7 @@ * File: Heap.h * * mods: * * comments: Heap Init Structure * -* version: $Id: Heap.h,v 1.130 2008-04-02 17:37:06 vsc Exp $ * +* version: $Id: Heap.h,v 1.131 2008-05-10 23:24:12 vsc Exp $ * *************************************************************************/ /* information that can be stored in Code Space */ @@ -196,6 +196,9 @@ typedef struct thandle { struct pred_entry *local_preds; pthread_t handle; int ref_count; +#ifdef LOW_LEVEL_TRACER + long long int thread_inst_count; +#endif pthread_mutex_t tlock; #if HAVE_GETRUSAGE struct timeval *start_of_timesp; diff --git a/LGPL/JPL/jpl_paths.yap.in b/LGPL/JPL/jpl_paths.yap.in index bbce753a3..2c0c94f3b 100644 --- a/LGPL/JPL/jpl_paths.yap.in +++ b/LGPL/JPL/jpl_paths.yap.in @@ -18,6 +18,8 @@ fetch_arch(Arch) :- gen_arch(L,mac) :- append(_,[0'd,0'a,0'r,0'w,0'i,0'n|_],L), !. +% handle compilation in 64 bit machine of 32 bit binary. +gen_arch([0'x,0'8,0'6,0'_,0'6,0'4|_],i386) :- yap_flag(max_tagged_integer, 67108863). gen_arch([0'x,0'8,0'6,0'_,0'6,0'4|_],amd64). gen_arch([0'i,_,0'8,0'6|_],i386). % take all versions of X86 gen_arch([0's,0'p,0'a,0'r,0'c|_],sparc). diff --git a/LGPL/JPL/src/jpl.c b/LGPL/JPL/src/jpl.c index 76fc78790..71aace51f 100644 --- a/LGPL/JPL/src/jpl.c +++ b/LGPL/JPL/src/jpl.c @@ -1,4 +1,4 @@ -/* $Id: jpl.c,v 1.15 2008-04-14 21:20:36 vsc Exp $ +/* $Id: jpl.c,v 1.16 2008-05-10 23:24:12 vsc Exp $ Part of JPL -- SWI-Prolog/Java interface @@ -1796,6 +1796,9 @@ jni_create_jvm_c( /* opt[optn].optionString = "abort"; // I don't understand this yet... */ /* opt[optn++].extraInfo = jvm_abort; // this function has been moved to jpl_extras.c */ /* opt[optn++].optionString = "-Xcheck:jni"; // extra checking of JNI calls */ +#if __YAP_PROLOG__ + opt[optn++].optionString = "-Xmx1512m"; // give java enough space +#endif /* opt[optn++].optionString = "-Xnoclassgc"; // so method/field IDs remain valid (?) */ /* opt[optn].optionString = "vfprintf"; */ /* opt[optn++].extraInfo = fprintf; // no O/P, then SEGV */ diff --git a/changes-5.1.html b/changes-5.1.html index 550228d0c..c867fd2f7 100644 --- a/changes-5.1.html +++ b/changes-5.1.html @@ -17,6 +17,8 @@ xb