From 07faf8fab55d74ef6108e56b9e0ccee3e62b0a2d Mon Sep 17 00:00:00 2001 From: Dominique Lefevre Date: Thu, 24 Aug 2023 10:14:54 +0300 Subject: [PATCH] cmd/compile: do not flag reflect.StructOf() as a ReflectMethod. StructOf() calls reflect.Type.Method(), but looks up only methods accessible via interfaces. DCE does not remove such methods, so there is no need to disable the DCE if StructOf() is used. There is a dependency chain between struct rtype and StructOf(): (*rtype).Method() -> FuncOf() -> initFuncTypes() -> StructOf(). Thus, any use of (*rtype).Method() or (*rtype).MethodByName() disables the DCE in the linker. This is not an issue just yet because all users of Method() and MethodByName() are flagged as ReflectMethods. A subsequent patch avoids this flag on callers of MethodByName(string literal). When that patch is applied, it becomes important to have no ReflectMethods down the call chain of MethodByName(). Change-Id: I9b3e55c495c122ed70ef31f9d978c0e2e0573799 Reviewed-on: https://go-review.googlesource.com/c/go/+/522435 Reviewed-by: Cherry Mui Reviewed-by: Joedian Reid TryBot-Result: Gopher Robot Run-TryBot: Cherry Mui --- src/cmd/compile/internal/walk/expr.go | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/walk/expr.go b/src/cmd/compile/internal/walk/expr.go index 4b83773932..b4179dddb1 100644 --- a/src/cmd/compile/internal/walk/expr.go +++ b/src/cmd/compile/internal/walk/expr.go @@ -951,8 +951,17 @@ func usemethod(n *ir.CallExpr) { // Those functions may be alive via the itab, which should not cause all methods // alive. We only want to mark their callers. if base.Ctxt.Pkgpath == "reflect" { - switch ir.CurFunc.Nname.Sym().Name { // TODO: is there a better way than hardcoding the names? - case "(*rtype).Method", "(*rtype).MethodByName", "(*interfaceType).Method", "(*interfaceType).MethodByName": + // TODO: is there a better way than hardcoding the names? + switch fn := ir.CurFunc.Nname.Sym().Name; { + case fn == "(*rtype).Method", fn == "(*rtype).MethodByName": + return + case fn == "(*interfaceType).Method", fn == "(*interfaceType).MethodByName": + return + // StructOf defines closures that look up methods. They only look up methods + // reachable via interfaces. The DCE does not remove such methods. It is ok + // to not flag closures in StructOf as ReflectMethods and let the DCE run + // even if StructOf is reachable. + case strings.HasPrefix(fn, "StructOf.func"): return } } -- 2.50.0