Merge commit 'ff39e2b159b6b21508ec3b96d20a65d77202527f' into dev-release
Change-Id: I1f8aa59502a288677bdb68f637c8db63a8c98b4e
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 8089d42..8f40057 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -734,6 +734,8 @@
R8LibraryDesugaring.runIfNecessary(appView, executorService, timing);
+ appView.withThrowBlockOutliner(outliner -> outliner.runForR8(executorService, timing));
+
if (appView.appInfo().hasLiveness()) {
SyntheticFinalization.finalizeWithLiveness(appView.withLiveness(), executorService, timing);
} else {
diff --git a/src/main/java/com/android/tools/r8/R8Command.java b/src/main/java/com/android/tools/r8/R8Command.java
index 9f1f42d..43953a0 100644
--- a/src/main/java/com/android/tools/r8/R8Command.java
+++ b/src/main/java/com/android/tools/r8/R8Command.java
@@ -1086,14 +1086,6 @@
parserOptionsBuilder.setEnableExperimentalCheckEnumUnboxed(true);
}
- void setEnableExperimentalConvertCheckNotNull() {
- parserOptionsBuilder.setEnableExperimentalConvertCheckNotNull(true);
- }
-
- void setEnableExperimentalWhyAreYouNotInlining() {
- parserOptionsBuilder.setEnableExperimentalWhyAreYouNotInlining(true);
- }
-
// Internal for-testing method to allow proguard options only available for testing.
void setEnableTestProguardOptions() {
parserOptionsBuilder.setEnableTestingOptions(true);
diff --git a/src/main/java/com/android/tools/r8/graph/AppView.java b/src/main/java/com/android/tools/r8/graph/AppView.java
index 5a4d355..124786f 100644
--- a/src/main/java/com/android/tools/r8/graph/AppView.java
+++ b/src/main/java/com/android/tools/r8/graph/AppView.java
@@ -617,6 +617,13 @@
}
}
+ public <E extends Throwable> void withD8ThrowBlockOutliner(
+ ThrowingConsumer<ThrowBlockOutliner, E> consumer) throws E {
+ if (!enableWholeProgramOptimizations()) {
+ withThrowBlockOutliner(consumer);
+ }
+ }
+
public LibraryMemberOptimizer libraryMethodOptimizer() {
return libraryMemberOptimizer;
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexMethod.java b/src/main/java/com/android/tools/r8/graph/DexMethod.java
index 4abdb68..ff4f333 100644
--- a/src/main/java/com/android/tools/r8/graph/DexMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexMethod.java
@@ -346,7 +346,10 @@
@Override
public DexMethod withHolder(DexReference reference, DexItemFactory dexItemFactory) {
- return dexItemFactory.createMethod(reference.getContextType(), proto, name);
+ DexType newHolder = reference.getContextType();
+ return newHolder.isIdenticalTo(holder)
+ ? this
+ : dexItemFactory.createMethod(newHolder, proto, name);
}
public DexMethod withName(String name, DexItemFactory dexItemFactory) {
diff --git a/src/main/java/com/android/tools/r8/graph/ProgramMethod.java b/src/main/java/com/android/tools/r8/graph/ProgramMethod.java
index 21b8de8..fe16b49 100644
--- a/src/main/java/com/android/tools/r8/graph/ProgramMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/ProgramMethod.java
@@ -6,18 +6,22 @@
import static com.android.tools.r8.ir.optimize.info.OptimizationFeedback.getSimpleFeedback;
import com.android.tools.r8.dex.IndexedItemCollection;
+import com.android.tools.r8.graph.bytecodemetadata.BytecodeMetadataProvider;
import com.android.tools.r8.graph.lens.GraphLens;
import com.android.tools.r8.graph.proto.RewrittenPrototypeDescription;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.NumberGenerator;
import com.android.tools.r8.ir.code.Position;
+import com.android.tools.r8.ir.conversion.IRFinalizer;
import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
import com.android.tools.r8.ir.conversion.MethodConversionOptions;
import com.android.tools.r8.ir.conversion.MethodConversionOptions.MutableMethodConversionOptions;
import com.android.tools.r8.ir.conversion.MethodProcessor;
+import com.android.tools.r8.ir.optimize.DeadCodeRemover;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.kotlin.KotlinMethodLevelInfo;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.utils.timing.Timing;
import it.unimi.dsi.fastutil.ints.Int2ReferenceMap;
/** Type representing a method definition in the programs compilation unit and its holder. */
@@ -211,6 +215,13 @@
getDefinition().setCode(newCode, parameterInfo);
}
+ public void setCode(
+ IRCode newCode, AppView<?> appView, DeadCodeRemover deadCodeRemover, Timing timing) {
+ IRFinalizer<?> finalizer =
+ newCode.getConversionOptions().getFinalizer(deadCodeRemover, appView);
+ setCode(finalizer.finalizeCode(newCode, BytecodeMetadataProvider.empty(), timing), appView);
+ }
+
public boolean keepLocals(AppView<?> appView) {
if (appView.testing().noLocalsTableOnInput) {
return false;
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/type/TypeUtils.java b/src/main/java/com/android/tools/r8/ir/analysis/type/TypeUtils.java
index 8d98060..65a5c1a 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/type/TypeUtils.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/type/TypeUtils.java
@@ -17,7 +17,6 @@
import static com.android.tools.r8.ir.code.Opcodes.RETURN;
import static com.android.tools.r8.ir.code.Opcodes.STATIC_PUT;
-import com.android.tools.r8.graph.AppInfo;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexField;
@@ -71,24 +70,15 @@
* value must have in order for the program to type check.
*/
public static TypeElement computeUseType(AppView<?> appView, DexType returnType, Value value) {
- if (appView.hasClassHierarchy()) {
- return computeUseType(appView, returnType, value, (s, t) -> s.join(t, appView));
- } else {
- AppView<AppInfo> appViewWithoutClassHierarchy = appView.withoutClassHierarchy();
- AppInfoWithClassHierarchy appInfo = appView.appInfoForDesugaring();
- return computeUseType(
- appView,
- returnType,
- value,
- (s, t) -> joinWithoutClassHierarchy(s, t, appViewWithoutClassHierarchy, appInfo));
- }
+ AppInfoWithClassHierarchy appInfo = appView.appInfoForDesugaring();
+ return computeUseType(appView, returnType, value, (s, t) -> meet(s, t, appView, appInfo));
}
private static TypeElement computeUseType(
AppView<?> appView,
DexType returnType,
Value value,
- BiFunction<TypeElement, TypeElement, TypeElement> joiner) {
+ BiFunction<TypeElement, TypeElement, TypeElement> meet) {
TypeElement staticType = value.getType();
TypeElement useType = TypeElement.getBottom();
WorkList<UserAndValuePair> users = WorkList.newEqualityWorkList();
@@ -101,9 +91,8 @@
} else {
Instruction instruction = user.asInstruction();
TypeElement instructionUseType =
- computeUseTypeForInstruction(
- appView, returnType, instruction, item.value, joiner, users);
- useType = joiner.apply(useType, instructionUseType);
+ computeUseTypeForInstruction(appView, returnType, instruction, item.value, meet, users);
+ useType = meet.apply(useType, instructionUseType);
if (useType.isTop() || useType.equalUpToNullability(staticType)) {
// Bail-out.
return staticType;
@@ -127,7 +116,7 @@
DexType returnType,
Instruction instruction,
Value value,
- BiFunction<TypeElement, TypeElement, TypeElement> joiner,
+ BiFunction<TypeElement, TypeElement, TypeElement> meet,
WorkList<UserAndValuePair> users) {
switch (instruction.opcode()) {
case ASSUME:
@@ -138,13 +127,13 @@
case INSTANCE_GET:
return computeUseTypeForInstanceGet(appView, instruction.asInstanceGet());
case INSTANCE_PUT:
- return computeUseTypeForInstancePut(appView, instruction.asInstancePut(), value, joiner);
+ return computeUseTypeForInstancePut(appView, instruction.asInstancePut(), value, meet);
case INVOKE_DIRECT:
case INVOKE_INTERFACE:
case INVOKE_STATIC:
case INVOKE_SUPER:
case INVOKE_VIRTUAL:
- return computeUseTypeForInvoke(appView, instruction.asInvokeMethod(), value, joiner);
+ return computeUseTypeForInvoke(appView, instruction.asInvokeMethod(), value, meet);
case RETURN:
return computeUseTypeForReturn(appView, returnType);
case STATIC_PUT:
@@ -170,14 +159,14 @@
AppView<?> appView,
InstancePut instancePut,
Value value,
- BiFunction<TypeElement, TypeElement, TypeElement> joiner) {
+ BiFunction<TypeElement, TypeElement, TypeElement> meet) {
DexField field = instancePut.getField();
TypeElement useType = TypeElement.getBottom();
if (instancePut.object() == value) {
- useType = joiner.apply(useType, field.getHolderType().toTypeElement(appView));
+ useType = meet.apply(useType, field.getHolderType().toTypeElement(appView));
}
if (instancePut.value() == value) {
- useType = joiner.apply(useType, field.getType().toTypeElement(appView));
+ useType = meet.apply(useType, field.getType().toTypeElement(appView));
}
return useType;
}
@@ -186,7 +175,7 @@
AppView<?> appView,
InvokeMethod invoke,
Value value,
- BiFunction<TypeElement, TypeElement, TypeElement> joiner) {
+ BiFunction<TypeElement, TypeElement, TypeElement> meet) {
TypeElement useType = TypeElement.getBottom();
for (int argumentIndex = 0; argumentIndex < invoke.arguments().size(); argumentIndex++) {
Value argument = invoke.getArgument(argumentIndex);
@@ -198,7 +187,7 @@
.getInvokedMethod()
.getArgumentType(argumentIndex, invoke.isInvokeStatic())
.toTypeElement(appView);
- useType = joiner.apply(useType, useTypeForArgument);
+ useType = meet.apply(useType, useTypeForArgument);
}
assert !useType.isBottom();
return useType;
@@ -212,19 +201,24 @@
return staticPut.getField().getType().toTypeElement(appView);
}
- private static TypeElement joinWithoutClassHierarchy(
- TypeElement type,
- TypeElement other,
- AppView<AppInfo> appView,
- AppInfoWithClassHierarchy appInfo) {
- assert !other.isBottom();
+ private static TypeElement meet(
+ TypeElement type, TypeElement other, AppView<?> appView, AppInfoWithClassHierarchy appInfo) {
+ if (other.isBottom()) {
+ return type;
+ }
if (type.isBottom()) {
return other;
}
if (type.isTop() || other.isTop()) {
return TypeElement.getTop();
}
- if (type.equals(other)) {
+ if (type.equalUpToNullability(other)) {
+ if (type.isReferenceType()) {
+ if (!type.nullability().equals(other.nullability())) {
+ return type.asReferenceType()
+ .getOrCreateVariant(type.nullability().meet(other.nullability()));
+ }
+ }
return type;
}
if (type.isPrimitiveType()) {
@@ -242,11 +236,16 @@
DexType classType = type.asClassType().getClassType();
DexType otherClassType = other.asClassType().getClassType();
if (appInfo.isSubtype(classType, otherClassType)) {
- return ClassTypeElement.createForD8(classType, type.nullability().join(other.nullability()));
+ if (type.nullability().equals(other.nullability())) {
+ return type;
+ }
+ return type.asClassType().getOrCreateVariant(type.nullability().meet(other.nullability()));
}
if (appInfo.isSubtype(otherClassType, classType)) {
- return ClassTypeElement.createForD8(
- otherClassType, type.nullability().join(other.nullability()));
+ if (type.nullability().equals(other.nullability())) {
+ return other;
+ }
+ return other.asClassType().getOrCreateVariant(type.nullability().meet(other.nullability()));
}
return TypeElement.getTop();
}
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
index b54a50a..d43e0b2 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -816,7 +816,7 @@
assert code.verifyNoNullabilityBottomTypes();
assert code.verifyTypes(appView);
- appView.withThrowBlockOutliner(outliner -> outliner.scan(code));
+ appView.withD8ThrowBlockOutliner(outliner -> outliner.scan(code));
previous = printMethod(code, "Optimized IR (SSA)", previous);
timing.begin("Finalize IR");
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxerImpl.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxerImpl.java
index 3154d72..297ebe1 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxerImpl.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxerImpl.java
@@ -1407,6 +1407,9 @@
// Check if this is a checkNotNull() user. In this case, we can create a copy of the method
// that takes an int instead of java.lang.Object and call that method instead.
if (singleTarget != null) {
+ if (singleTarget.getAccessFlags().isAbstract()) {
+ return Reason.INVALID_INVOKE;
+ }
EnumUnboxerMethodClassification classification =
singleTarget.getOptimizationInfo().getEnumUnboxerMethodClassification();
if (classification.isCheckNotNullClassification()) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingLens.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingLens.java
index 5068f5a..3b7abb1 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingLens.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingLens.java
@@ -50,7 +50,6 @@
private final AbstractValueFactory abstractValueFactory;
private final Map<DexMethod, RewrittenPrototypeDescription> prototypeChangesPerMethod;
private final EnumDataMap unboxedEnums;
- private final Set<DexMethod> dispatchMethods;
EnumUnboxingLens(
AppView<?> appView,
@@ -58,14 +57,12 @@
BidirectionalOneToManyRepresentativeMap<DexMethod, DexMethod> renamedSignatures,
BidirectionalManyToOneRepresentativeMap<DexType, DexType> typeMap,
Map<DexMethod, DexMethod> methodMap,
- Map<DexMethod, RewrittenPrototypeDescription> prototypeChangesPerMethod,
- Set<DexMethod> dispatchMethods) {
+ Map<DexMethod, RewrittenPrototypeDescription> prototypeChangesPerMethod) {
super(appView, fieldMap, methodMap, typeMap, renamedSignatures);
assert !appView.unboxedEnums().isEmpty();
this.abstractValueFactory = appView.abstractValueFactory();
this.prototypeChangesPerMethod = prototypeChangesPerMethod;
this.unboxedEnums = appView.unboxedEnums();
- this.dispatchMethods = dispatchMethods;
}
@Override
@@ -108,15 +105,12 @@
public DexMethod lookupRefinedDispatchMethod(
DexMethod method,
- DexMethod context,
- InvokeType type,
- GraphLens codeLens,
AbstractValue unboxedEnumValue,
DexType enumType) {
- assert codeLens == getPrevious();
- DexMethod reference = lookupMethod(method, context, type, codeLens).getReference();
- if (!dispatchMethods.contains(reference) || !unboxedEnumValue.isSingleNumberValue()) {
- return null;
+ DexMethod enumMethod = method.withHolder(enumType, dexItemFactory());
+ DexMethod rewrittenEnumMethod = newMethodSignatures.getRepresentativeValue(enumMethod);
+ if (!unboxedEnumValue.isSingleNumberValue()) {
+ return rewrittenEnumMethod;
}
// We know the exact type of enum, so there is no need to go for the dispatch method. Instead,
// we compute the exact target from the enum instance.
@@ -126,11 +120,12 @@
.get(enumType)
.valuesTypes
.getOrDefault(unboxedIntToOrdinal(unboxedEnum), enumType);
+ if (instanceType.isIdenticalTo(enumType)) {
+ return rewrittenEnumMethod;
+ }
DexMethod specializedMethod = method.withHolder(instanceType, dexItemFactory());
- DexMethod superEnumMethod = method.withHolder(enumType, dexItemFactory());
DexMethod refined =
- newMethodSignatures.getRepresentativeValueOrDefault(
- specializedMethod, newMethodSignatures.getRepresentativeValue(superEnumMethod));
+ newMethodSignatures.getRepresentativeValueOrDefault(specializedMethod, rewrittenEnumMethod);
assert refined != null;
return refined;
}
@@ -408,8 +403,7 @@
originalCheckNotNullMethodSignature, checkNotNullMethod.getReference());
}
- public EnumUnboxingLens build(
- AppView<AppInfoWithLiveness> appView, Set<DexMethod> dispatchMethods) {
+ public EnumUnboxingLens build(AppView<AppInfoWithLiveness> appView) {
assert !typeMap.isEmpty();
return new EnumUnboxingLens(
appView,
@@ -417,8 +411,7 @@
newMethodSignatures,
typeMap,
methodMap,
- ImmutableMap.copyOf(prototypeChangesPerMethod),
- dispatchMethods);
+ ImmutableMap.copyOf(prototypeChangesPerMethod));
}
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingRewriter.java
index 7cca071..0c5c644 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingRewriter.java
@@ -200,6 +200,7 @@
rewriteInvokeMethodWithReceiver(
code,
eventConsumer,
+ affectedPhis,
convertedEnums,
blocks,
block,
@@ -438,6 +439,7 @@
private void rewriteInvokeMethodWithReceiver(
IRCode code,
EnumUnboxerMethodProcessorEventConsumer eventConsumer,
+ Set<Phi> affectedPhis,
Map<Instruction, DexType> convertedEnums,
BasicBlockIterator blocks,
BasicBlock block,
@@ -499,18 +501,23 @@
} else if (invoke.isInvokeVirtual() || invoke.isInvokeInterface()) {
DexMethod refinedDispatchMethodReference =
enumUnboxingLens.lookupRefinedDispatchMethod(
- invokedMethod,
- context.getReference(),
- invoke.getType(),
- enumUnboxingLens.getPrevious(),
- invoke.getArgument(0).getAbstractValue(appView, context),
- enumType);
+ invokedMethod, invoke.getReceiver().getAbstractValue(appView, context), enumType);
if (refinedDispatchMethodReference != null) {
DexClassAndMethod refinedDispatchMethod =
appView.definitionFor(refinedDispatchMethodReference);
assert refinedDispatchMethod != null;
assert refinedDispatchMethod.isProgramMethod();
- replaceEnumInvoke(iterator, invoke, refinedDispatchMethod.asProgramMethod());
+ InvokeStatic replacement =
+ replaceEnumInvoke(iterator, invoke, refinedDispatchMethod.asProgramMethod());
+ if (replacement.hasOutValue()
+ && refinedDispatchMethodReference.getReturnType().isIntType()
+ && !invokedMethod.getReturnType().isIntType()) {
+ Value rewrittenOutValue = code.createValue(TypeElement.getInt());
+ replacement.outValue().replaceUsers(rewrittenOutValue);
+ replacement.setOutValue(rewrittenOutValue);
+ affectedPhis.addAll(rewrittenOutValue.uniquePhiUsers());
+ convertedEnums.put(replacement, enumType);
+ }
}
}
} else if (invokedMethod == factory.stringBuilderMethods.appendObject
@@ -859,12 +866,12 @@
.ensureGetInstanceFieldMethod(appView, field, context, eventConsumer);
}
- private void replaceEnumInvoke(
+ private InvokeStatic replaceEnumInvoke(
InstructionListIterator iterator, InvokeMethod invoke, ProgramMethod method) {
- replaceEnumInvoke(iterator, invoke, method, invoke.arguments());
+ return replaceEnumInvoke(iterator, invoke, method, invoke.arguments());
}
- private void replaceEnumInvoke(
+ private InvokeStatic replaceEnumInvoke(
InstructionListIterator iterator,
InvokeMethod invoke,
ProgramMethod method,
@@ -877,6 +884,7 @@
assert !replacement.hasOutValue()
|| !replacement.getInvokedMethod().getReturnType().isVoidType();
iterator.replaceCurrentInstruction(replacement);
+ return replacement;
}
private boolean validateArrayAccess(ArrayAccess arrayAccess) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingTreeFixer.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingTreeFixer.java
index a6bda7d..53051d0 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingTreeFixer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingTreeFixer.java
@@ -158,9 +158,7 @@
.fixupClassesConcurrentlyByConnectedProgramComponents(Timing.empty(), executorService);
// Install the new graph lens before processing any checkNotZero() methods.
- Set<DexMethod> dispatchMethodReferences = Sets.newIdentityHashSet();
- dispatchMethods.forEach((method, code) -> dispatchMethodReferences.add(method.getReference()));
- EnumUnboxingLens lens = lensBuilder.build(appView, dispatchMethodReferences);
+ EnumUnboxingLens lens = lensBuilder.build(appView);
appView.rewriteWithLens(lens, executorService, timing);
// Rewrite outliner with lens.
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutline.java b/src/main/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutline.java
index eca5fe3..0af7d88 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutline.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutline.java
@@ -253,6 +253,10 @@
builder ->
builder
.setAccessFlags(MethodAccessFlags.createPublicStaticSynthetic())
+ // TODO(b/434769547): The API level of the code may be higher than the min-api.
+ // This currently doesn't matter since outlining runs after API outlining.
+ .setApiLevelForCode(
+ appView.apiLevelCompute().computeInitialMinApiLevel(appView.options()))
.setCode(methodSig -> lirCode)
.setProto(getOptimizedProto(appView.dexItemFactory())));
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlineMarkerRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlineMarkerRewriter.java
index 232c840..e9de503 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlineMarkerRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlineMarkerRewriter.java
@@ -75,12 +75,16 @@
appView,
callerPosition,
outline.getProtoChanges(),
- MethodConversionOptions.forD8(appView, method));
+ appView.enableWholeProgramOptimizations()
+ ? MethodConversionOptions.forLirPhase(appView)
+ : MethodConversionOptions.forD8(appView, method));
}
private void finalizeCode(ProgramMethod method, IRCode code) {
// Convert to DEX.
- assert code.getConversionOptions().isGeneratingDex();
+ assert appView.enableWholeProgramOptimizations()
+ ? code.getConversionOptions().isGeneratingLir()
+ : code.getConversionOptions().isGeneratingDex();
IRFinalizer<?> finalizer = code.getConversionOptions().getFinalizer(deadCodeRemover, appView);
Code dexCode = finalizer.finalizeCode(code, BytecodeMetadataProvider.empty(), Timing.empty());
method.setCode(dexCode, appView);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutliner.java b/src/main/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutliner.java
index 755e836..004281a 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutliner.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.ir.optimize.outliner.exceptions;
import static com.android.tools.r8.utils.MapUtils.ignoreKey;
+import static com.google.common.base.Predicates.alwaysTrue;
import com.android.tools.r8.contexts.CompilationContext.MethodProcessingContext;
import com.android.tools.r8.contexts.CompilationContext.ProcessorContext;
@@ -12,20 +13,25 @@
import com.android.tools.r8.dex.code.DexInvokeStatic;
import com.android.tools.r8.dex.code.DexReturn;
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.code.IRCode;
+import com.android.tools.r8.ir.optimize.DeadCodeRemover;
import com.android.tools.r8.lightir.LirCode;
import com.android.tools.r8.lightir.LirConstant;
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.ThreadUtils;
import com.android.tools.r8.utils.collections.ProgramMethodMap;
+import com.android.tools.r8.utils.timing.Timing;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
import it.unimi.dsi.fastutil.objects.Reference2IntMap;
import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
@@ -55,6 +61,41 @@
: null;
}
+ // TODO(b/434769547): Ensure retracing works.
+ public void runForR8(ExecutorService executorService, Timing timing) throws ExecutionException {
+ timing.begin("Throw block outliner");
+ scan(executorService, timing);
+ tearDownScanner(Collections.emptyMap(), executorService);
+ // Commit pending synthetics.
+ appView.rebuildAppInfo();
+ appView.getTypeElementFactory().clearTypeElementsCache();
+ timing.end();
+ }
+
+ public void scan(ExecutorService executorService, Timing timing) throws ExecutionException {
+ ThreadUtils.processItemsThatMatches(
+ appView.appInfo().classes(),
+ alwaysTrue(),
+ this::scan,
+ appView.options(),
+ executorService,
+ timing,
+ timing.beginMerger("Scan for throw block outlines", executorService));
+ }
+
+ private void scan(DexProgramClass clazz, Timing timing) {
+ timing.begin("Scan " + clazz.getTypeName());
+ DeadCodeRemover deadCodeRemover = new DeadCodeRemover(appView);
+ clazz.forEachProgramMethodMatching(
+ DexEncodedMethod::hasLirCode,
+ method -> {
+ IRCode code = method.buildIR(appView);
+ scan(code);
+ method.setCode(code, appView, deadCodeRemover, timing);
+ });
+ timing.end();
+ }
+
public void scan(IRCode code) {
// Notify the scanner.
if (scanner != null) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerOptions.java b/src/main/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerOptions.java
index d1b50b6..55036d0 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerOptions.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerOptions.java
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.ir.optimize.outliner.exceptions;
-import com.android.tools.r8.errors.Unimplemented;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.utils.SystemPropertyUtils;
import java.util.Collection;
@@ -38,8 +37,8 @@
if (appView.options().debug && !forceDebug) {
return false;
}
- if (appView.enableWholeProgramOptimizations()) {
- throw new Unimplemented();
+ if (appView.options().partialSubCompilationConfiguration != null) {
+ return false;
}
return true;
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerScanner.java b/src/main/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerScanner.java
index 07b7470..840483a 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerScanner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerScanner.java
@@ -70,13 +70,17 @@
private final AppView<?> appView;
private final DexItemFactory factory;
- private final AbstractValueFactory valueFactory = new AbstractValueFactory();
+ private final AbstractValueFactory valueFactory;
private final Map<Wrapper<LirCode<?>>, ThrowBlockOutline> outlines = new ConcurrentHashMap<>();
ThrowBlockOutlinerScanner(AppView<?> appView) {
this.appView = appView;
this.factory = appView.dexItemFactory();
+ this.valueFactory =
+ appView.enableWholeProgramOptimizations()
+ ? appView.abstractValueFactory()
+ : new AbstractValueFactory();
}
public void run(IRCode code) {
@@ -85,16 +89,18 @@
new ThrowBlockOutlinerScannerForBlock(code, block).processThrowBlock();
}
if (code.metadata().mayHaveThrowBlockOutlineMarker()) {
- assert code.getConversionOptions().isGeneratingDex();
- code.mutateConversionOptions(MutableMethodConversionOptions::setIsGeneratingLir);
+ if (appView.enableWholeProgramOptimizations()) {
+ assert code.getConversionOptions().isGeneratingLir();
+ } else {
+ assert code.getConversionOptions().isGeneratingDex();
+ code.mutateConversionOptions(MutableMethodConversionOptions::setIsGeneratingLir);
+ }
} else {
assert code.streamInstructions().noneMatch(Instruction::isThrowBlockOutlineMarker);
}
}
public AbstractValueFactory getAbstractValueFactory() {
- // If/when extending this to R8, use the R8 AbstractValueFactory from AppView.
- assert !appView.enableWholeProgramOptimizations();
return valueFactory;
}
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
index 3c01885..dddd397 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
@@ -136,8 +136,6 @@
ProguardConfigurationParserOptions.builder()
.setEnableLegacyFullModeForKeepRules(false)
.setEnableExperimentalCheckEnumUnboxed(false)
- .setEnableExperimentalConvertCheckNotNull(false)
- .setEnableExperimentalWhyAreYouNotInlining(false)
.setEnableTestingOptions(false)
.build(),
null,
@@ -483,6 +481,13 @@
parseRuleWithClassSpec(optionStart, ProguardIdentifierNameStringRule.builder()));
} else if (acceptString("if")) {
configurationConsumer.addRule(parseIfRule(optionStart));
+ } else if (acceptString(ConvertCheckNotNullRule.RULE_NAME)) {
+ configurationConsumer.addRule(parseConvertCheckNotNullRule(optionStart));
+ return true;
+ } else if (acceptString(WhyAreYouNotInliningRule.RULE_NAME)) {
+ configurationConsumer.addRule(
+ parseRuleWithClassSpec(optionStart, WhyAreYouNotInliningRule.builder()));
+ return true;
} else if (parseMaximumRemovedAndroidLogLevelRule(optionStart)) {
return true;
} else {
@@ -507,20 +512,6 @@
}
return true;
}
- if (acceptString(ConvertCheckNotNullRule.RULE_NAME)) {
- ConvertCheckNotNullRule convertCheckNotNullRule = parseConvertCheckNotNullRule(optionStart);
- if (options.isExperimentalConvertCheckNotNullEnabled()) {
- configurationConsumer.addRule(convertCheckNotNullRule);
- }
- return true;
- }
- if (options.isExperimentalWhyAreYouNotInliningEnabled()) {
- if (acceptString(WhyAreYouNotInliningRule.RULE_NAME)) {
- configurationConsumer.addRule(
- parseRuleWithClassSpec(optionStart, WhyAreYouNotInliningRule.builder()));
- return true;
- }
- }
return false;
}
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParserOptions.java b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParserOptions.java
index df606a1..b7392e7 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParserOptions.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParserOptions.java
@@ -11,8 +11,6 @@
private final boolean enableLegacyFullModeForKeepRules;
private final boolean enableLegacyFullModeForKeepRulesWarnings;
private final boolean enableExperimentalCheckEnumUnboxed;
- private final boolean enableExperimentalConvertCheckNotNull;
- private final boolean enableExperimentalWhyAreYouNotInlining;
private final boolean enableKeepRuntimeInvisibleAnnotations;
private final boolean enableTestingOptions;
private final boolean forceProguardCompatibility;
@@ -21,14 +19,10 @@
boolean enableLegacyFullModeForKeepRules,
boolean enableLegacyFullModeForKeepRulesWarnings,
boolean enableExperimentalCheckEnumUnboxed,
- boolean enableExperimentalConvertCheckNotNull,
- boolean enableExperimentalWhyAreYouNotInlining,
boolean enableKeepRuntimeInvisibleAnnotations,
boolean enableTestingOptions,
boolean forceProguardCompatibility) {
this.enableExperimentalCheckEnumUnboxed = enableExperimentalCheckEnumUnboxed;
- this.enableExperimentalConvertCheckNotNull = enableExperimentalConvertCheckNotNull;
- this.enableExperimentalWhyAreYouNotInlining = enableExperimentalWhyAreYouNotInlining;
this.enableKeepRuntimeInvisibleAnnotations = enableKeepRuntimeInvisibleAnnotations;
this.enableTestingOptions = enableTestingOptions;
this.enableLegacyFullModeForKeepRules = enableLegacyFullModeForKeepRules;
@@ -54,14 +48,6 @@
return enableExperimentalCheckEnumUnboxed;
}
- public boolean isExperimentalConvertCheckNotNullEnabled() {
- return enableExperimentalConvertCheckNotNull;
- }
-
- public boolean isExperimentalWhyAreYouNotInliningEnabled() {
- return enableExperimentalWhyAreYouNotInlining;
- }
-
public boolean isKeepRuntimeInvisibleAnnotationsEnabled() {
return enableKeepRuntimeInvisibleAnnotations;
}
@@ -75,8 +61,6 @@
private boolean enableLegacyFullModeForKeepRules = true;
private boolean enableLegacyFullModeForKeepRulesWarnings = false;
private boolean enableExperimentalCheckEnumUnboxed;
- private boolean enableExperimentalConvertCheckNotNull;
- private boolean enableExperimentalWhyAreYouNotInlining;
private boolean enableKeepRuntimeInvisibleAnnotations = true;
private boolean enableTestingOptions;
private boolean forceProguardCompatibility = false;
@@ -91,12 +75,6 @@
enableExperimentalCheckEnumUnboxed =
parseSystemPropertyOrDefault(
"com.android.tools.r8.experimental.enablecheckenumunboxed", false);
- enableExperimentalConvertCheckNotNull =
- parseSystemPropertyOrDefault(
- "com.android.tools.r8.experimental.enableconvertchecknotnull", false);
- enableExperimentalWhyAreYouNotInlining =
- parseSystemPropertyOrDefault(
- "com.android.tools.r8.experimental.enablewhyareyounotinlining", false);
enableKeepRuntimeInvisibleAnnotations =
parseSystemPropertyOrDefault(
"com.android.tools.r8.enableKeepRuntimeInvisibleAnnotations", true);
@@ -122,18 +100,6 @@
return this;
}
- public Builder setEnableExperimentalConvertCheckNotNull(
- boolean enableExperimentalConvertCheckNotNull) {
- this.enableExperimentalConvertCheckNotNull = enableExperimentalConvertCheckNotNull;
- return this;
- }
-
- public Builder setEnableExperimentalWhyAreYouNotInlining(
- boolean enableExperimentalWhyAreYouNotInlining) {
- this.enableExperimentalWhyAreYouNotInlining = enableExperimentalWhyAreYouNotInlining;
- return this;
- }
-
public Builder setEnableTestingOptions(boolean enableTestingOptions) {
this.enableTestingOptions = enableTestingOptions;
return this;
@@ -149,8 +115,6 @@
enableLegacyFullModeForKeepRules,
enableLegacyFullModeForKeepRulesWarnings,
enableExperimentalCheckEnumUnboxed,
- enableExperimentalConvertCheckNotNull,
- enableExperimentalWhyAreYouNotInlining,
enableKeepRuntimeInvisibleAnnotations,
enableTestingOptions,
forceProguardCompatibility);
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index 8fadcd8..81cc3e0 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -1849,7 +1849,7 @@
public boolean enableConstructorInlining = true;
public boolean enableConstructorInliningWithFinalFields =
parseSystemPropertyOrDefault(
- "com.android.tools.r8.enableConstructorInliningWithFinalFields", false);
+ "com.android.tools.r8.enableConstructorInliningWithFinalFields", true);
public boolean skipStoreStoreFenceInConstructorInlining =
parseSystemPropertyOrDefault(
"com.android.tools.r8.skipStoreStoreFenceInConstructorInlining", false);
diff --git a/src/test/java/com/android/tools/r8/enumunboxing/InvokeInterfaceNoDevirtualizationEnumUnboxingTest.java b/src/test/java/com/android/tools/r8/enumunboxing/InvokeInterfaceNoDevirtualizationEnumUnboxingTest.java
index 0d04b20..3eb7953 100644
--- a/src/test/java/com/android/tools/r8/enumunboxing/InvokeInterfaceNoDevirtualizationEnumUnboxingTest.java
+++ b/src/test/java/com/android/tools/r8/enumunboxing/InvokeInterfaceNoDevirtualizationEnumUnboxingTest.java
@@ -3,10 +3,15 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.enumunboxing;
+import static org.junit.Assume.assumeFalse;
+import static org.junit.Assume.assumeTrue;
+
import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.NoAccessModification;
import com.android.tools.r8.NoVerticalClassMerging;
import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.utils.codeinspector.AssertUtils;
+import com.google.common.collect.ImmutableList;
+import java.io.IOException;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -22,7 +27,7 @@
@Parameters(name = "{0} valueOpt: {1} keep: {2}")
public static List<Object[]> data() {
- return enumUnboxingTestParameters();
+ return enumUnboxingTestParameters(getTestParameters().withAllRuntimesAndApiLevels().build());
}
public InvokeInterfaceNoDevirtualizationEnumUnboxingTest(
@@ -33,43 +38,66 @@
}
@Test
- public void test() throws Exception {
- AssertUtils.assertFailsCompilation(
- () ->
- testForR8(parameters)
- .addInnerClasses(getClass())
- .addKeepMainRule(Main.class)
- .addKeepRules(enumKeepRules.getKeepRules())
- // Disable devirtualization so that the enum unboxing rewriter sees the call to
- // I#greet instead of MyEnum#greet.
- .addOptionsModification(options -> options.enableDevirtualization = false)
- .addOptionsModification(
- options -> enableEnumOptions(options, enumValueOptimization))
- .enableInliningAnnotations()
- .enableNoVerticalClassMergingAnnotations()
- .compile()
- .run(parameters.getRuntime(), Main.class)
- .assertSuccessWithOutputLines("Hello, world!"));
+ public void testJvm() throws Exception {
+ parameters.assumeJvmTestParameters();
+ assumeFalse(enumValueOptimization);
+ assumeTrue(enumKeepRules.isNone());
+ testForJvm(parameters)
+ .addProgramClasses(I.class)
+ .addProgramClassFileData(getProgramClassFileData())
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines("Hello, world!");
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ testForR8(parameters)
+ .addProgramClasses(I.class)
+ .addProgramClassFileData(getProgramClassFileData())
+ .addKeepMainRule(Main.class)
+ .addKeepRules(enumKeepRules.getKeepRules())
+ .addOptionsModification(options -> enableEnumOptions(options, enumValueOptimization))
+ .enableInliningAnnotations()
+ .enableNoAccessModificationAnnotationsForClasses()
+ .enableNoVerticalClassMergingAnnotations()
+ .compile()
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines("Hello, world!");
+ }
+
+ private static List<byte[]> getProgramClassFileData() throws IOException {
+ return ImmutableList.of(
+ transformer(Main.class)
+ .replaceClassDescriptorInMethodInstructions(
+ descriptor(MyEnumAccessor.class), "LMyEnumAccessor;")
+ .transform(),
+ transformer(MyEnum.class).setClassDescriptor("LMyEnum;").transform(),
+ transformer(MyEnumAccessor.class)
+ .setClassDescriptor("LMyEnumAccessor;")
+ .replaceClassDescriptorInMethodInstructions(descriptor(MyEnum.class), "LMyEnum;")
+ .transform());
}
static class Main {
public static void main(String[] args) {
- MyEnum e = System.currentTimeMillis() > 0 ? MyEnum.A : MyEnum.B;
- greet(e);
+ greet(MyEnumAccessor.get());
}
static void greet(I i) {
+ // Cannot be rewritten to call MyEnum#greet since MyEnum is not public and in another package.
i.greet();
}
}
@NoVerticalClassMerging
- interface I {
+ public interface I {
void greet();
}
+ // Moved to separate package by transformer.
+ @NoAccessModification
enum MyEnum implements I {
A,
B;
@@ -80,4 +108,12 @@
System.out.println("Hello, world!");
}
}
+
+ // Moved to separate package by transformer.
+ public static class MyEnumAccessor {
+
+ public static I get() {
+ return System.currentTimeMillis() > 0 ? MyEnum.A : MyEnum.B;
+ }
+ }
}
diff --git a/src/test/java/com/android/tools/r8/enumunboxing/enummerging/AbstractMethodErrorEnumMergingTest.java b/src/test/java/com/android/tools/r8/enumunboxing/enummerging/AbstractMethodErrorEnumMergingTest.java
index 7937ef7..b11d6de 100644
--- a/src/test/java/com/android/tools/r8/enumunboxing/enummerging/AbstractMethodErrorEnumMergingTest.java
+++ b/src/test/java/com/android/tools/r8/enumunboxing/enummerging/AbstractMethodErrorEnumMergingTest.java
@@ -10,6 +10,7 @@
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.enumunboxing.EnumUnboxingTestBase;
import com.android.tools.r8.utils.StringUtils;
+import com.android.tools.r8.utils.codeinspector.EnumUnboxingInspector;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
@@ -49,25 +50,22 @@
@Test
public void testReference() throws Exception {
- testForD8(parameters.getBackend())
+ testForD8(parameters)
.addProgramClassFileData(inputProgram())
.addOptionsModification(opt -> enableEnumOptions(opt, enumValueOptimization))
- .setMinApi(parameters)
.run(parameters.getRuntime(), Main.class)
.assertSuccessWithOutput(EXPECTED_RESULT);
}
@Test
public void testEnumUnboxing() throws Exception {
- testForR8(parameters.getBackend())
+ testForR8(parameters)
.addProgramClassFileData(inputProgram())
.addKeepMainRule(Main.class)
.addKeepRules(enumKeepRules.getKeepRules())
- .addEnumUnboxingInspector(
- inspector -> inspector.assertUnboxed(MyEnum2Cases.class, MyEnum1Case.class))
+ .addEnumUnboxingInspector(EnumUnboxingInspector::assertNoEnumsUnboxed)
.enableInliningAnnotations()
.addOptionsModification(opt -> enableEnumOptions(opt, enumValueOptimization))
- .setMinApi(parameters)
.run(parameters.getRuntime(), Main.class)
.assertSuccessWithOutput(EXPECTED_RESULT);
}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/inliner/whyareyounotinlining/WhyAreYouNotInliningInvokeWithUnknownTargetTest.java b/src/test/java/com/android/tools/r8/ir/optimize/inliner/whyareyounotinlining/WhyAreYouNotInliningInvokeWithUnknownTargetTest.java
index 06f5aa2..9e6e511 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/inliner/whyareyounotinlining/WhyAreYouNotInliningInvokeWithUnknownTargetTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/inliner/whyareyounotinlining/WhyAreYouNotInliningInvokeWithUnknownTargetTest.java
@@ -38,7 +38,6 @@
.addInnerClasses(getClass())
.addKeepMainRule(TestClass.class)
.addKeepRules("-whyareyounotinlining class " + A.class.getTypeName() + " { void m(); }")
- .enableExperimentalWhyAreYouNotInlining()
.enableNoHorizontalClassMergingAnnotations()
.enableNeverReprocessMethodAnnotations()
.setMinApi(parameters)
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/inliner/whyareyounotinlining/WhyAreYouNotInliningLibraryTargetTest.java b/src/test/java/com/android/tools/r8/ir/optimize/inliner/whyareyounotinlining/WhyAreYouNotInliningLibraryTargetTest.java
index 1c85f7f..fc823ce 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/inliner/whyareyounotinlining/WhyAreYouNotInliningLibraryTargetTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/inliner/whyareyounotinlining/WhyAreYouNotInliningLibraryTargetTest.java
@@ -34,7 +34,6 @@
"-whyareyounotinlining class "
+ System.class.getTypeName()
+ " { long currentTimeMillis(); }")
- .enableExperimentalWhyAreYouNotInlining()
.setMinApi(parameters)
.compile()
// The Inliner is currently not reporting -whyareyounotinlining for library calls.
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerArrayUseTypeTest.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerArrayUseTypeTest.java
index 0ee7d9b..d07c1e6 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerArrayUseTypeTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerArrayUseTypeTest.java
@@ -3,22 +3,46 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.ir.optimize.outliner.exceptions;
+import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertEquals;
+import com.android.tools.r8.KeepUnusedArguments;
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.SingleTestRunResult;
+import com.android.tools.r8.TestCompileResult;
+import com.android.tools.r8.TestCompilerBuilder;
import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
import java.util.Collection;
import org.junit.Test;
public class ThrowBlockOutlinerArrayUseTypeTest extends ThrowBlockOutlinerTestBase {
@Test
- public void test() throws Exception {
- testForD8(parameters)
- .addInnerClasses(getClass())
- .apply(this::configure)
- .compile()
+ public void testD8() throws Exception {
+ runTest(testForD8(parameters));
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ assumeRelease();
+ runTest(
+ testForR8(parameters)
+ .addKeepMainRule(Main.class)
+ .enableInliningAnnotations()
+ .enableUnusedArgumentAnnotations());
+ }
+
+ private void runTest(
+ TestCompilerBuilder<?, ?, ?, ? extends SingleTestRunResult<?>, ?> testBuilder)
+ throws Exception {
+ TestCompileResult<?, ?> compileResult =
+ testBuilder.addInnerClasses(getClass()).apply(this::configure).compile();
+
+ ClassSubject exceptionClassSubject = compileResult.inspector().clazz(MyException.class);
+ compileResult
.run(parameters.getRuntime(), Main.class)
- .assertFailureWithErrorThatThrows(MyException.class);
+ .assertFailureWithErrorThatMatches(containsString(exceptionClassSubject.getFinalName()));
}
@Override
@@ -46,6 +70,8 @@
static class MyException extends RuntimeException {
+ @KeepUnusedArguments
+ @NeverInline
MyException(String msg, Main[] main) {}
}
}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerConstArgumentTest.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerConstArgumentTest.java
index cd6c533..2badee6 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerConstArgumentTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerConstArgumentTest.java
@@ -10,8 +10,11 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import com.android.tools.r8.SingleTestRunResult;
import com.android.tools.r8.TestCompileResult;
+import com.android.tools.r8.TestCompilerBuilder;
import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.ir.optimize.outliner.exceptions.ThrowBlockOutlinerArrayUseTypeTest.Main;
import com.android.tools.r8.synthesis.SyntheticItemsTestUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -24,9 +27,21 @@
public class ThrowBlockOutlinerConstArgumentTest extends ThrowBlockOutlinerTestBase {
@Test
- public void test() throws Exception {
+ public void testD8() throws Exception {
+ runTest(testForD8(parameters));
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ assumeRelease();
+ runTest(testForR8(parameters).addKeepMainRule(Main.class));
+ }
+
+ private void runTest(
+ TestCompilerBuilder<?, ?, ?, ? extends SingleTestRunResult<?>, ?> testBuilder)
+ throws Exception {
TestCompileResult<?, ?> compileResult =
- testForD8(parameters)
+ testBuilder
.addInnerClasses(getClass())
.apply(this::configure)
.compile()
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerInterfaceMethodDesugaringTest.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerInterfaceMethodDesugaringTest.java
index 3b9a6e4..d0c21e3 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerInterfaceMethodDesugaringTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerInterfaceMethodDesugaringTest.java
@@ -6,8 +6,11 @@
import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertEquals;
+import com.android.tools.r8.SingleTestRunResult;
import com.android.tools.r8.TestCompileResult;
+import com.android.tools.r8.TestCompilerBuilder;
import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.ir.optimize.outliner.exceptions.ThrowBlockOutlinerArrayUseTypeTest.Main;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import java.util.Collection;
import org.junit.Test;
@@ -15,9 +18,21 @@
public class ThrowBlockOutlinerInterfaceMethodDesugaringTest extends ThrowBlockOutlinerTestBase {
@Test
- public void test() throws Exception {
+ public void testD8() throws Exception {
+ runTest(testForD8(parameters));
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ assumeRelease();
+ runTest(testForR8(parameters).addKeepMainRule(Main.class));
+ }
+
+ private void runTest(
+ TestCompilerBuilder<?, ?, ?, ? extends SingleTestRunResult<?>, ?> testBuilder)
+ throws Exception {
TestCompileResult<?, ?> compileResult =
- testForD8(parameters)
+ testBuilder
.addProgramClasses(Main.class, A.class)
.addProgramClassFileData(
transformer(I.class)
@@ -25,7 +40,7 @@
.transform())
.apply(this::configure)
.compile()
- .inspect(this::inspectOutput);
+ .inspect(inspector -> inspectOutput(inspector, testBuilder));
compileResult
.run(parameters.getRuntime(), Main.class, "default")
.assertFailureWithErrorThatThrows(RuntimeException.class)
@@ -49,7 +64,12 @@
assertEquals(3, outline.getNumberOfUsers());
}
- private void inspectOutput(CodeInspector inspector) {
+ private void inspectOutput(
+ CodeInspector inspector,
+ TestCompilerBuilder<?, ?, ?, ? extends SingleTestRunResult<?>, ?> testBuilder) {
+ if (testBuilder.isR8TestBuilder()) {
+ return;
+ }
// Main, I, I$-CC, A and the synthetic outline class.
assertEquals(
parameters.canUseDefaultAndStaticInterfaceMethods() ? 4 : 5, inspector.allClasses().size());
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerNoArgumentsTest.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerNoArgumentsTest.java
index 994e8be..cfb6c30 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerNoArgumentsTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerNoArgumentsTest.java
@@ -10,7 +10,9 @@
import static org.junit.Assert.assertTrue;
import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.SingleTestRunResult;
import com.android.tools.r8.TestCompileResult;
+import com.android.tools.r8.TestCompilerBuilder;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.synthesis.SyntheticItemsTestUtils;
import com.android.tools.r8.utils.BooleanUtils;
@@ -39,9 +41,21 @@
}
@Test
- public void test() throws Exception {
+ public void testD8() throws Exception {
+ runTest(testForD8(parameters));
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ assumeRelease();
+ runTest(testForR8(parameters).addKeepMainRule(Main.class));
+ }
+
+ private void runTest(
+ TestCompilerBuilder<?, ?, ?, ? extends SingleTestRunResult<?>, ?> testBuilder)
+ throws Exception {
TestCompileResult<?, ?> compileResult =
- testForD8(parameters)
+ testBuilder
.addInnerClasses(getClass())
.apply(this::configure)
.addOptionsModification(
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerSharedStringBuilderTest.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerSharedStringBuilderTest.java
index bebc31b..51d44e7 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerSharedStringBuilderTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerSharedStringBuilderTest.java
@@ -10,9 +10,12 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import com.android.tools.r8.SingleTestRunResult;
import com.android.tools.r8.TestCompileResult;
+import com.android.tools.r8.TestCompilerBuilder;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
+import com.android.tools.r8.ir.optimize.outliner.exceptions.ThrowBlockOutlinerArrayUseTypeTest.Main;
import com.android.tools.r8.synthesis.SyntheticItemsTestUtils;
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
@@ -25,9 +28,21 @@
public class ThrowBlockOutlinerSharedStringBuilderTest extends ThrowBlockOutlinerTestBase {
@Test
- public void test() throws Exception {
+ public void testD8() throws Exception {
+ runTest(testForD8(parameters));
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ assumeRelease();
+ runTest(testForR8(parameters).addKeepMainRule(Main.class));
+ }
+
+ private void runTest(
+ TestCompilerBuilder<?, ?, ?, ? extends SingleTestRunResult<?>, ?> testBuilder)
+ throws Exception {
TestCompileResult<?, ?> compileResult =
- testForD8(parameters)
+ testBuilder
.addInnerClasses(getClass())
.apply(this::configure)
.compile()
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerTestBase.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerTestBase.java
index f507e28..5b62f54 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerTestBase.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerTestBase.java
@@ -3,8 +3,8 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.ir.optimize.outliner.exceptions;
-import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.SingleTestRunResult;
@@ -49,14 +49,20 @@
assertTrue(receivedCallback.isTrue());
}
+ public void assumeRelease() {
+ if (mode.isDebug()) {
+ receivedCallback.set();
+ }
+ assumeTrue(mode.isRelease());
+ }
+
public void configure(
TestCompilerBuilder<?, ?, ?, ? extends SingleTestRunResult<?>, ?> testBuilder) {
testBuilder
.addOptionsModification(
options -> {
ThrowBlockOutlinerOptions outlinerOptions = options.getThrowBlockOutlinerOptions();
- assertFalse(outlinerOptions.enable);
- outlinerOptions.enable = true;
+ assertTrue(outlinerOptions.enable);
outlinerOptions.forceDebug = true;
outlinerOptions.outlineConsumerForTesting =
outlines -> {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerUseTypeTest.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerUseTypeTest.java
index d48861d..5a3fcdb 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerUseTypeTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerUseTypeTest.java
@@ -3,22 +3,46 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.ir.optimize.outliner.exceptions;
+import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertEquals;
+import com.android.tools.r8.KeepUnusedArguments;
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.SingleTestRunResult;
+import com.android.tools.r8.TestCompileResult;
+import com.android.tools.r8.TestCompilerBuilder;
import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
import java.util.Collection;
import org.junit.Test;
public class ThrowBlockOutlinerUseTypeTest extends ThrowBlockOutlinerTestBase {
@Test
- public void test() throws Exception {
- testForD8(parameters)
- .addInnerClasses(getClass())
- .apply(this::configure)
- .compile()
+ public void testD8() throws Exception {
+ runTest(testForD8(parameters));
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ assumeRelease();
+ runTest(
+ testForR8(parameters)
+ .addKeepMainRule(Main.class)
+ .enableInliningAnnotations()
+ .enableUnusedArgumentAnnotations());
+ }
+
+ private void runTest(
+ TestCompilerBuilder<?, ?, ?, ? extends SingleTestRunResult<?>, ?> testBuilder)
+ throws Exception {
+ TestCompileResult<?, ?> compileResult =
+ testBuilder.addInnerClasses(getClass()).apply(this::configure).compile();
+
+ ClassSubject exceptionClassSubject = compileResult.inspector().clazz(MyException.class);
+ compileResult
.run(parameters.getRuntime(), Main.class)
- .assertFailureWithErrorThatThrows(MyException.class);
+ .assertFailureWithErrorThatMatches(containsString(exceptionClassSubject.getFinalName()));
}
@Override
@@ -46,6 +70,8 @@
static class MyException extends RuntimeException {
+ @KeepUnusedArguments
+ @NeverInline
MyException(String msg, Main main) {}
}
}
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInlineSuspendFunctionTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInlineSuspendFunctionTest.java
index 59d559a..58456ef 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInlineSuspendFunctionTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInlineSuspendFunctionTest.java
@@ -102,6 +102,7 @@
kotlinc.getKotlinStdlibJar(), kotlinc.getKotlinxCoroutinesCoreJar(), libJar)
.addClasspath(output)
.run(parameters.getRuntime(), PKG_APP + ".MainKt")
+ // TODO(b/449961100): R8 should keep $$forInline functions if original is kept.
.assertFailureWithErrorThatThrowsIf(keepOnlyPublic, VerifyError.class)
.assertSuccessWithOutputIf(!keepOnlyPublic, EXPECTED);
}
diff --git a/src/test/java/com/android/tools/r8/optimize/serviceloader/ServiceLoaderTestBase.java b/src/test/java/com/android/tools/r8/optimize/serviceloader/ServiceLoaderTestBase.java
index 54ba9f3..56f3eba 100644
--- a/src/test/java/com/android/tools/r8/optimize/serviceloader/ServiceLoaderTestBase.java
+++ b/src/test/java/com/android/tools/r8/optimize/serviceloader/ServiceLoaderTestBase.java
@@ -138,7 +138,6 @@
o.enableServiceLoaderRewriting = enableRewriting;
})
// Enables ServiceLoader optimization failure diagnostics.
- .enableExperimentalWhyAreYouNotInlining()
.addKeepRules("-whyareyounotinlining class java.util.ServiceLoader { *** load(...); }");
if (implClasses.length > 0) {
String implLines =
diff --git a/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java b/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
index f9f7c65..cb788dc 100644
--- a/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
@@ -185,8 +185,6 @@
ProguardConfigurationParserOptions.builder()
.setEnableLegacyFullModeForKeepRules(false)
.setEnableExperimentalCheckEnumUnboxed(false)
- .setEnableExperimentalConvertCheckNotNull(false)
- .setEnableExperimentalWhyAreYouNotInlining(false)
.setEnableTestingOptions(false)
.build(),
null,
@@ -205,8 +203,6 @@
reporter,
ProguardConfigurationParserOptions.builder()
.setEnableExperimentalCheckEnumUnboxed(false)
- .setEnableExperimentalConvertCheckNotNull(false)
- .setEnableExperimentalWhyAreYouNotInlining(false)
.setEnableTestingOptions(true)
.build(),
null,
@@ -728,8 +724,6 @@
reporter,
ProguardConfigurationParserOptions.builder()
.setEnableExperimentalCheckEnumUnboxed(false)
- .setEnableExperimentalConvertCheckNotNull(true)
- .setEnableExperimentalWhyAreYouNotInlining(false)
.setEnableTestingOptions(false)
.build(),
null,
@@ -750,8 +744,6 @@
reporter,
ProguardConfigurationParserOptions.builder()
.setEnableExperimentalCheckEnumUnboxed(false)
- .setEnableExperimentalConvertCheckNotNull(true)
- .setEnableExperimentalWhyAreYouNotInlining(false)
.setEnableTestingOptions(false)
.build(),
null,
diff --git a/src/test/java/com/android/tools/r8/shaking/convertchecknotnull/ConvertCheckNotNullTest.java b/src/test/java/com/android/tools/r8/shaking/convertchecknotnull/ConvertCheckNotNullTest.java
index b1ad9de..eeb7d6c 100644
--- a/src/test/java/com/android/tools/r8/shaking/convertchecknotnull/ConvertCheckNotNullTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/convertchecknotnull/ConvertCheckNotNullTest.java
@@ -54,7 +54,6 @@
"-convertchecknotnull class java.util.Objects {",
" ** requireNonNull(**, ...);",
"}")
- .enableExperimentalConvertCheckNotNull()
.setMinApi(parameters)
.compile()
.inspect(
diff --git a/src/test/java/com/android/tools/r8/shaking/convertchecknotnull/ConvertCheckNotNullWithAssumeNoSideEffectsTest.java b/src/test/java/com/android/tools/r8/shaking/convertchecknotnull/ConvertCheckNotNullWithAssumeNoSideEffectsTest.java
index fa3cc91..38f4d09 100644
--- a/src/test/java/com/android/tools/r8/shaking/convertchecknotnull/ConvertCheckNotNullWithAssumeNoSideEffectsTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/convertchecknotnull/ConvertCheckNotNullWithAssumeNoSideEffectsTest.java
@@ -45,7 +45,6 @@
"-convertchecknotnull class java.util.Objects {",
" ** requireNonNull(...);",
"}")
- .enableExperimentalConvertCheckNotNull()
.setMinApi(parameters)
.compile()
.inspect(
diff --git a/src/test/testbase/java/com/android/tools/r8/R8TestBuilder.java b/src/test/testbase/java/com/android/tools/r8/R8TestBuilder.java
index 2ac3d7b..58f7a23 100644
--- a/src/test/testbase/java/com/android/tools/r8/R8TestBuilder.java
+++ b/src/test/testbase/java/com/android/tools/r8/R8TestBuilder.java
@@ -818,16 +818,6 @@
return self();
}
- public T enableExperimentalConvertCheckNotNull() {
- builder.setEnableExperimentalConvertCheckNotNull();
- return self();
- }
-
- public T enableExperimentalWhyAreYouNotInlining() {
- builder.setEnableExperimentalWhyAreYouNotInlining();
- return self();
- }
-
public T enableExperimentalKeepAnnotations(KeepAnnotationLibrary keepAnnotationLibrary) {
return addOptionsModification(o -> o.testing.enableEmbeddedKeepAnnotations = true)
.addKeepAnnoLibToClasspath(keepAnnotationLibrary);
diff --git a/src/test/testbase/java/com/android/tools/r8/TestCompilerBuilder.java b/src/test/testbase/java/com/android/tools/r8/TestCompilerBuilder.java
index 35ab038..25efdbf 100644
--- a/src/test/testbase/java/com/android/tools/r8/TestCompilerBuilder.java
+++ b/src/test/testbase/java/com/android/tools/r8/TestCompilerBuilder.java
@@ -64,6 +64,7 @@
public static final Consumer<InternalOptions> DEFAULT_OPTIONS =
options -> {
options.testing.enableTestAssertions = true;
+ options.getThrowBlockOutlinerOptions().enable = true;
};
public static final Consumer<InternalOptions> DEFAULT_D8_OPTIONS = DEFAULT_OPTIONS;
@@ -76,7 +77,6 @@
options.testing.forcePruneMetaInfManifestMf = true;
options.horizontalClassMergerOptions().enable();
options.horizontalClassMergerOptions().setEnableInterfaceMerging();
- options.inlinerOptions().enableConstructorInliningWithFinalFields = true;
options
.getCfCodeAnalysisOptions()
.setAllowUnreachableCfBlocks(false)