blob: a580f046710cf28ae7504dd1595793530fe67090 [file] [log] [blame]
// Copyright (c) 2021, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.ir.conversion.callgraph;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.conversion.callgraph.CycleEliminator.CycleEliminationResult;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.Timing;
import com.google.common.collect.Sets;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
abstract class IRProcessingCallGraphBuilderBase extends CallGraphBuilderBase<Node> {
IRProcessingCallGraphBuilderBase(AppView<AppInfoWithLiveness> appView) {
super(appView);
}
public CallGraph build(ExecutorService executorService, Timing timing) throws ExecutionException {
timing.begin("Build IR processing order constraints");
timing.begin("Build call graph");
populateGraph(executorService);
assert verifyNoRedundantFieldReadEdges();
timing.end();
assert verifyAllMethodsWithCodeExists();
appView.withGeneratedMessageLiteBuilderShrinker(
shrinker -> shrinker.preprocessCallGraphBeforeCycleElimination(nodes));
timing.begin("Cycle elimination");
// Sort the nodes for deterministic cycle elimination.
Set<Node> nodesWithDeterministicOrder = Sets.newTreeSet(nodes.values());
CycleEliminator cycleEliminator = new CycleEliminator();
CycleEliminationResult cycleEliminationResult =
cycleEliminator.breakCycles(nodesWithDeterministicOrder);
timing.end();
timing.end();
assert cycleEliminator.breakCycles(nodesWithDeterministicOrder).numberOfRemovedCallEdges()
== 0; // The cycles should be gone.
return new CallGraph(nodes, cycleEliminationResult);
}
@Override
protected Node createNode(ProgramMethod method) {
return new Node(method);
}
abstract void populateGraph(ExecutorService executorService) throws ExecutionException;
/** Verify that there are no field read edges in the graph if there is also a call graph edge. */
private boolean verifyNoRedundantFieldReadEdges() {
for (Node writer : nodes.values()) {
for (Node reader : writer.getReadersWithDeterministicOrder()) {
assert !writer.hasCaller(reader);
}
}
return true;
}
abstract boolean verifyAllMethodsWithCodeExists();
}