mirror of
https://github.com/golang/go
synced 2024-11-23 06:40:05 -07:00
runtime: finish converting iface.goc to iface.go
LGTM=bradfitz, dvyukov R=golang-codereviews, bradfitz, dvyukov CC=golang-codereviews, iant, khr https://golang.org/cl/131510043
This commit is contained in:
parent
98e5a44a88
commit
b53b47f5ac
@ -584,7 +584,10 @@ itab_callback(Itab *tab)
|
||||
static void
|
||||
dumpitabs(void)
|
||||
{
|
||||
runtime·iterate_itabs(itab_callback);
|
||||
void (*fn)(Itab*);
|
||||
|
||||
fn = itab_callback;
|
||||
runtime·iterate_itabs(&fn);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -425,3 +425,16 @@ func efacethash(e interface{}) uint32 {
|
||||
}
|
||||
return t.hash
|
||||
}
|
||||
|
||||
func iterate_itabs(fn func(*itab)) {
|
||||
for _, h := range hash {
|
||||
for ; h != nil; h = h.link {
|
||||
fn(h)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func ifaceE2I2(inter *interfacetype, e interface{}, r *fInterface) (ok bool) {
|
||||
*r, ok = assertE2I2(inter, e)
|
||||
return
|
||||
}
|
||||
|
@ -1,155 +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"
|
||||
|
||||
extern Itab* runtime·hash[1009];
|
||||
extern Mutex runtime·ifaceLock;
|
||||
|
||||
// TODO: delete this when no longer used (ifaceE2I2 is all that's left)
|
||||
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->typ.hash;
|
||||
h += 17 * type->hash;
|
||||
// TODO(rsc): h += 23 * x->mhash ?
|
||||
h %= nelem(runtime·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(&runtime·ifaceLock);
|
||||
for(m=runtime·atomicloadp(&runtime·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(&runtime·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->typ.string,
|
||||
iname, &err);
|
||||
if(locked)
|
||||
runtime·unlock(&runtime·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 = runtime·hash[h];
|
||||
runtime·atomicstorep(&runtime·hash[h], m);
|
||||
runtime·unlock(&runtime·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(runtime·hash); i++) {
|
||||
for(tab = runtime·hash[i]; tab != nil; tab = tab->link) {
|
||||
callback(tab);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Still in C because it is called from C for finalizers. This will
|
||||
// get converted to Go in a separate CL. This is the last user of
|
||||
// the C version of itab().
|
||||
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;
|
||||
}
|
@ -959,7 +959,7 @@ void _rt0_go(void);
|
||||
void* runtime·funcdata(Func*, int32);
|
||||
void runtime·setmaxthreads_m(void);
|
||||
G* runtime·timejump(void);
|
||||
void runtime·iterate_itabs(void (*callback)(Itab*));
|
||||
void runtime·iterate_itabs(void (**callback)(Itab*));
|
||||
void runtime·iterate_finq(void (*callback)(FuncVal*, byte*, uintptr, Type*, PtrType*));
|
||||
|
||||
#pragma varargck argpos runtime·printf 1
|
||||
|
Loading…
Reference in New Issue
Block a user