Mercurial > hg > icedrobot > daneel
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); }