/** * Returns whether the given instruction may throw exceptions. */ public boolean mayThrowExceptions(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) { mayThrowExceptions = false; instruction.accept(clazz, method, codeAttribute, offset, this); return mayThrowExceptions; }
private boolean matchingOpcodes(Instruction instruction1, Instruction instruction2) { // Check the opcode. return instruction1.opcode == instruction2.opcode || instruction1.canonicalOpcode() == instruction2.opcode; }
/** * Writes the Instruction at the given offset in the given code array. */ public void write(byte[] code, int offset) { // Write the wide opcode, if necessary. if (isWide()) { code[offset++] = InstructionConstants.OP_WIDE; } // Write the opcode. code[offset++] = opcode; // Write any additional arguments. writeInfo(code, offset); }
protected static int readSignedValue(byte[] code, int offset, int valueSize) { switch (valueSize) { case 0: return 0; case 1: return readSignedByte( code, offset); case 2: return readSignedShort(code, offset); case 4: return readInt( code, offset); default: throw new IllegalArgumentException("Unsupported value size ["+valueSize+"]"); } }
protected static int readValue(byte[] code, int offset, int valueSize) { switch (valueSize) { case 0: return 0; case 1: return readByte( code, offset); case 2: return readShort(code, offset); case 4: return readInt( code, offset); default: throw new IllegalArgumentException("Unsupported value size ["+valueSize+"]"); } }
public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, InstructionVisitor instructionVisitor) { if (instructionVisitor != CodeAttributeEditor.this) { throw new UnsupportedOperationException("Unexpected visitor ["+instructionVisitor+"]"); } for (int index = 0; index < instructions.length; index++) { Instruction instruction = instructions[index]; instruction.accept(clazz, method, codeAttribute, offset, CodeAttributeEditor.this); offset += instruction.length(offset); } }
public int length(int offset) { int newOffset = offset; for (int index = 0; index < instructions.length; index++) { newOffset += instructions[index].length(newOffset); } return newOffset - offset; }
/** * Returns whether the specified block of code may throw exceptions. */ private boolean mayThrowExceptions(Clazz clazz, Method method, CodeAttribute codeAttribute, int startOffset, int endOffset) { byte[] code = codeAttribute.code; // Go over all instructions. int offset = startOffset; while (offset < endOffset) { // Get the current instruction. Instruction instruction = InstructionFactory.create(code, offset); // Check if it may be throwing exceptions. if (instruction.mayThrowExceptions()) { return true; } // Go to the next instruction. offset += instruction.length(offset); } return false; }
/** * Replaces the instruction at a given offset by a given push instruction. */ private void replaceInstruction(Clazz clazz, int offset, Instruction instruction, Instruction replacementInstruction) { // Pop unneeded stack entries if necessary. int popCount = instruction.stackPopCount(clazz) - replacementInstruction.stackPopCount(clazz); insertPopInstructions(offset, popCount); if (DEBUG) System.out.println(" Replacing instruction "+instruction.toString(offset)+" -> "+replacementInstruction.toString()+(popCount == 0 ? "" : " ("+popCount+" pops)")); codeAttributeEditor.replaceInstruction(offset, replacementInstruction); // Visit the instruction, if required. if (extraInstructionVisitor != null) { // Note: we're not passing the right arguments for now, knowing that // they aren't used anyway. instruction.accept(clazz, null, null, offset, extraInstructionVisitor); } }
/** * Creates the replacement instruction for the given index in the * instruction sequence. */ public Instruction create(int index) { // Create the instruction. replacementInstructions[index].accept(null, null, null, instructionSequenceMatcher.matchedInstructionOffset(index), this); // Return it. return replacementInstruction.shrink(); }
instruction.readInfo(code, index);
protected static int readSignedValue(byte[] code, int offset, int valueSize) { switch (valueSize) { case 0: return 0; case 1: return readSignedByte( code, offset); case 2: return readSignedShort(code, offset); case 4: return readInt( code, offset); default: throw new IllegalArgumentException("Unsupported value size ["+valueSize+"]"); } }
protected static int readValue(byte[] code, int offset, int valueSize) { switch (valueSize) { case 0: return 0; case 1: return readByte( code, offset); case 2: return readShort(code, offset); case 4: return readInt( code, offset); default: throw new IllegalArgumentException("Unsupported value size ["+valueSize+"]"); } }
/** * Applies the given instruction visitor to all instructions in the * specified range of offsets. */ public void instructionsAccept(Clazz clazz, Method method, int startOffset, int endOffset, InstructionVisitor instructionVisitor) { int offset = startOffset; while (offset < endOffset) { // Note that the instruction is only volatile. Instruction instruction = InstructionFactory.create(code, offset); int instructionLength = instruction.length(offset); instruction.accept(clazz, method, this, offset, instructionVisitor); offset += instructionLength; } }
public int length(int offset) { int newOffset = offset; for (int index = 0; index < instructions.length; index++) { newOffset += instructions[index].length(newOffset); } return newOffset - offset; }
/** * Returns whether the specified block of code may throw exceptions. */ private boolean mayThrowExceptions(Clazz clazz, Method method, CodeAttribute codeAttribute, int startOffset, int endOffset) { byte[] code = codeAttribute.code; // Go over all instructions. int offset = startOffset; while (offset < endOffset) { // Get the current instruction. Instruction instruction = InstructionFactory.create(code, offset); // Check if it may be throwing exceptions. if (instruction.mayThrowExceptions()) { return true; } // Go to the next instruction. offset += instruction.length(offset); } return false; }