Merge "Test framework.jar with -Xmx600m"
diff --git a/src/main/java/com/android/tools/r8/BSPatch.java b/src/main/java/com/android/tools/r8/BSPatch.java
index eda5f23..8c1d208 100644
--- a/src/main/java/com/android/tools/r8/BSPatch.java
+++ b/src/main/java/com/android/tools/r8/BSPatch.java
@@ -202,7 +202,6 @@
 
     @Override
     public void copyOld(int blockSize) throws IOException {
-      assert mergeBuffer != null;
       assert mergeBuffer.length == blockSize;
       byte[] data = new byte[blockSize];
       oldInput.get(data);
diff --git a/src/main/java/com/android/tools/r8/graph/CanonicalizedDexItem.java b/src/main/java/com/android/tools/r8/graph/CachedHashValueDexItem.java
similarity index 88%
rename from src/main/java/com/android/tools/r8/graph/CanonicalizedDexItem.java
rename to src/main/java/com/android/tools/r8/graph/CachedHashValueDexItem.java
index 7872801..8f110d5 100644
--- a/src/main/java/com/android/tools/r8/graph/CanonicalizedDexItem.java
+++ b/src/main/java/com/android/tools/r8/graph/CachedHashValueDexItem.java
@@ -4,9 +4,9 @@
 package com.android.tools.r8.graph;
 
 /**
- * DexItems of this kind have to be canonicalized for the whole application.
+ * DexItems of this kind have cached hash values and quick equals check.
  */
-public abstract class CanonicalizedDexItem extends DexItem {
+public abstract class CachedHashValueDexItem extends DexItem {
 
   private static final int NOT_COMPUTED_HASH_VALUE = -1;
   private static final int SENTINEL_HASH_VALUE = 0;
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 54f9470..3845507 100644
--- a/src/main/java/com/android/tools/r8/graph/Code.java
+++ b/src/main/java/com/android/tools/r8/graph/Code.java
@@ -11,7 +11,7 @@
 import com.android.tools.r8.naming.ClassNameMapper;
 import com.android.tools.r8.utils.InternalOptions;
 
-public abstract class Code extends CanonicalizedDexItem {
+public abstract class Code extends CachedHashValueDexItem {
 
   public abstract IRCode buildIR(DexEncodedMethod encodedMethod, InternalOptions options);
 
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 4277324..db55cd6 100644
--- a/src/main/java/com/android/tools/r8/graph/DexAnnotationDirectory.java
+++ b/src/main/java/com/android/tools/r8/graph/DexAnnotationDirectory.java
@@ -17,9 +17,11 @@
   private final List<DexEncodedMethod> methodAnnotations;
   private final List<DexEncodedMethod> parameterAnnotations;
   private final List<DexEncodedField> fieldAnnotations;
+  private final boolean classHasOnlyInternalizableAnnotations;
 
   public DexAnnotationDirectory(DexProgramClass clazz) {
     this.clazz = clazz;
+    this.classHasOnlyInternalizableAnnotations = clazz.hasOnlyInternalizableAnnotations();
     assert isSorted(clazz.directMethods());
     assert isSorted(clazz.virtualMethods());
     OrderedMergingIterator<DexEncodedMethod, DexMethod> methods =
@@ -77,7 +79,7 @@
     if (!(obj instanceof DexAnnotationDirectory)) {
       return false;
     }
-    if (clazz.hasOnlyInternalizableAnnotations()) {
+    if (classHasOnlyInternalizableAnnotations) {
       DexAnnotationDirectory other = (DexAnnotationDirectory) obj;
       if (!other.clazz.hasOnlyInternalizableAnnotations()) {
         return false;
@@ -89,7 +91,7 @@
 
   @Override
   public final int hashCode() {
-    if (clazz.hasOnlyInternalizableAnnotations()) {
+    if (classHasOnlyInternalizableAnnotations) {
       return clazz.annotations.hashCode();
     }
     return super.hashCode();
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 e91e1f0..00b99fa 100644
--- a/src/main/java/com/android/tools/r8/graph/DexAnnotationSet.java
+++ b/src/main/java/com/android/tools/r8/graph/DexAnnotationSet.java
@@ -7,7 +7,7 @@
 import com.android.tools.r8.dex.MixedSectionCollection;
 import java.util.Arrays;
 
-public class DexAnnotationSet extends DexItem {
+public class DexAnnotationSet extends CachedHashValueDexItem {
 
   private static final int UNSORTED = 0;
   private static final DexAnnotationSet THE_EMPTY_ANNOTATIONS_SET =
@@ -25,15 +25,12 @@
   }
 
   @Override
-  public int hashCode() {
+  public int computeHashCode() {
     return Arrays.hashCode(annotations);
   }
 
   @Override
-  public boolean equals(Object other) {
-    if (this == other) {
-      return true;
-    }
+  public boolean computeEquals(Object other) {
     if (other instanceof DexAnnotationSet) {
       DexAnnotationSet o = (DexAnnotationSet) other;
       return Arrays.equals(annotations, o.annotations);
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 f82fe2a..d2c9b3b 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDebugInfo.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDebugInfo.java
@@ -8,7 +8,7 @@
 import java.util.Arrays;
 import java.util.List;
 
-public class DexDebugInfo extends CanonicalizedDexItem {
+public class DexDebugInfo extends CachedHashValueDexItem {
 
   public final int startLine;
   public final DexString[] parameters;
diff --git a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
index 339f4c0..713bd53 100644
--- a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
+++ b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
@@ -29,7 +29,7 @@
 public class DexItemFactory {
 
   private final Map<DexString, DexString> strings = new HashMap<>();
-  private final Map<DexType, DexType> types = new HashMap<>();
+  private final Map<DexString, DexType> types = new HashMap<>();
   private final Map<DexField, DexField> fields = new HashMap<>();
   private final Map<DexProto, DexProto> protos = new HashMap<>();
   private final Map<DexMethod, DexMethod> methods = new HashMap<>();
@@ -302,10 +302,16 @@
     return null;
   }
 
-  public DexType createType(DexString descriptor) {
+  synchronized public DexType createType(DexString descriptor) {
     assert !sorted;
-    DexType type = new DexType(descriptor);
-    return canonicalize(types, type);
+    assert descriptor != null;
+    DexType result = types.get(descriptor);
+    if (result == null) {
+      result = new DexType(descriptor);
+      assert !internalSentinels.contains(result);
+      types.put(descriptor, result);
+    }
+    return result;
   }
 
   public DexType createType(String descriptor) {
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 d3d36e5..5c8f439 100644
--- a/src/main/java/com/android/tools/r8/graph/IndexedDexItem.java
+++ b/src/main/java/com/android/tools/r8/graph/IndexedDexItem.java
@@ -10,7 +10,7 @@
 /**
  * Subset of dex items that are referenced by some table index.
  */
-public abstract class IndexedDexItem extends CanonicalizedDexItem implements Presorted {
+public abstract class IndexedDexItem extends CachedHashValueDexItem implements Presorted {
 
   private static final int SORTED_INDEX_UNKNOWN = -1;
   private int sortedIndex = SORTED_INDEX_UNKNOWN; // assigned globally after reading.
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/MoveEliminator.java b/src/main/java/com/android/tools/r8/ir/optimize/MoveEliminator.java
index 0d93561..a228b20 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/MoveEliminator.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/MoveEliminator.java
@@ -5,6 +5,7 @@
 
 import com.android.tools.r8.ir.code.Instruction;
 import com.android.tools.r8.ir.code.Move;
+import com.android.tools.r8.ir.code.MoveType;
 import com.android.tools.r8.ir.code.Value;
 import com.android.tools.r8.ir.regalloc.RegisterAllocator;
 import java.util.HashSet;
@@ -30,21 +31,32 @@
             allocator.getRegisterForValue(activeMove.src(), activeMove.getNumber());
         int activeMoveDstRegister =
             allocator.getRegisterForValue(activeMove.dest(), activeMove.getNumber());
-        if (activeMoveSrcRegister == moveSrcRegister
-            && activeMoveDstRegister == moveDstRegister) {
+        if (activeMoveSrcRegister == moveSrcRegister && activeMoveDstRegister == moveDstRegister) {
           return true;
         }
+        if (activeMoveDstRegister == moveSrcRegister && activeMoveSrcRegister == moveDstRegister) {
+          if (move.outType() != MoveType.WIDE) {
+            return true;
+          }
+          // If the move is wide make sure the register pair is non-overlapping.
+          if (moveSrcRegister != moveDstRegister + 1 && moveSrcRegister + 1 != moveDstRegister) {
+            return true;
+          }
+        }
       }
     }
     if (instruction.outValue() != null && instruction.outValue().needsRegister()) {
       Value defined = instruction.outValue();
       int definedRegister = allocator.getRegisterForValue(defined, instruction.getNumber());
       activeMoves.removeIf((m) -> {
-        int moveSrcRegister = allocator.getRegisterForValue(m.inValues().get(0), m.getNumber());
-        int moveDstRegister = allocator.getRegisterForValue(m.outValue(), m.getNumber());
+        int moveSrcRegister = allocator.getRegisterForValue(m.src(), m.getNumber());
+        int moveDstRegister = allocator.getRegisterForValue(m.dest(), m.getNumber());
         for (int i = 0; i < defined.requiredRegisters(); i++) {
-          if (definedRegister + i == moveDstRegister || definedRegister + i == moveSrcRegister) {
-            return true;
+          for (int j = 0; j < m.outValue().requiredRegisters(); j++) {
+            if (definedRegister + i == moveDstRegister + j
+                || definedRegister + i == moveSrcRegister + j) {
+              return true;
+            }
           }
         }
         return false;
diff --git a/src/main/java/com/android/tools/r8/naming/NamingState.java b/src/main/java/com/android/tools/r8/naming/NamingState.java
index f42af78..2011530 100644
--- a/src/main/java/com/android/tools/r8/naming/NamingState.java
+++ b/src/main/java/com/android/tools/r8/naming/NamingState.java
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.naming;
 
-import com.android.tools.r8.graph.CanonicalizedDexItem;
+import com.android.tools.r8.graph.CachedHashValueDexItem;
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexString;
 import com.android.tools.r8.utils.StringUtils;
@@ -16,14 +16,14 @@
 import java.util.Map;
 import java.util.Set;
 
-class NamingState<T extends CanonicalizedDexItem> {
+class NamingState<T extends CachedHashValueDexItem> {
 
   private final NamingState<T> parent;
   private final Map<T, InternalState> usedNames = new IdentityHashMap<>();
   private final DexItemFactory itemFactory;
   private final ImmutableList<String> dictionary;
 
-  static <T extends CanonicalizedDexItem> NamingState<T> createRoot(
+  static <T extends CachedHashValueDexItem> NamingState<T> createRoot(
       DexItemFactory itemFactory, ImmutableList<String> dictionary) {
     return new NamingState<>(null, itemFactory, dictionary);
   }
diff --git a/src/test/java/com/android/tools/r8/jdwp/RunJdwpTests.java b/src/test/java/com/android/tools/r8/jdwp/RunJdwpTests.java
index 6ee0b66..a71291d 100644
--- a/src/test/java/com/android/tools/r8/jdwp/RunJdwpTests.java
+++ b/src/test/java/com/android/tools/r8/jdwp/RunJdwpTests.java
@@ -205,7 +205,7 @@
       String pkg = "org.apache.harmony.jpda.tests.jdwp";
       command = Arrays.asList(
           ToolHelper.getJavaExecutable(),
-          "-cp", System.getProperty("java.class.path") + ":" + lib,
+          "-cp", System.getProperty("java.class.path") + File.pathSeparator + lib,
           run, pkg + "." + test);
     } else {
       command = Arrays.asList(