1b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/*
2b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * ProGuard -- shrinking, optimization, obfuscation, and preverification
3b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *             of Java bytecode.
4b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
52270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * Copyright (c) 2002-2014 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.optimize.evaluation;
22b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
23b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.*;
24b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.attribute.*;
25b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.attribute.visitor.AttributeVisitor;
26b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.editor.*;
27b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.instruction.*;
28b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.instruction.visitor.InstructionVisitor;
29b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.util.*;
302270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstromimport proguard.classfile.visitor.ClassPrinter;
312270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstromimport proguard.evaluation.TracedVariables;
32b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.evaluation.value.*;
332270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstromimport proguard.optimize.info.SideEffectInstructionChecker;
342270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
352270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstromimport java.util.Arrays;
36b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
37b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/**
38b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This AttributeVisitor simplifies the code attributes that it visits, based
39b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * on partial evaluation.
40b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
41b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @author Eric Lafortune
42b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */
43b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratopublic class EvaluationSimplifier
44b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoextends      SimplifiedVisitor
45b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimplements   AttributeVisitor,
46b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato             InstructionVisitor
47b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato{
48b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    private static final int  POS_ZERO_FLOAT_BITS  = Float.floatToIntBits(0.0f);
49b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    private static final long POS_ZERO_DOUBLE_BITS = Double.doubleToLongBits(0.0);
50b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
51b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    //*
52b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private static final boolean DEBUG = false;
53b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /*/
542270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom    private static       boolean DEBUG = System.getProperty("es") != null;
55b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    //*/
56b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
57b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private final InstructionVisitor extraInstructionVisitor;
58b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
59b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private final PartialEvaluator             partialEvaluator;
60b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    private final SideEffectInstructionChecker sideEffectInstructionChecker = new SideEffectInstructionChecker(true, true);
61b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    private final CodeAttributeEditor          codeAttributeEditor          = new CodeAttributeEditor(false, true);
62b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
63b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
64b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
65b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Creates a new EvaluationSimplifier.
66b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
67b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public EvaluationSimplifier()
68b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
69b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        this(new PartialEvaluator(), null);
70b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
71b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
72b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
73b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
74b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Creates a new EvaluationSimplifier.
75b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @param partialEvaluator        the partial evaluator that will
76b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     *                                execute the code and provide
77b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     *                                information about the results.
78b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @param extraInstructionVisitor an optional extra visitor for all
79b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     *                                simplified instructions.
80b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
81b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public EvaluationSimplifier(PartialEvaluator   partialEvaluator,
82b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                InstructionVisitor extraInstructionVisitor)
83b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
84b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        this.partialEvaluator        = partialEvaluator;
85b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        this.extraInstructionVisitor = extraInstructionVisitor;
86b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
87b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
88b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
89b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    // Implementations for AttributeVisitor.
90b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
91b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
92b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
93b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
94b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
95b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
96b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato//        DEBUG =
97b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato//            clazz.getName().equals("abc/Def") &&
98b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato//            method.getName(clazz).equals("abc");
99b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
100b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // TODO: Remove this when the evaluation simplifier has stabilized.
101b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Catch any unexpected exceptions from the actual visiting method.
102b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        try
103b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
104b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Process the code.
105b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            visitCodeAttribute0(clazz, method, codeAttribute);
106b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
107b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        catch (RuntimeException ex)
108b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
109b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            System.err.println("Unexpected error while simplifying instructions after partial evaluation:");
110b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            System.err.println("  Class       = ["+clazz.getName()+"]");
111b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            System.err.println("  Method      = ["+method.getName(clazz)+method.getDescriptor(clazz)+"]");
112b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            System.err.println("  Exception   = ["+ex.getClass().getName()+"] ("+ex.getMessage()+")");
113b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            System.err.println("Not optimizing this method");
114b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
115b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (DEBUG)
116b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
117b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                method.accept(clazz, new ClassPrinter());
118b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
119b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                throw ex;
120b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
121b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
122b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
123b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
124b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
125b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitCodeAttribute0(Clazz clazz, Method method, CodeAttribute codeAttribute)
126b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
127b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (DEBUG)
128b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
129b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            System.out.println();
1302270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            System.out.println("EvaluationSimplifier ["+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"]");
131b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
132b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
133b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Evaluate the method.
134b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        partialEvaluator.visitCodeAttribute(clazz, method, codeAttribute);
135b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
136b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        int codeLength = codeAttribute.u4codeLength;
137b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
138b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Reset the code changes.
139b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        codeAttributeEditor.reset(codeLength);
140b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
141b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Replace any instructions that can be simplified.
142b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        for (int offset = 0; offset < codeLength; offset++)
143b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
144b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (partialEvaluator.isTraced(offset))
145b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
146b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                Instruction instruction = InstructionFactory.create(codeAttribute.code,
147b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                                    offset);
148b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
149b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                instruction.accept(clazz, method, codeAttribute, offset, this);
150b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
151b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
152b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
153b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Apply all accumulated changes to the code.
154b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        codeAttributeEditor.visitCodeAttribute(clazz, method, codeAttribute);
155b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
156b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
157b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
158b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    // Implementations for InstructionVisitor.
159b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
160b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction)
161b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
162b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        switch (simpleInstruction.opcode)
163b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
164b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_IALOAD:
165b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_BALOAD:
166b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_CALOAD:
167b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_SALOAD:
168b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_IADD:
169b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ISUB:
170b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_IMUL:
171b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_IDIV:
172b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_IREM:
173b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_INEG:
174b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ISHL:
175b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ISHR:
176b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_IUSHR:
177b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_IAND:
178b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_IOR:
179b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_IXOR:
180b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_L2I:
181b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_F2I:
182b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_D2I:
183b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_I2B:
184b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_I2C:
185b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_I2S:
1862270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            case InstructionConstants.OP_ARRAYLENGTH:
187b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                replaceIntegerPushInstruction(clazz, offset, simpleInstruction);
188b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                break;
189b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
190b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_LALOAD:
191b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_LADD:
192b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_LSUB:
193b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_LMUL:
194b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_LDIV:
195b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_LREM:
196b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_LNEG:
197b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_LSHL:
198b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_LSHR:
199b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_LUSHR:
200b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_LAND:
201b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_LOR:
202b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_LXOR:
203b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_I2L:
204b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_F2L:
205b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_D2L:
206b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                replaceLongPushInstruction(clazz, offset, simpleInstruction);
207b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                break;
208b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
209b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_FALOAD:
210b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_FADD:
211b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_FSUB:
212b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_FMUL:
213b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_FDIV:
214b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_FREM:
215b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_FNEG:
216b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_I2F:
217b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_L2F:
218b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_D2F:
219b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                replaceFloatPushInstruction(clazz, offset, simpleInstruction);
220b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                break;
221b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
222b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_DALOAD:
223b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_DADD:
224b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_DSUB:
225b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_DMUL:
226b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_DDIV:
227b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_DREM:
228b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_DNEG:
229b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_I2D:
230b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_L2D:
231b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_F2D:
232b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                replaceDoublePushInstruction(clazz, offset, simpleInstruction);
233b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                break;
234b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
235b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_AALOAD:
236b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                replaceReferencePushInstruction(clazz, offset, simpleInstruction);
237b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                break;
238b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
239b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
240b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
241b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
242b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
243b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
244b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        int variableIndex = variableInstruction.variableIndex;
245b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
246b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        switch (variableInstruction.opcode)
247b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
248b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ILOAD:
249b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ILOAD_0:
250b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ILOAD_1:
251b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ILOAD_2:
252b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ILOAD_3:
253b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                replaceIntegerPushInstruction(clazz, offset, variableInstruction, variableIndex);
254b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                break;
255b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
256b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_LLOAD:
257b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_LLOAD_0:
258b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_LLOAD_1:
259b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_LLOAD_2:
260b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_LLOAD_3:
261b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                replaceLongPushInstruction(clazz, offset, variableInstruction, variableIndex);
262b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                break;
263b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
264b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_FLOAD:
265b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_FLOAD_0:
266b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_FLOAD_1:
267b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_FLOAD_2:
268b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_FLOAD_3:
269b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                replaceFloatPushInstruction(clazz, offset, variableInstruction, variableIndex);
270b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                break;
271b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
272b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_DLOAD:
273b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_DLOAD_0:
274b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_DLOAD_1:
275b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_DLOAD_2:
276b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_DLOAD_3:
277b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                replaceDoublePushInstruction(clazz, offset, variableInstruction, variableIndex);
278b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                break;
279b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
280b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ALOAD:
281b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ALOAD_0:
282b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ALOAD_1:
283b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ALOAD_2:
284b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ALOAD_3:
285b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                replaceReferencePushInstruction(clazz, offset, variableInstruction);
286b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                break;
287b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
288b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ASTORE:
289b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ASTORE_0:
290b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ASTORE_1:
291b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ASTORE_2:
292b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_ASTORE_3:
293b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                deleteReferencePopInstruction(clazz, offset, variableInstruction);
294b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                break;
295b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
296b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_RET:
297b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                replaceBranchInstruction(clazz, offset, variableInstruction);
298b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                break;
299b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
300b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
301b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
302b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
303b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
304b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
305b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        switch (constantInstruction.opcode)
306b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
307b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_GETSTATIC:
308b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_GETFIELD:
309b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                replaceAnyPushInstruction(clazz, offset, constantInstruction);
310b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                break;
311b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
312b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_INVOKEVIRTUAL:
313b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_INVOKESPECIAL:
314b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_INVOKESTATIC:
315b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_INVOKEINTERFACE:
316b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                if (constantInstruction.stackPushCount(clazz) > 0 &&
317b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    !sideEffectInstructionChecker.hasSideEffects(clazz,
318b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                                 method,
319b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                                 codeAttribute,
320b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                                 offset,
321b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                                 constantInstruction))
322b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
323b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    replaceAnyPushInstruction(clazz, offset, constantInstruction);
324b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }
325b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
326b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                break;
327b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
328b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_CHECKCAST:
329b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                replaceReferencePushInstruction(clazz, offset, constantInstruction);
330b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                break;
331b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
332b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
333b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
334b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
335b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
336b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
337b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        switch (branchInstruction.opcode)
338b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
339b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_GOTO:
340b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_GOTO_W:
341b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Don't replace unconditional branches.
342b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                break;
343b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
344b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_JSR:
345b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_JSR_W:
346b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                replaceJsrInstruction(clazz, offset, branchInstruction);
347b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                break;
348b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
349b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            default:
350b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                replaceBranchInstruction(clazz, offset, branchInstruction);
351b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                break;
352b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
353b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
354b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
355b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
3562270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom    public void visitTableSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, TableSwitchInstruction tableSwitchInstruction)
357b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
358b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // First try to simplify it to a simple branch.
3592270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        replaceBranchInstruction(clazz, offset, tableSwitchInstruction);
360b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
3612270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        // Otherwise try to simplify simple enum switches.
362b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (!codeAttributeEditor.isModified(offset))
363b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
3642270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            replaceSimpleEnumSwitchInstruction(clazz,
3652270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                               codeAttribute,
3662270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                               offset,
3672270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                               tableSwitchInstruction);
3682270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
3692270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            // Otherwise make sure all branch targets are valid.
3702270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            if (!codeAttributeEditor.isModified(offset))
3712270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            {
3722270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                cleanUpSwitchInstruction(clazz, offset, tableSwitchInstruction);
3732270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
3742270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                trimSwitchInstruction(clazz, offset, tableSwitchInstruction);
3752270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            }
3762270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        }
3772270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom    }
3782270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
3792270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
3802270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom    public void visitLookUpSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LookUpSwitchInstruction lookUpSwitchInstruction)
3812270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom    {
3822270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        // First try to simplify it to a simple branch.
3832270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        replaceBranchInstruction(clazz, offset, lookUpSwitchInstruction);
3842270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
3852270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        // Otherwise try to simplify simple enum switches.
3862270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        if (!codeAttributeEditor.isModified(offset))
3872270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        {
3882270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            replaceSimpleEnumSwitchInstruction(clazz,
3892270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                               codeAttribute,
3902270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                               offset,
3912270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                               lookUpSwitchInstruction);
3922270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
3932270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            // Otherwise make sure all branch targets are valid.
3942270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            if (!codeAttributeEditor.isModified(offset))
3952270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            {
3962270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                cleanUpSwitchInstruction(clazz, offset, lookUpSwitchInstruction);
3972270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
3982270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                trimSwitchInstruction(clazz, offset, lookUpSwitchInstruction);
3992270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            }
400b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
401b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
402b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
403b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
404b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    // Small utility methods.
405b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
406b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
407b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Replaces the push instruction at the given offset by a simpler push
408b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * instruction, if possible.
409b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
410b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private void replaceAnyPushInstruction(Clazz       clazz,
411b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                           int         offset,
412b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                           Instruction instruction)
413b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
414b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
415b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (pushedValue.isParticular())
416b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
417b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            switch (pushedValue.computationalType())
418b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
419b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case Value.TYPE_INTEGER:
420b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    replaceIntegerPushInstruction(clazz, offset, instruction);
421b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    break;
422b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case Value.TYPE_LONG:
423b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    replaceLongPushInstruction(clazz, offset, instruction);
424b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    break;
425b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case Value.TYPE_FLOAT:
426b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    replaceFloatPushInstruction(clazz, offset, instruction);
427b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    break;
428b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case Value.TYPE_DOUBLE:
429b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    replaceDoublePushInstruction(clazz, offset, instruction);
430b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    break;
431b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case Value.TYPE_REFERENCE:
432b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    replaceReferencePushInstruction(clazz, offset, instruction);
433b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    break;
434b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
435b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
436b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
437b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
438b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
439b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
440b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Replaces the integer pushing instruction at the given offset by a simpler
441b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * push instruction, if possible.
442b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
443b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private void replaceIntegerPushInstruction(Clazz       clazz,
444b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                               int         offset,
445b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                               Instruction instruction)
446b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
447b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        replaceIntegerPushInstruction(clazz,
448b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                      offset,
449b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                      instruction,
450b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                      partialEvaluator.getVariablesBefore(offset).size());
451b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
452b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
453b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
454b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
455b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Replaces the integer pushing instruction at the given offset by a simpler
456b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * push instruction, if possible.
457b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
458b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private void replaceIntegerPushInstruction(Clazz       clazz,
459b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                               int         offset,
460b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                               Instruction instruction,
461b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                               int         maxVariableIndex)
462b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
463b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
464b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (pushedValue.isParticular())
465b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
466b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            // Push a constant instead.
467b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            int value = pushedValue.integerValue().value();
468b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            if ((short)value == value)
469b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
470b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                replaceConstantPushInstruction(clazz,
471b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                               offset,
472b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                               instruction,
473b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                               InstructionConstants.OP_SIPUSH,
474b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                               value);
475b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
476b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else
477b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
478b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                ConstantPoolEditor constantPoolEditor =
479b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    new ConstantPoolEditor((ProgramClass)clazz);
480b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
481b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                Instruction replacementInstruction =
482b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    new ConstantInstruction(InstructionConstants.OP_LDC,
483b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                                            constantPoolEditor.addIntegerConstant(value));
484b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
485b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                replaceInstruction(clazz, offset, instruction, replacementInstruction);
486b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
487b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
488b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        else if (pushedValue.isSpecific())
489b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
490b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            // Load an equivalent lower-numbered variable instead, if any.
491b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            TracedVariables variables = partialEvaluator.getVariablesBefore(offset);
492b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            for (int variableIndex = 0; variableIndex < maxVariableIndex; variableIndex++)
493b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
494b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                if (pushedValue.equals(variables.load(variableIndex)))
495b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
496b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    replaceVariablePushInstruction(clazz,
497b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                   offset,
498b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                   instruction,
499b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                   InstructionConstants.OP_ILOAD,
500b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                   variableIndex);
501b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                    break;
502b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }
503b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
504b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
505b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
506b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
507b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
508b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
509b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Replaces the long pushing instruction at the given offset by a simpler
510b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * push instruction, if possible.
511b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
512b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private void replaceLongPushInstruction(Clazz       clazz,
513b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                            int         offset,
514b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                            Instruction instruction)
515b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
516b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        replaceLongPushInstruction(clazz,
517b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                   offset,
518b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                   instruction,
519b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                   partialEvaluator.getVariablesBefore(offset).size());
520b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
521b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
522b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
523b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
524b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Replaces the long pushing instruction at the given offset by a simpler
525b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * push instruction, if possible.
526b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
527b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private void replaceLongPushInstruction(Clazz       clazz,
528b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                            int         offset,
529b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                            Instruction instruction,
530b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                            int         maxVariableIndex)
531b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
532b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
533b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (pushedValue.isParticular())
534b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
535b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            // Push a constant instead.
536b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            long value = pushedValue.longValue().value();
537b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (value == 0L ||
538b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                value == 1L)
539b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
540b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                replaceConstantPushInstruction(clazz,
541b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                       offset,
542b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                       instruction,
543b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                       InstructionConstants.OP_LCONST_0,
544b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                       (int)value);
545b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
546b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else
547b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
548b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                ConstantPoolEditor constantPoolEditor =
549b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    new ConstantPoolEditor((ProgramClass)clazz);
550b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
551b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                Instruction replacementInstruction =
552b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    new ConstantInstruction(InstructionConstants.OP_LDC2_W,
553b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                                            constantPoolEditor.addLongConstant(value));
554b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
555b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                replaceInstruction(clazz, offset, instruction, replacementInstruction);
556b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
557b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
558b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        else if (pushedValue.isSpecific())
559b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
560b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            // Load an equivalent lower-numbered variable instead, if any.
561b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            TracedVariables variables = partialEvaluator.getVariablesBefore(offset);
562b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            for (int variableIndex = 0; variableIndex < maxVariableIndex; variableIndex++)
563b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
564b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                // Note that we have to check the second part as well.
565b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                if (pushedValue.equals(variables.load(variableIndex)) &&
566b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                    variables.load(variableIndex + 1) != null         &&
567b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                    variables.load(variableIndex + 1).computationalType() == Value.TYPE_TOP)
568b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
569b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    replaceVariablePushInstruction(clazz,
570b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                   offset,
571b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                   instruction,
572b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                   InstructionConstants.OP_LLOAD,
573b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                   variableIndex);
574b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }
575b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
576b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
577b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
578b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
579b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
580b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
581b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Replaces the float pushing instruction at the given offset by a simpler
582b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * push instruction, if possible.
583b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
584b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private void replaceFloatPushInstruction(Clazz       clazz,
585b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                             int         offset,
586b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                             Instruction instruction)
587b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
588b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        replaceFloatPushInstruction(clazz,
589b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    offset,
590b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    instruction,
591b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    partialEvaluator.getVariablesBefore(offset).size());
592b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
593b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
594b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
595b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
596b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Replaces the float pushing instruction at the given offset by a simpler
597b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * push instruction, if possible.
598b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
599b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private void replaceFloatPushInstruction(Clazz       clazz,
600b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                             int         offset,
601b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                             Instruction instruction,
602b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                             int         maxVariableIndex)
603b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
604b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
605b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (pushedValue.isParticular())
606b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
607b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            // Push a constant instead.
608b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            // Make sure to distinguish between +0.0 and -0.0.
609b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            float value = pushedValue.floatValue().value();
610b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            if (value == 0.0f && Float.floatToIntBits(value) == POS_ZERO_FLOAT_BITS ||
611b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                value == 1.0f ||
612b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                value == 2.0f)
613b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
614b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                replaceConstantPushInstruction(clazz,
615b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                               offset,
616b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                               instruction,
617b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                               InstructionConstants.OP_FCONST_0,
618b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                               (int)value);
619b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
620b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else
621b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
622b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                ConstantPoolEditor constantPoolEditor =
623b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    new ConstantPoolEditor((ProgramClass)clazz);
624b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
625b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                Instruction replacementInstruction =
626b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    new ConstantInstruction(InstructionConstants.OP_LDC,
627b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                                            constantPoolEditor.addFloatConstant(value));
628b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
629b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                replaceInstruction(clazz, offset, instruction, replacementInstruction);
630b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
631b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
632b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        else if (pushedValue.isSpecific())
633b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
634b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            // Load an equivalent lower-numbered variable instead, if any.
635b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            TracedVariables variables = partialEvaluator.getVariablesBefore(offset);
636b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            for (int variableIndex = 0; variableIndex < maxVariableIndex; variableIndex++)
637b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
638b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                if (pushedValue.equals(variables.load(variableIndex)))
639b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
640b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    replaceVariablePushInstruction(clazz,
641b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                   offset,
642b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                   instruction,
643b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                   InstructionConstants.OP_FLOAD,
644b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                   variableIndex);
645b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }
646b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
647b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
648b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
649b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
650b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
651b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
652b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Replaces the double pushing instruction at the given offset by a simpler
653b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * push instruction, if possible.
654b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
655b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private void replaceDoublePushInstruction(Clazz       clazz,
656b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                              int         offset,
657b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                              Instruction instruction)
658b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
659b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        replaceDoublePushInstruction(clazz,
660b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                     offset,
661b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                     instruction,
662b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                     partialEvaluator.getVariablesBefore(offset).size());
663b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
664b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
665b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
666b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
667b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Replaces the double pushing instruction at the given offset by a simpler
668b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * push instruction, if possible.
669b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
670b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private void replaceDoublePushInstruction(Clazz       clazz,
671b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                              int         offset,
672b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                              Instruction instruction,
673b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                              int         maxVariableIndex)
674b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
675b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
676b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (pushedValue.isParticular())
677b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
678b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            // Push a constant instead.
679b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            // Make sure to distinguish between +0.0 and -0.0.
680b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            double value = pushedValue.doubleValue().value();
681b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            if (value == 0.0 && Double.doubleToLongBits(value) == POS_ZERO_DOUBLE_BITS ||
682b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                value == 1.0)
683b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
684b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                replaceConstantPushInstruction(clazz,
685b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                               offset,
686b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                               instruction,
687b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                               InstructionConstants.OP_DCONST_0,
688b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                               (int)value);
689b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
690b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else
691b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
692b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                ConstantPoolEditor constantPoolEditor =
693b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    new ConstantPoolEditor((ProgramClass)clazz);
694b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
695b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                Instruction replacementInstruction =
696b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    new ConstantInstruction(InstructionConstants.OP_LDC2_W,
697b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                                            constantPoolEditor.addDoubleConstant(value));
698b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
699b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                replaceInstruction(clazz, offset, instruction, replacementInstruction);
700b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
701b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
702b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        else if (pushedValue.isSpecific())
703b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
704b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            // Load an equivalent lower-numbered variable instead, if any.
705b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            TracedVariables variables = partialEvaluator.getVariablesBefore(offset);
706b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            for (int variableIndex = 0; variableIndex < maxVariableIndex; variableIndex++)
707b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
708b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                // Note that we have to check the second part as well.
709b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                if (pushedValue.equals(variables.load(variableIndex)) &&
710b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                    variables.load(variableIndex + 1) != null         &&
711b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                    variables.load(variableIndex + 1).computationalType() == Value.TYPE_TOP)
712b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
713b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    replaceVariablePushInstruction(clazz,
714b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                   offset,
715b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                   instruction,
716b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                   InstructionConstants.OP_DLOAD,
717b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                   variableIndex);
718b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }
719b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
720b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
721b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
722b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
723b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
724b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
725b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Replaces the reference pushing instruction at the given offset by a
726b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * simpler push instruction, if possible.
727b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
728b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private void replaceReferencePushInstruction(Clazz       clazz,
729b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                 int         offset,
730b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                 Instruction instruction)
731b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
732b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
733b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (pushedValue.isParticular())
734b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
735b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // A reference value can only be specific if it is null.
736b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            replaceConstantPushInstruction(clazz,
737b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                           offset,
738b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                           instruction,
739b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                           InstructionConstants.OP_ACONST_NULL,
740b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                           0);
741b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
742b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
743b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
744b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
745b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
746b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Replaces the instruction at a given offset by a given push instruction
747b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * of a constant.
748b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
749b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private void replaceConstantPushInstruction(Clazz       clazz,
750b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                int         offset,
751b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                Instruction instruction,
752b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                byte        replacementOpcode,
753b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                int         value)
754b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
755b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        Instruction replacementInstruction =
756b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            new SimpleInstruction(replacementOpcode, value);
757b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
758b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        replaceInstruction(clazz, offset, instruction, replacementInstruction);
759b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
760b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
761b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
762b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
763b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Replaces the instruction at a given offset by a given push instruction
764b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * of a variable.
765b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
766b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private void replaceVariablePushInstruction(Clazz       clazz,
767b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                int         offset,
768b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                Instruction instruction,
769b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                byte        replacementOpcode,
770b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                int         variableIndex)
771b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
772b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        Instruction replacementInstruction =
773b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            new VariableInstruction(replacementOpcode, variableIndex);
774b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
775b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        replaceInstruction(clazz, offset, instruction, replacementInstruction);
776b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
777b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
778b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
779b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
780b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Replaces the given 'jsr' instruction by a simpler branch instruction,
781b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * if it jumps to a subroutine that doesn't return or a subroutine that
782b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * is only called from one place.
783b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
784b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private void replaceJsrInstruction(Clazz             clazz,
785b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                       int               offset,
786b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                       BranchInstruction branchInstruction)
787b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
788b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Is the subroutine ever returning?
789b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        int subroutineStart = offset + branchInstruction.branchOffset;
790b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (!partialEvaluator.isSubroutineReturning(subroutineStart) ||
791b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            partialEvaluator.branchOrigins(subroutineStart).instructionOffsetCount() == 1)
792b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
793b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // All 'jsr' instructions to this subroutine can be replaced
794b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // by unconditional branch instructions.
795b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            replaceBranchInstruction(clazz, offset, branchInstruction);
796b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
797b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        else if (!partialEvaluator.isTraced(offset + branchInstruction.length(offset)))
798b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
799b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // We have to make sure the instruction after this 'jsr'
800b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // instruction is valid, even if it is never reached.
801b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            replaceByInfiniteLoop(clazz, offset + branchInstruction.length(offset), branchInstruction);
802b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
803b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
804b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
805b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
806b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
807b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Deletes the reference popping instruction at the given offset, if
808b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * it is at the start of a subroutine that doesn't return or a subroutine
809b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * that is only called from one place.
810b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
811b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private void deleteReferencePopInstruction(Clazz       clazz,
812b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                               int         offset,
813b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                               Instruction instruction)
814b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
815b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (partialEvaluator.isSubroutineStart(offset) &&
816b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            (!partialEvaluator.isSubroutineReturning(offset) ||
817b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato             partialEvaluator.branchOrigins(offset).instructionOffsetCount() == 1))
818b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
819b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (DEBUG) System.out.println("  Deleting store of subroutine return address "+instruction.toString(offset));
820b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
821b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // A reference value can only be specific if it is null.
822b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            codeAttributeEditor.deleteInstruction(offset);
823b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
824b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
825b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
826b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
827b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
828b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Deletes the given branch instruction, or replaces it by a simpler branch
829b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * instruction, if possible.
830b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
831b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private void replaceBranchInstruction(Clazz       clazz,
832b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                          int         offset,
833b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                          Instruction instruction)
834b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
835b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        InstructionOffsetValue branchTargets = partialEvaluator.branchTargets(offset);
836b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
837b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Is there exactly one branch target (not from a goto or jsr)?
838b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (branchTargets != null &&
839b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            branchTargets.instructionOffsetCount() == 1)
840b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
841b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Is it branching to the next instruction?
842b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            int branchOffset = branchTargets.instructionOffset(0) - offset;
843b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (branchOffset == instruction.length(offset))
844b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
845b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                if (DEBUG) System.out.println("  Ignoring zero branch instruction at ["+offset+"]");
846b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
847b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            else
848b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
849b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Replace the branch instruction by a simple branch instruction.
850b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                Instruction replacementInstruction =
851b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                    new BranchInstruction(InstructionConstants.OP_GOTO,
852b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                                          branchOffset);
853b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
854b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                replaceInstruction(clazz, offset, instruction, replacementInstruction);
855b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
856b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
857b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
858b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
859b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
860b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
8612270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom     * Replaces the given table switch instruction, if it is based on the value
8622270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom     * of a fixed array. This is typical for switches on simple enums.
8632270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom     */
8642270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom    private void replaceSimpleEnumSwitchInstruction(Clazz                  clazz,
8652270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                                    CodeAttribute          codeAttribute,
8662270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                                    int                    offset,
8672270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                                    TableSwitchInstruction tableSwitchInstruction)
8682270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom    {
8692270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        // Check if the switch instruction is consuming a single value loaded
8702270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        // from a fully specified array.
8712270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        InstructionOffsetValue producerOffsets =
8722270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            partialEvaluator.getStackBefore(offset).getTopProducerValue(0).instructionOffsetValue();
8732270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
8742270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        if (producerOffsets.instructionOffsetCount() == 1)
8752270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        {
8762270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            int producerOffset = producerOffsets.instructionOffset(0);
8772270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
8782270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            if (codeAttribute.code[producerOffset] == InstructionConstants.OP_IALOAD &&
8792270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                !codeAttributeEditor.isModified(producerOffset))
8802270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            {
8812270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                ReferenceValue referenceValue =
8822270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                    partialEvaluator.getStackBefore(producerOffset).getTop(1).referenceValue();
8832270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
8842270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                if (referenceValue.isParticular())
8852270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                {
8862270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                    // Simplify the entire construct.
8872270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                    replaceSimpleEnumSwitchInstruction(clazz,
8882270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                                       codeAttribute,
8892270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                                       producerOffset,
8902270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                                       offset,
8912270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                                       tableSwitchInstruction,
8922270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                                       referenceValue);
8932270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                }
8942270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            }
8952270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        }
8962270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom    }
8972270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
8982270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
8992270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom    /**
9002270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom     * Replaces the given table switch instruction that is based on a value of
9012270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom     * the given fixed array.
9022270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom     */
9032270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom    private void replaceSimpleEnumSwitchInstruction(Clazz                  clazz,
9042270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                                    CodeAttribute          codeAttribute,
9052270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                                    int                    loadOffset,
9062270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                                    int                    switchOffset,
9072270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                                    TableSwitchInstruction tableSwitchInstruction,
9082270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                                    ReferenceValue         mappingValue)
9092270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom    {
9102270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        ValueFactory valueFactory = new ParticularValueFactory();
9112270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
9122270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        // Transform the jump offsets.
9132270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        int[] jumpOffsets    = tableSwitchInstruction.jumpOffsets;
9142270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        int[] newJumpOffsets = new int[mappingValue.arrayLength(valueFactory).value()];
9152270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
9162270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        for (int index = 0; index < newJumpOffsets.length; index++)
9172270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        {
9182270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            int switchCase =
9192270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                mappingValue.integerArrayLoad(valueFactory.createIntegerValue(
9202270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                    index),
9212270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                              valueFactory).value();
9222270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
9232270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            newJumpOffsets[index] =
9242270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                switchCase >= tableSwitchInstruction.lowCase &&
9252270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                switchCase <= tableSwitchInstruction.highCase ?
9262270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                    jumpOffsets[switchCase - tableSwitchInstruction.lowCase] :
9272270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                    tableSwitchInstruction.defaultOffset;
9282270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        }
9292270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
9302270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        // Update the instruction.
9312270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        tableSwitchInstruction.lowCase     = 0;
9322270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        tableSwitchInstruction.highCase    = newJumpOffsets.length - 1;
9332270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        tableSwitchInstruction.jumpOffsets = newJumpOffsets;
9342270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
9352270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        // Replace the original one with the new version.
9362270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        replaceSimpleEnumSwitchInstruction(clazz,
9372270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                           loadOffset,
9382270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                           switchOffset,
9392270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                           tableSwitchInstruction);
9402270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
9412270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        cleanUpSwitchInstruction(clazz, switchOffset, tableSwitchInstruction);
9422270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
9432270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        trimSwitchInstruction(clazz, switchOffset, tableSwitchInstruction);
9442270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom    }
9452270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
9462270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
9472270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom    /**
9482270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom     * Replaces the given look up switch instruction, if it is based on the
9492270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom     * value of a fixed array. This is typical for switches on simple enums.
9502270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom     */
9512270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom    private void replaceSimpleEnumSwitchInstruction(Clazz                   clazz,
9522270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                                    CodeAttribute           codeAttribute,
9532270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                                    int                     offset,
9542270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                                    LookUpSwitchInstruction lookupSwitchInstruction)
9552270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom    {
9562270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        // Check if the switch instruction is consuming a single value loaded
9572270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        // from a fully specified array.
9582270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        InstructionOffsetValue producerOffsets =
9592270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            partialEvaluator.getStackBefore(offset).getTopProducerValue(0).instructionOffsetValue();
9602270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
9612270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        if (producerOffsets.instructionOffsetCount() == 1)
9622270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        {
9632270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            int producerOffset = producerOffsets.instructionOffset(0);
9642270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
9652270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            if (codeAttribute.code[producerOffset] == InstructionConstants.OP_IALOAD &&
9662270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                !codeAttributeEditor.isModified(producerOffset))
9672270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            {
9682270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                ReferenceValue referenceValue =
9692270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                    partialEvaluator.getStackBefore(producerOffset).getTop(1).referenceValue();
9702270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
9712270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                if (referenceValue.isParticular())
9722270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                {
9732270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                    // Simplify the entire construct.
9742270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                    replaceSimpleEnumSwitchInstruction(clazz,
9752270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                                       codeAttribute,
9762270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                                       producerOffset,
9772270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                                       offset,
9782270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                                       lookupSwitchInstruction,
9792270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                                       referenceValue);
9802270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                }
9812270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            }
9822270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        }
9832270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom    }
9842270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
9852270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
9862270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom    /**
9872270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom     * Replaces the given look up switch instruction that is based on a value of
9882270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom     * the given fixed array. This is typical for switches on simple enums.
9892270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom     */
9902270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom    private void replaceSimpleEnumSwitchInstruction(Clazz                   clazz,
9912270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                                    CodeAttribute           codeAttribute,
9922270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                                    int                     loadOffset,
9932270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                                    int                     switchOffset,
9942270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                                    LookUpSwitchInstruction lookupSwitchInstruction,
9952270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                                    ReferenceValue          mappingValue)
9962270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom    {
9972270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        ValueFactory valueFactory = new ParticularValueFactory();
9982270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
9992270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        // Transform the jump offsets.
10002270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        int[] cases          = lookupSwitchInstruction.cases;
10012270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        int[] jumpOffsets    = lookupSwitchInstruction.jumpOffsets;
10022270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        int[] newJumpOffsets = new int[mappingValue.arrayLength(valueFactory).value()];
10032270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
10042270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        for (int index = 0; index < newJumpOffsets.length; index++)
10052270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        {
10062270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            int switchCase =
10072270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                mappingValue.integerArrayLoad(valueFactory.createIntegerValue(index),
10082270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                              valueFactory).value();
10092270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
10102270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            int caseIndex = Arrays.binarySearch(cases, switchCase);
10112270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
10122270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            newJumpOffsets[index] = caseIndex >= 0 ?
10132270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                jumpOffsets[caseIndex] :
10142270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                lookupSwitchInstruction.defaultOffset;
10152270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        }
10162270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
10172270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        // Replace the original lookup switch with a table switch.
10182270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        TableSwitchInstruction replacementSwitchInstruction =
10192270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            new TableSwitchInstruction(InstructionConstants.OP_TABLESWITCH,
10202270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                       lookupSwitchInstruction.defaultOffset,
10212270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                       0,
10222270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                       newJumpOffsets.length - 1,
10232270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                       newJumpOffsets);
10242270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
10252270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        replaceSimpleEnumSwitchInstruction(clazz,
10262270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                           loadOffset,
10272270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                           switchOffset,
10282270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                           replacementSwitchInstruction);
10292270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
10302270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        cleanUpSwitchInstruction(clazz, switchOffset, replacementSwitchInstruction);
10312270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
10322270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        trimSwitchInstruction(clazz, switchOffset, replacementSwitchInstruction);
10332270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom    }
10342270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
10352270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
10362270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom    /**
1037b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Makes sure all branch targets of the given switch instruction are valid.
1038b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
10392270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom    private void cleanUpSwitchInstruction(Clazz             clazz,
1040b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                          int               offset,
1041b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                          SwitchInstruction switchInstruction)
1042b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
1043b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Get the actual branch targets.
1044b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        InstructionOffsetValue branchTargets = partialEvaluator.branchTargets(offset);
1045b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1046b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Get an offset that can serve as a valid default offset.
1047b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        int defaultOffset =
1048b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            branchTargets.instructionOffset(branchTargets.instructionOffsetCount()-1) -
1049b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            offset;
1050b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1051b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        Instruction replacementInstruction = null;
1052b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1053b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Check the jump offsets.
1054b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        int[] jumpOffsets = switchInstruction.jumpOffsets;
1055b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        for (int index = 0; index < jumpOffsets.length; index++)
1056b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
1057b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (!branchTargets.contains(offset + jumpOffsets[index]))
1058b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
1059b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Replace the unused offset.
1060b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                jumpOffsets[index] = defaultOffset;
1061b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1062b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Remember to replace the instruction.
1063b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                replacementInstruction = switchInstruction;
1064b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
1065b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
1066b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1067b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Check the default offset.
1068b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (!branchTargets.contains(offset + switchInstruction.defaultOffset))
1069b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
1070b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Replace the unused offset.
1071b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            switchInstruction.defaultOffset = defaultOffset;
1072b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1073b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Remember to replace the instruction.
1074b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            replacementInstruction = switchInstruction;
1075b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
1076b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1077b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (replacementInstruction != null)
1078b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
1079b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            replaceInstruction(clazz, offset, switchInstruction, replacementInstruction);
1080b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
1081b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
1082b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1083b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1084b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
10852270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom     * Trims redundant offsets from the given switch instruction.
10862270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom     */
10872270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom    private void trimSwitchInstruction(Clazz                  clazz,
10882270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                       int                    offset,
10892270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                       TableSwitchInstruction tableSwitchInstruction)
10902270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom    {
10912270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        // Get an offset that can serve as a valid default offset.
10922270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        int   defaultOffset = tableSwitchInstruction.defaultOffset;
10932270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        int[] jumpOffsets   = tableSwitchInstruction.jumpOffsets;
10942270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        int   length        = jumpOffsets.length;
10952270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
10962270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        // Find the lowest index with a non-default jump offset.
10972270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        int lowIndex = 0;
10982270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        while (lowIndex < length &&
10992270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom               jumpOffsets[lowIndex] == defaultOffset)
11002270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        {
11012270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            lowIndex++;
11022270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        }
11032270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
11042270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        // Find the highest index with a non-default jump offset.
11052270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        int highIndex = length - 1;
11062270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        while (highIndex >= 0 &&
11072270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom               jumpOffsets[highIndex] == defaultOffset)
11082270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        {
11092270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            highIndex--;
11102270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        }
11112270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
11122270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        // Can we use a shorter array?
11132270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        int newLength = highIndex - lowIndex + 1;
11142270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        if (newLength < length)
11152270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        {
11162270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            if (newLength <= 0)
11172270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            {
11182270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                // Replace the switch instruction by a simple branch instruction.
11192270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                Instruction replacementInstruction =
11202270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                    new BranchInstruction(InstructionConstants.OP_GOTO,
11212270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                          defaultOffset);
11222270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
11232270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                replaceInstruction(clazz, offset, tableSwitchInstruction,
11242270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                   replacementInstruction);
11252270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            }
11262270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            else
11272270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            {
11282270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                // Trim the array.
11292270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                int[] newJumpOffsets = new int[newLength];
11302270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
11312270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                System.arraycopy(jumpOffsets, lowIndex, newJumpOffsets, 0, newLength);
11322270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
11332270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                tableSwitchInstruction.jumpOffsets = newJumpOffsets;
11342270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                tableSwitchInstruction.lowCase    += lowIndex;
11352270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                tableSwitchInstruction.highCase   -= length - newLength - lowIndex;
11362270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
11372270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                replaceInstruction(clazz, offset, tableSwitchInstruction,
11382270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                   tableSwitchInstruction);
11392270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            }
11402270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        }
11412270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom    }
11422270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
11432270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
11442270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom    /**
11452270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom     * Trims redundant offsets from the given switch instruction.
11462270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom     */
11472270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom    private void trimSwitchInstruction(Clazz                   clazz,
11482270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                       int                     offset,
11492270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                       LookUpSwitchInstruction lookUpSwitchInstruction)
11502270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom    {
11512270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        // Get an offset that can serve as a valid default offset.
11522270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        int   defaultOffset = lookUpSwitchInstruction.defaultOffset;
11532270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        int[] jumpOffsets   = lookUpSwitchInstruction.jumpOffsets;
11542270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        int   length        = jumpOffsets.length;
11552270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        int   newLength     = length;
11562270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
11572270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        // Count the default jump offsets.
11582270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        for (int index = 0; index < length; index++)
11592270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        {
11602270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            if (jumpOffsets[index] == defaultOffset)
11612270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            {
11622270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                newLength--;
11632270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            }
11642270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        }
11652270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
11662270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        // Can we use shorter arrays?
11672270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        if (newLength < length)
11682270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        {
11692270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            if (newLength <= 0)
11702270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            {
11712270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                // Replace the switch instruction by a simple branch instruction.
11722270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                Instruction replacementInstruction =
11732270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                    new BranchInstruction(InstructionConstants.OP_GOTO,
11742270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                          defaultOffset);
11752270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
11762270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                replaceInstruction(clazz, offset, lookUpSwitchInstruction,
11772270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                   replacementInstruction);
11782270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            }
11792270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            else
11802270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            {
11812270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                // Remove redundant entries from the arrays.
11822270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                int[] cases          = lookUpSwitchInstruction.cases;
11832270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                int[] newJumpOffsets = new int[newLength];
11842270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                int[] newCases       = new int[newLength];
11852270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
11862270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                int newIndex = 0;
11872270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
11882270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                for (int index = 0; index < length; index++)
11892270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                {
11902270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                    if (jumpOffsets[index] != defaultOffset)
11912270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                    {
11922270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                        newJumpOffsets[newIndex] = jumpOffsets[index];
11932270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                        newCases[newIndex++]     = cases[index];
11942270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                    }
11952270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                }
11962270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
11972270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                lookUpSwitchInstruction.jumpOffsets = newJumpOffsets;
11982270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                lookUpSwitchInstruction.cases       = newCases;
11992270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
12002270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                replaceInstruction(clazz, offset, lookUpSwitchInstruction,
12012270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                   lookUpSwitchInstruction);
12022270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            }
12032270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        }
12042270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom    }
12052270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
12062270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
12072270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom    /**
1208b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Replaces the given instruction by an infinite loop.
1209b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
1210b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private void replaceByInfiniteLoop(Clazz       clazz,
1211b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                       int         offset,
1212b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                       Instruction instruction)
1213b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
1214b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Replace the instruction by an infinite loop.
1215b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        Instruction replacementInstruction =
1216b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            new BranchInstruction(InstructionConstants.OP_GOTO, 0);
1217b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1218b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (DEBUG) System.out.println("  Replacing unreachable instruction by infinite loop "+replacementInstruction.toString(offset));
1219b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1220b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        codeAttributeEditor.replaceInstruction(offset, replacementInstruction);
1221b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1222b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Visit the instruction, if required.
1223b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (extraInstructionVisitor != null)
1224b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
1225b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Note: we're not passing the right arguments for now, knowing that
1226b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // they aren't used anyway.
12272270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            instruction.accept(clazz,
12282270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                               null,
12292270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                               null,
12302270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                               offset,
12312270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                               extraInstructionVisitor);
1232b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
1233b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
1234b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1235b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1236b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
1237b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Replaces the instruction at a given offset by a given push instruction.
1238b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
1239b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private void replaceInstruction(Clazz       clazz,
1240b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    int         offset,
1241b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    Instruction instruction,
1242b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                    Instruction replacementInstruction)
1243b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
1244b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Pop unneeded stack entries if necessary.
1245b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        int popCount =
1246b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            instruction.stackPopCount(clazz) -
1247b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            replacementInstruction.stackPopCount(clazz);
1248b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1249b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        insertPopInstructions(offset, popCount);
1250b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1251b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (DEBUG) System.out.println("  Replacing instruction "+instruction.toString(offset)+" -> "+replacementInstruction.toString()+(popCount == 0 ? "" : " ("+popCount+" pops)"));
1252b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1253b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        codeAttributeEditor.replaceInstruction(offset, replacementInstruction);
1254b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1255b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Visit the instruction, if required.
1256b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (extraInstructionVisitor != null)
1257b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
1258b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Note: we're not passing the right arguments for now, knowing that
1259b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // they aren't used anyway.
1260b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            instruction.accept(clazz, null, null, offset, extraInstructionVisitor);
1261b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
1262b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
1263b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1264b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1265b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
1266b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Pops the given number of stack entries before the instruction at the
1267b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * given offset.
1268b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
1269b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private void insertPopInstructions(int offset, int popCount)
1270b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
1271b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        switch (popCount)
1272b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
1273b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case 0:
1274b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
1275b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                break;
1276b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
1277b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case 1:
1278b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
1279b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Insert a single pop instruction.
1280b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                Instruction popInstruction =
1281b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    new SimpleInstruction(InstructionConstants.OP_POP);
1282b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1283b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                codeAttributeEditor.insertBeforeInstruction(offset,
1284b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                            popInstruction);
1285b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                break;
1286b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
1287b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case 2:
1288b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
1289b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Insert a single pop2 instruction.
1290b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                Instruction popInstruction =
1291b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    new SimpleInstruction(InstructionConstants.OP_POP2);
1292b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1293b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                codeAttributeEditor.insertBeforeInstruction(offset,
1294b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                            popInstruction);
1295b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                break;
1296b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
1297b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            default:
1298b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
1299b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Insert the specified number of pop instructions.
1300b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                Instruction[] popInstructions =
1301b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    new Instruction[popCount / 2 + popCount % 2];
1302b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1303b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                Instruction popInstruction =
1304b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    new SimpleInstruction(InstructionConstants.OP_POP2);
1305b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1306b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                for (int index = 0; index < popCount / 2; index++)
1307b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
1308b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                      popInstructions[index] = popInstruction;
1309b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }
1310b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1311b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                if (popCount % 2 == 1)
1312b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
1313b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    popInstruction =
1314b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        new SimpleInstruction(InstructionConstants.OP_POP);
1315b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1316b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    popInstructions[popCount / 2] = popInstruction;
1317b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }
1318b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1319b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                codeAttributeEditor.insertBeforeInstruction(offset,
1320b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                            popInstructions);
1321b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                break;
1322b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
1323b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
1324b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
13252270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
13262270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
13272270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom    /**
13282270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom     * Replaces the simple enum switch instructions at a given offsets by a
13292270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom     * given replacement instruction.
13302270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom     */
13312270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom    private void replaceSimpleEnumSwitchInstruction(Clazz             clazz,
13322270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                                    int               loadOffset,
13332270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                                    int               switchOffset,
13342270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                                    SwitchInstruction replacementSwitchInstruction)
13352270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom    {
13362270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        if (DEBUG) System.out.println("  Replacing switch instruction at ["+switchOffset+"] -> ["+loadOffset+"] swap + pop, "+replacementSwitchInstruction.toString(switchOffset)+")");
13372270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
13382270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        // Remove the array load instruction.
13392270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        codeAttributeEditor.replaceInstruction(loadOffset, new Instruction[]
13402270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            {
13412270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                new SimpleInstruction(InstructionConstants.OP_SWAP),
13422270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                new SimpleInstruction(InstructionConstants.OP_POP),
13432270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            });
13442270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
13452270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        // Replace the switch instruction.
13462270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        codeAttributeEditor.replaceInstruction(switchOffset, replacementSwitchInstruction);
13472270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom
13482270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        // Visit the instruction, if required.
13492270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        if (extraInstructionVisitor != null)
13502270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        {
13512270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            // Note: we're not passing the right arguments for now, knowing that
13522270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            // they aren't used anyway.
13532270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom            replacementSwitchInstruction.accept(clazz,
13542270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                                null,
13552270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                                null,
13562270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                                switchOffset,
13572270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom                                                extraInstructionVisitor);
13582270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom        }
13592270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom    }
1360b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato}
1361