Fix edge removal in the CallGraph class + improve runtime a bit #2224
+127
−18
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.
First commit: Fix edge removal in the CallGraph class
If CallGraph.removeAllEdgesOutOf or CallGraph.removeEdges is called,
the corresponding edge(s) is not entirely removed from the CallGraph
data structures.
removeAllEdgesOutOf(Unit u):
The to be removed edges are not removed from the call graph data structures.
For each to be removed edge e, the code first calls e.remove(), which sets
the Edge.invalid attribute to true. Afterwards, removeEdge(e, false) is
calledonly executed. The edge removal code in removeEdge(...) is only
executed, if the edge e is contained in the edges set. Since Edge.invalid
was set to true, e.hashCode() returns the constant value 0. Since the return
value of e.hashCode() was different before Edge.invalid was set to true, the
edge cannot be found in the edges set. Hence, no edge removal code is
executed.
In order to fix this, do not call e.remove() before calling removeEdge(...).
Moreoever, the call to e.remove() is not needed because it is already called
in removeEdge(...).
removeEdges(Collection edges):
First, this.edges.removeAll(edges) is executed and afterwards, for each
edge e in the passed edges collection, removeEdge(e, false) is executed.
Since the edge is not contained anymore in the this.edges set, no edge
removal code in removeEdge(...) is executed.
In order to fix this, do not call this.edges.removeAll(edges).
The expected behavior is documented in the CallGraphTest test case.
Second commit: Improve the runtime of CallGraph.removeAllEdgesOutOf a bit
Instead of iterating over all callgraph edges to find all edges that
originate from a specific unit, simply call edgesOutOf(...) (which
internally uses a LinkedHashMap for the initial lookup).
This seems to cause a noticeable speedup in UnreachableCodeEliminator.