Parcourir la source

implemented gc finalizers

Nicolas Cannasse il y a 9 ans
Parent
commit
cfebc0cd27
3 fichiers modifiés avec 39 ajouts et 1 suppressions
  1. 1 0
      libs/fmt/fmt.c
  2. 37 1
      src/alloc.c
  3. 1 0
      src/std/file.c

+ 1 - 0
libs/fmt/fmt.c

@@ -72,6 +72,7 @@ static void free_stream_inf( fmt_zip *v ) {
 		deflateEnd(v->z);
 	free(v->z);
 	v->z = NULL;
+	v->finalize = NULL;
 }
 
 static void zlib_error( z_stream *z, int err ) {

+ 37 - 1
src/alloc.c

@@ -135,8 +135,15 @@ static struct {
 	int pages_count;
 	int pages_allocated;
 	int mark_bytes;
+	int mark_time;
 } gc_stats = {0};
 
+#ifdef HL_WIN
+#	define TIMESTAMP() ((int)GetTickCount())
+#else
+#	define TIMESTAMP() 0
+#endif
+
 // -------------------------  ROOTS ----------------------------------------------------------
 
 static void ***gc_roots = NULL;
@@ -494,7 +501,7 @@ static void *gc_alloc_gen( int size, int flags ) {
 	if( m ) size += GC_ALIGN - m;
 	if( size <= 0 )
 		return NULL;
-	if( size <= GC_SIZES[GC_FIXED_PARTS-1] && (flags & MEM_ALIGN_DOUBLE) == 0 )
+	if( size <= GC_SIZES[GC_FIXED_PARTS-1] && (flags & MEM_ALIGN_DOUBLE) == 0 && flags != MEM_KIND_FINALIZER )
 		return gc_alloc_fixed( (size >> GC_ALIGN_BITS) - 1, flags & PAGE_KIND_MASK);
 	for(p=GC_FIXED_PARTS;p<GC_PARTITIONS;p++) {
 		int block = GC_SIZES[p];
@@ -628,6 +635,31 @@ static void gc_clear_unmarked_mem() {
 }
 #endif
 
+static void gc_call_finalizers(){ 
+	int i;
+	for(i=MEM_KIND_FINALIZER;i<GC_ALL_PAGES;i+=1<<PAGE_KIND_BITS) {
+		gc_pheader *p = gc_pages[i];
+		while( p ) {
+			int bid;
+			for(bid=p->first_block;bid<p->max_blocks;bid++) {
+				int size = p->sizes[bid]; 
+				if( !size ) continue;
+				if( (p->bmp[bid>>3] & (1<<(bid&7))) == 0 ) {
+					unsigned char *ptr = (unsigned char*)p + bid * p->block_size;
+					void *finalizer = *(void**)ptr;
+					p->sizes[bid] = 0;
+					if( finalizer )
+						((void(*)(void *))finalizer)(ptr);
+#					ifdef GC_DEBUG
+					memset(ptr,0xDD,size*p->block_size);
+#					endif
+				}
+			}
+			p = p->next_page;
+		}
+	}
+}
+
 static void gc_mark() {
 	jmp_buf regs;
 	void **stack_head;
@@ -695,6 +727,7 @@ static void gc_mark() {
 	}
 	cur_mark_stack = mark_stack;
 	if( mark_stack ) gc_flush_mark();
+	gc_call_finalizers();
 #	ifdef GC_DEBUG
 	gc_clear_unmarked_mem();
 #	endif
@@ -814,8 +847,11 @@ HL_API void hl_gc_dump() {
 }
 
 HL_API void hl_gc_major() {
+	int time = TIMESTAMP();
 	gc_stats.last_mark = gc_stats.total_allocated;
 	gc_mark();
+	gc_stats.mark_time += TIMESTAMP() - time;
+	//printf("MARK %d\n",gc_stats.mark_time);
 }
 
 HL_API bool hl_is_gc_ptr( void *ptr ) {

+ 1 - 0
src/std/file.c

@@ -56,6 +56,7 @@ HL_PRIM hl_fdesc *hl_file_open( vbyte *name, int mode, bool binary ) {
 HL_PRIM void hl_file_close( hl_fdesc *f ) {
 	if( f->f ) fclose(f->f);
 	f->f = NULL;
+	f->finalize = NULL;
 }
 
 HL_PRIM int hl_file_write( hl_fdesc *f, vbyte *buf, int pos, int len ) {