aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2020-02-09 12:02:37 +0200
committerDmitry Vyukov <dvyukov@google.com>2020-02-09 14:09:19 +0200
commiteb99c7d3da996d1a1dabd18aea6781262648dadb (patch)
tree085dc11b39771626c09e06fbd52f52fdfdfaff3f
parent4f453297df90dffc5b5b76efcea073604b32ed02 (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.go20
-rw-r--r--prog/mutation_test.go18
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{}