runtime: use new reflect data structures (CL 31107)
in place of sigi, sigt.

R=ken
OCL=31118
CL=31277
diff --git a/src/pkg/runtime/Makefile b/src/pkg/runtime/Makefile
index 4e932b0..f3eb404 100644
--- a/src/pkg/runtime/Makefile
+++ b/src/pkg/runtime/Makefile
@@ -70,6 +70,7 @@
 	sys.$O\
 	thread.$O\
 	traceback.$O\
+	type.$O\
 	$(OFILES_$(GOARCH))\
 
 HFILES=\
diff --git a/src/pkg/runtime/iface.c b/src/pkg/runtime/iface.c
index 6c933b1..cc9eb7e 100644
--- a/src/pkg/runtime/iface.c
+++ b/src/pkg/runtime/iface.c
@@ -3,173 +3,64 @@
 // license that can be found in the LICENSE file.
 
 #include "runtime.h"
-
-int32	iface_debug	= 0;
-
-typedef	struct	Sigt	Sigt;
-typedef	struct	Sigi	Sigi;
-typedef	struct	Itype	Itype;
-
-/*
- * the layout of Iface, Sigt and Sigi are known to the compiler
- */
-struct	Sigt
-{
-	byte*	name;                   // name of basic type
-	Sigt*	link;			// for linking into hash tables
-	uint32	thash;                  // hash of type
-	uint32	mhash;                  // hash of methods
-	uint16	width;			// width of base type in bytes
-	uint16	alg;			// algorithm
-	// note: on amd64 there is a 32-bit pad here.
-	struct {
-		byte*	fname;
-		uint32	fhash;		// hash of type
-		uint32	offset;		// offset of substruct
-		void	(*fun)(void);
-	} meth[1];			// one or more - last name is nil
-};
-
-struct	Sigi
-{
-	byte*	name;
-	uint32	hash;
-	uint32	size;			// number of methods
-	struct {
-		byte*	fname;
-		uint32	fhash;
-		uint32	perm;		// location of fun in Sigt
-	} meth[1];			// [size+1] - last name is nil
-};
-
-struct	Itype
-{
-	Sigi*	sigi;
-	Sigt*	sigt;
-	Itype*	link;
-	int32	bad;
-	int32	unused;
-	void	(*fun[])(void);
-};
-
-static	Iface	niliface;
-static	Eface	nileface;
-
-static	Itype*	hash[1009];
-static	Lock	ifacelock;
-
-Sigi	sigi·empty[2] =	{ (byte*)"interface { }" };
-
-static void
-printsigi(Sigi *si)
-{
-	int32 i;
-	byte *name;
-
-	sys·printpointer(si);
-	prints("{");
-	prints((int8*)si->name);
-	prints(":");
-	for(i=0;; i++) {
-		name = si->meth[i].fname;
-		if(name == nil)
-			break;
-		prints("[");
-		sys·printint(i);
-		prints("]\"");
-		prints((int8*)name);
-		prints("\"");
-		sys·printint(si->meth[i].fhash%999);
-		prints("/");
-		sys·printint(si->meth[i].perm);
-	}
-	prints("}");
-}
-
-static void
-printsigt(Sigt *st)
-{
-	int32 i;
-	byte *name;
-
-	sys·printpointer(st);
-	prints("{");
-	prints((int8*)st->name);
-	prints(":");
-	sys·printint(st->thash%999);	// type hash
-	prints(",");
-	sys·printint(st->mhash%999);	// method hash
-	prints(",");
-	sys·printint(st->width);	// width
-	prints(",");
-	sys·printint(st->alg);	// algorithm
-	for(i=0;; i++) {
-		name = st->meth[i].fname;
-		if(name == nil)
-			break;
-		prints("[");
-		sys·printint(i);
-		prints("]\"");
-		prints((int8*)name);
-		prints("\"");
-		sys·printint(st->meth[i].fhash%999);
-		prints("/");
-		sys·printint(st->meth[i].offset);
-		prints("/");
-		sys·printpointer(st->meth[i].fun);
-	}
-	prints("}");
-}
+#include "type.h"
 
 static void
 printiface(Iface i)
 {
-	prints("(");
-	sys·printpointer(i.type);
-	prints(",");
-	sys·printpointer(i.data);
-	prints(")");
+	printf("(%p,%p)", i.tab, i.data);
 }
 
 static void
 printeface(Eface e)
 {
-	prints("(");
-	sys·printpointer(e.type);
-	prints(",");
-	sys·printpointer(e.data);
-	prints(")");
+	printf("(%p,%p)", e.type, e.data);
 }
 
