File tree Expand file tree Collapse file tree 2 files changed +18
-15
lines changed Expand file tree Collapse file tree 2 files changed +18
-15
lines changed Original file line number Diff line number Diff line change @@ -187,21 +187,15 @@ func runfinq() {
187
187
f := & fb .fin [i - 1 ]
188
188
189
189
var regs abi.RegArgs
190
- var framesz uintptr
191
- if argRegs > 0 {
192
- // The args can always be passed in registers if they're
193
- // available, because platforms we support always have no
194
- // argument registers available, or more than 2.
195
- //
196
- // But unfortunately because we can have an arbitrary
197
- // amount of returns and it would be complex to try and
198
- // figure out how many of those can get passed in registers,
199
- // just conservatively assume none of them do.
200
- framesz = f .nret
201
- } else {
202
- // Need to pass arguments on the stack too.
203
- framesz = unsafe .Sizeof ((interface {})(nil )) + f .nret
204
- }
190
+ // The args may be passed in registers or on stack. Even for
191
+ // the register case, we still need the spill slots.
192
+ // TODO: revisit if we remove spill slots.
193
+ //
194
+ // Unfortunately because we can have an arbitrary
195
+ // amount of returns and it would be complex to try and
196
+ // figure out how many of those can get passed in registers,
197
+ // just conservatively assume none of them do.
198
+ framesz := unsafe .Sizeof ((interface {})(nil )) + f .nret
205
199
if framecap < framesz {
206
200
// The frame does not contain pointers interesting for GC,
207
201
// all not yet finalized objects are stored in finq.
Original file line number Diff line number Diff line change @@ -42,6 +42,15 @@ func TestFinalizerType(t *testing.T) {
42
42
{func (x * int ) interface {} { return Tintptr (x ) }, func (v * int ) { finalize (v ) }},
43
43
{func (x * int ) interface {} { return (* Tint )(x ) }, func (v * Tint ) { finalize ((* int )(v )) }},
44
44
{func (x * int ) interface {} { return (* Tint )(x ) }, func (v Tinter ) { finalize ((* int )(v .(* Tint ))) }},
45
+ // Test case for argument spill slot.
46
+ // If the spill slot was not counted for the frame size, it will (incorrectly) choose
47
+ // call32 as the result has (exactly) 32 bytes. When the argument actually spills,
48
+ // it clobbers the caller's frame (likely the return PC).
49
+ {func (x * int ) interface {} { return x }, func (v interface {}) [4 ]int64 {
50
+ print () // force spill
51
+ finalize (v .(* int ))
52
+ return [4 ]int64 {}
53
+ }},
45
54
}
46
55
47
56
for i , tt := range finalizerTests {
You can’t perform that action at this time.
0 commit comments