From 114c6bd6fc877756a4adad3ce8a1d359683ef624 Mon Sep 17 00:00:00 2001 From: visualfc Date: Wed, 18 Dec 2024 09:57:58 +0800 Subject: [PATCH] internal/lib/reflect: fix call method --- runtime/internal/lib/reflect/value.go | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/runtime/internal/lib/reflect/value.go b/runtime/internal/lib/reflect/value.go index 4e63cdfd..25314ec4 100644 --- a/runtime/internal/lib/reflect/value.go +++ b/runtime/internal/lib/reflect/value.go @@ -2213,11 +2213,9 @@ func (v Value) call(op string, in []Value) (out []Value) { tin = append([]*abi.Type{rcvrtype}, ft.In...) tout = ft.Out ioff = 1 - if v.flag&flagIndir != 0 { - args = append(args, v.ptr) - } else { - args = append(args, unsafe.Pointer(&v.ptr)) - } + var ptr unsafe.Pointer + storeRcvr(v, unsafe.Pointer(&ptr)) + args = append(args, unsafe.Pointer(&ptr)) } else { if v.flag&flagIndir != 0 { fn = *(*unsafe.Pointer)(v.ptr) @@ -2314,6 +2312,23 @@ func (v Value) call(op string, in []Value) (out []Value) { return } +// v is a method receiver. Store at p the word which is used to +// encode that receiver at the start of the argument list. +// Reflect uses the "interface" calling convention for +// methods, which always uses one word to record the receiver. +func storeRcvr(v Value, p unsafe.Pointer) { + t := v.typ() + if t.Kind() == abi.Interface { + // the interface data word becomes the receiver word + iface := (*nonEmptyInterface)(v.ptr) + *(*unsafe.Pointer)(p) = iface.word + } else if v.flag&flagIndir != 0 && !ifaceIndir(t) { + *(*unsafe.Pointer)(p) = *(*unsafe.Pointer)(v.ptr) + } else { + *(*unsafe.Pointer)(p) = v.ptr + } +} + var stringType = rtypeOf("") // MapIndex returns the value associated with key in the map v.