Merge commit '8a8c4b56794f822e0dd053f6e510b8b6635234ab' into dev-release
diff --git a/src/main/java/com/android/tools/r8/D8.java b/src/main/java/com/android/tools/r8/D8.java
index 2e73927..99ff6a7 100644
--- a/src/main/java/com/android/tools/r8/D8.java
+++ b/src/main/java/com/android/tools/r8/D8.java
@@ -341,7 +341,7 @@
new KotlinMetadataRewriter(appView, prefixRewritingNamingLens).runForD8(executor);
new ApplicationWriter(
cfApp,
- null,
+ appView,
options,
null,
GraphLens.getIdentityLens(),
diff --git a/src/main/java/com/android/tools/r8/DexSplitterHelper.java b/src/main/java/com/android/tools/r8/DexSplitterHelper.java
index 7203f8e..9935d84 100644
--- a/src/main/java/com/android/tools/r8/DexSplitterHelper.java
+++ b/src/main/java/com/android/tools/r8/DexSplitterHelper.java
@@ -100,7 +100,7 @@
try {
new ApplicationWriter(
appView.appInfo().app(),
- null,
+ appView,
options,
markers,
GraphLens.getIdentityLens(),
diff --git a/src/main/java/com/android/tools/r8/L8.java b/src/main/java/com/android/tools/r8/L8.java
index aae1486..ef71e03 100644
--- a/src/main/java/com/android/tools/r8/L8.java
+++ b/src/main/java/com/android/tools/r8/L8.java
@@ -99,8 +99,12 @@
});
assert !options.cfToCfDesugar;
if (shrink) {
- R8.run(r8Command);
- } else {
+ AndroidApp r8CommandInputApp = r8Command.getInputApp();
+ InternalOptions r8CommandInternalOptions = r8Command.getInternalOptions();
+ // TODO(b/167843161): Disable temporarily enum unboxing in L8 due to naming issues.
+ r8CommandInternalOptions.enableEnumUnboxing = false;
+ R8.runForTesting(r8CommandInputApp, r8CommandInternalOptions);
+ } else if (d8Command != null) {
D8.run(d8Command, executorService);
}
} finally {
diff --git a/src/main/java/com/android/tools/r8/L8Command.java b/src/main/java/com/android/tools/r8/L8Command.java
index a2cf589..db24f23 100644
--- a/src/main/java/com/android/tools/r8/L8Command.java
+++ b/src/main/java/com/android/tools/r8/L8Command.java
@@ -260,9 +260,6 @@
if (!hasDesugaredLibraryConfiguration()) {
reporter.error("L8 requires a desugared library configuration");
}
- if (getProgramConsumer() instanceof ClassFileConsumer) {
- reporter.error("L8 does not support compiling to class files");
- }
if (getProgramConsumer() instanceof DexFilePerClassFileConsumer) {
reporter.error("L8 does not support compiling to dex per class");
}
@@ -271,6 +268,9 @@
} else if (getMainDexListConsumer() != null) {
reporter.error("L8 does not support generating a main dex list");
}
+ if (isShrinking() && getProgramConsumer() instanceof ClassFileConsumer) {
+ reporter.error("L8 does not support shrinking when generating class files");
+ }
super.validate();
}
@@ -292,12 +292,12 @@
D8Command d8Command = null;
AndroidApp inputs = getAppBuilder().build();
- DesugaredLibrary desugaredLibrary = new DesugaredLibrary();
-
+ ProgramConsumer l8CfConsumer = null;
if (isShrinking()) {
+ l8CfConsumer = new InMemoryJarContent();
R8Command.Builder r8Builder =
new CompatProguardCommandBuilder(true, getReporter())
- .addProgramResourceProvider(desugaredLibrary)
+ .addProgramResourceProvider((ProgramResourceProvider) l8CfConsumer)
.setSynthesizedClassesPrefix(
libraryConfiguration.getSynthesizedLibraryClassesPackagePrefix())
.setMinApiLevel(getMinApiLevel())
@@ -316,10 +316,11 @@
libraryConfiguration.getExtraKeepRules(), Origin.unknown());
r8Builder.addProguardConfigurationFiles(proguardConfigFiles);
r8Command = r8Builder.makeCommand();
- } else {
+ } else if (!(getProgramConsumer() instanceof ClassFileConsumer)) {
+ l8CfConsumer = new InMemoryJarContent();
D8Command.Builder d8Builder =
D8Command.builder(getReporter())
- .addProgramResourceProvider(desugaredLibrary)
+ .addProgramResourceProvider((ProgramResourceProvider) l8CfConsumer)
.setSynthesizedClassesPrefix(
libraryConfiguration.getSynthesizedLibraryClassesPackagePrefix())
.setMinApiLevel(getMinApiLevel())
@@ -332,13 +333,17 @@
d8Builder.addLibraryResourceProvider(libraryResourceProvider);
}
d8Command = d8Builder.makeCommand();
+ } else {
+ assert getProgramConsumer() instanceof ClassFileConsumer;
+ l8CfConsumer = getProgramConsumer();
+ d8Command = null;
}
return new L8Command(
r8Command,
d8Command,
inputs,
getMode(),
- desugaredLibrary,
+ l8CfConsumer,
getMainDexListConsumer(),
getMinApiLevel(),
getReporter(),
@@ -352,7 +357,7 @@
}
}
- static class DesugaredLibrary implements ClassFileConsumer, ProgramResourceProvider {
+ static class InMemoryJarContent implements ClassFileConsumer, ProgramResourceProvider {
private final List<ProgramResource> resources = new ArrayList<>();
diff --git a/src/main/java/com/android/tools/r8/L8CommandParser.java b/src/main/java/com/android/tools/r8/L8CommandParser.java
index e083cec..5d9392c 100644
--- a/src/main/java/com/android/tools/r8/L8CommandParser.java
+++ b/src/main/java/com/android/tools/r8/L8CommandParser.java
@@ -88,7 +88,7 @@
private L8Command.Builder parse(String[] args, Origin origin, L8Command.Builder builder) {
CompilationMode compilationMode = null;
Path outputPath = null;
- OutputMode outputMode = null;
+ OutputMode outputMode = OutputMode.DexIndexed;
boolean hasDefinedApiLevel = false;
OrderedClassFileResourceProvider.Builder classpathBuilder =
OrderedClassFileResourceProvider.builder();
@@ -149,6 +149,8 @@
builder.addProguardConfigurationFiles(Paths.get(nextArg));
} else if (arg.equals("--desugared-lib")) {
builder.addDesugaredLibraryConfiguration(StringResource.fromFile(Paths.get(nextArg)));
+ } else if (arg.equals("--classfile")) {
+ outputMode = OutputMode.ClassFile;
} else if (arg.equals(THREAD_COUNT_FLAG)) {
parsePositiveIntArgument(
builder::error, THREAD_COUNT_FLAG, nextArg, origin, builder::setThreadCount);
@@ -167,9 +169,6 @@
if (compilationMode != null) {
builder.setMode(compilationMode);
}
- if (outputMode == null) {
- outputMode = OutputMode.DexIndexed;
- }
if (outputPath == null) {
outputPath = Paths.get(".");
}
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 9d6b199..3a9b0d9 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -78,6 +78,7 @@
import com.android.tools.r8.optimize.VisibilityBridgeRemover;
import com.android.tools.r8.origin.CommandLineOrigin;
import com.android.tools.r8.repackaging.Repackaging;
+import com.android.tools.r8.repackaging.RepackagingLens;
import com.android.tools.r8.shaking.AbstractMethodRemover;
import com.android.tools.r8.shaking.AnnotationRemover;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
@@ -226,12 +227,7 @@
Set<Marker> markers = new HashSet<>(options.itemFactory.extractMarkers());
markers.remove(marker);
if (options.isGeneratingClassFiles()) {
- new CfApplicationWriter(
- appView,
- marker,
- graphLens,
- namingLens,
- proguardMapSupplier)
+ new CfApplicationWriter(appView, marker, graphLens, namingLens, proguardMapSupplier)
.write(options.getClassFileConsumer());
} else {
new ApplicationWriter(
@@ -390,7 +386,7 @@
assert appView.rootSet().verifyKeptFieldsAreAccessedAndLive(appViewWithLiveness.appInfo());
assert appView.rootSet().verifyKeptMethodsAreTargetedAndLive(appViewWithLiveness.appInfo());
assert appView.rootSet().verifyKeptTypesAreLive(appViewWithLiveness.appInfo());
- assert appView.rootSet().verifyKeptItemsAreKept(appView.appInfo().app(), appView.appInfo());
+ assert appView.rootSet().verifyKeptItemsAreKept(appView);
missingClasses =
Sets.union(missingClasses, appViewWithLiveness.appInfo().getMissingTypes());
@@ -551,7 +547,8 @@
if (options.enableHorizontalClassMerging) {
timing.begin("HorizontalClassMerger");
HorizontalClassMerger merger =
- new HorizontalClassMerger(appViewWithLiveness, mainDexClasses);
+ new HorizontalClassMerger(
+ appViewWithLiveness, mainDexClasses, classMergingEnqueuerExtension);
HorizontalClassMergerGraphLens lens = merger.run();
if (lens != null) {
appView.setHorizontallyMergedClasses(lens.getHorizontallyMergedClasses());
@@ -809,7 +806,15 @@
// Perform repackaging.
// TODO(b/165783399): Consider making repacking available without minification.
if (options.isMinifying() && options.testing.enableExperimentalRepackaging) {
- new Repackaging(appView.withLiveness()).run(executorService, timing);
+ DirectMappedDexApplication.Builder appBuilder =
+ appView.appInfo().app().asDirect().builder();
+ // TODO(b/165783399): We need to deal with non-rebound member references in the writer,
+ // possibly by adding a member rebinding lens on top of the repackaging lens.
+ RepackagingLens lens =
+ new Repackaging(appView.withLiveness()).run(appBuilder, executorService, timing);
+ if (lens != null) {
+ appView.rewriteWithLensAndApplication(lens, appBuilder.build());
+ }
}
// Perform minification.
@@ -886,7 +891,7 @@
if (options.isShrinking()
|| options.isMinifying()
|| options.getProguardConfiguration().hasApplyMappingFile()) {
- assert appView.rootSet().verifyKeptItemsAreKept(appView.appInfo().app(), appView.appInfo());
+ assert appView.rootSet().verifyKeptItemsAreKept(appView);
}
assert appView
.graphLens()
@@ -912,6 +917,7 @@
.run(appView.appInfo().classes(), executorService);
// Generate the resulting application resources.
+ // TODO(b/165783399): Apply the graph lens to all instructions in the CF and DEX backends.
writeApplication(
executorService,
appView,
diff --git a/src/main/java/com/android/tools/r8/ResourceShrinker.java b/src/main/java/com/android/tools/r8/ResourceShrinker.java
index 0affffd..8174420 100644
--- a/src/main/java/com/android/tools/r8/ResourceShrinker.java
+++ b/src/main/java/com/android/tools/r8/ResourceShrinker.java
@@ -288,7 +288,8 @@
// of integers. This can be improved later, but for now we make sure no ints are missed.
}
- methodIntArrayPayloadOffsets.add(fillArrayData.getPayloadOffset() + fillArrayData.offset);
+ methodIntArrayPayloadOffsets.add(
+ fillArrayData.getPayloadOffset() + fillArrayData.getOffset());
}
private void processAnnotationValue(DexValue value) {
diff --git a/src/main/java/com/android/tools/r8/bisect/Bisect.java b/src/main/java/com/android/tools/r8/bisect/Bisect.java
index 0e86dc7..80dd656 100644
--- a/src/main/java/com/android/tools/r8/bisect/Bisect.java
+++ b/src/main/java/com/android/tools/r8/bisect/Bisect.java
@@ -10,6 +10,8 @@
import com.android.tools.r8.dex.ApplicationReader;
import com.android.tools.r8.dex.ApplicationWriter;
import com.android.tools.r8.errors.CompilationError;
+import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.InitClassLens;
@@ -188,7 +190,7 @@
ApplicationWriter writer =
new ApplicationWriter(
app,
- null,
+ AppView.createForD8(AppInfo.createInitialAppInfo(app)),
options,
null,
null,
diff --git a/src/main/java/com/android/tools/r8/cf/CfCodePrinter.java b/src/main/java/com/android/tools/r8/cf/CfCodePrinter.java
index 21a5392..5fb9822 100644
--- a/src/main/java/com/android/tools/r8/cf/CfCodePrinter.java
+++ b/src/main/java/com/android/tools/r8/cf/CfCodePrinter.java
@@ -3,6 +3,8 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.cf;
+import static com.android.tools.r8.utils.StringUtils.join;
+
import com.android.tools.r8.cf.code.CfArithmeticBinop;
import com.android.tools.r8.cf.code.CfArrayLength;
import com.android.tools.r8.cf.code.CfArrayLoad;
@@ -18,6 +20,7 @@
import com.android.tools.r8.cf.code.CfDexItemBasedConstString;
import com.android.tools.r8.cf.code.CfFieldInstruction;
import com.android.tools.r8.cf.code.CfFrame;
+import com.android.tools.r8.cf.code.CfFrame.FrameType;
import com.android.tools.r8.cf.code.CfGoto;
import com.android.tools.r8.cf.code.CfIf;
import com.android.tools.r8.cf.code.CfIfCmp;
@@ -46,6 +49,7 @@
import com.android.tools.r8.cf.code.CfTryCatch;
import com.android.tools.r8.errors.Unimplemented;
import com.android.tools.r8.graph.CfCode;
+import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexString;
@@ -185,6 +189,23 @@
return type("ImmutableList", ImmutableList.of("com", "google", "common", "collect"));
}
+ private String int2ReferenceAVLTreeMapType() {
+ return type(
+ "Int2ReferenceAVLTreeMap", ImmutableList.of("it", "unimi", "dsi", "fastutil", "ints"));
+ }
+
+ private String frameTypeType() {
+ return r8Type("FrameType", ImmutableList.of("cf", "code", "CfFrame"));
+ }
+
+ private String dexItemFactoryType() {
+ return r8Type("DexItemFactory", "graph");
+ }
+
+ private String arraysType() {
+ return type("Arrays", ImmutableList.of("java", "util"));
+ }
+
private String r8Type(String name, String pkg) {
return r8Type(name, Collections.singletonList(pkg));
}
@@ -427,7 +448,40 @@
@Override
public void print(CfFrame frame) {
- throw new Unimplemented(frame.getClass().getSimpleName());
+ String keys = join(frame.getLocals().keySet(), ",", BraceType.NONE);
+ String values = join(frame.getLocals().values(), ",", BraceType.NONE, this::frameTypeType);
+ String stack = join(frame.getStack(), ",", BraceType.NONE, this::frameTypeType);
+ printNewInstruction(
+ "CfFrame",
+ "new "
+ + int2ReferenceAVLTreeMapType()
+ + "<>("
+ + "new int[] {"
+ + keys
+ + "},"
+ + "new "
+ + frameTypeType()
+ + "[] { "
+ + values
+ + " })",
+ arraysType() + ".asList(" + stack + ")");
+ }
+
+ private String frameTypeType(FrameType frameType) {
+ if (frameType.isTop()) {
+ return frameTypeType() + ".top()";
+ } else if (frameType.isUninitializedThis()) {
+ return frameTypeType() + ".uninitializedThis()";
+ } else if (frameType.isUninitializedNew()) {
+ return frameTypeType() + ".uninitializedNew(new " + cfType("CfLabel") + "())";
+ } else {
+ assert frameType.isInitialized();
+ if (frameType.getInitializedType() == DexItemFactory.nullValueType) {
+ return frameTypeType() + ".initialized(" + dexItemFactoryType() + ".nullValueType)";
+ } else {
+ return frameTypeType() + ".initialized(" + dexType(frameType.getInitializedType()) + ")";
+ }
+ }
}
@Override
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfArithmeticBinop.java b/src/main/java/com/android/tools/r8/cf/code/CfArithmeticBinop.java
index 6f4e958..b679a54 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfArithmeticBinop.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfArithmeticBinop.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.code.NumericType;
import com.android.tools.r8.ir.code.ValueType;
@@ -129,7 +130,8 @@
}
@Override
- public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
+ public void write(
+ MethodVisitor visitor, GraphLens graphLens, InitClassLens initClassLens, NamingLens lens) {
visitor.visitInsn(getAsmOpcode());
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfArrayLength.java b/src/main/java/com/android/tools/r8/cf/code/CfArrayLength.java
index 1290256..6510e23 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfArrayLength.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfArrayLength.java
@@ -5,6 +5,7 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.conversion.CfSourceCode;
import com.android.tools.r8.ir.conversion.CfState;
@@ -19,7 +20,8 @@
public class CfArrayLength extends CfInstruction {
@Override
- public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
+ public void write(
+ MethodVisitor visitor, GraphLens graphLens, InitClassLens initClassLens, NamingLens lens) {
visitor.visitInsn(Opcodes.ARRAYLENGTH);
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfArrayLoad.java b/src/main/java/com/android/tools/r8/cf/code/CfArrayLoad.java
index 02e20ea..a9d754e 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfArrayLoad.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfArrayLoad.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.code.MemberType;
import com.android.tools.r8.ir.code.ValueType;
@@ -56,7 +57,8 @@
}
@Override
- public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
+ public void write(
+ MethodVisitor visitor, GraphLens graphLens, InitClassLens initClassLens, NamingLens lens) {
visitor.visitInsn(getLoadType());
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfArrayStore.java b/src/main/java/com/android/tools/r8/cf/code/CfArrayStore.java
index 1976942..5e8c152 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfArrayStore.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfArrayStore.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.code.MemberType;
import com.android.tools.r8.ir.conversion.CfSourceCode;
@@ -54,7 +55,8 @@
}
@Override
- public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
+ public void write(
+ MethodVisitor visitor, GraphLens graphLens, InitClassLens initClassLens, NamingLens lens) {
visitor.visitInsn(getStoreType());
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfCheckCast.java b/src/main/java/com/android/tools/r8/cf/code/CfCheckCast.java
index a46e68c..7f6a380 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfCheckCast.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfCheckCast.java
@@ -7,6 +7,7 @@
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.CfSourceCode;
@@ -32,8 +33,9 @@
}
@Override
- public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
- visitor.visitTypeInsn(Opcodes.CHECKCAST, lens.lookupInternalName(type));
+ public void write(
+ MethodVisitor visitor, GraphLens graphLens, InitClassLens initClassLens, NamingLens lens) {
+ visitor.visitTypeInsn(Opcodes.CHECKCAST, lens.lookupInternalName(graphLens.lookupType(type)));
}
@Override
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfCmp.java b/src/main/java/com/android/tools/r8/cf/code/CfCmp.java
index 8d128be..1163483 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfCmp.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfCmp.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.code.Cmp;
import com.android.tools.r8.ir.code.Cmp.Bias;
@@ -79,7 +80,8 @@
}
@Override
- public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
+ public void write(
+ MethodVisitor visitor, GraphLens graphLens, InitClassLens initClassLens, NamingLens lens) {
visitor.visitInsn(getAsmOpcode());
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfConstClass.java b/src/main/java/com/android/tools/r8/cf/code/CfConstClass.java
index 05d8568..37255ff 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfConstClass.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfConstClass.java
@@ -8,6 +8,7 @@
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.CfSourceCode;
@@ -32,8 +33,12 @@
}
@Override
- public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
- visitor.visitLdcInsn(Type.getObjectType(getInternalName(lens)));
+ public void write(
+ MethodVisitor visitor,
+ GraphLens graphLens,
+ InitClassLens initClassLens,
+ NamingLens namingLens) {
+ visitor.visitLdcInsn(Type.getObjectType(getInternalName(graphLens, namingLens)));
}
@Override
@@ -46,11 +51,11 @@
return true;
}
- private String getInternalName(NamingLens lens) {
+ private String getInternalName(GraphLens graphLens, NamingLens namingLens) {
switch (type.toShorty()) {
case '[':
case 'L':
- return lens.lookupInternalName(type);
+ return namingLens.lookupInternalName(graphLens.lookupType(type));
case 'Z':
return "java/lang/Boolean/TYPE";
case 'B':
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfConstMethodHandle.java b/src/main/java/com/android/tools/r8/cf/code/CfConstMethodHandle.java
index 89fae02..c5d52f2 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfConstMethodHandle.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfConstMethodHandle.java
@@ -7,6 +7,7 @@
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexMethodHandle;
import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.graph.UseRegistry.MethodHandleUse;
@@ -31,7 +32,8 @@
}
@Override
- public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
+ public void write(
+ MethodVisitor visitor, GraphLens graphLens, InitClassLens initClassLens, NamingLens lens) {
visitor.visitLdcInsn(handle.toAsmHandle(lens));
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfConstMethodType.java b/src/main/java/com/android/tools/r8/cf/code/CfConstMethodType.java
index 8283278..17577b9 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfConstMethodType.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfConstMethodType.java
@@ -7,6 +7,7 @@
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexProto;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.CfSourceCode;
@@ -31,7 +32,8 @@
}
@Override
- public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
+ public void write(
+ MethodVisitor visitor, GraphLens graphLens, InitClassLens initClassLens, NamingLens lens) {
visitor.visitLdcInsn(Type.getType(type.toDescriptorString(lens)));
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfConstNull.java b/src/main/java/com/android/tools/r8/cf/code/CfConstNull.java
index 889a63c..1c5e970 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfConstNull.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfConstNull.java
@@ -5,6 +5,7 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.code.ValueType;
import com.android.tools.r8.ir.conversion.CfSourceCode;
@@ -19,7 +20,8 @@
public class CfConstNull extends CfInstruction {
@Override
- public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
+ public void write(
+ MethodVisitor visitor, GraphLens graphLens, InitClassLens initClassLens, NamingLens lens) {
visitor.visitInsn(Opcodes.ACONST_NULL);
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfConstNumber.java b/src/main/java/com/android/tools/r8/cf/code/CfConstNumber.java
index 5451986..b4e63a9 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfConstNumber.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfConstNumber.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.code.ValueType;
import com.android.tools.r8.ir.conversion.CfSourceCode;
@@ -56,7 +57,8 @@
}
@Override
- public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
+ public void write(
+ MethodVisitor visitor, GraphLens graphLens, InitClassLens initClassLens, NamingLens lens) {
switch (type) {
case INT:
{
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfConstString.java b/src/main/java/com/android/tools/r8/cf/code/CfConstString.java
index 3b113cb..649f756 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfConstString.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfConstString.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexString;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.conversion.CfSourceCode;
import com.android.tools.r8.ir.conversion.CfState;
@@ -42,7 +43,8 @@
}
@Override
- public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
+ public void write(
+ MethodVisitor visitor, GraphLens graphLens, InitClassLens initClassLens, NamingLens lens) {
visitor.visitLdcInsn(string.toString());
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfDexItemBasedConstString.java b/src/main/java/com/android/tools/r8/cf/code/CfDexItemBasedConstString.java
index 94eadd1..79e59db 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfDexItemBasedConstString.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfDexItemBasedConstString.java
@@ -8,6 +8,7 @@
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexReference;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.CfSourceCode;
@@ -48,7 +49,8 @@
}
@Override
- public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
+ public void write(
+ MethodVisitor visitor, GraphLens graphLens, InitClassLens initClassLens, NamingLens lens) {
throw new Unreachable(
"CfDexItemBasedConstString instructions should always be rewritten into CfConstString");
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfFieldInstruction.java b/src/main/java/com/android/tools/r8/cf/code/CfFieldInstruction.java
index 7e31f5b..32c8494 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfFieldInstruction.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfFieldInstruction.java
@@ -9,6 +9,7 @@
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.CfSourceCode;
@@ -53,10 +54,13 @@
}
@Override
- public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
- String owner = lens.lookupInternalName(field.holder);
- String name = lens.lookupName(declaringField).toString();
- String desc = lens.lookupDescriptor(field.type).toString();
+ public void write(
+ MethodVisitor visitor, GraphLens graphLens, InitClassLens initClassLens, NamingLens lens) {
+ DexField newField = graphLens.lookupField(field);
+ DexField newDeclaringField = graphLens.lookupField(declaringField);
+ String owner = lens.lookupInternalName(newField.holder);
+ String name = lens.lookupName(newDeclaringField).toString();
+ String desc = lens.lookupDescriptor(newField.type).toString();
visitor.visitFieldInsn(opcode, owner, name, desc);
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfFrame.java b/src/main/java/com/android/tools/r8/cf/code/CfFrame.java
index f1058d6..152f9e9 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfFrame.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfFrame.java
@@ -10,6 +10,7 @@
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.conversion.CfSourceCode;
import com.android.tools.r8.ir.conversion.CfState;
@@ -223,7 +224,8 @@
}
@Override
- public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
+ public void write(
+ MethodVisitor visitor, GraphLens graphLens, InitClassLens initClassLens, NamingLens lens) {
int stackCount = computeStackCount();
Object[] stackTypes = computeStackTypes(stackCount, lens);
int localsCount = computeLocalsCount();
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfGoto.java b/src/main/java/com/android/tools/r8/cf/code/CfGoto.java
index bbb8996..d38c0fe 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfGoto.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfGoto.java
@@ -5,6 +5,7 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.conversion.CfSourceCode;
import com.android.tools.r8.ir.conversion.CfState;
@@ -44,7 +45,8 @@
}
@Override
- public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
+ public void write(
+ MethodVisitor visitor, GraphLens graphLens, InitClassLens initClassLens, NamingLens lens) {
visitor.visitJumpInsn(Opcodes.GOTO, target.getLabel());
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfIf.java b/src/main/java/com/android/tools/r8/cf/code/CfIf.java
index a6d0fca..f64d79c 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfIf.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfIf.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.code.If;
import com.android.tools.r8.ir.code.If.Type;
@@ -69,7 +70,8 @@
}
@Override
- public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
+ public void write(
+ MethodVisitor visitor, GraphLens graphLens, InitClassLens initClassLens, NamingLens lens) {
visitor.visitJumpInsn(getOpcode(), target.getLabel());
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfIfCmp.java b/src/main/java/com/android/tools/r8/cf/code/CfIfCmp.java
index 24c81a5..1ee17b1 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfIfCmp.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfIfCmp.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.code.If;
import com.android.tools.r8.ir.code.If.Type;
@@ -69,7 +70,8 @@
}
@Override
- public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
+ public void write(
+ MethodVisitor visitor, GraphLens graphLens, InitClassLens initClassLens, NamingLens lens) {
visitor.visitJumpInsn(getOpcode(), target.getLabel());
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfIinc.java b/src/main/java/com/android/tools/r8/cf/code/CfIinc.java
index 4ce64a4..edba7b4 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfIinc.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfIinc.java
@@ -5,6 +5,7 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.code.NumericType;
import com.android.tools.r8.ir.conversion.CfSourceCode;
@@ -26,7 +27,8 @@
}
@Override
- public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
+ public void write(
+ MethodVisitor visitor, GraphLens graphLens, InitClassLens initClassLens, NamingLens lens) {
visitor.visitIincInsn(var, increment);
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfInitClass.java b/src/main/java/com/android/tools/r8/cf/code/CfInitClass.java
index 115d27a..afcae7d 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfInitClass.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfInitClass.java
@@ -8,6 +8,7 @@
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.CfSourceCode;
@@ -37,7 +38,8 @@
}
@Override
- public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
+ public void write(
+ MethodVisitor visitor, GraphLens graphLens, InitClassLens initClassLens, NamingLens lens) {
DexField field = initClassLens.getInitClassField(clazz);
String owner = lens.lookupInternalName(field.holder);
String name = lens.lookupName(field).toString();
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfInstanceOf.java b/src/main/java/com/android/tools/r8/cf/code/CfInstanceOf.java
index ca6b7ed..fc26a95 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfInstanceOf.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfInstanceOf.java
@@ -7,6 +7,7 @@
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.CfSourceCode;
@@ -41,7 +42,8 @@
}
@Override
- public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
+ public void write(
+ MethodVisitor visitor, GraphLens graphLens, InitClassLens initClassLens, NamingLens lens) {
visitor.visitTypeInsn(Opcodes.INSTANCEOF, lens.lookupInternalName(type));
}
@@ -52,7 +54,7 @@
@Override
void internalRegisterUse(UseRegistry registry, DexClassAndMethod context) {
- registry.registerTypeReference(type);
+ registry.registerInstanceOf(type);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfInstruction.java b/src/main/java/com/android/tools/r8/cf/code/CfInstruction.java
index 041409b..16ef22f 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfInstruction.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfInstruction.java
@@ -7,6 +7,7 @@
import com.android.tools.r8.graph.ClasspathMethod;
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.UseRegistry;
@@ -20,7 +21,8 @@
public abstract class CfInstruction {
- public abstract void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens);
+ public abstract void write(
+ MethodVisitor visitor, GraphLens graphLens, InitClassLens initClassLens, NamingLens lens);
public abstract void print(CfPrinter printer);
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfInvoke.java b/src/main/java/com/android/tools/r8/cf/code/CfInvoke.java
index 510249b..3851031 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfInvoke.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfInvoke.java
@@ -71,10 +71,12 @@
}
@Override
- public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
- String owner = lens.lookupInternalName(method.holder);
- String name = lens.lookupName(method).toString();
- String desc = method.proto.toDescriptorString(lens);
+ public void write(
+ MethodVisitor visitor, GraphLens graphLens, InitClassLens initClassLens, NamingLens lens) {
+ DexMethod newMethod = graphLens.lookupMethod(method);
+ String owner = lens.lookupInternalName(newMethod.holder);
+ String name = lens.lookupName(newMethod).toString();
+ String desc = newMethod.proto.toDescriptorString(lens);
visitor.visitMethodInsn(opcode, owner, name, desc, itf);
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfInvokeDynamic.java b/src/main/java/com/android/tools/r8/cf/code/CfInvokeDynamic.java
index fac04cd..f57046b 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfInvokeDynamic.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfInvokeDynamic.java
@@ -12,6 +12,7 @@
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.DexValue;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.code.ValueType;
@@ -36,7 +37,8 @@
}
@Override
- public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
+ public void write(
+ MethodVisitor visitor, GraphLens graphLens, InitClassLens initClassLens, NamingLens lens) {
DexMethodHandle bootstrapMethod = callSite.bootstrapMethod;
List<DexValue> bootstrapArgs = callSite.bootstrapArgs;
Object[] bsmArgs = new Object[bootstrapArgs.size()];
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfJsrRet.java b/src/main/java/com/android/tools/r8/cf/code/CfJsrRet.java
index 2fc78ea..88659de 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfJsrRet.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfJsrRet.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.conversion.CfSourceCode;
import com.android.tools.r8.ir.conversion.CfState;
@@ -29,7 +30,8 @@
}
@Override
- public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
+ public void write(
+ MethodVisitor visitor, GraphLens graphLens, InitClassLens initClassLens, NamingLens lens) {
throw error();
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfLabel.java b/src/main/java/com/android/tools/r8/cf/code/CfLabel.java
index 6cc49de..19ba74a 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfLabel.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfLabel.java
@@ -5,6 +5,7 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.conversion.CfSourceCode;
import com.android.tools.r8.ir.conversion.CfState;
@@ -42,7 +43,8 @@
}
@Override
- public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
+ public void write(
+ MethodVisitor visitor, GraphLens graphLens, InitClassLens initClassLens, NamingLens lens) {
visitor.visitLabel(getLabel());
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfLoad.java b/src/main/java/com/android/tools/r8/cf/code/CfLoad.java
index 0680d73..80bb1da 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfLoad.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfLoad.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.code.ValueType;
import com.android.tools.r8.ir.conversion.CfSourceCode;
@@ -56,7 +57,8 @@
}
@Override
- public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
+ public void write(
+ MethodVisitor visitor, GraphLens graphLens, InitClassLens initClassLens, NamingLens lens) {
visitor.visitVarInsn(getLoadType(), var);
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfLogicalBinop.java b/src/main/java/com/android/tools/r8/cf/code/CfLogicalBinop.java
index f34a7d7..0f5bd4e 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfLogicalBinop.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfLogicalBinop.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.code.NumericType;
import com.android.tools.r8.ir.code.ValueType;
@@ -104,7 +105,8 @@
}
@Override
- public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
+ public void write(
+ MethodVisitor visitor, GraphLens graphLens, InitClassLens initClassLens, NamingLens lens) {
visitor.visitInsn(getAsmOpcode());
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfMonitor.java b/src/main/java/com/android/tools/r8/cf/code/CfMonitor.java
index 7fd0167..ebefa78 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfMonitor.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfMonitor.java
@@ -5,6 +5,7 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.code.Monitor.Type;
import com.android.tools.r8.ir.conversion.CfSourceCode;
@@ -30,7 +31,8 @@
}
@Override
- public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
+ public void write(
+ MethodVisitor visitor, GraphLens graphLens, InitClassLens initClassLens, NamingLens lens) {
visitor.visitInsn(type == Type.ENTER ? Opcodes.MONITORENTER : Opcodes.MONITOREXIT);
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfMultiANewArray.java b/src/main/java/com/android/tools/r8/cf/code/CfMultiANewArray.java
index 1f787f8..69a69af 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfMultiANewArray.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfMultiANewArray.java
@@ -7,6 +7,7 @@
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.CfSourceCode;
@@ -37,7 +38,8 @@
}
@Override
- public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
+ public void write(
+ MethodVisitor visitor, GraphLens graphLens, InitClassLens initClassLens, NamingLens lens) {
visitor.visitMultiANewArrayInsn(lens.lookupInternalName(type), dimensions);
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfNeg.java b/src/main/java/com/android/tools/r8/cf/code/CfNeg.java
index cd61c29..32ef906 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfNeg.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfNeg.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.code.NumericType;
import com.android.tools.r8.ir.code.ValueType;
@@ -31,7 +32,8 @@
}
@Override
- public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
+ public void write(
+ MethodVisitor visitor, GraphLens graphLens, InitClassLens initClassLens, NamingLens lens) {
visitor.visitInsn(getAsmOpcode());
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfNew.java b/src/main/java/com/android/tools/r8/cf/code/CfNew.java
index 8bd1249..e0b8785 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfNew.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfNew.java
@@ -7,6 +7,7 @@
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.CfSourceCode;
@@ -31,7 +32,8 @@
}
@Override
- public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
+ public void write(
+ MethodVisitor visitor, GraphLens graphLens, InitClassLens initClassLens, NamingLens lens) {
visitor.visitTypeInsn(Opcodes.NEW, lens.lookupInternalName(type));
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfNewArray.java b/src/main/java/com/android/tools/r8/cf/code/CfNewArray.java
index 9ef5f1b..6c3869b 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfNewArray.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfNewArray.java
@@ -8,6 +8,7 @@
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.CfSourceCode;
@@ -66,7 +67,8 @@
}
@Override
- public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
+ public void write(
+ MethodVisitor visitor, GraphLens graphLens, InitClassLens initClassLens, NamingLens lens) {
if (type.isPrimitiveArrayType()) {
visitor.visitIntInsn(Opcodes.NEWARRAY, getPrimitiveTypeCode());
} else {
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfNop.java b/src/main/java/com/android/tools/r8/cf/code/CfNop.java
index 4578bff..18a2ae6 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfNop.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfNop.java
@@ -5,6 +5,7 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.conversion.CfSourceCode;
import com.android.tools.r8.ir.conversion.CfState;
@@ -18,7 +19,8 @@
public class CfNop extends CfInstruction {
@Override
- public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
+ public void write(
+ MethodVisitor visitor, GraphLens graphLens, InitClassLens initClassLens, NamingLens lens) {
visitor.visitInsn(Opcodes.NOP);
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfNumberConversion.java b/src/main/java/com/android/tools/r8/cf/code/CfNumberConversion.java
index afbff92..405fb42 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfNumberConversion.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfNumberConversion.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.code.NumericType;
import com.android.tools.r8.ir.code.ValueType;
@@ -41,7 +42,8 @@
}
@Override
- public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
+ public void write(
+ MethodVisitor visitor, GraphLens graphLens, InitClassLens initClassLens, NamingLens lens) {
visitor.visitInsn(this.getAsmOpcode());
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfPosition.java b/src/main/java/com/android/tools/r8/cf/code/CfPosition.java
index 93febbb..70a3f07 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfPosition.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfPosition.java
@@ -5,6 +5,7 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.code.Position;
import com.android.tools.r8.ir.conversion.CfSourceCode;
@@ -26,7 +27,8 @@
}
@Override
- public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
+ public void write(
+ MethodVisitor visitor, GraphLens graphLens, InitClassLens initClassLens, NamingLens lens) {
visitor.visitLineNumber(position.line, label.getLabel());
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfReturn.java b/src/main/java/com/android/tools/r8/cf/code/CfReturn.java
index 5934617..d66d6cf 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfReturn.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfReturn.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.code.ValueType;
import com.android.tools.r8.ir.conversion.CfSourceCode;
@@ -53,7 +54,8 @@
}
@Override
- public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
+ public void write(
+ MethodVisitor visitor, GraphLens graphLens, InitClassLens initClassLens, NamingLens lens) {
visitor.visitInsn(getOpcode());
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfReturnVoid.java b/src/main/java/com/android/tools/r8/cf/code/CfReturnVoid.java
index c9d7f51..83b5e60 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfReturnVoid.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfReturnVoid.java
@@ -5,6 +5,7 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.conversion.CfSourceCode;
import com.android.tools.r8.ir.conversion.CfState;
@@ -23,7 +24,8 @@
}
@Override
- public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
+ public void write(
+ MethodVisitor visitor, GraphLens graphLens, InitClassLens initClassLens, NamingLens lens) {
visitor.visitInsn(Opcodes.RETURN);
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfStackInstruction.java b/src/main/java/com/android/tools/r8/cf/code/CfStackInstruction.java
index ef291d0..a4ecce6 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfStackInstruction.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfStackInstruction.java
@@ -7,6 +7,7 @@
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.code.ValueType;
import com.android.tools.r8.ir.conversion.CfSourceCode;
@@ -75,7 +76,8 @@
}
@Override
- public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
+ public void write(
+ MethodVisitor visitor, GraphLens graphLens, InitClassLens initClassLens, NamingLens lens) {
visitor.visitInsn(opcode.opcode);
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfStore.java b/src/main/java/com/android/tools/r8/cf/code/CfStore.java
index d8f13d1..c3ce5db 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfStore.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfStore.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.code.ValueType;
import com.android.tools.r8.ir.conversion.CfSourceCode;
@@ -56,7 +57,8 @@
}
@Override
- public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
+ public void write(
+ MethodVisitor visitor, GraphLens graphLens, InitClassLens initClassLens, NamingLens lens) {
visitor.visitVarInsn(getStoreType(), var);
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfSwitch.java b/src/main/java/com/android/tools/r8/cf/code/CfSwitch.java
index 3169da0..3a3c72e 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfSwitch.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfSwitch.java
@@ -5,6 +5,7 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.conversion.CfSourceCode;
import com.android.tools.r8.ir.conversion.CfState;
@@ -69,7 +70,8 @@
}
@Override
- public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
+ public void write(
+ MethodVisitor visitor, GraphLens graphLens, InitClassLens initClassLens, NamingLens lens) {
Label[] labels = new Label[targets.size()];
for (int i = 0; i < targets.size(); i++) {
labels[i] = targets.get(i).getLabel();
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfThrow.java b/src/main/java/com/android/tools/r8/cf/code/CfThrow.java
index 9b88cb5..3b49cb0 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfThrow.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfThrow.java
@@ -5,6 +5,7 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.conversion.CfSourceCode;
import com.android.tools.r8.ir.conversion.CfState;
@@ -24,7 +25,8 @@
}
@Override
- public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
+ public void write(
+ MethodVisitor visitor, GraphLens graphLens, InitClassLens initClassLens, NamingLens lens) {
visitor.visitInsn(Opcodes.ATHROW);
}
diff --git a/src/main/java/com/android/tools/r8/code/CheckCast.java b/src/main/java/com/android/tools/r8/code/CheckCast.java
index f472800..569b358 100644
--- a/src/main/java/com/android/tools/r8/code/CheckCast.java
+++ b/src/main/java/com/android/tools/r8/code/CheckCast.java
@@ -3,12 +3,13 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.code;
+import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.OffsetToObjectMapping;
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class CheckCast extends Format21c {
+public class CheckCast extends Format21c<DexType> {
public static final int OPCODE = 0x1f;
public static final String NAME = "CheckCast";
@@ -38,6 +39,11 @@
}
@Override
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
+ getType().collectIndexedItems(indexedItems);
+ }
+
+ @Override
public CheckCast asCheckCast() {
return this;
}
@@ -53,7 +59,7 @@
}
public DexType getType() {
- return (DexType) BBBB;
+ return BBBB;
}
@Override
diff --git a/src/main/java/com/android/tools/r8/code/ConstClass.java b/src/main/java/com/android/tools/r8/code/ConstClass.java
index 33cef07..2f8f7db 100644
--- a/src/main/java/com/android/tools/r8/code/ConstClass.java
+++ b/src/main/java/com/android/tools/r8/code/ConstClass.java
@@ -3,12 +3,13 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.code;
+import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.OffsetToObjectMapping;
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class ConstClass extends Format21c {
+public class ConstClass extends Format21c<DexType> {
public static final int OPCODE = 0x1c;
public static final String NAME = "ConstClass";
@@ -38,12 +39,17 @@
}
@Override
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
+ getType().collectIndexedItems(indexedItems);
+ }
+
+ @Override
public void registerUse(UseRegistry registry) {
registry.registerConstClass(getType());
}
public DexType getType() {
- return (DexType) BBBB;
+ return BBBB;
}
@Override
diff --git a/src/main/java/com/android/tools/r8/code/ConstMethodHandle.java b/src/main/java/com/android/tools/r8/code/ConstMethodHandle.java
index fd17fef..8518946 100644
--- a/src/main/java/com/android/tools/r8/code/ConstMethodHandle.java
+++ b/src/main/java/com/android/tools/r8/code/ConstMethodHandle.java
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.code;
+import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.errors.InternalCompilerError;
import com.android.tools.r8.graph.DexMethodHandle;
import com.android.tools.r8.graph.ObjectToOffsetMapping;
@@ -13,7 +14,7 @@
import com.android.tools.r8.naming.ClassNameMapper;
import java.nio.ShortBuffer;
-public class ConstMethodHandle extends Format21c {
+public class ConstMethodHandle extends Format21c<DexMethodHandle> {
public static final int OPCODE = 0xfe;
public static final String NAME = "ConstMethodHandle";
@@ -28,7 +29,7 @@
}
public DexMethodHandle getMethodHandle() {
- return (DexMethodHandle) BBBB;
+ return BBBB;
}
@Override
@@ -72,8 +73,13 @@
}
@Override
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
+ getMethodHandle().collectIndexedItems(indexedItems);
+ }
+
+ @Override
public void buildIR(IRBuilder builder) {
- builder.addConstMethodHandle(AA, (DexMethodHandle) BBBB);
+ builder.addConstMethodHandle(AA, BBBB);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/code/ConstMethodType.java b/src/main/java/com/android/tools/r8/code/ConstMethodType.java
index 84c090a..8eb5443 100644
--- a/src/main/java/com/android/tools/r8/code/ConstMethodType.java
+++ b/src/main/java/com/android/tools/r8/code/ConstMethodType.java
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.code;
+import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.errors.InternalCompilerError;
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.ObjectToOffsetMapping;
@@ -12,7 +13,7 @@
import com.android.tools.r8.naming.ClassNameMapper;
import java.nio.ShortBuffer;
-public class ConstMethodType extends Format21c {
+public class ConstMethodType extends Format21c<DexProto> {
public static final int OPCODE = 0xff;
public static final String NAME = "ConstMethodType";
@@ -27,7 +28,7 @@
}
public DexProto getMethodType() {
- return (DexProto) BBBB;
+ return BBBB;
}
@Override
@@ -70,8 +71,13 @@
}
@Override
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
+ getMethodType().collectIndexedItems(indexedItems);
+ }
+
+ @Override
public void buildIR(IRBuilder builder) {
- builder.addConstMethodType(AA, (DexProto) BBBB);
+ builder.addConstMethodType(AA, BBBB);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/code/ConstString.java b/src/main/java/com/android/tools/r8/code/ConstString.java
index a5733ad..261016b 100644
--- a/src/main/java/com/android/tools/r8/code/ConstString.java
+++ b/src/main/java/com/android/tools/r8/code/ConstString.java
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.code;
+import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.errors.InternalCompilerError;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.ObjectToOffsetMapping;
@@ -11,7 +12,7 @@
import com.android.tools.r8.naming.ClassNameMapper;
import java.nio.ShortBuffer;
-public class ConstString extends Format21c {
+public class ConstString extends Format21c<DexString> {
public static final int OPCODE = 0x1a;
public static final String NAME = "ConstString";
@@ -26,7 +27,12 @@
}
public DexString getString() {
- return (DexString) BBBB;
+ return BBBB;
+ }
+
+ @Override
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
+ getString().collectIndexedItems(indexedItems);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/code/DexInitClass.java b/src/main/java/com/android/tools/r8/code/DexInitClass.java
index 9df8285..20f2047 100644
--- a/src/main/java/com/android/tools/r8/code/DexInitClass.java
+++ b/src/main/java/com/android/tools/r8/code/DexInitClass.java
@@ -7,7 +7,6 @@
import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.DexField;
-import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.ObjectToOffsetMapping;
import com.android.tools.r8.graph.UseRegistry;
@@ -37,10 +36,9 @@
}
@Override
- public void collectIndexedItems(
- IndexedItemCollection indexedItems, DexMethod method, int instructionOffset) {
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
DexField field = indexedItems.getInitClassLens().getInitClassField(clazz);
- field.collectIndexedItems(indexedItems, method, instructionOffset);
+ field.collectIndexedItems(indexedItems);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/code/DexItemBasedConstString.java b/src/main/java/com/android/tools/r8/code/DexItemBasedConstString.java
index 5ae471a..1fb6e8c 100644
--- a/src/main/java/com/android/tools/r8/code/DexItemBasedConstString.java
+++ b/src/main/java/com/android/tools/r8/code/DexItemBasedConstString.java
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.code;
+import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.ObjectToOffsetMapping;
@@ -12,7 +13,7 @@
import com.android.tools.r8.naming.dexitembasedstring.NameComputationInfo;
import java.nio.ShortBuffer;
-public class DexItemBasedConstString extends Format21c {
+public class DexItemBasedConstString extends Format21c<DexReference> {
public static final String NAME = "DexItemBasedConstString";
public static final String SMALI_NAME = "const-string*";
@@ -26,7 +27,7 @@
}
public DexReference getItem() {
- return (DexReference) BBBB;
+ return BBBB;
}
public NameComputationInfo<?> getNameComputationInfo() {
@@ -34,6 +35,11 @@
}
@Override
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
+ getItem().collectIndexedItems(indexedItems);
+ }
+
+ @Override
public String getName() {
return NAME;
}
diff --git a/src/main/java/com/android/tools/r8/code/FilledNewArray.java b/src/main/java/com/android/tools/r8/code/FilledNewArray.java
index 4f2ebb6..1932e16 100644
--- a/src/main/java/com/android/tools/r8/code/FilledNewArray.java
+++ b/src/main/java/com/android/tools/r8/code/FilledNewArray.java
@@ -3,11 +3,12 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.code;
+import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.OffsetToObjectMapping;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class FilledNewArray extends Format35c {
+public class FilledNewArray extends Format35c<DexType> {
public static final int OPCODE = 0x24;
public static final String NAME = "FilledNewArray";
@@ -36,8 +37,13 @@
return OPCODE;
}
+ @Override
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
+ getType().collectIndexedItems(indexedItems);
+ }
+
public DexType getType() {
- return (DexType) BBBB;
+ return BBBB;
}
@Override
diff --git a/src/main/java/com/android/tools/r8/code/FilledNewArrayRange.java b/src/main/java/com/android/tools/r8/code/FilledNewArrayRange.java
index 0ee63b0..7fc2adc 100644
--- a/src/main/java/com/android/tools/r8/code/FilledNewArrayRange.java
+++ b/src/main/java/com/android/tools/r8/code/FilledNewArrayRange.java
@@ -3,11 +3,12 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.code;
+import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.OffsetToObjectMapping;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class FilledNewArrayRange extends Format3rc {
+public class FilledNewArrayRange extends Format3rc<DexType> {
public static final int OPCODE = 0x25;
public static final String NAME = "FilledNewArrayRange";
@@ -36,8 +37,13 @@
return OPCODE;
}
+ @Override
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
+ getType().collectIndexedItems(indexedItems);
+ }
+
public DexType getType() {
- return (DexType) BBBB;
+ return BBBB;
}
@Override
diff --git a/src/main/java/com/android/tools/r8/code/Format10t.java b/src/main/java/com/android/tools/r8/code/Format10t.java
index 8365a28..4c61fa3 100644
--- a/src/main/java/com/android/tools/r8/code/Format10t.java
+++ b/src/main/java/com/android/tools/r8/code/Format10t.java
@@ -4,7 +4,6 @@
package com.android.tools.r8.code;
import com.android.tools.r8.dex.IndexedItemCollection;
-import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.ObjectToOffsetMapping;
import com.android.tools.r8.naming.ClassNameMapper;
import java.nio.ShortBuffer;
@@ -54,8 +53,7 @@
}
@Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
// No references.
}
}
diff --git a/src/main/java/com/android/tools/r8/code/Format10x.java b/src/main/java/com/android/tools/r8/code/Format10x.java
index 0b497fb..8eed571 100644
--- a/src/main/java/com/android/tools/r8/code/Format10x.java
+++ b/src/main/java/com/android/tools/r8/code/Format10x.java
@@ -4,7 +4,6 @@
package com.android.tools.r8.code;
import com.android.tools.r8.dex.IndexedItemCollection;
-import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.ObjectToOffsetMapping;
import com.android.tools.r8.naming.ClassNameMapper;
import java.nio.ShortBuffer;
@@ -46,8 +45,7 @@
}
@Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
// No references.
}
}
diff --git a/src/main/java/com/android/tools/r8/code/Format11n.java b/src/main/java/com/android/tools/r8/code/Format11n.java
index 4d9a01b..f2b8ac2 100644
--- a/src/main/java/com/android/tools/r8/code/Format11n.java
+++ b/src/main/java/com/android/tools/r8/code/Format11n.java
@@ -5,7 +5,6 @@
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.dex.IndexedItemCollection;
-import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.ObjectToOffsetMapping;
import com.android.tools.r8.naming.ClassNameMapper;
import java.nio.ShortBuffer;
@@ -59,8 +58,7 @@
}
@Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
// No references.
}
}
diff --git a/src/main/java/com/android/tools/r8/code/Format11x.java b/src/main/java/com/android/tools/r8/code/Format11x.java
index dd5a76b..318bf04 100644
--- a/src/main/java/com/android/tools/r8/code/Format11x.java
+++ b/src/main/java/com/android/tools/r8/code/Format11x.java
@@ -5,7 +5,6 @@
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.dex.IndexedItemCollection;
-import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.ObjectToOffsetMapping;
import com.android.tools.r8.naming.ClassNameMapper;
import java.nio.ShortBuffer;
@@ -54,8 +53,7 @@
}
@Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
// No references.
}
}
diff --git a/src/main/java/com/android/tools/r8/code/Format12x.java b/src/main/java/com/android/tools/r8/code/Format12x.java
index 07ec8e2..ac90623 100644
--- a/src/main/java/com/android/tools/r8/code/Format12x.java
+++ b/src/main/java/com/android/tools/r8/code/Format12x.java
@@ -5,7 +5,6 @@
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.dex.IndexedItemCollection;
-import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.ObjectToOffsetMapping;
import com.android.tools.r8.naming.ClassNameMapper;
import java.nio.ShortBuffer;
@@ -58,8 +57,7 @@
}
@Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
// No references.
}
}
diff --git a/src/main/java/com/android/tools/r8/code/Format20t.java b/src/main/java/com/android/tools/r8/code/Format20t.java
index ee32757..f145476 100644
--- a/src/main/java/com/android/tools/r8/code/Format20t.java
+++ b/src/main/java/com/android/tools/r8/code/Format20t.java
@@ -4,7 +4,6 @@
package com.android.tools.r8.code;
import com.android.tools.r8.dex.IndexedItemCollection;
-import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.ObjectToOffsetMapping;
import com.android.tools.r8.naming.ClassNameMapper;
import java.nio.ShortBuffer;
@@ -54,8 +53,7 @@
}
@Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
// No references.
}
}
diff --git a/src/main/java/com/android/tools/r8/code/Format21c.java b/src/main/java/com/android/tools/r8/code/Format21c.java
index faa9d58..04848f0 100644
--- a/src/main/java/com/android/tools/r8/code/Format21c.java
+++ b/src/main/java/com/android/tools/r8/code/Format21c.java
@@ -4,27 +4,25 @@
package com.android.tools.r8.code;
import com.android.tools.r8.dex.Constants;
-import com.android.tools.r8.dex.IndexedItemCollection;
-import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.IndexedDexItem;
import com.android.tools.r8.graph.ObjectToOffsetMapping;
import com.android.tools.r8.naming.ClassNameMapper;
import java.nio.ShortBuffer;
import java.util.function.BiPredicate;
-abstract class Format21c extends Base2Format {
+abstract class Format21c<T extends IndexedDexItem> extends Base2Format {
public final short AA;
- public IndexedDexItem BBBB;
+ public T BBBB;
// AA | op | [type|field|string]@BBBB
- Format21c(int high, BytecodeStream stream, IndexedDexItem[] map) {
+ Format21c(int high, BytecodeStream stream, T[] map) {
super(stream);
AA = (short) high;
BBBB = map[read16BitValue(stream)];
}
- protected Format21c(int AA, IndexedDexItem BBBB) {
+ protected Format21c(int AA, T BBBB) {
assert 0 <= AA && AA <= Constants.U8BIT_MAX;
this.AA = (short) AA;
this.BBBB = BBBB;
@@ -46,7 +44,7 @@
if (other == null || this.getClass() != other.getClass()) {
return false;
}
- Format21c o = (Format21c) other;
+ Format21c<?> o = (Format21c<?>) other;
return o.AA == AA && o.BBBB.equals(BBBB);
}
@@ -63,17 +61,11 @@
}
@Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
- BBBB.collectIndexedItems(indexedItems, method, instructionOffset);
- }
-
- @Override
public boolean equals(Instruction other, BiPredicate<IndexedDexItem, IndexedDexItem> equality) {
if (other == null || this.getClass() != other.getClass()) {
return false;
}
- Format21c o = (Format21c) other;
+ Format21c<?> o = (Format21c<?>) other;
return o.AA == AA && equality.test(BBBB, o.BBBB);
}
}
diff --git a/src/main/java/com/android/tools/r8/code/Format21h.java b/src/main/java/com/android/tools/r8/code/Format21h.java
index 074a0a0..221dc9e 100644
--- a/src/main/java/com/android/tools/r8/code/Format21h.java
+++ b/src/main/java/com/android/tools/r8/code/Format21h.java
@@ -5,7 +5,6 @@
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.dex.IndexedItemCollection;
-import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.ObjectToOffsetMapping;
import java.nio.ShortBuffer;
@@ -49,8 +48,7 @@
}
@Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
// No references.
}
}
diff --git a/src/main/java/com/android/tools/r8/code/Format21s.java b/src/main/java/com/android/tools/r8/code/Format21s.java
index 48f457c..a9d7dc1 100644
--- a/src/main/java/com/android/tools/r8/code/Format21s.java
+++ b/src/main/java/com/android/tools/r8/code/Format21s.java
@@ -5,7 +5,6 @@
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.dex.IndexedItemCollection;
-import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.ObjectToOffsetMapping;
import com.android.tools.r8.naming.ClassNameMapper;
import com.android.tools.r8.utils.StringUtils;
@@ -61,8 +60,7 @@
}
@Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
// No references.
}
}
diff --git a/src/main/java/com/android/tools/r8/code/Format21t.java b/src/main/java/com/android/tools/r8/code/Format21t.java
index 7266a6a..d89b029 100644
--- a/src/main/java/com/android/tools/r8/code/Format21t.java
+++ b/src/main/java/com/android/tools/r8/code/Format21t.java
@@ -5,7 +5,6 @@
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.dex.IndexedItemCollection;
-import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.ObjectToOffsetMapping;
import com.android.tools.r8.ir.code.If.Type;
import com.android.tools.r8.ir.code.ValueTypeConstraint;
@@ -79,8 +78,7 @@
}
@Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
// No references.
}
}
diff --git a/src/main/java/com/android/tools/r8/code/Format22b.java b/src/main/java/com/android/tools/r8/code/Format22b.java
index 86a51b6..3952eb7 100644
--- a/src/main/java/com/android/tools/r8/code/Format22b.java
+++ b/src/main/java/com/android/tools/r8/code/Format22b.java
@@ -5,7 +5,6 @@
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.dex.IndexedItemCollection;
-import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.ObjectToOffsetMapping;
import com.android.tools.r8.naming.ClassNameMapper;
import com.android.tools.r8.utils.StringUtils;
@@ -66,8 +65,7 @@
}
@Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
// No references.
}
}
diff --git a/src/main/java/com/android/tools/r8/code/Format22c.java b/src/main/java/com/android/tools/r8/code/Format22c.java
index 16082a4..751ef61 100644
--- a/src/main/java/com/android/tools/r8/code/Format22c.java
+++ b/src/main/java/com/android/tools/r8/code/Format22c.java
@@ -4,29 +4,27 @@
package com.android.tools.r8.code;
import com.android.tools.r8.dex.Constants;
-import com.android.tools.r8.dex.IndexedItemCollection;
-import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.IndexedDexItem;
import com.android.tools.r8.graph.ObjectToOffsetMapping;
import com.android.tools.r8.naming.ClassNameMapper;
import java.nio.ShortBuffer;
import java.util.function.BiPredicate;
-public abstract class Format22c extends Base2Format {
+public abstract class Format22c<T extends IndexedDexItem> extends Base2Format {
public final byte A;
public final byte B;
- public IndexedDexItem CCCC;
+ public T CCCC;
// vB | vA | op | [type|field]@CCCC
- /*package*/ Format22c(int high, BytecodeStream stream, IndexedDexItem[] map) {
+ /*package*/ Format22c(int high, BytecodeStream stream, T[] map) {
super(stream);
A = (byte) (high & 0xf);
B = (byte) ((high >> 4) & 0xf);
CCCC = map[read16BitValue(stream)];
}
- /*package*/ Format22c(int A, int B, IndexedDexItem CCCC) {
+ /*package*/ Format22c(int A, int B, T CCCC) {
assert 0 <= A && A <= Constants.U4BIT_MAX;
assert 0 <= B && B <= Constants.U4BIT_MAX;
this.A = (byte) A;
@@ -50,7 +48,7 @@
if (other == null || this.getClass() != other.getClass()) {
return false;
}
- Format22c o = (Format22c) other;
+ Format22c<?> o = (Format22c<?>) other;
return o.A == A && o.B == B && o.CCCC.equals(CCCC);
}
@@ -67,17 +65,11 @@
}
@Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
- CCCC.collectIndexedItems(indexedItems, method, instructionOffset);
- }
-
- @Override
public boolean equals(Instruction other, BiPredicate<IndexedDexItem, IndexedDexItem> equality) {
if (other == null || this.getClass() != other.getClass()) {
return false;
}
- Format22c o = (Format22c) other;
+ Format22c<?> o = (Format22c<?>) other;
return o.A == A && o.B == B && equality.test(CCCC, o.CCCC);
}
}
diff --git a/src/main/java/com/android/tools/r8/code/Format22s.java b/src/main/java/com/android/tools/r8/code/Format22s.java
index 9666b21..25c51d6 100644
--- a/src/main/java/com/android/tools/r8/code/Format22s.java
+++ b/src/main/java/com/android/tools/r8/code/Format22s.java
@@ -5,7 +5,6 @@
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.dex.IndexedItemCollection;
-import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.ObjectToOffsetMapping;
import com.android.tools.r8.naming.ClassNameMapper;
import com.android.tools.r8.utils.StringUtils;
@@ -66,8 +65,7 @@
}
@Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
// No references.
}
}
diff --git a/src/main/java/com/android/tools/r8/code/Format22t.java b/src/main/java/com/android/tools/r8/code/Format22t.java
index 66e5df1..6505e5c 100644
--- a/src/main/java/com/android/tools/r8/code/Format22t.java
+++ b/src/main/java/com/android/tools/r8/code/Format22t.java
@@ -5,7 +5,6 @@
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.dex.IndexedItemCollection;
-import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.ObjectToOffsetMapping;
import com.android.tools.r8.ir.code.If.Type;
import com.android.tools.r8.ir.code.ValueTypeConstraint;
@@ -83,8 +82,7 @@
}
@Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
// No references.
}
}
diff --git a/src/main/java/com/android/tools/r8/code/Format22x.java b/src/main/java/com/android/tools/r8/code/Format22x.java
index d30f023..5c1b2c4 100644
--- a/src/main/java/com/android/tools/r8/code/Format22x.java
+++ b/src/main/java/com/android/tools/r8/code/Format22x.java
@@ -5,7 +5,6 @@
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.dex.IndexedItemCollection;
-import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.ObjectToOffsetMapping;
import com.android.tools.r8.naming.ClassNameMapper;
import java.nio.ShortBuffer;
@@ -60,8 +59,7 @@
}
@Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
// No references.
}
}
diff --git a/src/main/java/com/android/tools/r8/code/Format23x.java b/src/main/java/com/android/tools/r8/code/Format23x.java
index 02722db..739b66f 100644
--- a/src/main/java/com/android/tools/r8/code/Format23x.java
+++ b/src/main/java/com/android/tools/r8/code/Format23x.java
@@ -5,7 +5,6 @@
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.dex.IndexedItemCollection;
-import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.ObjectToOffsetMapping;
import com.android.tools.r8.naming.ClassNameMapper;
import java.nio.ShortBuffer;
@@ -64,8 +63,7 @@
}
@Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
// No references.
}
}
diff --git a/src/main/java/com/android/tools/r8/code/Format30t.java b/src/main/java/com/android/tools/r8/code/Format30t.java
index 5ef18eb..bfcf0d3 100644
--- a/src/main/java/com/android/tools/r8/code/Format30t.java
+++ b/src/main/java/com/android/tools/r8/code/Format30t.java
@@ -4,7 +4,6 @@
package com.android.tools.r8.code;
import com.android.tools.r8.dex.IndexedItemCollection;
-import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.ObjectToOffsetMapping;
import com.android.tools.r8.naming.ClassNameMapper;
import java.nio.ShortBuffer;
@@ -53,8 +52,7 @@
}
@Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
// No references.
}
}
diff --git a/src/main/java/com/android/tools/r8/code/Format31c.java b/src/main/java/com/android/tools/r8/code/Format31c.java
index 3019b9b..ead4920 100644
--- a/src/main/java/com/android/tools/r8/code/Format31c.java
+++ b/src/main/java/com/android/tools/r8/code/Format31c.java
@@ -6,7 +6,6 @@
import static com.android.tools.r8.dex.Constants.U8BIT_MAX;
import com.android.tools.r8.dex.IndexedItemCollection;
-import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.IndexedDexItem;
import com.android.tools.r8.graph.ObjectToOffsetMapping;
@@ -59,9 +58,8 @@
}
@Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
- BBBBBBBB.collectIndexedItems(indexedItems, method, instructionOffset);
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
+ BBBBBBBB.collectIndexedItems(indexedItems);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/code/Format31i.java b/src/main/java/com/android/tools/r8/code/Format31i.java
index 192b28d..5e55ca4 100644
--- a/src/main/java/com/android/tools/r8/code/Format31i.java
+++ b/src/main/java/com/android/tools/r8/code/Format31i.java
@@ -5,7 +5,6 @@
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.dex.IndexedItemCollection;
-import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.ObjectToOffsetMapping;
import com.android.tools.r8.naming.ClassNameMapper;
import java.nio.ShortBuffer;
@@ -54,8 +53,7 @@
}
@Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
// No references.
}
}
diff --git a/src/main/java/com/android/tools/r8/code/Format31t.java b/src/main/java/com/android/tools/r8/code/Format31t.java
index 19de81f..d650fed 100644
--- a/src/main/java/com/android/tools/r8/code/Format31t.java
+++ b/src/main/java/com/android/tools/r8/code/Format31t.java
@@ -5,7 +5,6 @@
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.dex.IndexedItemCollection;
-import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.ObjectToOffsetMapping;
import com.android.tools.r8.naming.ClassNameMapper;
import java.nio.ShortBuffer;
@@ -69,8 +68,7 @@
}
@Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
// No references.
}
}
diff --git a/src/main/java/com/android/tools/r8/code/Format32x.java b/src/main/java/com/android/tools/r8/code/Format32x.java
index 4c70702..a31a494 100644
--- a/src/main/java/com/android/tools/r8/code/Format32x.java
+++ b/src/main/java/com/android/tools/r8/code/Format32x.java
@@ -6,7 +6,6 @@
import static com.android.tools.r8.dex.Constants.U16BIT_MAX;
import com.android.tools.r8.dex.IndexedItemCollection;
-import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.ObjectToOffsetMapping;
import com.android.tools.r8.naming.ClassNameMapper;
import java.nio.ShortBuffer;
@@ -62,8 +61,7 @@
}
@Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
// No references.
}
}
diff --git a/src/main/java/com/android/tools/r8/code/Format35c.java b/src/main/java/com/android/tools/r8/code/Format35c.java
index f8c68c3..fba7d0d 100644
--- a/src/main/java/com/android/tools/r8/code/Format35c.java
+++ b/src/main/java/com/android/tools/r8/code/Format35c.java
@@ -4,15 +4,13 @@
package com.android.tools.r8.code;
import com.android.tools.r8.dex.Constants;
-import com.android.tools.r8.dex.IndexedItemCollection;
-import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.IndexedDexItem;
import com.android.tools.r8.graph.ObjectToOffsetMapping;
import com.android.tools.r8.naming.ClassNameMapper;
import java.nio.ShortBuffer;
import java.util.function.BiPredicate;
-public abstract class Format35c extends Base3Format {
+public abstract class Format35c<T extends IndexedDexItem> extends Base3Format {
public final byte A;
public final byte C;
@@ -20,10 +18,10 @@
public final byte E;
public final byte F;
public final byte G;
- public IndexedDexItem BBBB;
+ public T BBBB;
// A | G | op | BBBB | F | E | D | C
- Format35c(int high, BytecodeStream stream, IndexedDexItem[] map) {
+ Format35c(int high, BytecodeStream stream, T[] map) {
super(stream);
G = (byte) (high & 0xf);
A = (byte) ((high >> 4) & 0xf);
@@ -36,7 +34,7 @@
D = (byte) ((next >> 4) & 0xf);
}
- protected Format35c(int A, IndexedDexItem BBBB, int C, int D, int E, int F, int G) {
+ Format35c(int A, T BBBB, int C, int D, int E, int F, int G) {
assert 0 <= A && A <= Constants.U4BIT_MAX;
assert 0 <= C && C <= Constants.U4BIT_MAX;
assert 0 <= D && D <= Constants.U4BIT_MAX;
@@ -111,12 +109,6 @@
}
@Override
- public void collectIndexedItems(
- IndexedItemCollection indexedItems, DexMethod method, int instructionOffset) {
- BBBB.collectIndexedItems(indexedItems, method, instructionOffset);
- }
-
- @Override
public boolean equals(Instruction other, BiPredicate<IndexedDexItem, IndexedDexItem> equality) {
if (other == null || (this.getClass() != other.getClass())) {
return false;
diff --git a/src/main/java/com/android/tools/r8/code/Format3rc.java b/src/main/java/com/android/tools/r8/code/Format3rc.java
index 77d3571..a50a9d9 100644
--- a/src/main/java/com/android/tools/r8/code/Format3rc.java
+++ b/src/main/java/com/android/tools/r8/code/Format3rc.java
@@ -4,29 +4,27 @@
package com.android.tools.r8.code;
import com.android.tools.r8.dex.Constants;
-import com.android.tools.r8.dex.IndexedItemCollection;
-import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.IndexedDexItem;
import com.android.tools.r8.graph.ObjectToOffsetMapping;
import com.android.tools.r8.naming.ClassNameMapper;
import java.nio.ShortBuffer;
import java.util.function.BiPredicate;
-public abstract class Format3rc extends Base3Format {
+public abstract class Format3rc<T extends IndexedDexItem> extends Base3Format {
public final short AA;
public final char CCCC;
- public IndexedDexItem BBBB;
+ public T BBBB;
// AA | op | [meth|type]@BBBBB | CCCC
- Format3rc(int high, BytecodeStream stream, IndexedDexItem[] map) {
+ Format3rc(int high, BytecodeStream stream, T[] map) {
super(stream);
this.AA = (short) high;
this.BBBB = map[read16BitValue(stream)];
this.CCCC = read16BitValue(stream);
}
- Format3rc(int firstArgumentRegister, int argumentCount, IndexedDexItem dexItem) {
+ Format3rc(int firstArgumentRegister, int argumentCount, T dexItem) {
assert 0 <= firstArgumentRegister && firstArgumentRegister <= Constants.U16BIT_MAX;
assert 0 <= argumentCount && argumentCount <= Constants.U8BIT_MAX;
this.CCCC = (char) firstArgumentRegister;
@@ -34,6 +32,10 @@
BBBB = dexItem;
}
+ public T getItem() {
+ return BBBB;
+ }
+
@Override
public void write(ShortBuffer dest, ObjectToOffsetMapping mapping) {
writeFirst(AA, dest);
@@ -51,7 +53,7 @@
if (other == null || (this.getClass() != other.getClass())) {
return false;
}
- Format3rc o = (Format3rc) other;
+ Format3rc<?> o = (Format3rc<?>) other;
return o.AA == AA && o.CCCC == CCCC && o.BBBB.equals(BBBB);
}
@@ -89,17 +91,11 @@
}
@Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
- BBBB.collectIndexedItems(indexedItems, method, instructionOffset);
- }
-
- @Override
public boolean equals(Instruction other, BiPredicate<IndexedDexItem, IndexedDexItem> equality) {
if (other == null || (this.getClass() != other.getClass())) {
return false;
}
- Format3rc o = (Format3rc) other;
+ Format3rc<?> o = (Format3rc<?>) other;
return o.AA == AA && o.CCCC == CCCC && equality.test(BBBB, o.BBBB);
}
}
diff --git a/src/main/java/com/android/tools/r8/code/Format45cc.java b/src/main/java/com/android/tools/r8/code/Format45cc.java
index fc88461..f5123cf 100644
--- a/src/main/java/com/android/tools/r8/code/Format45cc.java
+++ b/src/main/java/com/android/tools/r8/code/Format45cc.java
@@ -87,10 +87,9 @@
}
@Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
- BBBB.collectIndexedItems(indexedItems, method, instructionOffset);
- HHHH.collectIndexedItems(indexedItems, method, instructionOffset);
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
+ BBBB.collectIndexedItems(indexedItems);
+ HHHH.collectIndexedItems(indexedItems);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/code/Format4rcc.java b/src/main/java/com/android/tools/r8/code/Format4rcc.java
index c139b03..0ec2780 100644
--- a/src/main/java/com/android/tools/r8/code/Format4rcc.java
+++ b/src/main/java/com/android/tools/r8/code/Format4rcc.java
@@ -93,10 +93,9 @@
}
@Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
- BBBB.collectIndexedItems(indexedItems, method, instructionOffset);
- HHHH.collectIndexedItems(indexedItems, method, instructionOffset);
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
+ BBBB.collectIndexedItems(indexedItems);
+ HHHH.collectIndexedItems(indexedItems);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/code/Format51l.java b/src/main/java/com/android/tools/r8/code/Format51l.java
index 008e724..0e9ad93 100644
--- a/src/main/java/com/android/tools/r8/code/Format51l.java
+++ b/src/main/java/com/android/tools/r8/code/Format51l.java
@@ -5,7 +5,6 @@
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.dex.IndexedItemCollection;
-import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.ObjectToOffsetMapping;
import com.android.tools.r8.naming.ClassNameMapper;
import java.nio.ShortBuffer;
@@ -54,8 +53,7 @@
}
@Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
// No references.
}
}
diff --git a/src/main/java/com/android/tools/r8/code/Iget.java b/src/main/java/com/android/tools/r8/code/Iget.java
index 65ebb44..3625037 100644
--- a/src/main/java/com/android/tools/r8/code/Iget.java
+++ b/src/main/java/com/android/tools/r8/code/Iget.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class Iget extends Format22c {
+public class Iget extends IgetOrIput {
public static final int OPCODE = 0x52;
public static final String NAME = "Iget";
@@ -43,11 +43,6 @@
}
@Override
- public DexField getField() {
- return (DexField) CCCC;
- }
-
- @Override
public void buildIR(IRBuilder builder) {
builder.addInstanceGet(A, B, getField());
}
diff --git a/src/main/java/com/android/tools/r8/code/IgetBoolean.java b/src/main/java/com/android/tools/r8/code/IgetBoolean.java
index 756969c..0df2731 100644
--- a/src/main/java/com/android/tools/r8/code/IgetBoolean.java
+++ b/src/main/java/com/android/tools/r8/code/IgetBoolean.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class IgetBoolean extends Format22c {
+public class IgetBoolean extends IgetOrIput {
public static final int OPCODE = 0x55;
public static final String NAME = "IgetBoolean";
@@ -43,11 +43,6 @@
}
@Override
- public DexField getField() {
- return (DexField) CCCC;
- }
-
- @Override
public void buildIR(IRBuilder builder) {
builder.addInstanceGet(A, B, getField());
}
diff --git a/src/main/java/com/android/tools/r8/code/IgetByte.java b/src/main/java/com/android/tools/r8/code/IgetByte.java
index 56a239a..f3cb157 100644
--- a/src/main/java/com/android/tools/r8/code/IgetByte.java
+++ b/src/main/java/com/android/tools/r8/code/IgetByte.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class IgetByte extends Format22c {
+public class IgetByte extends IgetOrIput {
public static final int OPCODE = 0x56;
public static final String NAME = "IgetByte";
@@ -41,10 +41,6 @@
public void registerUse(UseRegistry registry) {
registry.registerInstanceFieldRead(getField());
}
- @Override
- public DexField getField() {
- return (DexField) CCCC;
- }
@Override
public void buildIR(IRBuilder builder) {
diff --git a/src/main/java/com/android/tools/r8/code/IgetChar.java b/src/main/java/com/android/tools/r8/code/IgetChar.java
index ad9c44e..2c0793c 100644
--- a/src/main/java/com/android/tools/r8/code/IgetChar.java
+++ b/src/main/java/com/android/tools/r8/code/IgetChar.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class IgetChar extends Format22c {
+public class IgetChar extends IgetOrIput {
public static final int OPCODE = 0x57;
public static final String NAME = "IgetChar";
@@ -41,10 +41,6 @@
public void registerUse(UseRegistry registry) {
registry.registerInstanceFieldRead(getField());
}
- @Override
- public DexField getField() {
- return (DexField) CCCC;
- }
@Override
public void buildIR(IRBuilder builder) {
diff --git a/src/main/java/com/android/tools/r8/code/IgetObject.java b/src/main/java/com/android/tools/r8/code/IgetObject.java
index d0c7c00..802409e 100644
--- a/src/main/java/com/android/tools/r8/code/IgetObject.java
+++ b/src/main/java/com/android/tools/r8/code/IgetObject.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class IgetObject extends Format22c {
+public class IgetObject extends IgetOrIput {
public static final int OPCODE = 0x54;
public static final String NAME = "IgetObject";
@@ -38,11 +38,6 @@
}
@Override
- public DexField getField() {
- return (DexField) CCCC;
- }
-
- @Override
public void registerUse(UseRegistry registry) {
registry.registerInstanceFieldRead(getField());
}
diff --git a/src/main/java/com/android/tools/r8/code/IgetOrIput.java b/src/main/java/com/android/tools/r8/code/IgetOrIput.java
new file mode 100644
index 0000000..7800ace
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/code/IgetOrIput.java
@@ -0,0 +1,28 @@
+// Copyright (c) 2016, 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.code;
+
+import com.android.tools.r8.dex.IndexedItemCollection;
+import com.android.tools.r8.graph.DexField;
+
+public abstract class IgetOrIput extends Format22c<DexField> {
+
+ IgetOrIput(int high, BytecodeStream stream, DexField[] map) {
+ super(high, stream, map);
+ }
+
+ IgetOrIput(int A, int B, DexField CCCC) {
+ super(A, B, CCCC);
+ }
+
+ @Override
+ public final void collectIndexedItems(IndexedItemCollection indexedItems) {
+ getField().collectIndexedItems(indexedItems);
+ }
+
+ @Override
+ public final DexField getField() {
+ return CCCC;
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/code/IgetShort.java b/src/main/java/com/android/tools/r8/code/IgetShort.java
index 75a9752..a8ca9a7 100644
--- a/src/main/java/com/android/tools/r8/code/IgetShort.java
+++ b/src/main/java/com/android/tools/r8/code/IgetShort.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class IgetShort extends Format22c {
+public class IgetShort extends IgetOrIput {
public static final int OPCODE = 0x58;
public static final String NAME = "IgetShort";
@@ -38,11 +38,6 @@
}
@Override
- public DexField getField() {
- return (DexField) CCCC;
- }
-
- @Override
public void registerUse(UseRegistry registry) {
registry.registerInstanceFieldRead(getField());
}
diff --git a/src/main/java/com/android/tools/r8/code/IgetWide.java b/src/main/java/com/android/tools/r8/code/IgetWide.java
index 9893911..bd63727 100644
--- a/src/main/java/com/android/tools/r8/code/IgetWide.java
+++ b/src/main/java/com/android/tools/r8/code/IgetWide.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class IgetWide extends Format22c {
+public class IgetWide extends IgetOrIput {
public static final int OPCODE = 0x53;
public static final String NAME = "IgetWide";
@@ -38,11 +38,6 @@
}
@Override
- public DexField getField() {
- return (DexField) CCCC;
- }
-
- @Override
public void registerUse(UseRegistry registry) {
registry.registerInstanceFieldRead(getField());
}
diff --git a/src/main/java/com/android/tools/r8/code/InstanceOf.java b/src/main/java/com/android/tools/r8/code/InstanceOf.java
index 36d7a0b..05a9558 100644
--- a/src/main/java/com/android/tools/r8/code/InstanceOf.java
+++ b/src/main/java/com/android/tools/r8/code/InstanceOf.java
@@ -3,12 +3,13 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.code;
+import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.OffsetToObjectMapping;
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class InstanceOf extends Format22c {
+public class InstanceOf extends Format22c<DexType> {
public static final int OPCODE = 0x20;
public static final String NAME = "InstanceOf";
@@ -48,12 +49,17 @@
}
@Override
- public void registerUse(UseRegistry registry) {
- registry.registerInstanceOf(getType());
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
+ getType().collectIndexedItems(indexedItems);
}
public DexType getType() {
- return (DexType) CCCC;
+ return CCCC;
+ }
+
+ @Override
+ public void registerUse(UseRegistry registry) {
+ registry.registerInstanceOf(getType());
}
@Override
diff --git a/src/main/java/com/android/tools/r8/code/Instruction.java b/src/main/java/com/android/tools/r8/code/Instruction.java
index 9d93b40..d8accd7 100644
--- a/src/main/java/com/android/tools/r8/code/Instruction.java
+++ b/src/main/java/com/android/tools/r8/code/Instruction.java
@@ -24,7 +24,7 @@
public final static int[] NO_TARGETS = null;
public final static int[] EXIT_TARGET = {};
- public int offset;
+ private int offset;
Instruction(BytecodeStream stream) {
// When this constructor is invoked, we have already read 1 ushort from the stream.
@@ -311,8 +311,7 @@
public abstract void write(ShortBuffer buffer, ObjectToOffsetMapping mapping);
- public abstract void collectIndexedItems(
- IndexedItemCollection indexedItems, DexMethod method, int instructionOffset);
+ public abstract void collectIndexedItems(IndexedItemCollection indexedItems);
public boolean equals(Instruction other, BiPredicate<IndexedDexItem, IndexedDexItem> equality) {
// In the default case, there is nothing to substitute.
diff --git a/src/main/java/com/android/tools/r8/code/InvokeCustom.java b/src/main/java/com/android/tools/r8/code/InvokeCustom.java
index 171aef2..72d0adb 100644
--- a/src/main/java/com/android/tools/r8/code/InvokeCustom.java
+++ b/src/main/java/com/android/tools/r8/code/InvokeCustom.java
@@ -3,13 +3,13 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.code;
+import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.graph.DexCallSite;
-import com.android.tools.r8.graph.IndexedDexItem;
import com.android.tools.r8.graph.OffsetToObjectMapping;
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class InvokeCustom extends Format35c {
+public class InvokeCustom extends Format35c<DexCallSite> {
public static final int OPCODE = 0xfc;
public static final String NAME = "InvokeCustom";
@@ -19,7 +19,7 @@
super(high, stream, mapping.getCallSiteMap());
}
- public InvokeCustom(int A, IndexedDexItem BBBB, int C, int D, int E, int F, int G) {
+ public InvokeCustom(int A, DexCallSite BBBB, int C, int D, int E, int F, int G) {
super(A, BBBB, C, D, E, F, G);
}
@@ -39,13 +39,18 @@
}
@Override
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
+ getCallSite().collectIndexedItems(indexedItems);
+ }
+
+ @Override
public void registerUse(UseRegistry registry) {
registry.registerCallSite(getCallSite());
}
@Override
public DexCallSite getCallSite() {
- return (DexCallSite) BBBB;
+ return BBBB;
}
@Override
diff --git a/src/main/java/com/android/tools/r8/code/InvokeCustomRange.java b/src/main/java/com/android/tools/r8/code/InvokeCustomRange.java
index 3aa60fc..ae63c4d 100644
--- a/src/main/java/com/android/tools/r8/code/InvokeCustomRange.java
+++ b/src/main/java/com/android/tools/r8/code/InvokeCustomRange.java
@@ -3,12 +3,13 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.code;
+import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.graph.DexCallSite;
import com.android.tools.r8.graph.OffsetToObjectMapping;
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class InvokeCustomRange extends Format3rc {
+public class InvokeCustomRange extends Format3rc<DexCallSite> {
public static final int OPCODE = 0xfd;
public static final String NAME = "InvokeCustomRange";
@@ -38,8 +39,13 @@
}
@Override
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
+ getCallSite().collectIndexedItems(indexedItems);
+ }
+
+ @Override
public DexCallSite getCallSite() {
- return (DexCallSite) BBBB;
+ return BBBB;
}
@Override
diff --git a/src/main/java/com/android/tools/r8/code/InvokeDirect.java b/src/main/java/com/android/tools/r8/code/InvokeDirect.java
index 08d6826..cd8c1b7 100644
--- a/src/main/java/com/android/tools/r8/code/InvokeDirect.java
+++ b/src/main/java/com/android/tools/r8/code/InvokeDirect.java
@@ -4,13 +4,12 @@
package com.android.tools.r8.code;
import com.android.tools.r8.graph.DexMethod;
-import com.android.tools.r8.graph.IndexedDexItem;
import com.android.tools.r8.graph.OffsetToObjectMapping;
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.code.Invoke.Type;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class InvokeDirect extends Format35c {
+public class InvokeDirect extends InvokeMethod {
public static final int OPCODE = 0x70;
public static final String NAME = "InvokeDirect";
@@ -20,7 +19,7 @@
super(high, stream, mapping.getMethodMap());
}
- public InvokeDirect(int A, IndexedDexItem BBBB, int C, int D, int E, int F, int G) {
+ public InvokeDirect(int A, DexMethod BBBB, int C, int D, int E, int F, int G) {
super(A, BBBB, C, D, E, F, G);
}
@@ -45,11 +44,6 @@
}
@Override
- public DexMethod getMethod() {
- return (DexMethod) BBBB;
- }
-
- @Override
public void buildIR(IRBuilder builder) {
builder.addInvokeRegisters(Type.DIRECT, getMethod(), getProto(), A, new int[]{C, D, E, F, G});
}
diff --git a/src/main/java/com/android/tools/r8/code/InvokeDirectRange.java b/src/main/java/com/android/tools/r8/code/InvokeDirectRange.java
index 8f72a2b..41070dd 100644
--- a/src/main/java/com/android/tools/r8/code/InvokeDirectRange.java
+++ b/src/main/java/com/android/tools/r8/code/InvokeDirectRange.java
@@ -9,7 +9,7 @@
import com.android.tools.r8.ir.code.Invoke.Type;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class InvokeDirectRange extends Format3rc {
+public class InvokeDirectRange extends InvokeMethodRange {
public static final int OPCODE = 0x76;
public static final String NAME = "InvokeDirectRange";
@@ -39,11 +39,6 @@
}
@Override
- public DexMethod getMethod() {
- return (DexMethod) BBBB;
- }
-
- @Override
public void registerUse(UseRegistry registry) {
registry.registerInvokeDirect(getMethod());
}
diff --git a/src/main/java/com/android/tools/r8/code/InvokeInterface.java b/src/main/java/com/android/tools/r8/code/InvokeInterface.java
index b98af41..3e172e2 100644
--- a/src/main/java/com/android/tools/r8/code/InvokeInterface.java
+++ b/src/main/java/com/android/tools/r8/code/InvokeInterface.java
@@ -4,13 +4,12 @@
package com.android.tools.r8.code;
import com.android.tools.r8.graph.DexMethod;
-import com.android.tools.r8.graph.IndexedDexItem;
import com.android.tools.r8.graph.OffsetToObjectMapping;
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.code.Invoke.Type;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class InvokeInterface extends Format35c {
+public class InvokeInterface extends InvokeMethod {
public static final int OPCODE = 0x72;
public static final String NAME = "InvokeInterface";
@@ -20,7 +19,7 @@
super(high, stream, mapping.getMethodMap());
}
- public InvokeInterface(int A, IndexedDexItem BBBB, int C, int D, int E, int F, int G) {
+ public InvokeInterface(int A, DexMethod BBBB, int C, int D, int E, int F, int G) {
super(A, BBBB, C, D, E, F, G);
}
@@ -45,11 +44,6 @@
}
@Override
- public DexMethod getMethod() {
- return (DexMethod) BBBB;
- }
-
- @Override
public void buildIR(IRBuilder builder) {
builder.addInvokeRegisters(
Type.INTERFACE, getMethod(), getProto(), A, new int[] {C, D, E, F, G});
diff --git a/src/main/java/com/android/tools/r8/code/InvokeInterfaceRange.java b/src/main/java/com/android/tools/r8/code/InvokeInterfaceRange.java
index e4d63b4..2d1986c 100644
--- a/src/main/java/com/android/tools/r8/code/InvokeInterfaceRange.java
+++ b/src/main/java/com/android/tools/r8/code/InvokeInterfaceRange.java
@@ -9,7 +9,7 @@
import com.android.tools.r8.ir.code.Invoke.Type;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class InvokeInterfaceRange extends Format3rc {
+public class InvokeInterfaceRange extends InvokeMethodRange {
public static final int OPCODE = 0x78;
public static final String NAME = "InvokeInterfaceRange";
@@ -44,11 +44,6 @@
}
@Override
- public DexMethod getMethod() {
- return (DexMethod) BBBB;
- }
-
- @Override
public void buildIR(IRBuilder builder) {
builder.addInvokeRange(Type.INTERFACE, getMethod(), getProto(), AA, CCCC);
}
diff --git a/src/main/java/com/android/tools/r8/code/InvokeMethod.java b/src/main/java/com/android/tools/r8/code/InvokeMethod.java
new file mode 100644
index 0000000..cab1eac
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/code/InvokeMethod.java
@@ -0,0 +1,28 @@
+// Copyright (c) 2016, 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.code;
+
+import com.android.tools.r8.dex.IndexedItemCollection;
+import com.android.tools.r8.graph.DexMethod;
+
+public abstract class InvokeMethod extends Format35c<DexMethod> {
+
+ InvokeMethod(int high, BytecodeStream stream, DexMethod[] map) {
+ super(high, stream, map);
+ }
+
+ InvokeMethod(int A, DexMethod BBBB, int C, int D, int E, int F, int G) {
+ super(A, BBBB, C, D, E, F, G);
+ }
+
+ @Override
+ public final void collectIndexedItems(IndexedItemCollection indexedItems) {
+ getMethod().collectIndexedItems(indexedItems);
+ }
+
+ @Override
+ public final DexMethod getMethod() {
+ return BBBB;
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/code/InvokeMethodRange.java b/src/main/java/com/android/tools/r8/code/InvokeMethodRange.java
new file mode 100644
index 0000000..25fad42
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/code/InvokeMethodRange.java
@@ -0,0 +1,28 @@
+// Copyright (c) 2016, 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.code;
+
+import com.android.tools.r8.dex.IndexedItemCollection;
+import com.android.tools.r8.graph.DexMethod;
+
+public abstract class InvokeMethodRange extends Format3rc<DexMethod> {
+
+ InvokeMethodRange(int high, BytecodeStream stream, DexMethod[] map) {
+ super(high, stream, map);
+ }
+
+ InvokeMethodRange(int firstArgumentRegister, int argumentCount, DexMethod dexItem) {
+ super(firstArgumentRegister, argumentCount, dexItem);
+ }
+
+ @Override
+ public final void collectIndexedItems(IndexedItemCollection indexedItems) {
+ getMethod().collectIndexedItems(indexedItems);
+ }
+
+ @Override
+ public final DexMethod getMethod() {
+ return BBBB;
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/code/InvokeStatic.java b/src/main/java/com/android/tools/r8/code/InvokeStatic.java
index 73cb887..531105b 100644
--- a/src/main/java/com/android/tools/r8/code/InvokeStatic.java
+++ b/src/main/java/com/android/tools/r8/code/InvokeStatic.java
@@ -9,7 +9,7 @@
import com.android.tools.r8.ir.code.Invoke.Type;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class InvokeStatic extends Format35c {
+public class InvokeStatic extends InvokeMethod {
public static final int OPCODE = 0x71;
public static final String NAME = "InvokeStatic";
@@ -44,11 +44,6 @@
}
@Override
- public DexMethod getMethod() {
- return (DexMethod) BBBB;
- }
-
- @Override
public void buildIR(IRBuilder builder) {
builder.addInvokeRegisters(Type.STATIC, getMethod(), getProto(), A, new int[]{C, D, E, F, G});
}
diff --git a/src/main/java/com/android/tools/r8/code/InvokeStaticRange.java b/src/main/java/com/android/tools/r8/code/InvokeStaticRange.java
index 6fd3f42..7d3ff3d 100644
--- a/src/main/java/com/android/tools/r8/code/InvokeStaticRange.java
+++ b/src/main/java/com/android/tools/r8/code/InvokeStaticRange.java
@@ -9,7 +9,7 @@
import com.android.tools.r8.ir.code.Invoke.Type;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class InvokeStaticRange extends Format3rc {
+public class InvokeStaticRange extends InvokeMethodRange {
public static final int OPCODE = 0x77;
public static final String NAME = "InvokeStaticRange";
@@ -44,11 +44,6 @@
}
@Override
- public DexMethod getMethod() {
- return (DexMethod) BBBB;
- }
-
- @Override
public void buildIR(IRBuilder builder) {
builder.addInvokeRange(Type.STATIC, getMethod(), getProto(), AA, CCCC);
}
diff --git a/src/main/java/com/android/tools/r8/code/InvokeSuper.java b/src/main/java/com/android/tools/r8/code/InvokeSuper.java
index 9575ed9..1dc8ac6 100644
--- a/src/main/java/com/android/tools/r8/code/InvokeSuper.java
+++ b/src/main/java/com/android/tools/r8/code/InvokeSuper.java
@@ -4,13 +4,12 @@
package com.android.tools.r8.code;
import com.android.tools.r8.graph.DexMethod;
-import com.android.tools.r8.graph.IndexedDexItem;
import com.android.tools.r8.graph.OffsetToObjectMapping;
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.code.Invoke.Type;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class InvokeSuper extends Format35c {
+public class InvokeSuper extends InvokeMethod {
public static final int OPCODE = 0x6f;
public static final String NAME = "InvokeSuper";
@@ -20,7 +19,7 @@
super(high, stream, mapping.getMethodMap());
}
- public InvokeSuper(int A, IndexedDexItem BBBB, int C, int D, int E, int F, int G) {
+ public InvokeSuper(int A, DexMethod BBBB, int C, int D, int E, int F, int G) {
super(A, BBBB, C, D, E, F, G);
}
@@ -45,11 +44,6 @@
}
@Override
- public DexMethod getMethod() {
- return (DexMethod) BBBB;
- }
-
- @Override
public void buildIR(IRBuilder builder) {
builder.addInvokeRegisters(Type.SUPER, getMethod(), getProto(), A, new int[]{C, D, E, F, G});
}
diff --git a/src/main/java/com/android/tools/r8/code/InvokeSuperRange.java b/src/main/java/com/android/tools/r8/code/InvokeSuperRange.java
index 63c6318..af6ebe8 100644
--- a/src/main/java/com/android/tools/r8/code/InvokeSuperRange.java
+++ b/src/main/java/com/android/tools/r8/code/InvokeSuperRange.java
@@ -9,7 +9,7 @@
import com.android.tools.r8.ir.code.Invoke.Type;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class InvokeSuperRange extends Format3rc {
+public class InvokeSuperRange extends InvokeMethodRange {
public static final int OPCODE = 0x75;
public static final String NAME = "InvokeSuperRange";
@@ -44,11 +44,6 @@
}
@Override
- public DexMethod getMethod() {
- return (DexMethod) BBBB;
- }
-
- @Override
public void buildIR(IRBuilder builder) {
builder.addInvokeRange(Type.SUPER, getMethod(), getProto(), AA, CCCC);
}
diff --git a/src/main/java/com/android/tools/r8/code/InvokeVirtual.java b/src/main/java/com/android/tools/r8/code/InvokeVirtual.java
index b35882b..17596a4 100644
--- a/src/main/java/com/android/tools/r8/code/InvokeVirtual.java
+++ b/src/main/java/com/android/tools/r8/code/InvokeVirtual.java
@@ -9,7 +9,7 @@
import com.android.tools.r8.ir.code.Invoke.Type;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class InvokeVirtual extends Format35c {
+public class InvokeVirtual extends InvokeMethod {
public static final int OPCODE = 0x6e;
public static final String NAME = "InvokeVirtual";
@@ -54,11 +54,6 @@
}
@Override
- public DexMethod getMethod() {
- return (DexMethod) BBBB;
- }
-
- @Override
public void buildIR(IRBuilder builder) {
builder.addInvokeRegisters(Type.VIRTUAL, getMethod(), getProto(), A, new int[]{C, D, E, F, G});
}
diff --git a/src/main/java/com/android/tools/r8/code/InvokeVirtualRange.java b/src/main/java/com/android/tools/r8/code/InvokeVirtualRange.java
index cd78458..c2a0d6c 100644
--- a/src/main/java/com/android/tools/r8/code/InvokeVirtualRange.java
+++ b/src/main/java/com/android/tools/r8/code/InvokeVirtualRange.java
@@ -9,7 +9,7 @@
import com.android.tools.r8.ir.code.Invoke.Type;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class InvokeVirtualRange extends Format3rc {
+public class InvokeVirtualRange extends InvokeMethodRange {
public static final int OPCODE = 0x74;
public static final String NAME = "InvokeVirtualRange";
@@ -54,11 +54,6 @@
}
@Override
- public DexMethod getMethod() {
- return (DexMethod) BBBB;
- }
-
- @Override
public void buildIR(IRBuilder builder) {
builder.addInvokeRange(Type.VIRTUAL, getMethod(), getProto(), AA, CCCC);
}
diff --git a/src/main/java/com/android/tools/r8/code/Iput.java b/src/main/java/com/android/tools/r8/code/Iput.java
index eabfb2b..ea170c7 100644
--- a/src/main/java/com/android/tools/r8/code/Iput.java
+++ b/src/main/java/com/android/tools/r8/code/Iput.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class Iput extends Format22c {
+public class Iput extends IgetOrIput {
public static final int OPCODE = 0x59;
public static final String NAME = "Iput";
@@ -43,11 +43,6 @@
}
@Override
- public DexField getField() {
- return (DexField) CCCC;
- }
-
- @Override
public void buildIR(IRBuilder builder) {
builder.addInstancePut(A, B, getField());
}
diff --git a/src/main/java/com/android/tools/r8/code/IputBoolean.java b/src/main/java/com/android/tools/r8/code/IputBoolean.java
index 6276441..8a992c7 100644
--- a/src/main/java/com/android/tools/r8/code/IputBoolean.java
+++ b/src/main/java/com/android/tools/r8/code/IputBoolean.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class IputBoolean extends Format22c {
+public class IputBoolean extends IgetOrIput {
public static final int OPCODE = 0x5c;
public static final String NAME = "IputBoolean";
@@ -43,11 +43,6 @@
}
@Override
- public DexField getField() {
- return (DexField) CCCC;
- }
-
- @Override
public void buildIR(IRBuilder builder) {
builder.addInstancePut(A, B, getField());
}
diff --git a/src/main/java/com/android/tools/r8/code/IputByte.java b/src/main/java/com/android/tools/r8/code/IputByte.java
index e333a9f..4005875 100644
--- a/src/main/java/com/android/tools/r8/code/IputByte.java
+++ b/src/main/java/com/android/tools/r8/code/IputByte.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class IputByte extends Format22c {
+public class IputByte extends IgetOrIput {
public static final int OPCODE = 0x5d;
public static final String NAME = "IputByte";
@@ -43,11 +43,6 @@
}
@Override
- public DexField getField() {
- return (DexField) CCCC;
- }
-
- @Override
public void buildIR(IRBuilder builder) {
builder.addInstancePut(A, B, getField());
}
diff --git a/src/main/java/com/android/tools/r8/code/IputChar.java b/src/main/java/com/android/tools/r8/code/IputChar.java
index f4902ee..55f72fe 100644
--- a/src/main/java/com/android/tools/r8/code/IputChar.java
+++ b/src/main/java/com/android/tools/r8/code/IputChar.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class IputChar extends Format22c {
+public class IputChar extends IgetOrIput {
public static final int OPCODE = 0x5e;
public static final String NAME = "IputChar";
@@ -43,11 +43,6 @@
}
@Override
- public DexField getField() {
- return (DexField) CCCC;
- }
-
- @Override
public void buildIR(IRBuilder builder) {
builder.addInstancePut(A, B, getField());
}
diff --git a/src/main/java/com/android/tools/r8/code/IputObject.java b/src/main/java/com/android/tools/r8/code/IputObject.java
index 7532340..5ca2f90 100644
--- a/src/main/java/com/android/tools/r8/code/IputObject.java
+++ b/src/main/java/com/android/tools/r8/code/IputObject.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class IputObject extends Format22c {
+public class IputObject extends IgetOrIput {
public static final int OPCODE = 0x5b;
public static final String NAME = "IputObject";
@@ -43,11 +43,6 @@
}
@Override
- public DexField getField() {
- return (DexField) CCCC;
- }
-
- @Override
public void buildIR(IRBuilder builder) {
builder.addInstancePut(A, B, getField());
}
diff --git a/src/main/java/com/android/tools/r8/code/IputShort.java b/src/main/java/com/android/tools/r8/code/IputShort.java
index f0d4308..bf41801 100644
--- a/src/main/java/com/android/tools/r8/code/IputShort.java
+++ b/src/main/java/com/android/tools/r8/code/IputShort.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class IputShort extends Format22c {
+public class IputShort extends IgetOrIput {
public static final int OPCODE = 0x5f;
public static final String NAME = "IputShort";
@@ -43,11 +43,6 @@
}
@Override
- public DexField getField() {
- return (DexField) CCCC;
- }
-
- @Override
public void buildIR(IRBuilder builder) {
builder.addInstancePut(A, B, getField());
}
diff --git a/src/main/java/com/android/tools/r8/code/IputWide.java b/src/main/java/com/android/tools/r8/code/IputWide.java
index 68d09a6..4462875 100644
--- a/src/main/java/com/android/tools/r8/code/IputWide.java
+++ b/src/main/java/com/android/tools/r8/code/IputWide.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class IputWide extends Format22c {
+public class IputWide extends IgetOrIput {
public static final int OPCODE = 0x5a;
public static final String NAME = "IputWide";
@@ -43,11 +43,6 @@
}
@Override
- public DexField getField() {
- return (DexField) CCCC;
- }
-
- @Override
public void buildIR(IRBuilder builder) {
builder.addInstancePut(A, B, getField());
}
diff --git a/src/main/java/com/android/tools/r8/code/NewArray.java b/src/main/java/com/android/tools/r8/code/NewArray.java
index 0cce39f..dfb4ccb 100644
--- a/src/main/java/com/android/tools/r8/code/NewArray.java
+++ b/src/main/java/com/android/tools/r8/code/NewArray.java
@@ -3,12 +3,13 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.code;
+import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.OffsetToObjectMapping;
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class NewArray extends Format22c {
+public class NewArray extends Format22c<DexType> {
public static final int OPCODE = 0x23;
public static final String NAME = "NewArray";
@@ -38,12 +39,17 @@
}
@Override
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
+ getType().collectIndexedItems(indexedItems);
+ }
+
+ @Override
public void registerUse(UseRegistry registry) {
registry.registerTypeReference(getType());
}
public DexType getType() {
- return (DexType) CCCC;
+ return CCCC;
}
@Override
diff --git a/src/main/java/com/android/tools/r8/code/NewInstance.java b/src/main/java/com/android/tools/r8/code/NewInstance.java
index 31b8f68..695ae96 100644
--- a/src/main/java/com/android/tools/r8/code/NewInstance.java
+++ b/src/main/java/com/android/tools/r8/code/NewInstance.java
@@ -3,12 +3,13 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.code;
+import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.OffsetToObjectMapping;
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class NewInstance extends Format21c {
+public class NewInstance extends Format21c<DexType> {
public static final int OPCODE = 0x22;
public static final String NAME = "NewInstance";
@@ -38,6 +39,11 @@
}
@Override
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
+ getType().collectIndexedItems(indexedItems);
+ }
+
+ @Override
public void registerUse(UseRegistry registry) {
registry.registerNewInstance(getType());
}
diff --git a/src/main/java/com/android/tools/r8/code/Sget.java b/src/main/java/com/android/tools/r8/code/Sget.java
index 3347fdd..0c727ac 100644
--- a/src/main/java/com/android/tools/r8/code/Sget.java
+++ b/src/main/java/com/android/tools/r8/code/Sget.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class Sget extends Format21c {
+public class Sget extends SgetOrSput {
public static final int OPCODE = 0x60;
public static final String NAME = "Sget";
@@ -43,11 +43,6 @@
}
@Override
- public DexField getField() {
- return (DexField) BBBB;
- }
-
- @Override
public void buildIR(IRBuilder builder) {
builder.addStaticGet(AA, getField());
}
diff --git a/src/main/java/com/android/tools/r8/code/SgetBoolean.java b/src/main/java/com/android/tools/r8/code/SgetBoolean.java
index 27f18f2..3efb6b1 100644
--- a/src/main/java/com/android/tools/r8/code/SgetBoolean.java
+++ b/src/main/java/com/android/tools/r8/code/SgetBoolean.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class SgetBoolean extends Format21c {
+public class SgetBoolean extends SgetOrSput {
public static final int OPCODE = 0x63;
public static final String NAME = "SgetBoolean";
@@ -43,11 +43,6 @@
}
@Override
- public DexField getField() {
- return (DexField) BBBB;
- }
-
- @Override
public void buildIR(IRBuilder builder) {
builder.addStaticGet(AA, getField());
}
diff --git a/src/main/java/com/android/tools/r8/code/SgetByte.java b/src/main/java/com/android/tools/r8/code/SgetByte.java
index 3c0219b..9a40297 100644
--- a/src/main/java/com/android/tools/r8/code/SgetByte.java
+++ b/src/main/java/com/android/tools/r8/code/SgetByte.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class SgetByte extends Format21c {
+public class SgetByte extends SgetOrSput {
public static final int OPCODE = 0x64;
public static final String NAME = "SgetByte";
@@ -43,11 +43,6 @@
}
@Override
- public DexField getField() {
- return (DexField) BBBB;
- }
-
- @Override
public void buildIR(IRBuilder builder) {
builder.addStaticGet(AA, getField());
}
diff --git a/src/main/java/com/android/tools/r8/code/SgetChar.java b/src/main/java/com/android/tools/r8/code/SgetChar.java
index aa69c7f..429eaa6 100644
--- a/src/main/java/com/android/tools/r8/code/SgetChar.java
+++ b/src/main/java/com/android/tools/r8/code/SgetChar.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class SgetChar extends Format21c {
+public class SgetChar extends SgetOrSput {
public static final int OPCODE = 0x65;
public static final String NAME = "SgetChar";
@@ -43,11 +43,6 @@
}
@Override
- public DexField getField() {
- return (DexField) BBBB;
- }
-
- @Override
public void buildIR(IRBuilder builder) {
builder.addStaticGet(AA, getField());
}
diff --git a/src/main/java/com/android/tools/r8/code/SgetObject.java b/src/main/java/com/android/tools/r8/code/SgetObject.java
index f70da49..6b1130d 100644
--- a/src/main/java/com/android/tools/r8/code/SgetObject.java
+++ b/src/main/java/com/android/tools/r8/code/SgetObject.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class SgetObject extends Format21c {
+public class SgetObject extends SgetOrSput {
public static final int OPCODE = 0x62;
public static final String NAME = "SgetObject";
@@ -43,11 +43,6 @@
}
@Override
- public DexField getField() {
- return (DexField) BBBB;
- }
-
- @Override
public void buildIR(IRBuilder builder) {
builder.addStaticGet(AA, getField());
}
diff --git a/src/main/java/com/android/tools/r8/code/SgetOrSput.java b/src/main/java/com/android/tools/r8/code/SgetOrSput.java
new file mode 100644
index 0000000..d04e098
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/code/SgetOrSput.java
@@ -0,0 +1,28 @@
+// Copyright (c) 2016, 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.code;
+
+import com.android.tools.r8.dex.IndexedItemCollection;
+import com.android.tools.r8.graph.DexField;
+
+abstract class SgetOrSput extends Format21c<DexField> {
+
+ SgetOrSput(int high, BytecodeStream stream, DexField[] map) {
+ super(high, stream, map);
+ }
+
+ protected SgetOrSput(int AA, DexField BBBB) {
+ super(AA, BBBB);
+ }
+
+ @Override
+ public final void collectIndexedItems(IndexedItemCollection indexedItems) {
+ getField().collectIndexedItems(indexedItems);
+ }
+
+ @Override
+ public final DexField getField() {
+ return BBBB;
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/code/SgetShort.java b/src/main/java/com/android/tools/r8/code/SgetShort.java
index 0149fb4..37f331e 100644
--- a/src/main/java/com/android/tools/r8/code/SgetShort.java
+++ b/src/main/java/com/android/tools/r8/code/SgetShort.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class SgetShort extends Format21c {
+public class SgetShort extends SgetOrSput {
public static final int OPCODE = 0x66;
public static final String NAME = "SgetShort";
@@ -43,11 +43,6 @@
}
@Override
- public DexField getField() {
- return (DexField) BBBB;
- }
-
- @Override
public void buildIR(IRBuilder builder) {
builder.addStaticGet(AA, getField());
}
diff --git a/src/main/java/com/android/tools/r8/code/SgetWide.java b/src/main/java/com/android/tools/r8/code/SgetWide.java
index ea008ad..638ca0c 100644
--- a/src/main/java/com/android/tools/r8/code/SgetWide.java
+++ b/src/main/java/com/android/tools/r8/code/SgetWide.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class SgetWide extends Format21c {
+public class SgetWide extends SgetOrSput {
public static final int OPCODE = 0x61;
public static final String NAME = "SgetWide";
@@ -43,11 +43,6 @@
}
@Override
- public DexField getField() {
- return (DexField) BBBB;
- }
-
- @Override
public void buildIR(IRBuilder builder) {
builder.addStaticGet(AA, getField());
}
diff --git a/src/main/java/com/android/tools/r8/code/Sput.java b/src/main/java/com/android/tools/r8/code/Sput.java
index 6885da6..e6f3b4e 100644
--- a/src/main/java/com/android/tools/r8/code/Sput.java
+++ b/src/main/java/com/android/tools/r8/code/Sput.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class Sput extends Format21c {
+public class Sput extends SgetOrSput {
public static final int OPCODE = 0x67;
public static final String NAME = "Sput";
@@ -43,11 +43,6 @@
}
@Override
- public DexField getField() {
- return (DexField) BBBB;
- }
-
- @Override
public void buildIR(IRBuilder builder) {
builder.addStaticPut(AA, getField());
}
diff --git a/src/main/java/com/android/tools/r8/code/SputBoolean.java b/src/main/java/com/android/tools/r8/code/SputBoolean.java
index 041ba02..6dae9b2 100644
--- a/src/main/java/com/android/tools/r8/code/SputBoolean.java
+++ b/src/main/java/com/android/tools/r8/code/SputBoolean.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class SputBoolean extends Format21c {
+public class SputBoolean extends SgetOrSput {
public static final int OPCODE = 0x6a;
public static final String NAME = "SputBoolean";
@@ -43,11 +43,6 @@
}
@Override
- public DexField getField() {
- return (DexField) BBBB;
- }
-
- @Override
public void buildIR(IRBuilder builder) {
builder.addStaticPut(AA, getField());
}
diff --git a/src/main/java/com/android/tools/r8/code/SputByte.java b/src/main/java/com/android/tools/r8/code/SputByte.java
index 87b79bd..c6cb521 100644
--- a/src/main/java/com/android/tools/r8/code/SputByte.java
+++ b/src/main/java/com/android/tools/r8/code/SputByte.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class SputByte extends Format21c {
+public class SputByte extends SgetOrSput {
public static final int OPCODE = 0x6b;
public static final String NAME = "SputByte";
@@ -43,11 +43,6 @@
}
@Override
- public DexField getField() {
- return (DexField) BBBB;
- }
-
- @Override
public void buildIR(IRBuilder builder) {
builder.addStaticPut(AA, getField());
}
diff --git a/src/main/java/com/android/tools/r8/code/SputChar.java b/src/main/java/com/android/tools/r8/code/SputChar.java
index 5fcd836..727ba25 100644
--- a/src/main/java/com/android/tools/r8/code/SputChar.java
+++ b/src/main/java/com/android/tools/r8/code/SputChar.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class SputChar extends Format21c {
+public class SputChar extends SgetOrSput {
public static final int OPCODE = 0x6c;
public static final String NAME = "SputChar";
@@ -43,11 +43,6 @@
}
@Override
- public DexField getField() {
- return (DexField) BBBB;
- }
-
- @Override
public void buildIR(IRBuilder builder) {
builder.addStaticPut(AA, getField());
}
diff --git a/src/main/java/com/android/tools/r8/code/SputObject.java b/src/main/java/com/android/tools/r8/code/SputObject.java
index fa661ea..4850664 100644
--- a/src/main/java/com/android/tools/r8/code/SputObject.java
+++ b/src/main/java/com/android/tools/r8/code/SputObject.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class SputObject extends Format21c {
+public class SputObject extends SgetOrSput {
public static final int OPCODE = 0x69;
public static final String NAME = "SputObject";
@@ -43,11 +43,6 @@
}
@Override
- public DexField getField() {
- return (DexField) BBBB;
- }
-
- @Override
public void buildIR(IRBuilder builder) {
builder.addStaticPut(AA, getField());
}
diff --git a/src/main/java/com/android/tools/r8/code/SputShort.java b/src/main/java/com/android/tools/r8/code/SputShort.java
index d2b5f85..eb33e33 100644
--- a/src/main/java/com/android/tools/r8/code/SputShort.java
+++ b/src/main/java/com/android/tools/r8/code/SputShort.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class SputShort extends Format21c {
+public class SputShort extends SgetOrSput {
public static final int OPCODE = 0x6d;
public static final String NAME = "SputShort";
@@ -43,11 +43,6 @@
}
@Override
- public DexField getField() {
- return (DexField) BBBB;
- }
-
- @Override
public void buildIR(IRBuilder builder) {
builder.addStaticPut(AA, getField());
}
diff --git a/src/main/java/com/android/tools/r8/code/SputWide.java b/src/main/java/com/android/tools/r8/code/SputWide.java
index 7e6aeaa..8104f75 100644
--- a/src/main/java/com/android/tools/r8/code/SputWide.java
+++ b/src/main/java/com/android/tools/r8/code/SputWide.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.IRBuilder;
-public class SputWide extends Format21c {
+public class SputWide extends SgetOrSput {
public static final int OPCODE = 0x68;
public static final String NAME = "SputWide";
@@ -43,11 +43,6 @@
}
@Override
- public DexField getField() {
- return (DexField) BBBB;
- }
-
- @Override
public void buildIR(IRBuilder builder) {
builder.addStaticPut(AA, getField());
}
diff --git a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
index f0e8da6..21b5cd4 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
@@ -14,6 +14,7 @@
import com.android.tools.r8.DexIndexedConsumer;
import com.android.tools.r8.ProgramConsumer;
import com.android.tools.r8.ResourceException;
+import com.android.tools.r8.code.Instruction;
import com.android.tools.r8.dex.FileWriter.ByteBufferResult;
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.features.FeatureSplitConfiguration.DataResourceProvidersAndConsumer;
@@ -23,6 +24,7 @@
import com.android.tools.r8.graph.DexAnnotationDirectory;
import com.android.tools.r8.graph.DexAnnotationSet;
import com.android.tools.r8.graph.DexApplication;
+import com.android.tools.r8.graph.DexCallSite;
import com.android.tools.r8.graph.DexCode;
import com.android.tools.r8.graph.DexDebugInfo;
import com.android.tools.r8.graph.DexEncodedArray;
@@ -251,6 +253,11 @@
// TODO(b/151313715): Move this to the writer threads.
insertAttributeAnnotations();
+ // Each DexCallSite must have its instruction offset set for sorting.
+ if (options.isGeneratingDex()) {
+ setCallSiteContexts(executorService);
+ }
+
// Generate the dex file contents.
List<Future<Boolean>> dexDataFutures = new ArrayList<>();
List<VirtualFile> virtualFiles = distribute(executorService);
@@ -526,6 +533,26 @@
}
}
+ private void setCallSiteContexts(ExecutorService executorService) throws ExecutionException {
+ ThreadUtils.processItems(
+ appView.appInfo().classes(), this::setCallSiteContexts, executorService);
+ }
+
+ private void setCallSiteContexts(DexProgramClass clazz) {
+ for (DexEncodedMethod method : clazz.methods()) {
+ if (method.hasCode()) {
+ DexCode code = method.getCode().asDexCode();
+ assert code != null;
+ for (Instruction instruction : code.instructions) {
+ DexCallSite callSite = instruction.getCallSite();
+ if (callSite != null) {
+ callSite.setContext(method.getReference(), instruction.getOffset());
+ }
+ }
+ }
+ }
+ }
+
/**
* Rewrites the code for all methods in the given file so that they use JumboString for at least
* the strings that require it in mapping.
diff --git a/src/main/java/com/android/tools/r8/dex/IndexedItemCollection.java b/src/main/java/com/android/tools/r8/dex/IndexedItemCollection.java
index 45b8bfe..273bf3b 100644
--- a/src/main/java/com/android/tools/r8/dex/IndexedItemCollection.java
+++ b/src/main/java/com/android/tools/r8/dex/IndexedItemCollection.java
@@ -12,6 +12,7 @@
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.GraphLens;
import com.android.tools.r8.graph.IndexedDexItem;
import com.android.tools.r8.graph.InitClassLens;
@@ -100,6 +101,10 @@
*/
boolean addMethodHandle(DexMethodHandle methodHandle);
+ default GraphLens getGraphLens() {
+ return GraphLens.getIdentityLens();
+ }
+
default InitClassLens getInitClassLens() {
return InitClassLens.getDefault();
}
diff --git a/src/main/java/com/android/tools/r8/dex/InheritanceClassInDexDistributor.java b/src/main/java/com/android/tools/r8/dex/InheritanceClassInDexDistributor.java
index e623f5e..709eb9d 100644
--- a/src/main/java/com/android/tools/r8/dex/InheritanceClassInDexDistributor.java
+++ b/src/main/java/com/android/tools/r8/dex/InheritanceClassInDexDistributor.java
@@ -10,6 +10,7 @@
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.utils.ThreadUtils;
@@ -70,7 +71,7 @@
public void updateNumbersOfIds() {
// Use a temporary VirtualFile to evaluate the number of ids in the group.
- VirtualFile virtualFile = new VirtualFile(0, initClassLens, namingLens);
+ VirtualFile virtualFile = new VirtualFile(0, graphLens, initClassLens, namingLens);
// Note: sort not needed.
for (DexProgramClass clazz : members) {
virtualFile.addClass(clazz);
@@ -284,6 +285,7 @@
private final Set<DexProgramClass> classes;
private final DexApplication app;
private int dexIndexOffset;
+ private final GraphLens graphLens;
private final InitClassLens initClassLens;
private final NamingLens namingLens;
private final DirectSubClassesInfo directSubClasses;
@@ -293,6 +295,7 @@
List<VirtualFile> dexes,
Set<DexProgramClass> classes,
int dexIndexOffset,
+ GraphLens graphLens,
InitClassLens initClassLens,
NamingLens namingLens,
DexApplication app,
@@ -301,6 +304,7 @@
this.dexes = dexes;
this.classes = classes;
this.dexIndexOffset = dexIndexOffset;
+ this.graphLens = graphLens;
this.initClassLens = initClassLens;
this.namingLens = namingLens;
this.app = app;
@@ -374,7 +378,7 @@
private Collection<VirtualFile> assignGroup(ClassGroup group, List<VirtualFile> dexBlackList) {
VirtualFileCycler cycler =
- new VirtualFileCycler(dexes, initClassLens, namingLens, dexIndexOffset);
+ new VirtualFileCycler(dexes, graphLens, initClassLens, namingLens, dexIndexOffset);
if (group.members.isEmpty()) {
return Collections.emptyList();
} else if (group.canFitInOneDex()) {
@@ -423,7 +427,7 @@
Collection<VirtualFile> usedDex = new ArrayList<>();
VirtualFileCycler cycler =
- new VirtualFileCycler(dexes, initClassLens, namingLens, dexIndexOffset);
+ new VirtualFileCycler(dexes, graphLens, initClassLens, namingLens, dexIndexOffset);
// Don't modify input dexBlackList. Think about modifying the input collection considering this
// is private API.
Set<VirtualFile> currentBlackList = new HashSet<>(dexBlackList);
diff --git a/src/main/java/com/android/tools/r8/dex/VirtualFile.java b/src/main/java/com/android/tools/r8/dex/VirtualFile.java
index a419f4a..b036d96 100644
--- a/src/main/java/com/android/tools/r8/dex/VirtualFile.java
+++ b/src/main/java/com/android/tools/r8/dex/VirtualFile.java
@@ -18,6 +18,7 @@
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.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.ObjectToOffsetMapping;
import com.android.tools.r8.logging.Log;
@@ -76,29 +77,39 @@
private final DexProgramClass primaryClass;
- VirtualFile(int id, InitClassLens initClassLens, NamingLens namingLens) {
- this(id, initClassLens, namingLens, null, null);
+ VirtualFile(int id, GraphLens graphLens, InitClassLens initClassLens, NamingLens namingLens) {
+ this(id, graphLens, initClassLens, namingLens, null, null);
}
VirtualFile(
- int id, InitClassLens initClassLens, NamingLens namingLens, FeatureSplit featureSplit) {
- this(id, initClassLens, namingLens, null, featureSplit);
- }
-
- private VirtualFile(
- int id, InitClassLens initClassLens, NamingLens namingLens, DexProgramClass primaryClass) {
- this(id, initClassLens, namingLens, primaryClass, null);
+ int id,
+ GraphLens graphLens,
+ InitClassLens initClassLens,
+ NamingLens namingLens,
+ FeatureSplit featureSplit) {
+ this(id, graphLens, initClassLens, namingLens, null, featureSplit);
}
private VirtualFile(
int id,
+ GraphLens graphLens,
+ InitClassLens initClassLens,
+ NamingLens namingLens,
+ DexProgramClass primaryClass) {
+ this(id, graphLens, initClassLens, namingLens, primaryClass, null);
+ }
+
+ private VirtualFile(
+ int id,
+ GraphLens graphLens,
InitClassLens initClassLens,
NamingLens namingLens,
DexProgramClass primaryClass,
FeatureSplit featureSplit) {
this.id = id;
- this.indexedItems = new VirtualFileIndexedItemCollection(initClassLens, namingLens);
- this.transaction = new IndexedItemTransaction(indexedItems, initClassLens, namingLens);
+ this.indexedItems = new VirtualFileIndexedItemCollection(graphLens, initClassLens, namingLens);
+ this.transaction =
+ new IndexedItemTransaction(indexedItems, graphLens, initClassLens, namingLens);
this.primaryClass = primaryClass;
this.featureSplit = featureSplit;
}
@@ -296,7 +307,12 @@
for (DexProgramClass clazz : application.classes()) {
if (!combineSyntheticClassesWithPrimaryClass || clazz.getSynthesizedFrom().isEmpty()) {
VirtualFile file =
- new VirtualFile(virtualFiles.size(), writer.initClassLens, writer.namingLens, clazz);
+ new VirtualFile(
+ virtualFiles.size(),
+ writer.graphLens,
+ writer.initClassLens,
+ writer.namingLens,
+ clazz);
virtualFiles.add(file);
file.addClass(clazz);
files.put(clazz, file);
@@ -329,7 +345,7 @@
this.options = options;
// Create the primary dex file. The distribution will add more if needed.
- mainDexFile = new VirtualFile(0, writer.initClassLens, writer.namingLens);
+ mainDexFile = new VirtualFile(0, writer.graphLens, writer.initClassLens, writer.namingLens);
assert virtualFiles.isEmpty();
virtualFiles.add(mainDexFile);
addMarkers(mainDexFile);
@@ -447,7 +463,11 @@
// Add a new virtual file, start from index 0 again
VirtualFile featureFile =
new VirtualFile(
- 0, writer.initClassLens, writer.namingLens, featureSplitSetEntry.getKey());
+ 0,
+ writer.graphLens,
+ writer.initClassLens,
+ writer.namingLens,
+ featureSplitSetEntry.getKey());
virtualFiles.add(featureFile);
addMarkers(featureFile);
Set<DexProgramClass> featureClasses =
@@ -461,6 +481,7 @@
application.dexItemFactory,
fillStrategy,
0,
+ writer.graphLens,
writer.initClassLens,
writer.namingLens,
options)
@@ -497,7 +518,8 @@
assert !virtualFiles.get(0).isEmpty();
assert virtualFiles.size() == 1;
// The main dex file is filtered out, so ensure at least one file for the remaining classes.
- virtualFiles.add(new VirtualFile(1, writer.initClassLens, writer.namingLens));
+ virtualFiles.add(
+ new VirtualFile(1, writer.graphLens, writer.initClassLens, writer.namingLens));
filesForDistribution = virtualFiles.subList(1, virtualFiles.size());
fileIndexOffset = 1;
}
@@ -511,6 +533,7 @@
filesForDistribution,
classes,
fileIndexOffset,
+ writer.graphLens,
writer.initClassLens,
writer.namingLens,
writer.application,
@@ -527,6 +550,7 @@
application.dexItemFactory,
fillStrategy,
fileIndexOffset,
+ writer.graphLens,
writer.initClassLens,
writer.namingLens,
options)
@@ -566,6 +590,7 @@
private static class VirtualFileIndexedItemCollection implements IndexedItemCollection {
+ private final GraphLens graphLens;
private final InitClassLens initClassLens;
private final NamingLens namingLens;
@@ -578,7 +603,9 @@
private final Set<DexCallSite> callSites = Sets.newIdentityHashSet();
private final Set<DexMethodHandle> methodHandles = Sets.newIdentityHashSet();
- public VirtualFileIndexedItemCollection(InitClassLens initClassLens, NamingLens namingLens) {
+ public VirtualFileIndexedItemCollection(
+ GraphLens graphLens, InitClassLens initClassLens, NamingLens namingLens) {
+ this.graphLens = graphLens;
this.initClassLens = initClassLens;
this.namingLens = namingLens;
}
@@ -636,6 +663,11 @@
}
@Override
+ public GraphLens getGraphLens() {
+ return graphLens;
+ }
+
+ @Override
public InitClassLens getInitClassLens() {
return initClassLens;
}
@@ -660,6 +692,7 @@
public static class IndexedItemTransaction implements IndexedItemCollection {
private final VirtualFileIndexedItemCollection base;
+ private final GraphLens graphLens;
private final InitClassLens initClassLens;
private final NamingLens namingLens;
@@ -673,8 +706,12 @@
private final Set<DexMethodHandle> methodHandles = new LinkedHashSet<>();
private IndexedItemTransaction(
- VirtualFileIndexedItemCollection base, InitClassLens initClassLens, NamingLens namingLens) {
+ VirtualFileIndexedItemCollection base,
+ GraphLens graphLens,
+ InitClassLens initClassLens,
+ NamingLens namingLens) {
this.base = base;
+ this.graphLens = graphLens;
this.initClassLens = initClassLens;
this.namingLens = namingLens;
}
@@ -732,6 +769,11 @@
}
@Override
+ public GraphLens getGraphLens() {
+ return graphLens;
+ }
+
+ @Override
public InitClassLens getInitClassLens() {
return initClassLens;
}
@@ -813,6 +855,7 @@
static class VirtualFileCycler {
private final List<VirtualFile> files;
+ private final GraphLens graphLens;
private final InitClassLens initClassLens;
private final NamingLens namingLens;
@@ -823,10 +866,12 @@
VirtualFileCycler(
List<VirtualFile> files,
+ GraphLens graphLens,
InitClassLens initClassLens,
NamingLens namingLens,
int fileIndexOffset) {
this.files = files;
+ this.graphLens = graphLens;
this.initClassLens = initClassLens;
this.namingLens = namingLens;
@@ -859,7 +904,7 @@
return activeFiles.next();
} else {
VirtualFile newFile =
- new VirtualFile(nextFileId++, initClassLens, namingLens, featuresplit);
+ new VirtualFile(nextFileId++, graphLens, initClassLens, namingLens, featuresplit);
files.add(newFile);
allFilesCyclic = Iterators.cycle(files);
return newFile;
@@ -890,7 +935,8 @@
}
VirtualFile addFile() {
- VirtualFile newFile = new VirtualFile(nextFileId++, initClassLens, namingLens, featuresplit);
+ VirtualFile newFile =
+ new VirtualFile(nextFileId++, graphLens, initClassLens, namingLens, featuresplit);
files.add(newFile);
reset();
@@ -936,6 +982,7 @@
DexItemFactory dexItemFactory,
FillStrategy fillStrategy,
int fileIndexOffset,
+ GraphLens graphLens,
InitClassLens initClassLens,
NamingLens namingLens,
InternalOptions options) {
@@ -944,7 +991,8 @@
this.dexItemFactory = dexItemFactory;
this.fillStrategy = fillStrategy;
this.options = options;
- this.cycler = new VirtualFileCycler(files, initClassLens, namingLens, fileIndexOffset);
+ this.cycler =
+ new VirtualFileCycler(files, graphLens, initClassLens, namingLens, fileIndexOffset);
}
static boolean coveredByPrefix(String originalName, String currentPrefix) {
diff --git a/src/main/java/com/android/tools/r8/errors/InternalCompilerError.java b/src/main/java/com/android/tools/r8/errors/InternalCompilerError.java
index a5080d3..be068d9 100644
--- a/src/main/java/com/android/tools/r8/errors/InternalCompilerError.java
+++ b/src/main/java/com/android/tools/r8/errors/InternalCompilerError.java
@@ -6,9 +6,12 @@
/**
* Exception to signal an unexpected state internally to the compiler.
*
- * Exceptions of this type always represent an bug in the compiler.
- * For expected errors, such as invalid input, the compiler should generate a CompilationError.
- */
+ * <p>Exceptions of this type always represent an bug in the compiler.
+ *
+ * <p>For expected errors, such as invalid input, the compiler should generate a CompilationError.
+ *
+ * <p>For internal recoverable exceptions (eg, control operators) this base should not be used.
+ */
public class InternalCompilerError extends IllegalStateException {
public InternalCompilerError() {
diff --git a/src/main/java/com/android/tools/r8/errors/InvalidDebugInfoException.java b/src/main/java/com/android/tools/r8/errors/InvalidDebugInfoException.java
index f3f99e2..faf93cd 100644
--- a/src/main/java/com/android/tools/r8/errors/InvalidDebugInfoException.java
+++ b/src/main/java/com/android/tools/r8/errors/InvalidDebugInfoException.java
@@ -3,7 +3,8 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.errors;
-public class InvalidDebugInfoException extends InternalCompilerError {
+/** An always caught exception to abort/restart IR construction due to invalid locals. */
+public class InvalidDebugInfoException extends RuntimeException {
public InvalidDebugInfoException(String message) {
super(message);
}
diff --git a/src/main/java/com/android/tools/r8/errors/InvalidDescriptorException.java b/src/main/java/com/android/tools/r8/errors/InvalidDescriptorException.java
index f6702b7..1b426bc 100644
--- a/src/main/java/com/android/tools/r8/errors/InvalidDescriptorException.java
+++ b/src/main/java/com/android/tools/r8/errors/InvalidDescriptorException.java
@@ -3,7 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.errors;
-public class InvalidDescriptorException extends InternalCompilerError {
+public class InvalidDescriptorException extends RuntimeException {
public InvalidDescriptorException(String message) {
super(message);
}
diff --git a/src/main/java/com/android/tools/r8/graph/AppInfo.java b/src/main/java/com/android/tools/r8/graph/AppInfo.java
index 66b00b8..59239db 100644
--- a/src/main/java/com/android/tools/r8/graph/AppInfo.java
+++ b/src/main/java/com/android/tools/r8/graph/AppInfo.java
@@ -115,9 +115,8 @@
return dependent;
}
DexClass definition = definitionFor(type);
- if (definition != null && !definition.isLibraryClass() && dependent.isProgramClass()) {
- InterfaceMethodRewriter.reportDependencyEdge(
- dependent.asProgramClass(), definition, options());
+ if (definition != null && !definition.isLibraryClass() && !dependent.isLibraryClass()) {
+ InterfaceMethodRewriter.reportDependencyEdge(dependent, definition, options());
}
return definition;
}
diff --git a/src/main/java/com/android/tools/r8/graph/AppView.java b/src/main/java/com/android/tools/r8/graph/AppView.java
index c6bc6b4..d0a3643 100644
--- a/src/main/java/com/android/tools/r8/graph/AppView.java
+++ b/src/main/java/com/android/tools/r8/graph/AppView.java
@@ -478,6 +478,9 @@
}
public OptionalBool isSubtype(DexType subtype, DexType supertype) {
+ // Even if we can compute isSubtype by having class hierarchy we may not be allowed to ask the
+ // question for all code paths in D8. Having the check for liveness ensure that we are in R8
+ // territory.
return appInfo().hasLiveness()
? OptionalBool.of(appInfo().withLiveness().isSubtype(subtype, supertype))
: OptionalBool.unknown();
diff --git a/src/main/java/com/android/tools/r8/graph/AppliedGraphLens.java b/src/main/java/com/android/tools/r8/graph/AppliedGraphLens.java
index 318b1bc..c9e4d4d 100644
--- a/src/main/java/com/android/tools/r8/graph/AppliedGraphLens.java
+++ b/src/main/java/com/android/tools/r8/graph/AppliedGraphLens.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.graph;
import com.android.tools.r8.ir.code.Invoke;
+import com.android.tools.r8.utils.MapUtils;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import java.util.IdentityHashMap;
@@ -24,8 +25,11 @@
private final BiMap<DexType, DexType> originalTypeNames = HashBiMap.create();
private final BiMap<DexField, DexField> originalFieldSignatures = HashBiMap.create();
private final BiMap<DexMethod, DexMethod> originalMethodSignatures = HashBiMap.create();
- private final Map<DexMethod, DexMethod> originalMethodSignaturesForBridges =
- new IdentityHashMap<>();
+
+ // Original method signatures for bridges and companion methods. Due to the synthesis of these
+ // methods, the mapping from original methods to final methods is not one-to-one, but one-to-many,
+ // which is why we need an additional map.
+ private final Map<DexMethod, DexMethod> extraOriginalMethodSignatures = new IdentityHashMap<>();
public AppliedGraphLens(AppView<? extends AppInfoWithClassHierarchy> appView) {
this.appView = appView;
@@ -58,22 +62,24 @@
for (DexEncodedMethod encodedMethod : clazz.methods()) {
DexMethod method = encodedMethod.method;
DexMethod original = appView.graphLens().getOriginalMethodSignature(method);
- if (original != method) {
- DexMethod existing = originalMethodSignatures.inverse().get(original);
- if (existing == null) {
- originalMethodSignatures.put(method, original);
+ DexMethod existing = originalMethodSignatures.inverse().get(original);
+ if (existing == null) {
+ originalMethodSignatures.put(method, original);
+ } else {
+ DexMethod renamed = appView.graphLens().getRenamedMethodSignature(original);
+ if (renamed == existing) {
+ extraOriginalMethodSignatures.put(method, original);
} else {
- DexMethod renamed = getRenamedMethodSignature(original);
- if (renamed == existing) {
- originalMethodSignaturesForBridges.put(method, original);
- } else {
- originalMethodSignatures.forcePut(method, original);
- originalMethodSignaturesForBridges.put(existing, original);
- }
+ originalMethodSignatures.forcePut(method, original);
+ extraOriginalMethodSignatures.put(existing, original);
}
}
}
}
+
+ // Trim original method signatures.
+ MapUtils.removeIdentityMappings(originalMethodSignatures);
+ MapUtils.removeIdentityMappings(extraOriginalMethodSignatures);
}
@Override
@@ -88,8 +94,8 @@
@Override
public DexMethod getOriginalMethodSignature(DexMethod method) {
- if (originalMethodSignaturesForBridges.containsKey(method)) {
- return originalMethodSignaturesForBridges.get(method);
+ if (extraOriginalMethodSignatures.containsKey(method)) {
+ return extraOriginalMethodSignatures.get(method);
}
return originalMethodSignatures.getOrDefault(method, method);
}
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 16533fe..c40931a 100644
--- a/src/main/java/com/android/tools/r8/graph/CfCode.java
+++ b/src/main/java/com/android/tools/r8/graph/CfCode.java
@@ -204,12 +204,13 @@
NamingLens namingLens,
AppView<?> appView,
int classFileVersion) {
+ GraphLens graphLens = appView.graphLens();
InitClassLens initClassLens = appView.initClassLens();
InternalOptions options = appView.options();
CfLabel parameterLabel = null;
if (shouldAddParameterNames(method, appView)) {
parameterLabel = new CfLabel();
- parameterLabel.write(visitor, initClassLens, namingLens);
+ parameterLabel.write(visitor, graphLens, initClassLens, namingLens);
}
for (CfInstruction instruction : instructions) {
if (instruction instanceof CfFrame
@@ -217,7 +218,7 @@
|| (classFileVersion == V1_6 && !options.shouldKeepStackMapTable()))) {
continue;
}
- instruction.write(visitor, initClassLens, namingLens);
+ instruction.write(visitor, graphLens, initClassLens, namingLens);
}
visitor.visitEnd();
visitor.visitMaxs(maxStack, maxLocals);
diff --git a/src/main/java/com/android/tools/r8/graph/Code.java b/src/main/java/com/android/tools/r8/graph/Code.java
index bb11c69..1f2a522 100644
--- a/src/main/java/com/android/tools/r8/graph/Code.java
+++ b/src/main/java/com/android/tools/r8/graph/Code.java
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.graph;
-import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.dex.MixedSectionCollection;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.ir.code.IRCode;
@@ -89,12 +88,6 @@
}
@Override
- void collectIndexedItems(IndexedItemCollection collection,
- DexMethod method, int instructionOffset) {
- throw new Unreachable();
- }
-
- @Override
void collectMixedSectionItems(MixedSectionCollection collection) {
throw new Unreachable();
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexAnnotation.java b/src/main/java/com/android/tools/r8/graph/DexAnnotation.java
index a409737..ade8d06 100644
--- a/src/main/java/com/android/tools/r8/graph/DexAnnotation.java
+++ b/src/main/java/com/android/tools/r8/graph/DexAnnotation.java
@@ -62,10 +62,8 @@
return visibility + " " + annotation;
}
- @Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
- annotation.collectIndexedItems(indexedItems, method, instructionOffset);
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
+ annotation.collectIndexedItems(indexedItems);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/graph/DexAnnotationDirectory.java b/src/main/java/com/android/tools/r8/graph/DexAnnotationDirectory.java
index a6b7824..04f59d7 100644
--- a/src/main/java/com/android/tools/r8/graph/DexAnnotationDirectory.java
+++ b/src/main/java/com/android/tools/r8/graph/DexAnnotationDirectory.java
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.graph;
-import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.dex.MixedSectionCollection;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.naming.NamingLens;
@@ -92,12 +91,6 @@
}
@Override
- public void collectIndexedItems(IndexedItemCollection collection,
- DexMethod method, int instructionOffset) {
- throw new Unreachable();
- }
-
- @Override
public void collectMixedSectionItems(MixedSectionCollection collection) {
throw new Unreachable();
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexAnnotationElement.java b/src/main/java/com/android/tools/r8/graph/DexAnnotationElement.java
index 10c6535..e1965be 100644
--- a/src/main/java/com/android/tools/r8/graph/DexAnnotationElement.java
+++ b/src/main/java/com/android/tools/r8/graph/DexAnnotationElement.java
@@ -39,11 +39,9 @@
return name + "=" + value;
}
- @Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
- name.collectIndexedItems(indexedItems, method, instructionOffset);
- value.collectIndexedItems(indexedItems, method, instructionOffset);
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
+ name.collectIndexedItems(indexedItems);
+ value.collectIndexedItems(indexedItems);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/graph/DexAnnotationSet.java b/src/main/java/com/android/tools/r8/graph/DexAnnotationSet.java
index 7371902..e13faf8 100644
--- a/src/main/java/com/android/tools/r8/graph/DexAnnotationSet.java
+++ b/src/main/java/com/android/tools/r8/graph/DexAnnotationSet.java
@@ -77,10 +77,10 @@
return false;
}
- @Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
- collectAll(indexedItems, annotations);
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
+ for (DexAnnotation annotation : annotations) {
+ annotation.collectIndexedItems(indexedItems);
+ }
}
@Override
diff --git a/src/main/java/com/android/tools/r8/graph/DexCallSite.java b/src/main/java/com/android/tools/r8/graph/DexCallSite.java
index 8c76ca1..bcb8873 100644
--- a/src/main/java/com/android/tools/r8/graph/DexCallSite.java
+++ b/src/main/java/com/android/tools/r8/graph/DexCallSite.java
@@ -35,7 +35,7 @@
// Only used for sorting for deterministic output. This is the method and the instruction
// offset where this DexCallSite ends up in the output.
private DexMethod method;
- private int instructionOffset;
+ private int instructionOffset = -1;
DexCallSite(
DexString methodName,
@@ -84,6 +84,15 @@
return application.getCallSite(name, desc, bootstrapMethod, bootstrapArgs);
}
+ public void setContext(DexMethod method, int instructionOffset) {
+ assert method != null;
+ assert instructionOffset >= 0;
+ assert this.method == null;
+ assert this.instructionOffset == -1;
+ this.method = method;
+ this.instructionOffset = instructionOffset;
+ }
+
@Override
public int computeHashCode() {
// Call sites are equal only when this == other, which was already computed by the caller of
@@ -115,23 +124,13 @@
return builder.toString();
}
- @Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
- assert method != null;
- // Since collectIndexedItems() is called in transactions that may be rolled back, we may end up
- // setting this.method and this.instructionOffset more than once. If we do set them more than
- // once, then we must have the same values for method and instructionOffset every time.
- assert this.method == null || this.method == method;
- assert this.instructionOffset == 0 || this.instructionOffset == instructionOffset;
- this.method = method;
- this.instructionOffset = instructionOffset;
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
if (indexedItems.addCallSite(this)) {
- methodName.collectIndexedItems(indexedItems, method, instructionOffset);
- methodProto.collectIndexedItems(indexedItems, method, instructionOffset);
- bootstrapMethod.collectIndexedItems(indexedItems, method, instructionOffset);
+ methodName.collectIndexedItems(indexedItems);
+ methodProto.collectIndexedItems(indexedItems);
+ bootstrapMethod.collectIndexedItems(indexedItems);
for (DexValue arg : bootstrapArgs) {
- arg.collectIndexedItems(indexedItems, method, instructionOffset);
+ arg.collectIndexedItems(indexedItems);
}
}
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexClass.java b/src/main/java/com/android/tools/r8/graph/DexClass.java
index fe2eabd..528b79b 100644
--- a/src/main/java/com/android/tools/r8/graph/DexClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexClass.java
@@ -113,6 +113,10 @@
return accessFlags;
}
+ public DexString getSourceFile() {
+ return sourceFile;
+ }
+
public Iterable<DexEncodedField> fields() {
return fields(Predicates.alwaysTrue());
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexClasspathClass.java b/src/main/java/com/android/tools/r8/graph/DexClasspathClass.java
index 1e85690..118a04d 100644
--- a/src/main/java/com/android/tools/r8/graph/DexClasspathClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexClasspathClass.java
@@ -5,7 +5,6 @@
import com.android.tools.r8.ProgramResource;
import com.android.tools.r8.ProgramResource.Kind;
-import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.dex.MixedSectionCollection;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.kotlin.KotlinClassLevelInfo;
@@ -54,12 +53,6 @@
}
@Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
- throw new Unreachable();
- }
-
- @Override
public String toString() {
return type.toString() + "(classpath class)";
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexCode.java b/src/main/java/com/android/tools/r8/graph/DexCode.java
index ae3fe1e..6716297 100644
--- a/src/main/java/com/android/tools/r8/graph/DexCode.java
+++ b/src/main/java/com/android/tools/r8/graph/DexCode.java
@@ -403,14 +403,11 @@
return builder.toString();
}
- @Override
- public void collectIndexedItems(
- IndexedItemCollection indexedItems, DexMethod method, int instructionOffset) {
- assert instructionOffset == -1;
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
highestSortingString = null;
for (Instruction insn : instructions) {
assert !insn.isDexItemBasedConstString();
- insn.collectIndexedItems(indexedItems, method, insn.getOffset());
+ insn.collectIndexedItems(indexedItems);
if (insn.isConstString()) {
updateHighestSortingString(insn.asConstString().getString());
} else if (insn.isConstStringJumbo()) {
@@ -512,12 +509,6 @@
}
@Override
- void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
- // Intentionally left empty.
- }
-
- @Override
void collectMixedSectionItems(MixedSectionCollection mixedItems) {
// Should never be visited.
assert false;
@@ -557,10 +548,10 @@
return false;
}
- @Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
- collectAll(indexedItems, pairs);
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
+ for (TypeAddrPair pair : pairs) {
+ pair.collectIndexedItems(indexedItems);
+ }
}
@Override
@@ -599,10 +590,8 @@
this.addr = addr;
}
- @Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
- type.collectIndexedItems(indexedItems, method, instructionOffset);
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
+ type.collectIndexedItems(indexedItems);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/graph/DexDebugEvent.java b/src/main/java/com/android/tools/r8/graph/DexDebugEvent.java
index 059f7f6..20fd6e6 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDebugEvent.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDebugEvent.java
@@ -13,9 +13,7 @@
abstract public class DexDebugEvent extends DexItem {
public static final DexDebugEvent[] EMPTY_ARRAY = {};
- @Override
- public void collectIndexedItems(IndexedItemCollection collection,
- DexMethod method, int instructionOffset) {
+ public void collectIndexedItems(IndexedItemCollection collection) {
// Empty by default.
}
@@ -222,16 +220,15 @@
}
@Override
- public void collectIndexedItems(IndexedItemCollection collection,
- DexMethod method, int instructionOffset) {
+ public void collectIndexedItems(IndexedItemCollection collection) {
if (name != null) {
- name.collectIndexedItems(collection, method, instructionOffset);
+ name.collectIndexedItems(collection);
}
if (type != null) {
- type.collectIndexedItems(collection, method, instructionOffset);
+ type.collectIndexedItems(collection);
}
if (signature != null) {
- signature.collectIndexedItems(collection, method, instructionOffset);
+ signature.collectIndexedItems(collection);
}
}
@@ -362,9 +359,8 @@
}
@Override
- public void collectIndexedItems(IndexedItemCollection collection,
- DexMethod method, int instructionOffset) {
- fileName.collectIndexedItems(collection, method, instructionOffset);
+ public void collectIndexedItems(IndexedItemCollection collection) {
+ fileName.collectIndexedItems(collection);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/graph/DexDebugInfo.java b/src/main/java/com/android/tools/r8/graph/DexDebugInfo.java
index 9c27243..51ad23c 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDebugInfo.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDebugInfo.java
@@ -54,11 +54,15 @@
return false;
}
- @Override
- public void collectIndexedItems(IndexedItemCollection collection,
- DexMethod method, int instructionOffset) {
- collectAll(collection, parameters);
- collectAll(collection, events);
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
+ for (DexString parameter : parameters) {
+ if (parameter != null) {
+ parameter.collectIndexedItems(indexedItems);
+ }
+ }
+ for (DexDebugEvent event : events) {
+ event.collectIndexedItems(indexedItems);
+ }
}
@Override
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedAnnotation.java b/src/main/java/com/android/tools/r8/graph/DexEncodedAnnotation.java
index f5c5272..0ed6769 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedAnnotation.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedAnnotation.java
@@ -23,11 +23,11 @@
this.elements = elements;
}
- @Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
- type.collectIndexedItems(indexedItems, method, instructionOffset);
- collectAll(indexedItems, elements);
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
+ type.collectIndexedItems(indexedItems);
+ for (DexAnnotationElement element : elements) {
+ element.collectIndexedItems(indexedItems);
+ }
}
@Override
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedArray.java b/src/main/java/com/android/tools/r8/graph/DexEncodedArray.java
index fac96c9..19ec6c2 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedArray.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedArray.java
@@ -15,10 +15,10 @@
this.values = values;
}
- @Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
- collectAll(indexedItems, values);
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
+ for (DexValue value : values) {
+ value.collectIndexedItems(indexedItems);
+ }
}
@Override
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 5d9fa45..4b6fd50 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedField.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedField.java
@@ -87,13 +87,11 @@
this.kotlinMemberInfo = kotlinMemberInfo;
}
- @Override
- public void collectIndexedItems(
- IndexedItemCollection indexedItems, DexMethod method, int instructionOffset) {
- field.collectIndexedItems(indexedItems, method, instructionOffset);
- annotations().collectIndexedItems(indexedItems, method, instructionOffset);
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
+ field.collectIndexedItems(indexedItems);
+ annotations().collectIndexedItems(indexedItems);
if (accessFlags.isStatic()) {
- getStaticValue().collectIndexedItems(indexedItems, method, instructionOffset);
+ getStaticValue().collectIndexedItems(indexedItems);
}
}
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 ff7e38c..ce6934a 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -648,13 +648,15 @@
return "Encoded method " + method;
}
- @Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
checkIfObsolete();
this.method.collectIndexedItems(indexedItems);
if (code != null) {
- code.collectIndexedItems(indexedItems, this.method);
+ if (code.isDexCode()) {
+ code.asDexCode().collectIndexedItems(indexedItems);
+ } else {
+ assert false;
+ }
}
annotations().collectIndexedItems(indexedItems);
parameterAnnotationsList.collectIndexedItems(indexedItems);
diff --git a/src/main/java/com/android/tools/r8/graph/DexField.java b/src/main/java/com/android/tools/r8/graph/DexField.java
index 84d581e..19b793d 100644
--- a/src/main/java/com/android/tools/r8/graph/DexField.java
+++ b/src/main/java/com/android/tools/r8/graph/DexField.java
@@ -79,13 +79,11 @@
}
@Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
if (indexedItems.addField(this)) {
- holder.collectIndexedItems(indexedItems, method, instructionOffset);
- type.collectIndexedItems(indexedItems, method, instructionOffset);
- indexedItems.getRenamedName(this).collectIndexedItems(
- indexedItems, method, instructionOffset);
+ holder.collectIndexedItems(indexedItems);
+ type.collectIndexedItems(indexedItems);
+ indexedItems.getRenamedName(this).collectIndexedItems(indexedItems);
}
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexItem.java b/src/main/java/com/android/tools/r8/graph/DexItem.java
index eb8e150..f26e41a 100644
--- a/src/main/java/com/android/tools/r8/graph/DexItem.java
+++ b/src/main/java/com/android/tools/r8/graph/DexItem.java
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.graph;
-import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.dex.MixedSectionCollection;
import java.util.Collection;
import java.util.function.Consumer;
@@ -11,17 +10,13 @@
public abstract class DexItem {
- static <T extends DexItem> void collectAll(IndexedItemCollection indexedItems, T[] items) {
- consumeArray(items, (T item) -> item.collectIndexedItems(indexedItems));
- }
-
public static <T extends DexItem> void collectAll(MixedSectionCollection mixedItems, T[] items) {
- consumeArray(items, (T item) -> item.collectMixedSectionItems(mixedItems));
+ consumeArray(items, item -> item.collectMixedSectionItems(mixedItems));
}
public static <T extends DexItem> void collectAll(MixedSectionCollection mixedItems,
Collection<T> items) {
- items.forEach((T item) -> item.collectMixedSectionItems(mixedItems));
+ items.forEach(item -> item.collectMixedSectionItems(mixedItems));
}
/**
@@ -39,17 +34,6 @@
}
}
- abstract void collectIndexedItems(IndexedItemCollection collection,
- DexMethod method, int instructionOffset);
-
- public void collectIndexedItems(IndexedItemCollection collection) {
- collectIndexedItems(collection, null, -1);
- }
-
- public void collectIndexedItems(IndexedItemCollection collection, DexMethod method) {
- collectIndexedItems(collection, method, -1);
- }
-
abstract void collectMixedSectionItems(MixedSectionCollection collection);
protected void flushCachedValues() {
diff --git a/src/main/java/com/android/tools/r8/graph/DexLibraryClass.java b/src/main/java/com/android/tools/r8/graph/DexLibraryClass.java
index 7711eb3..22920eb 100644
--- a/src/main/java/com/android/tools/r8/graph/DexLibraryClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexLibraryClass.java
@@ -5,7 +5,6 @@
import com.android.tools.r8.ProgramResource;
import com.android.tools.r8.ProgramResource.Kind;
-import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.dex.MixedSectionCollection;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.kotlin.KotlinClassLevelInfo;
@@ -81,12 +80,6 @@
}
@Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
- throw new Unreachable();
- }
-
- @Override
public String toString() {
return type.toString() + "(library class)";
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexMemberAnnotation.java b/src/main/java/com/android/tools/r8/graph/DexMemberAnnotation.java
index d9868a5..5c9dad2 100644
--- a/src/main/java/com/android/tools/r8/graph/DexMemberAnnotation.java
+++ b/src/main/java/com/android/tools/r8/graph/DexMemberAnnotation.java
@@ -17,13 +17,6 @@
}
@Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
- item.collectIndexedItems(indexedItems, method, instructionOffset);
- annotations.collectIndexedItems(indexedItems, method, instructionOffset);
- }
-
- @Override
void collectMixedSectionItems(MixedSectionCollection mixedItems) {
annotations.collectMixedSectionItems(mixedItems);
}
@@ -50,6 +43,11 @@
public DexFieldAnnotation(DexField item, DexAnnotationSet annotations) {
super(item, annotations);
}
+
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
+ item.collectIndexedItems(indexedItems);
+ annotations.collectIndexedItems(indexedItems);
+ }
}
public static class DexMethodAnnotation extends DexMemberAnnotation<DexMethod, DexAnnotationSet> {
@@ -57,6 +55,11 @@
public DexMethodAnnotation(DexMethod item, DexAnnotationSet annotations) {
super(item, annotations);
}
+
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
+ item.collectIndexedItems(indexedItems);
+ annotations.collectIndexedItems(indexedItems);
+ }
}
public static class DexParameterAnnotation extends
@@ -65,5 +68,10 @@
public DexParameterAnnotation(DexMethod item, ParameterAnnotationsList annotations) {
super(item, annotations);
}
+
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
+ item.collectIndexedItems(indexedItems);
+ annotations.collectIndexedItems(indexedItems);
+ }
}
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexMethod.java b/src/main/java/com/android/tools/r8/graph/DexMethod.java
index fce08d8..999f261 100644
--- a/src/main/java/com/android/tools/r8/graph/DexMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexMethod.java
@@ -31,6 +31,10 @@
}
}
+ public DexTypeList getParameters() {
+ return proto.parameters;
+ }
+
public DexType getReturnType() {
return proto.returnType;
}
@@ -92,26 +96,23 @@
}
@Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
- if (collectIndexedItemsExceptName(indexedItems, method, instructionOffset)) {
- collectIndexedItemsName(indexedItems, method, instructionOffset);
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
+ if (collectIndexedItemsExceptName(indexedItems)) {
+ collectIndexedItemsName(indexedItems);
}
}
- public boolean collectIndexedItemsExceptName(
- IndexedItemCollection indexedItems, DexMethod method, int instructionOffset) {
+ boolean collectIndexedItemsExceptName(IndexedItemCollection indexedItems) {
if (indexedItems.addMethod(this)) {
- holder.collectIndexedItems(indexedItems, method, instructionOffset);
- proto.collectIndexedItems(indexedItems, method, instructionOffset);
+ holder.collectIndexedItems(indexedItems);
+ proto.collectIndexedItems(indexedItems);
return true;
}
return false;
}
- public void collectIndexedItemsName(
- IndexedItemCollection indexedItems, DexMethod method, int instructionOffset) {
- indexedItems.getRenamedName(this).collectIndexedItems(indexedItems, method, instructionOffset);
+ void collectIndexedItemsName(IndexedItemCollection indexedItems) {
+ indexedItems.getRenamedName(this).collectIndexedItems(indexedItems);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/graph/DexMethodHandle.java b/src/main/java/com/android/tools/r8/graph/DexMethodHandle.java
index 6c37bc9..80a3cb9 100644
--- a/src/main/java/com/android/tools/r8/graph/DexMethodHandle.java
+++ b/src/main/java/com/android/tools/r8/graph/DexMethodHandle.java
@@ -187,7 +187,7 @@
public final MethodHandleType type;
// Field or method that the method handle is targeting.
- public final DexMember<? extends DexItem, ? extends DexMember<?, ?>> fieldOrMethod;
+ public final DexMember<? extends DexItem, ? extends DexMember<?, ?>> member;
public final boolean isInterface;
@@ -204,18 +204,18 @@
public DexMethodHandle(
MethodHandleType type,
- DexMember<? extends DexItem, ? extends DexMember<?, ?>> fieldOrMethod,
+ DexMember<? extends DexItem, ? extends DexMember<?, ?>> member,
boolean isInterface) {
- this(type, fieldOrMethod, isInterface, null);
+ this(type, member, isInterface, null);
}
public DexMethodHandle(
MethodHandleType type,
- DexMember<? extends DexItem, ? extends DexMember<?, ?>> fieldOrMethod,
+ DexMember<? extends DexItem, ? extends DexMember<?, ?>> member,
boolean isInterface,
DexMethod rewrittenTarget) {
this.type = type;
- this.fieldOrMethod = fieldOrMethod;
+ this.member = member;
this.isInterface = isInterface;
this.rewrittenTarget = rewrittenTarget;
}
@@ -232,7 +232,7 @@
@Override
public int computeHashCode() {
- return Objects.hash(type, fieldOrMethod.computeHashCode(), isInterface, rewrittenTarget);
+ return Objects.hash(type, member.computeHashCode(), isInterface, rewrittenTarget);
}
@Override
@@ -240,7 +240,7 @@
if (other instanceof DexMethodHandle) {
DexMethodHandle o = (DexMethodHandle) other;
return type.equals(o.type)
- && fieldOrMethod.equals(o.fieldOrMethod)
+ && member.equals(o.member)
&& (isInterface == o.isInterface)
&& Objects.equals(rewrittenTarget, o.rewrittenTarget);
}
@@ -249,28 +249,32 @@
@Override
public String toString() {
- StringBuilder builder = new StringBuilder("MethodHandle: {")
+ StringBuilder builder =
+ new StringBuilder("MethodHandle: {")
.append(type)
.append(", ")
- .append(fieldOrMethod.toSourceString())
+ .append(member.toSourceString())
.append("}");
return builder.toString();
}
- @Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
if (indexedItems.addMethodHandle(this)) {
- if (fieldOrMethod.isDexMethod() && rewrittenTarget != null) {
- // If there is a rewritten target we need to use that to get the right name of the
- // targeted method (only member rebound methods take part in naming). The rest of the
- // indexed items are collected from fieldOrMethod.
- if (fieldOrMethod.asDexMethod().collectIndexedItemsExceptName(
- indexedItems, method, instructionOffset)) {
- rewrittenTarget.collectIndexedItemsName(indexedItems, method, instructionOffset);
- }
+ if (member.isDexField()) {
+ DexField field = member.asDexField();
+ field.collectIndexedItems(indexedItems);
} else {
- fieldOrMethod.collectIndexedItems(indexedItems, method, instructionOffset);
+ DexMethod method = member.asDexMethod();
+ if (rewrittenTarget != null) {
+ // If there is a rewritten target we need to use that to get the right name of the
+ // targeted method (only member rebound methods take part in naming). The rest of the
+ // indexed items are collected from method.
+ if (method.collectIndexedItemsExceptName(indexedItems)) {
+ rewrittenTarget.collectIndexedItemsName(indexedItems);
+ }
+ } else {
+ method.collectIndexedItems(indexedItems);
+ }
}
}
}
@@ -300,12 +304,12 @@
public DexMethod asMethod() {
assert isMethodHandle();
- return (DexMethod) fieldOrMethod;
+ return (DexMethod) member;
}
public DexField asField() {
assert isFieldHandle();
- return (DexField) fieldOrMethod;
+ return (DexField) member;
}
@Override
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 0a5014a..90c37ed 100644
--- a/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
@@ -221,6 +221,10 @@
: TraversalContinuation.CONTINUE);
}
+ public Kind getOriginKind() {
+ return originKind;
+ }
+
public boolean originatesFromDexResource() {
return originKind == Kind.DEX;
}
@@ -229,22 +233,20 @@
return originKind == Kind.CF;
}
- @Override
- public void collectIndexedItems(
- IndexedItemCollection indexedItems, DexMethod method, int instructionOffset) {
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
if (indexedItems.addClass(this)) {
- type.collectIndexedItems(indexedItems, method, instructionOffset);
+ type.collectIndexedItems(indexedItems);
if (superType != null) {
- superType.collectIndexedItems(indexedItems, method, instructionOffset);
+ superType.collectIndexedItems(indexedItems);
} else {
assert type.toDescriptorString().equals("Ljava/lang/Object;");
}
if (sourceFile != null) {
- sourceFile.collectIndexedItems(indexedItems, method, instructionOffset);
+ sourceFile.collectIndexedItems(indexedItems);
}
- annotations().collectIndexedItems(indexedItems, method, instructionOffset);
+ annotations().collectIndexedItems(indexedItems);
if (interfaces != null) {
- interfaces.collectIndexedItems(indexedItems, method, instructionOffset);
+ interfaces.collectIndexedItems(indexedItems);
}
if (getEnclosingMethodAttribute() != null) {
getEnclosingMethodAttribute().collectIndexedItems(indexedItems);
@@ -252,18 +254,8 @@
for (InnerClassAttribute attribute : getInnerClasses()) {
attribute.collectIndexedItems(indexedItems);
}
- synchronizedCollectAll(indexedItems, staticFields);
- synchronizedCollectAll(indexedItems, instanceFields);
- synchronized (methodCollection) {
- methodCollection.forEachMethod(m -> m.collectIndexedItems(indexedItems));
- }
- }
- }
-
- private static <T extends DexItem> void synchronizedCollectAll(
- IndexedItemCollection collection, T[] items) {
- synchronized (items) {
- collectAll(collection, items);
+ forEachField(field -> field.collectIndexedItems(indexedItems));
+ forEachMethod(method -> method.collectIndexedItems(indexedItems));
}
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexProto.java b/src/main/java/com/android/tools/r8/graph/DexProto.java
index a9a15f3..77b9c42 100644
--- a/src/main/java/com/android/tools/r8/graph/DexProto.java
+++ b/src/main/java/com/android/tools/r8/graph/DexProto.java
@@ -47,13 +47,11 @@
return "Proto " + shorty + " " + returnType + " " + parameters;
}
- @Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
if (indexedItems.addProto(this)) {
- shorty.collectIndexedItems(indexedItems, method, instructionOffset);
- returnType.collectIndexedItems(indexedItems, method, instructionOffset);
- parameters.collectIndexedItems(indexedItems, method, instructionOffset);
+ shorty.collectIndexedItems(indexedItems);
+ returnType.collectIndexedItems(indexedItems);
+ parameters.collectIndexedItems(indexedItems);
}
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexReference.java b/src/main/java/com/android/tools/r8/graph/DexReference.java
index c37c9de..b296b43 100644
--- a/src/main/java/com/android/tools/r8/graph/DexReference.java
+++ b/src/main/java/com/android/tools/r8/graph/DexReference.java
@@ -3,11 +3,10 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.graph;
+import com.android.tools.r8.dex.IndexedItemCollection;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
-import java.util.function.Predicate;
-import java.util.stream.Stream;
/**
* A common interface for {@link DexType}, {@link DexField}, and {@link DexMethod}.
@@ -30,6 +29,8 @@
BiConsumer<DexMethod, T> methodConsumer,
T arg);
+ public abstract void collectIndexedItems(IndexedItemCollection indexedItems);
+
public boolean isDexType() {
return false;
}
@@ -61,27 +62,4 @@
public DexMethod asDexMethod() {
return null;
}
-
- public static Stream<DexReference> filterDexReference(Stream<DexItem> stream) {
- return DexItem.filter(stream, DexReference.class);
- }
-
- private static <T extends DexReference> Stream<T> filter(
- Stream<DexReference> stream,
- Predicate<DexReference> pred,
- Function<DexReference, T> f) {
- return stream.filter(pred).map(f);
- }
-
- public static Stream<DexType> filterDexType(Stream<DexReference> stream) {
- return filter(stream, DexReference::isDexType, DexReference::asDexType);
- }
-
- public static Stream<DexField> filterDexField(Stream<DexReference> stream) {
- return filter(stream, DexReference::isDexField, DexReference::asDexField);
- }
-
- public static Stream<DexMethod> filterDexMethod(Stream<DexReference> stream) {
- return filter(stream, DexReference::isDexMethod, DexReference::asDexMethod);
- }
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexString.java b/src/main/java/com/android/tools/r8/graph/DexString.java
index 03303f6..602a6b7 100644
--- a/src/main/java/com/android/tools/r8/graph/DexString.java
+++ b/src/main/java/com/android/tools/r8/graph/DexString.java
@@ -239,9 +239,7 @@
return offset;
}
- @Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
indexedItems.addString(this);
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexType.java b/src/main/java/com/android/tools/r8/graph/DexType.java
index 1190570..81c4dc5 100644
--- a/src/main/java/com/android/tools/r8/graph/DexType.java
+++ b/src/main/java/com/android/tools/r8/graph/DexType.java
@@ -171,12 +171,9 @@
}
@Override
- public void collectIndexedItems(
- IndexedItemCollection collection, DexMethod method, int instructionOffset) {
+ public void collectIndexedItems(IndexedItemCollection collection) {
if (collection.addType(this)) {
- collection
- .getRenamedDescriptor(this)
- .collectIndexedItems(collection, method, instructionOffset);
+ collection.getRenamedDescriptor(this).collectIndexedItems(collection);
}
}
@@ -387,6 +384,19 @@
return newBase.toArrayType(getNumberOfLeadingSquareBrackets(), dexItemFactory);
}
+ public DexType replacePackage(String newPackageDescriptor, DexItemFactory dexItemFactory) {
+ assert isClassType();
+ String descriptorString = toDescriptorString();
+ int lastPackageSeparator = descriptorString.lastIndexOf('/');
+ String newDescriptorString = "L" + newPackageDescriptor + "/";
+ if (lastPackageSeparator >= 0) {
+ newDescriptorString += descriptorString.substring(lastPackageSeparator + 1);
+ } else {
+ newDescriptorString += descriptorString.substring(1);
+ }
+ return dexItemFactory.createType(newDescriptorString);
+ }
+
public DexType toArrayType(int dimensions, DexItemFactory dexItemFactory) {
byte[] content = new byte[descriptor.content.length + dimensions];
Arrays.fill(content, 0, dimensions, (byte) '[');
diff --git a/src/main/java/com/android/tools/r8/graph/DexTypeList.java b/src/main/java/com/android/tools/r8/graph/DexTypeList.java
index 2272c98..c61de91 100644
--- a/src/main/java/com/android/tools/r8/graph/DexTypeList.java
+++ b/src/main/java/com/android/tools/r8/graph/DexTypeList.java
@@ -9,6 +9,7 @@
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.utils.ArrayUtils;
import java.util.Arrays;
+import java.util.stream.Stream;
public class DexTypeList extends DexItem {
@@ -38,11 +39,9 @@
return Arrays.hashCode(values);
}
- @Override
- void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
+ void collectIndexedItems(IndexedItemCollection indexedItems) {
for (DexType type : values) {
- type.collectIndexedItems(indexedItems, method, instructionOffset);
+ type.collectIndexedItems(indexedItems);
}
}
@@ -68,6 +67,10 @@
return values.length;
}
+ public Stream<DexType> stream() {
+ return Stream.of(values);
+ }
+
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
diff --git a/src/main/java/com/android/tools/r8/graph/DexValue.java b/src/main/java/com/android/tools/r8/graph/DexValue.java
index 96b6b5a..2fe8c3f 100644
--- a/src/main/java/com/android/tools/r8/graph/DexValue.java
+++ b/src/main/java/com/android/tools/r8/graph/DexValue.java
@@ -307,6 +307,10 @@
dest.putByte((byte) ((arg << 5) | kind.toByte()));
}
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
+ // Intentionally left empty
+ }
+
@Override
void collectMixedSectionItems(MixedSectionCollection mixedItems) {
// Should never be visited.
@@ -380,12 +384,6 @@
private abstract static class SimpleDexValue extends DexValue {
@Override
- public void collectIndexedItems(
- IndexedItemCollection indexedItems, DexMethod method, int instructionOffset) {
- // Intentionally left empty
- }
-
- @Override
public void sort() {
// Intentionally empty
}
@@ -1054,12 +1052,6 @@
}
@Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
- value.collectIndexedItems(indexedItems, method, instructionOffset);
- }
-
- @Override
public void sort() {
// Intentionally empty.
}
@@ -1094,6 +1086,11 @@
}
@Override
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
+ value.collectIndexedItems(indexedItems);
+ }
+
+ @Override
public DexValueString asDexValueString() {
return this;
}
@@ -1152,6 +1149,11 @@
this.nameComputationInfo = nameComputationInfo;
}
+ @Override
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
+ value.collectIndexedItems(indexedItems);
+ }
+
public NameComputationInfo<?> getNameComputationInfo() {
return nameComputationInfo;
}
@@ -1223,9 +1225,8 @@
}
@Override
- public void collectIndexedItems(
- IndexedItemCollection indexedItems, DexMethod method, int instructionOffset) {
- value.collectIndexedItems(indexedItems, method, instructionOffset);
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
+ value.collectIndexedItems(indexedItems);
}
@Override
@@ -1256,9 +1257,8 @@
}
@Override
- public void collectIndexedItems(
- IndexedItemCollection indexedItems, DexMethod method, int instructionOffset) {
- value.collectIndexedItems(indexedItems, method, instructionOffset);
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
+ value.collectIndexedItems(indexedItems);
}
@Override
@@ -1289,9 +1289,8 @@
}
@Override
- public void collectIndexedItems(
- IndexedItemCollection indexedItems, DexMethod method, int instructionOffset) {
- value.collectIndexedItems(indexedItems, method, instructionOffset);
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
+ value.collectIndexedItems(indexedItems);
}
@Override
@@ -1322,9 +1321,8 @@
}
@Override
- public void collectIndexedItems(
- IndexedItemCollection indexedItems, DexMethod method, int instructionOffset) {
- value.collectIndexedItems(indexedItems, method, instructionOffset);
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
+ value.collectIndexedItems(indexedItems);
}
@Override
@@ -1365,9 +1363,8 @@
}
@Override
- public void collectIndexedItems(
- IndexedItemCollection indexedItems, DexMethod method, int instructionOffset) {
- value.collectIndexedItems(indexedItems, method, instructionOffset);
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
+ value.collectIndexedItems(indexedItems);
}
@Override
@@ -1394,9 +1391,10 @@
}
@Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
- collectAll(indexedItems, values);
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
+ for (DexValue value : values) {
+ value.collectIndexedItems(indexedItems);
+ }
}
@Override
@@ -1492,9 +1490,8 @@
}
@Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
- value.collectIndexedItems(indexedItems, method, instructionOffset);
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
+ value.collectIndexedItems(indexedItems);
}
@Override
@@ -1736,9 +1733,8 @@
}
@Override
- public void collectIndexedItems(
- IndexedItemCollection indexedItems, DexMethod method, int instructionOffset) {
- value.collectIndexedItems(indexedItems, method, instructionOffset);
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
+ value.collectIndexedItems(indexedItems);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/graph/GraphLens.java b/src/main/java/com/android/tools/r8/graph/GraphLens.java
index edce8d8..2491193 100644
--- a/src/main/java/com/android/tools/r8/graph/GraphLens.java
+++ b/src/main/java/com/android/tools/r8/graph/GraphLens.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.graph;
import com.android.tools.r8.ir.code.Invoke.Type;
+import com.android.tools.r8.ir.desugar.InterfaceProcessor.InterfaceProcessorNestedGraphLens;
import com.android.tools.r8.shaking.KeepInfoCollection;
import com.android.tools.r8.utils.SetUtils;
import com.google.common.collect.BiMap;
@@ -151,6 +152,12 @@
public abstract DexField getRenamedFieldSignature(DexField originalField);
+ public final DexMember<?, ?> getRenamedMemberSignature(DexMember<?, ?> originalMember) {
+ return originalMember.isDexField()
+ ? getRenamedFieldSignature(originalMember.asDexField())
+ : getRenamedMethodSignature(originalMember.asDexMethod());
+ }
+
public final DexMethod getRenamedMethodSignature(DexMethod originalMethod) {
return getRenamedMethodSignature(originalMethod, null);
}
@@ -250,6 +257,22 @@
return this == getIdentityLens();
}
+ public boolean isInterfaceProcessorLens() {
+ return false;
+ }
+
+ public InterfaceProcessorNestedGraphLens asInterfaceProcessorLens() {
+ return null;
+ }
+
+ public boolean isGraphLensWithPrevious() {
+ return false;
+ }
+
+ public GraphLensWithPrevious asGraphLensWithPrevious() {
+ return null;
+ }
+
public GraphLens withCodeRewritingsApplied() {
if (hasCodeRewritings()) {
return new ClearCodeRewritingGraphLens(this);
@@ -471,7 +494,8 @@
// This lens clears all code rewriting (lookup methods mimics identity lens behavior) but still
// relies on the previous lens for names (getRenamed/Original methods).
- public static class ClearCodeRewritingGraphLens extends IdentityGraphLens {
+ public static class ClearCodeRewritingGraphLens extends IdentityGraphLens
+ implements GraphLensWithPrevious {
private final GraphLens previous;
@@ -480,6 +504,21 @@
}
@Override
+ public boolean isGraphLensWithPrevious() {
+ return true;
+ }
+
+ @Override
+ public GraphLensWithPrevious asGraphLensWithPrevious() {
+ return this;
+ }
+
+ @Override
+ public GraphLens getPrevious() {
+ return previous;
+ }
+
+ @Override
public DexType getOriginalType(DexType type) {
return previous.getOriginalType(type);
}
@@ -512,6 +551,11 @@
}
}
+ public interface GraphLensWithPrevious {
+
+ GraphLens getPrevious();
+ }
+
/**
* GraphLens implementation with a parent lens using a simple mapping for type, method and field
* mapping.
@@ -522,7 +566,7 @@
* #mapInvocationType(DexMethod, DexMethod, Type)} if the default name mapping applies, and only
* invocation type might need to change.
*/
- public static class NestedGraphLens extends GraphLens {
+ public static class NestedGraphLens extends GraphLens implements GraphLensWithPrevious {
protected GraphLens previousLens;
protected final DexItemFactory dexItemFactory;
@@ -535,7 +579,7 @@
// Maps that store the original signature of fields and methods that have been affected, for
// example, by vertical class merging. Needed to generate a correct Proguard map in the end.
protected final BiMap<DexField, DexField> originalFieldSignatures;
- protected final BiMap<DexMethod, DexMethod> originalMethodSignatures;
+ protected BiMap<DexMethod, DexMethod> originalMethodSignatures;
// Overrides this if the sub type needs to be a nested lens while it doesn't have any mappings
// at all, e.g., publicizer lens that changes invocation type only.
@@ -564,6 +608,11 @@
this.dexItemFactory = dexItemFactory;
}
+ @Override
+ public GraphLens getPrevious() {
+ return previousLens;
+ }
+
public <T> T withAlternativeParentLens(GraphLens lens, Supplier<T> action) {
GraphLens oldParent = previousLens;
previousLens = lens;
@@ -573,6 +622,16 @@
}
@Override
+ public boolean isGraphLensWithPrevious() {
+ return true;
+ }
+
+ @Override
+ public NestedGraphLens asGraphLensWithPrevious() {
+ return this;
+ }
+
+ @Override
public DexType getOriginalType(DexType type) {
return previousLens.getOriginalType(type);
}
diff --git a/src/main/java/com/android/tools/r8/graph/IndexedDexItem.java b/src/main/java/com/android/tools/r8/graph/IndexedDexItem.java
index 0c115e1..96bfb47 100644
--- a/src/main/java/com/android/tools/r8/graph/IndexedDexItem.java
+++ b/src/main/java/com/android/tools/r8/graph/IndexedDexItem.java
@@ -3,17 +3,12 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.graph;
-import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.dex.MixedSectionCollection;
/** Subset of dex items that are referenced by some table index. */
public abstract class IndexedDexItem extends CachedHashValueDexItem {
@Override
- public abstract void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset);
-
- @Override
void collectMixedSectionItems(MixedSectionCollection mixedItems) {
// Should never be visited.
assert false;
diff --git a/src/main/java/com/android/tools/r8/graph/ParameterAnnotationsList.java b/src/main/java/com/android/tools/r8/graph/ParameterAnnotationsList.java
index 6ff5c75..4b21c2b 100644
--- a/src/main/java/com/android/tools/r8/graph/ParameterAnnotationsList.java
+++ b/src/main/java/com/android/tools/r8/graph/ParameterAnnotationsList.java
@@ -82,10 +82,10 @@
return false;
}
- @Override
- public void collectIndexedItems(
- IndexedItemCollection indexedItems, DexMethod method, int instructionOffset) {
- collectAll(indexedItems, values);
+ public void collectIndexedItems(IndexedItemCollection indexedItems) {
+ for (DexAnnotationSet value : values) {
+ value.collectIndexedItems(indexedItems);
+ }
}
@Override
diff --git a/src/main/java/com/android/tools/r8/graph/ProgramPackage.java b/src/main/java/com/android/tools/r8/graph/ProgramPackage.java
index 28fc4e2..c244576 100644
--- a/src/main/java/com/android/tools/r8/graph/ProgramPackage.java
+++ b/src/main/java/com/android/tools/r8/graph/ProgramPackage.java
@@ -23,6 +23,14 @@
classes.add(clazz);
}
+ public String getLastPackageName() {
+ int index = packageDescriptor.lastIndexOf('/');
+ if (index >= 0) {
+ return packageDescriptor.substring(index + 1);
+ }
+ return packageDescriptor;
+ }
+
public void forEachClass(Consumer<DexProgramClass> consumer) {
forEach(consumer);
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/ClassMerger.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/ClassMerger.java
index e9aa061..51ef31e 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/ClassMerger.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/ClassMerger.java
@@ -4,15 +4,24 @@
package com.android.tools.r8.horizontalclassmerging;
+import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexAnnotationSet;
+import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexField;
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.DexType;
+import com.android.tools.r8.graph.FieldAccessFlags;
import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.shaking.FieldAccessInfoCollectionModifier;
import com.android.tools.r8.utils.MethodSignatureEquivalence;
import com.google.common.base.Equivalence.Wrapper;
+import it.unimi.dsi.fastutil.objects.Reference2IntMap;
+import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap;
import java.util.Collection;
import java.util.IdentityHashMap;
import java.util.Map;
@@ -28,24 +37,34 @@
private final Collection<DexProgramClass> toMergeGroup;
private final DexItemFactory dexItemFactory;
private final HorizontalClassMergerGraphLens.Builder lensBuilder;
+ private final FieldAccessInfoCollectionModifier.Builder fieldAccessChangesBuilder;
+ private final Reference2IntMap<DexType> classIdentifiers = new Reference2IntOpenHashMap<>();
private final Map<DexProto, ConstructorMerger.Builder> constructorMergers;
+ private final DexField classIdField;
ClassMerger(
AppView<?> appView,
HorizontalClassMergerGraphLens.Builder lensBuilder,
+ FieldAccessInfoCollectionModifier.Builder fieldAccessChangesBuilder,
DexProgramClass target,
Collection<DexProgramClass> toMergeGroup) {
this.appView = appView;
this.lensBuilder = lensBuilder;
+ this.fieldAccessChangesBuilder = fieldAccessChangesBuilder;
this.target = target;
this.toMergeGroup = toMergeGroup;
- this.constructorMergers = new IdentityHashMap<>();
+ this.constructorMergers = new IdentityHashMap<>();
this.dexItemFactory = appView.dexItemFactory();
+
+ // TODO(b/165498187): ensure the name for the field is fresh
+ classIdField = dexItemFactory.createField(target.type, dexItemFactory.intType, "$r8$classId");
+
+ buildClassIdentifierMap();
}
- private Wrapper<DexMethod> bySignature(DexMethod method) {
+ Wrapper<DexMethod> bySignature(DexMethod method) {
return MethodSignatureEquivalence.get().wrap(method);
}
@@ -56,7 +75,14 @@
.add(method);
}
- private void merge(DexProgramClass toMerge) {
+ void buildClassIdentifierMap() {
+ classIdentifiers.put(target.type, 0);
+ for (DexProgramClass toMerge : toMergeGroup) {
+ classIdentifiers.put(toMerge.type, classIdentifiers.size());
+ }
+ }
+
+ void merge(DexProgramClass toMerge) {
toMerge.forEachProgramMethod(
programMethod -> {
DexEncodedMethod method = programMethod.getDefinition();
@@ -98,8 +124,8 @@
void mergeConstructors() {
for (ConstructorMerger.Builder builder : constructorMergers.values()) {
- ConstructorMerger constructorMerger = builder.build(appView, target);
- constructorMerger.merge(lensBuilder);
+ ConstructorMerger constructorMerger = builder.build(appView, target, classIdField);
+ constructorMerger.merge(lensBuilder, fieldAccessChangesBuilder, classIdentifiers);
}
}
@@ -117,8 +143,20 @@
});
}
+ void appendClassIdField() {
+ DexEncodedField encodedField =
+ new DexEncodedField(
+ classIdField,
+ FieldAccessFlags.fromSharedAccessFlags(
+ Constants.ACC_PUBLIC + Constants.ACC_FINAL + Constants.ACC_SYNTHETIC),
+ DexAnnotationSet.empty(),
+ null);
+ target.appendInstanceField(encodedField);
+ }
+
public void mergeGroup() {
addTargetConstructors();
+ appendClassIdField();
for (DexProgramClass clazz : toMergeGroup) {
merge(clazz);
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/ConstructorEntryPoint.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/ConstructorEntryPoint.java
index b182afb..ff2a898 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/ConstructorEntryPoint.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/ConstructorEntryPoint.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.horizontalclassmerging;
+import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.ir.code.Invoke.Type;
import com.android.tools.r8.ir.code.Position;
@@ -12,78 +13,117 @@
import com.android.tools.r8.ir.conversion.IRBuilder;
import com.android.tools.r8.ir.synthetic.SyntheticSourceCode;
import com.android.tools.r8.utils.IntBox;
+import it.unimi.dsi.fastutil.ints.Int2ReferenceMap.Entry;
+import it.unimi.dsi.fastutil.ints.Int2ReferenceSortedMap;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
/**
* Generate code of the form: <code>
* MyClass(int constructorId, [args]) {
* switch (constructorId) {
- * case 0:
- * this.Constructor$A([args]);
- * return;
* case 1:
* this.Constructor$B([args]);
* return;
* ...
* default:
- * throw null;
+ * this.Constructor$A([args]);
+ * return;
* }
* }
* </code>
*/
public class ConstructorEntryPoint extends SyntheticSourceCode {
- private final Collection<DexMethod> typeConstructors;
+ private final DexField classIdField;
+ private final Int2ReferenceSortedMap<DexMethod> typeConstructors;
public ConstructorEntryPoint(
- Collection<DexMethod> typeConstructors, DexMethod method, Position callerPosition) {
- super(method.holder, method, callerPosition);
+ Int2ReferenceSortedMap<DexMethod> typeConstructors,
+ DexMethod newConstructor,
+ DexField classIdField,
+ Position callerPosition,
+ DexMethod originalMethod) {
+ super(newConstructor.holder, newConstructor, callerPosition, originalMethod);
this.typeConstructors = typeConstructors;
+ this.classIdField = classIdField;
}
- @Override
- protected void prepareInstructions() {
- int typeConstructorCount = typeConstructors.size();
- int idRegister = getParamRegister(0);
+ void addConstructorInvoke(DexMethod typeConstructor) {
+ add(
+ builder -> {
+ List<Value> arguments = new ArrayList<>(typeConstructor.getArity() + 1);
+ arguments.add(builder.getReceiverValue());
- int[] keys = new int[typeConstructorCount];
- int[] offsets = new int[typeConstructorCount];
+ // If there are any arguments add them to the list.
+ for (int i = 0; i < typeConstructor.getArity(); i++) {
+ arguments.add(builder.getArgumentValues().get(i));
+ }
+
+ builder.addInvoke(Type.DIRECT, typeConstructor, typeConstructor.proto, arguments, false);
+ });
+ }
+
+ /** Assign the given register to the class id field. */
+ void addRegisterClassIdAssignment(int idRegister) {
+ add(builder -> builder.addInstancePut(idRegister, getReceiverRegister(), classIdField));
+ }
+
+ /** Assign the given constant integer value to the class id field. */
+ void addConstantRegisterClassIdAssignment(int classId) {
+ int idRegister = nextRegister(ValueType.INT);
+ add(builder -> builder.addIntConst(idRegister, classId));
+ addRegisterClassIdAssignment(idRegister);
+ }
+
+ protected void prepareMultiConstructorInstructions() {
+ int typeConstructorCount = typeConstructors.size();
+ int idRegister = getParamRegister(method.getArity() - 1);
+
+ addRegisterClassIdAssignment(idRegister);
+
+ int[] keys = new int[typeConstructorCount - 1];
+ int[] offsets = new int[typeConstructorCount - 1];
IntBox fallthrough = new IntBox();
int switchIndex = lastInstructionIndex();
add(
builder -> builder.addSwitch(idRegister, keys, fallthrough.get(), offsets),
builder -> endsSwitch(builder, switchIndex, fallthrough.get(), offsets));
- fallthrough.set(nextInstructionIndex());
- int nullRegister = nextRegister(ValueType.OBJECT);
- add(builder -> builder.addNullConst(nullRegister));
- add(builder -> builder.addThrow(nullRegister), endsBlock);
-
int index = 0;
- for (DexMethod typeConstructor : typeConstructors) {
- keys[index] = index;
- offsets[index] = nextInstructionIndex();
+ for (Entry<DexMethod> entry : typeConstructors.int2ReferenceEntrySet()) {
+ int classId = entry.getIntKey();
+ DexMethod typeConstructor = entry.getValue();
- add(
- builder -> {
- List<Value> arguments = new ArrayList<>(typeConstructor.getArity());
- arguments.add(builder.getReceiverValue());
- int paramIndex = 0;
- for (Value argument : builder.getArgumentValues()) {
- if (paramIndex++ >= typeConstructor.getArity()) {
- break;
- }
- arguments.add(argument);
- }
- builder.addInvoke(
- Type.DIRECT, typeConstructor, typeConstructor.proto, arguments, false);
- });
+ if (index == 0) {
+ // The first constructor is the fallthrough case.
+ fallthrough.set(nextInstructionIndex());
+ } else {
+ // All subsequent constructors are matched on a specific case.
+ keys[index - 1] = classId;
+ offsets[index - 1] = nextInstructionIndex();
+ }
+ addConstructorInvoke(typeConstructor);
add(IRBuilder::addReturn, endsBlock);
index++;
}
}
+
+ protected void prepareSingleConstructorInstructions() {
+ Entry<DexMethod> entry = typeConstructors.int2ReferenceEntrySet().first();
+ addConstantRegisterClassIdAssignment(entry.getIntKey());
+ addConstructorInvoke(entry.getValue());
+ add(IRBuilder::addReturn, endsBlock);
+ }
+
+ @Override
+ protected void prepareInstructions() {
+ if (typeConstructors.size() > 1) {
+ prepareMultiConstructorInstructions();
+ } else {
+ prepareSingleConstructorInstructions();
+ }
+ }
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/ConstructorEntryPointSynthesizedCode.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/ConstructorEntryPointSynthesizedCode.java
new file mode 100644
index 0000000..7d250bb
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/ConstructorEntryPointSynthesizedCode.java
@@ -0,0 +1,48 @@
+// 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.horizontalclassmerging;
+
+import com.android.tools.r8.graph.DexField;
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.UseRegistry;
+import com.android.tools.r8.ir.synthetic.AbstractSynthesizedCode;
+import it.unimi.dsi.fastutil.ints.Int2ReferenceSortedMap;
+import java.util.function.Consumer;
+
+public class ConstructorEntryPointSynthesizedCode extends AbstractSynthesizedCode {
+ private final DexMethod newConstructor;
+ private final DexMethod originalMethod;
+ private final DexField classIdField;
+ private final Int2ReferenceSortedMap<DexMethod> typeConstructors;
+
+ public ConstructorEntryPointSynthesizedCode(
+ Int2ReferenceSortedMap<DexMethod> typeConstructors,
+ DexMethod newConstructor,
+ DexField classIdField,
+ DexMethod originalMethod) {
+ this.typeConstructors = typeConstructors;
+ this.newConstructor = newConstructor;
+ this.classIdField = classIdField;
+ this.originalMethod = originalMethod;
+ }
+
+ @Override
+ public SourceCodeProvider getSourceCodeProvider() {
+ return callerPosition ->
+ new ConstructorEntryPoint(
+ typeConstructors, newConstructor, classIdField, callerPosition, originalMethod);
+ }
+
+ @Override
+ public Consumer<UseRegistry> getRegistryCallback() {
+ return this::registerReachableDefinitions;
+ }
+
+ private void registerReachableDefinitions(UseRegistry registry) {
+ for (DexMethod typeConstructor : typeConstructors.values()) {
+ registry.registerInvokeDirect(typeConstructor);
+ }
+ }
+}
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 aae7b0e..76f4814 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/ConstructorMerger.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/ConstructorMerger.java
@@ -8,6 +8,7 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexAnnotationSet;
import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
@@ -15,25 +16,31 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.MethodAccessFlags;
import com.android.tools.r8.graph.ParameterAnnotationsList;
-import com.android.tools.r8.ir.synthetic.SynthesizedCode;
+import com.android.tools.r8.shaking.FieldAccessInfoCollectionModifier;
+import it.unimi.dsi.fastutil.ints.Int2ReferenceAVLTreeMap;
+import it.unimi.dsi.fastutil.ints.Int2ReferenceSortedMap;
+import it.unimi.dsi.fastutil.objects.Reference2IntMap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
-import java.util.IdentityHashMap;
import java.util.List;
-import java.util.Map;
public class ConstructorMerger {
private final AppView<?> appView;
private final DexProgramClass target;
private final Collection<DexEncodedMethod> constructors;
private final DexItemFactory dexItemFactory;
+ private final DexField classIdField;
ConstructorMerger(
- AppView<?> appView, DexProgramClass target, Collection<DexEncodedMethod> constructors) {
+ AppView<?> appView,
+ DexProgramClass target,
+ Collection<DexEncodedMethod> constructors,
+ DexField classIdField) {
this.appView = appView;
this.target = target;
this.constructors = constructors;
+ this.classIdField = classIdField;
// Constructors should not be empty and all constructors should have the same prototype.
assert !constructors.isEmpty();
@@ -54,11 +61,16 @@
return this;
}
- public ConstructorMerger build(AppView<?> appView, DexProgramClass target) {
- return new ConstructorMerger(appView, target, constructors);
+ public ConstructorMerger build(
+ AppView<?> appView, DexProgramClass target, DexField classIdField) {
+ return new ConstructorMerger(appView, target, constructors, classIdField);
}
}
+ private boolean isTrivialMerge() {
+ return constructors.size() == 1;
+ }
+
private DexMethod moveConstructor(DexEncodedMethod constructor) {
DexMethod method =
dexItemFactory.createFreshMethodName(
@@ -72,7 +84,9 @@
target.removeMethod(constructor.toReference());
}
- target.addDirectMethod(constructor.toTypeSubstitutedMethod(method));
+ DexEncodedMethod encodedMethod = constructor.toTypeSubstitutedMethod(method);
+ encodedMethod.getMutableOptimizationInfo().markForceInline();
+ target.addDirectMethod(encodedMethod);
return method;
}
@@ -80,6 +94,10 @@
DexEncodedMethod firstConstructor = constructors.stream().findFirst().get();
DexProto oldProto = firstConstructor.getProto();
+ if (isTrivialMerge()) {
+ return oldProto;
+ }
+
List<DexType> parameters = new ArrayList<>();
Collections.addAll(parameters, oldProto.parameters.values);
parameters.add(dexItemFactory.intType);
@@ -93,64 +111,63 @@
}
/** Synthesize a new method which selects the constructor based on a parameter type. */
- void mergeMany(HorizontalClassMergerGraphLens.Builder lensBuilder) {
- Map<DexType, DexMethod> typeConstructors = new IdentityHashMap<>();
+ void merge(
+ HorizontalClassMergerGraphLens.Builder lensBuilder,
+ FieldAccessInfoCollectionModifier.Builder fieldAccessChangesBuilder,
+ Reference2IntMap<DexType> classIdentifiers) {
+ // Tree map as must be sorted.
+ Int2ReferenceSortedMap<DexMethod> typeConstructorClassMap = new Int2ReferenceAVLTreeMap<>();
+ int classFileVersion = -1;
for (DexEncodedMethod constructor : constructors) {
- typeConstructors.put(constructor.holder(), moveConstructor(constructor));
+ if (constructor.hasClassFileVersion()) {
+ classFileVersion = Integer.max(classFileVersion, constructor.getClassFileVersion());
+ }
+ DexMethod movedConstructor = moveConstructor(constructor);
+ lensBuilder.recordOriginalSignature(constructor.method, movedConstructor);
+ typeConstructorClassMap.put(
+ classIdentifiers.getInt(constructor.getHolderType()), movedConstructor);
}
DexProto newProto = getNewConstructorProto();
- DexMethod newConstructor =
+ DexMethod originalConstructorReference = constructors.iterator().next().method;
+ DexMethod newConstructorReference =
appView.dexItemFactory().createMethod(target.type, newProto, dexItemFactory.initMethodName);
- SynthesizedCode synthesizedCode =
- new SynthesizedCode(
- callerPosition ->
- new ConstructorEntryPoint(
- typeConstructors.values(), newConstructor, callerPosition));
- DexEncodedMethod newMethod =
+ ConstructorEntryPointSynthesizedCode synthesizedCode =
+ new ConstructorEntryPointSynthesizedCode(
+ typeConstructorClassMap,
+ newConstructorReference,
+ classIdField,
+ originalConstructorReference);
+ DexEncodedMethod newConstructor =
new DexEncodedMethod(
- newConstructor,
+ newConstructorReference,
getAccessFlags(),
DexAnnotationSet.empty(),
ParameterAnnotationsList.empty(),
- synthesizedCode);
+ synthesizedCode,
+ classFileVersion,
+ true);
- // Map each old constructor to the newly synthesized constructor in the graph lens.
- int constructorId = 0;
- for (DexEncodedMethod constructor : constructors) {
- lensBuilder.mapConstructor(constructor.method, newMethod.method, constructorId++);
- }
-
- target.addDirectMethod(newMethod);
- }
-
- /**
- * The constructor does not conflict with any other constructors. Add the constructor (if any) to
- * the target directly.
- */
- void mergeTrivial(HorizontalClassMergerGraphLens.Builder lensBuilder) {
- assert constructors.size() <= 1;
-
- if (!constructors.isEmpty()) {
- DexEncodedMethod constructor = constructors.iterator().next();
-
- // Only move the constructor if it is not already in the target type.
- if (constructor.holder() != target.type) {
- DexEncodedMethod newConstructor =
- constructor.toRenamedHolderMethod(target.type, dexItemFactory);
- target.addDirectMethod(constructor);
- lensBuilder.moveConstructor(constructor.method, newConstructor.method);
+ if (isTrivialMerge()) {
+ // The constructor does not require the additional argument, just map it like a regular
+ // method.
+ lensBuilder.mapMethod(constructors.iterator().next().method, newConstructorReference);
+ } else {
+ // Map each old constructor to the newly synthesized constructor in the graph lens.
+ for (DexEncodedMethod oldConstructor : constructors) {
+ lensBuilder.mapMergedConstructor(
+ oldConstructor.method,
+ newConstructorReference,
+ classIdentifiers.getInt(oldConstructor.getHolderType()));
}
}
- }
+ // Map the first constructor to the newly synthesized constructor.
+ lensBuilder.recordExtraOriginalSignature(originalConstructorReference, newConstructorReference);
- public void merge(HorizontalClassMergerGraphLens.Builder lensBuilder) {
- if (constructors.size() <= 1) {
- mergeTrivial(lensBuilder);
- } else {
- mergeMany(lensBuilder);
- }
+ target.addDirectMethod(newConstructor);
+
+ fieldAccessChangesBuilder.fieldWrittenByMethod(classIdField, newConstructorReference);
}
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java
index 60949e5..f7ac858 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java
@@ -10,11 +10,13 @@
import com.android.tools.r8.horizontalclassmerging.policies.NoFields;
import com.android.tools.r8.horizontalclassmerging.policies.NoInterfaces;
import com.android.tools.r8.horizontalclassmerging.policies.NoInternalUtilityClasses;
-import com.android.tools.r8.horizontalclassmerging.policies.NoOverlappingConstructors;
+import com.android.tools.r8.horizontalclassmerging.policies.NoRuntimeTypeChecks;
import com.android.tools.r8.horizontalclassmerging.policies.NoStaticClassInitializer;
import com.android.tools.r8.horizontalclassmerging.policies.NotEntryPoint;
import com.android.tools.r8.horizontalclassmerging.policies.SameParentClass;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.shaking.ClassMergingEnqueuerExtension;
+import com.android.tools.r8.shaking.FieldAccessInfoCollectionModifier;
import com.android.tools.r8.shaking.MainDexClasses;
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
@@ -25,26 +27,25 @@
import java.util.Map;
public class HorizontalClassMerger {
-
private final AppView<AppInfoWithLiveness> appView;
- private final MainDexClasses mainDexClasses;
-
private final PolicyExecutor policyExecutor;
public HorizontalClassMerger(
- AppView<AppInfoWithLiveness> appView, MainDexClasses mainDexClasses) {
+ AppView<AppInfoWithLiveness> appView,
+ MainDexClasses mainDexClasses,
+ ClassMergingEnqueuerExtension classMergingEnqueuerExtension) {
this.appView = appView;
- this.mainDexClasses = mainDexClasses;
List<Policy> policies =
ImmutableList.of(
new NoFields(),
+ // TODO(b/166071504): Allow merging of classes that implement interfaces.
new NoInterfaces(),
new NoStaticClassInitializer(),
+ new NoRuntimeTypeChecks(classMergingEnqueuerExtension),
new NotEntryPoint(appView.dexItemFactory()),
new NoInternalUtilityClasses(appView.dexItemFactory()),
- new SameParentClass(),
- new NoOverlappingConstructors()
+ new SameParentClass()
// TODO: add policies
);
@@ -76,6 +77,8 @@
Map<DexType, DexType> mergedClasses = new IdentityHashMap<>();
HorizontalClassMergerGraphLens.Builder lensBuilder =
new HorizontalClassMergerGraphLens.Builder();
+ FieldAccessInfoCollectionModifier.Builder fieldAccessChangesBuilder =
+ new FieldAccessInfoCollectionModifier.Builder();
// TODO(b/166577694): Replace Collection<DexProgramClass> with MergeGroup
for (Collection<DexProgramClass> group : groups) {
@@ -88,12 +91,14 @@
mergedClasses.put(clazz.type, target.type);
}
- ClassMerger merger = new ClassMerger(appView, lensBuilder, target, group);
+ ClassMerger merger =
+ new ClassMerger(appView, lensBuilder, fieldAccessChangesBuilder, target, group);
merger.mergeGroup();
}
HorizontalClassMergerGraphLens lens =
- new TreeFixer(appView, lensBuilder, mergedClasses).fixupTypeReferences();
+ new TreeFixer(appView, lensBuilder, fieldAccessChangesBuilder, mergedClasses)
+ .fixupTypeReferences();
return lens;
}
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMergerGraphLens.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMergerGraphLens.java
index 451e550..4389282 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMergerGraphLens.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMergerGraphLens.java
@@ -10,6 +10,8 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.GraphLens.NestedGraphLens;
+import com.android.tools.r8.ir.code.Invoke.Type;
+import com.android.tools.r8.ir.conversion.ExtraConstantIntParameter;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import java.util.Collections;
@@ -20,14 +22,18 @@
public class HorizontalClassMergerGraphLens extends NestedGraphLens {
private final AppView<?> appView;
+ private final Map<DexMethod, Integer> constructorIds;
+ private final Map<DexMethod, DexMethod> originalConstructorSignatures;
private HorizontalClassMergerGraphLens(
AppView<?> appView,
+ Map<DexMethod, Integer> constructorIds,
Map<DexType, DexType> typeMap,
Map<DexField, DexField> fieldMap,
Map<DexMethod, DexMethod> methodMap,
BiMap<DexField, DexField> originalFieldSignatures,
BiMap<DexMethod, DexMethod> originalMethodSignatures,
+ Map<DexMethod, DexMethod> originalConstructorSignatures,
GraphLens previousLens) {
super(
typeMap,
@@ -38,12 +44,44 @@
previousLens,
appView.dexItemFactory());
this.appView = appView;
+ this.constructorIds = constructorIds;
+ this.originalConstructorSignatures = originalConstructorSignatures;
+ }
+
+ @Override
+ public DexMethod getOriginalMethodSignature(DexMethod method) {
+ DexMethod originalConstructor = originalConstructorSignatures.get(method);
+ if (originalConstructor == null) {
+ return super.getOriginalMethodSignature(method);
+ }
+ return previousLens.getOriginalMethodSignature(originalConstructor);
}
public HorizontallyMergedClasses getHorizontallyMergedClasses() {
return new HorizontallyMergedClasses(this.typeMap);
}
+ /**
+ * If an overloaded constructor is requested, add the constructor id as a parameter to the
+ * constructor. Otherwise return the lookup on the underlying graph lens.
+ */
+ @Override
+ public GraphLensLookupResult lookupMethod(DexMethod method, DexMethod context, Type type) {
+ Integer constructorId = constructorIds.get(method);
+ GraphLensLookupResult lookup = super.lookupMethod(method, context, type);
+ if (constructorId != null) {
+ DexMethod newMethod = lookup.getMethod();
+ return new GraphLensLookupResult(
+ newMethod,
+ mapInvocationType(newMethod, method, lookup.getType()),
+ lookup
+ .getPrototypeChanges()
+ .withExtraParameter(new ExtraConstantIntParameter(constructorId)));
+ } else {
+ return lookup;
+ }
+ }
+
public static class Builder {
protected final BiMap<DexField, DexField> fieldMap = HashBiMap.create();
protected final Map<DexMethod, DexMethod> methodMap = new IdentityHashMap<>();
@@ -51,6 +89,7 @@
new IdentityHashMap<>();
private final BiMap<DexMethod, DexMethod> originalMethodSignatures = HashBiMap.create();
+ private final Map<DexMethod, DexMethod> extraOriginalMethodSignatures = new IdentityHashMap<>();
private final Map<DexMethod, Integer> constructorIds = new IdentityHashMap<>();
@@ -64,11 +103,13 @@
BiMap<DexField, DexField> originalFieldSignatures = fieldMap.inverse();
return new HorizontalClassMergerGraphLens(
appView,
+ constructorIds,
mergedClasses,
fieldMap,
methodMap,
originalFieldSignatures,
originalMethodSignatures,
+ extraOriginalMethodSignatures,
appView.graphLens());
}
}
@@ -76,16 +117,23 @@
/** Bidirectional mapping from one method to another. */
public Builder moveMethod(DexMethod from, DexMethod to) {
mapMethod(from, to);
- originalMethodSignatures.put(to, from);
+ recordOriginalSignature(from, to);
return this;
}
- /**
- * Unidirectional mapping from one method to another. This seems to only be used by synthesized
- * constructors so is private for now. See {@link Builder#moveConstructor(DexMethod,
- * DexMethod)}.
- */
- private Builder mapMethod(DexMethod from, DexMethod to) {
+ public Builder recordOriginalSignature(DexMethod from, DexMethod to) {
+ originalMethodSignatures.forcePut(to, originalMethodSignatures.getOrDefault(from, from));
+ return this;
+ }
+
+ /** Unidirectional mapping from one method to another. */
+ public Builder recordExtraOriginalSignature(DexMethod from, DexMethod to) {
+ extraOriginalMethodSignatures.put(to, extraOriginalMethodSignatures.getOrDefault(from, from));
+ return this;
+ }
+
+ /** Unidirectional mapping from one method to another. */
+ public Builder mapMethod(DexMethod from, DexMethod to) {
for (DexMethod existingFrom :
completeInverseMethodMap.getOrDefault(from, Collections.emptySet())) {
methodMap.put(existingFrom, to);
@@ -100,6 +148,10 @@
return this;
}
+ public boolean hasExtraSignatureMappingFor(DexMethod method) {
+ return extraOriginalMethodSignatures.containsKey(method);
+ }
+
public boolean hasOriginalSignatureMappingFor(DexMethod method) {
return originalMethodSignatures.containsKey(method);
}
@@ -112,18 +164,10 @@
* @param constructorId The id that must be appended to the constructor call to ensure the
* correct constructor is called.
*/
- public Builder mapConstructor(DexMethod from, DexMethod to, int constructorId) {
+ public Builder mapMergedConstructor(DexMethod from, DexMethod to, int constructorId) {
mapMethod(from, to);
constructorIds.put(from, constructorId);
return this;
}
-
- /**
- * Bidirectional mapping from one constructor to another. When a single constructor is simply
- * moved from one class to another, we can uniquely map the new constructor back to the old one.
- */
- public Builder moveConstructor(DexMethod from, DexMethod to) {
- return moveMethod(from, to);
- }
}
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/TreeFixer.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/TreeFixer.java
index cd2cabf..7d0d5c0 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/TreeFixer.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/TreeFixer.java
@@ -15,6 +15,7 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.shaking.AnnotationFixer;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.shaking.FieldAccessInfoCollectionModifier;
import com.android.tools.r8.utils.OptionalBool;
import java.util.IdentityHashMap;
import java.util.List;
@@ -30,14 +31,17 @@
private final Map<DexType, DexType> mergedClasses;
private final Map<DexProto, DexProto> protoFixupCache = new IdentityHashMap<>();
private final HorizontalClassMergerGraphLens.Builder lensBuilder;
+ private final FieldAccessInfoCollectionModifier.Builder fieldAccessChangesBuilder;
private final AppView<AppInfoWithLiveness> appView;
public TreeFixer(
AppView<AppInfoWithLiveness> appView,
HorizontalClassMergerGraphLens.Builder lensBuilder,
+ FieldAccessInfoCollectionModifier.Builder fieldAccessChangesBuilder,
Map<DexType, DexType> mergedClasses) {
this.mergedClasses = mergedClasses;
this.lensBuilder = lensBuilder;
+ this.fieldAccessChangesBuilder = fieldAccessChangesBuilder;
this.appView = appView;
}
@@ -50,6 +54,8 @@
}
HorizontalClassMergerGraphLens lens = lensBuilder.build(appView, mergedClasses);
+ fieldAccessChangesBuilder.build(this::fixupMethod).modify(appView);
+
if (lens != null) {
new AnnotationFixer(lens).run(appView.appInfo().classes());
}
@@ -63,7 +69,15 @@
return method;
}
- lensBuilder.moveMethod(methodReference, newMethodReference);
+ // If the method is a synthesized method, then don't record the original signature.
+ if ((method.getCode() instanceof ConstructorEntryPointSynthesizedCode)) {
+ assert lensBuilder.hasExtraSignatureMappingFor(methodReference);
+ lensBuilder.recordExtraOriginalSignature(methodReference, newMethodReference);
+ lensBuilder.mapMethod(methodReference, newMethodReference);
+ } else {
+ lensBuilder.moveMethod(methodReference, newMethodReference);
+ }
+
DexEncodedMethod newMethod = method.toTypeSubstitutedMethod(newMethodReference);
if (newMethod.isNonPrivateVirtualMethod()) {
// Since we changed the return type or one of the parameters, this method cannot be a
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoRuntimeTypeChecks.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoRuntimeTypeChecks.java
new file mode 100644
index 0000000..dff9967
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoRuntimeTypeChecks.java
@@ -0,0 +1,24 @@
+// 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.horizontalclassmerging.policies;
+
+import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.horizontalclassmerging.SingleClassPolicy;
+import com.android.tools.r8.shaking.ClassMergingEnqueuerExtension;
+
+public class NoRuntimeTypeChecks extends SingleClassPolicy {
+ private final ClassMergingEnqueuerExtension classMergingEnqueuerExtension;
+
+ public NoRuntimeTypeChecks(ClassMergingEnqueuerExtension classMergingEnqueuerExtension) {
+ this.classMergingEnqueuerExtension = classMergingEnqueuerExtension;
+ }
+
+ @Override
+ public boolean canMerge(DexProgramClass clazz) {
+ // We currently assume we only merge classes that implement the same set of interfaces.
+ return !(this.classMergingEnqueuerExtension.isCheckCastType(clazz)
+ || this.classMergingEnqueuerExtension.isInstanceOfType(clazz));
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
index 7dc7daa..3f40cba 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
@@ -274,7 +274,7 @@
// the 'addForward' call-back is called with the target of the forward.
private void resolveForwardForSignature(
DexClass clazz, DexMethod method, BiConsumer<DexClass, DexEncodedMethod> addForward) {
- // Resolve the default method at base type as the symbolic holder at call sites is not known.
+ // Resolve the default method with base type as the symbolic holder as call sites are not known.
// The dispatch target is then looked up from the possible "instance" class.
// Doing so can cause an invalid invoke to become valid (at runtime resolution at a subtype
// might have failed which is hidden by the insertion of the forward method). However, not doing
@@ -298,7 +298,7 @@
DexEncodedMethod target = virtualDispatchTarget.getDefinition();
DexClass targetHolder = virtualDispatchTarget.getHolder();
- // Don-t forward if the target is explicitly marked as 'dont-rewrite'
+ // Don't forward if the target is explicitly marked as 'dont-rewrite'
if (dontRewrite(targetHolder, target)) {
return;
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
index 2167964..6f46dc6 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
@@ -26,7 +26,6 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.DexTypeList;
import com.android.tools.r8.graph.DexValue;
-import com.android.tools.r8.graph.GraphLens.NestedGraphLens;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.IRCode;
@@ -1032,7 +1031,8 @@
}
private Map<DexType, DexProgramClass> processInterfaces(Builder<?> builder, Flavor flavour) {
- NestedGraphLens.Builder graphLensBuilder = InterfaceProcessorNestedGraphLens.builder();
+ InterfaceProcessorNestedGraphLens.Builder graphLensBuilder =
+ InterfaceProcessorNestedGraphLens.builder();
InterfaceProcessor processor = new InterfaceProcessor(appView, this);
for (DexProgramClass clazz : builder.getProgramClasses()) {
if (shouldProcess(clazz, flavour, true)) {
@@ -1215,21 +1215,29 @@
}
public static void reportDependencyEdge(
- DexProgramClass dependent, DexClass dependency, InternalOptions options) {
+ DexClass dependent, DexClass dependency, InternalOptions options) {
+ assert !dependent.isLibraryClass();
assert !dependency.isLibraryClass();
DesugarGraphConsumer consumer = options.desugarGraphConsumer;
if (consumer != null) {
Origin dependencyOrigin = dependency.getOrigin();
- java.util.Collection<DexProgramClass> dependents = dependent.getSynthesizedFrom();
+ java.util.Collection<DexProgramClass> dependents =
+ dependent.isProgramClass() ? dependent.asProgramClass().getSynthesizedFrom() : null;
if (dependents == null || dependents.isEmpty()) {
- dependents = Collections.singletonList(dependent);
- }
- for (DexProgramClass clazz : dependents) {
- Origin dependentOrigin = clazz.getOrigin();
- if (dependentOrigin != dependencyOrigin) {
- consumer.accept(dependentOrigin, dependencyOrigin);
+ reportDependencyEdge(consumer, dependencyOrigin, dependent);
+ } else {
+ for (DexClass clazz : dependents) {
+ reportDependencyEdge(consumer, dependencyOrigin, clazz);
}
}
}
}
+
+ private static void reportDependencyEdge(
+ DesugarGraphConsumer consumer, Origin dependencyOrigin, DexClass clazz) {
+ Origin dependentOrigin = clazz.getOrigin();
+ if (dependentOrigin != dependencyOrigin) {
+ consumer.accept(dependentOrigin, dependencyOrigin);
+ }
+ }
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
index f400369..6864127 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
@@ -36,6 +36,7 @@
import com.android.tools.r8.origin.SynthesizedOrigin;
import com.android.tools.r8.utils.Pair;
import com.google.common.collect.BiMap;
+import com.google.common.collect.HashBiMap;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
@@ -52,7 +53,7 @@
// a companion class. Removes bridge default methods.
//
// Also moves static interface methods into a companion class.
-final class InterfaceProcessor {
+public final class InterfaceProcessor {
private final AppView<?> appView;
private final InterfaceMethodRewriter rewriter;
@@ -66,7 +67,7 @@
this.rewriter = rewriter;
}
- void process(DexProgramClass iface, NestedGraphLens.Builder graphLensBuilder) {
+ void process(DexProgramClass iface, InterfaceProcessorNestedGraphLens.Builder graphLensBuilder) {
assert iface.isInterface();
// The list of methods to be created in companion class.
List<DexEncodedMethod> companionMethods = new ArrayList<>();
@@ -105,7 +106,7 @@
implMethod.copyMetadata(virtual);
virtual.setDefaultInterfaceMethodImplementation(implMethod);
companionMethods.add(implMethod);
- graphLensBuilder.move(virtual.method, implMethod.method);
+ graphLensBuilder.recordOrigin(implMethod.method, virtual.method);
}
// Remove bridge methods.
@@ -385,12 +386,15 @@
// are to static companion methods.
public static class InterfaceProcessorNestedGraphLens extends NestedGraphLens {
+ private BiMap<DexMethod, DexMethod> extraOriginalMethodSignatures;
+
public InterfaceProcessorNestedGraphLens(
Map<DexType, DexType> typeMap,
Map<DexMethod, DexMethod> methodMap,
Map<DexField, DexField> fieldMap,
BiMap<DexField, DexField> originalFieldSignatures,
BiMap<DexMethod, DexMethod> originalMethodSignatures,
+ BiMap<DexMethod, DexMethod> extraOriginalMethodSignatures,
GraphLens previousLens,
DexItemFactory dexItemFactory) {
super(
@@ -401,6 +405,54 @@
originalMethodSignatures,
previousLens,
dexItemFactory);
+ this.extraOriginalMethodSignatures = extraOriginalMethodSignatures;
+ }
+
+ public static InterfaceProcessorNestedGraphLens find(GraphLens lens) {
+ if (lens.isInterfaceProcessorLens()) {
+ return lens.asInterfaceProcessorLens();
+ }
+ if (lens.isIdentityLens()) {
+ return null;
+ }
+ if (lens.isGraphLensWithPrevious()) {
+ return find(lens.asGraphLensWithPrevious().getPrevious());
+ }
+ assert false;
+ return null;
+ }
+
+ public void toggleMappingToExtraMethods() {
+ BiMap<DexMethod, DexMethod> tmp = originalMethodSignatures;
+ this.originalMethodSignatures = extraOriginalMethodSignatures;
+ this.extraOriginalMethodSignatures = tmp;
+ }
+
+ @Override
+ public boolean isInterfaceProcessorLens() {
+ return true;
+ }
+
+ @Override
+ public InterfaceProcessorNestedGraphLens asInterfaceProcessorLens() {
+ return this;
+ }
+
+ @Override
+ public boolean isLegitimateToHaveEmptyMappings() {
+ return true;
+ }
+
+ @Override
+ public DexMethod getOriginalMethodSignature(DexMethod method) {
+ DexMethod originalMethod = extraOriginalMethodSignatures.get(method);
+ if (originalMethod == null) {
+ originalMethod =
+ originalMethodSignatures != null
+ ? originalMethodSignatures.getOrDefault(method, method)
+ : method;
+ }
+ return previousLens.getOriginalMethodSignature(originalMethod);
}
@Override
@@ -408,14 +460,26 @@
return Type.STATIC;
}
- public static GraphLens.Builder builder() {
+ public static Builder builder() {
return new Builder();
}
public static class Builder extends NestedGraphLens.Builder {
+
+ private final BiMap<DexMethod, DexMethod> extraOriginalMethodSignatures = HashBiMap.create();
+
+ public void recordOrigin(DexMethod method, DexMethod origin) {
+ if (method == origin) {
+ return;
+ }
+ extraOriginalMethodSignatures.put(method, origin);
+ }
+
@Override
public GraphLens build(DexItemFactory dexItemFactory, GraphLens previousLens) {
- if (originalFieldSignatures.isEmpty() && originalMethodSignatures.isEmpty()) {
+ if (originalFieldSignatures.isEmpty()
+ && originalMethodSignatures.isEmpty()
+ && extraOriginalMethodSignatures.isEmpty()) {
return previousLens;
}
return new InterfaceProcessorNestedGraphLens(
@@ -424,6 +488,7 @@
fieldMap,
originalFieldSignatures,
originalMethodSignatures,
+ extraOriginalMethodSignatures,
previousLens,
dexItemFactory);
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethods.java b/src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethods.java
index bc3c320..d28ee6d 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethods.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethods.java
@@ -16,6 +16,8 @@
import com.android.tools.r8.cf.code.CfCmp;
import com.android.tools.r8.cf.code.CfConstNumber;
import com.android.tools.r8.cf.code.CfConstString;
+import com.android.tools.r8.cf.code.CfFrame;
+import com.android.tools.r8.cf.code.CfFrame.FrameType;
import com.android.tools.r8.cf.code.CfGoto;
import com.android.tools.r8.cf.code.CfIf;
import com.android.tools.r8.cf.code.CfIfCmp;
@@ -45,6 +47,8 @@
import com.android.tools.r8.ir.code.ValueType;
import com.android.tools.r8.utils.InternalOptions;
import com.google.common.collect.ImmutableList;
+import it.unimi.dsi.fastutil.ints.Int2ReferenceAVLTreeMap;
+import java.util.Arrays;
public final class BackportedMethods {
@@ -52,6 +56,7 @@
factory.createSynthesizedType("Ljava/lang/ArithmeticException;");
factory.createSynthesizedType("Ljava/lang/AssertionError;");
factory.createSynthesizedType("Ljava/lang/Double;");
+ factory.createSynthesizedType("Ljava/lang/Exception;");
factory.createSynthesizedType("Ljava/lang/ExceptionInInitializerError;");
factory.createSynthesizedType("Ljava/lang/Float;");
factory.createSynthesizedType("Ljava/lang/IllegalAccessException;");
@@ -97,8 +102,10 @@
factory.createSynthesizedType("Ljava/util/stream/IntStream;");
factory.createSynthesizedType("Ljava/util/stream/LongStream;");
factory.createSynthesizedType("Ljava/util/stream/Stream;");
+ factory.createSynthesizedType("[Ljava/lang/CharSequence;");
factory.createSynthesizedType("[Ljava/lang/Class;");
factory.createSynthesizedType("[Ljava/lang/Object;");
+ factory.createSynthesizedType("[Ljava/util/Map$Entry;");
}
public static CfCode BooleanMethods_compare(InternalOptions options, DexMethod method) {
@@ -119,13 +126,37 @@
new CfConstNumber(0, ValueType.INT),
new CfGoto(label3),
label1,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.INT, 0),
new CfIf(If.Type.EQ, ValueType.INT, label2),
new CfConstNumber(1, ValueType.INT),
new CfGoto(label3),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfConstNumber(-1, ValueType.INT),
label3,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList(FrameType.initialized(options.itemFactory.intType))),
new CfReturn(ValueType.INT),
label4),
ImmutableList.of(),
@@ -148,8 +179,18 @@
new CfConstNumber(1231, ValueType.INT),
new CfGoto(label2),
label1,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0},
+ new FrameType[] {FrameType.initialized(options.itemFactory.intType)}),
+ Arrays.asList()),
new CfConstNumber(1237, ValueType.INT),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0},
+ new FrameType[] {FrameType.initialized(options.itemFactory.intType)}),
+ Arrays.asList(FrameType.initialized(options.itemFactory.intType))),
new CfReturn(ValueType.INT),
label3),
ImmutableList.of(),
@@ -281,6 +322,16 @@
new CfConstNumber(0, ValueType.INT),
new CfReturn(ValueType.INT),
label4,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2, 3},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.charSequenceType),
+ FrameType.initialized(options.itemFactory.charSequenceType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfConstNumber(0, ValueType.INT),
new CfStore(ValueType.INT, 4),
label5,
@@ -298,6 +349,18 @@
false),
new CfStore(ValueType.INT, 5),
label6,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2, 3, 4, 5},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.charSequenceType),
+ FrameType.initialized(options.itemFactory.charSequenceType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.INT, 4),
new CfLoad(ValueType.INT, 5),
new CfIfCmp(If.Type.GE, ValueType.INT, label12),
@@ -335,9 +398,31 @@
new CfArithmeticBinop(CfArithmeticBinop.Opcode.Sub, NumericType.INT),
new CfReturn(ValueType.INT),
label11,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2, 3, 4, 5},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.charSequenceType),
+ FrameType.initialized(options.itemFactory.charSequenceType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfIinc(4, 1),
new CfGoto(label6),
label12,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2, 3},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.charSequenceType),
+ FrameType.initialized(options.itemFactory.charSequenceType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.INT, 2),
new CfLoad(ValueType.INT, 3),
new CfArithmeticBinop(CfArithmeticBinop.Opcode.Sub, NumericType.INT),
@@ -441,6 +526,14 @@
true),
new CfGoto(label11),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.throwableType),
+ FrameType.initialized(options.itemFactory.objectType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 1),
new CfInvoke(
182,
@@ -482,6 +575,16 @@
label4,
new CfGoto(label11),
label5,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.throwableType),
+ FrameType.initialized(options.itemFactory.objectType)
+ }),
+ Arrays.asList(
+ FrameType.initialized(
+ options.itemFactory.createType("Ljava/lang/Exception;")))),
new CfStore(ValueType.OBJECT, 2),
label6,
new CfNew(options.itemFactory.createType("Ljava/lang/AssertionError;")),
@@ -540,6 +643,14 @@
false),
new CfThrow(),
label7,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.throwableType),
+ FrameType.initialized(options.itemFactory.objectType)
+ }),
+ Arrays.asList(FrameType.initialized(options.itemFactory.throwableType))),
new CfStore(ValueType.OBJECT, 2),
label8,
new CfNew(options.itemFactory.createType("Ljava/lang/AssertionError;")),
@@ -598,6 +709,17 @@
false),
new CfThrow(),
label9,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.throwableType),
+ FrameType.initialized(options.itemFactory.objectType)
+ }),
+ Arrays.asList(
+ FrameType.initialized(
+ options.itemFactory.createType(
+ "Ljava/lang/reflect/InvocationTargetException;")))),
new CfStore(ValueType.OBJECT, 2),
label10,
new CfLoad(ValueType.OBJECT, 2),
@@ -610,8 +732,24 @@
false),
new CfThrow(),
label11,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.throwableType),
+ FrameType.initialized(options.itemFactory.objectType)
+ }),
+ Arrays.asList()),
new CfGoto(label16),
label12,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.throwableType),
+ FrameType.initialized(options.itemFactory.objectType)
+ }),
+ Arrays.asList(FrameType.initialized(options.itemFactory.throwableType))),
new CfStore(ValueType.OBJECT, 2),
label13,
new CfLoad(ValueType.OBJECT, 0),
@@ -619,10 +757,36 @@
new CfLoad(ValueType.OBJECT, 0),
new CfGoto(label15),
label14,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.throwableType),
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(options.itemFactory.throwableType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 2),
label15,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.throwableType),
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(options.itemFactory.throwableType)
+ }),
+ Arrays.asList(FrameType.initialized(options.itemFactory.throwableType))),
new CfThrow(),
label16,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.throwableType),
+ FrameType.initialized(options.itemFactory.objectType)
+ }),
+ Arrays.asList()),
new CfReturnVoid(),
label17),
ImmutableList.of(
@@ -706,6 +870,18 @@
new CfConstNumber(0, ValueType.INT),
new CfStore(ValueType.INT, 4),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2, 3, 4},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.createType("[Ljava/lang/Object;")),
+ FrameType.initialized(
+ options.itemFactory.createType("Ljava/util/ArrayList;")),
+ FrameType.initialized(options.itemFactory.createType("[Ljava/lang/Object;")),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.INT, 4),
new CfLoad(ValueType.INT, 3),
new CfIfCmp(If.Type.GE, ValueType.INT, label5),
@@ -737,6 +913,14 @@
new CfIinc(4, 1),
new CfGoto(label2),
label5,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.createType("[Ljava/lang/Object;")),
+ FrameType.initialized(options.itemFactory.createType("Ljava/util/ArrayList;"))
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 1),
new CfInvoke(
184,
@@ -844,6 +1028,19 @@
new CfConstNumber(0, ValueType.INT),
new CfStore(ValueType.INT, 4),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2, 3, 4},
+ new FrameType[] {
+ FrameType.initialized(
+ options.itemFactory.createType("[Ljava/util/Map$Entry;")),
+ FrameType.initialized(options.itemFactory.createType("Ljava/util/HashMap;")),
+ FrameType.initialized(
+ options.itemFactory.createType("[Ljava/util/Map$Entry;")),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.INT, 4),
new CfLoad(ValueType.INT, 3),
new CfIfCmp(If.Type.GE, ValueType.INT, label8),
@@ -949,9 +1146,31 @@
false),
new CfThrow(),
label7,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2, 3, 4},
+ new FrameType[] {
+ FrameType.initialized(
+ options.itemFactory.createType("[Ljava/util/Map$Entry;")),
+ FrameType.initialized(options.itemFactory.createType("Ljava/util/HashMap;")),
+ FrameType.initialized(
+ options.itemFactory.createType("[Ljava/util/Map$Entry;")),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfIinc(4, 1),
new CfGoto(label2),
label8,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(
+ options.itemFactory.createType("[Ljava/util/Map$Entry;")),
+ FrameType.initialized(options.itemFactory.createType("Ljava/util/HashMap;"))
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 1),
new CfInvoke(
184,
@@ -1005,6 +1224,17 @@
new CfConstNumber(0, ValueType.INT),
new CfStore(ValueType.INT, 4),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2, 3, 4},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.createType("[Ljava/lang/Object;")),
+ FrameType.initialized(options.itemFactory.createType("Ljava/util/HashSet;")),
+ FrameType.initialized(options.itemFactory.createType("[Ljava/lang/Object;")),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.INT, 4),
new CfLoad(ValueType.INT, 3),
new CfIfCmp(If.Type.GE, ValueType.INT, label6),
@@ -1079,9 +1309,28 @@
false),
new CfThrow(),
label5,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2, 3, 4},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.createType("[Ljava/lang/Object;")),
+ FrameType.initialized(options.itemFactory.createType("Ljava/util/HashSet;")),
+ FrameType.initialized(options.itemFactory.createType("[Ljava/lang/Object;")),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfIinc(4, 1),
new CfGoto(label2),
label6,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.createType("[Ljava/lang/Object;")),
+ FrameType.initialized(options.itemFactory.createType("Ljava/util/HashSet;"))
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 1),
new CfInvoke(
184,
@@ -1143,6 +1392,17 @@
true),
new CfStore(ValueType.OBJECT, 2),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2},
+ new FrameType[] {
+ FrameType.initialized(
+ options.itemFactory.createType("Ljava/util/Collection;")),
+ FrameType.initialized(
+ options.itemFactory.createType("Ljava/util/ArrayList;")),
+ FrameType.initialized(options.itemFactory.createType("Ljava/util/Iterator;"))
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 2),
new CfInvoke(
185,
@@ -1184,6 +1444,15 @@
label4,
new CfGoto(label2),
label5,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(
+ options.itemFactory.createType("Ljava/util/Collection;")),
+ FrameType.initialized(options.itemFactory.createType("Ljava/util/ArrayList;"))
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 1),
new CfInvoke(
184,
@@ -1256,6 +1525,15 @@
true),
new CfStore(ValueType.OBJECT, 2),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.createType("Ljava/util/Map;")),
+ FrameType.initialized(options.itemFactory.createType("Ljava/util/HashMap;")),
+ FrameType.initialized(options.itemFactory.createType("Ljava/util/Iterator;"))
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 2),
new CfInvoke(
185,
@@ -1326,6 +1604,14 @@
label7,
new CfGoto(label2),
label8,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.createType("Ljava/util/Map;")),
+ FrameType.initialized(options.itemFactory.createType("Ljava/util/HashMap;"))
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 1),
new CfInvoke(
184,
@@ -1387,6 +1673,16 @@
true),
new CfStore(ValueType.OBJECT, 2),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2},
+ new FrameType[] {
+ FrameType.initialized(
+ options.itemFactory.createType("Ljava/util/Collection;")),
+ FrameType.initialized(options.itemFactory.createType("Ljava/util/HashSet;")),
+ FrameType.initialized(options.itemFactory.createType("Ljava/util/Iterator;"))
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 2),
new CfInvoke(
185,
@@ -1428,6 +1724,15 @@
label4,
new CfGoto(label2),
label5,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(
+ options.itemFactory.createType("Ljava/util/Collection;")),
+ FrameType.initialized(options.itemFactory.createType("Ljava/util/HashSet;"))
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 1),
new CfInvoke(
184,
@@ -1601,8 +1906,18 @@
new CfConstNumber(1, ValueType.INT),
new CfGoto(label2),
label1,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0},
+ new FrameType[] {FrameType.initialized(options.itemFactory.doubleType)}),
+ Arrays.asList()),
new CfConstNumber(0, ValueType.INT),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0},
+ new FrameType[] {FrameType.initialized(options.itemFactory.doubleType)}),
+ Arrays.asList(FrameType.initialized(options.itemFactory.intType))),
new CfReturn(ValueType.INT),
label3),
ImmutableList.of(),
@@ -1643,8 +1958,18 @@
new CfConstNumber(1, ValueType.INT),
new CfGoto(label2),
label1,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0},
+ new FrameType[] {FrameType.initialized(options.itemFactory.floatType)}),
+ Arrays.asList()),
new CfConstNumber(0, ValueType.INT),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0},
+ new FrameType[] {FrameType.initialized(options.itemFactory.floatType)}),
+ Arrays.asList(FrameType.initialized(options.itemFactory.intType))),
new CfReturn(ValueType.INT),
label3),
ImmutableList.of(),
@@ -1669,14 +1994,38 @@
new CfConstNumber(0, ValueType.INT),
new CfGoto(label3),
label1,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.INT, 0),
new CfLoad(ValueType.INT, 1),
new CfIfCmp(If.Type.GE, ValueType.INT, label2),
new CfConstNumber(-1, ValueType.INT),
new CfGoto(label3),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfConstNumber(1, ValueType.INT),
label3,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList(FrameType.initialized(options.itemFactory.intType))),
new CfReturn(ValueType.INT),
label4),
ImmutableList.of(),
@@ -1832,6 +2181,14 @@
false),
new CfStore(ValueType.OBJECT, 0),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.stringType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 0),
new CfLoad(ValueType.INT, 1),
new CfInvoke(
@@ -1927,6 +2284,15 @@
false),
new CfThrow(),
label5,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.stringType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.longType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.LONG, 2),
new CfNumberConversion(NumericType.LONG, NumericType.INT),
new CfReturn(ValueType.INT),
@@ -2134,9 +2500,27 @@
new CfConstNumber(0, ValueType.LONG),
new CfReturn(ValueType.LONG),
label5,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 2, 4, 6},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType)
+ }),
+ Arrays.asList()),
new CfConstNumber(1, ValueType.LONG),
new CfReturn(ValueType.LONG),
label6,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 2},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.LONG, 0),
new CfConstNumber(0, ValueType.LONG),
new CfCmp(Cmp.Bias.NONE, NumericType.LONG),
@@ -2147,6 +2531,14 @@
new CfArithmeticBinop(CfArithmeticBinop.Opcode.Div, NumericType.LONG),
new CfReturn(ValueType.LONG),
label8,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 2},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.LONG, 0),
new CfConstNumber(1, ValueType.INT),
new CfLogicalBinop(CfLogicalBinop.Opcode.Ushr, NumericType.LONG),
@@ -2181,8 +2573,34 @@
new CfConstNumber(1, ValueType.INT),
new CfGoto(label14),
label13,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 2, 4, 6, 8, 10},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType)
+ }),
+ Arrays.asList(FrameType.initialized(options.itemFactory.longType))),
new CfConstNumber(0, ValueType.INT),
label14,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 2, 4, 6, 8, 10},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType)
+ }),
+ Arrays.asList(
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.intType))),
new CfNumberConversion(NumericType.INT, NumericType.LONG),
new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.LONG),
new CfReturn(ValueType.LONG),
@@ -2295,6 +2713,15 @@
false),
new CfThrow(),
label3,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.stringType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.INT, 1),
new CfConstNumber(2, ValueType.INT),
new CfIfCmp(If.Type.LT, ValueType.INT, label4),
@@ -2302,6 +2729,15 @@
new CfConstNumber(36, ValueType.INT),
new CfIfCmp(If.Type.LE, ValueType.INT, label5),
label4,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.stringType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfNew(options.itemFactory.createType("Ljava/lang/NumberFormatException;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfConstString(options.itemFactory.createString("illegal radix: ")),
@@ -2332,6 +2768,15 @@
false),
new CfThrow(),
label5,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.stringType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfConstNumber(-1, ValueType.LONG),
new CfLoad(ValueType.INT, 1),
new CfNumberConversion(NumericType.INT, NumericType.LONG),
@@ -2365,8 +2810,28 @@
new CfConstNumber(1, ValueType.INT),
new CfGoto(label8),
label7,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2, 3},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.stringType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.longType)
+ }),
+ Arrays.asList()),
new CfConstNumber(0, ValueType.INT),
label8,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2, 3},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.stringType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.longType)
+ }),
+ Arrays.asList(FrameType.initialized(options.itemFactory.intType))),
new CfStore(ValueType.INT, 5),
label9,
new CfConstNumber(0, ValueType.LONG),
@@ -2375,6 +2840,19 @@
new CfLoad(ValueType.INT, 5),
new CfStore(ValueType.INT, 8),
label11,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2, 3, 5, 6, 8},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.stringType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.INT, 8),
new CfLoad(ValueType.INT, 2),
new CfIfCmp(If.Type.GE, ValueType.INT, label20),
@@ -2419,6 +2897,20 @@
false),
new CfThrow(),
label15,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2, 3, 5, 6, 8, 9},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.stringType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.LONG, 6),
new CfConstNumber(0, ValueType.LONG),
new CfCmp(Cmp.Bias.NONE, NumericType.LONG),
@@ -2449,6 +2941,20 @@
new CfNumberConversion(NumericType.LONG, NumericType.INT),
new CfIfCmp(If.Type.LE, ValueType.INT, label18),
label17,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2, 3, 5, 6, 8, 9},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.stringType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfNew(options.itemFactory.createType("Ljava/lang/NumberFormatException;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfConstString(options.itemFactory.createString("Too large for unsigned long: ")),
@@ -2471,6 +2977,20 @@
false),
new CfThrow(),
label18,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2, 3, 5, 6, 8, 9},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.stringType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.LONG, 6),
new CfLoad(ValueType.INT, 1),
new CfNumberConversion(NumericType.INT, NumericType.LONG),
@@ -2483,6 +3003,18 @@
new CfIinc(8, 1),
new CfGoto(label11),
label20,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2, 3, 5, 6},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.stringType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.longType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.LONG, 6),
new CfReturn(ValueType.LONG),
label21),
@@ -2536,11 +3068,29 @@
new CfLoad(ValueType.LONG, 0),
new CfReturn(ValueType.LONG),
label5,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 2, 4, 6},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.LONG, 0),
new CfLoad(ValueType.LONG, 2),
new CfArithmeticBinop(CfArithmeticBinop.Opcode.Sub, NumericType.LONG),
new CfReturn(ValueType.LONG),
label6,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 2},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.LONG, 0),
new CfConstNumber(0, ValueType.LONG),
new CfCmp(Cmp.Bias.NONE, NumericType.LONG),
@@ -2551,6 +3101,14 @@
new CfArithmeticBinop(CfArithmeticBinop.Opcode.Rem, NumericType.LONG),
new CfReturn(ValueType.LONG),
label8,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 2},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.LONG, 0),
new CfConstNumber(1, ValueType.INT),
new CfLogicalBinop(CfLogicalBinop.Opcode.Ushr, NumericType.LONG),
@@ -2585,8 +3143,34 @@
new CfLoad(ValueType.LONG, 2),
new CfGoto(label14),
label13,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 2, 4, 6, 8, 10},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType)
+ }),
+ Arrays.asList(FrameType.initialized(options.itemFactory.longType))),
new CfConstNumber(0, ValueType.LONG),
label14,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 2, 4, 6, 8, 10},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType)
+ }),
+ Arrays.asList(
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType))),
new CfArithmeticBinop(CfArithmeticBinop.Opcode.Sub, NumericType.LONG),
new CfReturn(ValueType.LONG),
label15),
@@ -2664,6 +3248,14 @@
new CfConstString(options.itemFactory.createString("0")),
new CfReturn(ValueType.OBJECT),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 2},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.LONG, 0),
new CfConstNumber(0, ValueType.LONG),
new CfCmp(Cmp.Bias.NONE, NumericType.LONG),
@@ -2683,6 +3275,14 @@
false),
new CfReturn(ValueType.OBJECT),
label4,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 2},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.INT, 2),
new CfConstNumber(2, ValueType.INT),
new CfIfCmp(If.Type.LT, ValueType.INT, label5),
@@ -2690,9 +3290,25 @@
new CfConstNumber(36, ValueType.INT),
new CfIfCmp(If.Type.LE, ValueType.INT, label6),
label5,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 2},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfConstNumber(10, ValueType.INT),
new CfStore(ValueType.INT, 2),
label6,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 2},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfConstNumber(64, ValueType.INT),
new CfNewArray(options.itemFactory.charArrayType),
new CfStore(ValueType.OBJECT, 3),
@@ -2724,6 +3340,18 @@
new CfArithmeticBinop(CfArithmeticBinop.Opcode.Sub, NumericType.INT),
new CfStore(ValueType.INT, 6),
label11,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 2, 3, 4, 5, 6},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.charArrayType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 3),
new CfIinc(4, -1),
new CfLoad(ValueType.INT, 4),
@@ -2756,6 +3384,16 @@
label14,
new CfGoto(label25),
label15,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 2, 3, 4},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.charArrayType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.INT, 2),
new CfConstNumber(1, ValueType.INT),
new CfLogicalBinop(CfLogicalBinop.Opcode.And, NumericType.INT),
@@ -2773,6 +3411,16 @@
label17,
new CfGoto(label19),
label18,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 2, 3, 4},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.charArrayType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.LONG, 0),
new CfLoad(ValueType.INT, 2),
new CfNumberConversion(NumericType.INT, NumericType.LONG),
@@ -2788,6 +3436,17 @@
false),
new CfStore(ValueType.LONG, 5),
label19,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 2, 3, 4, 5},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.charArrayType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.longType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.LONG, 0),
new CfLoad(ValueType.LONG, 5),
new CfLoad(ValueType.INT, 2),
@@ -2817,6 +3476,18 @@
new CfLoad(ValueType.LONG, 5),
new CfStore(ValueType.LONG, 0),
label22,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 2, 3, 4, 5, 7},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.charArrayType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.LONG, 0),
new CfConstNumber(0, ValueType.LONG),
new CfCmp(Cmp.Bias.NONE, NumericType.LONG),
@@ -2850,6 +3521,16 @@
new CfStore(ValueType.LONG, 0),
new CfGoto(label22),
label25,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 2, 3, 4},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.charArrayType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfNew(options.itemFactory.stringType),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfLoad(ValueType.OBJECT, 3),
@@ -2908,6 +3589,16 @@
new CfLoad(ValueType.INT, 4),
new CfReturn(ValueType.INT),
label4,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2, 4},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfInvoke(
@@ -2953,8 +3644,26 @@
new CfConstNumber(1, ValueType.INT),
new CfGoto(label3),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 2, 4},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType)
+ }),
+ Arrays.asList()),
new CfConstNumber(0, ValueType.INT),
label3,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 2, 4},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType)
+ }),
+ Arrays.asList(FrameType.initialized(options.itemFactory.intType))),
new CfLoad(ValueType.LONG, 0),
new CfLoad(ValueType.LONG, 4),
new CfLogicalBinop(CfLogicalBinop.Opcode.Xor, NumericType.LONG),
@@ -2964,14 +3673,43 @@
new CfConstNumber(1, ValueType.INT),
new CfGoto(label5),
label4,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 2, 4},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType)
+ }),
+ Arrays.asList(FrameType.initialized(options.itemFactory.intType))),
new CfConstNumber(0, ValueType.INT),
label5,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 2, 4},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType)
+ }),
+ Arrays.asList(
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType))),
new CfLogicalBinop(CfLogicalBinop.Opcode.Or, NumericType.INT),
new CfIf(If.Type.EQ, ValueType.INT, label7),
label6,
new CfLoad(ValueType.LONG, 4),
new CfReturn(ValueType.LONG),
label7,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 2, 4},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType)
+ }),
+ Arrays.asList()),
new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfInvoke(
@@ -3013,6 +3751,11 @@
false),
new CfThrow(),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0},
+ new FrameType[] {FrameType.initialized(options.itemFactory.intType)}),
+ Arrays.asList()),
new CfLoad(ValueType.INT, 0),
new CfConstNumber(1, ValueType.INT),
new CfArithmeticBinop(CfArithmeticBinop.Opcode.Sub, NumericType.INT),
@@ -3049,6 +3792,11 @@
false),
new CfThrow(),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0},
+ new FrameType[] {FrameType.initialized(options.itemFactory.longType)}),
+ Arrays.asList()),
new CfLoad(ValueType.LONG, 0),
new CfConstNumber(1, ValueType.LONG),
new CfArithmeticBinop(CfArithmeticBinop.Opcode.Sub, NumericType.LONG),
@@ -3092,6 +3840,16 @@
new CfLoad(ValueType.INT, 2),
new CfReturn(ValueType.INT),
label4,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2, 3},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfConstNumber(1, ValueType.INT),
new CfLoad(ValueType.INT, 0),
new CfLoad(ValueType.INT, 1),
@@ -3108,8 +3866,30 @@
new CfArithmeticBinop(CfArithmeticBinop.Opcode.Sub, NumericType.INT),
new CfGoto(label7),
label6,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2, 3, 4},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.INT, 2),
label7,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2, 3, 4},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList(FrameType.initialized(options.itemFactory.intType))),
new CfReturn(ValueType.INT),
label8),
ImmutableList.of(),
@@ -3152,6 +3932,16 @@
new CfLoad(ValueType.LONG, 4),
new CfReturn(ValueType.LONG),
label4,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 2, 4, 6},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType)
+ }),
+ Arrays.asList()),
new CfConstNumber(1, ValueType.LONG),
new CfLoad(ValueType.LONG, 0),
new CfLoad(ValueType.LONG, 2),
@@ -3170,8 +3960,30 @@
new CfArithmeticBinop(CfArithmeticBinop.Opcode.Sub, NumericType.LONG),
new CfGoto(label7),
label6,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 2, 4, 6, 8},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.LONG, 4),
label7,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 2, 4, 6, 8},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType)
+ }),
+ Arrays.asList(FrameType.initialized(options.itemFactory.longType))),
new CfReturn(ValueType.LONG),
label8),
ImmutableList.of(),
@@ -3232,6 +4044,15 @@
new CfConstNumber(0, ValueType.INT),
new CfReturn(ValueType.INT),
label3,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfConstNumber(1, ValueType.INT),
new CfLoad(ValueType.INT, 0),
new CfLoad(ValueType.INT, 1),
@@ -3246,10 +4067,30 @@
new CfLoad(ValueType.INT, 2),
new CfGoto(label6),
label5,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2, 3},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.INT, 2),
new CfLoad(ValueType.INT, 1),
new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.INT),
label6,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2, 3},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList(FrameType.initialized(options.itemFactory.intType))),
new CfReturn(ValueType.INT),
label7),
ImmutableList.of(),
@@ -3284,6 +4125,15 @@
new CfConstNumber(0, ValueType.LONG),
new CfReturn(ValueType.LONG),
label3,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 2, 4},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType)
+ }),
+ Arrays.asList()),
new CfConstNumber(1, ValueType.LONG),
new CfLoad(ValueType.LONG, 0),
new CfLoad(ValueType.LONG, 2),
@@ -3300,10 +4150,30 @@
new CfLoad(ValueType.LONG, 4),
new CfGoto(label6),
label5,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 2, 4, 6},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.LONG, 4),
new CfLoad(ValueType.LONG, 2),
new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.LONG),
label6,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 2, 4, 6},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType)
+ }),
+ Arrays.asList(FrameType.initialized(options.itemFactory.longType))),
new CfReturn(ValueType.LONG),
label7),
ImmutableList.of(),
@@ -3365,6 +4235,11 @@
false),
new CfThrow(),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0},
+ new FrameType[] {FrameType.initialized(options.itemFactory.intType)}),
+ Arrays.asList()),
new CfLoad(ValueType.INT, 0),
new CfConstNumber(1, ValueType.INT),
new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.INT),
@@ -3401,6 +4276,11 @@
false),
new CfThrow(),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0},
+ new FrameType[] {FrameType.initialized(options.itemFactory.longType)}),
+ Arrays.asList()),
new CfLoad(ValueType.LONG, 0),
new CfConstNumber(1, ValueType.LONG),
new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.LONG),
@@ -3443,6 +4323,16 @@
new CfLoad(ValueType.INT, 4),
new CfReturn(ValueType.INT),
label4,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2, 4},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfInvoke(
@@ -3540,6 +4430,15 @@
new CfArithmeticBinop(CfArithmeticBinop.Opcode.Mul, NumericType.LONG),
new CfReturn(ValueType.LONG),
label7,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 2, 4},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.INT, 4),
new CfConstNumber(64, ValueType.INT),
new CfIfCmp(If.Type.LT, ValueType.INT, label15),
@@ -3550,8 +4449,26 @@
new CfConstNumber(1, ValueType.INT),
new CfGoto(label9),
label8,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 2, 4},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfConstNumber(0, ValueType.INT),
label9,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 2, 4},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList(FrameType.initialized(options.itemFactory.intType))),
new CfLoad(ValueType.LONG, 2),
new CfConstNumber(-9223372036854775808L, ValueType.LONG),
new CfCmp(Cmp.Bias.NONE, NumericType.LONG),
@@ -3559,8 +4476,28 @@
new CfConstNumber(1, ValueType.INT),
new CfGoto(label11),
label10,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 2, 4},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList(FrameType.initialized(options.itemFactory.intType))),
new CfConstNumber(0, ValueType.INT),
label11,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 2, 4},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList(
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType))),
new CfLogicalBinop(CfLogicalBinop.Opcode.Or, NumericType.INT),
new CfIf(If.Type.EQ, ValueType.INT, label15),
label12,
@@ -3580,9 +4517,28 @@
new CfCmp(Cmp.Bias.NONE, NumericType.LONG),
new CfIf(If.Type.NE, ValueType.INT, label15),
label14,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 2, 4, 5},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.longType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.LONG, 5),
new CfReturn(ValueType.LONG),
label15,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 2, 4},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfInvoke(
@@ -3776,6 +4732,11 @@
false),
new CfThrow(),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0},
+ new FrameType[] {FrameType.initialized(options.itemFactory.intType)}),
+ Arrays.asList()),
new CfLoad(ValueType.INT, 0),
new CfNeg(NumericType.INT),
new CfReturn(ValueType.INT),
@@ -3811,6 +4772,11 @@
false),
new CfThrow(),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0},
+ new FrameType[] {FrameType.initialized(options.itemFactory.longType)}),
+ Arrays.asList()),
new CfLoad(ValueType.LONG, 0),
new CfNeg(NumericType.LONG),
new CfReturn(ValueType.LONG),
@@ -3904,6 +4870,16 @@
new CfLoad(ValueType.INT, 4),
new CfReturn(ValueType.INT),
label4,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2, 4},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfInvoke(
@@ -3949,8 +4925,26 @@
new CfConstNumber(1, ValueType.INT),
new CfGoto(label3),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 2, 4},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType)
+ }),
+ Arrays.asList()),
new CfConstNumber(0, ValueType.INT),
label3,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 2, 4},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType)
+ }),
+ Arrays.asList(FrameType.initialized(options.itemFactory.intType))),
new CfLoad(ValueType.LONG, 0),
new CfLoad(ValueType.LONG, 4),
new CfLogicalBinop(CfLogicalBinop.Opcode.Xor, NumericType.LONG),
@@ -3960,14 +4954,43 @@
new CfConstNumber(1, ValueType.INT),
new CfGoto(label5),
label4,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 2, 4},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType)
+ }),
+ Arrays.asList(FrameType.initialized(options.itemFactory.intType))),
new CfConstNumber(0, ValueType.INT),
label5,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 2, 4},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType)
+ }),
+ Arrays.asList(
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType))),
new CfLogicalBinop(CfLogicalBinop.Opcode.Or, NumericType.INT),
new CfIf(If.Type.EQ, ValueType.INT, label7),
label6,
new CfLoad(ValueType.LONG, 4),
new CfReturn(ValueType.LONG),
label7,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 2, 4},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.longType)
+ }),
+ Arrays.asList()),
new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfInvoke(
@@ -4016,6 +5039,14 @@
false),
new CfThrow(),
label3,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 2},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.longType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.INT, 2),
new CfReturn(ValueType.INT),
label4),
@@ -4047,6 +5078,15 @@
new CfArithmeticBinop(CfArithmeticBinop.Opcode.Sub, NumericType.INT),
new CfIfCmp(If.Type.LE, ValueType.INT, label2),
label1,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfNew(options.itemFactory.createType("Ljava/lang/IndexOutOfBoundsException;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfNew(options.itemFactory.stringBuilderType),
@@ -4147,6 +5187,15 @@
false),
new CfThrow(),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.INT, 0),
new CfReturn(ValueType.INT),
label3),
@@ -4174,6 +5223,15 @@
new CfLoad(ValueType.INT, 2),
new CfIfCmp(If.Type.LE, ValueType.INT, label2),
label1,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfNew(options.itemFactory.createType("Ljava/lang/IndexOutOfBoundsException;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfNew(options.itemFactory.stringBuilderType),
@@ -4256,6 +5314,15 @@
false),
new CfThrow(),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.INT, 0),
new CfReturn(ValueType.INT),
label3),
@@ -4280,6 +5347,14 @@
new CfLoad(ValueType.INT, 1),
new CfIfCmp(If.Type.LT, ValueType.INT, label2),
label1,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfNew(options.itemFactory.createType("Ljava/lang/IndexOutOfBoundsException;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfNew(options.itemFactory.stringBuilderType),
@@ -4344,6 +5419,14 @@
false),
new CfThrow(),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.INT, 0),
new CfReturn(ValueType.INT),
label3),
@@ -4368,6 +5451,16 @@
new CfConstNumber(0, ValueType.INT),
new CfGoto(label2),
label1,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(
+ options.itemFactory.createType("Ljava/util/Comparator;"))
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 2),
new CfLoad(ValueType.OBJECT, 0),
new CfLoad(ValueType.OBJECT, 1),
@@ -4382,6 +5475,16 @@
options.itemFactory.createString("compare")),
true),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(
+ options.itemFactory.createType("Ljava/util/Comparator;"))
+ }),
+ Arrays.asList(FrameType.initialized(options.itemFactory.intType))),
new CfReturn(ValueType.INT),
label3),
ImmutableList.of(),
@@ -4441,11 +5544,27 @@
new CfConstNumber(1, ValueType.INT),
new CfReturn(ValueType.INT),
label1,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(options.itemFactory.objectType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 0),
new CfIf(If.Type.NE, ValueType.OBJECT, label2),
new CfConstNumber(0, ValueType.INT),
new CfReturn(ValueType.INT),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(options.itemFactory.objectType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 0),
new CfInstanceOf(options.itemFactory.booleanArrayType),
new CfIf(If.Type.EQ, ValueType.INT, label6),
@@ -4471,10 +5590,34 @@
new CfConstNumber(1, ValueType.INT),
new CfGoto(label5),
label4,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(options.itemFactory.objectType)
+ }),
+ Arrays.asList()),
new CfConstNumber(0, ValueType.INT),
label5,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(options.itemFactory.objectType)
+ }),
+ Arrays.asList(FrameType.initialized(options.itemFactory.intType))),
new CfReturn(ValueType.INT),
label6,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(options.itemFactory.objectType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 0),
new CfInstanceOf(options.itemFactory.byteArrayType),
new CfIf(If.Type.EQ, ValueType.INT, label10),
@@ -4500,10 +5643,34 @@
new CfConstNumber(1, ValueType.INT),
new CfGoto(label9),
label8,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(options.itemFactory.objectType)
+ }),
+ Arrays.asList()),
new CfConstNumber(0, ValueType.INT),
label9,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(options.itemFactory.objectType)
+ }),
+ Arrays.asList(FrameType.initialized(options.itemFactory.intType))),
new CfReturn(ValueType.INT),
label10,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(options.itemFactory.objectType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 0),
new CfInstanceOf(options.itemFactory.charArrayType),
new CfIf(If.Type.EQ, ValueType.INT, label14),
@@ -4529,10 +5696,34 @@
new CfConstNumber(1, ValueType.INT),
new CfGoto(label13),
label12,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(options.itemFactory.objectType)
+ }),
+ Arrays.asList()),
new CfConstNumber(0, ValueType.INT),
label13,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(options.itemFactory.objectType)
+ }),
+ Arrays.asList(FrameType.initialized(options.itemFactory.intType))),
new CfReturn(ValueType.INT),
label14,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(options.itemFactory.objectType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 0),
new CfInstanceOf(options.itemFactory.doubleArrayType),
new CfIf(If.Type.EQ, ValueType.INT, label18),
@@ -4558,10 +5749,34 @@
new CfConstNumber(1, ValueType.INT),
new CfGoto(label17),
label16,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(options.itemFactory.objectType)
+ }),
+ Arrays.asList()),
new CfConstNumber(0, ValueType.INT),
label17,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(options.itemFactory.objectType)
+ }),
+ Arrays.asList(FrameType.initialized(options.itemFactory.intType))),
new CfReturn(ValueType.INT),
label18,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(options.itemFactory.objectType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 0),
new CfInstanceOf(options.itemFactory.floatArrayType),
new CfIf(If.Type.EQ, ValueType.INT, label22),
@@ -4587,10 +5802,34 @@
new CfConstNumber(1, ValueType.INT),
new CfGoto(label21),
label20,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(options.itemFactory.objectType)
+ }),
+ Arrays.asList()),
new CfConstNumber(0, ValueType.INT),
label21,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(options.itemFactory.objectType)
+ }),
+ Arrays.asList(FrameType.initialized(options.itemFactory.intType))),
new CfReturn(ValueType.INT),
label22,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(options.itemFactory.objectType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 0),
new CfInstanceOf(options.itemFactory.intArrayType),
new CfIf(If.Type.EQ, ValueType.INT, label26),
@@ -4616,10 +5855,34 @@
new CfConstNumber(1, ValueType.INT),
new CfGoto(label25),
label24,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(options.itemFactory.objectType)
+ }),
+ Arrays.asList()),
new CfConstNumber(0, ValueType.INT),
label25,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(options.itemFactory.objectType)
+ }),
+ Arrays.asList(FrameType.initialized(options.itemFactory.intType))),
new CfReturn(ValueType.INT),
label26,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(options.itemFactory.objectType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 0),
new CfInstanceOf(options.itemFactory.longArrayType),
new CfIf(If.Type.EQ, ValueType.INT, label30),
@@ -4645,10 +5908,34 @@
new CfConstNumber(1, ValueType.INT),
new CfGoto(label29),
label28,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(options.itemFactory.objectType)
+ }),
+ Arrays.asList()),
new CfConstNumber(0, ValueType.INT),
label29,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(options.itemFactory.objectType)
+ }),
+ Arrays.asList(FrameType.initialized(options.itemFactory.intType))),
new CfReturn(ValueType.INT),
label30,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(options.itemFactory.objectType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 0),
new CfInstanceOf(options.itemFactory.shortArrayType),
new CfIf(If.Type.EQ, ValueType.INT, label34),
@@ -4674,10 +5961,34 @@
new CfConstNumber(1, ValueType.INT),
new CfGoto(label33),
label32,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(options.itemFactory.objectType)
+ }),
+ Arrays.asList()),
new CfConstNumber(0, ValueType.INT),
label33,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(options.itemFactory.objectType)
+ }),
+ Arrays.asList(FrameType.initialized(options.itemFactory.intType))),
new CfReturn(ValueType.INT),
label34,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(options.itemFactory.objectType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 0),
new CfInstanceOf(options.itemFactory.createType("[Ljava/lang/Object;")),
new CfIf(If.Type.EQ, ValueType.INT, label38),
@@ -4703,10 +6014,34 @@
new CfConstNumber(1, ValueType.INT),
new CfGoto(label37),
label36,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(options.itemFactory.objectType)
+ }),
+ Arrays.asList()),
new CfConstNumber(0, ValueType.INT),
label37,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(options.itemFactory.objectType)
+ }),
+ Arrays.asList(FrameType.initialized(options.itemFactory.intType))),
new CfReturn(ValueType.INT),
label38,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(options.itemFactory.objectType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 0),
new CfLoad(ValueType.OBJECT, 1),
new CfInvoke(
@@ -4752,11 +6087,35 @@
false),
new CfIf(If.Type.EQ, ValueType.INT, label2),
label1,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(options.itemFactory.objectType)
+ }),
+ Arrays.asList()),
new CfConstNumber(1, ValueType.INT),
new CfGoto(label3),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(options.itemFactory.objectType)
+ }),
+ Arrays.asList()),
new CfConstNumber(0, ValueType.INT),
label3,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(options.itemFactory.objectType)
+ }),
+ Arrays.asList(FrameType.initialized(options.itemFactory.intType))),
new CfReturn(ValueType.INT),
label4),
ImmutableList.of(),
@@ -4779,6 +6138,11 @@
new CfConstNumber(0, ValueType.INT),
new CfGoto(label2),
label1,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0},
+ new FrameType[] {FrameType.initialized(options.itemFactory.objectType)}),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 0),
new CfInvoke(
182,
@@ -4788,6 +6152,11 @@
options.itemFactory.createString("hashCode")),
false),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0},
+ new FrameType[] {FrameType.initialized(options.itemFactory.objectType)}),
+ Arrays.asList(FrameType.initialized(options.itemFactory.intType))),
new CfReturn(ValueType.INT),
label3),
ImmutableList.of(),
@@ -4810,8 +6179,18 @@
new CfConstNumber(1, ValueType.INT),
new CfGoto(label2),
label1,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0},
+ new FrameType[] {FrameType.initialized(options.itemFactory.objectType)}),
+ Arrays.asList()),
new CfConstNumber(0, ValueType.INT),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0},
+ new FrameType[] {FrameType.initialized(options.itemFactory.objectType)}),
+ Arrays.asList(FrameType.initialized(options.itemFactory.intType))),
new CfReturn(ValueType.INT),
label3),
ImmutableList.of(),
@@ -4834,8 +6213,18 @@
new CfConstNumber(1, ValueType.INT),
new CfGoto(label2),
label1,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0},
+ new FrameType[] {FrameType.initialized(options.itemFactory.objectType)}),
+ Arrays.asList()),
new CfConstNumber(0, ValueType.INT),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0},
+ new FrameType[] {FrameType.initialized(options.itemFactory.objectType)}),
+ Arrays.asList(FrameType.initialized(options.itemFactory.intType))),
new CfReturn(ValueType.INT),
label3),
ImmutableList.of(),
@@ -4858,6 +6247,14 @@
new CfLoad(ValueType.OBJECT, 0),
new CfReturn(ValueType.OBJECT),
label1,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(options.itemFactory.objectType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 1),
new CfConstString(options.itemFactory.createString("defaultObj")),
new CfInvoke(
@@ -4893,6 +6290,15 @@
new CfLoad(ValueType.OBJECT, 0),
new CfReturn(ValueType.OBJECT),
label1,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(
+ options.itemFactory.createType("Ljava/util/function/Supplier;"))
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 1),
new CfConstString(options.itemFactory.createString("supplier")),
new CfInvoke(
@@ -4961,6 +6367,14 @@
false),
new CfThrow(),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(options.itemFactory.stringType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 0),
new CfReturn(ValueType.OBJECT),
label3),
@@ -5011,6 +6425,14 @@
new CfLoad(ValueType.OBJECT, 1),
new CfGoto(label2),
label1,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(options.itemFactory.stringType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 0),
new CfInvoke(
182,
@@ -5020,6 +6442,14 @@
options.itemFactory.createString("toString")),
false),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(options.itemFactory.stringType)
+ }),
+ Arrays.asList(FrameType.initialized(options.itemFactory.stringType))),
new CfReturn(ValueType.OBJECT),
label3),
ImmutableList.of(),
@@ -5067,6 +6497,16 @@
true),
new CfGoto(label3),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.createType("Ljava/util/Optional;")),
+ FrameType.initialized(
+ options.itemFactory.createType("Ljava/util/function/Consumer;")),
+ FrameType.initialized(options.itemFactory.createType("Ljava/lang/Runnable;"))
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 2),
new CfInvoke(
185,
@@ -5076,6 +6516,16 @@
options.itemFactory.createString("run")),
true),
label3,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.createType("Ljava/util/Optional;")),
+ FrameType.initialized(
+ options.itemFactory.createType("Ljava/util/function/Consumer;")),
+ FrameType.initialized(options.itemFactory.createType("Ljava/lang/Runnable;"))
+ }),
+ Arrays.asList()),
new CfReturnVoid(),
label4),
ImmutableList.of(),
@@ -5124,6 +6574,17 @@
true),
new CfGoto(label3),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2},
+ new FrameType[] {
+ FrameType.initialized(
+ options.itemFactory.createType("Ljava/util/OptionalDouble;")),
+ FrameType.initialized(
+ options.itemFactory.createType("Ljava/util/function/DoubleConsumer;")),
+ FrameType.initialized(options.itemFactory.createType("Ljava/lang/Runnable;"))
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 2),
new CfInvoke(
185,
@@ -5133,6 +6594,17 @@
options.itemFactory.createString("run")),
true),
label3,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2},
+ new FrameType[] {
+ FrameType.initialized(
+ options.itemFactory.createType("Ljava/util/OptionalDouble;")),
+ FrameType.initialized(
+ options.itemFactory.createType("Ljava/util/function/DoubleConsumer;")),
+ FrameType.initialized(options.itemFactory.createType("Ljava/lang/Runnable;"))
+ }),
+ Arrays.asList()),
new CfReturnVoid(),
label4),
ImmutableList.of(),
@@ -5181,6 +6653,17 @@
true),
new CfGoto(label3),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2},
+ new FrameType[] {
+ FrameType.initialized(
+ options.itemFactory.createType("Ljava/util/OptionalInt;")),
+ FrameType.initialized(
+ options.itemFactory.createType("Ljava/util/function/IntConsumer;")),
+ FrameType.initialized(options.itemFactory.createType("Ljava/lang/Runnable;"))
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 2),
new CfInvoke(
185,
@@ -5190,6 +6673,17 @@
options.itemFactory.createString("run")),
true),
label3,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2},
+ new FrameType[] {
+ FrameType.initialized(
+ options.itemFactory.createType("Ljava/util/OptionalInt;")),
+ FrameType.initialized(
+ options.itemFactory.createType("Ljava/util/function/IntConsumer;")),
+ FrameType.initialized(options.itemFactory.createType("Ljava/lang/Runnable;"))
+ }),
+ Arrays.asList()),
new CfReturnVoid(),
label4),
ImmutableList.of(),
@@ -5238,6 +6732,17 @@
true),
new CfGoto(label3),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2},
+ new FrameType[] {
+ FrameType.initialized(
+ options.itemFactory.createType("Ljava/util/OptionalLong;")),
+ FrameType.initialized(
+ options.itemFactory.createType("Ljava/util/function/LongConsumer;")),
+ FrameType.initialized(options.itemFactory.createType("Ljava/lang/Runnable;"))
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 2),
new CfInvoke(
185,
@@ -5247,6 +6752,17 @@
options.itemFactory.createString("run")),
true),
label3,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2},
+ new FrameType[] {
+ FrameType.initialized(
+ options.itemFactory.createType("Ljava/util/OptionalLong;")),
+ FrameType.initialized(
+ options.itemFactory.createType("Ljava/util/function/LongConsumer;")),
+ FrameType.initialized(options.itemFactory.createType("Ljava/lang/Runnable;"))
+ }),
+ Arrays.asList()),
new CfReturnVoid(),
label4),
ImmutableList.of(),
@@ -5276,8 +6792,22 @@
new CfConstNumber(1, ValueType.INT),
new CfGoto(label2),
label1,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.createType("Ljava/util/Optional;"))
+ }),
+ Arrays.asList()),
new CfConstNumber(0, ValueType.INT),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.createType("Ljava/util/Optional;"))
+ }),
+ Arrays.asList(FrameType.initialized(options.itemFactory.intType))),
new CfReturn(ValueType.INT),
label3),
ImmutableList.of(),
@@ -5307,8 +6837,24 @@
new CfConstNumber(1, ValueType.INT),
new CfGoto(label2),
label1,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0},
+ new FrameType[] {
+ FrameType.initialized(
+ options.itemFactory.createType("Ljava/util/OptionalDouble;"))
+ }),
+ Arrays.asList()),
new CfConstNumber(0, ValueType.INT),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0},
+ new FrameType[] {
+ FrameType.initialized(
+ options.itemFactory.createType("Ljava/util/OptionalDouble;"))
+ }),
+ Arrays.asList(FrameType.initialized(options.itemFactory.intType))),
new CfReturn(ValueType.INT),
label3),
ImmutableList.of(),
@@ -5338,8 +6884,24 @@
new CfConstNumber(1, ValueType.INT),
new CfGoto(label2),
label1,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0},
+ new FrameType[] {
+ FrameType.initialized(
+ options.itemFactory.createType("Ljava/util/OptionalInt;"))
+ }),
+ Arrays.asList()),
new CfConstNumber(0, ValueType.INT),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0},
+ new FrameType[] {
+ FrameType.initialized(
+ options.itemFactory.createType("Ljava/util/OptionalInt;"))
+ }),
+ Arrays.asList(FrameType.initialized(options.itemFactory.intType))),
new CfReturn(ValueType.INT),
label3),
ImmutableList.of(),
@@ -5369,8 +6931,24 @@
new CfConstNumber(1, ValueType.INT),
new CfGoto(label2),
label1,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0},
+ new FrameType[] {
+ FrameType.initialized(
+ options.itemFactory.createType("Ljava/util/OptionalLong;"))
+ }),
+ Arrays.asList()),
new CfConstNumber(0, ValueType.INT),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0},
+ new FrameType[] {
+ FrameType.initialized(
+ options.itemFactory.createType("Ljava/util/OptionalLong;"))
+ }),
+ Arrays.asList(FrameType.initialized(options.itemFactory.intType))),
new CfReturn(ValueType.INT),
label3),
ImmutableList.of(),
@@ -5414,6 +6992,15 @@
new CfLoad(ValueType.OBJECT, 0),
new CfReturn(ValueType.OBJECT),
label3,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.createType("Ljava/util/Optional;")),
+ FrameType.initialized(
+ options.itemFactory.createType("Ljava/util/function/Supplier;"))
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 1),
new CfInvoke(
185,
@@ -5481,6 +7068,13 @@
true),
new CfReturn(ValueType.OBJECT),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.createType("Ljava/util/Optional;"))
+ }),
+ Arrays.asList()),
new CfInvoke(
184,
options.itemFactory.createMethod(
@@ -5535,6 +7129,14 @@
true),
new CfReturn(ValueType.OBJECT),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0},
+ new FrameType[] {
+ FrameType.initialized(
+ options.itemFactory.createType("Ljava/util/OptionalDouble;"))
+ }),
+ Arrays.asList()),
new CfInvoke(
184,
options.itemFactory.createMethod(
@@ -5589,6 +7191,14 @@
true),
new CfReturn(ValueType.OBJECT),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0},
+ new FrameType[] {
+ FrameType.initialized(
+ options.itemFactory.createType("Ljava/util/OptionalInt;"))
+ }),
+ Arrays.asList()),
new CfInvoke(
184,
options.itemFactory.createMethod(
@@ -5643,6 +7253,14 @@
true),
new CfReturn(ValueType.OBJECT),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0},
+ new FrameType[] {
+ FrameType.initialized(
+ options.itemFactory.createType("Ljava/util/OptionalLong;"))
+ }),
+ Arrays.asList()),
new CfInvoke(
184,
options.itemFactory.createMethod(
@@ -5757,6 +7375,11 @@
true),
new CfGoto(label2),
label1,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0},
+ new FrameType[] {FrameType.initialized(options.itemFactory.objectType)}),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 0),
new CfInvoke(
184,
@@ -5768,6 +7391,13 @@
options.itemFactory.createString("of")),
true),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0},
+ new FrameType[] {FrameType.initialized(options.itemFactory.objectType)}),
+ Arrays.asList(
+ FrameType.initialized(
+ options.itemFactory.createType("Ljava/util/stream/Stream;")))),
new CfReturn(ValueType.OBJECT),
label3),
ImmutableList.of(),
@@ -5804,6 +7434,15 @@
false),
new CfStore(ValueType.INT, 2),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.stringType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.INT, 1),
new CfLoad(ValueType.INT, 2),
new CfIfCmp(If.Type.GE, ValueType.INT, label8),
@@ -5834,6 +7473,16 @@
new CfConstNumber(0, ValueType.INT),
new CfReturn(ValueType.INT),
label6,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2, 3},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.stringType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.INT, 1),
new CfLoad(ValueType.INT, 3),
new CfInvoke(
@@ -5849,6 +7498,11 @@
label7,
new CfGoto(label2),
label8,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0},
+ new FrameType[] {FrameType.initialized(options.itemFactory.stringType)}),
+ Arrays.asList()),
new CfConstNumber(1, ValueType.INT),
new CfReturn(ValueType.INT),
label9),
@@ -5889,6 +7543,15 @@
false),
new CfThrow(),
label1,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.charSequenceType),
+ FrameType.initialized(
+ options.itemFactory.createType("[Ljava/lang/CharSequence;"))
+ }),
+ Arrays.asList()),
new CfNew(options.itemFactory.stringBuilderType),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfInvoke(
@@ -5922,6 +7585,17 @@
new CfConstNumber(1, ValueType.INT),
new CfStore(ValueType.INT, 3),
label5,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2, 3},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.charSequenceType),
+ FrameType.initialized(
+ options.itemFactory.createType("[Ljava/lang/CharSequence;")),
+ FrameType.initialized(options.itemFactory.stringBuilderType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.INT, 3),
new CfLoad(ValueType.OBJECT, 1),
new CfArrayLength(),
@@ -5958,6 +7632,16 @@
new CfIinc(3, 1),
new CfGoto(label5),
label9,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.charSequenceType),
+ FrameType.initialized(
+ options.itemFactory.createType("[Ljava/lang/CharSequence;")),
+ FrameType.initialized(options.itemFactory.stringBuilderType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 2),
new CfInvoke(
182,
@@ -6004,6 +7688,14 @@
false),
new CfThrow(),
label1,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.charSequenceType),
+ FrameType.initialized(options.itemFactory.createType("Ljava/lang/Iterable;"))
+ }),
+ Arrays.asList()),
new CfNew(options.itemFactory.stringBuilderType),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfInvoke(
@@ -6057,6 +7749,16 @@
false),
new CfStackInstruction(CfStackInstruction.Opcode.Pop),
label5,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2, 3},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.charSequenceType),
+ FrameType.initialized(options.itemFactory.createType("Ljava/lang/Iterable;")),
+ FrameType.initialized(options.itemFactory.stringBuilderType),
+ FrameType.initialized(options.itemFactory.createType("Ljava/util/Iterator;"))
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 3),
new CfInvoke(
185,
@@ -6102,6 +7804,16 @@
new CfStackInstruction(CfStackInstruction.Opcode.Pop),
new CfGoto(label5),
label8,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2, 3},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.charSequenceType),
+ FrameType.initialized(options.itemFactory.createType("Ljava/lang/Iterable;")),
+ FrameType.initialized(options.itemFactory.stringBuilderType),
+ FrameType.initialized(options.itemFactory.createType("Ljava/util/Iterator;"))
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 2),
new CfInvoke(
182,
@@ -6186,6 +7898,14 @@
false),
new CfThrow(),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.stringType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 0),
new CfInvoke(
182,
@@ -6201,9 +7921,27 @@
new CfLoad(ValueType.INT, 2),
new CfIf(If.Type.NE, ValueType.INT, label5),
label4,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.stringType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfConstString(options.itemFactory.createString("")),
new CfReturn(ValueType.OBJECT),
label5,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.stringType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.INT, 1),
new CfConstNumber(1, ValueType.INT),
new CfIfCmp(If.Type.NE, ValueType.INT, label7),
@@ -6211,6 +7949,15 @@
new CfLoad(ValueType.OBJECT, 0),
new CfReturn(ValueType.OBJECT),
label7,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.stringType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfNew(options.itemFactory.stringBuilderType),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfLoad(ValueType.INT, 2),
@@ -6229,6 +7976,17 @@
new CfConstNumber(0, ValueType.INT),
new CfStore(ValueType.INT, 4),
label9,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2, 3, 4},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.stringType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.stringBuilderType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.INT, 4),
new CfLoad(ValueType.INT, 1),
new CfIfCmp(If.Type.GE, ValueType.INT, label12),
@@ -6248,6 +8006,16 @@
new CfIinc(4, 1),
new CfGoto(label9),
label12,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2, 3},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.stringType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.stringBuilderType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 3),
new CfInvoke(
182,
@@ -6298,6 +8066,15 @@
false),
new CfStore(ValueType.INT, 2),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.stringType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.INT, 1),
new CfLoad(ValueType.INT, 2),
new CfIfCmp(If.Type.GE, ValueType.INT, label8),
@@ -6327,6 +8104,16 @@
label5,
new CfGoto(label8),
label6,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2, 3},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.stringType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.INT, 1),
new CfLoad(ValueType.INT, 3),
new CfInvoke(
@@ -6342,6 +8129,15 @@
label7,
new CfGoto(label2),
label8,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.stringType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.INT, 2),
new CfLoad(ValueType.INT, 1),
new CfIfCmp(If.Type.LE, ValueType.INT, label14),
@@ -6373,6 +8169,16 @@
label11,
new CfGoto(label14),
label12,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2, 3},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.stringType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.INT, 2),
new CfLoad(ValueType.INT, 3),
new CfInvoke(
@@ -6388,6 +8194,15 @@
label13,
new CfGoto(label8),
label14,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.stringType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 0),
new CfLoad(ValueType.INT, 1),
new CfLoad(ValueType.INT, 2),
@@ -6437,6 +8252,15 @@
false),
new CfStore(ValueType.INT, 2),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.stringType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.INT, 1),
new CfLoad(ValueType.INT, 2),
new CfIfCmp(If.Type.GE, ValueType.INT, label8),
@@ -6466,6 +8290,16 @@
label5,
new CfGoto(label8),
label6,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2, 3},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.stringType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.INT, 1),
new CfLoad(ValueType.INT, 3),
new CfInvoke(
@@ -6481,6 +8315,15 @@
label7,
new CfGoto(label2),
label8,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.stringType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 0),
new CfLoad(ValueType.INT, 1),
new CfLoad(ValueType.INT, 2),
@@ -6526,6 +8369,14 @@
false),
new CfStore(ValueType.INT, 1),
label1,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.stringType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.INT, 1),
new CfIf(If.Type.LE, ValueType.INT, label7),
label2,
@@ -6556,6 +8407,15 @@
label4,
new CfGoto(label7),
label5,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.stringType),
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.INT, 1),
new CfLoad(ValueType.INT, 2),
new CfInvoke(
@@ -6571,6 +8431,14 @@
label6,
new CfGoto(label1),
label7,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.stringType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 0),
new CfConstNumber(0, ValueType.INT),
new CfLoad(ValueType.INT, 1),
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/InliningConstraints.java b/src/main/java/com/android/tools/r8/ir/optimize/InliningConstraints.java
index 1d32c0b..0968624 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/InliningConstraints.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/InliningConstraints.java
@@ -5,23 +5,24 @@
package com.android.tools.r8.ir.optimize;
import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
-import com.android.tools.r8.graph.DexEncodedField;
+import com.android.tools.r8.graph.DexEncodedMember;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.FieldResolutionResult;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.ResolutionResult;
-import com.android.tools.r8.graph.ResolutionResult.SingleResolutionResult;
import com.android.tools.r8.ir.code.Invoke.Type;
import com.android.tools.r8.ir.optimize.Inliner.Constraint;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
-import java.util.function.BiFunction;
+import com.android.tools.r8.utils.TriFunction;
// Computes the inlining constraint for a given instruction.
public class InliningConstraints {
@@ -131,8 +132,7 @@
}
public ConstraintWithTarget forInstanceGet(DexField field, DexProgramClass context) {
- DexField lookup = graphLens.lookupField(field);
- return forFieldInstruction(lookup, appView.appInfo().lookupInstanceTarget(lookup), context);
+ return forFieldInstruction(field, context);
}
public ConstraintWithTarget forInstanceOf(DexType type, DexProgramClass context) {
@@ -140,8 +140,7 @@
}
public ConstraintWithTarget forInstancePut(DexField field, DexProgramClass context) {
- DexField lookup = graphLens.lookupField(field);
- return forFieldInstruction(lookup, appView.appInfo().lookupInstanceTarget(lookup), context);
+ return forFieldInstruction(field, context);
}
public ConstraintWithTarget forInvoke(DexMethod method, Type type, DexProgramClass context) {
@@ -170,43 +169,16 @@
return ConstraintWithTarget.NEVER;
}
- private DexEncodedMethod lookupWhileVerticalClassMerging(
- DexMethod method,
- DexProgramClass context,
- BiFunction<SingleResolutionResult, DexProgramClass, DexEncodedMethod> lookupFunction) {
- SingleResolutionResult singleResolutionResult =
- appView.appInfo().unsafeResolveMethodDueToDexFormat(method).asSingleResolution();
- if (singleResolutionResult == null) {
- return null;
- }
- DexEncodedMethod dexEncodedMethod = lookupFunction.apply(singleResolutionResult, context);
- if (dexEncodedMethod != null) {
- return dexEncodedMethod;
- }
- assert graphLens.lookupType(context.superType) == context.type;
- DexProgramClass superContext = appView.definitionForProgramType(context.superType);
- if (superContext == null) {
- return null;
- }
- DexEncodedMethod alternativeDexEncodedMethod =
- lookupFunction.apply(singleResolutionResult, superContext);
- if (alternativeDexEncodedMethod != null
- && alternativeDexEncodedMethod.holder() == superContext.type) {
- return alternativeDexEncodedMethod;
- }
- return null;
- }
-
public ConstraintWithTarget forInvokeDirect(DexMethod method, DexProgramClass context) {
DexMethod lookup = graphLens.lookupMethod(method);
+ if (lookup.holder.isArrayType()) {
+ return ConstraintWithTarget.ALWAYS;
+ }
+ ResolutionResult resolutionResult = appView.appInfo().unsafeResolveMethodDueToDexFormat(lookup);
DexEncodedMethod target =
- isVerticalClassMerging()
- ? lookupWhileVerticalClassMerging(
- lookup,
- context,
- (res, ctxt) -> res.lookupInvokeDirectTarget(ctxt, appView.appInfo()))
- : appView.appInfo().lookupDirectTarget(lookup, context);
- return forSingleTargetInvoke(lookup, target, context);
+ singleTargetWhileVerticalClassMerging(
+ resolutionResult, context, ResolutionResult::lookupInvokeDirectTarget);
+ return forResolvedMember(resolutionResult.getInitialResolutionHolder(), context, target);
}
public ConstraintWithTarget forInvokeInterface(DexMethod method, DexProgramClass context) {
@@ -228,14 +200,49 @@
public ConstraintWithTarget forInvokeStatic(DexMethod method, DexProgramClass context) {
DexMethod lookup = graphLens.lookupMethod(method);
+ if (lookup.holder.isArrayType()) {
+ return ConstraintWithTarget.ALWAYS;
+ }
+ ResolutionResult resolutionResult = appView.appInfo().unsafeResolveMethodDueToDexFormat(lookup);
DexEncodedMethod target =
- isVerticalClassMerging()
- ? lookupWhileVerticalClassMerging(
- lookup,
- context,
- (res, ctxt) -> res.lookupInvokeStaticTarget(ctxt, appView.appInfo()))
- : appView.appInfo().lookupStaticTarget(lookup, context);
- return forSingleTargetInvoke(lookup, target, context);
+ singleTargetWhileVerticalClassMerging(
+ resolutionResult, context, ResolutionResult::lookupInvokeStaticTarget);
+ if (!allowStaticInterfaceMethodCalls && target != null) {
+ // See b/120121170.
+ DexClass methodClass = appView.definitionFor(graphLens.lookupType(target.holder()));
+ if (methodClass != null && methodClass.isInterface() && target.hasCode()) {
+ return ConstraintWithTarget.NEVER;
+ }
+ }
+ return forResolvedMember(resolutionResult.getInitialResolutionHolder(), context, target);
+ }
+
+ @SuppressWarnings("ConstantConditions")
+ private DexEncodedMethod singleTargetWhileVerticalClassMerging(
+ ResolutionResult resolutionResult,
+ DexProgramClass context,
+ TriFunction<ResolutionResult, DexProgramClass, AppInfoWithClassHierarchy, DexEncodedMethod>
+ lookup) {
+ if (!resolutionResult.isSingleResolution()) {
+ return null;
+ }
+ DexEncodedMethod dexEncodedMethod = lookup.apply(resolutionResult, context, appView.appInfo());
+ if (!isVerticalClassMerging() || dexEncodedMethod != null) {
+ return dexEncodedMethod;
+ }
+ assert isVerticalClassMerging();
+ assert graphLens.lookupType(context.superType) == context.type;
+ DexProgramClass superContext = appView.programDefinitionFor(context.superType, context);
+ if (superContext == null) {
+ return null;
+ }
+ DexEncodedMethod alternativeDexEncodedMethod =
+ lookup.apply(resolutionResult, superContext, appView.appInfo());
+ if (alternativeDexEncodedMethod != null
+ && alternativeDexEncodedMethod.holder() == superContext.type) {
+ return alternativeDexEncodedMethod;
+ }
+ return null;
}
public ConstraintWithTarget forInvokeSuper(DexMethod method, DexProgramClass context) {
@@ -293,13 +300,11 @@
}
public ConstraintWithTarget forStaticGet(DexField field, DexProgramClass context) {
- DexField lookup = graphLens.lookupField(field);
- return forFieldInstruction(lookup, appView.appInfo().lookupStaticTarget(lookup), context);
+ return forFieldInstruction(field, context);
}
public ConstraintWithTarget forStaticPut(DexField field, DexProgramClass context) {
- DexField lookup = graphLens.lookupField(field);
- return forFieldInstruction(lookup, appView.appInfo().lookupStaticTarget(lookup), context);
+ return forFieldInstruction(field, context);
}
public ConstraintWithTarget forStore() {
@@ -326,64 +331,13 @@
return ConstraintWithTarget.NEVER;
}
- private ConstraintWithTarget forFieldInstruction(
- DexField field, DexEncodedField target, DexProgramClass context) {
- // Resolve the field if possible and decide whether the instruction can inlined.
- DexType fieldHolder = graphLens.lookupType(field.holder);
- DexClass fieldClass = appView.definitionFor(fieldHolder);
- if (target != null && fieldClass != null) {
- ConstraintWithTarget fieldConstraintWithTarget =
- ConstraintWithTarget.deriveConstraint(context, fieldHolder, target.accessFlags, appView);
-
- // If the field has not been member-rebound, then we also need to make sure that the
- // `context` has access to the definition of the field.
- //
- // See, for example, InlineNonReboundFieldTest (b/128604123).
- if (field.holder != target.holder()) {
- DexType actualFieldHolder = graphLens.lookupType(target.holder());
- fieldConstraintWithTarget =
- ConstraintWithTarget.meet(
- fieldConstraintWithTarget,
- ConstraintWithTarget.deriveConstraint(
- context, actualFieldHolder, target.accessFlags, appView),
- appView);
- }
-
- ConstraintWithTarget classConstraintWithTarget =
- ConstraintWithTarget.deriveConstraint(
- context, fieldHolder, fieldClass.accessFlags, appView);
- return ConstraintWithTarget.meet(
- fieldConstraintWithTarget, classConstraintWithTarget, appView);
- }
- return ConstraintWithTarget.NEVER;
- }
-
- private ConstraintWithTarget forSingleTargetInvoke(
- DexMethod method, DexEncodedMethod target, DexProgramClass context) {
- if (method.holder.isArrayType()) {
- return ConstraintWithTarget.ALWAYS;
- }
- if (target != null) {
- DexType methodHolder = graphLens.lookupType(target.holder());
- DexClass methodClass = appView.definitionFor(methodHolder);
- if (methodClass != null) {
- if (!allowStaticInterfaceMethodCalls && methodClass.isInterface() && target.hasCode()) {
- // See b/120121170.
- return ConstraintWithTarget.NEVER;
- }
-
- ConstraintWithTarget methodConstraintWithTarget =
- ConstraintWithTarget.deriveConstraint(
- context, methodHolder, target.accessFlags, appView);
- // We also have to take the constraint of the enclosing class into account.
- ConstraintWithTarget classConstraintWithTarget =
- ConstraintWithTarget.deriveConstraint(
- context, methodHolder, methodClass.accessFlags, appView);
- return ConstraintWithTarget.meet(
- methodConstraintWithTarget, classConstraintWithTarget, appView);
- }
- }
- return ConstraintWithTarget.NEVER;
+ private ConstraintWithTarget forFieldInstruction(DexField field, DexProgramClass context) {
+ DexField lookup = graphLens.lookupField(field);
+ FieldResolutionResult fieldResolutionResult = appView.appInfo().resolveField(lookup);
+ return forResolvedMember(
+ fieldResolutionResult.getInitialResolutionHolder(),
+ context,
+ fieldResolutionResult.getResolvedField());
}
private ConstraintWithTarget forVirtualInvoke(
@@ -399,27 +353,28 @@
return ConstraintWithTarget.NEVER;
}
- DexEncodedMethod resolutionTarget = resolutionResult.getSingleTarget();
- if (resolutionTarget == null) {
+ return forResolvedMember(
+ resolutionResult.getInitialResolutionHolder(), context, resolutionResult.getSingleTarget());
+ }
+
+ private ConstraintWithTarget forResolvedMember(
+ DexClass initialResolutionHolder,
+ DexProgramClass context,
+ DexEncodedMember<?, ?> resolvedMember) {
+ if (resolvedMember == null) {
// This will fail at runtime.
return ConstraintWithTarget.NEVER;
}
-
- DexType methodHolder = graphLens.lookupType(resolutionTarget.holder());
- DexClass methodClass = appView.definitionFor(methodHolder);
- assert methodClass != null;
- ConstraintWithTarget methodConstraintWithTarget =
+ DexType resolvedHolder = graphLens.lookupType(resolvedMember.holder());
+ assert initialResolutionHolder != null;
+ ConstraintWithTarget memberConstraintWithTarget =
ConstraintWithTarget.deriveConstraint(
- context, methodHolder, resolutionTarget.accessFlags, appView);
- // We also have to take the constraint of the enclosing class of the resolution result
- // into account. We do not allow inlining this method if it is calling something that
- // is inaccessible. Inlining in that case could move the code to another package making a
- // call succeed that should not succeed. Conversely, if the resolution result is accessible,
- // we have to make sure that inlining cannot make it inaccessible.
+ context, resolvedHolder, resolvedMember.getAccessFlags(), appView);
+ // We also have to take the constraint of the initial resolution holder into account.
ConstraintWithTarget classConstraintWithTarget =
ConstraintWithTarget.deriveConstraint(
- context, methodHolder, methodClass.accessFlags, appView);
+ context, initialResolutionHolder.type, initialResolutionHolder.accessFlags, appView);
return ConstraintWithTarget.meet(
- methodConstraintWithTarget, classConstraintWithTarget, appView);
+ classConstraintWithTarget, memberConstraintWithTarget, appView);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java b/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
index c7e7b6b..7287edd 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
@@ -58,6 +58,7 @@
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.desugar.InterfaceProcessor.InterfaceProcessorNestedGraphLens;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.naming.ClassNameMapper;
import com.android.tools.r8.origin.Origin;
@@ -1313,12 +1314,29 @@
public ProgramMethodSet selectMethodsForOutlining() {
ProgramMethodSet methodsSelectedForOutlining = ProgramMethodSet.create();
assert outlineSites.isEmpty();
+
+ // TODO(b/167345026): This is needed to ensure that default interface methods are mapped to
+ // the corresponding companion methods that contain the code objects. This should be removed
+ // once default interface methods are desugared prior to the first optimization pass.
+ InterfaceProcessorNestedGraphLens interfaceProcessorLens =
+ InterfaceProcessorNestedGraphLens.find(appView.graphLens());
+ if (interfaceProcessorLens != null) {
+ interfaceProcessorLens.toggleMappingToExtraMethods();
+ }
+
for (LongLivedProgramMethodMultisetBuilder outlineMethods : candidateMethodLists) {
if (outlineMethods.size() >= appView.options().outline.threshold) {
ProgramMethodMultiset multiset = outlineMethods.build(appView);
multiset.forEachEntry((method, ignore) -> methodsSelectedForOutlining.add(method));
}
}
+
+ // TODO(b/167345026): Remove once default interface methods are desugared prior to the first
+ // optimization pass.
+ if (interfaceProcessorLens != null) {
+ interfaceProcessorLens.toggleMappingToExtraMethods();
+ }
+
candidateMethodLists.clear();
return methodsSelectedForOutlining;
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java
index 12b42aa..3d7d397 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java
@@ -283,8 +283,11 @@
private void analyzeConstClass(ConstClass constClass, Set<DexType> eligibleEnums) {
// We are using the ConstClass of an enum, which typically means the enum cannot be unboxed.
- // We however allow unboxing if the ConstClass is only used as an argument to Enum#valueOf, to
- // allow unboxing of: MyEnum a = Enum.valueOf(MyEnum.class, "A");.
+ // We however allow unboxing if the ConstClass is used only:
+ // - as an argument to Enum#valueOf, to allow unboxing of:
+ // MyEnum a = Enum.valueOf(MyEnum.class, "A");
+ // - as a receiver for a name method, to allow unboxing of:
+ // MyEnum.class.getName();
DexType enumType = constClass.getValue();
if (!enumsUnboxingCandidates.containsKey(enumType)) {
return;
@@ -299,6 +302,10 @@
return;
}
for (Instruction user : constClass.outValue().uniqueUsers()) {
+ if (user.isInvokeVirtual()
+ && isUnboxableNameMethod(user.asInvokeVirtual().getInvokedMethod())) {
+ continue;
+ }
if (!(user.isInvokeStatic()
&& user.asInvokeStatic().getInvokedMethod() == factory.enumMembers.valueOf)) {
markEnumAsUnboxable(Reason.CONST_CLASS, enumClass);
@@ -311,6 +318,12 @@
eligibleEnums.add(enumType);
}
+ private boolean isUnboxableNameMethod(DexMethod method) {
+ return method == factory.classMethods.getName
+ || method == factory.classMethods.getCanonicalName
+ || method == factory.classMethods.getSimpleName;
+ }
+
private void addNullDependencies(IRCode code, Set<Instruction> uses, Set<DexType> eligibleEnums) {
for (Instruction use : uses) {
if (use.isInvokeMethod()) {
@@ -372,7 +385,7 @@
}
ImmutableSet<DexType> enumsToUnbox = ImmutableSet.copyOf(this.enumsUnboxingCandidates.keySet());
// Update keep info on any of the enum methods of the removed classes.
- updatePinnedItems(enumsToUnbox);
+ updateKeepInfo(enumsToUnbox);
enumUnboxerRewriter = new EnumUnboxingRewriter(appView, enumsToUnbox, enumInstanceFieldDataMap);
DirectMappedDexApplication.Builder appBuilder = appView.appInfo().app().asDirect().builder();
Map<DexType, DexType> newMethodLocation = synthesizeUnboxedEnumsMethodsLocations(appBuilder);
@@ -480,8 +493,7 @@
return syntheticClass;
}
-
- private void updatePinnedItems(Set<DexType> enumsToUnbox) {
+ private void updateKeepInfo(Set<DexType> enumsToUnbox) {
appView
.appInfo()
.getKeepInfo()
@@ -490,8 +502,16 @@
for (DexType type : enumsToUnbox) {
DexProgramClass clazz = asProgramClassOrNull(appView.definitionFor(type));
assert !keepInfo.getClassInfo(clazz).isPinned();
- clazz.forEachProgramMethod(keepInfo::unsafeUnpinMethod);
- clazz.forEachField(field -> keepInfo.unsafeUnpinField(clazz, field));
+ clazz.forEachProgramMethod(
+ method -> {
+ keepInfo.unsafeAllowMinificationOfMethod(method);
+ keepInfo.unsafeUnpinMethod(method);
+ });
+ clazz.forEachProgramField(
+ field -> {
+ keepInfo.unsafeAllowMinificationOfField(field);
+ keepInfo.unsafeUnpinField(field);
+ });
}
});
}
@@ -852,9 +872,20 @@
assert dexClass.isLibraryClass();
if (dexClass.type != factory.enumType) {
// System.identityHashCode(Object) is supported for proto enums.
+ // Object#getClass without outValue and Objects.requireNonNull are supported since R8
+ // rewrites explicit null checks to such instructions.
if (singleTarget == factory.javaLangSystemMethods.identityHashCode) {
return Reason.ELIGIBLE;
}
+ if (singleTarget == factory.objectMembers.getClass
+ && (!invokeMethod.hasOutValue() || !invokeMethod.outValue().hasAnyUsers())) {
+ // This is a hidden null check.
+ return Reason.ELIGIBLE;
+ }
+ if (singleTarget == factory.objectsMethods.requireNonNull
+ || singleTarget == factory.objectsMethods.requireNonNullWithMessage) {
+ return Reason.ELIGIBLE;
+ }
return Reason.UNSUPPORTED_LIBRARY_CALL;
}
// TODO(b/147860220): EnumSet and EnumMap may be interesting to model.
@@ -873,9 +904,7 @@
return Reason.ELIGIBLE;
} else if (singleTarget == factory.enumMembers.constructor) {
// Enum constructor call is allowed only if first call of an enum initializer.
- if (code.method().isInstanceInitializer()
- && code.method().holder() == enumClass.type
- && isFirstInstructionAfterArguments(invokeMethod, code)) {
+ if (code.method().isInstanceInitializer() && code.method().holder() == enumClass.type) {
return Reason.ELIGIBLE;
}
}
@@ -1076,16 +1105,6 @@
return ObjectState.empty();
}
- private boolean isFirstInstructionAfterArguments(InvokeMethod invokeMethod, IRCode code) {
- BasicBlock basicBlock = code.entryBlock();
- for (Instruction instruction : basicBlock.getInstructions()) {
- if (!instruction.isArgument()) {
- return instruction == invokeMethod;
- }
- }
- return false;
- }
-
private void reportEnumsAnalysis() {
assert debugLogEnabled;
Reporter reporter = appView.options().reporter;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingCfMethods.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingCfMethods.java
index a09ea37..922b5f0 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingCfMethods.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingCfMethods.java
@@ -12,6 +12,8 @@
import com.android.tools.r8.cf.code.CfArrayLength;
import com.android.tools.r8.cf.code.CfArrayStore;
import com.android.tools.r8.cf.code.CfConstNumber;
+import com.android.tools.r8.cf.code.CfFrame;
+import com.android.tools.r8.cf.code.CfFrame.FrameType;
import com.android.tools.r8.cf.code.CfGoto;
import com.android.tools.r8.cf.code.CfIf;
import com.android.tools.r8.cf.code.CfIfCmp;
@@ -22,6 +24,7 @@
import com.android.tools.r8.cf.code.CfNew;
import com.android.tools.r8.cf.code.CfNewArray;
import com.android.tools.r8.cf.code.CfReturn;
+import com.android.tools.r8.cf.code.CfReturnVoid;
import com.android.tools.r8.cf.code.CfStackInstruction;
import com.android.tools.r8.cf.code.CfStore;
import com.android.tools.r8.cf.code.CfThrow;
@@ -34,6 +37,8 @@
import com.android.tools.r8.ir.code.ValueType;
import com.android.tools.r8.utils.InternalOptions;
import com.google.common.collect.ImmutableList;
+import it.unimi.dsi.fastutil.ints.Int2ReferenceAVLTreeMap;
+import java.util.Arrays;
public final class EnumUnboxingCfMethods {
@@ -57,6 +62,14 @@
new CfLoad(ValueType.INT, 1),
new CfIf(If.Type.NE, ValueType.INT, label2),
label1,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfNew(options.itemFactory.createType("Ljava/lang/NullPointerException;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfInvoke(
@@ -68,6 +81,14 @@
false),
new CfThrow(),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.INT, 0),
new CfLoad(ValueType.INT, 1),
new CfArithmeticBinop(CfArithmeticBinop.Opcode.Sub, NumericType.INT),
@@ -104,14 +125,38 @@
false),
new CfThrow(),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.INT, 0),
new CfLoad(ValueType.INT, 1),
new CfIfCmp(If.Type.NE, ValueType.INT, label3),
new CfConstNumber(1, ValueType.INT),
new CfGoto(label4),
label3,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfConstNumber(0, ValueType.INT),
label4,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList(FrameType.initialized(options.itemFactory.intType))),
new CfReturn(ValueType.INT),
label5),
ImmutableList.of(),
@@ -143,6 +188,11 @@
false),
new CfThrow(),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0},
+ new FrameType[] {FrameType.initialized(options.itemFactory.intType)}),
+ Arrays.asList()),
new CfLoad(ValueType.INT, 0),
new CfConstNumber(1, ValueType.INT),
new CfArithmeticBinop(CfArithmeticBinop.Opcode.Sub, NumericType.INT),
@@ -173,6 +223,15 @@
new CfConstNumber(0, ValueType.INT),
new CfStore(ValueType.INT, 2),
label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1, 2},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intArrayType),
+ FrameType.initialized(options.itemFactory.intType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.INT, 2),
new CfLoad(ValueType.OBJECT, 1),
new CfArrayLength(),
@@ -188,10 +247,96 @@
new CfIinc(2, 1),
new CfGoto(label2),
label5,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.intArrayType)
+ }),
+ Arrays.asList()),
new CfLoad(ValueType.OBJECT, 1),
new CfReturn(ValueType.OBJECT),
label6),
ImmutableList.of(),
ImmutableList.of());
}
+
+ public static CfCode EnumUnboxingMethods_zeroCheck(InternalOptions options, DexMethod method) {
+ CfLabel label0 = new CfLabel();
+ CfLabel label1 = new CfLabel();
+ CfLabel label2 = new CfLabel();
+ CfLabel label3 = new CfLabel();
+ return new CfCode(
+ method.holder,
+ 2,
+ 1,
+ ImmutableList.of(
+ label0,
+ new CfLoad(ValueType.INT, 0),
+ new CfIf(If.Type.NE, ValueType.INT, label2),
+ label1,
+ new CfNew(options.itemFactory.createType("Ljava/lang/NullPointerException;")),
+ new CfStackInstruction(CfStackInstruction.Opcode.Dup),
+ new CfInvoke(
+ 183,
+ options.itemFactory.createMethod(
+ options.itemFactory.createType("Ljava/lang/NullPointerException;"),
+ options.itemFactory.createProto(options.itemFactory.voidType),
+ options.itemFactory.createString("<init>")),
+ false),
+ new CfThrow(),
+ label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0},
+ new FrameType[] {FrameType.initialized(options.itemFactory.intType)}),
+ Arrays.asList()),
+ new CfReturnVoid(),
+ label3),
+ ImmutableList.of(),
+ ImmutableList.of());
+ }
+
+ public static CfCode EnumUnboxingMethods_zeroCheckMessage(
+ InternalOptions options, DexMethod method) {
+ CfLabel label0 = new CfLabel();
+ CfLabel label1 = new CfLabel();
+ CfLabel label2 = new CfLabel();
+ CfLabel label3 = new CfLabel();
+ return new CfCode(
+ method.holder,
+ 3,
+ 2,
+ ImmutableList.of(
+ label0,
+ new CfLoad(ValueType.INT, 0),
+ new CfIf(If.Type.NE, ValueType.INT, label2),
+ label1,
+ new CfNew(options.itemFactory.createType("Ljava/lang/NullPointerException;")),
+ new CfStackInstruction(CfStackInstruction.Opcode.Dup),
+ new CfLoad(ValueType.OBJECT, 1),
+ new CfInvoke(
+ 183,
+ options.itemFactory.createMethod(
+ options.itemFactory.createType("Ljava/lang/NullPointerException;"),
+ options.itemFactory.createProto(
+ options.itemFactory.voidType, options.itemFactory.stringType),
+ options.itemFactory.createString("<init>")),
+ false),
+ new CfThrow(),
+ label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.intType),
+ FrameType.initialized(options.itemFactory.stringType)
+ }),
+ Arrays.asList()),
+ new CfReturnVoid(),
+ label3),
+ ImmutableList.of(),
+ ImmutableList.of());
+ }
}
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 54d9aaf..ca106ab 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
@@ -77,6 +77,8 @@
private final DexMethod equalsUtilityMethod;
private final DexMethod compareToUtilityMethod;
private final DexMethod valuesUtilityMethod;
+ private final DexMethod zeroCheckMethod;
+ private final DexMethod zeroCheckMessageMethod;
EnumUnboxingRewriter(
AppView<AppInfoWithLiveness> appView,
@@ -114,6 +116,17 @@
factory.enumUnboxingUtilityType,
factory.createProto(factory.intArrayType, factory.intType),
ENUM_UNBOXING_UTILITY_METHOD_PREFIX + "values");
+ // Custom methods for Object#getClass without outValue and Objects.requireNonNull.
+ this.zeroCheckMethod =
+ factory.createMethod(
+ factory.enumUnboxingUtilityType,
+ factory.createProto(factory.voidType, factory.intType),
+ ENUM_UNBOXING_UTILITY_METHOD_PREFIX + "zeroCheck");
+ this.zeroCheckMessageMethod =
+ factory.createMethod(
+ factory.enumUnboxingUtilityType,
+ factory.createProto(factory.voidType, factory.intType, factory.stringType),
+ ENUM_UNBOXING_UTILITY_METHOD_PREFIX + "zeroCheckMessage");
}
public EnumValueInfoMapCollection getEnumsToUnbox() {
@@ -160,6 +173,10 @@
new InvokeStatic(
toStringMethod, invokeMethod.outValue(), invokeMethod.arguments()));
continue;
+ } else if (invokedMethod == factory.objectMembers.getClass) {
+ assert !invokeMethod.hasOutValue() || !invokeMethod.outValue().hasAnyUsers();
+ replaceEnumInvoke(
+ iterator, invokeMethod, zeroCheckMethod, m -> synthesizeZeroCheckMethod());
}
}
// TODO(b/147860220): rewrite also other enum methods.
@@ -195,6 +212,25 @@
invokeStatic.outValue().replaceUsers(argument);
iterator.removeOrReplaceByDebugLocalRead();
}
+ } else if (invokedMethod == factory.objectsMethods.requireNonNull) {
+ assert invokeStatic.inValues().size() == 1;
+ Value argument = invokeStatic.getArgument(0);
+ DexType enumType = getEnumTypeOrNull(argument, convertedEnums);
+ if (enumType != null) {
+ replaceEnumInvoke(
+ iterator, invokeStatic, zeroCheckMethod, m -> synthesizeZeroCheckMethod());
+ }
+ } else if (invokedMethod == factory.objectsMethods.requireNonNullWithMessage) {
+ assert invokeStatic.inValues().size() == 2;
+ Value argument = invokeStatic.getArgument(0);
+ DexType enumType = getEnumTypeOrNull(argument, convertedEnums);
+ if (enumType != null) {
+ replaceEnumInvoke(
+ iterator,
+ invokeStatic,
+ zeroCheckMessageMethod,
+ m -> synthesizeZeroCheckMessageMethod());
+ }
}
}
if (instruction.isStaticGet()) {
@@ -497,6 +533,19 @@
return false;
}
+ private DexEncodedMethod synthesizeZeroCheckMethod() {
+ CfCode cfCode =
+ EnumUnboxingCfMethods.EnumUnboxingMethods_zeroCheck(appView.options(), zeroCheckMethod);
+ return synthesizeUtilityMethod(cfCode, zeroCheckMethod, false);
+ }
+
+ private DexEncodedMethod synthesizeZeroCheckMessageMethod() {
+ CfCode cfCode =
+ EnumUnboxingCfMethods.EnumUnboxingMethods_zeroCheckMessage(
+ appView.options(), zeroCheckMessageMethod);
+ return synthesizeUtilityMethod(cfCode, zeroCheckMessageMethod, false);
+ }
+
private DexEncodedMethod synthesizeOrdinalMethod() {
CfCode cfCode =
EnumUnboxingCfMethods.EnumUnboxingMethods_ordinal(appView.options(), ordinalUtilityMethod);
diff --git a/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java b/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java
index 48f0d33..6f5a765 100644
--- a/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java
@@ -22,6 +22,7 @@
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.InternalOptions.PackageObfuscationMode;
+import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.Timing;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
@@ -73,10 +74,19 @@
this.keepInnerClassStructure = options.keepInnerClassStructure();
// Initialize top-level naming state.
- topLevelState =
- new Namespace(
- getPackageBinaryNameFromJavaType(
- options.getProguardConfiguration().getPackagePrefix()));
+ if (options.testing.enableExperimentalRepackaging) {
+ topLevelState = new Namespace("");
+ String newPackageDescriptor =
+ StringUtils.replaceAll(options.getProguardConfiguration().getPackagePrefix(), ".", "/");
+ if (!newPackageDescriptor.isEmpty()) {
+ registerPackagePrefixesAsUsed(newPackageDescriptor, false);
+ }
+ } else {
+ topLevelState =
+ new Namespace(
+ getPackageBinaryNameFromJavaType(
+ options.getProguardConfiguration().getPackagePrefix()));
+ }
states.put("", topLevelState);
@@ -199,7 +209,8 @@
private void registerClassAsUsed(DexType type, DexString descriptor) {
renaming.put(type, descriptor);
registerPackagePrefixesAsUsed(
- getParentPackagePrefix(getClassBinaryNameFromDescriptor(descriptor.toSourceString())));
+ getParentPackagePrefix(getClassBinaryNameFromDescriptor(descriptor.toSourceString())),
+ isAccessModificationAllowed);
setUsedTypeName(descriptor.toString());
if (keepInnerClassStructure) {
DexType outerClass = getOutClassForType(type);
@@ -215,10 +226,10 @@
}
/** Registers the given package prefix and all of parent packages as used. */
- private void registerPackagePrefixesAsUsed(String packagePrefix) {
+ private void registerPackagePrefixesAsUsed(String packagePrefix, boolean isMinificationAllowed) {
// If -allowaccessmodification is not set, we may keep classes in their original packages,
// accounting for package-private accesses.
- if (!isAccessModificationAllowed) {
+ if (!isMinificationAllowed) {
noObfuscationPrefixes.add(packagePrefix);
}
String usedPrefix = packagePrefix;
diff --git a/src/main/java/com/android/tools/r8/repackaging/Repackaging.java b/src/main/java/com/android/tools/r8/repackaging/Repackaging.java
index 4077f36..5163a17 100644
--- a/src/main/java/com/android/tools/r8/repackaging/Repackaging.java
+++ b/src/main/java/com/android/tools/r8/repackaging/Repackaging.java
@@ -5,12 +5,18 @@
package com.android.tools.r8.repackaging;
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DirectMappedDexApplication;
import com.android.tools.r8.graph.ProgramPackage;
import com.android.tools.r8.graph.ProgramPackageCollection;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.ProguardConfiguration;
+import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.Timing;
+import java.util.IdentityHashMap;
+import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
@@ -29,34 +35,52 @@
public class Repackaging {
private final AppView<AppInfoWithLiveness> appView;
+ private final DexItemFactory dexItemFactory;
private final ProguardConfiguration proguardConfiguration;
public Repackaging(AppView<AppInfoWithLiveness> appView) {
this.appView = appView;
+ this.dexItemFactory = appView.dexItemFactory();
this.proguardConfiguration = appView.options().getProguardConfiguration();
}
- public void run(ExecutorService executorService, Timing timing) throws ExecutionException {
+ public RepackagingLens run(
+ DirectMappedDexApplication.Builder appBuilder, ExecutorService executorService, Timing timing)
+ throws ExecutionException {
timing.begin("Repackage classes");
- run(executorService);
+ RepackagingLens lens = run(appBuilder, executorService);
timing.end();
+ return lens;
}
- private void run(ExecutorService executorService) throws ExecutionException {
+ private RepackagingLens run(
+ DirectMappedDexApplication.Builder appBuilder, ExecutorService executorService)
+ throws ExecutionException {
if (proguardConfiguration.getPackageObfuscationMode().isNone()) {
- return;
+ return null;
}
// For each package, find the set of classes that can be repackaged, and move them to the
// desired namespace.
- ProgramPackageCollection packages = ProgramPackageCollection.create(appView);
- for (ProgramPackage pkg : packages) {
+ Map<DexType, DexType> mappings = new IdentityHashMap<>();
+ for (ProgramPackage pkg : ProgramPackageCollection.create(appView)) {
Iterable<DexProgramClass> classesToRepackage =
computeClassesToRepackage(pkg, executorService);
- // TODO(b/165783399): Move each class in `classesToRepackage`.
+ String newPackageDescriptor = getNewPackageDescriptor(pkg);
+ for (DexProgramClass classToRepackage : classesToRepackage) {
+ // TODO(b/165783399): Handle class collisions when different packages are repackaged into
+ // the same package.
+ DexType newType =
+ classToRepackage.getType().replacePackage(newPackageDescriptor, dexItemFactory);
+ mappings.put(classToRepackage.getType(), newType);
+ }
// TODO(b/165783399): Investigate if repackaging can lead to different dynamic dispatch. See,
// for example, CrossPackageInvokeSuperToPackagePrivateMethodTest.
}
+ if (mappings.isEmpty()) {
+ return null;
+ }
+ return new RepackagingTreeFixer(appBuilder, appView, mappings).run();
}
private Iterable<DexProgramClass> computeClassesToRepackage(
@@ -69,4 +93,14 @@
constraintGraph.populateConstraints(executorService);
return constraintGraph.computeClassesToRepackage();
}
+
+ private String getNewPackageDescriptor(ProgramPackage pkg) {
+ String newPackageDescriptor =
+ StringUtils.replaceAll(proguardConfiguration.getPackagePrefix(), ".", "/");
+ if (proguardConfiguration.getPackageObfuscationMode().isFlattenPackageHierarchy()) {
+ // TODO(b/165783399): Handle collisions among package names.
+ newPackageDescriptor += "/" + pkg.getLastPackageName();
+ }
+ return newPackageDescriptor;
+ }
}
diff --git a/src/main/java/com/android/tools/r8/repackaging/RepackagingConstraintGraph.java b/src/main/java/com/android/tools/r8/repackaging/RepackagingConstraintGraph.java
index 9619f5a..33bbc11 100644
--- a/src/main/java/com/android/tools/r8/repackaging/RepackagingConstraintGraph.java
+++ b/src/main/java/com/android/tools/r8/repackaging/RepackagingConstraintGraph.java
@@ -14,9 +14,11 @@
import com.android.tools.r8.graph.ProgramPackage;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.ThreadUtils;
+import com.android.tools.r8.utils.WorkList;
import com.google.common.collect.Sets;
-import java.util.Collections;
+import java.util.ArrayList;
import java.util.IdentityHashMap;
+import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
@@ -37,6 +39,7 @@
private final AppView<AppInfoWithLiveness> appView;
private final ProgramPackage pkg;
private final Map<DexDefinition, Node> nodes = new IdentityHashMap<>();
+ private final Set<Node> pinnedNodes = Sets.newIdentityHashSet();
public RepackagingConstraintGraph(AppView<AppInfoWithLiveness> appView, ProgramPackage pkg) {
this.appView = appView;
@@ -48,19 +51,26 @@
// Add all the items in the package into the graph. This way we know which items belong to the
// package without having to extract package descriptor strings and comparing them with the
// package descriptor.
- boolean hasPackagePrivateOrProtectedItem = false;
boolean hasPinnedItem = false;
for (DexProgramClass clazz : pkg) {
boolean isPinned = !appView.appInfo().isMinificationAllowed(clazz.getType());
- hasPinnedItem |= isPinned;
- nodes.put(clazz, new Node(clazz));
- hasPackagePrivateOrProtectedItem |= clazz.getAccessFlags().isPackagePrivateOrProtected();
- for (DexEncodedMember<?, ?> member : clazz.members()) {
- nodes.put(member, new Node(member));
- hasPackagePrivateOrProtectedItem |= member.getAccessFlags().isPackagePrivateOrProtected();
+ Node classNode = createNode(clazz);
+ if (isPinned) {
+ pinnedNodes.add(classNode);
}
+ for (DexEncodedMember<?, ?> member : clazz.members()) {
+ Node memberNode = createNode(member);
+ classNode.addNeighbor(memberNode);
+ }
+ hasPinnedItem |= isPinned;
}
- return !hasPinnedItem || !hasPackagePrivateOrProtectedItem;
+ return !hasPinnedItem;
+ }
+
+ private Node createNode(DexDefinition definition) {
+ Node node = new Node(definition);
+ nodes.put(definition, node);
+ return node;
}
Node getNode(DexDefinition definition) {
@@ -101,9 +111,18 @@
}
public Iterable<DexProgramClass> computeClassesToRepackage() {
- // TODO(b/165783399): From each node in the graph that cannot be moved elsewhere due to a -keep
- // rule, mark all neighbors as pinned, and repeat.
- return Collections.emptyList();
+ WorkList<Node> worklist = WorkList.newIdentityWorkList(pinnedNodes);
+ while (worklist.hasNext()) {
+ worklist.addIfNotSeen(worklist.next().getNeighbors());
+ }
+ Set<Node> pinnedNodes = worklist.getSeenSet();
+ List<DexProgramClass> classesToRepackage = new ArrayList<>();
+ for (DexProgramClass clazz : pkg) {
+ if (!pinnedNodes.contains(getNode(clazz))) {
+ classesToRepackage.add(clazz);
+ }
+ }
+ return classesToRepackage;
}
static class Node {
@@ -120,5 +139,9 @@
neighbors.add(neighbor);
neighbor.neighbors.add(this);
}
+
+ public Set<Node> getNeighbors() {
+ return neighbors;
+ }
}
}
diff --git a/src/main/java/com/android/tools/r8/repackaging/RepackagingLens.java b/src/main/java/com/android/tools/r8/repackaging/RepackagingLens.java
new file mode 100644
index 0000000..7c19b0b
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/repackaging/RepackagingLens.java
@@ -0,0 +1,66 @@
+// 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.repackaging;
+
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexField;
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.GraphLens.NestedGraphLens;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.google.common.collect.BiMap;
+import com.google.common.collect.HashBiMap;
+
+public class RepackagingLens extends NestedGraphLens {
+
+ private final BiMap<DexType, DexType> originalTypes;
+
+ private RepackagingLens(
+ AppView<AppInfoWithLiveness> appView,
+ BiMap<DexField, DexField> originalFieldSignatures,
+ BiMap<DexMethod, DexMethod> originalMethodSignatures,
+ BiMap<DexType, DexType> originalTypes) {
+ super(
+ originalTypes.inverse(),
+ originalMethodSignatures.inverse(),
+ originalFieldSignatures.inverse(),
+ originalFieldSignatures,
+ originalMethodSignatures,
+ appView.graphLens(),
+ appView.dexItemFactory());
+ this.originalTypes = originalTypes;
+ }
+
+ @Override
+ public DexType getOriginalType(DexType type) {
+ DexType previous = originalTypes.getOrDefault(type, type);
+ return previousLens.getOriginalType(previous);
+ }
+
+ public static class Builder {
+
+ protected final BiMap<DexType, DexType> originalTypes = HashBiMap.create();
+ protected final BiMap<DexField, DexField> originalFieldSignatures = HashBiMap.create();
+ protected final BiMap<DexMethod, DexMethod> originalMethodSignatures = HashBiMap.create();
+
+ public void recordMove(DexField from, DexField to) {
+ originalFieldSignatures.put(to, from);
+ }
+
+ public void recordMove(DexMethod from, DexMethod to) {
+ originalMethodSignatures.put(to, from);
+ }
+
+ public void recordMove(DexType from, DexType to) {
+ originalTypes.put(to, from);
+ }
+
+ public RepackagingLens build(AppView<AppInfoWithLiveness> appView) {
+ assert !originalTypes.isEmpty();
+ return new RepackagingLens(
+ appView, originalFieldSignatures, originalMethodSignatures, originalTypes);
+ }
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/repackaging/RepackagingTreeFixer.java b/src/main/java/com/android/tools/r8/repackaging/RepackagingTreeFixer.java
new file mode 100644
index 0000000..3591ff7
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/repackaging/RepackagingTreeFixer.java
@@ -0,0 +1,281 @@
+// 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.repackaging;
+
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexEncodedField;
+import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexField;
+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.DexType;
+import com.android.tools.r8.graph.DexTypeList;
+import com.android.tools.r8.graph.DirectMappedDexApplication;
+import com.android.tools.r8.graph.EnclosingMethodAttribute;
+import com.android.tools.r8.graph.InnerClassAttribute;
+import com.android.tools.r8.graph.NestHostClassAttribute;
+import com.android.tools.r8.graph.NestMemberClassAttribute;
+import com.android.tools.r8.shaking.AnnotationFixer;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.IdentityHashMap;
+import java.util.List;
+import java.util.Map;
+
+public class RepackagingTreeFixer {
+
+ private final DirectMappedDexApplication.Builder appBuilder;
+ private final AppView<AppInfoWithLiveness> appView;
+ private final DexItemFactory dexItemFactory;
+ private final RepackagingLens.Builder lensBuilder = new RepackagingLens.Builder();
+ private final Map<DexType, DexType> repackagedClasses;
+
+ private final Map<DexType, DexProgramClass> newProgramClasses = new IdentityHashMap<>();
+ private final Map<DexProto, DexProto> protoFixupCache = new IdentityHashMap<>();
+
+ public RepackagingTreeFixer(
+ DirectMappedDexApplication.Builder appBuilder,
+ AppView<AppInfoWithLiveness> appView,
+ Map<DexType, DexType> repackagedClasses) {
+ this.appBuilder = appBuilder;
+ this.appView = appView;
+ this.dexItemFactory = appView.dexItemFactory();
+ this.repackagedClasses = repackagedClasses;
+ }
+
+ public RepackagingLens run() {
+ // Globally substitute repackaged class types.
+ for (DexProgramClass clazz : appView.appInfo().classesWithDeterministicOrder()) {
+ newProgramClasses.computeIfAbsent(clazz.getType(), ignore -> fixupClass(clazz));
+ }
+ appBuilder.replaceProgramClasses(new ArrayList<>(newProgramClasses.values()));
+ RepackagingLens lens = lensBuilder.build(appView);
+ new AnnotationFixer(lens).run(appView.appInfo().classes());
+ return lens;
+ }
+
+ private DexProgramClass fixupClass(DexProgramClass clazz) {
+ DexProgramClass newClass =
+ new DexProgramClass(
+ fixupType(clazz.getType()),
+ clazz.getOriginKind(),
+ clazz.getOrigin(),
+ clazz.getAccessFlags(),
+ fixupType(clazz.superType),
+ fixupTypeList(clazz.interfaces),
+ clazz.getSourceFile(),
+ fixupNestHost(clazz.getNestHost()),
+ fixupNestMemberAttributes(clazz.getNestMembersClassAttributes()),
+ fixupEnclosingMethodAttribute(clazz.getEnclosingMethodAttribute()),
+ fixupInnerClassAttributes(clazz.getInnerClasses()),
+ clazz.annotations(),
+ DexEncodedField.EMPTY_ARRAY,
+ DexEncodedField.EMPTY_ARRAY,
+ DexEncodedMethod.EMPTY_ARRAY,
+ DexEncodedMethod.EMPTY_ARRAY,
+ dexItemFactory.getSkipNameValidationForTesting(),
+ DexProgramClass::checksumFromType,
+ fixupSynthesizedFrom(clazz.getSynthesizedFrom()));
+ newClass.setInstanceFields(fixupFields(clazz.instanceFields()));
+ newClass.setStaticFields(fixupFields(clazz.staticFields()));
+ newClass.setDirectMethods(
+ fixupMethods(
+ clazz.getMethodCollection().directMethods(),
+ clazz.getMethodCollection().numberOfDirectMethods()));
+ newClass.setVirtualMethods(
+ fixupMethods(
+ clazz.getMethodCollection().virtualMethods(),
+ clazz.getMethodCollection().numberOfVirtualMethods()));
+ if (newClass.getType() != clazz.getType()) {
+ lensBuilder.recordMove(clazz.getType(), newClass.getType());
+ }
+ return newClass;
+ }
+
+ private EnclosingMethodAttribute fixupEnclosingMethodAttribute(
+ EnclosingMethodAttribute enclosingMethodAttribute) {
+ if (enclosingMethodAttribute == null) {
+ return null;
+ }
+ DexType enclosingClassType = enclosingMethodAttribute.getEnclosingClass();
+ if (enclosingClassType != null) {
+ DexType newEnclosingClassType = fixupType(enclosingClassType);
+ return newEnclosingClassType != enclosingClassType
+ ? new EnclosingMethodAttribute(newEnclosingClassType)
+ : enclosingMethodAttribute;
+ }
+ DexMethod enclosingMethod = enclosingMethodAttribute.getEnclosingMethod();
+ assert enclosingMethod != null;
+ DexMethod newEnclosingMethod =
+ fixupMethodReference(enclosingMethodAttribute.getEnclosingMethod());
+ return newEnclosingMethod != enclosingMethod
+ ? new EnclosingMethodAttribute(newEnclosingMethod)
+ : enclosingMethodAttribute;
+ }
+
+ private DexEncodedField[] fixupFields(List<DexEncodedField> fields) {
+ if (fields == null) {
+ return DexEncodedField.EMPTY_ARRAY;
+ }
+ DexEncodedField[] newFields = new DexEncodedField[fields.size()];
+ for (int i = 0; i < fields.size(); i++) {
+ newFields[i] = fixupField(fields.get(i));
+ }
+ return newFields;
+ }
+
+ private DexEncodedField fixupField(DexEncodedField field) {
+ DexField fieldReference = field.toReference();
+ DexField newFieldReference = fixupFieldReference(fieldReference);
+ if (newFieldReference != fieldReference) {
+ lensBuilder.recordMove(fieldReference, newFieldReference);
+ return field.toTypeSubstitutedField(newFieldReference);
+ }
+ return field;
+ }
+
+ private DexField fixupFieldReference(DexField field) {
+ DexType newType = fixupType(field.type);
+ DexType newHolder = fixupType(field.holder);
+ return dexItemFactory.createField(newHolder, newType, field.name);
+ }
+
+ private List<InnerClassAttribute> fixupInnerClassAttributes(
+ List<InnerClassAttribute> innerClassAttributes) {
+ if (innerClassAttributes.isEmpty()) {
+ return innerClassAttributes;
+ }
+ boolean changed = false;
+ List<InnerClassAttribute> newInnerClassAttributes = new ArrayList<>();
+ for (InnerClassAttribute innerClassAttribute : innerClassAttributes) {
+ DexType innerClassType = innerClassAttribute.getInner();
+ DexType newInnerClassType = fixupType(innerClassType);
+ DexType outerClassType = innerClassAttribute.getOuter();
+ DexType newOuterClassType = fixupType(outerClassType);
+ newInnerClassAttributes.add(
+ new InnerClassAttribute(
+ innerClassAttribute.getAccess(),
+ newInnerClassType,
+ newOuterClassType,
+ innerClassAttribute.getInnerName()));
+ changed |= newInnerClassType != innerClassType || newOuterClassType != outerClassType;
+ }
+ return changed ? newInnerClassAttributes : innerClassAttributes;
+ }
+
+ private DexEncodedMethod[] fixupMethods(Iterable<DexEncodedMethod> methods, int size) {
+ if (size == 0) {
+ return DexEncodedMethod.EMPTY_ARRAY;
+ }
+ int i = 0;
+ DexEncodedMethod[] newMethods = new DexEncodedMethod[size];
+ for (DexEncodedMethod method : methods) {
+ newMethods[i++] = fixupMethod(method);
+ }
+ return newMethods;
+ }
+
+ private DexEncodedMethod fixupMethod(DexEncodedMethod method) {
+ DexMethod methodReference = method.toReference();
+ DexMethod newMethodReference = fixupMethodReference(methodReference);
+ if (newMethodReference != methodReference) {
+ lensBuilder.recordMove(methodReference, newMethodReference);
+ return method.toTypeSubstitutedMethod(newMethodReference);
+ }
+ return method;
+ }
+
+ private DexMethod fixupMethodReference(DexMethod method) {
+ return appView
+ .dexItemFactory()
+ .createMethod(fixupType(method.holder), fixupProto(method.proto), method.name);
+ }
+
+ private NestHostClassAttribute fixupNestHost(DexType type) {
+ return type != null ? new NestHostClassAttribute(fixupType(type)) : null;
+ }
+
+ private List<NestMemberClassAttribute> fixupNestMemberAttributes(
+ List<NestMemberClassAttribute> nestMemberAttributes) {
+ if (nestMemberAttributes.isEmpty()) {
+ return nestMemberAttributes;
+ }
+ boolean changed = false;
+ List<NestMemberClassAttribute> newNestMemberAttributes =
+ new ArrayList<>(nestMemberAttributes.size());
+ for (NestMemberClassAttribute nestMemberAttribute : nestMemberAttributes) {
+ DexType nestMemberType = nestMemberAttribute.getNestMember();
+ DexType newNestMemberType = fixupType(nestMemberType);
+ newNestMemberAttributes.add(new NestMemberClassAttribute(newNestMemberType));
+ changed |= newNestMemberType != nestMemberType;
+ }
+ return changed ? newNestMemberAttributes : nestMemberAttributes;
+ }
+
+ private DexProto fixupProto(DexProto proto) {
+ DexProto result = protoFixupCache.get(proto);
+ if (result == null) {
+ DexType returnType = fixupType(proto.returnType);
+ DexType[] arguments = fixupTypes(proto.parameters.values);
+ result = dexItemFactory.createProto(returnType, arguments);
+ protoFixupCache.put(proto, result);
+ }
+ return result;
+ }
+
+ private Collection<DexProgramClass> fixupSynthesizedFrom(
+ Collection<DexProgramClass> synthesizedFrom) {
+ if (synthesizedFrom.isEmpty()) {
+ return synthesizedFrom;
+ }
+ boolean changed = false;
+ List<DexProgramClass> newSynthesizedFrom = new ArrayList<>(synthesizedFrom.size());
+ for (DexProgramClass clazz : synthesizedFrom) {
+ // TODO(b/165783399): What do we want to put here if the class that this was synthesized from
+ // is no longer in the application?
+ assert appView.definitionFor(clazz.type) != null;
+ DexProgramClass newClass =
+ newProgramClasses.computeIfAbsent(clazz.getType(), ignore -> fixupClass(clazz));
+ newSynthesizedFrom.add(newClass);
+ changed |= newClass != clazz;
+ }
+ return changed ? newSynthesizedFrom : synthesizedFrom;
+ }
+
+ private DexType fixupType(DexType type) {
+ if (type.isArrayType()) {
+ DexType base = type.toBaseType(dexItemFactory);
+ DexType fixed = fixupType(base);
+ if (base == fixed) {
+ return type;
+ }
+ return type.replaceBaseType(fixed, dexItemFactory);
+ }
+ if (type.isClassType()) {
+ return repackagedClasses.getOrDefault(type, type);
+ }
+ return type;
+ }
+
+ private DexType[] fixupTypes(DexType[] types) {
+ boolean changed = false;
+ DexType[] newTypes = new DexType[types.length];
+ for (int i = 0; i < newTypes.length; i++) {
+ DexType type = types[i];
+ DexType newType = fixupType(types[i]);
+ newTypes[i] = newType;
+ changed |= newType != type;
+ }
+ return changed ? newTypes : types;
+ }
+
+ private DexTypeList fixupTypeList(DexTypeList types) {
+ DexType[] newTypes = fixupTypes(types.values);
+ return newTypes != types.values ? new DexTypeList(newTypes) : types;
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
index 6768368..05c6f6c 100644
--- a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
+++ b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
@@ -1025,7 +1025,7 @@
// TODO(sgjesse): Rewrite call sites as well? Right now they are only used by minification
// after second tree shaking.
callSites,
- keepInfo.rewrite(lens),
+ keepInfo.rewrite(lens, application.options),
lens.rewriteReferenceKeys(mayHaveSideEffects),
lens.rewriteReferenceKeys(noSideEffects),
lens.rewriteReferenceKeys(assumedValues),
diff --git a/src/main/java/com/android/tools/r8/shaking/FieldAccessInfoCollectionModifier.java b/src/main/java/com/android/tools/r8/shaking/FieldAccessInfoCollectionModifier.java
new file mode 100644
index 0000000..4e9d977
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/shaking/FieldAccessInfoCollectionModifier.java
@@ -0,0 +1,96 @@
+// 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.shaking;
+
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexField;
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.FieldAccessInfoCollectionImpl;
+import com.android.tools.r8.graph.FieldAccessInfoImpl;
+import com.android.tools.r8.graph.ProgramMethod;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.IdentityHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.BiConsumer;
+import java.util.function.Function;
+
+public class FieldAccessInfoCollectionModifier {
+
+ static class FieldReferences {
+ final List<DexMethod> writeContexts = new ArrayList<>();
+ final List<DexMethod> readContexts = new ArrayList<>();
+
+ void fixUpMethods(List<DexMethod> methods, Function<DexMethod, DexMethod> fixUpMethod) {
+ for (int i = 0; i < methods.size(); i++) {
+ DexMethod method = methods.get(i);
+ DexMethod newMethod = fixUpMethod.apply(method);
+ if (method != newMethod) {
+ methods.set(i, newMethod);
+ }
+ }
+ }
+
+ void fixUp(Function<DexMethod, DexMethod> fixUpMethod) {
+ fixUpMethods(writeContexts, fixUpMethod);
+ fixUpMethods(readContexts, fixUpMethod);
+ }
+ }
+
+ final Map<DexField, FieldReferences> newFieldAccesses;
+
+ FieldAccessInfoCollectionModifier(Map<DexField, FieldReferences> newFieldAccesses) {
+ this.newFieldAccesses = newFieldAccesses;
+ }
+
+ void forEachFieldAccess(
+ AppView<?> appView,
+ Collection<DexMethod> methods,
+ DexField field,
+ BiConsumer<DexField, ProgramMethod> record) {
+ for (DexMethod method : methods) {
+ ProgramMethod programMethod =
+ appView.definitionFor(method.holder).asProgramClass().lookupProgramMethod(method);
+ record.accept(field, programMethod);
+ }
+ }
+
+ public void modify(AppView<AppInfoWithLiveness> appView) {
+ FieldAccessInfoCollectionImpl impl = appView.appInfo().getMutableFieldAccessInfoCollection();
+ newFieldAccesses.forEach(
+ (field, info) -> {
+ FieldAccessInfoImpl fieldAccessInfo = new FieldAccessInfoImpl(field);
+ forEachFieldAccess(appView, info.readContexts, field, fieldAccessInfo::recordRead);
+ forEachFieldAccess(appView, info.writeContexts, field, fieldAccessInfo::recordWrite);
+ impl.extend(field, fieldAccessInfo);
+ });
+ }
+
+ public static class Builder {
+ final Map<DexField, FieldReferences> newFieldAccesses = new IdentityHashMap<>();
+
+ public Builder() {}
+
+ public FieldAccessInfoCollectionModifier build(Function<DexMethod, DexMethod> fixupMethod) {
+ for (FieldReferences fieldReference : newFieldAccesses.values()) {
+ fieldReference.fixUp(fixupMethod);
+ }
+ return new FieldAccessInfoCollectionModifier(newFieldAccesses);
+ }
+
+ FieldReferences getFieldReferences(DexField field) {
+ return newFieldAccesses.computeIfAbsent(field, ignore -> new FieldReferences());
+ }
+
+ public void fieldReadByMethod(DexField field, DexMethod method) {
+ getFieldReferences(field).readContexts.add(method);
+ }
+
+ public void fieldWrittenByMethod(DexField field, DexMethod method) {
+ getFieldReferences(field).writeContexts.add(method);
+ }
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/shaking/KeepInfoCollection.java b/src/main/java/com/android/tools/r8/shaking/KeepInfoCollection.java
index ee30fce..efc610a 100644
--- a/src/main/java/com/android/tools/r8/shaking/KeepInfoCollection.java
+++ b/src/main/java/com/android/tools/r8/shaking/KeepInfoCollection.java
@@ -20,6 +20,8 @@
import com.android.tools.r8.graph.ProgramField;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.shaking.KeepFieldInfo.Joiner;
+import com.android.tools.r8.utils.InternalOptions;
+import com.google.common.collect.Streams;
import java.util.ArrayList;
import java.util.Collection;
import java.util.IdentityHashMap;
@@ -160,7 +162,7 @@
@Deprecated
public abstract void forEachPinnedField(Consumer<DexField> consumer);
- public abstract KeepInfoCollection rewrite(NestedGraphLens lens);
+ public abstract KeepInfoCollection rewrite(NestedGraphLens lens, InternalOptions options);
public abstract KeepInfoCollection mutate(Consumer<MutableKeepInfoCollection> mutator);
@@ -196,26 +198,39 @@
}
@Override
- public KeepInfoCollection rewrite(NestedGraphLens lens) {
+ public KeepInfoCollection rewrite(NestedGraphLens lens, InternalOptions options) {
Map<DexType, KeepClassInfo> newClassInfo = new IdentityHashMap<>(keepClassInfo.size());
keepClassInfo.forEach(
(type, info) -> {
DexType newType = lens.lookupType(type);
- assert !info.isPinned() || type == newType;
+ assert newType == type || !info.isPinned() || info.isMinificationAllowed(options);
newClassInfo.put(newType, info);
});
Map<DexMethod, KeepMethodInfo> newMethodInfo = new IdentityHashMap<>(keepMethodInfo.size());
keepMethodInfo.forEach(
(method, info) -> {
DexMethod newMethod = lens.getRenamedMethodSignature(method);
- assert !info.isPinned() || method == newMethod;
+ assert !info.isPinned()
+ || info.isMinificationAllowed(options)
+ || newMethod.name == method.name;
+ assert !info.isPinned() || newMethod.getArity() == method.getArity();
+ assert !info.isPinned()
+ || Streams.zip(
+ newMethod.getParameters().stream(),
+ method.getParameters().stream().map(lens::lookupType),
+ Object::equals)
+ .allMatch(x -> x);
+ assert !info.isPinned()
+ || newMethod.getReturnType() == lens.lookupType(method.getReturnType());
newMethodInfo.put(newMethod, info);
});
Map<DexField, KeepFieldInfo> newFieldInfo = new IdentityHashMap<>(keepFieldInfo.size());
keepFieldInfo.forEach(
(field, info) -> {
DexField newField = lens.getRenamedFieldSignature(field);
- assert !info.isPinned() || field == newField;
+ assert newField.name == field.name
+ || !info.isPinned()
+ || info.isMinificationAllowed(options);
newFieldInfo.put(newField, info);
});
Map<DexReference, List<Consumer<KeepInfo.Joiner<?, ?, ?>>>> newRuleInstances =
@@ -353,6 +368,13 @@
joinMethod(holder, method, KeepInfo.Joiner::pin);
}
+ public void unsafeAllowMinificationOfMethod(ProgramMethod method) {
+ KeepMethodInfo info = keepMethodInfo.get(method.getReference());
+ if (info != null && !info.internalIsMinificationAllowed()) {
+ keepMethodInfo.put(method.getReference(), info.builder().allowMinification().build());
+ }
+ }
+
// Unpinning a method represents a non-monotonic change to the keep info of that item.
// This is generally unsound as it requires additional analysis to determine that a method that
// was pinned no longer is. A known sound example is the enum analysis that will identify
@@ -409,12 +431,19 @@
}
}
- public void unsafeUnpinField(DexProgramClass holder, DexEncodedField field) {
- assert holder.type == field.holder();
- assert !getClassInfo(holder).isPinned();
- KeepFieldInfo info = this.keepFieldInfo.get(field.toReference());
+ public void unsafeAllowMinificationOfField(ProgramField field) {
+ assert !getClassInfo(field.getHolder()).isPinned();
+ KeepFieldInfo info = keepFieldInfo.get(field.getReference());
+ if (info != null && !info.internalIsMinificationAllowed()) {
+ keepFieldInfo.put(field.getReference(), info.builder().allowAccessModification().build());
+ }
+ }
+
+ public void unsafeUnpinField(ProgramField field) {
+ assert !getClassInfo(field.getHolder()).isPinned();
+ KeepFieldInfo info = this.keepFieldInfo.get(field.getReference());
if (info != null && info.isPinned()) {
- keepFieldInfo.put(field.toReference(), info.builder().unpin().build());
+ keepFieldInfo.put(field.getReference(), info.builder().unpin().build());
}
}
diff --git a/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java b/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
index 08830cc..db43676 100644
--- a/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
+++ b/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
@@ -8,13 +8,11 @@
import com.android.tools.r8.Diagnostic;
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.BottomUpClassHierarchyTraversal;
import com.android.tools.r8.graph.DexAnnotation;
import com.android.tools.r8.graph.DexAnnotationSet;
-import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexDefinition;
import com.android.tools.r8.graph.DexDefinitionSupplier;
@@ -29,6 +27,7 @@
import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.DirectMappedDexApplication;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.ResolutionResult.SingleResolutionResult;
import com.android.tools.r8.graph.SubtypingInfo;
@@ -1962,26 +1961,30 @@
return false;
}
- public boolean verifyKeptItemsAreKept(DexApplication application, AppInfo appInfo) {
+ public boolean verifyKeptItemsAreKept(AppView<? extends AppInfoWithClassHierarchy> appView) {
+ AppInfoWithClassHierarchy appInfo = appView.appInfo();
+ GraphLens lens = appView.graphLens();
// Create a mapping from each required type to the set of required members on that type.
Map<DexType, Set<DexMember<?, ?>>> requiredMembersPerType = new IdentityHashMap<>();
noShrinking.forEachClass(
type -> {
- assert !appInfo.hasLiveness() || appInfo.withLiveness().isPinned(type)
- : "Expected reference `" + type.toSourceString() + "` to be pinned";
- requiredMembersPerType.computeIfAbsent(type, key -> Sets.newIdentityHashSet());
+ DexType rewrittenType = lens.lookupType(type);
+ assert !appInfo.hasLiveness() || appInfo.withLiveness().isPinned(rewrittenType)
+ : "Expected reference `" + rewrittenType.toSourceString() + "` to be pinned";
+ requiredMembersPerType.computeIfAbsent(rewrittenType, key -> Sets.newIdentityHashSet());
});
noShrinking.forEachMember(
member -> {
- assert !appInfo.hasLiveness() || appInfo.withLiveness().isPinned(member)
- : "Expected reference `" + member.toSourceString() + "` to be pinned";
+ DexMember<?, ?> rewrittenMember = lens.getRenamedMemberSignature(member);
+ assert !appInfo.hasLiveness() || appInfo.withLiveness().isPinned(rewrittenMember)
+ : "Expected reference `" + rewrittenMember.toSourceString() + "` to be pinned";
requiredMembersPerType
- .computeIfAbsent(member.holder, key -> Sets.newIdentityHashSet())
- .add(member);
+ .computeIfAbsent(rewrittenMember.holder, key -> Sets.newIdentityHashSet())
+ .add(rewrittenMember);
});
// Run through each class in the program and check that it has members it must have.
- for (DexProgramClass clazz : application.classes()) {
+ for (DexProgramClass clazz : appView.appInfo().classes()) {
Set<DexMember<?, ?>> requiredMembers =
requiredMembersPerType.getOrDefault(clazz.type, ImmutableSet.of());
@@ -2023,7 +2026,7 @@
// If the map is non-empty, then a type in the root set was not in the application.
if (!requiredMembersPerType.isEmpty()) {
DexType type = requiredMembersPerType.keySet().iterator().next();
- DexClass clazz = application.definitionFor(type);
+ DexClass clazz = appView.definitionFor(type);
assert clazz == null || clazz.isProgramClass()
: "Unexpected library type in root set: `" + type + "`";
assert requiredMembersPerType.isEmpty()
diff --git a/src/main/java/com/android/tools/r8/utils/MapUtils.java b/src/main/java/com/android/tools/r8/utils/MapUtils.java
new file mode 100644
index 0000000..3929e87
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/utils/MapUtils.java
@@ -0,0 +1,14 @@
+// Copyright (c) 2019, 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 java.util.Map;
+
+public class MapUtils {
+
+ public static <T> void removeIdentityMappings(Map<T, T> map) {
+ map.entrySet().removeIf(entry -> entry.getKey() == entry.getValue());
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/AsmTestBase.java b/src/test/java/com/android/tools/r8/AsmTestBase.java
index 6195ea0..4a24331 100644
--- a/src/test/java/com/android/tools/r8/AsmTestBase.java
+++ b/src/test/java/com/android/tools/r8/AsmTestBase.java
@@ -21,18 +21,6 @@
public class AsmTestBase extends TestBase {
- protected void ensureException(String main, Class<? extends Throwable> exceptionClass,
- byte[]... classes) throws Exception {
- ensureExceptionThrown(runOnJavaRaw(main, classes), exceptionClass);
- AndroidApp app = buildAndroidApp(classes);
- ensureExceptionThrown(runOnArtRaw(compileWithD8(app), main), exceptionClass);
- ensureExceptionThrown(runOnArtRaw(compileWithR8(app), main), exceptionClass);
- ensureExceptionThrown(
- runOnArtRaw(compileWithR8(app, keepMainProguardConfiguration(main) + "-dontobfuscate\n"),
- main),
- exceptionClass);
- }
-
protected void ensureSameOutput(String main, AndroidApiLevel apiLevel, byte[]... classes)
throws Exception {
ensureSameOutput(main, apiLevel, Collections.emptyList(), classes);
diff --git a/src/test/java/com/android/tools/r8/JvmTestBuilder.java b/src/test/java/com/android/tools/r8/JvmTestBuilder.java
index e59ea66..8698d61 100644
--- a/src/test/java/com/android/tools/r8/JvmTestBuilder.java
+++ b/src/test/java/com/android/tools/r8/JvmTestBuilder.java
@@ -167,6 +167,10 @@
return self();
}
+ public JvmTestBuilder noVerify() {
+ return addVmArguments("-noverify");
+ }
+
public JvmTestBuilder addAndroidBuildVersion() {
addVmArguments("-D" + AndroidBuildVersion.PROPERTY + "=10000");
return addProgramClasses(AndroidBuildVersion.class);
diff --git a/src/test/java/com/android/tools/r8/L8CommandTest.java b/src/test/java/com/android/tools/r8/L8CommandTest.java
index 1631830..c83cd38 100644
--- a/src/test/java/com/android/tools/r8/L8CommandTest.java
+++ b/src/test/java/com/android/tools/r8/L8CommandTest.java
@@ -4,6 +4,8 @@
package com.android.tools.r8;
import static com.android.tools.r8.DiagnosticsMatcher.diagnosticMessage;
+import static com.android.tools.r8.MarkerMatcher.assertMarkersMatch;
+import static com.android.tools.r8.MarkerMatcher.markerTool;
import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -14,11 +16,13 @@
import com.android.tools.r8.AssertionsConfiguration.AssertionTransformation;
import com.android.tools.r8.AssertionsConfiguration.AssertionTransformationScope;
import com.android.tools.r8.dex.Marker;
+import com.android.tools.r8.dex.Marker.Tool;
import com.android.tools.r8.origin.EmbeddedOrigin;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.FileUtils;
import com.android.tools.r8.utils.ThreadUtils;
+import com.google.common.collect.ImmutableList;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -26,7 +30,6 @@
import java.util.Collection;
import java.util.Collections;
import java.util.List;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -66,7 +69,7 @@
}
@Test
- public void testMarker() throws Throwable {
+ public void testDexMarker() throws Throwable {
Path output = temp.newFolder().toPath().resolve("desugar_jdk_libs.zip");
L8.run(
L8Command.builder()
@@ -77,14 +80,28 @@
StringResource.fromFile(ToolHelper.DESUGAR_LIB_JSON_FOR_TESTING))
.setOutput(output, OutputMode.DexIndexed)
.build());
- Collection<Marker> markers = ExtractMarker.extractMarkerFromDexFile(output);
- // TODO(b/134732760): Shouldn't we remove the D8/R8 marker?
- assertEquals(2, markers.size());
- Marker marker = markers.iterator().next();
+ assertMarkersMatch(
+ ExtractMarker.extractMarkerFromDexFile(output),
+ ImmutableList.of(markerTool(Tool.L8), markerTool(Tool.D8)));
}
@Test
- public void testMarkerCommandLine() throws Throwable {
+ public void testClassFileMarker() throws Throwable {
+ Path output = temp.newFolder().toPath().resolve("desugar_jdk_libs.zip");
+ L8.run(
+ L8Command.builder()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
+ .addProgramFiles(ToolHelper.getDesugarJDKLibs())
+ .setMinApiLevel(20)
+ .addDesugaredLibraryConfiguration(
+ StringResource.fromFile(ToolHelper.DESUGAR_LIB_JSON_FOR_TESTING))
+ .setOutput(output, OutputMode.ClassFile)
+ .build());
+ assertMarkersMatch(ExtractMarker.extractMarkerFromDexFile(output), markerTool(Tool.L8));
+ }
+
+ @Test
+ public void testDexMarkerCommandLine() throws Throwable {
Path output = temp.newFolder().toPath().resolve("desugar_jdk_libs.zip");
L8Command l8Command =
parse(
@@ -99,9 +116,28 @@
output.toString());
L8.run(l8Command);
Collection<Marker> markers = ExtractMarker.extractMarkerFromDexFile(output);
- // TODO(b/134732760): Shouldn't we remove the D8/R8 marker?
- assertEquals(2, markers.size());
- Marker marker = markers.iterator().next();
+ assertMarkersMatch(
+ ExtractMarker.extractMarkerFromDexFile(output),
+ ImmutableList.of(markerTool(Tool.L8), markerTool(Tool.D8)));
+ }
+
+ @Test
+ public void testClassFileMarkerCommandLine() throws Throwable {
+ Path output = temp.newFolder().toPath().resolve("desugar_jdk_libs.zip");
+ L8Command l8Command =
+ parse(
+ ToolHelper.getDesugarJDKLibs().toString(),
+ "--lib",
+ ToolHelper.getAndroidJar(AndroidApiLevel.P).toString(),
+ "--min-api",
+ "20",
+ "--desugared-lib",
+ ToolHelper.DESUGAR_LIB_JSON_FOR_TESTING.toString(),
+ "--output",
+ output.toString(),
+ "--classfile");
+ L8.run(l8Command);
+ assertMarkersMatch(ExtractMarker.extractMarkerFromDexFile(output), markerTool(Tool.L8));
}
@Test
@@ -118,6 +154,26 @@
}
@Test
+ public void testFlagPgConfWithClassFile() throws Exception {
+ TestDiagnosticMessagesImpl diagnostics = new TestDiagnosticMessagesImpl();
+ try {
+ Path pgconf = temp.newFolder().toPath().resolve("pg.conf");
+ FileUtils.writeTextFile(pgconf, "");
+ parse(
+ diagnostics,
+ "--desugared-lib",
+ ToolHelper.DESUGAR_LIB_JSON_FOR_TESTING.toString(),
+ "--pg-conf",
+ pgconf.toString(),
+ "--classfile");
+ fail("Expected failure");
+ } catch (CompilationFailedException e) {
+ diagnostics.assertErrorsMatch(
+ diagnosticMessage(containsString("not support shrinking when generating class files")));
+ }
+ }
+
+ @Test
public void testFlagPgConfMissingParameter() {
TestDiagnosticMessagesImpl diagnostics = new TestDiagnosticMessagesImpl();
try {
@@ -162,14 +218,6 @@
}
@Test(expected = CompilationFailedException.class)
- public void classFileOutputNotSupported() throws Throwable {
- DiagnosticsChecker.checkErrorsContains(
- "L8 does not support compiling to class files",
- (handler) ->
- prepareBuilder(handler).setProgramConsumer(ClassFileConsumer.emptyConsumer()).build());
- }
-
- @Test(expected = CompilationFailedException.class)
public void desugaredLibraryConfigurationRequired() throws Throwable {
DiagnosticsChecker.checkErrorsContains(
"L8 requires a desugared library configuration",
@@ -177,15 +225,14 @@
prepareBuilder(handler).setProgramConsumer(ClassFileConsumer.emptyConsumer()).build());
}
- @Test
- @Ignore("b/143431384: Re-enable shrinking")
- public void addProguardConfigurationString() throws Throwable {
+ private void addProguardConfigurationString(
+ DiagnosticsHandler diagnostics, ProgramConsumer programConsumer) throws Throwable {
String keepRule = "-keep class java.time.*";
List<String> keepRules = new ArrayList<>();
keepRules.add(keepRule);
L8Command.Builder builder =
- prepareBuilder(new TestDiagnosticMessagesImpl())
- .setProgramConsumer(DexIndexedConsumer.emptyConsumer())
+ prepareBuilder(diagnostics)
+ .setProgramConsumer(programConsumer)
.addDesugaredLibraryConfiguration(
StringResource.fromFile(ToolHelper.DESUGAR_LIB_JSON_FOR_TESTING))
.addProguardConfiguration(keepRules, Origin.unknown());
@@ -194,15 +241,32 @@
}
@Test
- @Ignore("b/143431384: Re-enable shrinking")
- public void addProguardConfigurationFile() throws Throwable {
+ public void addProguardConfigurationStringWithDex() throws Throwable {
+ addProguardConfigurationString(
+ new TestDiagnosticMessagesImpl(), DexIndexedConsumer.emptyConsumer());
+ }
+
+ @Test
+ public void addProguardConfigurationStringWithClassFile() throws Throwable {
+ TestDiagnosticMessagesImpl diagnostics = new TestDiagnosticMessagesImpl();
+ try {
+ addProguardConfigurationString(diagnostics, ClassFileConsumer.emptyConsumer());
+ fail("Expected failure");
+ } catch (CompilationFailedException e) {
+ diagnostics.assertErrorsMatch(
+ diagnosticMessage(containsString("not support shrinking when generating class files")));
+ }
+ }
+
+ private void addProguardConfigurationFile(
+ DiagnosticsHandler diagnostics, ProgramConsumer programConsumer) throws Throwable {
String keepRule = "-keep class java.time.*";
Path keepRuleFile = temp.newFile("keepRuleFile.txt").toPath();
Files.write(keepRuleFile, Collections.singletonList(keepRule), StandardCharsets.UTF_8);
L8Command.Builder builder1 =
- prepareBuilder(new TestDiagnosticMessagesImpl())
- .setProgramConsumer(DexIndexedConsumer.emptyConsumer())
+ prepareBuilder(diagnostics)
+ .setProgramConsumer(programConsumer)
.addDesugaredLibraryConfiguration(
StringResource.fromFile(ToolHelper.DESUGAR_LIB_JSON_FOR_TESTING))
.addProguardConfigurationFiles(keepRuleFile);
@@ -222,6 +286,24 @@
}
@Test
+ public void addProguardConfigurationFileDex() throws Throwable {
+ addProguardConfigurationFile(
+ new TestDiagnosticMessagesImpl(), DexIndexedConsumer.emptyConsumer());
+ }
+
+ @Test
+ public void addProguardConfigurationFileClassFile() throws Throwable {
+ TestDiagnosticMessagesImpl diagnostics = new TestDiagnosticMessagesImpl();
+ try {
+ addProguardConfigurationFile(diagnostics, ClassFileConsumer.emptyConsumer());
+ fail("Expected failure");
+ } catch (CompilationFailedException e) {
+ diagnostics.assertErrorsMatch(
+ diagnosticMessage(containsString("not support shrinking when generating class files")));
+ }
+ }
+
+ @Test
public void desugaredLibrary() throws CompilationFailedException {
L8Command l8Command =
parse("--desugared-lib", ToolHelper.DESUGAR_LIB_JSON_FOR_TESTING.toString());
diff --git a/src/test/java/com/android/tools/r8/SingleTestRunResult.java b/src/test/java/com/android/tools/r8/SingleTestRunResult.java
index 4d72d22..c03c8e05 100644
--- a/src/test/java/com/android/tools/r8/SingleTestRunResult.java
+++ b/src/test/java/com/android/tools/r8/SingleTestRunResult.java
@@ -118,6 +118,7 @@
return self();
}
+ @Override
public RR disassemble() throws IOException, ExecutionException {
return disassemble(System.out);
}
diff --git a/src/test/java/com/android/tools/r8/TestBase.java b/src/test/java/com/android/tools/r8/TestBase.java
index 1bd188a..9aa9789 100644
--- a/src/test/java/com/android/tools/r8/TestBase.java
+++ b/src/test/java/com/android/tools/r8/TestBase.java
@@ -120,7 +120,11 @@
public enum Backend {
CF,
- DEX
+ DEX;
+
+ public static Backend fromConsumer(ProgramConsumer consumer) {
+ return consumer instanceof ClassFileConsumer ? CF : DEX;
+ }
}
public static R8FullTestBuilder testForR8(TemporaryFolder temp, Backend backend) {
diff --git a/src/test/java/com/android/tools/r8/TestCompilerBuilder.java b/src/test/java/com/android/tools/r8/TestCompilerBuilder.java
index 6f6263a..43b5478 100644
--- a/src/test/java/com/android/tools/r8/TestCompilerBuilder.java
+++ b/src/test/java/com/android/tools/r8/TestCompilerBuilder.java
@@ -300,6 +300,7 @@
public T setProgramConsumer(ProgramConsumer programConsumer) {
assert programConsumer != null;
+ assert backend == Backend.fromConsumer(programConsumer);
this.programConsumer = programConsumer;
return self();
}
diff --git a/src/test/java/com/android/tools/r8/TestParameters.java b/src/test/java/com/android/tools/r8/TestParameters.java
index 75b7336..06fd76e 100644
--- a/src/test/java/com/android/tools/r8/TestParameters.java
+++ b/src/test/java/com/android/tools/r8/TestParameters.java
@@ -4,9 +4,11 @@
package com.android.tools.r8;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import com.android.tools.r8.TestBase.Backend;
import com.android.tools.r8.TestRuntime.NoneRuntime;
+import com.android.tools.r8.ToolHelper.DexVm;
import com.android.tools.r8.utils.AndroidApiLevel;
// Actual test parameters for a specific configuration. Currently just the runtime configuration.
@@ -76,4 +78,9 @@
public void assertNoneRuntime() {
assertEquals(NoneRuntime.getInstance(), runtime);
}
+
+ public DexVm.Version getDexRuntimeVersion() {
+ assertTrue(isDexRuntime());
+ return getRuntime().asDex().getVm().getVersion();
+ }
}
diff --git a/src/test/java/com/android/tools/r8/TestShrinkerBuilder.java b/src/test/java/com/android/tools/r8/TestShrinkerBuilder.java
index 3069351..98881e9 100644
--- a/src/test/java/com/android/tools/r8/TestShrinkerBuilder.java
+++ b/src/test/java/com/android/tools/r8/TestShrinkerBuilder.java
@@ -10,6 +10,8 @@
import com.android.tools.r8.references.TypeReference;
import com.android.tools.r8.shaking.ProguardKeepAttributes;
import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.FileUtils;
+import com.android.tools.r8.utils.StringUtils;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Arrays;
@@ -75,6 +77,12 @@
return minification(false);
}
+ public T addClassObfuscationDictionary(String... names) throws IOException {
+ Path path = getState().getNewTempFolder().resolve("classobfuscationdictionary.txt");
+ FileUtils.writeTextFile(path, StringUtils.join(" ", names));
+ return addKeepRules("-classobfuscationdictionary " + path.toString());
+ }
+
public abstract T addDataEntryResources(DataEntryResource... resources);
public abstract T addKeepRuleFiles(List<Path> files);
diff --git a/src/test/java/com/android/tools/r8/accessrelaxation/AccessRelaxationProguardCompatTest.java b/src/test/java/com/android/tools/r8/accessrelaxation/AccessRelaxationProguardCompatTest.java
index 3efb9b1..11bf740 100644
--- a/src/test/java/com/android/tools/r8/accessrelaxation/AccessRelaxationProguardCompatTest.java
+++ b/src/test/java/com/android/tools/r8/accessrelaxation/AccessRelaxationProguardCompatTest.java
@@ -10,17 +10,32 @@
import static org.hamcrest.MatcherAssert.assertThat;
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 com.android.tools.r8.utils.codeinspector.FieldSubject;
import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
/** Tests that Proguard may change the visibility of a field or method that is explicitly kept. */
+@RunWith(Parameterized.class)
public class AccessRelaxationProguardCompatTest extends TestBase {
private static Class<?> clazz = AccessRelaxationProguardCompatTestClass.class;
private static Class<?> clazzWithGetter = TestClassWithGetter.class;
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withNoneRuntime().build();
+ }
+
+ public AccessRelaxationProguardCompatTest(TestParameters parameters) {
+ parameters.assertNoneRuntime();
+ }
+
@Test
public void r8Test() throws Exception {
testForR8(Backend.DEX)
diff --git a/src/test/java/com/android/tools/r8/accessrelaxation/InvokeTypeConversionTest.java b/src/test/java/com/android/tools/r8/accessrelaxation/InvokeTypeConversionTest.java
index 8c2adf3..209aa18 100644
--- a/src/test/java/com/android/tools/r8/accessrelaxation/InvokeTypeConversionTest.java
+++ b/src/test/java/com/android/tools/r8/accessrelaxation/InvokeTypeConversionTest.java
@@ -6,37 +6,46 @@
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.assertNotNull;
import static org.junit.Assert.assertTrue;
-import com.android.tools.r8.R8Command;
-import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.R8TestRunResult;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.ToolHelper.DexVm.Version;
-import com.android.tools.r8.ToolHelper.ProcessResult;
-import com.android.tools.r8.VmTestRunner;
import com.android.tools.r8.code.InvokeDirect;
import com.android.tools.r8.code.InvokeVirtual;
import com.android.tools.r8.graph.DexCode;
import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.smali.SmaliBuilder;
import com.android.tools.r8.smali.SmaliBuilder.MethodSignature;
import com.android.tools.r8.smali.SmaliTestBase;
-import com.android.tools.r8.utils.AndroidApp;
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.List;
import java.util.function.Consumer;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
-@RunWith(VmTestRunner.class)
+@RunWith(Parameterized.class)
public class InvokeTypeConversionTest extends SmaliTestBase {
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withDexRuntimes().withAllApiLevels().build();
+ }
+
private final String CLASS_NAME = "Example";
private MethodSignature main;
+ private final TestParameters parameters;
+
+ public InvokeTypeConversionTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
private SmaliBuilder buildTestClass(String invokeLine) {
SmaliBuilder builder = new SmaliBuilder(CLASS_NAME);
builder.addDefaultConstructor();
@@ -63,29 +72,23 @@
SmaliBuilder builder,
String expectedException,
Consumer<CodeInspector> inspectorConsumer) throws Exception {
- AndroidApp app = buildApplication(builder);
- List<String> pgConfigs =
- ImmutableList.of(
- keepMainProguardConfiguration(CLASS_NAME),
- // We're testing lens-based invocation type conversions.
- "-dontoptimize",
- "-dontobfuscate",
- "-allowaccessmodification");
- R8Command.Builder command = ToolHelper.prepareR8CommandBuilder(app);
- command.addProguardConfiguration(pgConfigs, Origin.unknown());
- AndroidApp processedApp = ToolHelper.runR8(command.build(), o -> {
- o.enableInlining = false;
- });
- ProcessResult artResult = runOnArtRaw(processedApp, CLASS_NAME);
+ R8TestRunResult result =
+ testForR8(parameters.getBackend())
+ .addProgramDexFileData(builder.compile())
+ .addKeepMainRule(CLASS_NAME)
+ .addKeepRules(
+ // We're testing lens-based invocation type conversions.
+ "-dontoptimize", "-dontobfuscate", "-allowaccessmodification")
+ .addOptionsModification(o -> o.enableInlining = false)
+ .setMinApi(parameters.getApiLevel())
+ .run(parameters.getRuntime(), CLASS_NAME);
if (expectedException == null) {
- assertEquals(0, artResult.exitCode);
- assertEquals("0", artResult.stdout);
+ result.assertSuccessWithOutput("0");
+ result.inspect(inspectorConsumer::accept);
} else {
- assertEquals(1, artResult.exitCode);
- assertThat(artResult.stderr, containsString(expectedException));
+ result.assertFailureWithErrorThatMatches(containsString(expectedException));
+ result.inspectFailure(inspectorConsumer::accept);
}
- CodeInspector inspector = new CodeInspector(processedApp);
- inspectorConsumer.accept(inspector);
}
// The following test checks invoke-direct, which refers to the private static method, is *not*
@@ -105,8 +108,9 @@
SmaliBuilder builder = buildTestClass(
"invoke-direct { v1 }, L" + CLASS_NAME + ";->bar()I");
String expectedError =
- ToolHelper.getDexVm().getVersion().isOlderThanOrEqual(Version.V4_4_4)
- ? "VerifyError" : "IncompatibleClassChangeError";
+ parameters.getRuntime().asDex().getVm().getVersion().isOlderThanOrEqual(Version.V4_4_4)
+ ? "VerifyError"
+ : "IncompatibleClassChangeError";
run(builder, expectedError, dexInspector -> {
ClassSubject clazz = dexInspector.clazz(CLASS_NAME);
assertThat(clazz, isPresent());
diff --git a/src/test/java/com/android/tools/r8/cfmethodgeneration/MethodGenerationBase.java b/src/test/java/com/android/tools/r8/cfmethodgeneration/MethodGenerationBase.java
index 164259f..e190074 100644
--- a/src/test/java/com/android/tools/r8/cfmethodgeneration/MethodGenerationBase.java
+++ b/src/test/java/com/android/tools/r8/cfmethodgeneration/MethodGenerationBase.java
@@ -28,6 +28,7 @@
import java.util.Calendar;
import java.util.List;
import java.util.TreeSet;
+import java.util.function.Consumer;
public abstract class MethodGenerationBase extends TestBase {
@@ -74,17 +75,18 @@
}
// Running this method will regenerate / overwrite the content of the generated class.
- protected void generateMethodsAndWriteThemToFile() throws IOException {
- FileUtils.writeToFile(getGeneratedFile(), null, generateMethods().getBytes());
+ protected void generateMethodsAndWriteThemToFile(Consumer<InternalOptions> optionsConsumer)
+ throws IOException {
+ FileUtils.writeToFile(getGeneratedFile(), null, generateMethods(optionsConsumer).getBytes());
}
// Running this method generate the content of the generated class but does not overwrite it.
- protected String generateMethods() throws IOException {
+ protected String generateMethods(Consumer<InternalOptions> optionsConsumer) throws IOException {
CfCodePrinter codePrinter = new CfCodePrinter();
File tempFile = File.createTempFile("output-", ".java");
- readMethodTemplatesInto(codePrinter);
+ readMethodTemplatesInto(codePrinter, optionsConsumer);
generateRawOutput(codePrinter, tempFile.toPath());
String result = formatRawOutput(tempFile.toPath());
@@ -92,8 +94,10 @@
return result;
}
- private void readMethodTemplatesInto(CfCodePrinter codePrinter) throws IOException {
+ private void readMethodTemplatesInto(
+ CfCodePrinter codePrinter, Consumer<InternalOptions> optionsConsumer) throws IOException {
InternalOptions options = new InternalOptions();
+ optionsConsumer.accept(options);
JarClassFileReader reader =
new JarClassFileReader(
new JarApplicationReader(options),
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesDistinguishedByDirectCheckCastTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesDistinguishedByDirectCheckCastTest.java
new file mode 100644
index 0000000..745fc26
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesDistinguishedByDirectCheckCastTest.java
@@ -0,0 +1,75 @@
+// 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.classmerging.horizontal;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import com.android.tools.r8.NeverClassInline;
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.TestParameters;
+import org.junit.Test;
+
+public class ClassesDistinguishedByDirectCheckCastTest extends HorizontalClassMergingTestBase {
+ public ClassesDistinguishedByDirectCheckCastTest(
+ TestParameters parameters, boolean enableHorizontalClassMerging) {
+ super(parameters, enableHorizontalClassMerging);
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ testForR8(parameters.getBackend())
+ .addInnerClasses(getClass())
+ .addKeepMainRule(Main.class)
+ .addOptionsModification(
+ options -> options.enableHorizontalClassMerging = enableHorizontalClassMerging)
+ .enableInliningAnnotations()
+ .enableNeverClassInliningAnnotations()
+ .setMinApi(parameters.getApiLevel())
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines("fail", "bar")
+ .inspect(
+ codeInspector -> {
+ // The two classes should not be merged.
+ assertThat(codeInspector.clazz(A.class), isPresent());
+ assertThat(codeInspector.clazz(B.class), isPresent());
+ });
+ }
+
+ @NeverClassInline
+ public static class A {
+ @NeverInline
+ public void foo() {
+ System.out.println("foo");
+ }
+ }
+
+ @NeverClassInline
+ public static class B {
+ @NeverInline
+ public void bar() {
+ System.out.println("bar");
+ }
+ }
+
+ public static class Main {
+ @NeverInline
+ public static void checkObject(Object o) {
+ try {
+ B b = (B) o;
+ b.bar();
+ } catch (ClassCastException ex) {
+ System.out.println("fail");
+ }
+ }
+
+ public static void main(String[] args) {
+ A a = new A();
+ B b = new B();
+ checkObject(a);
+ checkObject(b);
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesDistinguishedByDirectInstanceOfTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesDistinguishedByDirectInstanceOfTest.java
new file mode 100644
index 0000000..6a61d2f
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesDistinguishedByDirectInstanceOfTest.java
@@ -0,0 +1,74 @@
+// 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.classmerging.horizontal;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import com.android.tools.r8.NeverClassInline;
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.TestParameters;
+import org.junit.Test;
+
+public class ClassesDistinguishedByDirectInstanceOfTest extends HorizontalClassMergingTestBase {
+ public ClassesDistinguishedByDirectInstanceOfTest(
+ TestParameters parameters, boolean enableHorizontalClassMerging) {
+ super(parameters, enableHorizontalClassMerging);
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ testForR8(parameters.getBackend())
+ .addInnerClasses(getClass())
+ .addKeepMainRule(Main.class)
+ .addOptionsModification(
+ options -> options.enableHorizontalClassMerging = enableHorizontalClassMerging)
+ .enableInliningAnnotations()
+ .enableNeverClassInliningAnnotations()
+ .setMinApi(parameters.getApiLevel())
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines("foo", "bar", "false", "true")
+ .inspect(
+ codeInspector -> {
+ // The two classes should not be merged.
+ assertThat(codeInspector.clazz(A.class), isPresent());
+ assertThat(codeInspector.clazz(B.class), isPresent());
+ });
+ }
+
+ @NeverClassInline
+ public static class A {
+ @NeverInline
+ public void foo() {
+ System.out.println("foo");
+ }
+ }
+
+ @NeverClassInline
+ public static class B {
+ public B(String a) {}
+
+ @NeverInline
+ public void bar() {
+ System.out.println("bar");
+ }
+ }
+
+ public static class Main {
+ @NeverInline
+ public static void checkObject(Object o) {
+ System.out.println(o instanceof B);
+ }
+
+ public static void main(String[] args) {
+ A a = new A();
+ a.foo();
+ B b = new B("hello");
+ b.bar();
+ checkObject(a);
+ checkObject(b);
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesDistinguishedByIndirectCheckCastToInterfaceTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesDistinguishedByIndirectCheckCastToInterfaceTest.java
new file mode 100644
index 0000000..edd84cb
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesDistinguishedByIndirectCheckCastToInterfaceTest.java
@@ -0,0 +1,84 @@
+// 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.classmerging.horizontal;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import com.android.tools.r8.NeverClassInline;
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.NeverMerge;
+import com.android.tools.r8.TestParameters;
+import org.junit.Test;
+
+public class ClassesDistinguishedByIndirectCheckCastToInterfaceTest
+ extends HorizontalClassMergingTestBase {
+ public ClassesDistinguishedByIndirectCheckCastToInterfaceTest(
+ TestParameters parameters, boolean enableHorizontalClassMerging) {
+ super(parameters, enableHorizontalClassMerging);
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ testForR8(parameters.getBackend())
+ .addInnerClasses(getClass())
+ .addKeepMainRule(Main.class)
+ .addOptionsModification(
+ options -> options.enableHorizontalClassMerging = enableHorizontalClassMerging)
+ .enableMergeAnnotations()
+ .enableInliningAnnotations()
+ .enableNeverClassInliningAnnotations()
+ .setMinApi(parameters.getApiLevel())
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines("fail", "bar")
+ .inspect(
+ codeInspector -> {
+ // The two classes should not be merged.
+ assertThat(codeInspector.clazz(A.class), isPresent());
+ assertThat(codeInspector.clazz(B.class), isPresent());
+ });
+ }
+
+ @NeverMerge
+ @NeverClassInline
+ public interface I {
+ void bar();
+ }
+
+ @NeverClassInline
+ public static class A {
+ @NeverInline
+ public void foo() {
+ System.out.println("foo");
+ }
+ }
+
+ @NeverClassInline
+ public static class B implements I {
+ @NeverInline
+ public void bar() {
+ System.out.println("bar");
+ }
+ }
+
+ public static class Main {
+ @NeverInline
+ public static void checkObject(Object o) {
+ try {
+ I b = (I) o;
+ b.bar();
+ } catch (ClassCastException ex) {
+ System.out.println("fail");
+ }
+ }
+
+ public static void main(String[] args) {
+ A a = new A();
+ B b = new B();
+ checkObject(a);
+ checkObject(b);
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesDistuingishedByIndirectInstanceOfInterfaceCheckCast.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesDistuingishedByIndirectInstanceOfInterfaceCheckCast.java
new file mode 100644
index 0000000..c6f58af
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/ClassesDistuingishedByIndirectInstanceOfInterfaceCheckCast.java
@@ -0,0 +1,79 @@
+// 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.classmerging.horizontal;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import com.android.tools.r8.NeverClassInline;
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.NeverMerge;
+import com.android.tools.r8.TestParameters;
+import org.junit.Test;
+
+public class ClassesDistuingishedByIndirectInstanceOfInterfaceCheckCast
+ extends HorizontalClassMergingTestBase {
+ public ClassesDistuingishedByIndirectInstanceOfInterfaceCheckCast(
+ TestParameters parameters, boolean enableHorizontalClassMerging) {
+ super(parameters, enableHorizontalClassMerging);
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ testForR8(parameters.getBackend())
+ .addInnerClasses(getClass())
+ .addKeepMainRule(Main.class)
+ .addOptionsModification(
+ options -> options.enableHorizontalClassMerging = enableHorizontalClassMerging)
+ .enableInliningAnnotations()
+ .enableMergeAnnotations()
+ .enableNeverClassInliningAnnotations()
+ .setMinApi(parameters.getApiLevel())
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines("false", "true")
+ .inspect(
+ codeInspector -> {
+ // The two classes should not be merged.
+ assertThat(codeInspector.clazz(A.class), isPresent());
+ assertThat(codeInspector.clazz(B.class), isPresent());
+ });
+ }
+
+ @NeverClassInline
+ @NeverMerge
+ public interface I {
+ void bar();
+ }
+
+ @NeverClassInline
+ public static class A {
+ @NeverInline
+ public void foo() {
+ System.out.println("foo");
+ }
+ }
+
+ @NeverClassInline
+ public static class B implements I {
+ @NeverInline
+ public void bar() {
+ System.out.println("bar");
+ }
+ }
+
+ public static class Main {
+ @NeverInline
+ public static void checkObject(Object o) {
+ System.out.println(o instanceof I);
+ }
+
+ public static void main(String[] args) {
+ A a = new A();
+ B b = new B();
+ checkObject(a);
+ checkObject(b);
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingTest.java
new file mode 100644
index 0000000..b1d77c2
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingTest.java
@@ -0,0 +1,64 @@
+// 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.classmerging.horizontal;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.IsNot.not;
+
+import com.android.tools.r8.NeverClassInline;
+import com.android.tools.r8.TestParameters;
+import org.junit.Test;
+
+public class ConstructorMergingTest extends HorizontalClassMergingTestBase {
+ public ConstructorMergingTest(TestParameters parameters, boolean enableHorizontalClassMerging) {
+ super(parameters, enableHorizontalClassMerging);
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ testForR8(parameters.getBackend())
+ .addInnerClasses(getClass())
+ .addKeepMainRule(Main.class)
+ .addOptionsModification(
+ options -> options.enableHorizontalClassMerging = enableHorizontalClassMerging)
+ .enableNeverClassInliningAnnotations()
+ .setMinApi(parameters.getApiLevel())
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines("foo", "bar")
+ .inspect(
+ codeInspector -> {
+ if (enableHorizontalClassMerging) {
+ assertThat(codeInspector.clazz(A.class), isPresent());
+ assertThat(codeInspector.clazz(B.class), not(isPresent()));
+ // TODO(b/165517236): Explicitly check classes have been merged.
+ } else {
+ assertThat(codeInspector.clazz(A.class), isPresent());
+ assertThat(codeInspector.clazz(B.class), isPresent());
+ }
+ });
+ }
+
+ @NeverClassInline
+ public static class A {
+ public A() {
+ System.out.println("foo");
+ }
+ }
+
+ @NeverClassInline
+ public static class B {
+ public B() {
+ System.out.println("bar");
+ }
+ }
+
+ public static class Main {
+ public static void main(String[] args) {
+ A a = new A();
+ B b = new B();
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingWithArgumentsTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingWithArgumentsTest.java
new file mode 100644
index 0000000..a1b2d1a
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/ConstructorMergingWithArgumentsTest.java
@@ -0,0 +1,65 @@
+// 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.classmerging.horizontal;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.IsNot.not;
+
+import com.android.tools.r8.NeverClassInline;
+import com.android.tools.r8.TestParameters;
+import org.junit.Test;
+
+public class ConstructorMergingWithArgumentsTest extends HorizontalClassMergingTestBase {
+ public ConstructorMergingWithArgumentsTest(
+ TestParameters parameters, boolean enableHorizontalClassMerging) {
+ super(parameters, enableHorizontalClassMerging);
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ testForR8(parameters.getBackend())
+ .addInnerClasses(getClass())
+ .addKeepMainRule(Main.class)
+ .addOptionsModification(
+ options -> options.enableHorizontalClassMerging = enableHorizontalClassMerging)
+ .enableNeverClassInliningAnnotations()
+ .setMinApi(parameters.getApiLevel())
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines("foo hello", "bar world")
+ .inspect(
+ codeInspector -> {
+ if (enableHorizontalClassMerging) {
+ assertThat(codeInspector.clazz(A.class), isPresent());
+ assertThat(codeInspector.clazz(B.class), not(isPresent()));
+ // TODO(b/165517236): Explicitly check classes have been merged.
+ } else {
+ assertThat(codeInspector.clazz(A.class), isPresent());
+ assertThat(codeInspector.clazz(B.class), isPresent());
+ }
+ });
+ }
+
+ @NeverClassInline
+ public static class A {
+ public A(String arg) {
+ System.out.println("foo " + arg);
+ }
+ }
+
+ @NeverClassInline
+ public static class B {
+ public B(String arg) {
+ System.out.println("bar " + arg);
+ }
+ }
+
+ public static class Main {
+ public static void main(String[] args) {
+ A a = new A("hello");
+ B b = new B("world");
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/shaking/horizontalclassmerging/EmptyClassTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/EmptyClassTest.java
similarity index 70%
rename from src/test/java/com/android/tools/r8/shaking/horizontalclassmerging/EmptyClassTest.java
rename to src/test/java/com/android/tools/r8/classmerging/horizontal/EmptyClassTest.java
index e0d9a33..ffdae33 100644
--- a/src/test/java/com/android/tools/r8/shaking/horizontalclassmerging/EmptyClassTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/EmptyClassTest.java
@@ -2,41 +2,25 @@
// 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.shaking.horizontalclassmerging;
+package com.android.tools.r8.classmerging.horizontal;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.IsNot.not;
import com.android.tools.r8.NeverClassInline;
-import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
-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;
-@RunWith(Parameterized.class)
-public class EmptyClassTest extends TestBase {
- private final TestParameters parameters;
- private final boolean enableHorizontalClassMerging;
-
+public class EmptyClassTest extends HorizontalClassMergingTestBase {
public EmptyClassTest(TestParameters parameters, boolean enableHorizontalClassMerging) {
- this.parameters = parameters;
- this.enableHorizontalClassMerging = enableHorizontalClassMerging;
- }
-
- @Parameterized.Parameters(name = "{0}, horizontalClassMerging:{1}")
- public static List<Object[]> data() {
- return buildParameters(
- getTestParameters().withAllRuntimesAndApiLevels().build(), BooleanUtils.values());
+ super(parameters, enableHorizontalClassMerging);
}
@Test
public void testR8() throws Exception {
testForR8(parameters.getBackend())
- .addInnerClasses(EmptyClassTest.class)
+ .addInnerClasses(getClass())
.addKeepMainRule(Main.class)
.addOptionsModification(
options -> options.enableHorizontalClassMerging = enableHorizontalClassMerging)
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/HorizontalClassMergingTestBase.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/HorizontalClassMergingTestBase.java
new file mode 100644
index 0000000..72e016b
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/HorizontalClassMergingTestBase.java
@@ -0,0 +1,30 @@
+// 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.classmerging.horizontal;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.utils.BooleanUtils;
+import java.util.List;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public abstract class HorizontalClassMergingTestBase extends TestBase {
+ protected final TestParameters parameters;
+ protected final boolean enableHorizontalClassMerging;
+
+ protected HorizontalClassMergingTestBase(
+ TestParameters parameters, boolean enableHorizontalClassMerging) {
+ this.parameters = parameters;
+ this.enableHorizontalClassMerging = enableHorizontalClassMerging;
+ }
+
+ @Parameterized.Parameters(name = "{0}, horizontalClassMerging:{1}")
+ public static List<Object[]> data() {
+ return buildParameters(
+ getTestParameters().withAllRuntimesAndApiLevels().build(), BooleanUtils.values());
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/shaking/horizontalclassmerging/IdenticalFieldMembersTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/IdenticalFieldMembersTest.java
similarity index 74%
rename from src/test/java/com/android/tools/r8/shaking/horizontalclassmerging/IdenticalFieldMembersTest.java
rename to src/test/java/com/android/tools/r8/classmerging/horizontal/IdenticalFieldMembersTest.java
index 7935860..1cb2d2d 100644
--- a/src/test/java/com/android/tools/r8/shaking/horizontalclassmerging/IdenticalFieldMembersTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/IdenticalFieldMembersTest.java
@@ -2,39 +2,24 @@
// 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.shaking.horizontalclassmerging;
+package com.android.tools.r8.classmerging.horizontal;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
import com.android.tools.r8.*;
-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;
-@RunWith(Parameterized.class)
-public class IdenticalFieldMembersTest extends TestBase {
- private final TestParameters parameters;
- private final boolean enableHorizontalClassMerging;
-
+public class IdenticalFieldMembersTest extends HorizontalClassMergingTestBase {
public IdenticalFieldMembersTest(
TestParameters parameters, boolean enableHorizontalClassMerging) {
- this.parameters = parameters;
- this.enableHorizontalClassMerging = enableHorizontalClassMerging;
- }
-
- @Parameterized.Parameters(name = "{0}, horizontalClassMerging:{1}")
- public static List<Object[]> data() {
- return buildParameters(
- getTestParameters().withAllRuntimesAndApiLevels().build(), BooleanUtils.values());
+ super(parameters, enableHorizontalClassMerging);
}
@Test
public void testR8() throws Exception {
testForR8(parameters.getBackend())
- .addInnerClasses(IdenticalFieldMembersTest.class)
+ .addInnerClasses(getClass())
.addKeepMainRule(Main.class)
.addOptionsModification(
options -> options.enableHorizontalClassMerging = enableHorizontalClassMerging)
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/MergedConstructorForwardingTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/MergedConstructorForwardingTest.java
new file mode 100644
index 0000000..226af98
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/MergedConstructorForwardingTest.java
@@ -0,0 +1,79 @@
+// 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.classmerging.horizontal;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.IsNot.not;
+
+import com.android.tools.r8.NeverClassInline;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.classmerging.horizontal.ConstructorMergingTest.A;
+import com.android.tools.r8.classmerging.horizontal.ConstructorMergingTest.B;
+import com.android.tools.r8.classmerging.horizontal.ConstructorMergingTest.Main;
+import org.junit.Test;
+
+public class MergedConstructorForwardingTest extends HorizontalClassMergingTestBase {
+
+ public MergedConstructorForwardingTest(
+ TestParameters parameters, boolean enableHorizontalClassMerging) {
+ super(parameters, enableHorizontalClassMerging);
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ testForR8(parameters.getBackend())
+ .addInnerClasses(getClass())
+ .addKeepMainRule(Main.class)
+ .addOptionsModification(
+ options -> options.enableHorizontalClassMerging = enableHorizontalClassMerging)
+ .enableNeverClassInliningAnnotations()
+ .setMinApi(parameters.getApiLevel())
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines("42", "13", "21", "39")
+ .inspect(
+ codeInspector -> {
+ if (enableHorizontalClassMerging) {
+ assertThat(codeInspector.clazz(A.class), isPresent());
+ assertThat(codeInspector.clazz(B.class), not(isPresent()));
+ // TODO(b/165517236): Explicitly check classes have been merged.
+ } else {
+ assertThat(codeInspector.clazz(A.class), isPresent());
+ assertThat(codeInspector.clazz(B.class), isPresent());
+ }
+ });
+ }
+
+ @NeverClassInline
+ public static class A {
+ public A() {
+ this(42);
+ }
+
+ public A(long x) {
+ System.out.println(x);
+ }
+ }
+
+ @NeverClassInline
+ public static class B {
+ public B() {
+ this(7);
+ }
+
+ public B(long y) {
+ System.out.println(y * 3);
+ }
+ }
+
+ public static class Main {
+ public static void main(String[] args) {
+ A a = new A();
+ a = new A(13);
+ B b = new B();
+ b = new B(13);
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/shaking/horizontalclassmerging/NoOverlappingConstructorsPolicyTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/OverlappingConstructorsTest.java
similarity index 65%
rename from src/test/java/com/android/tools/r8/shaking/horizontalclassmerging/NoOverlappingConstructorsPolicyTest.java
rename to src/test/java/com/android/tools/r8/classmerging/horizontal/OverlappingConstructorsTest.java
index e646087..fbd587d 100644
--- a/src/test/java/com/android/tools/r8/shaking/horizontalclassmerging/NoOverlappingConstructorsPolicyTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/OverlappingConstructorsTest.java
@@ -2,45 +2,27 @@
// 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.shaking.horizontalclassmerging;
+package com.android.tools.r8.classmerging.horizontal;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.IsNot.not;
import com.android.tools.r8.NeverClassInline;
-import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.shaking.horizontalclassmerging.EmptyClassTest.A;
-import com.android.tools.r8.shaking.horizontalclassmerging.EmptyClassTest.B;
-import com.android.tools.r8.shaking.horizontalclassmerging.EmptyClassTest.Main;
-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;
-@RunWith(Parameterized.class)
-public class NoOverlappingConstructorsPolicyTest extends TestBase {
- private final TestParameters parameters;
- private final boolean enableHorizontalClassMerging;
+public class OverlappingConstructorsTest extends HorizontalClassMergingTestBase {
- public NoOverlappingConstructorsPolicyTest(
+ public OverlappingConstructorsTest(
TestParameters parameters, boolean enableHorizontalClassMerging) {
- this.parameters = parameters;
- this.enableHorizontalClassMerging = enableHorizontalClassMerging;
- }
-
- @Parameterized.Parameters(name = "{0}, horizontalClassMerging:{1}")
- public static List<Object[]> data() {
- return buildParameters(
- getTestParameters().withAllRuntimesAndApiLevels().build(), BooleanUtils.values());
+ super(parameters, enableHorizontalClassMerging);
}
@Test
public void testR8() throws Exception {
testForR8(parameters.getBackend())
- .addInnerClasses(this.getClass())
+ .addInnerClasses(getClass())
.addKeepMainRule(Main.class)
.addOptionsModification(
options -> options.enableHorizontalClassMerging = enableHorizontalClassMerging)
@@ -51,7 +33,7 @@
codeInspector -> {
if (enableHorizontalClassMerging) {
assertThat(codeInspector.clazz(A.class), isPresent());
- assertThat(codeInspector.clazz(B.class), isPresent());
+ assertThat(codeInspector.clazz(B.class), not(isPresent()));
assertThat(codeInspector.clazz(C.class), not(isPresent()));
// TODO(b/165517236): Explicitly check classes have been merged.
} else {
diff --git a/src/test/java/com/android/tools/r8/shaking/horizontalclassmerging/RemapMethodTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/RemapMethodTest.java
similarity index 73%
rename from src/test/java/com/android/tools/r8/shaking/horizontalclassmerging/RemapMethodTest.java
rename to src/test/java/com/android/tools/r8/classmerging/horizontal/RemapMethodTest.java
index 97df366..f0814bd 100644
--- a/src/test/java/com/android/tools/r8/shaking/horizontalclassmerging/RemapMethodTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/RemapMethodTest.java
@@ -2,7 +2,7 @@
// 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.shaking.horizontalclassmerging;
+package com.android.tools.r8.classmerging.horizontal;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -10,46 +10,29 @@
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.utils.BooleanUtils;
-import java.util.List;
import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-@RunWith(Parameterized.class)
-public class RemapMethodTest extends TestBase {
- private final TestParameters parameters;
- private final boolean enableHorizontalClassMerging;
-
+public class RemapMethodTest extends HorizontalClassMergingTestBase {
public RemapMethodTest(TestParameters parameters, boolean enableHorizontalClassMerging) {
- this.parameters = parameters;
- this.enableHorizontalClassMerging = enableHorizontalClassMerging;
- }
-
- @Parameterized.Parameters(name = "{0}, horizontalClassMerging:{1}")
- public static List<Object[]> data() {
- return buildParameters(
- getTestParameters().withAllRuntimesAndApiLevels().build(), BooleanUtils.values());
+ super(parameters, enableHorizontalClassMerging);
}
@Test
public void testR8() throws Exception {
testForR8(parameters.getBackend())
- .addInnerClasses(this.getClass())
+ .addInnerClasses(getClass())
.addKeepMainRule(Main.class)
.addOptionsModification(
options -> {
options.enableHorizontalClassMerging = enableHorizontalClassMerging;
- options.enableVerticalClassMerging = false;
})
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
.compile()
- // .run(parameters.getRuntime(), Main.class)
- // .assertSuccessWithOutputLines("foo", "foo", "bar", "bar")
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines("foo", "foo", "bar", "bar")
.inspect(
codeInspector -> {
assertThat(codeInspector.clazz(A.class), isPresent());
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/SyntheticConstructorArgumentsMerged.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/SyntheticConstructorArgumentsMerged.java
new file mode 100644
index 0000000..59ea0b2
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/SyntheticConstructorArgumentsMerged.java
@@ -0,0 +1,78 @@
+// 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.classmerging.horizontal;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.IsNot.not;
+
+import com.android.tools.r8.NeverClassInline;
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.TestParameters;
+import org.junit.Test;
+
+public class SyntheticConstructorArgumentsMerged extends HorizontalClassMergingTestBase {
+ public SyntheticConstructorArgumentsMerged(
+ TestParameters parameters, boolean enableHorizontalClassMerging) {
+ super(parameters, enableHorizontalClassMerging);
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ testForR8(parameters.getBackend())
+ .addInnerClasses(getClass())
+ .addKeepMainRule(Main.class)
+ .addOptionsModification(
+ options -> {
+ options.enableHorizontalClassMerging = enableHorizontalClassMerging;
+ })
+ .enableInliningAnnotations()
+ .enableNeverClassInliningAnnotations()
+ .setMinApi(parameters.getApiLevel())
+ .compile()
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines("5", "42")
+ .inspect(
+ codeInspector -> {
+ if (enableHorizontalClassMerging) {
+ assertThat(codeInspector.clazz(A.class), isPresent());
+ assertThat(codeInspector.clazz(B.class), not(isPresent()));
+ // TODO(b/165517236): Explicitly check classes have been merged.
+ } else {
+ assertThat(codeInspector.clazz(A.class), isPresent());
+ assertThat(codeInspector.clazz(B.class), isPresent());
+ }
+ });
+ }
+
+ @NeverClassInline
+ public static class A {
+ public A(B b) {
+ b.print(42);
+ }
+ }
+
+ @NeverClassInline
+ public static class B {
+ public B(B b) {
+ if (b != null) {
+ b.print(5);
+ }
+ }
+
+ @NeverInline
+ void print(int v) {
+ System.out.println(v);
+ }
+ }
+
+ public static class Main {
+ public static void main(String[] args) {
+ B b = new B(null);
+ B b1 = new B(b);
+ A a = new A(b);
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/shaking/horizontalclassmerging/VirtualMethodNotOverlappingTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/VirtualMethodNotOverlappingTest.java
similarity index 72%
rename from src/test/java/com/android/tools/r8/shaking/horizontalclassmerging/VirtualMethodNotOverlappingTest.java
rename to src/test/java/com/android/tools/r8/classmerging/horizontal/VirtualMethodNotOverlappingTest.java
index 711f217..c80c1ef 100644
--- a/src/test/java/com/android/tools/r8/shaking/horizontalclassmerging/VirtualMethodNotOverlappingTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/VirtualMethodNotOverlappingTest.java
@@ -2,40 +2,25 @@
// 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.shaking.horizontalclassmerging;
+package com.android.tools.r8.classmerging.horizontal;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.IsNot.not;
import com.android.tools.r8.*;
-import com.android.tools.r8.utils.BooleanUtils;
-import java.util.*;
import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-@RunWith(Parameterized.class)
-public class VirtualMethodNotOverlappingTest extends TestBase {
- private final TestParameters parameters;
- private final boolean enableHorizontalClassMerging;
-
+public class VirtualMethodNotOverlappingTest extends HorizontalClassMergingTestBase {
public VirtualMethodNotOverlappingTest(
TestParameters parameters, boolean enableHorizontalClassMerging) {
- this.parameters = parameters;
- this.enableHorizontalClassMerging = enableHorizontalClassMerging;
- }
-
- @Parameterized.Parameters(name = "{0}, horizontalClassMerging:{1}")
- public static List<Object[]> data() {
- return buildParameters(
- getTestParameters().withAllRuntimesAndApiLevels().build(), BooleanUtils.values());
+ super(parameters, enableHorizontalClassMerging);
}
@Test
public void testR8() throws Exception {
testForR8(parameters.getBackend())
- .addInnerClasses(VirtualMethodNotOverlappingTest.class)
+ .addInnerClasses(getClass())
.addKeepMainRule(Main.class)
.addOptionsModification(
options -> options.enableHorizontalClassMerging = enableHorizontalClassMerging)
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 e42f33d..db4d3df 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,11 +5,18 @@
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 com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.L8Command;
import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.OutputMode;
+import com.android.tools.r8.StringResource;
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;
import com.android.tools.r8.utils.BooleanUtils;
@@ -27,6 +34,7 @@
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
+import org.junit.Assume;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -51,8 +59,8 @@
return buildParameters(
BooleanUtils.values(),
getTestParameters()
- .withDexRuntimes()
- .withAllApiLevels()
+ .withAllRuntimes()
+ .withAllApiLevelsAlsoForCf()
.withApiLevel(AndroidApiLevel.N)
.build());
}
@@ -126,30 +134,62 @@
.inspect(this::checkRewrittenInvokes)
.writeToZip();
- // Collection keep rules is only implemented in the DEX writer.
- String desugaredLibraryKeepRules = keepRuleConsumer.get();
- if (desugaredLibraryKeepRules != null) {
- assertEquals(0, desugaredLibraryKeepRules.length());
- desugaredLibraryKeepRules = "-keep class * { *; }";
- }
+ if (parameters.getRuntime().isDex()) {
+ // Collection keep rules is only implemented in the DEX writer.
+ String desugaredLibraryKeepRules = keepRuleConsumer.get();
+ if (desugaredLibraryKeepRules != null) {
+ assertEquals(0, desugaredLibraryKeepRules.length());
+ desugaredLibraryKeepRules = "-keep class * { *; }";
+ }
- // Convert to DEX without desugaring.
- testForD8()
- .addProgramFiles(jar)
- .setMinApi(parameters.getApiLevel())
- .disableDesugaring()
- .compile()
- .addDesugaredCoreLibraryRunClassPath(
- this::buildDesugaredLibrary,
- parameters.getApiLevel(),
- desugaredLibraryKeepRules,
- shrinkDesugaredLibrary)
- .run(parameters.getRuntime(), TestClass.class)
- .assertSuccessWithOutput(expectedOutput);
+ // Convert to DEX without desugaring and run.
+ testForD8()
+ .addProgramFiles(jar)
+ .setMinApi(parameters.getApiLevel())
+ .disableDesugaring()
+ .compile()
+ .addDesugaredCoreLibraryRunClassPath(
+ this::buildDesugaredLibrary,
+ parameters.getApiLevel(),
+ desugaredLibraryKeepRules,
+ shrinkDesugaredLibrary)
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutput(expectedOutput);
+ } else {
+ // Build the desugared library in class file format.
+ Path desugaredLib = temp.newFolder().toPath().resolve("desugar_jdk_libs.jar");
+ L8Command.Builder l8Builder =
+ L8Command.builder()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
+ .addProgramFiles(ToolHelper.getDesugarJDKLibs())
+ .addProgramFiles(ToolHelper.DESUGAR_LIB_CONVERSIONS)
+ .setMode(CompilationMode.DEBUG)
+ .addDesugaredLibraryConfiguration(
+ StringResource.fromFile(ToolHelper.DESUGAR_LIB_JSON_FOR_TESTING))
+ .setMinApiLevel(parameters.getApiLevel().getLevel())
+ .setOutput(desugaredLib, OutputMode.ClassFile);
+ ToolHelper.runL8(l8Builder.build());
+
+ // Run on the JVM with desuagred library on classpath.
+ TestRunResult result =
+ testForJvm()
+ .addProgramFiles(jar)
+ .addRunClasspathFiles(desugaredLib)
+ .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"));
+ }
+ }
}
@Test
public void testTimeD8() throws Exception {
+ Assume.assumeTrue(parameters.getRuntime().isDex());
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
.addInnerClasses(JavaTimeTest.class)
@@ -168,6 +208,7 @@
@Test
public void testTimeR8() throws Exception {
+ Assume.assumeTrue(parameters.getRuntime().isDex());
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForR8(parameters.getBackend())
.addInnerClasses(JavaTimeTest.class)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/MergingJ$Test.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/MergingJ$Test.java
index 2275a44..2b84919 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/MergingJ$Test.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/MergingJ$Test.java
@@ -66,7 +66,6 @@
}
private Path buildSplitDesugaredLibraryPart2() throws Exception {
- Path outputCf = temp.newFolder().toPath().resolve("merger-input-split-cf.zip");
Path outputDex = temp.newFolder().toPath().resolve("merger-input-split-dex.zip");
L8.run(
L8Command.builder()
@@ -76,13 +75,8 @@
.addDesugaredLibraryConfiguration(
StringResource.fromFile(ToolHelper.DESUGAR_LIB_JSON_FOR_TESTING))
.setMinApiLevel(AndroidApiLevel.B.getLevel())
- .setOutput(outputCf, OutputMode.DexIndexed)
+ .setOutput(outputDex, OutputMode.DexIndexed)
.build());
- testForD8()
- .addProgramFiles(outputCf)
- .setMinApi(AndroidApiLevel.B)
- .compile()
- .writeToZip(outputDex);
return outputDex;
}
}
diff --git a/src/test/java/com/android/tools/r8/desugar/graph/DesugarGraphTestConsumer.java b/src/test/java/com/android/tools/r8/desugar/graph/DesugarGraphTestConsumer.java
index 186b01b..cb0da77 100644
--- a/src/test/java/com/android/tools/r8/desugar/graph/DesugarGraphTestConsumer.java
+++ b/src/test/java/com/android/tools/r8/desugar/graph/DesugarGraphTestConsumer.java
@@ -8,26 +8,74 @@
import com.android.tools.r8.DesugarGraphConsumer;
import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.utils.StringUtils;
+import com.android.tools.r8.utils.StringUtils.BraceType;
+import com.android.tools.r8.utils.WorkList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
+import java.util.function.Function;
public class DesugarGraphTestConsumer implements DesugarGraphConsumer {
private boolean finished = false;
- private Map<Origin, Set<Origin>> edges = new HashMap<>();
+
+ // Map from a dependency to its immediate dependents.
+ private final Map<Origin, Set<Origin>> dependents = new HashMap<>();
+
+ // Map from a dependent to its immedate dependencies.
+ private Map<Origin, Set<Origin>> dependencies = null;
+
+ @Override
+ public String toString() {
+ if (dependents.isEmpty()) {
+ return "<empty>";
+ }
+ StringBuilder builder = new StringBuilder();
+ dependents.forEach(
+ (k, vs) ->
+ StringUtils.append(builder.append(k).append(" -> "), vs, ", ", BraceType.TUBORG)
+ .append("\n"));
+ return builder.toString();
+ }
+
+ public Set<Origin> getDirectDependencies(Origin dependent) {
+ return Collections.unmodifiableSet(
+ dependencies.getOrDefault(dependent, Collections.emptySet()));
+ }
+
+ public Set<Origin> getDirectDependents(Origin dependency) {
+ return Collections.unmodifiableSet(dependents.getOrDefault(dependency, Collections.emptySet()));
+ }
+
+ public Set<Origin> getTransitiveDependencies(Origin dependent) {
+ return getTransitiveClosure(dependent, this::getDirectDependencies);
+ }
+
+ public Set<Origin> getTransitiveDependents(Origin dependency) {
+ return getTransitiveClosure(dependency, this::getDirectDependents);
+ }
+
+ private static Set<Origin> getTransitiveClosure(
+ Origin item, Function<Origin, Set<Origin>> edges) {
+ WorkList<Origin> worklist = WorkList.newEqualityWorkList(edges.apply(item));
+ while (worklist.hasNext()) {
+ worklist.addIfNotSeen(edges.apply(worklist.next()));
+ }
+ return worklist.getSeenSet();
+ }
public boolean contains(Origin dependency, Origin dependent) {
assertTrue(finished);
- return edges.getOrDefault(dependency, Collections.emptySet()).contains(dependent);
+ return dependents.getOrDefault(dependency, Collections.emptySet()).contains(dependent);
}
public int totalEdgeCount() {
assertTrue(finished);
int count = 0;
- for (Set<Origin> dependents : edges.values()) {
+ for (Set<Origin> dependents : dependents.values()) {
count += dependents.size();
}
return count;
@@ -36,12 +84,18 @@
@Override
public synchronized void accept(Origin dependent, Origin dependency) {
assertFalse(finished);
- edges.computeIfAbsent(dependency, s -> new HashSet<>()).add(dependent);
+ dependents.computeIfAbsent(dependency, s -> new HashSet<>()).add(dependent);
}
@Override
public void finished() {
assertFalse(finished);
finished = true;
+ dependencies = new HashMap<>();
+ dependents.forEach(
+ (dependency, dependents) ->
+ dependents.forEach(
+ dependent ->
+ dependencies.computeIfAbsent(dependent, k -> new HashSet<>()).add(dependency)));
}
}
diff --git a/src/test/java/com/android/tools/r8/desugar/graph/DesugarGraphUtils.java b/src/test/java/com/android/tools/r8/desugar/graph/DesugarGraphUtils.java
index 937540e..480f81d 100644
--- a/src/test/java/com/android/tools/r8/desugar/graph/DesugarGraphUtils.java
+++ b/src/test/java/com/android/tools/r8/desugar/graph/DesugarGraphUtils.java
@@ -3,10 +3,18 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.desugar.graph;
+import com.android.tools.r8.ClassFileResourceProvider;
import com.android.tools.r8.D8TestBuilder;
+import com.android.tools.r8.ProgramResource;
+import com.android.tools.r8.ProgramResource.Kind;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.utils.DescriptorUtils;
import java.io.IOException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
public class DesugarGraphUtils {
@@ -21,6 +29,8 @@
return origin;
}
+ private final Map<String, Origin> origins = new HashMap<>();
+
private static Origin makeOrigin(String name) {
return new Origin(Origin.root()) {
@Override
@@ -29,4 +39,46 @@
}
};
}
+
+ public Origin origin(String typeName) {
+ return origins.computeIfAbsent(typeName, DesugarGraphUtils::makeOrigin);
+ }
+
+ public Origin origin(Class<?> clazz) {
+ return origin(clazz.getTypeName());
+ }
+
+ public void addProgramClasses(D8TestBuilder builder, Class<?>... classes) throws IOException {
+ for (Class<?> clazz : classes) {
+ builder.getBuilder().addClassProgramData(ToolHelper.getClassAsBytes(clazz), origin(clazz));
+ }
+ }
+
+ public void addClasspathClass(D8TestBuilder builder, Class<?>... classes) throws IOException {
+ Map<String, ProgramResource> map = new HashMap<>();
+ for (Class<?> clazz : classes) {
+ String descriptor = DescriptorUtils.javaTypeToDescriptor(clazz.getTypeName());
+ map.put(
+ descriptor,
+ ProgramResource.fromBytes(
+ origin(clazz),
+ Kind.CF,
+ ToolHelper.getClassAsBytes(clazz),
+ Collections.singleton(descriptor)));
+ }
+ builder
+ .getBuilder()
+ .addClasspathResourceProvider(
+ new ClassFileResourceProvider() {
+ @Override
+ public Set<String> getClassDescriptors() {
+ return map.keySet();
+ }
+
+ @Override
+ public ProgramResource getProgramResource(String descriptor) {
+ return map.get(descriptor);
+ }
+ });
+ }
}
diff --git a/src/test/java/com/android/tools/r8/desugar/graph/Regress167562221Test.java b/src/test/java/com/android/tools/r8/desugar/graph/Regress167562221Test.java
new file mode 100644
index 0000000..650338c
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/graph/Regress167562221Test.java
@@ -0,0 +1,74 @@
+// 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.graph;
+
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.google.common.collect.ImmutableSet;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class Regress167562221Test extends TestBase {
+
+ // Classpath classes:
+
+ public interface I {}
+
+ public interface J extends I {}
+
+ // Does not contribute to C so won't be in any edges.
+ public interface K extends I {}
+
+ public static class A implements J {}
+
+ // Does not contribute to C so won't be in any edges.
+ public static class B implements K {}
+
+ // Program class:
+
+ public static class C extends A {}
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withNoneRuntime().build();
+ }
+
+ public Regress167562221Test(TestParameters parameters) {
+ parameters.assertNoneRuntime();
+ }
+
+ @Test
+ public void repro() throws Throwable {
+ DesugarGraphUtils utils = new DesugarGraphUtils();
+ DesugarGraphTestConsumer consumer = new DesugarGraphTestConsumer();
+ testForD8()
+ .apply(b -> b.getBuilder().setDesugarGraphConsumer(consumer))
+ .apply(b -> utils.addClasspathClass(b, I.class, J.class, K.class, A.class, B.class))
+ .apply(b -> utils.addProgramClasses(b, C.class))
+ .setMinApi(AndroidApiLevel.B)
+ .compile();
+
+ assertEquals(
+ ImmutableSet.of(utils.origin(A.class)),
+ consumer.getDirectDependencies(utils.origin(C.class)));
+
+ assertEquals(
+ ImmutableSet.of(utils.origin(A.class), utils.origin(J.class), utils.origin(I.class)),
+ consumer.getTransitiveDependencies(utils.origin(C.class)));
+
+ // Check that the unrelated CP types are not in the graph.
+
+ assertEquals(ImmutableSet.of(), consumer.getTransitiveDependencies(utils.origin(K.class)));
+ assertEquals(ImmutableSet.of(), consumer.getTransitiveDependencies(utils.origin(B.class)));
+
+ assertEquals(ImmutableSet.of(), consumer.getTransitiveDependents(utils.origin(K.class)));
+ assertEquals(ImmutableSet.of(), consumer.getTransitiveDependents(utils.origin(B.class)));
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/staticinterfacemethod/MissingMethodTest.java b/src/test/java/com/android/tools/r8/desugar/staticinterfacemethod/MissingMethodTest.java
index 4106cd58..f147d3b 100644
--- a/src/test/java/com/android/tools/r8/desugar/staticinterfacemethod/MissingMethodTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/staticinterfacemethod/MissingMethodTest.java
@@ -3,15 +3,58 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.desugar.staticinterfacemethod;
-import com.android.tools.r8.AsmTestBase;
-import org.junit.Ignore;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.TestRunResult;
import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
-public class MissingMethodTest extends AsmTestBase {
+@RunWith(Parameterized.class)
+public class MissingMethodTest extends TestBase {
- @Ignore("b/69835274")
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ private final TestParameters parameters;
+
+ public MissingMethodTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
@Test
- public void testDesugarInvokeMissingMethod() throws Exception {
- ensureException("Main", NoSuchMethodError.class, InterfaceDump.dump(), MainDump.dump());
+ public void testReference() throws Exception {
+ TestRunResult<?> result =
+ testForRuntime(parameters)
+ .addProgramClassFileData(InterfaceDump.dump(), MainDump.dump())
+ .run(parameters.getRuntime(), "Main");
+ if (parameters.isDexRuntime()
+ && parameters.getApiLevel().isLessThan(apiLevelWithStaticInterfaceMethodsSupport())) {
+ // TODO(b/69835274): Desugaring should preserve exception.
+ result.assertFailureWithErrorThatThrows(NoClassDefFoundError.class);
+ } else {
+ result.assertFailureWithErrorThatThrows(NoSuchMethodError.class);
+ }
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ TestRunResult<?> result =
+ testForR8(parameters.getBackend())
+ .addProgramClassFileData(InterfaceDump.dump(), MainDump.dump())
+ .addKeepMainRule("Main")
+ .setMinApi(parameters.getApiLevel())
+ .run(parameters.getRuntime(), "Main");
+ if (parameters.isDexRuntime()
+ && parameters.getApiLevel().isLessThan(apiLevelWithStaticInterfaceMethodsSupport())) {
+ // TODO(b/69835274): Desugaring should preserve exception.
+ result.assertFailureWithErrorThatThrows(NoClassDefFoundError.class);
+ } else {
+ result.assertFailureWithErrorThatThrows(NoSuchMethodError.class);
+ }
}
}
diff --git a/src/test/java/com/android/tools/r8/dex/SharedClassWritingTest.java b/src/test/java/com/android/tools/r8/dex/SharedClassWritingTest.java
index 49e7256..5cb94de 100644
--- a/src/test/java/com/android/tools/r8/dex/SharedClassWritingTest.java
+++ b/src/test/java/com/android/tools/r8/dex/SharedClassWritingTest.java
@@ -9,6 +9,8 @@
import com.android.tools.r8.code.ConstString;
import com.android.tools.r8.code.Instruction;
import com.android.tools.r8.code.ReturnVoid;
+import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.ClassAccessFlags;
import com.android.tools.r8.graph.DexAnnotationSet;
import com.android.tools.r8.graph.DexApplication;
@@ -152,7 +154,7 @@
ApplicationWriter writer =
new ApplicationWriter(
application,
- null,
+ AppView.createForD8(AppInfo.createInitialAppInfo(application)),
options,
null,
GraphLens.getIdentityLens(),
diff --git a/src/test/java/com/android/tools/r8/enumunboxing/ClassAccessEnumUnboxingTest.java b/src/test/java/com/android/tools/r8/enumunboxing/ClassAccessEnumUnboxingTest.java
new file mode 100644
index 0000000..a39e30f
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/enumunboxing/ClassAccessEnumUnboxingTest.java
@@ -0,0 +1,155 @@
+// 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.enumunboxing;
+
+import com.android.tools.r8.NeverClassInline;
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.R8TestRunResult;
+import com.android.tools.r8.TestParameters;
+import java.util.List;
+import org.junit.Assume;
+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 ClassAccessEnumUnboxingTest extends EnumUnboxingTestBase {
+
+ private final TestParameters parameters;
+ private final boolean enumValueOptimization;
+ private final EnumKeepRules enumKeepRules;
+
+ @Parameters(name = "{0} valueOpt: {1} keep: {2}")
+ public static List<Object[]> data() {
+ return enumUnboxingTestParameters();
+ }
+
+ public ClassAccessEnumUnboxingTest(
+ TestParameters parameters, boolean enumValueOptimization, EnumKeepRules enumKeepRules) {
+ this.parameters = parameters;
+ this.enumValueOptimization = enumValueOptimization;
+ this.enumKeepRules = enumKeepRules;
+ }
+
+ @Test
+ public void testEnumUnboxing() throws Exception {
+ Assume.assumeTrue("studio rules required to use valueOf", enumKeepRules.isStudio());
+ R8TestRunResult run =
+ testForR8(parameters.getBackend())
+ .addInnerClasses(ClassAccessEnumUnboxingTest.class)
+ .addKeepMainRule(Main.class)
+ .addKeepRules(enumKeepRules.getKeepRules())
+ .enableNeverClassInliningAnnotations()
+ .enableInliningAnnotations()
+ .addOptionsModification(opt -> enableEnumOptions(opt, enumValueOptimization))
+ .allowDiagnosticInfoMessages()
+ .setMinApi(parameters.getApiLevel())
+ .compile()
+ .inspectDiagnosticMessages(
+ m -> {
+ assertEnumIsUnboxed(ProtoEnumLike.class, ProtoEnumLike.class.getSimpleName(), m);
+ assertEnumIsUnboxed(UnboxableEnum.class, UnboxableEnum.class.getSimpleName(), m);
+ assertEnumIsBoxed(EscapingEnum1.class, EscapingEnum1.class.getSimpleName(), m);
+ assertEnumIsBoxed(EscapingEnum2.class, EscapingEnum2.class.getSimpleName(), m);
+ })
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccess();
+ assertLines2By2Correct(run.getStdOut());
+ }
+
+ @NeverClassInline
+ enum ProtoEnumLike {
+ A,
+ B,
+ C;
+
+ @Override
+ @NeverInline
+ public String toString() {
+ return "an instance of " + this.getClass().getName();
+ }
+ }
+
+ @NeverClassInline
+ enum UnboxableEnum {
+ A,
+ B,
+ C;
+
+ @Override
+ @NeverInline
+ public String toString() {
+ return "an instance of "
+ + this.getClass().getName()
+ + this.getClass().getSimpleName()
+ + this.getClass().getCanonicalName();
+ }
+ }
+
+ @NeverClassInline
+ enum EscapingEnum1 {
+ A,
+ B,
+ C;
+ }
+
+ @NeverClassInline
+ enum EscapingEnum2 {
+ A,
+ B,
+ C;
+ }
+
+ static class Main {
+
+ public static void main(String[] args) {
+ unboxableProtoCase();
+ unboxableCase();
+ nonUnboxableCase();
+ }
+
+ @NeverInline
+ private static void unboxableCase() {
+ System.out.println(UnboxableEnum.A.ordinal());
+ System.out.println(0);
+ System.out.println(UnboxableEnum.A.toString());
+ System.out.println("an instance of intintint");
+ }
+
+ @NeverInline
+ private static void unboxableProtoCase() {
+ System.out.println(ProtoEnumLike.A.ordinal());
+ System.out.println(0);
+ System.out.println(ProtoEnumLike.A.toString());
+ System.out.println("an instance of int");
+ }
+
+ @NeverInline
+ private static void nonUnboxableCase() {
+ System.out.println(EscapingEnum1.A.ordinal());
+ System.out.println(0);
+ System.out.println(EscapingEnum2.A.ordinal());
+ System.out.println(0);
+ System.out.println(EscapingEnum1.B.ordinal());
+ System.out.println(1);
+ System.out.println(EscapingEnum2.B.ordinal());
+ System.out.println(1);
+ System.out.println(getEnum(EscapingEnum1.class, "A").ordinal());
+ System.out.println(0);
+ System.out.println(getEnum(EscapingEnum2.class, "A").ordinal());
+ System.out.println(0);
+ System.out.println(getEnum(EscapingEnum1.class, "B").ordinal());
+ System.out.println(1);
+ System.out.println(getEnum(EscapingEnum2.class, "B").ordinal());
+ System.out.println(1);
+ }
+
+ @NeverInline
+ private static <T extends Enum<T>> Enum<T> getEnum(Class<T> enumClass, String value) {
+ return Enum.valueOf(enumClass, value);
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/enumunboxing/EnumUnboxingMethods.java b/src/test/java/com/android/tools/r8/enumunboxing/EnumUnboxingMethods.java
index e1d51cc..cc2aa0c 100644
--- a/src/test/java/com/android/tools/r8/enumunboxing/EnumUnboxingMethods.java
+++ b/src/test/java/com/android/tools/r8/enumunboxing/EnumUnboxingMethods.java
@@ -51,4 +51,17 @@
}
return unboxedEnum1 == unboxedEnum2;
}
+
+ // Methods zeroCheck and zeroCheckMessage are used to replace null checks on unboxed enums.
+ public static void zeroCheck(int unboxedEnum) {
+ if (unboxedEnum == 0) {
+ throw new NullPointerException();
+ }
+ }
+
+ public static void zeroCheckMessage(int unboxedEnum, String message) {
+ if (unboxedEnum == 0) {
+ throw new NullPointerException(message);
+ }
+ }
}
diff --git a/src/test/java/com/android/tools/r8/enumunboxing/GenerateEnumUnboxingMethods.java b/src/test/java/com/android/tools/r8/enumunboxing/GenerateEnumUnboxingMethods.java
index 706cdc7..4abe533 100644
--- a/src/test/java/com/android/tools/r8/enumunboxing/GenerateEnumUnboxingMethods.java
+++ b/src/test/java/com/android/tools/r8/enumunboxing/GenerateEnumUnboxingMethods.java
@@ -11,6 +11,7 @@
import com.android.tools.r8.cfmethodgeneration.MethodGenerationBase;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.utils.FileUtils;
+import com.android.tools.r8.utils.InternalOptions;
import com.google.common.collect.ImmutableList;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
@@ -50,16 +51,22 @@
return METHOD_TEMPLATE_CLASSES;
}
+ private static void setReadInputStackMap(InternalOptions options) {
+ options.testing.readInputStackMaps = true;
+ }
+
@Test
public void testEnumUtilityMethodsGenerated() throws Exception {
ArrayList<Class<?>> sorted = new ArrayList<>(getMethodTemplateClasses());
sorted.sort(Comparator.comparing(Class::getTypeName));
assertEquals("Classes should be listed in sorted order", sorted, getMethodTemplateClasses());
assertEquals(
- FileUtils.readTextFile(getGeneratedFile(), StandardCharsets.UTF_8), generateMethods());
+ FileUtils.readTextFile(getGeneratedFile(), StandardCharsets.UTF_8),
+ generateMethods(GenerateEnumUnboxingMethods::setReadInputStackMap));
}
public static void main(String[] args) throws Exception {
- new GenerateEnumUnboxingMethods(null).generateMethodsAndWriteThemToFile();
+ new GenerateEnumUnboxingMethods(null)
+ .generateMethodsAndWriteThemToFile(GenerateEnumUnboxingMethods::setReadInputStackMap);
}
}
diff --git a/src/test/java/com/android/tools/r8/enumunboxing/InstanceFieldsEnumUnboxingTest.java b/src/test/java/com/android/tools/r8/enumunboxing/InstanceFieldsEnumUnboxingTest.java
index e91be2b..dc21961 100644
--- a/src/test/java/com/android/tools/r8/enumunboxing/InstanceFieldsEnumUnboxingTest.java
+++ b/src/test/java/com/android/tools/r8/enumunboxing/InstanceFieldsEnumUnboxingTest.java
@@ -33,7 +33,7 @@
SuccessIntFieldOrdinal.class,
SuccessIntFieldInitializerInit.class,
SuccessStringField.class,
- SuccessMultiConstructorIntField.class
+ SuccessMultiConstructorIntField.class,
};
private final TestParameters parameters;
@@ -71,7 +71,7 @@
testClass(compile, failure, true);
}
for (Class<?> success : SUCCESSES) {
- testClass(compile, success, success != SuccessUnusedField.class);
+ testClass(compile, success, false);
}
}
@@ -423,8 +423,7 @@
int field1;
EnumField(int i0) {
- this.field0 = i0;
- this.field1 = -1;
+ this(i0, -1);
}
EnumField(int i0, int i1) {
diff --git a/src/test/java/com/android/tools/r8/enumunboxing/NullCheckEnumUnboxingTest.java b/src/test/java/com/android/tools/r8/enumunboxing/NullCheckEnumUnboxingTest.java
new file mode 100644
index 0000000..25a3434
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/enumunboxing/NullCheckEnumUnboxingTest.java
@@ -0,0 +1,197 @@
+// 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.enumunboxing;
+
+import com.android.tools.r8.NeverClassInline;
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.R8TestRunResult;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import java.util.List;
+import java.util.Objects;
+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 NullCheckEnumUnboxingTest extends EnumUnboxingTestBase {
+
+ private final TestParameters parameters;
+ private final boolean enumValueOptimization;
+ private final EnumKeepRules enumKeepRules;
+
+ @Parameters(name = "{0} valueOpt: {1} keep: {2}")
+ public static List<Object[]> data() {
+ return enumUnboxingTestParameters();
+ }
+
+ public NullCheckEnumUnboxingTest(
+ TestParameters parameters, boolean enumValueOptimization, EnumKeepRules enumKeepRules) {
+ this.parameters = parameters;
+ this.enumValueOptimization = enumValueOptimization;
+ this.enumKeepRules = enumKeepRules;
+ }
+
+ @Test
+ public void testEnumUnboxing() throws Exception {
+ R8TestRunResult run =
+ testForR8(parameters.getBackend())
+ .addInnerClasses(NullCheckEnumUnboxingTest.class)
+ .addKeepMainRule(MainNullTest.class)
+ .addKeepRules(enumKeepRules.getKeepRules())
+ .enableNeverClassInliningAnnotations()
+ .enableInliningAnnotations()
+ .addOptionsModification(opt -> enableEnumOptions(opt, enumValueOptimization))
+ .allowDiagnosticMessages()
+ .setMinApi(parameters.getApiLevel())
+ .compile()
+ .inspectDiagnosticMessages(
+ m -> {
+ assertEnumIsUnboxed(MyEnum.class, MyEnum.class.getSimpleName(), m);
+ // MyEnum19 is unboxed only if minAPI > 19 because Objects#requiredNonNull is then
+ // present.
+ if (parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.K)) {
+ assertEnumIsUnboxed(MyEnum19.class, MyEnum19.class.getSimpleName(), m);
+ } else {
+ assertEnumIsBoxed(MyEnum19.class, MyEnum19.class.getSimpleName(), m);
+ }
+ })
+ .run(parameters.getRuntime(), MainNullTest.class)
+ .assertSuccess();
+ assertLines2By2Correct(run.getStdOut());
+ }
+
+ @NeverClassInline
+ enum MyEnum {
+ A,
+ B,
+ C
+ }
+
+ @NeverClassInline
+ enum MyEnum19 {
+ A,
+ B,
+ C
+ }
+
+ static class MainNullTest {
+
+ public static void main(String[] args) {
+ nullCheckTests();
+ nullCheckMessageTests();
+ }
+
+ private static void nullCheckTests() {
+ nullCheck0Test(MyEnum.A, false);
+ nullCheck0Test(MyEnum.B, false);
+ nullCheck0Test(null, true);
+
+ nullCheck1Test(MyEnum.A, false);
+ nullCheck1Test(MyEnum.B, false);
+ nullCheck1Test(null, true);
+
+ nullCheck2Test(MyEnum19.A, false);
+ nullCheck2Test(MyEnum19.B, false);
+ nullCheck2Test(null, true);
+ }
+
+ private static void nullCheckMessageTests() {
+ nullCheckMessage0Test(MyEnum.A, "myMessageA", false);
+ nullCheckMessage0Test(MyEnum.B, "myMessageB", false);
+ nullCheckMessage0Test(null, "myMessageN", true);
+
+ nullCheckMessage1Test(MyEnum19.A, "myMessageA", false);
+ nullCheckMessage1Test(MyEnum19.B, "myMessageB", false);
+ nullCheckMessage1Test(null, "myMessageN", true);
+ }
+
+ private static void nullCheck0Test(MyEnum input, boolean isNull) {
+ String result = "pass";
+ try {
+ nullCheck0(input);
+ } catch (NullPointerException ex8) {
+ result = "fail";
+ }
+ System.out.println(result);
+ System.out.println(isNull ? "fail" : "pass");
+ }
+
+ private static void nullCheck1Test(MyEnum input, boolean isNull) {
+ String result = "pass";
+ try {
+ nullCheck1(input);
+ } catch (NullPointerException ex8) {
+ result = "fail";
+ }
+ System.out.println(result);
+ System.out.println(isNull ? "fail" : "pass");
+ }
+
+ private static void nullCheck2Test(MyEnum19 input, boolean isNull) {
+ String result = "pass";
+ try {
+ nullCheck2(input);
+ } catch (NullPointerException ex) {
+ result = "fail";
+ }
+ System.out.println(result);
+ System.out.println(isNull ? "fail" : "pass");
+ }
+
+ private static void nullCheckMessage0Test(MyEnum input, String message, boolean isNull) {
+ String result = "pass";
+ try {
+ nullCheckMessage0(input, message);
+ } catch (NullPointerException ex) {
+ result = ex.getMessage();
+ }
+ System.out.println(result);
+ System.out.println(isNull ? message : "pass");
+ }
+
+ private static void nullCheckMessage1Test(MyEnum19 input, String message, boolean isNull) {
+ String result = "pass";
+ try {
+ nullCheckMessage1(input, message);
+ } catch (NullPointerException ex) {
+ result = ex.getMessage();
+ }
+ System.out.println(result);
+ System.out.println(isNull ? message : "pass");
+ }
+
+ @NeverInline
+ private static void nullCheck0(MyEnum e) {
+ if (e == null) {
+ throw new NullPointerException();
+ }
+ }
+
+ @SuppressWarnings("ResultOfMethodCallIgnored")
+ @NeverInline
+ private static void nullCheck1(MyEnum e) {
+ e.getClass();
+ }
+
+ @NeverInline
+ private static void nullCheck2(MyEnum19 e) {
+ Objects.requireNonNull(e);
+ }
+
+ @NeverInline
+ private static void nullCheckMessage0(MyEnum e, String message) {
+ if (e == null) {
+ throw new NullPointerException(message);
+ }
+ }
+
+ @NeverInline
+ private static void nullCheckMessage1(MyEnum19 e, String message) {
+ Objects.requireNonNull(e, message);
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/desugar/backports/GenerateBackportMethods.java b/src/test/java/com/android/tools/r8/ir/desugar/backports/GenerateBackportMethods.java
index 05c11c4..cd417d1 100644
--- a/src/test/java/com/android/tools/r8/ir/desugar/backports/GenerateBackportMethods.java
+++ b/src/test/java/com/android/tools/r8/ir/desugar/backports/GenerateBackportMethods.java
@@ -12,6 +12,7 @@
import com.android.tools.r8.cfmethodgeneration.MethodGenerationBase;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.utils.FileUtils;
+import com.android.tools.r8.utils.InternalOptions;
import com.google.common.collect.ImmutableList;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
@@ -68,16 +69,22 @@
return METHOD_TEMPLATE_CLASSES;
}
+ private static void setReadInputStackMap(InternalOptions options) {
+ options.testing.readInputStackMaps = true;
+ }
+
@Test
public void testBackportsGenerated() throws Exception {
ArrayList<Class<?>> sorted = new ArrayList<>(getMethodTemplateClasses());
sorted.sort(Comparator.comparing(Class::getTypeName));
assertEquals("Classes should be listed in sorted order", sorted, getMethodTemplateClasses());
assertEquals(
- FileUtils.readTextFile(getGeneratedFile(), StandardCharsets.UTF_8), generateMethods());
+ FileUtils.readTextFile(getGeneratedFile(), StandardCharsets.UTF_8),
+ generateMethods(GenerateBackportMethods::setReadInputStackMap));
}
public static void main(String[] args) throws Exception {
- new GenerateBackportMethods(null).generateMethodsAndWriteThemToFile();
+ new GenerateBackportMethods(null)
+ .generateMethodsAndWriteThemToFile(GenerateBackportMethods::setReadInputStackMap);
}
}
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 e4e0b53..fdc2ab9 100644
--- a/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
+++ b/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
@@ -30,6 +30,7 @@
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.errors.DexFileOverflowDiagnostic;
import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.graph.AppInfo;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.ClassAccessFlags;
import com.android.tools.r8.graph.Code;
@@ -866,7 +867,7 @@
ApplicationWriter writer =
new ApplicationWriter(
application,
- null,
+ AppView.createForD8(AppInfo.createInitialAppInfo(application)),
options,
null,
GraphLens.getIdentityLens(),
diff --git a/src/test/java/com/android/tools/r8/naming/arraytypes/ArrayTypesTest.java b/src/test/java/com/android/tools/r8/naming/arraytypes/ArrayTypesTest.java
index adfbcec..8100e16 100644
--- a/src/test/java/com/android/tools/r8/naming/arraytypes/ArrayTypesTest.java
+++ b/src/test/java/com/android/tools/r8/naming/arraytypes/ArrayTypesTest.java
@@ -4,8 +4,6 @@
package com.android.tools.r8.naming.arraytypes;
-import static org.junit.Assume.assumeTrue;
-
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
@@ -41,7 +39,7 @@
@Parameterized.Parameters(name = "{0}")
public static TestParametersCollection data() {
- return getTestParameters().withAllRuntimes().build();
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
}
@BeforeClass
@@ -75,7 +73,7 @@
.addProgramClassFileData(generateTestClass())
.addKeepMainRule(Main.class)
.addKeepRules("-keep class " + generatedTestClassName + " { test(...); }")
- .setMinApi(parameters.getRuntime())
+ .setMinApi(parameters.getApiLevel())
.run(parameters.getRuntime(), Main.class)
.assertSuccessWithOutput(expectedOutput);
}
@@ -106,20 +104,17 @@
.addKeepRules("-applymapping " + mappingFile.toAbsolutePath())
.noMinification()
.noTreeShaking()
- .setMinApi(parameters.getRuntime())
+ .setMinApi(parameters.getApiLevel())
.run(parameters.getRuntime(), Main.class)
.assertSuccessWithOutput(expectedOutput);
}
@Test
- public void testD8() throws Exception {
- assumeTrue(parameters.isDexRuntime());
- testForD8()
+ public void testRuntime() throws Exception {
+ testForRuntime(parameters)
.addProgramClasses(Main.class, A.class)
.addProgramClassFileData(generateTestClass())
- .setMinApi(parameters.getRuntime())
.run(parameters.getRuntime(), Main.class)
- .writeProcessResult(System.out)
.assertSuccessWithOutput(expectedOutput);
}
@@ -129,7 +124,7 @@
MethodVisitor mv;
classWriter.visit(
- Opcodes.V1_8,
+ Opcodes.V1_6,
Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL | Opcodes.ACC_SUPER | Opcodes.ACC_ENUM,
DescriptorUtils.getBinaryNameFromJavaType(generatedTestClassName),
null,
@@ -165,15 +160,19 @@
mv.visitVarInsn(Opcodes.ALOAD, 2);
});
- printCompareIntergers("Hashcode: ", mv, (mvCopy) -> {
- assert mv == mvCopy;
- // Invoke hashCode using both java.lang.Object and array type an holder.
- mv.visitVarInsn(Opcodes.ALOAD, 0);
- mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "hashCode", "()I", false);
+ printCompareIntegers(
+ "Hashcode: ",
+ mv,
+ (mvCopy) -> {
+ assert mv == mvCopy;
+ // Invoke hashCode using both java.lang.Object and array type an holder.
+ mv.visitVarInsn(Opcodes.ALOAD, 0);
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "hashCode", "()I", false);
- mv.visitVarInsn(Opcodes.ALOAD, 0);
- mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, arrayTypeDescriptor, "hashCode", "()I", false);
- });
+ mv.visitVarInsn(Opcodes.ALOAD, 0);
+ mv.visitMethodInsn(
+ Opcodes.INVOKEVIRTUAL, arrayTypeDescriptor, "hashCode", "()I", false);
+ });
printBoolean("Compare with Object: ", mv, (mvCopy) -> {
assert mv == mvCopy;
@@ -213,7 +212,7 @@
Opcodes.INVOKEVIRTUAL, arrayTypeDescriptor, "notPresent", "()Ljava/lang/String;", false);
mv.visitInsn(Opcodes.RETURN);
- mv.visitMaxs(-1, -1);
+ mv.visitMaxs(10, 10);
mv.visitEnd();
}
@@ -221,7 +220,8 @@
return classWriter.toByteArray();
}
- public static void printCompareIntergers(
+
+ public static void printCompareIntegers(
String header, MethodVisitor mv, Consumer<MethodVisitor> consumer) {
mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
mv.visitLdcInsn(header);
diff --git a/src/test/java/com/android/tools/r8/regress/b152973695/CompileToInvalidFileTest.java b/src/test/java/com/android/tools/r8/regress/b152973695/CompileToInvalidFileTest.java
index c96cbda..745d166 100644
--- a/src/test/java/com/android/tools/r8/regress/b152973695/CompileToInvalidFileTest.java
+++ b/src/test/java/com/android/tools/r8/regress/b152973695/CompileToInvalidFileTest.java
@@ -51,7 +51,7 @@
? new ClassFileConsumer.ArchiveConsumer(INVALID_FILE)
: new ArchiveConsumer(INVALID_FILE);
try {
- testForD8()
+ testForD8(Backend.fromConsumer(programConsumer))
.addProgramClasses(Main.class)
.setProgramConsumer(programConsumer)
.compileWithExpectedDiagnostics(diagnostics -> checkDiagnostics(diagnostics, true));
@@ -69,7 +69,7 @@
? new ClassFileConsumer.ArchiveConsumer(INVALID_FILE)
: new ArchiveConsumer(INVALID_FILE);
try {
- testForR8(classFileConsumer ? Backend.CF : Backend.DEX)
+ testForR8(Backend.fromConsumer(programConsumer))
.addProgramClasses(Main.class)
.addKeepMainRule(Main.class)
.setProgramConsumer(programConsumer)
diff --git a/src/test/java/com/android/tools/r8/regress/b78493232/Regress78493232_WithPhi.java b/src/test/java/com/android/tools/r8/regress/b78493232/Regress78493232_WithPhi.java
index 8f3eea0..0afec27 100644
--- a/src/test/java/com/android/tools/r8/regress/b78493232/Regress78493232_WithPhi.java
+++ b/src/test/java/com/android/tools/r8/regress/b78493232/Regress78493232_WithPhi.java
@@ -3,73 +3,106 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.regress.b78493232;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assume.assumeTrue;
import com.android.tools.r8.AsmTestBase;
-import com.android.tools.r8.ToolHelper;
-import com.android.tools.r8.ToolHelper.ProcessResult;
-import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.D8TestRunResult;
+import com.android.tools.r8.R8TestRunResult;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.TestRunResult;
import com.android.tools.r8.utils.StringUtils;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
// Variant of Regress78493232, but where the new-instance is forced to flow to a non-trivial phi
// function prior to the call to <init>. Due to the non-trivial phi this JVM code will not pass
// the verifier. This test is kept to allow inspection of the code path hit in D8/R8 for such
// inputs, but besides that just documents the behaviour on the various VMs.
+@RunWith(Parameterized.class)
public class Regress78493232_WithPhi extends AsmTestBase {
- static final String expected =
+ private static final String EXPECTED =
StringUtils.lines(
"After 0 iterations, expected \"java.security.SecureRandom\", but got \"null\"");
+ private static final String MAIN = Regress78493232Dump_WithPhi.CLASS_NAME;
+ private static final List<Class<?>> CLASSES = ImmutableList.of(Regress78493232Utils.class);
+ private static final List<byte[]> CLASS_BYTES =
+ ImmutableList.of(Regress78493232Dump_WithPhi.dump());
+
+ private final TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ public Regress78493232_WithPhi(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
@Test
- public void test() throws Exception {
- AndroidApp app =
- buildAndroidApp(
- Regress78493232Dump_WithPhi.dump(),
- ToolHelper.getClassAsBytes(Regress78493232Utils.class));
- ProcessResult javaResult =
- runOnJavaRawNoVerify(
- Regress78493232Dump_WithPhi.CLASS_NAME,
- Regress78493232Dump_WithPhi.dump(),
- ToolHelper.getClassAsBytes(Regress78493232Utils.class));
- ProcessResult d8Result =
- runOnArtRaw(compileWithD8(app), Regress78493232Dump_WithPhi.CLASS_NAME);
- ProcessResult r8Result =
- runOnArtRaw(
- compileWithR8(app, "-dontshrink\n-dontobfuscate\n"),
- Regress78493232Dump_WithPhi.CLASS_NAME);
- String proguardConfig =
- keepMainProguardConfiguration(Regress78493232Dump_WithPhi.CLASS_NAME) + "-dontobfuscate\n";
- ProcessResult r8ShakenResult =
- runOnArtRaw(compileWithR8(app, proguardConfig), Regress78493232Dump_WithPhi.CLASS_NAME);
- assertEquals(expected, javaResult.stdout);
- assertEquals(0, javaResult.exitCode);
- switch (ToolHelper.getDexVm().getVersion()) {
+ public void testReference() throws Exception {
+ assumeTrue(parameters.isCfRuntime());
+ testForJvm()
+ .noVerify()
+ .addProgramClassFileData(CLASS_BYTES)
+ .addProgramClasses(CLASSES)
+ .run(parameters.getRuntime(), MAIN)
+ .assertSuccessWithOutput(EXPECTED);
+ }
+
+ @Test
+ public void testD8() throws Exception {
+ assumeTrue(parameters.isDexRuntime());
+ D8TestRunResult result =
+ testForD8()
+ .addProgramClasses(CLASSES)
+ .addProgramClassFileData(CLASS_BYTES)
+ .setMinApi(parameters.getApiLevel())
+ .run(parameters.getRuntime(), MAIN);
+ checkResult(result);
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ testR8(true);
+ }
+
+ @Test
+ public void testNoTreeShakingR8() throws Exception {
+ testR8(false);
+ }
+
+ private void testR8(boolean treeShake) throws Exception {
+ assumeTrue(parameters.isDexRuntime());
+ R8TestRunResult result =
+ testForR8(parameters.getBackend())
+ .addProgramClasses(CLASSES)
+ .addProgramClassFileData(CLASS_BYTES)
+ .treeShaking(treeShake)
+ .noMinification()
+ .setMinApi(parameters.getApiLevel())
+ .addKeepMainRule(MAIN)
+ .run(parameters.getRuntime(), MAIN);
+ checkResult(result);
+ }
+
+ private void checkResult(TestRunResult<?> result) {
+ switch (parameters.getDexRuntimeVersion()) {
case V6_0_1:
- assertEquals("Completed successfully after 1000 iterations\n", d8Result.stdout);
- assertEquals("Completed successfully after 1000 iterations\n", r8Result.stdout);
- assertEquals("Completed successfully after 1000 iterations\n", r8ShakenResult.stdout);
- assertEquals(0, d8Result.exitCode);
- assertEquals(0, r8Result.exitCode);
- assertEquals(0, r8ShakenResult.exitCode);
+ result.assertSuccessWithOutput("Completed successfully after 1000 iterations\n");
break;
case V5_1_1:
- assertEquals(expected, d8Result.stdout);
- assertEquals(expected, r8Result.stdout);
- assertEquals(expected, r8ShakenResult.stdout);
- assertEquals(0, d8Result.exitCode);
- assertEquals(0, r8Result.exitCode);
- assertEquals(0, r8ShakenResult.exitCode);
+ result.assertSuccessWithOutput(EXPECTED);
break;
default:
- assertNotEquals(-1, d8Result.stderr.indexOf("java.lang.VerifyError"));
- assertNotEquals(-1, r8Result.stderr.indexOf("java.lang.VerifyError"));
- assertNotEquals(-1, r8ShakenResult.stderr.indexOf("java.lang.VerifyError"));
- assertEquals(1, d8Result.exitCode);
- assertEquals(1, r8Result.exitCode);
- assertEquals(1, r8ShakenResult.exitCode);
+ result.assertFailureWithErrorThatThrows(VerifyError.class);
break;
}
}
diff --git a/src/test/java/com/android/tools/r8/repackage/RepackageAfterCollisionWithPackagePrivateSignatureTest.java b/src/test/java/com/android/tools/r8/repackage/RepackageAfterCollisionWithPackagePrivateSignatureTest.java
new file mode 100644
index 0000000..47157aa
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/repackage/RepackageAfterCollisionWithPackagePrivateSignatureTest.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.repackage;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assume.assumeTrue;
+
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.repackage.testclasses.repackagetest.TestClass;
+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.List;
+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 RepackageAfterCollisionWithPackagePrivateSignatureTest extends TestBase {
+
+ private static final String FLATTEN_PACKAGE_HIERARCHY = "flattenpackagehierarchy";
+ private static final String REPACKAGE_CLASSES = "repackageclasses";
+ private static final String REPACKAGE_DIR = "foo";
+
+ private final String flattenPackageHierarchyOrRepackageClasses;
+ private final TestParameters parameters;
+
+ @Parameters(name = "{1}, kind: {0}")
+ public static List<Object[]> data() {
+ return buildParameters(
+ ImmutableList.of(FLATTEN_PACKAGE_HIERARCHY, REPACKAGE_CLASSES),
+ getTestParameters().withAllRuntimesAndApiLevels().build());
+ }
+
+ public RepackageAfterCollisionWithPackagePrivateSignatureTest(
+ String flattenPackageHierarchyOrRepackageClasses, TestParameters parameters) {
+ this.flattenPackageHierarchyOrRepackageClasses = flattenPackageHierarchyOrRepackageClasses;
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ assumeTrue(parameters.isCfRuntime());
+ testForR8(parameters.getBackend())
+ .addInnerClasses(RepackageAfterCollisionWithPackagePrivateSignatureTest.class)
+ .addKeepClassAndMembersRules(TestClass.class)
+ .addKeepRules(
+ "-" + flattenPackageHierarchyOrRepackageClasses + " \"" + REPACKAGE_DIR + "\"")
+ .addClassObfuscationDictionary("a")
+ .addOptionsModification(options -> options.testing.enableExperimentalRepackaging = true)
+ .enableInliningAnnotations()
+ .setMinApi(parameters.getApiLevel())
+ .compile()
+ .inspect(this::inspect)
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutputLines("Hello world!");
+ }
+
+ private void inspect(CodeInspector inspector) {
+ ClassSubject repackageClassSubject = inspector.clazz(RepackageCandidate.class);
+ assertThat(repackageClassSubject, isPresent());
+ assertEquals(
+ flattenPackageHierarchyOrRepackageClasses.equals(FLATTEN_PACKAGE_HIERARCHY)
+ ? REPACKAGE_DIR + ".a"
+ : REPACKAGE_DIR,
+ repackageClassSubject.getDexProgramClass().getType().getPackageName());
+ }
+
+ public static class TestClass {
+
+ public static void main(String[] args) {
+ RepackageCandidate.foo(0);
+ RepackageCandidate.foo((int) System.currentTimeMillis(), 0);
+ }
+
+ static void restrictToCurrentPackage() {
+ System.out.print("Hello");
+ }
+ }
+
+ public static class RepackageCandidate {
+
+ public static void foo(int unused) {
+ TestClass.restrictToCurrentPackage();
+ }
+
+ @NeverInline
+ public static void foo(int used, int unused) {
+ if (used >= 0) {
+ System.out.println(" world!");
+ }
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/repackage/RepackageTest.java b/src/test/java/com/android/tools/r8/repackage/RepackageTest.java
index 6d468f4..69a88d0 100644
--- a/src/test/java/com/android/tools/r8/repackage/RepackageTest.java
+++ b/src/test/java/com/android/tools/r8/repackage/RepackageTest.java
@@ -7,6 +7,7 @@
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
import com.android.tools.r8.TestBase;
@@ -47,6 +48,8 @@
@RunWith(Parameterized.class)
public class RepackageTest extends TestBase {
+ private static final String FLATTEN_PACKAGE_HIERARCHY = "flattenpackagehierarchy";
+ private static final String REPACKAGE_CLASSES = "repackageclasses";
private static final String REPACKAGE_DIR = "foo";
private static final List<String> EXPECTED =
@@ -68,28 +71,35 @@
"ReachableClass.packagePrivateMethod()");
private final boolean allowAccessModification;
+ private final boolean enableExperimentalRepackaging;
private final String flattenPackageHierarchyOrRepackageClasses;
private final TestParameters parameters;
- @Parameters(name = "{1}, allow access modification: {0}")
+ @Parameters(name = "{3}, allow access modification: {0}, experimental: {1}, kind: {2}")
public static List<Object[]> data() {
return buildParameters(
BooleanUtils.values(),
- ImmutableList.of("flattenpackagehierarchy", "repackageclasses"),
+ BooleanUtils.values(),
+ ImmutableList.of(FLATTEN_PACKAGE_HIERARCHY, REPACKAGE_CLASSES),
getTestParameters().withAllRuntimesAndApiLevels().build());
}
public RepackageTest(
boolean allowAccessModification,
+ boolean enableExperimentalRepackaging,
String flattenPackageHierarchyOrRepackageClasses,
TestParameters parameters) {
this.allowAccessModification = allowAccessModification;
+ this.enableExperimentalRepackaging = enableExperimentalRepackaging;
this.flattenPackageHierarchyOrRepackageClasses = flattenPackageHierarchyOrRepackageClasses;
this.parameters = parameters;
}
@Test
public void testJvm() throws Exception {
+ assumeFalse(allowAccessModification);
+ assumeFalse(enableExperimentalRepackaging);
+ assumeTrue(flattenPackageHierarchyOrRepackageClasses.equals(FLATTEN_PACKAGE_HIERARCHY));
assumeTrue(parameters.isCfRuntime());
testForJvm()
.addTestClasspath()
@@ -99,6 +109,7 @@
@Test
public void testR8() throws Exception {
+ assumeTrue(!enableExperimentalRepackaging || parameters.isCfRuntime());
testForR8(parameters.getBackend())
.addProgramFiles(ToolHelper.getClassFilesForTestPackage(TestClass.class.getPackage()))
.addKeepMainRule(TestClass.class)
@@ -115,6 +126,9 @@
" <methods>;",
"}")
.allowAccessModification(allowAccessModification)
+ .addOptionsModification(
+ options ->
+ options.testing.enableExperimentalRepackaging = enableExperimentalRepackaging)
.enableInliningAnnotations()
.enableMergeAnnotations()
.setMinApi(parameters.getApiLevel())
@@ -132,9 +146,9 @@
if (eligibleForRepackaging) {
assertEquals(
clazz.getTypeName(),
- flattenPackageHierarchyOrRepackageClasses.equals("flattenpackagehierarchy")
+ flattenPackageHierarchyOrRepackageClasses.equals(FLATTEN_PACKAGE_HIERARCHY)
? REPACKAGE_DIR + ".a"
- : REPACKAGE_DIR + "",
+ : REPACKAGE_DIR,
subject.getDexProgramClass().getType().getPackageName());
} else {
assertEquals(
@@ -154,7 +168,7 @@
// the consumer, since these classes should be repackaged independent of
// -allowaccessmodification.
Consumer<Class<?>> markShouldAlwaysBeEligible =
- clazz -> consumer.accept(clazz, allowAccessModification);
+ clazz -> consumer.accept(clazz, allowAccessModification || enableExperimentalRepackaging);
Consumer<Class<?>> markEligibleWithAllowAccessModification =
clazz -> consumer.accept(clazz, allowAccessModification);
diff --git a/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPackagePrivateKeptMethodAllowRenamingOnReachableClassDirect.java b/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPackagePrivateKeptMethodAllowRenamingOnReachableClassDirect.java
index a7af296..8089eb2 100644
--- a/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPackagePrivateKeptMethodAllowRenamingOnReachableClassDirect.java
+++ b/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPackagePrivateKeptMethodAllowRenamingOnReachableClassDirect.java
@@ -11,7 +11,7 @@
public class AccessPackagePrivateKeptMethodAllowRenamingOnReachableClassDirect {
@NeverInline
- static void test() {
+ public static void test() {
ReachableClassWithKeptMethodAllowRenaming.packagePrivateMethod();
}
}
diff --git a/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPackagePrivateKeptMethodAllowRenamingOnReachableClassIndirect.java b/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPackagePrivateKeptMethodAllowRenamingOnReachableClassIndirect.java
index 9310128..c7c3695 100644
--- a/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPackagePrivateKeptMethodAllowRenamingOnReachableClassIndirect.java
+++ b/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPackagePrivateKeptMethodAllowRenamingOnReachableClassIndirect.java
@@ -11,7 +11,16 @@
public class AccessPackagePrivateKeptMethodAllowRenamingOnReachableClassIndirect {
@NeverInline
- static void test() {
- AccessPackagePrivateKeptMethodAllowRenamingOnReachableClassDirect.test();
+ public static void test() {
+ Helper.test();
+ }
+
+ @NeverMerge
+ public static class Helper {
+
+ @NeverInline
+ static void test() {
+ ReachableClassWithKeptMethodAllowRenaming.packagePrivateMethod();
+ }
}
}
diff --git a/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPackagePrivateKeptMethodOnReachableClassDirect.java b/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPackagePrivateKeptMethodOnReachableClassDirect.java
index 1c159f0..6948b55 100644
--- a/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPackagePrivateKeptMethodOnReachableClassDirect.java
+++ b/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPackagePrivateKeptMethodOnReachableClassDirect.java
@@ -11,7 +11,7 @@
public class AccessPackagePrivateKeptMethodOnReachableClassDirect {
@NeverInline
- static void test() {
+ public static void test() {
ReachableClassWithKeptMethod.packagePrivateMethod();
}
}
diff --git a/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPackagePrivateKeptMethodOnReachableClassIndirect.java b/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPackagePrivateKeptMethodOnReachableClassIndirect.java
index 043c43a..7d5baae 100644
--- a/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPackagePrivateKeptMethodOnReachableClassIndirect.java
+++ b/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPackagePrivateKeptMethodOnReachableClassIndirect.java
@@ -11,7 +11,16 @@
public class AccessPackagePrivateKeptMethodOnReachableClassIndirect {
@NeverInline
- static void test() {
- AccessPackagePrivateKeptMethodOnReachableClassDirect.test();
+ public static void test() {
+ Helper.test();
+ }
+
+ @NeverMerge
+ public static class Helper {
+
+ @NeverInline
+ static void test() {
+ ReachableClassWithKeptMethod.packagePrivateMethod();
+ }
}
}
diff --git a/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPackagePrivateMethodOnKeptClassAllowRenamingDirect.java b/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPackagePrivateMethodOnKeptClassAllowRenamingDirect.java
index 45049a6..f3a90e6 100644
--- a/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPackagePrivateMethodOnKeptClassAllowRenamingDirect.java
+++ b/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPackagePrivateMethodOnKeptClassAllowRenamingDirect.java
@@ -11,7 +11,7 @@
public class AccessPackagePrivateMethodOnKeptClassAllowRenamingDirect {
@NeverInline
- static void test() {
+ public static void test() {
KeptClassAllowRenaming.packagePrivateMethod();
}
}
diff --git a/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPackagePrivateMethodOnKeptClassAllowRenamingIndirect.java b/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPackagePrivateMethodOnKeptClassAllowRenamingIndirect.java
index 8ff327f..ddfd95b 100644
--- a/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPackagePrivateMethodOnKeptClassAllowRenamingIndirect.java
+++ b/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPackagePrivateMethodOnKeptClassAllowRenamingIndirect.java
@@ -11,7 +11,16 @@
public class AccessPackagePrivateMethodOnKeptClassAllowRenamingIndirect {
@NeverInline
- static void test() {
- AccessPackagePrivateMethodOnKeptClassAllowRenamingDirect.test();
+ public static void test() {
+ Helper.test();
+ }
+
+ @NeverMerge
+ public static class Helper {
+
+ @NeverInline
+ static void test() {
+ KeptClassAllowRenaming.packagePrivateMethod();
+ }
}
}
diff --git a/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPackagePrivateMethodOnKeptClassDirect.java b/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPackagePrivateMethodOnKeptClassDirect.java
index 8ae7f71..11110bd 100644
--- a/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPackagePrivateMethodOnKeptClassDirect.java
+++ b/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPackagePrivateMethodOnKeptClassDirect.java
@@ -11,7 +11,7 @@
public class AccessPackagePrivateMethodOnKeptClassDirect {
@NeverInline
- static void test() {
+ public static void test() {
KeptClass.packagePrivateMethod();
}
}
diff --git a/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPackagePrivateMethodOnKeptClassIndirect.java b/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPackagePrivateMethodOnKeptClassIndirect.java
index 6e769dd..0b737ff 100644
--- a/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPackagePrivateMethodOnKeptClassIndirect.java
+++ b/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPackagePrivateMethodOnKeptClassIndirect.java
@@ -11,7 +11,16 @@
public class AccessPackagePrivateMethodOnKeptClassIndirect {
@NeverInline
- static void test() {
- AccessPackagePrivateMethodOnKeptClassDirect.test();
+ public static void test() {
+ Helper.test();
+ }
+
+ @NeverMerge
+ public static class Helper {
+
+ @NeverInline
+ static void test() {
+ KeptClass.packagePrivateMethod();
+ }
}
}
diff --git a/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPackagePrivateMethodOnReachableClassDirect.java b/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPackagePrivateMethodOnReachableClassDirect.java
index 8ef5364..f9a5b76 100644
--- a/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPackagePrivateMethodOnReachableClassDirect.java
+++ b/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPackagePrivateMethodOnReachableClassDirect.java
@@ -11,7 +11,7 @@
public class AccessPackagePrivateMethodOnReachableClassDirect {
@NeverInline
- static void test() {
+ public static void test() {
ReachableClass.packagePrivateMethod();
}
}
diff --git a/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPackagePrivateMethodOnReachableClassIndirect.java b/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPackagePrivateMethodOnReachableClassIndirect.java
index 63d0072..2c0a1b2 100644
--- a/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPackagePrivateMethodOnReachableClassIndirect.java
+++ b/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPackagePrivateMethodOnReachableClassIndirect.java
@@ -11,7 +11,16 @@
public class AccessPackagePrivateMethodOnReachableClassIndirect {
@NeverInline
- static void test() {
- AccessPackagePrivateMethodOnReachableClassDirect.test();
+ public static void test() {
+ Helper.test();
+ }
+
+ @NeverMerge
+ public static class Helper {
+
+ @NeverInline
+ static void test() {
+ ReachableClass.packagePrivateMethod();
+ }
}
}
diff --git a/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPublicKeptMethodAllowRenamingOnReachableClass.java b/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPublicKeptMethodAllowRenamingOnReachableClass.java
index 460e3e1..0f54397 100644
--- a/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPublicKeptMethodAllowRenamingOnReachableClass.java
+++ b/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPublicKeptMethodAllowRenamingOnReachableClass.java
@@ -11,7 +11,7 @@
public class AccessPublicKeptMethodAllowRenamingOnReachableClass {
@NeverInline
- static void test() {
+ public static void test() {
ReachableClassWithKeptMethodAllowRenaming.publicMethod();
}
}
diff --git a/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPublicKeptMethodOnReachableClass.java b/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPublicKeptMethodOnReachableClass.java
index be42852..dcd6aa4 100644
--- a/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPublicKeptMethodOnReachableClass.java
+++ b/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPublicKeptMethodOnReachableClass.java
@@ -11,7 +11,7 @@
public class AccessPublicKeptMethodOnReachableClass {
@NeverInline
- static void test() {
+ public static void test() {
ReachableClassWithKeptMethod.publicMethod();
}
}
diff --git a/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPublicMethodOnKeptClass.java b/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPublicMethodOnKeptClass.java
index 54f999d..f6cf98a 100644
--- a/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPublicMethodOnKeptClass.java
+++ b/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPublicMethodOnKeptClass.java
@@ -11,7 +11,7 @@
public class AccessPublicMethodOnKeptClass {
@NeverInline
- static void test() {
+ public static void test() {
KeptClass.publicMethod();
}
}
diff --git a/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPublicMethodOnKeptClassAllowRenaming.java b/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPublicMethodOnKeptClassAllowRenaming.java
index 16acfb5..05f943c 100644
--- a/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPublicMethodOnKeptClassAllowRenaming.java
+++ b/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPublicMethodOnKeptClassAllowRenaming.java
@@ -11,7 +11,7 @@
public class AccessPublicMethodOnKeptClassAllowRenaming {
@NeverInline
- static void test() {
+ public static void test() {
KeptClassAllowRenaming.publicMethod();
}
}
diff --git a/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPublicMethodOnReachableClass.java b/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPublicMethodOnReachableClass.java
index 4414fd6..0c21cef 100644
--- a/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPublicMethodOnReachableClass.java
+++ b/src/test/java/com/android/tools/r8/repackage/testclasses/repackagetest/AccessPublicMethodOnReachableClass.java
@@ -11,7 +11,7 @@
public class AccessPublicMethodOnReachableClass {
@NeverInline
- static void test() {
+ public static void test() {
ReachableClass.publicMethod();
}
}
diff --git a/src/test/java/com/android/tools/r8/resolution/AsmBasedTests.java b/src/test/java/com/android/tools/r8/resolution/AsmBasedTests.java
deleted file mode 100644
index 7264dd7..0000000
--- a/src/test/java/com/android/tools/r8/resolution/AsmBasedTests.java
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (c) 2017, 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.resolution;
-
-import com.android.tools.r8.AsmTestBase;
-import com.android.tools.r8.resolution.shadowing1.AClassDump;
-import com.android.tools.r8.resolution.shadowing1.InterfaceDump;
-import com.android.tools.r8.resolution.shadowing1.MainDump;
-import com.android.tools.r8.resolution.shadowing1.SubInterfaceDump;
-import org.junit.Ignore;
-import org.junit.Test;
-
-public class AsmBasedTests extends AsmTestBase {
-
- @Test
- @Ignore("b/69356146")
- public void defaultMethodShadowedByStatic() throws Exception {
- ensureException("Main", IncompatibleClassChangeError.class,
- InterfaceDump.dump(),
- SubInterfaceDump.dump(),
- AClassDump.dump(),
- MainDump.dump());
- }
-
- @Test
- @Ignore("b/69356146")
- public void invokeDefaultMethodViaStatic() throws Exception {
- ensureException("Main", IncompatibleClassChangeError.class,
- com.android.tools.r8.resolution.invokestaticinterfacedefault.InterfaceDump.dump(),
- com.android.tools.r8.resolution.invokestaticinterfacedefault.MainDump.dump());
-
- }
-}
diff --git a/src/test/java/com/android/tools/r8/resolution/DefaultMethodShadowedByStaticTest.java b/src/test/java/com/android/tools/r8/resolution/DefaultMethodShadowedByStaticTest.java
new file mode 100644
index 0000000..19424d8
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/resolution/DefaultMethodShadowedByStaticTest.java
@@ -0,0 +1,69 @@
+// Copyright (c) 2017, 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.resolution;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.TestRunResult;
+import com.android.tools.r8.ToolHelper.DexVm.Version;
+import com.android.tools.r8.resolution.shadowing1.AClassDump;
+import com.android.tools.r8.resolution.shadowing1.InterfaceDump;
+import com.android.tools.r8.resolution.shadowing1.MainDump;
+import com.android.tools.r8.resolution.shadowing1.SubInterfaceDump;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+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 DefaultMethodShadowedByStaticTest extends TestBase {
+
+ private final List<byte[]> CLASSES =
+ ImmutableList.of(
+ InterfaceDump.dump(), SubInterfaceDump.dump(), AClassDump.dump(), MainDump.dump());
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ private final TestParameters parameters;
+
+ public DefaultMethodShadowedByStaticTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testReference() throws Exception {
+ TestRunResult<?> result =
+ testForRuntime(parameters)
+ .addProgramClassFileData(CLASSES)
+ .run(parameters.getRuntime(), "Main");
+ if (parameters.isDexRuntime()
+ && (parameters.getApiLevel().isLessThan(apiLevelWithStaticInterfaceMethodsSupport())
+ || parameters.getDexRuntimeVersion().equals(Version.V7_0_0))) {
+ // TODO(b/167535447): Desugaring should preserve the error.
+ result.assertSuccessWithOutputLines("42");
+ } else if (parameters.isDexRuntime()
+ && parameters.getDexRuntimeVersion().equals(Version.V7_0_0)) {
+ // Note: VM 7.0.0 without desugaring of defaults will incorrectly allow the virtual dispatch.
+ result.assertSuccessWithOutputLines("42");
+ } else {
+ result.assertFailureWithErrorThatThrows(IncompatibleClassChangeError.class);
+ }
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ testForR8(parameters.getBackend())
+ .addProgramClassFileData(CLASSES)
+ .addKeepMainRule("Main")
+ .setMinApi(parameters.getApiLevel())
+ .run(parameters.getRuntime(), "Main")
+ .assertFailureWithErrorThatThrows(IncompatibleClassChangeError.class);
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/resolution/InvokeDefaultMethodViaStaticTest.java b/src/test/java/com/android/tools/r8/resolution/InvokeDefaultMethodViaStaticTest.java
new file mode 100644
index 0000000..2080b42
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/resolution/InvokeDefaultMethodViaStaticTest.java
@@ -0,0 +1,68 @@
+// Copyright (c) 2017, 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.resolution;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.TestRunResult;
+import com.android.tools.r8.resolution.invokestaticinterfacedefault.InterfaceDump;
+import com.android.tools.r8.resolution.invokestaticinterfacedefault.MainDump;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+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 InvokeDefaultMethodViaStaticTest extends TestBase {
+
+ private static final List<byte[]> CLASSES =
+ ImmutableList.of(InterfaceDump.dump(), MainDump.dump());
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ private final TestParameters parameters;
+
+ public InvokeDefaultMethodViaStaticTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testReference() throws Exception {
+ TestRunResult<?> result =
+ testForRuntime(parameters)
+ .addProgramClassFileData(CLASSES)
+ .run(parameters.getRuntime(), "Main");
+ if (parameters.isDexRuntime()
+ && parameters.getApiLevel().isLessThan(apiLevelWithDefaultInterfaceMethodsSupport())) {
+ // TODO(b/167535447): Desugaring should preserve the error.
+ result.assertFailureWithErrorThatThrows(NoSuchMethodError.class);
+ } else {
+ result.assertFailureWithErrorThatThrows(IncompatibleClassChangeError.class);
+ }
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ TestRunResult<?> result =
+ testForR8(parameters.getBackend())
+ .addProgramClassFileData(CLASSES)
+ .addKeepMainRule("Main")
+ .setMinApi(parameters.getApiLevel())
+ .addOptionsModification(o -> o.testing.allowInvokeErrors = true)
+ .run(parameters.getRuntime(), "Main");
+ if (parameters.isDexRuntime()
+ && parameters.getApiLevel().isLessThan(apiLevelWithDefaultInterfaceMethodsSupport())) {
+ // TODO(b/167535447): Desugaring should preserve the error.
+ result.assertFailureWithErrorThatThrows(NoClassDefFoundError.class);
+ } else {
+ result.assertFailureWithErrorThatThrows(IncompatibleClassChangeError.class);
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/resolution/invokestaticinterfacedefault/InterfaceDump.java b/src/test/java/com/android/tools/r8/resolution/invokestaticinterfacedefault/InterfaceDump.java
index 56d67aa..37a6f2b 100644
--- a/src/test/java/com/android/tools/r8/resolution/invokestaticinterfacedefault/InterfaceDump.java
+++ b/src/test/java/com/android/tools/r8/resolution/invokestaticinterfacedefault/InterfaceDump.java
@@ -22,7 +22,7 @@
*/
public class InterfaceDump implements Opcodes {
- public static byte[] dump() throws Exception {
+ public static byte[] dump() {
ClassWriter cw = new ClassWriter(0);
FieldVisitor fv;
diff --git a/src/test/java/com/android/tools/r8/resolution/invokestaticinterfacedefault/MainDump.java b/src/test/java/com/android/tools/r8/resolution/invokestaticinterfacedefault/MainDump.java
index 15f12b9..0de68a4 100644
--- a/src/test/java/com/android/tools/r8/resolution/invokestaticinterfacedefault/MainDump.java
+++ b/src/test/java/com/android/tools/r8/resolution/invokestaticinterfacedefault/MainDump.java
@@ -14,7 +14,7 @@
*/
public class MainDump implements Opcodes {
- public static byte[] dump() throws Exception {
+ public static byte[] dump() {
ClassWriter cw = new ClassWriter(0);
FieldVisitor fv;
diff --git a/src/test/java/com/android/tools/r8/resolution/shadowing1/AClassDump.java b/src/test/java/com/android/tools/r8/resolution/shadowing1/AClassDump.java
index 9701db0..7f1be60 100644
--- a/src/test/java/com/android/tools/r8/resolution/shadowing1/AClassDump.java
+++ b/src/test/java/com/android/tools/r8/resolution/shadowing1/AClassDump.java
@@ -19,7 +19,7 @@
*/
public class AClassDump implements Opcodes {
- public static byte[] dump() throws Exception {
+ public static byte[] dump() {
ClassWriter cw = new ClassWriter(0);
FieldVisitor fv;
diff --git a/src/test/java/com/android/tools/r8/resolution/shadowing1/InterfaceDump.java b/src/test/java/com/android/tools/r8/resolution/shadowing1/InterfaceDump.java
index 603071a..cc8b019 100644
--- a/src/test/java/com/android/tools/r8/resolution/shadowing1/InterfaceDump.java
+++ b/src/test/java/com/android/tools/r8/resolution/shadowing1/InterfaceDump.java
@@ -11,7 +11,7 @@
public class InterfaceDump implements Opcodes {
- public static byte[] dump() throws Exception {
+ public static byte[] dump() {
ClassWriter cw = new ClassWriter(0);
FieldVisitor fv;
diff --git a/src/test/java/com/android/tools/r8/resolution/shadowing1/MainDump.java b/src/test/java/com/android/tools/r8/resolution/shadowing1/MainDump.java
index 09bd3b2..b21c15f 100644
--- a/src/test/java/com/android/tools/r8/resolution/shadowing1/MainDump.java
+++ b/src/test/java/com/android/tools/r8/resolution/shadowing1/MainDump.java
@@ -23,7 +23,7 @@
*/
public class MainDump implements Opcodes {
- public static byte[] dump() throws Exception {
+ public static byte[] dump() {
ClassWriter cw = new ClassWriter(0);
FieldVisitor fv;
diff --git a/src/test/java/com/android/tools/r8/resolution/shadowing1/SubInterfaceDump.java b/src/test/java/com/android/tools/r8/resolution/shadowing1/SubInterfaceDump.java
index f70cf4f..7e51c28 100644
--- a/src/test/java/com/android/tools/r8/resolution/shadowing1/SubInterfaceDump.java
+++ b/src/test/java/com/android/tools/r8/resolution/shadowing1/SubInterfaceDump.java
@@ -11,7 +11,7 @@
public class SubInterfaceDump implements Opcodes {
- public static byte[] dump() throws Exception {
+ public static byte[] dump() {
ClassWriter cw = new ClassWriter(0);
FieldVisitor fv;
diff --git a/src/test/java/com/android/tools/r8/utils/Smali.java b/src/test/java/com/android/tools/r8/utils/Smali.java
index 2bb72cd..ac64695 100644
--- a/src/test/java/com/android/tools/r8/utils/Smali.java
+++ b/src/test/java/com/android/tools/r8/utils/Smali.java
@@ -8,6 +8,8 @@
import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.dex.ApplicationReader;
import com.android.tools.r8.dex.ApplicationWriter;
+import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
@@ -114,7 +116,7 @@
ApplicationWriter writer =
new ApplicationWriter(
dexApp,
- null,
+ AppView.createForD8(AppInfo.createInitialAppInfo(dexApp)),
options,
null,
GraphLens.getIdentityLens(),
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentClassSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentClassSubject.java
index 59c8760..3125afe 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentClassSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentClassSubject.java
@@ -183,4 +183,9 @@
public ClassNamingForNameMapper getNaming() {
return null;
}
+
+ @Override
+ public void disassembleUsingJavap(boolean verbose) throws Exception {
+ throw new Unreachable("Cannot disassembly an absent class");
+ }
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/ClassSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/ClassSubject.java
index b2266ce..28fd839 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/ClassSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/ClassSubject.java
@@ -214,4 +214,6 @@
}
public abstract ClassNamingForNameMapper getNaming();
+
+ public abstract void disassembleUsingJavap(boolean verbose) throws Exception;
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundClassSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundClassSubject.java
index 0b1d950..f12840f 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundClassSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundClassSubject.java
@@ -7,6 +7,9 @@
import static com.android.tools.r8.KotlinTestBase.METADATA_TYPE;
import static org.junit.Assert.assertTrue;
+import com.android.tools.r8.TestRuntime.CfRuntime;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.graph.DexAnnotation;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedField;
@@ -27,6 +30,7 @@
import com.android.tools.r8.references.ClassReference;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.StringUtils;
+import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import kotlinx.metadata.jvm.KotlinClassMetadata;
@@ -408,4 +412,25 @@
public ClassNamingForNameMapper getNaming() {
return naming;
}
+
+ @Override
+ public void disassembleUsingJavap(boolean verbose) throws Exception {
+ assert dexClass.origin != null;
+ List<String> command = new ArrayList<>();
+ command.add(
+ CfRuntime.getCheckedInJdk9().getJavaHome().resolve("bin").resolve("javap").toString());
+ if (verbose) {
+ command.add("-v");
+ command.add("-c");
+ command.add("-p");
+ }
+ command.add("-cp");
+ List<String> parts = dexClass.origin.parts();
+ assert parts.size() == 2;
+ command.add(parts.get(0));
+ command.add(parts.get(1).replace(".class", ""));
+ ProcessResult processResult = ToolHelper.runProcess(new ProcessBuilder(command));
+ assert processResult.exitCode == 0;
+ System.out.println(processResult.stdout);
+ }
}