bbgc.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. #ifndef BB_THREADS
  2. #include "bbgc.h"
  3. #include "bbweakref.h"
  4. namespace bbDB{
  5. void stop();
  6. void stopped();
  7. void error( bbString err );
  8. }
  9. namespace bbGC{
  10. int memused;
  11. int malloced;
  12. size_t trigger=4*1024*1024;
  13. int suspended=1;
  14. int markedBit;
  15. int unmarkedBit;
  16. bbGCNode *markQueue;
  17. bbGCNode *markedList;
  18. bbGCNode *unmarkedList;
  19. bbGCRoot *roots;
  20. bbGCFiber *fibers;
  21. bbGCFiber *currentFiber;
  22. bbGCTmp *freeTmps;
  23. bbGCTmp *retained;
  24. bbGCNode markLists[2];
  25. bbGCNode freeList;
  26. size_t markedBytes;
  27. size_t unmarkedBytes;
  28. size_t allocedBytes;
  29. void *pools[32];
  30. unsigned char *poolBuf;
  31. size_t poolBufSize;
  32. bool inited;
  33. void init(){
  34. if( inited ) return;
  35. inited=true;
  36. markedBit=1;
  37. markedList=&markLists[0];
  38. markedList->succ=markedList->pred=markedList;
  39. unmarkedBit=2;
  40. unmarkedList=&markLists[1];
  41. unmarkedList->succ=unmarkedList->pred=unmarkedList;
  42. freeList.succ=freeList.pred=&freeList;
  43. fibers=new bbGCFiber;
  44. currentFiber=fibers;
  45. suspended=0;
  46. }
  47. void setTrigger( size_t size ){
  48. trigger=size;
  49. }
  50. void suspend(){
  51. ++suspended;
  52. }
  53. void resume(){
  54. --suspended;
  55. }
  56. void reclaim( size_t size=0x7fffffff ){
  57. size_t freed=0;
  58. while( freeList.succ!=&freeList && freed<size ){
  59. bbGCNode *p=freeList.succ;
  60. freed+=mallocSize( p );
  61. remove( p );
  62. if( p->flags & 2 ){
  63. //printf( "deleting weak refs for: %s %p\n",p->typeName(),p );fflush( stdout );
  64. bbGCWeakRef **pred=&bbGC::weakRefs,*curr;
  65. while( curr=*pred ){
  66. if( curr->target==p ){
  67. curr->target=0;
  68. *pred=curr->succ;
  69. }else{
  70. pred=&curr->succ;
  71. }
  72. }
  73. }
  74. if( p->flags & 1 ){
  75. //printf( "finalizing: %s %p\n",p->typeName(),p );fflush( stdout );
  76. ++suspended;
  77. p->state=unmarkedBit;
  78. p->gcFinalize();
  79. if( p->state==markedBit ) bbRuntimeError( "Object resurrected in finalizer" );
  80. --suspended;
  81. }
  82. p->~bbGCNode();
  83. bbGC::free( p );
  84. }
  85. }
  86. void markQueued( size_t tomark=0x7fffffff ){
  87. while( markQueue && markedBytes<tomark ){
  88. bbGCNode *p=markQueue;
  89. markQueue=p->succ;
  90. insert( p,markedList );
  91. markedBytes+=mallocSize( p );
  92. p->gcMark();
  93. }
  94. }
  95. void markRoots(){
  96. for( bbGCRoot *root=roots;root;root=root->succ ){
  97. root->gcMark();
  98. }
  99. }
  100. void markRetained(){
  101. for( bbGCTmp *tmp=retained;tmp;tmp=tmp->succ ){
  102. enqueue( tmp->node );
  103. }
  104. }
  105. void markFibers(){
  106. bbGCFiber *fiber=fibers;
  107. for(;;){
  108. bbGCMark( fiber->entry );
  109. for( bbGCFrame *frame=fiber->frames;frame;frame=frame->succ ){
  110. frame->gcMark();
  111. }
  112. for( bbGCNode *node=fiber->ctoring;node;node=node->succ ){
  113. node->gcMark();
  114. }
  115. for( bbGCTmp *tmp=fiber->tmps;tmp;tmp=tmp->succ ){
  116. enqueue( tmp->node );
  117. }
  118. fiber=fiber->succ;
  119. if( fiber==fibers ) break;
  120. }
  121. }
  122. void sweep(){
  123. markRetained();
  124. markFibers();
  125. markQueued();
  126. if( unmarkedList->succ!=unmarkedList ){
  127. //append unmarked to end of free queue
  128. unmarkedList->succ->pred=freeList.pred;
  129. unmarkedList->pred->succ=&freeList;
  130. freeList.pred->succ=unmarkedList->succ;
  131. freeList.pred=unmarkedList->pred;
  132. //clear unmarked
  133. unmarkedList->succ=unmarkedList->pred=unmarkedList;
  134. }
  135. //swap mark/unmarked lists
  136. auto tmp1=markedList;markedList=unmarkedList;unmarkedList=tmp1;
  137. auto tmp2=markedBit;markedBit=unmarkedBit;unmarkedBit=tmp2;
  138. unmarkedBytes=markedBytes;
  139. markedBytes=0;
  140. //start new sweep phase
  141. allocedBytes=0;
  142. markRoots();
  143. }
  144. void retain( bbGCNode *node ){
  145. BBGC_VALIDATE( node );
  146. if( !node ) return;
  147. bbGCTmp *tmp=freeTmps;
  148. if( tmp ) freeTmps=tmp->succ; else tmp=new bbGCTmp;
  149. tmp->node=node;
  150. tmp->succ=retained;
  151. retained=tmp;
  152. }
  153. void release( bbGCNode *node ){
  154. if( !node ) return;
  155. bbGCTmp **p=&retained;
  156. while( bbGCTmp *tmp=*p ){
  157. if( tmp->node==node ){
  158. *p=tmp->succ;
  159. tmp->succ=freeTmps;
  160. freeTmps=tmp;
  161. return;
  162. }
  163. p=&tmp->succ;
  164. }
  165. printf( "Warning! bbGC::release() - node not found!\n" );
  166. }
  167. void *malloc( size_t size ){
  168. size=(size+8+7) & ~7;
  169. memused+=size;
  170. if( !suspended ){
  171. if( allocedBytes+size>=trigger ){
  172. sweep();
  173. }else{
  174. markQueued( double( allocedBytes+size ) / double( trigger ) * double( unmarkedBytes + trigger ) );
  175. }
  176. reclaim( size );
  177. }
  178. void *p;
  179. if( size<256 ){
  180. if( pools[size>>3] ){
  181. p=pools[size>>3];
  182. pools[size>>3]=*(void**)p;
  183. }else{
  184. if( size>poolBufSize ){
  185. if( poolBufSize ){
  186. *(void**)poolBuf=pools[poolBufSize>>3];
  187. pools[poolBufSize>>3]=poolBuf;
  188. }
  189. poolBufSize=65536;
  190. poolBuf=(unsigned char*)::malloc( poolBufSize );
  191. malloced+=poolBufSize;
  192. }
  193. p=poolBuf;
  194. poolBuf+=size;
  195. poolBufSize-=size;
  196. }
  197. }else{
  198. p=::malloc( size );
  199. malloced+=size;
  200. }
  201. allocedBytes+=size;
  202. size_t *q=(size_t*)p;
  203. if( sizeof(size_t)==4 ) ++q;
  204. *q++=size;
  205. return q;
  206. }
  207. size_t mallocSize( void *p ){
  208. if( p ) return *((size_t*)p-1);
  209. return 0;
  210. }
  211. void free( void *p ){
  212. if( !p ) return;
  213. size_t *q=(size_t*)p;
  214. size_t size=*--q;
  215. if( sizeof(size_t)==4 ) --q;
  216. #ifndef NDEBUG
  217. memset( q,0xa5,size );
  218. #endif
  219. memused-=size;
  220. if( size<256 ){
  221. *(void**)q=pools[size>>3];
  222. pools[size>>3]=q;
  223. }else{
  224. malloced-=size;
  225. ::free( q );
  226. }
  227. }
  228. /*
  229. bbGCNode *alloc( size_t size ){
  230. bbGCNode *p=(bbGCNode*)bbGC::malloc( size );
  231. *((void**)p)=(void*)0xcafebabe;
  232. p->state=0;
  233. p->flags=0;
  234. return p;
  235. }
  236. */
  237. void collect(){
  238. if( !inited ) return;
  239. static size_t maxused;
  240. sweep();
  241. reclaim();
  242. if( memused>maxused ) maxused=memused;
  243. // printf( "Collect complete: memused=%i max memused=%i\n",memused,maxused );fflush( stdout );
  244. }
  245. }
  246. #endif