Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Dead code elimination using golang.org/x/tools/go/pointer #1183

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
nevkontakte opened this issue Jan 15, 2023 · 0 comments
Open

Dead code elimination using golang.org/x/tools/go/pointer #1183

nevkontakte opened this issue Jan 15, 2023 · 0 comments
Labels
enhancement NeedsHelp Community contributions are welcome for this feature!

Comments

@nevkontakte
Copy link
Member

GopherJS implements a basic form of DCE (dead code elimination), however it is known to be over-conservative. In the recent years a few packages emerged that should be able to build a more accurate call graph for a Go program, which also means better detection of the dead code. Notably there are several such packages under https://pkg.go.dev/golang.org/x/[email protected]/go/callgraph and there is also https://pkg.go.dev/golang.org/x/tools/go/pointer. The latter seems to be most interesting, since it claims to model use of reflection to a certain extent, so it should in theory be the most accurate of them.

I think GopherJS could use this to address #136 and eliminate more dead code. It may contribute a considerable increase to the compilation time, but may be worth it in the end. The main challenge is that this algorithm requires SSA of the complete program, so it can't be done incrementally on per-package basis. I haven't tried to prototype this myself, but I think an implementation would look roughly like this:

  1. Archive type should include all sources that were compiled into it (after with augmentations already applied). Since there is no easy way to serialize already parsed AST, we will have to format it into source code and re-parse it later.
  2. In the WriteProgramCode function we have a list of all Archives that represent a program we've built. We extract sources bundles in the Archives, parse, type-check them and construct SSA representation. We will have to use ssa.Program.CreatePackage method to do that, since we are not loading sources from the file system.
  3. Then we build a complete call graph of the program using https://pkg.go.dev/golang.org/x/tools/go/pointer#Analyze. An example of how to do that can be found in https://pkg.go.dev/golang.org/x/[email protected]/cmd/callgraph.
  4. Finally, convert the call graph into the dceSelection := make(map[*Decl]struct{}) map, which can be passed down to the WritePkgCode function.

If the analysis is precise as it claims to be, we might have some significant output size reductions. A few possible gotchas we'll likely have to work around:

  • I don't think the package understands //go:linkname directives (or maybe the SSA package does?), we'll have to do something about that.
  • I'm pretty sure the algorithm will miss some calls in the end. We will have to provide a custom //gopherjs:keep-alive directive to forcibly mark such functions reachable.
@nevkontakte nevkontakte added the NeedsHelp Community contributions are welcome for this feature! label Jan 15, 2023
@nevkontakte nevkontakte added this to the Output size reduction milestone Jan 15, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement NeedsHelp Community contributions are welcome for this feature!
Projects
None yet
Development

No branches or pull requests

1 participant