label.put(code, code.length - 1, true); } else if (baseOpcode != opcode) { label.put(code, code.length - 1, true); } else { label.put(code, code.length - 1, false); currentBasicBlock.frame.execute(baseOpcode, 0, null, null); label.getCanonicalInstance().flags |= Label.FLAG_JUMP_TARGET; nextBasicBlock = new Label(); nextBasicBlock = new Label(); } else {
/** * Puts a reference to this label in the bytecode of a method. If the bytecode offset of the label * is known, the relative bytecode offset between the label and the instruction referencing it is * computed and written directly. Otherwise, a null relative offset is written and a new forward * reference is declared for this label. * * @param code the bytecode of the method. This is where the reference is appended. * @param sourceInsnBytecodeOffset the bytecode offset of the instruction that contains the * reference to be appended. * @param wideReference whether the reference must be stored in 4 bytes (instead of 2 bytes). */ final void put( final ByteVector code, final int sourceInsnBytecodeOffset, final boolean wideReference) { if ((flags & FLAG_RESOLVED) == 0) { if (wideReference) { addForwardReference(sourceInsnBytecodeOffset, FORWARD_REFERENCE_TYPE_WIDE, code.length); code.putInt(-1); } else { addForwardReference(sourceInsnBytecodeOffset, FORWARD_REFERENCE_TYPE_SHORT, code.length); code.putShort(-1); } } else { if (wideReference) { code.putInt(bytecodeOffset - sourceInsnBytecodeOffset); } else { code.putShort(bytecodeOffset - sourceInsnBytecodeOffset); } } }
firstBasicBlock.markSubroutine(numSubroutines); if (jsrTarget.subroutineId == 0) { jsrTarget.markSubroutine(++numSubroutines); subroutine.addSubroutineRetSuccessors(basicBlock);
/** * Ends the current basic block. This method must be used in the case where the current basic * block does not have any successor. * * <p>WARNING: this method must be called after the currently visited instruction has been put in * {@link #code} (if frames are computed, this method inserts a new Label to start a new basic * block after the current instruction). */ private void endCurrentBasicBlockWithNoSuccessor() { if (compute == COMPUTE_ALL_FRAMES) { Label nextBasicBlock = new Label(); nextBasicBlock.frame = new Frame(nextBasicBlock); nextBasicBlock.resolve(code.data, code.length); lastBasicBlock.nextBasicBlock = nextBasicBlock; lastBasicBlock = nextBasicBlock; currentBasicBlock = null; } else if (compute == COMPUTE_MAX_STACK_AND_LOCAL) { currentBasicBlock.outputStackMax = (short) maxRelativeStackSize; currentBasicBlock = null; } }
/** * Returns the label corresponding to the given bytecode offset. The default implementation of * this method creates a label for the given offset if it has not been already created. * * @param bytecodeOffset a bytecode offset in a method. * @param labels the already created labels, indexed by their offset. If a label already exists * for bytecodeOffset this method must not create a new one. Otherwise it must store the new * label in this array. * @return a non null Label, which must be equal to labels[bytecodeOffset]. */ protected Label readLabel(final int bytecodeOffset, final Label[] labels) { if (labels[bytecodeOffset] == null) { labels[bytecodeOffset] = new Label(); } return labels[bytecodeOffset]; }
currentLineNumberTableOffset += 4; createDebugLabel(startPc, labels); labels[startPc].addLineNumber(lineNumber); currentLabel.accept(methodVisitor, (context.parsingOptions & SKIP_DEBUG) == 0);
@Override public void visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels) { lastBytecodeOffset = code.length; // Add the instruction to the bytecode of the method. code.putByte(Opcodes.LOOKUPSWITCH).putByteArray(null, 0, (4 - code.length % 4) % 4); dflt.put(code, lastBytecodeOffset, true); code.putInt(labels.length); for (int i = 0; i < labels.length; ++i) { code.putInt(keys[i]); labels[i].put(code, lastBytecodeOffset, true); } // If needed, update the maximum stack size and number of locals, and stack map frames. visitSwitchInsn(dflt, labels); }
private void visitSwitchInsn(final Label dflt, final Label[] labels) { if (currentBasicBlock != null) { if (compute == COMPUTE_ALL_FRAMES) { currentBasicBlock.frame.execute(Opcodes.LOOKUPSWITCH, 0, null, null); // Add all the labels as successors of the current basic block. addSuccessorToCurrentBasicBlock(Edge.JUMP, dflt); dflt.getCanonicalInstance().flags |= Label.FLAG_JUMP_TARGET; for (Label label : labels) { addSuccessorToCurrentBasicBlock(Edge.JUMP, label); label.getCanonicalInstance().flags |= Label.FLAG_JUMP_TARGET; } } else if (compute == COMPUTE_MAX_STACK_AND_LOCAL) { // No need to update maxRelativeStackSize (the stack size delta is always negative). --relativeStackSize; // Add all the labels as successors of the current basic block. addSuccessorToCurrentBasicBlock(relativeStackSize, dflt); for (Label label : labels) { addSuccessorToCurrentBasicBlock(relativeStackSize, label); } } // End the current basic block. endCurrentBasicBlockWithNoSuccessor(); } }
listOfBlocksToProcess = basicBlock.pushSuccessors(listOfBlocksToProcess);
@Override public void visitLabel(final Label label) { hasAsmInstructions |= label.resolve(code.data, code.length);
currentLocals = argumentsSize; firstBasicBlock = new Label(); visitLabel(firstBasicBlock);
/** * Ends the current basic block. This method must be used in the case where the current basic * block does not have any successor. * * <p>WARNING: this method must be called after the currently visited instruction has been put in * {@link #code} (if frames are computed, this method inserts a new Label to start a new basic * block after the current instruction). */ private void endCurrentBasicBlockWithNoSuccessor() { if (compute == COMPUTE_ALL_FRAMES) { Label nextBasicBlock = new Label(); nextBasicBlock.frame = new Frame(nextBasicBlock); nextBasicBlock.resolve(code.data, code.length); lastBasicBlock.nextBasicBlock = nextBasicBlock; lastBasicBlock = nextBasicBlock; currentBasicBlock = null; } else if (compute == COMPUTE_MAX_STACK_AND_LOCAL) { currentBasicBlock.outputStackMax = (short) maxRelativeStackSize; currentBasicBlock = null; } }
currentLineNumberTableOffset += 4; createDebugLabel(startPc, labels); labels[startPc].addLineNumber(lineNumber); currentLabel.accept(methodVisitor, (context.parsingOptions & SKIP_DEBUG) == 0);
@Override public void visitTableSwitchInsn( final int min, final int max, final Label dflt, final Label... labels) { lastBytecodeOffset = code.length; // Add the instruction to the bytecode of the method. code.putByte(Opcodes.TABLESWITCH).putByteArray(null, 0, (4 - code.length % 4) % 4); dflt.put(code, lastBytecodeOffset, true); code.putInt(min).putInt(max); for (Label label : labels) { label.put(code, lastBytecodeOffset, true); } // If needed, update the maximum stack size and number of locals, and stack map frames. visitSwitchInsn(dflt, labels); }
int catchType = Frame.getAbstractTypeFromInternalName(symbolTable, catchTypeDescriptor); Label handlerBlock = handler.handlerPc.getCanonicalInstance(); handlerBlock.flags |= Label.FLAG_JUMP_TARGET; Label handlerRangeBlock = handler.startPc.getCanonicalInstance(); Label handlerRangeEnd = handler.endPc.getCanonicalInstance(); while (handlerRangeBlock != handlerRangeEnd) { handlerRangeBlock.outgoingEdges = Label successorBlock = outgoingEdge.successor.getCanonicalInstance(); boolean successorBlockChanged = basicBlock.frame.merge(symbolTable, successorBlock.frame, outgoingEdge.info);
listOfBlocksToProcess = basicBlock.pushSuccessors(listOfBlocksToProcess);
@Override public void visitLabel(final Label label) { hasAsmInstructions |= label.resolve(code.data, code.length);
label.put(code, code.length - 1, true); } else if (baseOpcode != opcode) { label.put(code, code.length - 1, true); } else { label.put(code, code.length - 1, false); currentBasicBlock.frame.execute(baseOpcode, 0, null, null); label.getCanonicalInstance().flags |= Label.FLAG_JUMP_TARGET; nextBasicBlock = new Label(); nextBasicBlock = new Label(); } else {
visitLabel(new Label());
firstBasicBlock.markSubroutine(numSubroutines); if (jsrTarget.subroutineId == 0) { jsrTarget.markSubroutine(++numSubroutines); subroutine.addSubroutineRetSuccessors(basicBlock);