Merge commit '7fd2616561134814c9baee894370ff7f82f99520' into dev-release
diff --git a/src/main/java/com/android/tools/r8/GenerateLintFiles.java b/src/main/java/com/android/tools/r8/GenerateLintFiles.java
index 74da57f..17b7485 100644
--- a/src/main/java/com/android/tools/r8/GenerateLintFiles.java
+++ b/src/main/java/com/android/tools/r8/GenerateLintFiles.java
@@ -144,7 +144,9 @@
DexAnnotationSet.empty(),
ParameterAnnotationsList.empty(),
code,
- 50);
+ false,
+ 50,
+ false);
if (method.isStatic() || method.isDirectMethod()) {
directMethods.add(throwingMethod);
} else {
diff --git a/src/main/java/com/android/tools/r8/cf/TypeVerificationHelper.java b/src/main/java/com/android/tools/r8/cf/TypeVerificationHelper.java
index b98c4cb..4574386 100644
--- a/src/main/java/com/android/tools/r8/cf/TypeVerificationHelper.java
+++ b/src/main/java/com/android/tools/r8/cf/TypeVerificationHelper.java
@@ -311,7 +311,7 @@
private DexType computeVerificationType(Value value) {
return value.isPhi()
- ? value.asPhi().computeVerificationType(this)
+ ? value.asPhi().computeVerificationType(appView, this)
: value.definition.computeVerificationType(appView, this);
}
diff --git a/src/main/java/com/android/tools/r8/graph/CfCode.java b/src/main/java/com/android/tools/r8/graph/CfCode.java
index 02af4ee..79d6d83 100644
--- a/src/main/java/com/android/tools/r8/graph/CfCode.java
+++ b/src/main/java/com/android/tools/r8/graph/CfCode.java
@@ -64,6 +64,12 @@
public class CfCode extends Code implements Comparable<CfCode> {
+ public enum StackMapStatus {
+ NOT_VERIFIED,
+ INVALID_OR_NOT_PRESENT,
+ VALID
+ }
+
public static class LocalVariableInfo {
private final int index;
@@ -129,6 +135,7 @@
private List<CfInstruction> instructions;
private final List<CfTryCatch> tryCatchRanges;
private final List<LocalVariableInfo> localVariables;
+ private StackMapStatus stackMapStatus = StackMapStatus.NOT_VERIFIED;
public CfCode(
DexType originalHolder,
@@ -157,6 +164,11 @@
return maxLocals;
}
+ public StackMapStatus getStackMapStatus() {
+ assert stackMapStatus != StackMapStatus.NOT_VERIFIED;
+ return stackMapStatus;
+ }
+
public void setMaxLocals(int newMaxLocals) {
maxLocals = newMaxLocals;
}
@@ -371,7 +383,7 @@
@Override
public IRCode buildIR(ProgramMethod method, AppView<?> appView, Origin origin) {
- // TODO(b/164396438): Assert that we can validate frames.
+ verifyFramesOrRemove(method.getDefinition(), appView, origin, true);
return internalBuildPossiblyWithLocals(method, method, appView, null, null, origin, null);
}
@@ -386,11 +398,22 @@
MethodProcessor methodProcessor) {
assert valueNumberGenerator != null;
assert callerPosition != null;
- // TODO(b/164396438): Assert that we can validate frames.
+ verifyFramesOrRemove(
+ method.getDefinition(), appView, origin, methodProcessor.shouldApplyCodeRewritings(method));
return internalBuildPossiblyWithLocals(
context, method, appView, valueNumberGenerator, callerPosition, origin, methodProcessor);
}
+ private void verifyFramesOrRemove(
+ DexEncodedMethod method,
+ AppView<?> appView,
+ Origin origin,
+ boolean shouldApplyCodeRewritings) {
+ if (!verifyFrames(method, appView, origin, shouldApplyCodeRewritings)) {
+ instructions.removeIf(CfInstruction::isFrame);
+ }
+ }
+
// First build entry. Will either strip locals or build with locals.
private IRCode internalBuildPossiblyWithLocals(
ProgramMethod context,
@@ -657,9 +680,11 @@
DexEncodedMethod method, AppView<?> appView, Origin origin, boolean applyProtoTypeChanges) {
if (!appView.options().testing.readInputStackMaps
|| appView.options().testing.disableStackMapVerification) {
+ stackMapStatus = StackMapStatus.INVALID_OR_NOT_PRESENT;
return true;
}
if (method.hasClassFileVersion() && method.getClassFileVersion() <= V1_6) {
+ stackMapStatus = StackMapStatus.INVALID_OR_NOT_PRESENT;
return true;
}
if (!method.isInstanceInitializer()
@@ -668,6 +693,7 @@
.getOriginalMethodSignature(method.method)
.isInstanceInitializer(appView.dexItemFactory())) {
// We cannot verify instance initializers if they are moved.
+ stackMapStatus = StackMapStatus.INVALID_OR_NOT_PRESENT;
return true;
}
// Build a map from labels to frames.
@@ -767,6 +793,7 @@
appView);
}
}
+ stackMapStatus = StackMapStatus.VALID;
return true;
}
@@ -775,6 +802,7 @@
// started enforcing stack maps from 51 in JVM 8. As a consequence, we have different android
// libraries that has V1_7 code but has no stack maps. To not fail on compilations we only
// report a warning.
+ stackMapStatus = StackMapStatus.INVALID_OR_NOT_PRESENT;
appView.options().reporter.warning(diagnostics);
return false;
}
diff --git a/src/main/java/com/android/tools/r8/graph/CfCodeDiagnostics.java b/src/main/java/com/android/tools/r8/graph/CfCodeDiagnostics.java
index 764a812..8a664ec 100644
--- a/src/main/java/com/android/tools/r8/graph/CfCodeDiagnostics.java
+++ b/src/main/java/com/android/tools/r8/graph/CfCodeDiagnostics.java
@@ -30,7 +30,7 @@
private final MethodPosition methodPosition;
private final String diagnosticMessage;
- CfCodeDiagnostics(Origin origin, DexMethod method, String diagnosticMessage) {
+ public CfCodeDiagnostics(Origin origin, DexMethod method, String diagnosticMessage) {
this.origin = origin;
this.methodPosition = new MethodPosition(method.asMethodReference());
this.diagnosticMessage = diagnosticMessage;
diff --git a/src/main/java/com/android/tools/r8/graph/CfCodeStackMapValidatingException.java b/src/main/java/com/android/tools/r8/graph/CfCodeStackMapValidatingException.java
index 6c54a1a..b6d1b1e 100644
--- a/src/main/java/com/android/tools/r8/graph/CfCodeStackMapValidatingException.java
+++ b/src/main/java/com/android/tools/r8/graph/CfCodeStackMapValidatingException.java
@@ -13,8 +13,8 @@
super(message);
}
- public static CfCodeStackMapValidatingException error(String messsage) {
- return new CfCodeStackMapValidatingException(messsage);
+ public static CfCodeStackMapValidatingException error(String message) {
+ return new CfCodeStackMapValidatingException(message);
}
public static CfCodeDiagnostics unexpectedStackMapFrame(
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedField.java b/src/main/java/com/android/tools/r8/graph/DexEncodedField.java
index 7683f12..8068417 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedField.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedField.java
@@ -27,6 +27,7 @@
public final DexField field;
public final FieldAccessFlags accessFlags;
private DexValue staticValue;
+ private final boolean deprecated;
private FieldOptimizationInfo optimizationInfo = DefaultFieldOptimizationInfo.getInstance();
private KotlinFieldLevelInfo kotlinMemberInfo = NO_KOTLIN_INFO;
@@ -35,17 +36,31 @@
DexField field,
FieldAccessFlags accessFlags,
DexAnnotationSet annotations,
- DexValue staticValue) {
+ DexValue staticValue,
+ boolean deprecated) {
super(annotations);
this.field = field;
this.accessFlags = accessFlags;
this.staticValue = staticValue;
+ this.deprecated = deprecated;
+ }
+
+ public DexEncodedField(
+ DexField field,
+ FieldAccessFlags accessFlags,
+ DexAnnotationSet annotations,
+ DexValue staticValue) {
+ this(field, accessFlags, annotations, staticValue, false);
}
public DexType type() {
return field.type;
}
+ public boolean isDeprecated() {
+ return deprecated;
+ }
+
public boolean isProgramField(DexDefinitionSupplier definitions) {
if (field.holder.isClassType()) {
DexClass clazz = definitions.definitionFor(field.holder);
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
index f049ec5..24776d0 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -139,6 +139,7 @@
public final DexMethod method;
public final MethodAccessFlags accessFlags;
+ public final boolean deprecated;
public ParameterAnnotationsList parameterAnnotationsList;
private Code code;
// TODO(b/128967328): towards finer-grained inlining constraints,
@@ -227,7 +228,7 @@
DexAnnotationSet annotations,
ParameterAnnotationsList parameterAnnotationsList,
Code code) {
- this(method, accessFlags, annotations, parameterAnnotationsList, code, -1);
+ this(method, accessFlags, annotations, parameterAnnotationsList, code, false, -1);
}
public DexEncodedMethod(
@@ -236,8 +237,27 @@
DexAnnotationSet annotations,
ParameterAnnotationsList parameterAnnotationsList,
Code code,
+ boolean d8R8Synthesized) {
+ this(method, accessFlags, annotations, parameterAnnotationsList, code, d8R8Synthesized, -1);
+ }
+
+ public DexEncodedMethod(
+ DexMethod method,
+ MethodAccessFlags accessFlags,
+ DexAnnotationSet annotations,
+ ParameterAnnotationsList parameterAnnotationsList,
+ Code code,
+ boolean d8R8Synthesized,
int classFileVersion) {
- this(method, accessFlags, annotations, parameterAnnotationsList, code, classFileVersion, false);
+ this(
+ method,
+ accessFlags,
+ annotations,
+ parameterAnnotationsList,
+ code,
+ d8R8Synthesized,
+ classFileVersion,
+ false);
}
public DexEncodedMethod(
@@ -246,21 +266,13 @@
DexAnnotationSet annotations,
ParameterAnnotationsList parameterAnnotationsList,
Code code,
- boolean d8R8Synthesized) {
- this(method, accessFlags, annotations, parameterAnnotationsList, code, -1, d8R8Synthesized);
- }
-
- public DexEncodedMethod(
- DexMethod method,
- MethodAccessFlags accessFlags,
- DexAnnotationSet annotations,
- ParameterAnnotationsList parameterAnnotationsList,
- Code code,
+ boolean d8R8Synthesized,
int classFileVersion,
- boolean d8R8Synthesized) {
+ boolean deprecated) {
super(annotations);
this.method = method;
this.accessFlags = accessFlags;
+ this.deprecated = deprecated;
this.parameterAnnotationsList = parameterAnnotationsList;
this.code = code;
this.classFileVersion = classFileVersion;
@@ -270,6 +282,10 @@
assert parameterAnnotationsList != null;
}
+ public boolean isDeprecated() {
+ return deprecated;
+ }
+
public void hashSyntheticContent(Hasher hasher) {
// Method holder does not contribute to the synthetic hash (it is freely chosen).
// Method name does not contribute to the synthetic hash (it is freely chosen).
@@ -1511,8 +1527,8 @@
annotations,
parameterAnnotations,
code,
- classFileVersion,
- d8R8Synthesized);
+ d8R8Synthesized,
+ classFileVersion);
result.setKotlinMemberInfo(kotlinMemberInfo);
result.compilationState = compilationState;
result.optimizationInfo = optimizationInfo;
diff --git a/src/main/java/com/android/tools/r8/graph/DexProgramClass.java b/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
index ca7a264..68da447 100644
--- a/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
@@ -45,6 +45,7 @@
private final ProgramResource.Kind originKind;
private final Collection<DexProgramClass> synthesizedFrom;
private int initialClassFileVersion = -1;
+ private boolean deprecated = false;
private KotlinClassLevelInfo kotlinInfo = NO_KOTLIN_INFO;
private final ChecksumSupplier checksumSupplier;
@@ -516,6 +517,14 @@
return initialClassFileVersion;
}
+ public void setDeprecated() {
+ deprecated = true;
+ }
+
+ public boolean isDeprecated() {
+ return deprecated;
+ }
+
/**
* Is the class reachability sensitive.
*
diff --git a/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java b/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java
index 2b38f4f..ea58f8d 100644
--- a/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java
+++ b/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java
@@ -35,6 +35,7 @@
import com.android.tools.r8.jar.CfApplicationWriter;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.shaking.ProguardKeepAttributes;
+import com.android.tools.r8.utils.AsmUtils;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.ExceptionUtils;
import com.android.tools.r8.utils.FieldSignatureEquivalence;
@@ -195,6 +196,7 @@
// DexClass data.
private int version;
+ private boolean deprecated;
private DexType type;
private ClassAccessFlags accessFlags;
private DexType superType;
@@ -301,6 +303,7 @@
if (InternalOptions.SUPPORTED_CF_MAJOR_VERSION < getMajorVersion()) {
throw new CompilationError("Unsupported class file version: " + getMajorVersion(), origin);
}
+ this.deprecated = AsmUtils.isDeprecated(access);
accessFlags = ClassAccessFlags.fromCfAccessFlags(cleanAccessFlags(access));
type = application.getTypeFromName(name);
// Check if constraints from
@@ -449,6 +452,9 @@
if (clazz.isProgramClass()) {
DexProgramClass programClass = clazz.asProgramClass();
programClass.setInitialClassFileVersion(version);
+ if (deprecated) {
+ programClass.setDeprecated();
+ }
}
classConsumer.accept(clazz);
}
@@ -587,7 +593,9 @@
DexAnnotationSet annotationSet =
createAnnotationSet(annotations, parent.application.options);
DexValue staticValue = flags.isStatic() ? getStaticValue(value, dexField.type) : null;
- DexEncodedField field = new DexEncodedField(dexField, flags, annotationSet, staticValue);
+ DexEncodedField field =
+ new DexEncodedField(
+ dexField, flags, annotationSet, staticValue, AsmUtils.isDeprecated(access));
if (flags.isStatic()) {
parent.staticFields.add(field);
} else {
@@ -662,6 +670,7 @@
private List<DexValue> parameterFlags = null;
final DexMethod method;
final MethodAccessFlags flags;
+ final boolean deprecated;
Code code = null;
public CreateMethodVisitor(int access, String name, String desc, String signature,
@@ -671,6 +680,7 @@
this.parent = parent;
this.method = parent.application.getMethod(parent.type, name, desc);
this.flags = createMethodAccessFlags(name, access);
+ this.deprecated = AsmUtils.isDeprecated(access);
parameterCount = DescriptorUtils.getArgumentCount(desc);
if (exceptions != null && exceptions.length > 0) {
DexValue[] values = new DexValue[exceptions.length];
@@ -813,7 +823,9 @@
createAnnotationSet(annotations, options),
parameterAnnotationsList,
code,
- parent.version);
+ false,
+ parent.version,
+ deprecated);
Wrapper<DexMethod> signature = MethodSignatureEquivalence.get().wrap(method);
if (parent.methodSignatures.add(signature)) {
parent.hasReachabilitySensitiveMethod |= isReachabilitySensitive();
diff --git a/src/main/java/com/android/tools/r8/graph/LazyCfCode.java b/src/main/java/com/android/tools/r8/graph/LazyCfCode.java
index f783b63..e0aace9 100644
--- a/src/main/java/com/android/tools/r8/graph/LazyCfCode.java
+++ b/src/main/java/com/android/tools/r8/graph/LazyCfCode.java
@@ -212,8 +212,7 @@
@Override
public IRCode buildIR(ProgramMethod method, AppView<?> appView, Origin origin) {
- return verifyFrames(asCfCode(), method.getDefinition(), appView, origin, true)
- .buildIR(method, appView, origin);
+ return asCfCode().buildIR(method, appView, origin);
}
@Override
@@ -225,12 +224,7 @@
Position callerPosition,
Origin origin,
MethodProcessor methodProcessor) {
- return verifyFrames(
- asCfCode(),
- method.getDefinition(),
- appView,
- origin,
- methodProcessor.shouldApplyCodeRewritings(method))
+ return asCfCode()
.buildInliningIR(
context,
method,
@@ -241,20 +235,6 @@
methodProcessor);
}
- private CfCode verifyFrames(
- CfCode cfCode,
- DexEncodedMethod method,
- AppView<?> appView,
- Origin origin,
- boolean shouldApplyCodeRewritings) {
- if (!cfCode.verifyFrames(method, appView, origin, shouldApplyCodeRewritings)) {
- ArrayList<CfInstruction> newInstructions = new ArrayList<>(cfCode.getInstructions());
- newInstructions.removeIf(CfInstruction::isFrame);
- cfCode.setInstructions(newInstructions);
- }
- return cfCode;
- }
-
@Override
public void registerCodeReferences(ProgramMethod method, UseRegistry registry) {
asCfCode().registerCodeReferences(method, registry);
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/ConstructorMerger.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/ConstructorMerger.java
index 2f3c068..37e1690 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/ConstructorMerger.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/ConstructorMerger.java
@@ -165,8 +165,8 @@
DexAnnotationSet.empty(),
ParameterAnnotationsList.empty(),
synthesizedCode,
- classFileVersion,
- true);
+ true,
+ classFileVersion);
if (isTrivialMerge()) {
// The constructor does not require the additional argument, just map it like a regular
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/VirtualMethodMerger.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/VirtualMethodMerger.java
index fd998a5..c8f2f6d 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/VirtualMethodMerger.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/VirtualMethodMerger.java
@@ -170,8 +170,8 @@
DexAnnotationSet.empty(),
ParameterAnnotationsList.empty(),
synthesizedCode,
- classFileVersion,
- true);
+ true,
+ classFileVersion);
// Map each old method to the newly synthesized method in the graph lens.
for (ProgramMethod oldMethod : methods) {
diff --git a/src/main/java/com/android/tools/r8/ir/code/Phi.java b/src/main/java/com/android/tools/r8/ir/code/Phi.java
index cd5cb77..c1de847 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Phi.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Phi.java
@@ -123,7 +123,7 @@
operands.add(operand);
}
- if (readType != RegisterReadType.NORMAL) {
+ if (readType == RegisterReadType.DEBUG) {
for (Value operand : operands) {
TypeElement type = operand.getType();
ValueTypeConstraint constraint = TypeConstraintResolver.constraintForType(type);
@@ -397,7 +397,7 @@
return operands.indexOf(usedValue) == operands.lastIndexOf(usedValue);
}
- public DexType computeVerificationType(TypeVerificationHelper helper) {
+ public DexType computeVerificationType(AppView<?> appView, TypeVerificationHelper helper) {
assert outType().isObject();
Set<DexType> operandTypes = new HashSet<>(operands.size());
for (Value operand : operands) {
@@ -447,4 +447,38 @@
}
return result;
}
+
+ // TODO(b/169120386) This class is added to ensure we do not narrow or widen phi's in D8 when
+ // having stack map information. It should be removed when we are certain to never widen or
+ // narrowing phi's in D8.
+ public static class StackMapPhi extends Phi {
+
+ public StackMapPhi(
+ int number,
+ BasicBlock block,
+ TypeElement type,
+ DebugLocalInfo local,
+ RegisterReadType readType) {
+ super(number, block, type, local, readType);
+ }
+
+ @Override
+ public DexType computeVerificationType(AppView<?> appView, TypeVerificationHelper helper) {
+ assert !appView.enableWholeProgramOptimizations();
+ if (type.isPrimitiveType()) {
+ return type.asPrimitiveType().toDexType(appView.dexItemFactory());
+ } else if (type.isArrayType()) {
+ return type.asArrayType().toDexType(appView.dexItemFactory());
+ } else {
+ assert type.isClassType();
+ return type.asClassType().getClassType();
+ }
+ }
+
+ @Override
+ public TypeElement computePhiType(AppView<?> appView) {
+ assert !appView.enableWholeProgramOptimizations();
+ return type;
+ }
+ }
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/Value.java b/src/main/java/com/android/tools/r8/ir/code/Value.java
index c2a63d4..b842c63 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Value.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Value.java
@@ -1027,7 +1027,7 @@
public void widening(AppView<?> appView, TypeElement newType) {
// During WIDENING (due to fix-point iteration), type update is monotonically upwards,
// i.e., towards something wider.
- assert this.type.lessThanOrEqual(newType, appView)
+ assert skipWideningOrNarrowingCheck(appView) || this.type.lessThanOrEqual(newType, appView)
: "During WIDENING, "
+ newType
+ " < "
@@ -1040,9 +1040,7 @@
public void narrowing(AppView<?> appView, TypeElement newType) {
// During NARROWING (e.g., after inlining), type update is monotonically downwards,
// i.e., towards something narrower, with more specific type info.
- assert (!appView.options().testing.enableNarrowingChecksInD8
- && !appView.enableWholeProgramOptimizations())
- || !this.type.strictlyLessThan(newType, appView)
+ assert skipWideningOrNarrowingCheck(appView) || !this.type.strictlyLessThan(newType, appView)
: "During NARROWING, "
+ type
+ " < "
@@ -1052,6 +1050,12 @@
setType(newType);
}
+ private boolean skipWideningOrNarrowingCheck(AppView<?> appView) {
+ // TODO(b/169120386): We should not check widening or narrowing when in D8 with valid type-info.
+ return !appView.options().testing.enableNarrowAndWideningingChecksInD8
+ && !appView.enableWholeProgramOptimizations();
+ }
+
public BasicBlock getBlock() {
return definition.getBlock();
}
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/CfSourceCode.java b/src/main/java/com/android/tools/r8/ir/conversion/CfSourceCode.java
index 36c4111..6deea80 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/CfSourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/CfSourceCode.java
@@ -20,6 +20,8 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.CfCode.LocalVariableInfo;
+import com.android.tools.r8.graph.CfCode.StackMapStatus;
+import com.android.tools.r8.graph.CfCodeDiagnostics;
import com.android.tools.r8.graph.DebugLocalInfo;
import com.android.tools.r8.graph.DebugLocalInfo.PrintLevel;
import com.android.tools.r8.graph.DexEncodedMethod;
@@ -30,8 +32,10 @@
import com.android.tools.r8.ir.code.CanonicalPositions;
import com.android.tools.r8.ir.code.CatchHandlers;
import com.android.tools.r8.ir.code.Monitor;
+import com.android.tools.r8.ir.code.Phi.RegisterReadType;
import com.android.tools.r8.ir.code.Position;
import com.android.tools.r8.ir.code.ValueType;
+import com.android.tools.r8.ir.code.ValueTypeConstraint;
import com.android.tools.r8.ir.conversion.CfState.Slot;
import com.android.tools.r8.ir.conversion.CfState.Snapshot;
import com.android.tools.r8.ir.conversion.IRBuilder.BlockInfo;
@@ -210,6 +214,7 @@
private TryHandlerList cachedTryHandlerList;
private LocalVariableList cachedLocalVariableList;
private int currentInstructionIndex;
+ private int currentBlockIndex;
private boolean inPrelude;
private Int2ReferenceMap<DebugLocalInfo> incomingLocals;
private Int2ReferenceMap<DebugLocalInfo> outgoingLocals;
@@ -526,6 +531,7 @@
incomingState.get(instructionIndex),
instructionIndex == 0,
getCanonicalDebugPositionAtOffset(instructionIndex));
+ currentBlockIndex = currentInstructionIndex;
}
assert currentBlockInfo != null;
@@ -613,8 +619,13 @@
for (FrameType frameType : frame.getStack()) {
stack[index++] = convertUninitialized(frameType);
}
- state.setStateFromFrame(
- locals, stack, getCanonicalDebugPositionAtOffset(currentInstructionIndex));
+ // TODO(b/169135126) Assert that all values are precise.
+ Snapshot snapshot =
+ state.setStateFromFrame(
+ locals, stack, getCanonicalDebugPositionAtOffset(currentInstructionIndex));
+ // Update the incoming state as well with precise information.
+ assert incomingState.get(currentBlockIndex) != null;
+ incomingState.put(currentBlockIndex, snapshot);
}
private DexType convertUninitialized(FrameType type) {
@@ -659,6 +670,74 @@
}
@Override
+ public DexType getPhiTypeForBlock(
+ int register, int blockOffset, ValueTypeConstraint constraint, RegisterReadType readType) {
+ assert code.getStackMapStatus() != StackMapStatus.NOT_VERIFIED;
+ if (code.getStackMapStatus() == StackMapStatus.INVALID_OR_NOT_PRESENT) {
+ return null;
+ }
+ // We should be able to find the a snapshot at the block-offset:
+ Snapshot snapshot = incomingState.get(blockOffset);
+ if (snapshot == null) {
+ appView
+ .options()
+ .reporter
+ .warning(
+ new CfCodeDiagnostics(
+ origin,
+ method.getReference(),
+ "Could not find stack map for block at offset "
+ + blockOffset
+ + ". This is most likely due to invalid"
+ + " stack maps in input."));
+ return null;
+ }
+ // TODO(b/169135126) Assert that all values are precise.
+ Slot slot =
+ Slot.isStackSlot(register)
+ ? snapshot.getStack(Slot.stackPosition(register))
+ : snapshot.getLocal(register);
+ if (slot == null) {
+ if (readType == RegisterReadType.DEBUG) {
+ DebugLocalInfo incomingLocalAtBlock = getIncomingLocalAtBlock(register, blockOffset);
+ if (incomingLocalAtBlock != null) {
+ return incomingLocalAtBlock.type;
+ }
+ // TODO(b/b/169137397): The local ranges are not defined on the block. We should investigate
+ // the impact of this when debugging. For now, make a final attempt at finding a local
+ // variable with specified register.
+ List<LocalVariableInfo> localVariablesWithRegister = new ArrayList<>();
+ for (LocalVariableInfo variable : localVariables) {
+ if (variable.getIndex() == register) {
+ localVariablesWithRegister.add(variable);
+ }
+ }
+ if (localVariablesWithRegister.size() == 1) {
+ return localVariablesWithRegister.get(0).getLocal().type;
+ }
+ }
+ appView
+ .options()
+ .reporter
+ .warning(
+ new CfCodeDiagnostics(
+ origin,
+ method.getReference(),
+ "Could not find phi type for register "
+ + register
+ + ". This is most likely due to invalid stack maps in input."));
+ return null;
+ }
+ if (slot.isPrecise()) {
+ return slot.preciseType;
+ }
+ // TODO(b/169135126): We should be able to remove this when having valid stack maps.
+ return slot.type.isObject()
+ ? appView.dexItemFactory().objectType
+ : slot.type.toPrimitiveType().toDexType(appView.dexItemFactory());
+ }
+
+ @Override
public DebugLocalInfo getIncomingLocal(int register) {
return isCurrentlyGeneratingMethodSynchronization() ? null : incomingLocals.get(register);
}
@@ -774,6 +853,11 @@
}
@Override
+ public boolean hasValidTypesFromStackMap() {
+ return code.getStackMapStatus() == StackMapStatus.VALID;
+ }
+
+ @Override
public Position getCanonicalDebugPositionAtOffset(int offset) {
if (offset == EXCEPTIONAL_SYNC_EXIT_OFFSET) {
return canonicalPositions.getExceptionalExitPosition(
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/CfState.java b/src/main/java/com/android/tools/r8/ir/conversion/CfState.java
index 0f111de..353faac 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/CfState.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/CfState.java
@@ -17,6 +17,10 @@
public abstract ValueType getImprecise();
+ public boolean isPrecise() {
+ return false;
+ }
+
private static class Precise extends SlotType {
private final DexType type;
@@ -38,6 +42,11 @@
public String toString() {
return "Precise(" + type + ")";
}
+
+ @Override
+ public boolean isPrecise() {
+ return true;
+ }
}
private static class Imprecise extends SlotType {
@@ -90,9 +99,11 @@
this.position = position;
}
- public void setStateFromFrame(DexType[] locals, DexType[] stack, Position position) {
+ public BaseSnapshot setStateFromFrame(DexType[] locals, DexType[] stack, Position position) {
assert current == null || stackHeight() == stack.length;
- current = new BaseSnapshot(locals, stack, position);
+ BaseSnapshot newSnapShot = new BaseSnapshot(locals, stack, position);
+ this.current = newSnapShot;
+ return newSnapShot;
}
public void merge(Snapshot snapshot) {
@@ -233,10 +244,6 @@
public final DexType preciseType;
private final SlotType slotType;
- private Slot(int register, DexType preciseType) {
- this(register, new SlotType.Precise(preciseType));
- }
-
private Slot(int register, SlotType type) {
this.register = register;
this.slotType = type;
@@ -249,6 +256,11 @@
}
private int stackPosition() {
+ return stackPosition(register);
+ }
+
+ public static int stackPosition(int register) {
+ assert isStackSlot(register);
assert register >= STACK_OFFSET;
return register - STACK_OFFSET;
}
@@ -259,6 +271,18 @@
? register + "=" + slotType
: "s" + (register - STACK_OFFSET) + "=" + slotType;
}
+
+ public boolean isStackSlot() {
+ return isStackSlot(register);
+ }
+
+ public static boolean isStackSlot(int register) {
+ return register >= STACK_OFFSET;
+ }
+
+ public boolean isPrecise() {
+ return slotType.isPrecise();
+ }
}
public abstract static class Snapshot {
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
index f2da1ac..6382b86 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
@@ -14,6 +14,7 @@
import static com.android.tools.r8.ir.analysis.type.TypeElement.getNull;
import static com.android.tools.r8.ir.analysis.type.TypeElement.getSingle;
import static com.android.tools.r8.ir.analysis.type.TypeElement.getWide;
+import static org.objectweb.asm.Opcodes.V1_8;
import com.android.tools.r8.ApiLevelException;
import com.android.tools.r8.errors.CompilationError;
@@ -97,6 +98,7 @@
import com.android.tools.r8.ir.code.Or;
import com.android.tools.r8.ir.code.Phi;
import com.android.tools.r8.ir.code.Phi.RegisterReadType;
+import com.android.tools.r8.ir.code.Phi.StackMapPhi;
import com.android.tools.r8.ir.code.Position;
import com.android.tools.r8.ir.code.Rem;
import com.android.tools.r8.ir.code.Return;
@@ -176,10 +178,6 @@
}
}
- public TypeElement getTypeLattice(DexType type, Nullability nullability) {
- return TypeElement.fromDexType(type, nullability, appView);
- }
-
// SSA construction uses a worklist of basic blocks reachable from the entry and their
// instruction offsets.
private static class WorklistItem {
@@ -415,14 +413,15 @@
// Lazily populated list of local values that are referenced without being actually defined.
private Int2ReferenceMap<List<Value>> uninitializedDebugLocalValues = null;
- private int nextBlockNumber = 0;
-
// Flag indicating if any instructions have imprecise internal types (eg, int|float member types)
private List<ImpreciseMemberTypeInstruction> impreciseInstructions = null;
// Flag indicating if any values have imprecise types.
private boolean hasImpreciseValues = false;
+ // Flag indicating incorrect reading of stack map phi types.
+ private boolean hasIncorrectStackMapTypes = false;
+
// Information about which kinds of instructions that may be present in the IR. This information
// is sound (i.e., if the IR has a const-string instruction then metadata.mayHaveConstString()
// returns true) but not necessarily complete (i.e., if metadata.mayHaveConstString() returns true
@@ -720,9 +719,13 @@
// In DEX we may need to constrain all values and instructions to precise types.
assert source instanceof DexSourceCode;
new TypeConstraintResolver(appView, this).resolve(impreciseInstructions, ir);
- } else {
+ } else if (!canUseStackMapTypes() || hasIncorrectStackMapTypes) {
+ // TODO(b/169137397): We may have ended up generating StackMapPhi's before concluding
+ // having incorrect stack map types. Figure out a way to clean that up.
new TypeAnalysis(appView).widening(ir);
}
+ // TODO(b/169137397): If we have canUseStackMapTypes() && !hasIncorrectStackMapTypes we should
+ // have that all phi's are stack-map phis.
// Update the IR code if collected call site optimization info has something useful.
// While aggregation of parameter information at call sites would be more precise than static
@@ -747,6 +750,11 @@
return ir;
}
+ public boolean canUseStackMapTypes() {
+ // TODO(b/168592290): See if we can get using stack map types to work with R8.
+ return !appView.enableWholeProgramOptimizations() && source.hasValidTypesFromStackMap();
+ }
+
public void constrainType(Value value, ValueTypeConstraint constraint) {
value.constrainType(constraint, method.getReference(), origin, appView.options().reporter);
}
@@ -1123,7 +1131,19 @@
public void addArrayGet(MemberType type, int dest, int array, int index) {
Value in1 = readRegister(array, ValueTypeConstraint.OBJECT);
Value in2 = readRegister(index, ValueTypeConstraint.INT);
- TypeElement typeLattice = fromMemberType(type);
+ TypeElement typeLattice;
+ if (type == MemberType.OBJECT && canUseStackMapTypes()) {
+ if (in1.getType().isNullType()) {
+ typeLattice = TypeElement.getNull();
+ } else if (in1.getType().isArrayType()) {
+ typeLattice = in1.getType().asArrayType().getMemberType();
+ } else {
+ assert in1.getType().isBottom() && hasIncorrectStackMapTypes;
+ typeLattice = fromMemberType(type);
+ }
+ } else {
+ typeLattice = fromMemberType(type);
+ }
Value out = writeRegister(dest, typeLattice, ThrowingInfo.CAN_THROW);
ArrayGet instruction = new ArrayGet(type, out, in1, in2);
assert instruction.instructionTypeCanThrow();
@@ -2164,9 +2184,28 @@
value = getUninitializedDebugLocalValue(register, constraint);
} else {
DebugLocalInfo local = getIncomingLocalAtBlock(register, block);
- TypeElement phiType = TypeConstraintResolver.typeForConstraint(constraint);
- hasImpreciseValues |= !phiType.isPreciseType();
- Phi phi = new Phi(valueNumberGenerator.next(), block, phiType, local, readType);
+ TypeElement constrainedType = TypeConstraintResolver.typeForConstraint(constraint);
+ hasImpreciseValues |= !constrainedType.isPreciseType();
+ Phi phi = null;
+ if (canUseStackMapTypes() && !hasIncorrectStackMapTypes) {
+ DexType phiTypeForBlock =
+ source.getPhiTypeForBlock(register, offsets.getInt(block), constraint, readType);
+ if (phiTypeForBlock != null) {
+ phi =
+ new StackMapPhi(
+ valueNumberGenerator.next(),
+ block,
+ TypeElement.fromDexType(phiTypeForBlock, Nullability.maybeNull(), appView),
+ local,
+ readType);
+ } else {
+ assert method.getDefinition().getClassFileVersion() < V1_8;
+ hasIncorrectStackMapTypes = true;
+ }
+ }
+ if (phi == null) {
+ phi = new Phi(valueNumberGenerator.next(), block, constrainedType, local, readType);
+ }
if (!block.isSealed()) {
block.addIncompletePhi(register, phi, readingEdge);
value = phi;
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 100131c..8db8c01 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
@@ -1132,9 +1132,13 @@
return false;
}
boolean didDesugar = false;
+ Supplier<AppInfoWithClassHierarchy> lazyAppInfo =
+ Suppliers.memoize(() -> appView.appInfoForDesugaring());
if (lambdaRewriter != null) {
- AppInfoWithClassHierarchy appInfo = appView.appInfoForDesugaring();
- didDesugar |= lambdaRewriter.desugarLambdas(method, appInfo) > 0;
+ didDesugar |= lambdaRewriter.desugarLambdas(method, lazyAppInfo.get()) > 0;
+ }
+ if (backportedMethodRewriter != null) {
+ didDesugar |= backportedMethodRewriter.desugar(method, lazyAppInfo.get());
}
return didDesugar;
}
@@ -1420,12 +1424,6 @@
timing.end();
}
- if (backportedMethodRewriter != null) {
- timing.begin("Rewrite backport methods");
- backportedMethodRewriter.desugar(code);
- timing.end();
- }
-
timing.begin("Desugar string concat");
stringConcatRewriter.desugarStringConcats(method.method, code);
timing.end();
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/SourceCode.java b/src/main/java/com/android/tools/r8/ir/conversion/SourceCode.java
index df2b663..e3b69b7 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/SourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/SourceCode.java
@@ -5,8 +5,11 @@
package com.android.tools.r8.ir.conversion;
import com.android.tools.r8.graph.DebugLocalInfo;
+import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.code.CatchHandlers;
+import com.android.tools.r8.ir.code.Phi.RegisterReadType;
import com.android.tools.r8.ir.code.Position;
+import com.android.tools.r8.ir.code.ValueTypeConstraint;
/**
* Abstraction of the input/source code for the IRBuilder.
@@ -23,6 +26,11 @@
DebugLocalInfo getIncomingLocalAtBlock(int register, int blockOffset);
+ default DexType getPhiTypeForBlock(
+ int register, int blockOffset, ValueTypeConstraint constraint, RegisterReadType readType) {
+ return null;
+ }
+
DebugLocalInfo getIncomingLocal(int register);
DebugLocalInfo getOutgoingLocal(int register);
@@ -71,4 +79,8 @@
boolean verifyRegister(int register);
boolean verifyCurrentInstructionCanThrow();
boolean verifyLocalInScope(DebugLocalInfo local);
+
+ default boolean hasValidTypesFromStackMap() {
+ return false;
+ }
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
index da1a799..1f41aa4 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
@@ -4,27 +4,25 @@
package com.android.tools.r8.ir.desugar;
-
+import com.android.tools.r8.cf.code.CfInstruction;
+import com.android.tools.r8.cf.code.CfInvoke;
import com.android.tools.r8.dex.ApplicationReader;
import com.android.tools.r8.dex.Constants;
+import com.android.tools.r8.errors.Unreachable;
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.CfCode;
import com.android.tools.r8.graph.Code;
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.MethodAccessFlags;
import com.android.tools.r8.graph.ProgramMethod;
-import com.android.tools.r8.ir.analysis.type.TypeAnalysis;
-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.InvokeMethod;
-import com.android.tools.r8.ir.code.InvokeStatic;
-import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.ir.conversion.IRConverter;
import com.android.tools.r8.ir.desugar.backports.BackportedMethods;
import com.android.tools.r8.ir.desugar.backports.BooleanMethodRewrites;
@@ -40,19 +38,19 @@
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.InternalOptions.DesugarState;
import com.android.tools.r8.utils.Timing;
-import com.google.common.collect.Sets;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.List;
+import java.util.ListIterator;
import java.util.Map;
import java.util.Queue;
-import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.function.Consumer;
+import org.objectweb.asm.Opcodes;
public final class BackportedMethodRewriter {
@@ -111,29 +109,34 @@
BackportedMethods.registerSynthesizedCodeReferences(options.itemFactory);
}
- public void desugar(IRCode code) {
+ public boolean desugar(ProgramMethod method, AppInfoWithClassHierarchy appInfo) {
if (!enabled) {
- return; // Nothing to do!
+ return false;
}
- Set<Value> affectedValues = Sets.newIdentityHashSet();
- InstructionListIterator iterator = code.instructionListIterator();
+ CfCode code = method.getDefinition().getCode().asCfCode();
+ ListIterator<CfInstruction> iterator = code.getInstructions().listIterator();
+ boolean replaced = false;
while (iterator.hasNext()) {
- Instruction instruction = iterator.next();
- if (!instruction.isInvokeMethod()) {
+ CfInvoke invoke = iterator.next().asInvoke();
+ if (invoke == null) {
continue;
}
-
- InvokeMethod invoke = instruction.asInvokeMethod();
- DexMethod invokedMethod = invoke.getInvokedMethod();
+ DexMethod invokedMethod = invoke.getMethod();
MethodProvider provider = getMethodProviderOrNull(invokedMethod);
if (provider != null) {
+ if (!replaced) {
+ // Create mutable instructions on first write.
+ ArrayList<CfInstruction> mutableInstructions = new ArrayList<>(code.getInstructions());
+ code.setInstructions(mutableInstructions);
+ iterator = mutableInstructions.listIterator(iterator.previousIndex());
+ iterator.next();
+ }
provider.rewriteInvoke(
- invoke, iterator, code, appView, affectedValues, synthesizedMethods::add);
+ invoke, iterator, method.getHolder(), appInfo, synthesizedMethods::add);
+ replaced = true;
}
}
- if (!affectedValues.isEmpty()) {
- new TypeAnalysis(appView).narrowing(affectedValues);
- }
+ return replaced;
}
public void processSynthesizedClasses(IRConverter converter, ExecutorService executor)
@@ -248,7 +251,7 @@
name = factory.createString("compare");
proto = factory.createProto(factory.intType, factory.longType, factory.longType);
method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, LongMethodRewrites::rewriteCompare));
+ addProvider(new InvokeRewriter(method, LongMethodRewrites.rewriteCompare()));
// Boolean
type = factory.boxedBooleanType;
@@ -293,7 +296,7 @@
name = factory.createString("hash");
proto = factory.createProto(factory.intType, factory.objectArrayType);
method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, ObjectsMethodRewrites::rewriteToArraysHashCode));
+ addProvider(new InvokeRewriter(method, ObjectsMethodRewrites.rewriteToArraysHashCode()));
// int Objects.hashCode(Object o)
name = factory.createString("hashCode");
@@ -303,7 +306,7 @@
// T Objects.requireNonNull(T obj)
method = factory.objectsMethods.requireNonNull;
- addProvider(new InvokeRewriter(method, ObjectsMethodRewrites::rewriteRequireNonNull));
+ addProvider(new InvokeRewriter(method, ObjectsMethodRewrites.rewriteRequireNonNull()));
// T Objects.requireNonNull(T obj, String message)
name = factory.createString("requireNonNull");
@@ -360,7 +363,7 @@
DexString name = factory.createString("hashCode");
DexProto proto = factory.createProto(factory.intType, factory.byteType);
DexMethod method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, NumericMethodRewrites::rewriteAsIdentity));
+ addProvider(new InvokeRewriter(method, NumericMethodRewrites.rewriteAsIdentity()));
// Short
type = factory.boxedShortType;
@@ -368,7 +371,7 @@
name = factory.createString("hashCode");
proto = factory.createProto(factory.intType, factory.shortType);
method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, NumericMethodRewrites::rewriteAsIdentity));
+ addProvider(new InvokeRewriter(method, NumericMethodRewrites.rewriteAsIdentity()));
// Integer
type = factory.boxedIntType;
@@ -377,25 +380,25 @@
name = factory.createString("hashCode");
proto = factory.createProto(factory.intType, factory.intType);
method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, NumericMethodRewrites::rewriteAsIdentity));
+ addProvider(new InvokeRewriter(method, NumericMethodRewrites.rewriteAsIdentity()));
// int Integer.max(int a, int b)
name = factory.createString("max");
proto = factory.createProto(factory.intType, factory.intType, factory.intType);
method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, NumericMethodRewrites::rewriteToInvokeMath));
+ addProvider(new InvokeRewriter(method, NumericMethodRewrites.rewriteToInvokeMath()));
// int Integer.min(int a, int b)
name = factory.createString("min");
proto = factory.createProto(factory.intType, factory.intType, factory.intType);
method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, NumericMethodRewrites::rewriteToInvokeMath));
+ addProvider(new InvokeRewriter(method, NumericMethodRewrites.rewriteToInvokeMath()));
// int Integer.sum(int a, int b)
name = factory.createString("sum");
proto = factory.createProto(factory.intType, factory.intType, factory.intType);
method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, NumericMethodRewrites::rewriteToAddInstruction));
+ addProvider(new InvokeRewriter(method, NumericMethodRewrites.rewriteToAddInstruction()));
// Double
type = factory.boxedDoubleType;
@@ -410,19 +413,19 @@
name = factory.createString("max");
proto = factory.createProto(factory.doubleType, factory.doubleType, factory.doubleType);
method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, NumericMethodRewrites::rewriteToInvokeMath));
+ addProvider(new InvokeRewriter(method, NumericMethodRewrites.rewriteToInvokeMath()));
// double Double.min(double a, double b)
name = factory.createString("min");
proto = factory.createProto(factory.doubleType, factory.doubleType, factory.doubleType);
method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, NumericMethodRewrites::rewriteToInvokeMath));
+ addProvider(new InvokeRewriter(method, NumericMethodRewrites.rewriteToInvokeMath()));
// double Double.sum(double a, double b)
name = factory.createString("sum");
proto = factory.createProto(factory.doubleType, factory.doubleType, factory.doubleType);
method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, NumericMethodRewrites::rewriteToAddInstruction));
+ addProvider(new InvokeRewriter(method, NumericMethodRewrites.rewriteToAddInstruction()));
// boolean Double.isFinite(double a)
name = factory.createString("isFinite");
@@ -437,25 +440,25 @@
name = factory.createString("hashCode");
proto = factory.createProto(factory.intType, factory.floatType);
method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, FloatMethodRewrites::rewriteHashCode));
+ addProvider(new InvokeRewriter(method, FloatMethodRewrites.rewriteHashCode()));
// float Float.max(float a, float b)
name = factory.createString("max");
proto = factory.createProto(factory.floatType, factory.floatType, factory.floatType);
method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, NumericMethodRewrites::rewriteToInvokeMath));
+ addProvider(new InvokeRewriter(method, NumericMethodRewrites.rewriteToInvokeMath()));
// float Float.min(float a, float b)
name = factory.createString("min");
proto = factory.createProto(factory.floatType, factory.floatType, factory.floatType);
method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, NumericMethodRewrites::rewriteToInvokeMath));
+ addProvider(new InvokeRewriter(method, NumericMethodRewrites.rewriteToInvokeMath()));
// float Float.sum(float a, float b)
name = factory.createString("sum");
proto = factory.createProto(factory.floatType, factory.floatType, factory.floatType);
method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, NumericMethodRewrites::rewriteToAddInstruction));
+ addProvider(new InvokeRewriter(method, NumericMethodRewrites.rewriteToAddInstruction()));
// boolean Float.isFinite(float a)
name = factory.createString("isFinite");
@@ -476,19 +479,19 @@
name = factory.createString("logicalAnd");
proto = factory.createProto(factory.booleanType, factory.booleanType, factory.booleanType);
method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, BooleanMethodRewrites::rewriteLogicalAnd));
+ addProvider(new InvokeRewriter(method, BooleanMethodRewrites.rewriteLogicalAnd()));
// boolean Boolean.logicalOr(boolean a, boolean b)
name = factory.createString("logicalOr");
proto = factory.createProto(factory.booleanType, factory.booleanType, factory.booleanType);
method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, BooleanMethodRewrites::rewriteLogicalOr));
+ addProvider(new InvokeRewriter(method, BooleanMethodRewrites.rewriteLogicalOr()));
// boolean Boolean.logicalXor(boolean a, boolean b)
name = factory.createString("logicalXor");
proto = factory.createProto(factory.booleanType, factory.booleanType, factory.booleanType);
method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, BooleanMethodRewrites::rewriteLogicalXor));
+ addProvider(new InvokeRewriter(method, BooleanMethodRewrites.rewriteLogicalXor()));
// Long
type = factory.boxedLongType;
@@ -503,19 +506,19 @@
name = factory.createString("max");
proto = factory.createProto(factory.longType, factory.longType, factory.longType);
method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, NumericMethodRewrites::rewriteToInvokeMath));
+ addProvider(new InvokeRewriter(method, NumericMethodRewrites.rewriteToInvokeMath()));
// long Long.min(long a, long b)
name = factory.createString("min");
proto = factory.createProto(factory.longType, factory.longType, factory.longType);
method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, NumericMethodRewrites::rewriteToInvokeMath));
+ addProvider(new InvokeRewriter(method, NumericMethodRewrites.rewriteToInvokeMath()));
// long Long.sum(long a, long b)
name = factory.createString("sum");
proto = factory.createProto(factory.longType, factory.longType, factory.longType);
method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, NumericMethodRewrites::rewriteToAddInstruction));
+ addProvider(new InvokeRewriter(method, NumericMethodRewrites.rewriteToAddInstruction()));
// Character
type = factory.boxedCharType;
@@ -524,7 +527,7 @@
name = factory.createString("hashCode");
proto = factory.createProto(factory.intType, factory.charType);
method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, NumericMethodRewrites::rewriteAsIdentity));
+ addProvider(new InvokeRewriter(method, NumericMethodRewrites.rewriteAsIdentity()));
// Objects
type = factory.objectsType;
@@ -916,7 +919,7 @@
method = factory.createMethod(type, proto, name);
addProvider(
i == 0
- ? new InvokeRewriter(method, CollectionMethodRewrites::rewriteListOfEmpty)
+ ? new InvokeRewriter(method, CollectionMethodRewrites.rewriteListOfEmpty())
: new MethodGenerator(
method,
(options, methodArg) ->
@@ -937,7 +940,7 @@
method = factory.createMethod(type, proto, name);
addProvider(
i == 0
- ? new InvokeRewriter(method, CollectionMethodRewrites::rewriteSetOfEmpty)
+ ? new InvokeRewriter(method, CollectionMethodRewrites.rewriteSetOfEmpty())
: new MethodGenerator(
method,
(options, methodArg) ->
@@ -957,7 +960,7 @@
method = factory.createMethod(type, proto, name);
addProvider(
i == 0
- ? new InvokeRewriter(method, CollectionMethodRewrites::rewriteMapOfEmpty)
+ ? new InvokeRewriter(method, CollectionMethodRewrites.rewriteMapOfEmpty())
: new MethodGenerator(
method,
(options, methodArg) ->
@@ -1224,10 +1227,10 @@
};
MethodInvokeRewriter[] rewriters =
new MethodInvokeRewriter[] {
- OptionalMethodRewrites::rewriteOrElseGet,
- OptionalMethodRewrites::rewriteDoubleOrElseGet,
- OptionalMethodRewrites::rewriteLongOrElseGet,
- OptionalMethodRewrites::rewriteIntOrElseGet,
+ OptionalMethodRewrites.rewriteOrElseGet(),
+ OptionalMethodRewrites.rewriteDoubleOrElseGet(),
+ OptionalMethodRewrites.rewriteLongOrElseGet(),
+ OptionalMethodRewrites.rewriteIntOrElseGet(),
};
DexString name = factory.createString("orElseThrow");
for (int i = 0; i < optionalTypes.length; i++) {
@@ -1294,11 +1297,10 @@
}
public abstract void rewriteInvoke(
- InvokeMethod invoke,
- InstructionListIterator iterator,
- IRCode code,
- AppView<?> appView,
- Set<Value> affectedValues,
+ CfInvoke invoke,
+ ListIterator<CfInstruction> iterator,
+ DexProgramClass context,
+ AppInfoWithClassHierarchy appInfo,
Consumer<ProgramMethod> registerSynthesizedMethod);
}
@@ -1313,14 +1315,12 @@
@Override
public void rewriteInvoke(
- InvokeMethod invoke,
- InstructionListIterator iterator,
- IRCode code,
- AppView<?> appView,
- Set<Value> affectedValues,
+ CfInvoke invoke,
+ ListIterator<CfInstruction> iterator,
+ DexProgramClass context,
+ AppInfoWithClassHierarchy appInfo,
Consumer<ProgramMethod> registerSynthesizedMethod) {
- rewriter.rewrite(invoke, iterator, appView.dexItemFactory(), affectedValues);
- assert code.isConsistentSSA();
+ rewriter.rewrite(invoke, iterator, appInfo.dexItemFactory());
}
}
@@ -1341,34 +1341,33 @@
@Override
public void rewriteInvoke(
- InvokeMethod invoke,
- InstructionListIterator iterator,
- IRCode code,
- AppView<?> appView,
- Set<Value> affectedValues,
+ CfInvoke invoke,
+ ListIterator<CfInstruction> iterator,
+ DexProgramClass context,
+ AppInfoWithClassHierarchy appInfo,
Consumer<ProgramMethod> registerSynthesizedMethod) {
- ProgramMethod method =
- appView
- .getSyntheticItems()
- .createMethod(
- code.context().getHolder(),
- appView.dexItemFactory(),
- builder ->
- builder
- .setProto(getProto(appView.dexItemFactory()))
- .setAccessFlags(
- MethodAccessFlags.fromSharedAccessFlags(
- Constants.ACC_PUBLIC
- | Constants.ACC_STATIC
- | Constants.ACC_SYNTHETIC,
- false))
- .setCode(
- methodSig -> generateTemplateMethod(appView.options(), methodSig)));
-
- iterator.replaceCurrentInstruction(
- new InvokeStatic(method.getReference(), invoke.outValue(), invoke.inValues()));
-
+ ProgramMethod method = getSyntheticMethod(context, appInfo);
registerSynthesizedMethod.accept(method);
+ iterator.remove();
+ iterator.add(new CfInvoke(Opcodes.INVOKESTATIC, method.getReference(), false));
+ }
+
+ private ProgramMethod getSyntheticMethod(
+ DexProgramClass context, AppInfoWithClassHierarchy appInfo) {
+ return appInfo
+ .getSyntheticItems()
+ .createMethod(
+ context,
+ appInfo.dexItemFactory(),
+ builder ->
+ builder
+ .setProto(getProto(appInfo.dexItemFactory()))
+ .setAccessFlags(
+ MethodAccessFlags.fromSharedAccessFlags(
+ Constants.ACC_PUBLIC | Constants.ACC_STATIC | Constants.ACC_SYNTHETIC,
+ false))
+ .setCode(
+ methodSig -> generateTemplateMethod(appInfo.app().options, methodSig)));
}
public DexProto getProto(DexItemFactory itemFactory) {
@@ -1400,16 +1399,30 @@
}
private interface TemplateMethodFactory {
-
Code create(InternalOptions options, DexMethod method);
}
- private interface MethodInvokeRewriter {
+ public interface MethodInvokeRewriter {
- void rewrite(
- InvokeMethod invoke,
- InstructionListIterator iterator,
- DexItemFactory factory,
- Set<Value> affectedValues);
+ CfInstruction rewriteSingle(CfInvoke invoke, DexItemFactory factory);
+
+ // Convenience wrapper since most rewrites are to a single instruction.
+ default void rewrite(
+ CfInvoke invoke, ListIterator<CfInstruction> iterator, DexItemFactory factory) {
+ iterator.remove();
+ iterator.add(rewriteSingle(invoke, factory));
+ }
+ }
+
+ public abstract static class FullMethodInvokeRewriter implements MethodInvokeRewriter {
+
+ @Override
+ public final CfInstruction rewriteSingle(CfInvoke invoke, DexItemFactory factory) {
+ throw new Unreachable();
+ }
+
+ @Override
+ public abstract void rewrite(
+ CfInvoke invoke, ListIterator<CfInstruction> iterator, DexItemFactory factory);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/backports/BooleanMethodRewrites.java b/src/main/java/com/android/tools/r8/ir/desugar/backports/BooleanMethodRewrites.java
index 90654b2..ec0a554 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/backports/BooleanMethodRewrites.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/backports/BooleanMethodRewrites.java
@@ -4,52 +4,27 @@
package com.android.tools.r8.ir.desugar.backports;
-import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.ir.code.And;
-import com.android.tools.r8.ir.code.InstructionListIterator;
-import com.android.tools.r8.ir.code.InvokeMethod;
+import com.android.tools.r8.cf.code.CfLogicalBinop;
+import com.android.tools.r8.cf.code.CfLogicalBinop.Opcode;
import com.android.tools.r8.ir.code.NumericType;
-import com.android.tools.r8.ir.code.Or;
-import com.android.tools.r8.ir.code.Value;
-import com.android.tools.r8.ir.code.Xor;
-import java.util.List;
-import java.util.Set;
+import com.android.tools.r8.ir.desugar.BackportedMethodRewriter.MethodInvokeRewriter;
public final class BooleanMethodRewrites {
- public static void rewriteLogicalAnd(
- InvokeMethod invoke,
- InstructionListIterator iterator,
- DexItemFactory factory,
- Set<Value> affectedValues) {
- List<Value> inValues = invoke.inValues();
- assert inValues.size() == 2;
- iterator.replaceCurrentInstruction(
- new And(NumericType.INT, invoke.outValue(), inValues.get(0), inValues.get(1)));
+ private static MethodInvokeRewriter createRewriter(CfLogicalBinop.Opcode op) {
+ return (invoke, factory) -> new CfLogicalBinop(op, NumericType.INT);
}
- public static void rewriteLogicalOr(
- InvokeMethod invoke,
- InstructionListIterator iterator,
- DexItemFactory factory,
- Set<Value> affectedValues) {
- List<Value> inValues = invoke.inValues();
- assert inValues.size() == 2;
-
- iterator.replaceCurrentInstruction(
- new Or(NumericType.INT, invoke.outValue(), inValues.get(0), inValues.get(1)));
+ public static MethodInvokeRewriter rewriteLogicalAnd() {
+ return createRewriter(Opcode.And);
}
- public static void rewriteLogicalXor(
- InvokeMethod invoke,
- InstructionListIterator iterator,
- DexItemFactory factory,
- Set<Value> affectedValues) {
- List<Value> inValues = invoke.inValues();
- assert inValues.size() == 2;
+ public static MethodInvokeRewriter rewriteLogicalOr() {
+ return createRewriter(Opcode.Or);
+ }
- iterator.replaceCurrentInstruction(
- new Xor(NumericType.INT, invoke.outValue(), inValues.get(0), inValues.get(1)));
+ public static MethodInvokeRewriter rewriteLogicalXor() {
+ return createRewriter(Opcode.Xor);
}
private BooleanMethodRewrites() {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/backports/CollectionMethodRewrites.java b/src/main/java/com/android/tools/r8/ir/desugar/backports/CollectionMethodRewrites.java
index 695f51f..64c94c5 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/backports/CollectionMethodRewrites.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/backports/CollectionMethodRewrites.java
@@ -4,51 +4,31 @@
package com.android.tools.r8.ir.desugar.backports;
-import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexMethod;
-import com.android.tools.r8.ir.code.InstructionListIterator;
-import com.android.tools.r8.ir.code.InvokeMethod;
-import com.android.tools.r8.ir.code.InvokeStatic;
-import com.android.tools.r8.ir.code.Value;
-import java.util.Collections;
-import java.util.Set;
+import com.android.tools.r8.cf.code.CfInvoke;
+import com.android.tools.r8.ir.desugar.BackportedMethodRewriter.MethodInvokeRewriter;
+import org.objectweb.asm.Opcodes;
public final class CollectionMethodRewrites {
private CollectionMethodRewrites() {}
- public static void rewriteListOfEmpty(
- InvokeMethod invoke,
- InstructionListIterator iterator,
- DexItemFactory factory,
- Set<Value> affectedValues) {
- rewriteToCollectionMethod(invoke, iterator, factory, "emptyList");
+ public static MethodInvokeRewriter rewriteListOfEmpty() {
+ return rewriteToCollectionMethod("emptyList");
}
- public static void rewriteSetOfEmpty(
- InvokeMethod invoke,
- InstructionListIterator iterator,
- DexItemFactory factory,
- Set<Value> affectedValues) {
- rewriteToCollectionMethod(invoke, iterator, factory, "emptySet");
+ public static MethodInvokeRewriter rewriteSetOfEmpty() {
+ return rewriteToCollectionMethod("emptySet");
}
- public static void rewriteMapOfEmpty(
- InvokeMethod invoke,
- InstructionListIterator iterator,
- DexItemFactory factory,
- Set<Value> affectedValues) {
- rewriteToCollectionMethod(invoke, iterator, factory, "emptyMap");
+ public static MethodInvokeRewriter rewriteMapOfEmpty() {
+ return rewriteToCollectionMethod("emptyMap");
}
- private static void rewriteToCollectionMethod(InvokeMethod invoke,
- InstructionListIterator iterator, DexItemFactory factory, String methodName) {
- assert invoke.inValues().isEmpty();
-
- DexMethod collectionsEmptyList =
- factory.createMethod(factory.collectionsType, invoke.getInvokedMethod().proto, methodName);
- InvokeStatic newInvoke =
- new InvokeStatic(collectionsEmptyList, invoke.outValue(), Collections.emptyList());
- iterator.replaceCurrentInstruction(newInvoke);
+ private static MethodInvokeRewriter rewriteToCollectionMethod(String methodName) {
+ return (invoke, factory) ->
+ new CfInvoke(
+ Opcodes.INVOKESTATIC,
+ factory.createMethod(factory.collectionsType, invoke.getMethod().proto, methodName),
+ false);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/backports/FloatMethodRewrites.java b/src/main/java/com/android/tools/r8/ir/desugar/backports/FloatMethodRewrites.java
index a5d557d..8670d3b 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/backports/FloatMethodRewrites.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/backports/FloatMethodRewrites.java
@@ -4,25 +4,20 @@
package com.android.tools.r8.ir.desugar.backports;
-import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.ir.code.InstructionListIterator;
-import com.android.tools.r8.ir.code.InvokeMethod;
-import com.android.tools.r8.ir.code.InvokeStatic;
-import com.android.tools.r8.ir.code.Value;
-import java.util.Set;
+import com.android.tools.r8.cf.code.CfInvoke;
+import com.android.tools.r8.ir.desugar.BackportedMethodRewriter.MethodInvokeRewriter;
+import org.objectweb.asm.Opcodes;
public final class FloatMethodRewrites {
private FloatMethodRewrites() {}
- public static void rewriteHashCode(
- InvokeMethod invoke,
- InstructionListIterator iterator,
- DexItemFactory factory,
- Set<Value> affectedValues) {
- InvokeStatic mathInvoke = new InvokeStatic(
- factory.createMethod(factory.boxedFloatType, invoke.getInvokedMethod().proto,
- "floatToIntBits"), invoke.outValue(), invoke.inValues(), false);
- iterator.replaceCurrentInstruction(mathInvoke);
+ public static MethodInvokeRewriter rewriteHashCode() {
+ return (invoke, factory) ->
+ new CfInvoke(
+ Opcodes.INVOKESTATIC,
+ factory.createMethod(
+ factory.boxedFloatType, invoke.getMethod().proto, "floatToIntBits"),
+ false);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/backports/LongMethodRewrites.java b/src/main/java/com/android/tools/r8/ir/desugar/backports/LongMethodRewrites.java
index 348194b..5c29f81 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/backports/LongMethodRewrites.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/backports/LongMethodRewrites.java
@@ -4,28 +4,16 @@
package com.android.tools.r8.ir.desugar.backports;
-import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.ir.code.Cmp;
+import com.android.tools.r8.cf.code.CfCmp;
import com.android.tools.r8.ir.code.Cmp.Bias;
-import com.android.tools.r8.ir.code.InstructionListIterator;
-import com.android.tools.r8.ir.code.InvokeMethod;
import com.android.tools.r8.ir.code.NumericType;
-import com.android.tools.r8.ir.code.Value;
-import java.util.List;
-import java.util.Set;
+import com.android.tools.r8.ir.desugar.BackportedMethodRewriter.MethodInvokeRewriter;
public final class LongMethodRewrites {
private LongMethodRewrites() {}
- public static void rewriteCompare(
- InvokeMethod invoke,
- InstructionListIterator iterator,
- DexItemFactory factory,
- Set<Value> affectedValues) {
- List<Value> inValues = invoke.inValues();
- assert inValues.size() == 2;
- iterator.replaceCurrentInstruction(
- new Cmp(NumericType.LONG, Bias.NONE, invoke.outValue(), inValues.get(0), inValues.get(1)));
+ public static MethodInvokeRewriter rewriteCompare() {
+ return (invoke, factory) -> new CfCmp(Bias.NONE, NumericType.LONG);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/backports/NumericMethodRewrites.java b/src/main/java/com/android/tools/r8/ir/desugar/backports/NumericMethodRewrites.java
index 342c767..050aefa 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/backports/NumericMethodRewrites.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/backports/NumericMethodRewrites.java
@@ -1,52 +1,44 @@
package com.android.tools.r8.ir.desugar.backports;
+import com.android.tools.r8.cf.code.CfArithmeticBinop;
+import com.android.tools.r8.cf.code.CfInstruction;
+import com.android.tools.r8.cf.code.CfInvoke;
import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.ir.code.Add;
-import com.android.tools.r8.ir.code.InstructionListIterator;
-import com.android.tools.r8.ir.code.InvokeMethod;
-import com.android.tools.r8.ir.code.InvokeStatic;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.ir.code.NumericType;
-import com.android.tools.r8.ir.code.Value;
-import java.util.List;
-import java.util.Set;
+import com.android.tools.r8.ir.desugar.BackportedMethodRewriter.FullMethodInvokeRewriter;
+import com.android.tools.r8.ir.desugar.BackportedMethodRewriter.MethodInvokeRewriter;
+import java.util.ListIterator;
+import org.objectweb.asm.Opcodes;
public final class NumericMethodRewrites {
- public static void rewriteToInvokeMath(
- InvokeMethod invoke,
- InstructionListIterator iterator,
- DexItemFactory factory,
- Set<Value> affectedValues) {
- InvokeStatic mathInvoke = new InvokeStatic(
- factory.createMethod(factory.mathType, invoke.getInvokedMethod().proto,
- invoke.getInvokedMethod().name), invoke.outValue(), invoke.inValues(), false);
- iterator.replaceCurrentInstruction(mathInvoke);
+
+ public static MethodInvokeRewriter rewriteToInvokeMath() {
+ return (invoke, factory) -> {
+ DexMethod method = invoke.getMethod();
+ return new CfInvoke(
+ Opcodes.INVOKESTATIC,
+ factory.createMethod(factory.mathType, method.proto, method.name),
+ false);
+ };
}
- public static void rewriteToAddInstruction(
- InvokeMethod invoke,
- InstructionListIterator iterator,
- DexItemFactory factory,
- Set<Value> affectedValues) {
- List<Value> values = invoke.inValues();
- assert values.size() == 2;
-
- NumericType numericType = NumericType.fromDexType(invoke.getReturnType());
- Add add = new Add(numericType, invoke.outValue(), values.get(0), values.get(1));
- iterator.replaceCurrentInstruction(add);
+ public static MethodInvokeRewriter rewriteToAddInstruction() {
+ return (invoke, factory) -> {
+ NumericType numericType = NumericType.fromDexType(invoke.getMethod().getReturnType());
+ return new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, numericType);
+ };
}
- public static void rewriteAsIdentity(
- InvokeMethod invoke,
- InstructionListIterator iterator,
- DexItemFactory factory,
- Set<Value> affectedValues) {
- List<Value> values = invoke.inValues();
- assert values.size() == 1;
- if (invoke.hasOutValue()) {
- invoke.outValue().replaceUsers(values.get(0));
- }
- // TODO(b/152853271): Debugging information is lost here (DebugLocalWrite may be required).
- iterator.removeOrReplaceByDebugLocalRead();
+ public static MethodInvokeRewriter rewriteAsIdentity() {
+ return new FullMethodInvokeRewriter() {
+ @Override
+ public void rewrite(
+ CfInvoke invoke, ListIterator<CfInstruction> iterator, DexItemFactory factory) {
+ // The invoke consumes the stack value and pushes another assumed to be the same.
+ iterator.remove();
+ }
+ };
}
private NumericMethodRewrites() {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/backports/ObjectsMethodRewrites.java b/src/main/java/com/android/tools/r8/ir/desugar/backports/ObjectsMethodRewrites.java
index de16e98..69253be 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/backports/ObjectsMethodRewrites.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/backports/ObjectsMethodRewrites.java
@@ -4,43 +4,41 @@
package com.android.tools.r8.ir.desugar.backports;
+import com.android.tools.r8.cf.code.CfInstruction;
+import com.android.tools.r8.cf.code.CfInvoke;
+import com.android.tools.r8.cf.code.CfStackInstruction;
+import com.android.tools.r8.cf.code.CfStackInstruction.Opcode;
import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.ir.code.InstructionListIterator;
-import com.android.tools.r8.ir.code.InvokeMethod;
-import com.android.tools.r8.ir.code.InvokeStatic;
-import com.android.tools.r8.ir.code.InvokeVirtual;
-import com.android.tools.r8.ir.code.Value;
-import java.util.Set;
+import com.android.tools.r8.ir.desugar.BackportedMethodRewriter.FullMethodInvokeRewriter;
+import com.android.tools.r8.ir.desugar.BackportedMethodRewriter.MethodInvokeRewriter;
+import java.util.ListIterator;
+import org.objectweb.asm.Opcodes;
public final class ObjectsMethodRewrites {
- public static void rewriteToArraysHashCode(
- InvokeMethod invoke,
- InstructionListIterator iterator,
- DexItemFactory factory,
- Set<Value> affectedValues) {
- DexType arraysType = factory.createType(factory.arraysDescriptor);
- DexMethod hashCodeMethod =
- factory.createMethod(arraysType, invoke.getInvokedMethod().proto, "hashCode");
- InvokeStatic arraysHashCode =
- new InvokeStatic(hashCodeMethod, invoke.outValue(), invoke.inValues(), false);
- iterator.replaceCurrentInstruction(arraysHashCode);
+ public static MethodInvokeRewriter rewriteToArraysHashCode() {
+ return (invoke, factory) -> {
+ DexType arraysType = factory.createType(factory.arraysDescriptor);
+ return new CfInvoke(
+ Opcodes.INVOKESTATIC,
+ factory.createMethod(arraysType, invoke.getMethod().proto, "hashCode"),
+ false);
+ };
}
- public static void rewriteRequireNonNull(
- InvokeMethod invoke,
- InstructionListIterator iterator,
- DexItemFactory factory,
- Set<Value> affectedValues) {
- InvokeVirtual getClass =
- new InvokeVirtual(factory.objectMembers.getClass, null, invoke.inValues());
- if (invoke.hasOutValue()) {
- affectedValues.addAll(invoke.outValue().affectedValues());
- invoke.outValue().replaceUsers(invoke.inValues().get(0));
- invoke.setOutValue(null);
- }
- iterator.replaceCurrentInstruction(getClass);
+ public static MethodInvokeRewriter rewriteRequireNonNull() {
+ return new FullMethodInvokeRewriter() {
+
+ @Override
+ public void rewrite(
+ CfInvoke invoke, ListIterator<CfInstruction> iterator, DexItemFactory factory) {
+ iterator.remove();
+ // requireNonNull returns the operand, so dup top-of-stack, do getClass and pop the class.
+ iterator.add(new CfStackInstruction(Opcode.Dup));
+ iterator.add(new CfInvoke(Opcodes.INVOKEVIRTUAL, factory.objectMembers.getClass, false));
+ iterator.add(new CfStackInstruction(Opcode.Pop));
+ }
+ };
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/backports/OptionalMethodRewrites.java b/src/main/java/com/android/tools/r8/ir/desugar/backports/OptionalMethodRewrites.java
index c10a292..d66d7f5 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/backports/OptionalMethodRewrites.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/backports/OptionalMethodRewrites.java
@@ -4,58 +4,40 @@
package com.android.tools.r8.ir.desugar.backports;
+import com.android.tools.r8.cf.code.CfInvoke;
import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.ir.code.InstructionListIterator;
-import com.android.tools.r8.ir.code.InvokeMethod;
-import com.android.tools.r8.ir.code.InvokeVirtual;
-import com.android.tools.r8.ir.code.Value;
-import java.util.Set;
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.ir.desugar.BackportedMethodRewriter.MethodInvokeRewriter;
+import java.util.function.Function;
+import org.objectweb.asm.Opcodes;
public final class OptionalMethodRewrites {
private OptionalMethodRewrites() {}
- public static void rewriteOrElseGet(
- InvokeMethod invoke,
- InstructionListIterator iterator,
- DexItemFactory factory,
- Set<Value> affectedValues) {
- InvokeVirtual getInvoke = new InvokeVirtual(
- factory.createMethod(factory.optionalType, invoke.getInvokedMethod().proto,
- "get"), invoke.outValue(), invoke.inValues());
- iterator.replaceCurrentInstruction(getInvoke);
+ private static MethodInvokeRewriter createRewriter(
+ Function<DexItemFactory, DexType> holderTypeSupplier, String methodName) {
+ return (invoke, factory) ->
+ new CfInvoke(
+ Opcodes.INVOKEVIRTUAL,
+ factory.createMethod(
+ holderTypeSupplier.apply(factory), invoke.getMethod().proto, methodName),
+ false);
}
- public static void rewriteDoubleOrElseGet(
- InvokeMethod invoke,
- InstructionListIterator iterator,
- DexItemFactory factory,
- Set<Value> affectedValues) {
- InvokeVirtual getInvoke = new InvokeVirtual(
- factory.createMethod(factory.optionalDoubleType, invoke.getInvokedMethod().proto,
- "getAsDouble"), invoke.outValue(), invoke.inValues());
- iterator.replaceCurrentInstruction(getInvoke);
+ public static MethodInvokeRewriter rewriteOrElseGet() {
+ return createRewriter(factory -> factory.optionalType, "get");
}
- public static void rewriteIntOrElseGet(
- InvokeMethod invoke,
- InstructionListIterator iterator,
- DexItemFactory factory,
- Set<Value> affectedValues) {
- InvokeVirtual getInvoke = new InvokeVirtual(
- factory.createMethod(factory.optionalIntType, invoke.getInvokedMethod().proto,
- "getAsInt"), invoke.outValue(), invoke.inValues());
- iterator.replaceCurrentInstruction(getInvoke);
+ public static MethodInvokeRewriter rewriteDoubleOrElseGet() {
+ return createRewriter(factory -> factory.optionalDoubleType, "getAsDouble");
}
- public static void rewriteLongOrElseGet(
- InvokeMethod invoke,
- InstructionListIterator iterator,
- DexItemFactory factory,
- Set<Value> affectedValues) {
- InvokeVirtual getInvoke = new InvokeVirtual(
- factory.createMethod(factory.optionalLongType, invoke.getInvokedMethod().proto,
- "getAsLong"), invoke.outValue(), invoke.inValues());
- iterator.replaceCurrentInstruction(getInvoke);
+ public static MethodInvokeRewriter rewriteIntOrElseGet() {
+ return createRewriter(factory -> factory.optionalIntType, "getAsInt");
+ }
+
+ public static MethodInvokeRewriter rewriteLongOrElseGet() {
+ return createRewriter(factory -> factory.optionalLongType, "getAsLong");
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/DefaultInliningOracle.java b/src/main/java/com/android/tools/r8/ir/optimize/DefaultInliningOracle.java
index 7a5dce9..0fc9b80 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/DefaultInliningOracle.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/DefaultInliningOracle.java
@@ -264,8 +264,7 @@
return null;
}
- if (inliner.isBlacklisted(
- invoke, resolutionResult, singleTarget, whyAreYouNotInliningReporter)) {
+ if (inliner.neverInline(invoke, resolutionResult, singleTarget, whyAreYouNotInliningReporter)) {
return null;
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
index a36f313..ca93336 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
@@ -85,7 +85,7 @@
public class Inliner implements PostOptimization {
protected final AppView<AppInfoWithLiveness> appView;
- private final Set<DexMethod> blacklist;
+ private final Set<DexMethod> extraNeverInlineMethods;
private final LambdaMerger lambdaMerger;
private final LensCodeRewriter lensCodeRewriter;
final MainDexTracingResult mainDexClasses;
@@ -106,7 +106,7 @@
LensCodeRewriter lensCodeRewriter) {
Kotlin.Intrinsics intrinsics = appView.dexItemFactory().kotlin.intrinsics;
this.appView = appView;
- this.blacklist =
+ this.extraNeverInlineMethods =
appView.options().kotlinOptimizationOptions().disableKotlinSpecificOptimizations
? ImmutableSet.of()
: ImmutableSet.of(intrinsics.throwNpe, intrinsics.throwParameterIsNullException);
@@ -119,7 +119,7 @@
: null;
}
- boolean isBlacklisted(
+ boolean neverInline(
InvokeMethod invoke,
SingleResolutionResult resolutionResult,
ProgramMethod singleTarget,
@@ -136,10 +136,11 @@
return true;
}
- if (blacklist.contains(appView.graphLens().getOriginalMethodSignature(singleTargetReference))
+ if (extraNeverInlineMethods.contains(
+ appView.graphLens().getOriginalMethodSignature(singleTargetReference))
|| TwrCloseResourceRewriter.isSynthesizedCloseResourceMethod(
singleTargetReference, appView)) {
- whyAreYouNotInliningReporter.reportBlacklisted();
+ whyAreYouNotInliningReporter.reportExtraNeverInline();
return true;
}
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 e09dab4..7d40dba 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
@@ -635,8 +635,8 @@
DexAnnotationSet.empty(),
ParameterAnnotationsList.empty(),
cfCode,
- REQUIRED_CLASS_FILE_VERSION,
- true);
+ true,
+ REQUIRED_CLASS_FILE_VERSION);
}
private MethodAccessFlags synthesizedMethodAccessFlags(boolean sync) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/inliner/NopWhyAreYouNotInliningReporter.java b/src/main/java/com/android/tools/r8/ir/optimize/inliner/NopWhyAreYouNotInliningReporter.java
index 8cbb1f4..e398dce 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/inliner/NopWhyAreYouNotInliningReporter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/inliner/NopWhyAreYouNotInliningReporter.java
@@ -22,7 +22,7 @@
}
@Override
- public void reportBlacklisted() {}
+ public void reportExtraNeverInline() {}
@Override
public void reportCallerNotSameClass() {}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/inliner/WhyAreYouNotInliningReporter.java b/src/main/java/com/android/tools/r8/ir/optimize/inliner/WhyAreYouNotInliningReporter.java
index 05d9b49..b3e72bf 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/inliner/WhyAreYouNotInliningReporter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/inliner/WhyAreYouNotInliningReporter.java
@@ -45,7 +45,7 @@
}
}
- public abstract void reportBlacklisted();
+ public abstract void reportExtraNeverInline();
public abstract void reportCallerNotSameClass();
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/inliner/WhyAreYouNotInliningReporterImpl.java b/src/main/java/com/android/tools/r8/ir/optimize/inliner/WhyAreYouNotInliningReporterImpl.java
index 934651c..ee2d4b5 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/inliner/WhyAreYouNotInliningReporterImpl.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/inliner/WhyAreYouNotInliningReporterImpl.java
@@ -48,8 +48,8 @@
}
@Override
- public void reportBlacklisted() {
- print("method is blacklisted from inlining.");
+ public void reportExtraNeverInline() {
+ print("method is marked as an additional never inline method.");
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/synthetic/SyntheticSourceCode.java b/src/main/java/com/android/tools/r8/ir/synthetic/SyntheticSourceCode.java
index 3f6569e..ae06b60 100644
--- a/src/main/java/com/android/tools/r8/ir/synthetic/SyntheticSourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/synthetic/SyntheticSourceCode.java
@@ -174,7 +174,7 @@
@Override
public void buildBlockTransfer(
IRBuilder builder, int predecessorOffset, int successorOffset, boolean isExceptional) {
- // Intensionally empty as synthetic code does not contain locals information.
+ // Intentionally empty as synthetic code does not contain locals information.
}
@Override
diff --git a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
index 9ccc19c..e28734b 100644
--- a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
@@ -43,6 +43,7 @@
import com.android.tools.r8.naming.ProguardMapSupplier;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.synthesis.SyntheticItems;
+import com.android.tools.r8.utils.AsmUtils;
import com.android.tools.r8.utils.ExceptionUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.google.common.collect.ImmutableMap;
@@ -173,6 +174,9 @@
}
}
int access = clazz.accessFlags.getAsCfAccessFlags();
+ if (clazz.isDeprecated()) {
+ access = AsmUtils.withDeprecated(access);
+ }
String desc = namingLens.lookupDescriptor(clazz.type).toString();
String name = namingLens.lookupInternalName(clazz.type);
String signature = getSignature(clazz.annotations());
@@ -326,6 +330,9 @@
private void writeField(DexEncodedField field, ClassWriter writer) {
int access = field.accessFlags.getAsCfAccessFlags();
+ if (field.isDeprecated()) {
+ access = AsmUtils.withDeprecated(access);
+ }
String name = namingLens.lookupName(field.field).toString();
String desc = namingLens.lookupDescriptor(field.field.type).toString();
String signature = getSignature(field.annotations());
@@ -343,6 +350,9 @@
ImmutableMap<DexString, DexValue> defaults) {
DexEncodedMethod definition = method.getDefinition();
int access = definition.getAccessFlags().getAsCfAccessFlags();
+ if (definition.isDeprecated()) {
+ access = AsmUtils.withDeprecated(access);
+ }
String name = namingLens.lookupName(method.getReference()).toString();
String desc = definition.descriptor(namingLens);
String signature = getSignature(definition.annotations());
diff --git a/src/main/java/com/android/tools/r8/optimize/BridgeHoisting.java b/src/main/java/com/android/tools/r8/optimize/BridgeHoisting.java
index 038d078..4dc644c 100644
--- a/src/main/java/com/android/tools/r8/optimize/BridgeHoisting.java
+++ b/src/main/java/com/android/tools/r8/optimize/BridgeHoisting.java
@@ -247,6 +247,9 @@
appView.dexItemFactory().createMethod(clazz.type, method.proto, method.name);
DexEncodedMethod newMethod =
representative.getDefinition().toTypeSubstitutedMethod(newMethodReference);
+ if (newMethod.getAccessFlags().isFinal()) {
+ newMethod.getAccessFlags().demoteFromFinal();
+ }
clazz.addVirtualMethod(newMethod);
lensBuilder.move(representative.getReference(), newMethodReference);
diff --git a/src/main/java/com/android/tools/r8/retrace/RetraceUtils.java b/src/main/java/com/android/tools/r8/retrace/RetraceUtils.java
index 77aff7d..fe0bac2 100644
--- a/src/main/java/com/android/tools/r8/retrace/RetraceUtils.java
+++ b/src/main/java/com/android/tools/r8/retrace/RetraceUtils.java
@@ -19,14 +19,14 @@
public static String methodDescriptionFromMethodReference(
MethodReference methodReference, boolean appendHolder, boolean verbose) {
- if (!verbose || methodReference.isUnknown()) {
- return methodReference.getHolderClass().getTypeName() + "." + methodReference.getMethodName();
- }
StringBuilder sb = new StringBuilder();
if (appendHolder) {
sb.append(methodReference.getHolderClass().getTypeName());
sb.append(".");
}
+ if (!verbose || methodReference.isUnknown()) {
+ return sb.append(methodReference.getMethodName()).toString();
+ }
sb.append(
methodReference.getReturnType() == null
? "void"
diff --git a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
index 953779d..0815577 100644
--- a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
@@ -1251,8 +1251,8 @@
DexAnnotationSet.empty(),
ParameterAnnotationsList.empty(),
code,
- method.hasClassFileVersion() ? method.getClassFileVersion() : -1,
- true);
+ true,
+ method.hasClassFileVersion() ? method.getClassFileVersion() : -1);
bridge.setLibraryMethodOverride(method.isLibraryMethodOverride());
if (method.accessFlags.isPromotedToPublic()) {
// The bridge is now the public method serving the role of the original method, and should
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
index 31a4afd..9dd8bee 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
@@ -16,6 +16,7 @@
import com.android.tools.r8.shaking.MainDexClasses;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.ListUtils;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
@@ -96,8 +97,11 @@
List<SyntheticMethodDefinition> methodDefinitions =
lookupSyntheticMethodDefinitions(application);
- Map<HashCode, List<SyntheticMethodDefinition>> potentialEquivalences =
- computePotentialEquivalences(methodDefinitions);
+ Collection<List<SyntheticMethodDefinition>> potentialEquivalences =
+ // Don't share synthetics in intermediate mode builds.
+ options.intermediate
+ ? ListUtils.map(methodDefinitions, Collections::singletonList)
+ : computePotentialEquivalences(methodDefinitions);
Map<DexType, EquivalenceGroup<SyntheticMethodDefinition>> equivalences =
computeActualEquivalences(potentialEquivalences, options.itemFactory);
@@ -328,10 +332,10 @@
private static <T extends SyntheticDefinition & Comparable<T>>
Map<DexType, EquivalenceGroup<T>> computeActualEquivalences(
- Map<HashCode, List<T>> potentialEquivalences, DexItemFactory factory) {
+ Collection<List<T>> potentialEquivalences, DexItemFactory factory) {
Map<DexType, List<EquivalenceGroup<T>>> groupsPerContext = new IdentityHashMap<>();
potentialEquivalences.forEach(
- (hash, members) -> {
+ members -> {
// Get a representative member and add to its group.
T representative = findDeterministicRepresentative(members);
List<T> group = new ArrayList<>(members.size());
@@ -391,14 +395,14 @@
+ nextContextId));
}
- private static <T extends SyntheticDefinition>
- Map<HashCode, List<T>> computePotentialEquivalences(List<T> definitions) {
+ private static <T extends SyntheticDefinition> Collection<List<T>> computePotentialEquivalences(
+ List<T> definitions) {
Map<HashCode, List<T>> equivalences = new HashMap<>(definitions.size());
for (T definition : definitions) {
HashCode hash = definition.computeHash();
equivalences.computeIfAbsent(hash, k -> new ArrayList<>()).add(definition);
}
- return equivalences;
+ return equivalences.values();
}
private List<SyntheticMethodDefinition> lookupSyntheticMethodDefinitions(
diff --git a/src/main/java/com/android/tools/r8/utils/AsmUtils.java b/src/main/java/com/android/tools/r8/utils/AsmUtils.java
new file mode 100644
index 0000000..44fcc6f
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/utils/AsmUtils.java
@@ -0,0 +1,23 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.utils;
+
+import static org.objectweb.asm.Opcodes.ACC_DEPRECATED;
+
+public class AsmUtils {
+ public static boolean isDeprecated(int access) {
+ // ASM stores the Deprecated attribute
+ // (https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.15) in the
+ // access flags.
+ return (access & ACC_DEPRECATED) == ACC_DEPRECATED;
+ }
+
+ public static int withDeprecated(int access) {
+ // ASM stores the Deprecated attribute
+ // (https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.15) in the
+ // access flags.
+ return access | ACC_DEPRECATED;
+ }
+}
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 df274fe..cdd3ca3 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -1241,7 +1241,7 @@
public Set<Inliner.Reason> validInliningReasons = null;
public boolean noLocalsTableOnInput = false;
public boolean forceNameReflectionOptimization = false;
- public boolean enableNarrowingChecksInD8 = false;
+ public boolean enableNarrowAndWideningingChecksInD8 = false;
public Consumer<IRCode> irModifier = null;
public int basicBlockMuncherIterationLimit = NO_LIMIT;
public boolean dontReportFailingCheckDiscarded = false;
diff --git a/src/test/java/com/android/tools/r8/R8FullTestBuilder.java b/src/test/java/com/android/tools/r8/R8FullTestBuilder.java
index 7e41239..3343329 100644
--- a/src/test/java/com/android/tools/r8/R8FullTestBuilder.java
+++ b/src/test/java/com/android/tools/r8/R8FullTestBuilder.java
@@ -5,6 +5,7 @@
import com.android.tools.r8.R8Command.Builder;
import com.android.tools.r8.TestBase.Backend;
+import com.android.tools.r8.utils.AndroidApp;
public class R8FullTestBuilder extends R8TestBuilder<R8FullTestBuilder> {
@@ -17,6 +18,11 @@
return new R8FullTestBuilder(state, builder, backend);
}
+ public static R8FullTestBuilder create(
+ TestState state, AndroidApp.Builder appBuilder, Backend backend) {
+ return new R8FullTestBuilder(state, R8Command.builder(appBuilder.build()), backend);
+ }
+
@Override
R8FullTestBuilder self() {
return this;
diff --git a/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java b/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java
index d9ed43f..9fe1539 100644
--- a/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java
+++ b/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java
@@ -620,76 +620,87 @@
"461-get-reference-vreg",
TestCondition.match(
TestCondition.D8_COMPILER,
- TestCondition
- .runtimes(DexVm.Version.V7_0_0, DexVm.Version.V6_0_1, DexVm.Version.V5_1_1)))
+ TestCondition.runtimes(
+ DexVm.Version.V7_0_0, DexVm.Version.V6_0_1, DexVm.Version.V5_1_1)))
// Dalvik fails on reading an uninitialized local.
.put(
"471-uninitialized-locals",
TestCondition.match(TestCondition.runtimesUpTo(DexVm.Version.V4_4_4)))
// Out of memory.
- .put("152-dead-large-object",
+ .put(
+ "152-dead-large-object",
TestCondition.match(TestCondition.runtimesUpTo(DexVm.Version.V4_4_4)))
// Cannot resolve exception handler. Interestingly, D8 generates different code in
// release mode (which is also the code generated by R8) which passes.
- .put("111-unresolvable-exception",
+ .put(
+ "111-unresolvable-exception",
TestCondition.match(
- TestCondition.D8_COMPILER,
- TestCondition.runtimesUpTo(DexVm.Version.V4_4_4)))
+ TestCondition.D8_COMPILER, TestCondition.runtimesUpTo(DexVm.Version.V4_4_4)))
// Fails because the code has to be desugared to run on art <= 6.0.1
// When running from dx code we don't desugar.
- .put("530-checker-lse2",
+ .put(
+ "530-checker-lse2",
TestCondition.match(
TestCondition.tools(DexTool.DX),
- TestCondition.D8_COMPILER,
TestCondition.runtimesUpTo(DexVm.Version.V6_0_1)))
- .put("534-checker-bce-deoptimization",
- TestCondition
- .match(TestCondition.D8_COMPILER, TestCondition.runtimes(DexVm.Version.V6_0_1)))
+ .put(
+ "534-checker-bce-deoptimization",
+ TestCondition.match(
+ TestCondition.D8_COMPILER, TestCondition.runtimes(DexVm.Version.V6_0_1)))
// Type not present.
- .put("124-missing-classes",
+ .put(
+ "124-missing-classes",
TestCondition.match(TestCondition.runtimesUpTo(DexVm.Version.V4_4_4)))
// Failed creating vtable.
- .put("587-inline-class-error",
+ .put(
+ "587-inline-class-error",
TestCondition.match(TestCondition.runtimesUpTo(DexVm.Version.V4_4_4)))
// Failed creating vtable.
- .put("595-error-class",
+ .put(
+ "595-error-class",
TestCondition.match(TestCondition.runtimesUpTo(DexVm.Version.V4_4_4)))
// NoSuchFieldException: systemThreadGroup on Art 4.4.4.
- .put("129-ThreadGetId",
+ .put(
+ "129-ThreadGetId",
TestCondition.match(TestCondition.runtimesUpTo(DexVm.Version.V4_4_4)))
// Verifier says: can't modify final field LMain;.staticFinalField.
- .put("600-verifier-fails",
+ .put(
+ "600-verifier-fails",
TestCondition.match(TestCondition.runtimesUpTo(DexVm.Version.V4_4_4)))
// VFY: tried to get class from non-ref register.
- .put("506-verify-aput",
+ .put(
+ "506-verify-aput",
TestCondition.match(TestCondition.runtimesUpTo(DexVm.Version.V4_4_4)))
// NoSuchMethod: startMethodTracing.
- .put("545-tracing-and-jit",
+ .put(
+ "545-tracing-and-jit",
TestCondition.match(TestCondition.runtimesUpTo(DexVm.Version.V4_4_4)))
// filled-new-array arg 0(1) not valid.
- .put("412-new-array",
+ .put(
+ "412-new-array",
TestCondition.match(TestCondition.runtimesUpTo(DexVm.Version.V4_4_4)))
// TODO(ager): unclear what is failing here.
- .put("098-ddmc",
- TestCondition.match(TestCondition.runtimesUpTo(DexVm.Version.V4_4_4)))
+ .put("098-ddmc", TestCondition.match(TestCondition.runtimesUpTo(DexVm.Version.V4_4_4)))
// Unsatisfiable link error:
// libarttest.so: undefined symbol: _ZN3art6Thread18RunEmptyCheckpointEv
- .put("543-env-long-ref",
+ .put(
+ "543-env-long-ref",
TestCondition.match(
TestCondition.D8_COMPILER,
- TestCondition
- .runtimes(
- DexVm.Version.V8_1_0,
- DexVm.Version.V7_0_0,
- DexVm.Version.V6_0_1,
- DexVm.Version.V5_1_1)))
+ TestCondition.runtimes(
+ DexVm.Version.V8_1_0,
+ DexVm.Version.V7_0_0,
+ DexVm.Version.V6_0_1,
+ DexVm.Version.V5_1_1)))
// lib64 libarttest.so: wrong ELF class ELFCLASS64.
- .put("543-env-long-ref",
+ .put(
+ "543-env-long-ref",
TestCondition.match(TestCondition.runtimesUpTo(DexVm.Version.V4_4_4)))
// Leaving two static-get triggers LSE bug on 6.0.1 (b/25735083).
// R8, with subtyping, knows the first sget is dead, and removing it avoids the bug.
// Due to the lack of subtype hierarchy, D8 can't guarantee <clinit> side effects.
- .put("550-new-instance-clinit",
+ .put(
+ "550-new-instance-clinit",
TestCondition.match(
TestCondition.D8_COMPILER, TestCondition.runtimes(DexVm.Version.V6_0_1)))
// Regression test for an issue that is not fixed on version 5.1.1. Throws an Exception
@@ -697,40 +708,37 @@
// running the R8 generated code when starting from jar or from dex code generated with
// dx. However, the code that R8 generates is valid and there is nothing we can do for
// this one.
- .put("551-implicit-null-checks",
+ .put(
+ "551-implicit-null-checks",
TestCondition.match(
TestCondition.tools(DexTool.NONE, DexTool.DX),
TestCondition.R8DEX_COMPILER,
TestCondition.runtimes(DexVm.Version.V5_1_1)))
// Contains a method (B.<init>) which pass too few arguments to invoke. Also, contains an
// iput on a static field.
- .put("600-verifier-fails",
+ .put(
+ "600-verifier-fails",
TestCondition.match(
TestCondition.D8_COMPILER,
- TestCondition.runtimes(DexVm.Version.V7_0_0, DexVm.Version.V6_0_1,
- DexVm.Version.V5_1_1)))
+ TestCondition.runtimes(
+ DexVm.Version.V7_0_0, DexVm.Version.V6_0_1, DexVm.Version.V5_1_1)))
// Dalvik 4.0.4 is missing ReflectiveOperationException class.
- .put("140-field-packing",
- TestCondition.match(
- TestCondition.runtimes(DexVm.Version.V4_0_4)))
+ .put(
+ "140-field-packing",
+ TestCondition.match(TestCondition.runtimes(DexVm.Version.V4_0_4)))
// Dalvik 4.0.4 is missing theUnsafe field.
- .put("528-long-hint",
- TestCondition.match(
- TestCondition.runtimes(DexVm.Version.V4_0_4)))
+ .put("528-long-hint", TestCondition.match(TestCondition.runtimes(DexVm.Version.V4_0_4)))
// Cannot catch exception in Dalvik 4.0.4.
- .put("084-class-init",
- TestCondition.match(
- TestCondition.runtimes(DexVm.Version.V4_0_4)))
+ .put("084-class-init", TestCondition.match(TestCondition.runtimes(DexVm.Version.V4_0_4)))
// Tested regression still exists in Dalvik 4.0.4.
- .put("301-abstract-protected",
- TestCondition.match(
- TestCondition.runtimes(DexVm.Version.V4_0_4)))
+ .put(
+ "301-abstract-protected",
+ TestCondition.match(TestCondition.runtimes(DexVm.Version.V4_0_4)))
// Illegal class flags in Dalvik 4.0.4.
- .put("121-modifiers",
- TestCondition.match(
- TestCondition.runtimes(DexVm.Version.V4_0_4)))
+ .put("121-modifiers", TestCondition.match(TestCondition.runtimes(DexVm.Version.V4_0_4)))
// Switch regression still present in Dalvik 4.0.4.
- .put("095-switch-MAX_INT",
+ .put(
+ "095-switch-MAX_INT",
TestCondition.match(
TestCondition.tools(DexTool.DX),
TestCondition.D8_COMPILER,
diff --git a/src/test/java/com/android/tools/r8/SwitchDebugLocalsConflictTest.java b/src/test/java/com/android/tools/r8/SwitchDebugLocalsConflictTest.java
index bec20c9..7a679e5 100644
--- a/src/test/java/com/android/tools/r8/SwitchDebugLocalsConflictTest.java
+++ b/src/test/java/com/android/tools/r8/SwitchDebugLocalsConflictTest.java
@@ -3,7 +3,8 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8;
-import static org.junit.Assert.assertTrue;
+import static com.android.tools.r8.DiagnosticsMatcher.diagnosticMessage;
+import static org.hamcrest.CoreMatchers.containsString;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -35,11 +36,11 @@
.noDesugaring()
.compileWithExpectedDiagnostics(
diagnotics -> {
- diagnotics.assertOnlyInfos();
- assertTrue(
- diagnotics.getInfos().stream()
- .anyMatch(
- d -> d.getDiagnosticMessage().contains("invalid locals information")));
+ diagnotics.assertNoErrors();
+ diagnotics.assertInfoThatMatches(
+ diagnosticMessage(containsString("invalid locals information")));
+ diagnotics.assertAllWarningsMatch(
+ diagnosticMessage(containsString("Could not find phi type for register 14")));
});
}
diff --git a/src/test/java/com/android/tools/r8/TestBase.java b/src/test/java/com/android/tools/r8/TestBase.java
index d065497..bb8cb6e 100644
--- a/src/test/java/com/android/tools/r8/TestBase.java
+++ b/src/test/java/com/android/tools/r8/TestBase.java
@@ -1482,6 +1482,10 @@
public boolean isAggressive() {
return this == AGGRESSIVE;
}
+
+ public static MinifyMode[] withoutNone() {
+ return new MinifyMode[] {JAVA, AGGRESSIVE};
+ }
}
public static ProgramConsumer emptyConsumer(Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/bridgeremoval/hoisting/FinalBridgeHoistingTest.java b/src/test/java/com/android/tools/r8/bridgeremoval/hoisting/FinalBridgeHoistingTest.java
new file mode 100644
index 0000000..de2e041
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/bridgeremoval/hoisting/FinalBridgeHoistingTest.java
@@ -0,0 +1,101 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8.bridgeremoval.hoisting;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import com.android.tools.r8.NeverClassInline;
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class FinalBridgeHoistingTest extends TestBase {
+
+ private final TestParameters parameters;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ public FinalBridgeHoistingTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void test() throws Exception {
+ testForR8(parameters.getBackend())
+ .addProgramClasses(TestClass.class, A.class, B1.class)
+ .addProgramClassFileData(
+ transformer(B2.class)
+ .setBridge(B2.class.getDeclaredMethod("virtualBridge", Object.class))
+ .transform())
+ .addKeepMainRule(TestClass.class)
+ .addKeepClassAndMembersRules(B1.class)
+ .enableInliningAnnotations()
+ .enableNeverClassInliningAnnotations()
+ .setMinApi(parameters.getApiLevel())
+ .compile()
+ .inspect(this::inspect)
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutputLines("Hello world!");
+ }
+
+ private void inspect(CodeInspector inspector) {
+ ClassSubject aClassSubject = inspector.clazz(A.class);
+ assertThat(aClassSubject, isPresent());
+ assertThat(aClassSubject.uniqueMethodWithName("m"), isPresent());
+ assertThat(aClassSubject.uniqueMethodWithName("virtualBridge"), isPresent());
+
+ ClassSubject b1ClassSubject = inspector.clazz(B1.class);
+ assertThat(b1ClassSubject, isPresent());
+ assertThat(b1ClassSubject.uniqueMethodWithName("virtualBridge"), isPresent());
+
+ ClassSubject b2ClassSubject = inspector.clazz(B2.class);
+ assertThat(b2ClassSubject, isPresent());
+ assertThat(b2ClassSubject.uniqueMethodWithName("virtualBridge"), not(isPresent()));
+ }
+
+ static class TestClass {
+
+ public static void main(String[] args) {
+ System.out.print(new B1().virtualBridge("Hello"));
+ System.out.println(new B2().virtualBridge(" world!"));
+ }
+ }
+
+ static class A {
+
+ @NeverInline
+ public Object m(String arg) {
+ return System.currentTimeMillis() >= 0 ? arg : null;
+ }
+ }
+
+ @NeverClassInline
+ static class B1 extends A {
+
+ public String virtualBridge(Object o) {
+ return (String) m((String) o);
+ }
+ }
+
+ @NeverClassInline
+ static class B2 extends A {
+
+ @NeverInline
+ public final /*bridge*/ String virtualBridge(Object o) {
+ return (String) m((String) o);
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/DesugarToClassFileDeprecatedAttribute.java b/src/test/java/com/android/tools/r8/desugar/DesugarToClassFileDeprecatedAttribute.java
new file mode 100644
index 0000000..0eac295
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/DesugarToClassFileDeprecatedAttribute.java
@@ -0,0 +1,128 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.desugar;
+
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.ByteDataView;
+import com.android.tools.r8.ClassFileConsumer;
+import com.android.tools.r8.DiagnosticsHandler;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.InternalOptions;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+
+@RunWith(Parameterized.class)
+public class DesugarToClassFileDeprecatedAttribute extends TestBase {
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimes().withAllApiLevelsAlsoForCf().build();
+ }
+
+ private final TestParameters parameters;
+
+ public DesugarToClassFileDeprecatedAttribute(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ private boolean isDeprecated(int access) {
+ return (access & Opcodes.ACC_DEPRECATED) == Opcodes.ACC_DEPRECATED;
+ }
+
+ private void checkDeprecatedAttributes(byte[] classBytes) {
+ ClassReader cr = new ClassReader(classBytes);
+ cr.accept(
+ new ClassVisitor(InternalOptions.ASM_VERSION) {
+ @Override
+ public void visit(
+ int version,
+ int access,
+ String name,
+ String signature,
+ String superName,
+ String[] interfaces) {
+ assertTrue(isDeprecated(access));
+ }
+
+ @Override
+ public MethodVisitor visitMethod(
+ int access, String name, String desc, String signature, String[] exceptions) {
+ if (!name.equals("<init>")) {
+ assertTrue(isDeprecated(access));
+ }
+ return super.visitMethod(access, name, desc, signature, exceptions);
+ }
+
+ @Override
+ public FieldVisitor visitField(
+ int access, String name, String descriptor, String signature, Object value) {
+ assertTrue(isDeprecated(access));
+ return super.visitField(access, name, descriptor, signature, value);
+ }
+ },
+ 0);
+ }
+
+ @Test
+ public void test() throws Exception {
+ checkDeprecatedAttributes(
+ Files.readAllBytes(ToolHelper.getClassFileForTestClass(TestClass.class)));
+
+ // Use D8 to desugar with Java classfile output.
+ Path jar =
+ testForD8(Backend.CF)
+ .addProgramClasses(TestClass.class)
+ .setMinApi(parameters.getApiLevel())
+ .setProgramConsumer(
+ new ClassFileConsumer.ForwardingConsumer(null) {
+ @Override
+ public void accept(
+ ByteDataView data, String descriptor, DiagnosticsHandler handler) {
+ checkDeprecatedAttributes(data.getBuffer());
+ }
+ })
+ .compile()
+ .writeToZip();
+
+ if (parameters.getRuntime().isCf()) {
+ // Run on the JVM.
+ testForJvm()
+ .addProgramFiles(jar)
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutputLines("Hello, world!");
+ } else {
+ assert parameters.getRuntime().isDex();
+ // Convert to DEX without desugaring.
+ testForD8()
+ .addProgramFiles(jar)
+ .setMinApi(parameters.getApiLevel())
+ .disableDesugaring()
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutputLines("Hello, world!");
+ }
+ }
+
+ @Deprecated
+ public static class TestClass {
+ @Deprecated public Object object = new Object();
+
+ @Deprecated
+ public static void main(String[] args) {
+ System.out.println("Hello, world!");
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/BackportDuplicationTest.java b/src/test/java/com/android/tools/r8/desugar/backports/BackportDuplicationTest.java
index 31575df..d4346cc 100644
--- a/src/test/java/com/android/tools/r8/desugar/backports/BackportDuplicationTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/backports/BackportDuplicationTest.java
@@ -8,6 +8,7 @@
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
+import com.android.tools.r8.OutputMode;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
@@ -155,6 +156,33 @@
});
}
+ @Test
+ public void testD8FilePerClassFile() throws Exception {
+ runD8FilePerMode(OutputMode.DexFilePerClassFile);
+ }
+
+ @Test
+ public void testD8FilePerClass() throws Exception {
+ runD8FilePerMode(OutputMode.DexFilePerClass);
+ }
+
+ public void runD8FilePerMode(OutputMode outputMode) throws Exception {
+ Path perClassOutput =
+ testForD8(parameters.getBackend())
+ .setOutputMode(outputMode)
+ .addProgramClasses(CLASSES)
+ .setMinApi(parameters.getApiLevel())
+ .compile()
+ .writeToZip();
+ testForD8()
+ .addProgramFiles(perClassOutput)
+ .setMinApi(parameters.getApiLevel())
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutput(EXPECTED)
+ .inspect(this::checkNoInternalSyntheticNames)
+ .inspect(this::checkExpectedSynthetics);
+ }
+
private void checkNoInternalSyntheticNames(CodeInspector inspector) {
inspector.forAllClasses(
clazz -> {
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/BackportMainDexTest.java b/src/test/java/com/android/tools/r8/desugar/backports/BackportMainDexTest.java
index 424a48f..4a2e645 100644
--- a/src/test/java/com/android/tools/r8/desugar/backports/BackportMainDexTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/backports/BackportMainDexTest.java
@@ -15,6 +15,7 @@
import com.android.tools.r8.DexIndexedConsumer;
import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.GenerateMainDexListRunResult;
+import com.android.tools.r8.OutputMode;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
@@ -119,9 +120,6 @@
Path out =
testForD8()
.addProgramClasses(CLASSES)
- // Setting intermediate will annotate synthetics, which should not cause types in those
- // to become main-dex included.
- .setIntermediate(true)
.setMinApi(parameters.getApiLevel())
.compile()
.writeToZip();
@@ -136,6 +134,24 @@
}
@Test
+ public void testMainDexTracingDexIntermediates() throws Exception {
+ assumeTrue(parameters.isDexRuntime());
+ Path out =
+ testForD8()
+ .addProgramClasses(CLASSES)
+ // Setting intermediate will annotate synthetics, which should not cause types in those
+ // to become main-dex included.
+ .setIntermediate(true)
+ .setMinApi(parameters.getApiLevel())
+ .compile()
+ .writeToZip();
+ GenerateMainDexListRunResult mainDexListFromDex =
+ traceMainDex(Collections.emptyList(), Collections.singleton(out));
+ // Compiling in intermediate will not share the synthetics so there is one per call site.
+ assertEquals(MAIN_DEX_LIST_CLASSES.size() + 6, mainDexListFromDex.getMainDexList().size());
+ }
+
+ @Test
public void testD8() throws Exception {
assumeTrue(parameters.isDexRuntime());
MainDexConsumer mainDexConsumer = new MainDexConsumer();
@@ -151,6 +167,38 @@
checkMainDex(mainDexConsumer);
}
+ @Test
+ public void testD8FilePerClassFile() throws Exception {
+ runD8FilePerMode(OutputMode.DexFilePerClassFile);
+ }
+
+ @Test
+ public void testD8FilePerClass() throws Exception {
+ runD8FilePerMode(OutputMode.DexFilePerClass);
+ }
+
+ private void runD8FilePerMode(OutputMode outputMode) throws Exception {
+ assumeTrue(parameters.isDexRuntime());
+ Path perClassOutput =
+ testForD8(parameters.getBackend())
+ .setOutputMode(outputMode)
+ .addProgramClasses(CLASSES)
+ .setMinApi(parameters.getApiLevel())
+ .compile()
+ .writeToZip();
+ MainDexConsumer mainDexConsumer = new MainDexConsumer();
+ testForD8()
+ .addProgramFiles(perClassOutput)
+ .setMinApi(parameters.getApiLevel())
+ .addMainDexListClasses(MiniAssert.class, TestClass.class, User2.class)
+ .setProgramConsumer(mainDexConsumer)
+ .compile()
+ .inspect(this::checkExpectedSynthetics)
+ .run(parameters.getRuntime(), TestClass.class, getRunArgs())
+ .assertSuccessWithOutput(EXPECTED);
+ checkMainDex(mainDexConsumer);
+ }
+
// TODO(b/168584485): This test should be removed once support is dropped.
@Test
public void testD8MergingWithTraceCf() throws Exception {
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaTimeTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaTimeTest.java
index 6db1591..558b5f1 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaTimeTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaTimeTest.java
@@ -5,7 +5,6 @@
package com.android.tools.r8.desugar.desugaredlibrary;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
@@ -18,7 +17,6 @@
import com.android.tools.r8.StringResource;
import com.android.tools.r8.TestCompileResult;
import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.TestRunResult;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.utils.AndroidApiLevel;
@@ -230,19 +228,11 @@
.assertSuccessWithOutput(expectedOutput);
} else {
// Run on the JVM with desugared library on classpath.
- TestRunResult<?> result =
- testForJvm()
- .addProgramFiles(jar)
- .addRunClasspathFiles(desugaredLibraryClassFile.get())
- .run(parameters.getRuntime(), TestClass.class);
- if (parameters.getApiLevel().isGreaterThan(AndroidApiLevel.N_MR1)) {
- // java.time is present from O, so the desugared library classes are not loaded.
- result.assertSuccessWithOutput(expectedOutput);
- } else {
- // TODO(b/164396438): Produce correct stack map.
- result.assertFailureWithErrorThatMatches(
- containsString("java.lang.VerifyError: Bad type on operand stack"));
- }
+ testForJvm()
+ .addProgramFiles(jar)
+ .addRunClasspathFiles(desugaredLibraryClassFile.get())
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutput(expectedOutput);
}
}
diff --git a/src/test/java/com/android/tools/r8/ir/DebugLocalSynchronizedBlockTest.java b/src/test/java/com/android/tools/r8/ir/DebugLocalSynchronizedBlockTest.java
new file mode 100644
index 0000000..f6be937
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/DebugLocalSynchronizedBlockTest.java
@@ -0,0 +1,67 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.ir;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class DebugLocalSynchronizedBlockTest extends TestBase {
+
+ private final TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimes().withAllApiLevelsAlsoForCf().build();
+ }
+
+ public DebugLocalSynchronizedBlockTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testD8() throws Exception {
+ testForD8(parameters.getBackend())
+ .addProgramClasses(Main.class)
+ .setMinApi(parameters.getApiLevel())
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines("Hello World!");
+ }
+
+ public static class Main {
+
+ private int state = 0;
+ private int[] values = {42};
+
+ public static void main(String[] args) {
+ Main main = new Main();
+ if (args.length == 0) {
+ main.state = 1;
+ } else {
+ main.state = 0;
+ }
+ main.thread1();
+ System.out.println("Hello World!");
+ }
+
+ void thread1() {
+ int s;
+ do {
+ synchronized (Main.class) {
+ s = state;
+ }
+ } while (s != 1); // Busy loop.
+ synchronized (Main.class) {
+ values = null;
+ state = 2;
+ }
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/DebugLocalWithoutStackMapTypeTest.java b/src/test/java/com/android/tools/r8/ir/DebugLocalWithoutStackMapTypeTest.java
new file mode 100644
index 0000000..0326e06
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/DebugLocalWithoutStackMapTypeTest.java
@@ -0,0 +1,200 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.ir;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import java.lang.reflect.Method;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+
+@RunWith(Parameterized.class)
+public class DebugLocalWithoutStackMapTypeTest extends TestBase {
+
+ private final TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimes().withAllApiLevelsAlsoForCf().build();
+ }
+
+ public DebugLocalWithoutStackMapTypeTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testD8() throws Exception {
+ testForD8(parameters.getBackend())
+ .addProgramClassFileData(MainDump.dump())
+ .setMinApi(parameters.getApiLevel())
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines("addSuppressed");
+ }
+
+ public static class Main {
+
+ private static final Method addSuppressedExceptionMethod;
+
+ static {
+ Method m;
+ try {
+ m = Throwable.class.getDeclaredMethod("addSuppressed", Throwable.class);
+ } catch (Exception e) {
+ m = null;
+ }
+ addSuppressedExceptionMethod = m;
+ }
+
+ public static void main(String[] args) {
+ System.out.println(addSuppressedExceptionMethod.getName());
+ }
+ }
+
+ // When compiling with JDK 7 the local variable for m is not split in Main::<clinit>. See
+ // comment below where the local variable ranges for clinit is added.
+ public static class MainDump implements Opcodes {
+
+ public static byte[] dump() {
+
+ ClassWriter classWriter = new ClassWriter(0);
+ FieldVisitor fieldVisitor;
+ MethodVisitor methodVisitor;
+
+ classWriter.visit(
+ V1_8,
+ ACC_PUBLIC | ACC_SUPER,
+ "com/android/tools/r8/ir/DebugLocalWithoutStackMapTypeTest$Main",
+ null,
+ "java/lang/Object",
+ null);
+
+ classWriter.visitInnerClass(
+ "com/android/tools/r8/ir/DebugLocalWithoutStackMapTypeTest$Main",
+ "com/android/tools/r8/ir/DebugLocalWithoutStackMapTypeTest",
+ "Main",
+ ACC_PUBLIC | ACC_STATIC);
+
+ {
+ fieldVisitor =
+ classWriter.visitField(
+ ACC_PRIVATE | ACC_FINAL | ACC_STATIC,
+ "addSuppressedExceptionMethod",
+ "Ljava/lang/reflect/Method;",
+ null,
+ null);
+ fieldVisitor.visitEnd();
+ }
+ {
+ methodVisitor = classWriter.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
+ methodVisitor.visitCode();
+ methodVisitor.visitVarInsn(ALOAD, 0);
+ methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
+ methodVisitor.visitInsn(RETURN);
+ methodVisitor.visitMaxs(1, 1);
+ methodVisitor.visitEnd();
+ }
+ {
+ methodVisitor =
+ classWriter.visitMethod(
+ ACC_PUBLIC | ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null);
+ methodVisitor.visitCode();
+ Label label0 = new Label();
+ methodVisitor.visitLabel(label0);
+ methodVisitor.visitLineNumber(63, label0);
+ methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+ methodVisitor.visitFieldInsn(
+ GETSTATIC,
+ "com/android/tools/r8/ir/DebugLocalWithoutStackMapTypeTest$Main",
+ "addSuppressedExceptionMethod",
+ "Ljava/lang/reflect/Method;");
+ methodVisitor.visitMethodInsn(
+ INVOKEVIRTUAL, "java/lang/reflect/Method", "getName", "()Ljava/lang/String;", false);
+ methodVisitor.visitMethodInsn(
+ INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
+ Label label1 = new Label();
+ methodVisitor.visitLabel(label1);
+ methodVisitor.visitLineNumber(64, label1);
+ methodVisitor.visitInsn(RETURN);
+ Label label2 = new Label();
+ methodVisitor.visitLabel(label2);
+ methodVisitor.visitLocalVariable("args", "[Ljava/lang/String;", null, label0, label2, 0);
+ methodVisitor.visitMaxs(2, 1);
+ methodVisitor.visitEnd();
+ }
+ {
+ methodVisitor = classWriter.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null);
+ methodVisitor.visitCode();
+ Label label0 = new Label();
+ Label label1 = new Label();
+ Label label2 = new Label();
+ methodVisitor.visitTryCatchBlock(label0, label1, label2, "java/lang/Exception");
+ methodVisitor.visitLabel(label0);
+ methodVisitor.visitLineNumber(55, label0);
+ methodVisitor.visitLdcInsn(Type.getType("Ljava/lang/Throwable;"));
+ methodVisitor.visitLdcInsn("addSuppressed");
+ methodVisitor.visitInsn(ICONST_1);
+ methodVisitor.visitTypeInsn(ANEWARRAY, "java/lang/Class");
+ methodVisitor.visitInsn(DUP);
+ methodVisitor.visitInsn(ICONST_0);
+ methodVisitor.visitLdcInsn(Type.getType("Ljava/lang/Throwable;"));
+ methodVisitor.visitInsn(AASTORE);
+ methodVisitor.visitMethodInsn(
+ INVOKEVIRTUAL,
+ "java/lang/Class",
+ "getDeclaredMethod",
+ "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;",
+ false);
+ methodVisitor.visitVarInsn(ASTORE, 0);
+ methodVisitor.visitLabel(label1);
+ methodVisitor.visitLineNumber(58, label1);
+ Label label3 = new Label();
+ methodVisitor.visitJumpInsn(GOTO, label3);
+ methodVisitor.visitLabel(label2);
+ methodVisitor.visitLineNumber(56, label2);
+ methodVisitor.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {"java/lang/Exception"});
+ methodVisitor.visitVarInsn(ASTORE, 1);
+ Label label4 = new Label();
+ methodVisitor.visitLabel(label4);
+ methodVisitor.visitLineNumber(57, label4);
+ methodVisitor.visitInsn(ACONST_NULL);
+ methodVisitor.visitVarInsn(ASTORE, 0);
+ methodVisitor.visitLabel(label3);
+ methodVisitor.visitLineNumber(59, label3);
+ methodVisitor.visitFrame(
+ Opcodes.F_APPEND, 1, new Object[] {"java/lang/reflect/Method"}, 0, null);
+ methodVisitor.visitVarInsn(ALOAD, 0);
+ methodVisitor.visitFieldInsn(
+ PUTSTATIC,
+ "com/android/tools/r8/ir/DebugLocalWithoutStackMapTypeTest$Main",
+ "addSuppressedExceptionMethod",
+ "Ljava/lang/reflect/Method;");
+ Label label5 = new Label();
+ methodVisitor.visitLabel(label5);
+ methodVisitor.visitLineNumber(60, label5);
+ methodVisitor.visitInsn(RETURN);
+ // When compiling with JDK v7 the local variable for m is not split, and m therefore ranges
+ // from label1 to label5. From JDK v8 and upward, the range for m is split in label1-label2
+ // and label4-label5.
+ methodVisitor.visitLocalVariable(
+ "m", "Ljava/lang/reflect/Method;", null, label1, label5, 0);
+ methodVisitor.visitLocalVariable("e", "Ljava/lang/Exception;", null, label4, label3, 1);
+ methodVisitor.visitMaxs(6, 2);
+ methodVisitor.visitEnd();
+ }
+ classWriter.visitEnd();
+
+ return classWriter.toByteArray();
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/analysis/type/NarrowingWithoutSubtypingTest.java b/src/test/java/com/android/tools/r8/ir/analysis/type/NarrowingWithoutSubtypingTest.java
index 6644af2..403372c 100644
--- a/src/test/java/com/android/tools/r8/ir/analysis/type/NarrowingWithoutSubtypingTest.java
+++ b/src/test/java/com/android/tools/r8/ir/analysis/type/NarrowingWithoutSubtypingTest.java
@@ -4,10 +4,16 @@
package com.android.tools.r8.ir.analysis.type;
+import static com.android.tools.r8.DiagnosticsMatcher.diagnosticMessage;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.junit.Assert.assertThrows;
+
import com.android.tools.r8.CompilationFailedException;
+import com.android.tools.r8.D8TestBuilder;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.BooleanUtils;
+import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -17,29 +23,47 @@
public class NarrowingWithoutSubtypingTest extends TestBase {
private final TestParameters parameters;
+ private final boolean readStackMap;
- @Parameters(name = "{0}")
- public static TestParametersCollection data() {
- return getTestParameters().withDexRuntimes().withAllApiLevels().build();
+ @Parameters(name = "{0}, read stack map: {1}")
+ public static List<Object[]> data() {
+ return buildParameters(
+ getTestParameters().withDexRuntimes().withAllApiLevels().build(), BooleanUtils.values());
}
- public NarrowingWithoutSubtypingTest(TestParameters parameters) {
+ public NarrowingWithoutSubtypingTest(TestParameters parameters, boolean readStackMap) {
this.parameters = parameters;
+ this.readStackMap = readStackMap;
}
- @Test(expected = CompilationFailedException.class)
+ @Test
public void test() throws Exception {
- testForD8()
- .addInnerClasses(NarrowingWithoutSubtypingTest.class)
- .addOptionsModification(
- options -> {
- options.testing.enableNarrowingChecksInD8 = true;
- options.testing.noLocalsTableOnInput = true;
- })
- .setMinApi(parameters.getApiLevel())
- .compile()
- .run(parameters.getRuntime(), TestClass.class)
- .assertSuccessWithOutputLines("Hello world!");
+ D8TestBuilder d8TestBuilder =
+ testForD8()
+ .addInnerClasses(NarrowingWithoutSubtypingTest.class)
+ .addOptionsModification(
+ options -> {
+ options.testing.readInputStackMaps = readStackMap;
+ options.testing.enableNarrowAndWideningingChecksInD8 = true;
+ options.testing.noLocalsTableOnInput = true;
+ })
+ .setMinApi(parameters.getApiLevel());
+ if (readStackMap) {
+ d8TestBuilder
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutputLines("Hello world!");
+ } else {
+ // TODO(b/169120386): We should not be narrowing in D8.
+ assertThrows(
+ CompilationFailedException.class,
+ () -> {
+ d8TestBuilder.compileWithExpectedDiagnostics(
+ diagnostics ->
+ diagnostics.assertAllErrorsMatch(
+ diagnosticMessage(
+ containsString("java.lang.AssertionError: During NARROWING"))));
+ });
+ }
}
static class TestClass {
diff --git a/src/test/java/com/android/tools/r8/jasmin/JasminTestBase.java b/src/test/java/com/android/tools/r8/jasmin/JasminTestBase.java
index b7a60bc..ab2d643 100644
--- a/src/test/java/com/android/tools/r8/jasmin/JasminTestBase.java
+++ b/src/test/java/com/android/tools/r8/jasmin/JasminTestBase.java
@@ -253,6 +253,7 @@
return ToolHelper.runArtRaw(ImmutableList.of(dex.toString(), libraryDex.toString()), main, null);
}
+ @Override
protected ProcessResult runOnArtRaw(AndroidApp app, String main) throws IOException {
Path out = temp.getRoot().toPath().resolve("out.zip");
app.writeToZip(out, OutputMode.DexIndexed);
diff --git a/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java b/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
index 37d2899..e03e056 100644
--- a/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
+++ b/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
@@ -53,7 +53,9 @@
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.code.CatchHandlers;
import com.android.tools.r8.ir.code.IRCode;
+import com.android.tools.r8.ir.code.Phi.RegisterReadType;
import com.android.tools.r8.ir.code.Position;
+import com.android.tools.r8.ir.code.ValueTypeConstraint;
import com.android.tools.r8.ir.conversion.IRBuilder;
import com.android.tools.r8.ir.conversion.SourceCode;
import com.android.tools.r8.ir.regalloc.LinearScanRegisterAllocator;
@@ -915,6 +917,12 @@
}
@Override
+ public DexType getPhiTypeForBlock(
+ int register, int blockOffset, ValueTypeConstraint constraint, RegisterReadType readType) {
+ throw new Unreachable("Should never generate a phi");
+ }
+
+ @Override
public DebugLocalInfo getIncomingLocal(int register) {
return null;
}
diff --git a/src/test/java/com/android/tools/r8/retrace/RetraceCommandLineTests.java b/src/test/java/com/android/tools/r8/retrace/RetraceCommandLineTests.java
index 8a0f5e5..15ed0d9 100644
--- a/src/test/java/com/android/tools/r8/retrace/RetraceCommandLineTests.java
+++ b/src/test/java/com/android/tools/r8/retrace/RetraceCommandLineTests.java
@@ -7,7 +7,6 @@
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.StringContains.containsString;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.ProcessResult;
@@ -175,14 +174,6 @@
assertEquals(expected, result.stdout);
}
- private void runTestNotEquals(
- String mapping, String stackTrace, boolean stacktraceStdIn, String expected, String... args)
- throws IOException {
- ProcessResult result = runRetrace(mapping, stackTrace, stacktraceStdIn, args);
- assertEquals(0, result.exitCode);
- assertNotEquals(expected, result.stdout);
- }
-
private void runAbortTest(Matcher<String> errorMatch, String... args) throws IOException {
ProcessResult result = runRetraceCommandLine(null, Arrays.asList(args));
assertEquals(1, result.exitCode);
diff --git a/src/test/java/com/android/tools/r8/retrace/RetraceTests.java b/src/test/java/com/android/tools/r8/retrace/RetraceTests.java
index 8bf3b29..d7a5246 100644
--- a/src/test/java/com/android/tools/r8/retrace/RetraceTests.java
+++ b/src/test/java/com/android/tools/r8/retrace/RetraceTests.java
@@ -20,6 +20,8 @@
import com.android.tools.r8.retrace.stacktraces.ActualRetraceBotStackTrace;
import com.android.tools.r8.retrace.stacktraces.AmbiguousMissingLineStackTrace;
import com.android.tools.r8.retrace.stacktraces.AmbiguousStackTrace;
+import com.android.tools.r8.retrace.stacktraces.AmbiguousWithMultipleLineMappingsStackTrace;
+import com.android.tools.r8.retrace.stacktraces.AmbiguousWithSignatureNonVerboseStackTrace;
import com.android.tools.r8.retrace.stacktraces.CircularReferenceStackTrace;
import com.android.tools.r8.retrace.stacktraces.FileNameExtensionStackTrace;
import com.android.tools.r8.retrace.stacktraces.InlineFileNameStackTrace;
@@ -141,6 +143,16 @@
}
@Test
+ public void testAmbiguousMissingLineNotVerbose() {
+ runRetraceTest(new AmbiguousWithSignatureNonVerboseStackTrace());
+ }
+
+ @Test
+ public void testAmbiguousMultipleMappingsTest() {
+ runRetraceTest(new AmbiguousWithMultipleLineMappingsStackTrace());
+ }
+
+ @Test
public void testInliningWithLineNumbers() {
runRetraceTest(new InlineWithLineNumbersStackTrace());
}
diff --git a/src/test/java/com/android/tools/r8/retrace/RetraceVerboseTests.java b/src/test/java/com/android/tools/r8/retrace/RetraceVerboseTests.java
index 277d190..fb65c1d 100644
--- a/src/test/java/com/android/tools/r8/retrace/RetraceVerboseTests.java
+++ b/src/test/java/com/android/tools/r8/retrace/RetraceVerboseTests.java
@@ -4,15 +4,19 @@
package com.android.tools.r8.retrace;
+import static com.android.tools.r8.retrace.Retrace.DEFAULT_REGULAR_EXPRESSION;
import static junit.framework.TestCase.assertEquals;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestDiagnosticMessagesImpl;
import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.retrace.stacktraces.AmbiguousMethodVerboseStackTrace;
+import com.android.tools.r8.retrace.stacktraces.AmbiguousWithSignatureVerboseStackTrace;
import com.android.tools.r8.retrace.stacktraces.FoundMethodVerboseStackTrace;
import com.android.tools.r8.retrace.stacktraces.StackTraceForTest;
-import com.android.tools.r8.retrace.stacktraces.UnknownMethodVerboseStackTrace;
+import com.android.tools.r8.retrace.stacktraces.VerboseUnknownStackTrace;
+import com.android.tools.r8.utils.BooleanUtils;
+import java.util.Collection;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -21,12 +25,16 @@
@RunWith(Parameterized.class)
public class RetraceVerboseTests extends TestBase {
- @Parameters(name = "{0}")
- public static TestParametersCollection data() {
- return getTestParameters().withNoneRuntime().build();
+ @Parameters(name = "{0}, use regular expression: {1}")
+ public static Collection<Object[]> data() {
+ return buildParameters(getTestParameters().withNoneRuntime().build(), BooleanUtils.values());
}
- public RetraceVerboseTests(TestParameters parameters) {}
+ private final boolean useRegExpParsing;
+
+ public RetraceVerboseTests(TestParameters parameters, boolean useRegExpParsing) {
+ this.useRegExpParsing = useRegExpParsing;
+ }
@Test
public void testFoundMethod() {
@@ -35,7 +43,17 @@
@Test
public void testUnknownMethod() {
- runRetraceTest(new UnknownMethodVerboseStackTrace());
+ runRetraceTest(new AmbiguousMethodVerboseStackTrace());
+ }
+
+ @Test
+ public void testVerboseUnknownMethod() {
+ runRetraceTest(new VerboseUnknownStackTrace());
+ }
+
+ @Test
+ public void testAmbiguousMissingLineVerbose() {
+ runRetraceTest(new AmbiguousWithSignatureVerboseStackTrace());
}
private TestDiagnosticMessagesImpl runRetraceTest(StackTraceForTest stackTraceForTest) {
@@ -44,6 +62,7 @@
RetraceCommand.builder(diagnosticsHandler)
.setProguardMapProducer(stackTraceForTest::mapping)
.setStackTrace(stackTraceForTest.obfuscatedStackTrace())
+ .setRegularExpression(useRegExpParsing ? DEFAULT_REGULAR_EXPRESSION : null)
.setVerbose(true)
.setRetracedStackTraceConsumer(
retraced -> assertEquals(stackTraceForTest.retracedStackTrace(), retraced))
diff --git a/src/test/java/com/android/tools/r8/retrace/stacktraces/UnknownMethodVerboseStackTrace.java b/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousMethodVerboseStackTrace.java
similarity index 95%
rename from src/test/java/com/android/tools/r8/retrace/stacktraces/UnknownMethodVerboseStackTrace.java
rename to src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousMethodVerboseStackTrace.java
index 5a47079..dcaaa58 100644
--- a/src/test/java/com/android/tools/r8/retrace/stacktraces/UnknownMethodVerboseStackTrace.java
+++ b/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousMethodVerboseStackTrace.java
@@ -8,7 +8,7 @@
import java.util.Arrays;
import java.util.List;
-public class UnknownMethodVerboseStackTrace implements StackTraceForTest {
+public class AmbiguousMethodVerboseStackTrace implements StackTraceForTest {
@Override
public List<String> obfuscatedStackTrace() {
diff --git a/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousWithMultipleLineMappingsStackTrace.java b/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousWithMultipleLineMappingsStackTrace.java
new file mode 100644
index 0000000..ddd4b92
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousWithMultipleLineMappingsStackTrace.java
@@ -0,0 +1,44 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.retrace.stacktraces;
+
+import com.android.tools.r8.utils.StringUtils;
+import java.util.Arrays;
+import java.util.List;
+
+public class AmbiguousWithMultipleLineMappingsStackTrace implements StackTraceForTest {
+
+ @Override
+ public List<String> obfuscatedStackTrace() {
+ return Arrays.asList(
+ "java.lang.IndexOutOfBoundsException",
+ "\tat java.util.ArrayList.get(ArrayList.java:411)",
+ "\tat com.android.tools.r8.Internal.zza(Unknown)");
+ }
+
+ @Override
+ public String mapping() {
+ return StringUtils.lines(
+ "com.android.tools.r8.Internal -> com.android.tools.r8.Internal:",
+ " 10:10:void foo(int):10:10 -> zza",
+ " 11:11:void foo(int):11:11 -> zza",
+ " 12:12:void foo(int):12:12 -> zza");
+ }
+
+ @Override
+ public List<String> retracedStackTrace() {
+ return Arrays.asList(
+ "java.lang.IndexOutOfBoundsException",
+ "\tat java.util.ArrayList.get(ArrayList.java:411)",
+ "\tat com.android.tools.r8.Internal.foo(Internal.java)",
+ "\t<OR> at com.android.tools.r8.Internal.foo(Internal.java)",
+ "\t<OR> at com.android.tools.r8.Internal.foo(Internal.java)");
+ }
+
+ @Override
+ public int expectedWarnings() {
+ return 0;
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousWithSignatureNonVerboseStackTrace.java b/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousWithSignatureNonVerboseStackTrace.java
new file mode 100644
index 0000000..aa5946c
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousWithSignatureNonVerboseStackTrace.java
@@ -0,0 +1,46 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.retrace.stacktraces;
+
+import com.android.tools.r8.utils.StringUtils;
+import java.util.Arrays;
+import java.util.List;
+
+public class AmbiguousWithSignatureNonVerboseStackTrace implements StackTraceForTest {
+
+ @Override
+ public List<String> obfuscatedStackTrace() {
+ return Arrays.asList(
+ "java.lang.IndexOutOfBoundsException",
+ "\tat java.util.ArrayList.get(ArrayList.java:411)",
+ "\tat com.android.tools.r8.Internal.zza(Unknown)");
+ }
+
+ @Override
+ public String mapping() {
+ return StringUtils.lines(
+ "com.android.tools.r8.Internal -> com.android.tools.r8.Internal:",
+ " 10:10:void foo(int):10:10 -> zza",
+ " 11:11:void foo(int, int):11:11 -> zza",
+ " 12:12:void foo(int, boolean):12:12 -> zza",
+ " 13:13:boolean foo(int, int):13:13 -> zza");
+ }
+
+ @Override
+ public List<String> retracedStackTrace() {
+ return Arrays.asList(
+ "java.lang.IndexOutOfBoundsException",
+ "\tat java.util.ArrayList.get(ArrayList.java:411)",
+ "\tat com.android.tools.r8.Internal.foo(Internal.java)",
+ "\t<OR> at com.android.tools.r8.Internal.foo(Internal.java)",
+ "\t<OR> at com.android.tools.r8.Internal.foo(Internal.java)",
+ "\t<OR> at com.android.tools.r8.Internal.foo(Internal.java)");
+ }
+
+ @Override
+ public int expectedWarnings() {
+ return 0;
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousWithSignatureVerboseStackTrace.java b/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousWithSignatureVerboseStackTrace.java
new file mode 100644
index 0000000..1dfb3c9
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousWithSignatureVerboseStackTrace.java
@@ -0,0 +1,46 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.retrace.stacktraces;
+
+import com.android.tools.r8.utils.StringUtils;
+import java.util.Arrays;
+import java.util.List;
+
+public class AmbiguousWithSignatureVerboseStackTrace implements StackTraceForTest {
+
+ @Override
+ public List<String> obfuscatedStackTrace() {
+ return Arrays.asList(
+ "java.lang.IndexOutOfBoundsException",
+ "\tat java.util.ArrayList.get(ArrayList.java:411)",
+ "\tat com.android.tools.r8.Internal.zza(Unknown)");
+ }
+
+ @Override
+ public String mapping() {
+ return StringUtils.lines(
+ "com.android.tools.r8.Internal -> com.android.tools.r8.Internal:",
+ " 10:10:void foo(int):10:10 -> zza",
+ " 11:11:void foo(int,int):11:11 -> zza",
+ " 12:12:void foo(int,boolean):12:12 -> zza",
+ " 13:13:boolean foo(int,int):13:13 -> zza");
+ }
+
+ @Override
+ public List<String> retracedStackTrace() {
+ return Arrays.asList(
+ "java.lang.IndexOutOfBoundsException",
+ "\tat java.util.ArrayList.get(ArrayList.java:411)",
+ "\tat com.android.tools.r8.Internal.void foo(int)(Internal.java)",
+ "\t<OR> at com.android.tools.r8.Internal.void foo(int,int)(Internal.java)",
+ "\t<OR> at com.android.tools.r8.Internal.void foo(int,boolean)(Internal.java)",
+ "\t<OR> at com.android.tools.r8.Internal.boolean foo(int,int)(Internal.java)");
+ }
+
+ @Override
+ public int expectedWarnings() {
+ return 0;
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/retrace/stacktraces/VerboseUnknownStackTrace.java b/src/test/java/com/android/tools/r8/retrace/stacktraces/VerboseUnknownStackTrace.java
new file mode 100644
index 0000000..3cb6808
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/retrace/stacktraces/VerboseUnknownStackTrace.java
@@ -0,0 +1,33 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.retrace.stacktraces;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class VerboseUnknownStackTrace implements StackTraceForTest {
+
+ @Override
+ public List<String> obfuscatedStackTrace() {
+ return Arrays.asList(
+ "java.lang.IndexOutOfBoundsException", "\tat java.util.ArrayList.get(ArrayList.java:411)");
+ }
+
+ @Override
+ public String mapping() {
+ return "";
+ }
+
+ @Override
+ public List<String> retracedStackTrace() {
+ return Arrays.asList(
+ "java.lang.IndexOutOfBoundsException", "\tat java.util.ArrayList.get(ArrayList.java:411)");
+ }
+
+ @Override
+ public int expectedWarnings() {
+ return 0;
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/shaking/TreeShakingTest.java b/src/test/java/com/android/tools/r8/shaking/TreeShakingTest.java
index 6f7c644..96c6fb3 100644
--- a/src/test/java/com/android/tools/r8/shaking/TreeShakingTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/TreeShakingTest.java
@@ -3,25 +3,28 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking;
-import static com.android.tools.r8.ToolHelper.DEFAULT_PROGUARD_MAP_FILE;
+import static org.junit.Assume.assumeFalse;
-import com.android.tools.r8.OutputMode;
-import com.android.tools.r8.R8Command;
+import com.android.tools.r8.R8FullTestBuilder;
+import com.android.tools.r8.R8TestCompileResult;
import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestCompilerBuilder.DiagnosticsConsumer;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestRuntime.CfRuntime;
+import com.android.tools.r8.ThrowableConsumer;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.ArtCommandBuilder;
+import com.android.tools.r8.ToolHelper.DexVm;
import com.android.tools.r8.ToolHelper.ProcessResult;
-import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.naming.MemberNaming.FieldSignature;
import com.android.tools.r8.naming.MemberNaming.MethodSignature;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.ListUtils;
-import com.android.tools.r8.utils.TestDescriptionWatcher;
+import com.android.tools.r8.utils.ThrowingConsumer;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.FoundFieldSubject;
import com.android.tools.r8.utils.codeinspector.FoundMethodSubject;
-import com.google.common.collect.ImmutableList;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -31,8 +34,7 @@
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import org.junit.Assert;
-import org.junit.Rule;
-import org.junit.rules.TemporaryFolder;
+import org.junit.runners.Parameterized.Parameters;
/**
* Base class of individual tree shaking tests in com.android.tools.r8.shaking.examples.
@@ -46,94 +48,50 @@
*/
public abstract class TreeShakingTest extends TestBase {
- private Path proguardMap;
- private Path out;
+ @Parameters(name = "mode:{0}-{1} minify:{2}")
+ public static List<Object[]> defaultTreeShakingParameters() {
+ return data(Frontend.values(), MinifyMode.values());
+ }
+
+ public static List<Object[]> data(MinifyMode[] minifyModes) {
+ return data(Frontend.values(), minifyModes);
+ }
+
+ public static List<Object[]> data(Frontend[] frontends, MinifyMode[] minifyModes) {
+ return buildParameters(
+ frontends, getTestParameters().withAllRuntimesAndApiLevels().build(), minifyModes);
+ }
+
+ protected abstract String getName();
+
+ protected abstract String getMainClass();
protected enum Frontend {
DEX, JAR
}
- private final String name;
- private final String mainClass;
private final Frontend frontend;
- private final Backend backend;
+ private final TestParameters parameters;
private final MinifyMode minify;
public Frontend getFrontend() {
return frontend;
}
- public Backend getBackend() {
- return backend;
+ public TestParameters getParameters() {
+ return parameters;
}
public MinifyMode getMinify() {
return minify;
}
- @Rule
- public TemporaryFolder temp = ToolHelper.getTemporaryFolderForTest();
-
- @Rule
- public TestDescriptionWatcher watcher = new TestDescriptionWatcher();
-
- protected TreeShakingTest(
- String name, String mainClass, Frontend frontend, Backend backend, MinifyMode minify) {
- this.name = name;
- this.mainClass = mainClass;
+ public TreeShakingTest(Frontend frontend, TestParameters parameters, MinifyMode minify) {
this.frontend = frontend;
- this.backend = backend;
+ this.parameters = parameters;
this.minify = minify;
}
- private void generateTreeShakedVersion(
- Backend backend,
- String programFile,
- List<Path> jarLibraries,
- MinifyMode minify,
- List<String> keepRulesFiles,
- Consumer<InternalOptions> optionsConsumer)
- throws Exception {
- out = temp.getRoot().toPath().resolve("out.zip");
- proguardMap = temp.getRoot().toPath().resolve(DEFAULT_PROGUARD_MAP_FILE);
- // Generate R8 processed version without library option.
- boolean inline = programFile.contains("inlining");
-
- R8Command.Builder builder =
- ToolHelper.addProguardConfigurationConsumer(
- R8Command.builder(),
- pgConfig -> {
- pgConfig.setPrintMapping(true);
- pgConfig.setPrintMappingFile(proguardMap);
- pgConfig.setOverloadAggressively(minify == MinifyMode.AGGRESSIVE);
- if (!minify.isMinify()) {
- pgConfig.disableObfuscation();
- }
- })
- .addProguardConfigurationFiles(ListUtils.map(keepRulesFiles, Paths::get))
- .addLibraryFiles(jarLibraries);
- switch (backend) {
- case CF:
- builder.setOutput(out, OutputMode.ClassFile);
- break;
- case DEX:
- builder.setOutput(out, OutputMode.DexIndexed);
- break;
- default:
- throw new Unreachable();
- }
- ToolHelper.getAppBuilder(builder).addProgramFiles(Paths.get(programFile));
- ToolHelper.allowTestProguardOptions(builder);
- ToolHelper.runR8(
- builder.build(),
- options -> {
- options.enableInlining = inline;
- if (optionsConsumer != null) {
- optionsConsumer.accept(options);
- }
- });
- }
-
protected static void checkSameStructure(CodeInspector ref, CodeInspector inspector) {
ref.forAllClasses(
refClazz ->
@@ -169,59 +127,82 @@
}
protected void runTest(
- Consumer<CodeInspector> inspection,
+ ThrowingConsumer<CodeInspector, Exception> inspection,
BiConsumer<String, String> outputComparator,
BiConsumer<CodeInspector, CodeInspector> dexComparator,
List<String> keepRulesFiles)
throws Exception {
- runTest(inspection, outputComparator, dexComparator, keepRulesFiles, null);
+ runTest(inspection, outputComparator, dexComparator, keepRulesFiles, null, null, null);
}
protected void runTest(
- Consumer<CodeInspector> inspection,
+ ThrowingConsumer<CodeInspector, Exception> inspection,
BiConsumer<String, String> outputComparator,
BiConsumer<CodeInspector, CodeInspector> dexComparator,
List<String> keepRulesFiles,
Consumer<InternalOptions> optionsConsumer)
throws Exception {
- String originalDex = ToolHelper.TESTS_BUILD_DIR + name + "/classes.dex";
- String programFile;
- if (frontend == Frontend.DEX) {
- programFile = originalDex;
- } else {
- programFile = ToolHelper.TESTS_BUILD_DIR + name + ".jar";
- }
- List<Path> jarLibraries;
- if (backend == Backend.CF) {
- jarLibraries =
- ImmutableList.of(
- ToolHelper.getJava8RuntimeJar(),
- Paths.get(ToolHelper.EXAMPLES_BUILD_DIR + "shakinglib.jar"));
- } else {
- jarLibraries =
- ImmutableList.of(
- ToolHelper.getDefaultAndroidJar(),
- Paths.get(ToolHelper.EXAMPLES_BUILD_DIR + "shakinglib.jar"));
- }
+ runTest(
+ inspection, outputComparator, dexComparator, keepRulesFiles, optionsConsumer, null, null);
+ }
- generateTreeShakedVersion(
- backend, programFile, jarLibraries, minify, keepRulesFiles, optionsConsumer);
-
- if (backend == Backend.CF) {
+ protected void runTest(
+ ThrowingConsumer<CodeInspector, Exception> inspection,
+ BiConsumer<String, String> outputComparator,
+ BiConsumer<CodeInspector, CodeInspector> dexComparator,
+ List<String> keepRulesFiles,
+ Consumer<InternalOptions> optionsConsumer,
+ ThrowableConsumer<R8FullTestBuilder> testBuilderConsumer,
+ DiagnosticsConsumer diagnosticsConsumer)
+ throws Exception {
+ assumeFalse(frontend == Frontend.DEX && parameters.isCfRuntime());
+ String originalDex = ToolHelper.TESTS_BUILD_DIR + getName() + "/classes.dex";
+ String programFile =
+ frontend == Frontend.DEX ? originalDex : ToolHelper.TESTS_BUILD_DIR + getName() + ".jar";
+ R8FullTestBuilder testBuilder =
+ testForR8(parameters.getBackend())
+ // Go through app builder to add dex files.
+ .apply(
+ b ->
+ ToolHelper.getAppBuilder(b.getBuilder())
+ .addProgramFiles(Paths.get(programFile)))
+ .enableProguardTestOptions()
+ .applyIf(minify.isAggressive(), b -> b.addKeepRules("-overloadaggressively"))
+ .minification(minify.isMinify())
+ .setMinApi(parameters.getApiLevel())
+ .addKeepRuleFiles(ListUtils.map(keepRulesFiles, Paths::get))
+ .addLibraryFiles(Paths.get(ToolHelper.EXAMPLES_BUILD_DIR + "shakinglib.jar"))
+ .addDefaultRuntimeLibrary(parameters)
+ .addOptionsModification(
+ options -> {
+ options.enableInlining = programFile.contains("inlining");
+ if (optionsConsumer != null) {
+ optionsConsumer.accept(options);
+ }
+ })
+ .allowStdoutMessages()
+ .applyIf(testBuilderConsumer != null, testBuilderConsumer);
+ R8TestCompileResult compileResult =
+ diagnosticsConsumer == null
+ ? testBuilder.compile()
+ : testBuilder.compileWithExpectedDiagnostics(diagnosticsConsumer);
+ Path outJar = compileResult.writeToZip();
+ if (parameters.isCfRuntime()) {
Path shakinglib = Paths.get(ToolHelper.EXAMPLES_BUILD_DIR, "shakinglib.jar");
+ CfRuntime cfRuntime = parameters.getRuntime().asCf();
ProcessResult resultInput =
- ToolHelper.runJava(Arrays.asList(Paths.get(programFile), shakinglib), mainClass);
+ ToolHelper.runJava(
+ cfRuntime, Arrays.asList(Paths.get(programFile), shakinglib), getMainClass());
Assert.assertEquals(0, resultInput.exitCode);
ProcessResult resultOutput =
- ToolHelper.runJava(Arrays.asList(out, shakinglib), mainClass);
+ ToolHelper.runJava(cfRuntime, Arrays.asList(outJar, shakinglib), getMainClass());
if (outputComparator != null) {
outputComparator.accept(resultInput.stdout, resultOutput.stdout);
} else {
Assert.assertEquals(resultInput.toString(), resultOutput.toString());
}
if (inspection != null) {
- CodeInspector inspector = new CodeInspector(out, minify.isMinify() ? proguardMap : null);
- inspection.accept(inspector);
+ compileResult.inspect(inspection);
}
return;
}
@@ -231,35 +212,36 @@
Consumer<ArtCommandBuilder> extraArtArgs = builder -> {
builder.appendClasspath(ToolHelper.EXAMPLES_BUILD_DIR + "shakinglib/classes.dex");
};
-
+ DexVm dexVm = parameters.getRuntime().asDex().getVm();
if (Files.exists(Paths.get(originalDex))) {
if (outputComparator != null) {
- String output1 = ToolHelper.runArtNoVerificationErrors(
- Collections.singletonList(originalDex), mainClass, extraArtArgs, null);
- String output2 = ToolHelper.runArtNoVerificationErrors(
- Collections.singletonList(out.toString()), mainClass, extraArtArgs, null);
+ String output1 =
+ ToolHelper.runArtNoVerificationErrors(
+ Collections.singletonList(originalDex), getMainClass(), extraArtArgs, dexVm);
+ String output2 =
+ ToolHelper.runArtNoVerificationErrors(
+ Collections.singletonList(outJar.toString()), getMainClass(), extraArtArgs, dexVm);
outputComparator.accept(output1, output2);
} else {
- ToolHelper.checkArtOutputIdentical(Collections.singletonList(originalDex),
- Collections.singletonList(out.toString()), mainClass,
- extraArtArgs, null);
+ ToolHelper.checkArtOutputIdentical(
+ Collections.singletonList(originalDex),
+ Collections.singletonList(outJar.toString()),
+ getMainClass(),
+ extraArtArgs,
+ null);
}
-
if (dexComparator != null) {
CodeInspector ref = new CodeInspector(Paths.get(originalDex));
- CodeInspector inspector = new CodeInspector(out, minify.isMinify() ? proguardMap : null);
- dexComparator.accept(ref, inspector);
+ dexComparator.accept(ref, compileResult.inspector());
}
} else {
Assert.assertNull(outputComparator);
Assert.assertNull(dexComparator);
ToolHelper.runArtNoVerificationErrors(
- Collections.singletonList(out.toString()), mainClass, extraArtArgs, null);
+ Collections.singletonList(outJar.toString()), getMainClass(), extraArtArgs, dexVm);
}
-
if (inspection != null) {
- CodeInspector inspector = new CodeInspector(out, minify.isMinify() ? proguardMap : null);
- inspection.accept(inspector);
+ compileResult.inspect(inspection);
}
}
}
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking10Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking10Test.java
index fea123d..c20ebb6 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking10Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking10Test.java
@@ -3,10 +3,9 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking.examples;
+import com.android.tools.r8.TestParameters;
import com.android.tools.r8.shaking.TreeShakingTest;
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -17,18 +16,22 @@
public class TreeShaking10Test extends TreeShakingTest {
@Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
+ public static List<Object[]> data() {
+ return defaultTreeShakingParameters();
}
- public TreeShaking10Test(Frontend frontend, Backend backend, MinifyMode minify) {
- super("examples/shaking10", "shaking10.Shaking", frontend, backend, minify);
+ public TreeShaking10Test(Frontend frontend, TestParameters parameters, MinifyMode minify) {
+ super(frontend, parameters, minify);
+ }
+
+ @Override
+ protected String getName() {
+ return "examples/shaking10";
+ }
+
+ @Override
+ protected String getMainClass() {
+ return "shaking10.Shaking";
}
@Test
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking11Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking11Test.java
index 3833645..47b696d 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking11Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking11Test.java
@@ -3,11 +3,10 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking.examples;
+import com.android.tools.r8.TestParameters;
import com.android.tools.r8.shaking.TreeShakingTest;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.junit.Assert;
@@ -20,18 +19,22 @@
public class TreeShaking11Test extends TreeShakingTest {
@Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
+ public static List<Object[]> data() {
+ return defaultTreeShakingParameters();
}
- public TreeShaking11Test(Frontend frontend, Backend backend, MinifyMode minify) {
- super("examples/shaking11", "shaking11.Shaking", frontend, backend, minify);
+ public TreeShaking11Test(Frontend frontend, TestParameters parameters, MinifyMode minify) {
+ super(frontend, parameters, minify);
+ }
+
+ @Override
+ protected String getName() {
+ return "examples/shaking11";
+ }
+
+ @Override
+ protected String getMainClass() {
+ return "shaking11.Shaking";
}
@Test
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking12Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking12Test.java
index 82ab49b..b30a14d 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking12Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking12Test.java
@@ -7,12 +7,11 @@
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
+import com.android.tools.r8.TestParameters;
import com.android.tools.r8.shaking.TreeShakingTest;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.junit.Assert;
@@ -25,18 +24,22 @@
public class TreeShaking12Test extends TreeShakingTest {
@Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
+ public static List<Object[]> data() {
+ return defaultTreeShakingParameters();
}
- public TreeShaking12Test(Frontend frontend, Backend backend, MinifyMode minify) {
- super("examples/shaking12", "shaking12.Shaking", frontend, backend, minify);
+ public TreeShaking12Test(Frontend frontend, TestParameters parameters, MinifyMode minify) {
+ super(frontend, parameters, minify);
+ }
+
+ @Override
+ protected String getName() {
+ return "examples/shaking12";
+ }
+
+ @Override
+ protected String getMainClass() {
+ return "shaking12.Shaking";
}
@Test
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking13Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking13Test.java
index 5cdc80e..eab4bff 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking13Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking13Test.java
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking.examples;
+import com.android.tools.r8.TestParameters;
import com.android.tools.r8.shaking.TreeShakingTest;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -10,8 +11,6 @@
import com.android.tools.r8.utils.codeinspector.InstructionSubject;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import org.junit.Assert;
@@ -24,18 +23,22 @@
public class TreeShaking13Test extends TreeShakingTest {
@Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
+ public static List<Object[]> data() {
+ return defaultTreeShakingParameters();
}
- public TreeShaking13Test(Frontend frontend, Backend backend, MinifyMode minify) {
- super("examples/shaking13", "shaking13.Shaking", frontend, backend, minify);
+ public TreeShaking13Test(Frontend frontend, TestParameters parameters, MinifyMode minify) {
+ super(frontend, parameters, minify);
+ }
+
+ @Override
+ protected String getName() {
+ return "examples/shaking13";
+ }
+
+ @Override
+ protected String getMainClass() {
+ return "shaking13.Shaking";
}
@Test
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking14Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking14Test.java
index 74a4efe..36b3b37 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking14Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking14Test.java
@@ -3,12 +3,11 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking.examples;
+import com.android.tools.r8.TestParameters;
import com.android.tools.r8.shaking.TreeShakingTest;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
@@ -20,18 +19,22 @@
public class TreeShaking14Test extends TreeShakingTest {
@Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
+ public static List<Object[]> data() {
+ return defaultTreeShakingParameters();
}
- public TreeShaking14Test(Frontend frontend, Backend backend, MinifyMode minify) {
- super("examples/shaking14", "shaking14.Shaking", frontend, backend, minify);
+ public TreeShaking14Test(Frontend frontend, TestParameters parameters, MinifyMode minify) {
+ super(frontend, parameters, minify);
+ }
+
+ @Override
+ protected String getName() {
+ return "examples/shaking14";
+ }
+
+ @Override
+ protected String getMainClass() {
+ return "shaking14.Shaking";
}
@Test
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking15Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking15Test.java
index 2b5cd16..7111f51 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking15Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking15Test.java
@@ -3,14 +3,17 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking.examples;
+import static com.android.tools.r8.DiagnosticsMatcher.diagnosticMessage;
+import static org.hamcrest.CoreMatchers.containsString;
+
+import com.android.tools.r8.R8TestBuilder;
+import com.android.tools.r8.TestParameters;
import com.android.tools.r8.shaking.TreeShakingTest;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.FieldSubject;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -21,21 +24,22 @@
public class TreeShaking15Test extends TreeShakingTest {
@Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- if (minify == MinifyMode.NONE) {
- continue;
- }
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
+ public static List<Object[]> data() {
+ return data(MinifyMode.withoutNone());
}
- public TreeShaking15Test(Frontend frontend, Backend backend, MinifyMode minify) {
- super("examples/shaking15", "shaking15.Shaking", frontend, backend, minify);
+ public TreeShaking15Test(Frontend frontend, TestParameters parameters, MinifyMode minify) {
+ super(frontend, parameters, minify);
+ }
+
+ @Override
+ protected String getName() {
+ return "examples/shaking15";
+ }
+
+ @Override
+ protected String getMainClass() {
+ return "shaking15.Shaking";
}
@Test
@@ -44,11 +48,16 @@
TreeShaking15Test::shaking15testDictionary,
null,
null,
- ImmutableList.of("src/test/examples/shaking15/keep-rules.txt"));
+ ImmutableList.of("src/test/examples/shaking15/keep-rules.txt"),
+ null,
+ R8TestBuilder::allowDiagnosticInfoMessages,
+ diagnostics ->
+ diagnostics.assertAllInfosMatch(
+ diagnosticMessage(containsString("Invalid character in dictionary"))));
}
private static void shaking15testDictionary(CodeInspector inspector) {
- inspector.forAllClasses((clazz) -> checkClassAndMemberInDictionary(clazz));
+ inspector.forAllClasses(TreeShaking15Test::checkClassAndMemberInDictionary);
}
private static List<String> names =
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking16Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking16Test.java
index dbae1da..785e505 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking16Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking16Test.java
@@ -3,10 +3,9 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking.examples;
+import com.android.tools.r8.TestParameters;
import com.android.tools.r8.shaking.TreeShakingTest;
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -17,21 +16,22 @@
public class TreeShaking16Test extends TreeShakingTest {
@Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- if (minify == MinifyMode.NONE) {
- continue;
- }
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
+ public static List<Object[]> data() {
+ return data(MinifyMode.withoutNone());
}
- public TreeShaking16Test(Frontend frontend, Backend backend, MinifyMode minify) {
- super("examples/shaking16", "shaking16.Shaking", frontend, backend, minify);
+ public TreeShaking16Test(Frontend frontend, TestParameters parameters, MinifyMode minify) {
+ super(frontend, parameters, minify);
+ }
+
+ @Override
+ protected String getName() {
+ return "examples/shaking16";
+ }
+
+ @Override
+ protected String getMainClass() {
+ return "shaking16.Shaking";
}
@Test
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking17Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking17Test.java
index 88d3b65..e2b7095 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking17Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking17Test.java
@@ -3,12 +3,11 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking.examples;
+import com.android.tools.r8.TestParameters;
import com.android.tools.r8.shaking.TreeShakingTest;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.junit.Assert;
@@ -21,18 +20,22 @@
public class TreeShaking17Test extends TreeShakingTest {
@Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
+ public static List<Object[]> data() {
+ return defaultTreeShakingParameters();
}
- public TreeShaking17Test(Frontend frontend, Backend backend, MinifyMode minify) {
- super("examples/shaking17", "shaking17.Shaking", frontend, backend, minify);
+ public TreeShaking17Test(Frontend frontend, TestParameters parameters, MinifyMode minify) {
+ super(frontend, parameters, minify);
+ }
+
+ @Override
+ protected String getName() {
+ return "examples/shaking17";
+ }
+
+ @Override
+ protected String getMainClass() {
+ return "shaking17.Shaking";
}
@Test
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking18Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking18Test.java
index f28f242..d91a2fd 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking18Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking18Test.java
@@ -5,11 +5,10 @@
import static org.junit.Assert.assertFalse;
+import com.android.tools.r8.TestParameters;
import com.android.tools.r8.shaking.TreeShakingTest;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -20,18 +19,22 @@
public class TreeShaking18Test extends TreeShakingTest {
@Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
+ public static List<Object[]> data() {
+ return defaultTreeShakingParameters();
}
- public TreeShaking18Test(Frontend frontend, Backend backend, MinifyMode minify) {
- super("examples/shaking18", "shaking18.Shaking", frontend, backend, minify);
+ public TreeShaking18Test(Frontend frontend, TestParameters parameters, MinifyMode minify) {
+ super(frontend, parameters, minify);
+ }
+
+ @Override
+ protected String getName() {
+ return "examples/shaking18";
+ }
+
+ @Override
+ protected String getMainClass() {
+ return "shaking18.Shaking";
}
@Test
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking19Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking19Test.java
index dcc71b0..e5f45bb 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking19Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking19Test.java
@@ -7,13 +7,12 @@
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
+import com.android.tools.r8.TestParameters;
import com.android.tools.r8.shaking.TreeShakingTest;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -24,18 +23,22 @@
public class TreeShaking19Test extends TreeShakingTest {
@Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
+ public static List<Object[]> data() {
+ return defaultTreeShakingParameters();
}
- public TreeShaking19Test(Frontend frontend, Backend backend, MinifyMode minify) {
- super("examples/shaking19", "shaking19.Shaking", frontend, backend, minify);
+ public TreeShaking19Test(Frontend frontend, TestParameters parameters, MinifyMode minify) {
+ super(frontend, parameters, minify);
+ }
+
+ @Override
+ protected String getName() {
+ return "examples/shaking19";
+ }
+
+ @Override
+ protected String getMainClass() {
+ return "shaking19.Shaking";
}
@Test
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking1Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking1Test.java
index 6189f73..ad658b9 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking1Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking1Test.java
@@ -3,13 +3,12 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking.examples;
+import com.android.tools.r8.TestParameters;
import com.android.tools.r8.shaking.TreeShakingTest;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.junit.Assert;
@@ -23,18 +22,22 @@
public class TreeShaking1Test extends TreeShakingTest {
@Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
+ public static List<Object[]> data() {
+ return defaultTreeShakingParameters();
}
- public TreeShaking1Test(Frontend frontend, Backend backend, MinifyMode minify) {
- super("examples/shaking1", "shaking1.Shaking", frontend, backend, minify);
+ public TreeShaking1Test(Frontend frontend, TestParameters parameters, MinifyMode minify) {
+ super(frontend, parameters, minify);
+ }
+
+ @Override
+ protected String getName() {
+ return "examples/shaking1";
+ }
+
+ @Override
+ protected String getMainClass() {
+ return "shaking1.Shaking";
}
@Test
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking2Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking2Test.java
index 49a5910..d951404 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking2Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking2Test.java
@@ -3,12 +3,11 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking.examples;
+import com.android.tools.r8.TestParameters;
import com.android.tools.r8.shaking.TreeShakingTest;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.junit.Assert;
@@ -21,18 +20,22 @@
public class TreeShaking2Test extends TreeShakingTest {
@Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
+ public static List<Object[]> data() {
+ return defaultTreeShakingParameters();
}
- public TreeShaking2Test(Frontend frontend, Backend backend, MinifyMode minify) {
- super("examples/shaking2", "shaking2.Shaking", frontend, backend, minify);
+ public TreeShaking2Test(Frontend frontend, TestParameters parameters, MinifyMode minify) {
+ super(frontend, parameters, minify);
+ }
+
+ @Override
+ protected String getName() {
+ return "examples/shaking2";
+ }
+
+ @Override
+ protected String getMainClass() {
+ return "shaking2.Shaking";
}
@Test
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking3Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking3Test.java
index 49a1e14..38cee4e 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking3Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking3Test.java
@@ -3,12 +3,11 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking.examples;
+import com.android.tools.r8.TestParameters;
import com.android.tools.r8.shaking.TreeShakingTest;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
@@ -20,18 +19,22 @@
public class TreeShaking3Test extends TreeShakingTest {
@Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
+ public static List<Object[]> data() {
+ return defaultTreeShakingParameters();
}
- public TreeShaking3Test(Frontend frontend, Backend backend, MinifyMode minify) {
- super("examples/shaking3", "shaking3.Shaking", frontend, backend, minify);
+ public TreeShaking3Test(Frontend frontend, TestParameters parameters, MinifyMode minify) {
+ super(frontend, parameters, minify);
+ }
+
+ @Override
+ protected String getName() {
+ return "examples/shaking3";
+ }
+
+ @Override
+ protected String getMainClass() {
+ return "shaking3.Shaking";
}
@Test
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking4Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking4Test.java
index d2e1cd0..abf9be6 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking4Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking4Test.java
@@ -3,10 +3,9 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking.examples;
+import com.android.tools.r8.TestParameters;
import com.android.tools.r8.shaking.TreeShakingTest;
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -17,18 +16,22 @@
public class TreeShaking4Test extends TreeShakingTest {
@Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
+ public static List<Object[]> data() {
+ return defaultTreeShakingParameters();
}
- public TreeShaking4Test(Frontend frontend, Backend backend, MinifyMode minify) {
- super("examples/shaking4", "shaking4.Shaking", frontend, backend, minify);
+ public TreeShaking4Test(Frontend frontend, TestParameters parameters, MinifyMode minify) {
+ super(frontend, parameters, minify);
+ }
+
+ @Override
+ protected String getName() {
+ return "examples/shaking4";
+ }
+
+ @Override
+ protected String getMainClass() {
+ return "shaking4.Shaking";
}
@Test
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking5Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking5Test.java
index 212e883..cca8f8b 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking5Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking5Test.java
@@ -3,11 +3,10 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking.examples;
+import com.android.tools.r8.TestParameters;
import com.android.tools.r8.shaking.TreeShakingTest;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.junit.Assert;
@@ -20,18 +19,22 @@
public class TreeShaking5Test extends TreeShakingTest {
@Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
+ public static List<Object[]> data() {
+ return defaultTreeShakingParameters();
}
- public TreeShaking5Test(Frontend frontend, Backend backend, MinifyMode minify) {
- super("examples/shaking5", "shaking5.Shaking", frontend, backend, minify);
+ public TreeShaking5Test(Frontend frontend, TestParameters parameters, MinifyMode minify) {
+ super(frontend, parameters, minify);
+ }
+
+ @Override
+ protected String getName() {
+ return "examples/shaking5";
+ }
+
+ @Override
+ protected String getMainClass() {
+ return "shaking5.Shaking";
}
@Test
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking6Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking6Test.java
index 01c0de9..7a91541 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking6Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking6Test.java
@@ -3,12 +3,11 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking.examples;
+import com.android.tools.r8.TestParameters;
import com.android.tools.r8.shaking.TreeShakingTest;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.junit.Assert;
@@ -21,18 +20,22 @@
public class TreeShaking6Test extends TreeShakingTest {
@Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
+ public static List<Object[]> data() {
+ return defaultTreeShakingParameters();
}
- public TreeShaking6Test(Frontend frontend, Backend backend, MinifyMode minify) {
- super("examples/shaking6", "shaking6.Shaking", frontend, backend, minify);
+ public TreeShaking6Test(Frontend frontend, TestParameters parameters, MinifyMode minify) {
+ super(frontend, parameters, minify);
+ }
+
+ @Override
+ protected String getName() {
+ return "examples/shaking6";
+ }
+
+ @Override
+ protected String getMainClass() {
+ return "shaking6.Shaking";
}
@Test
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking7Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking7Test.java
index 4cbd1c0..8a6cf36 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking7Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking7Test.java
@@ -3,12 +3,11 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking.examples;
+import com.android.tools.r8.TestParameters;
import com.android.tools.r8.shaking.TreeShakingTest;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
@@ -20,18 +19,22 @@
public class TreeShaking7Test extends TreeShakingTest {
@Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
+ public static List<Object[]> data() {
+ return defaultTreeShakingParameters();
}
- public TreeShaking7Test(Frontend frontend, Backend backend, MinifyMode minify) {
- super("examples/shaking7", "shaking7.Shaking", frontend, backend, minify);
+ public TreeShaking7Test(Frontend frontend, TestParameters parameters, MinifyMode minify) {
+ super(frontend, parameters, minify);
+ }
+
+ @Override
+ protected String getName() {
+ return "examples/shaking7";
+ }
+
+ @Override
+ protected String getMainClass() {
+ return "shaking7.Shaking";
}
@Test
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking8Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking8Test.java
index 9b8d209..9da3d01 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking8Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking8Test.java
@@ -7,12 +7,11 @@
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
+import com.android.tools.r8.TestParameters;
import com.android.tools.r8.shaking.TreeShakingTest;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
@@ -24,18 +23,22 @@
public class TreeShaking8Test extends TreeShakingTest {
@Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
+ public static List<Object[]> data() {
+ return defaultTreeShakingParameters();
}
- public TreeShaking8Test(Frontend frontend, Backend backend, MinifyMode minify) {
- super("examples/shaking8", "shaking8.Shaking", frontend, backend, minify);
+ public TreeShaking8Test(Frontend frontend, TestParameters parameters, MinifyMode minify) {
+ super(frontend, parameters, minify);
+ }
+
+ @Override
+ protected String getName() {
+ return "examples/shaking8";
+ }
+
+ @Override
+ protected String getMainClass() {
+ return "shaking8.Shaking";
}
@Test
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking9Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking9Test.java
index 8974d6b..ec8c6ad 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking9Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShaking9Test.java
@@ -3,12 +3,11 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking.examples;
+import com.android.tools.r8.TestParameters;
import com.android.tools.r8.shaking.TreeShakingTest;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
@@ -20,18 +19,22 @@
public class TreeShaking9Test extends TreeShakingTest {
@Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
+ public static List<Object[]> data() {
+ return defaultTreeShakingParameters();
}
- public TreeShaking9Test(Frontend frontend, Backend backend, MinifyMode minify) {
- super("examples/shaking9", "shaking9.Shaking", frontend, backend, minify);
+ public TreeShaking9Test(Frontend frontend, TestParameters parameters, MinifyMode minify) {
+ super(frontend, parameters, minify);
+ }
+
+ @Override
+ protected String getName() {
+ return "examples/shaking9";
+ }
+
+ @Override
+ protected String getMainClass() {
+ return "shaking9.Shaking";
}
@Test
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAbstractMethodRemovalTest.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAbstractMethodRemovalTest.java
index c204e06..b008254 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAbstractMethodRemovalTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAbstractMethodRemovalTest.java
@@ -3,10 +3,9 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking.examples;
+import com.android.tools.r8.TestParameters;
import com.android.tools.r8.shaking.TreeShakingTest;
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -17,24 +16,23 @@
public class TreeShakingAbstractMethodRemovalTest extends TreeShakingTest {
@Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
+ public static List<Object[]> data() {
+ return defaultTreeShakingParameters();
}
public TreeShakingAbstractMethodRemovalTest(
- Frontend frontend, Backend backend, MinifyMode minify) {
- super(
- "examples/abstractmethodremoval",
- "abstractmethodremoval.AbstractMethodRemoval",
- frontend,
- backend,
- minify);
+ Frontend frontend, TestParameters parameters, MinifyMode minify) {
+ super(frontend, parameters, minify);
+ }
+
+ @Override
+ protected String getName() {
+ return "examples/abstractmethodremoval";
+ }
+
+ @Override
+ protected String getMainClass() {
+ return "abstractmethodremoval.AbstractMethodRemoval";
}
@Test
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAndroidNTest.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAndroidNTest.java
index 4d64e0e..0c65f06 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAndroidNTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAndroidNTest.java
@@ -3,10 +3,9 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking.examples;
+import com.android.tools.r8.TestParameters;
import com.android.tools.r8.shaking.TreeShakingTest;
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -17,17 +16,22 @@
public class TreeShakingAndroidNTest extends TreeShakingTest {
@Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- }
- return parameters;
+ public static List<Object[]> data() {
+ return data(new Frontend[] {Frontend.JAR}, MinifyMode.values());
}
- public TreeShakingAndroidNTest(Frontend frontend, Backend backend, MinifyMode minify) {
- super("examplesAndroidN/shaking", "shaking.Shaking", frontend, backend, minify);
+ public TreeShakingAndroidNTest(Frontend frontend, TestParameters parameters, MinifyMode minify) {
+ super(frontend, parameters, minify);
+ }
+
+ @Override
+ protected String getName() {
+ return "examplesAndroidN/shaking";
+ }
+
+ @Override
+ protected String getMainClass() {
+ return "shaking.Shaking";
}
@Test
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAnnotationremovalTest.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAnnotationremovalTest.java
index 1c9a3d0..728aa09 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAnnotationremovalTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAnnotationremovalTest.java
@@ -3,12 +3,11 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking.examples;
+import com.android.tools.r8.TestParameters;
import com.android.tools.r8.shaking.TreeShakingTest;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
@@ -20,23 +19,23 @@
public class TreeShakingAnnotationremovalTest extends TreeShakingTest {
@Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
+ public static List<Object[]> data() {
+ return defaultTreeShakingParameters();
}
- public TreeShakingAnnotationremovalTest(Frontend frontend, Backend backend, MinifyMode minify) {
- super(
- "examples/annotationremoval",
- "annotationremoval.Annotationremoval",
- frontend,
- backend,
- minify);
+ public TreeShakingAnnotationremovalTest(
+ Frontend frontend, TestParameters parameters, MinifyMode minify) {
+ super(frontend, parameters, minify);
+ }
+
+ @Override
+ protected String getName() {
+ return "examples/annotationremoval";
+ }
+
+ @Override
+ protected String getMainClass() {
+ return "annotationremoval.Annotationremoval";
}
@Test
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects1Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects1Test.java
index 9c2c387..1aa50e1 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects1Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects1Test.java
@@ -3,11 +3,10 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking.examples;
+import com.android.tools.r8.TestParameters;
import com.android.tools.r8.shaking.TreeShakingTest;
import com.android.tools.r8.utils.StringUtils;
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
@@ -19,24 +18,23 @@
public class TreeShakingAssumenosideeffects1Test extends TreeShakingTest {
@Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
+ public static List<Object[]> data() {
+ return defaultTreeShakingParameters();
}
public TreeShakingAssumenosideeffects1Test(
- Frontend frontend, Backend backend, MinifyMode minify) {
- super(
- "examples/assumenosideeffects1",
- "assumenosideeffects1.Assumenosideeffects",
- frontend,
- backend,
- minify);
+ Frontend frontend, TestParameters parameters, MinifyMode minify) {
+ super(frontend, parameters, minify);
+ }
+
+ @Override
+ protected String getName() {
+ return "examples/assumenosideeffects1";
+ }
+
+ @Override
+ protected String getMainClass() {
+ return "assumenosideeffects1.Assumenosideeffects";
}
@Test
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects2Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects2Test.java
index e4b9ed6..a57e98f 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects2Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects2Test.java
@@ -3,11 +3,10 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking.examples;
+import com.android.tools.r8.TestParameters;
import com.android.tools.r8.shaking.TreeShakingTest;
import com.android.tools.r8.utils.StringUtils;
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
import org.junit.Assert;
import org.junit.Ignore;
@@ -21,24 +20,23 @@
public class TreeShakingAssumenosideeffects2Test extends TreeShakingTest {
@Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
+ public static List<Object[]> data() {
+ return defaultTreeShakingParameters();
}
public TreeShakingAssumenosideeffects2Test(
- Frontend frontend, Backend backend, MinifyMode minify) {
- super(
- "examples/assumenosideeffects2",
- "assumenosideeffects2.Assumenosideeffects",
- frontend,
- backend,
- minify);
+ Frontend frontend, TestParameters parameters, MinifyMode minify) {
+ super(frontend, parameters, minify);
+ }
+
+ @Override
+ protected String getName() {
+ return "examples/assumenosideeffects2";
+ }
+
+ @Override
+ protected String getMainClass() {
+ return "assumenosideeffects2.Assumenosideeffects";
}
@Test
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects3Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects3Test.java
index 72b6d17..b83e0b9 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects3Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects3Test.java
@@ -3,11 +3,10 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking.examples;
+import com.android.tools.r8.TestParameters;
import com.android.tools.r8.shaking.TreeShakingTest;
import com.android.tools.r8.utils.StringUtils;
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
@@ -19,24 +18,23 @@
public class TreeShakingAssumenosideeffects3Test extends TreeShakingTest {
@Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
+ public static List<Object[]> data() {
+ return defaultTreeShakingParameters();
}
public TreeShakingAssumenosideeffects3Test(
- Frontend frontend, Backend backend, MinifyMode minify) {
- super(
- "examples/assumenosideeffects3",
- "assumenosideeffects3.Assumenosideeffects",
- frontend,
- backend,
- minify);
+ Frontend frontend, TestParameters parameters, MinifyMode minify) {
+ super(frontend, parameters, minify);
+ }
+
+ @Override
+ protected String getName() {
+ return "examples/assumenosideeffects3";
+ }
+
+ @Override
+ protected String getMainClass() {
+ return "assumenosideeffects3.Assumenosideeffects";
}
@Test
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects4Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects4Test.java
index c36ddd7..56083fc 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects4Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects4Test.java
@@ -3,11 +3,10 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking.examples;
+import com.android.tools.r8.TestParameters;
import com.android.tools.r8.shaking.TreeShakingTest;
import com.android.tools.r8.utils.StringUtils;
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
@@ -19,24 +18,23 @@
public class TreeShakingAssumenosideeffects4Test extends TreeShakingTest {
@Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
+ public static List<Object[]> data() {
+ return defaultTreeShakingParameters();
}
public TreeShakingAssumenosideeffects4Test(
- Frontend frontend, Backend backend, MinifyMode minify) {
- super(
- "examples/assumenosideeffects4",
- "assumenosideeffects4.Assumenosideeffects",
- frontend,
- backend,
- minify);
+ Frontend frontend, TestParameters parameters, MinifyMode minify) {
+ super(frontend, parameters, minify);
+ }
+
+ @Override
+ protected String getName() {
+ return "examples/assumenosideeffects4";
+ }
+
+ @Override
+ protected String getMainClass() {
+ return "assumenosideeffects4.Assumenosideeffects";
}
@Test
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects5Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects5Test.java
index 60cbd65..fa138dd 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects5Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects5Test.java
@@ -3,11 +3,10 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking.examples;
+import com.android.tools.r8.TestParameters;
import com.android.tools.r8.shaking.TreeShakingTest;
import com.android.tools.r8.utils.StringUtils;
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
@@ -19,24 +18,23 @@
public class TreeShakingAssumenosideeffects5Test extends TreeShakingTest {
@Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
+ public static List<Object[]> data() {
+ return defaultTreeShakingParameters();
}
public TreeShakingAssumenosideeffects5Test(
- Frontend frontend, Backend backend, MinifyMode minify) {
- super(
- "examples/assumenosideeffects5",
- "assumenosideeffects5.Assumenosideeffects",
- frontend,
- backend,
- minify);
+ Frontend frontend, TestParameters parameters, MinifyMode minify) {
+ super(frontend, parameters, minify);
+ }
+
+ @Override
+ protected String getName() {
+ return "examples/assumenosideeffects5";
+ }
+
+ @Override
+ protected String getMainClass() {
+ return "assumenosideeffects5.Assumenosideeffects";
}
@Test
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects6Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects6Test.java
index 59d8dd2..172c64d 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects6Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumenosideeffects6Test.java
@@ -3,11 +3,10 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking.examples;
+import com.android.tools.r8.TestParameters;
import com.android.tools.r8.shaking.TreeShakingTest;
import com.android.tools.r8.utils.StringUtils;
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
@@ -19,24 +18,23 @@
public class TreeShakingAssumenosideeffects6Test extends TreeShakingTest {
@Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
+ public static List<Object[]> data() {
+ return defaultTreeShakingParameters();
}
public TreeShakingAssumenosideeffects6Test(
- Frontend frontend, Backend backend, MinifyMode minify) {
- super(
- "examples/assumenosideeffects6",
- "assumenosideeffects6.Assumenosideeffects",
- frontend,
- backend,
- minify);
+ Frontend frontend, TestParameters parameters, MinifyMode minify) {
+ super(frontend, parameters, minify);
+ }
+
+ @Override
+ protected String getName() {
+ return "examples/assumenosideeffects6";
+ }
+
+ @Override
+ protected String getMainClass() {
+ return "assumenosideeffects6.Assumenosideeffects";
}
@Test
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues1Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues1Test.java
index 15e8195..45511b7 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues1Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues1Test.java
@@ -3,11 +3,10 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking.examples;
+import com.android.tools.r8.TestParameters;
import com.android.tools.r8.shaking.TreeShakingTest;
import com.android.tools.r8.utils.StringUtils;
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
@@ -19,18 +18,23 @@
public class TreeShakingAssumevalues1Test extends TreeShakingTest {
@Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
+ public static List<Object[]> data() {
+ return defaultTreeShakingParameters();
}
- public TreeShakingAssumevalues1Test(Frontend frontend, Backend backend, MinifyMode minify) {
- super("examples/assumevalues1", "assumevalues1.Assumevalues", frontend, backend, minify);
+ public TreeShakingAssumevalues1Test(
+ Frontend frontend, TestParameters parameters, MinifyMode minify) {
+ super(frontend, parameters, minify);
+ }
+
+ @Override
+ protected String getName() {
+ return "examples/assumevalues1";
+ }
+
+ @Override
+ protected String getMainClass() {
+ return "assumevalues1.Assumevalues";
}
@Test
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues2Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues2Test.java
index 6f2d721..88ca339 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues2Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues2Test.java
@@ -3,11 +3,10 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking.examples;
+import com.android.tools.r8.TestParameters;
import com.android.tools.r8.shaking.TreeShakingTest;
import com.android.tools.r8.utils.StringUtils;
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
@@ -19,18 +18,23 @@
public class TreeShakingAssumevalues2Test extends TreeShakingTest {
@Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
+ public static List<Object[]> data() {
+ return defaultTreeShakingParameters();
}
- public TreeShakingAssumevalues2Test(Frontend frontend, Backend backend, MinifyMode minify) {
- super("examples/assumevalues2", "assumevalues2.Assumevalues", frontend, backend, minify);
+ public TreeShakingAssumevalues2Test(
+ Frontend frontend, TestParameters parameters, MinifyMode minify) {
+ super(frontend, parameters, minify);
+ }
+
+ @Override
+ protected String getName() {
+ return "examples/assumevalues2";
+ }
+
+ @Override
+ protected String getMainClass() {
+ return "assumevalues2.Assumevalues";
}
@Test
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues3Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues3Test.java
index a765f30..5237778 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues3Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues3Test.java
@@ -3,11 +3,10 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking.examples;
+import com.android.tools.r8.TestParameters;
import com.android.tools.r8.shaking.TreeShakingTest;
import com.android.tools.r8.utils.StringUtils;
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
@@ -19,18 +18,23 @@
public class TreeShakingAssumevalues3Test extends TreeShakingTest {
@Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
+ public static List<Object[]> data() {
+ return defaultTreeShakingParameters();
}
- public TreeShakingAssumevalues3Test(Frontend frontend, Backend backend, MinifyMode minify) {
- super("examples/assumevalues3", "assumevalues3.Assumevalues", frontend, backend, minify);
+ public TreeShakingAssumevalues3Test(
+ Frontend frontend, TestParameters parameters, MinifyMode minify) {
+ super(frontend, parameters, minify);
+ }
+
+ @Override
+ protected String getName() {
+ return "examples/assumevalues3";
+ }
+
+ @Override
+ protected String getMainClass() {
+ return "assumevalues3.Assumevalues";
}
@Test
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues4Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues4Test.java
index 61b4154..4790850 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues4Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues4Test.java
@@ -3,11 +3,10 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking.examples;
+import com.android.tools.r8.TestParameters;
import com.android.tools.r8.shaking.TreeShakingTest;
import com.android.tools.r8.utils.StringUtils;
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
@@ -19,18 +18,23 @@
public class TreeShakingAssumevalues4Test extends TreeShakingTest {
@Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
+ public static List<Object[]> data() {
+ return defaultTreeShakingParameters();
}
- public TreeShakingAssumevalues4Test(Frontend frontend, Backend backend, MinifyMode minify) {
- super("examples/assumevalues4", "assumevalues4.Assumevalues", frontend, backend, minify);
+ public TreeShakingAssumevalues4Test(
+ Frontend frontend, TestParameters parameters, MinifyMode minify) {
+ super(frontend, parameters, minify);
+ }
+
+ @Override
+ protected String getName() {
+ return "examples/assumevalues4";
+ }
+
+ @Override
+ protected String getMainClass() {
+ return "assumevalues4.Assumevalues";
}
@Test
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues5Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues5Test.java
index 48ef889..9304ed8 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues5Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues5Test.java
@@ -3,11 +3,10 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking.examples;
+import com.android.tools.r8.TestParameters;
import com.android.tools.r8.shaking.TreeShakingTest;
import com.android.tools.r8.utils.StringUtils;
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
@@ -19,18 +18,23 @@
public class TreeShakingAssumevalues5Test extends TreeShakingTest {
@Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
+ public static List<Object[]> data() {
+ return defaultTreeShakingParameters();
}
- public TreeShakingAssumevalues5Test(Frontend frontend, Backend backend, MinifyMode minify) {
- super("examples/assumevalues5", "assumevalues5.Assumevalues", frontend, backend, minify);
+ public TreeShakingAssumevalues5Test(
+ Frontend frontend, TestParameters parameters, MinifyMode minify) {
+ super(frontend, parameters, minify);
+ }
+
+ @Override
+ protected String getName() {
+ return "examples/assumevalues5";
+ }
+
+ @Override
+ protected String getMainClass() {
+ return "assumevalues5.Assumevalues";
}
@Test
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues6Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues6Test.java
index de515d0..59c535d 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues6Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues6Test.java
@@ -3,14 +3,13 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking.examples;
+import com.android.tools.r8.TestParameters;
import com.android.tools.r8.shaking.TreeShakingTest;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.ConstStringInstructionSubject;
import com.android.tools.r8.utils.codeinspector.InstructionSubject.JumboStringMode;
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
@@ -22,24 +21,31 @@
public class TreeShakingAssumevalues6Test extends TreeShakingTest {
@Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
+ public static List<Object[]> data() {
+ return defaultTreeShakingParameters();
}
- public TreeShakingAssumevalues6Test(Frontend frontend, Backend backend, MinifyMode minify) {
- super("examples/assumevalues6", "assumevalues6.Assumevalues", frontend, backend, minify);
+ public TreeShakingAssumevalues6Test(
+ Frontend frontend, TestParameters parameters, MinifyMode minify) {
+ super(frontend, parameters, minify);
+ }
+
+ @Override
+ protected String getName() {
+ return "examples/assumevalues6";
+ }
+
+ @Override
+ protected String getMainClass() {
+ return "assumevalues6.Assumevalues";
}
@Test
public void test() throws Exception {
runTest(
- getBackend() == Backend.DEX ? TreeShakingAssumevalues6Test::assumevalues6CheckCode : null,
+ getParameters().isDexRuntime()
+ ? TreeShakingAssumevalues6Test::assumevalues6CheckCode
+ : null,
TreeShakingAssumevalues6Test::assumevalues6CheckOutput,
null,
ImmutableList.of("src/test/examples/assumevalues6/keep-rules.txt"));
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues7Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues7Test.java
index e02b4cd..c6ca232 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues7Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAssumevalues7Test.java
@@ -3,14 +3,13 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking.examples;
+import com.android.tools.r8.TestParameters;
import com.android.tools.r8.shaking.TreeShakingTest;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.ConstStringInstructionSubject;
import com.android.tools.r8.utils.codeinspector.InstructionSubject.JumboStringMode;
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
@@ -22,24 +21,31 @@
public class TreeShakingAssumevalues7Test extends TreeShakingTest {
@Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
+ public static List<Object[]> data() {
+ return defaultTreeShakingParameters();
}
- public TreeShakingAssumevalues7Test(Frontend frontend, Backend backend, MinifyMode minify) {
- super("examples/assumevalues7", "assumevalues7.Assumevalues", frontend, backend, minify);
+ public TreeShakingAssumevalues7Test(
+ Frontend frontend, TestParameters parameters, MinifyMode minify) {
+ super(frontend, parameters, minify);
+ }
+
+ @Override
+ protected String getName() {
+ return "examples/assumevalues7";
+ }
+
+ @Override
+ protected String getMainClass() {
+ return "assumevalues7.Assumevalues";
}
@Test
public void test() throws Exception {
runTest(
- getBackend() == Backend.DEX ? TreeShakingAssumevalues7Test::assumevalues7CheckCode : null,
+ getParameters().isDexRuntime()
+ ? TreeShakingAssumevalues7Test::assumevalues7CheckCode
+ : null,
TreeShakingAssumevalues7Test::assumevalues7CheckOutput,
null,
ImmutableList.of("src/test/examples/assumevalues7/keep-rules.txt"));
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingInliningTest.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingInliningTest.java
index a6fb153..08dfc6a 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingInliningTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingInliningTest.java
@@ -3,10 +3,10 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking.examples;
+import com.android.tools.r8.TestCompilerBuilder;
+import com.android.tools.r8.TestParameters;
import com.android.tools.r8.shaking.TreeShakingTest;
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -17,18 +17,22 @@
public class TreeShakingInliningTest extends TreeShakingTest {
@Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
+ public static List<Object[]> data() {
+ return defaultTreeShakingParameters();
}
- public TreeShakingInliningTest(Frontend frontend, Backend backend, MinifyMode minify) {
- super("examples/inlining", "inlining.Inlining", frontend, backend, minify);
+ public TreeShakingInliningTest(Frontend frontend, TestParameters parameters, MinifyMode minify) {
+ super(frontend, parameters, minify);
+ }
+
+ @Override
+ protected String getName() {
+ return "examples/inlining";
+ }
+
+ @Override
+ protected String getMainClass() {
+ return "inlining.Inlining";
}
@Test
@@ -39,11 +43,12 @@
@Test
public void testKeeprulesdiscard() throws Exception {
// On the cf backend, we don't inline into constructors, see: b/136250031
- List<String> keepRules = getBackend() == Backend.CF
- ? ImmutableList.of("src/test/examples/inlining/keep-rules-discard.txt")
- : ImmutableList.of("src/test/examples/inlining/keep-rules-discard.txt",
- "src/test/examples/inlining/keep-rules-discard-constructor.txt");
- runTest(
- null, null, null, keepRules);
+ List<String> keepRules =
+ getParameters().isCfRuntime()
+ ? ImmutableList.of("src/test/examples/inlining/keep-rules-discard.txt")
+ : ImmutableList.of(
+ "src/test/examples/inlining/keep-rules-discard.txt",
+ "src/test/examples/inlining/keep-rules-discard-constructor.txt");
+ runTest(null, null, null, keepRules, null, TestCompilerBuilder::allowStderrMessages, null);
}
}
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingMemberrebinding2Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingMemberrebinding2Test.java
index 779c140..95a0876 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingMemberrebinding2Test.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingMemberrebinding2Test.java
@@ -3,10 +3,9 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking.examples;
+import com.android.tools.r8.TestParameters;
import com.android.tools.r8.shaking.TreeShakingTest;
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -17,19 +16,23 @@
public class TreeShakingMemberrebinding2Test extends TreeShakingTest {
@Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
+ public static List<Object[]> data() {
+ return defaultTreeShakingParameters();
}
- public TreeShakingMemberrebinding2Test(Frontend frontend, Backend backend, MinifyMode minify) {
- super(
- "examples/memberrebinding2", "memberrebinding2.Memberrebinding", frontend, backend, minify);
+ public TreeShakingMemberrebinding2Test(
+ Frontend frontend, TestParameters parameters, MinifyMode minify) {
+ super(frontend, parameters, minify);
+ }
+
+ @Override
+ protected String getName() {
+ return "examples/memberrebinding2";
+ }
+
+ @Override
+ protected String getMainClass() {
+ return "memberrebinding2.Memberrebinding";
}
@Test
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingMinificationTest.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingMinificationTest.java
index 7ca8334..b8151d6 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingMinificationTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingMinificationTest.java
@@ -3,10 +3,9 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking.examples;
+import com.android.tools.r8.TestParameters;
import com.android.tools.r8.shaking.TreeShakingTest;
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
import org.junit.Ignore;
import org.junit.Test;
@@ -18,18 +17,23 @@
public class TreeShakingMinificationTest extends TreeShakingTest {
@Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
+ public static List<Object[]> data() {
+ return defaultTreeShakingParameters();
}
- public TreeShakingMinificationTest(Frontend frontend, Backend backend, MinifyMode minify) {
- super("examples/minification", "minification.Minification", frontend, backend, minify);
+ public TreeShakingMinificationTest(
+ Frontend frontend, TestParameters parameters, MinifyMode minify) {
+ super(frontend, parameters, minify);
+ }
+
+ @Override
+ protected String getName() {
+ return "examples/minification";
+ }
+
+ @Override
+ protected String getMainClass() {
+ return "minification.Minification";
}
@Test
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingMinifygenericTest.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingMinifygenericTest.java
index 0a48ba2..7223763 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingMinifygenericTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingMinifygenericTest.java
@@ -3,10 +3,9 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking.examples;
+import com.android.tools.r8.TestParameters;
import com.android.tools.r8.shaking.TreeShakingTest;
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -17,21 +16,23 @@
public class TreeShakingMinifygenericTest extends TreeShakingTest {
@Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- if (minify == MinifyMode.NONE) {
- continue;
- }
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
+ public static List<Object[]> data() {
+ return data(MinifyMode.withoutNone());
}
- public TreeShakingMinifygenericTest(Frontend frontend, Backend backend, MinifyMode minify) {
- super("examples/minifygeneric", "minifygeneric.Minifygeneric", frontend, backend, minify);
+ public TreeShakingMinifygenericTest(
+ Frontend frontend, TestParameters parameters, MinifyMode minify) {
+ super(frontend, parameters, minify);
+ }
+
+ @Override
+ protected String getName() {
+ return "examples/minifygeneric";
+ }
+
+ @Override
+ protected String getMainClass() {
+ return "minifygeneric.Minifygeneric";
}
@Test
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingMinifygenericwithinnerTest.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingMinifygenericwithinnerTest.java
index 977de65..968ef92 100644
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingMinifygenericwithinnerTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingMinifygenericwithinnerTest.java
@@ -3,10 +3,9 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking.examples;
+import com.android.tools.r8.TestParameters;
import com.android.tools.r8.shaking.TreeShakingTest;
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -17,27 +16,23 @@
public class TreeShakingMinifygenericwithinnerTest extends TreeShakingTest {
@Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- if (minify == MinifyMode.NONE) {
- continue;
- }
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
+ public static List<Object[]> data() {
+ return data(MinifyMode.withoutNone());
}
public TreeShakingMinifygenericwithinnerTest(
- Frontend frontend, Backend backend, MinifyMode minify) {
- super(
- "examples/minifygenericwithinner",
- "minifygenericwithinner.Minifygenericwithinner",
- frontend,
- backend,
- minify);
+ Frontend frontend, TestParameters parameters, MinifyMode minify) {
+ super(frontend, parameters, minify);
+ }
+
+ @Override
+ protected String getName() {
+ return "examples/minifygenericwithinner";
+ }
+
+ @Override
+ protected String getMainClass() {
+ return "minifygenericwithinner.Minifygenericwithinner";
}
@Test