-static Itype*
-itype(Sigi *si, Sigt *st, int32 canfail)
+/*
+ * layout of Itab known to compilers
+ */
+struct Itab
+{
+	InterfaceType*	inter;
+	Type*	type;
+	Itab*	link;
+	int32	bad;
+	int32	unused;
+	void	(*fun[])(void);
+};
+
+static	Itab*	hash[1009];
+static	Lock	ifacelock;
+
+static Itab*
+itab(InterfaceType *inter, Type *type, int32 canfail)
 {
 	int32 locked;
-	int32 nt, ni;
+	int32 ni;
+	Method *t, *et;
+	IMethod *i, *ei;
 	uint32 ihash, h;
-	byte *sname, *iname;
-	Itype *m;
+	String *iname;
+	Itab *m;
+	UncommonType *x;
 
-	if(si->size == 0)
-		throw("internal error - misuse of itype");
+	if(inter->mhdr.nel == 0)
+		throw("internal error - misuse of itab");
 
 	// easy case
-	if(st->meth[0].fname == nil) {
+	x = type->x;
+	if(x == nil) {
 		if(canfail)
 			return nil;
-		iname = si->meth[0].fname;
-		goto throw1;
+		iname = inter->m[0].name;
+		goto throw;
 	}
 
 	// compiler has provided some good hash codes for us.
-	h = 0;
-	if(si)
-		h += si->hash;
-	if(st) {
-		h += st->thash;
-		h += st->mhash;
-	}
-
+	h = inter->hash;
+	h += 17 * type->hash;
+	// TODO(rsc): h += 23 * x->mhash ?
 	h %= nelem(hash);
 
 	// look twice - once without lock, once with.
@@ -178,7 +69,7 @@
 		if(locked)
 			lock(&ifacelock);
 		for(m=hash[h]; m!=nil; m=m->link) {
-			if(m->sigi == si && m->sigt == st) {
+			if(m->inter == inter && m->type == type) {
 				if(m->bad) {
 					m = nil;
 					if(!canfail) {
@@ -188,8 +79,8 @@
 						// the cached result doesn't record which
 						// interface function was missing, so jump
 						// down to the interface check, which will
-						// give a better error.
-						goto throw;
+						// do more work but give a better error.
+						goto search;
 					}
 				}
 				if(locked)
@@ -199,69 +90,60 @@
 		}
 	}
 
-	ni = si->size;
-	m = malloc(sizeof(*m) + ni*sizeof(m->fun[0]));
-	m->sigi = si;
-	m->sigt = st;
+	ni = inter->mhdr.nel;
+	m = malloc(sizeof(*m) + ni*sizeof m->fun[0]);
+	m->inter = inter;
+	m->type = type;
 
-throw:
-	nt = 0;
-	for(ni=0;; ni++) {
-		iname = si->meth[ni].fname;
-		if(iname == nil)
-			break;
-
-		// pick up next name from
-		// interface signature
-		ihash = si->meth[ni].fhash;
-
-		for(;; nt++) {
-			// pick up and compare next name
-			// from structure signature
-			sname = st->meth[nt].fname;
-			if(sname == nil) {
+search:
+	// both inter and type have method sorted by hash,
+	// so can iterate over both in lock step;
+	// the loop is O(ni+nt) not O(ni*nt).
+	i = inter->m;
+	ei = i + inter->mhdr.nel;
+	t = x->m;
+	et = t + x->mhdr.nel;
+	for(; i < ei; i++) {
+		ihash = i->hash;
+		iname = i->name;
+		for(;; t++) {
+			if(t >= et) {
 				if(!canfail) {
-				throw1:
-					printf("cannot convert type %s to interface %s: missing method %s\n",
-						st->name, si->name, iname);
-					if(iface_debug) {
-						prints("interface");
-						printsigi(si);
-						prints("\ntype");
-						printsigt(st);
-						prints("\n");
-					}
+				throw:
+					// didn't find method
+					printf("%S is not %S: missing method %S\n",
+						*type->string, *inter->string, *iname);
 					throw("interface conversion");
 					return nil;	// not reached
 				}
 				m->bad = 1;
-				m->link = hash[h];
-				hash[h] = m;
-				if(locked)
-					unlock(&ifacelock);
-				return nil;
+				goto out;
 			}
-			if(ihash == st->meth[nt].fhash && strcmp(sname, iname) == 0)
+			if(t->hash == ihash && t->name == iname)
 				break;
 		}
-		m->fun[si->meth[ni].perm] = st->meth[nt].fun;
+		if(m)
+			m->fun[i->perm] = t->ifn;
 	}
+
+out:
 	m->link = hash[h];
 	hash[h] = m;
 	if(locked)
 		unlock(&ifacelock);
-
+	if(m->bad)
+		return nil;
 	return m;
 }
 
 static void
-copyin(Sigt *st, void *src, void **dst)
+copyin(Type *t, void *src, void **dst)
 {
 	int32 wid, alg;
 	void *p;
 
-	wid = st->width;
-	alg = st->alg;
+	wid = t->size;
+	alg = t->alg;
 
 	if(wid <= sizeof(*dst))
 		algarray[alg].copy(wid, dst, src);
@@ -273,12 +155,12 @@
 }
 
 static void
-copyout(Sigt *st, void **src, void *dst)
+copyout(Type *t, void **src, void *dst)
 {
 	int32 wid, alg;
 
-	wid = st->width;
-	alg = st->alg;
+	wid = t->size;
+	alg = t->alg;
 
 	if(wid <= sizeof(*src))
 		algarray[alg].copy(wid, dst, src);
@@ -286,132 +168,123 @@
 		algarray[alg].copy(wid, dst, *src);
 }
 
-// ifaceT2I(sigi *byte, sigt *byte, elem any) (ret any);
+// ifaceT2I(sigi *byte, sigt *byte, elem any) (ret Iface);
 #pragma textflag 7
 void
-sys·ifaceT2I(Sigi *si, Sigt *st, ...)
+sys·ifaceT2I(InterfaceType *inter, Type *t, ...)
 {
 	byte *elem;
 	Iface *ret;
 	int32 wid;
 
-	elem = (byte*)(&st+1);
-	wid = st->width;
-	ret = (Iface*)(elem + rnd(wid, sizeof(uintptr)));
-
-	ret->type = itype(si, st, 0);
-	copyin(st, elem, &ret->data);
+	elem = (byte*)(&t+1);
+	wid = t->size;
+	ret = (Iface*)(elem + rnd(wid, Structrnd));
+	ret->tab = itab(inter, t, 0);
+	copyin(t, elem, &ret->data);
 }
 
-// ifaceT2E(sigt *byte, elem any) (ret any);
+// ifaceT2E(sigt *byte, elem any) (ret Eface);
 #pragma textflag 7
 void
-sys·ifaceT2E(Sigt *st, ...)
+sys·ifaceT2E(Type *t, ...)
 {
 	byte *elem;
 	Eface *ret;
 	int32 wid;
 
-	elem = (byte*)(&st+1);
-	wid = st->width;
-	ret = (Eface*)(elem + rnd(wid, sizeof(uintptr)));
+	elem = (byte*)(&t+1);
+	wid = t->size;
+	ret = (Eface*)(elem + rnd(wid, Structrnd));
 
-	ret->type = st;
-	copyin(st, elem, &ret->data);
+	ret->type = t;
+	copyin(t, elem, &ret->data);
 }
 
 // ifaceI2T(sigt *byte, iface any) (ret any);
 #pragma textflag 7
 void
-sys·ifaceI2T(Sigt *st, Iface i, ...)
+sys·ifaceI2T(Type *t, Iface i, ...)
 {
-	Itype *im;
+	Itab *tab;
 	byte *ret;
 
 	ret = (byte*)(&i+1);
-
-	im = i.type;
-	if(im == nil) {
-		printf("interface is nil, not %s\n", st->name);
+	tab = i.tab;
+	if(tab == nil) {
+		printf("interface is nil, not %S\n", *t->string);
 		throw("interface conversion");
 	}
-	if(im->sigt != st) {
-		printf("%s is %s, not %s\n", im->sigi->name, im->sigt->name, st->name);
+	if(tab->type != t) {
+		printf("%S is %S, not %S\n", *tab->inter->string, *tab->type->string, *t->string);
 		throw("interface conversion");
 	}
-	copyout(st, &i.data, ret);
+	copyout(t, &i.data, ret);
 }
 
-// ifaceI2T2(sigt *byte, iface any) (ret any, ok bool);
+// ifaceI2T2(sigt *byte, i Iface) (ret any, ok bool);
 #pragma textflag 7
 void
-sys·ifaceI2T2(Sigt *st, Iface i, ...)
+sys·ifaceI2T2(Type *t, Iface i, ...)
 {
 	byte *ret;
 	bool *ok;
-	Itype *im;
 	int32 wid;
 
 	ret = (byte*)(&i+1);
-	wid = st->width;
+	wid = t->size;
 	ok = (bool*)(ret+rnd(wid, 1));
 
-	im = i.type;
-	if(im == nil || im->sigt != st) {
+	if(i.tab == nil || i.tab->type != t) {
 		*ok = false;
 		sys·memclr(ret, wid);
 		return;
 	}
 
 	*ok = true;
-	copyout(st, &i.data, ret);
+	copyout(t, &i.data, ret);
 }
 
-// ifaceE2T(sigt *byte, iface any) (ret any);
+// ifaceE2T(sigt *byte, e Eface) (ret any);
 #pragma textflag 7
 void
-sys·ifaceE2T(Sigt *st, Eface e, ...)
+sys·ifaceE2T(Type *t, Eface e, ...)
 {
-	Sigt *t;
 	byte *ret;
 
 	ret = (byte*)(&e+1);
 
-	t = e.type;
-	if(t == nil) {
-		printf("interface is nil, not %s\n", st->name);
+	if(e.type != t) {
+		if(e.type == nil)
+			printf("interface is nil, not %S\n", *t->string);
+		else
+			printf("interface is %S, not %S\n", *e.type->string, *t->string);
 		throw("interface conversion");
 	}
-	if(t != st) {
-		printf("interface is %s, not %s\n", t->name, st->name);
-		throw("interface conversion");
-	}
-	copyout(st, &e.data, ret);
+	copyout(t, &e.data, ret);
 }
 
 // ifaceE2T2(sigt *byte, iface any) (ret any, ok bool);
 #pragma textflag 7
 void
-sys·ifaceE2T2(Sigt *st, Eface e, ...)
+sys·ifaceE2T2(Type *t, Eface e, ...)
 {
 	byte *ret;
 	bool *ok;
-	Sigt *t;
 	int32 wid;
 
 	ret = (byte*)(&e+1);
-	wid = st->width;
+	wid = t->size;
 	ok = (bool*)(ret+rnd(wid, 1));
 
-	t = e.type;
-	if(t != st) {
+	if(t != e.type) {
 		*ok = false;
 		sys·memclr(ret, wid);
 		return;
 	}
 
 	*ok = true;
-	copyout(st, &e.data, ret);
+	copyout(t, &e.data, ret);
 }
 
 // ifaceI2E(sigi *byte, iface any) (ret any);
@@ -419,33 +292,35 @@
 void
 sys·ifaceI2E(Iface i, Eface ret)
 {
-	Itype *im;
+	Itab *tab;
 
 	ret.data = i.data;
-	im = i.type;
-	if(im == nil)
+	tab = i.tab;
+	if(tab == nil)
 		ret.type = nil;
 	else
-		ret.type = im->sigt;
+		ret.type = tab->type;
 	FLUSH(&ret);
 }
 
 // ifaceI2I(sigi *byte, iface any) (ret any);
-// called only for implicit (no type assertion) conversions
+// called only for implicit (no type assertion) conversions.
+// converting nil is okay.
 void
-sys·ifaceI2I(Sigi *si, Iface i, Iface ret)
+sys·ifaceI2I(InterfaceType *inter, Iface i, Iface ret)
 {
-	Itype *im;
+	Itab *tab;
 
-	im = i.type;
-	if(im == nil) {
+	tab = i.tab;
+	if(tab == nil) {
 		// If incoming interface is uninitialized (zeroed)
 		// make the outgoing interface zeroed as well.
-		ret = niliface;
+		ret.tab = nil;
+		ret.data = nil;
 	} else {
 		ret = i;
-		if(im->sigi != si)
-			ret.type = itype(si, im->sigt, 0);
+		if(tab->inter != inter)
+			ret.tab = itab(inter, tab->type, 0);
 	}
 
 	FLUSH(&ret);
@@ -453,20 +328,21 @@
 
 // ifaceI2Ix(sigi *byte, iface any) (ret any);
 // called only for explicit conversions (with type assertion).
+// converting nil is not okay.
 void
-sys·ifaceI2Ix(Sigi *si, Iface i, Iface ret)
+sys·ifaceI2Ix(InterfaceType *inter, Iface i, Iface ret)
 {
-	Itype *im;
+	Itab *tab;
 
-	im = i.type;
-	if(im == nil) {
+	tab = i.tab;
+	if(tab == nil) {
 		// explicit conversions require non-nil interface value.
-		printf("interface is nil, not %s\n", si->name);
+		printf("interface is nil, not %S\n", *inter->string);
 		throw("interface conversion");
 	} else {
 		ret = i;
-		if(im->sigi != si)
-			ret.type = itype(si, im->sigt, 0);
+		if(tab->inter != inter)
+			ret.tab = itab(inter, tab->type, 0);
 	}
 
 	FLUSH(&ret);
@@ -474,22 +350,23 @@
 
 // ifaceI2I2(sigi *byte, iface any) (ret any, ok bool);
 void
-sys·ifaceI2I2(Sigi *si, Iface i, Iface ret, bool ok)
+sys·ifaceI2I2(InterfaceType *inter, Iface i, Iface ret, bool ok)
 {
-	Itype *im;
+	Itab *tab;
 
-	im = i.type;
-	if(im == nil) {
+	tab = i.tab;
+	if(tab == nil) {
 		// If incoming interface is nil, the conversion fails.
-		ret = niliface;
+		ret.tab = nil;
+		ret.data = nil;
 		ok = false;
 	} else {
 		ret = i;
 		ok = true;
-		if(im->sigi != si) {
-			ret.type = itype(si, im->sigt, 1);
-			if(ret.type == nil) {
-				ret = niliface;
+		if(tab->inter != inter) {
+			ret.tab = itab(inter, tab->type, 1);
+			if(ret.tab == nil) {
+				ret.data = nil;
 				ok = false;
 			}
 		}
@@ -502,39 +379,40 @@
 // ifaceE2I(sigi *byte, iface any) (ret any);
 // Called only for explicit conversions (with type assertion).
 void
-sys·ifaceE2I(Sigi *si, Eface e, Iface ret)
+sys·ifaceE2I(InterfaceType *inter, Eface e, Iface ret)
 {
-	Sigt *t;
+	Type *t;
 
 	t = e.type;
 	if(t == nil) {
 		// explicit conversions require non-nil interface value.
-		printf("interface is nil, not %s\n", si->name);
+		printf("interface is nil, not %S\n", *inter->string);
 		throw("interface conversion");
 	} else {
 		ret.data = e.data;
-		ret.type = itype(si, t, 0);
+		ret.tab = itab(inter, t, 0);
 	}
 	FLUSH(&ret);
 }
 
 // ifaceE2I2(sigi *byte, iface any) (ret any, ok bool);
 void
-sys·ifaceE2I2(Sigi *si, Eface e, Iface ret, bool ok)
+sys·ifaceE2I2(InterfaceType *inter, Eface e, Iface ret, bool ok)
 {
-	Sigt *t;
+	Type *t;
 
 	t = e.type;
 	ok = true;
 	if(t == nil) {
 		// If incoming interface is nil, the conversion fails.
-		ret = niliface;
+		ret.data = nil;
+		ret.tab = nil;
 		ok = false;
 	} else {
 		ret.data = e.data;
-		ret.type = itype(si, t, 1);
-		if(ret.type == nil) {
-			ret = niliface;
+		ret.tab = itab(inter, t, 1);
+		if(ret.tab == nil) {
+			ret.data = nil;
 			ok = false;
 		}
 	}
@@ -543,19 +421,19 @@
 }
 
 static uintptr
-ifacehash1(void *data, Sigt *sigt)
+ifacehash1(void *data, Type *t)
 {
 	int32 alg, wid;
 
-	if(sigt == nil)
+	if(t == nil)
 		return 0;
 
-	alg = sigt->alg;
-	wid = sigt->width;
+	alg = t->alg;
+	wid = t->size;
 	if(algarray[alg].hash == nohash) {
 		// calling nohash will throw too,
 		// but we can print a better error.
-		printf("hash of unhashable type %s\n", sigt->name);
+		printf("hash of unhashable type %S\n", *t->string);
 		if(alg == AFAKE)
 			throw("fake interface hash");
 		throw("interface hash");
@@ -568,9 +446,9 @@
 uintptr
 ifacehash(Iface a)
 {
-	if(a.type == nil)
+	if(a.tab == nil)
 		return 0;
-	return ifacehash1(a.data, a.type->sigt);
+	return ifacehash1(a.data, a.tab->type);
 }
 
 uintptr
@@ -580,17 +458,17 @@
 }
 
 static bool
-ifaceeq1(void *data1, void *data2, Sigt *sigt)
+ifaceeq1(void *data1, void *data2, Type *t)
 {
 	int32 alg, wid;
 
-	alg = sigt->alg;
-	wid = sigt->width;
+	alg = t->alg;
+	wid = t->size;
 
 	if(algarray[alg].equal == noequal) {
 		// calling noequal will throw too,
 		// but we can print a better error.
-		printf("comparing uncomparable type %s\n", sigt->name);
+		printf("comparing uncomparable type %S\n", *t->string);
 		if(alg == AFAKE)
 			throw("fake interface compare");
 		throw("interface compare");
@@ -604,11 +482,11 @@
 bool
 ifaceeq(Iface i1, Iface i2)
 {
-	if(i1.type != i2.type)
+	if(i1.tab != i2.tab)
 		return false;
-	if(i1.type == nil)
+	if(i1.tab == nil)
 		return true;
-	return ifaceeq1(i1.data, i2.data, i1.type->sigt);
+	return ifaceeq1(i1.data, i2.data, i1.tab->type);
 }
 
 bool
@@ -641,16 +519,12 @@
 void
 sys·ifacethash(Iface i1, uint32 ret)
 {
-	Itype *im;
-	Sigt *st;
+	Itab *tab;
 
 	ret = 0;
-	im = i1.type;
-	if(im != nil) {
-		st = im->sigt;
-		if(st != nil)
-			ret = st->thash;
-	}
+	tab = i1.tab;
+	if(tab != nil)
+		ret = tab->type->hash;
 	FLUSH(&ret);
 }
 
@@ -658,12 +532,12 @@
 void
 sys·efacethash(Eface e1, uint32 ret)
 {
-	Sigt *st;
+	Type *t;
 
 	ret = 0;
-	st = e1.type;
-	if(st != nil)
-		ret = st->thash;
+	t = e1.type;
+	if(t != nil)
+		ret = t->hash;
 	FLUSH(&ret);
 }
 
@@ -680,227 +554,68 @@
 }
 
 void
-unsafe·Reflect(Eface i, uint64 retit, String rettype, bool retindir)
+unsafe·Typeof(Eface e, Eface ret)
 {
-	int32 wid;
-
-	if(i.type == nil) {
-		retit = 0;
-		rettype = emptystring;
-		retindir = false;
-	} else {
-		retit = (uint64)i.data;
-		rettype = gostring(i.type->name);
-		wid = i.type->width;
-		retindir = wid > sizeof(i.data);
-	}
-	FLUSH(&retit);
-	FLUSH(&rettype);
-	FLUSH(&retindir);
+	if(e.type == nil) {
+		ret.type = nil;
+		ret.data = nil;
+	} else
+		ret = *(Eface*)e.type;
+	FLUSH(&ret);
 }
 
-extern Sigt *gotypesigs[];
-extern int32 ngotypesigs;
-
-
-// The reflection library can ask to unreflect on a type
-// that has never been used, so we don't have a signature for it.
-// For concreteness, suppose a program does
-//
-// 	type T struct{ x []int }
-// 	var t T;
-// 	v := reflect.NewValue(v);
-// 	vv := v.Field(0);
-// 	if s, ok := vv.Interface().(string) {
-// 		print("first field is string");
-// 	}
-//
-// vv.Interface() returns the result of sys.Unreflect with
-// a typestring of "[]int".  If []int is not used with interfaces
-// in the rest of the program, there will be no signature in gotypesigs
-// for "[]int", so we have to invent one.  The requirements
-// on the fake signature are:
-//
-//	(1) any interface conversion using the signature will fail
-//	(2) calling unsafe.Reflect() returns the args to unreflect
-//	(3) the right algorithm type is used, for == and map insertion
-//
-// (1) is ensured by the fact that we allocate a new Sigt,
-// so it will necessarily be != any Sigt in gotypesigs.
-// (2) is ensured by storing the type string in the signature
-// and setting the width to force the correct value of the bool indir.
-// (3) is ensured by sniffing the type string.
-//
-// Note that (1) is correct behavior: if the program had tested
-// for .([]int) instead of .(string) above, then there would be a
-// signature with type string "[]int" in gotypesigs, and unreflect
-// wouldn't call fakesigt.
-
-static	Sigt*	fake[1009];
-static	int32	nfake;
-
-enum
-{
-	SizeofInt = 4,
-	SizeofFloat = 4,
-};
-
-// Table of prefixes of names of comparable types.
-static	struct {
-	int8 *s;
-	int8 n;
-	int8 alg;
-	int8 w;
-} cmp[] =
-{
-	// basic types
-	"int", 3+1, AMEM, SizeofInt, // +1 is NUL
-	"uint", 4+1, AMEM, SizeofInt,
-	"int8", 4+1, AMEM, 1,
-	"uint8", 5+1, AMEM, 1,
-	"int16", 5+1, AMEM, 2,
-	"uint16", 6+1, AMEM, 2,
-	"int32", 5+1, AMEM, 4,
-	"uint32", 6+1, AMEM, 4,
-	"int64", 5+1, AMEM, 8,
-	"uint64", 6+1, AMEM, 8,
-	"uintptr", 7+1, AMEM, sizeof(uintptr),
-	"float", 5+1, AMEM, SizeofFloat,
-	"float32", 7+1, AMEM, 4,
-	"float64", 7+1, AMEM, 8,
-	"bool", 4+1, AMEM, sizeof(bool),
-
-	// string compare is special
-	"string", 6+1, ASTRING, sizeof(String),
-
-	// generic types, identified by prefix
-	"*", 1, AMEM, sizeof(uintptr),
-	"chan ", 5, AMEM, sizeof(uintptr),
-	"func(", 5, AMEM, sizeof(uintptr),
-	"map[", 4, AMEM, sizeof(uintptr),
-};
-
-static Sigt*
-fakesigt(String type, bool indir)
-{
-	Sigt *sigt;
-	uint32 h;
-	int32 i, locked;
-
-	h = 0;
-	for(i=0; i<type.len; i++)
-		h = h*37 + type.str[i];
-	h += indir;
-	h %= nelem(fake);
-
-	for(locked=0; locked<2; locked++) {
-		if(locked)
-			lock(&ifacelock);
-		for(sigt = fake[h]; sigt != nil; sigt = sigt->link) {
-			// don't need to compare indir.
-			// same type string but different indir will have
-			// different hashes.
-			if(mcmp(sigt->name, type.str, type.len) == 0)
-			if(sigt->name[type.len] == '\0') {
-				if(locked)
-					unlock(&ifacelock);
-				return sigt;
-			}
-		}
-	}
-
-	sigt = malloc(sizeof(*sigt));
-	sigt->name = malloc(type.len + 1);
-	mcpy(sigt->name, type.str, type.len);
-
-	sigt->alg = AFAKE;
-	sigt->width = 1;  // small width
-	if(indir)
-		sigt->width = 2*sizeof(niliface.data);  // big width
-
-	// AFAKE is like ANOEQ; check whether the type
-	// should have a more capable algorithm.
-	for(i=0; i<nelem(cmp); i++) {
-		if(mcmp((byte*)sigt->name, (byte*)cmp[i].s, cmp[i].n) == 0) {
-			sigt->alg = cmp[i].alg;
-			sigt->width = cmp[i].w;
-			break;
-		}
-	}
-
-	sigt->link = fake[h];
-	fake[h] = sigt;
-
-	unlock(&ifacelock);
-	return sigt;
-}
-
-static int32
-cmpstringchars(String a, uint8 *b)
-{
-	int32 i;
-	byte c1, c2;
-
-	for(i=0;; i++) {
-		c1 = 0;
-		if(i < a.len)
-			c1 = a.str[i];
-		c2 = b[i];
-		if(c1 < c2)
-			return -1;
-		if(c1 > c2)
-			return +1;
-		if(c1 == 0)
-			return 0;
-	}
-}
-
-static Sigt*
-findtype(String type, bool indir)
-{
-	int32 i, lo, hi, m;
-
-	lo = 0;
-	hi = ngotypesigs;
-	while(lo < hi) {
-		m = lo + (hi - lo)/2;
-		i = cmpstringchars(type, gotypesigs[m]->name);
-		if(i == 0)
-			return gotypesigs[m];
-		if(i < 0)
-			hi = m;
-		else
-			lo = m+1;
-	}
-	return fakesigt(type, indir);
-}
-
-
 void
-unsafe·Unreflect(uint64 it, String type, bool indir, Eface ret)
+unsafe·Reflect(Eface e, Eface rettype, void *retaddr)
 {
-	Sigt *sigt;
+	uintptr *p;
+	uintptr x;
 
-	ret = nileface;
+	if(e.type == nil) {
+		rettype.type = nil;
+		rettype.data = nil;
+		retaddr = 0;
+	} else {
+		rettype = *(Eface*)e.type;
+		if(e.type->size <= sizeof(uintptr)) {
+			// Copy data into x ...
+			x = 0;
+			algarray[e.type->alg].copy(e.type->size, &x, &e.data);
 
-	if(cmpstring(type, emptystring) == 0)
-		goto out;
+			// but then build pointer to x so that Reflect
+			// always returns pointer to data.
+			p = mallocgc(sizeof(uintptr));
+			*p = x;
+		} else {
+			// Already a pointer, but still make a copy,
+			// to preserve value semantics for interface data.
+			p = mallocgc(e.type->size);
+			algarray[e.type->alg].copy(e.type->size, p, e.data);
+		}
+		retaddr = p;
+	}
+	FLUSH(&rettype);
+	FLUSH(&retaddr);
+}
 
-	if(type.len > 10 && mcmp(type.str, (byte*)"interface ", 10) == 0) {
-		printf("unsafe.Unreflect: cannot put %S in interface\n", type);
-		throw("unsafe.Unreflect");
+void
+unsafe·Unreflect(Iface typ, void *addr, Eface e)
+{
+	// Reflect library has reinterpreted typ
+	// as its own kind of type structure.
+	// We know that the pointer to the original
+	// type structure sits before the data pointer.
+	e.type = (Type*)((Eface*)typ.data-1);
+
+	// Interface holds either pointer to data
+	// or copy of original data.
+	if(e.type->size <= sizeof(uintptr))
+		algarray[e.type->alg].copy(e.type->size, &e.data, addr);
+	else {
+		// Easier: already a pointer to data.
+		// TODO(rsc): Should this make a copy?
+		e.data = addr;
 	}
 
-	// if we think the type should be indirect
-	// and caller does not, play it safe, return nil.
-	sigt = findtype(type, indir);
-	if(indir != (sigt->width > sizeof(ret.data)))
-		goto out;
-
-	ret.type = sigt;
-	ret.data = (void*)it;
-
-out:
-	FLUSH(&ret);
+	FLUSH(&e);
 }
 
diff --git a/src/pkg/runtime/print.c b/src/pkg/runtime/print.c
index c7e0903..c9929cd 100644
--- a/src/pkg/runtime/print.c
+++ b/src/pkg/runtime/print.c
@@ -76,10 +76,10 @@
 			sys·printint(*(int64*)arg);
 			break;
 		case 'x':
-			sys·printhex(*(int32*)arg);
+			sys·printhex(*(uint32*)arg);
 			break;
 		case 'X':
-			sys·printhex(*(int64*)arg);
+			sys·printhex(*(uint64*)arg);
 			break;
 		case 'p':
 			sys·printpointer(*(void**)arg);
diff --git a/src/pkg/runtime/runtime.h b/src/pkg/runtime/runtime.h
index 8f1cfa7..26dfe70 100644
--- a/src/pkg/runtime/runtime.h
+++ b/src/pkg/runtime/runtime.h
@@ -56,9 +56,9 @@
 typedef	struct	SigTab		SigTab;
 typedef	struct	MCache		MCache;
 typedef	struct	Iface		Iface;
-typedef	struct	Itype		Itype;
+typedef	struct	Itab		Itab;
 typedef	struct	Eface	Eface;
-typedef	struct	Sigt		Sigt;
+typedef	struct	Type		Type;
 typedef	struct	Defer		Defer;
 
 /*
@@ -117,12 +117,12 @@
 };
 struct Iface
 {
-	Itype*	type;
+	Itab*	tab;
 	void*	data;
 };
 struct Eface
 {
-	Sigt*		type;
+	Type*	type;
 	void*	data;
 };