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:
Daniel Morsing 2012-11-06 20:40:40 +01:00
parent 433b2f17ee
commit d098bffd84
4 changed files with 43 additions and 0 deletions

View File

@ -54,6 +54,8 @@ char *runtimeimport =
"func @\"\".assertI2I2(@\"\".typ *byte, @\"\".iface any) (@\"\".ret any, @\"\".ok bool)\n" "func @\"\".assertI2I2(@\"\".typ *byte, @\"\".iface any) (@\"\".ret any, @\"\".ok bool)\n"
"func @\"\".assertI2T(@\"\".typ *byte, @\"\".iface any) (@\"\".ret any)\n" "func @\"\".assertI2T(@\"\".typ *byte, @\"\".iface any) (@\"\".ret any)\n"
"func @\"\".assertI2T2(@\"\".typ *byte, @\"\".iface any) (@\"\".ret any, @\"\".ok bool)\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 @\"\".ifaceeq(@\"\".i1 any, @\"\".i2 any) (@\"\".ret bool)\n"
"func @\"\".efaceeq(@\"\".i1 any, @\"\".i2 any) (@\"\".ret bool)\n" "func @\"\".efaceeq(@\"\".i1 any, @\"\".i2 any) (@\"\".ret bool)\n"
"func @\"\".ifacethash(@\"\".i1 any) (@\"\".ret uint32)\n" "func @\"\".ifacethash(@\"\".i1 any) (@\"\".ret uint32)\n"

View File

@ -76,6 +76,8 @@ func assertI2I(typ *byte, iface any) (ret any)
func assertI2I2(typ *byte, iface any) (ret any, ok bool) func assertI2I2(typ *byte, iface any) (ret any, ok bool)
func assertI2T(typ *byte, iface any) (ret any) func assertI2T(typ *byte, iface any) (ret any)
func assertI2T2(typ *byte, iface any) (ret any, ok bool) 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 ifaceeq(i1 any, i2 any) (ret bool)
func efaceeq(i1 any, i2 any) (ret bool) func efaceeq(i1 any, i2 any) (ret bool)

View File

@ -686,6 +686,31 @@ walkexpr(Node **np, NodeList **init)
n->ninit = nil; n->ninit = nil;
r = n->rlist->n; r = n->rlist->n;
walkexprlistsafe(n->list, init); 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; r->op = ODOTTYPE2;
walkexpr(&r, init); walkexpr(&r, init);
ll = ascompatet(n->op, n->list, &r->type, 0, init); ll = ascompatet(n->op, n->list, &r->type, 0, init);

View File

@ -278,6 +278,13 @@ runtime·assertI2T2(Type *t, Iface i, ...)
copyout(t, &i.data, ret); 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); static void assertE2Tret(Type *t, Eface e, byte *ret);
// func ifaceE2T(typ *byte, iface any) (ret any) // func ifaceE2T(typ *byte, iface any) (ret any)
@ -334,6 +341,13 @@ runtime·assertE2T2(Type *t, Eface e, ...)
copyout(t, &e.data, ret); 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) // func convI2E(elem any) (ret any)
void void
runtime·convI2E(Iface i, Eface ret) runtime·convI2E(Iface i, Eface ret)