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.IOException;
2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.util.List;
2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.util.ArrayList;
2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.util.Iterator;
2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.util.Map;
2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/**
2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>Code_attribute</code>.
2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>To browse the <code>code</code> field of
3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * a <code>Code_attribute</code> structure,
3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * use <code>CodeIterator</code>.
3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see CodeIterator
3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */
3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpublic class CodeAttribute extends AttributeInfo implements Opcode {
3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * The name of this attribute <code>"Code"</code>.
3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static final String tag = "Code";
4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    // code[] is stored in AttributeInfo.info.
4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private int maxStack;
4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private int maxLocals;
4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private ExceptionTable exceptions;
4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private ArrayList attributes;
4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Constructs a <code>Code_attribute</code>.
5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param cp        constant pool table
5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param stack     <code>max_stack</code>
5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param locals    <code>max_locals</code>
5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param code      <code>code[]</code>
5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param etable    <code>exception_table[]</code>
5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public CodeAttribute(ConstPool cp, int stack, int locals, byte[] code,
5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                         ExceptionTable etable)
5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        super(cp, tag);
6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        maxStack = stack;
6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        maxLocals = locals;
6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        info = code;
6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        exceptions = etable;
6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        attributes = new ArrayList();
6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Constructs a copy of <code>Code_attribute</code>.
7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Specified class names are replaced during the copy.
7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param cp                constant pool table.
7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param src               source Code attribute.
7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param classnames        pairs of replaced and substituted
7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                          class names.
7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private CodeAttribute(ConstPool cp, CodeAttribute src, Map classnames)
7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws BadBytecode
7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        super(cp, tag);
8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        maxStack = src.getMaxStack();
8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        maxLocals = src.getMaxLocals();
8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        exceptions = src.getExceptionTable().copy(cp, classnames);
8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        attributes = new ArrayList();
8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        List src_attr = src.getAttributes();
8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int num = src_attr.size();
8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < num; ++i) {
8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            AttributeInfo ai = (AttributeInfo)src_attr.get(i);
9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            attributes.add(ai.copy(cp, classnames));
9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        info = src.copyCode(cp, classnames, exceptions, this);
9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    CodeAttribute(ConstPool cp, int name_id, DataInputStream in)
9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws IOException
9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        super(cp, name_id, (byte[])null);
10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int attr_len = in.readInt();
10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        maxStack = in.readUnsignedShort();
10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        maxLocals = in.readUnsignedShort();
10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int code_len = in.readInt();
10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        info = new byte[code_len];
10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        in.readFully(info);
10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        exceptions = new ExceptionTable(cp, in);
11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        attributes = new ArrayList();
11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int num = in.readUnsignedShort();
11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < num; ++i)
11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            attributes.add(AttributeInfo.read(cp, in));
11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Makes a copy.  Class names are replaced according to the
11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * given <code>Map</code> object.
12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param newCp     the constant pool table used by the new copy.
12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param classnames        pairs of replaced and substituted
12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                          class names.
12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @exception RuntimeCopyException  if a <code>BadBytecode</code>
12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                          exception is thrown, it is
12669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                          converted into
12769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                          <code>RuntimeCopyException</code>.
12869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
12969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @return <code>CodeAttribute</code> object.
13069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
13169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public AttributeInfo copy(ConstPool newCp, Map classnames)
13269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws RuntimeCopyException
13369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
13469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        try {
13569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return new CodeAttribute(newCp, this, classnames);
13669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
13769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch (BadBytecode e) {
13869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new RuntimeCopyException("bad bytecode. fatal?");
13969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
14069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
14169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
14269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
14369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * An exception that may be thrown by <code>copy()</code>
14469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * in <code>CodeAttribute</code>.
14569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
14669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static class RuntimeCopyException extends RuntimeException {
14769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
14869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Constructs an exception.
14969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
15069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public RuntimeCopyException(String s) {
15169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            super(s);
15269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
15369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
15469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
15569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
15669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the length of this <code>attribute_info</code>
15769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * structure.
15869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * The returned value is <code>attribute_length + 6</code>.
15969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
16069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int length() {
16169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return 18 + info.length + exceptions.size() * 8
16269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal               + AttributeInfo.getLength(attributes);
16369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
16469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
16569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    void write(DataOutputStream out) throws IOException {
16669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        out.writeShort(name);           // attribute_name_index
16769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        out.writeInt(length() - 6);     // attribute_length
16869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        out.writeShort(maxStack);       // max_stack
16969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        out.writeShort(maxLocals);      // max_locals
17069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        out.writeInt(info.length);      // code_length
17169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        out.write(info);                // code
17269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        exceptions.write(out);
17369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        out.writeShort(attributes.size());      // attributes_count
17469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        AttributeInfo.writeAll(attributes, out);        // attributes
17569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
17669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
17769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
17869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * This method is not available.
17969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
18069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @throws java.lang.UnsupportedOperationException  always thrown.
18169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
18269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public byte[] get() {
18369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throw new UnsupportedOperationException("CodeAttribute.get()");
18469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
18569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
18669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
18769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * This method is not available.
18869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
18969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @throws java.lang.UnsupportedOperationException  always thrown.
19069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
19169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void set(byte[] newinfo) {
19269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throw new UnsupportedOperationException("CodeAttribute.set()");
19369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
19469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
19569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    void renameClass(String oldname, String newname) {
19669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        AttributeInfo.renameClass(attributes, oldname, newname);
19769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
19869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
19969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    void renameClass(Map classnames) {
20069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        AttributeInfo.renameClass(attributes, classnames);
20169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
20269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
20369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    void getRefClasses(Map classnames) {
20469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        AttributeInfo.getRefClasses(attributes, classnames);
20569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
20669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
20769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
20869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the name of the class declaring the method including
20969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * this code attribute.
21069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
21169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public String getDeclaringClass() {
21269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ConstPool cp = getConstPool();
21369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return cp.getClassName();
21469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
21569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
21669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
21769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns <code>max_stack</code>.
21869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
21969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int getMaxStack() {
22069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return maxStack;
22169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
22269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
22369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
22469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Sets <code>max_stack</code>.
22569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
22669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void setMaxStack(int value) {
22769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        maxStack = value;
22869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
22969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
23069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
23169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Computes the maximum stack size and sets <code>max_stack</code>
23269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * to the computed size.
23369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
23469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @throws BadBytecode      if this method fails in computing.
23569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @return the newly computed value of <code>max_stack</code>
23669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
23769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int computeMaxStack() throws BadBytecode {
23869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        maxStack = new CodeAnalyzer(this).computeMaxStack();
23969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return maxStack;
24069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
24169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
24269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
24369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns <code>max_locals</code>.
24469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
24569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int getMaxLocals() {
24669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return maxLocals;
24769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
24869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
24969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
25069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Sets <code>max_locals</code>.
25169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
25269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void setMaxLocals(int value) {
25369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        maxLocals = value;
25469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
25569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
25669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
25769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns <code>code_length</code>.
25869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
25969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int getCodeLength() {
26069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return info.length;
26169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
26269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
26369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
26469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns <code>code[]</code>.
26569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
26669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public byte[] getCode() {
26769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return info;
26869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
26969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
27069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
27169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Sets <code>code[]</code>.
27269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
27369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    void setCode(byte[] newinfo) { super.set(newinfo); }
27469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
27569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
27669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Makes a new iterator for reading this code attribute.
27769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
27869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public CodeIterator iterator() {
27969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return new CodeIterator(this);
28069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
28169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
28269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
28369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns <code>exception_table[]</code>.
28469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
28569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public ExceptionTable getExceptionTable() { return exceptions; }
28669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
28769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
28869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns <code>attributes[]</code>.
28969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * It returns a list of <code>AttributeInfo</code>.
29069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * A new element can be added to the returned list
29169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * and an existing element can be removed from the list.
29269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
29369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see AttributeInfo
29469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
29569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public List getAttributes() { return attributes; }
29669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
29769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
29869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the attribute with the specified name.
29969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * If it is not found, this method returns null.
30069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
30169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param name      attribute name
30269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @return          an <code>AttributeInfo</code> object or null.
30369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
30469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public AttributeInfo getAttribute(String name) {
30569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return AttributeInfo.lookup(attributes, name);
30669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
30769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
30869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
30969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Adds a stack map table.  If another copy of stack map table
31069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * is already contained, the old one is removed.
31169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
31269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param smt       the stack map table added to this code attribute.
31369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  If it is null, a new stack map is not added.
31469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  Only the old stack map is removed.
31569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
31669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void setAttribute(StackMapTable smt) {
31769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        AttributeInfo.remove(attributes, StackMapTable.tag);
31869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (smt != null)
31969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            attributes.add(smt);
32069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
32169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
32269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
32369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Adds a stack map table for J2ME (CLDC).  If another copy of stack map table
32469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * is already contained, the old one is removed.
32569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
32669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param sm        the stack map table added to this code attribute.
32769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  If it is null, a new stack map is not added.
32869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  Only the old stack map is removed.
32969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @since 3.12
33069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
33169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void setAttribute(StackMap sm) {
33269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        AttributeInfo.remove(attributes, StackMap.tag);
33369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (sm != null)
33469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            attributes.add(sm);
33569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
33669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
33769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
33869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Copies code.
33969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
34069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private byte[] copyCode(ConstPool destCp, Map classnames,
34169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                            ExceptionTable etable, CodeAttribute destCa)
34269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws BadBytecode
34369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
34469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int len = getCodeLength();
34569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        byte[] newCode = new byte[len];
34669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        destCa.info = newCode;
34769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        LdcEntry ldc = copyCode(this.info, 0, len, this.getConstPool(),
34869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                newCode, destCp, classnames);
34969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return LdcEntry.doit(newCode, ldc, etable, destCa);
35069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
35169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
35269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private static LdcEntry copyCode(byte[] code, int beginPos, int endPos,
35369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                     ConstPool srcCp, byte[] newcode,
35469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                     ConstPool destCp, Map classnameMap)
35569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws BadBytecode
35669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
35769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int i2, index;
35869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        LdcEntry ldcEntry = null;
35969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
36069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = beginPos; i < endPos; i = i2) {
36169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            i2 = CodeIterator.nextOpcode(code, i);
36269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            byte c = code[i];
36369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            newcode[i] = c;
36469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            switch (c & 0xff) {
36569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            case LDC_W :
36669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            case LDC2_W :
36769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            case GETSTATIC :
36869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            case PUTSTATIC :
36969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            case GETFIELD :
37069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            case PUTFIELD :
37169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            case INVOKEVIRTUAL :
37269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            case INVOKESPECIAL :
37369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            case INVOKESTATIC :
37469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            case NEW :
37569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            case ANEWARRAY :
37669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            case CHECKCAST :
37769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            case INSTANCEOF :
37869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                copyConstPoolInfo(i + 1, code, srcCp, newcode, destCp,
37969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                  classnameMap);
38069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                break;
38169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            case LDC :
38269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                index = code[i + 1] & 0xff;
38369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                index = srcCp.copy(index, destCp, classnameMap);
38469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (index < 0x100)
38569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    newcode[i + 1] = (byte)index;
38669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                else {
38769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    newcode[i] = NOP;
38869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    newcode[i + 1] = NOP;
38969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    LdcEntry ldc = new LdcEntry();
39069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    ldc.where = i;
39169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    ldc.index = index;
39269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    ldc.next = ldcEntry;
39369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    ldcEntry = ldc;
39469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                }
39569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                break;
39669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            case INVOKEINTERFACE :
39769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                copyConstPoolInfo(i + 1, code, srcCp, newcode, destCp,
39869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                  classnameMap);
39969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                newcode[i + 3] = code[i + 3];
40069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                newcode[i + 4] = code[i + 4];
40169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                break;
40269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            case MULTIANEWARRAY :
40369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                copyConstPoolInfo(i + 1, code, srcCp, newcode, destCp,
40469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                  classnameMap);
40569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                newcode[i + 3] = code[i + 3];
40669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                break;
40769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            default :
40869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                while (++i < i2)
40969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    newcode[i] = code[i];
41069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
41169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                break;
41269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
41369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
41469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
41569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return ldcEntry;
41669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
41769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
41869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private static void copyConstPoolInfo(int i, byte[] code, ConstPool srcCp,
41969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                          byte[] newcode, ConstPool destCp,
42069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                          Map classnameMap) {
42169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int index = ((code[i] & 0xff) << 8) | (code[i + 1] & 0xff);
42269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        index = srcCp.copy(index, destCp, classnameMap);
42369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        newcode[i] = (byte)(index >> 8);
42469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        newcode[i + 1] = (byte)index;
42569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
42669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
42769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    static class LdcEntry {
42869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        LdcEntry next;
42969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int where;
43069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int index;
43169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
43269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        static byte[] doit(byte[] code, LdcEntry ldc, ExceptionTable etable,
43369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                           CodeAttribute ca)
43469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throws BadBytecode
43569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        {
43669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (ldc != null)
43769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                code = CodeIterator.changeLdcToLdcW(code, etable, ca, ldc);
43869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
43969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            /* The original code was the following:
44069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
44169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal               while (ldc != null) {
44269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                 int where = ldc.where;
44369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                 code = CodeIterator.insertGapCore0(code, where, 1, false, etable, ca);
44469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                 code[where] = (byte)Opcode.LDC_W;
44569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                 ByteArray.write16bit(ldc.index, code, where + 1);
44669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                 ldc = ldc.next;
44769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal               }
44869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
44969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal               But this code does not support a large method > 32KB.
45069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            */
45169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
45269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return code;
45369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
45469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
45569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
45669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
45769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Changes the index numbers of the local variables
45869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * to append a new parameter.
45969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * This method does not update <code>LocalVariableAttribute</code>,
46069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <code>StackMapTable</code>, or <code>StackMap</code>.
46169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * These attributes must be explicitly updated.
46269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
46369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param where         the index of the new parameter.
46469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param size         the type size of the new parameter (1 or 2).
46569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
46669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see LocalVariableAttribute#shiftIndex(int, int)
46769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see StackMapTable#insertLocal(int, int, int)
46869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see StackMap#insertLocal(int, int, int)
46969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
47069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void insertLocalVar(int where, int size) throws BadBytecode {
47169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CodeIterator ci = iterator();
47269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        while (ci.hasNext())
47369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            shiftIndex(ci, where, size);
47469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
47569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        setMaxLocals(getMaxLocals() + size);
47669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
47769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
47869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
47969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param lessThan      If the index of the local variable is
48069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                      less than this value, it does not change.
48169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                      Otherwise, the index is increased.
48269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param delta         the indexes of the local variables are
48369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                      increased by this value.
48469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
48569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private static void shiftIndex(CodeIterator ci, int lessThan, int delta) throws BadBytecode {
48669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int index = ci.next();
48769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int opcode = ci.byteAt(index);
48869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (opcode < ILOAD)
48969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return;
49069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else if (opcode < IASTORE) {
49169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (opcode < ILOAD_0) {
49269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                // iload, lload, fload, dload, aload
49369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                shiftIndex8(ci, index, opcode, lessThan, delta);
49469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
49569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else if (opcode < IALOAD) {
49669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                // iload_0, ..., aload_3
49769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                shiftIndex0(ci, index, opcode, lessThan, delta, ILOAD_0, ILOAD);
49869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
49969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else if (opcode < ISTORE)
50069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                return;
50169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else if (opcode < ISTORE_0) {
50269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                // istore, lstore, ...
50369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                shiftIndex8(ci, index, opcode, lessThan, delta);
50469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
50569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else {
50669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                // istore_0, ..., astore_3
50769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                shiftIndex0(ci, index, opcode, lessThan, delta, ISTORE_0, ISTORE);
50869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
50969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
51069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else if (opcode == IINC) {
51169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int var = ci.byteAt(index + 1);
51269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (var < lessThan)
51369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                return;
51469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
51569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            var += delta;
51669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (var < 0x100)
51769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                ci.writeByte(var, index + 1);
51869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else {
51969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                int plus = (byte)ci.byteAt(index + 2);
52069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                int pos = ci.insertExGap(3);
52169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                ci.writeByte(WIDE, pos - 3);
52269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                ci.writeByte(IINC, pos - 2);
52369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                ci.write16bit(var, pos - 1);
52469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                ci.write16bit(plus, pos + 1);
52569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
52669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
52769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else if (opcode == RET)
52869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            shiftIndex8(ci, index, opcode, lessThan, delta);
52969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else if (opcode == WIDE) {
53069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int var = ci.u16bitAt(index + 2);
53169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (var < lessThan)
53269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                return;
53369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
53469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            var += delta;
53569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            ci.write16bit(var, index + 2);
53669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
53769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
53869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
53969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private static void shiftIndex8(CodeIterator ci, int index, int opcode,
54069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                    int lessThan, int delta)
54169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         throws BadBytecode
54269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
54369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int var = ci.byteAt(index + 1);
54469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (var < lessThan)
54569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return;
54669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
54769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        var += delta;
54869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (var < 0x100)
54969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            ci.writeByte(var, index + 1);
55069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else {
55169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int pos = ci.insertExGap(2);
55269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            ci.writeByte(WIDE, pos - 2);
55369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            ci.writeByte(opcode, pos - 1);
55469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            ci.write16bit(var, pos);
55569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
55669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
55769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
55869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private static void shiftIndex0(CodeIterator ci, int index, int opcode,
55969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                    int lessThan, int delta,
56069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                    int opcode_i_0, int opcode_i)
56169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws BadBytecode
56269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
56369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int var = (opcode - opcode_i_0) % 4;
56469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (var < lessThan)
56569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return;
56669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
56769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        var += delta;
56869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (var < 4)
56969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            ci.writeByte(opcode + delta, index);
57069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else {
57169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            opcode = (opcode - opcode_i_0) / 4 + opcode_i;
57269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (var < 0x100) {
57369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                int pos = ci.insertExGap(1);
57469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                ci.writeByte(opcode, pos - 1);
57569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                ci.writeByte(var, pos);
57669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
57769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else {
57869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                int pos = ci.insertExGap(3);
57969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                ci.writeByte(WIDE, pos - 1);
58069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                ci.writeByte(opcode, pos);
58169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                ci.write16bit(var, pos + 1);
58269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
58369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
58469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
58569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal}
586