aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/internal
diff options
context:
space:
mode:
authorMartin Möhrmann <moehrmann@google.com>2018-01-27 11:55:34 +0100
committerMartin Möhrmann <moehrmann@google.com>2018-10-15 17:58:06 +0000
commitc9130cae9a9cd59178e842851f3f30b1d97ab0bd (patch)
tree1c39f76c8b36dc646d7de76300065663daf67c86 /src/runtime/internal
parent240a30da1b3f5d4d60640a09f135275e8fee8b92 (diff)
downloadgo-c9130cae9a9cd59178e842851f3f30b1d97ab0bd.tar.gz
go-c9130cae9a9cd59178e842851f3f30b1d97ab0bd.zip
runtime/internal/math: add multiplication with overflow check
This CL adds a new internal math package for use by the runtime. The new package exports a MulUintptr function with uintptr arguments a and b and returns uintptr(a*b) and whether the full-width product x*y does overflow the uintptr value range (uintptr(x*y) != x*y). Uses of MulUinptr in the runtime and intrinsics for performance will be added in followup CLs. Updates #21588 Change-Id: Ia5a02eeabc955249118e4edf68c67d9fc0858058 Reviewed-on: https://go-review.googlesource.com/c/91755 Run-TryBot: Martin Möhrmann <moehrmann@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org>
Diffstat (limited to 'src/runtime/internal')
-rw-r--r--src/runtime/internal/math/math.go19
-rw-r--r--src/runtime/internal/math/math_test.go51
2 files changed, 70 insertions, 0 deletions
diff --git a/src/runtime/internal/math/math.go b/src/runtime/internal/math/math.go
new file mode 100644
index 0000000000..5385f5dd86
--- /dev/null
+++ b/src/runtime/internal/math/math.go
@@ -0,0 +1,19 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package math
+
+import "runtime/internal/sys"
+
+const MaxUintptr = ^uintptr(0)
+
+// MulUintptr returns a * b and whether the multiplication overflowed.
+// On supported platforms this is an intrinsic lowered by the compiler.
+func MulUintptr(a, b uintptr) (uintptr, bool) {
+ if a|b < 1<<(4*sys.PtrSize) || a == 0 {
+ return a * b, false
+ }
+ overflow := b > MaxUintptr/a
+ return a * b, overflow
+}
diff --git a/src/runtime/internal/math/math_test.go b/src/runtime/internal/math/math_test.go
new file mode 100644
index 0000000000..9447bd23f9
--- /dev/null
+++ b/src/runtime/internal/math/math_test.go
@@ -0,0 +1,51 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package math_test
+
+import (
+ . "runtime/internal/math"
+ "testing"
+)
+
+const (
+ UintptrSize = 32 << (^uintptr(0) >> 63)
+)
+
+type mulUintptrTest struct {
+ a uintptr
+ b uintptr
+ overflow bool
+}
+
+var mulUintptrTests = []mulUintptrTest{
+ {0, 0, false},
+ {1000, 1000, false},
+ {MaxUintptr, 0, false},
+ {MaxUintptr, 1, false},
+ {MaxUintptr / 2, 2, false},
+ {MaxUintptr / 2, 3, true},
+ {MaxUintptr, 10, true},
+ {MaxUintptr, 100, true},
+ {MaxUintptr / 100, 100, false},
+ {MaxUintptr / 1000, 1001, true},
+ {1<<(UintptrSize/2) - 1, 1<<(UintptrSize/2) - 1, false},
+ {1 << (UintptrSize / 2), 1 << (UintptrSize / 2), true},
+ {MaxUintptr >> 32, MaxUintptr >> 32, false},
+ {MaxUintptr, MaxUintptr, true},
+}
+
+func TestMulUintptr(t *testing.T) {
+ for _, test := range mulUintptrTests {
+ a, b := test.a, test.b
+ for i := 0; i < 2; i++ {
+ mul, overflow := MulUintptr(a, b)
+ if mul != a*b || overflow != test.overflow {
+ t.Errorf("MulUintptr(%v, %v) = %v, %v want %v, %v",
+ a, b, mul, overflow, a*b, test.overflow)
+ }
+ a, b = b, a
+ }
+ }
+}