123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380 |
- #ifndef BB_THREADS
- #include "bbgc.h"
- #include "bbweakref.h"
- namespace bbDB{
- void stop();
-
- void stopped();
-
- void error( bbString err );
- }
- namespace bbGC{
- int memused;
-
- int malloced;
- size_t trigger=4*1024*1024;
- int suspended=1;
-
- int markedBit;
- int unmarkedBit;
- bbGCNode *markQueue;
- bbGCNode *markedList;
- bbGCNode *unmarkedList;
-
- bbGCRoot *roots;
-
- bbGCFiber *fibers;
- bbGCFiber *currentFiber;
-
- bbGCTmp *freeTmps;
-
- bbGCTmp *retained;
- bbGCNode markLists[2];
- bbGCNode freeList;
-
- size_t markedBytes;
- size_t unmarkedBytes;
-
- size_t allocedBytes;
-
- void *pools[32];
-
- unsigned char *poolBuf;
- size_t poolBufSize;
-
- bool inited;
-
- void init(){
- if( inited ) return;
- inited=true;
- markedBit=1;
- markedList=&markLists[0];
- markedList->succ=markedList->pred=markedList;
-
- unmarkedBit=2;
- unmarkedList=&markLists[1];
- unmarkedList->succ=unmarkedList->pred=unmarkedList;
-
- freeList.succ=freeList.pred=&freeList;
-
- fibers=new bbGCFiber;
-
- currentFiber=fibers;
-
- suspended=0;
- }
-
- void setTrigger( size_t size ){
-
- trigger=size;
- }
-
- void suspend(){
-
- ++suspended;
- }
-
- void resume(){
-
- --suspended;
- }
-
- void reclaim( size_t size=0x7fffffff ){
-
- size_t freed=0;
-
- while( freeList.succ!=&freeList && freed<size ){
-
- bbGCNode *p=freeList.succ;
-
- freed+=mallocSize( p );
-
- remove( p );
-
- if( p->flags & 2 ){
- //printf( "deleting weak refs for: %s %p\n",p->typeName(),p );fflush( stdout );
-
- bbGCWeakRef **pred=&bbGC::weakRefs,*curr;
-
- while( curr=*pred ){
- if( curr->target==p ){
- curr->target=0;
- *pred=curr->succ;
- }else{
- pred=&curr->succ;
- }
- }
- }
-
- if( p->flags & 1 ){
-
- //printf( "finalizing: %s %p\n",p->typeName(),p );fflush( stdout );
-
- ++suspended;
-
- p->state=unmarkedBit;
-
- p->gcFinalize();
-
- if( p->state==markedBit ) bbRuntimeError( "Object resurrected in finalizer" );
-
- --suspended;
- }
-
- p->~bbGCNode();
-
- bbGC::free( p );
- }
- }
-
- void markQueued( size_t tomark=0x7fffffff ){
-
- while( markQueue && markedBytes<tomark ){
- bbGCNode *p=markQueue;
- markQueue=p->succ;
-
- insert( p,markedList );
-
- markedBytes+=mallocSize( p );
-
- p->gcMark();
- }
- }
- void markRoots(){
-
- for( bbGCRoot *root=roots;root;root=root->succ ){
-
- root->gcMark();
- }
- }
-
- void markRetained(){
-
- for( bbGCTmp *tmp=retained;tmp;tmp=tmp->succ ){
-
- enqueue( tmp->node );
- }
- }
-
- void markFibers(){
-
- bbGCFiber *fiber=fibers;
-
- for(;;){
-
- bbGCMark( fiber->entry );
- for( bbGCFrame *frame=fiber->frames;frame;frame=frame->succ ){
-
- frame->gcMark();
- }
-
- for( bbGCNode *node=fiber->ctoring;node;node=node->succ ){
-
- node->gcMark();
- }
-
- for( bbGCTmp *tmp=fiber->tmps;tmp;tmp=tmp->succ ){
-
- enqueue( tmp->node );
- }
-
- fiber=fiber->succ;
-
- if( fiber==fibers ) break;
- }
- }
-
- void sweep(){
-
- markRetained();
-
- markFibers();
-
- markQueued();
-
- if( unmarkedList->succ!=unmarkedList ){
-
- //append unmarked to end of free queue
- unmarkedList->succ->pred=freeList.pred;
- unmarkedList->pred->succ=&freeList;
- freeList.pred->succ=unmarkedList->succ;
- freeList.pred=unmarkedList->pred;
-
- //clear unmarked
- unmarkedList->succ=unmarkedList->pred=unmarkedList;
- }
- //swap mark/unmarked lists
- auto tmp1=markedList;markedList=unmarkedList;unmarkedList=tmp1;
- auto tmp2=markedBit;markedBit=unmarkedBit;unmarkedBit=tmp2;
- unmarkedBytes=markedBytes;
- markedBytes=0;
- //start new sweep phase
- allocedBytes=0;
- markRoots();
- }
-
- void retain( bbGCNode *node ){
- BBGC_VALIDATE( node );
- if( !node ) return;
-
- bbGCTmp *tmp=freeTmps;
- if( tmp ) freeTmps=tmp->succ; else tmp=new bbGCTmp;
-
- tmp->node=node;
- tmp->succ=retained;
- retained=tmp;
- }
-
- void release( bbGCNode *node ){
- if( !node ) return;
-
- bbGCTmp **p=&retained;
- while( bbGCTmp *tmp=*p ){
- if( tmp->node==node ){
- *p=tmp->succ;
- tmp->succ=freeTmps;
- freeTmps=tmp;
- return;
- }
- p=&tmp->succ;
- }
- printf( "Warning! bbGC::release() - node not found!\n" );
- }
-
- void *malloc( size_t size ){
-
- size=(size+8+7) & ~7;
-
- memused+=size;
-
-
- if( !suspended ){
- if( allocedBytes+size>=trigger ){
-
- sweep();
-
- }else{
-
- markQueued( double( allocedBytes+size ) / double( trigger ) * double( unmarkedBytes + trigger ) );
- }
-
- reclaim( size );
- }
-
- void *p;
-
- if( size<256 ){
-
- if( pools[size>>3] ){
-
- p=pools[size>>3];
- pools[size>>3]=*(void**)p;
-
- }else{
-
- if( size>poolBufSize ){
- if( poolBufSize ){
- *(void**)poolBuf=pools[poolBufSize>>3];
- pools[poolBufSize>>3]=poolBuf;
- }
- poolBufSize=65536;
- poolBuf=(unsigned char*)::malloc( poolBufSize );
- malloced+=poolBufSize;
- }
- p=poolBuf;
- poolBuf+=size;
- poolBufSize-=size;
- }
- }else{
- p=::malloc( size );
- malloced+=size;
- }
-
- allocedBytes+=size;
- size_t *q=(size_t*)p;
- if( sizeof(size_t)==4 ) ++q;
- *q++=size;
- return q;
- }
-
- size_t mallocSize( void *p ){
-
- if( p ) return *((size_t*)p-1);
-
- return 0;
- }
-
- void free( void *p ){
-
- if( !p ) return;
-
- size_t *q=(size_t*)p;
- size_t size=*--q;
- if( sizeof(size_t)==4 ) --q;
-
- #ifndef NDEBUG
- memset( q,0xa5,size );
- #endif
-
- memused-=size;
-
- if( size<256 ){
- *(void**)q=pools[size>>3];
- pools[size>>3]=q;
- }else{
- malloced-=size;
- ::free( q );
- }
- }
- /*
- bbGCNode *alloc( size_t size ){
- bbGCNode *p=(bbGCNode*)bbGC::malloc( size );
-
- *((void**)p)=(void*)0xcafebabe;
-
- p->state=0;
- p->flags=0;
-
- return p;
- }
- */
- void collect(){
-
- if( !inited ) return;
-
- static size_t maxused;
-
- sweep();
-
- reclaim();
-
- if( memused>maxused ) maxused=memused;
-
- // printf( "Collect complete: memused=%i max memused=%i\n",memused,maxused );fflush( stdout );
- }
- }
- #endif
|