Merge "dx: workaround a verifier bug"
diff --git a/dx/src/com/android/dx/dex/code/OutputCollector.java b/dx/src/com/android/dx/dex/code/OutputCollector.java
index 833c0f2..8c8867a 100644
--- a/dx/src/com/android/dx/dex/code/OutputCollector.java
+++ b/dx/src/com/android/dx/dex/code/OutputCollector.java
@@ -65,6 +65,18 @@
         finisher.add(insn);
     }
 
+    public DalvInsn get(int at) {
+        if (at >= finisher.size() || at < 0) {
+            return null;
+        } else {
+            return finisher.get(at);
+        }
+    }
+
+    public int size() {
+        return finisher.size();
+    }
+
     /**
      * Reverses a branch which is buried a given number of instructions
      * backward in the output. It is illegal to call this unless the
diff --git a/dx/src/com/android/dx/dex/code/OutputFinisher.java b/dx/src/com/android/dx/dex/code/OutputFinisher.java
index 3b711fb..82a4725 100644
--- a/dx/src/com/android/dx/dex/code/OutputFinisher.java
+++ b/dx/src/com/android/dx/dex/code/OutputFinisher.java
@@ -256,6 +256,14 @@
         updateInfo(insn);
     }
 
+    public DalvInsn get(int at) {
+        return insns.get(at);
+    }
+
+    public int size() {
+        return insns.size();
+    }
+
     /**
      * Helper for {@link #add} and {@link #insert},
      * which updates the position and local info flags.
diff --git a/dx/src/com/android/dx/dex/code/RopTranslator.java b/dx/src/com/android/dx/dex/code/RopTranslator.java
index 8375f9e..517b4f8 100644
--- a/dx/src/com/android/dx/dex/code/RopTranslator.java
+++ b/dx/src/com/android/dx/dex/code/RopTranslator.java
@@ -762,7 +762,27 @@
                      */
                     di = new CstInsn(opcode, pos, regs, cst);
                 }
-
+                // (b/120985556) update the following code
+                // move-object vX, vY
+                // instance-of vY, vX, LMyClass;
+                // into
+                // move-object vX, vY
+                // nop
+                // instance-of vY, vX, LMyClass;
+                DalvInsn previousDi = getPrevNonSpecialInsn();
+                if (opcode.getOpcode() == Opcodes.INSTANCE_OF && previousDi != null) {
+                    int prevOpcode = previousDi.getOpcode().getOpcode();
+                    if (prevOpcode == Opcodes.MOVE_OBJECT
+                        || prevOpcode == Opcodes.MOVE_OBJECT_FROM16
+                        || prevOpcode == Opcodes.MOVE_OBJECT_16) {
+                        if (di.getRegisters().size() > 0 && previousDi.getRegisters().size() > 1
+                            && (di.getRegisters().get(0).getReg()
+                                    == previousDi.getRegisters().get(1).getReg())) {
+                            DalvInsn nopDi = new SimpleInsn(Dops.NOP, pos, RegisterSpecList.EMPTY);
+                            addOutput(nopDi);
+                        }
+                    }
+                }
                 addOutput(di);
             }
         }
@@ -830,6 +850,16 @@
             output.add(insn);
         }
 
+        protected DalvInsn getPrevNonSpecialInsn() {
+            for (int i = output.size() - 1; i >= 0; --i) {
+                DalvInsn insn = output.get(i);
+                if (insn.getOpcode().getOpcode() != Opcodes.SPECIAL_FORMAT) {
+                    return insn;
+                }
+            }
+            return null;
+        }
+
         /**
          * Adds to the output suffix.
          *