Compute join of reference types in cf analysis
Change-Id: I00fea3ec7a7cb5d349184e012389f99c01ab4921
diff --git a/src/main/java/com/android/tools/r8/cf/code/frame/FrameType.java b/src/main/java/com/android/tools/r8/cf/code/frame/FrameType.java
index f614d65..35fc8e5 100644
--- a/src/main/java/com/android/tools/r8/cf/code/frame/FrameType.java
+++ b/src/main/java/com/android/tools/r8/cf/code/frame/FrameType.java
@@ -52,6 +52,11 @@
if (type.isPrimitiveType()) {
return primitive(type);
}
+ return initializedReference(type);
+ }
+
+ static InitializedReferenceFrameType initializedReference(DexType type) {
+ assert type.isReferenceType();
return new InitializedReferenceFrameType(type);
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/frame/InitializedReferenceFrameType.java b/src/main/java/com/android/tools/r8/cf/code/frame/InitializedReferenceFrameType.java
index fd00888..27ada3e 100644
--- a/src/main/java/com/android/tools/r8/cf/code/frame/InitializedReferenceFrameType.java
+++ b/src/main/java/com/android/tools/r8/cf/code/frame/InitializedReferenceFrameType.java
@@ -4,10 +4,12 @@
package com.android.tools.r8.cf.code.frame;
-import com.android.tools.r8.errors.Unimplemented;
import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexTypeUtils;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.naming.NamingLens;
import org.objectweb.asm.Opcodes;
@@ -44,7 +46,8 @@
}
@Override
- public SingleFrameType join(SingleFrameType frameType) {
+ public SingleFrameType join(
+ AppView<? extends AppInfoWithClassHierarchy> appView, SingleFrameType frameType) {
if (equals(frameType)) {
return this;
}
@@ -62,8 +65,10 @@
}
assert type.isArrayType() || type.isClassType();
assert otherType.isArrayType() || otherType.isClassType();
- // TODO(b/214496607): Implement join of different reference types using class hierarchy.
- throw new Unimplemented();
+ DexType joinType =
+ DexTypeUtils.toDexType(
+ appView, type.toTypeElement(appView).join(otherType.toTypeElement(appView), appView));
+ return FrameType.initializedReference(joinType);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/cf/code/frame/OneWord.java b/src/main/java/com/android/tools/r8/cf/code/frame/OneWord.java
index 9ac5082..06add68 100644
--- a/src/main/java/com/android/tools/r8/cf/code/frame/OneWord.java
+++ b/src/main/java/com/android/tools/r8/cf/code/frame/OneWord.java
@@ -4,6 +4,8 @@
package com.android.tools.r8.cf.code.frame;
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.naming.NamingLens;
import org.objectweb.asm.Opcodes;
@@ -25,7 +27,8 @@
}
@Override
- public SingleFrameType join(SingleFrameType frameType) {
+ public SingleFrameType join(
+ AppView<? extends AppInfoWithClassHierarchy> appView, SingleFrameType frameType) {
return this;
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/frame/SingleFrameType.java b/src/main/java/com/android/tools/r8/cf/code/frame/SingleFrameType.java
index 657d493..39c6e70 100644
--- a/src/main/java/com/android/tools/r8/cf/code/frame/SingleFrameType.java
+++ b/src/main/java/com/android/tools/r8/cf/code/frame/SingleFrameType.java
@@ -4,8 +4,11 @@
package com.android.tools.r8.cf.code.frame;
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
+import com.android.tools.r8.graph.AppView;
public interface SingleFrameType extends FrameType {
- SingleFrameType join(SingleFrameType frameType);
+ SingleFrameType join(
+ AppView<? extends AppInfoWithClassHierarchy> appView, SingleFrameType frameType);
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/frame/SinglePrimitiveFrameType.java b/src/main/java/com/android/tools/r8/cf/code/frame/SinglePrimitiveFrameType.java
index 69ba4b6..0739869 100644
--- a/src/main/java/com/android/tools/r8/cf/code/frame/SinglePrimitiveFrameType.java
+++ b/src/main/java/com/android/tools/r8/cf/code/frame/SinglePrimitiveFrameType.java
@@ -4,6 +4,9 @@
package com.android.tools.r8.cf.code.frame;
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
+import com.android.tools.r8.graph.AppView;
+
public abstract class SinglePrimitiveFrameType extends SingletonFrameType
implements PrimitiveFrameType, SingleFrameType {
@@ -47,7 +50,8 @@
}
@Override
- public final SingleFrameType join(SingleFrameType frameType) {
+ public final SingleFrameType join(
+ AppView<? extends AppInfoWithClassHierarchy> appView, SingleFrameType frameType) {
if (this == frameType) {
return this;
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/frame/UninitializedNew.java b/src/main/java/com/android/tools/r8/cf/code/frame/UninitializedNew.java
index 03eff42..bfaccfb 100644
--- a/src/main/java/com/android/tools/r8/cf/code/frame/UninitializedNew.java
+++ b/src/main/java/com/android/tools/r8/cf/code/frame/UninitializedNew.java
@@ -5,6 +5,8 @@
package com.android.tools.r8.cf.code.frame;
import com.android.tools.r8.cf.code.CfLabel;
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.naming.NamingLens;
@@ -51,7 +53,8 @@
}
@Override
- public SingleFrameType join(SingleFrameType frameType) {
+ public SingleFrameType join(
+ AppView<? extends AppInfoWithClassHierarchy> appView, SingleFrameType frameType) {
return equals(frameType) ? this : FrameType.oneWord();
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/frame/UninitializedThis.java b/src/main/java/com/android/tools/r8/cf/code/frame/UninitializedThis.java
index 69d1ecb..5b6730d 100644
--- a/src/main/java/com/android/tools/r8/cf/code/frame/UninitializedThis.java
+++ b/src/main/java/com/android/tools/r8/cf/code/frame/UninitializedThis.java
@@ -4,6 +4,8 @@
package com.android.tools.r8.cf.code.frame;
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.naming.NamingLens;
@@ -36,7 +38,8 @@
}
@Override
- public SingleFrameType join(SingleFrameType frameType) {
+ public SingleFrameType join(
+ AppView<? extends AppInfoWithClassHierarchy> appView, SingleFrameType frameType) {
if (this == frameType) {
return this;
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexTypeUtils.java b/src/main/java/com/android/tools/r8/graph/DexTypeUtils.java
index bff5528..62531ba 100644
--- a/src/main/java/com/android/tools/r8/graph/DexTypeUtils.java
+++ b/src/main/java/com/android/tools/r8/graph/DexTypeUtils.java
@@ -18,7 +18,7 @@
return toDexType(appView, join);
}
- private static DexType toDexType(
+ public static DexType toDexType(
AppView<? extends AppInfoWithClassHierarchy> appView, TypeElement type) {
DexItemFactory dexItemFactory = appView.dexItemFactory();
if (type.isPrimitiveType()) {
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/AbstractState.java b/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/AbstractState.java
index 914cc9e..f940edf 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/AbstractState.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/AbstractState.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.ir.analysis.framework.intraprocedural;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.ir.code.BasicBlock;
/** The abstract state of the dataflow analysis, which is computed for each {@link BasicBlock}. */
@@ -16,10 +17,10 @@
return asAbstractState();
}
- public abstract StateType join(StateType state);
+ public abstract StateType join(AppView<?> appView, StateType state);
- public boolean isGreaterThanOrEquals(StateType state) {
- StateType leastUpperBound = join(state);
+ public boolean isGreaterThanOrEquals(AppView<?> appView, StateType state) {
+ StateType leastUpperBound = join(appView, state);
return equals(leastUpperBound);
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/DataflowAnalysisResult.java b/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/DataflowAnalysisResult.java
index 8974bbf..73eeb55 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/DataflowAnalysisResult.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/DataflowAnalysisResult.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.ir.analysis.framework.intraprocedural;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.ir.code.BasicBlock;
import java.util.Map;
@@ -43,10 +44,10 @@
this.blockExitStates = blockExitStates;
}
- public StateType join() {
+ public StateType join(AppView<?> appView) {
StateType result = null;
for (StateType blockExitState : blockExitStates.values()) {
- result = result != null ? result.join(blockExitState) : blockExitState;
+ result = result != null ? result.join(appView, blockExitState) : blockExitState;
}
return result;
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/IntraProceduralDataflowAnalysisBase.java b/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/IntraProceduralDataflowAnalysisBase.java
index d7dbeb3..3a8b75c 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/IntraProceduralDataflowAnalysisBase.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/IntraProceduralDataflowAnalysisBase.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.ir.analysis.framework.intraprocedural;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.ir.analysis.framework.intraprocedural.DataflowAnalysisResult.FailedDataflowAnalysisResult;
import com.android.tools.r8.ir.analysis.framework.intraprocedural.DataflowAnalysisResult.SuccessfulDataflowAnalysisResult;
import com.android.tools.r8.utils.Timing;
@@ -27,6 +28,8 @@
public class IntraProceduralDataflowAnalysisBase<
Block, Instruction extends AbstractInstruction, StateType extends AbstractState<StateType>> {
+ final AppView<?> appView;
+
final StateType bottom;
final ControlFlowGraph<Block, Instruction> cfg;
@@ -48,10 +51,12 @@
final IntraProceduralDataflowAnalysisOptions options;
public IntraProceduralDataflowAnalysisBase(
+ AppView<?> appView,
StateType bottom,
ControlFlowGraph<Block, Instruction> cfg,
AbstractTransferFunction<Block, Instruction, StateType> transfer,
IntraProceduralDataflowAnalysisOptions options) {
+ this.appView = appView;
this.bottom = bottom;
this.cfg = cfg;
this.transfer = transfer;
@@ -137,7 +142,7 @@
if (block == cfg.getEntryBlock()) {
return transfer
.computeInitialState(block, bottom)
- .join(computeBlockEntryStateForNormalBlock(block));
+ .join(appView, computeBlockEntryStateForNormalBlock(block));
}
if (cfg.hasExceptionalPredecessors(block)) {
return exceptionalBlockEntryStates.getOrDefault(block, bottom).clone();
@@ -162,7 +167,7 @@
block,
predecessor,
blockExitStates.getOrDefault(predecessor, bottom).clone());
- return TraversalContinuation.doContinue(entryState.join(edgeState));
+ return TraversalContinuation.doContinue(entryState.join(appView, edgeState));
},
bottom);
return traversalContinuation.asContinue().getValue().clone();
@@ -171,7 +176,7 @@
boolean setBlockExitState(Block block, StateType state) {
assert !isBlockWithIntermediateSuccessorBlock(block);
StateType previous = blockExitStates.put(block, state);
- assert previous == null || state.isGreaterThanOrEquals(previous);
+ assert previous == null || state.isGreaterThanOrEquals(appView, previous);
return !state.equals(previous);
}
@@ -202,7 +207,7 @@
private void updateBlockEntryStateForBlock(
Block block, StateType edgeState, Map<Block, StateType> states) {
StateType previous = states.getOrDefault(block, bottom);
- states.put(block, previous.join(edgeState));
+ states.put(block, previous.join(appView, edgeState));
}
public boolean isIntermediateBlock(Block block) {
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/IntraproceduralDataflowAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/IntraproceduralDataflowAnalysis.java
index 9f3ea94..5e2a7ec 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/IntraproceduralDataflowAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/IntraproceduralDataflowAnalysis.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.ir.analysis.framework.intraprocedural;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
@@ -12,10 +13,16 @@
extends IntraProceduralDataflowAnalysisBase<BasicBlock, Instruction, StateType> {
public IntraproceduralDataflowAnalysis(
+ AppView<?> appView,
StateType bottom,
IRCode code,
AbstractTransferFunction<BasicBlock, Instruction, StateType> transfer) {
- super(bottom, code, transfer, IntraProceduralDataflowAnalysisOptions.getCollapseInstance());
+ super(
+ appView,
+ bottom,
+ code,
+ transfer,
+ IntraProceduralDataflowAnalysisOptions.getCollapseInstance());
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/cf/CfIntraproceduralDataflowAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/cf/CfIntraproceduralDataflowAnalysis.java
index 99205b5..cef6a5d 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/cf/CfIntraproceduralDataflowAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/cf/CfIntraproceduralDataflowAnalysis.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.ir.analysis.framework.intraprocedural.cf;
import com.android.tools.r8.cf.code.CfInstruction;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.ir.analysis.framework.intraprocedural.AbstractState;
import com.android.tools.r8.ir.analysis.framework.intraprocedural.AbstractTransferFunction;
import com.android.tools.r8.ir.analysis.framework.intraprocedural.IntraProceduralDataflowAnalysisBase;
@@ -14,9 +15,15 @@
extends IntraProceduralDataflowAnalysisBase<CfBlock, CfInstruction, StateType> {
public CfIntraproceduralDataflowAnalysis(
+ AppView<?> appView,
StateType bottom,
CfControlFlowGraph cfg,
AbstractTransferFunction<CfBlock, CfInstruction, StateType> transfer) {
- super(bottom, cfg, transfer, IntraProceduralDataflowAnalysisOptions.getCollapseInstance());
+ super(
+ appView,
+ bottom,
+ cfg,
+ transfer,
+ IntraProceduralDataflowAnalysisOptions.getCollapseInstance());
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/analysis/ClassInlinerMethodConstraintAnalysis.java b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/analysis/ClassInlinerMethodConstraintAnalysis.java
index f45344f..8842317 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/analysis/ClassInlinerMethodConstraintAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/analysis/ClassInlinerMethodConstraintAnalysis.java
@@ -26,7 +26,7 @@
// Analyze code.
IntraproceduralDataflowAnalysis<ParameterUsages> analysis =
new IntraproceduralDataflowAnalysis<>(
- ParameterUsages.bottom(), code, new TransferFunction(appView, method, code));
+ appView, ParameterUsages.bottom(), code, new TransferFunction(appView, method, code));
SuccessfulDataflowAnalysisResult<?, ParameterUsages> result =
timing.time(
"Data flow analysis",
@@ -34,7 +34,7 @@
if (result == null) {
return ClassInlinerMethodConstraint.alwaysFalse();
}
- ParameterUsages usages = timing.time("Externalize", () -> result.join().externalize());
+ ParameterUsages usages = timing.time("Externalize", () -> result.join(appView).externalize());
if (usages.isBottom()) {
return ClassInlinerMethodConstraint.alwaysTrue();
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/analysis/ParameterUsages.java b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/analysis/ParameterUsages.java
index ac81581..f4a45a8 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/analysis/ParameterUsages.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/analysis/ParameterUsages.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.ir.optimize.classinliner.analysis;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.ir.analysis.framework.intraprocedural.AbstractState;
import com.android.tools.r8.utils.IntObjToObjFunction;
@@ -42,7 +43,7 @@
}
@Override
- public ParameterUsages join(ParameterUsages state) {
+ public ParameterUsages join(AppView<?> appView, ParameterUsages state) {
if (isBottom()) {
return state;
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/string/StringBuilderAppendFlowAnalysis.java b/src/main/java/com/android/tools/r8/ir/optimize/string/StringBuilderAppendFlowAnalysis.java
index 1179c6d..bb75dc2 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/string/StringBuilderAppendFlowAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/string/StringBuilderAppendFlowAnalysis.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.ir.optimize.string;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.ir.analysis.framework.intraprocedural.AbstractState;
import com.android.tools.r8.ir.analysis.framework.intraprocedural.AbstractTransferFunction;
@@ -40,10 +41,16 @@
* loop.
*/
static boolean hasAppendInstructionInLoop(
- IRCode code, Value builder, StringBuilderOptimizationConfiguration configuration) {
+ AppView<?> appView,
+ IRCode code,
+ Value builder,
+ StringBuilderOptimizationConfiguration configuration) {
IntraproceduralDataflowAnalysis<AbstractStateImpl> analysis =
new IntraproceduralDataflowAnalysis<>(
- AbstractStateImpl.bottom(), code, new TransferFunction(builder, configuration));
+ appView,
+ AbstractStateImpl.bottom(),
+ code,
+ new TransferFunction(builder, configuration));
DataflowAnalysisResult result = analysis.run(builder.definition.getBlock());
return result.isFailedAnalysisResult();
}
@@ -86,7 +93,7 @@
}
@Override
- public AbstractStateImpl join(AbstractStateImpl state) {
+ public AbstractStateImpl join(AppView<?> appView, AbstractStateImpl state) {
if (liveAppendInstructions.isEmpty()) {
return state;
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/string/StringBuilderEscapeState.java b/src/main/java/com/android/tools/r8/ir/optimize/string/StringBuilderEscapeState.java
index 5d9c471..f1e7fb8 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/string/StringBuilderEscapeState.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/string/StringBuilderEscapeState.java
@@ -6,6 +6,7 @@
import static com.android.tools.r8.utils.FunctionUtils.ignoreArgument;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.ir.analysis.framework.intraprocedural.AbstractState;
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.utils.MapUtils;
@@ -98,7 +99,7 @@
}
@Override
- public StringBuilderEscapeState join(StringBuilderEscapeState other) {
+ public StringBuilderEscapeState join(AppView<?> appView, StringBuilderEscapeState other) {
if (this.isBottom()) {
return other;
} else if (other.isBottom()) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/string/StringBuilderOptimizer.java b/src/main/java/com/android/tools/r8/ir/optimize/string/StringBuilderOptimizer.java
index 3ad14fb..957ccfe 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/string/StringBuilderOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/string/StringBuilderOptimizer.java
@@ -722,7 +722,7 @@
return null;
}
if (StringBuilderAppendFlowAnalysis.hasAppendInstructionInLoop(
- code, builder, optimizationConfiguration)) {
+ appView, code, builder, optimizationConfiguration)) {
return null;
}
return StringUtils.join("", contents);
diff --git a/src/main/java/com/android/tools/r8/optimize/interfaces/analysis/CfFrameState.java b/src/main/java/com/android/tools/r8/optimize/interfaces/analysis/CfFrameState.java
index dfa38f5..239cb8e 100644
--- a/src/main/java/com/android/tools/r8/optimize/interfaces/analysis/CfFrameState.java
+++ b/src/main/java/com/android/tools/r8/optimize/interfaces/analysis/CfFrameState.java
@@ -12,6 +12,7 @@
import com.android.tools.r8.cf.code.frame.FrameType;
import com.android.tools.r8.cf.code.frame.PreciseFrameType;
import com.android.tools.r8.cf.code.frame.UninitializedFrameType;
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
@@ -72,11 +73,13 @@
}
@Override
- public boolean isGreaterThanOrEquals(CfFrameState state) {
+ public boolean isGreaterThanOrEquals(AppView<?> appView, CfFrameState state) {
if (this == state) {
return true;
}
- CfFrameState leastUpperBound = join(state, UnaryOperator.identity());
+ assert appView.hasClassHierarchy();
+ CfFrameState leastUpperBound =
+ join(appView.withClassHierarchy(), state, UnaryOperator.identity());
return equals(leastUpperBound);
}
@@ -313,13 +316,18 @@
}
@Override
- public final CfFrameState join(CfFrameState state) {
+ public final CfFrameState join(AppView<?> appView, CfFrameState state) {
+ assert appView.hasClassHierarchy();
return join(
- state, frameType -> frameType.isSingle() ? FrameType.oneWord() : FrameType.twoWord());
+ appView.withClassHierarchy(),
+ state,
+ frameType -> frameType.isSingle() ? FrameType.oneWord() : FrameType.twoWord());
}
public final CfFrameState join(
- CfFrameState state, UnaryOperator<FrameType> joinWithMissingLocal) {
+ AppView<? extends AppInfoWithClassHierarchy> appView,
+ CfFrameState state,
+ UnaryOperator<FrameType> joinWithMissingLocal) {
if (state.isBottom() || isError()) {
return this;
}
@@ -328,7 +336,7 @@
}
assert isConcrete();
assert state.isConcrete();
- return asConcrete().join(state.asConcrete(), joinWithMissingLocal);
+ return asConcrete().join(appView, state.asConcrete(), joinWithMissingLocal);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/optimize/interfaces/analysis/CfOpenClosedInterfacesAnalysis.java b/src/main/java/com/android/tools/r8/optimize/interfaces/analysis/CfOpenClosedInterfacesAnalysis.java
index 049a279..b21c294 100644
--- a/src/main/java/com/android/tools/r8/optimize/interfaces/analysis/CfOpenClosedInterfacesAnalysis.java
+++ b/src/main/java/com/android/tools/r8/optimize/interfaces/analysis/CfOpenClosedInterfacesAnalysis.java
@@ -48,7 +48,7 @@
CfControlFlowGraph cfg = CfControlFlowGraph.create(cfCode, appView.options());
CfIntraproceduralDataflowAnalysis<CfFrameState> analysis =
new CfIntraproceduralDataflowAnalysis<>(
- CfFrameState.bottom(), cfg, new TransferFunction(method));
+ appView, CfFrameState.bottom(), cfg, new TransferFunction(method));
DataflowAnalysisResult result = analysis.run(cfg.getEntryBlock());
// TODO(b/214496607): Determine open interfaces.
}
diff --git a/src/main/java/com/android/tools/r8/optimize/interfaces/analysis/ConcreteCfFrameState.java b/src/main/java/com/android/tools/r8/optimize/interfaces/analysis/ConcreteCfFrameState.java
index f995cbc..90d3701 100644
--- a/src/main/java/com/android/tools/r8/optimize/interfaces/analysis/ConcreteCfFrameState.java
+++ b/src/main/java/com/android/tools/r8/optimize/interfaces/analysis/ConcreteCfFrameState.java
@@ -10,11 +10,13 @@
import com.android.tools.r8.cf.code.CfAssignability;
import com.android.tools.r8.cf.code.CfAssignability.AssignabilityResult;
import com.android.tools.r8.cf.code.CfFrame;
+import com.android.tools.r8.cf.code.CfFrame.Builder;
import com.android.tools.r8.cf.code.frame.FrameType;
import com.android.tools.r8.cf.code.frame.PreciseFrameType;
import com.android.tools.r8.cf.code.frame.SingleFrameType;
import com.android.tools.r8.cf.code.frame.UninitializedFrameType;
import com.android.tools.r8.cf.code.frame.WideFrameType;
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
@@ -309,10 +311,12 @@
}
public CfFrameState join(
- ConcreteCfFrameState state, UnaryOperator<FrameType> joinWithMissingLocal) {
+ AppView<? extends AppInfoWithClassHierarchy> appView,
+ ConcreteCfFrameState state,
+ UnaryOperator<FrameType> joinWithMissingLocal) {
CfFrame.Builder builder = CfFrame.builder();
- joinLocals(state.locals, builder, joinWithMissingLocal);
- ErroneousCfFrameState error = joinStack(state.stack, builder);
+ joinLocals(appView, state.locals, builder, joinWithMissingLocal);
+ ErroneousCfFrameState error = joinStack(appView, state.stack, builder);
if (error != null) {
return error;
}
@@ -321,8 +325,9 @@
}
private void joinLocals(
+ AppView<? extends AppInfoWithClassHierarchy> appView,
Int2ObjectSortedMap<FrameType> locals,
- CfFrame.Builder builder,
+ Builder builder,
UnaryOperator<FrameType> joinWithMissingLocal) {
ObjectBidirectionalIterator<Entry<FrameType>> iterator =
this.locals.int2ObjectEntrySet().iterator();
@@ -357,7 +362,7 @@
builder);
} else {
joinLocalsWithSameIndex(
- localIndex, frameType, otherFrameType, iterator, otherIterator, builder);
+ localIndex, frameType, otherFrameType, iterator, otherIterator, appView, builder);
}
}
joinLocalsOnlyPresentInOne(iterator, builder, joinWithMissingLocal);
@@ -399,11 +404,12 @@
FrameType otherFrameType,
ObjectBidirectionalIterator<Entry<FrameType>> iterator,
ObjectBidirectionalIterator<Entry<FrameType>> otherIterator,
+ AppView<? extends AppInfoWithClassHierarchy> appView,
CfFrame.Builder builder) {
if (frameType.isSingle()) {
if (otherFrameType.isSingle()) {
joinSingleLocalsWithSameIndex(
- localIndex, frameType.asSingle(), otherFrameType.asSingle(), builder);
+ localIndex, frameType.asSingle(), otherFrameType.asSingle(), appView, builder);
} else {
setWideLocalToTop(localIndex, builder);
handleOverlappingLocals(localIndex + 1, iterator, otherIterator, builder);
@@ -423,8 +429,9 @@
int localIndex,
SingleFrameType frameType,
SingleFrameType otherFrameType,
+ AppView<? extends AppInfoWithClassHierarchy> appView,
CfFrame.Builder builder) {
- builder.store(localIndex, frameType.join(otherFrameType));
+ builder.store(localIndex, frameType.join(appView, otherFrameType));
}
private void joinWideLocalsWithSameIndex(
@@ -543,7 +550,10 @@
setSingleLocalToTop(localIndex + 1, builder);
}
- private ErroneousCfFrameState joinStack(Deque<PreciseFrameType> stack, CfFrame.Builder builder) {
+ private ErroneousCfFrameState joinStack(
+ AppView<? extends AppInfoWithClassHierarchy> appView,
+ Deque<PreciseFrameType> stack,
+ CfFrame.Builder builder) {
Iterator<PreciseFrameType> iterator = this.stack.iterator();
Iterator<PreciseFrameType> otherIterator = stack.iterator();
int stackIndex = 0;
@@ -561,7 +571,7 @@
}
PreciseFrameType preciseJoin;
if (frameType.isSingle()) {
- SingleFrameType join = frameType.asSingle().join(otherFrameType.asSingle());
+ SingleFrameType join = frameType.asSingle().join(appView, otherFrameType.asSingle());
if (join.isOneWord()) {
return joinStackImpreciseJoinError(stackIndex, frameType, otherFrameType);
}