1b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/*
2b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * ProGuard -- shrinking, optimization, obfuscation, and preverification
3b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *             of Java bytecode.
4b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
5b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
6b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
7b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This program is free software; you can redistribute it and/or modify it
8b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * under the terms of the GNU General Public License as published by the Free
9b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Software Foundation; either version 2 of the License, or (at your option)
10b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * any later version.
11b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
12b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This program is distributed in the hope that it will be useful, but WITHOUT
13b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * more details.
16b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
17b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * You should have received a copy of the GNU General Public License along
18b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * with this program; if not, write to the Free Software Foundation, Inc.,
19b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */
21b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratopackage proguard.classfile.instruction;
22b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
23b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.*;
24b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.attribute.CodeAttribute;
25b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.instruction.visitor.InstructionVisitor;
26b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
27b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/**
28b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This Instruction represents an instruction that refers to a variable on the
29b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * local variable stack.
30b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
31b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @author Eric Lafortune
32b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */
33b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratopublic class VariableInstruction extends Instruction
34b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato{
35b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public boolean wide;
36b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public int     variableIndex;
37b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public int     constant;
38b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
39b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
40b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
41b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Creates an uninitialized VariableInstruction.
42b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
43b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public VariableInstruction() {}
44b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
45b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
46b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public VariableInstruction(boolean wide)
47b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
48b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        this.wide = wide;
49b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
50b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
51b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
52b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public VariableInstruction(byte opcode)
53b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
54b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        this(opcode, embeddedVariable(opcode), 0);
55b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
56b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
57b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
58b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public VariableInstruction(byte opcode,
59b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                               int  variableIndex)
60b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
61b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        this(opcode, variableIndex, 0);
62b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
63b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
64b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
65b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public VariableInstruction(byte opcode,
66b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                               int  variableIndex,
67b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                               int  constant)
68b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
69b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        this.opcode        = opcode;
70b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        this.variableIndex = variableIndex;
71b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        this.constant      = constant;
72b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        this.wide          = requiredVariableIndexSize() > 1 ||
73b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                             requiredConstantSize()      > 1;
74b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
75b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
76b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
77b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
78b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Copies the given instruction into this instruction.
79b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @param variableInstruction the instruction to be copied.
80b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @return this instruction.
81b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
82b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public VariableInstruction copy(VariableInstruction variableInstruction)
83b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
84b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        this.opcode        = variableInstruction.opcode;
85b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        this.variableIndex = variableInstruction.variableIndex;
86b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        this.constant      = variableInstruction.constant;
87b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        this.wide          = variableInstruction.wide;
88b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
89b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return this;
90b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
91b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
92b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
93b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
94b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Return the embedded variable of the given opcode, or 0 if the opcode
95b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * doesn't have one.
96b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
97b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private static int embeddedVariable(byte opcode)
98b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
99b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        switch (opcode)
100b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
101b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ILOAD_1:
102b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_LLOAD_1:
103b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_FLOAD_1:
104b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_DLOAD_1:
105b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ALOAD_1:
106b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ISTORE_1:
107b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_LSTORE_1:
108b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_FSTORE_1:
109b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_DSTORE_1:
110b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ASTORE_1: return 1;
111b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
112b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ILOAD_2:
113b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_LLOAD_2:
114b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_FLOAD_2:
115b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_DLOAD_2:
116b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ALOAD_2:
117b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ISTORE_2:
118b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_LSTORE_2:
119b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_FSTORE_2:
120b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_DSTORE_2:
121b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ASTORE_2: return 2;
122b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
123b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ILOAD_3:
124b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_LLOAD_3:
125b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_FLOAD_3:
126b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_DLOAD_3:
127b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ALOAD_3:
128b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ISTORE_3:
129b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_LSTORE_3:
130b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_FSTORE_3:
131b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_DSTORE_3:
132b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ASTORE_3: return 3;
133b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
134b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            default: return 0;
135b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
136b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
137b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
138b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
139b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
140b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Returns whether this instruction stores the value of a variable.
141b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * The value is false for the ret instruction, but true for the iinc
142b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * instruction.
143b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
144b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public boolean isStore()
145b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
146b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // A store instruction can be recognized as follows. Note that this
147b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // excludes the ret instruction, which has a negative opcode.
148b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return opcode >= InstructionConstants.OP_ISTORE ||
149b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato               opcode == InstructionConstants.OP_IINC;
150b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
151b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
152b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
153b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
154b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Returns whether this instruction loads the value of a variable.
155b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * The value is true for the ret instruction and for the iinc
156b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * instruction.
157b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
158b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public boolean isLoad()
159b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
160b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // A load instruction can be recognized as follows. Note that this
161b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // includes the ret instruction, which has a negative opcode.
162b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return opcode < InstructionConstants.OP_ISTORE;
163b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
164b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
165b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
166b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    // Implementations for Instruction.
167b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
168b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public byte canonicalOpcode()
169b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
170b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Remove the _0, _1, _2, _3 extension, if any.
171b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        switch (opcode)
172b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
173b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ILOAD_0:
174b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ILOAD_1:
175b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ILOAD_2:
176b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ILOAD_3: return InstructionConstants.OP_ILOAD;
177b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_LLOAD_0:
178b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_LLOAD_1:
179b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_LLOAD_2:
180b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_LLOAD_3: return InstructionConstants.OP_LLOAD;
181b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_FLOAD_0:
182b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_FLOAD_1:
183b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_FLOAD_2:
184b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_FLOAD_3: return InstructionConstants.OP_FLOAD;
185b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_DLOAD_0:
186b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_DLOAD_1:
187b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_DLOAD_2:
188b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_DLOAD_3: return InstructionConstants.OP_DLOAD;
189b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ALOAD_0:
190b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ALOAD_1:
191b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ALOAD_2:
192b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ALOAD_3: return InstructionConstants.OP_ALOAD;
193b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
194b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ISTORE_0:
195b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ISTORE_1:
196b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ISTORE_2:
197b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ISTORE_3: return InstructionConstants.OP_ISTORE;
198b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_LSTORE_0:
199b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_LSTORE_1:
200b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_LSTORE_2:
201b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_LSTORE_3: return InstructionConstants.OP_LSTORE;
202b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_FSTORE_0:
203b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_FSTORE_1:
204b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_FSTORE_2:
205b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_FSTORE_3: return InstructionConstants.OP_FSTORE;
206b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_DSTORE_0:
207b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_DSTORE_1:
208b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_DSTORE_2:
209b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_DSTORE_3: return InstructionConstants.OP_DSTORE;
210b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ASTORE_0:
211b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ASTORE_1:
212b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ASTORE_2:
213b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ASTORE_3: return InstructionConstants.OP_ASTORE;
214b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
215b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            default: return opcode;
216b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
217b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
218b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
219b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public Instruction shrink()
220b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
221b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        opcode = canonicalOpcode();
222b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
223b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Is this instruction pointing to a variable with index from 0 to 3?
224b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (variableIndex <= 3)
225b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
226b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            switch (opcode)
227b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
228b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case InstructionConstants.OP_ILOAD: opcode = (byte)(InstructionConstants.OP_ILOAD_0 + variableIndex); break;
229b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case InstructionConstants.OP_LLOAD: opcode = (byte)(InstructionConstants.OP_LLOAD_0 + variableIndex); break;
230b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case InstructionConstants.OP_FLOAD: opcode = (byte)(InstructionConstants.OP_FLOAD_0 + variableIndex); break;
231b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case InstructionConstants.OP_DLOAD: opcode = (byte)(InstructionConstants.OP_DLOAD_0 + variableIndex); break;
232b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case InstructionConstants.OP_ALOAD: opcode = (byte)(InstructionConstants.OP_ALOAD_0 + variableIndex); break;
233b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
234b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case InstructionConstants.OP_ISTORE: opcode = (byte)(InstructionConstants.OP_ISTORE_0 + variableIndex); break;
235b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case InstructionConstants.OP_LSTORE: opcode = (byte)(InstructionConstants.OP_LSTORE_0 + variableIndex); break;
236b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case InstructionConstants.OP_FSTORE: opcode = (byte)(InstructionConstants.OP_FSTORE_0 + variableIndex); break;
237b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case InstructionConstants.OP_DSTORE: opcode = (byte)(InstructionConstants.OP_DSTORE_0 + variableIndex); break;
238b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case InstructionConstants.OP_ASTORE: opcode = (byte)(InstructionConstants.OP_ASTORE_0 + variableIndex); break;
239b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
240b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
241b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
242b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Only make the instruction wide if necessary.
243b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        wide = requiredVariableIndexSize() > 1 ||
244b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato               requiredConstantSize()      > 1;
245b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
246b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return this;
247b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
248b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
249b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
250b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    protected boolean isWide()
251b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
252b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return wide;
253b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
254b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
255b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
256b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    protected void readInfo(byte[] code, int offset)
257b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
258b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        int variableIndexSize = variableIndexSize();
259b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        int constantSize      = constantSize();
260b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
261b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Also initialize embedded variable indexes.
262b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (variableIndexSize == 0)
263b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
264b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // An embedded variable index can be decoded as follows.
265b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            variableIndex = opcode < InstructionConstants.OP_ISTORE_0 ?
266b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                (opcode - InstructionConstants.OP_ILOAD_0 ) & 3 :
267b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                (opcode - InstructionConstants.OP_ISTORE_0) & 3;
268b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
269b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        else
270b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
271b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            variableIndex = readValue(code, offset, variableIndexSize); offset += variableIndexSize;
272b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
273b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
274b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        constant = readSignedValue(code, offset, constantSize);
275b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
276b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
277b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
278b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    protected void writeInfo(byte[] code, int offset)
279b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
280b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        int variableIndexSize = variableIndexSize();
281b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        int constantSize      = constantSize();
282b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
283b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (requiredVariableIndexSize() > variableIndexSize)
284b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
285b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            throw new IllegalArgumentException("Instruction has invalid variable index size ("+this.toString(offset)+")");
286b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
287b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
288b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (requiredConstantSize() > constantSize)
289b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
290b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            throw new IllegalArgumentException("Instruction has invalid constant size ("+this.toString(offset)+")");
291b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
292b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
293b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        writeValue(code, offset, variableIndex, variableIndexSize); offset += variableIndexSize;
294b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        writeSignedValue(code, offset, constant, constantSize);
295b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
296b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
297b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
298b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public int length(int offset)
299b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
300b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return (wide ? 2 : 1) + variableIndexSize() + constantSize();
301b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
302b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
303b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
304b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, InstructionVisitor instructionVisitor)
305b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
306b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        instructionVisitor.visitVariableInstruction(clazz, method, codeAttribute, offset, this);
307b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
308b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
309b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
310b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    // Implementations for Object.
311b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
312b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public String toString()
313b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
314b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return getName() +
315b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato               (wide ? "_w" : "") +
316b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato               " v"+variableIndex +
317b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato               (constantSize() > 0 ? ", "+constant : "");
318b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
319b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
320b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
321b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    // Small utility methods.
322b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
323b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
324b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Returns the variable index size for this instruction.
325b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
326b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private int variableIndexSize()
327b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
328b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return (opcode >= InstructionConstants.OP_ILOAD_0 &&
329b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                opcode <= InstructionConstants.OP_ALOAD_3) ||
330b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato               (opcode >= InstructionConstants.OP_ISTORE_0 &&
331b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                opcode <= InstructionConstants.OP_ASTORE_3) ? 0 :
332b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato               wide                                         ? 2 :
333b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                              1;
334b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
335b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
336b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
337b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
338b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Computes the required variable index size for this instruction's variable
339b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * index.
340b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
341b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private int requiredVariableIndexSize()
342b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
343b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return (variableIndex &    0x3) == variableIndex ? 0 :
344b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato               (variableIndex &   0xff) == variableIndex ? 1 :
345b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato               (variableIndex & 0xffff) == variableIndex ? 2 :
346b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                           4;
347b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
348b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
349b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
350b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
351b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
352b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Returns the constant size for this instruction.
353b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
354b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private int constantSize()
355b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
356b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return opcode != InstructionConstants.OP_IINC ? 0 :
357b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato               wide                                   ? 2 :
358b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                        1;
359b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
360b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
361b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
362b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
363b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Computes the required constant size for this instruction's constant.
364b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
365b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private int requiredConstantSize()
366b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
367b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return opcode != InstructionConstants.OP_IINC ? 0 :
368b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato               constant << 24 >> 24 == constant       ? 1 :
369b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato               constant << 16 >> 16 == constant       ? 2 :
370b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                        4;
371b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
372b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato}
373