Go Stack: Should it be
Moving Like That?
Yarden Laifenfeld
Slide 2
Slide 2 text
2
Who Am I?
• Software Engineer at Rookout
• Go, Java, Ruby
• C#, Python, JavaScript, C++
• Amateur sewist
Slide 3
Slide 3 text
What is Stack?
● Section of memory
○ One stack per thread
● Works like a stack (LIFO)
● Stores function parameters, local variables, return addresses
3
Slide 4
Slide 4 text
What is Stack?
4
…
func runFirst() {
a := 1
runSecond(a, 2)
return
}
func runSecond(b, c int) {
var d int
...
}
Stack
Slide 5
Slide 5 text
What is Stack?
5
…
1
a
Local
variables
Stack
func runFirst() {
a := 1
runSecond(a, 2)
return
}
func runSecond(b, c int) {
var d int
...
}
Slide 6
Slide 6 text
What is Stack?
6
…
1
a
Local
variables
Stack
1
b
Function
parameters
2
c
func runFirst() {
a := 1
runSecond(a, 2)
return
}
func runSecond(b, c int) {
var d int
...
}
Slide 7
Slide 7 text
What is Stack?
7
…
1
a
Local
variables
Stack
1
b
Function
parameters
2
c
0x12345
Return
address
func runFirst() {
a := 1
runSecond(a, 2)
return
}
func runSecond(b, c int) {
var d int
...
}
Slide 8
Slide 8 text
What is Stack?
8
…
1
a
Local
variables
Stack
1
b
Function
parameters
2
c
0x12345
Return
address
func runFirst() {
a := 1
runSecond(a, 2)
return
}
func runSecond(b, c int) {
var d int
...
}
0
d
Local
variables
Slide 9
Slide 9 text
What is Stack?
9
…
1
a
Local
variables
Stack
1
b
Function
parameters
2
c
0x12345
Return
address
0
d
Local
variables
func runFirst() {
a := 1
runSecond(a, 2)
return
}
func runSecond(b, c int) {
var d int
...
}
Slide 10
Slide 10 text
What is Stack?
10
…
1
a
Local
variables
Stack
1
b
Function
parameters
2
c
0x12345
Return
address
func runFirst() {
a := 1
runSecond(a, 2)
return
}
func runSecond(b, c int) {
var d int
...
}
Slide 11
Slide 11 text
What is Stack?
● Grows down - last thing we pushed onto the stack will be at the
lowest address
● RSP - “variable” that holds the last address of the stack
11
Slide 12
Slide 12 text
What is Stack?
12
…
1
0x1238
Local
variables
Stack
1
0x1230
Function
parameters
2
0x1228
0x12345
func runFirst() {
a := 1
runSecond(a, 2)
return
}
func runSecond(b, c int) {
var d int
...
}
Return
address
0x1220
Slide 13
Slide 13 text
What is Stack?
13
…
1
0x1238
Local
variables
Stack
1
0x1230
Function
parameters
2
0x1228
0x12345
func runFirst() {
a := 1
runSecond(a, 2)
return
}
func runSecond(b, c int) {
var d int
...
}
Return
address
0x1220
rsp
Slide 14
Slide 14 text
What is Stack?
14
…
1
0x1238
Local
variables
Stack
1
0x1230
Function
parameters
2
0x1228
rsp
Bigger rsp →
smaller stack
Slide 15
Slide 15 text
What’s So Special About Go?
15
● Threads ≠ Goroutines
● Threads - 1-10MB
● Goroutines - 4K
Slide 16
Slide 16 text
What If I Need morestack?
16
Slide 17
Slide 17 text
When Is morestack Called?
17
● The compiler adds a prologue and epilogue to every function
● Prologue checks if more stack is needed
● Epilogue calls `morestack`
Slide 18
Slide 18 text
When is morestack Called?
18
Slide 19
Slide 19 text
needsMorestack()
19
● Not a real function
● A condition that compares:
○ Available stack
○ Stack in use
● How does that look like?
g struct
21
Stack
0x1000
0x1008
0x1090
0x1088
0x1080
0x1010
...
x
x
x
rsp: 0x1078
g.stack.lo
g.stack.hi
Slide 22
Slide 22 text
g struct
22
Stack
0x1000
0x1008
0x1090
0x1088
0x1080
0x1010
...
x
x
x
x
x
x
x
x
x
x
x
x
x
x
x
rsp: 0x1010
x
g.stack.lo
g.stack.hi
Slide 23
Slide 23 text
g struct
23
Stack
0x1000
0x1008
0x1090
0x1088
0x1080
0x1010
...
x
x
x
x
x
x
x
x
x
x
x
x
x
x
x
rsp: 0x1000
x
g.stack.lo
g.stack.hi
x
x
Slide 24
Slide 24 text
g struct
24
Stack
0x1000
0x1008
0x1090
0x1088
0x1080
0x1010
...
x
x
x
x
x
x
x
x
x
x
x
x
x
x
x
rsp: 0x1000
x
g.stack.lo
g.stack.hi
x
x
Slide 25
Slide 25 text
25
`morestack` needs 0x10
stack!
Slide 26
Slide 26 text
`morestack` needs 0x10 stack
26
Stack
0x1000
0x1008
0x1090
0x1088
0x1080
0x1010
...
x
x
x
x
x
x
x
x
x
x
x
x
x
x
x
rsp: 0x1000
x
g.stack.lo
g.stack.hi
x
x
0xff8
0xff0
Slide 27
Slide 27 text
`morestack` needs 0x10 stack
27
Stack
0x1000
0x1008
0x1090
0x1088
0x1080
0x1010
...
x
x
x
x
x
x
x
x
x
x
x
x
x
x
x
rsp: 0x1000
x
g.stack.lo
g.stack.hi
x
x
0xff8
0xff0
Slide 28
Slide 28 text
`morestack` needs 0x10 stack
28
Stack
0x1000
0x1008
0x1090
0x1088
0x1080
0x1010
...
x
x
x
x
x
x
x
x
x
x
x
x
x
x
x
rsp: 0x1000
x
g.stack.lo
g.stack.hi
x
x
0xff8
0xff0
Slide 29
Slide 29 text
`morestack` needs 0x10 stack
29
Stack
0x1000
0x1008
0x1090
0x1088
0x1080
0x1010
...
x
x
x
x
x
x
x
x
x
x
x
x
x
x
x
rsp: 0x1000
x
g.stack.lo
g.stack.hi
x
x
0xff8
0xff0
Slide 30
Slide 30 text
`morestack` needs 0x10 stack
30
Stack
0x1000
0x1008
0x1090
0x1088
0x1080
0x1010
...
x
x
x
x
x
x
x
x
x
x
x
x
x
x
x
rsp: 0x1000
x
g.stack.lo
g.stack.hi
x
x
0xff8
0xff0
Slide 31
Slide 31 text
`morestack` needs 0x10 stack
31
Stack
0x1000
0x1008
0x1090
0x1088
0x1080
0x1010
...
x
x
x
x
x
x
x
x
x
x
x
x
x
x
x
rsp: 0x1000
x
g.stack.lo
g.stack.hi
x
x
0xff8
0xff0
Slide 32
Slide 32 text
`morestack` needs 0x10 stack
32
Stack
0x1000
0x1008
0x1090
0x1088
0x1080
0x1010
...
x
x
x
x
x
x
x
x
x
x
x
x
x
x
x
rsp: 0x1000
x
g.stack.lo
g.stack.hi
x
x
0xff8
0xff0
Slide 33
Slide 33 text
`morestack` needs 0x10 stack
33
Stack
0x1000
0x1008
0x1090
0x1088
0x1080
0x1010
...
x
x
x
x
x
x
x
x
x
x
x
x
x
x
x
rsp: 0x1000
x
g.stack.lo
g.stack.hi
x
x
0xff8
0xff0
Slide 34
Slide 34 text
`morestack` needs 0x10 stack
34
Stack
0x1000
0x1008
0x1090
0x1088
0x1080
0x1010
...
x
x
x
x
x
x
x
x
x
x
x
x
x
x
x
rsp: 0x1000
x
g.stack.lo
g.stack.hi
x
x
0xff8
0xff0
Slide 35
Slide 35 text
`morestack` needs 0x10 stack
35
Stack
0x1000
0x1008
0x1090
0x1088
0x1080
0x1010
...
x
x
x
x
x
x
x
x
x
x
x
x
x
x
x
rsp: 0x1000
x
g.stack.lo
g.stack.hi
x
x
0xff8
0xff0
Slide 36
Slide 36 text
`morestack` needs 0x10 stack
36
Stack
0x1000
0x1008
0x1090
0x1088
0x1080
0x1010
...
x
x
x
x
x
x
x
x
x
x
x
x
x
x
x
rsp: 0x1000
x
g.stack.lo
g.stack.hi
x
x
0xff8
0xff0
Slide 37
Slide 37 text
`morestack` needs 0x10 stack
37
Stack
0x1000
0x1008
0x1090
0x1088
0x1080
0x1010
...
x
x
x
x
x
x
x
x
x
x
x
x
x
x
x
rsp: 0xff0
x
g.stack.lo
g.stack.hi
x
x
x
x
0xff8
0xff0
`morestack` needs 0x10 stack
39
Stack
g.stack.lo
g.stack.hi
0x1000
0x1008
0x1088
0x1080
0x1010
...
rsp: 0x1010
x
x
x
x
x
x
x
x
x
x
x
x
x
x
x
x
g.stack.lo+0x10
Slide 40
Slide 40 text
`morestack` needs 0x10 stack
40
Stack
g.stack.lo
g.stack.hi
0x1000
0x1008
0x1088
0x1080
0x1010
...
rsp: 0x1010
x
x
x
x
x
x
x
x
x
x
x
x
x
x
x
x
g.stack.lo+0x10
Slide 41
Slide 41 text
`morestack` needs 0x10 stack
41
Stack
g.stack.lo
g.stack.hi
0x1000
0x1008
0x1088
0x1080
0x1010
...
rsp: 0x1010
x
x
x
x
x
x
x
x
x
x
x
x
x
x
x
x
g.stack.lo+0x10
Slide 42
Slide 42 text
`morestack` needs 0x10 stack
42
Stack
g.stack.lo
g.stack.hi
0x1000
0x1008
0x1088
0x1080
0x1010
...
rsp: 0x1000
x
x
x
x
x
x
x
x
x
x
x
x
x
x
x
x
g.stack.lo+0x10 x
x
Slide 43
Slide 43 text
43
g.stackguard0 =
g.stack.lo + 0x10
Slide 44
Slide 44 text
Stackguard
44
● Used to check if we have enough
stack
● Always between stack.lo and stack.hi
● Will leave enough memory for calls to
functions like `morestack`
Slide 45
Slide 45 text
45
Slide 46
Slide 46 text
Stack Usage
46
Slide 47
Slide 47 text
Stack Usage
47
Slide 48
Slide 48 text
Stack Usage
48
Stack
g.stack.lo
g.stack.hi
0x1000
0x1008
0x1088
0x1080
0x1010
...
rsp: 0x1020
x
x
x
x
x
x
x
x
x
x
x
x
x
x
g.stackguard0
Slide 49
Slide 49 text
Stack Usage
49
Stack
g.stack.lo
g.stack.hi
0x1000
0x1008
0x1088
0x1080
0x1010
...
rsp: 0x1020
x
x
x
x
x
x
x
x
x
x
x
x
x
x
g.stackguard0
Slide 50
Slide 50 text
Stack Usage
50
Stack
g.stack.lo
g.stack.hi
0x1000
0x1008
0x1088
0x1080
0x1010
...
rsp: 0x1020
x
x
x
x
x
x
x
x
x
x
x
x
x
x
g.stackguard0
Slide 51
Slide 51 text
Stack Usage
51
Stack
g.stack.lo
g.stack.hi
0x1000
0x1008
0x1088
0x1080
0x1010
...
rsp: 0xf20
x
x
x
x
x
x
x
x
x
x
x
x
x
x
g.stackguard0
x
x
x
x
x
x
x
x
x
x
x
x
x
x
x
x
Slide 52
Slide 52 text
What is Stack?
52
…
func runFirst() {
a := 1
runSecond(a, 2)
return
}
func runSecond(b, c int) {
var d int
...
}
Stack
Slide 53
Slide 53 text
What is Stack?
53
…
1
a
Local
variables
Stack
func runFirst() {
a := 1
runSecond(a, 2)
return
}
func runSecond(b, c int) {
var d int
...
}
Slide 54
Slide 54 text
What is Stack?
54
…
1
a
Local
variables
Stack
1
b
Function
parameters
2
c
func runFirst() {
a := 1
runSecond(a, 2)
return
}
func runSecond(b, c int) {
var d int
...
}
Slide 55
Slide 55 text
What is Stack?
55
…
1
a
Local
variables
Stack
1
b
Function
parameters
2
c
func runFirst() {
a := 1
runSecond(a, 2)
return
}
func runSecond(b, c int) {
var d int
...
}
Slide 56
Slide 56 text
What is Stack?
56
…
1
a
Local
variables
Stack
1
b
Function
parameters
2
c
func runFirst() {
a := 1
if shouldRunSecond {
runSecond(a, 2)
}
return
}
Slide 57
Slide 57 text
Stack Usage
57
Stack
g.stack.lo
g.stack.hi
0x1000
0x1008
0x1088
0x1080
0x1010
...
rsp: 0x1020
x
x
x
x
x
x
x
x
x
x
x
x
x
x
g.stackguard0
Slide 58
Slide 58 text
Stack Usage
58
Stack
g.stack.lo
g.stack.hi
0x1000
0x1008
0x1088
0x1080
0x1010
...
rsp: 0x1020
x
x
x
x
x
x
x
x
x
x
x
x
x
x
g.stackguard0
Slide 59
Slide 59 text
Stack Usage
59
Stack
g.stack.lo
g.stack.hi
0x1000
0x1008
0x1088
0x1080
0x1010
...
rsp: 0x1020
x
x
x
x
x
x
x
x
x
x
x
x
x
x
g.stackguard0
Slide 60
Slide 60 text
Stack Usage
60
Slide 61
Slide 61 text
61
What Goes Up Must
Come Back Down
Slide 62
Slide 62 text
Stack Shrink
● `shrinkstack`
● Called by GC
● Shrink stack if less than a quarter is being used
62