Skip to content
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

Rewrite LocalSplitter #841

Merged
merged 24 commits into from
Feb 8, 2024
Merged

Rewrite LocalSplitter #841

merged 24 commits into from
Feb 8, 2024

Conversation

Timbals
Copy link
Contributor

@Timbals Timbals commented Feb 7, 2024

This PR rewrites the LocalSplitter to use a simpler algorithm.

The algorithm uses a disjoint set to find any definitions for locals that can't be split because they have overlapping uses.
Then it splits the locals by modifying the statements in the graph.

I also did some easy performance optimization. Running the LocalSplitter over the entire Java Runtime Library (roughly 200_000 methods of varying length and complexity) takes around 10 seconds on my machine. That seems adequate for now.
There is definitely more room for optimization here (potential for caching results, reduce the amount of hashing done, reduce the amount of expensive indexOf calls).

Closes #798
Fixes the problems with the LocalSplitter from #716

- use `graph.getNodes()` instead of `builder.getStmts()` because the linearized ordering is not important for the `LocalSplitter` (it uses `successors`/`exceptionalSuccessors` to step through the statements)
- exit early when there is only one assignment or when the local can't be split
- use a stack instead of a queue (iteration order makes no difference)
- only search through all statements for definitions once instead of repeating it for every local

Potential speedups still remaining:
- Calls to `successors` use `indexOf` which can be slow; this only affects cases where there are thousands of statements without any control flow and heavy re-use of locals
- `getUses`, `getDefs` and `getUsesAndDefs` show up in the profiler; these could probably be cached
- Most of the time is spent hashing. There are ways to improve this.
Previously used `getNodes` instead of `getStmts` for a small performance improvement. This unintentionally made the naming of locals non-deterministic.
@Timbals Timbals marked this pull request as ready for review February 8, 2024 15:25
Copy link

codecov bot commented Feb 8, 2024

Codecov Report

Attention: 7 lines in your changes are missing coverage. Please review.

Comparison is base (84b98b6) 63.74% compared to head (3cd6721) 64.04%.

Files Patch % Lines
...otup/java/bytecode/interceptors/LocalSplitter.java 93.06% 1 Missing and 6 partials ⚠️
Additional details and impacted files
@@              Coverage Diff              @@
##             develop     #841      +/-   ##
=============================================
+ Coverage      63.74%   64.04%   +0.30%     
- Complexity      3417     3421       +4     
=============================================
  Files            312      312              
  Lines          15086    15045      -41     
  Branches        2559     2542      -17     
=============================================
+ Hits            9616     9636      +20     
+ Misses          4557     4502      -55     
+ Partials         913      907       -6     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Collaborator

@swissiety swissiety left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good job!

@swissiety swissiety merged commit 141ed9b into soot-oss:develop Feb 8, 2024
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Fix LocalSplitter
3 participants