📄 constantanalyzer.java
字号:
for (int i=0; i< locals.length; i++) { if (locals[i] != null && locals[i].value instanceof JSRTargetInfo) { JSRTargetInfo jsrInfo = (JSRTargetInfo) locals[i].value; jsrInfo = jsrInfo.copy(); locals[i] = locals[i].copy(); locals[i].value = jsrInfo; for (int slot = 0; slot < locals.length; slot++) { if (jsrTargetInfo.uses(slot)) jsrInfo.addUsed(slot); } } } for (int i=0; i< stack.length; i++) { if (stack[i] != null && stack[i].value instanceof JSRTargetInfo) { JSRTargetInfo jsrInfo = (JSRTargetInfo)stack[i].value; jsrInfo = jsrInfo.copy(); stack[i] = stack[i].copy(); stack[i].value = jsrInfo; for (int slot = 0; slot < locals.length; slot++) { if (jsrTargetInfo.uses(slot)) jsrInfo.addUsed(slot); } } } return this; } public void merge(StackLocalInfo other) { for (int i=0; i < locals.length; i++) { if (locals[i] != null) { if (other.locals[i] == null) { locals[i].constantChanged(); locals[i] = null; enqueue(); } else { locals[i].merge(other.locals[i]); } } } if (stack.length != other.stack.length) throw new jode.AssertError("stack length differs"); for (int i=0; i < stack.length; i++) { if ((other.stack[i] == null) != (stack[i] == null)) throw new jode.AssertError("stack types differ"); else if (stack[i] != null) stack[i].merge(other.stack[i]); } } public String toString() { return "Locals: "+Arrays.asList(locals) +"Stack: "+Arrays.asList(stack)+ "Instr: "+instr; } } private static class ConstantInfo implements ConstantListener { ConstantInfo() { this(0, null); } ConstantInfo(int flags) { this(flags, null); } ConstantInfo(int flags, Object constant) { this.flags = flags; this.constant = constant; } int flags; /** * The constant, may be an Instruction for CONSTANTFLOW. */ Object constant; public void constantChanged() { constant = null; flags &= ~(CONSTANT | CONSTANTFLOW); } } private static ConstValue[] unknownValue = { new ConstValue(1), new ConstValue(2) }; private static ConstantInfo unknownConstInfo = new ConstantInfo(); public ConstantAnalyzer() { } public void mergeInfo(Instruction instr, StackLocalInfo info) { if (instr.getTmpInfo() == null) { instr.setTmpInfo(info); info.instr = instr; info.enqueue(); } else ((StackLocalInfo)instr.getTmpInfo()).merge(info); } public void handleReference(Reference ref, boolean isVirtual) { Main.getClassBundle().reachableReference(ref, isVirtual); } public void handleClass(String clName) { int i = 0; while (i < clName.length() && clName.charAt(i) == '[') i++; if (i < clName.length() && clName.charAt(i) == 'L') { clName = clName.substring(i+1, clName.length()-1); Main.getClassBundle().reachableClass(clName); } } public void handleOpcode(StackLocalInfo info, Identifier fieldListener) { Instruction instr = info.instr; info.constInfo = unknownConstInfo; int opcode = instr.getOpcode(); Handler[] handlers = bytecode.getExceptionHandlers(); for (int i=0; i< handlers.length; i++) { if (handlers[i].start.getAddr() <= instr.getAddr() && handlers[i].end.getAddr() >= instr.getAddr()) mergeInfo(handlers[i].catcher, info.poppush(info.stack.length, unknownValue[0])); } ConstValue result; switch (opcode) { case opc_nop: mergeInfo(instr.getNextByAddr(), info.pop(0)); break; case opc_ldc: case opc_ldc2_w: result = new ConstValue(instr.getConstant()); mergeInfo(instr.getNextByAddr(), info.poppush(0, result)); break; case opc_iload: case opc_lload: case opc_fload: case opc_dload: case opc_aload: result = info.getLocal(instr.getLocalSlot()); if (result == null) { dumpStackLocalInfo(); System.err.println(info); System.err.println(instr); } if (result.value != ConstValue.VOLATILE) { info.constInfo = new ConstantInfo(CONSTANT, result.value); result.addConstantListener(info.constInfo); } mergeInfo(instr.getNextByAddr(), info.poppush(0, result) .setLocal(instr.getLocalSlot(), result.copy())); break; case opc_iaload: case opc_laload: case opc_faload: case opc_daload: case opc_aaload: case opc_baload: case opc_caload: case opc_saload: {// ConstValue array = info.getStack(2);// ConstValue index = info.getStack(1);// ConstValue newValue = null;// if (index.value != index.ConstValue.VOLATILE// && array.value != array.ConstValue.VOLATILE// && array.value != null) {// int indexVal = ((Integer) index.value).intValue();// Object content;// switch(opcode) {// case opc_baload: // content = new Integer// (array.value instanceof byte[]// ? ((byte[])array.value)[indexVal]// : ((boolean[])array.value)[indexVal] ? 1 : 0);// case opc_caload: // content = new Integer(((char[])array.value)[indexVal]);// break;// case opc_saload:// content = new Integer(((short[])array.value)[indexVal]);// break;// case opc_iaload: // case opc_laload: // case opc_faload: // case opc_daload: // case opc_aaload:// content = Array.get(array.value, indexVal);// break;// default:// throw new jode.AssertError("Can't happen.");// }// result = new ConstValue(content);// array.addConstantListener(result);// index.addConstantListener(result);// } else { result = unknownValue[(opcode == opc_laload || opcode == opc_daload) ? 1 : 0];// } mergeInfo(instr.getNextByAddr(), info.poppush(2, result)); break; } case opc_istore: case opc_fstore: case opc_astore: { result = info.getStack(1); if (result.value instanceof JSRTargetInfo) info.constInfo.flags |= RETASTORE; mergeInfo(instr.getNextByAddr(), info.pop(1).setLocal(instr.getLocalSlot(), result)); break; } case opc_lstore: case opc_dstore: { mergeInfo(instr.getNextByAddr(), info.pop(2).setLocal(instr.getLocalSlot(), info.getStack(2))); break; } case opc_iastore: case opc_lastore: case opc_fastore: case opc_dastore: case opc_aastore: case opc_bastore: case opc_castore: case opc_sastore: { int size = (opcode == opc_lastore || opcode == opc_dastore) ? 2 : 1; mergeInfo(instr.getNextByAddr(), info.pop(2+size)); break; } case opc_pop: mergeInfo(instr.getNextByAddr(), info.pop(1)); break; case opc_pop2: mergeInfo(instr.getNextByAddr(), info.pop(2)); break; case opc_dup: case opc_dup_x1: case opc_dup_x2: case opc_dup2: case opc_dup2_x1: case opc_dup2_x2: mergeInfo(instr.getNextByAddr(), info.dup((opcode - (opc_dup - 3)) / 3, (opcode - (opc_dup - 3)) % 3)); break; case opc_swap: mergeInfo(instr.getNextByAddr(), info.swap()); break; case opc_iadd: case opc_ladd: case opc_fadd: case opc_dadd: case opc_isub: case opc_lsub: case opc_fsub: case opc_dsub: case opc_imul: case opc_lmul: case opc_fmul: case opc_dmul: case opc_idiv: case opc_ldiv: case opc_fdiv: case opc_ddiv: case opc_irem: case opc_lrem: case opc_frem: case opc_drem: case opc_iand: case opc_land: case opc_ior : case opc_lor : case opc_ixor: case opc_lxor: { int size = 1 + (opcode - opc_iadd & 1); ConstValue value1 = info.getStack(2*size); ConstValue value2 = info.getStack(1*size); boolean known = value1.value != ConstValue.VOLATILE && value2.value != ConstValue.VOLATILE; if (known) { if (((opcode == opc_idiv || opcode == opc_irem) && ((Integer)value2.value).intValue() == 0) || ((opcode == opc_ldiv || opcode == opc_lrem) && ((Long)value2.value).longValue() == 0)) known = false; } if (known) { Object newValue; switch (opcode) { case opc_iadd: newValue = new Integer (((Integer)value1.value).intValue() + ((Integer)value2.value).intValue()); break; case opc_isub: newValue = new Integer (((Integer)value1.value).intValue() - ((Integer)value2.value).intValue()); break; case opc_imul: newValue = new Integer (((Integer)value1.value).intValue() * ((Integer)value2.value).intValue()); break; case opc_idiv: newValue = new Integer (((Integer)value1.value).intValue() / ((Integer)value2.value).intValue()); break; case opc_irem: newValue = new Integer (((Integer)value1.value).intValue() % ((Integer)value2.value).intValue()); break; case opc_iand: newValue = new Integer (((Integer)value1.value).intValue() & ((Integer)value2.value).intValue()); break; case opc_ior: newValue = new Integer (((Integer)value1.value).intValue() | ((Integer)value2.value).intValue()); break; case opc_ixor: newValue = new Integer (((Integer)value1.value).intValue() ^ ((Integer)value2.value).intValue()); break; case opc_ladd: newValue = new Long (((Long)value1.value).longValue() + ((Long)value2.value).longValue()); break; case opc_lsub: newValue = new Long (((Long)value1.value).longValue() - ((Long)value2.value).longValue()); break; case opc_lmul: newValue = new Long (((Long)value1.value).longValue() * ((Long)value2.value).longValue()); break; case opc_ldiv: newValue = new Long (((Long)value1.value).longValue() / ((Long)value2.value).longValue()); break; case opc_lrem: newValue = new Long (((Long)value1.value).longValue() % ((Long)value2.value).longValue()); break; case opc_land: newValue = new Long (((Long)value1.value).longValue() & ((Long)value2.value).longValue()); break; case opc_lor: newValue = new Long (((Long)value1.value).longValue() | ((Long)value2.value).longValue()); break; case opc_lxor: newValue = new Long (((Long)value1.value).longValue() ^ ((Long)value2.value).longValue()); break; case opc_fadd: newValue = new Float (((Float)value1.value).floatValue() + ((Float)value2.value).floatValue()); break; case opc_fsub: newValue = new Float (((Float)value1.value).floatValue() - ((Float)value2.value).floatValue()); break; case opc_fmul: newValue = new Float (((Float)value1.value).floatValue() * ((Float)value2.value).floatValue()); break; case opc_fdiv: newValue = new Float (((Float)value1.value).floatValue() / ((Float)value2.value).floatValue()); break; case opc_frem: newValue = new Float (((Float)value1.value).floatValue() % ((Float)value2.value).floatValue()); break; case opc_dadd: newValue = new Double (((Double)value1.value).doubleValue() + ((Double)value2.value).doubleValue()); break; case opc_dsub: newValue = new Double (((Double)value1.value).doubleValue() - ((Double)value2.value).doubleValue()); break; case opc_dmul: newValue = new Double (((Double)value1.value).doubleValue() * ((Double)value2.value).doubleValue()); break; case opc_ddiv: newValue = new Double (((Double)value1.value).doubleValue() / ((Double)value2.value).doubleValue()); break; case opc_drem: newValue = new Double (((Double)value1.value).doubleValue() % ((Double)value2.value).doubleValue()); break; default: throw new jode.AssertError("Can't happen."); } info.constInfo = new ConstantInfo(CONSTANT, newValue); result = new ConstValue(newValue); result.addConstantListener(info.constInfo); value1.addConstantListener(result); value2.addConstantListener(result); } else result = unknownValue[size-1]; mergeInfo(instr.getNextByAddr(), info.poppush(2*size, result)); break; } case opc_ineg: case opc_lneg: case opc_fneg: case opc_dneg: { int size = 1 + (opcode - opc_ineg & 1); ConstValue value = info.getStack(size); if (value.value != ConstValue.VOLATILE) { Object newValue; switch (opcode) { case opc_ineg: newValue = new Integer (-((Integer)value.value).intValue()); break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -