Sfoglia il codice sorgente

added recast to speedup virtual access

ncannasse 7 anni fa
parent
commit
13d0f63d45
1 ha cambiato i file con 33 aggiunte e 1 eliminazioni
  1. 33 1
      src/std/obj.c

+ 33 - 1
src/std/obj.c

@@ -457,6 +457,20 @@ vdynamic *hl_virtual_make_value( vvirtual *v ) {
 	return v->value;
 }
 
+static bool should_recast( hl_type *t, hl_type *vt ) {
+	if( vt->kind == HF64 && t->kind == HI32 )
+		return true;
+	if( vt->kind == HNULL && vt->tparam->kind == t->kind )
+		return true;
+	if( vt->kind == HNULL && vt->tparam->kind == HF64 && t->kind == HI32 )
+		return true;
+	if( vt->kind == HVIRTUAL && t->kind == HDYNOBJ )
+		return true;
+	if( vt->kind == HOBJ && t->kind == HOBJ && vt->obj->rt->castFun )
+		return true;
+	return false;
+}
+
 /**
 	Allocate a virtual fields mapping to a given value.
 **/
@@ -493,6 +507,7 @@ vvirtual *hl_to_virtual( hl_type *vt, vdynamic *obj ) {
 	case HDYNOBJ:
 		{
 			int i;
+			int64 need_recast = 0;
 			vdynobj *o = (vdynobj*)obj;
 			v = o->virtuals;
 			while( v ) {
@@ -506,11 +521,28 @@ vvirtual *hl_to_virtual( hl_type *vt, vdynamic *obj ) {
 			v->value = obj;
 			for(i=0;i<vt->virt->nfields;i++) {
 				hl_field_lookup *f = hl_lookup_find(o->lookup,o->nfields,vt->virt->fields[i].hashed_name);
-				hl_vfields(v)[i] = f == NULL || !hl_same_type(f->t,vt->virt->fields[i].t) ? NULL : hl_dynobj_field(o,f);
+				hl_type *vft = vt->virt->fields[i].t;
+				void *addr = f == NULL || !hl_same_type(f->t,vft) ? NULL : hl_dynobj_field(o,f);
+				// check if we will perform recast of some fields to match the virtual definition
+				// recast will not work for >64 fields, but this should be pretty rare
+				if( addr == NULL && f && !o->virtuals && should_recast(f->t,vft) )
+					need_recast |= ((int64)1) << ((int64)i);
+				hl_vfields(v)[i] = addr;
 			}
 			// add it to the list
 			v->next = o->virtuals;
 			o->virtuals = v;
+			// recast
+			if( need_recast ) {
+				for(i=0;i<vt->virt->nfields;i++)
+					if( need_recast & (((int64)1) << ((int64)i)) ) {
+						hl_obj_field *f = vt->virt->fields + i;
+						if( hl_is_ptr(f->t) )
+							hl_dyn_setp(obj,f->hashed_name,f->t,hl_dyn_getp(obj,f->hashed_name,f->t));
+						else if( f->t->kind == HF64 )
+							hl_dyn_setd(obj,f->hashed_name,hl_dyn_getd(obj,f->hashed_name));
+					}
+			}
 		}
 		break;
 	case HVIRTUAL: