⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 methodwriter.java

📁 jboss规则引擎
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
        // adds the instruction to the bytecode of the method
        if ( opcode == Opcodes.SIPUSH ) {
            this.code.put12( opcode,
                             operand );
        } else { // BIPUSH or NEWARRAY
            this.code.put11( opcode,
                             operand );
        }
    }

    public void visitVarInsn(final int opcode,
                             final int var) {
        if ( this.computeMaxs ) {
            // updates current and max stack sizes
            if ( opcode == Opcodes.RET ) {
                // no stack change, but end of current block (no successor)
                if ( this.currentBlock != null ) {
                    this.currentBlock.maxStackSize = this.maxStackSize;
                    this.currentBlock = null;
                }
            } else { // xLOAD or xSTORE
                final int size = this.stackSize + MethodWriter.SIZE[opcode];
                if ( size > this.maxStackSize ) {
                    this.maxStackSize = size;
                }
                this.stackSize = size;
            }
            // updates max locals
            int n;
            if ( opcode == Opcodes.LLOAD || opcode == Opcodes.DLOAD || opcode == Opcodes.LSTORE || opcode == Opcodes.DSTORE ) {
                n = var + 2;
            } else {
                n = var + 1;
            }
            if ( n > this.maxLocals ) {
                this.maxLocals = n;
            }
        }
        // adds the instruction to the bytecode of the method
        if ( var < 4 && opcode != Opcodes.RET ) {
            int opt;
            if ( opcode < Opcodes.ISTORE ) {
                /* ILOAD_0 */
                opt = 26 + ((opcode - Opcodes.ILOAD) << 2) + var;
            } else {
                /* ISTORE_0 */
                opt = 59 + ((opcode - Opcodes.ISTORE) << 2) + var;
            }
            this.code.putByte( opt );
        } else if ( var >= 256 ) {
            this.code.putByte( 196 /* WIDE */).put12( opcode,
                                                       var );
        } else {
            this.code.put11( opcode,
                             var );
        }
    }

    public void visitTypeInsn(final int opcode,
                              final String desc) {
        if ( this.computeMaxs && opcode == Opcodes.NEW ) {
            // updates current and max stack sizes only if opcode == NEW
            // (stack size variation = 0 for ANEWARRAY, CHECKCAST, INSTANCEOF)
            final int size = this.stackSize + 1;
            if ( size > this.maxStackSize ) {
                this.maxStackSize = size;
            }
            this.stackSize = size;
        }
        // adds the instruction to the bytecode of the method
        this.code.put12( opcode,
                         this.cw.newClass( desc ) );
    }

    public void visitFieldInsn(final int opcode,
                               final String owner,
                               final String name,
                               final String desc) {
        if ( this.computeMaxs ) {
            int size;
            // computes the stack size variation
            final char c = desc.charAt( 0 );
            switch ( opcode ) {
                case Opcodes.GETSTATIC :
                    size = this.stackSize + (c == 'D' || c == 'J' ? 2 : 1);
                    break;
                case Opcodes.PUTSTATIC :
                    size = this.stackSize + (c == 'D' || c == 'J' ? -2 : -1);
                    break;
                case Opcodes.GETFIELD :
                    size = this.stackSize + (c == 'D' || c == 'J' ? 1 : 0);
                    break;
                // case Constants.PUTFIELD:
                default :
                    size = this.stackSize + (c == 'D' || c == 'J' ? -3 : -2);
                    break;
            }
            // updates current and max stack sizes
            if ( size > this.maxStackSize ) {
                this.maxStackSize = size;
            }
            this.stackSize = size;
        }
        // adds the instruction to the bytecode of the method
        this.code.put12( opcode,
                         this.cw.newField( owner,
                                           name,
                                           desc ) );
    }

    public void visitMethodInsn(final int opcode,
                                final String owner,
                                final String name,
                                final String desc) {
        final boolean itf = opcode == Opcodes.INVOKEINTERFACE;
        final Item i = this.cw.newMethodItem( owner,
                                              name,
                                              desc,
                                              itf );
        int argSize = i.intVal;
        if ( this.computeMaxs ) {
            /*
             * computes the stack size variation. In order not to recompute
             * several times this variation for the same Item, we use the intVal
             * field of this item to store this variation, once it has been
             * computed. More precisely this intVal field stores the sizes of
             * the arguments and of the return value corresponding to desc.
             */
            if ( argSize == 0 ) {
                // the above sizes have not been computed yet, so we compute
                // them...
                argSize = getArgumentsAndReturnSizes( desc );
                // ... and we save them in order not to recompute them in the
                // future
                i.intVal = argSize;
            }
            int size;
            if ( opcode == Opcodes.INVOKESTATIC ) {
                size = this.stackSize - (argSize >> 2) + (argSize & 0x03) + 1;
            } else {
                size = this.stackSize - (argSize >> 2) + (argSize & 0x03);
            }
            // updates current and max stack sizes
            if ( size > this.maxStackSize ) {
                this.maxStackSize = size;
            }
            this.stackSize = size;
        }
        // adds the instruction to the bytecode of the method
        if ( itf ) {
            if ( !this.computeMaxs ) {
                if ( argSize == 0 ) {
                    argSize = getArgumentsAndReturnSizes( desc );
                    i.intVal = argSize;
                }
            }
            this.code.put12( Opcodes.INVOKEINTERFACE,
                             i.index ).put11( argSize >> 2,
                                              0 );
        } else {
            this.code.put12( opcode,
                             i.index );
        }
    }

    public void visitJumpInsn(final int opcode,
                              final Label label) {
        if ( this.computeMaxs ) {
            if ( opcode == Opcodes.GOTO ) {
                // no stack change, but end of current block (with one new
                // successor)
                if ( this.currentBlock != null ) {
                    this.currentBlock.maxStackSize = this.maxStackSize;
                    addSuccessor( this.stackSize,
                                  label );
                    this.currentBlock = null;
                }
            } else if ( opcode == Opcodes.JSR ) {
                if ( this.currentBlock != null ) {
                    addSuccessor( this.stackSize + 1,
                                  label );
                }
            } else {
                // updates current stack size (max stack size unchanged because
                // stack size variation always negative in this case)
                this.stackSize += MethodWriter.SIZE[opcode];
                if ( this.currentBlock != null ) {
                    addSuccessor( this.stackSize,
                                  label );
                }
            }
        }
        // adds the instruction to the bytecode of the method
        if ( label.resolved && label.position - this.code.length < Short.MIN_VALUE ) {
            /*
             * case of a backward jump with an offset < -32768. In this case we
             * automatically replace GOTO with GOTO_W, JSR with JSR_W and IFxxx
             * <l> with IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is the
             * "opposite" opcode of IFxxx (i.e., IFNE for IFEQ) and where <l'>
             * designates the instruction just after the GOTO_W.
             */
            if ( opcode == Opcodes.GOTO ) {
                this.code.putByte( 200 ); // GOTO_W
            } else if ( opcode == Opcodes.JSR ) {
                this.code.putByte( 201 ); // JSR_W
            } else {
                this.code.putByte( opcode <= 166 ? ((opcode + 1) ^ 1) - 1 : opcode ^ 1 );
                this.code.putShort( 8 ); // jump offset
                this.code.putByte( 200 ); // GOTO_W
            }
            label.put( this,
                       this.code,
                       this.code.length - 1,
                       true );
        } else {
            /*
             * case of a backward jump with an offset >= -32768, or of a forward
             * jump with, of course, an unknown offset. In these cases we store
             * the offset in 2 bytes (which will be increased in
             * resizeInstructions, if needed).
             */
            this.code.putByte( opcode );
            label.put( this,
                       this.code,
                       this.code.length - 1,
                       false );
        }
    }

    public void visitLabel(final Label label) {
        if ( this.computeMaxs ) {
            if ( this.currentBlock != null ) {
                // ends current block (with one new successor)
                this.currentBlock.maxStackSize = this.maxStackSize;
                addSuccessor( this.stackSize,
                              label );
            }
            // begins a new current block,
            // resets the relative current and max stack sizes
            this.currentBlock = label;
            this.stackSize = 0;
            this.maxStackSize = 0;
        }
        // resolves previous forward references to label, if any
        this.resize |= label.resolve( this,
                                      this.code.length,
                                      this.code.data );
    }

    public void visitLdcInsn(final Object cst) {
        final Item i = this.cw.newConstItem( cst );
        if ( this.computeMaxs ) {
            int size;
            // computes the stack size variation
            if ( i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE ) {
                size = this.stackSize + 2;
            } else {
                size = this.stackSize + 1;
            }
            // updates current and max stack sizes
            if ( size > this.maxStackSize ) {
                this.maxStackSize = size;
            }
            this.stackSize = size;
        }
        // adds the instruction to the bytecode of the method
        final int index = i.index;
        if ( i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE ) {
            this.code.put12( 20 /* LDC2_W */,
                             index );
        } else if ( index >= 256 ) {
            this.code.put12( 19 /* LDC_W */,
                             index );
        } else {
            this.code.put11( Opcodes.LDC,
                             index );
        }
    }

    public void visitIincInsn(final int var,
                              final int increment) {
        if ( this.computeMaxs ) {
            // updates max locals only (no stack change)
            final int n = var + 1;
            if ( n > this.maxLocals ) {
                this.maxLocals = n;
            }
        }
        // adds the instruction to the bytecode of the method
        if ( (var > 255) || (increment > 127) || (increment < -128) ) {
            this.code.putByte( 196 /* WIDE */).put12( Opcodes.IINC,
                                                       var ).putShort( increment );
        } else {
            this.code.putByte( Opcodes.IINC ).put11( var,
                                                     increment );
        }
    }

    public void visitTableSwitchInsn(final int min,
                                     final int max,
                                     final Label dflt,
                                     final Label labels[]) {
        if ( this.computeMaxs ) {
            // updates current stack size (max stack size unchanged)
            --this.stackSize;
            // ends current block (with many new successors)
            if ( this.currentBlock != null ) {
                this.currentBlock.maxStackSize = this.maxStackSize;
                addSuccessor( this.stackSize,
                              dflt );
                for ( int i = 0; i < labels.length; ++i ) {
                    addSuccessor( this.stackSize,
                                  labels[i] );
                }
                this.currentBlock = null;
            }
        }
        // adds the instruction to the bytecode of the method
        final int source = this.code.length;
        this.code.putByte( Opcodes.TABLESWITCH );
        while ( this.code.length % 4 != 0 ) {
            this.code.putByte( 0 );
        }
        dflt.put( this,
                  this.code,
                  source,
                  true );
        this.code.putInt( min ).putInt( max );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -