You're correct. I'm sorry about my first response; it was too brief and led
to the confusion you have. The Go escape analysis algorithm has a concept
of "loopdepth" (shortened as ld in debug output). The loopdepth is -1 for
global variables, 0 for input arguments to a function, 1 for the top level
of a function, and is incremented by 1 for each for or label statement
encountered to mark a new independent scope. In your most recent example,
using `{ }` creates a new scope technically, but for our purposes in escape
analysis, we only consider loops and labels as new scope; that means if
statements and switch statements are not counted as well. Every expression
and statement is given a loopdepth and when walking through the graph of
connected nodes, we consider an expression to be leaking if it involves a
dereference and the lhs has a lower loopdepth than the rhs (
https://github.com/golang/go/blob/master/src/cmd/compile/internal/gc/esc.go#L1803
).


For the most recent example, this is the output I get from -gcflags "-m -m
-m -m":
# command-line-arguments
./ex.go:3: can inline @"".main as: func() { var @"".m·1 map[int]int; ;
@"".m·1 = make(map[int]int); _ = @"".m·1 }
./ex.go:4:[1] main esc: m
./ex.go:4:[1] main esc: var m map[int]int
./ex.go:4:[1] main esc: m
./ex.go:4:[1] main esc: m = <N>
./ex.go:7:[1] main esc: m
./ex.go:7:[1] main esc: 0
./ex.go:7:[1] main esc: make(map[int]int)
./ex.go:7:[1] main esc: m = make(map[int]int)
./ex.go:7:[1] main escassign: m( l(4) class(PAUTO) f(1) ld(1)
assigned)[NAME] = make(map[int]int)( l(7) esc(no) ld(1))[MAKEMAP]
./ex.go:7::flows:: m <- make(map[int]int)
./ex.go:10:[1] main esc: _
./ex.go:10:[1] main esc: m
./ex.go:10:[1] main esc: _ = m

escflood:0: dst m scope:main[1]
escwalk: level:{0 0} depth:0  op=MAKEMAP make(map[int]int)( l(7) esc(no)
ld(1)) scope:main[1] extraloopdepth=-1
./ex.go:7: main make(map[int]int) does not escape

Let's focus on the following line:
./ex.go:7:[1] main escassign: m( l(4) class(PAUTO) f(1) ld(1)
assigned)[NAME] = make(map[int]int)( l(7) esc(no) ld(1))[MAKEMAP]

This describes line 7: `m = make(map[int]int)`. Notice that both `m` and
`make(map[int]int)` has loopdepth, ld(1). This is not considered to be a
leak.

Now let's look at your first escaping example, which you labeled as
example2.go:
# command-line-arguments
./example2.go:5:[1] main esc: m
./example2.go:5:[1] main esc: var m map[int]int
./example2.go:5:[1] main esc: m
./example2.go:5:[1] main esc: m = <N>
./example2.go:6:[2] main esc: false
./example2.go:7:[2] main esc: m
./example2.go:7:[2] main esc: 0
./example2.go:7:[2] main esc: make(map[int]int)
./example2.go:7:[2] main esc: m = make(map[int]int)
./example2.go:7:[2] main escassign: m( l(5) class(PAUTO) f(1) ld(1)
assigned)[NAME] = make(map[int]int)( l(7) esc(no) ld(2))[MAKEMAP]
./example2.go:7::flows:: m <- make(map[int]int)
./example2.go:6:[1] main esc: for loop
./example2.go:10:[1] main esc: _
./example2.go:10:[1] main esc: m
./example2.go:10:[1] main esc: _ = m

escflood:0: dst m scope:main[1]
escwalk: level:{0 0} depth:0  op=MAKEMAP make(map[int]int)( l(7) esc(no)
ld(2)) scope:main[2] extraloopdepth=-1
./example2.go:7: make(map[int]int) escapes to heap
./example2.go:7: from m (assigned) at ./example2.go:5

And focus on the corresponding line:
./example2.go:7:[2] main escassign: m( l(5) class(PAUTO) f(1) ld(1)
assigned)[NAME] = make(map[int]int)( l(7) esc(no) ld(2))[MAKEMAP]

Note that the loopdepth, ld, of `m` is 1, and the loopdepth, ld of
`make(map[int]int)` is 2. When walking through the MAKEMAP op `escwalk:
level:{0 0} depth:0  op=MAKEMAP make(map[int]int)( l(7) esc(no) ld(2))
scope:main[2] extraloopdepth=-1`, we consider `make(map[int]int)` to be
leaking and decide to heap allocate it.

I hope that explanation clarifies the decision made by the compiler in
these different example. Feel free to ask more questions if you'd like. You
can message me directly if you don't want to clutter the mailing list.

Thanks,
Chris

On Thu, Sep 29, 2016 at 8:20 PM, 刘桂祥 <liuguixiang...@gmail.com> wrote:

> package main
>
> func main() {
>     var m map[int]int
>
>     {
>         m = make(map[int]int)
>     }
>
>     _ = m
> }
>
> if I do this m will not escape just want to know what's the scope rule for
> escape ?  puzzled
> <http://www.baidu.com/link?url=ApC817U9uUoCFHhS_dqb5JzUWJQsslUUA6_TDv3LDZBJgaA-G2ZbRfWA-2cGajgU_MHmTiXVEouMmdPN53mMMXxYd1nvCWWJJvfu5Mmg4Ca>
>
>
> 在 2016年9月29日星期四 UTC+8上午1:39:09,Chris Manghane写道:
>>
>> In the first example, make does not escape the scope of the for
>> statement. In the second example, make is assigned to m, which is outside
>> of the scope of the for statement, which means the make operation escapes
>> its scope and subsequently, is heap allocated. If you want more information
>> about why something escapes, try compiling with -gcflags "-m -m" for an
>> explanation of the escape analysis information.
>>
>> On Wed, Sep 28, 2016 at 7:56 AM, 刘桂祥 <liuguix...@gmail.com> wrote:
>>
>>> go 1.7
>>>
>>> 在 2016年9月28日星期三 UTC+8下午10:41:09,Dave Cheney写道:
>>>
>>>> Which version of Go?
>>>>
>>>> On Thursday, 29 September 2016 00:18:29 UTC+10, 刘桂祥 wrote:
>>>>>
>>>>> // example1.go
>>>>> package main
>>>>>
>>>>>
>>>>> func main() {
>>>>>
>>>>>     for i := 0; i < 2; i++ {
>>>>>         m := make(map[int]int)
>>>>>
>>>>>
>>>>>         m[1] = 100
>>>>>     }
>>>>>
>>>>>
>>>>> }
>>>>>
>>>>>
>>>>> main make(map[int]int) does not escape
>>>>>
>>>>>
>>>>> // example2.go
>>>>> package main
>>>>>
>>>>>
>>>>> func main() {
>>>>>     var m map[int]int
>>>>>     for i := 0; i < 2; i++ {
>>>>>         m = make(map[int]int)
>>>>>
>>>>>
>>>>>         m[1] = 100
>>>>>     }
>>>>>
>>>>>
>>>>> }
>>>>>
>>>>>  make(map[int]int) escapes to heap    why ???
>>>>>
>>>>>
>>>>> --
>>> You received this message because you are subscribed to the Google
>>> Groups "golang-nuts" group.
>>> To unsubscribe from this group and stop receiving emails from it, send
>>> an email to golang-nuts...@googlegroups.com.
>>> For more options, visit https://groups.google.com/d/optout.
>>>
>>
>> --
> You received this message because you are subscribed to the Google Groups
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to golang-nuts+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to