Merge "Also rematerialize constant string values"
diff --git a/.gitignore b/.gitignore
index cdc19a1..41e22c4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -46,8 +46,6 @@
third_party/jdwp-tests
third_party/kotlin.tar.gz
third_party/kotlin
-third_party/shadow
-third_party/shadow.tar.gz
third_party/photos/*
!third_party/photos/*.sha1
third_party/proguard/*
diff --git a/build.gradle b/build.gradle
index ff22c66..f5d54ee 100644
--- a/build.gradle
+++ b/build.gradle
@@ -85,11 +85,7 @@
dependencies {
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.1'
classpath 'com.cookpad.android.licensetools:license-tools-plugin:0.23.0'
- // TODO(ager): shadow does not support java9 class files yet. Once it does,
- // we should use the offial version instead of our fork using ASM 6.0 to
- // support java9.
- // classpath 'com.github.jengelman.gradle.plugins:shadow:2.0.1'
- classpath files("third_party/shadow/shadow-2.0.1.jar")
+ classpath 'com.github.jengelman.gradle.plugins:shadow:2.0.3'
classpath "net.ltgt.gradle:gradle-errorprone-plugin:0.0.13"
classpath "net.ltgt.gradle:gradle-apt-plugin:0.12"
}
@@ -307,7 +303,6 @@
"jctf",
"kotlin",
"android_cts_baseline",
- "shadow",
"ddmlib",
"core-lambda-stubs",
"openjdk/openjdk-rt-1.8",
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 d5a7013..7f9f13f 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
@@ -369,20 +369,24 @@
* If run multiple times on a class, the lowest index that is required to be a JumboString will
* be used.
*/
- private static void rewriteCodeWithJumboStrings(ObjectToOffsetMapping mapping,
+ private void rewriteCodeWithJumboStrings(ObjectToOffsetMapping mapping,
Collection<DexProgramClass> classes, DexApplication application) {
- // If there are no strings with jumbo indices at all this is a no-op.
- if (!mapping.hasJumboStrings()) {
- return;
- }
- // If the globally highest sorting string is not a jumbo string this is also a no-op.
- if (application.highestSortingString != null &&
- application.highestSortingString.slowCompareTo(mapping.getFirstJumboString()) < 0) {
- return;
+ // Do not bail out early if forcing jumbo string processing.
+ if (!options.testing.forceJumboStringProcessing) {
+ // If there are no strings with jumbo indices at all this is a no-op.
+ if (!mapping.hasJumboStrings()) {
+ return;
+ }
+ // If the globally highest sorting string is not a jumbo string this is also a no-op.
+ if (application.highestSortingString != null &&
+ application.highestSortingString.slowCompareTo(mapping.getFirstJumboString()) < 0) {
+ return;
+ }
}
// At least one method needs a jumbo string.
for (DexProgramClass clazz : classes) {
- clazz.forEachMethod(method -> method.rewriteCodeWithJumboStrings(mapping, application));
+ clazz.forEachMethod(method -> method.rewriteCodeWithJumboStrings(
+ mapping, application, options.testing.forceJumboStringProcessing));
}
}
diff --git a/src/main/java/com/android/tools/r8/dex/JumboStringRewriter.java b/src/main/java/com/android/tools/r8/dex/JumboStringRewriter.java
index c96a31a..519bd58 100644
--- a/src/main/java/com/android/tools/r8/dex/JumboStringRewriter.java
+++ b/src/main/java/com/android/tools/r8/dex/JumboStringRewriter.java
@@ -226,7 +226,7 @@
lastOriginalOffset += advance.delta;
Instruction target = debugEventTargets.get(lastOriginalOffset);
int pcDelta = target.getOffset() - lastNewOffset;
- addAdvancementEvents(0, pcDelta, events);
+ events.add(factory.createAdvancePC(pcDelta));
lastNewOffset = target.getOffset();
} else if (event instanceof Default) {
Default defaultEvent = (Default) event;
@@ -234,7 +234,7 @@
Instruction target = debugEventTargets.get(lastOriginalOffset);
int lineDelta = defaultEvent.getLineDelta();
int pcDelta = target.getOffset() - lastNewOffset;
- addAdvancementEvents(lineDelta, pcDelta, events);
+ addDefaultEvent(lineDelta, pcDelta, events);
lastNewOffset = target.getOffset();
} else {
events.add(event);
@@ -248,21 +248,19 @@
return code.getDebugInfo();
}
- private void addAdvancementEvents(int lineDelta, int pcDelta, List<DexDebugEvent> events) {
+ // Add a default event. If the lineDelta and pcDelta can be encoded in one default event
+ // that will be done. Otherwise, this can output an advance line and/or advance pc event
+ // followed by a default event. A default event is always emitted as that is what will
+ // materialize an entry in the line table.
+ private void addDefaultEvent(int lineDelta, int pcDelta, List<DexDebugEvent> events) {
if (lineDelta < Constants.DBG_LINE_BASE
|| lineDelta - Constants.DBG_LINE_BASE >= Constants.DBG_LINE_RANGE) {
events.add(factory.createAdvanceLine(lineDelta));
lineDelta = 0;
- if (pcDelta == 0) {
- return;
- }
}
if (pcDelta >= Constants.DBG_ADDRESS_RANGE) {
events.add(factory.createAdvancePC(pcDelta));
pcDelta = 0;
- if (lineDelta == 0) {
- return;
- }
}
int specialOpcode =
0x0a + (lineDelta - Constants.DBG_LINE_BASE) + Constants.DBG_LINE_RANGE * pcDelta;
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 e18bf8a..d437180 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -502,19 +502,23 @@
* was rewritten to avoid rewriting again unless needed.
*/
public synchronized void rewriteCodeWithJumboStrings(ObjectToOffsetMapping mapping,
- DexApplication application) {
+ DexApplication application, boolean force) {
assert code == null || code.isDexCode();
if (code == null) {
return;
}
DexCode code = this.code.asDexCode();
- if (code.highestSortingString != null) {
- if (mapping.getOffsetFor(code.highestSortingString) > Constants.MAX_NON_JUMBO_INDEX) {
- JumboStringRewriter rewriter =
- new JumboStringRewriter(this, mapping.getFirstJumboString(),
- application.dexItemFactory);
- rewriter.rewrite();
- }
+ DexString firstJumboString = null;
+ if (force) {
+ firstJumboString = mapping.getFirstString();
+ } else if (code.highestSortingString != null
+ && mapping.getOffsetFor(code.highestSortingString) > Constants.MAX_NON_JUMBO_INDEX) {
+ firstJumboString = mapping.getFirstJumboString();
+ }
+ if (firstJumboString != null) {
+ JumboStringRewriter rewriter =
+ new JumboStringRewriter(this, firstJumboString, application.dexItemFactory);
+ rewriter.rewrite();
}
}
diff --git a/src/main/java/com/android/tools/r8/graph/ObjectToOffsetMapping.java b/src/main/java/com/android/tools/r8/graph/ObjectToOffsetMapping.java
index b3be107..a8b431c 100644
--- a/src/main/java/com/android/tools/r8/graph/ObjectToOffsetMapping.java
+++ b/src/main/java/com/android/tools/r8/graph/ObjectToOffsetMapping.java
@@ -7,6 +7,7 @@
import com.android.tools.r8.errors.CompilationError;
import it.unimi.dsi.fastutil.objects.Reference2IntLinkedOpenHashMap;
import it.unimi.dsi.fastutil.objects.Reference2IntMap;
+import it.unimi.dsi.fastutil.objects.Reference2IntMap.Entry;
import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap;
import java.util.Collection;
import java.util.Collections;
@@ -197,6 +198,15 @@
return firstJumboString;
}
+ public DexString getFirstString() {
+ for (Entry<DexString> dexStringEntry : strings.reference2IntEntrySet()) {
+ if (dexStringEntry.getIntValue() == 0) {
+ return dexStringEntry.getKey();
+ }
+ }
+ return null;
+ }
+
private <T extends IndexedDexItem> int getOffsetFor(T item, Reference2IntMap<T> map) {
int index = map.getInt(item);
assert index != NOT_SET : "Index was not set: " + item;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
index 16050b2..f49962c 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
@@ -2478,70 +2478,40 @@
iterator.add(new InvokeVirtual(print, null, ImmutableList.of(out, value)));
Value openParenthesis = addConstString(code, iterator, "(");
- Value comma = addConstString(code, iterator, ",");
+ Value comma = addConstString(code, iterator, ", ");
Value closeParenthesis = addConstString(code, iterator, ")");
- Value indent = addConstString(code, iterator, " ");
- Value nul = addConstString(code, iterator, "(null)");
- Value primitive = addConstString(code, iterator, "(primitive)");
- Value empty = addConstString(code, iterator, "");
- iterator.add(new InvokeVirtual(printLn, null, ImmutableList.of(out, openParenthesis)));
+ iterator.add(new InvokeVirtual(print, null, ImmutableList.of(out, openParenthesis)));
for (int i = 0; i < arguments.size(); i++) {
- iterator.add(new InvokeVirtual(print, null, ImmutableList.of(out, indent)));
-
- // Add a block for end-of-line printing.
- BasicBlock eol = BasicBlock.createGotoBlock(code.blocks.size());
- code.blocks.add(eol);
-
- BasicBlock successor = block.unlinkSingleSuccessor();
- block.link(eol);
- eol.link(successor);
-
+ if (i != 0) {
+ iterator.add(new InvokeVirtual(print, null, ImmutableList.of(out, comma)));
+ }
Value argument = arguments.get(i);
- if (argument.outType() != ValueType.OBJECT) {
- iterator.add(new InvokeVirtual(print, null, ImmutableList.of(out, primitive)));
+ if (i == 0 && !method.isStaticMethod()) {
+ Value thisString = addConstString(code, iterator, "this");
+ iterator.add(createPrint(out, dexItemFactory.stringType, thisString));
} else {
- // Insert "if (argument != null) ...".
- successor = block.unlinkSingleSuccessor();
- If theIf = new If(If.Type.NE, argument);
- theIf.setPosition(position);
- BasicBlock ifBlock = BasicBlock.createIfBlock(code.blocks.size(), theIf);
- code.blocks.add(ifBlock);
- // Fallthrough block must be added right after the if.
- BasicBlock isNullBlock = BasicBlock.createGotoBlock(code.blocks.size());
- code.blocks.add(isNullBlock);
- BasicBlock isNotNullBlock = BasicBlock.createGotoBlock(code.blocks.size());
- code.blocks.add(isNotNullBlock);
-
- // Link the added blocks together.
- block.link(ifBlock);
- ifBlock.link(isNotNullBlock);
- ifBlock.link(isNullBlock);
- isNotNullBlock.link(successor);
- isNullBlock.link(successor);
-
- // Fill code into the blocks.
- iterator = isNullBlock.listIterator();
- iterator.setInsertionPosition(position);
- iterator.add(new InvokeVirtual(print, null, ImmutableList.of(out, nul)));
- iterator = isNotNullBlock.listIterator();
- iterator.setInsertionPosition(position);
- value = code.createValue(ValueType.OBJECT);
- iterator.add(new InvokeVirtual(dexItemFactory.objectMethods.getClass, value,
- ImmutableList.of(arguments.get(i))));
- iterator.add(new InvokeVirtual(print, null, ImmutableList.of(out, value)));
+ int formalIndex = method.isStaticMethod() ? i : i - 1;
+ DexType argumentType = method.method.proto.parameters.values[formalIndex];
+ iterator.add(createPrint(out, argumentType, argument));
}
-
- iterator = eol.listIterator();
- iterator.setInsertionPosition(position);
- if (i == arguments.size() - 1) {
- iterator.add(new InvokeVirtual(printLn, null, ImmutableList.of(out, closeParenthesis)));
- } else {
- iterator.add(new InvokeVirtual(printLn, null, ImmutableList.of(out, comma)));
- }
- block = eol;
}
- // When we fall out of the loop the iterator is in the last eol block.
- iterator.add(new InvokeVirtual(printLn, null, ImmutableList.of(out, empty)));
+ iterator.add(new InvokeVirtual(printLn, null, ImmutableList.of(out, closeParenthesis)));
+ }
+
+ private Instruction createPrint(Value printStream, DexType argumentType, Value argumentValue) {
+ if (argumentType.isPrimitiveType()) {
+ if (argumentType != dexItemFactory.longType
+ && argumentType != dexItemFactory.doubleType
+ && argumentType != dexItemFactory.floatType) {
+ argumentType = dexItemFactory.intType;
+ }
+ } else {
+ argumentType = dexItemFactory.objectType;
+ }
+ DexType javaIoPrintStreamType = dexItemFactory.createType("Ljava/io/PrintStream;");
+ DexProto proto = dexItemFactory.createProto(dexItemFactory.voidType, argumentType);
+ DexMethod print = dexItemFactory.createMethod(javaIoPrintStreamType, proto, "print");
+ return new InvokeVirtual(print, null, ImmutableList.of(printStream, argumentValue));
}
}
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index 4099912..a740a03 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -412,6 +412,7 @@
public boolean invertConditionals = false;
public boolean placeExceptionalBlocksLast = false;
public boolean dontCreateMarkerInD8 = false;
+ public boolean forceJumboStringProcessing = false;
}
public boolean canUseInvokePolymorphicOnVarHandle() {
diff --git a/src/test/java/com/android/tools/r8/cf/BootstrapTest.java b/src/test/java/com/android/tools/r8/cf/BootstrapTest.java
new file mode 100644
index 0000000..0f92fb3
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/cf/BootstrapTest.java
@@ -0,0 +1,156 @@
+// Copyright (c) 2018, 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.cf;
+
+import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
+import static com.google.common.io.ByteStreams.toByteArray;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.ArchiveClassFileProvider;
+import com.android.tools.r8.ClassFileConsumer;
+import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.R8Command;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.ToolHelper.ProcessResult;
+import com.android.tools.r8.utils.FileUtils;
+import com.google.common.base.Charsets;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.junit.Test;
+
+public class BootstrapTest extends TestBase {
+
+ private static final Path R8_STABLE_JAR = Paths.get("third_party/r8/r8.jar");
+
+ private static final String R8_NAME = "com.android.tools.r8.R8";
+ private static final String[] KEEP_R8 = {
+ "-keep public class " + R8_NAME + " {",
+ " public static void main(...);",
+ "}",
+ };
+
+ private static final String HELLO_NAME = "hello.Hello";
+ private static final String[] KEEP_HELLO = {
+ "-keep class " + HELLO_NAME + " {",
+ " public static void main(...);",
+ "}",
+ };
+
+ private class R8Result {
+
+ final ProcessResult processResult;
+ final Path outputJar;
+ final String pgMap;
+
+ R8Result(ProcessResult processResult, Path outputJar, String pgMap) {
+ this.processResult = processResult;
+ this.outputJar = outputJar;
+ this.pgMap = pgMap;
+ }
+
+ @Override
+ public String toString() {
+ // TODO(mathiasr): Add pgMap to output when resource API (go/r8g/19460) has landed.
+ // Without resource API, comparing pgMaps will fail because R8 does not keep the resource
+ // indicating which Git revision R8 was compiled from.
+ return processResult.toString();
+ }
+ }
+
+ @Test
+ public void test() throws Exception {
+ // Run hello.jar to ensure it exists and is valid.
+ Path hello = Paths.get(ToolHelper.EXAMPLES_BUILD_DIR, "hello" + JAR_EXTENSION);
+ ProcessResult runHello = ToolHelper.runJava(hello, "hello.Hello");
+ assertEquals(0, runHello.exitCode);
+
+ // Run r8.jar on hello.jar to ensure that r8.jar is a working compiler.
+ R8Result runInputR8 = runExternalR8(R8_STABLE_JAR, hello, "input", KEEP_HELLO);
+ ProcessResult runHelloR8 = ToolHelper.runJava(runInputR8.outputJar, "hello.Hello");
+ assertEquals(runHello.toString(), runHelloR8.toString());
+
+ // Run R8 on r8.jar, and run the resulting compiler on hello.jar.
+ Path output = runR8(R8_STABLE_JAR, "r8-r8", KEEP_R8);
+ R8Result runR8R8 = runExternalR8(output, hello, "output", KEEP_HELLO);
+ // Check that the process outputs (exit code, stdout, stderr) are the same.
+ assertEquals(runInputR8.toString(), runR8R8.toString());
+ // Check that the output jars are the same.
+ assertProgramsEqual(runInputR8.outputJar, runR8R8.outputJar);
+ }
+
+ private Path runR8(Path inputJar, String outputFolder, String[] keepRules) throws Exception {
+ Path outputPath = temp.newFolder(outputFolder).toPath();
+ Path outputJar = outputPath.resolve("output.jar");
+ Path pgConfigFile = outputPath.resolve("keep.rules");
+ FileUtils.writeTextFile(pgConfigFile, keepRules);
+ ToolHelper.runR8(
+ R8Command.builder()
+ .setMode(CompilationMode.DEBUG)
+ .addLibraryFiles(Paths.get(ToolHelper.JAVA_8_RUNTIME))
+ // TODO(mathiasr): Add resources to output when resource API (go/r8g/19460) has landed.
+ .setProgramConsumer(new ClassFileConsumer.ArchiveConsumer(outputJar))
+ .addProgramFiles(inputJar)
+ .addProguardConfigurationFiles(pgConfigFile)
+ .build());
+ return outputJar;
+ }
+
+ private R8Result runExternalR8(Path r8Jar, Path inputJar, String outputFolder, String[] keepRules)
+ throws Exception {
+ Path outputPath = temp.newFolder(outputFolder).toPath();
+ Path pgConfigFile = outputPath.resolve("keep.rules");
+ Path outputJar = outputPath.resolve("output.jar");
+ Path pgMapFile = outputPath.resolve("map.txt");
+ FileUtils.writeTextFile(pgConfigFile, keepRules);
+ ProcessResult processResult =
+ ToolHelper.runJava(
+ r8Jar,
+ R8_NAME,
+ "--lib",
+ ToolHelper.JAVA_8_RUNTIME,
+ "--classfile",
+ inputJar.toString(),
+ "--output",
+ outputJar.toString(),
+ "--pg-conf",
+ pgConfigFile.toString(),
+ "--debug",
+ "--pg-map-output",
+ pgMapFile.toString());
+ if (processResult.exitCode != 0) {
+ System.out.println(processResult);
+ }
+ assertEquals(0, processResult.exitCode);
+ String pgMap = FileUtils.readTextFile(pgMapFile, Charsets.UTF_8);
+ return new R8Result(processResult, outputJar, pgMap);
+ }
+
+ private static void assertProgramsEqual(Path expectedJar, Path actualJar) throws Exception {
+ ArchiveClassFileProvider expected = new ArchiveClassFileProvider(expectedJar);
+ ArchiveClassFileProvider actual = new ArchiveClassFileProvider(actualJar);
+ assertEquals(getSortedDescriptorList(expected), getSortedDescriptorList(actual));
+ for (String descriptor : expected.getClassDescriptors()) {
+ assertArrayEquals(
+ "Class " + descriptor + " differs",
+ getClassAsBytes(expected, descriptor),
+ getClassAsBytes(actual, descriptor));
+ }
+ }
+
+ private static List<String> getSortedDescriptorList(ArchiveClassFileProvider inputJar) {
+ ArrayList<String> descriptorList = new ArrayList<>(inputJar.getClassDescriptors());
+ Collections.sort(descriptorList);
+ return descriptorList;
+ }
+
+ private static byte[] getClassAsBytes(ArchiveClassFileProvider inputJar, String descriptor)
+ throws Exception {
+ return toByteArray(inputJar.getProgramResource(descriptor).getByteStream());
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/debug/DebugInfoWhenInliningTest.java b/src/test/java/com/android/tools/r8/debug/DebugInfoWhenInliningTest.java
index 6432530..f2e96b3 100644
--- a/src/test/java/com/android/tools/r8/debug/DebugInfoWhenInliningTest.java
+++ b/src/test/java/com/android/tools/r8/debug/DebugInfoWhenInliningTest.java
@@ -27,16 +27,13 @@
private static final String SOURCE_FILE = "Inlining1.java";
- private static DebugTestConfig makeConfig(
- OutputMode outputMode,
+ private DebugTestConfig makeConfig(
LineNumberOptimization lineNumberOptimization,
boolean writeProguardMap)
throws Exception {
- assert outputMode == OutputMode.DexIndexed || outputMode == OutputMode.ClassFile;
AndroidApiLevel minSdk = ToolHelper.getMinApiLevelForDexVm();
- String prefix = outputMode == OutputMode.ClassFile ? "cf" : "dex";
Path outdir = temp.newFolder().toPath();
- Path outjar = outdir.resolve(prefix + "_r8_compiled.jar");
+ Path outjar = outdir.resolve("dex_r8_compiled.jar");
Path proguardMapPath = writeProguardMap ? outdir.resolve("proguard.map") : null;
R8Command.Builder builder =
R8Command.builder()
@@ -44,29 +41,29 @@
.setMinApiLevel(minSdk.getLevel())
.addLibraryFiles(ToolHelper.getAndroidJar(minSdk))
.setMode(CompilationMode.RELEASE)
- .setOutput(outjar, outputMode);
+ .setOutput(outjar, OutputMode.DexIndexed);
if (proguardMapPath != null) {
builder.setProguardMapOutputPath(proguardMapPath);
}
ToolHelper.runR8(
- builder.build(), options -> options.lineNumberOptimization = lineNumberOptimization);
- DebugTestConfig config =
- outputMode == OutputMode.ClassFile
- ? new CfDebugTestConfig(outjar)
- : new DexDebugTestConfig(outjar);
+ builder.build(), options -> {
+ options.lineNumberOptimization = lineNumberOptimization;
+ options.testing.forceJumboStringProcessing = forceJumboStringProcessing;
+ });
+ DebugTestConfig config = new DexDebugTestConfig(outjar);
config.setProguardMap(proguardMapPath);
return config;
}
- private OutputMode outputMode;
+ private boolean forceJumboStringProcessing;
- @Parameters(name = "{0}")
- public static Collection<OutputMode> data() {
- return Arrays.asList(OutputMode.DexIndexed);
+ @Parameters(name="forceJumbo: {0}")
+ public static Collection<Boolean> data() {
+ return Arrays.asList(true, false);
}
- public DebugInfoWhenInliningTest(OutputMode outputMode) {
- this.outputMode = outputMode;
+ public DebugInfoWhenInliningTest(boolean forceJumboStringProcessing) {
+ this.forceJumboStringProcessing = forceJumboStringProcessing;
}
@Test
@@ -78,7 +75,7 @@
// (innermost callee) the line numbers are actually 7, 7, 32, 32, ... but even if the positions
// are emitted duplicated in the dex code, the debugger stops only when there's a change.
int[] lineNumbers = {7, 32, 11, 7};
- testEachLine(makeConfig(outputMode, LineNumberOptimization.OFF, false), lineNumbers);
+ testEachLine(makeConfig(LineNumberOptimization.OFF, false), lineNumbers);
}
@Test
@@ -90,13 +87,13 @@
// (innermost callee) the line numbers are actually 7, 7, 32, 32, ... but even if the positions
// are emitted duplicated in the dex code, the debugger stops only when there's a change.
int[] lineNumbers = {7, 32, 11, 7};
- testEachLine(makeConfig(outputMode, LineNumberOptimization.OFF, true), lineNumbers);
+ testEachLine(makeConfig(LineNumberOptimization.OFF, true), lineNumbers);
}
@Test
public void testEachLineOptimized() throws Throwable {
int[] lineNumbers = {1, 2, 3, 4, 5, 6, 7, 8};
- testEachLine(makeConfig(outputMode, LineNumberOptimization.ON, false), lineNumbers);
+ testEachLine(makeConfig(LineNumberOptimization.ON, false), lineNumbers);
}
@Test
@@ -133,7 +130,7 @@
new SignatureAndLine("void Inlining2.differentFileMultilevelInliningLevel1()", 36),
new SignatureAndLine("void main(java.lang.String[])", 26)));
testEachLine(
- makeConfig(outputMode, LineNumberOptimization.ON, true), lineNumbers, inlineFramesList);
+ makeConfig(LineNumberOptimization.ON, true), lineNumbers, inlineFramesList);
}
private void testEachLine(DebugTestConfig config, int[] lineNumbers) throws Throwable {
diff --git a/src/test/java/com/android/tools/r8/regress/b78493232/Regress78493232.java b/src/test/java/com/android/tools/r8/regress/b78493232/Regress78493232.java
new file mode 100644
index 0000000..abe889e
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/regress/b78493232/Regress78493232.java
@@ -0,0 +1,21 @@
+// Copyright (c) 2018, 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.regress.b78493232;
+
+import com.android.tools.r8.AsmTestBase;
+import com.android.tools.r8.ToolHelper;
+import org.junit.Test;
+
+public class Regress78493232 extends AsmTestBase {
+
+ @Test
+ public void test() throws Exception {
+ // Run test on JVM and ART(x86) to ensure expected behavior.
+ // Running the same test on an ARM JIT causes errors.
+ ensureSameOutput(
+ Regress78493232Dump.CLASS_NAME,
+ Regress78493232Dump.dump(),
+ ToolHelper.getClassAsBytes(Regress78493232Utils.class));
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/regress/b78493232/Regress78493232Dump.java b/src/test/java/com/android/tools/r8/regress/b78493232/Regress78493232Dump.java
new file mode 100644
index 0000000..ba7ec6b
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/regress/b78493232/Regress78493232Dump.java
@@ -0,0 +1,376 @@
+// Copyright (c) 2018, 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.regress.b78493232;
+
+import com.android.tools.r8.utils.DescriptorUtils;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+
+public class Regress78493232Dump implements Opcodes {
+
+ public static final String CLASS_NAME = "regress78493232.Test";
+ public static final String CLASS_DESC = DescriptorUtils.javaTypeToDescriptor(CLASS_NAME);
+ public static final String CLASS_INTERNAL = DescriptorUtils.descriptorToInternalName(CLASS_DESC);
+
+ public static final String UTILS_CLASS_NAME = Regress78493232Utils.class.getCanonicalName();
+ public static final String UTILS_CLASS_DESC =
+ DescriptorUtils.javaTypeToDescriptor(UTILS_CLASS_NAME);
+ public static final String UTILS_CLASS_INTERNAL =
+ DescriptorUtils.descriptorToInternalName(UTILS_CLASS_DESC);
+
+ static final int iterations = 1000;
+
+ // Arguments that have been seen when issue occurred.
+ static byte arg0 = 13;
+ static short arg1 = 25;
+ static int arg2 = 312;
+
+ // Static state of the class seen when the issue occurred.
+ static int staticIntA = 0;
+ static int staticIntB = 29;
+ static byte[] staticByteArray =
+ new byte[] {
+ 63, 101, 52, -33, 9, -21, 21, 51, -59, -6, 65, -27, -37, -2, -5, 1, 33, -33, 2, 13, 4, -12,
+ -53, 54, 2, -15, 46, 2, 13, 4, -3, 30, -47, 9, 0, -13, 3, -11, -10, 13, -2, 61, -69, -6, 6,
+ -1, 15, -8, 63, -22, -33, -19, 50, -35, -3, 7, 8, 2, -7, 9, -21, 21, 51, -62, 11, -13, 7,
+ 57, -37, -38, 6, -1, 15, -8, -53, 3, -19, 19, 50, -53, 3, -19, 19, 50, 9, -21, 21, 51, -59,
+ -6, 65, -27, -6, 10, -51, 21, -2, -11, -4, 11, -6, 1, 1, 11, -3, 61, -50, 50, -75, 75, -52,
+ 0, 52, -53, -9, -3, -4, 14, 2, -15, 49, -41, 11, -18, 0, 39, -35, 14, -3, -1, -13, 9, -21,
+ 21, 51, -59, -6, 65, -70, 7, -3, 12, -5, -9, 2, -13, 23, -27, 9, -11, 15, -6, 11, 11, 11, 7,
+ 16, -31, -2, 4, 7, 9, -21, 21, 51, -69, 14, 2, -18, 3, 9, -11, -5, 75, -37, -18, 2, -18, 3,
+ 13, 19, -15, -13, 10, -11, 2, -1, -7, 7, -15, 15, 5, 9, -11, 15, 13, 4, -3, -18, 3, 0, 13,
+ -9, -6, 32, -21, -4, 8, 24, -28, -3, 0, 3, -10, 9, -21, 21, 51, -59, -6, 65, -20, -55, 5,
+ 15, 36, -49, 0, 17, -24, 48, -37, -2, -5, 1, 33, -33, 2, 13, 4, -12, 9, -21, 21, 51, -59,
+ -6, 65, -24, -35, -3, 7, 22, -38, 1, 4, -5, 1, 33, -33, 2, 13, 4, -12, 1, 11, -3, 61, -50,
+ 50, -75, 75, -52, 0, 52, -52, 63, -77, 2, -15, 47, -51, 4, 15, -13, 4, 13, -11, 25, -33, 5,
+ -3, 17, -6, 2, 33, -37, -9, 13, 2, -17, 5, -3, -7, -3, 14, -3, 33, -41, 11, -18, 0, 2, -15,
+ 43, -37, -5, -1, 19, -13, 11, -2, -13, 10, -14, 3, 6, 5, 54, -65, -4, 69, -23, -41, -8, 13,
+ -9, 3, 1, 1, 8, -9, -6, 21, -4, 20, -8, 9, -21, 21, 51, -62, 11, -13, 7, 57, -21, -41, 11,
+ -18, 0, 39, -35, 14, -3, -1, -13, -3, 14, -3, 32, -33, -19, 1, 11, -3, 62, -51, 51, -76, 76,
+ -53, 0, 53, -54, 14, -15, 33, -18, 0, 1, 9, -21, 21, 51, -59, -6, 65, -22, -29, -19, 19, 24,
+ -37, -2, -5, 1, 33, -33, 2, 13, 4, -12, 2, -15, 36, -34, 3, -1, 11, -13, -2, -5, 2, -15, 51,
+ -33, -17, 4, 3, -9, 1, 15, 21, -17, -19, 12, 9, -21, 21, 51, -59, -6, 65, -24, -35, -3, 7,
+ 9, -21, 21, 51, -59, -6, 65, -24, -35, -3, 7, 33, -33, -14, 16, -15, 9, -7, -4, 5, -3, 21,
+ -3, 19, -8, 9, -19, 4, 43, -37, -6
+ };
+
+ public static byte[] dump() {
+ return dump(arg0, arg1, arg2, staticIntA, staticIntB, staticByteArray);
+ }
+
+ public static byte[] dump(
+ byte arg0, short arg1, int arg2, int staticIntA, int staticIntB, byte[] staticByteArray) {
+ ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
+ FieldVisitor fv;
+ MethodVisitor mv;
+
+ cw.visit(V1_6, ACC_PUBLIC + ACC_SUPER, CLASS_INTERNAL, null, "java/lang/Object", null);
+
+ {
+ fv = cw.visitField(ACC_PRIVATE + ACC_FINAL + ACC_STATIC, "staticByteArray", "[B", null, null);
+ fv.visitEnd();
+ }
+ {
+ fv = cw.visitField(ACC_PRIVATE + ACC_STATIC, "staticIntA", "I", null, null);
+ fv.visitEnd();
+ }
+ {
+ fv = cw.visitField(ACC_PRIVATE + ACC_STATIC, "staticIntB", "I", null, null);
+ fv.visitEnd();
+ }
+
+ {
+ mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "run", "()Ljava/lang/String;", null, null);
+ mv.visitCode();
+ mv.visitIntInsn(BIPUSH, arg0);
+ mv.visitIntInsn(SIPUSH, arg1);
+ mv.visitIntInsn(SIPUSH, arg2);
+ mv.visitMethodInsn(
+ INVOKESTATIC, CLASS_INTERNAL, "methodCausingIssue", "(BSI)Ljava/lang/String;", false);
+ mv.visitInsn(ARETURN);
+ mv.visitMaxs(-1, -1);
+ mv.visitEnd();
+ }
+
+ {
+ mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "getHash", "()I", null, null);
+ mv.visitCode();
+ getHash(mv);
+ mv.visitInsn(IRETURN);
+ mv.visitMaxs(-1, -1);
+ mv.visitEnd();
+ }
+
+ {
+ mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null);
+ mv.visitCode();
+
+ mv.visitInsn(ICONST_0);
+ mv.visitVarInsn(ISTORE, 1);
+ Label l0 = new Label();
+ mv.visitLabel(l0);
+ mv.visitVarInsn(ILOAD, 1);
+ mv.visitLdcInsn(new Integer(iterations));
+ Label l1 = new Label();
+ mv.visitJumpInsn(IF_ICMPGE, l1);
+ {
+ mv.visitMethodInsn(INVOKESTATIC, CLASS_INTERNAL, "run", "()Ljava/lang/String;", false);
+
+ mv.visitVarInsn(ASTORE, 2);
+ mv.visitVarInsn(ALOAD, 2);
+ mv.visitLdcInsn("java.security.SecureRandom");
+ mv.visitMethodInsn(
+ INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false);
+ Label l2 = new Label();
+ mv.visitJumpInsn(IFNE, l2);
+ mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+ mv.visitLdcInsn("result incorrect: ");
+ mv.visitMethodInsn(
+ INVOKEVIRTUAL, "java/io/PrintStream", "print", "(Ljava/lang/String;)V", false);
+ mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+ mv.visitVarInsn(ALOAD, 2);
+ mv.visitMethodInsn(
+ INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
+ mv.visitInsn(ICONST_1);
+ mv.visitMethodInsn(INVOKESTATIC, "java/lang/System", "exit", "(I)V", false);
+ mv.visitInsn(RETURN);
+
+ mv.visitLabel(l2);
+ getHash(mv);
+ mv.visitLdcInsn(new Integer(419176645));
+ Label l3 = new Label();
+ mv.visitJumpInsn(IF_ICMPEQ, l3);
+ mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+ mv.visitLdcInsn("state incorrect: ");
+ mv.visitMethodInsn(
+ INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
+ mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+ printState(mv);
+ mv.visitInsn(ICONST_2);
+ mv.visitMethodInsn(INVOKESTATIC, "java/lang/System", "exit", "(I)V", false);
+ mv.visitInsn(RETURN);
+ mv.visitLabel(l3);
+ }
+ mv.visitIincInsn(1, 1);
+ mv.visitJumpInsn(GOTO, l0);
+ mv.visitLabel(l1);
+
+ println(mv, "Completed successfully after " + iterations + " iterations");
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(-1, -1);
+ mv.visitEnd();
+ }
+
+ {
+ mv = cw.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null);
+ mv.visitCode();
+ mv.visitIntInsn(BIPUSH, staticIntA);
+ mv.visitFieldInsn(PUTSTATIC, CLASS_INTERNAL, "staticIntA", "I");
+ mv.visitIntInsn(BIPUSH, staticIntB);
+ mv.visitFieldInsn(PUTSTATIC, CLASS_INTERNAL, "staticIntB", "I");
+ mv.visitLdcInsn(staticByteArray.length);
+ mv.visitIntInsn(NEWARRAY, T_BYTE);
+ for (int i = 0; i < staticByteArray.length; i++) {
+ mv.visitInsn(DUP);
+ mv.visitIntInsn(SIPUSH, i);
+ mv.visitIntInsn(BIPUSH, staticByteArray[i]);
+ mv.visitInsn(BASTORE);
+ }
+ mv.visitFieldInsn(PUTSTATIC, CLASS_INTERNAL, "staticByteArray", "[B");
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(-1, -1);
+ mv.visitEnd();
+ }
+
+ {
+ mv =
+ cw.visitMethod(
+ ACC_PRIVATE + ACC_STATIC,
+ "methodCausingIssue",
+ "(BSI)Ljava/lang/String;",
+ null,
+ null);
+ mv.visitCode();
+ Label l0 = new Label();
+ mv.visitJumpInsn(GOTO, l0);
+ mv.visitLabel(l0);
+ mv.visitIntInsn(SIPUSH, 472);
+ mv.visitVarInsn(ILOAD, 2);
+ mv.visitInsn(ISUB);
+ mv.visitVarInsn(ISTORE, 2);
+ mv.visitInsn(ICONST_0);
+ mv.visitVarInsn(ISTORE, 3);
+ mv.visitTypeInsn(NEW, "java/lang/String");
+ mv.visitInsn(DUP);
+ mv.visitIntInsn(BIPUSH, 119);
+ mv.visitVarInsn(ILOAD, 0);
+ mv.visitInsn(ISUB);
+ mv.visitVarInsn(ISTORE, 0);
+ mv.visitIincInsn(1, 1);
+ mv.visitFieldInsn(GETSTATIC, CLASS_INTERNAL, "staticByteArray", "[B");
+ mv.visitVarInsn(ASTORE, 4);
+ mv.visitVarInsn(ILOAD, 1);
+ mv.visitIntInsn(NEWARRAY, T_BYTE);
+ mv.visitVarInsn(ALOAD, 4);
+ Label l1 = new Label();
+ mv.visitJumpInsn(IFNONNULL, l1);
+ Label l2 = new Label();
+ mv.visitJumpInsn(GOTO, l2);
+ mv.visitLabel(l1);
+ Label l3 = new Label();
+ mv.visitJumpInsn(GOTO, l3);
+ mv.visitLabel(l2);
+ mv.visitVarInsn(ILOAD, 1);
+ mv.visitVarInsn(ILOAD, 2);
+ Label l4 = new Label();
+ mv.visitJumpInsn(GOTO, l4);
+ Label l5 = new Label();
+ mv.visitLabel(l5);
+ mv.visitInsn(INEG);
+ mv.visitInsn(IADD);
+ mv.visitVarInsn(ISTORE, 0);
+ mv.visitJumpInsn(GOTO, l3);
+ mv.visitLabel(l3);
+ mv.visitInsn(DUP);
+ mv.visitVarInsn(ILOAD, 3);
+ mv.visitIincInsn(3, 1);
+ mv.visitVarInsn(ILOAD, 0);
+ mv.visitInsn(I2B);
+ mv.visitInsn(BASTORE);
+ mv.visitVarInsn(ILOAD, 3);
+ mv.visitVarInsn(ILOAD, 1);
+ Label l6 = new Label();
+ mv.visitJumpInsn(IF_ICMPNE, l6);
+ Label l7 = new Label();
+ mv.visitJumpInsn(GOTO, l7);
+ mv.visitLabel(l6);
+ Label l8 = new Label();
+ mv.visitJumpInsn(GOTO, l8);
+ mv.visitLabel(l7);
+ mv.visitInsn(ICONST_0);
+ mv.visitMethodInsn(INVOKESPECIAL, "java/lang/String", "<init>", "([BI)V", false);
+ mv.visitInsn(ARETURN);
+ mv.visitLabel(l8);
+ mv.visitVarInsn(ILOAD, 0);
+ mv.visitVarInsn(ALOAD, 4);
+ mv.visitIincInsn(2, 1);
+ mv.visitVarInsn(ILOAD, 2);
+ mv.visitInsn(BALOAD);
+ Label l9 = new Label();
+ mv.visitJumpInsn(GOTO, l9);
+ mv.visitLabel(l4);
+ mv.visitFieldInsn(GETSTATIC, CLASS_INTERNAL, "staticIntB", "I");
+ mv.visitIntInsn(BIPUSH, 125);
+ mv.visitInsn(IADD);
+ mv.visitInsn(DUP);
+ mv.visitIntInsn(SIPUSH, 128);
+ mv.visitInsn(IREM);
+ mv.visitFieldInsn(PUTSTATIC, CLASS_INTERNAL, "staticIntA", "I");
+ mv.visitInsn(ICONST_2);
+ mv.visitInsn(IREM);
+ Label l10 = new Label();
+ mv.visitJumpInsn(IFEQ, l10);
+ Label l11 = new Label();
+ mv.visitJumpInsn(GOTO, l11);
+ mv.visitLabel(l10);
+ Label l12 = new Label();
+ mv.visitJumpInsn(GOTO, l12);
+ Label l13 = new Label();
+ mv.visitLabel(l13);
+ mv.visitInsn(INEG);
+ mv.visitInsn(IADD);
+ mv.visitVarInsn(ISTORE, 0);
+ mv.visitJumpInsn(GOTO, l3);
+ mv.visitLabel(l9);
+ mv.visitFieldInsn(GETSTATIC, CLASS_INTERNAL, "staticIntA", "I");
+ mv.visitIntInsn(BIPUSH, 29);
+ mv.visitInsn(IADD);
+ mv.visitInsn(DUP);
+ mv.visitIntInsn(SIPUSH, 128);
+ mv.visitInsn(IREM);
+ mv.visitFieldInsn(PUTSTATIC, CLASS_INTERNAL, "staticIntB", "I");
+ mv.visitInsn(ICONST_2);
+ mv.visitInsn(IREM);
+ Label l14 = new Label();
+ mv.visitJumpInsn(IFNE, l14);
+ Label l15 = new Label();
+ mv.visitJumpInsn(GOTO, l15);
+ mv.visitLabel(l14);
+ Label l16 = new Label();
+ mv.visitJumpInsn(GOTO, l16);
+ Label l17 = new Label();
+ mv.visitLabel(l17);
+ mv.visitInsn(INEG);
+ mv.visitInsn(IADD);
+ mv.visitVarInsn(ISTORE, 0);
+ mv.visitJumpInsn(GOTO, l3);
+ Label l18 = new Label();
+ mv.visitLabel(l18);
+ mv.visitTableSwitchInsn(0, 1, l11, new Label[] {l13, l5});
+ mv.visitLabel(l12);
+ mv.visitInsn(ICONST_1);
+ mv.visitJumpInsn(GOTO, l18);
+ mv.visitLabel(l11);
+ mv.visitInsn(ICONST_0);
+ mv.visitJumpInsn(GOTO, l18);
+ Label l19 = new Label();
+ mv.visitLabel(l19);
+ mv.visitTableSwitchInsn(0, 1, l15, new Label[] {l5, l17});
+ mv.visitLabel(l16);
+ mv.visitInsn(ICONST_0);
+ mv.visitJumpInsn(GOTO, l19);
+ mv.visitLabel(l15);
+ mv.visitInsn(ICONST_1);
+ mv.visitJumpInsn(GOTO, l19);
+ mv.visitMaxs(8, 5);
+ mv.visitEnd();
+ }
+
+ cw.visitEnd();
+
+ return cw.toByteArray();
+ }
+
+ private static void printState(MethodVisitor mv) {
+ println(mv, "staticIntA:");
+ mv.visitFieldInsn(GETSTATIC, CLASS_INTERNAL, "staticIntA", "I");
+ printlnInt(mv);
+
+ println(mv, "staticIntB:");
+ mv.visitFieldInsn(GETSTATIC, CLASS_INTERNAL, "staticIntB", "I");
+ printlnInt(mv);
+
+ println(mv, "staticByteArray:");
+ mv.visitFieldInsn(GETSTATIC, CLASS_INTERNAL, "staticByteArray", "[B");
+ printByteArray(mv);
+ }
+
+ private static void getHash(MethodVisitor mv) {
+ mv.visitFieldInsn(GETSTATIC, CLASS_INTERNAL, "staticIntA", "I");
+ mv.visitFieldInsn(GETSTATIC, CLASS_INTERNAL, "staticIntB", "I");
+ mv.visitFieldInsn(GETSTATIC, CLASS_INTERNAL, "staticByteArray", "[B");
+ mv.visitMethodInsn(INVOKESTATIC, UTILS_CLASS_INTERNAL, "getHash", "(II[B)I", false);
+ }
+
+ private static void printByteArray(MethodVisitor mv) {
+ mv.visitMethodInsn(INVOKESTATIC, UTILS_CLASS_INTERNAL, "printByteArray", "([B)V", false);
+ }
+
+ private static void printlnInt(MethodVisitor mv) {
+ mv.visitMethodInsn(INVOKESTATIC, UTILS_CLASS_INTERNAL, "println", "(I)V", false);
+ }
+
+ private static void printlnString(MethodVisitor mv) {
+ mv.visitMethodInsn(
+ INVOKESTATIC, UTILS_CLASS_INTERNAL, "println", "(Ljava/lang/String;)V", false);
+ }
+
+ private static void println(MethodVisitor mv, String msg) {
+ mv.visitLdcInsn(msg);
+ printlnString(mv);
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/regress/b78493232/Regress78493232Utils.java b/src/test/java/com/android/tools/r8/regress/b78493232/Regress78493232Utils.java
new file mode 100644
index 0000000..14b17ce
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/regress/b78493232/Regress78493232Utils.java
@@ -0,0 +1,35 @@
+// Copyright (c) 2018, 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.regress.b78493232;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class Regress78493232Utils {
+
+ public static void println(String msg) {
+ System.out.println(msg);
+ }
+
+ public static void println(int msg) {
+ System.out.println(msg);
+ }
+
+ public static void printByteArray(byte[] array) {
+ List<String> strings = new ArrayList<>(array.length);
+ for (byte b : array) {
+ strings.add(Byte.toString(b));
+ }
+ System.out.println(String.join(",", strings));
+ }
+
+ public static int getHash(int a, int b, byte[] c) {
+ return a + 7 * b + 13 * Arrays.hashCode(c);
+ }
+
+ public static void printHash(int a, int b, byte[] c) {
+ System.out.println(getHash(a, b, c));
+ }
+}
diff --git a/third_party/r8.tar.gz.sha1 b/third_party/r8.tar.gz.sha1
new file mode 100644
index 0000000..fbb2aa8
--- /dev/null
+++ b/third_party/r8.tar.gz.sha1
@@ -0,0 +1 @@
+38b85dcea75f12c37332a5425c87733e78754ba6
\ No newline at end of file
diff --git a/third_party/shadow.tar.gz.sha1 b/third_party/shadow.tar.gz.sha1
deleted file mode 100644
index 2dfb69e..0000000
--- a/third_party/shadow.tar.gz.sha1
+++ /dev/null
@@ -1 +0,0 @@
-2e350b99a72aba5d45b018b0f5391130c8751371
\ No newline at end of file
diff --git a/tools/gradle.py b/tools/gradle.py
index 862dd57..ff90779 100755
--- a/tools/gradle.py
+++ b/tools/gradle.py
@@ -16,17 +16,11 @@
GRADLE_SHA1 = os.path.join(GRADLE_DIR, 'gradle.tar.gz.sha1')
GRADLE_TGZ = os.path.join(GRADLE_DIR, 'gradle.tar.gz')
-SHADOW_DIR = os.path.join(utils.REPO_ROOT, 'third_party')
-SHADOW_SHA1 = os.path.join(SHADOW_DIR, 'shadow.tar.gz.sha1')
-SHADOW_TGZ = os.path.join(SHADOW_DIR, 'shadow.tar.gz')
-
if utils.IsWindows():
GRADLE = os.path.join(GRADLE_DIR, 'gradle', 'bin', 'gradle.bat')
else:
GRADLE = os.path.join(GRADLE_DIR, 'gradle', 'bin', 'gradle')
-SHADOW = os.path.join(SHADOW_DIR, 'shadow', 'shadow-2.0.1.jar')
-
def PrintCmd(s):
if type(s) is list:
s = ' '.join(s)
@@ -44,19 +38,8 @@
else:
print 'gradle.py: Gradle binary present'
-def EnsureShadow():
- if not os.path.exists(SHADOW) or os.path.getmtime(SHADOW_TGZ) < os.path.getmtime(SHADOW_SHA1):
- # Bootstrap or update gradle, everything else is controlled using gradle.
- utils.DownloadFromGoogleCloudStorage(SHADOW_SHA1)
- # Update the mtime of the tar file to make sure we do not run again unless
- # there is an update.
- os.utime(SHADOW_TGZ, None)
- else:
- print 'gradle.py: Shadow library present'
-
def EnsureDeps():
EnsureGradle()
- EnsureShadow()
def RunGradleIn(gradleCmd, args, cwd, throw_on_failure=True, env=None):
EnsureDeps()