]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/link: remove special cases for Method() and MethodByName().
authorDominique Lefevre <domingolefevre@gmail.com>
Thu, 24 Aug 2023 07:17:20 +0000 (10:17 +0300)
committerCherry Mui <cherryyz@google.com>
Fri, 1 Sep 2023 15:07:16 +0000 (15:07 +0000)
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>
src/cmd/link/internal/ld/deadcode.go

index c68756587855327779852a7ab823153a9e94c78f..2ef9de4d0edfa5bad1895ed3af1e5ea3a31bbbcc 100644 (file)
@@ -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