alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (Instruction.java)

This example Java source code file (Instruction.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

bc_branch, bc_con, bc_index, bc_length, bc_name, bc_slot, bc_tag, constant_loadablevalue, constant_none, formatexception, instruction, lookupswitch, string, switch, util

The Instruction.java Java example source code

/*
 * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.java.util.jar.pack;

import java.io.IOException;
import java.util.Arrays;
import static com.sun.java.util.jar.pack.Constants.*;

/**
 * A parsed bytecode instruction.
 * Provides accessors to various relevant bits.
 * @author John Rose
 */
class Instruction  {
    protected byte[] bytes;  // bytecodes
    protected int pc;        // location of this instruction
    protected int bc;        // opcode of this instruction
    protected int w;         // 0 if normal, 1 if a _wide prefix at pc
    protected int length;    // bytes in this instruction

    protected boolean special;

    protected Instruction(byte[] bytes, int pc, int bc, int w, int length) {
        reset(bytes, pc, bc, w, length);
    }
    private void reset(byte[] bytes, int pc, int bc, int w, int length) {
        this.bytes = bytes;
        this.pc = pc;
        this.bc = bc;
        this.w = w;
        this.length = length;
    }

    public int getBC() {
        return bc;
    }
    public boolean isWide() {
        return w != 0;
    }
    public byte[] getBytes() {
        return bytes;
    }
    public int getPC() {
        return pc;
    }
    public int getLength() {
        return length;
    }
    public int getNextPC() {
        return pc + length;
    }

    public Instruction next() {
        int npc = pc + length;
        if (npc == bytes.length)
            return null;
        else
            return Instruction.at(bytes, npc, this);
    }

    public boolean isNonstandard() {
        return isNonstandard(bc);
    }

    public void setNonstandardLength(int length) {
        assert(isNonstandard());
        this.length = length;
    }


    /** A fake instruction at this pc whose next() will be at nextpc. */
    public Instruction forceNextPC(int nextpc) {
        int llength = nextpc - pc;
        return new Instruction(bytes, pc, -1, -1, llength);
    }

    public static Instruction at(byte[] bytes, int pc) {
        return Instruction.at(bytes, pc, null);
    }

    public static Instruction at(byte[] bytes, int pc, Instruction reuse) {
        int bc = getByte(bytes, pc);
        int prefix = -1;
        int w = 0;
        int length = BC_LENGTH[w][bc];
        if (length == 0) {
            // Hard cases:
            switch (bc) {
            case _wide:
                bc = getByte(bytes, pc+1);
                w = 1;
                length = BC_LENGTH[w][bc];
                if (length == 0) {
                    // unknown instruction; treat as one byte
                    length = 1;
                }
                break;
            case _tableswitch:
                return new TableSwitch(bytes, pc);
            case _lookupswitch:
                return new LookupSwitch(bytes, pc);
            default:
                // unknown instruction; treat as one byte
                length = 1;
                break;
            }
        }
        assert(length > 0);
        assert(pc+length <= bytes.length);
        // Speed hack:  Instruction.next reuses self if possible.
        if (reuse != null && !reuse.special) {
            reuse.reset(bytes, pc, bc, w, length);
            return reuse;
        }
        return new Instruction(bytes, pc, bc, w, length);
    }

    // Return the constant pool reference type, or 0 if none.
    public byte getCPTag() {
        return BC_TAG[w][bc];
    }

    // Return the constant pool index, or -1 if none.
    public int getCPIndex() {
        int indexLoc = BC_INDEX[w][bc];
        if (indexLoc == 0)  return -1;
        assert(w == 0);
        if (length == 2)
            return getByte(bytes, pc+indexLoc);  // _ldc opcode only
        else
            return getShort(bytes, pc+indexLoc);
    }

    public void setCPIndex(int cpi) {
        int indexLoc = BC_INDEX[w][bc];
        assert(indexLoc != 0);
        if (length == 2)
            setByte(bytes, pc+indexLoc, cpi);  // _ldc opcode only
        else
            setShort(bytes, pc+indexLoc, cpi);
        assert(getCPIndex() == cpi);
    }

    public ConstantPool.Entry getCPRef(ConstantPool.Entry[] cpMap) {
        int index = getCPIndex();
        return (index < 0) ? null : cpMap[index];
    }

    // Return the slot of the affected local, or -1 if none.
    public int getLocalSlot() {
        int slotLoc = BC_SLOT[w][bc];
        if (slotLoc == 0)  return -1;
        if (w == 0)
            return getByte(bytes, pc+slotLoc);
        else
            return getShort(bytes, pc+slotLoc);
    }

    // Return the target of the branch, or -1 if none.
    public int getBranchLabel() {
        int branchLoc = BC_BRANCH[w][bc];
        if (branchLoc == 0)  return -1;
        assert(w == 0);
        assert(length == 3 || length == 5);
        int offset;
        if (length == 3)
            offset = (short)getShort(bytes, pc+branchLoc);
        else
            offset = getInt(bytes, pc+branchLoc);
        assert(offset+pc >= 0);
        assert(offset+pc <= bytes.length);
        return offset+pc;
    }

    public void setBranchLabel(int targetPC) {
        int branchLoc = BC_BRANCH[w][bc];
        assert(branchLoc != 0);
        if (length == 3)
            setShort(bytes, pc+branchLoc, targetPC-pc);
        else
            setInt(bytes, pc+branchLoc, targetPC-pc);
        assert(targetPC == getBranchLabel());
    }

    // Return the trailing constant in the instruction (as a signed value).
    // Return 0 if there is none.
    public int getConstant() {
        int conLoc = BC_CON[w][bc];
        if (conLoc == 0)  return 0;
        switch (length - conLoc) {
        case 1: return (byte) getByte(bytes, pc+conLoc);
        case 2: return (short) getShort(bytes, pc+conLoc);
        }
        assert(false);
        return 0;
    }

    public void setConstant(int con) {
        int conLoc = BC_CON[w][bc];
        assert(conLoc != 0);
        switch (length - conLoc) {
        case 1: setByte(bytes, pc+conLoc, con); break;
        case 2: setShort(bytes, pc+conLoc, con); break;
        }
        assert(con == getConstant());
    }

    public abstract static class Switch extends Instruction {
        // Each case is a (value, label) pair, indexed 0 <= n < caseCount
        public abstract int  getCaseCount();
        public abstract int  getCaseValue(int n);
        public abstract int  getCaseLabel(int n);
        public abstract void setCaseCount(int caseCount);
        public abstract void setCaseValue(int n, int value);
        public abstract void setCaseLabel(int n, int targetPC);
        protected abstract int getLength(int caseCount);

        public int  getDefaultLabel()             { return intAt(0)+pc; }
        public void setDefaultLabel(int targetPC) { setIntAt(0, targetPC-pc); }

        protected int apc;        // aligned pc (table base)
        protected int intAt(int n) { return getInt(bytes, apc + n*4); }
        protected void setIntAt(int n, int x) { setInt(bytes, apc + n*4, x); }
        protected Switch(byte[] bytes, int pc, int bc) {
            super(bytes, pc, bc, /*w*/0, /*length*/0);
            this.apc = alignPC(pc+1);
            this.special = true;
            length = getLength(getCaseCount());
        }
        public int getAlignedPC() { return apc; }
        public String toString() {
            String s = super.toString();
            s += " Default:"+labstr(getDefaultLabel());
            int caseCount = getCaseCount();
            for (int i = 0; i < caseCount; i++) {
                s += "\n\tCase "+getCaseValue(i)+":"+labstr(getCaseLabel(i));
            }
            return s;
        }
        public static int alignPC(int apc) {
            while (apc % 4 != 0)  ++apc;
            return apc;
        }
    }

    public static class TableSwitch extends Switch {
        // apc:  (df, lo, hi, (hi-lo+1)*(label))
        public int getLowCase()        { return intAt(1); }
        public int getHighCase()       { return intAt(2); }
        public int getCaseCount()      { return intAt(2)-intAt(1)+1; }
        public int getCaseValue(int n) { return getLowCase()+n; }
        public int getCaseLabel(int n) { return intAt(3+n)+pc; }

        public void setLowCase(int val)  { setIntAt(1, val); }
        public void setHighCase(int val) { setIntAt(2, val); }
        public void setCaseLabel(int n, int tpc) { setIntAt(3+n, tpc-pc); }
        public void setCaseCount(int caseCount) {
            setHighCase(getLowCase() + caseCount - 1);
            length = getLength(caseCount);
        }
        public void setCaseValue(int n, int val) {
            if (n != 0)  throw new UnsupportedOperationException();
            int caseCount = getCaseCount();
            setLowCase(val);
            setCaseCount(caseCount);  // keep invariant
        }

        TableSwitch(byte[] bytes, int pc) {
            super(bytes, pc, _tableswitch);
        }
        protected int getLength(int caseCount) {
            return (apc-pc) + (3 + caseCount) * 4;
        }
    }

    public static class LookupSwitch extends Switch {
        // apc:  (df, nc, nc*(case, label))
        public int getCaseCount()      { return intAt(1); }
        public int getCaseValue(int n) { return intAt(2+n*2+0); }
        public int getCaseLabel(int n) { return intAt(2+n*2+1)+pc; }

        public void setCaseCount(int caseCount)  {
            setIntAt(1, caseCount);
            length = getLength(caseCount);
        }
        public void setCaseValue(int n, int val) { setIntAt(2+n*2+0, val); }
        public void setCaseLabel(int n, int tpc) { setIntAt(2+n*2+1, tpc-pc); }

        LookupSwitch(byte[] bytes, int pc) {
            super(bytes, pc, _lookupswitch);
        }
        protected int getLength(int caseCount) {
            return (apc-pc) + (2 + caseCount*2) * 4;
        }
    }

    /** Two instructions are equal if they have the same bytes. */
    public boolean equals(Object o) {
        return (o != null) && (o.getClass() == Instruction.class)
                && equals((Instruction) o);
    }

    public int hashCode() {
        int hash = 3;
        hash = 11 * hash + Arrays.hashCode(this.bytes);
        hash = 11 * hash + this.pc;
        hash = 11 * hash + this.bc;
        hash = 11 * hash + this.w;
        hash = 11 * hash + this.length;
        return hash;
    }

    public boolean equals(Instruction that) {
        if (this.pc != that.pc)            return false;
        if (this.bc != that.bc)            return false;
        if (this.w  != that.w)             return false;
        if (this.length  != that.length)   return false;
        for (int i = 1; i < length; i++) {
            if (this.bytes[this.pc+i] != that.bytes[that.pc+i])
                return false;
        }
        return true;
    }

    static String labstr(int pc) {
        if (pc >= 0 && pc < 100000)
            return ((100000+pc)+"").substring(1);
        return pc+"";
    }
    public String toString() {
        return toString(null);
    }
    public String toString(ConstantPool.Entry[] cpMap) {
        String s = labstr(pc) + ": ";
        if (bc >= _bytecode_limit) {
            s += Integer.toHexString(bc);
            return s;
        }
        if (w == 1)  s += "wide ";
        String bcname = (bc < BC_NAME.length)? BC_NAME[bc]: null;
        if (bcname == null) {
            return s+"opcode#"+bc;
        }
        s += bcname;
        int tag = getCPTag();
        if (tag != 0)  s += " "+ConstantPool.tagName(tag)+":";
        int idx = getCPIndex();
        if (idx >= 0)  s += (cpMap == null) ? ""+idx : "="+cpMap[idx].stringValue();
        int slt = getLocalSlot();
        if (slt >= 0)  s += " Local:"+slt;
        int lab = getBranchLabel();
        if (lab >= 0)  s += " To:"+labstr(lab);
        int con = getConstant();
        if (con != 0)  s += " Con:"+con;
        return s;
    }


    //public static byte constantPoolTagFor(int bc) { return BC_TAG[0][bc]; }

    /// Fetching values from byte arrays:

    public int getIntAt(int off) {
        return getInt(bytes, pc+off);
    }
    public int getShortAt(int off) {
        return getShort(bytes, pc+off);
    }
    public int getByteAt(int off) {
        return getByte(bytes, pc+off);
    }


    public static int getInt(byte[] bytes, int pc) {
        return (getShort(bytes, pc+0) << 16) + (getShort(bytes, pc+2) << 0);
    }
    public static int getShort(byte[] bytes, int pc) {
        return (getByte(bytes, pc+0) << 8) + (getByte(bytes, pc+1) << 0);
    }
    public static int getByte(byte[] bytes, int pc) {
        return bytes[pc] & 0xFF;
    }


    public static void setInt(byte[] bytes, int pc, int x) {
        setShort(bytes, pc+0, x >> 16);
        setShort(bytes, pc+2, x >> 0);
    }
    public static void setShort(byte[] bytes, int pc, int x) {
        setByte(bytes, pc+0, x >> 8);
        setByte(bytes, pc+1, x >> 0);
    }
    public static void setByte(byte[] bytes, int pc, int x) {
        bytes[pc] = (byte)x;
    }

    // some bytecode classifiers


    public static boolean isNonstandard(int bc) {
        return BC_LENGTH[0][bc] < 0;
    }

    public static int opLength(int bc) {
        int l = BC_LENGTH[0][bc];
        assert(l > 0);
        return l;
    }
    public static int opWideLength(int bc) {
        int l = BC_LENGTH[1][bc];
        assert(l > 0);
        return l;
    }

    public static boolean isLocalSlotOp(int bc) {
        return (bc < BC_SLOT[0].length && BC_SLOT[0][bc] > 0);
    }

    public static boolean isBranchOp(int bc) {
        return (bc < BC_BRANCH[0].length && BC_BRANCH[0][bc] > 0);
    }

    public static boolean isCPRefOp(int bc) {
        if (bc < BC_INDEX[0].length && BC_INDEX[0][bc] > 0)  return true;
        if (bc >= _xldc_op && bc < _xldc_limit)  return true;
        if (bc == _invokespecial_int || bc == _invokestatic_int) return true;
        return false;
    }

    public static byte getCPRefOpTag(int bc) {
        if (bc < BC_INDEX[0].length && BC_INDEX[0][bc] > 0)  return BC_TAG[0][bc];
        if (bc >= _xldc_op && bc < _xldc_limit)  return CONSTANT_LoadableValue;
        if (bc == _invokestatic_int || bc == _invokespecial_int) return CONSTANT_InterfaceMethodref;
        return CONSTANT_None;
    }

    public static boolean isFieldOp(int bc) {
        return (bc >= _getstatic && bc <= _putfield);
    }

    public static boolean isInvokeInitOp(int bc) {
        return (bc >= _invokeinit_op && bc < _invokeinit_limit);
    }

    public static boolean isSelfLinkerOp(int bc) {
        return (bc >= _self_linker_op && bc < _self_linker_limit);
    }

    /// Format definitions.

    static private final byte[][] BC_LENGTH  = new byte[2][0x100];
    static private final byte[][] BC_INDEX   = new byte[2][0x100];
    static private final byte[][] BC_TAG     = new byte[2][0x100];
    static private final byte[][] BC_BRANCH  = new byte[2][0x100];
    static private final byte[][] BC_SLOT    = new byte[2][0x100];
    static private final byte[][] BC_CON     = new byte[2][0x100];
    static private final String[] BC_NAME    = new String[0x100]; // debug only
    static private final String[][] BC_FORMAT  = new String[2][_bytecode_limit]; // debug only
    static {
        for (int i = 0; i < _bytecode_limit; i++) {
            BC_LENGTH[0][i] = -1;
            BC_LENGTH[1][i] = -1;
        }
        def("b", _nop, _dconst_1);
        def("bx", _bipush);
        def("bxx", _sipush);
        def("bk", _ldc);                                // do not pack
        def("bkk", _ldc_w, _ldc2_w);            // do not pack
        def("blwbll", _iload, _aload);
        def("b", _iload_0, _saload);
        def("blwbll", _istore, _astore);
        def("b", _istore_0, _lxor);
        def("blxwbllxx", _iinc);
        def("b", _i2l, _dcmpg);
        def("boo", _ifeq, _jsr);                        // pack oo
        def("blwbll", _ret);
        def("", _tableswitch, _lookupswitch);   // pack all ints, omit padding
        def("b", _ireturn, _return);
        def("bkf", _getstatic, _putfield);              // pack kf (base=Field)
        def("bkm", _invokevirtual, _invokestatic);      // pack kn (base=Method)
        def("bkixx", _invokeinterface);         // pack ki (base=IMethod), omit xx
        def("bkyxx", _invokedynamic);           // pack ky (base=Any), omit xx
        def("bkc", _new);                               // pack kc
        def("bx", _newarray);
        def("bkc", _anewarray);                 // pack kc
        def("b", _arraylength, _athrow);
        def("bkc", _checkcast, _instanceof);    // pack kc
        def("b", _monitorenter, _monitorexit);
        def("", _wide);
        def("bkcx", _multianewarray);           // pack kc
        def("boo", _ifnull, _ifnonnull);                // pack oo
        def("boooo", _goto_w, _jsr_w);          // pack oooo
        for (int i = 0; i < _bytecode_limit; i++) {
            //System.out.println(i+": l="+BC_LENGTH[0][i]+" i="+BC_INDEX[0][i]);
            //assert(BC_LENGTH[0][i] != -1);
            if (BC_LENGTH[0][i] == -1) {
                continue;  // unknown opcode
            }

            // Have a complete mapping, to support spurious _wide prefixes.
            if (BC_LENGTH[1][i] == -1)
                BC_LENGTH[1][i] = (byte)(1+BC_LENGTH[0][i]);
        }

        String names =
  "nop aconst_null iconst_m1 iconst_0 iconst_1 iconst_2 iconst_3 iconst_4 "+
  "iconst_5 lconst_0 lconst_1 fconst_0 fconst_1 fconst_2 dconst_0 dconst_1 "+
  "bipush sipush ldc ldc_w ldc2_w iload lload fload dload aload iload_0 "+
  "iload_1 iload_2 iload_3 lload_0 lload_1 lload_2 lload_3 fload_0 fload_1 "+
  "fload_2 fload_3 dload_0 dload_1 dload_2 dload_3 aload_0 aload_1 aload_2 "+
  "aload_3 iaload laload faload daload aaload baload caload saload istore "+
  "lstore fstore dstore astore istore_0 istore_1 istore_2 istore_3 lstore_0 "+
  "lstore_1 lstore_2 lstore_3 fstore_0 fstore_1 fstore_2 fstore_3 dstore_0 "+
  "dstore_1 dstore_2 dstore_3 astore_0 astore_1 astore_2 astore_3 iastore "+
  "lastore fastore dastore aastore bastore castore sastore pop pop2 dup "+
  "dup_x1 dup_x2 dup2 dup2_x1 dup2_x2 swap iadd ladd fadd dadd isub lsub "+
  "fsub dsub imul lmul fmul dmul idiv ldiv fdiv ddiv irem lrem frem drem "+
  "ineg lneg fneg dneg ishl lshl ishr lshr iushr lushr iand land ior lor "+
  "ixor lxor iinc i2l i2f i2d l2i l2f l2d f2i f2l f2d d2i d2l d2f i2b i2c "+
  "i2s lcmp fcmpl fcmpg dcmpl dcmpg ifeq ifne iflt ifge ifgt ifle if_icmpeq "+
  "if_icmpne if_icmplt if_icmpge if_icmpgt if_icmple if_acmpeq if_acmpne "+
  "goto jsr ret tableswitch lookupswitch ireturn lreturn freturn dreturn "+
  "areturn return getstatic putstatic getfield putfield invokevirtual "+
  "invokespecial invokestatic invokeinterface invokedynamic new newarray "+
  "anewarray arraylength athrow checkcast instanceof monitorenter "+
  "monitorexit wide multianewarray ifnull ifnonnull goto_w jsr_w ";
        for (int bc = 0; names.length() > 0; bc++) {
            int sp = names.indexOf(' ');
            BC_NAME[bc] = names.substring(0, sp);
            names = names.substring(sp+1);
        }
    }
    public static String byteName(int bc) {
        String iname;
        if (bc < BC_NAME.length && BC_NAME[bc] != null) {
            iname = BC_NAME[bc];
        } else if (isSelfLinkerOp(bc)) {
            int idx = (bc - _self_linker_op);
            boolean isSuper = (idx >= _self_linker_super_flag);
            if (isSuper)  idx -= _self_linker_super_flag;
            boolean isAload = (idx >= _self_linker_aload_flag);
            if (isAload)  idx -= _self_linker_aload_flag;
            int origBC = _first_linker_op + idx;
            assert(origBC >= _first_linker_op && origBC <= _last_linker_op);
            iname = BC_NAME[origBC];
            iname += (isSuper ? "_super" : "_this");
            if (isAload)  iname = "aload_0&" + iname;
            iname = "*"+iname;
        } else if (isInvokeInitOp(bc)) {
            int idx = (bc - _invokeinit_op);
            switch (idx) {
            case _invokeinit_self_option:
                iname = "*invokespecial_init_this"; break;
            case _invokeinit_super_option:
                iname = "*invokespecial_init_super"; break;
            default:
                assert(idx == _invokeinit_new_option);
                iname = "*invokespecial_init_new"; break;
            }
        } else {
            switch (bc) {
            case _ildc:  iname = "*ildc"; break;
            case _fldc:  iname = "*fldc"; break;
            case _ildc_w:  iname = "*ildc_w"; break;
            case _fldc_w:  iname = "*fldc_w"; break;
            case _dldc2_w:  iname = "*dldc2_w"; break;
            case _cldc:  iname = "*cldc"; break;
            case _cldc_w:  iname = "*cldc_w"; break;
            case _qldc:  iname = "*qldc"; break;
            case _qldc_w:  iname = "*qldc_w"; break;
            case _byte_escape:  iname = "*byte_escape"; break;
            case _ref_escape:  iname = "*ref_escape"; break;
            case _end_marker:  iname = "*end"; break;
            default:  iname = "*bc#"+bc; break;
            }
        }
        return iname;
    }
    private static int BW = 4;  // width of classification field
    private static void def(String fmt, int bc) {
        def(fmt, bc, bc);
    }
    private static void def(String fmt, int from_bc, int to_bc) {
        String[] fmts = { fmt, null };
        if (fmt.indexOf('w') > 0) {
            fmts[1] = fmt.substring(fmt.indexOf('w'));
            fmts[0] = fmt.substring(0, fmt.indexOf('w'));
        }
        for (int w = 0; w <= 1; w++) {
            fmt = fmts[w];
            if (fmt == null)  continue;
            int length = fmt.length();
            int index  = Math.max(0, fmt.indexOf('k'));
            int tag    = CONSTANT_None;
            int branch = Math.max(0, fmt.indexOf('o'));
            int slot   = Math.max(0, fmt.indexOf('l'));
            int con    = Math.max(0, fmt.indexOf('x'));
            if (index > 0 && index+1 < length) {
                switch (fmt.charAt(index+1)) {
                    case 'c': tag = CONSTANT_Class; break;
                    case 'k': tag = CONSTANT_LoadableValue; break;
                    case 'f': tag = CONSTANT_Fieldref; break;
                    case 'm': tag = CONSTANT_Methodref; break;
                    case 'i': tag = CONSTANT_InterfaceMethodref; break;
                    case 'y': tag = CONSTANT_InvokeDynamic; break;
                }
                assert(tag != CONSTANT_None);
            } else if (index > 0 && length == 2) {
                assert(from_bc == _ldc);
                tag = CONSTANT_LoadableValue;  // _ldc opcode only
            }
            for (int bc = from_bc; bc <= to_bc; bc++) {
                BC_FORMAT[w][bc] = fmt;
                assert(BC_LENGTH[w][bc] == -1);
                BC_LENGTH[w][bc] = (byte) length;
                BC_INDEX[w][bc]  = (byte) index;
                BC_TAG[w][bc]    = (byte) tag;
                assert(!(index == 0 && tag != CONSTANT_None));
                BC_BRANCH[w][bc] = (byte) branch;
                BC_SLOT[w][bc]   = (byte) slot;
                assert(branch == 0 || slot == 0);   // not both branch & local
                assert(branch == 0 || index == 0);  // not both branch & cp
                assert(slot == 0   || index == 0);  // not both local & cp
                BC_CON[w][bc]    = (byte) con;
            }
        }
    }

    public static void opcodeChecker(byte[] code, ConstantPool.Entry[] cpMap,
            Package.Version clsVersion) throws FormatException {
        Instruction i = at(code, 0);
        while (i != null) {
            int opcode = i.getBC();
            if (opcode < _nop || opcode > _jsr_w) {
                String message = "illegal opcode: " + opcode + " " + i;
                throw new FormatException(message);
            }
            ConstantPool.Entry e = i.getCPRef(cpMap);
            if (e != null) {
                byte tag = i.getCPTag();
                boolean match = e.tagMatches(tag);
                if (!match &&
                        (i.bc == _invokespecial || i.bc == _invokestatic) &&
                        e.tagMatches(CONSTANT_InterfaceMethodref) &&
                        clsVersion.greaterThan(Constants.JAVA7_MAX_CLASS_VERSION)) {
                    match = true;
                }
                if (!match) {
                    String message = "illegal reference, expected type="
                            + ConstantPool.tagName(tag) + ": "
                            + i.toString(cpMap);
                    throw new FormatException(message);
                }
            }
            i = i.next();
        }
    }
    static class FormatException extends IOException {
        private static final long serialVersionUID = 3175572275651367015L;

        FormatException(String message) {
            super(message);
        }
    }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java Instruction.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.