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