mirror of
https://git.code.sf.net/p/newrpl/sources
synced 2024-11-16 19:51:25 +01:00
7cba1a3e9b
Improved memory handling during GC.
203 lines
5.4 KiB
C
203 lines
5.4 KiB
C
/*
|
|
* Copyright (c) 2014, Claudio Lapilli and the newRPL Team
|
|
* All rights reserved.
|
|
* This file is released under the 3-clause BSD license.
|
|
* See the file LICENSE.txt that shipped with this distribution.
|
|
*/
|
|
|
|
#include "newrpl.h"
|
|
#include "hal.h"
|
|
|
|
|
|
// ALLOCATES MEMORY FROM TEMPOB
|
|
// SIZE IS THE NUMBER OF WORDS REQUIRED, NOT COUNTING THE PROLOG!
|
|
// IT AUTOMATICALLY RESERVES ONE EXTRA WORD FOR THE PROLOG
|
|
|
|
WORDPTR rplAllocTempOb(WORD size)
|
|
{
|
|
// SIMPLY ADD A NEW BLOCK AT END OF CHAIN
|
|
|
|
if( TempObEnd+size+1+TEMPOBSLACK>TempObSize) {
|
|
// ENLARGE TEMPOB AS NEEDED
|
|
growTempOb((BINT)(TempObEnd-TempOb)+size+1+TEMPOBSLACK);
|
|
if(Exceptions) return 0;
|
|
}
|
|
|
|
rplAddTempBlock(TempObEnd);
|
|
if(Exceptions) return 0;
|
|
|
|
WORDPTR ptr=TempObEnd;
|
|
TempObEnd+=size+1;
|
|
return ptr;
|
|
}
|
|
|
|
|
|
// TRUNCATES A RECENTLY ALLOCATED BLOCK AT THE END OF TEMPOB
|
|
// IT HAS TO BE THE LAST BLOCK ALLOCATED WITH ALLOCTEMPOB
|
|
void rplTruncateLastObject(WORDPTR newend)
|
|
{
|
|
|
|
if(newend<=*(TempBlocksEnd-1)) {
|
|
// TRIED TO TRUNCATE BEYOND THE LAST OBJECT, CAN'T ALLOW THAT
|
|
// REMOVE LAST ALLOCATED BLOCK COMPLETELY
|
|
--TempBlocksEnd;
|
|
TempObEnd=*TempBlocksEnd;
|
|
return;
|
|
}
|
|
TempObEnd=newend;
|
|
}
|
|
|
|
// RESIZE THE LAST OBJECT BY APPENDING WORDS AT THE END OF TEMPOB
|
|
// DOES NOT CREATE A NEW OBJECT OR A NEW BLOCK
|
|
// APPEND additionalsize WORDS TO THE END OF TEMPOB
|
|
|
|
void rplResizeLastObject(WORD additionalsize)
|
|
{
|
|
if( TempObEnd+additionalsize+TEMPOBSLACK>TempObSize) {
|
|
// ENLARGE TEMPOB AS NEEDED
|
|
growTempOb((BINT)(TempObEnd-TempOb)+additionalsize+TEMPOBSLACK);
|
|
if(Exceptions) return;
|
|
}
|
|
|
|
TempObEnd+=additionalsize;
|
|
|
|
}
|
|
|
|
|
|
|
|
// BORROW THE PATCH FUNCTION FROM THE GARBAGE COLLECTOR
|
|
void Patch(WORDPTR *start,WORDPTR *end,WORDPTR startfrom,WORDPTR endfrom,BINT offset);
|
|
|
|
// GROW THE TEMPORARY OBJECT MEMORY
|
|
|
|
void growTempOb(WORD newtotalsize)
|
|
{
|
|
WORDPTR *newtempob;
|
|
WORD slack=newtotalsize-(WORD)(TempObEnd-TempOb);
|
|
BINT gc_done=0;
|
|
|
|
do {
|
|
newtotalsize=(newtotalsize+1023)&~1023;
|
|
|
|
newtempob=halGrowMemory(MEM_AREA_TEMPOB,(WORDPTR *)TempOb,newtotalsize);
|
|
|
|
if(!newtempob) {
|
|
if(!gc_done) {
|
|
rplGCollect(); ++gc_done; newtotalsize=(WORD)(TempObEnd-TempOb)+slack; }
|
|
else {
|
|
rplException(EX_OUTOFMEM);
|
|
return;
|
|
}
|
|
}
|
|
|
|
} while(!newtempob);
|
|
|
|
if(TempOb && (((WORDPTR *)TempOb)!=newtempob)) {
|
|
// TEMPOB HAD TO BE MOVED IN MEMORY
|
|
// FIX ALL DSTK/RSTK/TEMPBLOCKS/DIRECTORIES/LAMS POINTERS
|
|
|
|
Patch(DStk,DSTop,TempOb,TempObSize,newtempob-(WORDPTR *)TempOb); // DATA STACK
|
|
|
|
Patch(RStk,RSTop,TempOb,TempObSize,newtempob-(WORDPTR *)TempOb); // RETURN STACK
|
|
|
|
Patch(LAMs,LAMTop,TempOb,TempObSize,newtempob-(WORDPTR *)TempOb); // LOCAL VARIABLES
|
|
|
|
Patch(Directories,DirsTop,TempOb,TempObSize,newtempob-(WORDPTR *)TempOb); // GLOBAL VARIABLES
|
|
|
|
Patch(GC_PTRUpdate,GC_PTRUpdate+MAX_GC_PTRUPDATE,TempOb,TempObSize+1,newtempob-(WORDPTR *)TempOb); // SYSTEM POINTERS, USE TempObSize+1 TO UPDATE POINTERS POINTING TO END OF TEMPOB TOO
|
|
|
|
Patch(TempBlocks,TempBlocksEnd,TempOb,TempObSize,newtempob-(WORDPTR *)TempOb); // ALL TEMPBLOCK POINTERS
|
|
|
|
}
|
|
TempOb=(WORDPTR) newtempob;
|
|
TempObSize=TempOb+newtotalsize;
|
|
// FOR DEBUG ONLY
|
|
//halCheckRplMemory();
|
|
}
|
|
|
|
// SHRINK THE TEMPORARY OBJECT MEMORY
|
|
// SAME AS GROW BUT DOESN'T GARBAGE COLLECT AND RETRY
|
|
|
|
void shrinkTempOb(WORD newtotalsize)
|
|
{
|
|
WORDPTR *newtempob;
|
|
|
|
newtotalsize=(newtotalsize+1023)&~1023;
|
|
|
|
newtempob=halGrowMemory(MEM_AREA_TEMPOB,(WORDPTR *)TempOb,newtotalsize);
|
|
|
|
if(!newtempob) {
|
|
rplException(EX_OUTOFMEM);
|
|
return;
|
|
}
|
|
|
|
TempOb=(WORDPTR) newtempob;
|
|
TempObSize=TempOb+newtotalsize;
|
|
}
|
|
|
|
|
|
|
|
|
|
void growTempBlocks(WORD newtotalsize)
|
|
{
|
|
WORDPTR *newtempblocks;
|
|
WORD slack=newtotalsize-(WORD)(TempBlocksEnd-TempBlocks);
|
|
BINT gc_done=0;
|
|
|
|
do {
|
|
newtotalsize=(newtotalsize+1023)&~1023;
|
|
|
|
newtempblocks=halGrowMemory(MEM_AREA_TEMPBLOCKS,TempBlocks,newtotalsize);
|
|
|
|
if(!newtempblocks) {
|
|
if(!gc_done) {
|
|
rplGCollect();
|
|
++gc_done;
|
|
newtotalsize=(WORD)((TempBlocksEnd+slack)-TempBlocks); }
|
|
else {
|
|
rplException(EX_OUTOFMEM);
|
|
return;
|
|
}
|
|
}
|
|
|
|
} while(!newtempblocks);
|
|
|
|
TempBlocksEnd=TempBlocksEnd-TempBlocks+newtempblocks;
|
|
TempBlocks=newtempblocks;
|
|
TempBlocksSize=newtotalsize;
|
|
if(TempBlocksEnd>=TempBlocks+TempBlocksSize) throw_dbgexception("Bad TempBlocksEnd!",1);
|
|
|
|
// NOTHING TO FIX
|
|
}
|
|
|
|
void shrinkTempBlocks(WORD newtotalsize)
|
|
{
|
|
WORDPTR *newtempblocks;
|
|
|
|
newtotalsize=(newtotalsize+1023)&~1023;
|
|
|
|
newtempblocks=halGrowMemory(MEM_AREA_TEMPBLOCKS,TempBlocks,newtotalsize);
|
|
|
|
if(!newtempblocks) {
|
|
rplException(EX_OUTOFMEM);
|
|
return;
|
|
}
|
|
TempBlocksEnd=TempBlocksEnd-TempBlocks+newtempblocks;
|
|
TempBlocks=newtempblocks;
|
|
TempBlocksSize=newtotalsize;
|
|
|
|
if(TempBlocksEnd>=TempBlocks+TempBlocksSize) throw_dbgexception("Bad TempBlocksEnd!",__EX_CONT | __EX_RPLREGS);
|
|
// NOTHING TO FIX
|
|
}
|
|
|
|
|
|
// TEMPBLOCKS ARE INCREASE AFTER FOR WRITE, DECREASE BEFORE FOR READ.
|
|
|
|
void rplAddTempBlock(WORDPTR block)
|
|
{
|
|
*TempBlocksEnd++=block;
|
|
|
|
if(TempBlocksEnd+TEMPBLOCKSLACK>=TempBlocks+TempBlocksSize)
|
|
growTempBlocks(TempBlocksEnd-TempBlocks+TEMPBLOCKSLACK+1024);
|
|
if(Exceptions) return;
|
|
}
|