diff options
Diffstat (limited to 'src/pkg/runtime/iface.goc')
-rw-r--r-- | src/pkg/runtime/iface.goc | 620 |
1 files changed, 0 insertions, 620 deletions
diff --git a/src/pkg/runtime/iface.goc b/src/pkg/runtime/iface.goc deleted file mode 100644 index c0a17e303..000000000 --- a/src/pkg/runtime/iface.goc +++ /dev/null @@ -1,620 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package runtime -#include "runtime.h" -#include "arch_GOARCH.h" -#include "type.h" -#include "typekind.h" -#include "malloc.h" -#include "../../cmd/ld/textflag.h" - -func printiface(i Iface) { - runtime·printf("(%p,%p)", i.tab, i.data); -} - -func printeface(e Eface) { - runtime·printf("(%p,%p)", e.type, e.data); -} - -static Itab* hash[1009]; -static Lock ifacelock; - -static Itab* -itab(InterfaceType *inter, Type *type, int32 canfail) -{ - int32 locked; - int32 ni; - Method *t, *et; - IMethod *i, *ei; - uint32 h; - String *iname, *ipkgPath; - Itab *m; - UncommonType *x; - Type *itype; - Eface err; - - if(inter->mhdr.len == 0) - runtime·throw("internal error - misuse of itab"); - - locked = 0; - - // easy case - x = type->x; - if(x == nil) { - if(canfail) - return nil; - iname = inter->m[0].name; - goto throw; - } - - // compiler has provided some good hash codes for us. - h = inter->hash; - h += 17 * type->hash; - // TODO(rsc): h += 23 * x->mhash ? - h %= nelem(hash); - - // look twice - once without lock, once with. - // common case will be no lock contention. - for(locked=0; locked<2; locked++) { - if(locked) - runtime·lock(&ifacelock); - for(m=runtime·atomicloadp(&hash[h]); m!=nil; m=m->link) { - if(m->inter == inter && m->type == type) { - if(m->bad) { - m = nil; - if(!canfail) { - // this can only happen if the conversion - // was already done once using the , ok form - // and we have a cached negative result. - // the cached result doesn't record which - // interface function was missing, so jump - // down to the interface check, which will - // do more work but give a better error. - goto search; - } - } - if(locked) - runtime·unlock(&ifacelock); - return m; - } - } - } - - ni = inter->mhdr.len; - m = runtime·persistentalloc(sizeof(*m) + ni*sizeof m->fun[0], 0, &mstats.other_sys); - m->inter = inter; - m->type = type; - -search: - // both inter and type have method sorted by name, - // and interface names are unique, - // 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.len; - t = x->m; - et = t + x->mhdr.len; - for(; i < ei; i++) { - itype = i->type; - iname = i->name; - ipkgPath = i->pkgPath; - for(;; t++) { - if(t >= et) { - if(!canfail) { - throw: - // didn't find method - runtime·newTypeAssertionError( - nil, type->string, inter->string, - iname, &err); - if(locked) - runtime·unlock(&ifacelock); - runtime·panic(err); - return nil; // not reached - } - m->bad = 1; - goto out; - } - if(t->mtyp == itype && t->name == iname && t->pkgPath == ipkgPath) - break; - } - if(m) - m->fun[i - inter->m] = t->ifn; - } - -out: - if(!locked) - runtime·panicstring("invalid itab locking"); - m->link = hash[h]; - runtime·atomicstorep(&hash[h], m); - runtime·unlock(&ifacelock); - if(m->bad) - return nil; - return m; -} - -// call the callback for every itab that is currently allocated. -void -runtime·iterate_itabs(void (*callback)(Itab*)) -{ - int32 i; - Itab *tab; - - for(i = 0; i < nelem(hash); i++) { - for(tab = hash[i]; tab != nil; tab = tab->link) { - callback(tab); - } - } -} - -static void -copyin(Type *t, void *src, void **dst) -{ - uintptr size; - void *p; - Alg *alg; - - size = t->size; - alg = t->alg; - - if(size <= sizeof(*dst)) - alg->copy(size, dst, src); - else { - p = runtime·cnew(t); - alg->copy(size, p, src); - *dst = p; - } -} - -static void -copyout(Type *t, void **src, void *dst) -{ - uintptr size; - Alg *alg; - - size = t->size; - alg = t->alg; - - if(size <= sizeof(*src)) - alg->copy(size, dst, src); - else - alg->copy(size, dst, *src); -} - -#pragma textflag NOSPLIT -func typ2Itab(t *Type, inter *InterfaceType, cache **Itab) (tab *Itab) { - tab = itab(inter, t, 0); - runtime·atomicstorep(cache, tab); -} - -#pragma textflag NOSPLIT -func convT2I(t *Type, inter *InterfaceType, cache **Itab, elem *byte) (ret Iface) { - Itab *tab; - - tab = runtime·atomicloadp(cache); - if(!tab) { - tab = itab(inter, t, 0); - runtime·atomicstorep(cache, tab); - } - ret.tab = tab; - copyin(t, elem, &ret.data); -} - -#pragma textflag NOSPLIT -func convT2E(t *Type, elem *byte) (ret Eface) { - ret.type = t; - copyin(t, elem, &ret.data); -} - -static void assertI2Tret(Type *t, Iface i, byte *ret); - -/* - * NOTE: Cannot use 'func' here, because we have to declare - * a return value, the only types we have are at least 1 byte large, - * goc2c will zero the return value, and the actual return value - * might have size 0 bytes, in which case the zeroing of the - * 1 or more bytes would be wrong. - * Using C lets us control (avoid) the initial zeroing. - */ -#pragma textflag NOSPLIT -void -runtime·assertI2T(Type *t, Iface i, GoOutput retbase) -{ - assertI2Tret(t, i, (byte*)&retbase); -} - -static void -assertI2Tret(Type *t, Iface i, byte *ret) -{ - Itab *tab; - Eface err; - - tab = i.tab; - if(tab == nil) { - runtime·newTypeAssertionError( - nil, nil, t->string, - nil, &err); - runtime·panic(err); - } - if(tab->type != t) { - runtime·newTypeAssertionError( - tab->inter->string, tab->type->string, t->string, - nil, &err); - runtime·panic(err); - } - copyout(t, &i.data, ret); -} - -#pragma textflag NOSPLIT -func assertI2T2(t *Type, i Iface) (ret byte, ...) { - bool *ok; - int32 wid; - - wid = t->size; - ok = (bool*)(&ret + wid); - - if(i.tab == nil || i.tab->type != t) { - *ok = false; - runtime·memclr(&ret, wid); - return; - } - - *ok = true; - copyout(t, &i.data, &ret); -} - -func assertI2TOK(t *Type, i Iface) (ok bool) { - ok = i.tab!=nil && i.tab->type==t; -} - -static void assertE2Tret(Type *t, Eface e, byte *ret); - -/* - * NOTE: Cannot use 'func' here. See assertI2T above. - */ -#pragma textflag NOSPLIT -void -runtime·assertE2T(Type *t, Eface e, GoOutput retbase) -{ - assertE2Tret(t, e, (byte*)&retbase); -} - -static void -assertE2Tret(Type *t, Eface e, byte *ret) -{ - Eface err; - - if(e.type == nil) { - runtime·newTypeAssertionError( - nil, nil, t->string, - nil, &err); - runtime·panic(err); - } - if(e.type != t) { - runtime·newTypeAssertionError( - nil, e.type->string, t->string, - nil, &err); - runtime·panic(err); - } - copyout(t, &e.data, ret); -} - -#pragma textflag NOSPLIT -func assertE2T2(t *Type, e Eface) (ret byte, ...) { - bool *ok; - int32 wid; - - wid = t->size; - ok = (bool*)(&ret + wid); - - if(t != e.type) { - *ok = false; - runtime·memclr(&ret, wid); - return; - } - - *ok = true; - copyout(t, &e.data, &ret); -} - -func assertE2TOK(t *Type, e Eface) (ok bool) { - ok = t==e.type; -} - -func convI2E(i Iface) (ret Eface) { - Itab *tab; - - ret.data = i.data; - if((tab = i.tab) == nil) - ret.type = nil; - else - ret.type = tab->type; -} - -func assertI2E(inter *InterfaceType, i Iface) (ret Eface) { - Itab *tab; - Eface err; - - tab = i.tab; - if(tab == nil) { - // explicit conversions require non-nil interface value. - runtime·newTypeAssertionError( - nil, nil, inter->string, - nil, &err); - runtime·panic(err); - } - ret.data = i.data; - ret.type = tab->type; -} - -func assertI2E2(inter *InterfaceType, i Iface) (ret Eface, ok bool) { - Itab *tab; - - USED(inter); - tab = i.tab; - if(tab == nil) { - ret.type = nil; - ok = 0; - } else { - ret.type = tab->type; - ok = 1; - } - ret.data = i.data; -} - -func convI2I(inter *InterfaceType, i Iface) (ret Iface) { - Itab *tab; - - ret.data = i.data; - if((tab = i.tab) == nil) - ret.tab = nil; - else if(tab->inter == inter) - ret.tab = tab; - else - ret.tab = itab(inter, tab->type, 0); -} - -void -runtime·ifaceI2I(InterfaceType *inter, Iface i, Iface *ret) -{ - Itab *tab; - Eface err; - - tab = i.tab; - if(tab == nil) { - // explicit conversions require non-nil interface value. - runtime·newTypeAssertionError( - nil, nil, inter->string, - nil, &err); - runtime·panic(err); - } - ret->data = i.data; - ret->tab = itab(inter, tab->type, 0); -} - -func assertI2I(inter *InterfaceType, i Iface) (ret Iface) { - runtime·ifaceI2I(inter, i, &ret); -} - -func assertI2I2(inter *InterfaceType, i Iface) (ret Iface, ok bool) { - Itab *tab; - - tab = i.tab; - if(tab != nil && (tab->inter == inter || (tab = itab(inter, tab->type, 1)) != nil)) { - ret.data = i.data; - ret.tab = tab; - ok = 1; - } else { - ret.data = 0; - ret.tab = 0; - ok = 0; - } -} - -void -runtime·ifaceE2I(InterfaceType *inter, Eface e, Iface *ret) -{ - Type *t; - Eface err; - - t = e.type; - if(t == nil) { - // explicit conversions require non-nil interface value. - runtime·newTypeAssertionError( - nil, nil, inter->string, - nil, &err); - runtime·panic(err); - } - ret->data = e.data; - ret->tab = itab(inter, t, 0); -} - -bool -runtime·ifaceE2I2(InterfaceType *inter, Eface e, Iface *ret) -{ - ret->tab = itab(inter, e.type, 1); - if(ret->tab == nil) - return false; - ret->data = e.data; - return true; -} - -func reflect·ifaceE2I(inter *InterfaceType, e Eface, dst *Iface) { - runtime·ifaceE2I(inter, e, dst); -} - -func assertE2I(inter *InterfaceType, e Eface) (ret Iface) { - runtime·ifaceE2I(inter, e, &ret); -} - -func assertE2I2(inter *InterfaceType, e Eface) (ret Iface, ok bool) { - if(e.type == nil) { - ok = 0; - ret.data = nil; - ret.tab = nil; - } else if((ret.tab = itab(inter, e.type, 1)) == nil) { - ok = 0; - ret.data = nil; - } else { - ok = 1; - ret.data = e.data; - } -} - -func assertE2E(inter *InterfaceType, e Eface) (ret Eface) { - Type *t; - Eface err; - - t = e.type; - if(t == nil) { - // explicit conversions require non-nil interface value. - runtime·newTypeAssertionError( - nil, nil, inter->string, - nil, &err); - runtime·panic(err); - } - ret = e; -} - -func assertE2E2(inter *InterfaceType, e Eface) (ret Eface, ok bool) { - USED(inter); - ret = e; - ok = e.type != nil; -} - -static uintptr -ifacehash1(void *data, Type *t, uintptr h) -{ - Alg *alg; - uintptr size; - Eface err; - - if(t == nil) - return 0; - - alg = t->alg; - size = t->size; - if(alg->hash == runtime·nohash) { - // calling nohash will panic too, - // but we can print a better error. - runtime·newErrorString(runtime·catstring(runtime·gostringnocopy((byte*)"hash of unhashable type "), *t->string), &err); - runtime·panic(err); - } - if(size <= sizeof(data)) - alg->hash(&h, size, &data); - else - alg->hash(&h, size, data); - return h; -} - -uintptr -runtime·ifacehash(Iface a, uintptr h) -{ - if(a.tab == nil) - return h; - return ifacehash1(a.data, a.tab->type, h); -} - -uintptr -runtime·efacehash(Eface a, uintptr h) -{ - return ifacehash1(a.data, a.type, h); -} - -static bool -ifaceeq1(void *data1, void *data2, Type *t) -{ - uintptr size; - Alg *alg; - Eface err; - bool eq; - - alg = t->alg; - size = t->size; - - if(alg->equal == runtime·noequal) { - // calling noequal will panic too, - // but we can print a better error. - runtime·newErrorString(runtime·catstring(runtime·gostringnocopy((byte*)"comparing uncomparable type "), *t->string), &err); - runtime·panic(err); - } - - eq = 0; - if(size <= sizeof(data1)) - alg->equal(&eq, size, &data1, &data2); - else - alg->equal(&eq, size, data1, data2); - return eq; -} - -bool -runtime·ifaceeq_c(Iface i1, Iface i2) -{ - if(i1.tab != i2.tab) - return false; - if(i1.tab == nil) - return true; - return ifaceeq1(i1.data, i2.data, i1.tab->type); -} - -bool -runtime·efaceeq_c(Eface e1, Eface e2) -{ - if(e1.type != e2.type) - return false; - if(e1.type == nil) - return true; - return ifaceeq1(e1.data, e2.data, e1.type); -} - -func ifaceeq(i1 Iface, i2 Iface) (ret bool) { - ret = runtime·ifaceeq_c(i1, i2); -} - -func efaceeq(e1 Eface, e2 Eface) (ret bool) { - ret = runtime·efaceeq_c(e1, e2); -} - -func ifacethash(i1 Iface) (ret uint32) { - Itab *tab; - - ret = 0; - tab = i1.tab; - if(tab != nil) - ret = tab->type->hash; -} - -func efacethash(e1 Eface) (ret uint32) { - Type *t; - - ret = 0; - t = e1.type; - if(t != nil) - ret = t->hash; -} - -func reflect·unsafe_Typeof(e Eface) (ret Eface) { - if(e.type == nil) { - ret.type = nil; - ret.data = nil; - } else { - ret = *(Eface*)(e.type); - } -} - -func reflect·unsafe_New(t *Type) (ret *byte) { - ret = runtime·cnew(t); -} - -func reflect·unsafe_NewArray(t *Type, n int) (ret *byte) { - ret = runtime·cnewarray(t, n); -} - -func reflect·typelinks() (ret Slice) { - extern Type *typelink[], *etypelink[]; - static int32 first = 1; - ret.array = (byte*)typelink; - ret.len = etypelink - typelink; - ret.cap = ret.len; -} |