public boolean isInstanceofRedundant(InstanceofInstruction instruction) { return !myUsefulInstanceofs.contains(instruction) && !instruction.isConditionConst() && myReachable.contains(instruction); }
private int decodeBytecodeInstruction(int index, int stackLen, byte[] stackWords) throws InvalidBytecodeException { int opcode = code[index] & 0xFF; Instruction i = simpleInstructions[opcode]; if (i != null) { decoded.add(i); return index + 1; } boolean wide = false; while (true) { index++; switch (opcode) { case OP_nop: break; case OP_bipush: i = ConstantInstruction.make(code[index]); index++; break; case OP_sipush: i = ConstantInstruction.make(decodeShort(index)); index += 2; break; case OP_ldc: i = makeConstantPoolLoad(code[index] & 0xFF); index++; break; case OP_ldc_w: i = makeConstantPoolLoad(decodeShort(index)); index += 2; break; case OP_ldc2_w: i = makeConstantPoolLoad(decodeShort(index)); index += 2; break; case OP_iload: case OP_lload: case OP_fload: case OP_dload: case OP_aload: i = LoadInstruction.make( indexedTypes[opcode - OP_iload], wide ? decodeUShort(index) : (code[index] & 0xFF)); index += wide ? 2 : 1; break; case OP_istore: case OP_lstore: case OP_fstore: case OP_dstore: case OP_astore: i = StoreInstruction.make( indexedTypes[opcode - OP_istore], wide ? decodeUShort(index) : (code[index] & 0xFF)); index += wide ? 2 : 1; break; case OP_pop2: i = PopInstruction.make(elemCount(stackWords, stackLen - 1)); break; case OP_dup_x2: i = DupInstruction.make(1, elemCount(stackWords, stackLen - 2)); break; case OP_dup2: i = DupInstruction.make(elemCount(stackWords, stackLen - 1), 0); break; case OP_dup2_x1: i = DupInstruction.make(elemCount(stackWords, stackLen - 1), 1); break; case OP_dup2_x2: i = DupInstruction.make( elemCount(stackWords, stackLen - 1), elemCount(stackWords, stackLen - 2)); break; case OP_iinc: { int v = wide ? decodeUShort(index) : (code[index] & 0xFF); int c = wide ? decodeShort(index + 2) : code[index + 1]; decoded.add(LoadInstruction.make(TYPE_int, v)); decoded.add(ConstantInstruction.make(c)); decoded.add(BinaryOpInstruction.make(TYPE_int, Operator.ADD)); i = StoreInstruction.make(TYPE_int, v); index += wide ? 4 : 2; break; } case OP_ifeq: case OP_ifne: case OP_iflt: case OP_ifle: case OP_ifgt: case OP_ifge: decoded.add(makeZero); i = ConditionalBranchInstruction.make( TYPE_int, ConditionalBranchInstruction.Operator.values()[opcode - OP_ifeq], (index - 1) + decodeShort(index)); index += 2; break; case OP_if_icmpeq: case OP_if_icmpne: case OP_if_icmplt: case OP_if_icmple: case OP_if_icmpgt: case OP_if_icmpge: i = ConditionalBranchInstruction.make((short) opcode, (index - 1) + decodeShort(index)); index += 2; break; case OP_if_acmpeq: case OP_if_acmpne: i = ConditionalBranchInstruction.make( TYPE_Object, ConditionalBranchInstruction.Operator.values()[opcode - OP_if_acmpeq], (index - 1) + decodeShort(index)); index += 2; break; case OP_goto: i = GotoInstruction.make((index - 1) + decodeShort(index)); index += 2; break; case OP_jsr: { index += 2; break; } case OP_jsr_w: { index += 4; break; } case OP_ret: int v = wide ? decodeUShort(index) : (code[index] & 0xFF); i = GotoInstruction.make(-1 - v); if (retInfo == null) { throw new InvalidBytecodeException("'ret' outside of subroutine"); } retInfo[index - (wide ? 2 : 1)] = new RetInfo(-1, v, stackLen, stackWords); index += wide ? 2 : 1; break; case OP_tableswitch: { int start = index - 1; while ((index & 3) != 0) { index++; } int def = start + decodeInt(index); int low = decodeInt(index + 4); int high = decodeInt(index + 8); int[] t = new int[(high - low + 1) * 2]; for (int j = 0; j < t.length; j += 2) { t[j] = j / 2 + low; t[j + 1] = start + decodeInt(index + 12 + j * 2); } i = SwitchInstruction.make(t, def); index += 12 + (high - low + 1) * 4; break; } case OP_lookupswitch: { int start = index - 1; while ((index & 3) != 0) { index++; } int def = start + decodeInt(index); int n = decodeInt(index + 4); int[] t = new int[n * 2]; for (int j = 0; j < t.length; j += 2) { t[j] = decodeInt(index + 8 + j * 4); t[j + 1] = start + decodeInt(index + 12 + j * 4); } i = SwitchInstruction.make(t, def); index += 8 + n * 8; break; } case OP_getstatic: case OP_getfield: { int f = decodeUShort(index); i = GetInstruction.make(constantPool, f, opcode == OP_getstatic); index += 2; break; } case OP_putstatic: case OP_putfield: { int f = decodeUShort(index); i = PutInstruction.make(constantPool, f, opcode == OP_putstatic); index += 2; break; } case OP_invokevirtual: case OP_invokespecial: case OP_invokestatic: { int m = decodeUShort(index); i = InvokeInstruction.make(constantPool, m, opcode); index += 2; break; } case OP_invokeinterface: { int m = decodeUShort(index); i = InvokeInstruction.make(constantPool, m, opcode); index += 4; break; } case OP_new: i = NewInstruction.make(constantPool.getConstantPoolClassType(decodeUShort(index)), 0); index += 2; break; case OP_newarray: i = NewInstruction.make(Util.makeArray(getPrimitiveType(code[index])), 1); index++; break; case OP_anewarray: i = NewInstruction.make( Util.makeArray(constantPool.getConstantPoolClassType(decodeUShort(index))), 1); index += 2; break; case OP_checkcast: i = CheckCastInstruction.make(constantPool.getConstantPoolClassType(decodeUShort(index))); index += 2; break; case OP_instanceof: i = InstanceofInstruction.make( constantPool.getConstantPoolClassType(decodeUShort(index))); index += 2; break; case OP_wide: wide = true; opcode = code[index] & 0xFF; continue; case OP_multianewarray: i = NewInstruction.make( constantPool.getConstantPoolClassType(decodeUShort(index)), code[index + 2] & 0xFF); index += 3; break; case OP_ifnull: case OP_ifnonnull: decoded.add(ConstantInstruction.make(TYPE_Object, null)); i = ConditionalBranchInstruction.make( TYPE_Object, ConditionalBranchInstruction.Operator.values()[opcode - OP_ifnull], (index - 1) + decodeShort(index)); index += 2; break; case OP_goto_w: i = GotoInstruction.make((index - 1) + decodeInt(index)); index += 4; break; default: throw new InvalidBytecodeException("Unknown opcode " + opcode); } break; } if (i != null) { decoded.add(i); } return index; }