diff --git a/libgo/go/reflect/all_test.go b/libgo/go/reflect/all_test.go index f888d648c19..3e107795bdf 100644 --- a/libgo/go/reflect/all_test.go +++ b/libgo/go/reflect/all_test.go @@ -1543,7 +1543,17 @@ func TestMakeFuncVariadic(t *testing.T) { fv := MakeFunc(TypeOf(fn), func(in []Value) []Value { return in[1:2] }) ValueOf(&fn).Elem().Set(fv) - r := fv.Call([]Value{ValueOf(1), ValueOf(2), ValueOf(3)})[0].Interface().([]int) + r := fn(1, 2, 3) + if r[0] != 2 || r[1] != 3 { + t.Errorf("Call returned [%v, %v]; want 2, 3", r[0], r[1]) + } + + r = fn(1, []int{2, 3}...) + if r[0] != 2 || r[1] != 3 { + t.Errorf("Call returned [%v, %v]; want 2, 3", r[0], r[1]) + } + + r = fv.Call([]Value{ValueOf(1), ValueOf(2), ValueOf(3)})[0].Interface().([]int) if r[0] != 2 || r[1] != 3 { t.Errorf("Call returned [%v, %v]; want 2, 3", r[0], r[1]) } @@ -1552,6 +1562,17 @@ func TestMakeFuncVariadic(t *testing.T) { if r[0] != 2 || r[1] != 3 { t.Errorf("Call returned [%v, %v]; want 2, 3", r[0], r[1]) } + + f := fv.Interface().(func(int, ...int) []int) + + r = f(1, 2, 3) + if r[0] != 2 || r[1] != 3 { + t.Errorf("Call returned [%v, %v]; want 2, 3", r[0], r[1]) + } + r = f(1, []int{2, 3}...) + if r[0] != 2 || r[1] != 3 { + t.Errorf("Call returned [%v, %v]; want 2, 3", r[0], r[1]) + } } type Point struct { @@ -1569,6 +1590,24 @@ func (p Point) Dist(scale int) int { return p.x*p.x*scale + p.y*p.y*scale } +// This will be index 2. +func (p Point) GCMethod(k int) int { + runtime.GC() + return k + p.x +} + +// This will be index 3. +func (p Point) TotalDist(points ...Point) int { + tot := 0 + for _, q := range points { + dx := q.x - p.x + dy := q.y - p.y + tot += dx*dx + dy*dy // Should call Sqrt, but it's just a test. + + } + return tot +} + func TestMethod(t *testing.T) { // Non-curried method of type. p := Point{3, 4} @@ -1751,6 +1790,37 @@ func TestMethodValue(t *testing.T) { } } +func TestVariadicMethodValue(t *testing.T) { + p := Point{3, 4} + points := []Point{{20, 21}, {22, 23}, {24, 25}} + want := int64(p.TotalDist(points[0], points[1], points[2])) + + // Curried method of value. + tfunc := TypeOf((func(...Point) int)(nil)) + v := ValueOf(p).Method(3) + if tt := v.Type(); tt != tfunc { + t.Errorf("Variadic Method Type is %s; want %s", tt, tfunc) + } + i := ValueOf(v.Interface()).Call([]Value{ValueOf(points[0]), ValueOf(points[1]), ValueOf(points[2])})[0].Int() + if i != want { + t.Errorf("Variadic Method returned %d; want %d", i, want) + } + i = ValueOf(v.Interface()).CallSlice([]Value{ValueOf(points)})[0].Int() + if i != want { + t.Errorf("Variadic Method CallSlice returned %d; want %d", i, want) + } + + f := v.Interface().(func(...Point) int) + i = int64(f(points[0], points[1], points[2])) + if i != want { + t.Errorf("Variadic Method Interface returned %d; want %d", i, want) + } + i = int64(f(points...)) + if i != want { + t.Errorf("Variadic Method Interface Slice returned %d; want %d", i, want) + } +} + // Reflect version of $GOROOT/test/method5.go // Concrete types implementing M method. @@ -3718,11 +3788,6 @@ func TestReflectFuncTraceback(t *testing.T) { f.Call([]Value{}) } -func (p Point) GCMethod(k int) int { - runtime.GC() - return k + p.x -} - func TestReflectMethodTraceback(t *testing.T) { p := Point{3, 4} m := ValueOf(p).MethodByName("GCMethod") diff --git a/libgo/go/reflect/makefunc.go b/libgo/go/reflect/makefunc.go index 736ac36ade7..977aacfd438 100644 --- a/libgo/go/reflect/makefunc.go +++ b/libgo/go/reflect/makefunc.go @@ -117,29 +117,21 @@ func makeMethodValue(op string, v Value) Value { ftyp := (*funcType)(unsafe.Pointer(t)) method := int(v.flag) >> flagMethodShift - var code uintptr - var ffi *ffiData + fv := &makeFuncImpl{ + typ: ftyp, + method: method, + rcvr: rcvr, + } + switch runtime.GOARCH { case "amd64", "386": // Indirect Go func value (dummy) to obtain actual // code address. (A Go func value is a pointer to a C // function pointer. http://golang.org/s/go11func.) dummy := makeFuncStub - code = **(**uintptr)(unsafe.Pointer(&dummy)) + fv.code = **(**uintptr)(unsafe.Pointer(&dummy)) default: - code, ffi = makeFuncFFI(ftyp, - func(in []Value) []Value { - m := rcvr.Method(method) - return m.Call(in) - }) - } - - fv := &makeFuncImpl{ - code: code, - typ: ftyp, - method: method, - rcvr: rcvr, - ffi: ffi, + fv.code, fv.ffi = makeFuncFFI(ftyp, fv.call) } return Value{ft, unsafe.Pointer(&fv), v.flag&flagRO | flag(Func)<