1b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/* 2b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * ProGuard -- shrinking, optimization, obfuscation, and preverification 3b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * of Java bytecode. 4b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 5b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) 6b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 7b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This program is free software; you can redistribute it and/or modify it 8b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * under the terms of the GNU General Public License as published by the Free 9b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Software Foundation; either version 2 of the License, or (at your option) 10b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * any later version. 11b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 12b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This program is distributed in the hope that it will be useful, but WITHOUT 13b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * more details. 16b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 17b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * You should have received a copy of the GNU General Public License along 18b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * with this program; if not, write to the Free Software Foundation, Inc., 19b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 21b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratopackage proguard.classfile.editor; 22b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 23b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.*; 24b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.attribute.CodeAttribute; 25b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.attribute.visitor.AttributeVisitor; 26b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.instruction.*; 27b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.instruction.visitor.InstructionVisitor; 28b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.util.SimplifiedVisitor; 29b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 30b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/** 31b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This InstructionVisitor writes out the instructions that it visits, 32b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * collecting instructions that have to be widened. As an AttributeVisitor, 33b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * it then applies the collected changes. The process will be repeated 34b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * recursively, if necessary. The caller still has to update the frame sizes. 35b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 36b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @author Eric Lafortune 37b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 38b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratopublic class InstructionWriter 39b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoextends SimplifiedVisitor 40b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimplements InstructionVisitor, 41b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato AttributeVisitor 42b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato{ 43b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang //* 44b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang private static final boolean DEBUG = false; 45b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang /*/ 46b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang public static boolean DEBUG = false; 47b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang //*/ 48b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 49b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 50b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private int codeLength; 51b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 52b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private CodeAttributeEditor codeAttributeEditor; 53b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 54b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 55b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 56b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * Resets the accumulated code. 57b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param codeLength the length of the code that will be edited next. 58b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 59b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void reset(int codeLength) 60b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 61b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato this.codeLength = codeLength; 62b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 63b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (codeAttributeEditor != null) 64b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 65b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato codeAttributeEditor.reset(codeLength); 66b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 67b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 68b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 69b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 70b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang /** 71b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * Extends the size of the accumulated code. 72b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * @param codeLength the length of the code that will be edited next. 73b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang */ 74b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang public void extend(int codeLength) 75b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang { 76b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang this.codeLength = codeLength; 77b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 78b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang if (codeAttributeEditor != null) 79b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang { 80b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang codeAttributeEditor.extend(codeLength); 81b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang } 82b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang } 83b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 84b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 85b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Implementations for InstructionVisitor. 86b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 87b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction) 88b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 89b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Try to write out the instruction. 90b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Simple instructions should always fit. 91b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato simpleInstruction.write(codeAttribute, offset); 92b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 93b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 94b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 95b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction) 96b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 97b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato try 98b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 99b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Try to write out the instruction. 100b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato constantInstruction.write(codeAttribute, offset); 101b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 102b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato catch (IllegalArgumentException exception) 103b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 104b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Create a new constant instruction that will fit. 105b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction replacementInstruction = 106b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new ConstantInstruction(constantInstruction.opcode, 107b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato constantInstruction.constantIndex, 108b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang constantInstruction.constant); 109b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 110b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang if (DEBUG) 111b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang { 112b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang System.out.println(" "+constantInstruction.toString(offset)+" will be widened to "+replacementInstruction.toString()); 113b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang } 114b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 115b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceInstruction(offset, replacementInstruction); 116b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 117b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Write out a dummy constant instruction for now. 118b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato constantInstruction.constantIndex = 0; 119b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato constantInstruction.constant = 0; 120b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato constantInstruction.write(codeAttribute, offset); 121b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 122b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 123b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 124b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 125b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction) 126b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 127b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato try 128b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 129b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Try to write out the instruction. 130b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato variableInstruction.write(codeAttribute, offset); 131b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 132b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato catch (IllegalArgumentException exception) 133b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 134b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Create a new variable instruction that will fit. 135b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction replacementInstruction = 136b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new VariableInstruction(variableInstruction.opcode, 137b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato variableInstruction.variableIndex, 138b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang variableInstruction.constant); 139b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 140b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceInstruction(offset, replacementInstruction); 141b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 142b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang if (DEBUG) 143b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang { 144b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang System.out.println(" "+variableInstruction.toString(offset)+" will be widened to "+replacementInstruction.toString()); 145b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang } 146b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 147b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Write out a dummy variable instruction for now. 148b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato variableInstruction.variableIndex = 0; 149b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato variableInstruction.constant = 0; 150b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato variableInstruction.write(codeAttribute, offset); 151b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 152b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 153b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 154b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 155b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction) 156b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 157b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato try 158b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 159b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Try to write out the instruction. 160b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato branchInstruction.write(codeAttribute, offset); 161b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 162b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato catch (IllegalArgumentException exception) 163b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 164b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Create a new unconditional branch that will fit. 165b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction replacementInstruction = 166b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new BranchInstruction(InstructionConstants.OP_GOTO_W, 167b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato branchInstruction.branchOffset); 168b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 169b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Create a new instruction that will fit. 170b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato switch (branchInstruction.opcode) 171b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 172b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato default: 173b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 174b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Create a new branch instruction that will fit. 175b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replacementInstruction = 176b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new BranchInstruction(branchInstruction.opcode, 177b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang branchInstruction.branchOffset); 178b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 179b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato break; 180b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 181b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 182b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Some special cases, for which a wide branch doesn't exist. 183b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_IFEQ: 184b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_IFNE: 185b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_IFLT: 186b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_IFGE: 187b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_IFGT: 188b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_IFLE: 189b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_IFICMPEQ: 190b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_IFICMPNE: 191b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_IFICMPLT: 192b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_IFICMPGE: 193b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_IFICMPGT: 194b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_IFICMPLE: 195b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_IFACMPEQ: 196b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_IFACMPNE: 197b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 198b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Insert the complementary conditional branch. 199b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction complementaryConditionalBranch = 200b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new BranchInstruction((byte)(((branchInstruction.opcode+1) ^ 1) - 1), 201b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato (1+2) + (1+4)); 202b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 203b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato insertBeforeInstruction(offset, complementaryConditionalBranch); 204b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 205b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Create a new unconditional branch that will fit. 206b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato break; 207b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 208b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 209b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_IFNULL: 210b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_IFNONNULL: 211b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 212b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Insert the complementary conditional branch. 213b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction complementaryConditionalBranch = 214b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new BranchInstruction((byte)(branchInstruction.opcode ^ 1), 215b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato (1+2) + (1+4)); 216b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 217b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato insertBeforeInstruction(offset, complementaryConditionalBranch); 218b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 219b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Create a new unconditional branch that will fit. 220b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato break; 221b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 222b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 223b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 224b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang if (DEBUG) 225b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang { 226b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang System.out.println(" "+branchInstruction.toString(offset)+" will be widened to "+replacementInstruction.toString()); 227b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang } 228b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 229b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceInstruction(offset, replacementInstruction); 230b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 231b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Write out a dummy branch instruction for now. 232b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato branchInstruction.branchOffset = 0; 233b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato branchInstruction.write(codeAttribute, offset); 234b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 235b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 236b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 237b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 238b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitAnySwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SwitchInstruction switchInstruction) 239b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 240b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Try to write out the instruction. 241b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Switch instructions should always fit. 242b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato switchInstruction.write(codeAttribute, offset); 243b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 244b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 245b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 246b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Implementations for AttributeVisitor. 247b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 248b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) 249b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 250b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Avoid doing any work if nothing is changing anyway. 251b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (codeAttributeEditor != null) 252b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 253b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang if (DEBUG) 254b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang { 255b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang System.out.println("InstructionWriter: widening instructions in "+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)); 256b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang } 257b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 258b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Apply the collected expansions. 259b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato codeAttributeEditor.visitCodeAttribute(clazz, method, codeAttribute); 260b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 261b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Don't keep the editor around. We're assuming it won't be needed 262b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // very often, so we don't want to be resetting it all the time. 263b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato codeAttributeEditor = null; 264b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 265b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 266b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 267b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 268b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Small utility methods. 269b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 270b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 271b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Remembers to place the given instruction right before the instruction 272b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * at the given offset. 273b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 274b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private void insertBeforeInstruction(int instructionOffset, Instruction instruction) 275b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 276b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ensureCodeAttributeEditor(); 277b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 278b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Replace the instruction. 279b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato codeAttributeEditor.insertBeforeInstruction(instructionOffset, instruction); 280b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 281b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 282b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 283b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 284b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Remembers to replace the instruction at the given offset by the given 285b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * instruction. 286b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 287b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private void replaceInstruction(int instructionOffset, Instruction instruction) 288b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 289b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ensureCodeAttributeEditor(); 290b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 291b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Replace the instruction. 292b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato codeAttributeEditor.replaceInstruction(instructionOffset, instruction); 293b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 294b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 295b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 296b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 297b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Remembers to place the given instruction right after the instruction 298b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * at the given offset. 299b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 300b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private void insertAfterInstruction(int instructionOffset, Instruction instruction) 301b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 302b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ensureCodeAttributeEditor(); 303b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 304b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Replace the instruction. 305b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato codeAttributeEditor.insertAfterInstruction(instructionOffset, instruction); 306b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 307b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 308b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 309b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 310b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Makes sure there is a code attribute editor for the given code attribute. 311b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 312b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private void ensureCodeAttributeEditor() 313b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 314b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (codeAttributeEditor == null) 315b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 316b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang codeAttributeEditor = new CodeAttributeEditor(false, true); 317b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato codeAttributeEditor.reset(codeLength); 318b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 319b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 320b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato} 321