changeset 69:87dfb067ca0e

Fixed rewriter to drop unused invocation results. Contributed-by: Remi Forax * rewriter/DexRewriter.java (fixStackAfterAMethodCall): New stack fixing method, needs to be called at each instruction.
author Michael Starzinger <michi@complang.tuwien.ac.at>
date Wed, 23 Mar 2011 00:59:25 +0100
parents ba55a434c9c0
children 9cf792cbb36c
files src/main/java/org/icedrobot/daneel/rewriter/DexRewriter.java
diffstat 1 files changed, 42 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/src/main/java/org/icedrobot/daneel/rewriter/DexRewriter.java	Tue Mar 22 23:27:44 2011 +0100
+++ b/src/main/java/org/icedrobot/daneel/rewriter/DexRewriter.java	Wed Mar 23 00:59:25 2011 +0100
@@ -166,7 +166,7 @@
         public MethodRewriter(MethodVisitor mv, String desc) {
             this.mv = new PatchMethodVisitor(mv);
             this.desc = desc;
-            this.returnRegisterType = NO_TYPE;
+            this.returnRegisterType = VOID_TYPE;
         }
 
         /**
@@ -257,6 +257,19 @@
             return asmLabel;
         }
         
+        /** This method must be called before each instruction unless the instruction
+         *  is a MOVE_RESULT*.
+         *  It checks if the last instruction was an invoke and corrects the stack
+         *  if the current instruction is not a MOVE_RESULT*.
+         */
+        private void fixStackAfterAMethodCall() {
+            int returnRegisterType = this.returnRegisterType;
+            if (returnRegisterType != VOID_TYPE) {
+                mv.visitInsn((returnRegisterType == LONG_TYPE || returnRegisterType == DOUBLE_TYPE)? POP2: POP);
+                this.returnRegisterType = VOID_TYPE;
+            }
+        }
+        
         private static AssertionError newAssertionError(Opcode opcode) {
             return new AssertionError("Invalid opcode: " + opcode);
         }
