瀏覽代碼

start work on precise gc

Nicolas Cannasse 8 年之前
父節點
當前提交
01f8da7272
共有 5 個文件被更改,包括 79 次插入7 次删除
  1. 29 3
      src/alloc.c
  2. 2 2
      src/hl.h
  3. 1 1
      src/module.c
  4. 30 0
      src/std/obj.c
  5. 17 1
      src/std/types.c

+ 29 - 3
src/alloc.c

@@ -658,15 +658,40 @@ static void gc_flush_mark() {
 		void **block = (void**)*--mark_stack;
 		void **block = (void**)*--mark_stack;
 		gc_pheader *page = (gc_pheader*)((int_val)page_bid & ~(GC_PAGE_SIZE - 1));
 		gc_pheader *page = (gc_pheader*)((int_val)page_bid & ~(GC_PAGE_SIZE - 1));
 		int bid = ((int)(int_val)page_bid) & (GC_PAGE_SIZE - 1);
 		int bid = ((int)(int_val)page_bid) & (GC_PAGE_SIZE - 1);
-		int size, nwords;
+		unsigned int *mark_bits = NULL;
+		int pos = 0, size, nwords;
 		if( !block ) {
 		if( !block ) {
 			mark_stack += 2;
 			mark_stack += 2;
 			break;
 			break;
 		}
 		}
 		size = page->sizes ? page->sizes[bid] * page->block_size : page->block_size;
 		size = page->sizes ? page->sizes[bid] * page->block_size : page->block_size;
 		nwords = size / HL_WSIZE;
 		nwords = size / HL_WSIZE;
-		while( nwords-- ) {
-			void *p = *block++;
+#		ifdef GC_PRECISE
+		if( page->page_kind == MEM_KIND_DYNAMIC ) {
+			hl_type *t = *(hl_type**)block;
+#			ifdef GC_DEBUG
+#				ifdef HL_64
+				if( (int_val)t == 0xDDDDDDDDDDDDDDDD ) continue;
+#				else
+				if( (int_val)t == 0xDDDDDDDD ) continue;
+#				endif
+#			endif
+			if( t && t->kind != HFUN && t->mark_bits ) {
+				mark_bits = t->mark_bits;
+				block++;
+				pos++;
+			}
+		}
+#		endif
+		while( pos < nwords ) {
+			void *p;
+			if( mark_bits && (mark_bits[pos >> 5] & (1 << pos)) == 0 ) { // &31 implicit
+				pos++;
+				block++;
+				continue;
+			}
+			p = *block++;
+			pos++;
 			page = GC_GET_PAGE(p);
 			page = GC_GET_PAGE(p);
 			if( !page || ((((unsigned char*)p - (unsigned char*)page))%page->block_size) != 0 ) continue;
 			if( !page || ((((unsigned char*)p - (unsigned char*)page))%page->block_size) != 0 ) continue;
 #			ifdef HL_64
 #			ifdef HL_64
@@ -891,6 +916,7 @@ void hl_alloc_init( hl_alloc *a ) {
 void *hl_malloc( hl_alloc *a, int size ) {
 void *hl_malloc( hl_alloc *a, int size ) {
 	hl_alloc_block *b = a->cur;
 	hl_alloc_block *b = a->cur;
 	void *p;
 	void *p;
+	if( !size ) return NULL;
 	if( b == NULL || b->size <= size ) {
 	if( b == NULL || b->size <= size ) {
 		int alloc = size < 4096-sizeof(hl_alloc_block) ? 4096-sizeof(hl_alloc_block) : size;
 		int alloc = size < 4096-sizeof(hl_alloc_block) ? 4096-sizeof(hl_alloc_block) : size;
 		b = (hl_alloc_block *)malloc(sizeof(hl_alloc_block) + alloc);
 		b = (hl_alloc_block *)malloc(sizeof(hl_alloc_block) + alloc);

+ 2 - 2
src/hl.h

@@ -310,7 +310,7 @@ struct hl_type {
 		const uchar *abs_name;
 		const uchar *abs_name;
 	};
 	};
 	void **vobj_proto;
 	void **vobj_proto;
-	uint64 no_ptr_bits;
+	unsigned int *mark_bits;
 };
 };
 
 
 C_FUNCTION_BEGIN
 C_FUNCTION_BEGIN
@@ -321,7 +321,7 @@ HL_API int hl_stack_size( hl_type *t );
 
 
 HL_API hl_runtime_obj *hl_get_obj_rt( hl_type *ot );
 HL_API hl_runtime_obj *hl_get_obj_rt( hl_type *ot );
 HL_API hl_runtime_obj *hl_get_obj_proto( hl_type *ot );
 HL_API hl_runtime_obj *hl_get_obj_proto( hl_type *ot );
-HL_API void hl_init_enum( hl_type *et );
+HL_API void hl_init_enum( hl_type *et, hl_module_context *m );
 
 
 /* -------------------- VALUES ------------------------------ */
 /* -------------------- VALUES ------------------------------ */
 
 

+ 1 - 1
src/module.c

@@ -325,7 +325,7 @@ int hl_module_init( hl_module *m, void *stack_top_val ) {
 			}
 			}
 			break;
 			break;
 		case HENUM:
 		case HENUM:
-			hl_init_enum(t);
+			hl_init_enum(t,&m->ctx);
 			t->tenum->global_value = ((int)(int_val)t->tenum->global_value) ? (void**)(int_val)(m->globals_data + m->globals_indexes[(int)(int_val)t->tenum->global_value-1]) : NULL;
 			t->tenum->global_value = ((int)(int_val)t->tenum->global_value) ? (void**)(int_val)(m->globals_data + m->globals_indexes[(int)(int_val)t->tenum->global_value-1]) : NULL;
 			break;
 			break;
 		case HVIRTUAL:
 		case HVIRTUAL:

+ 30 - 0
src/std/obj.c

@@ -147,6 +147,11 @@ HL_PRIM hl_obj_field *hl_obj_field_fetch( hl_type *t, int fid ) {
 	return rt->t->obj->fields + (fid - (rt->parent?rt->parent->nfields:0));
 	return rt->t->obj->fields + (fid - (rt->parent?rt->parent->nfields:0));
 }
 }
 
 
+HL_PRIM int hl_mark_size( int data_size ) {
+	int ptr_count = (data_size + HL_WSIZE - 1) / HL_WSIZE;
+	return ((ptr_count + 31) >> 5) * sizeof(int);
+}
+
 /**
 /**
 	Builds class metadata (fields indexes, etc.)
 	Builds class metadata (fields indexes, etc.)
 	Does not require the method table to be finalized.
 	Does not require the method table to be finalized.
@@ -246,6 +251,20 @@ HL_PRIM hl_runtime_obj *hl_get_obj_rt( hl_type *ot ) {
 		if( pr->hashed_name == compareHash )
 		if( pr->hashed_name == compareHash )
 			t->compareFun = (void*)(int_val)pr->findex;
 			t->compareFun = (void*)(int_val)pr->findex;
 	}
 	}
+
+	// mark bits
+	if( t->hasPtr ) {
+		unsigned int *mark = (unsigned int*)hl_zalloc(alloc,hl_mark_size(t->size));
+		ot->mark_bits = mark;
+		if( p && p->t->mark_bits ) memcpy(mark, p->t->mark_bits, hl_mark_size(p->size));
+		for(i=0;i<o->nfields;i++) {
+			hl_type *ft = o->fields[i].t;
+			if( hl_is_ptr(ft) ) {
+				int pos = t->fields_indexes[i + start] / HL_WSIZE;
+				mark[pos >> 5] |= 1 << (pos & 31);
+			}
+		}
+	}
 	return t;
 	return t;
 }
 }
 
 
@@ -357,6 +376,7 @@ void hl_init_virtual( hl_type *vt, hl_module_context *ctx ) {
 	int size = vsize;
 	int size = vsize;
 	hl_field_lookup *l = (hl_field_lookup*)hl_malloc(&ctx->alloc,sizeof(hl_field_lookup)*vt->virt->nfields);
 	hl_field_lookup *l = (hl_field_lookup*)hl_malloc(&ctx->alloc,sizeof(hl_field_lookup)*vt->virt->nfields);
 	int *indexes = (int*)hl_malloc(&ctx->alloc,sizeof(int)*vt->virt->nfields);
 	int *indexes = (int*)hl_malloc(&ctx->alloc,sizeof(int)*vt->virt->nfields);
+	unsigned int *mark;
 	for(i=0;i<vt->virt->nfields;i++) {
 	for(i=0;i<vt->virt->nfields;i++) {
 		hl_obj_field *f = vt->virt->fields + i;
 		hl_obj_field *f = vt->virt->fields + i;
 		hl_lookup_insert(l,i,f->hashed_name,f->t,i);
 		hl_lookup_insert(l,i,f->hashed_name,f->t,i);
@@ -367,6 +387,16 @@ void hl_init_virtual( hl_type *vt, hl_module_context *ctx ) {
 	vt->virt->lookup = l;
 	vt->virt->lookup = l;
 	vt->virt->indexes = indexes;
 	vt->virt->indexes = indexes;
 	vt->virt->dataSize = size - vsize;
 	vt->virt->dataSize = size - vsize;
+	mark = (unsigned int*)hl_zalloc(&ctx->alloc, hl_mark_size(size));
+	vt->mark_bits = mark;
+	mark[0] = 2 | 4; // value | next
+	for(i=0;i<vt->virt->nfields;i++) {
+		hl_obj_field *f = vt->virt->fields + i;
+		if( hl_is_ptr(f->t) ) {
+			int pos = indexes[i] / HL_WSIZE;
+			mark[pos >> 5] |= 1 << (pos & 31);
+		}
+	}
 }
 }
 
 
 vdynamic *hl_virtual_make_value( vvirtual *v ) {
 vdynamic *hl_virtual_make_value( vvirtual *v ) {

+ 17 - 1
src/std/types.c

@@ -292,8 +292,12 @@ HL_PRIM vbyte* hl_type_name( hl_type *t ) {
 	return NULL;
 	return NULL;
 }
 }
 
 
-HL_PRIM void hl_init_enum( hl_type *et ) {
+HL_PRIM int hl_mark_size( int data_size );
+
+HL_PRIM void hl_init_enum( hl_type *et, hl_module_context *m ) {
 	int i, j;
 	int i, j;
+	int max_size = 0;
+	unsigned int *mark;
 	for(i=0;i<et->tenum->nconstructs;i++) {
 	for(i=0;i<et->tenum->nconstructs;i++) {
 		hl_enum_construct *c = et->tenum->constructs + i;
 		hl_enum_construct *c = et->tenum->constructs + i;
 		c->hasptr = false;
 		c->hasptr = false;
@@ -305,7 +309,19 @@ HL_PRIM void hl_init_enum( hl_type *et ) {
 			if( hl_is_ptr(t) ) c->hasptr = true;
 			if( hl_is_ptr(t) ) c->hasptr = true;
 			c->size += hl_type_size(t);
 			c->size += hl_type_size(t);
 		}
 		}
+		if( c->size > max_size && c->hasptr ) max_size = c->size;
+	}
+	mark = (unsigned int*)hl_zalloc(&m->alloc,hl_mark_size(max_size));
+	for(i=0;i<et->tenum->nconstructs;i++) {
+		hl_enum_construct *c = et->tenum->constructs + i;
+		if( !c->hasptr ) continue;
+		for(j=0;j<c->nparams;j++)
+			if( hl_is_ptr(c->params[j]) ) {
+				int pos = c->offsets[j];
+				mark[pos >> 5] |= 1 << (pos & 31);
+			}
 	}
 	}
+	et->mark_bits = mark;
 }
 }
 
 
 HL_PRIM varray* hl_type_enum_fields( hl_type *t ) {
 HL_PRIM varray* hl_type_enum_fields( hl_type *t ) {