]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/gc, runtime: avoid unnecessary copy on type assertion.
authorDaniel Morsing <daniel.morsing@gmail.com>
Tue, 6 Nov 2012 19:40:40 +0000 (20:40 +0100)
committerDaniel Morsing <daniel.morsing@gmail.com>
Tue, 6 Nov 2012 19:40:40 +0000 (20:40 +0100)
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

src/cmd/gc/builtin.c
src/cmd/gc/runtime.go
src/cmd/gc/walk.c
src/pkg/runtime/iface.c

index d993bc7fc83029a7b9b21fac7c80910f05c39648..fc9959738751ad94a89593b3a8e4affa48e239c1 100644 (file)
@@ -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"
index b8204ebcf394b636b3c7cad85c75218c5875abe4..f45de0c9978747a2bf1938ce7f92764e0525f214 100644 (file)
@@ -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)
index 2c1a32eaefd06c3f1c0fd8827c67ef5c030e54ab..ecc81c41bb570a97ec69ee3063252ad44694f3a8 100644 (file)
@@ -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);
index 634c9e98f6a0241c2f07a037afb290e0abcf1e61..f12ff7626d7e671397c81cb47d7dad4abbb25005 100644 (file)
@@ -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)