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 Sigal package javassist.bytecode.stackmap;
1769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
1869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.*;
1969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpublic class Liveness {
2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    protected static final byte UNKNOWN = 0;
2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    protected static final byte READ = 1;
2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    protected static final byte UPDATED = 2;
2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    protected byte[] localsUsage;
2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * If true, all the arguments become alive within the whole method body.
2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * To correctly compute a stack map table, all the arguments must
3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * be alive (localsUsage[?] must be READ) at least in the first block.
3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static boolean useArgs = true;
3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void compute(CodeIterator ci, TypedBlock[] blocks, int maxLocals,
3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        TypeData[] args)
3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws BadBytecode
3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        computeUsage(ci, blocks, maxLocals);
3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (useArgs)
4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            useAllArgs(blocks, args);
4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        computeLiveness1(blocks[0]);
4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        while (hasChanged(blocks))
4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            computeLiveness2(blocks[0]);
4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private void useAllArgs(TypedBlock[] blocks, TypeData[] args) {
4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int k = 0; k < blocks.length; k++) {
4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            byte[] usage = blocks[k].localsUsage;
5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            for (int i = 0; i < args.length; i++)
5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (args[i] != TypeTag.TOP)
5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    usage[i] = READ;
5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    static final int NOT_YET = 0;
5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    static final int CHANGED_LAST = 1;
5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    static final int DONE = 2;
5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    static final int CHANGED_NOW = 3;
6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private void computeLiveness1(TypedBlock tb) {
6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (tb.updating) {
6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            // a loop was detected.
6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            computeLiveness1u(tb);
6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return;
6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (tb.inputs != null)
6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return;
7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        tb.updating = true;
7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        byte[] usage = tb.localsUsage;
7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int n = usage.length;
7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        boolean[] in = new boolean[n];
7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < n; i++)
7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            in[i] = usage[i] == READ;
7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        BasicBlock.Catch handlers = tb.toCatch;
7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        while (handlers != null) {
8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            TypedBlock h = (TypedBlock)handlers.body;
8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            computeLiveness1(h);
8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            for (int k = 0; k < n; k++)
8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (h.inputs[k])
8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    in[k] = true;
8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            handlers = handlers.next;
8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (tb.exit != null) {
9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            for (int i = 0; i < tb.exit.length; i++) {
9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                TypedBlock e = (TypedBlock)tb.exit[i];
9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                computeLiveness1(e);
9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                for (int k = 0; k < n; k++)
9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    if (!in[k])
9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        in[k] = usage[k] == UNKNOWN && e.inputs[k];
9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        tb.updating = false;
10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (tb.inputs == null) {
10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            tb.inputs = in;
10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            tb.status = DONE;
10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else {
10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            for (int i = 0; i < n; i++)
10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (in[i] && !tb.inputs[i]) {
10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    tb.inputs[i] = true;
10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    tb.status = CHANGED_NOW;
10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                }
11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private void computeLiveness1u(TypedBlock tb) {
11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (tb.inputs == null) {
11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            byte[] usage = tb.localsUsage;
11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int n = usage.length;
11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            boolean[] in = new boolean[n];
11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            for (int i = 0; i < n; i++)
11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                in[i] = usage[i] == READ;
12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            tb.inputs = in;
12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            tb.status = DONE;
12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
12669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private void computeLiveness2(TypedBlock tb) {
12769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (tb.updating || tb.status >= DONE)
12869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return;
12969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
13069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        tb.updating = true;
13169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (tb.exit == null)
13269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            tb.status = DONE;
13369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else {
13469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            boolean changed = false;
13569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            for (int i = 0; i < tb.exit.length; i++) {
13669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                TypedBlock e = (TypedBlock)tb.exit[i];
13769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                computeLiveness2(e);
13869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (e.status != DONE)
13969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    changed = true;
14069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
14169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
14269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (changed) {
14369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                changed = false;
14469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                byte[] usage = tb.localsUsage;
14569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                int n = usage.length;
14669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                for (int i = 0; i < tb.exit.length; i++) {
14769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    TypedBlock e = (TypedBlock)tb.exit[i];
14869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    if (e.status != DONE)
14969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        for (int k = 0; k < n; k++)
15069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                            if (!tb.inputs[k]) {
15169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                if (usage[k] == UNKNOWN && e.inputs[k]) {
15269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                    tb.inputs[k] = true;
15369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                    changed = true;
15469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                }
15569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                            }
15669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                }
15769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
15869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                tb.status = changed ? CHANGED_NOW : DONE;
15969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
16069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else
16169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                tb.status = DONE;
16269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
16369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
16469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (computeLiveness2except(tb))
16569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            tb.status = CHANGED_NOW;
16669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
16769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        tb.updating = false;
16869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
16969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
17069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private boolean computeLiveness2except(TypedBlock tb) {
17169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        BasicBlock.Catch handlers = tb.toCatch;
17269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        boolean changed = false;
17369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        while (handlers != null) {
17469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            TypedBlock h = (TypedBlock)handlers.body;
17569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            computeLiveness2(h);
17669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (h.status != DONE) {
17769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                boolean[] in = tb.inputs;
17869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                int n = in.length;
17969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                for (int k = 0; k < n; k++)
18069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    if (!in[k] && h.inputs[k]) {
18169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        in[k] = true;
18269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        changed = true;
18369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    }
18469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
18569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
18669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            handlers = handlers.next;
18769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
18869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
18969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return changed;
19069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
19169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
19269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private boolean hasChanged(TypedBlock[] blocks) {
19369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int n = blocks.length;
19469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        boolean changed = false;
19569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < n; i++) {
19669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            TypedBlock tb = blocks[i];
19769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (tb.status == CHANGED_NOW) {
19869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                tb.status = CHANGED_LAST;
19969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                changed = true;
20069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
20169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else
20269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                tb.status = NOT_YET;
20369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
20469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
20569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return changed;
20669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
20769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
20869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private void computeUsage(CodeIterator ci, TypedBlock[] blocks, int maxLocals)
20969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws BadBytecode
21069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
21169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int n = blocks.length;
21269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < n; i++) {
21369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            TypedBlock tb = blocks[i];
21469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            localsUsage = tb.localsUsage = new byte[maxLocals];
21569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int pos = tb.position;
21669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            analyze(ci, pos, pos + tb.length);
21769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            localsUsage = null;
21869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
21969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
22069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
22169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    protected final void readLocal(int reg) {
22269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (localsUsage[reg] == UNKNOWN)
22369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            localsUsage[reg] = READ;
22469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
22569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
22669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    protected final void writeLocal(int reg) {
22769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (localsUsage[reg] == UNKNOWN)
22869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            localsUsage[reg] = UPDATED;
22969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
23069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
23169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    protected void analyze(CodeIterator ci, int begin, int end)
23269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws BadBytecode
23369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
23469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ci.begin();
23569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ci.move(begin);
23669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        while (ci.hasNext()) {
23769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int index = ci.next();
23869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (index >= end)
23969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                break;
24069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
24169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int op = ci.byteAt(index);
24269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (op < 96)
24369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (op < 54)
24469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    doOpcode0_53(ci, index, op);
24569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                else
24669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    doOpcode54_95(ci, index, op);
24769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else
24869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (op == Opcode.IINC) {
24969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    // this does not call writeLocal().
25069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    readLocal(ci.byteAt(index + 1));
25169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                }
25269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                else if (op == Opcode.WIDE)
25369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    doWIDE(ci, index);
25469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
25569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
25669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
25769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private void doOpcode0_53(CodeIterator ci, int pos, int op) {
25869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        switch (op) {
25969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.ILOAD :
26069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.LLOAD :
26169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.FLOAD :
26269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.DLOAD :
26369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.ALOAD :
26469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            readLocal(ci.byteAt(pos + 1));
26569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            break;
26669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.ILOAD_0 :
26769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.ILOAD_1 :
26869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.ILOAD_2 :
26969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.ILOAD_3 :
27069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            readLocal(op - Opcode.ILOAD_0);
27169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            break;
27269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.LLOAD_0 :
27369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.LLOAD_1 :
27469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.LLOAD_2 :
27569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.LLOAD_3 :
27669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            readLocal(op - Opcode.LLOAD_0);
27769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            break;
27869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.FLOAD_0 :
27969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.FLOAD_1 :
28069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.FLOAD_2 :
28169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.FLOAD_3 :
28269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            readLocal(op - Opcode.FLOAD_0);
28369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            break;
28469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.DLOAD_0 :
28569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.DLOAD_1 :
28669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.DLOAD_2 :
28769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.DLOAD_3 :
28869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            readLocal(op - Opcode.DLOAD_0);
28969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            break;
29069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.ALOAD_0 :
29169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.ALOAD_1 :
29269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.ALOAD_2 :
29369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.ALOAD_3 :
29469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            readLocal(op - Opcode.ALOAD_0);
29569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            break;
29669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
29769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
29869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
29969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private void doOpcode54_95(CodeIterator ci, int pos, int op) {
30069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        switch (op) {
30169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.ISTORE :
30269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.LSTORE :
30369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.FSTORE :
30469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.DSTORE :
30569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.ASTORE :
30669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            writeLocal(ci.byteAt(pos + 1));
30769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            break;
30869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.ISTORE_0 :
30969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.ISTORE_1 :
31069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.ISTORE_2 :
31169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.ISTORE_3 :
31269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            writeLocal(op - Opcode.ISTORE_0);
31369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            break;
31469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.LSTORE_0 :
31569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.LSTORE_1 :
31669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.LSTORE_2 :
31769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.LSTORE_3 :
31869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            writeLocal(op - Opcode.LSTORE_0);
31969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            break;
32069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.FSTORE_0 :
32169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.FSTORE_1 :
32269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.FSTORE_2 :
32369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.FSTORE_3 :
32469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            writeLocal(op - Opcode.FSTORE_0);
32569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            break;
32669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.DSTORE_0 :
32769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.DSTORE_1 :
32869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.DSTORE_2 :
32969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.DSTORE_3 :
33069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            writeLocal(op - Opcode.DSTORE_0);
33169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            break;
33269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.ASTORE_0 :
33369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.ASTORE_1 :
33469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.ASTORE_2 :
33569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.ASTORE_3 :
33669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            writeLocal(op - Opcode.ASTORE_0);
33769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            break;
33869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
33969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
34069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
34169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private void doWIDE(CodeIterator ci, int pos) throws BadBytecode {
34269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int op = ci.byteAt(pos + 1);
34369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int var = ci.u16bitAt(pos + 2);
34469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        switch (op) {
34569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.ILOAD :
34669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.LLOAD :
34769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.FLOAD :
34869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.DLOAD :
34969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.ALOAD :
35069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            readLocal(var);
35169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            break;
35269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.ISTORE :
35369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.LSTORE :
35469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.FSTORE :
35569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.DSTORE :
35669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.ASTORE :
35769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            writeLocal(var);
35869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            break;
35969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case Opcode.IINC :
36069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            readLocal(var);
36169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            // this does not call writeLocal().
36269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            break;
36369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
36469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
36569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal}
366