Prevent FieldAccessExpr in Elimination - #13
Open
leslieyip02 wants to merge 4 commits into
Open
leslieyip02 wants to merge 4 commits into
leslieyip02 wants to merge 4 commits into
Conversation
- Renamed variables and function names to improve readability. - Reduced nesting by wrapping logic into helper functions. - Separated data flow graph building into a private helper class. - Added unit tests to verify behavior.
Add a check in copyOperation to avoid duplicating existing values. For stack rearrangment instructions like DUP, new values are not created so performing the copy just creates extra variables aliases unnecessarily.
When decompiling an expression, check if the expression is a redundant assignment (e.g. x = x). We don't need to create statements in such cases.
Improve expression elimination logic. Previously, Elimination would onyl prune dead NamedExpr. This led to some expressions being pruned even though they were still used. Furthermore, this also doesn't consider the side effects of calling the RHS of an assignment. Added a `canDiscard` function which decides whether or not an expression can be discarded more conservatively. Added test cases to verify behaviors.
leslieyip02
force-pushed
the
refactor/elimination
branch
from
September 11, 2026 05:50
715d42c to
4fb8149
Compare
FieldAccessExpr eliminationFieldAccessExpr in Elimination
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fix decompilation of field updates by avoiding artificial SSA aliases, removing redundant self-assignments, and making expression elimination conservative about side effects and exceptions.
Bug
Given:
Jade previously produced:
Both
copyVar3_1andinsnVar6were undeclared.There were two underlying causes:
1. Duplicated variables
JVM stack rearrangement instructions such as DUP created new SSA copy variables even though they only duplicate or move an existing value. This results in extra copies of variables:
Jade assigns
insnVar4 = copyVar3_2.value, but then also assignscopyVar3_1.value = insnVar6. Thethisvariable was duplicated even though we are still referring to the samethis.2. Elimination was too aggressive
Elimination retains field assignments but do not mark its receiver and value as live, allowing their declarations to be removed.
jade/src/main/kotlin/org/ucombinator/jade/decompile/Elimination.kt
Lines 174 to 186 in 844706a
In the logic, only
NameExpris preserved. In theFooexample above, there is aFieldAccessExpr(i.e.this.value) which was incorrectly eliminated. It also does not account for the fact that the RHS of the assignment could cause side effects. Consider:{ int x = foo(); return; }Even though
xis unused,foocould cause side effects that we want to keep.A
canDiscardmethod has been added which is more conservative in deciding what can be discarded.Result
After the fixes, the decompiled output is:
This is certainly more verbose, but it compiles and seems to be correct. This can be optimized in the future.
insnVar4is unused becauseFieldAccessExpris currently propagated like a constant. However, elimination keeps the original field access statement because field access may have side effects or throw an exception (e.g. trying to access a field an object that is null).jade/src/main/kotlin/org/ucombinator/jade/decompile/Propogation.kt
Lines 199 to 221 in 844706a
Propagation should be updated so that field access is not copied freely. A later optimization could combine propagation and and elimination: if an expression has only one use and can be moved safely, inline it and remove its original assignment. This could also remove temporary variables such as
copyVar2_1andinsnVar6.Side note:
Propogationneeds to be renamed too. I'll rename it when refactoring.Additional Info
This PR also introduces unit tests to verify behaviors and minimize risk of regressions. The test cases also clearly illustrate the expected behaviors.
Eliminationwas also refactored significantly to reduce code duplication and to improve readability. It has been reorganized into explicit graph-building, liveness-analysis, and pruning phases.