summaryrefslogtreecommitdiff
path: root/src/pkg/runtime/iface.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/runtime/iface.c')
-rw-r--r--src/pkg/runtime/iface.c787
1 files changed, 0 insertions, 787 deletions
diff --git a/src/pkg/runtime/iface.c b/src/pkg/runtime/iface.c
deleted file mode 100644
index b1015f695..000000000
--- a/src/pkg/runtime/iface.c
+++ /dev/null
@@ -1,787 +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.
-
-#include "runtime.h"
-#include "type.h"
-#include "malloc.h"
-
-enum
-{
- // If an empty interface has these bits set in its type
- // pointer, it was copied from a reflect.Value and is
- // not a valid empty interface.
- reflectFlags = 3,
-};
-
-void
-runtime·printiface(Iface i)
-{
- runtime·printf("(%p,%p)", i.tab, i.data);
-}
-
-void
-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;
-
-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=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·malloc(sizeof(*m) + ni*sizeof m->fun[0]);
- 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, inter,
- 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:
- m->link = hash[h];
- hash[h] = m;
- if(locked)
- runtime·unlock(&ifacelock);
- if(m->bad)
- return nil;
- return m;
-}
-
-static void
-copyin(Type *t, void *src, void **dst)
-{
- int32 wid, alg;
- void *p;
-
- wid = t->size;
- alg = t->alg;
-
- if(wid <= sizeof(*dst))
- runtime·algarray[alg].copy(wid, dst, src);
- else {
- p = runtime·mal(wid);
- runtime·algarray[alg].copy(wid, p, src);
- *dst = p;
- }
-}
-
-static void
-copyout(Type *t, void **src, void *dst)
-{
- int32 wid, alg;
-
- wid = t->size;
- alg = t->alg;
-
- if(wid <= sizeof(*src))
- runtime·algarray[alg].copy(wid, dst, src);
- else
- runtime·algarray[alg].copy(wid, dst, *src);
-}
-
-// func convT2I(typ *byte, typ2 *byte, elem any) (ret any)
-#pragma textflag 7
-void
-runtime·convT2I(Type *t, InterfaceType *inter, ...)
-{
- byte *elem;
- Iface *ret;
- int32 wid;
-
- elem = (byte*)(&inter+1);
- wid = t->size;
- ret = (Iface*)(elem + runtime·rnd(wid, Structrnd));
- ret->tab = itab(inter, t, 0);
- copyin(t, elem, &ret->data);
-}
-
-// func convT2E(typ *byte, elem any) (ret any)
-#pragma textflag 7
-void
-runtime·convT2E(Type *t, ...)
-{
- byte *elem;
- Eface *ret;
- int32 wid;
-
- elem = (byte*)(&t+1);
- wid = t->size;
- ret = (Eface*)(elem + runtime·rnd(wid, Structrnd));
- ret->type = t;
- copyin(t, elem, &ret->data);
-}
-
-static void assertI2Tret(Type *t, Iface i, byte *ret);
-
-// func ifaceI2T(typ *byte, iface any) (ret any)
-#pragma textflag 7
-void
-runtime·assertI2T(Type *t, Iface i, ...)
-{
- byte *ret;
-
- ret = (byte*)(&i+1);
- assertI2Tret(t, i, ret);
-}
-
-static void
-assertI2Tret(Type *t, Iface i, byte *ret)
-{
- Itab *tab;
- Eface err;
-
- tab = i.tab;
- if(tab == nil) {
- runtime·newTypeAssertionError(nil, nil, t,
- nil, nil, t->string,
- nil, &err);
- runtime·panic(err);
- }
- if(tab->type != t) {
- runtime·newTypeAssertionError(tab->inter, tab->type, t,
- tab->inter->string, tab->type->string, t->string,
- nil, &err);
- runtime·panic(err);
- }
- copyout(t, &i.data, ret);
-}
-
-// func ifaceI2T2(typ *byte, iface any) (ret any, ok bool)
-#pragma textflag 7
-void
-runtime·assertI2T2(Type *t, Iface i, ...)
-{
- byte *ret;
- bool *ok;
- int32 wid;
-
- ret = (byte*)(&i+1);
- wid = t->size;
- ok = (bool*)(ret+runtime·rnd(wid, 1));
-
- if(i.tab == nil || i.tab->type != t) {
- *ok = false;
- runtime·memclr(ret, wid);
- return;
- }
-
- *ok = true;
- copyout(t, &i.data, ret);
-}
-
-static void assertE2Tret(Type *t, Eface e, byte *ret);
-
-// func ifaceE2T(typ *byte, iface any) (ret any)
-#pragma textflag 7
-void
-runtime·assertE2T(Type *t, Eface e, ...)
-{
- byte *ret;
-
- if(((uintptr)e.type&reflectFlags) != 0)
- runtime·throw("invalid interface value");
- ret = (byte*)(&e+1);
- assertE2Tret(t, e, ret);
-}
-
-static void
-assertE2Tret(Type *t, Eface e, byte *ret)
-{
- Eface err;
-
- if(((uintptr)e.type&reflectFlags) != 0)
- runtime·throw("invalid interface value");
- if(e.type == nil) {
- runtime·newTypeAssertionError(nil, nil, t,
- nil, nil, t->string,
- nil, &err);
- runtime·panic(err);
- }
- if(e.type != t) {
- runtime·newTypeAssertionError(nil, e.type, t,
- nil, e.type->string, t->string,
- nil, &err);
- runtime·panic(err);
- }
- copyout(t, &e.data, ret);
-}
-
-// func ifaceE2T2(sigt *byte, iface any) (ret any, ok bool);
-#pragma textflag 7
-void
-runtime·assertE2T2(Type *t, Eface e, ...)
-{
- byte *ret;
- bool *ok;
- int32 wid;
-
- if(((uintptr)e.type&reflectFlags) != 0)
- runtime·throw("invalid interface value");
- ret = (byte*)(&e+1);
- wid = t->size;
- ok = (bool*)(ret+runtime·rnd(wid, 1));
-
- if(t != e.type) {
- *ok = false;
- runtime·memclr(ret, wid);
- return;
- }
-
- *ok = true;
- copyout(t, &e.data, ret);
-}
-
-// func convI2E(elem any) (ret any)
-void
-runtime·convI2E(Iface i, Eface ret)
-{
- Itab *tab;
-
- ret.data = i.data;
- if((tab = i.tab) == nil)
- ret.type = nil;
- else
- ret.type = tab->type;
- FLUSH(&ret);
-}
-
-// func ifaceI2E(typ *byte, iface any) (ret any)
-void
-runtime·assertI2E(InterfaceType* inter, Iface i, Eface ret)
-{
- Itab *tab;
- Eface err;
-
- tab = i.tab;
- if(tab == nil) {
- // explicit conversions require non-nil interface value.
- runtime·newTypeAssertionError(nil, nil, inter,
- nil, nil, inter->string,
- nil, &err);
- runtime·panic(err);
- }
- ret.data = i.data;
- ret.type = tab->type;
- FLUSH(&ret);
-}
-
-// func ifaceI2E2(typ *byte, iface any) (ret any, ok bool)
-void
-runtime·assertI2E2(InterfaceType* inter, Iface i, Eface ret, bool ok)
-{
- 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;
- FLUSH(&ret);
- FLUSH(&ok);
-}
-
-// func convI2I(typ *byte, elem any) (ret any)
-void
-runtime·convI2I(InterfaceType* inter, Iface i, Iface ret)
-{
- 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);
- FLUSH(&ret);
-}
-
-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,
- nil, nil, inter->string,
- nil, &err);
- runtime·panic(err);
- }
- ret->data = i.data;
- ret->tab = itab(inter, tab->type, 0);
-}
-
-// func ifaceI2I(sigi *byte, iface any) (ret any)
-void
-runtime·assertI2I(InterfaceType* inter, Iface i, Iface ret)
-{
- runtime·ifaceI2I(inter, i, &ret);
-}
-
-// func ifaceI2I2(sigi *byte, iface any) (ret any, ok bool)
-void
-runtime·assertI2I2(InterfaceType *inter, Iface i, Iface ret, bool ok)
-{
- 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;
- }
- FLUSH(&ret);
- FLUSH(&ok);
-}
-
-void
-runtime·ifaceE2I(InterfaceType *inter, Eface e, Iface *ret)
-{
- Type *t;
- Eface err;
-
- if(((uintptr)e.type&reflectFlags) != 0)
- runtime·throw("invalid interface value");
- t = e.type;
- if(t == nil) {
- // explicit conversions require non-nil interface value.
- runtime·newTypeAssertionError(nil, nil, inter,
- nil, nil, inter->string,
- nil, &err);
- runtime·panic(err);
- }
- ret->data = e.data;
- ret->tab = itab(inter, t, 0);
-}
-
-// For reflect
-// func ifaceE2I(t *InterfaceType, e interface{}, dst *Iface)
-void
-reflect·ifaceE2I(InterfaceType *inter, Eface e, Iface *dst)
-{
- runtime·ifaceE2I(inter, e, dst);
-}
-
-// func ifaceE2I(sigi *byte, iface any) (ret any)
-void
-runtime·assertE2I(InterfaceType* inter, Eface e, Iface ret)
-{
- runtime·ifaceE2I(inter, e, &ret);
-}
-
-// ifaceE2I2(sigi *byte, iface any) (ret any, ok bool)
-void
-runtime·assertE2I2(InterfaceType *inter, Eface e, Iface ret, bool ok)
-{
- if(((uintptr)e.type&reflectFlags) != 0)
- runtime·throw("invalid interface value");
- 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;
- }
- FLUSH(&ret);
- FLUSH(&ok);
-}
-
-// func ifaceE2E(typ *byte, iface any) (ret any)
-void
-runtime·assertE2E(InterfaceType* inter, Eface e, Eface ret)
-{
- Type *t;
- Eface err;
-
- if(((uintptr)e.type&reflectFlags) != 0)
- runtime·throw("invalid interface value");
- t = e.type;
- if(t == nil) {
- // explicit conversions require non-nil interface value.
- runtime·newTypeAssertionError(nil, nil, inter,
- nil, nil, inter->string,
- nil, &err);
- runtime·panic(err);
- }
- ret = e;
- FLUSH(&ret);
-}
-
-// func ifaceE2E2(iface any) (ret any, ok bool)
-void
-runtime·assertE2E2(InterfaceType* inter, Eface e, Eface ret, bool ok)
-{
- if(((uintptr)e.type&reflectFlags) != 0)
- runtime·throw("invalid interface value");
- USED(inter);
- ret = e;
- ok = e.type != nil;
- FLUSH(&ret);
- FLUSH(&ok);
-}
-
-static uintptr
-ifacehash1(void *data, Type *t)
-{
- int32 alg, wid;
- Eface err;
-
- if(t == nil)
- return 0;
-
- alg = t->alg;
- wid = t->size;
- if(runtime·algarray[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(wid <= sizeof(data))
- return runtime·algarray[alg].hash(wid, &data);
- return runtime·algarray[alg].hash(wid, data);
-}
-
-uintptr
-runtime·ifacehash(Iface a)
-{
- if(a.tab == nil)
- return 0;
- return ifacehash1(a.data, a.tab->type);
-}
-
-uintptr
-runtime·efacehash(Eface a)
-{
- return ifacehash1(a.data, a.type);
-}
-
-static bool
-ifaceeq1(void *data1, void *data2, Type *t)
-{
- int32 alg, wid;
- Eface err;
-
- alg = t->alg;
- wid = t->size;
-
- if(runtime·algarray[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);
- }
-
- if(wid <= sizeof(data1))
- return runtime·algarray[alg].equal(wid, &data1, &data2);
- return runtime·algarray[alg].equal(wid, data1, data2);
-}
-
-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(((uintptr)e1.type&reflectFlags) != 0)
- runtime·throw("invalid interface value");
- if(((uintptr)e2.type&reflectFlags) != 0)
- runtime·throw("invalid interface value");
- if(e1.type != e2.type)
- return false;
- if(e1.type == nil)
- return true;
- return ifaceeq1(e1.data, e2.data, e1.type);
-}
-
-// ifaceeq(i1 any, i2 any) (ret bool);
-void
-runtime·ifaceeq(Iface i1, Iface i2, bool ret)
-{
- ret = runtime·ifaceeq_c(i1, i2);
- FLUSH(&ret);
-}
-
-// efaceeq(i1 any, i2 any) (ret bool)
-void
-runtime·efaceeq(Eface e1, Eface e2, bool ret)
-{
- ret = runtime·efaceeq_c(e1, e2);
- FLUSH(&ret);
-}
-
-// ifacethash(i1 any) (ret uint32);
-void
-runtime·ifacethash(Iface i1, uint32 ret)
-{
- Itab *tab;
-
- ret = 0;
- tab = i1.tab;
- if(tab != nil)
- ret = tab->type->hash;
- FLUSH(&ret);
-}
-
-// efacethash(e1 any) (ret uint32)
-void
-runtime·efacethash(Eface e1, uint32 ret)
-{
- Type *t;
-
- if(((uintptr)e1.type&reflectFlags) != 0)
- runtime·throw("invalid interface value");
- ret = 0;
- t = e1.type;
- if(t != nil)
- ret = t->hash;
- FLUSH(&ret);
-}
-
-void
-unsafe·Typeof(Eface e, Eface ret)
-{
- if(((uintptr)e.type&reflectFlags) != 0)
- runtime·throw("invalid interface value");
- if(e.type == nil) {
- ret.type = nil;
- ret.data = nil;
- } else {
- ret = *(Eface*)(e.type);
- }
- FLUSH(&ret);
-}
-
-void
-unsafe·Reflect(Eface e, Eface rettype, void *retaddr)
-{
- uintptr *p;
- uintptr x;
-
- if(((uintptr)e.type&reflectFlags) != 0)
- runtime·throw("invalid interface value");
- 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;
- runtime·algarray[e.type->alg].copy(e.type->size, &x, &e.data);
-
- // but then build pointer to x so that Reflect
- // always returns pointer to data.
- p = runtime·mal(sizeof(uintptr));
- *p = x;
- } else {
- // Already a pointer, but still make a copy,
- // to preserve value semantics for interface data.
- p = runtime·mal(e.type->size);
- runtime·algarray[e.type->alg].copy(e.type->size, p, e.data);
- }
- retaddr = p;
- }
- FLUSH(&rettype);
- FLUSH(&retaddr);
-}
-
-void
-unsafe·Unreflect(Eface typ, void *addr, Eface e)
-{
- if(((uintptr)typ.type&reflectFlags) != 0)
- runtime·throw("invalid interface value");
-
- // 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))
- runtime·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;
- }
-
- FLUSH(&e);
-}
-
-void
-unsafe·New(Eface typ, void *ret)
-{
- Type *t;
-
- if(((uintptr)typ.type&reflectFlags) != 0)
- runtime·throw("invalid interface value");
-
- // 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);
-
- if(t->kind&KindNoPointers)
- ret = runtime·mallocgc(t->size, FlagNoPointers, 1, 1);
- else
- ret = runtime·mal(t->size);
- FLUSH(&ret);
-}
-
-void
-unsafe·NewArray(Eface typ, uint32 n, void *ret)
-{
- uint64 size;
- Type *t;
-
- if(((uintptr)typ.type&reflectFlags) != 0)
- runtime·throw("invalid interface value");
-
- // 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)
- ret = runtime·mallocgc(size, FlagNoPointers, 1, 1);
- else
- ret = runtime·mal(size);
- FLUSH(&ret);
-}