summaryrefslogtreecommitdiff
path: root/libgo/go/reflect/value.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/reflect/value.go')
-rw-r--r--libgo/go/reflect/value.go39
1 files changed, 31 insertions, 8 deletions
diff --git a/libgo/go/reflect/value.go b/libgo/go/reflect/value.go
index 15f571509b9..f8126e676d8 100644
--- a/libgo/go/reflect/value.go
+++ b/libgo/go/reflect/value.go
@@ -377,7 +377,7 @@ func (v Value) call(method string, in []Value) []Value {
if iface.itab == nil {
panic(method + " of method on nil interface value")
}
- fn = iface.itab.fun[i]
+ fn = unsafe.Pointer(&iface.itab.fun[i])
rcvr = iface.word
} else {
ut := v.typ.uncommon()
@@ -388,7 +388,7 @@ func (v Value) call(method string, in []Value) []Value {
if m.pkgPath != nil {
panic(method + " of unexported method")
}
- fn = m.tfn
+ fn = unsafe.Pointer(&m.tfn)
t = m.mtyp
rcvr = v.iword()
}
@@ -462,6 +462,10 @@ func (v Value) call(method string, in []Value) []Value {
if v.flag&flagMethod != 0 {
nin++
}
+ firstPointer := len(in) > 0 && Kind(t.In(0).(*rtype).kind) != Ptr && v.flag&flagMethod == 0 && isMethod(v.typ)
+ if v.flag&flagMethod == 0 && !firstPointer {
+ nin++
+ }
params := make([]unsafe.Pointer, nin)
off := 0
if v.flag&flagMethod != 0 {
@@ -471,7 +475,6 @@ func (v Value) call(method string, in []Value) []Value {
params[0] = unsafe.Pointer(p)
off = 1
}
- first_pointer := false
for i, pv := range in {
pv.mustBeExported()
targ := t.In(i).(*rtype)
@@ -483,14 +486,17 @@ func (v Value) call(method string, in []Value) []Value {
} else {
params[off] = pv.val
}
- if i == 0 && Kind(targ.kind) != Ptr && v.flag&flagMethod == 0 && isMethod(v.typ) {
+ if i == 0 && firstPointer {
p := new(unsafe.Pointer)
*p = params[off]
params[off] = unsafe.Pointer(p)
- first_pointer = true
}
off++
}
+ if v.flag&flagMethod == 0 && !firstPointer {
+ // Closure argument.
+ params[off] = unsafe.Pointer(&fn)
+ }
ret := make([]Value, nout)
results := make([]unsafe.Pointer, nout)
@@ -509,7 +515,7 @@ func (v Value) call(method string, in []Value) []Value {
pr = &results[0]
}
- call(t, fn, v.flag&flagMethod != 0, first_pointer, pp, pr)
+ call(t, fn, v.flag&flagMethod != 0, firstPointer, pp, pr)
return ret
}
@@ -1209,18 +1215,35 @@ func (v Value) OverflowUint(x uint64) bool {
// code using reflect cannot obtain unsafe.Pointers
// without importing the unsafe package explicitly.
// It panics if v's Kind is not Chan, Func, Map, Ptr, Slice, or UnsafePointer.
+//
+// If v's Kind is Func, the returned pointer is an underlying
+// code pointer, but not necessarily enough to identify a
+// single function uniquely. The only guarantee is that the
+// result is zero if and only if v is a nil func Value.
func (v Value) Pointer() uintptr {
k := v.kind()
switch k {
- case Chan, Func, Map, Ptr, UnsafePointer:
- if k == Func && v.flag&flagMethod != 0 {
+ case Chan, Map, Ptr, UnsafePointer:
+ p := v.val
+ if v.flag&flagIndir != 0 {
+ p = *(*unsafe.Pointer)(p)
+ }
+ return uintptr(p)
+ case Func:
+ if v.flag&flagMethod != 0 {
panic("reflect.Value.Pointer of method Value")
}
p := v.val
if v.flag&flagIndir != 0 {
p = *(*unsafe.Pointer)(p)
}
+ // Non-nil func value points at data block.
+ // First word of data block is actual code.
+ if p != nil {
+ p = *(*unsafe.Pointer)(p)
+ }
return uintptr(p)
+
case Slice:
return (*SliceHeader)(v.val).Data
}