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.editor;
22b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
23b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.*;
24b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.attribute.CodeAttribute;
25b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.attribute.visitor.AttributeVisitor;
26b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.instruction.*;
27b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.instruction.visitor.InstructionVisitor;
28b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.util.SimplifiedVisitor;
29b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
30b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/**
31b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This InstructionVisitor writes out the instructions that it visits,
32b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * collecting instructions that have to be widened. As an AttributeVisitor,
33b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * it then applies the collected changes. The process will be repeated
34b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * recursively, if necessary.
35b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
36b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @author Eric Lafortune
37b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */
38b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratopublic class InstructionWriter
39b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoextends      SimplifiedVisitor
40b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimplements   InstructionVisitor,
41b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato             AttributeVisitor
42b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato{
43b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private int codeLength;
44b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
45b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private CodeAttributeEditor codeAttributeEditor;
46b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
47b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
48b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
49b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Resets the accumulated code changes.
50b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @param codeLength the length of the code that will be edited next.
51b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
52b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void reset(int codeLength)
53b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
54b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        this.codeLength = codeLength;
55b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
56b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // The code attribute editor has to be created lazily.
57b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (codeAttributeEditor != null)
58b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
59b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            codeAttributeEditor.reset(codeLength);
60b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
61b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
62b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
63b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
64b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    // Implementations for InstructionVisitor.
65b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
66b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction)
67b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
68b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Try to write out the instruction.
69b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Simple instructions should always fit.
70b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        simpleInstruction.write(codeAttribute, offset);
71b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
72b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
73b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
74b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
75b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
76b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        try
77b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
78b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Try to write out the instruction.
79b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            constantInstruction.write(codeAttribute, offset);
80b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
81b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        catch (IllegalArgumentException exception)
82b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
83b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Create a new constant instruction that will fit.
84b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            Instruction replacementInstruction =
85b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                new ConstantInstruction(constantInstruction.opcode,
86b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                        constantInstruction.constantIndex,
87b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                        constantInstruction.constant).shrink();
88b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
89b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            replaceInstruction(offset, replacementInstruction);
90b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
91b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Write out a dummy constant instruction for now.
92b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            constantInstruction.constantIndex = 0;
93b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            constantInstruction.constant      = 0;
94b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            constantInstruction.write(codeAttribute, offset);
95b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
96b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
97b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
98b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
99b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
100b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
101b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        try
102b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
103b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Try to write out the instruction.
104b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            variableInstruction.write(codeAttribute, offset);
105b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
106b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        catch (IllegalArgumentException exception)
107b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
108b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Create a new variable instruction that will fit.
109b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            Instruction replacementInstruction =
110b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                new VariableInstruction(variableInstruction.opcode,
111b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                        variableInstruction.variableIndex,
112b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                        variableInstruction.constant).shrink();
113b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
114b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            replaceInstruction(offset, replacementInstruction);
115b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
116b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Write out a dummy variable instruction for now.
117b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            variableInstruction.variableIndex = 0;
118b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            variableInstruction.constant      = 0;
119b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            variableInstruction.write(codeAttribute, offset);
120b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
121b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
122b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
123b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
124b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
125b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
126b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        try
127b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
128b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Try to write out the instruction.
129b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            branchInstruction.write(codeAttribute, offset);
130b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
131b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        catch (IllegalArgumentException exception)
132b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
133b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Create a new unconditional branch that will fit.
134b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            Instruction replacementInstruction =
135b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                new BranchInstruction(InstructionConstants.OP_GOTO_W,
136b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                      branchInstruction.branchOffset);
137b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
138b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Create a new instruction that will fit.
139b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            switch (branchInstruction.opcode)
140b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
141b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                default:
142b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
143b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    // Create a new branch instruction that will fit.
144b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    replacementInstruction =
145b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        new BranchInstruction(branchInstruction.opcode,
146b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                              branchInstruction.branchOffset).shrink();
147b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
148b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    break;
149b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }
150b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
151b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Some special cases, for which a wide branch doesn't exist.
152b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case InstructionConstants.OP_IFEQ:
153b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case InstructionConstants.OP_IFNE:
154b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case InstructionConstants.OP_IFLT:
155b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case InstructionConstants.OP_IFGE:
156b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case InstructionConstants.OP_IFGT:
157b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case InstructionConstants.OP_IFLE:
158b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case InstructionConstants.OP_IFICMPEQ:
159b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case InstructionConstants.OP_IFICMPNE:
160b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case InstructionConstants.OP_IFICMPLT:
161b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case InstructionConstants.OP_IFICMPGE:
162b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case InstructionConstants.OP_IFICMPGT:
163b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case InstructionConstants.OP_IFICMPLE:
164b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case InstructionConstants.OP_IFACMPEQ:
165b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case InstructionConstants.OP_IFACMPNE:
166b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
167b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    // Insert the complementary conditional branch.
168b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    Instruction complementaryConditionalBranch =
169b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        new BranchInstruction((byte)(((branchInstruction.opcode+1) ^ 1) - 1),
170b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                              (1+2) + (1+4));
171b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
172b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    insertBeforeInstruction(offset, complementaryConditionalBranch);
173b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
174b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    // Create a new unconditional branch that will fit.
175b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    break;
176b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }
177b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
178b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case InstructionConstants.OP_IFNULL:
179b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case InstructionConstants.OP_IFNONNULL:
180b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
181b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    // Insert the complementary conditional branch.
182b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    Instruction complementaryConditionalBranch =
183b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        new BranchInstruction((byte)(branchInstruction.opcode ^ 1),
184b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                              (1+2) + (1+4));
185b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
186b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    insertBeforeInstruction(offset, complementaryConditionalBranch);
187b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
188b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    // Create a new unconditional branch that will fit.
189b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    break;
190b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }
191b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
192b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
193b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            replaceInstruction(offset, replacementInstruction);
194b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
195b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Write out a dummy branch instruction for now.
196b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            branchInstruction.branchOffset = 0;
197b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            branchInstruction.write(codeAttribute, offset);
198b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
199b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
200b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
201b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
202b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitAnySwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SwitchInstruction switchInstruction)
203b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
204b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Try to write out the instruction.
205b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Switch instructions should always fit.
206b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        switchInstruction.write(codeAttribute, offset);
207b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
208b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
209b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
210b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    // Implementations for AttributeVisitor.
211b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
212b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
213b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
214b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Avoid doing any work if nothing is changing anyway.
215b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (codeAttributeEditor != null)
216b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
217b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Apply the collected expansions.
218b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            codeAttributeEditor.visitCodeAttribute(clazz, method, codeAttribute);
219b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
220b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Clear the modifications for the next run.
221b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            codeAttributeEditor = null;
222b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
223b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
224b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
225b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
226b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    // Small utility methods.
227b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
228b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
229b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Remembers to place the given instruction right before the instruction
230b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * at the given offset.
231b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
232b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private void insertBeforeInstruction(int instructionOffset, Instruction instruction)
233b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
234b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        ensureCodeAttributeEditor();
235b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
236b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Replace the instruction.
237b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        codeAttributeEditor.insertBeforeInstruction(instructionOffset, instruction);
238b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
239b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
240b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
241b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
242b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Remembers to replace the instruction at the given offset by the given
243b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * instruction.
244b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
245b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private void replaceInstruction(int instructionOffset, Instruction instruction)
246b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
247b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        ensureCodeAttributeEditor();
248b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
249b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Replace the instruction.
250b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        codeAttributeEditor.replaceInstruction(instructionOffset, instruction);
251b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
252b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
253b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
254b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
255b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Remembers to place the given instruction right after the instruction
256b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * at the given offset.
257b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
258b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private void insertAfterInstruction(int instructionOffset, Instruction instruction)
259b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
260b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        ensureCodeAttributeEditor();
261b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
262b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Replace the instruction.
263b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        codeAttributeEditor.insertAfterInstruction(instructionOffset, instruction);
264b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
265b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
266b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
267b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
268b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Makes sure there is a code attribute editor for the given code attribute.
269b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
270b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private void ensureCodeAttributeEditor()
271b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
272b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (codeAttributeEditor == null)
273b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
274b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            codeAttributeEditor = new CodeAttributeEditor();
275b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            codeAttributeEditor.reset(codeLength);
276b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
277b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
278b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato}
279