/** * Creates a new null value guard using a jump instruction for {@code null} values. * * @param instrumentedMethod The instrumented method. */ protected UsingJump(MethodDescription instrumentedMethod) { this.instrumentedMethod = instrumentedMethod; firstValueNull = new Label(); secondValueNull = new Label(); endOfBlock = new Label(); }
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; } }
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 {
currentLineNumberTableOffset += 4; createDebugLabel(startPc, labels); labels[startPc].addLineNumber(lineNumber); currentLabel.accept(methodVisitor, (context.parsingOptions & SKIP_DEBUG) == 0);
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(); } }
/** * 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); } } }
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);
/** * Creates a new null value guard using a jump instruction for {@code null} values. * * @param instrumentedMethod The instrumented method. */ protected UsingJump(MethodDescription instrumentedMethod) { this.instrumentedMethod = instrumentedMethod; label = new Label(); }
/** * Creates a new active, bound suppression handler. * * @param suppressedType The suppressed throwable type. * @param exceptionHandler The stack manipulation to apply within a suppression handler. */ protected Bound(TypeDescription suppressedType, StackManipulation exceptionHandler) { this.suppressedType = suppressedType; this.exceptionHandler = exceptionHandler; startOfMethod = new Label(); endOfMethod = new Label(); }
/** * Creates a new line number prepending method visitor. * * @param methodVisitor The method visitor to delegate to. */ public LineNumberPrependingMethodVisitor(MethodVisitor methodVisitor) { super(OpenedClassReader.ASM_API, methodVisitor); startOfMethod = new Label(); prependLineNumber = true; }
/** * 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]; }
/** * Creates a new appending initialization handler without a drain and with an active record. * * @param methodVisitor The underlying method visitor. * @param instrumentedType The instrumented type. * @param record The method pool record for the type initializer. * @param annotationValueFilterFactory The used annotation value filter factory. * @param requireFrames {@code true} if the visitor is required to add frames. * @param expandFrames {@code true} if the visitor is required to expand any added frame. */ protected WithActiveRecord(MethodVisitor methodVisitor, TypeDescription instrumentedType, MethodPool.Record record, AnnotationValueFilter.Factory annotationValueFilterFactory, boolean requireFrames, boolean expandFrames) { super(methodVisitor, instrumentedType, record, annotationValueFilterFactory, requireFrames, expandFrames); label = new Label(); }
/** * Creates a new appending initialization handler with a drain. * * @param methodVisitor The underlying method visitor. * @param instrumentedType The instrumented type. * @param record The method pool record for the type initializer. * @param annotationValueFilterFactory The used annotation value filter factory. * @param requireFrames {@code true} if the visitor is required to add frames. * @param expandFrames {@code true} if the visitor is required to expand any added frame. */ protected WithDrain(MethodVisitor methodVisitor, TypeDescription instrumentedType, MethodPool.Record record, AnnotationValueFilter.Factory annotationValueFilterFactory, boolean requireFrames, boolean expandFrames) { super(methodVisitor, instrumentedType, record, annotationValueFilterFactory, requireFrames, expandFrames); appended = new Label(); original = new Label(); }
/** * Creates a new appending initialization handler with a drain and with an active record. * * @param methodVisitor The underlying method visitor. * @param instrumentedType The instrumented type. * @param record The method pool record for the type initializer. * @param annotationValueFilterFactory The used annotation value filter factory. * @param requireFrames {@code true} if the visitor is required to add frames. * @param expandFrames {@code true} if the visitor is required to expand any added frame. */ protected WithActiveRecord(MethodVisitor methodVisitor, TypeDescription instrumentedType, MethodPool.Record record, AnnotationValueFilter.Factory annotationValueFilterFactory, boolean requireFrames, boolean expandFrames) { super(methodVisitor, instrumentedType, record, annotationValueFilterFactory, requireFrames, expandFrames); label = new Label(); }
this.suppressionHandler = suppressionHandler; this.relocationHandler = relocationHandler; endOfMethod = new Label();
writerFlags, readerFlags); returnHandler = new Label();
/** * {@inheritDoc} */ public void onEndWithSkip(MethodVisitor methodVisitor, Implementation.Context implementationContext, MethodSizeHandler.ForAdvice methodSizeHandler, StackMapFrameHandler.ForAdvice stackMapFrameHandler, TypeDefinition returnType) { Label skipExceptionHandler = new Label(); methodVisitor.visitJumpInsn(Opcodes.GOTO, skipExceptionHandler); onEnd(methodVisitor, implementationContext, methodSizeHandler, stackMapFrameHandler, returnType); methodVisitor.visitLabel(skipExceptionHandler); stackMapFrameHandler.injectReturnFrame(methodVisitor); } }
/** * {@inheritDoc} */ public int apply(MethodVisitor methodVisitor, int offset) { if (instrumentedMethod.isConstructor()) { throw new IllegalStateException("Cannot skip code execution from constructor: " + instrumentedMethod); } methodVisitor.visitVarInsn(load, offset); convertValue(methodVisitor); Label noSkip = new Label(); methodVisitor.visitJumpInsn(inverted ? nonDefaultJump : defaultJump, noSkip); relocation.apply(methodVisitor); methodVisitor.visitLabel(noSkip); return requiredSize; } }