Browse Source

pass allocated type to alloc_gen

Nicolas Cannasse 8 years ago
parent
commit
ecdae2128f
8 changed files with 34 additions and 182 deletions
  1. 1 0
      libhl.vcxproj
  2. 3 0
      libhl.vcxproj.filters
  3. 12 166
      src/alloc.c
  4. 7 6
      src/hl.h
  5. 4 4
      src/jit.c
  6. 1 1
      src/std/array.c
  7. 4 3
      src/std/fun.c
  8. 2 2
      src/std/obj.c

+ 1 - 0
libhl.vcxproj

@@ -268,6 +268,7 @@
     <ClCompile Include="src\std\thread.c" />
     <ClCompile Include="src\std\thread.c" />
     <ClCompile Include="src\std\types.c" />
     <ClCompile Include="src\std\types.c" />
     <ClCompile Include="src\std\ucs2.c" />
     <ClCompile Include="src\std\ucs2.c" />
+    <ClCompile Include="src\track.c" />
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClInclude Include="include\pcre\config.h" />
     <ClInclude Include="include\pcre\config.h" />

+ 3 - 0
libhl.vcxproj.filters

@@ -103,6 +103,9 @@
     <ClCompile Include="src\std\debug.c">
     <ClCompile Include="src\std\debug.c">
       <Filter>std</Filter>
       <Filter>std</Filter>
     </ClCompile>
     </ClCompile>
+    <ClCompile Include="src\track.c">
+      <Filter>std</Filter>
+    </ClCompile>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClInclude Include="include\pcre\config.h">
     <ClInclude Include="include\pcre\config.h">

+ 12 - 166
src/alloc.c

@@ -132,6 +132,7 @@ static int gc_free_blocks[GC_ALL_PAGES] = {0};
 static gc_pheader *gc_free_pages[GC_ALL_PAGES] = {NULL};
 static gc_pheader *gc_free_pages[GC_ALL_PAGES] = {NULL};
 static gc_pheader *gc_level1_null[1<<GC_LEVEL1_BITS] = {NULL};
 static gc_pheader *gc_level1_null[1<<GC_LEVEL1_BITS] = {NULL};
 static gc_pheader **hl_gc_page_map[1<<GC_LEVEL0_BITS] = {NULL};
 static gc_pheader **hl_gc_page_map[1<<GC_LEVEL0_BITS] = {NULL};
