]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/gc: apply escape analysis results to closures.
authorRémy Oudompheng <oudomphe@phare.normalesup.org>
Mon, 25 Feb 2013 23:40:28 +0000 (00:40 +0100)
committerRémy Oudompheng <oudomphe@phare.normalesup.org>
Mon, 25 Feb 2013 23:40:28 +0000 (00:40 +0100)
This avoids an allocation when closures are used
as "macros", in Walk idioms, or as argument to defer.

benchmark                old ns/op    new ns/op    delta
BenchmarkSearchWrappers       1171          354  -69.77%
BenchmarkCallClosure             3            3  -12.54%
BenchmarkCallClosure1          119            7  -93.95%
BenchmarkCallClosure2          183           74  -59.18%
BenchmarkCallClosure3          187           75  -59.57%
BenchmarkCallClosure4          187           76  -58.98%

Compared to Go 1:
benchmark                  old ns/op    new ns/op    delta
BenchmarkSearchWrappers         3208          354  -88.97%

Fixes #3520.

R=daniel.morsing, bradfitz, minux.ma, dave, rsc
CC=golang-dev
https://golang.org/cl/7397056

src/cmd/gc/closure.c
src/pkg/sort/search_test.go

index 78b73d847cafb14da8bfeaca3fc9c48a3d633b14..4e029ef83a6989a09f099055887b2108f965c109 100644 (file)
@@ -238,14 +238,18 @@ walkclosure(Node *func, NodeList **init)
        }
 
        clos = nod(OCOMPLIT, N, nod(OIND, typ, N));
+       clos->esc = func->esc;
        clos->right->implicit = 1;
        clos->list = concat(list1(nod(OCFUNC, func->closure->nname, N)), func->enter);
 
        // Force type conversion from *struct to the func type.
        clos = nod(OCONVNOP, clos, N);
        clos->type = func->type;
-       
+
        typecheck(&clos, Erv);
+       // typecheck will insert a PTRLIT node under CONVNOP,
+       // tag it with escape analysis result.
+       clos->left->esc = func->esc;
        walkexpr(&clos, init);
 
        return clos;
index 07295ffa976dc4ddc9b78966acc8d9541bf824ff..4d8d6d930b2a92952d65bf595dbb28299e061e84 100644 (file)
@@ -117,6 +117,28 @@ func TestSearchWrappers(t *testing.T) {
        }
 }
 
+func runSearchWrappers() {
+       SearchInts(data, 11)
+       SearchFloat64s(fdata, 2.1)
+       SearchStrings(sdata, "")
+       IntSlice(data).Search(0)
+       Float64Slice(fdata).Search(2.0)
+       StringSlice(sdata).Search("x")
+}
+
+func TestSearchWrappersDontAlloc(t *testing.T) {
+       allocs := testing.AllocsPerRun(100, runSearchWrappers)
+       if allocs != 0 {
+               t.Errorf("expected no allocs for runSearchWrappers, got %v", allocs)
+       }
+}
+
+func BenchmarkSearchWrappers(b *testing.B) {
+       for i := 0; i < b.N; i++ {
+               runSearchWrappers()
+       }
+}
+
 // Abstract exhaustive test: all sizes up to 100,
 // all possible return values.  If there are any small
 // corner cases, this test exercises them.