/** * Sets this CurrentFrame to the input stack map frame of the next "current" instruction, i.e. the * instruction just after the given one. It is assumed that the value of this object when this * method is called is the stack map frame status just before the given instruction is executed. */ @Override void execute( final int opcode, final int arg, final Symbol symbolArg, final SymbolTable symbolTable) { super.execute(opcode, arg, symbolArg, symbolTable); Frame successor = new Frame(null); merge(symbolTable, successor, 0); copyFrom(successor); } }
t = init(cw, t); changed |= merge(cw, t, frame.inputLocals, i); for (i = 0; i < nLocal; ++i) { t = inputLocals[i]; changed |= merge(cw, t, frame.inputLocals, i); changed = true; changed |= merge(cw, edge, frame.inputStack, 0); return changed; t = inputStack[i]; if (initializations != null) { t = init(cw, t); changed |= merge(cw, t, frame.inputStack, i); t = init(cw, t); changed |= merge(cw, t, frame.inputStack, nInputStack + i);
break; case Opcodes.ACONST_NULL: push(NULL); break; case Opcodes.ICONST_M1: case Opcodes.SIPUSH: case Opcodes.ILOAD: push(INTEGER); break; case Opcodes.LCONST_0: case Opcodes.LCONST_1: case Opcodes.LLOAD: push(LONG); push(TOP); break; case Opcodes.FCONST_0: case Opcodes.FCONST_2: case Opcodes.FLOAD: push(FLOAT); break; case Opcodes.DCONST_0: case Opcodes.DCONST_1: case Opcodes.DLOAD: push(DOUBLE); push(TOP); break; case Opcodes.LDC:
/** * Pushes a new type onto the output frame stack. * * @param cw the ClassWriter to which this label belongs. * @param desc the descriptor of the type to be pushed. Can also be a method * descriptor (in this case this method pushes its return type onto * the output frame stack). */ private void push(final ClassWriter cw, final String desc) { int type = type(cw, desc); if (type != 0) { push(type); if (type == LONG || type == DOUBLE) { push(TOP); } } }
/** * Pushes the abstract type corresponding to the given descriptor on the output frame stack. * * @param symbolTable the type table to use to lookup and store type {@link Symbol}. * @param descriptor a type or method descriptor (in which case its return type is pushed). */ private void push(final SymbolTable symbolTable, final String descriptor) { int typeDescriptorOffset = descriptor.charAt(0) == '(' ? descriptor.indexOf(')') + 1 : 0; int abstractType = getAbstractTypeFromDescriptor(symbolTable, descriptor, typeDescriptorOffset); if (abstractType != 0) { push(abstractType); if (abstractType == LONG || abstractType == DOUBLE) { push(TOP); } } }
concreteOutputType = getInitializedType(symbolTable, concreteOutputType); frameChanged |= merge(symbolTable, concreteOutputType, dstFrame.inputLocals, i); frameChanged |= merge(symbolTable, inputLocals[i], dstFrame.inputLocals, i); frameChanged = true; frameChanged |= merge(symbolTable, catchTypeIndex, dstFrame.inputStack, 0); return frameChanged; int concreteOutputType = inputStack[i]; if (initializations != null) { concreteOutputType = getInitializedType(symbolTable, concreteOutputType); frameChanged |= merge(symbolTable, concreteOutputType, dstFrame.inputStack, i); concreteOutputType = getInitializedType(symbolTable, concreteOutputType); merge(symbolTable, concreteOutputType, dstFrame.inputStack, numInputStack + i);
@Override public void visitTypeInsn(final int opcode, final String type) { lastBytecodeOffset = code.length; // Add the instruction to the bytecode of the method. Symbol typeSymbol = symbolTable.addConstantClass(type); code.put12(opcode, typeSymbol.index); // If needed, update the maximum stack size and number of locals, and stack map frames. if (currentBasicBlock != null) { if (compute == COMPUTE_ALL_FRAMES || compute == COMPUTE_INSERTED_FRAMES) { currentBasicBlock.frame.execute(opcode, lastBytecodeOffset, typeSymbol, symbolTable); } else if (opcode == Opcodes.NEW) { // The stack size delta is 1 for NEW, and 0 for ANEWARRAY, CHECKCAST, or INSTANCEOF. int size = relativeStackSize + 1; if (size > maxRelativeStackSize) { maxRelativeStackSize = size; } relativeStackSize = size; } } }
break; case Opcodes.ACONST_NULL: push(NULL); break; case Opcodes.ICONST_M1: case Opcodes.SIPUSH: case Opcodes.ILOAD: push(INTEGER); break; case Opcodes.LCONST_0: case Opcodes.LCONST_1: case Opcodes.LLOAD: push(LONG); push(TOP); break; case Opcodes.FCONST_0: case Opcodes.FCONST_2: case Opcodes.FLOAD: push(FLOAT); break; case Opcodes.DCONST_0: case Opcodes.DCONST_1: case Opcodes.DLOAD: push(DOUBLE); push(TOP); break; case Opcodes.LDC:
String catchTypeDescriptor = handler.catchTypeDescriptor == null ? "java/lang/Throwable" : handler.catchTypeDescriptor; int catchType = Frame.getAbstractTypeFromInternalName(symbolTable, catchTypeDescriptor); firstFrame.setInputFrameFromDescriptor(symbolTable, accessFlags, descriptor, this.maxLocals); firstFrame.accept(this); int maxBlockStackSize = basicBlock.frame.getInputStackSize() + basicBlock.outputStackMax; if (maxBlockStackSize > maxStackSize) { maxStackSize = maxBlockStackSize; Label successorBlock = outgoingEdge.successor.getCanonicalInstance(); boolean successorBlockChanged = basicBlock.frame.merge(symbolTable, successorBlock.frame, outgoingEdge.info); if (successorBlockChanged && successorBlock.nextListElement == null) { if ((basicBlock.flags & (Label.FLAG_JUMP_TARGET | Label.FLAG_REACHABLE)) == (Label.FLAG_JUMP_TARGET | Label.FLAG_REACHABLE)) { basicBlock.frame.accept(this); Frame.getAbstractTypeFromInternalName(symbolTable, "java/lang/Throwable"); visitFrameEnd();
currentBasicBlock.frame.setInputFrameFromDescriptor( symbolTable, accessFlags, descriptor, numLocal); currentBasicBlock.frame.accept(this); } else { if (type == Opcodes.F_NEW) { currentBasicBlock.frame.setInputFrameFromApiFormat( symbolTable, numLocal, local, numStack, stack); currentBasicBlock.frame.accept(this); Frame implicitFirstFrame = new Frame(new Label()); implicitFirstFrame.setInputFrameFromDescriptor( symbolTable, accessFlags, descriptor, argumentsSize); implicitFirstFrame.accept(this); currentFrame[frameIndex++] = Frame.getAbstractTypeFromApiFormat(symbolTable, local[i]); currentFrame[frameIndex++] = Frame.getAbstractTypeFromApiFormat(symbolTable, stack[i]);
/** * Ends the current basic ast. This method must be used in the case where * the current basic ast does not have any successor. */ private void noSuccessor() { if (compute == FRAMES) { Label l = new Label(); l.frame = new Frame(); l.frame.owner = l; l.resolve(this, code.length, code.data); previousBlock.successor = l; previousBlock = l; } else { currentBlock.outputStackMax = maxStackSize; } currentBlock = null; }
f.initInputFrame(cw, access, Type.getArgumentTypes(descriptor), this.maxLocals); visitFrame(f); while (e != null) { Label n = e.successor.getFirst(); boolean change = f.merge(cw, n.frame, e.info); if (change && n.next == null) {
currentBlock.frame.initInputFrame(cw, access, Type.getArgumentTypes(descriptor), nLocal); visitImplicitFirstFrame(); } else { if (type == Opcodes.F_NEW) { currentBlock.frame.set(cw, nLocal, local, nStack, stack); } else { if (local[i] instanceof String) { String desc = Type.getObjectType((String) local[i]).getDescriptor(); frame[frameIndex++] = Frame.type(cw, desc); } else if (local[i] instanceof Integer) { frame[frameIndex++] = Frame.BASE | ((Integer) local[i]).intValue(); if (stack[i] instanceof String) { String desc = Type.getObjectType((String) stack[i]).getDescriptor(); frame[frameIndex++] = Frame.type(cw, desc); } else if (stack[i] instanceof Integer) { frame[frameIndex++] = Frame.BASE | ((Integer) stack[i]).intValue();
/** * Pops as many abstract types from the output frame stack as described by the given descriptor. * * @param descriptor a type or method descriptor (in which case its argument types are popped). */ private void pop(final String descriptor) { char firstDescriptorChar = descriptor.charAt(0); if (firstDescriptorChar == '(') { pop((Type.getArgumentsAndReturnSizes(descriptor) >> 2) - 1); } else if (firstDescriptorChar == 'J' || firstDescriptorChar == 'D') { pop(2); } else { pop(1); } }
previousFrame = null; frame = null; Frame f = new Frame(); f.owner = labels; Type[] args = Type.getArgumentTypes(descriptor); f.initInputFrame(cw, access, args, maxLocals); visitFrame(f); Label l = labels;
int t = type(cw, args[j].getDescriptor()); inputLocals[i++] = t; if (t == LONG || t == DOUBLE) {
@Override public void visitInsn(final int opcode) { lastBytecodeOffset = code.length; // Add the instruction to the bytecode of the method. code.putByte(opcode); // If needed, update the maximum stack size and number of locals, and stack map frames. if (currentBasicBlock != null) { if (compute == COMPUTE_ALL_FRAMES || compute == COMPUTE_INSERTED_FRAMES) { currentBasicBlock.frame.execute(opcode, 0, null, null); } else { int size = relativeStackSize + STACK_SIZE_DELTA[opcode]; if (size > maxRelativeStackSize) { maxRelativeStackSize = size; } relativeStackSize = size; } if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN) || opcode == Opcodes.ATHROW) { endCurrentBasicBlockWithNoSuccessor(); } } }
/** * Ends the current basic block. This method must be used in the case where * the current basic block does not have any successor. */ private void noSuccessor() { if (compute == FRAMES) { Label l = new Label(); l.frame = new Frame(); l.frame.owner = l; l.resolve(this, code.length, code.data); previousBlock.successor = l; previousBlock = l; } else { currentBlock.outputStackMax = maxStackSize; } if (compute != INSERTED_FRAMES) { currentBlock = null; } }
/** * Pushes a new type onto the output frame stack. * * @param cw * the ClassWriter to which this label belongs. * @param desc * the descriptor of the type to be pushed. Can also be a method * descriptor (in this case this method pushes its return type * onto the output frame stack). */ private void push(final ClassWriter cw, final String desc) { int type = type(cw, desc); if (type != 0) { push(type); if (type == LONG || type == DOUBLE) { push(TOP); } } }
f.initInputFrame(cw, access, args, this.maxLocals); visitFrame(f); while (e != null) { Label n = e.successor.getFirst(); boolean change = f.merge(cw, n.frame, e.info); if (change && n.next == null) {