@@ -295,6 +308,7 @@
 
         @Override
         public void visitInstr(Opcode opcode) {
+            fixStackAfterAMethodCall();
             if (opcode == Opcode.RETURN_VOID) {
                 mv.visitInsn(RETURN);
                 interpreter.setDead();
@@ -310,6 +324,7 @@
         @Override
         public void visitInstrField(Opcode opcode, int vsrcOrDest, int vref,
                 String owner, String name, String desc) {
+            fixStackAfterAMethodCall();
             vsrcOrDest = registerToSlot(vsrcOrDest);
             vref = registerToSlot(vref);
             owner = TypeUtil.convertDescToInternal(owner);
@@ -348,6 +363,7 @@
 
         @Override
         public void visitInstrConstString(Opcode opcode, int vdest, String value) {
+            fixStackAfterAMethodCall();
             vdest = registerToSlot(vdest);
             mv.visitLdcInsn(value);
             mv.visitVarInsn(ASTORE, vdest);
@@ -356,6 +372,7 @@
         
         @Override
         public void visitInstrClass(Opcode opcode, int vsrcOrDest, String typeDesc) {
+            fixStackAfterAMethodCall();
             vsrcOrDest = registerToSlot(vsrcOrDest);
             switch(opcode) {
             case CONST_CLASS:
@@ -385,7 +402,7 @@
         @Override
         public void visitInstrMethod(Opcode opcode, int num, int va,
                 int vpacked, String owner, String name, String desc) {
-
+            fixStackAfterAMethodCall();
             Opcode erasedRangeOpcode;
             int[] registers;
             if (opcode.compareTo(Opcode.INVOKE_VIRTUAL_RANGE) >= 0) { // *_range
@@ -456,6 +473,7 @@
         @Override
         public void visitInstrConstU32(Opcode opcode, int vdest,
                 final int value) {
+            fixStackAfterAMethodCall();
             final int sdest = registerToSlot(vdest);
             mv.setPatchMode();
             mv.visitLdcInsn(value);
@@ -477,6 +495,7 @@
         @Override
         public void visitInstrConstU64(Opcode opcode, int vdest,
                 final long value) {
+            fixStackAfterAMethodCall();
             final int sdest = registerToSlot(vdest);
             mv.setPatchMode();
             mv.visitLdcInsn(value);
@@ -502,23 +521,25 @@
             case RETURN:
             case RETURN_WIDE:
             case RETURN_OBJECT: {
+                fixStackAfterAMethodCall();
                 int type = getReturnTypeFromMethodDescriptor(desc);
                 mv.visitVarInsn(Register.getJavaOpcode(type, ILOAD), srcOrDst);
                 interpreter.load(srcOrDst, type);
                 mv.visitInsn(Register.getJavaOpcode(type, IRETURN));
+                break;
             }
-            break;
             case MOVE_RESULT:
             case MOVE_RESULT_WIDE:
             case MOVE_RESULT_OBJECT: {
                 // INVOKE + MOVE_RESULT is equivalent to INVOKE + STORE
-                if(returnRegisterType!=VOID_TYPE)
-                    mv.visitVarInsn(Register.getJavaOpcode(returnRegisterType,
-                        ISTORE), srcOrDst);
-                // TODO: What to do if returnRegisterType==VOID_TYPE?
-                returnRegisterType=NO_TYPE;
+                if (returnRegisterType != VOID_TYPE) {
+                    mv.visitVarInsn(
+                            Register.getJavaOpcode(returnRegisterType, ISTORE),
+                            srcOrDst);
+                    returnRegisterType = VOID_TYPE;
+                }
+                break;
             }
-            break;
             default:
                 throw new UnsupportedOperationException("NYI " + opcode);
             }
@@ -526,9 +547,9 @@
         
         @Override
         public void visitInstrUnaryOp(Opcode opcode, int dest, int src) {
+            fixStackAfterAMethodCall();
             final int vdest = registerToSlot(dest);
             final int vsrc = registerToSlot(src);
-            
             switch(opcode) {
             case MOVE:
             case MOVE_FROM16:
@@ -582,6 +603,7 @@
         @Override
         public void visitInstrBinOp(Opcode opcode, int vdest, int vsrc1,
                 int vsrc2) {
+            fixStackAfterAMethodCall();
             vdest = registerToSlot(vdest);
             vsrc1 = registerToSlot(vsrc1);
             vsrc2 = registerToSlot(vsrc2);
@@ -631,9 +653,9 @@
         @Override
         public void visitInstrBinOpAndLiteral(Opcode opcode, int vdest,
                 int vsrc, int value) {
+            fixStackAfterAMethodCall();
             vdest = registerToSlot(vdest);
             vsrc = registerToSlot(vsrc);
-            
             boolean rsub = opcode == Opcode.RSUB_INT_LIT16
                     || opcode == Opcode.RSUB_INT_LIT8;
             if (rsub) {
@@ -662,6 +684,7 @@
         
         @Override
         public void visitInstrGoto(Opcode opcode, Label label) {
+            fixStackAfterAMethodCall();
             Register[] registers = interpreter.getJoinPoint(label);
             if (registers != null) { // backward goto
                 interpreter.merge(registers);
@@ -675,6 +698,7 @@
         
         @Override
         public void visitInstrIfTestZ(Opcode opcode, int vsrc, Label label) {
+            fixStackAfterAMethodCall();
             vsrc = registerToSlot(vsrc);
             mv.visitVarInsn(ILOAD, vsrc);
             interpreter.load(vsrc, INT_TYPE);
@@ -693,9 +717,9 @@
         @Override
         public void visitInstrNewArray(Opcode opcode, int vdest, int vsize,
                 String typeDesc) {
+            fixStackAfterAMethodCall();
             vdest = registerToSlot(vdest);
             vsize = registerToSlot(vsize);
-            
             mv.visitVarInsn(ILOAD, vsize);
             interpreter.load(vsize, INT_TYPE);
             mv.visitIntInsn(NEWARRAY, getNewArrayKindFromASMType(Type.getType(typeDesc).getElementType()));
@@ -706,14 +730,13 @@
         @Override
         public void visitInstrArray(Opcode opcode, int vsrcOrDest, int varray,
                 int vindex) {
+            fixStackAfterAMethodCall();
             vsrcOrDest = registerToSlot(vsrcOrDest);
             varray = registerToSlot(varray);
             vindex = registerToSlot(vindex);
-            
             int type = interpreter.getRegister(varray).getType();
             int componentType = Register.getComponentType(type);
             interpreter.load(vindex, INT_TYPE);
-            
             switch(opcode) {
             case APUT: case APUT_WIDE: case APUT_OBJECT:
             case APUT_BOOLEAN: case APUT_BYTE: case APUT_CHAR: case APUT_SHORT:
@@ -741,6 +764,7 @@
         @Override
         public void visitInstrIfTest(Opcode opcode, int vsrc1, int vsrc2,
                 Label label) {
+            fixStackAfterAMethodCall();
             vsrc1 = registerToSlot(vsrc1);
             vsrc2 = registerToSlot(vsrc2);
             throw new UnsupportedOperationException("NYI " + opcode);
@@ -749,6 +773,7 @@
         @Override
         public void visitInstrFillArrayData(Opcode opcode, int vsrc,
                 Object arrayData) {
+            fixStackAfterAMethodCall();
             vsrc = registerToSlot(vsrc);
             throw new UnsupportedOperationException("NYI " + opcode);
         }
@@ -756,6 +781,7 @@
         @Override
         public void visitInstrFilledNewArray(Opcode opcode, int num, int va,
                 int vpacked, String type) {
+            fixStackAfterAMethodCall();
             // don't forget to use registerToSlot
             throw new UnsupportedOperationException("NYI " + opcode);
         }
@@ -763,6 +789,7 @@
         @Override
         public void visitInstrInstanceof(Opcode opcode, int vdest, int vsrc,
                 String type) {
+            fixStackAfterAMethodCall();
             vdest = registerToSlot(vdest);
             vsrc = registerToSlot(vsrc);
             throw new UnsupportedOperationException("NYI " + opcode);
@@ -771,6 +798,7 @@
         @Override
         public void visitInstrSwitch(Opcode opcode, int vsrc,
                 Map<Integer, Label> labels) {
+            fixStackAfterAMethodCall();
             vsrc = registerToSlot(vsrc);
             throw new UnsupportedOperationException("NYI " + opcode);
         }