From: Rémy Oudompheng Date: Mon, 25 Feb 2013 23:40:28 +0000 (+0100) Subject: cmd/gc: apply escape analysis results to closures. X-Git-Tag: go1.1rc2~849 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=9fe60801aeca801010b42e1dd7ad57a173dc9740;p=gostls13.git cmd/gc: apply escape analysis results to closures. 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 --- diff --git a/src/cmd/gc/closure.c b/src/cmd/gc/closure.c index 78b73d847c..4e029ef83a 100644 --- a/src/cmd/gc/closure.c +++ b/src/cmd/gc/closure.c @@ -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; diff --git a/src/pkg/sort/search_test.go b/src/pkg/sort/search_test.go index 07295ffa97..4d8d6d930b 100644 --- a/src/pkg/sort/search_test.go +++ b/src/pkg/sort/search_test.go @@ -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.