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