summaryrefslogtreecommitdiff
path: root/libgo/go/reflect
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2017-01-23 22:18:42 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2017-01-23 22:18:42 +0000
commitc25edd44a04672573946138da9c8fdc8c0eef5fd (patch)
tree843ee0b88a49a9a81be51f8853f88eb3c11256b1 /libgo/go/reflect
parent28826a66fb457b6655d66a40638a759617aa8673 (diff)
libgo: update to go1.8rc2
Fix a bug in the generation of the hash value in reflect.FuncOf. The merge script missed a bunch of testdata files over the years. Copy them over. Reviewed-on: https://go-review.googlesource.com/35570 From-SVN: r244835
Diffstat (limited to 'libgo/go/reflect')
-rw-r--r--libgo/go/reflect/all_test.go68
-rw-r--r--libgo/go/reflect/type.go3
2 files changed, 70 insertions, 1 deletions
diff --git a/libgo/go/reflect/all_test.go b/libgo/go/reflect/all_test.go
index f51e95fd734..6b143df00e1 100644
--- a/libgo/go/reflect/all_test.go
+++ b/libgo/go/reflect/all_test.go
@@ -26,6 +26,8 @@ import (
"unsafe"
)
+var sink interface{}
+
func TestBool(t *testing.T) {
v := ValueOf(true)
if v.Bool() != true {
@@ -5348,6 +5350,72 @@ func TestCallGC(t *testing.T) {
f2("four", "five5", "six666", "seven77", "eight888")
}
+// Issue 18635 (function version).
+func TestKeepFuncLive(t *testing.T) {
+ // Test that we keep makeFuncImpl live as long as it is
+ // referenced on the stack.
+ typ := TypeOf(func(i int) {})
+ var f, g func(in []Value) []Value
+ f = func(in []Value) []Value {
+ clobber()
+ i := int(in[0].Int())
+ if i > 0 {
+ // We can't use Value.Call here because
+ // runtime.call* will keep the makeFuncImpl
+ // alive. However, by converting it to an
+ // interface value and calling that,
+ // reflect.callReflect is the only thing that
+ // can keep the makeFuncImpl live.
+ //
+ // Alternate between f and g so that if we do
+ // reuse the memory prematurely it's more
+ // likely to get obviously corrupted.
+ MakeFunc(typ, g).Interface().(func(i int))(i - 1)
+ }
+ return nil
+ }
+ g = func(in []Value) []Value {
+ clobber()
+ i := int(in[0].Int())
+ MakeFunc(typ, f).Interface().(func(i int))(i)
+ return nil
+ }
+ MakeFunc(typ, f).Call([]Value{ValueOf(10)})
+}
+
+// Issue 18635 (method version).
+type KeepMethodLive struct{}
+
+func (k KeepMethodLive) Method1(i int) {
+ clobber()
+ if i > 0 {
+ ValueOf(k).MethodByName("Method2").Interface().(func(i int))(i - 1)
+ }
+}
+
+func (k KeepMethodLive) Method2(i int) {
+ clobber()
+ ValueOf(k).MethodByName("Method1").Interface().(func(i int))(i)
+}
+
+func TestKeepMethodLive(t *testing.T) {
+ // Test that we keep methodValue live as long as it is
+ // referenced on the stack.
+ KeepMethodLive{}.Method1(10)
+}
+
+// clobber tries to clobber unreachable memory.
+func clobber() {
+ runtime.GC()
+ for i := 1; i < 32; i++ {
+ for j := 0; j < 10; j++ {
+ obj := make([]*byte, i)
+ sink = obj
+ }
+ }
+ runtime.GC()
+}
+
type funcLayoutTest struct {
rcvr, t Type
size, argsize, retOffset uintptr
diff --git a/libgo/go/reflect/type.go b/libgo/go/reflect/type.go
index 07a355d5e41..29d89f7176d 100644
--- a/libgo/go/reflect/type.go
+++ b/libgo/go/reflect/type.go
@@ -1677,7 +1677,7 @@ func FuncOf(in, out []Type, variadic bool) Type {
*ft = *prototype
// Build a hash and minimally populate ft.
- var hash uint32 = 8
+ var hash uint32
var fin, fout []*rtype
shift := uint(1)
for _, in := range in {
@@ -1697,6 +1697,7 @@ func FuncOf(in, out []Type, variadic bool) Type {
hash++
}
hash <<= 4
+ hash += 8
ft.hash = hash
ft.in = fin
ft.out = fout