fix(verify): fix flaky JIT tests with global buffers and KeepAlive
This commit is contained in:
@@ -4,6 +4,7 @@
|
|||||||
package verify
|
package verify
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
@@ -100,6 +101,8 @@ func TestABILZ4Kernels(t *testing.T) {
|
|||||||
PutUint64(args, 40, 128)
|
PutUint64(args, 40, 128)
|
||||||
|
|
||||||
_, report, err := k.CallFuncChecked("wideCopyAVX2", args)
|
_, report, err := k.CallFuncChecked("wideCopyAVX2", args)
|
||||||
|
runtime.KeepAlive(dst)
|
||||||
|
runtime.KeepAlive(src)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("CallFuncChecked(wideCopyAVX2): %v", err)
|
t.Fatalf("CallFuncChecked(wideCopyAVX2): %v", err)
|
||||||
}
|
}
|
||||||
@@ -120,6 +123,8 @@ func TestABILZ4Kernels(t *testing.T) {
|
|||||||
PutUint64(decArgs, 40, uint64(cap(decDst)))
|
PutUint64(decArgs, 40, uint64(cap(decDst)))
|
||||||
|
|
||||||
_, report, err = k.CallFuncChecked("decodeBlockAVX2", decArgs)
|
_, report, err = k.CallFuncChecked("decodeBlockAVX2", decArgs)
|
||||||
|
runtime.KeepAlive(decSrc)
|
||||||
|
runtime.KeepAlive(decDst)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("CallFuncChecked(decodeBlockAVX2): %v", err)
|
t.Fatalf("CallFuncChecked(decodeBlockAVX2): %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"os"
|
"os"
|
||||||
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
@@ -53,6 +54,8 @@ func TestAVX512DecodeKnownAnswers(t *testing.T) {
|
|||||||
PutUint64(args, 40, uint64(cap(dst)))
|
PutUint64(args, 40, uint64(cap(dst)))
|
||||||
|
|
||||||
out, err := k.CallFunc("decodeBlockAVX512", args)
|
out, err := k.CallFunc("decodeBlockAVX512", args)
|
||||||
|
runtime.KeepAlive(tt.src)
|
||||||
|
runtime.KeepAlive(dst)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("CallFunc: %v", err)
|
t.Fatalf("CallFunc: %v", err)
|
||||||
}
|
}
|
||||||
@@ -91,6 +94,8 @@ func TestAVX512DifferentialFuzz(t *testing.T) {
|
|||||||
PutUint64(args, 40, uint64(cap(jitDst)))
|
PutUint64(args, 40, uint64(cap(jitDst)))
|
||||||
|
|
||||||
out, err := k.CallFunc("decodeBlockAVX512", args)
|
out, err := k.CallFunc("decodeBlockAVX512", args)
|
||||||
|
runtime.KeepAlive(src)
|
||||||
|
runtime.KeepAlive(jitDst)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("iter %d: %v", i, err)
|
t.Fatalf("iter %d: %v", i, err)
|
||||||
}
|
}
|
||||||
@@ -134,6 +139,8 @@ func TestAVX512WideCopy(t *testing.T) {
|
|||||||
PutUint64(args, 40, uint64(n))
|
PutUint64(args, 40, uint64(n))
|
||||||
|
|
||||||
_, err := k.CallFunc("wideCopyAVX512", args)
|
_, err := k.CallFunc("wideCopyAVX512", args)
|
||||||
|
runtime.KeepAlive(dst)
|
||||||
|
runtime.KeepAlive(src)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("wideCopyAVX512(n=%d): %v", n, err)
|
t.Fatalf("wideCopyAVX512(n=%d): %v", n, err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package verify
|
package verify
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
@@ -44,6 +45,7 @@ func TestProfilePaths(t *testing.T) {
|
|||||||
|
|
||||||
// Build a corpus of varied LZ4 blocks.
|
// Build a corpus of varied LZ4 blocks.
|
||||||
var argSets [][]byte
|
var argSets [][]byte
|
||||||
|
var liveDsts [][]byte // keep dst buffers alive across ProfilePaths
|
||||||
blocks := []struct {
|
blocks := []struct {
|
||||||
src []byte
|
src []byte
|
||||||
dstSize int
|
dstSize int
|
||||||
@@ -63,6 +65,7 @@ func TestProfilePaths(t *testing.T) {
|
|||||||
PutUint64(args, 8, uint64(len(b.src)))
|
PutUint64(args, 8, uint64(len(b.src)))
|
||||||
PutUint64(args, 16, uint64(cap(b.src)))
|
PutUint64(args, 16, uint64(cap(b.src)))
|
||||||
dst := make([]byte, b.dstSize)
|
dst := make([]byte, b.dstSize)
|
||||||
|
liveDsts = append(liveDsts, dst)
|
||||||
if len(dst) > 0 {
|
if len(dst) > 0 {
|
||||||
PutPtr(args, 24, unsafe.Pointer(&dst[0]))
|
PutPtr(args, 24, unsafe.Pointer(&dst[0]))
|
||||||
}
|
}
|
||||||
@@ -73,6 +76,8 @@ func TestProfilePaths(t *testing.T) {
|
|||||||
|
|
||||||
// Result offsets: n+48 and code+56.
|
// Result offsets: n+48 and code+56.
|
||||||
paths, err := k.ProfilePaths("decodeBlockAVX2", argSets, []int{48, 56})
|
paths, err := k.ProfilePaths("decodeBlockAVX2", argSets, []int{48, 56})
|
||||||
|
runtime.KeepAlive(blocks)
|
||||||
|
runtime.KeepAlive(liveDsts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("ProfilePaths: %v", err)
|
t.Fatalf("ProfilePaths: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ package verify
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
@@ -288,6 +289,8 @@ func callDecodeBlockAVX2Raw(t *testing.T, k *Kernel, src, dst []byte) (int, int)
|
|||||||
PutUint64(args, 40, uint64(cap(dst)))
|
PutUint64(args, 40, uint64(cap(dst)))
|
||||||
|
|
||||||
out, err := k.CallFunc("decodeBlockAVX2", args)
|
out, err := k.CallFunc("decodeBlockAVX2", args)
|
||||||
|
runtime.KeepAlive(src)
|
||||||
|
runtime.KeepAlive(dst)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("CallFunc(decodeBlockAVX2): %v", err)
|
t.Fatalf("CallFunc(decodeBlockAVX2): %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
+134
-27
@@ -7,6 +7,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"os"
|
"os"
|
||||||
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
@@ -157,19 +158,51 @@ func decodeStereo16Go(src []byte, left, right []int32) {
|
|||||||
|
|
||||||
// --- Differential tests ---
|
// --- Differential tests ---
|
||||||
|
|
||||||
|
// Buffers whose addresses are passed to JIT code via unsafe.Pointer are
|
||||||
|
// package-level globals: their addresses are stable and the GC never moves
|
||||||
|
// or collects them, unlike per-iteration make() buffers (which caused flaky
|
||||||
|
// stale reads, especially under -race). Sizes cover the maximum n from the
|
||||||
|
// rng.Intn(N) call in each test, rounded up.
|
||||||
|
var (
|
||||||
|
mono16Src [512]byte // TestFLACDecodeMono16: max n = 255 → 2*n = 510
|
||||||
|
mono16JitDst [256]int32 // max n = 255
|
||||||
|
|
||||||
|
pack16Src [256]int32 // TestFLACPack16: max n = 255
|
||||||
|
pack16JitDst [512]byte // max 2*n = 510
|
||||||
|
|
||||||
|
decorLeft [128]int32 // TestFLACDecorrelate: max n = 127
|
||||||
|
decorRight [128]int32 // max n = 127
|
||||||
|
decorJitOut [256]int32 // max 2*n = 254
|
||||||
|
|
||||||
|
mono24Src [768]byte // TestFLACDecodeMono24: max n = 255 → 3*n = 765
|
||||||
|
mono24JitDst [256]int32 // max n = 255
|
||||||
|
|
||||||
|
stereo16Src [1024]byte // TestFLACDecodeStereo16: max n = 255 → 4*n = 1020
|
||||||
|
stereo16JitLeft [256]int32 // max n = 255
|
||||||
|
stereo16JitRight [256]int32 // max n = 255
|
||||||
|
|
||||||
|
fastStereoLeft [256]int32 // TestFLACFastStereoSums: max n = 255
|
||||||
|
fastStereoRight [256]int32 // max n = 255
|
||||||
|
)
|
||||||
|
|
||||||
func TestFLACDecodeMono16(t *testing.T) {
|
func TestFLACDecodeMono16(t *testing.T) {
|
||||||
k := loadFLACKernel(t)
|
k := loadFLACKernel(t)
|
||||||
rng := rand.New(rand.NewSource(7))
|
rng := rand.New(rand.NewSource(7))
|
||||||
|
|
||||||
|
src := mono16Src[:0]
|
||||||
|
jitDst := mono16JitDst[:0]
|
||||||
for iter := 0; iter < 500; iter++ {
|
for iter := 0; iter < 500; iter++ {
|
||||||
n := rng.Intn(256)
|
n := rng.Intn(256)
|
||||||
src := make([]byte, 2*n)
|
src = src[:2*n]
|
||||||
rng.Read(src)
|
rng.Read(src)
|
||||||
|
|
||||||
goDst := make([]int32, n)
|
goDst := make([]int32, n)
|
||||||
decodeMono16Go(src, goDst)
|
decodeMono16Go(src, goDst)
|
||||||
|
|
||||||
jitDst := make([]int32, n)
|
jitDst = jitDst[:n]
|
||||||
|
for i := range jitDst {
|
||||||
|
jitDst[i] = 0
|
||||||
|
}
|
||||||
args := make([]byte, 48)
|
args := make([]byte, 48)
|
||||||
if len(src) > 0 {
|
if len(src) > 0 {
|
||||||
PutPtr(args, 0, unsafe.Pointer(&src[0]))
|
PutPtr(args, 0, unsafe.Pointer(&src[0]))
|
||||||
@@ -183,6 +216,8 @@ func TestFLACDecodeMono16(t *testing.T) {
|
|||||||
PutUint64(args, 40, uint64(cap(jitDst)))
|
PutUint64(args, 40, uint64(cap(jitDst)))
|
||||||
|
|
||||||
_, err := k.CallFunc("decodeMono16AVX2", args)
|
_, err := k.CallFunc("decodeMono16AVX2", args)
|
||||||
|
runtime.KeepAlive(src)
|
||||||
|
runtime.KeepAlive(jitDst)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("iter %d: %v", iter, err)
|
t.Fatalf("iter %d: %v", iter, err)
|
||||||
}
|
}
|
||||||
@@ -198,9 +233,11 @@ func TestFLACPack16(t *testing.T) {
|
|||||||
k := loadFLACKernel(t)
|
k := loadFLACKernel(t)
|
||||||
rng := rand.New(rand.NewSource(13))
|
rng := rand.New(rand.NewSource(13))
|
||||||
|
|
||||||
|
src := pack16Src[:0]
|
||||||
|
jitDst := pack16JitDst[:0]
|
||||||
for iter := 0; iter < 500; iter++ {
|
for iter := 0; iter < 500; iter++ {
|
||||||
n := rng.Intn(256)
|
n := rng.Intn(256)
|
||||||
src := make([]int32, n)
|
src = src[:n]
|
||||||
for i := range src {
|
for i := range src {
|
||||||
src[i] = int32(rng.Intn(65536) - 32768)
|
src[i] = int32(rng.Intn(65536) - 32768)
|
||||||
}
|
}
|
||||||
@@ -208,7 +245,10 @@ func TestFLACPack16(t *testing.T) {
|
|||||||
goDst := make([]byte, 2*n)
|
goDst := make([]byte, 2*n)
|
||||||
pack16Go(goDst, src)
|
pack16Go(goDst, src)
|
||||||
|
|
||||||
jitDst := make([]byte, 2*n)
|
jitDst = jitDst[:2*n]
|
||||||
|
for i := range jitDst {
|
||||||
|
jitDst[i] = 0
|
||||||
|
}
|
||||||
args := make([]byte, 48)
|
args := make([]byte, 48)
|
||||||
if len(jitDst) > 0 {
|
if len(jitDst) > 0 {
|
||||||
PutPtr(args, 0, unsafe.Pointer(&jitDst[0]))
|
PutPtr(args, 0, unsafe.Pointer(&jitDst[0]))
|
||||||
@@ -222,6 +262,8 @@ func TestFLACPack16(t *testing.T) {
|
|||||||
PutUint64(args, 40, uint64(cap(src)))
|
PutUint64(args, 40, uint64(cap(src)))
|
||||||
|
|
||||||
_, err := k.CallFunc("pack16AVX2", args)
|
_, err := k.CallFunc("pack16AVX2", args)
|
||||||
|
runtime.KeepAlive(jitDst)
|
||||||
|
runtime.KeepAlive(src)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("iter %d: %v", iter, err)
|
t.Fatalf("iter %d: %v", iter, err)
|
||||||
}
|
}
|
||||||
@@ -247,10 +289,13 @@ func TestFLACDecorrelate(t *testing.T) {
|
|||||||
|
|
||||||
for _, kk := range kernels {
|
for _, kk := range kernels {
|
||||||
t.Run(kk.name, func(t *testing.T) {
|
t.Run(kk.name, func(t *testing.T) {
|
||||||
|
left := decorLeft[:0]
|
||||||
|
right := decorRight[:0]
|
||||||
|
jitOut := decorJitOut[:0]
|
||||||
for iter := 0; iter < 200; iter++ {
|
for iter := 0; iter < 200; iter++ {
|
||||||
n := rng.Intn(128)
|
n := rng.Intn(128)
|
||||||
left := make([]int32, n)
|
left = left[:n]
|
||||||
right := make([]int32, n)
|
right = right[:n]
|
||||||
for i := range left {
|
for i := range left {
|
||||||
left[i] = int32(rng.Intn(1<<24) - 1<<23)
|
left[i] = int32(rng.Intn(1<<24) - 1<<23)
|
||||||
right[i] = int32(rng.Intn(1<<24) - 1<<23)
|
right[i] = int32(rng.Intn(1<<24) - 1<<23)
|
||||||
@@ -259,7 +304,10 @@ func TestFLACDecorrelate(t *testing.T) {
|
|||||||
goOut := make([]int32, 2*n)
|
goOut := make([]int32, 2*n)
|
||||||
kk.ref(left, right, goOut)
|
kk.ref(left, right, goOut)
|
||||||
|
|
||||||
jitOut := make([]int32, 2*n)
|
jitOut = jitOut[:2*n]
|
||||||
|
for i := range jitOut {
|
||||||
|
jitOut[i] = 0
|
||||||
|
}
|
||||||
args := make([]byte, 72)
|
args := make([]byte, 72)
|
||||||
if n > 0 {
|
if n > 0 {
|
||||||
PutPtr(args, 0, unsafe.Pointer(&left[0]))
|
PutPtr(args, 0, unsafe.Pointer(&left[0]))
|
||||||
@@ -274,6 +322,9 @@ func TestFLACDecorrelate(t *testing.T) {
|
|||||||
PutUint64(args, 64, uint64(cap(jitOut)))
|
PutUint64(args, 64, uint64(cap(jitOut)))
|
||||||
|
|
||||||
_, err := k.CallFunc(kk.name, args)
|
_, err := k.CallFunc(kk.name, args)
|
||||||
|
runtime.KeepAlive(left)
|
||||||
|
runtime.KeepAlive(right)
|
||||||
|
runtime.KeepAlive(jitOut)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("iter %d: %v", iter, err)
|
t.Fatalf("iter %d: %v", iter, err)
|
||||||
}
|
}
|
||||||
@@ -291,9 +342,11 @@ func TestFLACAnalyzeO1Range(t *testing.T) {
|
|||||||
k := loadFLACKernel(t)
|
k := loadFLACKernel(t)
|
||||||
rng := rand.New(rand.NewSource(33))
|
rng := rand.New(rand.NewSource(33))
|
||||||
|
|
||||||
|
swin := analyzeSwin[:0]
|
||||||
|
jitDstP := analyzeJitDstP[:0]
|
||||||
for iter := 0; iter < 300; iter++ {
|
for iter := 0; iter < 300; iter++ {
|
||||||
n := 1 + rng.Intn(128) // partition size
|
n := 1 + rng.Intn(128) // partition size
|
||||||
swin := make([]int32, n+1)
|
swin = swin[:n+1]
|
||||||
for i := range swin {
|
for i := range swin {
|
||||||
swin[i] = int32(rng.Intn(1<<20) - 1<<19)
|
swin[i] = int32(rng.Intn(1<<20) - 1<<19)
|
||||||
}
|
}
|
||||||
@@ -302,8 +355,12 @@ func TestFLACAnalyzeO1Range(t *testing.T) {
|
|||||||
var goHist [32]uint16
|
var goHist [32]uint16
|
||||||
goSum, goOvf := analyzeO1RangeGo(swin, goDstP, &goHist)
|
goSum, goOvf := analyzeO1RangeGo(swin, goDstP, &goHist)
|
||||||
|
|
||||||
jitDstP := make([]uint32, n)
|
jitDstP = jitDstP[:n]
|
||||||
var jitHist [32]uint16
|
for i := range jitDstP {
|
||||||
|
jitDstP[i] = 0
|
||||||
|
}
|
||||||
|
jitHist := &analyzeJitHist
|
||||||
|
*jitHist = [32]uint16{} // reset for this iteration
|
||||||
args := make([]byte, 72) // 65 rounded up
|
args := make([]byte, 72) // 65 rounded up
|
||||||
PutPtr(args, 0, unsafe.Pointer(&swin[0]))
|
PutPtr(args, 0, unsafe.Pointer(&swin[0]))
|
||||||
PutUint64(args, 8, uint64(len(swin)))
|
PutUint64(args, 8, uint64(len(swin)))
|
||||||
@@ -314,6 +371,9 @@ func TestFLACAnalyzeO1Range(t *testing.T) {
|
|||||||
PutPtr(args, 48, unsafe.Pointer(&jitHist[0]))
|
PutPtr(args, 48, unsafe.Pointer(&jitHist[0]))
|
||||||
|
|
||||||
out, err := k.CallFunc("analyzeO1RangeAVX2", args)
|
out, err := k.CallFunc("analyzeO1RangeAVX2", args)
|
||||||
|
runtime.KeepAlive(swin)
|
||||||
|
runtime.KeepAlive(jitDstP)
|
||||||
|
runtime.KeepAlive(jitHist)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("iter %d: %v", iter, err)
|
t.Fatalf("iter %d: %v", iter, err)
|
||||||
}
|
}
|
||||||
@@ -331,8 +391,8 @@ func TestFLACAnalyzeO1Range(t *testing.T) {
|
|||||||
t.Fatalf("iter %d: dstP[%d] mismatch: JIT=%d Go=%d", iter, i, jitDstP[i], goDstP[i])
|
t.Fatalf("iter %d: dstP[%d] mismatch: JIT=%d Go=%d", iter, i, jitDstP[i], goDstP[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if jitHist != goHist {
|
if *jitHist != goHist {
|
||||||
t.Fatalf("iter %d: hist mismatch: JIT=%v Go=%v", iter, jitHist, goHist)
|
t.Fatalf("iter %d: hist mismatch: JIT=%v Go=%v", iter, *jitHist, goHist)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -341,10 +401,12 @@ func TestFLACFastStereoSums(t *testing.T) {
|
|||||||
k := loadFLACKernel(t)
|
k := loadFLACKernel(t)
|
||||||
rng := rand.New(rand.NewSource(44))
|
rng := rand.New(rand.NewSource(44))
|
||||||
|
|
||||||
|
left := fastStereoLeft[:0]
|
||||||
|
right := fastStereoRight[:0]
|
||||||
for iter := 0; iter < 300; iter++ {
|
for iter := 0; iter < 300; iter++ {
|
||||||
n := 1 + rng.Intn(256)
|
n := 1 + rng.Intn(256)
|
||||||
left := make([]int32, n)
|
left = left[:n]
|
||||||
right := make([]int32, n)
|
right = right[:n]
|
||||||
for i := range left {
|
for i := range left {
|
||||||
left[i] = int32(rng.Intn(1<<24) - 1<<23)
|
left[i] = int32(rng.Intn(1<<24) - 1<<23)
|
||||||
right[i] = int32(rng.Intn(1<<24) - 1<<23)
|
right[i] = int32(rng.Intn(1<<24) - 1<<23)
|
||||||
@@ -363,7 +425,8 @@ func TestFLACFastStereoSums(t *testing.T) {
|
|||||||
goSums[3] += foldAbs(mid) + foldAbs(side)
|
goSums[3] += foldAbs(mid) + foldAbs(side)
|
||||||
}
|
}
|
||||||
|
|
||||||
var jitSums [4]uint64
|
jitSums := &analyzeJitSums
|
||||||
|
*jitSums = [4]uint64{} // reset for this iteration
|
||||||
args := make([]byte, 56)
|
args := make([]byte, 56)
|
||||||
PutPtr(args, 0, unsafe.Pointer(&left[0]))
|
PutPtr(args, 0, unsafe.Pointer(&left[0]))
|
||||||
PutUint64(args, 8, uint64(n))
|
PutUint64(args, 8, uint64(n))
|
||||||
@@ -374,11 +437,14 @@ func TestFLACFastStereoSums(t *testing.T) {
|
|||||||
PutPtr(args, 48, unsafe.Pointer(&jitSums[0]))
|
PutPtr(args, 48, unsafe.Pointer(&jitSums[0]))
|
||||||
|
|
||||||
_, err := k.CallFunc("fastStereoSumsAVX2", args)
|
_, err := k.CallFunc("fastStereoSumsAVX2", args)
|
||||||
|
runtime.KeepAlive(left)
|
||||||
|
runtime.KeepAlive(right)
|
||||||
|
runtime.KeepAlive(jitSums)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("iter %d: %v", iter, err)
|
t.Fatalf("iter %d: %v", iter, err)
|
||||||
}
|
}
|
||||||
if jitSums != goSums {
|
if *jitSums != goSums {
|
||||||
t.Fatalf("iter %d: sums mismatch:\n JIT=%v\n Go =%v", iter, jitSums, goSums)
|
t.Fatalf("iter %d: sums mismatch:\n JIT=%v\n Go =%v", iter, *jitSums, goSums)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -388,12 +454,27 @@ func foldAbs(v int32) uint64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// runAnalyzeTest is the shared harness for the analyzeO*Range family.
|
// runAnalyzeTest is the shared harness for the analyzeO*Range family.
|
||||||
|
// analyzeJitHist is a shared histogram buffer for the analyze tests.
|
||||||
|
// It is package-level so its address is stable across all calls.
|
||||||
|
var analyzeJitHist [32]uint16
|
||||||
|
|
||||||
|
// analyzeJitSums is a shared sums buffer for the fastStereoSums test.
|
||||||
|
var analyzeJitSums [4]uint64
|
||||||
|
|
||||||
|
// analyzeSwin and analyzeJitDstP are shared input/output buffers for the
|
||||||
|
// analyze tests. Package-level so their addresses are stable.
|
||||||
|
var analyzeSwin [136]int32 // max n(128) + max order(4) = 132, rounded up
|
||||||
|
var analyzeJitDstP [128]uint32
|
||||||
|
|
||||||
func runAnalyzeTest(t *testing.T, k *Kernel, name string, order int, ref func([]int32, []uint32, *[32]uint16) (uint64, bool)) {
|
func runAnalyzeTest(t *testing.T, k *Kernel, name string, order int, ref func([]int32, []uint32, *[32]uint16) (uint64, bool)) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
rng := rand.New(rand.NewSource(int64(order)*100 + 7))
|
rng := rand.New(rand.NewSource(int64(order)*100 + 7))
|
||||||
|
jitHist := &analyzeJitHist
|
||||||
|
swin := analyzeSwin[:0]
|
||||||
|
jitDstP := analyzeJitDstP[:0]
|
||||||
for iter := 0; iter < 200; iter++ {
|
for iter := 0; iter < 200; iter++ {
|
||||||
n := 1 + rng.Intn(128)
|
n := 1 + rng.Intn(128)
|
||||||
swin := make([]int32, n+order)
|
swin = swin[:n+order]
|
||||||
for i := range swin {
|
for i := range swin {
|
||||||
swin[i] = int32(rng.Intn(1<<20) - 1<<19)
|
swin[i] = int32(rng.Intn(1<<20) - 1<<19)
|
||||||
}
|
}
|
||||||
@@ -402,8 +483,11 @@ func runAnalyzeTest(t *testing.T, k *Kernel, name string, order int, ref func([]
|
|||||||
var goHist [32]uint16
|
var goHist [32]uint16
|
||||||
goSum, goOvf := ref(swin, goDstP, &goHist)
|
goSum, goOvf := ref(swin, goDstP, &goHist)
|
||||||
|
|
||||||
jitDstP := make([]uint32, n)
|
jitDstP = jitDstP[:n]
|
||||||
var jitHist [32]uint16
|
for i := range jitDstP {
|
||||||
|
jitDstP[i] = 0
|
||||||
|
}
|
||||||
|
*jitHist = [32]uint16{} // reset for this iteration
|
||||||
args := make([]byte, 72)
|
args := make([]byte, 72)
|
||||||
PutPtr(args, 0, unsafe.Pointer(&swin[0]))
|
PutPtr(args, 0, unsafe.Pointer(&swin[0]))
|
||||||
PutUint64(args, 8, uint64(len(swin)))
|
PutUint64(args, 8, uint64(len(swin)))
|
||||||
@@ -413,7 +497,13 @@ func runAnalyzeTest(t *testing.T, k *Kernel, name string, order int, ref func([]
|
|||||||
PutUint64(args, 40, uint64(cap(jitDstP)))
|
PutUint64(args, 40, uint64(cap(jitDstP)))
|
||||||
PutPtr(args, 48, unsafe.Pointer(&jitHist[0]))
|
PutPtr(args, 48, unsafe.Pointer(&jitHist[0]))
|
||||||
|
|
||||||
|
// Memory barrier: ensure all writes above are visible to the JIT code.
|
||||||
|
runtime.KeepAlive(args)
|
||||||
|
|
||||||
out, err := k.CallFunc(name, args)
|
out, err := k.CallFunc(name, args)
|
||||||
|
runtime.KeepAlive(swin)
|
||||||
|
runtime.KeepAlive(jitDstP)
|
||||||
|
runtime.KeepAlive(jitHist)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("iter %d: %v", iter, err)
|
t.Fatalf("iter %d: %v", iter, err)
|
||||||
}
|
}
|
||||||
@@ -431,8 +521,8 @@ func runAnalyzeTest(t *testing.T, k *Kernel, name string, order int, ref func([]
|
|||||||
t.Fatalf("iter %d: dstP[%d]: JIT=%d Go=%d", iter, i, jitDstP[i], goDstP[i])
|
t.Fatalf("iter %d: dstP[%d]: JIT=%d Go=%d", iter, i, jitDstP[i], goDstP[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if jitHist != goHist {
|
if *jitHist != goHist {
|
||||||
t.Fatalf("iter %d: hist mismatch", iter)
|
t.Fatalf("iter %d: hist mismatch\n JIT=%v\n Go =%v\n n=%d", iter, *jitHist, goHist, n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -508,15 +598,20 @@ func TestFLACDecodeMono24(t *testing.T) {
|
|||||||
k := loadFLACKernel(t)
|
k := loadFLACKernel(t)
|
||||||
rng := rand.New(rand.NewSource(55))
|
rng := rand.New(rand.NewSource(55))
|
||||||
|
|
||||||
|
src := mono24Src[:0]
|
||||||
|
jitDst := mono24JitDst[:0]
|
||||||
for iter := 0; iter < 500; iter++ {
|
for iter := 0; iter < 500; iter++ {
|
||||||
n := rng.Intn(256)
|
n := rng.Intn(256)
|
||||||
src := make([]byte, 3*n)
|
src = src[:3*n]
|
||||||
rng.Read(src)
|
rng.Read(src)
|
||||||
|
|
||||||
goDst := make([]int32, n)
|
goDst := make([]int32, n)
|
||||||
decodeMono24Go(src, goDst)
|
decodeMono24Go(src, goDst)
|
||||||
|
|
||||||
jitDst := make([]int32, n)
|
jitDst = jitDst[:n]
|
||||||
|
for i := range jitDst {
|
||||||
|
jitDst[i] = 0
|
||||||
|
}
|
||||||
args := make([]byte, 48)
|
args := make([]byte, 48)
|
||||||
if len(src) > 0 {
|
if len(src) > 0 {
|
||||||
PutPtr(args, 0, unsafe.Pointer(&src[0]))
|
PutPtr(args, 0, unsafe.Pointer(&src[0]))
|
||||||
@@ -530,6 +625,8 @@ func TestFLACDecodeMono24(t *testing.T) {
|
|||||||
PutUint64(args, 40, uint64(cap(jitDst)))
|
PutUint64(args, 40, uint64(cap(jitDst)))
|
||||||
|
|
||||||
_, err := k.CallFunc("decodeMono24AVX2", args)
|
_, err := k.CallFunc("decodeMono24AVX2", args)
|
||||||
|
runtime.KeepAlive(src)
|
||||||
|
runtime.KeepAlive(jitDst)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("iter %d: %v", iter, err)
|
t.Fatalf("iter %d: %v", iter, err)
|
||||||
}
|
}
|
||||||
@@ -545,17 +642,24 @@ func TestFLACDecodeStereo16(t *testing.T) {
|
|||||||
k := loadFLACKernel(t)
|
k := loadFLACKernel(t)
|
||||||
rng := rand.New(rand.NewSource(66))
|
rng := rand.New(rand.NewSource(66))
|
||||||
|
|
||||||
|
src := stereo16Src[:0]
|
||||||
|
jitLeft := stereo16JitLeft[:0]
|
||||||
|
jitRight := stereo16JitRight[:0]
|
||||||
for iter := 0; iter < 500; iter++ {
|
for iter := 0; iter < 500; iter++ {
|
||||||
n := rng.Intn(256)
|
n := rng.Intn(256)
|
||||||
src := make([]byte, 4*n) // [L0,R0,L1,R1,...]
|
src = src[:4*n] // [L0,R0,L1,R1,...]
|
||||||
rng.Read(src)
|
rng.Read(src)
|
||||||
|
|
||||||
goLeft := make([]int32, n)
|
goLeft := make([]int32, n)
|
||||||
goRight := make([]int32, n)
|
goRight := make([]int32, n)
|
||||||
decodeStereo16Go(src, goLeft, goRight)
|
decodeStereo16Go(src, goLeft, goRight)
|
||||||
|
|
||||||
jitLeft := make([]int32, n)
|
jitLeft = jitLeft[:n]
|
||||||
jitRight := make([]int32, n)
|
jitRight = jitRight[:n]
|
||||||
|
for i := range jitLeft {
|
||||||
|
jitLeft[i] = 0
|
||||||
|
jitRight[i] = 0
|
||||||
|
}
|
||||||
args := make([]byte, 72)
|
args := make([]byte, 72)
|
||||||
if len(src) > 0 {
|
if len(src) > 0 {
|
||||||
PutPtr(args, 0, unsafe.Pointer(&src[0]))
|
PutPtr(args, 0, unsafe.Pointer(&src[0]))
|
||||||
@@ -572,6 +676,9 @@ func TestFLACDecodeStereo16(t *testing.T) {
|
|||||||
PutUint64(args, 64, uint64(cap(jitRight)))
|
PutUint64(args, 64, uint64(cap(jitRight)))
|
||||||
|
|
||||||
_, err := k.CallFunc("decodeStereo16AVX2", args)
|
_, err := k.CallFunc("decodeStereo16AVX2", args)
|
||||||
|
runtime.KeepAlive(src)
|
||||||
|
runtime.KeepAlive(jitLeft)
|
||||||
|
runtime.KeepAlive(jitRight)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("iter %d: %v", iter, err)
|
t.Fatalf("iter %d: %v", iter, err)
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-9
@@ -7,6 +7,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
@@ -192,7 +193,7 @@ func (k *Kernel) FuzzFunc(name string, sig funcSig, goCode []byte, iterations in
|
|||||||
if result.FirstFail == "" {
|
if result.FirstFail == "" {
|
||||||
result.FirstFail = fmt.Sprintf("iter %d: gasm call: %v", i, err)
|
result.FirstFail = fmt.Sprintf("iter %d: gasm call: %v", i, err)
|
||||||
}
|
}
|
||||||
releaseBufs(bufs)
|
runtime.KeepAlive(bufs)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,7 +204,7 @@ func (k *Kernel) FuzzFunc(name string, sig funcSig, goCode []byte, iterations in
|
|||||||
if result.FirstFail == "" {
|
if result.FirstFail == "" {
|
||||||
result.FirstFail = fmt.Sprintf("iter %d: go call: %v", i, err)
|
result.FirstFail = fmt.Sprintf("iter %d: go call: %v", i, err)
|
||||||
}
|
}
|
||||||
releaseBufs(bufs)
|
runtime.KeepAlive(bufs)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,7 +222,7 @@ func (k *Kernel) FuzzFunc(name string, sig funcSig, goCode []byte, iterations in
|
|||||||
} else {
|
} else {
|
||||||
result.Matches++
|
result.Matches++
|
||||||
}
|
}
|
||||||
releaseBufs(bufs)
|
runtime.KeepAlive(bufs)
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
@@ -384,9 +385,3 @@ func equalBytes(a, b []byte) bool {
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func releaseBufs(bufs [][]byte) {
|
|
||||||
// Keep buffers alive until after the call; nothing to free in Go,
|
|
||||||
// but this prevents the compiler from collecting them too early.
|
|
||||||
_ = bufs
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ package verify
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
@@ -68,6 +69,7 @@ func TestJITSum(t *testing.T) {
|
|||||||
PutUint64(args, 16, uint64(cap(tt.data)))
|
PutUint64(args, 16, uint64(cap(tt.data)))
|
||||||
|
|
||||||
out, err := k.CallFunc("sum", args)
|
out, err := k.CallFunc("sum", args)
|
||||||
|
runtime.KeepAlive(tt.data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("CallFunc(sum, %v): %v", tt.data, err)
|
t.Fatalf("CallFunc(sum, %v): %v", tt.data, err)
|
||||||
}
|
}
|
||||||
@@ -111,6 +113,8 @@ func TestJITWideCopy(t *testing.T) {
|
|||||||
PutUint64(args, 40, uint64(tt.n)) // src_cap
|
PutUint64(args, 40, uint64(tt.n)) // src_cap
|
||||||
|
|
||||||
_, err := k.CallFunc("wideCopy", args)
|
_, err := k.CallFunc("wideCopy", args)
|
||||||
|
runtime.KeepAlive(dst)
|
||||||
|
runtime.KeepAlive(src)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("CallFunc(wideCopy): %v", err)
|
t.Fatalf("CallFunc(wideCopy): %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ package verify
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"os"
|
"os"
|
||||||
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
@@ -45,6 +46,8 @@ func callDecodeBlockAVX2(t *testing.T, k *Kernel, src, dst []byte) (int, int) {
|
|||||||
PutUint64(args, 40, uint64(cap(dst)))
|
PutUint64(args, 40, uint64(cap(dst)))
|
||||||
|
|
||||||
out, err := k.CallFunc("decodeBlockAVX2", args)
|
out, err := k.CallFunc("decodeBlockAVX2", args)
|
||||||
|
runtime.KeepAlive(src)
|
||||||
|
runtime.KeepAlive(dst)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("CallFunc(decodeBlockAVX2): %v", err)
|
t.Fatalf("CallFunc(decodeBlockAVX2): %v", err)
|
||||||
}
|
}
|
||||||
@@ -150,6 +153,8 @@ func TestLZ4WideCopyAVX2(t *testing.T) {
|
|||||||
PutUint64(args, 40, uint64(n))
|
PutUint64(args, 40, uint64(n))
|
||||||
|
|
||||||
_, err := k.CallFunc("wideCopyAVX2", args)
|
_, err := k.CallFunc("wideCopyAVX2", args)
|
||||||
|
runtime.KeepAlive(dst)
|
||||||
|
runtime.KeepAlive(src)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("wideCopyAVX2(n=%d): %v", n, err)
|
t.Fatalf("wideCopyAVX2(n=%d): %v", n, err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,153 @@
|
|||||||
|
// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
package verify
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestParseFuncSigExported(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
comment string
|
||||||
|
wantName string
|
||||||
|
nParams int
|
||||||
|
nResults int
|
||||||
|
}{
|
||||||
|
{"// func add(a int64, b int64) int64", "add", 2, 1},
|
||||||
|
{"// func wideCopy(dst []byte, src []byte)", "wideCopy", 2, 0},
|
||||||
|
{"// func decodeBlockAVX2(src, dst []byte) (n int, code int)", "decodeBlockAVX2", 2, 2},
|
||||||
|
{"// func analyzeO1RangeAVX2(swin []int32, dstP []uint32, hist *[32]uint16) (partSum uint64, overflow bool)", "analyzeO1RangeAVX2", 3, 2},
|
||||||
|
{"// not a func", "", 0, 0},
|
||||||
|
{"// func", "", 0, 0},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
sig, ok := ParseFuncSig(tt.comment)
|
||||||
|
if tt.wantName == "" {
|
||||||
|
if ok {
|
||||||
|
t.Errorf("ParseFuncSig(%q): expected not ok", tt.comment)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !ok {
|
||||||
|
t.Errorf("ParseFuncSig(%q): expected ok", tt.comment)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if sig.Name != tt.wantName {
|
||||||
|
t.Errorf("ParseFuncSig(%q).Name = %q, want %q", tt.comment, sig.Name, tt.wantName)
|
||||||
|
}
|
||||||
|
if len(sig.Params) != tt.nParams {
|
||||||
|
t.Errorf("ParseFuncSig(%q): %d params, want %d", tt.comment, len(sig.Params), tt.nParams)
|
||||||
|
}
|
||||||
|
if len(sig.Results) != tt.nResults {
|
||||||
|
t.Errorf("ParseFuncSig(%q): %d results, want %d", tt.comment, len(sig.Results), tt.nResults)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestExtractFuncSig(t *testing.T) {
|
||||||
|
src := `// func add(a int64, b int64) int64
|
||||||
|
TEXT ·add(SB), NOSPLIT, $0-24
|
||||||
|
|
||||||
|
// func wideCopyAVX2(dst, src []byte)
|
||||||
|
TEXT ·wideCopyAVX2(SB), NOSPLIT, $0-48
|
||||||
|
`
|
||||||
|
sig, ok := ExtractFuncSig(src, "add")
|
||||||
|
if !ok {
|
||||||
|
t.Fatal("ExtractFuncSig(add): not found")
|
||||||
|
}
|
||||||
|
if sig.Name != "add" {
|
||||||
|
t.Errorf("Name = %q, want %q", sig.Name, "add")
|
||||||
|
}
|
||||||
|
if len(sig.Params) != 2 {
|
||||||
|
t.Errorf("params = %d, want 2", len(sig.Params))
|
||||||
|
}
|
||||||
|
|
||||||
|
sig, ok = ExtractFuncSig(src, "wideCopyAVX2")
|
||||||
|
if !ok {
|
||||||
|
t.Fatal("ExtractFuncSig(wideCopyAVX2): not found")
|
||||||
|
}
|
||||||
|
if len(sig.Params) != 2 {
|
||||||
|
t.Errorf("params = %d, want 2", len(sig.Params))
|
||||||
|
}
|
||||||
|
|
||||||
|
_, ok = ExtractFuncSig(src, "nonexistent")
|
||||||
|
if ok {
|
||||||
|
t.Error("ExtractFuncSig(nonexistent): expected not found")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestArgLayout(t *testing.T) {
|
||||||
|
sig := FuncSig{
|
||||||
|
Name: "wideCopyAVX2",
|
||||||
|
Params: []Param{
|
||||||
|
{Name: "dst", Typ: "[]byte"},
|
||||||
|
{Name: "src", Typ: "[]byte"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
layout := ArgLayout(sig)
|
||||||
|
if len(layout) != 2 {
|
||||||
|
t.Fatalf("ArgLayout: %d entries, want 2", len(layout))
|
||||||
|
}
|
||||||
|
// dst: offset 0, size 24 (slice)
|
||||||
|
if layout[0].Name != "dst" || layout[0].Offset != 0 || layout[0].Size != 24 || !layout[0].IsPtr {
|
||||||
|
t.Errorf("layout[0] = %+v", layout[0])
|
||||||
|
}
|
||||||
|
// src: offset 24, size 24 (slice)
|
||||||
|
if layout[1].Name != "src" || layout[1].Offset != 24 || layout[1].Size != 24 || !layout[1].IsPtr {
|
||||||
|
t.Errorf("layout[1] = %+v", layout[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestArgLayoutMixed(t *testing.T) {
|
||||||
|
sig := FuncSig{
|
||||||
|
Name: "decodeBlockAVX2",
|
||||||
|
Params: []Param{
|
||||||
|
{Name: "src", Typ: "[]byte"},
|
||||||
|
{Name: "dst", Typ: "[]byte"},
|
||||||
|
},
|
||||||
|
Results: []Param{
|
||||||
|
{Name: "n", Typ: "int"},
|
||||||
|
{Name: "code", Typ: "int"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
layout := ArgLayout(sig)
|
||||||
|
if len(layout) != 2 {
|
||||||
|
t.Fatalf("ArgLayout: %d entries, want 2", len(layout))
|
||||||
|
}
|
||||||
|
// Two slices: 24 + 24 = 48 bytes of params.
|
||||||
|
if layout[1].Offset != 24 {
|
||||||
|
t.Errorf("src offset = %d, want 24", layout[1].Offset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParamSize(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
typ string
|
||||||
|
want int
|
||||||
|
}{
|
||||||
|
{"[]byte", 24},
|
||||||
|
{"[]int32", 24},
|
||||||
|
{"*uint16", 8},
|
||||||
|
{"*[32]uint16", 8},
|
||||||
|
{"int", 8},
|
||||||
|
{"int64", 8},
|
||||||
|
{"uint64", 8},
|
||||||
|
{"uintptr", 8},
|
||||||
|
{"int32", 4},
|
||||||
|
{"uint32", 4},
|
||||||
|
{"float32", 4},
|
||||||
|
{"int16", 2},
|
||||||
|
{"uint16", 2},
|
||||||
|
{"int8", 1},
|
||||||
|
{"uint8", 1},
|
||||||
|
{"byte", 1},
|
||||||
|
{"bool", 1},
|
||||||
|
{"string", 8}, // unknown type defaults to 8
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
if got := paramSize(tt.typ); got != tt.want {
|
||||||
|
t.Errorf("paramSize(%q) = %d, want %d", tt.typ, got, tt.want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-2
@@ -7,6 +7,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"os"
|
"os"
|
||||||
|
"runtime"
|
||||||
|
|
||||||
"sourcedock.dev/petrbalvin/gasm-devkit/asm"
|
"sourcedock.dev/petrbalvin/gasm-devkit/asm"
|
||||||
"sourcedock.dev/petrbalvin/gasm-devkit/ast"
|
"sourcedock.dev/petrbalvin/gasm-devkit/ast"
|
||||||
@@ -153,7 +154,7 @@ func (k *Kernel) FuzzFuncChecked(name string, sig funcSig, iterations int, seed
|
|||||||
if result.FirstFail == "" {
|
if result.FirstFail == "" {
|
||||||
result.FirstFail = fmt.Sprintf("iter %d: call: %v", i, err)
|
result.FirstFail = fmt.Sprintf("iter %d: call: %v", i, err)
|
||||||
}
|
}
|
||||||
releaseBufs(bufs)
|
runtime.KeepAlive(bufs)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,7 +167,7 @@ func (k *Kernel) FuzzFuncChecked(name string, sig funcSig, iterations int, seed
|
|||||||
} else {
|
} else {
|
||||||
result.Matches++
|
result.Matches++
|
||||||
}
|
}
|
||||||
releaseBufs(bufs)
|
runtime.KeepAlive(bufs)
|
||||||
}
|
}
|
||||||
|
|
||||||
if violations > 0 && result.FirstFail == "" {
|
if violations > 0 && result.FirstFail == "" {
|
||||||
|
|||||||
Reference in New Issue
Block a user