Mercurial > hg > icedrobot > daneel
changeset 81:96c63feb973c
This patch:
- compute register types from method parameters
- implements array_length
- refactor the code that creates array to allow array of objects
author | forax |
---|---|
date | Sat, 26 Mar 2011 00:46:50 +0100 |
parents | 817b7941153f |
children | 474e8b694138 |
files | src/main/java/org/icedrobot/daneel/rewriter/DexRewriter.java src/main/java/org/icedrobot/daneel/rewriter/Interpreter.java src/main/java/org/icedrobot/daneel/rewriter/Register.java |
diffstat | 3 files changed, 61 insertions(+), 21 deletions(-) [+] |
line wrap: on
line diff
--- a/src/main/java/org/icedrobot/daneel/rewriter/DexRewriter.java Fri Mar 25 23:59:09 2011 +0100 +++ b/src/main/java/org/icedrobot/daneel/rewriter/DexRewriter.java Sat Mar 26 00:46:50 2011 +0100 @@ -43,6 +43,7 @@ import static org.icedrobot.daneel.rewriter.Registers.*; import java.nio.ByteBuffer; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.IdentityHashMap; @@ -60,6 +61,7 @@ import org.objectweb.asm.ClassWriter; import org.objectweb.asm.FieldVisitor; import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.tree.InsnNode; @@ -68,7 +70,7 @@ public class DexRewriter implements DexClassVisitor { private final ClassVisitor cv; - + /** * Rewrites a class from Dalvik bytecode into Java bytecode representation. * The source class is given by specifying its name and the DEX source it is @@ -145,7 +147,7 @@ return null; } - return new MethodRewriter(mv, desc); + return new MethodRewriter(mv, (access & Opcodes.ACC_STATIC) != 0, desc); } @Override @@ -155,7 +157,8 @@ static class MethodRewriter implements DexMethodVisitor { final PatchMethodVisitor mv; - final String desc; + private final boolean isStatic; + private final String desc; private Interpreter interpreter; private int returnRegisterType; // type of the register used to stored @@ -171,8 +174,9 @@ private final Set<Label> exceptionHandlerSet = Collections.newSetFromMap(new IdentityHashMap<Label, Boolean>()); - public MethodRewriter(MethodVisitor mv, String desc) { + public MethodRewriter(MethodVisitor mv, boolean isStatic, String desc) { this.mv = new PatchMethodVisitor(mv); + this.isStatic = isStatic; this.desc = desc; this.returnRegisterType = VOID_TYPE; } @@ -326,7 +330,26 @@ mv.visitCode(); this.locals = registerSize - insSize; this.parameters = insSize; - interpreter = new Interpreter(registerSize); + + Register[] registers = new Register[registerSize]; + Arrays.fill(registers, 0, registerSize, Register.UNINITIALIZED); + + Type[] parameterTypes = Type.getArgumentTypes(desc); + int length = parameterTypes.length; + int slot; + if (isStatic) { + slot = 0; + } else { + registers[0] = new Register(OBJECT_TYPE, null); + slot = 1; + } + for (int i = 0; i < length; i++) { + Type type = parameterTypes[i]; + registers[slot] = new Register(getTypeFromASMType(type), null); + slot += type.getSize(); + } + + interpreter = new Interpreter(registers); } @Override @@ -641,6 +664,10 @@ return; } + case ARRAY_LENGTH: + srcType = OBJECT_TYPE; + dstType = INT_TYPE; + break; case NEG_INT: case NOT_INT: dstType = INT_TYPE; break; @@ -660,7 +687,9 @@ dstType = BYTE_TYPE + opcode.ordinal() - Opcode.INT_TO_BYTE.ordinal(); break; - default: { + default: { // INT_TO_LONG, INT_TO_FLOAT, INT_TO_DOUBLE, LONG_TO_INT, LONG_TO_FLOAT, + // LONG_TO_DOUBLE, FLOAT_TO_INT, FLOAT_TO_LONG, DOUBLE_TO_INT, + // DOUBLE_TO_LONG, DOUBLE_TO_FLOAT int conversion = opcode.ordinal() - Opcode.INT_TO_LONG.ordinal(); int div = conversion / 3; int modulo = conversion % 3; @@ -810,9 +839,18 @@ vsize = registerToSlot(vsize); mv.visitVarInsn(ILOAD, vsize); interpreter.load(vsize, INT_TYPE); - mv.visitIntInsn(NEWARRAY, getNewArrayKindFromASMType(Type.getType(typeDesc).getElementType())); + + String componentTypeDesc = typeDesc.substring(1); + Type asmComponentType = Type.getType(componentTypeDesc); + int componentType = getTypeFromASMType(asmComponentType); + if (Register.isArray(componentType) || componentType == OBJECT_TYPE) { + mv.visitTypeInsn(ANEWARRAY, asmComponentType.getInternalName()); + } else { + mv.visitIntInsn(NEWARRAY, getNewArrayKindFromASMType(asmComponentType)); + } + mv.visitVarInsn(ASTORE, vdest); - interpreter.store(vdest, getTypeFromASMType(Type.getType(typeDesc))); + interpreter.store(vdest, Register.makeArray(componentType, 1)); } @Override @@ -921,6 +959,7 @@ throw new UnsupportedOperationException("NYI " + opcode); } + @Override public void visitInstrPackedSwitch(Opcode opcode, int vsrc, int firstKey, Label[] targets) { fixStackAfterAMethodCallOrAnExceptionHandler();
--- a/src/main/java/org/icedrobot/daneel/rewriter/Interpreter.java Fri Mar 25 23:59:09 2011 +0100 +++ b/src/main/java/org/icedrobot/daneel/rewriter/Interpreter.java Sat Mar 26 00:46:50 2011 +0100 @@ -40,11 +40,13 @@ import java.util.Arrays; import java.util.HashMap; +import org.objectweb.asm.Type; + /** * An abstract interpreter for virtual registers. It is used to infer the * register type information by tracking all load and store operations on them. */ -public class Interpreter { +class Interpreter { private final Register[] registers; private final HashMap<Object, Register[]> joinPointMap = new HashMap<Object, Register[]>(); private boolean isDead; @@ -53,12 +55,10 @@ * Creates a new abstract interpreter capable of tracking a given number of * virtual registers. * - * @param maxRegisters The number of registers to handle. + * @param registers The array of registers to handle. */ - public Interpreter(int maxRegisters) { - Register[] registers = new Register[maxRegisters]; - Arrays.fill(registers, Register.UNINITIALIZED); - this.registers = registers; + Interpreter(Register[] registers) { + this.registers = registers; } /**
--- a/src/main/java/org/icedrobot/daneel/rewriter/Register.java Fri Mar 25 23:59:09 2011 +0100 +++ b/src/main/java/org/icedrobot/daneel/rewriter/Register.java Sat Mar 26 00:46:50 2011 +0100 @@ -211,17 +211,18 @@ return (type & UNTYPED_MASK) != 0; } - /** Create the type of an array of type. - * @param elementType the element type of the array (which can't be an array itself) - * @param dimension the dimension of the array. As in Java or Dalvik, the dimension - * is limited to 255. + /** Create an array of type. + * @param componentType the component type of the array (which can be an array itself) + * @param dimension the dimension of the array. As in Java or Dalvik, the resulting + * array dimension is limited to 255. * @return the corresponding array type. */ - public static int makeArray(int elementType, int dimension) { - if (isUntyped(elementType) || isArray(elementType)) { + public static int makeArray(int componentType, int dimension) { + if (isUntyped(componentType)) { throw new IllegalArgumentException("invalid type"); } - return dimension << 8 | (elementType & 0xFF); + return ((((componentType >> 8) & 0xFF) + dimension) << 8) + | (componentType & 0xFF); } /** Returns true if the type is an array type.