Skip to content

Commit b084073

Browse files
committed
reflect: refactor funcLayout tests
This change refactors the existing funcLayout tests and sets them up to support the new register ABI by explicitly setting the register counts to zero. This allows the test to pass if GOEXPERIMENT=regabiargs is set. A follow-up change will add tests for a non-zero register count. For #40724. Change-Id: Ibbe061b4ed4fd70566eb38b9e6182dca32b81127 Reviewed-on: https://go-review.googlesource.com/c/go/+/307869 Trust: Michael Knyszek <[email protected]> Run-TryBot: Michael Knyszek <[email protected]> Reviewed-by: Cherry Zhang <[email protected]>
1 parent 0a51047 commit b084073

File tree

3 files changed

+158
-188
lines changed

3 files changed

+158
-188
lines changed

src/reflect/abi_test.go

Lines changed: 3 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -22,23 +22,7 @@ func TestMethodValueCallABI(t *testing.T) {
2222
// Enable register-based reflect.Call and ensure we don't
2323
// use potentially incorrect cached versions by clearing
2424
// the cache before we start and after we're done.
25-
var oldRegs struct {
26-
ints, floats int
27-
floatSize uintptr
28-
}
29-
oldRegs.ints = *reflect.IntArgRegs
30-
oldRegs.floats = *reflect.FloatArgRegs
31-
oldRegs.floatSize = *reflect.FloatRegSize
32-
*reflect.IntArgRegs = abi.IntArgRegs
33-
*reflect.FloatArgRegs = abi.FloatArgRegs
34-
*reflect.FloatRegSize = uintptr(abi.EffectiveFloatRegSize)
35-
reflect.ClearLayoutCache()
36-
defer func() {
37-
*reflect.IntArgRegs = oldRegs.ints
38-
*reflect.FloatArgRegs = oldRegs.floats
39-
*reflect.FloatRegSize = oldRegs.floatSize
40-
reflect.ClearLayoutCache()
41-
}()
25+
defer reflect.SetArgRegs(reflect.SetArgRegs(abi.IntArgRegs, abi.FloatArgRegs, abi.EffectiveFloatRegSize))
4226

4327
// This test is simple. Calling a method value involves
4428
// pretty much just plumbing whatever arguments in whichever
@@ -129,23 +113,7 @@ func TestReflectCallABI(t *testing.T) {
129113
// Enable register-based reflect.Call and ensure we don't
130114
// use potentially incorrect cached versions by clearing
131115
// the cache before we start and after we're done.
132-
var oldRegs struct {
133-
ints, floats int
134-
floatSize uintptr
135-
}
136-
oldRegs.ints = *reflect.IntArgRegs
137-
oldRegs.floats = *reflect.FloatArgRegs
138-
oldRegs.floatSize = *reflect.FloatRegSize
139-
*reflect.IntArgRegs = abi.IntArgRegs
140-
*reflect.FloatArgRegs = abi.FloatArgRegs
141-
*reflect.FloatRegSize = uintptr(abi.EffectiveFloatRegSize)
142-
reflect.ClearLayoutCache()
143-
defer func() {
144-
*reflect.IntArgRegs = oldRegs.ints
145-
*reflect.FloatArgRegs = oldRegs.floats
146-
*reflect.FloatRegSize = oldRegs.floatSize
147-
reflect.ClearLayoutCache()
148-
}()
116+
defer reflect.SetArgRegs(reflect.SetArgRegs(abi.IntArgRegs, abi.FloatArgRegs, abi.EffectiveFloatRegSize))
149117

150118
// Execute the functions defined below which all have the
151119
// same form and perform the same function: pass all arguments
@@ -182,23 +150,7 @@ func TestReflectMakeFuncCallABI(t *testing.T) {
182150
// Enable register-based reflect.MakeFunc and ensure we don't
183151
// use potentially incorrect cached versions by clearing
184152
// the cache before we start and after we're done.
185-
var oldRegs struct {
186-
ints, floats int
187-
floatSize uintptr
188-
}
189-
oldRegs.ints = *reflect.IntArgRegs
190-
oldRegs.floats = *reflect.FloatArgRegs
191-
oldRegs.floatSize = *reflect.FloatRegSize
192-
*reflect.IntArgRegs = abi.IntArgRegs
193-
*reflect.FloatArgRegs = abi.FloatArgRegs
194-
*reflect.FloatRegSize = uintptr(abi.EffectiveFloatRegSize)
195-
reflect.ClearLayoutCache()
196-
defer func() {
197-
*reflect.IntArgRegs = oldRegs.ints
198-
*reflect.FloatArgRegs = oldRegs.floats
199-
*reflect.FloatRegSize = oldRegs.floatSize
200-
reflect.ClearLayoutCache()
201-
}()
153+
defer reflect.SetArgRegs(reflect.SetArgRegs(abi.IntArgRegs, abi.FloatArgRegs, abi.EffectiveFloatRegSize))
202154

203155
// Execute the functions defined below which all have the
204156
// same form and perform the same function: pass all arguments

src/reflect/all_test.go

Lines changed: 113 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -6396,144 +6396,135 @@ func clobber() {
63966396
runtime.GC()
63976397
}
63986398

6399-
type funcLayoutTest struct {
6400-
rcvr, t Type
6401-
size, argsize, retOffset uintptr
6402-
stack []byte // pointer bitmap: 1 is pointer, 0 is scalar
6403-
gc []byte
6404-
}
6405-
6406-
var funcLayoutTests []funcLayoutTest
6407-
6408-
func init() {
6409-
var argAlign uintptr = PtrSize
6410-
roundup := func(x uintptr, a uintptr) uintptr {
6411-
return (x + a - 1) / a * a
6412-
}
6413-
6414-
funcLayoutTests = append(funcLayoutTests,
6415-
funcLayoutTest{
6416-
nil,
6417-
ValueOf(func(a, b string) string { return "" }).Type(),
6418-
6 * PtrSize,
6419-
4 * PtrSize,
6420-
4 * PtrSize,
6421-
[]byte{1, 0, 1, 0, 1},
6422-
[]byte{1, 0, 1, 0, 1},
6423-
})
6424-
6399+
func TestFuncLayout(t *testing.T) {
6400+
align := func(x uintptr) uintptr {
6401+
return (x + PtrSize - 1) &^ (PtrSize - 1)
6402+
}
64256403
var r []byte
64266404
if PtrSize == 4 {
64276405
r = []byte{0, 0, 0, 1}
64286406
} else {
64296407
r = []byte{0, 0, 1}
64306408
}
6431-
funcLayoutTests = append(funcLayoutTests,
6432-
funcLayoutTest{
6433-
nil,
6434-
ValueOf(func(a, b, c uint32, p *byte, d uint16) {}).Type(),
6435-
roundup(roundup(3*4, PtrSize)+PtrSize+2, argAlign),
6436-
roundup(3*4, PtrSize) + PtrSize + 2,
6437-
roundup(roundup(3*4, PtrSize)+PtrSize+2, argAlign),
6438-
r,
6439-
r,
6440-
})
6441-
6442-
funcLayoutTests = append(funcLayoutTests,
6443-
funcLayoutTest{
6444-
nil,
6445-
ValueOf(func(a map[int]int, b uintptr, c interface{}) {}).Type(),
6446-
4 * PtrSize,
6447-
4 * PtrSize,
6448-
4 * PtrSize,
6449-
[]byte{1, 0, 1, 1},
6450-
[]byte{1, 0, 1, 1},
6451-
})
64526409

64536410
type S struct {
64546411
a, b uintptr
64556412
c, d *byte
64566413
}
6457-
funcLayoutTests = append(funcLayoutTests,
6458-
funcLayoutTest{
6459-
nil,
6460-
ValueOf(func(a S) {}).Type(),
6461-
4 * PtrSize,
6462-
4 * PtrSize,
6463-
4 * PtrSize,
6464-
[]byte{0, 0, 1, 1},
6465-
[]byte{0, 0, 1, 1},
6466-
})
6467-
6468-
funcLayoutTests = append(funcLayoutTests,
6469-
funcLayoutTest{
6470-
ValueOf((*byte)(nil)).Type(),
6471-
ValueOf(func(a uintptr, b *int) {}).Type(),
6472-
roundup(3*PtrSize, argAlign),
6473-
3 * PtrSize,
6474-
roundup(3*PtrSize, argAlign),
6475-
[]byte{1, 0, 1},
6476-
[]byte{1, 0, 1},
6477-
})
64786414

6479-
funcLayoutTests = append(funcLayoutTests,
6480-
funcLayoutTest{
6481-
nil,
6482-
ValueOf(func(a uintptr) {}).Type(),
6483-
roundup(PtrSize, argAlign),
6484-
PtrSize,
6485-
roundup(PtrSize, argAlign),
6486-
[]byte{},
6487-
[]byte{},
6488-
})
6489-
6490-
funcLayoutTests = append(funcLayoutTests,
6491-
funcLayoutTest{
6492-
nil,
6493-
ValueOf(func() uintptr { return 0 }).Type(),
6494-
PtrSize,
6495-
0,
6496-
0,
6497-
[]byte{},
6498-
[]byte{},
6499-
})
6500-
6501-
funcLayoutTests = append(funcLayoutTests,
6502-
funcLayoutTest{
6503-
ValueOf(uintptr(0)).Type(),
6504-
ValueOf(func(a uintptr) {}).Type(),
6505-
2 * PtrSize,
6506-
2 * PtrSize,
6507-
2 * PtrSize,
6508-
[]byte{1},
6509-
[]byte{1},
6415+
type test struct {
6416+
rcvr, typ Type
6417+
size, argsize, retOffset uintptr
6418+
stack, gc, inRegs, outRegs []byte // pointer bitmap: 1 is pointer, 0 is scalar
6419+
intRegs, floatRegs int
6420+
floatRegSize uintptr
6421+
}
6422+
tests := []test{
6423+
{
6424+
typ: ValueOf(func(a, b string) string { return "" }).Type(),
6425+
size: 6 * PtrSize,
6426+
argsize: 4 * PtrSize,
6427+
retOffset: 4 * PtrSize,
6428+
stack: []byte{1, 0, 1, 0, 1},
6429+
gc: []byte{1, 0, 1, 0, 1},
6430+
},
6431+
{
6432+
typ: ValueOf(func(a, b, c uint32, p *byte, d uint16) {}).Type(),
6433+
size: align(align(3*4) + PtrSize + 2),
6434+
argsize: align(3*4) + PtrSize + 2,
6435+
retOffset: align(align(3*4) + PtrSize + 2),
6436+
stack: r,
6437+
gc: r,
6438+
},
6439+
{
6440+
typ: ValueOf(func(a map[int]int, b uintptr, c interface{}) {}).Type(),
6441+
size: 4 * PtrSize,
6442+
argsize: 4 * PtrSize,
6443+
retOffset: 4 * PtrSize,
6444+
stack: []byte{1, 0, 1, 1},
6445+
gc: []byte{1, 0, 1, 1},
6446+
},
6447+
{
6448+
typ: ValueOf(func(a S) {}).Type(),
6449+
size: 4 * PtrSize,
6450+
argsize: 4 * PtrSize,
6451+
retOffset: 4 * PtrSize,
6452+
stack: []byte{0, 0, 1, 1},
6453+
gc: []byte{0, 0, 1, 1},
6454+
},
6455+
{
6456+
rcvr: ValueOf((*byte)(nil)).Type(),
6457+
typ: ValueOf(func(a uintptr, b *int) {}).Type(),
6458+
size: 3 * PtrSize,
6459+
argsize: 3 * PtrSize,
6460+
retOffset: 3 * PtrSize,
6461+
stack: []byte{1, 0, 1},
6462+
gc: []byte{1, 0, 1},
6463+
},
6464+
{
6465+
typ: ValueOf(func(a uintptr) {}).Type(),
6466+
size: PtrSize,
6467+
argsize: PtrSize,
6468+
retOffset: PtrSize,
6469+
stack: []byte{},
6470+
gc: []byte{},
6471+
},
6472+
{
6473+
typ: ValueOf(func() uintptr { return 0 }).Type(),
6474+
size: PtrSize,
6475+
argsize: 0,
6476+
retOffset: 0,
6477+
stack: []byte{},
6478+
gc: []byte{},
6479+
},
6480+
{
6481+
rcvr: ValueOf(uintptr(0)).Type(),
6482+
typ: ValueOf(func(a uintptr) {}).Type(),
6483+
size: 2 * PtrSize,
6484+
argsize: 2 * PtrSize,
6485+
retOffset: 2 * PtrSize,
6486+
stack: []byte{1},
6487+
gc: []byte{1},
65106488
// Note: this one is tricky, as the receiver is not a pointer. But we
65116489
// pass the receiver by reference to the autogenerated pointer-receiver
65126490
// version of the function.
6513-
})
6514-
}
6515-
6516-
func TestFuncLayout(t *testing.T) {
6517-
for _, lt := range funcLayoutTests {
6518-
typ, argsize, retOffset, stack, gc, ptrs := FuncLayout(lt.t, lt.rcvr)
6519-
if typ.Size() != lt.size {
6520-
t.Errorf("funcLayout(%v, %v).size=%d, want %d", lt.t, lt.rcvr, typ.Size(), lt.size)
6521-
}
6522-
if argsize != lt.argsize {
6523-
t.Errorf("funcLayout(%v, %v).argsize=%d, want %d", lt.t, lt.rcvr, argsize, lt.argsize)
6524-
}
6525-
if retOffset != lt.retOffset {
6526-
t.Errorf("funcLayout(%v, %v).retOffset=%d, want %d", lt.t, lt.rcvr, retOffset, lt.retOffset)
6527-
}
6528-
if !bytes.Equal(stack, lt.stack) {
6529-
t.Errorf("funcLayout(%v, %v).stack=%v, want %v", lt.t, lt.rcvr, stack, lt.stack)
6530-
}
6531-
if !bytes.Equal(gc, lt.gc) {
6532-
t.Errorf("funcLayout(%v, %v).gc=%v, want %v", lt.t, lt.rcvr, gc, lt.gc)
6533-
}
6534-
if ptrs && len(stack) == 0 || !ptrs && len(stack) > 0 {
6535-
t.Errorf("funcLayout(%v, %v) pointers flag=%v, want %v", lt.t, lt.rcvr, ptrs, !ptrs)
6491+
},
6492+
// TODO(mknyszek): Add tests for non-zero register count.
6493+
}
6494+
for _, lt := range tests {
6495+
name := lt.typ.String()
6496+
if lt.rcvr != nil {
6497+
name = lt.rcvr.String() + "." + name
65366498
}
6499+
t.Run(name, func(t *testing.T) {
6500+
defer SetArgRegs(SetArgRegs(lt.intRegs, lt.floatRegs, lt.floatRegSize))
6501+
6502+
typ, argsize, retOffset, stack, gc, inRegs, outRegs, ptrs := FuncLayout(lt.typ, lt.rcvr)
6503+
if typ.Size() != lt.size {
6504+
t.Errorf("funcLayout(%v, %v).size=%d, want %d", lt.typ, lt.rcvr, typ.Size(), lt.size)
6505+
}
6506+
if argsize != lt.argsize {
6507+
t.Errorf("funcLayout(%v, %v).argsize=%d, want %d", lt.typ, lt.rcvr, argsize, lt.argsize)
6508+
}
6509+
if retOffset != lt.retOffset {
6510+
t.Errorf("funcLayout(%v, %v).retOffset=%d, want %d", lt.typ, lt.rcvr, retOffset, lt.retOffset)
6511+
}
6512+
if !bytes.Equal(stack, lt.stack) {
6513+
t.Errorf("funcLayout(%v, %v).stack=%v, want %v", lt.typ, lt.rcvr, stack, lt.stack)
6514+
}
6515+
if !bytes.Equal(gc, lt.gc) {
6516+
t.Errorf("funcLayout(%v, %v).gc=%v, want %v", lt.typ, lt.rcvr, gc, lt.gc)
6517+
}
6518+
if !bytes.Equal(inRegs, lt.inRegs) {
6519+
t.Errorf("funcLayout(%v, %v).inRegs=%v, want %v", lt.typ, lt.rcvr, inRegs, lt.inRegs)
6520+
}
6521+
if !bytes.Equal(outRegs, lt.outRegs) {
6522+
t.Errorf("funcLayout(%v, %v).outRegs=%v, want %v", lt.typ, lt.rcvr, outRegs, lt.outRegs)
6523+
}
6524+
if ptrs && len(stack) == 0 || !ptrs && len(stack) > 0 {
6525+
t.Errorf("funcLayout(%v, %v) pointers flag=%v, want %v", lt.typ, lt.rcvr, ptrs, !ptrs)
6526+
}
6527+
})
65376528
}
65386529
}
65396530

0 commit comments

Comments
 (0)