/** * Constructs and returns an immutable instance whose elements are * identical to the ones in the given list, in the same order. * * @param list {@code non-null;} the list to use for elements * @param regCount count, in register-units, of the number of registers * this code block requires. * @return {@code non-null;} an appropriately-constructed instance of this * class */ public static DalvInsnList makeImmutable(ArrayList<DalvInsn> list, int regCount) { int size = list.size(); DalvInsnList result = new DalvInsnList(size, regCount); for (int i = 0; i < size; i++) { result.set(i, list.get(i)); } result.setImmutable(); return result; }
/** * Does a human-friendly dump of this instance. * * @param out {@code non-null;} where to dump * @param prefix {@code non-null;} prefix to attach to each line of output * @param verbose whether to be verbose; verbose output includes * lines for zero-size instructions */ public void debugPrint(OutputStream out, String prefix, boolean verbose) { Writer w = new OutputStreamWriter(out); debugPrint(w, prefix, verbose); try { w.flush(); } catch (IOException ex) { throw new RuntimeException(ex); } } }
/** * Gets the size of this instance, in 16-bit code units. This will only * return a meaningful result if the instructions in this instance all * have valid addresses. * * @return {@code >= 0;} the size */ public int codeSize() { int sz = size(); if (sz == 0) { return 0; } DalvInsn last = get(sz - 1); return last.getNextAddress(); }
/** * Validates an encoded debug info stream against data used to encode it, * throwing an exception if they do not match. Used to validate the * encoder. * * @param info encoded debug info * @param file {@code non-null;} file to refer to during decoding * @param ref {@code non-null;} method whose info is being decoded * @param code {@code non-null;} original code object that was encoded * @param isStatic whether the method is static */ public static void validateEncode(byte[] info, DexFile file, CstMethodRef ref, DalvCode code, boolean isStatic) { PositionList pl = code.getPositions(); LocalList ll = code.getLocals(); DalvInsnList insns = code.getInsns(); int codeSize = insns.codeSize(); int countRegisters = insns.getRegistersSize(); try { validateEncode0(info, codeSize, countRegisters, isStatic, ref, file, pl, ll); } catch (RuntimeException ex) { System.err.println("instructions:"); insns.debugPrint(System.err, " ", true); System.err.println("local list:"); ll.debugPrint(System.err, " "); throw ExceptionWithContext.withContext(ex, "while processing " + ref.toHuman()); } }
/** * Updates the dex statistics. * * @param nonOptCode non-optimized code block * @param code optimized code block */ public static void updateDexStatistics(DalvCode nonOptCode, DalvCode code) { if (DEBUG) { System.err.println("dex insns (old/new) " + nonOptCode.getInsns().codeSize() + "/" + code.getInsns().codeSize() + " regs (o/n) " + nonOptCode.getInsns().getRegistersSize() + "/" + code.getInsns().getRegistersSize() ); } dexRunningDeltaInsns += (code.getInsns().codeSize() - nonOptCode.getInsns().codeSize()); dexRunningDeltaRegisters += (code.getInsns().getRegistersSize() - nonOptCode.getInsns().getRegistersSize()); dexRunningTotalInsns += code.getInsns().codeSize(); }
/** * Gets the size of the outgoing arguments area required by this * method. This is equal to the largest argument word count of any * method referred to by this instance. * * @return {@code >= 0;} the required outgoing arguments size */ public int getOutsSize() { int sz = size(); int result = 0; for (int i = 0; i < sz; i++) { DalvInsn insn = (DalvInsn) get0(i); if (!(insn instanceof CstInsn)) { continue; } Constant cst = ((CstInsn) insn).getConstant(); if (!(cst instanceof CstBaseMethodRef)) { continue; } boolean isStatic = (insn.getOpcode().getFamily() == Opcodes.INVOKE_STATIC); int count = ((CstBaseMethodRef) cst).getParameterWordCount(isStatic); if (count > result) { result = count; } } return result; }
/** * Gets the element at the given index. It is an error to call * this with the index for an element which was never set; if you * do that, this will throw {@code NullPointerException}. * * @param n {@code >= 0, < size();} which index * @return {@code non-null;} element at that index */ public DalvInsn get(int n) { return (DalvInsn) get0(n); }
/** * Get the total registers count. * * @return the count */ private int getRegistersSize() { return code.getInsns().getRegistersSize(); } }
/** * Get the out registers count. * * @return the count */ private int getOutsSize() { return code.getInsns().getOutsSize(); }
/** * Sets the instruction at the given index. * * @param n {@code >= 0, < size();} which index * @param insn {@code non-null;} the instruction to set at {@code n} */ public void set(int n, DalvInsn insn) { set0(n, insn); }
assignAddressesAndFixBranches(); return DalvInsnList.makeImmutable(insns, reservedCount + unreservedRegCount);
/** * Validates an encoded debug info stream against data used to encode it, * throwing an exception if they do not match. Used to validate the * encoder. * * @param info encoded debug info * @param file {@code non-null;} file to refer to during decoding * @param ref {@code non-null;} method whose info is being decoded * @param code {@code non-null;} original code object that was encoded * @param isStatic whether the method is static */ public static void validateEncode(byte[] info, DexFile file, CstMethodRef ref, DalvCode code, boolean isStatic) { PositionList pl = code.getPositions(); LocalList ll = code.getLocals(); DalvInsnList insns = code.getInsns(); int codeSize = insns.codeSize(); int countRegisters = insns.getRegistersSize(); try { validateEncode0(info, codeSize, countRegisters, isStatic, ref, file, pl, ll); } catch (RuntimeException ex) { System.err.println("instructions:"); insns.debugPrint(System.err, " ", true); System.err.println("local list:"); ll.debugPrint(System.err, " "); throw ExceptionWithContext.withContext(ex, "while processing " + ref.toHuman()); } }
/** * Updates the dex statistics. * * @param nonOptCode non-optimized code block * @param code optimized code block */ public static void updateDexStatistics(DalvCode nonOptCode, DalvCode code) { if (DEBUG) { System.err.println("dex insns (old/new) " + nonOptCode.getInsns().codeSize() + "/" + code.getInsns().codeSize() + " regs (o/n) " + nonOptCode.getInsns().getRegistersSize() + "/" + code.getInsns().getRegistersSize() ); } dexRunningDeltaInsns += (code.getInsns().codeSize() - nonOptCode.getInsns().codeSize()); dexRunningDeltaRegisters += (code.getInsns().getRegistersSize() - nonOptCode.getInsns().getRegistersSize()); dexRunningTotalInsns += code.getInsns().codeSize(); }
/** * Gets the size of the outgoing arguments area required by this * method. This is equal to the largest argument word count of any * method referred to by this instance. * * @return {@code >= 0;} the required outgoing arguments size */ public int getOutsSize() { int sz = size(); int result = 0; for (int i = 0; i < sz; i++) { DalvInsn insn = (DalvInsn) get0(i); if (!(insn instanceof CstInsn)) { continue; } Constant cst = ((CstInsn) insn).getConstant(); if (!(cst instanceof CstBaseMethodRef)) { continue; } boolean isStatic = (insn.getOpcode().getFamily() == Opcodes.INVOKE_STATIC); int count = ((CstBaseMethodRef) cst).getParameterWordCount(isStatic); if (count > result) { result = count; } } return result; }
/** * Gets the element at the given index. It is an error to call * this with the index for an element which was never set; if you * do that, this will throw {@code NullPointerException}. * * @param n {@code >= 0, < size();} which index * @return {@code non-null;} element at that index */ public DalvInsn get(int n) { return (DalvInsn) get0(n); }
/** * Get the total registers count. * * @return the count */ private int getRegistersSize() { return code.getInsns().getRegistersSize(); } }
/** * Get the out registers count. * * @return the count */ private int getOutsSize() { return code.getInsns().getOutsSize(); }
/** * Sets the instruction at the given index. * * @param n {@code >= 0, < size();} which index * @param insn {@code non-null;} the instruction to set at {@code n} */ public void set(int n, DalvInsn insn) { set0(n, insn); }
assignAddressesAndFixBranches(); return DalvInsnList.makeImmutable(insns, reservedCount + unreservedRegCount);
/** * Constructs and returns an immutable instance whose elements are * identical to the ones in the given list, in the same order. * * @param list {@code non-null;} the list to use for elements * @param regCount count, in register-units, of the number of registers * this code block requires. * @return {@code non-null;} an appropriately-constructed instance of this * class */ public static DalvInsnList makeImmutable(ArrayList<DalvInsn> list, int regCount) { int size = list.size(); DalvInsnList result = new DalvInsnList(size, regCount); for (int i = 0; i < size; i++) { result.set(i, list.get(i)); } result.setImmutable(); return result; }