Merge "Allow to use error prone"
diff --git a/src/main/java/com/android/tools/r8/D8.java b/src/main/java/com/android/tools/r8/D8.java
index e025665..ab46628 100644
--- a/src/main/java/com/android/tools/r8/D8.java
+++ b/src/main/java/com/android/tools/r8/D8.java
@@ -108,7 +108,7 @@
return;
}
if (command.isPrintVersion()) {
- System.out.println("D8 " + Version.LABEL);
+ Version.printToolVersion("D8");
return;
}
run(command);
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 27e7d02..62e3413 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -504,7 +504,7 @@
return;
}
if (command.isPrintVersion()) {
- System.out.println("R8 " + Version.LABEL);
+ Version.printToolVersion("R8");
return;
}
run(command);
diff --git a/src/main/java/com/android/tools/r8/R8Command.java b/src/main/java/com/android/tools/r8/R8Command.java
index 9a11817..564aa9c 100644
--- a/src/main/java/com/android/tools/r8/R8Command.java
+++ b/src/main/java/com/android/tools/r8/R8Command.java
@@ -43,8 +43,8 @@
super(CompilationMode.RELEASE);
}
- protected Builder(boolean forceProguardCompatibility) {
- super(CompilationMode.RELEASE);
+ protected Builder(boolean ignoreDexInArchive, boolean forceProguardCompatibility) {
+ super(CompilationMode.RELEASE, ignoreDexInArchive);
this.forceProguardCompatibility = forceProguardCompatibility;
}
diff --git a/src/main/java/com/android/tools/r8/Version.java b/src/main/java/com/android/tools/r8/Version.java
index ed19d71..c59c205 100644
--- a/src/main/java/com/android/tools/r8/Version.java
+++ b/src/main/java/com/android/tools/r8/Version.java
@@ -4,10 +4,25 @@
package com.android.tools.r8;
+import com.android.tools.r8.utils.VersionProperties;
+import java.io.IOException;
+
public final class Version {
public static final String LABEL = "v0.2.0-dev";
private Version() {
}
+
+ public static void printToolVersion(String toolName) {
+ System.out.println(toolName + " " + Version.LABEL);
+ try {
+ VersionProperties version =
+ new VersionProperties(Version.class.getClassLoader());
+ System.out.println(version.getDescription());
+ } catch (IOException e) {
+ System.out.println("eng build");
+ }
+
+ }
}
diff --git a/src/main/java/com/android/tools/r8/compatdx/CompatDx.java b/src/main/java/com/android/tools/r8/compatdx/CompatDx.java
index 905b356..09f3321 100644
--- a/src/main/java/com/android/tools/r8/compatdx/CompatDx.java
+++ b/src/main/java/com/android/tools/r8/compatdx/CompatDx.java
@@ -16,6 +16,7 @@
import com.android.tools.r8.D8Command;
import com.android.tools.r8.D8Output;
import com.android.tools.r8.Resource;
+import com.android.tools.r8.Version;
import com.android.tools.r8.compatdx.CompatDx.DxCompatOptions.DxUsageMessage;
import com.android.tools.r8.compatdx.CompatDx.DxCompatOptions.PositionInfo;
import com.android.tools.r8.errors.CompilationError;
@@ -62,6 +63,7 @@
// Final values after parsing.
// Note: These are ordered by their occurrence in "dx --help"
public final boolean help;
+ public final boolean version;
public final boolean debug;
public final boolean verbose;
public final PositionInfo positions;
@@ -165,6 +167,7 @@
final OptionSpec<Integer> minApiLevel;
final OptionSpec<String> inputList;
final OptionSpec<String> inputs;
+ final OptionSpec<Void> version;
final OptionSpec<Void> help;
final OptionSpec<Integer> maxIndexNumber;
@@ -246,12 +249,14 @@
.withRequiredArg()
.describedAs(FILE_ARG);
inputs = parser.nonOptions("Input files");
+ version = parser.accepts("version", "Print the version of this tool").forHelp();
help = parser.accepts("help", "Print this message").forHelp();
}
}
private DxCompatOptions(OptionSet options, Spec spec) {
help = options.has(spec.help);
+ version = options.has(spec.version);
debug = options.has(spec.debug);
verbose = options.has(spec.verbose);
if (options.has(spec.positions)) {
@@ -336,6 +341,10 @@
printHelpOn(System.out);
return;
}
+ if (dexArgs.version) {
+ Version.printToolVersion("CompatDx");
+ return;
+ }
CompilationMode mode = CompilationMode.RELEASE;
Path output = null;
List<Path> inputs = new ArrayList<>();
diff --git a/src/main/java/com/android/tools/r8/compatproguard/CompatProguard.java b/src/main/java/com/android/tools/r8/compatproguard/CompatProguard.java
index 9dc5424..75c28d1 100644
--- a/src/main/java/com/android/tools/r8/compatproguard/CompatProguard.java
+++ b/src/main/java/com/android/tools/r8/compatproguard/CompatProguard.java
@@ -7,6 +7,7 @@
import com.android.tools.r8.CompilationException;
import com.android.tools.r8.R8;
import com.android.tools.r8.R8Command;
+import com.android.tools.r8.Version;
import com.google.common.collect.ImmutableList;
import java.io.IOException;
import java.nio.file.Paths;
@@ -71,6 +72,10 @@
}
private static void run(String[] args) throws IOException, CompilationException {
+ if (args.length == 0) {
+ Version.printToolVersion("CompatProguard");
+ return;
+ }
System.out.println("CompatProguard " + String.join(" ", args));
// Run R8 passing all the options from the command line as a Proguard configuration.
CompatProguardOptions options = CompatProguardOptions.parse(args);
diff --git a/src/main/java/com/android/tools/r8/compatproguard/CompatProguardCommandBuilder.java b/src/main/java/com/android/tools/r8/compatproguard/CompatProguardCommandBuilder.java
index df2298c..145d0e6 100644
--- a/src/main/java/com/android/tools/r8/compatproguard/CompatProguardCommandBuilder.java
+++ b/src/main/java/com/android/tools/r8/compatproguard/CompatProguardCommandBuilder.java
@@ -8,6 +8,6 @@
public class CompatProguardCommandBuilder extends R8Command.Builder {
CompatProguardCommandBuilder(boolean forceProguardCompatibility) {
- super(forceProguardCompatibility);
+ super(true, forceProguardCompatibility);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java b/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java
index 7f640c3..75967cf 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java
@@ -43,12 +43,10 @@
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
-import java.util.Map;
import java.util.Queue;
import java.util.Set;
import org.objectweb.asm.Handle;
@@ -191,34 +189,11 @@
this.application = application;
this.clazz = clazz;
parameterTypes = Arrays.asList(Type.getArgumentTypes(node.desc));
- state = new JarState(node.maxLocals, computeLocals(node.localVariables, application));
+ state = new JarState(node.maxLocals, node.localVariables, application);
AbstractInsnNode first = node.instructions.getFirst();
initialLabel = first instanceof LabelNode ? (LabelNode) first : null;
}
- private static Map<LocalVariableNode, DebugLocalInfo> computeLocals(
- List localNodes, JarApplicationReader application) {
- Map<DebugLocalInfo, DebugLocalInfo> canonical = new HashMap<>(localNodes.size());
- Map<LocalVariableNode, DebugLocalInfo> localVariables = new HashMap<>(localNodes.size());
- for (Object o : localNodes) {
- LocalVariableNode node = (LocalVariableNode) o;
- localVariables.computeIfAbsent(node, n -> canonicalizeLocal(n, canonical, application));
- }
- return localVariables;
- }
-
- private static DebugLocalInfo canonicalizeLocal(
- LocalVariableNode node,
- Map<DebugLocalInfo, DebugLocalInfo> canonicalLocalVariables,
- JarApplicationReader application) {
- DebugLocalInfo info = new DebugLocalInfo(
- application.getString(node.name),
- application.getTypeFromDescriptor(node.desc),
- node.signature == null ? null : application.getString(node.signature));
- DebugLocalInfo canonical = canonicalLocalVariables.putIfAbsent(info, info);
- return canonical != null ? canonical : info;
- }
-
private boolean isStatic() {
return (node.access & Opcodes.ACC_STATIC) > 0;
}
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/JarState.java b/src/main/java/com/android/tools/r8/ir/conversion/JarState.java
index 6faba19..d211a03 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/JarState.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/JarState.java
@@ -5,7 +5,9 @@
import com.android.tools.r8.errors.InvalidDebugInfoException;
import com.android.tools.r8.graph.DebugLocalInfo;
+import com.android.tools.r8.graph.JarApplicationReader;
import com.android.tools.r8.utils.DescriptorUtils;
+import com.google.common.base.Equivalence;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Multimap;
@@ -13,6 +15,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.Comparator;
import java.util.Deque;
import java.util.HashMap;
@@ -42,6 +45,26 @@
// Type representative for a value that may be either a boolean or a byte.
public static final Type BYTE_OR_BOOL_TYPE = null;
+ // Equivalence to canonicalize local-variable information.
+ private static class LocalNodeEquivalence extends Equivalence<LocalVariableNode> {
+
+ @Override
+ protected boolean doEquivalent(LocalVariableNode a, LocalVariableNode b) {
+ if (!a.name.equals(b.name) || !a.desc.equals(b.desc)) {
+ return false;
+ }
+ return (a.signature == null && b.signature == null)
+ || (a.signature != null && a.signature.equals(b.signature));
+ }
+
+ @Override
+ protected int doHash(LocalVariableNode local) {
+ return 31 * local.name.hashCode()
+ + 7 * local.desc.hashCode()
+ + (local.signature == null ? 0 : local.signature.hashCode());
+ }
+ }
+
// Typed mapping from a local slot or stack slot to a virtual register.
public static class Slot {
public final int register;
@@ -183,7 +206,8 @@
private final Local[] locals;
// Mapping from local-variable nodes to their canonical local info.
- private final Map<LocalVariableNode, DebugLocalInfo> localVariables;
+ private final Map<Equivalence.Wrapper<LocalVariableNode>, DebugLocalInfo> localVariables;
+ private final LocalNodeEquivalence localNodeEquivalence = new LocalNodeEquivalence();
// Scope-points of all local variables for inserting debug scoping instructions.
private final Multimap<LabelNode, LocalVariableNode> localVariableStartPoints;
@@ -198,20 +222,54 @@
// Concretely we treat all remaining byte-or-bool types as bytes (no actual type can flow there).
private boolean building = false;
- public JarState(int maxLocals, Map<LocalVariableNode, DebugLocalInfo> localVariables) {
+ // TODO(zerny): Precompute the necessary local structures for faster access and remove this.
+ private final List localNodes;
+
+ public JarState(int maxLocals, List localNodes, JarApplicationReader application) {
int localsRegistersSize = maxLocals * 3;
localsSize = maxLocals;
locals = new Local[localsRegistersSize];
startOfStack = localsRegistersSize;
topOfStack = startOfStack;
- this.localVariables = localVariables;
+ this.localNodes = localNodes;
+ localVariables = computeLocals(localNodes, application);
localVariableStartPoints = HashMultimap.create();
localVariableEndPoints = HashMultimap.create();
- populateLocalTables();
+ populateLocalTables(localNodes);
}
- private void populateLocalTables() {
- for (LocalVariableNode node : localVariables.keySet()) {
+ private Map<Equivalence.Wrapper<LocalVariableNode>, DebugLocalInfo> computeLocals(
+ List localNodes, JarApplicationReader application) {
+ int size = localNodes.size();
+ if (size == 0) {
+ return Collections.emptyMap();
+ }
+ if (size == 1) {
+ LocalVariableNode local = (LocalVariableNode) localNodes.get(0);
+ return Collections.singletonMap(
+ localNodeEquivalence.wrap(local), createLocalInfo(local, application));
+ }
+ Map<Equivalence.Wrapper<LocalVariableNode>, DebugLocalInfo> locals = new HashMap<>(size);
+ for (Object o : localNodes) {
+ LocalVariableNode node = (LocalVariableNode) o;
+ Equivalence.Wrapper<LocalVariableNode> wrapped = localNodeEquivalence.wrap(node);
+ locals.computeIfAbsent(wrapped, w -> createLocalInfo(w.get(), application));
+ }
+ return locals;
+ }
+
+ private static DebugLocalInfo createLocalInfo(
+ LocalVariableNode node,
+ JarApplicationReader application) {
+ return new DebugLocalInfo(
+ application.getString(node.name),
+ application.getTypeFromDescriptor(node.desc),
+ node.signature == null ? null : application.getString(node.signature));
+ }
+
+ private void populateLocalTables(List localNodes) {
+ for (Object object : localNodes) {
+ LocalVariableNode node = (LocalVariableNode) object;
if (node.start != node.end) {
localVariableStartPoints.put(node.start, node);
localVariableEndPoints.put(node.end, node);
@@ -221,9 +279,10 @@
public boolean localLiveAt(Local local, int offset, JarSourceCode source) {
// TODO(zerny): Precompute and sort the local ranges.
- for (Entry<LocalVariableNode, DebugLocalInfo> entry : localVariables.entrySet()) {
- LocalVariableNode node = entry.getKey();
- if (entry.getValue() != local.info) {
+ for (Object object : localNodes) {
+ LocalVariableNode node = (LocalVariableNode) object;
+ DebugLocalInfo nodeInfo = localVariables.get(localNodeEquivalence.wrap(node));
+ if (nodeInfo != local.info) {
continue;
}
Type type = Type.getType(node.desc);
@@ -279,7 +338,8 @@
Collection<LocalVariableNode> nodes = localVariableStartPoints.get(label);
ArrayList<Local> locals = new ArrayList<>(nodes.size());
for (LocalVariableNode node : nodes) {
- locals.add(setLocalInfo(node.index, Type.getType(node.desc), localVariables.get(node)));
+ DebugLocalInfo info = localVariables.get(localNodeEquivalence.wrap(node));
+ locals.add(setLocalInfo(node.index, Type.getType(node.desc), info));
}
// Sort to ensure deterministic instruction ordering (correctness is unaffected).
locals.sort(Comparator.comparingInt(local -> local.slot.register));
@@ -501,14 +561,15 @@
}
}
// TODO(zerny): Precompute and sort the local ranges.
- for (Entry<LocalVariableNode, DebugLocalInfo> entry : localVariables.entrySet()) {
- LocalVariableNode node = entry.getKey();
+ for (Object object : localNodes) {
+ LocalVariableNode node = (LocalVariableNode) object;
int startOffset = source.getOffset(node.start);
int endOffset = source.getOffset(node.end);
if (startOffset <= target && target < endOffset) {
int register = getLocalRegister(node.index, Type.getType(node.desc));
Local local = locals[register];
- locals[register] = new Local(local.slot, entry.getValue());
+ DebugLocalInfo info = localVariables.get(localNodeEquivalence.wrap(node));
+ locals[register] = new Local(local.slot, info);
}
}
}
diff --git a/src/main/java/com/android/tools/r8/utils/VersionProperties.java b/src/main/java/com/android/tools/r8/utils/VersionProperties.java
new file mode 100644
index 0000000..c2253de
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/utils/VersionProperties.java
@@ -0,0 +1,60 @@
+// 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.utils;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+/**
+ * A class describing version properties.
+ */
+public class VersionProperties {
+ private static final int VERSION_CODE = 1;
+
+ private static final String VERSION_CODE_KEY = "version-file.version.code";
+ private static final String SHA_KEY = "version.sha";
+ private static final String RELEASER_KEY = "releaser";
+
+ private static final String RESOURCE_NAME = "r8-version.properties";
+
+ private String codeBase;
+ private String releaser;
+
+ public VersionProperties(ClassLoader loader)
+ throws IOException {
+ try (InputStream resourceStream = loader.getResourceAsStream(RESOURCE_NAME)) {
+ if (resourceStream == null) {
+ throw new FileNotFoundException(RESOURCE_NAME);
+ }
+ initWithInputStream(resourceStream);
+ }
+ }
+
+ private void initWithInputStream(InputStream is) throws IOException {
+ Properties prop = new Properties();
+ prop.load(is);
+
+ long versionFileVersion = Long.parseLong(prop.getProperty(VERSION_CODE_KEY));
+ assert versionFileVersion >= 1;
+
+ codeBase = prop.getProperty(SHA_KEY);
+ releaser = prop.getProperty(RELEASER_KEY);
+ }
+
+ public String getDescription() {
+ if (codeBase != null && !codeBase.trim().isEmpty()) {
+ return "build " + codeBase + (releaser != null ? " from " + releaser : "");
+ } else {
+ return "eng build" + (releaser != null ? " from " + releaser : "");
+ }
+ }
+
+ @Override
+ public String toString() {
+ return codeBase + " from " + releaser;
+ }
+}
diff --git a/tools/archive.py b/tools/archive.py
index 2ab1f1f..bb6c984 100755
--- a/tools/archive.py
+++ b/tools/archive.py
@@ -10,12 +10,14 @@
import subprocess
import sys
import utils
+import shutil
+import zipfile
ARCHIVE_BUCKET = 'r8-releases'
def GetVersion():
- r8_version = r8.run(['--version'], build = False).strip()
- d8_version = d8.run(['--version'], build = False).strip()
+ r8_version = r8.run(['--version'], build = False).splitlines()[0].strip()
+ d8_version = d8.run(['--version'], build = False).splitlines()[0].strip()
# The version printed is "D8 vVERSION_NUMBER" and "R8 vVERSION_NUMBER"
# Sanity check that versions match.
if d8_version.split()[1] != r8_version.split()[1]:
@@ -63,7 +65,7 @@
if not 'BUILDBOT_BUILDERNAME' in os.environ:
raise Exception('You are not a bot, don\'t archive builds')
version = GetVersion()
- is_master = IsMaster(version)
+ is_master = True #IsMaster(version)
if is_master:
# On master we use the git hash to archive with
print 'On master, using git hash for archiving'
@@ -72,12 +74,23 @@
# Ensure all archived artifacts has been built before archiving.
gradle.RunGradle([utils.D8, utils.R8, utils.COMPATDX, utils.COMPATPROGUARD])
- for jar in [utils.D8_JAR, utils.R8_JAR, utils.COMPATDX_JAR, utils.COMPATPROGUARD_JAR]:
- file_name = os.path.basename(jar)
- destination = GetUploadDestination(version, file_name, is_master)
- print('Uploading %s to %s' % (jar, destination))
- utils.upload_file_to_cloud_storage(jar, destination)
- print('File available at: %s' % GetUrl(version, file_name, is_master))
+ with utils.TempDir() as temp:
+ version_file = os.path.join(temp, 'r8-version.properties')
+ with open(version_file,'w') as version_writer:
+ version_writer.write('version.sha=' + GetGitHash() + '\n')
+ version_writer.write('releaser=' + os.environ.get('BUILDBOT_BUILDERNAME') + '\n')
+ version_writer.write('version-file.version.code=1\n')
+
+ for jar in [utils.D8_JAR, utils.R8_JAR, utils.COMPATDX_JAR, utils.COMPATPROGUARD_JAR]:
+ file_name = os.path.basename(jar)
+ tagged_jar = os.path.join(temp, file_name)
+ shutil.copyfile(jar, tagged_jar)
+ with zipfile.ZipFile(tagged_jar, 'a') as zip:
+ zip.write(version_file, os.path.basename(version_file))
+ destination = GetUploadDestination(version, file_name, is_master)
+ print('Uploading %s to %s' % (tagged_jar, destination))
+ utils.upload_file_to_cloud_storage(tagged_jar, destination)
+ print('File available at: %s' % GetUrl(version, file_name, is_master))
if __name__ == '__main__':
sys.exit(Main())