From: Dominique Lefevre Date: Thu, 24 Aug 2023 07:17:20 +0000 (+0300) Subject: cmd/link: remove special cases for Method() and MethodByName(). X-Git-Tag: go1.22rc1~1016 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=6b52bfa393a7f8942568e7a29816c673ff73f797;p=gostls13.git cmd/link: remove special cases for Method() and MethodByName(). There is no more need to do this in the linker. The compiler now handles both Type.Method() and Value.Method(), and flags their users as ReflectMethod. Change-Id: Ice93d5d975a1b93a324471e8abdebdce141d17d0 Reviewed-on: https://go-review.googlesource.com/c/go/+/522437 Run-TryBot: Cherry Mui Reviewed-by: Joedian Reid TryBot-Result: Gopher Robot Reviewed-by: Cherry Mui --- diff --git a/src/cmd/link/internal/ld/deadcode.go b/src/cmd/link/internal/ld/deadcode.go index c687565878..2ef9de4d0e 100644 --- a/src/cmd/link/internal/ld/deadcode.go +++ b/src/cmd/link/internal/ld/deadcode.go @@ -123,6 +123,8 @@ func (d *deadcodePass) flood() { for !d.wq.empty() { symIdx := d.wq.pop() + // Methods may be called via reflection. Give up on static analysis, + // and mark all exported methods of all reachable types as reachable. d.reflectSeen = d.reflectSeen || d.ldr.IsReflectMethod(symIdx) isgotype := d.ldr.IsGoType(symIdx) @@ -391,13 +393,20 @@ func (d *deadcodePass) markMethod(m methodref) { // against the interface method signatures, if it matches it is marked // as reachable. This is extremely conservative, but easy and correct. // -// The third case is handled by looking to see if any of: -// - reflect.Value.Method or MethodByName is reachable -// - reflect.Type.Method or MethodByName is called (through the -// REFLECTMETHOD attribute marked by the compiler). +// The third case is handled by looking for functions that compiler flagged +// as REFLECTMETHOD. REFLECTMETHOD on a function F means that F does a method +// lookup with reflection, but the compiler was not able to statically determine +// the method name. // -// If any of these happen, all bets are off and all exported methods -// of reachable types are marked reachable. +// All functions that call reflect.Value.Method or reflect.Type.Method are REFLECTMETHODs. +// Functions that call reflect.Value.MethodByName or reflect.Type.MethodByName with +// a non-constant argument are REFLECTMETHODs, too. If we find a REFLECTMETHOD, +// we give up on static analysis, and mark all exported methods of all reachable +// types as reachable. +// +// If the argument to MethodByName is a compile-time constant, the compiler +// emits a relocation with the method name. Matching methods are kept in all +// reachable types. // // Any unreached text symbols are removed from ctxt.Textp. func deadcode(ctxt *Link) { @@ -406,9 +415,6 @@ func deadcode(ctxt *Link) { d.init() d.flood() - methSym := ldr.Lookup("reflect.Value.Method", abiInternalVer) - methByNameSym := ldr.Lookup("reflect.Value.MethodByName", abiInternalVer) - if ctxt.DynlinkingGo() { // Exported methods may satisfy interfaces we don't know // about yet when dynamically linking. @@ -416,11 +422,6 @@ func deadcode(ctxt *Link) { } for { - // Methods might be called via reflection. Give up on - // static analysis, mark all exported methods of - // all reachable types as reachable. - d.reflectSeen = d.reflectSeen || (methSym != 0 && ldr.AttrReachable(methSym)) || (methByNameSym != 0 && ldr.AttrReachable(methByNameSym)) - // Mark all methods that could satisfy a discovered // interface as reachable. We recheck old marked interfaces // as new types (with new methods) may have been discovered