diff options
| author | Dominique Lefevre <domingolefevre@gmail.com> | 2023-08-24 10:17:20 +0300 |
|---|---|---|
| committer | Cherry Mui <cherryyz@google.com> | 2023-09-01 15:07:16 +0000 |
| commit | 6b52bfa393a7f8942568e7a29816c673ff73f797 (patch) | |
| tree | 1c89172c6f2880cbb9e8038c676a9c02a9565878 /src | |
| parent | e802f211b0d3f9dac5c4ca56c9f83df0cb745070 (diff) | |
| download | go-6b52bfa393a7f8942568e7a29816c673ff73f797.tar.xz | |
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 <cherryyz@google.com>
Reviewed-by: Joedian Reid <joedian@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Diffstat (limited to 'src')
| -rw-r--r-- | src/cmd/link/internal/ld/deadcode.go | 29 |
1 files changed, 15 insertions, 14 deletions
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 |