+static void (*gc_track_callback)(hl_type *,int,int,void*) = NULL;
 
 
 static struct {
 static struct {
 	int64 total_requested;
 	int64 total_requested;
@@ -167,6 +168,10 @@ static void ***gc_roots = NULL;
 static int gc_roots_count = 0;
 static int gc_roots_count = 0;
 static int gc_roots_max = 0;
 static int gc_roots_max = 0;
 
 
+HL_PRIM void hl_gc_set_track( void *f ) {
+	gc_track_callback = f;
+}
+
 HL_PRIM void hl_add_root( void *r ) {
 HL_PRIM void hl_add_root( void *r ) {
 	if( gc_roots_count == gc_roots_max ) {
 	if( gc_roots_count == gc_roots_max ) {
 		int nroots = gc_roots_max ? (gc_roots_max << 1) : 16;
 		int nroots = gc_roots_max ? (gc_roots_max << 1) : 16;
@@ -554,9 +559,7 @@ static unsigned char *alloc_all = NULL;
 static unsigned char *alloc_end = NULL;
 static unsigned char *alloc_end = NULL;
 #endif
 #endif
 
 
-static void hl_gc_check_track();
-
-void *hl_gc_alloc_gen( int size, int flags ) {
+void *hl_gc_alloc_gen( hl_type *t, int size, int flags ) {
 	void *ptr;
 	void *ptr;
 	int time = 0;
 	int time = 0;
 	int allocated = 0;
 	int allocated = 0;
@@ -583,7 +586,8 @@ void *hl_gc_alloc_gen( int size, int flags ) {
 		MZERO(ptr,allocated);
 		MZERO(ptr,allocated);
 	else if( MEM_HAS_PTR(flags) && allocated != size )
 	else if( MEM_HAS_PTR(flags) && allocated != size )
 		MZERO((char*)ptr+size,allocated-size); // erase possible pointers after data
 		MZERO((char*)ptr+size,allocated-size); // erase possible pointers after data
-	if( gc_flags & GC_TRACK ) hl_gc_check_track();
+	if( (gc_flags & GC_TRACK) && gc_track_callback )
+		((void (*)(hl_type *,int,int,void*))gc_track_callback)(t,size,flags,ptr);
 	return ptr;
 	return ptr;
 }
 }
 
 
@@ -1025,16 +1029,8 @@ static void gc_free_page_memory( void *ptr, int size ) {
 }
 }
 
 
 vdynamic *hl_alloc_dynamic( hl_type *t ) {
 vdynamic *hl_alloc_dynamic( hl_type *t ) {
-	vdynamic *d = (vdynamic*) (hl_is_ptr(t) ? hl_gc_alloc(sizeof(vdynamic)) : hl_gc_alloc_noptr(sizeof(vdynamic)));
+	vdynamic *d = (vdynamic*)hl_gc_alloc_gen(t, sizeof(vdynamic), (hl_is_ptr(t) ? MEM_KIND_DYNAMIC : MEM_KIND_NOPTR) | MEM_ZERO);
 	d->t = t;
 	d->t = t;
-#	ifndef HL_64
-	d->__pad = 0;
-#	endif
-	d->v.d = 0.;
-#	ifdef GC_DEBUG
-	if( t->kind == HVOID )
-		hl_error("alloc_dynamic(VOID)");
-#	endif
 	return d;
 	return d;
 }
 }
 
 
@@ -1046,7 +1042,7 @@ vdynamic *hl_alloc_obj( hl_type *t ) {
 	if( rt == NULL || rt->methods == NULL ) rt = hl_get_obj_proto(t);
 	if( rt == NULL || rt->methods == NULL ) rt = hl_get_obj_proto(t);
 	size = rt->size;
 	size = rt->size;
 	if( size & (HL_WSIZE-1) ) size += HL_WSIZE - (size & (HL_WSIZE-1));
 	if( size & (HL_WSIZE-1) ) size += HL_WSIZE - (size & (HL_WSIZE-1));
-	o = (vobj*)hl_gc_alloc_gen(size, (rt->hasPtr ? MEM_KIND_DYNAMIC : MEM_KIND_NOPTR) | MEM_ZERO);
+	o = (vobj*)hl_gc_alloc_gen(t, size, (rt->hasPtr ? MEM_KIND_DYNAMIC : MEM_KIND_NOPTR) | MEM_ZERO);
 	o->t = t;
 	o->t = t;
 	for(i=0;i<rt->nbindings;i++) {
 	for(i=0;i<rt->nbindings;i++) {
 		hl_runtime_binding *b = rt->bindings + i;
 		hl_runtime_binding *b = rt->bindings + i;
@@ -1056,7 +1052,7 @@ vdynamic *hl_alloc_obj( hl_type *t ) {
 }
 }
 
 
 vdynobj *hl_alloc_dynobj() {
 vdynobj *hl_alloc_dynobj() {
-	vdynobj *o = (vdynobj*)hl_gc_alloc(sizeof(vdynobj));
+	vdynobj *o = (vdynobj*)hl_gc_alloc(&hlt_dynobj,sizeof(vdynobj));
 	o->t = &hlt_dynobj;
 	o->t = &hlt_dynobj;
 	o->lookup = NULL;
 	o->lookup = NULL;
 	o->nfields = 0;
 	o->nfields = 0;
@@ -1067,7 +1063,7 @@ vdynobj *hl_alloc_dynobj() {
 }
 }
 
 
 vvirtual *hl_alloc_virtual( hl_type *t ) {
 vvirtual *hl_alloc_virtual( hl_type *t ) {
-	vvirtual *v = (vvirtual*)hl_gc_alloc(t->virt->dataSize + sizeof(vvirtual) + sizeof(void*) * t->virt->nfields);
+	vvirtual *v = (vvirtual*)hl_gc_alloc(t, t->virt->dataSize + sizeof(vvirtual) + sizeof(void*) * t->virt->nfields);
 	void **fields = (void**)(v + 1);
 	void **fields = (void**)(v + 1);
 	char *vdata = (char*)(fields + t->virt->nfields);
 	char *vdata = (char*)(fields + t->virt->nfields);
 	int i;
 	int i;
@@ -1185,154 +1181,4 @@ DEFINE_PRIM(_VOID, gc_dump_memory, _BYTES);
 DEFINE_PRIM(_I32, gc_get_flags, _NO_ARG);
 DEFINE_PRIM(_I32, gc_get_flags, _NO_ARG);
 DEFINE_PRIM(_VOID, gc_set_flags, _I32);
 DEFINE_PRIM(_VOID, gc_set_flags, _I32);
 
 
-// ------- TRACKING ------------------------
-
-typedef struct {
-	int_val obj;
-	int_val old_value;
-	void **value;
-	vclosure *callb;
-} hl_track;
-
-static hl_track *tracked = NULL;
-static int tracked_count = 0;
-static int tracked_max = 0;
-
-#define hide_ptr(v)		(((int_val)(v))^1)
-
-static uchar *hl_gc_reason( void *ptr ) {
-	gc_pheader *page = GC_GET_PAGE(ptr);
-	int bid;
-	if( !hl_is_ptr(&hlt_dyn) ) return USTR("BrokenDyn");
-	if( cur_mark_stack != mark_stack_end - mark_stack_size + 2 ) return USTR("MarkStack");
-	if( !page ) return USTR("NoPage");
-	if( ((unsigned char*)ptr - (unsigned char*)page) % page->block_size != 0 ) return USTR("Unaligned");
-	bid = (int)((unsigned char*)ptr - (unsigned char*)page) / page->block_size;
-	if( bid < page->first_block || bid >= page->max_blocks ) return USTR("OutPage");
-	if( page->sizes && page->sizes[bid] == 0 ) return USTR("ZeroSize");
-	// not live (only available if we haven't allocate since then)
-	if( page->bmp && page->next_block == page->first_block && (page->bmp[bid>>3]&(1<<(bid&7))) == 0 ) {
-		if( gc_stats.last_mark_allocs > gc_stats.allocation_count + 1 )
-			return USTR("MaybeUnref");
-		return USTR("Unref");
-	}
-	return USTR("IsBlock");
-}
-
-static void hl_gc_check_track() {
-	int i;
-	vdynamic b;
-	vdynamic *pptr[2];
-	pptr[1] = &b;
-	b.t = &hlt_bytes;
-	for(i=0;i<tracked_count;i++) {
-		hl_track *tr = tracked + i;
-		vdynamic *obj = (vdynamic*)hide_ptr(tr->obj);
-		if( !tr->value ) continue;
-		if( !hl_is_gc_ptr(obj) /*GC'ed!*/ ) {
-			tr->value = NULL;
-			b.v.ptr = hl_gc_reason(obj);
-		} else {
-			int_val v = hide_ptr(*tr->value);
-			if( v == tr->old_value ) continue;
-			tr->old_value = v;
-			b.v.ptr = USTR("Changed");
-		}
-		pptr[0] = obj;
-		hl_dyn_call(tr->callb,pptr,2);
-		pptr[0] = NULL;
-	}
-}
-
-HL_API bool hl_gc_track( vdynamic *dobj, int fid, vclosure *callb ) {
-	void *obj = NULL, **value = NULL;
-	hl_track *tr;
-	if( dobj == NULL )
-		return false;
-	switch( dobj->t->kind ) {
-	case HENUM:
-		{
-			int cid = *(int*)dobj->v.ptr;
-			hl_enum_construct *c = dobj->t->tenum->constructs + cid;
-			if( fid >= c->nparams ) return false;
-			obj = (void*)dobj->v.ptr;
-			value = (void**)((char*)obj + c->offsets[fid]);
-		}
-		break;
-	case HOBJ:
-		{
-			hl_runtime_obj *rt = dobj->t->obj->rt;
-			hl_field_lookup *f = NULL;
-			while( rt ) {
-				f = hl_lookup_find(rt->lookup,rt->nlookup,fid);
-				if( f ) break;
-				rt = rt->parent;
-			}
-			if( !f || f->field_index < 0 ) return false;
-			obj = dobj;
-			value = (void**)((char*)obj + f->field_index);
-		}
-		break;
-	default:
-		return false;
-	}
-	if( value == NULL )
-		return false;
-
-	if( !hl_is_gc_ptr(obj) )
-		return false;
-
-	if( tracked_count == tracked_max ) {
-		hl_track *newt;
-		tracked_max = tracked_max ? tracked_max << 1 : 16;
-		newt = hl_gc_alloc_raw(sizeof(hl_track)*tracked_max);
-		if( tracked ) {
-			memcpy(newt,tracked,tracked_count*sizeof(hl_track));
-		} else {
-			hl_add_root(&tracked);
-		}
-		tracked = newt;
-	}
-	tr = tracked + tracked_count++;
-	tr->callb = callb;
-	tr->value = value;
-	tr->old_value = hide_ptr(*value);
-	tr->obj = hide_ptr(obj);
-	return true;
-}
-
-HL_API bool hl_gc_untrack( vdynamic *obj ) {
-	int_val oval;
-	int i;
-	if( obj == NULL )
-		return false;
-	if( obj->t->kind == HENUM )
-		obj = (vdynamic*)obj->v.ptr;
-	oval = hide_ptr(obj);
-	for(i=0;i<tracked_count;i++) {
-		hl_track *tr = tracked + i;
-		if( tr->obj == oval ) {
-			tracked_count--;
-			memmove(tracked + i, tracked + i + 1, (tracked_count - i) * sizeof(hl_track));
-			memset(tracked + tracked_count, 0, sizeof(hl_track));
-			return true;
-		}
-	}
-	return false;
-}
-
-HL_API void hl_gc_untrack_all() {
-	if( tracked_count == 0 ) return;
-	memset(tracked, 0, sizeof(hl_track) * tracked_count);
-	tracked_count = 0;
-}
-
-HL_API int hl_gc_track_count() {
-	return tracked_count;
-}
-
-DEFINE_PRIM(_BOOL, gc_track, _DYN _I32 _FUN(_VOID, _DYN _BYTES));
-DEFINE_PRIM(_BOOL, gc_untrack, _DYN);
-DEFINE_PRIM(_VOID, gc_untrack_all, _NO_ARG);
-DEFINE_PRIM(_I32, gc_track_count, _NO_ARG);
 
 

+ 7 - 6
src/hl.h

@@ -313,12 +313,12 @@ typedef struct {
 struct hl_type {
 struct hl_type {
 	hl_type_kind kind;
 	hl_type_kind kind;
 	union {
 	union {
+		const uchar *abs_name;
 		hl_type_fun *fun;
 		hl_type_fun *fun;
 		hl_type_obj *obj;
 		hl_type_obj *obj;
 		hl_type_enum *tenum;
 		hl_type_enum *tenum;
 		hl_type_virtual *virt;
 		hl_type_virtual *virt;
 		hl_type	*tparam;
 		hl_type	*tparam;
-		const uchar *abs_name;
 	};
 	};
 	void **vobj_proto;
 	void **vobj_proto;
 	unsigned int *mark_bits;
 	unsigned int *mark_bits;
@@ -446,6 +446,7 @@ HL_API hl_type hlt_array;
 HL_API hl_type hlt_bytes;
 HL_API hl_type hlt_bytes;
 HL_API hl_type hlt_dynobj;
 HL_API hl_type hlt_dynobj;
 HL_API hl_type hlt_bool;
 HL_API hl_type hlt_bool;
+HL_API hl_type hlt_abstract;
 
 
 HL_API double hl_nan();
 HL_API double hl_nan();
 HL_API bool hl_is_dynamic( hl_type *t );
 HL_API bool hl_is_dynamic( hl_type *t );
@@ -553,7 +554,7 @@ HL_API bool hl_thread_set_context( hl_thread *t, hl_thread_registers *regs );
 #define MEM_ALIGN_DOUBLE	128
 #define MEM_ALIGN_DOUBLE	128
 #define MEM_ZERO			256
 #define MEM_ZERO			256
 
 
-HL_API void *hl_gc_alloc_gen( int size, int flags );
+HL_API void *hl_gc_alloc_gen( hl_type *t, int size, int flags );
 HL_API void hl_add_root( void *ptr );
 HL_API void hl_add_root( void *ptr );
 HL_API void hl_pop_root();
 HL_API void hl_pop_root();
 HL_API void hl_remove_root( void *ptr );
 HL_API void hl_remove_root( void *ptr );
@@ -563,10 +564,10 @@ HL_API bool hl_is_gc_ptr( void *ptr );
 typedef void (*hl_types_dump)( void (*)( void *, int) );
 typedef void (*hl_types_dump)( void (*)( void *, int) );
 HL_API void hl_gc_set_dump_types( hl_types_dump tdump );
 HL_API void hl_gc_set_dump_types( hl_types_dump tdump );
 
 
-#define hl_gc_alloc_noptr(size)		hl_gc_alloc_gen(size,MEM_KIND_NOPTR)
-#define hl_gc_alloc(size)			hl_gc_alloc_gen(size,MEM_KIND_DYNAMIC)
-#define hl_gc_alloc_raw(size)		hl_gc_alloc_gen(size,MEM_KIND_RAW)
-#define hl_gc_alloc_finalizer(size) hl_gc_alloc_gen(size,MEM_KIND_FINALIZER)
+#define hl_gc_alloc_noptr(size)		hl_gc_alloc_gen(&hlt_bytes,size,MEM_KIND_NOPTR)
+#define hl_gc_alloc(t,size)			hl_gc_alloc_gen(t,size,MEM_KIND_DYNAMIC)
+#define hl_gc_alloc_raw(size)		hl_gc_alloc_gen(&hlt_abstract,size,MEM_KIND_RAW)
+#define hl_gc_alloc_finalizer(size) hl_gc_alloc_gen(&hlt_abstract,size,MEM_KIND_FINALIZER)
 
 
 HL_API void hl_alloc_init( hl_alloc *a );
 HL_API void hl_alloc_init( hl_alloc *a );
 HL_API void *hl_malloc( hl_alloc *a, int size );
 HL_API void *hl_malloc( hl_alloc *a, int size );

+ 4 - 4
src/jit.c

@@ -3027,9 +3027,9 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
 		case OMakeEnum:
 		case OMakeEnum:
 			{
 			{
 				hl_enum_construct *c = &dst->t->tenum->constructs[o->p2];
 				hl_enum_construct *c = &dst->t->tenum->constructs[o->p2];
-				int_val args[] = { c->size, c->hasptr?MEM_KIND_RAW:MEM_KIND_NOPTR };
+				int_val args[] = { (int_val)dst->t, c->size, c->hasptr?MEM_KIND_RAW:MEM_KIND_NOPTR };
 				int i;
 				int i;
-				call_native_consts(ctx, hl_gc_alloc_gen, args, 2);
+				call_native_consts(ctx, hl_gc_alloc_gen, args, 3);
 				op32(ctx,MOV,REG_AT(Ecx),pconst(&p,o->p2));
 				op32(ctx,MOV,REG_AT(Ecx),pconst(&p,o->p2));
 				op32(ctx,MOV,pmem(&p,Eax,0),REG_AT(Ecx));
 				op32(ctx,MOV,pmem(&p,Eax,0),REG_AT(Ecx));
 				RLOCK(PEAX);
 				RLOCK(PEAX);
@@ -3045,8 +3045,8 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
 		case OEnumAlloc:
 		case OEnumAlloc:
 			{
 			{
 				hl_enum_construct *c = &dst->t->tenum->constructs[o->p2];
 				hl_enum_construct *c = &dst->t->tenum->constructs[o->p2];
-				int_val args[] = { c->size, (c->hasptr?MEM_KIND_RAW:MEM_KIND_NOPTR) | MEM_ZERO };
-				call_native_consts(ctx, hl_gc_alloc_gen, args, 2);
+				int_val args[] = { (int_val)dst->t, c->size, (c->hasptr?MEM_KIND_RAW:MEM_KIND_NOPTR) | MEM_ZERO };
+				call_native_consts(ctx, hl_gc_alloc_gen, args, 3);
 				store(ctx, dst, PEAX, true);
 				store(ctx, dst, PEAX, true);
 				op32(ctx,MOV,REG_AT(Ecx),pconst(&p,o->p2));
 				op32(ctx,MOV,REG_AT(Ecx),pconst(&p,o->p2));
 				op32(ctx,MOV,pmem(&p,Eax,0),REG_AT(Ecx));
 				op32(ctx,MOV,pmem(&p,Eax,0),REG_AT(Ecx));

+ 1 - 1
src/std/array.c

@@ -23,7 +23,7 @@
 
 
 HL_PRIM varray *hl_alloc_array( hl_type *at, int size ) {
 HL_PRIM varray *hl_alloc_array( hl_type *at, int size ) {
 	int esize = hl_type_size(at);
 	int esize = hl_type_size(at);
-	varray *a = (varray*)hl_gc_alloc_gen(sizeof(varray) + esize*size, (hl_is_ptr(at) ? MEM_KIND_DYNAMIC : MEM_KIND_NOPTR) | MEM_ZERO);
+	varray *a = (varray*)hl_gc_alloc_gen(&hlt_array, sizeof(varray) + esize*size, (hl_is_ptr(at) ? MEM_KIND_DYNAMIC : MEM_KIND_NOPTR) | MEM_ZERO);
 	a->t = &hlt_array;
 	a->t = &hlt_array;
 	a->at = at;
 	a->at = at;
 	a->size = size;
 	a->size = size;

+ 4 - 3
src/std/fun.c

@@ -48,8 +48,9 @@ static hl_type *hl_get_closure_type( hl_type *t ) {
 }
 }
 
 
 HL_PRIM vclosure *hl_alloc_closure_ptr( hl_type *fullt, void *fvalue, void *v ) {
 HL_PRIM vclosure *hl_alloc_closure_ptr( hl_type *fullt, void *fvalue, void *v ) {
-	vclosure *c = (vclosure*)hl_gc_alloc(sizeof(vclosure));
-	c->t = hl_get_closure_type(fullt);
+	hl_type *t = hl_get_closure_type(fullt); 
+	vclosure *c = (vclosure*)hl_gc_alloc(t, sizeof(vclosure));
+	c->t = t;
 	c->fun = fvalue;
 	c->fun = fvalue;
 	c->hasValue = 1;
 	c->hasValue = 1;
 	c->value = v;
 	c->value = v;
@@ -328,7 +329,7 @@ HL_PRIM vclosure *hl_make_fun_wrapper( vclosure *v, hl_type *to ) {
 	if( wrap == NULL ) return NULL;
 	if( wrap == NULL ) return NULL;
 	if( v->fun != fun_var_args && v->t->fun->nargs != to->fun->nargs )
 	if( v->fun != fun_var_args && v->t->fun->nargs != to->fun->nargs )
 		return NULL;
 		return NULL;
-	c = (vclosure_wrapper*)hl_gc_alloc(sizeof(vclosure_wrapper));
+	c = (vclosure_wrapper*)hl_gc_alloc(to, sizeof(vclosure_wrapper));
 	c->cl.t = to;
 	c->cl.t = to;
 	c->cl.fun = wrap;
 	c->cl.fun = wrap;
 	c->cl.hasValue = 2;
 	c->cl.hasValue = 2;

+ 2 - 2
src/std/obj.c

@@ -436,7 +436,7 @@ vvirtual *hl_to_virtual( hl_type *vt, vdynamic *obj ) {
 	case HOBJ:
 	case HOBJ:
 		{
 		{
 			int i;
 			int i;
-			v = (vvirtual*)hl_gc_alloc(sizeof(vvirtual) + sizeof(void*)*vt->virt->nfields);
+			v = (vvirtual*)hl_gc_alloc(vt, sizeof(vvirtual) + sizeof(void*)*vt->virt->nfields);
 			v->t = vt;
 			v->t = vt;
 			v->value = obj;
 			v->value = obj;
 			v->next = NULL;
 			v->next = NULL;
@@ -467,7 +467,7 @@ vvirtual *hl_to_virtual( hl_type *vt, vdynamic *obj ) {
 				v = v->next;
 				v = v->next;
 			}
 			}
 			// allocate a new virtual mapping
 			// allocate a new virtual mapping
-			v = (vvirtual*)hl_gc_alloc(sizeof(vvirtual) + sizeof(void*) * vt->virt->nfields);
+			v = (vvirtual*)hl_gc_alloc(vt, sizeof(vvirtual) + sizeof(void*) * vt->virt->nfields);
 			v->t = vt;
 			v->t = vt;
 			v->value = obj;
 			v->value = obj;
 			for(i=0;i<vt->virt->nfields;i++) {
 			for(i=0;i<vt->virt->nfields;i++) {