Update AssertionErrorRewriter to not remove NewInstance on the fly Bug: b/245692849 Change-Id: I805d4dbe80ceaa3821eec01138469e0ea9727297
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/AssertionErrorTwoArgsConstructorRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/AssertionErrorTwoArgsConstructorRewriter.java index 06d9d8f..6d5083c 100644 --- a/src/main/java/com/android/tools/r8/ir/optimize/AssertionErrorTwoArgsConstructorRewriter.java +++ b/src/main/java/com/android/tools/r8/ir/optimize/AssertionErrorTwoArgsConstructorRewriter.java
@@ -11,19 +11,24 @@ import com.android.tools.r8.graph.DexProto; import com.android.tools.r8.graph.MethodAccessFlags; import com.android.tools.r8.graph.ProgramMethod; +import com.android.tools.r8.ir.analysis.type.DynamicType; import com.android.tools.r8.ir.analysis.type.Nullability; -import com.android.tools.r8.ir.analysis.type.TypeElement; +import com.android.tools.r8.ir.analysis.type.TypeAnalysis; import com.android.tools.r8.ir.code.BasicBlock; import com.android.tools.r8.ir.code.IRCode; import com.android.tools.r8.ir.code.Instruction; import com.android.tools.r8.ir.code.InstructionListIterator; import com.android.tools.r8.ir.code.InvokeStatic; +import com.android.tools.r8.ir.code.NewInstance; import com.android.tools.r8.ir.code.Value; import com.android.tools.r8.ir.desugar.backports.BackportedMethods; +import com.android.tools.r8.ir.optimize.info.OptimizationFeedback; import com.android.tools.r8.utils.InternalOptions; +import com.google.common.collect.Sets; import java.util.ArrayList; import java.util.List; import java.util.ListIterator; +import java.util.Set; public class AssertionErrorTwoArgsConstructorRewriter { @@ -41,11 +46,12 @@ if (options.canUseAssertionErrorTwoArgumentConstructor()) { return; } - + Set<Value> newOutValues = Sets.newIdentityHashSet(); ListIterator<BasicBlock> blockIterator = code.listIterator(); while (blockIterator.hasNext()) { BasicBlock block = blockIterator.next(); InstructionListIterator insnIterator = block.listIterator(code); + List<NewInstance> newInstancesToRemove = new ArrayList<>(); while (insnIterator.hasNext()) { Instruction current = insnIterator.next(); if (current.isInvokeMethod()) { @@ -53,24 +59,31 @@ if (invokedMethod == dexItemFactory.assertionErrorMethods.initMessageAndCause) { List<Value> inValues = current.inValues(); assert inValues.size() == 3; // receiver, message, cause - - Value assertionError = - code.createValue( - TypeElement.fromDexType( - dexItemFactory.assertionErrorType, - Nullability.definitelyNotNull(), - appView)); - Instruction invoke = - new InvokeStatic( - createSynthetic(methodProcessingContext).getReference(), - assertionError, - inValues.subList(1, 3)); + Value newInstanceValue = current.getFirstOperand(); + Instruction definition = newInstanceValue.getDefinition(); + if (!definition.isNewInstance()) { + continue; + } + InvokeStatic invoke = + InvokeStatic.builder() + .setMethod(createSynthetic(methodProcessingContext).getReference()) + .setFreshOutValue( + code, dexItemFactory.assertionErrorType.toTypeElement(appView)) + .setPosition(current) + .setArguments(inValues.subList(1, 3)) + .build(); insnIterator.replaceCurrentInstruction(invoke); - inValues.get(0).replaceUsers(assertionError); - inValues.get(0).definition.removeOrReplaceByDebugLocalRead(code); + newInstanceValue.replaceUsers(invoke.outValue()); + newOutValues.add(invoke.outValue()); + newInstancesToRemove.add(definition.asNewInstance()); } } } + newInstancesToRemove.forEach( + newInstance -> newInstance.removeOrReplaceByDebugLocalRead(code)); + } + if (!newOutValues.isEmpty()) { + new TypeAnalysis(appView).widening(newOutValues); } assert code.isConsistentSSA(appView); } @@ -103,6 +116,15 @@ factory, methodSig))); synchronized (synthesizedMethods) { synthesizedMethods.add(method); + OptimizationFeedback.getSimpleFeedback() + .setDynamicReturnType( + method, + appView, + DynamicType.createExact( + dexItemFactory + .assertionErrorType + .toTypeElement(appView, Nullability.definitelyNotNull()) + .asClassType())); } return method; }