|
3 | 3 | 在 Go 1.14 中,增加了一种新的 defer 实现:open coded defer。当函数内 defer 不超过 8 个时,则会使用这种实现。 |
4 | 4 |
|
5 | 5 | ```go |
6 | | -package main |
| 6 | + 1 package main |
| 7 | + 2 |
| 8 | + 3 import "fmt" |
| 9 | + 4 |
| 10 | + 5 var i = 100 |
| 11 | + 6 |
| 12 | + 7 func main() { |
| 13 | + 8 if i == 0 { |
| 14 | + 9 defer fmt.Println("1") |
| 15 | + 10 } |
| 16 | + 11 |
| 17 | + 12 if i == 1 { |
| 18 | + 13 defer fmt.Println("2") |
| 19 | + 14 } |
| 20 | + 15 |
| 21 | + 16 if i == 2 { |
| 22 | + 17 defer fmt.Println("3") |
| 23 | + 18 } |
| 24 | + 19 |
| 25 | + 20 if i == 3 { |
| 26 | + 21 defer fmt.Println("4") |
| 27 | + 22 } |
| 28 | + 23 |
| 29 | + 24 if i == 4 { |
| 30 | + 25 defer fmt.Println("5") |
| 31 | + 26 } |
| 32 | + 27 |
| 33 | + 28 if i == 5 { |
| 34 | + 29 defer fmt.Println("6") |
| 35 | + 30 } |
| 36 | + 31 } |
| 37 | +``` |
7 | 38 |
|
8 | | -import "fmt" |
| 39 | +可以分析上面的代码生成的汇编来理解这个新版的 open coded defer 到底是怎么实现的: |
9 | 40 |
|
10 | | -var i = 100 |
| 41 | +``` |
| 42 | +"".main STEXT size=1125 args=0x0 locals=0x160 |
| 43 | +if i == 0: |
| 44 | + 0x0055 00085 (open-coded-defer.go:8) CMPQ "".i(SB), $0 |
| 45 | + 0x005d 00093 (open-coded-defer.go:8) JNE 1075 // 1075 是条废指令,其实本质是跳过这条 if 的 DEFER PREPARE BLOCK,去地址 188 |
11 | 46 |
|
12 | | -func main() { |
13 | | - if i == 0 { |
14 | | - defer fmt.Println("1") |
15 | | - } |
| 47 | +DEFER PREPARE BLOCK 1,主要工作是将 fmt.Println 的参数和函数地址搬运到栈上该 defer 对应的区域: |
| 48 | + 0x0063 00099 (open-coded-defer.go:9) XORPS X0, X0 |
| 49 | + 0x0066 00102 (open-coded-defer.go:9) MOVUPS X0, ""..autotmp_3+72(SP) |
| 50 | + 0x006b 00107 (open-coded-defer.go:9) LEAQ type.string(SB), AX |
| 51 | + 0x0072 00114 (open-coded-defer.go:9) MOVQ AX, ""..autotmp_3+72(SP) |
| 52 | + 0x0077 00119 (open-coded-defer.go:9) LEAQ ""..stmp_0(SB), CX |
| 53 | + 0x007e 00126 (open-coded-defer.go:9) MOVQ CX, ""..autotmp_3+80(SP) |
| 54 | + 0x0083 00131 (open-coded-defer.go:9) LEAQ fmt.Println·f(SB), CX |
| 55 | + 0x008a 00138 (open-coded-defer.go:9) MOVQ CX, ""..autotmp_25+192(SP) |
| 56 | + 0x0092 00146 (open-coded-defer.go:9) LEAQ ""..autotmp_3+72(SP), DX |
| 57 | + 0x0097 00151 (open-coded-defer.go:9) MOVQ DX, ""..autotmp_26+320(SP) |
| 58 | + 0x009f 00159 (open-coded-defer.go:9) MOVQ $1, ""..autotmp_26+328(SP) |
| 59 | + 0x00ab 00171 (open-coded-defer.go:9) MOVQ $1, ""..autotmp_26+336(SP) |
| 60 | + 0x00b7 00183 (open-coded-defer.go:9) MOVB $1, ""..autotmp_24+55(SP) |
| 61 | + |
| 62 | + // 根据 zero flag 设置值,如果 zero flag = 1,那么 DI = 1,如果 zero flag = 0,那么 DI = 0 |
| 63 | + // 详情参见 intel 手册的 sete/setz 指令 |
| 64 | + // 也就是说,只要走了上面的 DEFER PREPARE BLOCK,那么这里就 DI = 1,否则 DI = 0 |
| 65 | + 0x00bc 00188 (open-coded-defer.go:8) SETEQ DL |
16 | 66 |
|
17 | | - if i == 1 { |
18 | | - defer fmt.Println("2") |
19 | | - } |
| 67 | +if i == 1: |
| 68 | + 0x00bf 00191 (open-coded-defer.go:12) CMPQ "".i(SB), $1 |
| 69 | + 0x00c7 00199 (open-coded-defer.go:12) JNE 278 |
20 | 70 |
|
21 | | - if i == 2 { |
22 | | - defer fmt.Println("3") |
23 | | - } |
| 71 | +DEFER PREPARE BLOCK 2, 和 BLOCK 1 工作差不多,是把第二个 defer 的参数和函数地址保存在栈上: |
| 72 | + 0x00c9 00201 (open-coded-defer.go:13) XORPS X0, X0 |
| 73 | + 0x00cc 00204 (open-coded-defer.go:13) MOVUPS X0, ""..autotmp_7+56(SP) |
| 74 | + 0x00d1 00209 (open-coded-defer.go:13) MOVQ AX, ""..autotmp_7+56(SP) |
| 75 | + 0x00d6 00214 (open-coded-defer.go:13) LEAQ ""..stmp_1(SB), BX |
| 76 | + 0x00dd 00221 (open-coded-defer.go:13) MOVQ BX, ""..autotmp_7+64(SP) |
| 77 | + 0x00e2 00226 (open-coded-defer.go:13) MOVQ CX, ""..autotmp_27+184(SP) |
| 78 | + 0x00ea 00234 (open-coded-defer.go:13) LEAQ ""..autotmp_7+56(SP), BX |
| 79 | + 0x00ef 00239 (open-coded-defer.go:13) MOVQ BX, ""..autotmp_28+296(SP) |
| 80 | + 0x00f7 00247 (open-coded-defer.go:13) MOVQ $1, ""..autotmp_28+304(SP) |
| 81 | + 0x0103 00259 (open-coded-defer.go:13) MOVQ $1, ""..autotmp_28+312(SP) |
24 | 82 |
|
25 | | - if i == 3 { |
26 | | - defer fmt.Println("4") |
27 | | - } |
| 83 | + 0x010f 00271 (open-coded-defer.go:13) ORL $2, DX // 设置 DX 的第二个标记位为 1 |
| 84 | + 0x0112 00274 (open-coded-defer.go:13) MOVB DL, ""..autotmp_24+55(SP) // TODO |
28 | 85 |
|
29 | | - if i == 4 { |
30 | | - defer fmt.Println("5") |
31 | | - } |
| 86 | +if i == 2: |
| 87 | + 0x0116 00278 (open-coded-defer.go:16) CMPQ "".i(SB), $2 |
| 88 | + 0x011e 00286 (open-coded-defer.go:16) JNE 377 |
32 | 89 |
|
33 | | - if i == 5 { |
34 | | - defer fmt.Println("6") |
35 | | - } |
36 | | -} |
| 90 | +DEFER PREPARE BLOCK 3,和上面类似,就不解释了: |
| 91 | + 0x0120 00288 (open-coded-defer.go:17) XORPS X0, X0 |
| 92 | + 0x0123 00291 (open-coded-defer.go:17) MOVUPS X0, ""..autotmp_11+136(SP) |
| 93 | + 0x012b 00299 (open-coded-defer.go:17) MOVQ AX, ""..autotmp_11+136(SP) |
| 94 | + 0x0133 00307 (open-coded-defer.go:17) LEAQ ""..stmp_2(SB), BX |
| 95 | + 0x013a 00314 (open-coded-defer.go:17) MOVQ BX, ""..autotmp_11+144(SP) |
| 96 | + 0x0142 00322 (open-coded-defer.go:17) MOVQ CX, ""..autotmp_29+176(SP) |
| 97 | + 0x014a 00330 (open-coded-defer.go:17) LEAQ ""..autotmp_11+136(SP), BX |
| 98 | + 0x0152 00338 (open-coded-defer.go:17) MOVQ BX, ""..autotmp_30+272(SP) |
| 99 | + 0x015a 00346 (open-coded-defer.go:17) MOVQ $1, ""..autotmp_30+280(SP) |
| 100 | + 0x0166 00358 (open-coded-defer.go:17) MOVQ $1, ""..autotmp_30+288(SP) |
37 | 101 |
|
38 | | -``` |
| 102 | + 0x0172 00370 (open-coded-defer.go:17) ORL $4, DX // 设置 DX 的第三个标记位为 1 |
| 103 | + 0x0175 00373 (open-coded-defer.go:17) MOVB DL, ""..autotmp_24+55(SP) |
39 | 104 |
|
40 | | -可以分析上面的代码生成的汇编来理解这个新版的 open coded defer 到底是怎么实现的: |
| 105 | +if i == 3 |
| 106 | + 0x0179 00377 (open-coded-defer.go:20) CMPQ "".i(SB), $3 |
| 107 | + 0x0181 00385 (open-coded-defer.go:20) JNE 467 |
41 | 108 |
|
42 | | -``` |
| 109 | +DEFER PREPARE BLOCK 4: |
| 110 | + 0x0183 00387 (open-coded-defer.go:21) XORPS X0, X0 |
| 111 | + 0x0186 00390 (open-coded-defer.go:21) MOVUPS X0, ""..autotmp_15+120(SP) |
| 112 | + 0x018b 00395 (open-coded-defer.go:21) MOVQ AX, ""..autotmp_15+120(SP) |
| 113 | + 0x0190 00400 (open-coded-defer.go:21) LEAQ ""..stmp_3(SB), BX |
| 114 | + 0x0197 00407 (open-coded-defer.go:21) MOVQ BX, ""..autotmp_15+128(SP) |
| 115 | + 0x019f 00415 (open-coded-defer.go:21) MOVQ CX, ""..autotmp_31+168(SP) |
| 116 | + 0x01a7 00423 (open-coded-defer.go:21) LEAQ ""..autotmp_15+120(SP), BX |
| 117 | + 0x01ac 00428 (open-coded-defer.go:21) MOVQ BX, ""..autotmp_32+248(SP) |
| 118 | + 0x01b4 00436 (open-coded-defer.go:21) MOVQ $1, ""..autotmp_32+256(SP) |
| 119 | + 0x01c0 00448 (open-coded-defer.go:21) MOVQ $1, ""..autotmp_32+264(SP) |
| 120 | +
|
| 121 | + 0x01cc 00460 (open-coded-defer.go:21) ORL $8, DX // 设置 DX 的第四个标记位为 1 |
| 122 | + 0x01cf 00463 (open-coded-defer.go:21) MOVB DL, ""..autotmp_24+55(SP) |
| 123 | +
|
| 124 | +if i == 4: |
| 125 | + 0x01d3 00467 (open-coded-defer.go:24) CMPQ "".i(SB), $4 |
| 126 | + 0x01db 00475 (open-coded-defer.go:24) JNE 554 |
| 127 | +
|
| 128 | +DEFER PREPARE BLOCK 5: |
| 129 | + 0x01dd 00477 (open-coded-defer.go:25) XORPS X0, X0 |
| 130 | + 0x01e0 00480 (open-coded-defer.go:25) MOVUPS X0, ""..autotmp_19+104(SP) |
| 131 | + 0x01e5 00485 (open-coded-defer.go:25) MOVQ AX, ""..autotmp_19+104(SP) |
| 132 | + 0x01ea 00490 (open-coded-defer.go:25) LEAQ ""..stmp_4(SB), BX |
| 133 | + 0x01f1 00497 (open-coded-defer.go:25) MOVQ BX, ""..autotmp_19+112(SP) |
| 134 | + 0x01f6 00502 (open-coded-defer.go:25) MOVQ CX, ""..autotmp_33+160(SP) |
| 135 | + 0x01fe 00510 (open-coded-defer.go:25) LEAQ ""..autotmp_19+104(SP), BX |
| 136 | + 0x0203 00515 (open-coded-defer.go:25) MOVQ BX, ""..autotmp_34+224(SP) |
| 137 | + 0x020b 00523 (open-coded-defer.go:25) MOVQ $1, ""..autotmp_34+232(SP) |
| 138 | + 0x0217 00535 (open-coded-defer.go:25) MOVQ $1, ""..autotmp_34+240(SP) |
| 139 | +
|
| 140 | + 0x0223 00547 (open-coded-defer.go:25) ORL $16, DX // 设置 DX 的第五个标记位为 1 |
| 141 | + 0x0226 00550 (open-coded-defer.go:25) MOVB DL, ""..autotmp_24+55(SP) |
| 142 | +
|
| 143 | +if i == 5: |
| 144 | + 0x022a 00554 (open-coded-defer.go:28) CMPQ "".i(SB), $5 |
| 145 | + 0x0232 00562 (open-coded-defer.go:28) JNE 641 |
| 146 | +
|
| 147 | +DEFER PREPARE BLOCK 6: |
| 148 | + 0x0234 00564 (open-coded-defer.go:29) XORPS X0, X0 |
| 149 | + 0x0237 00567 (open-coded-defer.go:29) MOVUPS X0, ""..autotmp_23+88(SP) |
| 150 | + 0x023c 00572 (open-coded-defer.go:29) MOVQ AX, ""..autotmp_23+88(SP) |
| 151 | + 0x0241 00577 (open-coded-defer.go:29) LEAQ ""..stmp_5(SB), AX |
| 152 | + 0x0248 00584 (open-coded-defer.go:29) MOVQ AX, ""..autotmp_23+96(SP) |
| 153 | + 0x024d 00589 (open-coded-defer.go:29) MOVQ CX, ""..autotmp_35+152(SP) |
| 154 | + 0x0255 00597 (open-coded-defer.go:29) LEAQ ""..autotmp_23+88(SP), AX |
| 155 | + 0x025a 00602 (open-coded-defer.go:29) MOVQ AX, ""..autotmp_36+200(SP) |
| 156 | + 0x0262 00610 (open-coded-defer.go:29) MOVQ $1, ""..autotmp_36+208(SP) |
| 157 | + 0x026e 00622 (open-coded-defer.go:29) MOVQ $1, ""..autotmp_36+216(SP) |
| 158 | +
|
| 159 | + 0x027a 00634 (open-coded-defer.go:29) ORL $32, DX // 设置 DX 的第六个标志位为 1 |
| 160 | + 0x027d 00637 (open-coded-defer.go:29) MOVB DL, ""..autotmp_24+55(SP) |
| 161 | +
|
| 162 | +FUNCTION END, FLAG CHECKS, 这里要检查上面设置的所有的 open coded defer bits 了,可以看到与 flag 的设置顺序是相反的: |
| 163 | + 0x0281 00641 (open-coded-defer.go:31) TESTB $32, DL |
| 164 | + 0x0284 00644 (open-coded-defer.go:31) JNE 1011 |
| 165 | + 0x028a 00650 (open-coded-defer.go:31) TESTB $16, DL |
| 166 | + 0x028d 00653 (open-coded-defer.go:31) JNE 947 |
| 167 | + 0x0293 00659 (open-coded-defer.go:31) TESTB $8, DL |
| 168 | + 0x0296 00662 (open-coded-defer.go:31) JNE 883 |
| 169 | + 0x029c 00668 (open-coded-defer.go:31) TESTB $4, DL |
| 170 | + 0x029f 00671 (open-coded-defer.go:31) JNE 819 |
| 171 | + 0x02a5 00677 (open-coded-defer.go:31) TESTB $2, DL |
| 172 | + 0x02a8 00680 (open-coded-defer.go:31) JNE 755 |
| 173 | + 0x02aa 00682 (open-coded-defer.go:31) TESTB $1, DL |
| 174 | + 0x02ad 00685 (open-coded-defer.go:31) JNE 703 |
| 175 | + 0x02af 00687 (open-coded-defer.go:31) MOVQ 344(SP), BP |
| 176 | + 0x02b7 00695 (open-coded-defer.go:31) ADDQ $352, SP |
| 177 | + 0x02be 00702 (open-coded-defer.go:31) RET |
| 178 | +
|
| 179 | +DEFER 逻辑执行部分: |
| 180 | + 0x02bf 00703 (open-coded-defer.go:31) ANDL $-2, DX |
| 181 | + 0x02c2 00706 (open-coded-defer.go:31) MOVB DL, ""..autotmp_24+55(SP) |
| 182 | + 0x02c6 00710 (open-coded-defer.go:31) MOVQ ""..autotmp_26+320(SP), AX |
| 183 | + 0x02ce 00718 (open-coded-defer.go:31) MOVQ ""..autotmp_26+328(SP), CX |
| 184 | + 0x02d6 00726 (open-coded-defer.go:31) MOVQ ""..autotmp_26+336(SP), DX |
| 185 | + 0x02de 00734 (open-coded-defer.go:31) MOVQ AX, (SP) |
| 186 | + 0x02e2 00738 (open-coded-defer.go:31) MOVQ CX, 8(SP) |
| 187 | + 0x02e7 00743 (open-coded-defer.go:31) MOVQ DX, 16(SP) |
| 188 | + 0x02ec 00748 (open-coded-defer.go:31) CALL fmt.Println(SB) |
| 189 | + 0x02f1 00753 (open-coded-defer.go:31) JMP 687 |
| 190 | +
|
| 191 | + 0x02f3 00755 (open-coded-defer.go:31) ANDL $-3, DX |
| 192 | + 0x02f6 00758 (open-coded-defer.go:31) MOVB DL, ""..autotmp_37+54(SP) |
| 193 | + 0x02fa 00762 (open-coded-defer.go:31) MOVB DL, ""..autotmp_24+55(SP) |
| 194 | + 0x02fe 00766 (open-coded-defer.go:31) MOVQ ""..autotmp_28+312(SP), AX |
| 195 | + 0x0306 00774 (open-coded-defer.go:31) MOVQ ""..autotmp_28+304(SP), CX |
| 196 | + 0x030e 00782 (open-coded-defer.go:31) MOVQ ""..autotmp_28+296(SP), BX |
| 197 | + 0x0316 00790 (open-coded-defer.go:31) MOVQ BX, (SP) |
| 198 | + 0x031a 00794 (open-coded-defer.go:31) MOVQ CX, 8(SP) |
| 199 | + 0x031f 00799 (open-coded-defer.go:31) MOVQ AX, 16(SP) |
| 200 | + 0x0324 00804 (open-coded-defer.go:31) CALL fmt.Println(SB) |
| 201 | + 0x0329 00809 (open-coded-defer.go:31) MOVBLZX ""..autotmp_37+54(SP), DX |
| 202 | + 0x032e 00814 (open-coded-defer.go:31) JMP 682 |
| 203 | +
|
| 204 | + 0x0333 00819 (open-coded-defer.go:31) ANDL $-5, DX |
| 205 | + 0x0336 00822 (open-coded-defer.go:31) MOVB DL, ""..autotmp_37+54(SP) |
| 206 | + 0x033a 00826 (open-coded-defer.go:31) MOVB DL, ""..autotmp_24+55(SP) |
| 207 | + 0x033e 00830 (open-coded-defer.go:31) MOVQ ""..autotmp_30+288(SP), AX |
| 208 | + 0x0346 00838 (open-coded-defer.go:31) MOVQ ""..autotmp_30+280(SP), CX |
| 209 | + 0x034e 00846 (open-coded-defer.go:31) MOVQ ""..autotmp_30+272(SP), BX |
| 210 | + 0x0356 00854 (open-coded-defer.go:31) MOVQ BX, (SP) |
| 211 | + 0x035a 00858 (open-coded-defer.go:31) MOVQ CX, 8(SP) |
| 212 | + 0x035f 00863 (open-coded-defer.go:31) MOVQ AX, 16(SP) |
| 213 | + 0x0364 00868 (open-coded-defer.go:31) CALL fmt.Println(SB) |
| 214 | + 0x0369 00873 (open-coded-defer.go:31) MOVBLZX ""..autotmp_37+54(SP), DX |
| 215 | + 0x036e 00878 (open-coded-defer.go:31) JMP 677 |
| 216 | +
|
| 217 | + 0x0373 00883 (open-coded-defer.go:31) ANDL $-9, DX |
| 218 | + 0x0376 00886 (open-coded-defer.go:31) MOVB DL, ""..autotmp_37+54(SP) |
| 219 | + 0x037a 00890 (open-coded-defer.go:31) MOVB DL, ""..autotmp_24+55(SP) |
| 220 | + 0x037e 00894 (open-coded-defer.go:31) MOVQ ""..autotmp_32+264(SP), AX |
| 221 | + 0x0386 00902 (open-coded-defer.go:31) MOVQ ""..autotmp_32+256(SP), CX |
| 222 | + 0x038e 00910 (open-coded-defer.go:31) MOVQ ""..autotmp_32+248(SP), BX |
| 223 | + 0x0396 00918 (open-coded-defer.go:31) MOVQ BX, (SP) |
| 224 | + 0x039a 00922 (open-coded-defer.go:31) MOVQ CX, 8(SP) |
| 225 | + 0x039f 00927 (open-coded-defer.go:31) MOVQ AX, 16(SP) |
| 226 | + 0x03a4 00932 (open-coded-defer.go:31) CALL fmt.Println(SB) |
| 227 | + 0x03a9 00937 (open-coded-defer.go:31) MOVBLZX ""..autotmp_37+54(SP), DX |
| 228 | + 0x03ae 00942 (open-coded-defer.go:31) JMP 668 |
| 229 | +
|
| 230 | + 0x03b3 00947 (open-coded-defer.go:31) ANDL $-17, DX |
| 231 | + 0x03b6 00950 (open-coded-defer.go:31) MOVB DL, ""..autotmp_37+54(SP) |
| 232 | + 0x03ba 00954 (open-coded-defer.go:31) MOVB DL, ""..autotmp_24+55(SP) |
| 233 | + 0x03be 00958 (open-coded-defer.go:31) MOVQ ""..autotmp_34+224(SP), AX |
| 234 | + 0x03c6 00966 (open-coded-defer.go:31) MOVQ ""..autotmp_34+240(SP), CX |
| 235 | + 0x03ce 00974 (open-coded-defer.go:31) MOVQ ""..autotmp_34+232(SP), BX |
| 236 | + 0x03d6 00982 (open-coded-defer.go:31) MOVQ AX, (SP) |
| 237 | + 0x03da 00986 (open-coded-defer.go:31) MOVQ BX, 8(SP) |
| 238 | + 0x03df 00991 (open-coded-defer.go:31) MOVQ CX, 16(SP) |
| 239 | + 0x03e4 00996 (open-coded-defer.go:31) CALL fmt.Println(SB) |
| 240 | + 0x03e9 01001 (open-coded-defer.go:31) MOVBLZX ""..autotmp_37+54(SP), DX |
| 241 | + 0x03ee 01006 (open-coded-defer.go:31) JMP 659 |
| 242 | +
|
| 243 | + 0x03f3 01011 (open-coded-defer.go:31) ANDL $-33, DX |
| 244 | + 0x03f6 01014 (open-coded-defer.go:31) MOVB DL, ""..autotmp_37+54(SP) |
| 245 | + 0x03fa 01018 (open-coded-defer.go:31) MOVB DL, ""..autotmp_24+55(SP) |
| 246 | + 0x03fe 01022 (open-coded-defer.go:31) MOVQ ""..autotmp_36+216(SP), AX |
| 247 | + 0x0406 01030 (open-coded-defer.go:31) MOVQ ""..autotmp_36+200(SP), CX |
| 248 | + 0x040e 01038 (open-coded-defer.go:31) MOVQ ""..autotmp_36+208(SP), BX |
| 249 | + 0x0416 01046 (open-coded-defer.go:31) MOVQ CX, (SP) |
| 250 | + 0x041a 01050 (open-coded-defer.go:31) MOVQ BX, 8(SP) |
| 251 | + 0x041f 01055 (open-coded-defer.go:31) MOVQ AX, 16(SP) |
| 252 | + 0x0424 01060 (open-coded-defer.go:31) CALL fmt.Println(SB) |
| 253 | + 0x0429 01065 (open-coded-defer.go:31) MOVBLZX ""..autotmp_37+54(SP), DX |
| 254 | + 0x042e 01070 (open-coded-defer.go:31) JMP 650 |
| 255 | +
|
| 256 | +如果第一个 if 不满足,会跳到这里: |
| 257 | + 0x0433 01075 (open-coded-defer.go:31) LEAQ type.string(SB), AX |
| 258 | + 0x043a 01082 (open-coded-defer.go:31) LEAQ fmt.Println·f(SB), CX |
| 259 | + 0x0441 01089 (open-coded-defer.go:8) JMP 188 |
| 260 | +
|
| 261 | + 0x0446 01094 (open-coded-defer.go:8) CALL runtime.deferreturn(SB) |
| 262 | + 0x044b 01099 (open-coded-defer.go:8) MOVQ 344(SP), BP |
| 263 | + 0x0453 01107 (open-coded-defer.go:8) ADDQ $352, SP |
| 264 | + 0x045a 01114 (open-coded-defer.go:8) RET |
| 265 | + 0x045b 01115 (open-coded-defer.go:8) NOP |
| 266 | + 0x045b 01115 (open-coded-defer.go:7) CALL runtime.morestack_noctxt(SB) |
| 267 | + 0x0460 01120 (open-coded-defer.go:7) JMP 0 |
43 | 268 | ``` |
0 commit comments