mirror of
https://github.com/golang/go
synced 2024-11-19 22:04:44 -07:00
cmd/gc, runtime: avoid unnecessary copy on type assertion.
When the first result of a type assertion is blank, the compiler would still copy out a potentially large non-interface type. Fixes #1021. R=golang-dev, bradfitz, rsc CC=golang-dev https://golang.org/cl/6812079
This commit is contained in:
parent
433b2f17ee
commit
d098bffd84
@ -54,6 +54,8 @@ char *runtimeimport =
|
||||
"func @\"\".assertI2I2(@\"\".typ *byte, @\"\".iface any) (@\"\".ret any, @\"\".ok bool)\n"
|
||||
"func @\"\".assertI2T(@\"\".typ *byte, @\"\".iface any) (@\"\".ret any)\n"
|
||||
"func @\"\".assertI2T2(@\"\".typ *byte, @\"\".iface any) (@\"\".ret any, @\"\".ok bool)\n"
|
||||
"func @\"\".assertI2TOK(@\"\".typ *byte, @\"\".iface any) (@\"\".ok bool)\n"
|
||||
"func @\"\".assertE2TOK(@\"\".typ *byte, @\"\".iface any) (@\"\".ok bool)\n"
|
||||
"func @\"\".ifaceeq(@\"\".i1 any, @\"\".i2 any) (@\"\".ret bool)\n"
|
||||
"func @\"\".efaceeq(@\"\".i1 any, @\"\".i2 any) (@\"\".ret bool)\n"
|
||||
"func @\"\".ifacethash(@\"\".i1 any) (@\"\".ret uint32)\n"
|
||||
|
@ -76,6 +76,8 @@ func assertI2I(typ *byte, iface any) (ret any)
|
||||
func assertI2I2(typ *byte, iface any) (ret any, ok bool)
|
||||
func assertI2T(typ *byte, iface any) (ret any)
|
||||
func assertI2T2(typ *byte, iface any) (ret any, ok bool)
|
||||
func assertI2TOK(typ *byte, iface any) (ok bool)
|
||||
func assertE2TOK(typ *byte, iface any) (ok bool)
|
||||
|
||||
func ifaceeq(i1 any, i2 any) (ret bool)
|
||||
func efaceeq(i1 any, i2 any) (ret bool)
|
||||
|
@ -686,6 +686,31 @@ walkexpr(Node **np, NodeList **init)
|
||||
n->ninit = nil;
|
||||
r = n->rlist->n;
|
||||
walkexprlistsafe(n->list, init);
|
||||
if(isblank(n->list->n) && !isinter(r->type)) {
|
||||
strcpy(buf, "assert");
|
||||
p = buf+strlen(buf);
|
||||
if(isnilinter(r->left->type))
|
||||
*p++ = 'E';
|
||||
else
|
||||
*p++ = 'I';
|
||||
*p++ = '2';
|
||||
*p++ = 'T';
|
||||
*p++ = 'O';
|
||||
*p++ = 'K';
|
||||
*p = '\0';
|
||||
|
||||
fn = syslook(buf, 1);
|
||||
ll = list1(typename(r->type));
|
||||
ll = list(ll, r->left);
|
||||
argtype(fn, r->left->type);
|
||||
n1 = nod(OCALL, fn, N);
|
||||
n1->list = ll;
|
||||
n = nod(OAS, n->list->next->n, n1);
|
||||
typecheck(&n, Etop);
|
||||
walkexpr(&n, init);
|
||||
goto ret;
|
||||
}
|
||||
|
||||
r->op = ODOTTYPE2;
|
||||
walkexpr(&r, init);
|
||||
ll = ascompatet(n->op, n->list, &r->type, 0, init);
|
||||
|
@ -278,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)
|
||||
@ -334,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)
|
||||
|
Loading…
Reference in New Issue
Block a user