aboutsummaryrefslogtreecommitdiff
path: root/libgo/go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go')
-rw-r--r--libgo/go/reflect/all_test.go77
-rw-r--r--libgo/go/reflect/makefunc.go59
2 files changed, 97 insertions, 39 deletions
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)<<flagKindShift | flagIndir}
@@ -160,28 +152,21 @@ func makeValueMethod(v Value) Value {
t := typ.common()
ftyp := (*funcType)(unsafe.Pointer(t))
- var code uintptr
- var ffi *ffiData
+ impl := &makeFuncImpl{
+ typ: ftyp,
+ method: -2,
+ rcvr: v,
+ }
+
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))
+ impl.code = **(**uintptr)(unsafe.Pointer(&dummy))
default:
- code, ffi = makeFuncFFI(ftyp,
- func(in []Value) []Value {
- return v.Call(in)
- })
- }
-
- impl := &makeFuncImpl{
- code: code,
- typ: ftyp,
- method: -2,
- rcvr: v,
- ffi: ffi,
+ impl.code, impl.ffi = makeFuncFFI(ftyp, impl.call)
}
return Value{t, unsafe.Pointer(&impl), flag(Func<<flagKindShift) | flagIndir}
@@ -192,9 +177,17 @@ func (c *makeFuncImpl) call(in []Value) []Value {
if c.method == -1 {
return c.fn(in)
} else if c.method == -2 {
- return c.rcvr.Call(in)
+ if c.typ.IsVariadic() {
+ return c.rcvr.CallSlice(in)
+ } else {
+ return c.rcvr.Call(in)
+ }
} else {
m := c.rcvr.Method(c.method)
- return m.Call(in)
+ if c.typ.IsVariadic() {
+ return m.CallSlice(in)
+ } else {
+ return m.Call(in)
+ }
}
}