Browse Source

replace HL OSetMethod by object method binding (for static & dynamic methods)

Nicolas Cannasse 8 years ago
parent
commit
b528b62c1b
10 changed files with 132 additions and 34 deletions
  1. 4 0
      .gitignore
  2. 10 11
      hlc.vcxproj
  3. 0 1
      hlc.vcxproj.filters
  4. 5 0
      src/alloc.c
  5. 7 0
      src/code.c
  6. 11 0
      src/hl.h
  7. 2 18
      src/jit.c
  8. 17 0
      src/module.c
  9. 0 1
      src/opcodes.h
  10. 76 3
      src/std/obj.c

+ 4 - 0
.gitignore

@@ -27,3 +27,7 @@ ReleaseStatic
 
 
 /bin*
 /bin*
 /other/memory/*.dump
 /other/memory/*.dump
+/src/_std
+/src/hl
+/src/haxe
+/src/Makefile

+ 10 - 11
hlc.vcxproj

@@ -129,13 +129,13 @@
       <PrecompiledHeader>
       <PrecompiledHeader>
       </PrecompiledHeader>
       </PrecompiledHeader>
       <Optimization>Disabled</Optimization>
       <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions);INCLUDE_ALL</PreprocessorDefinitions>
       <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
       <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
     </ClCompile>
     </ClCompile>
     <Link>
     <Link>
       <SubSystem>Console</SubSystem>
       <SubSystem>Console</SubSystem>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>std.lib;sdl.lib;fmt.lib;ui.lib</AdditionalDependencies>
+      <AdditionalDependencies>libhl.lib;sdl.lib;fmt.lib;ui.lib;ssl.lib</AdditionalDependencies>
     </Link>
     </Link>
   </ItemDefinitionGroup>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@@ -144,12 +144,12 @@
       </PrecompiledHeader>
       </PrecompiledHeader>
       <WarningLevel>Level3</WarningLevel>
       <WarningLevel>Level3</WarningLevel>
       <Optimization>Disabled</Optimization>
       <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions);INCLUDE_ALL</PreprocessorDefinitions>
     </ClCompile>
     </ClCompile>
     <Link>
     <Link>
       <SubSystem>Console</SubSystem>
       <SubSystem>Console</SubSystem>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>std.lib;sdl.lib;fmt.lib;ui.lib</AdditionalDependencies>
+      <AdditionalDependencies>libhl.lib;sdl.lib;fmt.lib;ui.lib;ssl.lib</AdditionalDependencies>
     </Link>
     </Link>
   </ItemDefinitionGroup>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -160,7 +160,7 @@
       <Optimization>MaxSpeed</Optimization>
       <Optimization>MaxSpeed</Optimization>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <IntrinsicFunctions>true</IntrinsicFunctions>
       <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);INCLUDE_ALL</PreprocessorDefinitions>
       <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
       <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
       <WholeProgramOptimization>false</WholeProgramOptimization>
       <WholeProgramOptimization>false</WholeProgramOptimization>
       <BufferSecurityCheck>false</BufferSecurityCheck>
       <BufferSecurityCheck>false</BufferSecurityCheck>
@@ -170,7 +170,7 @@
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
       <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalDependencies>std.lib;sdl.lib;fmt.lib;ui.lib</AdditionalDependencies>
+      <AdditionalDependencies>libhl.lib;sdl.lib;fmt.lib;ui.lib;ssl.lib</AdditionalDependencies>
     </Link>
     </Link>
   </ItemDefinitionGroup>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseStatic|Win32'">
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseStatic|Win32'">
@@ -181,7 +181,7 @@
       <Optimization>MaxSpeed</Optimization>
       <Optimization>MaxSpeed</Optimization>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <IntrinsicFunctions>true</IntrinsicFunctions>
       <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);INCLUDE_ALL</PreprocessorDefinitions>
       <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
       <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
       <WholeProgramOptimization>false</WholeProgramOptimization>
       <WholeProgramOptimization>false</WholeProgramOptimization>
       <BufferSecurityCheck>false</BufferSecurityCheck>
       <BufferSecurityCheck>false</BufferSecurityCheck>
@@ -202,7 +202,7 @@
       <Optimization>MaxSpeed</Optimization>
       <Optimization>MaxSpeed</Optimization>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <IntrinsicFunctions>true</IntrinsicFunctions>
       <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);INCLUDE_ALL</PreprocessorDefinitions>
       <WholeProgramOptimization>false</WholeProgramOptimization>
       <WholeProgramOptimization>false</WholeProgramOptimization>
       <BufferSecurityCheck>false</BufferSecurityCheck>
       <BufferSecurityCheck>false</BufferSecurityCheck>
     </ClCompile>
     </ClCompile>
@@ -211,7 +211,7 @@
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
       <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalDependencies>std.lib;sdl.lib;fmt.lib;ui.lib</AdditionalDependencies>
+      <AdditionalDependencies>libhl.lib;sdl.lib;fmt.lib;ui.lib;ssl.lib</AdditionalDependencies>
     </Link>
     </Link>
   </ItemDefinitionGroup>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseStatic|x64'">
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseStatic|x64'">
@@ -222,7 +222,7 @@
       <Optimization>MaxSpeed</Optimization>
       <Optimization>MaxSpeed</Optimization>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <IntrinsicFunctions>true</IntrinsicFunctions>
       <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);INCLUDE_ALL</PreprocessorDefinitions>
       <WholeProgramOptimization>false</WholeProgramOptimization>
       <WholeProgramOptimization>false</WholeProgramOptimization>
       <BufferSecurityCheck>false</BufferSecurityCheck>
       <BufferSecurityCheck>false</BufferSecurityCheck>
     </ClCompile>
     </ClCompile>
@@ -235,7 +235,6 @@
     </Link>
     </Link>
   </ItemDefinitionGroup>
   </ItemDefinitionGroup>
   <ItemGroup>
   <ItemGroup>
-    <ClCompile Include="src\hlc_main.c" />
     <ClCompile Include="src\_main.c" />
     <ClCompile Include="src\_main.c" />
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>

+ 0 - 1
hlc.vcxproj.filters

@@ -2,7 +2,6 @@
 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup>
   <ItemGroup>
     <ClCompile Include="src\_main.c" />
     <ClCompile Include="src\_main.c" />
-    <ClCompile Include="src\hlc_main.c" />
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClInclude Include="src\hlc.h" />
     <ClInclude Include="src\hlc.h" />

+ 5 - 0
src/alloc.c

@@ -943,12 +943,17 @@ vdynamic *hl_alloc_dynamic( hl_type *t ) {
 vdynamic *hl_alloc_obj( hl_type *t ) {
 vdynamic *hl_alloc_obj( hl_type *t ) {
 	vobj *o;
 	vobj *o;
 	int size;
 	int size;
+	int i;
 	hl_runtime_obj *rt = t->obj->rt;
 	hl_runtime_obj *rt = t->obj->rt;
 	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(size, (rt->hasPtr ? MEM_KIND_DYNAMIC : MEM_KIND_NOPTR) | MEM_ZERO);
 	o->t = t;
 	o->t = t;
+	for(i=0;i<rt->nbindings;i++) {
+		hl_runtime_binding *b = rt->bindings + i;
+		*(void**)(((char*)o) + rt->fields_indexes[b->fid]) = b->closure ? hl_alloc_closure_ptr(b->closure,b->ptr,o) : b->ptr;
+	}
 	return (vdynamic*)o;
 	return (vdynamic*)o;
 }
 }
 
 

+ 7 - 0
src/code.c

@@ -173,14 +173,17 @@ static void hl_read_type( hl_reader *r, hl_type *t ) {
 			int global = UINDEX();
 			int global = UINDEX();
 			int nfields = UINDEX();
 			int nfields = UINDEX();
 			int nproto = UINDEX();
 			int nproto = UINDEX();
+			int nbindings = UINDEX();
 			t->obj = (hl_type_obj*)hl_malloc(&r->code->alloc,sizeof(hl_type_obj));
 			t->obj = (hl_type_obj*)hl_malloc(&r->code->alloc,sizeof(hl_type_obj));
 			t->obj->name = name;
 			t->obj->name = name;
 			t->obj->super = super < 0 ? NULL : r->code->types + super;
 			t->obj->super = super < 0 ? NULL : r->code->types + super;
 			t->obj->global_value = (void**)(int_val)global;
 			t->obj->global_value = (void**)(int_val)global;
 			t->obj->nfields = nfields;
 			t->obj->nfields = nfields;
 			t->obj->nproto = nproto;
 			t->obj->nproto = nproto;
+			t->obj->nbindings = nbindings;
 			t->obj->fields = (hl_obj_field*)hl_malloc(&r->code->alloc,sizeof(hl_obj_field)*nfields);
 			t->obj->fields = (hl_obj_field*)hl_malloc(&r->code->alloc,sizeof(hl_obj_field)*nfields);
 			t->obj->proto = (hl_obj_proto*)hl_malloc(&r->code->alloc,sizeof(hl_obj_proto)*nproto);
 			t->obj->proto = (hl_obj_proto*)hl_malloc(&r->code->alloc,sizeof(hl_obj_proto)*nproto);
+			t->obj->bindings = (int*)hl_malloc(&r->code->alloc,sizeof(int)*nbindings*2);
 			t->obj->rt = NULL;
 			t->obj->rt = NULL;
 			for(i=0;i<nfields;i++) {
 			for(i=0;i<nfields;i++) {
 				hl_obj_field *f = t->obj->fields + i;
 				hl_obj_field *f = t->obj->fields + i;
@@ -195,6 +198,10 @@ static void hl_read_type( hl_reader *r, hl_type *t ) {
 				p->findex = UINDEX();
 				p->findex = UINDEX();
 				p->pindex = INDEX();
 				p->pindex = INDEX();
 			}
 			}
+			for(i=0;i<nbindings;i++) {
+				t->obj->bindings[i<<1] = UINDEX();
+				t->obj->bindings[(i<<1)|1] = UINDEX();
+			}
 		}
 		}
 		break;
 		break;
 	case HREF:
 	case HREF:

+ 11 - 0
src/hl.h

@@ -260,10 +260,12 @@ typedef struct {
 typedef struct {
 typedef struct {
 	int nfields;
 	int nfields;
 	int nproto;
 	int nproto;
+	int nbindings;
 	const uchar *name;
 	const uchar *name;
 	hl_type *super;
 	hl_type *super;
 	hl_obj_field *fields;
 	hl_obj_field *fields;
 	hl_obj_proto *proto;
 	hl_obj_proto *proto;
+	int *bindings;
 	void **global_value;
 	void **global_value;
 	hl_module_context *m;
 	hl_module_context *m;
 	hl_runtime_obj *rt;
 	hl_runtime_obj *rt;
@@ -376,6 +378,12 @@ struct _hl_field_lookup {
 	int field_index; // negative or zero : index in methods
 	int field_index; // negative or zero : index in methods
 };
 };
 
 
+typedef struct {
+	void *ptr;
+	hl_type *closure;
+	int fid;
+} hl_runtime_binding;
+
 struct hl_runtime_obj {
 struct hl_runtime_obj {
 	hl_type *t;
 	hl_type *t;
 	// absolute
 	// absolute
@@ -383,9 +391,11 @@ struct hl_runtime_obj {
 	int nproto;
 	int nproto;
 	int size;
 	int size;
 	int nmethods;
 	int nmethods;
+	int nbindings;
 	bool hasPtr;
 	bool hasPtr;
 	void **methods;
 	void **methods;
 	int *fields_indexes;
 	int *fields_indexes;
+	hl_runtime_binding *bindings;
 	hl_runtime_obj *parent;
 	hl_runtime_obj *parent;
 	const uchar *(*toStringFun)( vdynamic *obj );
 	const uchar *(*toStringFun)( vdynamic *obj );
 	int (*compareFun)( vdynamic *a, vdynamic *b );
 	int (*compareFun)( vdynamic *a, vdynamic *b );
@@ -443,6 +453,7 @@ HL_API int hl_from_utf8( uchar *out, int outLen, const char *str );
 HL_API char *hl_to_utf8( const uchar *bytes );
 HL_API char *hl_to_utf8( const uchar *bytes );
 HL_API uchar *hl_to_utf16( const char *str );
 HL_API uchar *hl_to_utf16( const char *str );
 HL_API vdynamic *hl_virtual_make_value( vvirtual *v );
 HL_API vdynamic *hl_virtual_make_value( vvirtual *v );
+HL_API hl_obj_field *hl_obj_field_fetch( hl_type *t, int fid );
 
 
 HL_API int hl_hash( vbyte *name );
 HL_API int hl_hash( vbyte *name );
 HL_API int hl_hash_utf8( const char *str ); // no cache
 HL_API int hl_hash_utf8( const char *str ); // no cache

+ 2 - 18
src/jit.c

@@ -2073,7 +2073,7 @@ static double uint_to_double( unsigned int v ) {
 	return v;
 	return v;
 }
 }
 
 
-static vclosure *alloc_static_closure( jit_ctx *ctx, int fid, hl_runtime_obj *obj, int field ) {
+static vclosure *alloc_static_closure( jit_ctx *ctx, int fid ) {
 	hl_module *m = ctx->m;
 	hl_module *m = ctx->m;
 	vclosure *c = hl_malloc(&m->ctx.alloc,sizeof(vclosure));
 	vclosure *c = hl_malloc(&m->ctx.alloc,sizeof(vclosure));
 	int fidx = m->functions_indexes[fid];
 	int fidx = m->functions_indexes[fid];
@@ -2088,12 +2088,6 @@ static vclosure *alloc_static_closure( jit_ctx *ctx, int fid, hl_runtime_obj *ob
 		c->fun = (void*)(int_val)fid;
 		c->fun = (void*)(int_val)fid;
 		c->value = ctx->closure_list;
 		c->value = ctx->closure_list;
 		ctx->closure_list = c;
 		ctx->closure_list = c;
-		if( obj ) {
-			m->code->functions[fidx].obj = obj->t->obj;
-			while( field < obj->nfields - obj->t->obj->nfields )
-				obj = obj->parent;
-			m->code->functions[fidx].field = obj->t->obj->fields[field - (obj->parent?obj->parent->nfields:0)].name;
-		}
 	}
 	}
 	return c;
 	return c;
 }
 }
@@ -2607,22 +2601,12 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
 			break;
 			break;
 		case OStaticClosure:
 		case OStaticClosure:
 			{
 			{
-				vclosure *c = alloc_static_closure(ctx,o->p2,NULL,0);
+				vclosure *c = alloc_static_closure(ctx,o->p2);
 				preg *r = alloc_reg(ctx, RCPU);
 				preg *r = alloc_reg(ctx, RCPU);
 				op64(ctx, MOV, r, pconst64(&p,(int_val)c));
 				op64(ctx, MOV, r, pconst64(&p,(int_val)c));
 				store(ctx,dst,r,true);
 				store(ctx,dst,r,true);
 			}
 			}
 			break;
 			break;
-		case OSetMethod:
-			{
-				hl_runtime_obj *rt = hl_get_obj_rt(dst->t);
-				vclosure *c = alloc_static_closure(ctx,o->p3,rt,o->p2);
-				preg *r = alloc_reg(ctx, RCPU);
-				preg *ro = alloc_cpu(ctx, dst, true);
-				op64(ctx, MOV, r, pconst64(&p,(int_val)c));
-				op64(ctx, MOV, pmem(&p,(CpuReg)ro->id, rt->fields_indexes[o->p2]), r);
-			}
-			break;
 		case OField:
 		case OField:
 			{
 			{
 				switch( ra->t->kind ) {
 				switch( ra->t->kind ) {

+ 17 - 0
src/module.c

@@ -321,6 +321,23 @@ int hl_module_init( hl_module *m, void *stack_top_val ) {
 					f->obj = t->obj;
 					f->obj = t->obj;
 					f->field = p->name;
 					f->field = p->name;
 				}
 				}
+				for(j=0;j<t->obj->nbindings;j++) {
+					int fid = t->obj->bindings[j<<1];
+					int mid = t->obj->bindings[(j<<1)|1];
+					hl_obj_field *of = hl_obj_field_fetch(t,fid);
+					switch( of->t->kind ) {
+					case HFUN:
+					case HDYN:
+						{
+							hl_function *f = m->code->functions + m->functions_indexes[mid];
+							f->obj = t->obj;
+							f->field = of->name;
+						}
+						break;
+					default:
+						break;
+					}
+				}
 			}
 			}
 			break;
 			break;
 		case HENUM:
 		case HENUM:

+ 0 - 1
src/opcodes.h

@@ -79,7 +79,6 @@ OP_BEGIN
 	OP(OSetThis,2)
 	OP(OSetThis,2)
 	OP(ODynGet,3)
 	OP(ODynGet,3)
 	OP(ODynSet,3)
 	OP(ODynSet,3)
-	OP(OSetMethod,3)
 
 
 	OP(OJTrue,2)
 	OP(OJTrue,2)
 	OP(OJFalse,2)
 	OP(OJFalse,2)

+ 76 - 3
src/std/obj.c

@@ -135,6 +135,18 @@ HL_PRIM void hl_cache_free() {
 	hl_cache_count = hl_cache_size = 0;
 	hl_cache_count = hl_cache_size = 0;
 }
 }
 
 
+HL_PRIM hl_obj_field *hl_obj_field_fetch( hl_type *t, int fid ) {
+	hl_runtime_obj *rt;
+	if( t->kind != HOBJ )
+		return NULL;
+	rt = hl_get_obj_rt(t);
+	if( fid < 0 || fid >= rt->nfields )
+		return NULL;
+	while( rt->parent && fid < rt->parent->nfields )
+		rt = rt->parent;
+	return rt->t->obj->fields + (fid - (rt->parent?rt->parent->nfields:0));
+}
+
 /**
 /**
 	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.
@@ -152,21 +164,35 @@ HL_PRIM hl_runtime_obj *hl_get_obj_rt( hl_type *ot ) {
 	t->nfields = o->nfields + (p ? p->nfields : 0);
 	t->nfields = o->nfields + (p ? p->nfields : 0);
 	t->nproto = p ? p->nproto : 0;
 	t->nproto = p ? p->nproto : 0;
 	t->nlookup = o->nfields;
 	t->nlookup = o->nfields;
+	t->nbindings = p ? p->nbindings : 0;
 	t->hasPtr = p ? p->hasPtr : false;
 	t->hasPtr = p ? p->hasPtr : false;
 
 
-	if( !p )
+	if( !p ) {
 		t->nlookup += o->nproto;
 		t->nlookup += o->nproto;
-	else {
+		t->nbindings += o->nbindings;
+	} else {
 		for(i=0;i<o->nproto;i++) {
 		for(i=0;i<o->nproto;i++) {
 			hl_obj_proto *pr = o->proto + i;
 			hl_obj_proto *pr = o->proto + i;
 			if( pr->pindex >= 0 && pr->pindex < p->nproto )
 			if( pr->pindex >= 0 && pr->pindex < p->nproto )
 				continue;
 				continue;
 			t->nlookup++;
 			t->nlookup++;
 		}
 		}
+		for(i=0;i<o->nbindings;i++) {
+			int j;
+			bool found = false;
+			for(j=0;j<p->nbindings;j++)
+				if( o->bindings[i<<1] == p->bindings[j].fid ) {
+					found = true;
+					break;
+				}
+			if( !found )
+				t->nbindings++;
+		}
 	}
 	}
 
 
 	t->lookup = (hl_field_lookup*)hl_malloc(alloc,sizeof(hl_field_lookup) * t->nlookup);
 	t->lookup = (hl_field_lookup*)hl_malloc(alloc,sizeof(hl_field_lookup) * t->nlookup);
 	t->fields_indexes = (int*)hl_malloc(alloc,sizeof(int)*t->nfields);
 	t->fields_indexes = (int*)hl_malloc(alloc,sizeof(int)*t->nfields);
+	t->bindings = (hl_runtime_binding*)hl_malloc(alloc,sizeof(hl_runtime_binding)*t->nbindings);
 	t->toStringFun = NULL;
 	t->toStringFun = NULL;
 	t->compareFun = NULL;
 	t->compareFun = NULL;
 	t->castFun = NULL;
 	t->castFun = NULL;
@@ -229,7 +255,7 @@ HL_API hl_runtime_obj *hl_get_obj_proto( hl_type *ot ) {
 	hl_runtime_obj *p = NULL, *t = hl_get_obj_rt(ot);
 	hl_runtime_obj *p = NULL, *t = hl_get_obj_rt(ot);
 	hl_field_lookup *strField, *cmpField, *castField, *getField;
 	hl_field_lookup *strField, *cmpField, *castField, *getField;
 	int i;
 	int i;
-	int nmethods;
+	int nmethods, nbindings;
 	if( ot->vobj_proto ) return t;
 	if( ot->vobj_proto ) return t;
 	if( o->super ) p = hl_get_obj_proto(o->super);
 	if( o->super ) p = hl_get_obj_proto(o->super);
 
 
@@ -261,6 +287,53 @@ HL_API hl_runtime_obj *hl_get_obj_proto( hl_type *ot ) {
 		t->methods[method_index] = m->functions_ptrs[pr->findex];
 		t->methods[method_index] = m->functions_ptrs[pr->findex];
 	}
 	}
 
 
+	// bindings
+	if( p ) {
+		nbindings = p->nbindings;
+		memcpy(t->bindings,p->bindings,p->nbindings*sizeof(hl_runtime_binding));
+	} else
+		nbindings = 0;
+	for(i=0;i<o->nbindings;i++) {
+		int fid = o->bindings[i<<1];
+		int mid = o->bindings[(i<<1)|1];
+		hl_runtime_binding *b = NULL;
+		hl_type *ft;
+		if( p ) {
+			int j;
+			for(j=0;j<p->nbindings;j++)
+				if( p->bindings[j].fid == fid ) {
+					b = t->bindings + j;
+					break;
+				}
+		}
+		if( b == NULL )
+			b = t->bindings + nbindings++;
+		b->fid = fid;
+		ft = hl_obj_field_fetch(t->t, fid)->t;
+		switch( ft->kind ) {
+		case HFUN:
+			if( ft->fun->nargs == m->functions_types[mid]->fun->nargs ) {
+				// static fun
+				vclosure *c = (vclosure*)hl_malloc(alloc,sizeof(vclosure));
+				c->fun = m->functions_ptrs[mid];
+				c->t = m->functions_types[mid];
+				c->hasValue = false;
+				c->value = NULL;
+				b->closure = NULL;
+				b->ptr = c;
+				break;
+			}
+			// fallthrough
+		case HDYN: // __constructor__ is defined as dynamic in Class
+			b->closure = m->functions_types[mid];
+			b->ptr = m->functions_ptrs[mid];
+			break;
+		default:
+			hl_fatal("invalid bind field");
+			break;
+		}
+	}
+
 	strField = obj_resolve_field(o,hl_hash_gen(USTR("__string"),false));
 	strField = obj_resolve_field(o,hl_hash_gen(USTR("__string"),false));
 	cmpField = obj_resolve_field(o,hl_hash_gen(USTR("__compare"),false));
 	cmpField = obj_resolve_field(o,hl_hash_gen(USTR("__compare"),false));
 	castField = obj_resolve_field(o,hl_hash_gen(USTR("__cast"),false));
 	castField = obj_resolve_field(o,hl_hash_gen(USTR("__cast"),false));