bf12533e9f
git-svn-id: https://yap.svn.sf.net/svnroot/yap/trunk@767 b08c6af1-5177-4d33-ba66-4b1c6b8b522a
1025 lines
26 KiB
C
1025 lines
26 KiB
C
/*************************************************************************
|
|
* *
|
|
* YAP Prolog *
|
|
* *
|
|
* Yap Prolog was developed at NCCUP - Universidade do Porto *
|
|
* *
|
|
* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
|
|
* *
|
|
**************************************************************************
|
|
* *
|
|
* File: grow.c *
|
|
* Last rev: Thu Feb 23 1989 vv *
|
|
* mods: *
|
|
* comments: Shifting the stacks *
|
|
* *
|
|
*************************************************************************/
|
|
|
|
#include "Yap.h"
|
|
#include "Yatom.h"
|
|
#include "Heap.h"
|
|
#include "yapio.h"
|
|
#include "alloc.h"
|
|
#include "sshift.h"
|
|
#include "compile.h"
|
|
#if HAVE_STRING_H
|
|
#include <string.h>
|
|
#endif
|
|
|
|
#if !HAVE_STRNCAT
|
|
#define strncat(s0,s1,sz) strcat(s0,s1)
|
|
#endif
|
|
|
|
static int heap_overflows = 0;
|
|
static Int total_heap_overflow_time = 0;
|
|
|
|
int stack_overflows = 0;
|
|
static Int total_stack_overflow_time = 0;
|
|
|
|
int delay_overflows = 0;
|
|
static Int total_delay_overflow_time = 0;
|
|
|
|
static int trail_overflows = 0;
|
|
static Int total_trail_overflow_time = 0;
|
|
|
|
STATIC_PROTO(Int p_growheap, (void));
|
|
STATIC_PROTO(Int p_growstack, (void));
|
|
STATIC_PROTO(Int p_inform_trail_overflows, (void));
|
|
STATIC_PROTO(Int p_inform_heap_overflows, (void));
|
|
STATIC_PROTO(Int p_inform_stack_overflows, (void));
|
|
|
|
/* #define undf7 */
|
|
/* #define undf5 */
|
|
|
|
STATIC_PROTO(int growstack, (long));
|
|
STATIC_PROTO(void MoveGlobal, (void));
|
|
STATIC_PROTO(void MoveLocalAndTrail, (void));
|
|
STATIC_PROTO(void SetHeapRegs, (void));
|
|
STATIC_PROTO(void SetStackRegs, (void));
|
|
STATIC_PROTO(void AdjustTrail, (int));
|
|
STATIC_PROTO(void AdjustLocal, (void));
|
|
STATIC_PROTO(void AdjustGlobal, (void));
|
|
STATIC_PROTO(void AdjustGrowStack, (void));
|
|
STATIC_PROTO(int static_growheap, (long,int));
|
|
STATIC_PROTO(void cpcellsd, (CELL *, CELL *, CELL));
|
|
STATIC_PROTO(CELL AdjustAppl, (CELL));
|
|
STATIC_PROTO(CELL AdjustPair, (CELL));
|
|
STATIC_PROTO(void AdjustStacksAndTrail, (void));
|
|
STATIC_PROTO(void AdjustRegs, (int));
|
|
|
|
static void
|
|
cpcellsd(register CELL *Dest, register CELL *Org, CELL NOf)
|
|
{
|
|
#if HAVE_MEMMOVE
|
|
memmove((void *)Dest, (void *)Org, NOf*sizeof(CELL));
|
|
#else
|
|
register Int n_of = NOf;
|
|
for (; n_of >= 0; n_of--)
|
|
*--Dest = *--Org;
|
|
#endif
|
|
}
|
|
|
|
|
|
/* The old stack pointers */
|
|
CELL *OldASP, *OldLCL0;
|
|
tr_fr_ptr OldTR;
|
|
CELL *OldGlobalBase, *OldH, *OldH0;
|
|
ADDR OldTrailBase, OldTrailTop;
|
|
ADDR OldHeapBase, OldHeapTop;
|
|
|
|
Int
|
|
GDiff,
|
|
HDiff,
|
|
LDiff,
|
|
TrDiff,
|
|
XDiff,
|
|
DelayDiff;
|
|
|
|
static void
|
|
SetHeapRegs(void)
|
|
{
|
|
#ifdef undf7
|
|
fprintf(Yap_stderr,"HeapBase = %x\tHeapTop=%x\nGlobalBase=%x\tGlobalTop=%x\nLocalBase=%x\tLocatTop=%x\n", Yap_HeapBase, HeapTop, Yap_GlobalBase, H, LCL0, ASP);
|
|
#endif
|
|
/* The old stack pointers */
|
|
OldLCL0 = LCL0;
|
|
OldASP = ASP;
|
|
OldGlobalBase = (CELL *)Yap_GlobalBase;
|
|
OldH = H;
|
|
OldH0 = H0;
|
|
OldTrailBase = Yap_TrailBase;
|
|
OldTrailTop = Yap_TrailTop;
|
|
OldTR = TR;
|
|
OldHeapBase = Yap_HeapBase;
|
|
OldHeapTop = HeapTop;
|
|
/* Adjust stack addresses */
|
|
Yap_TrailBase = TrailAddrAdjust(Yap_TrailBase);
|
|
Yap_TrailTop = TrailAddrAdjust(Yap_TrailTop);
|
|
Yap_GlobalBase = DelayAddrAdjust(Yap_GlobalBase);
|
|
Yap_LocalBase = LocalAddrAdjust(Yap_LocalBase);
|
|
AuxSp = PtoDelayAdjust(AuxSp);
|
|
AuxTop = DelayAddrAdjust(AuxTop);
|
|
/* The registers pointing to one of the stacks */
|
|
ENV = PtoLocAdjust(ENV);
|
|
ASP = PtoLocAdjust(ASP);
|
|
H0 = PtoGloAdjust(H0);
|
|
LCL0 = PtoLocAdjust(LCL0);
|
|
H = PtoGloAdjust(H);
|
|
HB = PtoGloAdjust(HB);
|
|
B = ChoicePtrAdjust(B);
|
|
#ifdef TABLING
|
|
B_FZ = ChoicePtrAdjust(B_FZ);
|
|
BB = ChoicePtrAdjust(BB);
|
|
H_FZ = PtoGloAdjust(H_FZ);
|
|
TR_FZ = PtoTRAdjust(TR_FZ);
|
|
#endif
|
|
TR = PtoTRAdjust(TR);
|
|
YENV = PtoLocAdjust(YENV);
|
|
if (IsOldGlobalPtr(S))
|
|
S = PtoGloAdjust(S);
|
|
if (MyTR)
|
|
MyTR = PtoTRAdjust(MyTR);
|
|
#ifdef COROUTINING
|
|
DelayedVars = AbsAppl(PtoGloAdjust(RepAppl(DelayedVars)));
|
|
MutableList = AbsAppl(PtoGloAdjust(RepAppl(MutableList)));
|
|
AttsMutableList = AbsAppl(PtoGloAdjust(RepAppl(AttsMutableList)));
|
|
WokenGoals = AbsAppl(PtoGloAdjust(RepAppl(WokenGoals)));
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
SetStackRegs(void)
|
|
{
|
|
/* The old local stack pointers */
|
|
OldLCL0 = LCL0;
|
|
OldASP = ASP;
|
|
OldH = H;
|
|
OldH0 = H0;
|
|
OldGlobalBase = (CELL *)Yap_GlobalBase;
|
|
OldTrailTop = Yap_TrailTop;
|
|
OldTrailBase = Yap_TrailBase;
|
|
OldTR = TR;
|
|
OldHeapBase = Yap_HeapBase;
|
|
OldHeapTop = HeapTop;
|
|
/* The local and aux stack addresses */
|
|
Yap_TrailBase = TrailAddrAdjust(Yap_TrailBase);
|
|
Yap_TrailTop = TrailAddrAdjust(Yap_TrailTop);
|
|
Yap_LocalBase = LocalAddrAdjust(Yap_LocalBase);
|
|
TR = PtoTRAdjust(TR);
|
|
/* The registers pointing to the local stack */
|
|
ENV = PtoLocAdjust(ENV);
|
|
ASP = PtoLocAdjust(ASP);
|
|
LCL0 = PtoLocAdjust(LCL0);
|
|
B = ChoicePtrAdjust(B);
|
|
#ifdef TABLING
|
|
B_FZ = ChoicePtrAdjust(B_FZ);
|
|
BB = ChoicePtrAdjust(BB);
|
|
TR_FZ = PtoTRAdjust(TR_FZ);
|
|
#endif
|
|
YENV = PtoLocAdjust(YENV);
|
|
if (MyTR)
|
|
MyTR = PtoTRAdjust(MyTR);
|
|
}
|
|
|
|
static void
|
|
MoveLocalAndTrail(void)
|
|
{
|
|
/* cpcellsd(To,From,NOfCells) - copy the cells downwards */
|
|
#if HAVE_MEMMOVE
|
|
cpcellsd(ASP, OldASP, (CELL *)OldTR - OldASP);
|
|
#else
|
|
cpcellsd((CELL *)TR, (CELL *)OldTR, (CELL *)OldTR - OldASP);
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
MoveGlobal(void)
|
|
{
|
|
/*
|
|
* cpcellsd(To,From,NOfCells) - copy the cells downwards - in
|
|
* absmi.asm
|
|
*/
|
|
#if HAVE_MEMMOVE
|
|
cpcellsd((CELL *)Yap_GlobalBase, (CELL *)OldGlobalBase, OldH - (CELL *)OldGlobalBase);
|
|
#else
|
|
cpcellsd(H, OldH, OldH - (CELL *)OldGlobalBase);
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
MoveGlobalOnly(void)
|
|
{
|
|
/*
|
|
* cpcellsd(To,From,NOfCells) - copy the cells downwards - in
|
|
* absmi.asm
|
|
*/
|
|
#if HAVE_MEMMOVE
|
|
cpcellsd(H0, OldH0, OldH - OldH0);
|
|
#else
|
|
cpcellsd(H, OldH, OldH - OldH0);
|
|
#endif
|
|
}
|
|
|
|
static inline CELL
|
|
AdjustAppl(register CELL t0)
|
|
{
|
|
register CELL *t = RepAppl(t0);
|
|
|
|
if (IsOldGlobalPtr(t))
|
|
return (AbsAppl(PtoGloAdjust(t)));
|
|
else if (IsOldDelayPtr(t))
|
|
return (AbsAppl(PtoDelayAdjust(t)));
|
|
else if (IsOldTrailPtr(t))
|
|
return (AbsAppl(CellPtoTRAdjust(t)));
|
|
else if (IsHeapP(t))
|
|
return (AbsAppl(CellPtoHeapAdjust(t)));
|
|
#ifdef DEBUG
|
|
else {
|
|
/* strange cell */
|
|
/* fprintf(Yap_stderr,"[ garbage appl %lx found in stacks by stack shifter ]\n", t0);*/
|
|
}
|
|
#endif
|
|
return(t0);
|
|
}
|
|
|
|
static inline CELL
|
|
AdjustPair(register CELL t0)
|
|
{
|
|
register CELL *t = RepPair(t0);
|
|
|
|
if (IsOldGlobalPtr(t))
|
|
return (AbsPair(PtoGloAdjust(t)));
|
|
if (IsOldDelayPtr(t))
|
|
return (AbsPair(PtoDelayAdjust(t)));
|
|
if (IsOldTrailPtr(t))
|
|
return (AbsPair(CellPtoTRAdjust(t)));
|
|
else if (IsHeapP(t))
|
|
return (AbsPair(CellPtoHeapAdjust(t)));
|
|
#ifdef DEBUG
|
|
/* fprintf(Yap_stderr,"[ garbage pair %lx found in stacks by stack shifter ]\n", t0);*/
|
|
#endif
|
|
return(t0);
|
|
}
|
|
|
|
static void
|
|
AdjustTrail(int adjusting_heap)
|
|
{
|
|
register tr_fr_ptr ptt;
|
|
|
|
ptt = TR;
|
|
/* moving the trail is simple */
|
|
while (ptt != (tr_fr_ptr)Yap_TrailBase) {
|
|
register CELL reg = TrailTerm(ptt-1);
|
|
#ifdef FROZEN_STACKS
|
|
register CELL reg2 = TrailVal(ptt-1);
|
|
#endif
|
|
|
|
ptt--;
|
|
if (IsVarTerm(reg)) {
|
|
if (IsOldLocalInTR(reg))
|
|
TrailTerm(ptt) = LocalAdjust(reg);
|
|
else if (IsOldGlobal(reg))
|
|
TrailTerm(ptt) = GlobalAdjust(reg);
|
|
else if (IsOldDelay(reg))
|
|
TrailTerm(ptt) = DelayAdjust(reg);
|
|
else if (IsOldTrail(reg))
|
|
TrailTerm(ptt) = TrailAdjust(reg);
|
|
else if (IsOldCode(reg)) {
|
|
CELL *ptr;
|
|
TrailTerm(ptt) = reg = CodeAdjust(reg);
|
|
ptr = (CELL *)reg;
|
|
if (IsApplTerm(*ptr)) {
|
|
*ptr = AdjustAppl(*ptr);
|
|
} else if (IsPairTerm(*ptr)) {
|
|
*ptr = AdjustAppl(*ptr);
|
|
}
|
|
#ifdef DEBUG
|
|
else
|
|
fprintf(Yap_stderr,"[ garbage heap ptr %p to %lx found in trail at %p by stack shifter ]\n", ptr, (unsigned long int)*ptr, ptt);
|
|
#endif
|
|
}
|
|
} else if (IsPairTerm(reg)) {
|
|
TrailTerm(ptt) = AdjustPair(reg);
|
|
#ifdef MULTI_ASSIGNMENT_VARIABLES /* does not work with new structures */
|
|
/* check it whether we are protecting a
|
|
multi-assignment */
|
|
} else if (IsApplTerm(reg)) {
|
|
TrailTerm(ptt) = AdjustAppl(reg);
|
|
#endif
|
|
}
|
|
#ifdef FROZEN_STACKS
|
|
if (IsVarTerm(reg2)) {
|
|
if (IsOldLocal(reg2))
|
|
TrailVal(ptt) = LocalAdjust(reg2);
|
|
else if (IsOldGlobal(reg2))
|
|
TrailVal(ptt) = GlobalAdjust(reg2);
|
|
else if (IsOldDelay(reg2))
|
|
TrailVal(ptt) = DelayAdjust(reg2);
|
|
else if (IsOldTrail(reg2))
|
|
TrailVal(ptt) = TrailAdjust(reg2);
|
|
else if (IsOldCode(reg2))
|
|
TrailVal(ptt) = CodeAdjust(reg2);
|
|
} else if (IsApplTerm(reg2)) {
|
|
TrailVal(ptt) = AdjustAppl(reg2);
|
|
} else if (IsPairTerm(reg2)) {
|
|
TrailVal(ptt) = AdjustPair(reg2);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
}
|
|
|
|
static void
|
|
AdjustLocal(void)
|
|
{
|
|
register CELL reg, *pt;
|
|
|
|
/* Adjusting the local */
|
|
pt = LCL0;
|
|
while (pt > ASP) {
|
|
reg = *--pt;
|
|
if (IsVarTerm(reg)) {
|
|
if (IsOldLocal(reg))
|
|
*pt = LocalAdjust(reg);
|
|
else if (IsOldGlobal(reg))
|
|
*pt = GlobalAdjust(reg);
|
|
else if (IsOldDelay(reg))
|
|
*pt = DelayAdjust(reg);
|
|
else if (IsOldTrail(reg))
|
|
*pt = TrailAdjust(reg);
|
|
else if (IsOldCode(reg))
|
|
*pt = CodeAdjust(reg);
|
|
} else if (IsApplTerm(reg)) {
|
|
*pt = AdjustAppl(reg);
|
|
} else if (IsPairTerm(reg)) {
|
|
*pt = AdjustPair(reg);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
static void
|
|
AdjustGlobal(void)
|
|
{
|
|
register CELL *pt;
|
|
|
|
/*
|
|
* to clean the global now that functors are just variables pointing to
|
|
* the code
|
|
*/
|
|
pt = CellPtr(Yap_GlobalBase);
|
|
while (pt < H) {
|
|
register CELL reg;
|
|
|
|
reg = *pt;
|
|
if (IsVarTerm(reg)) {
|
|
if (IsOldGlobal(reg))
|
|
*pt = GlobalAdjust(reg);
|
|
if (IsOldDelay(reg))
|
|
*pt = DelayAdjust(reg);
|
|
else if (IsOldLocal(reg))
|
|
*pt = LocalAdjust(reg);
|
|
else if (IsOldCode(reg)) {
|
|
Functor f;
|
|
f = (Functor)(*pt = CodeAdjust(reg));
|
|
if (f <= FunctorDouble && f >= FunctorLongInt) {
|
|
/* skip bitmaps */
|
|
switch((CELL)f) {
|
|
case (CELL)FunctorDouble:
|
|
#if SIZEOF_DOUBLE == 2*SIZEOF_LONG_INT
|
|
pt += 3;
|
|
#else
|
|
pt += 2;
|
|
#endif
|
|
break;
|
|
#if USE_GMP
|
|
case (CELL)FunctorBigInt:
|
|
{
|
|
Int sz = 1+
|
|
sizeof(MP_INT)+
|
|
(((MP_INT *)(pt+1))->_mp_alloc*sizeof(mp_limb_t));
|
|
pt += sz;
|
|
}
|
|
break;
|
|
#endif
|
|
case (CELL)FunctorLongInt:
|
|
default:
|
|
pt += 2;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#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++;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* When growing the stack we need to adjust: the local stack cells pointing
|
|
* to the local; the local stack cells and the X terms pointing to the global
|
|
* (just once) the trail cells pointing both to the global and to the local
|
|
*/
|
|
static void
|
|
AdjustStacksAndTrail(void)
|
|
{
|
|
AdjustTrail(TRUE);
|
|
AdjustLocal();
|
|
AdjustGlobal();
|
|
}
|
|
|
|
void
|
|
Yap_AdjustStacksAndTrail(void)
|
|
{
|
|
AdjustStacksAndTrail();
|
|
}
|
|
|
|
/*
|
|
* When growing the stack we need to adjust: the local cells pointing to the
|
|
* local; the trail cells pointing to the local
|
|
*/
|
|
static void
|
|
AdjustGrowStack(void)
|
|
{
|
|
AdjustTrail(FALSE);
|
|
AdjustLocal();
|
|
}
|
|
|
|
static void
|
|
AdjustRegs(int n)
|
|
{
|
|
int i;
|
|
CELL reg;
|
|
|
|
for (i = 1; i < n; ++i) {
|
|
reg = (CELL) XREGS[i];
|
|
if (IsVarTerm(reg)) {
|
|
if (IsOldLocal(reg))
|
|
reg = LocalAdjust(reg);
|
|
else if (IsOldGlobal(reg))
|
|
reg = GlobalAdjust(reg);
|
|
else if (IsOldDelay(reg))
|
|
reg = DelayAdjust(reg);
|
|
else if (IsOldTrail(reg))
|
|
reg = TrailAdjust(reg);
|
|
else if (IsOldCode(reg))
|
|
reg = CodeAdjust(reg);
|
|
} else if (IsApplTerm(reg))
|
|
reg = AdjustAppl(reg);
|
|
else if (IsPairTerm(reg))
|
|
reg = AdjustPair(reg);
|
|
XREGS[i] = (Term) reg;
|
|
}
|
|
}
|
|
|
|
void
|
|
Yap_AdjustRegs(int n)
|
|
{
|
|
AdjustRegs(n);
|
|
}
|
|
|
|
/* Used by do_goal() when we're short of heap space */
|
|
static int
|
|
static_growheap(long size, int fix_code)
|
|
{
|
|
Int start_growth_time, growth_time;
|
|
int gc_verbose;
|
|
|
|
/* adjust to a multiple of 256) */
|
|
size = AdjustPageSize(size);
|
|
Yap_ErrorMessage = NULL;
|
|
if (!Yap_ExtendWorkSpace(size)) {
|
|
strncat(Yap_ErrorMessage,": heap crashed against stacks", MAX_ERROR_MSG_SIZE);
|
|
return(FALSE);
|
|
}
|
|
start_growth_time = Yap_cputime();
|
|
gc_verbose = Yap_is_gc_verbose();
|
|
heap_overflows++;
|
|
if (gc_verbose) {
|
|
fprintf(Yap_stderr, "[HO] Heap overflow %d\n", heap_overflows);
|
|
fprintf(Yap_stderr, "[HO] growing the heap %ld bytes\n", size);
|
|
}
|
|
ASP -= 256;
|
|
TrDiff = LDiff = GDiff = DelayDiff = size;
|
|
XDiff = HDiff = 0;
|
|
YAPEnterCriticalSection();
|
|
SetHeapRegs();
|
|
MoveLocalAndTrail();
|
|
if (fix_code) {
|
|
CELL *SaveOldH = OldH;
|
|
OldH = (CELL *)freep;
|
|
MoveGlobal();
|
|
OldH = SaveOldH;
|
|
} else {
|
|
MoveGlobal();
|
|
}
|
|
AdjustStacksAndTrail();
|
|
AdjustRegs(MaxTemps);
|
|
YAPLeaveCriticalSection();
|
|
ASP += 256;
|
|
growth_time = Yap_cputime()-start_growth_time;
|
|
total_heap_overflow_time += growth_time;
|
|
if (gc_verbose) {
|
|
fprintf(Yap_stderr, "[HO] took %g sec\n", (double)growth_time/1000);
|
|
fprintf(Yap_stderr, "[HO] Total of %g sec expanding heap \n", (double)total_heap_overflow_time/1000);
|
|
}
|
|
return(TRUE);
|
|
}
|
|
|
|
/* Used by do_goal() when we're short of heap space */
|
|
static int
|
|
static_growglobal(long size, CELL **ptr)
|
|
{
|
|
Int start_growth_time, growth_time;
|
|
int gc_verbose;
|
|
|
|
/* adjust to a multiple of 256) */
|
|
size = AdjustPageSize(size);
|
|
Yap_ErrorMessage = NULL;
|
|
if (!Yap_ExtendWorkSpace(size)) {
|
|
strncat(Yap_ErrorMessage,": global crashed against local", MAX_ERROR_MSG_SIZE);
|
|
return(FALSE);
|
|
}
|
|
start_growth_time = Yap_cputime();
|
|
gc_verbose = Yap_is_gc_verbose();
|
|
delay_overflows++;
|
|
if (gc_verbose) {
|
|
fprintf(Yap_stderr, "[DO] Delay overflow %d\n", delay_overflows);
|
|
fprintf(Yap_stderr, "[DO] growing the stacks %ld bytes\n", size);
|
|
}
|
|
ASP -= 256;
|
|
TrDiff = LDiff = GDiff = size;
|
|
XDiff = HDiff = DelayDiff = 0;
|
|
YAPEnterCriticalSection();
|
|
SetHeapRegs();
|
|
MoveLocalAndTrail();
|
|
MoveGlobalOnly();
|
|
AdjustStacksAndTrail();
|
|
AdjustRegs(MaxTemps);
|
|
if (ptr)
|
|
*ptr = PtoLocAdjust(*ptr);
|
|
YAPLeaveCriticalSection();
|
|
ASP += 256;
|
|
growth_time = Yap_cputime()-start_growth_time;
|
|
total_delay_overflow_time += growth_time;
|
|
if (gc_verbose) {
|
|
fprintf(Yap_stderr, "[DO] took %g sec\n", (double)growth_time/1000);
|
|
fprintf(Yap_stderr, "[DO] Total of %g sec expanding stacks \n", (double)total_delay_overflow_time/1000);
|
|
}
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
static void
|
|
fix_compiler_instructions(PInstr *pcpc)
|
|
{
|
|
while (pcpc != NULL) {
|
|
PInstr *ncpc = pcpc->nextInst;
|
|
|
|
switch(pcpc->op) {
|
|
/* check c_var for functions that point at variables */
|
|
case get_var_op:
|
|
case get_val_op:
|
|
case unify_var_op:
|
|
case unify_last_var_op:
|
|
case unify_val_op:
|
|
case unify_last_val_op:
|
|
case put_var_op:
|
|
case put_val_op:
|
|
case write_var_op:
|
|
case write_val_op:
|
|
case f_var_op:
|
|
case f_val_op:
|
|
case fetch_args_for_bccall:
|
|
case bccall_op:
|
|
case save_pair_op:
|
|
case save_appl_op:
|
|
case save_b_op:
|
|
case comit_b_op:
|
|
pcpc->rnd1 = GlobalAdjust(pcpc->rnd1);
|
|
break;
|
|
default:
|
|
/* hopefully nothing to do */
|
|
break;
|
|
}
|
|
if (ncpc != NULL) {
|
|
ncpc = (PInstr *)GlobalAddrAdjust((ADDR)(pcpc->nextInst));
|
|
pcpc->nextInst = ncpc;
|
|
}
|
|
pcpc = ncpc;
|
|
}
|
|
}
|
|
|
|
#ifdef TABLING
|
|
static void
|
|
fix_tabling_info(void)
|
|
{
|
|
/* we must fix the dependency frames and the subgoal frames, as they are
|
|
pointing back to the global stack. */
|
|
struct dependency_frame *df;
|
|
struct subgoal_frame *sg;
|
|
|
|
df = LOCAL_top_dep_fr;
|
|
while (df != NULL) {
|
|
if (DepFr_backchain_cp(df))
|
|
DepFr_backchain_cp(df) = ChoicePtrAdjust(DepFr_backchain_cp(df));
|
|
DepFr_leader_cp(df) = ChoicePtrAdjust(DepFr_leader_cp(df));
|
|
DepFr_cons_cp(df) = ConsumerChoicePtrAdjust(DepFr_cons_cp(df));
|
|
df = DepFr_next(df);
|
|
}
|
|
sg = LOCAL_top_sg_fr;
|
|
while (sg != NULL) {
|
|
SgFr_gen_cp(sg) = GeneratorChoicePtrAdjust(SgFr_gen_cp(sg));
|
|
sg = SgFr_next(sg);
|
|
}
|
|
}
|
|
#endif /* TABLING */
|
|
|
|
int
|
|
Yap_growheap(int fix_code)
|
|
{
|
|
unsigned long size = sizeof(CELL) * 16 * 1024L;
|
|
int shift_factor = (heap_overflows > 8 ? 8 : heap_overflows);
|
|
unsigned long sz = size << shift_factor;
|
|
|
|
#if defined(YAPOR) || defined(THREADS)
|
|
if (NOfThreads != 1) {
|
|
Yap_Error(SYSTEM_ERROR,TermNil,"cannot grow Heap: more than a worker/thread running");
|
|
return(FALSE);
|
|
}
|
|
#endif
|
|
if (SizeOfOverflow > sz)
|
|
sz = AdjustPageSize(SizeOfOverflow);
|
|
while(sz >= sizeof(CELL) * 16 * 1024L && !static_growheap(sz, fix_code)) {
|
|
size = size/2;
|
|
sz = size << shift_factor;
|
|
}
|
|
/* we must fix an instruction chain */
|
|
if (fix_code) {
|
|
PInstr *pcpc = CodeStart;
|
|
if (pcpc != NULL) {
|
|
CodeStart = pcpc = (PInstr *)GlobalAddrAdjust((ADDR)pcpc);
|
|
}
|
|
fix_compiler_instructions(pcpc);
|
|
pcpc = BlobsStart;
|
|
if (pcpc != NULL) {
|
|
BlobsStart = pcpc = (PInstr *)GlobalAddrAdjust((ADDR)pcpc);
|
|
}
|
|
fix_compiler_instructions(pcpc);
|
|
freep = (char *)GlobalAddrAdjust((ADDR)freep);
|
|
label_offset = (int *)GlobalAddrAdjust((ADDR)label_offset);
|
|
}
|
|
#ifdef TABLING
|
|
fix_tabling_info();
|
|
#endif
|
|
if (sz >= sizeof(CELL) * 16 * 1024L) {
|
|
return (TRUE);
|
|
}
|
|
/* failed */
|
|
return(FALSE);
|
|
}
|
|
|
|
int
|
|
Yap_growglobal(CELL **ptr)
|
|
{
|
|
unsigned long sz = sizeof(CELL) * 16 * 1024L;
|
|
|
|
#if defined(YAPOR) || defined(THREADS)
|
|
if (NOfThreads != 1) {
|
|
Yap_Error(SYSTEM_ERROR,TermNil,"cannot grow Global: more than a worker/thread running");
|
|
return(FALSE);
|
|
}
|
|
#endif
|
|
if (!static_growglobal(sz, ptr))
|
|
return(FALSE);
|
|
#ifdef TABLING
|
|
fix_tabling_info();
|
|
#endif
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
/* Used by do_goal() when we're short of stack space */
|
|
static int
|
|
growstack(long size)
|
|
{
|
|
Int start_growth_time, growth_time;
|
|
int gc_verbose;
|
|
|
|
#if defined(YAPOR) || defined(THREADS)
|
|
if (NOfThreads != 1) {
|
|
Yap_Error(SYSTEM_ERROR,TermNil,"cannot grow Local: more than a worker/thread running");
|
|
return(FALSE);
|
|
}
|
|
#endif
|
|
/* adjust to a multiple of 256) */
|
|
size = AdjustPageSize(size);
|
|
Yap_ErrorMessage = NULL;
|
|
if (!Yap_ExtendWorkSpace(size)) {
|
|
strncat(Yap_ErrorMessage,": local crashed against global", MAX_ERROR_MSG_SIZE);
|
|
return(FALSE);
|
|
}
|
|
start_growth_time = Yap_cputime();
|
|
gc_verbose = Yap_is_gc_verbose();
|
|
stack_overflows++;
|
|
if (gc_verbose) {
|
|
fprintf(Yap_stderr, "[SO] Stack Overflow %d\n", stack_overflows);
|
|
fprintf(Yap_stderr, "[SO] Heap: %8ld cells (%p-%p)\n", (unsigned long int)(H-(CELL *)Yap_GlobalBase),Yap_GlobalBase,H);
|
|
fprintf(Yap_stderr, "[SO] Local:%8ld cells (%p-%p)\n", (unsigned long int)(LCL0-ASP),LCL0,ASP);
|
|
fprintf(Yap_stderr, "[SO] Trail:%8ld cells (%p-%p)\n",
|
|
(unsigned long int)(TR-(tr_fr_ptr)Yap_TrailBase),Yap_TrailBase,TR);
|
|
fprintf(Yap_stderr, "[SO] growing the stacks %ld bytes\n", size);
|
|
}
|
|
TrDiff = LDiff = size;
|
|
XDiff = HDiff = GDiff = DelayDiff = 0;
|
|
ASP -= 256;
|
|
YAPEnterCriticalSection();
|
|
SetStackRegs();
|
|
MoveLocalAndTrail();
|
|
AdjustGrowStack();
|
|
AdjustRegs(MaxTemps);
|
|
#ifdef TABLING
|
|
fix_tabling_info();
|
|
#endif
|
|
YAPLeaveCriticalSection();
|
|
CreepFlag = CalculateStackGap();
|
|
ASP += 256;
|
|
growth_time = Yap_cputime()-start_growth_time;
|
|
total_stack_overflow_time += growth_time;
|
|
if (gc_verbose) {
|
|
fprintf(Yap_stderr, "[SO] took %g sec\n", (double)growth_time/1000);
|
|
fprintf(Yap_stderr, "[SO] Total of %g sec expanding stacks \n", (double)total_stack_overflow_time/1000);
|
|
}
|
|
return(TRUE);
|
|
}
|
|
|
|
int
|
|
Yap_growstack(long size)
|
|
{
|
|
return growstack(size);
|
|
}
|
|
|
|
static void
|
|
AdjustVarTable(VarEntry *ves)
|
|
{
|
|
ves->VarAdr = TermNil;
|
|
if (ves->VarRight != NULL) {
|
|
ves->VarRight = (VarEntry *)TrailAddrAdjust((ADDR)(ves->VarRight));
|
|
AdjustVarTable(ves->VarRight);
|
|
}
|
|
if (ves->VarLeft != NULL) {
|
|
ves->VarLeft = (VarEntry *)TrailAddrAdjust((ADDR)(ves->VarLeft));
|
|
AdjustVarTable(ves->VarLeft);
|
|
}
|
|
}
|
|
|
|
/*
|
|
If we have to shift while we are scanning we need to adjust all
|
|
pointers created by the scanner (Tokens and Variables)
|
|
*/
|
|
static void
|
|
AdjustScannerStacks(TokEntry **tksp, VarEntry **vep)
|
|
{
|
|
TokEntry *tks = *tksp;
|
|
VarEntry *ves = *vep;
|
|
|
|
if (tks != NULL) {
|
|
tks = *tksp = TokEntryAdjust(tks);
|
|
}
|
|
while (tks != NULL) {
|
|
TokEntry *tktmp;
|
|
|
|
switch (tks->Tok) {
|
|
case Var_tok:
|
|
case String_tok:
|
|
tks->TokInfo = TrailAdjust(tks->TokInfo);
|
|
break;
|
|
case Name_tok:
|
|
tks->TokInfo = (Term)AtomAdjust((Atom)(tks->TokInfo));
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
tktmp = tks->TokNext;
|
|
if (tktmp != NULL) {
|
|
tktmp = TokEntryAdjust(tktmp);
|
|
tks->TokNext = tktmp;
|
|
}
|
|
tks = tktmp;
|
|
}
|
|
if (ves != NULL) {
|
|
ves = *vep = (VarEntry *)TrailAddrAdjust((ADDR)ves);
|
|
AdjustVarTable(ves);
|
|
}
|
|
ves = Yap_AnonVarTable;
|
|
if (ves != NULL) {
|
|
ves = Yap_AnonVarTable = VarEntryAdjust(ves);
|
|
}
|
|
while (ves != NULL) {
|
|
VarEntry *vetmp = ves->VarLeft;
|
|
if (vetmp != NULL) {
|
|
vetmp = VarEntryAdjust(vetmp);
|
|
ves->VarLeft = vetmp;
|
|
}
|
|
ves->VarAdr = TermNil;
|
|
ves = vetmp;
|
|
}
|
|
}
|
|
|
|
/* Used by parser when we're short of stack space */
|
|
int
|
|
Yap_growstack_in_parser(tr_fr_ptr *old_trp, TokEntry **tksp, VarEntry **vep)
|
|
{
|
|
Int start_growth_time, growth_time;
|
|
int gc_verbose;
|
|
long size = sizeof(CELL)*(LCL0-(CELL *)Yap_GlobalBase);
|
|
|
|
#if defined(YAPOR) || defined(THREADS)
|
|
if (NOfThreads != 1) {
|
|
Yap_Error(SYSTEM_ERROR,TermNil,"cannot grow Parser Stack: more than a worker/thread running");
|
|
return(FALSE);
|
|
}
|
|
#endif
|
|
/* adjust to a multiple of 256) */
|
|
size = AdjustPageSize(size);
|
|
Yap_ErrorMessage = NULL;
|
|
if (!Yap_ExtendWorkSpace(size)) {
|
|
strncat(Yap_ErrorMessage,": parser stack overflowed", MAX_ERROR_MSG_SIZE);
|
|
return(FALSE);
|
|
}
|
|
start_growth_time = Yap_cputime();
|
|
gc_verbose = Yap_is_gc_verbose();
|
|
stack_overflows++;
|
|
if (gc_verbose) {
|
|
fprintf(Yap_stderr, "[SO] Stack overflow %d\n", stack_overflows);
|
|
fprintf(Yap_stderr, "[SO] Heap: %8ld cells (%p-%p)\n", (unsigned long int)(H-(CELL *)Yap_GlobalBase),(CELL *)Yap_GlobalBase,H);
|
|
fprintf(Yap_stderr, "[SO] Local:%8ld cells (%p-%p)\n", (unsigned long int)(LCL0-ASP),LCL0,ASP);
|
|
fprintf(Yap_stderr, "[SO] Trail:%8ld cells (%p-%p)\n",
|
|
(unsigned long int)(TR-(tr_fr_ptr)Yap_TrailBase),Yap_TrailBase,TR);
|
|
fprintf(Yap_stderr, "[SO] growing the stacks %ld bytes\n", size);
|
|
}
|
|
TrDiff = LDiff = size;
|
|
XDiff = HDiff = GDiff = DelayDiff = 0;
|
|
ASP -= 256;
|
|
YAPEnterCriticalSection();
|
|
SetStackRegs();
|
|
MoveLocalAndTrail();
|
|
AdjustScannerStacks(tksp, vep);
|
|
{
|
|
tr_fr_ptr nTR;
|
|
nTR = TR;
|
|
*old_trp = PtoTRAdjust(*old_trp);
|
|
TR = *old_trp;
|
|
AdjustGrowStack();
|
|
TR = nTR;
|
|
}
|
|
AdjustRegs(MaxTemps);
|
|
YAPLeaveCriticalSection();
|
|
CreepFlag = CalculateStackGap();
|
|
ASP += 256;
|
|
growth_time = Yap_cputime()-start_growth_time;
|
|
total_stack_overflow_time += growth_time;
|
|
if (gc_verbose) {
|
|
fprintf(Yap_stderr, "[SO] took %g sec\n", (double)growth_time/1000);
|
|
fprintf(Yap_stderr, "[SO] Total of %g sec expanding stacks \n", (double)total_stack_overflow_time/1000);
|
|
}
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
/* Used by do_goal() when we're short of stack space */
|
|
int
|
|
Yap_growtrail(long size)
|
|
{
|
|
Int start_growth_time = Yap_cputime(), growth_time;
|
|
int gc_verbose = Yap_is_gc_verbose();
|
|
|
|
#if defined(YAPOR) || defined(THREADS)
|
|
if (NOfThreads != 1) {
|
|
Yap_Error(SYSTEM_ERROR,TermNil,"cannot grow trail: more than a worker/thread running");
|
|
return(FALSE);
|
|
}
|
|
#endif
|
|
/* adjust to a multiple of 256) */
|
|
size = AdjustPageSize(size);
|
|
trail_overflows++;
|
|
if (gc_verbose) {
|
|
fprintf(Yap_stderr, "[TO] Trail overflow %d\n", trail_overflows);
|
|
fprintf(Yap_stderr, "[TO] growing the trail %ld bytes\n", size);
|
|
}
|
|
Yap_ErrorMessage = NULL;
|
|
if (!Yap_ExtendWorkSpace(size)) {
|
|
strncat(Yap_ErrorMessage,": trail stack overflowed", MAX_ERROR_MSG_SIZE);
|
|
return(FALSE);
|
|
}
|
|
YAPEnterCriticalSection();
|
|
Yap_TrailTop += size;
|
|
YAPLeaveCriticalSection();
|
|
growth_time = Yap_cputime()-start_growth_time;
|
|
total_trail_overflow_time += growth_time;
|
|
if (gc_verbose) {
|
|
fprintf(Yap_stderr, "[TO] took %g sec\n", (double)growth_time/1000);
|
|
fprintf(Yap_stderr, "[TO] Total of %g sec expanding stacks \n", (double)total_stack_overflow_time/1000);
|
|
}
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
static Int
|
|
p_inform_trail_overflows(void)
|
|
{
|
|
Term tn = MkIntTerm(trail_overflows);
|
|
Term tt = MkIntegerTerm(total_trail_overflow_time);
|
|
|
|
return(Yap_unify(tn, ARG1) && Yap_unify(tt, ARG2));
|
|
}
|
|
|
|
/* :- grow_heap(Size) */
|
|
static Int
|
|
p_growheap(void)
|
|
{
|
|
Int diff;
|
|
Term t1 = Deref(ARG1);
|
|
|
|
if (IsVarTerm(t1)) {
|
|
Yap_Error(INSTANTIATION_ERROR, t1, "grow_heap/1");
|
|
return(FALSE);
|
|
} else if (!IsIntTerm(t1)) {
|
|
Yap_Error(TYPE_ERROR_INTEGER, t1, "grow_heap/1");
|
|
return(FALSE);
|
|
}
|
|
diff = IntOfTerm(t1);
|
|
if (diff < 0) {
|
|
Yap_Error(DOMAIN_ERROR_NOT_LESS_THAN_ZERO, t1, "grow_heap/1");
|
|
}
|
|
return(static_growheap(diff, FALSE));
|
|
}
|
|
|
|
static Int
|
|
p_inform_heap_overflows(void)
|
|
{
|
|
Term tn = MkIntTerm(heap_overflows);
|
|
Term tt = MkIntegerTerm(total_heap_overflow_time);
|
|
|
|
return(Yap_unify(tn, ARG1) && Yap_unify(tt, ARG2));
|
|
}
|
|
|
|
/* :- grow_stack(Size) */
|
|
static Int
|
|
p_growstack(void)
|
|
{
|
|
Int diff;
|
|
Term t1 = Deref(ARG1);
|
|
|
|
if (IsVarTerm(t1)) {
|
|
Yap_Error(INSTANTIATION_ERROR, t1, "grow_stack/1");
|
|
return(FALSE);
|
|
} else if (!IsIntTerm(t1)) {
|
|
Yap_Error(TYPE_ERROR_INTEGER, t1, "grow_stack/1");
|
|
return(FALSE);
|
|
}
|
|
diff = IntOfTerm(t1);
|
|
if (diff < 0) {
|
|
Yap_Error(DOMAIN_ERROR_NOT_LESS_THAN_ZERO, t1, "grow_stack/1");
|
|
}
|
|
return(growstack(diff));
|
|
}
|
|
|
|
static Int
|
|
p_inform_stack_overflows(void)
|
|
{
|
|
Term tn = MkIntTerm(stack_overflows);
|
|
Term tt = MkIntegerTerm(total_stack_overflow_time);
|
|
|
|
return(Yap_unify(tn, ARG1) && Yap_unify(tt, ARG2));
|
|
|
|
}
|
|
|
|
Int
|
|
Yap_total_stack_shift_time(void)
|
|
{
|
|
return(total_heap_overflow_time+
|
|
total_stack_overflow_time+
|
|
total_trail_overflow_time);
|
|
}
|
|
|
|
void
|
|
Yap_InitGrowPreds(void)
|
|
{
|
|
Yap_InitCPred("$grow_heap", 1, p_growheap, SafePredFlag);
|
|
Yap_InitCPred("$grow_stack", 1, p_growstack, SafePredFlag);
|
|
Yap_InitCPred("$inform_trail_overflows", 2, p_inform_trail_overflows, SafePredFlag);
|
|
Yap_InitCPred("$inform_heap_overflows", 2, p_inform_heap_overflows, SafePredFlag);
|
|
Yap_InitCPred("$inform_stack_overflows", 2, p_inform_stack_overflows, SafePredFlag);
|
|
Yap_init_gc();
|
|
Yap_init_agc();
|
|
}
|