diff options
Diffstat (limited to 'src/pkg/runtime/iface.c')
-rw-r--r-- | src/pkg/runtime/iface.c | 134 |
1 files changed, 84 insertions, 50 deletions
diff --git a/src/pkg/runtime/iface.c b/src/pkg/runtime/iface.c index 2b60c4f23..370edffb8 100644 --- a/src/pkg/runtime/iface.c +++ b/src/pkg/runtime/iface.c @@ -5,6 +5,7 @@ #include "runtime.h" #include "arch_GOARCH.h" #include "type.h" +#include "typekind.h" #include "malloc.h" void @@ -19,19 +20,6 @@ runtime·printeface(Eface e) runtime·printf("(%p,%p)", e.type, e.data); } -/* - * 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; @@ -182,19 +170,37 @@ copyout(Type *t, void **src, void *dst) alg->copy(size, dst, *src); } -// func convT2I(typ *byte, typ2 *byte, elem any) (ret any) #pragma textflag 7 void -runtime·convT2I(Type *t, InterfaceType *inter, ...) +runtime·typ2Itab(Type *t, InterfaceType *inter, Itab **cache, Itab *ret) +{ + Itab *tab; + + tab = itab(inter, t, 0); + runtime·atomicstorep(cache, tab); + ret = tab; + FLUSH(&ret); +} + +// func convT2I(typ *byte, typ2 *byte, cache **byte, elem any) (ret any) +#pragma textflag 7 +void +runtime·convT2I(Type *t, InterfaceType *inter, Itab **cache, ...) { byte *elem; Iface *ret; + Itab *tab; int32 wid; - elem = (byte*)(&inter+1); + elem = (byte*)(&cache+1); wid = t->size; - ret = (Iface*)(elem + runtime·rnd(wid, Structrnd)); - ret->tab = itab(inter, t, 0); + ret = (Iface*)(elem + ROUND(wid, Structrnd)); + tab = runtime·atomicloadp(cache); + if(!tab) { + tab = itab(inter, t, 0); + runtime·atomicstorep(cache, tab); + } + ret->tab = tab; copyin(t, elem, &ret->data); } @@ -209,7 +215,7 @@ runtime·convT2E(Type *t, ...) elem = (byte*)(&t+1); wid = t->size; - ret = (Eface*)(elem + runtime·rnd(wid, Structrnd)); + ret = (Eface*)(elem + ROUND(wid, Structrnd)); ret->type = t; copyin(t, elem, &ret->data); } @@ -272,6 +278,13 @@ runtime·assertI2T2(Type *t, Iface i, ...) copyout(t, &i.data, ret); } +void +runtime·assertI2TOK(Type *t, Iface i, bool ok) +{ + ok = i.tab!=nil && i.tab->type==t; + FLUSH(&ok); +} + static void assertE2Tret(Type *t, Eface e, byte *ret); // func ifaceE2T(typ *byte, iface any) (ret any) @@ -328,6 +341,13 @@ runtime·assertE2T2(Type *t, Eface e, ...) copyout(t, &e.data, ret); } +void +runtime·assertE2TOK(Type *t, Eface e, bool ok) +{ + ok = t==e.type; + FLUSH(&ok); +} + // func convI2E(elem any) (ret any) void runtime·convI2E(Iface i, Eface ret) @@ -387,7 +407,7 @@ void runtime·convI2I(InterfaceType* inter, Iface i, Iface ret) { Itab *tab; - + ret.data = i.data; if((tab = i.tab) == nil) ret.tab = nil; @@ -526,10 +546,10 @@ runtime·assertE2E2(InterfaceType* inter, Eface e, Eface ret, bool ok) } static uintptr -ifacehash1(void *data, Type *t) +ifacehash1(void *data, Type *t, uintptr h) { Alg *alg; - uintptr size, h; + uintptr size; Eface err; if(t == nil) @@ -543,7 +563,6 @@ ifacehash1(void *data, Type *t) runtime·newErrorString(runtime·catstring(runtime·gostringnocopy((byte*)"hash of unhashable type "), *t->string), &err); runtime·panic(err); } - h = 0; if(size <= sizeof(data)) alg->hash(&h, size, &data); else @@ -552,17 +571,17 @@ ifacehash1(void *data, Type *t) } uintptr -runtime·ifacehash(Iface a) +runtime·ifacehash(Iface a, uintptr h) { if(a.tab == nil) - return 0; - return ifacehash1(a.data, a.tab->type); + return h; + return ifacehash1(a.data, a.tab->type, h); } uintptr -runtime·efacehash(Eface a) +runtime·efacehash(Eface a, uintptr h) { - return ifacehash1(a.data, a.type); + return ifacehash1(a.data, a.type, h); } static bool @@ -666,39 +685,54 @@ reflect·unsafe_Typeof(Eface e, Eface ret) } void -reflect·unsafe_New(Eface typ, void *ret) +reflect·unsafe_New(Type *t, void *ret) { - Type *t; + uint32 flag; - // 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. - t = (Type*)((Eface*)typ.data-1); + flag = t->kind&KindNoPointers ? FlagNoPointers : 0; + ret = runtime·mallocgc(t->size, flag, 1, 1); + + if(UseSpanType && !flag) { + if(false) { + runtime·printf("unsafe_New %S: %p\n", *t->string, ret); + } + runtime·settype(ret, (uintptr)t | TypeInfo_SingleObject); + } - if(t->kind&KindNoPointers) - ret = runtime·mallocgc(t->size, FlagNoPointers, 1, 1); - else - ret = runtime·mal(t->size); FLUSH(&ret); } void -reflect·unsafe_NewArray(Eface typ, uint32 n, void *ret) +reflect·unsafe_NewArray(Type *t, intgo n, void *ret) { uint64 size; - Type *t; - // 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. - t = (Type*)((Eface*)typ.data-1); - size = n*t->size; - if(t->kind&KindNoPointers) + if(size == 0) + ret = (byte*)&runtime·zerobase; + else if(t->kind&KindNoPointers) ret = runtime·mallocgc(size, FlagNoPointers, 1, 1); - else - ret = runtime·mal(size); + else { + ret = runtime·mallocgc(size, 0, 1, 1); + + if(UseSpanType) { + if(false) { + runtime·printf("unsafe_NewArray [%D]%S: %p\n", (int64)n, *t->string, ret); + } + runtime·settype(ret, (uintptr)t | TypeInfo_Array); + } + } + + FLUSH(&ret); +} + +void +reflect·typelinks(Slice ret) +{ + extern Type *typelink[], *etypelink[]; + static int32 first = 1; + ret.array = (byte*)typelink; + ret.len = etypelink - typelink; + ret.cap = ret.len; FLUSH(&ret); } |