diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2020-02-09 12:02:37 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2020-02-09 14:09:19 +0200 |
| commit | eb99c7d3da996d1a1dabd18aea6781262648dadb (patch) | |
| tree | 085dc11b39771626c09e06fbd52f52fdfdfaff3f | |
| parent | 4f453297df90dffc5b5b76efcea073604b32ed02 (diff) | |
prog: remove use of unsafe
Unsafe is, well, unsafe.
Plus it fails under the new checkptr mode in go1.14.
Remove use of unsafe.
No statistically significant change in performance:
name old time/op new time/op delta
StoreLoadInt-8 21.2ns ± 5% 21.6ns ± 9% ~ (p=0.136 n=20+20)
| -rw-r--r-- | prog/mutation.go | 20 | ||||
| -rw-r--r-- | prog/mutation_test.go | 18 |
2 files changed, 27 insertions, 11 deletions
diff --git a/prog/mutation.go b/prog/mutation.go index f70a62cbe..b50f48803 100644 --- a/prog/mutation.go +++ b/prog/mutation.go @@ -4,11 +4,11 @@ package prog import ( + "encoding/binary" "fmt" "math" "math/rand" "sort" - "unsafe" ) // Maximum length of generated binary blobs inserted into the program. @@ -840,32 +840,30 @@ func swapInt(v uint64, size int) uint64 { } func loadInt(data []byte, size int) uint64 { - p := unsafe.Pointer(&data[0]) switch size { case 1: - return uint64(*(*uint8)(p)) + return uint64(data[0]) case 2: - return uint64(*(*uint16)(p)) + return uint64(binary.LittleEndian.Uint16(data)) case 4: - return uint64(*(*uint32)(p)) + return uint64(binary.LittleEndian.Uint32(data)) case 8: - return *(*uint64)(p) + return binary.LittleEndian.Uint64(data) default: panic(fmt.Sprintf("loadInt: bad size %v", size)) } } func storeInt(data []byte, v uint64, size int) { - p := unsafe.Pointer(&data[0]) switch size { case 1: - *(*uint8)(p) = uint8(v) + data[0] = uint8(v) case 2: - *(*uint16)(p) = uint16(v) + binary.LittleEndian.PutUint16(data, uint16(v)) case 4: - *(*uint32)(p) = uint32(v) + binary.LittleEndian.PutUint32(data, uint32(v)) case 8: - *(*uint64)(p) = v + binary.LittleEndian.PutUint64(data, v) default: panic(fmt.Sprintf("storeInt: bad size %v", size)) } diff --git a/prog/mutation_test.go b/prog/mutation_test.go index 76812df2a..89fe5473a 100644 --- a/prog/mutation_test.go +++ b/prog/mutation_test.go @@ -494,3 +494,21 @@ func buildTestContext(test [2]string, target *Target) (rs rand.Source, ct *Choic rs = rand.NewSource(0) return } + +func BenchmarkStoreLoadInt(b *testing.B) { + // To get unaligned data on heap (compiler manages to align it on stack). + data := make([]byte, 9) + sink = data + data = sink.([]byte)[1:] + for i := 0; i < b.N; i++ { + for size := 1; size <= 8; size *= 2 { + storeInt(data, uint64(i), size) + v := loadInt(data, size) + if uint8(v) != uint8(i) { + panic("bad") + } + } + } +} + +var sink interface{} |
