169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/*
269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Javassist, a Java-bytecode translator toolkit.
369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved.
469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The contents of this file are subject to the Mozilla Public License Version
669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1.1 (the "License"); you may not use this file except in compliance with
769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the License.  Alternatively, the contents of this file may be used under
869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the terms of the GNU Lesser General Public License Version 2.1 or later.
969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
1069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Software distributed under the License is distributed on an "AS IS" basis,
1169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
1269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * for the specific language governing rights and limitations under the
1369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * License.
1469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */
1569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
1669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpackage javassist.bytecode;
1769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
1869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.DataInputStream;
1969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.DataOutputStream;
2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.ByteArrayOutputStream;
2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.PrintWriter;
2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.IOException;
2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.util.Map;
2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.CannotCompileException;
2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/**
2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>stack_map</code> attribute.
2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>This is an entry in the attributes table of a Code attribute.
3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * It was introduced by J2SE 6 for the process of verification by
3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * typechecking.
3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see StackMap
3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @since 3.4
3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */
3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpublic class StackMapTable extends AttributeInfo {
3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * The name of this attribute <code>"StackMapTable"</code>.
3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static final String tag = "StackMapTable";
4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Constructs a <code>stack_map</code> attribute.
4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    StackMapTable(ConstPool cp, byte[] newInfo) {
4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        super(cp, tag, newInfo);
4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    StackMapTable(ConstPool cp, int name_id, DataInputStream in)
5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws IOException
5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        super(cp, name_id, in);
5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Makes a copy.
5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @exception RuntimeCopyException  if a <code>BadBytecode</code>
5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                          exception is thrown while copying,
6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                          it is converted into
6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                          <code>RuntimeCopyException</code>.
6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public AttributeInfo copy(ConstPool newCp, Map classnames)
6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws RuntimeCopyException
6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        try {
6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return new StackMapTable(newCp,
6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                            new Copier(this.constPool, info, newCp).doit());
7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch (BadBytecode e) {
7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new RuntimeCopyException("bad bytecode. fatal?");
7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * An exception that may be thrown by <code>copy()</code>
7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * in <code>StackMapTable</code>.
7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static class RuntimeCopyException extends RuntimeException {
8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Constructs an exception.
8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public RuntimeCopyException(String s) {
8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            super(s);
8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    void write(DataOutputStream out) throws IOException {
9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        super.write(out);
9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <code>Top_variable_info.tag</code>.
9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static final int TOP = 0;
9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <code>Integer_variable_info.tag</code>.
10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static final int INTEGER = 1;
10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <code>Float_variable_info.tag</code>.
10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static final int FLOAT = 2;
10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <code>Double_variable_info.tag</code>.
11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static final int DOUBLE = 3;
11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <code>Long_variable_info.tag</code>.
11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static final int LONG = 4;
11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <code>Null_variable_info.tag</code>.
12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static final int NULL = 5;
12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <code>UninitializedThis_variable_info.tag</code>.
12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
12669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static final int THIS = 6;
12769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
12869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
12969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <code>Object_variable_info.tag</code>.
13069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
13169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static final int OBJECT = 7;
13269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
13369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
13469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <code>Uninitialized_variable_info.tag</code>.
13569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
13669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static final int UNINIT = 8;
13769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
13869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
13969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * A code walker for a StackMapTable attribute.
14069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
14169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static class Walker {
14269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        byte[] info;
14369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int numOfEntries;
14469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
14569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
14669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Constructs a walker.
14769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *
14869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @param smt       the StackMapTable that this walker
14969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *                  walks around.
15069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
15169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public Walker(StackMapTable smt) {
15269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            this(smt.get());
15369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
15469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
15569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
15669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Constructs a walker.
15769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *
15869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @param data      the <code>info</code> field of the
15969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *                  <code>attribute_info</code> structure.
16069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *                  It can be obtained by <code>get()</code>
16169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *                  in the <code>AttributeInfo</code> class.
16269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
16369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public Walker(byte[] data) {
16469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            info = data;
16569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            numOfEntries = ByteArray.readU16bit(data, 0);
16669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
16769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
16869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
16969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Returns the number of the entries.
17069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
17169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public final int size() { return numOfEntries; }
17269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
17369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
17469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Visits each entry of the stack map frames.
17569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
17669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public void parse() throws BadBytecode {
17769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int n = numOfEntries;
17869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int pos = 2;
17969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            for (int i = 0; i < n; i++)
18069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                pos = stackMapFrames(pos, i);
18169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
18269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
18369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
18469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Invoked when the next entry of the stack map frames is visited.
18569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *
18669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @param pos       the position of the frame in the <code>info</code>
18769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *                  field of <code>attribute_info</code> structure.
18869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @param nth       the frame is the N-th
18969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *                  (0, 1st, 2nd, 3rd, 4th, ...) entry.
19069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @return          the position of the next frame.
19169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
19269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int stackMapFrames(int pos, int nth) throws BadBytecode {
19369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int type = info[pos] & 0xff;
19469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (type < 64) {
19569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                sameFrame(pos, type);
19669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                pos++;
19769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
19869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else if (type < 128)
19969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                pos = sameLocals(pos, type);
20069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else if (type < 247)
20169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                throw new BadBytecode("bad frame_type in StackMapTable");
20269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else if (type == 247)   // SAME_LOCALS_1_STACK_ITEM_EXTENDED
20369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                pos = sameLocals(pos, type);
20469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else if (type < 251) {
20569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                int offset = ByteArray.readU16bit(info, pos + 1);
20669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                chopFrame(pos, offset, 251 - type);
20769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                pos += 3;
20869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
20969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else if (type == 251) { // SAME_FRAME_EXTENDED
21069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                int offset = ByteArray.readU16bit(info, pos + 1);
21169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                sameFrame(pos, offset);
21269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                pos += 3;
21369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
21469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else if (type < 255)
21569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                pos = appendFrame(pos, type);
21669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else    // FULL_FRAME
21769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                pos = fullFrame(pos);
21869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
21969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return pos;
22069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
22169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
22269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
22369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Invoked if the visited frame is a <code>same_frame</code> or
22469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * a <code>same_frame_extended</code>.
22569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *
22669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @param pos       the position of this frame in the <code>info</code>
22769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *                  field of <code>attribute_info</code> structure.
22869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @param offsetDelta
22969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
23069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public void sameFrame(int pos, int offsetDelta) throws BadBytecode {}
23169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
23269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        private int sameLocals(int pos, int type) throws BadBytecode {
23369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int top = pos;
23469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int offset;
23569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (type < 128)
23669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                offset = type - 64;
23769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else { // type == 247
23869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                offset = ByteArray.readU16bit(info, pos + 1);
23969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                pos += 2;
24069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
24169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
24269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int tag = info[pos + 1] & 0xff;
24369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int data = 0;
24469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (tag == OBJECT || tag == UNINIT) {
24569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                data = ByteArray.readU16bit(info, pos + 2);
24669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                pos += 2;
24769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
24869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
24969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            sameLocals(top, offset, tag, data);
25069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return pos + 2;
25169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
25269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
25369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
25469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Invoked if the visited frame is a <code>same_locals_1_stack_item_frame</code>
25569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * or a <code>same_locals_1_stack_item_frame_extended</code>.
25669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *
25769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @param pos               the position.
25869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @param offsetDelta
25969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @param stackTag          <code>stack[0].tag</code>.
26069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @param stackData         <code>stack[0].cpool_index</code>
26169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *                          if the tag is <code>OBJECT</code>,
26269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *                          or <code>stack[0].offset</code>
26369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *                          if the tag is <code>UNINIT</code>.
26469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
26569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public void sameLocals(int pos, int offsetDelta, int stackTag, int stackData)
26669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throws BadBytecode {}
26769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
26869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
26969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Invoked if the visited frame is a <code>chop_frame</code>.
27069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *
27169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @param pos               the position.
27269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @param offsetDelta
27369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @param k                 the <cod>k</code> last locals are absent.
27469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
27569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public void chopFrame(int pos, int offsetDelta, int k) throws BadBytecode {}
27669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
27769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        private int appendFrame(int pos, int type) throws BadBytecode {
27869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int k = type - 251;
27969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int offset = ByteArray.readU16bit(info, pos + 1);
28069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int[] tags = new int[k];
28169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int[] data = new int[k];
28269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int p = pos + 3;
28369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            for (int i = 0; i < k; i++) {
28469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                int tag = info[p] & 0xff;
28569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                tags[i] = tag;
28669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (tag == OBJECT || tag == UNINIT) {
28769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    data[i] = ByteArray.readU16bit(info, p + 1);
28869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    p += 3;
28969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                }
29069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                else {
29169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    data[i] = 0;
29269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    p++;
29369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                }
29469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
29569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
29669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            appendFrame(pos, offset, tags, data);
29769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return p;
29869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
29969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
30069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
30169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Invoked if the visited frame is a <code>append_frame</code>.
30269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *
30369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @param pos           the position.
30469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @param offsetDelta
30569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @param tags          <code>locals[i].tag</code>.
30669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @param data          <code>locals[i].cpool_index</code>
30769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *                      or <cod>locals[i].offset</code>.
30869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
30969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public void appendFrame(int pos, int offsetDelta, int[] tags, int[] data)
31069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throws BadBytecode {}
31169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
31269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        private int fullFrame(int pos) throws BadBytecode {
31369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int offset = ByteArray.readU16bit(info, pos + 1);
31469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int numOfLocals = ByteArray.readU16bit(info, pos + 3);
31569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int[] localsTags = new int[numOfLocals];
31669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int[] localsData = new int[numOfLocals];
31769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int p = verifyTypeInfo(pos + 5, numOfLocals, localsTags, localsData);
31869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int numOfItems = ByteArray.readU16bit(info, p);
31969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int[] itemsTags = new int[numOfItems];
32069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int[] itemsData = new int[numOfItems];
32169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            p = verifyTypeInfo(p + 2, numOfItems, itemsTags, itemsData);
32269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            fullFrame(pos, offset, localsTags, localsData, itemsTags, itemsData);
32369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return p;
32469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
32569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
32669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
32769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Invoked if the visited frame is <code>full_frame</code>.
32869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *
32969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @param pos               the position.
33069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @param offsetDelta
33169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @param localTags         <code>locals[i].tag</code>
33269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @param localData         <code>locals[i].cpool_index</code>
33369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *                          or <code>locals[i].offset</code>
33469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @param stackTags         <code>stack[i].tag</code>
33569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @param stackData         <code>stack[i].cpool_index</code>
33669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *                          or <code>stack[i].offset</code>
33769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
33869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public void fullFrame(int pos, int offsetDelta, int[] localTags, int[] localData,
33969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                              int[] stackTags, int[] stackData)
34069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throws BadBytecode {}
34169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
34269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        private int verifyTypeInfo(int pos, int n, int[] tags, int[] data) {
34369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            for (int i = 0; i < n; i++) {
34469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                int tag = info[pos++] & 0xff;
34569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                tags[i] = tag;
34669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (tag == OBJECT || tag == UNINIT) {
34769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    data[i] = ByteArray.readU16bit(info, pos);
34869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    pos += 2;
34969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                }
35069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
35169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
35269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return pos;
35369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
35469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
35569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
35669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    static class SimpleCopy extends Walker {
35769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        private Writer writer;
35869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
35969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public SimpleCopy(byte[] data) {
36069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            super(data);
36169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            writer = new Writer(data.length);
36269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
36369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
36469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public byte[] doit() throws BadBytecode {
36569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            parse();
36669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return writer.toByteArray();
36769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
36869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
36969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public void sameFrame(int pos, int offsetDelta) {
37069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            writer.sameFrame(offsetDelta);
37169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
37269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
37369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public void sameLocals(int pos, int offsetDelta, int stackTag, int stackData) {
37469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            writer.sameLocals(offsetDelta, stackTag, copyData(stackTag, stackData));
37569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
37669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
37769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public void chopFrame(int pos, int offsetDelta, int k) {
37869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            writer.chopFrame(offsetDelta, k);
37969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
38069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
38169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public void appendFrame(int pos, int offsetDelta, int[] tags, int[] data) {
38269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            writer.appendFrame(offsetDelta, tags, copyData(tags, data));
38369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
38469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
38569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public void fullFrame(int pos, int offsetDelta, int[] localTags, int[] localData,
38669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                              int[] stackTags, int[] stackData) {
38769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            writer.fullFrame(offsetDelta, localTags, copyData(localTags, localData),
38869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                             stackTags, copyData(stackTags, stackData));
38969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
39069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
39169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        protected int copyData(int tag, int data) {
39269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return data;
39369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
39469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
39569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        protected int[] copyData(int[] tags, int[] data) {
39669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return data;
39769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
39869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
39969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
40069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    static class Copier extends SimpleCopy {
40169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        private ConstPool srcPool, destPool;
40269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
40369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public Copier(ConstPool src, byte[] data, ConstPool dest) {
40469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            super(data);
40569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            srcPool = src;
40669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            destPool = dest;
40769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
40869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
40969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        protected int copyData(int tag, int data) {
41069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (tag == OBJECT)
41169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                return srcPool.copy(data, destPool, null);
41269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else
41369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                return data;
41469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
41569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
41669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        protected int[] copyData(int[] tags, int[] data) {
41769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int[] newData = new int[data.length];
41869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            for (int i = 0; i < data.length; i++)
41969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (tags[i] == OBJECT)
42069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    newData[i] = srcPool.copy(data[i], destPool, null);
42169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                else
42269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    newData[i] = data[i];
42369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
42469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return newData;
42569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
42669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
42769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
42869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
42969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Updates this stack map table when a new local variable is inserted
43069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * for a new parameter.
43169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
43269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param index          the index of the added local variable.
43369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param tag            the type tag of that local variable.
43469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param classInfo      the index of the <code>CONSTANT_Class_info</code> structure
43569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                       in a constant pool table.  This should be zero unless the tag
43669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                       is <code>ITEM_Object</code>.
43769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
43869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see javassist.CtBehavior#addParameter(javassist.CtClass)
43969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see #typeTagOf(char)
44069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see ConstPool
44169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
44269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void insertLocal(int index, int tag, int classInfo)
44369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws BadBytecode
44469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
44569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        byte[] data = new InsertLocal(this.get(), index, tag, classInfo).doit();
44669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        this.set(data);
44769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
44869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
44969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
45069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the tag of the type specified by the
45169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * descriptor.  This method returns <code>INTEGER</code>
45269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * unless the descriptor is either D (double), F (float),
45369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * J (long), L (class type), or [ (array).
45469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
45569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param descriptor        the type descriptor.
45669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see Descriptor
45769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
45869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static int typeTagOf(char descriptor) {
45969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        switch (descriptor) {
46069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case 'D' :
46169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return DOUBLE;
46269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case 'F' :
46369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return FLOAT;
46469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case 'J' :
46569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return LONG;
46669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case 'L' :
46769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case '[' :
46869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return OBJECT;
46969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        // case 'V' :
47069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        default :
47169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return INTEGER;
47269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
47369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
47469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
47569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /* This implementation assumes that a local variable initially
47669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * holding a parameter value is never changed to be a different
47769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * type.
47869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
47969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
48069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    static class InsertLocal extends SimpleCopy {
48169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        private int varIndex;
48269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        private int varTag, varData;
48369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
48469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public InsertLocal(byte[] data, int varIndex, int varTag, int varData) {
48569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            super(data);
48669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            this.varIndex = varIndex;
48769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            this.varTag = varTag;
48869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            this.varData = varData;
48969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
49069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
49169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public void fullFrame(int pos, int offsetDelta, int[] localTags, int[] localData,
49269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                              int[] stackTags, int[] stackData) {
49369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int len = localTags.length;
49469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (len < varIndex) {
49569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                super.fullFrame(pos, offsetDelta, localTags, localData, stackTags, stackData);
49669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                return;
49769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
49869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
49969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int typeSize = (varTag == LONG || varTag == DOUBLE) ? 2 : 1;
50069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int[] localTags2 = new int[len + typeSize];
50169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int[] localData2 = new int[len + typeSize];
50269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int index = varIndex;
50369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int j = 0;
50469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            for (int i = 0; i < len; i++) {
50569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (j == index)
50669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    j += typeSize;
50769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
50869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                localTags2[j] = localTags[i];
50969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                localData2[j++] = localData[i];
51069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
51169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
51269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            localTags2[index] = varTag;
51369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            localData2[index] = varData;
51469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (typeSize > 1) {
51569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                localTags2[index + 1] = TOP;
51669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                localData2[index + 1] = 0;
51769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
51869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
51969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            super.fullFrame(pos, offsetDelta, localTags2, localData2, stackTags, stackData);
52069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
52169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
52269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
52369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
52469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * A writer of stack map tables.
52569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
52669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static class Writer {
52769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ByteArrayOutputStream output;
52869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int numOfEntries;
52969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
53069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
53169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Constructs a writer.
53269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @param size      the initial buffer size.
53369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
53469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public Writer(int size) {
53569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            output = new ByteArrayOutputStream(size);
53669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            numOfEntries = 0;
53769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            output.write(0);        // u2 number_of_entries
53869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            output.write(0);
53969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
54069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
54169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
54269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Returns the stack map table written out.
54369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
54469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public byte[] toByteArray() {
54569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            byte[] b = output.toByteArray();
54669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            ByteArray.write16bit(numOfEntries, b, 0);
54769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return b;
54869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
54969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
55069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
55169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Constructs and a return a stack map table containing
55269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * the written stack map entries.
55369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *
55469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @param cp        the constant pool used to write
55569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *                  the stack map entries.
55669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
55769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public StackMapTable toStackMapTable(ConstPool cp) {
55869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return new StackMapTable(cp, toByteArray());
55969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
56069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
56169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
56269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Writes a <code>same_frame</code> or a <code>same_frame_extended</code>.
56369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
56469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public void sameFrame(int offsetDelta) {
56569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            numOfEntries++;
56669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (offsetDelta < 64)
56769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                output.write(offsetDelta);
56869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else {
56969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                output.write(251);  // SAME_FRAME_EXTENDED
57069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                write16(offsetDelta);
57169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
57269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
57369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
57469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
57569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Writes a <code>same_locals_1_stack_item</code>
57669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * or a <code>same_locals_1_stack_item_extended</code>.
57769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *
57869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @param tag           <code>stack[0].tag</code>.
57969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @param data          <code>stack[0].cpool_index</code>
58069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *                      if the tag is <code>OBJECT</code>,
58169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *                      or <cod>stack[0].offset</code>
58269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *                      if the tag is <code>UNINIT</code>.
58369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *                      Otherwise, this parameter is not used.
58469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
58569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public void sameLocals(int offsetDelta, int tag, int data) {
58669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            numOfEntries++;
58769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (offsetDelta < 64)
58869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                output.write(offsetDelta + 64);
58969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else {
59069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                output.write(247);  // SAME_LOCALS_1_STACK_ITEM_EXTENDED
59169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                write16(offsetDelta);
59269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
59369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
59469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            writeTypeInfo(tag, data);
59569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
59669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
59769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
59869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Writes a <code>chop_frame</code>.
59969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *
60069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @param k                 the number of absent locals. 1, 2, or 3.
60169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
60269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public void chopFrame(int offsetDelta, int k) {
60369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            numOfEntries++;
60469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            output.write(251 - k);
60569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            write16(offsetDelta);
60669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
60769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
60869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
60969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Writes a <code>append_frame</code>.  The number of the appended
61069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * locals is specified by the length of <code>tags</code>.
61169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *
61269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @param tags           <code>locals[].tag</code>.
61369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *                      The length of this array must be
61469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *                      either 1, 2, or 3.
61569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @param data          <code>locals[].cpool_index</code>
61669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *                      if the tag is <code>OBJECT</code>,
61769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *                      or <cod>locals[].offset</code>
61869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *                      if the tag is <code>UNINIT</code>.
61969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *                      Otherwise, this parameter is not used.
62069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
62169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public void appendFrame(int offsetDelta, int[] tags, int[] data) {
62269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            numOfEntries++;
62369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int k = tags.length;    // k is 1, 2, or 3
62469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            output.write(k + 251);
62569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            write16(offsetDelta);
62669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            for (int i = 0; i < k; i++)
62769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                writeTypeInfo(tags[i], data[i]);
62869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
62969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
63069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
63169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Writes a <code>full_frame</code>.
63269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * <code>number_of_locals</code> and <code>number_of_stack_items</code>
63369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * are specified by the the length of <code>localTags</code> and
63469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * <code>stackTags</code>.
63569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *
63669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @param localTags     <code>locals[].tag</code>.
63769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @param localData     <code>locals[].cpool_index</code>
63869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *                      if the tag is <code>OBJECT</code>,
63969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *                      or <cod>locals[].offset</code>
64069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *                      if the tag is <code>UNINIT</code>.
64169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *                      Otherwise, this parameter is not used.
64269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @param stackTags     <code>stack[].tag</code>.
64369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @param stackData     <code>stack[].cpool_index</code>
64469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *                      if the tag is <code>OBJECT</code>,
64569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *                      or <cod>stack[].offset</code>
64669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *                      if the tag is <code>UNINIT</code>.
64769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *                      Otherwise, this parameter is not used.
64869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
64969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public void fullFrame(int offsetDelta, int[] localTags, int[] localData,
65069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                              int[] stackTags, int[] stackData) {
65169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            numOfEntries++;
65269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            output.write(255);      // FULL_FRAME
65369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            write16(offsetDelta);
65469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int n = localTags.length;
65569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            write16(n);
65669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            for (int i = 0; i < n; i++)
65769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                writeTypeInfo(localTags[i], localData[i]);
65869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
65969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            n = stackTags.length;
66069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            write16(n);
66169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            for (int i = 0; i < n; i++)
66269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                writeTypeInfo(stackTags[i], stackData[i]);
66369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
66469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
66569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        private void writeTypeInfo(int tag, int data) {
66669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            output.write(tag);
66769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (tag == OBJECT || tag == UNINIT)
66869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                write16(data);
66969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
67069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
67169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        private void write16(int value) {
67269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            output.write((value >>> 8) & 0xff);
67369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            output.write(value & 0xff);
67469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
67569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
67669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
67769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
67869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Prints the stack table map.
67969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
68069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void println(PrintWriter w) {
68169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Printer.print(this, w);
68269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
68369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
68469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
68569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Prints the stack table map.
68669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
68769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param ps    a print stream such as <code>System.out</code>.
68869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
68969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void println(java.io.PrintStream ps) {
69069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Printer.print(this, new java.io.PrintWriter(ps, true));
69169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
69269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
69369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    static class Printer extends Walker {
69469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        private PrintWriter writer;
69569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        private int offset;
69669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
69769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
69869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Prints the stack table map.
69969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
70069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public static void print(StackMapTable smt, PrintWriter writer) {
70169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            try {
70269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                new Printer(smt.get(), writer).parse();
70369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
70469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            catch (BadBytecode e) {
70569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                writer.println(e.getMessage());
70669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
70769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
70869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
70969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Printer(byte[] data, PrintWriter pw) {
71069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            super(data);
71169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            writer = pw;
71269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            offset = -1;
71369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
71469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
71569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public void sameFrame(int pos, int offsetDelta) {
71669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            offset += offsetDelta + 1;
71769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            writer.println(offset + " same frame: " + offsetDelta);
71869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
71969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
72069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public void sameLocals(int pos, int offsetDelta, int stackTag, int stackData) {
72169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            offset += offsetDelta + 1;
72269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            writer.println(offset + " same locals: " + offsetDelta);
72369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            printTypeInfo(stackTag, stackData);
72469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
72569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
72669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public void chopFrame(int pos, int offsetDelta, int k) {
72769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            offset += offsetDelta + 1;
72869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            writer.println(offset + " chop frame: " + offsetDelta + ",    " + k + " last locals");
72969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
73069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
73169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public void appendFrame(int pos, int offsetDelta, int[] tags, int[] data) {
73269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            offset += offsetDelta + 1;
73369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            writer.println(offset + " append frame: " + offsetDelta);
73469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            for (int i = 0; i < tags.length; i++)
73569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                printTypeInfo(tags[i], data[i]);
73669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
73769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
73869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public void fullFrame(int pos, int offsetDelta, int[] localTags, int[] localData,
73969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                              int[] stackTags, int[] stackData) {
74069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            offset += offsetDelta + 1;
74169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            writer.println(offset + " full frame: " + offsetDelta);
74269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            writer.println("[locals]");
74369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            for (int i = 0; i < localTags.length; i++)
74469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                printTypeInfo(localTags[i], localData[i]);
74569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
74669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            writer.println("[stack]");
74769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            for (int i = 0; i < stackTags.length; i++)
74869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                printTypeInfo(stackTags[i], stackData[i]);
74969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
75069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
75169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        private void printTypeInfo(int tag, int data) {
75269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            String msg = null;
75369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            switch (tag) {
75469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            case TOP :
75569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                msg = "top";
75669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                break;
75769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            case INTEGER :
75869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                msg = "integer";
75969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                break;
76069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            case FLOAT :
76169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                msg = "float";
76269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                break;
76369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            case DOUBLE :
76469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                msg = "double";
76569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                break;
76669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            case LONG :
76769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                msg = "long";
76869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                break;
76969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            case NULL :
77069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                msg = "null";
77169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                break;
77269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            case THIS :
77369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                msg = "this";
77469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                break;
77569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            case OBJECT :
77669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                msg = "object (cpool_index " + data + ")";
77769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                break;
77869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            case UNINIT :
77969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                msg = "uninitialized (offset " + data + ")";
78069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                break;
78169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
78269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
78369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            writer.print("    ");
78469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            writer.println(msg);
78569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
78669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
78769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
78869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    void shiftPc(int where, int gapSize, boolean exclusive)
78969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws BadBytecode
79069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
79169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        new Shifter(this, where, gapSize, exclusive).doit();
79269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
79369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
79469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    static class Shifter extends Walker {
79569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        private StackMapTable stackMap;
79669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        private int where, gap;
79769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        private int position;
79869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        private byte[] updatedInfo;
79969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        private boolean exclusive;
80069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
80169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public Shifter(StackMapTable smt, int where, int gap, boolean exclusive) {
80269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            super(smt);
80369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            stackMap = smt;
80469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            this.where = where;
80569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            this.gap = gap;
80669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            this.position = 0;
80769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            this.updatedInfo = null;
80869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            this.exclusive = exclusive;
80969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
81069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
81169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public void doit() throws BadBytecode {
81269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            parse();
81369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (updatedInfo != null)
81469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                stackMap.set(updatedInfo);
81569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
81669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
81769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public void sameFrame(int pos, int offsetDelta) {
81869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            update(pos, offsetDelta, 0, 251);
81969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
82069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
82169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public void sameLocals(int pos, int offsetDelta, int stackTag, int stackData) {
82269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            update(pos, offsetDelta, 64, 247);
82369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
82469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
82569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        private void update(int pos, int offsetDelta, int base, int entry) {
82669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int oldPos = position;
82769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            position = oldPos + offsetDelta + (oldPos == 0 ? 0 : 1);
82869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            boolean match;
82969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (exclusive)
83069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                match = oldPos < where  && where <= position;
83169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else
83269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                match = oldPos <= where  && where < position;
83369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
83469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (match) {
83569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                int newDelta = offsetDelta + gap;
83669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                position += gap;
83769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (newDelta < 64)
83869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    info[pos] = (byte)(newDelta + base);
83969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                else if (offsetDelta < 64) {
84069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    byte[] newinfo = insertGap(info, pos, 2);
84169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    newinfo[pos] = (byte)entry;
84269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    ByteArray.write16bit(newDelta, newinfo, pos + 1);
84369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    updatedInfo = newinfo;
84469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                }
84569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                else
84669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    ByteArray.write16bit(newDelta, info, pos + 1);
84769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
84869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
84969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
85069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        private static byte[] insertGap(byte[] info, int where, int gap) {
85169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int len = info.length;
85269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            byte[] newinfo = new byte[len + gap];
85369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            for (int i = 0; i < len; i++)
85469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                newinfo[i + (i < where ? 0 : gap)] = info[i];
85569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
85669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return newinfo;
85769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
85869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
85969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public void chopFrame(int pos, int offsetDelta, int k) {
86069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            update(pos, offsetDelta);
86169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
86269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
86369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public void appendFrame(int pos, int offsetDelta, int[] tags, int[] data) {
86469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            update(pos, offsetDelta);
86569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
86669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
86769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public void fullFrame(int pos, int offsetDelta, int[] localTags, int[] localData,
86869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                              int[] stackTags, int[] stackData) {
86969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            update(pos, offsetDelta);
87069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
87169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
87269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        private void update(int pos, int offsetDelta) {
87369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int oldPos = position;
87469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            position = oldPos + offsetDelta + (oldPos == 0 ? 0 : 1);
87569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            boolean match;
87669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (exclusive)
87769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                match = oldPos < where  && where <= position;
87869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else
87969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                match = oldPos <= where  && where < position;
88069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
88169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (match) {
88269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                int newDelta = offsetDelta + gap;
88369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                ByteArray.write16bit(newDelta, info, pos + 1);
88469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                position += gap;
88569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
88669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
88769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
88869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
88969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
89069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Undocumented method.  Do not use; internal-use only.
89169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
89269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <p>This method is for javassist.convert.TransformNew.
89369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * It is called to update the stack map table when
89469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * the NEW opcode (and the following DUP) is removed.
89569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
89669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param where     the position of the removed NEW opcode.
89769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
89869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     public void removeNew(int where) throws CannotCompileException {
89969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        try {
90069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            byte[] data = new NewRemover(this.get(), where).doit();
90169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            this.set(data);
90269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
90369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch (BadBytecode e) {
90469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new CannotCompileException("bad stack map table", e);
90569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
90669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
90769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
90869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    static class NewRemover extends SimpleCopy {
90969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int posOfNew;
91069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
91169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public NewRemover(byte[] data, int pos) {
91269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            super(data);
91369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            posOfNew = pos;
91469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
91569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
91669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public void sameLocals(int pos, int offsetDelta, int stackTag, int stackData) {
91769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (stackTag == UNINIT && stackData == posOfNew)
91869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                super.sameFrame(pos, offsetDelta);
91969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else
92069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                super.sameLocals(pos, offsetDelta, stackTag, stackData);
92169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
92269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
92369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public void fullFrame(int pos, int offsetDelta, int[] localTags, int[] localData,
92469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                              int[] stackTags, int[] stackData) {
92569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int n = stackTags.length - 1;
92669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            for (int i = 0; i < n; i++)
92769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (stackTags[i] == UNINIT && stackData[i] == posOfNew
92869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    && stackTags[i + 1] == UNINIT && stackData[i + 1] == posOfNew) {
92969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    n++;
93069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    int[] stackTags2 = new int[n - 2];
93169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    int[] stackData2 = new int[n - 2];
93269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    int k = 0;
93369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    for (int j = 0; j < n; j++)
93469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        if (j == i)
93569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                            j++;
93669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        else {
93769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                            stackTags2[k] = stackTags[j];
93869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                            stackData2[k++] = stackData[j];
93969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        }
94069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
94169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    stackTags = stackTags2;
94269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    stackData = stackData2;
94369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    break;
94469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                }
94569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
94669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            super.fullFrame(pos, offsetDelta, localTags, localData, stackTags, stackData);
94769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
94869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
94969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal}
950