4
4
// Escape Analysis Flaws:
5
5
// https://docs.google.com/document/d/1CxgUBPlx9iJzkz9JWkb6tIpTe5q32QDmz8l0BouG0Cw/view
6
6
7
- // Sample program to show variables stay on or escape from the stack .
7
+ // Sample program to teach the mechanics of escape analysis .
8
8
package main
9
9
10
10
// user represents a user in the system.
@@ -15,12 +15,13 @@ type user struct {
15
15
16
16
// main is the entry point for the application.
17
17
func main () {
18
- stayOnStack ()
19
- escapeToHeap ()
18
+ createUserV1 ()
19
+ createUserV2 ()
20
20
}
21
21
22
- // stayOnStack shows how the variable does not escape.
23
- func stayOnStack () user {
22
+ // createUserV1 creates a user value and passed
23
+ // a copy back to the caller.
24
+ func createUserV1 () user {
24
25
u := user {
25
26
name : "Bill" ,
26
27
@@ -29,8 +30,9 @@ func stayOnStack() user {
29
30
return u
30
31
}
31
32
32
- // escapeToHeap shows how the variable does escape.
33
- func escapeToHeap () * user {
33
+ // createUserV2 creates a user value and shares
34
+ // the value with the caller.
35
+ func createUserV2 () * user {
34
36
u := user {
35
37
name : "Bill" ,
36
38
@@ -44,49 +46,62 @@ func escapeToHeap() *user {
44
46
45
47
go build -gcflags "-m -m"
46
48
47
- ./example4.go:23 : can inline stayOnStack as: func() user { u := user literal; return u }
48
- ./example4.go:33 : can inline escapeToHeap as: func() *user { u := user literal; return &u }
49
- ./example4.go:17: can inline main as: func() { stayOnStack (); escapeToHeap () }
50
- ./example4.go:18: inlining call to stayOnStack func() user { u := user literal; return u }
51
- ./example4.go:19: inlining call to escapeToHeap func() *user { u := user literal; return &u }
49
+ ./example4.go:24 : can inline createUserV1 as: func() user { u := user literal; return u }
50
+ ./example4.go:35 : can inline createUserV2 as: func() *user { u := user literal; return &u }
51
+ ./example4.go:17: can inline main as: func() { createUserV1 (); createUserV2 () }
52
+ ./example4.go:18: inlining call to createUserV1 func() user { u := user literal; return u }
53
+ ./example4.go:19: inlining call to createUserV2 func() *user { u := user literal; return &u }
52
54
./example4.go:19: main &u does not escape
53
- ./example4.go:39 : &u escapes to heap
54
- ./example4.go:39 : from ~r0 (return) at ./example4.go:39
55
- ./example4.go:37 : moved to heap: u
55
+ ./example4.go:41 : &u escapes to heap
56
+ ./example4.go:41 : from ~r0 (return) at ./example4.go:41
57
+ ./example4.go:39 : moved to heap: u
56
58
57
59
// See the intermediate assembly phase before
58
60
// generating the actual arch-specific assembly.
59
61
60
62
go build -gcflags -S
61
63
62
- 0x000f 00015 (pointers/example4/example4.go:18) MOVQ $4, DX
63
- 0x0016 00022 (pointers/example4/example4.go:18) LEAQ go.string."[email protected] "(SB), CX
64
- 0x001d 00029 (pointers/example4/example4.go:18) MOVQ $18, AX
65
- 0x0024 00036 (pointers/example4/example4.go:18) NOP
66
- 0x0024 00036 (pointers/example4/example4.go:19) MOVQ $0, AX
67
-
64
+ "".createUserV1 t=1 size=43 args=0x20 locals=0x0
65
+ 0x0000 00000 example4.go:24 TEXT "".createUserV1(SB), $0-32
66
+ 0x0000 00000 example4.go:24 FUNCDATA $0, gclocals·ff19ed39bdde8a01a800918ac3ef0ec7(SB)
67
+ 0x0000 00000 example4.go:24 FUNCDATA $1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
68
+ 0x0000 00000 example4.go:18 LEAQ go.string."Bill"(SB), AX
69
+ 0x0007 00007 example4.go:30 MOVQ AX, "".~r0+8(FP)
70
+ 0x000c 00012 example4.go:30 MOVQ $4, "".~r0+16(FP)
71
+ 0x0015 00021 example4.go:18 LEAQ go.string."[email protected] "(SB), AX
72
+ 0x001c 00028 example4.go:30 MOVQ AX, "".~r0+24(FP)
73
+ 0x0021 00033 example4.go:30 MOVQ $18, "".~r0+32(FP)
74
+ 0x002a 00042 example4.go:30 RET
68
75
69
76
// See the actual machine representation by using
70
77
// the disasembler.
71
78
72
79
go tool objdump -s main.main example4
73
80
74
- example4.go:17 0x2040 4883ec28 SUBQ $0x28, SP
75
- example4.go:17 0x2044 48896c2420 MOVQ BP, 0x20(SP)
76
- example4.go:17 0x2049 488d6c2420 LEAQ 0x20(SP), BP
77
- example4.go:19 0x204e 48c7042400000000 MOVQ $0x0, 0(SP)
78
- example4.go:19 0x2056 48c744240800000000 MOVQ $0x0, 0x8(SP)
81
+ TEXT main.main(SB) example4.go
82
+ example4.go:17 0x104bf10 4883ec28 SUBQ $0x28, SP
83
+ example4.go:17 0x104bf14 48896c2420 MOVQ BP, 0x20(SP)
84
+ example4.go:17 0x104bf19 488d6c2420 LEAQ 0x20(SP), BP
85
+ example4.go:19 0x104bf1e 48c7042400000000 MOVQ $0x0, 0(SP)
86
+ example4.go:19 0x104bf26 48c744240800000000 MOVQ $0x0, 0x8(SP)
87
+ example4.go:19 0x104bf2f 48c744241800000000 MOVQ $0x0, 0x18(SP)
88
+ example4.go:19 0x104bf38 488d05c9a30100 LEAQ 0x1a3c9(IP), AX
89
+ example4.go:19 0x104bf3f 48890424 MOVQ AX, 0(SP)
90
+ example4.go:19 0x104bf43 48c744240804000000 MOVQ $0x4, 0x8(SP)
91
+ example4.go:19 0x104bf4c 488d05acb30100 LEAQ 0x1b3ac(IP), AX
92
+ example4.go:19 0x104bf53 4889442410 MOVQ AX, 0x10(SP)
93
+ example4.go:19 0x104bf58 48c744241812000000 MOVQ $0x12, 0x18(SP)
94
+ example4.go:20 0x104bf61 488b6c2420 MOVQ 0x20(SP), BP
95
+ example4.go:20 0x104bf66 4883c428 ADDQ $0x28, SP
96
+ example4.go:20 0x104bf6a c3 RET
79
97
80
98
// See a list of the symbols in an artifact with
81
99
// annotations and size.
82
100
83
101
go tool nm example4
84
102
85
- 6cea0 R $f64.bfe62e42fefa39ef
86
- 96d20 B __cgo_init
87
- 96d28 B __cgo_notify_runtime_init_done
88
- 96d30 B __cgo_thread_start
89
- 4c8a0 T __rt0_amd64_darwin
90
- 4af50 T _gosave
91
- 4c8c0 T _main
103
+ 104bf70 T main.init
104
+ 10b2940 B main.initdone.
105
+ 104bf10 T main.main
106
+ 10983d0 B os.executablePath
92
107
*/
0 commit comments