1 21 package proguard.classfile.instruction; 22 23 import proguard.classfile.*; 24 import proguard.classfile.instruction.visitor.InstructionVisitor; 25 import proguard.classfile.attribute.*; 26 27 33 public class BranchInstruction extends Instruction 34 { 35 public int branchOffset; 36 37 38 41 public BranchInstruction() {} 42 43 44 public BranchInstruction(byte opcode, int branchOffset) 45 { 46 this.opcode = opcode; 47 this.branchOffset = branchOffset; 48 } 49 50 51 56 public BranchInstruction copy(BranchInstruction branchInstruction) 57 { 58 this.opcode = branchInstruction.opcode; 59 this.branchOffset = branchInstruction.branchOffset; 60 61 return this; 62 } 63 64 65 67 public byte canonicalOpcode() 68 { 69 switch (opcode) 71 { 72 case InstructionConstants.OP_GOTO_W: return InstructionConstants.OP_GOTO; 73 74 case InstructionConstants.OP_JSR_W: return InstructionConstants.OP_JSR; 75 76 default: return opcode; 77 } 78 } 79 80 public Instruction shrink() 81 { 82 if (requiredBranchOffsetSize() == 2) 84 { 85 if (opcode == InstructionConstants.OP_GOTO_W) 87 { 88 opcode = InstructionConstants.OP_GOTO; 89 } 90 else if (opcode == InstructionConstants.OP_JSR_W) 91 { 92 opcode = InstructionConstants.OP_JSR; 93 } 94 } 95 else 96 { 97 if (opcode == InstructionConstants.OP_GOTO) 99 { 100 opcode = InstructionConstants.OP_GOTO_W; 101 } 102 else if (opcode == InstructionConstants.OP_JSR) 103 { 104 opcode = InstructionConstants.OP_JSR_W; 105 } 106 else 107 { 108 throw new IllegalArgumentException ("Branch instruction can't be widened ("+this.toString()+")"); 109 } 110 } 111 112 return this; 113 } 114 115 protected void readInfo(byte[] code, int offset) 116 { 117 branchOffset = readSignedValue(code, offset, branchOffsetSize()); 118 } 119 120 121 protected void writeInfo(byte[] code, int offset) 122 { 123 if (requiredBranchOffsetSize() > branchOffsetSize()) 124 { 125 throw new IllegalArgumentException ("Instruction has invalid branch offset size ("+this.toString(offset)+")"); 126 } 127 128 writeSignedValue(code, offset, branchOffset, branchOffsetSize()); 129 } 130 131 132 public int length(int offset) 133 { 134 return 1 + branchOffsetSize(); 135 } 136 137 138 public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, InstructionVisitor instructionVisitor) 139 { 140 instructionVisitor.visitBranchInstruction(clazz, method, codeAttribute, offset, this); 141 } 142 143 144 public String toString(int offset) 145 { 146 return "["+offset+"] "+toString()+" (target="+(offset+branchOffset)+")"; 147 } 148 149 150 152 public String toString() 153 { 154 return getName()+" "+(branchOffset >= 0 ? "+" : "")+branchOffset; 155 } 156 157 158 160 163 private int branchOffsetSize() 164 { 165 return opcode == InstructionConstants.OP_GOTO_W || 166 opcode == InstructionConstants.OP_JSR_W ? 4 : 167 2; 168 } 169 170 171 175 private int requiredBranchOffsetSize() 176 { 177 return branchOffset << 16 >> 16 == branchOffset ? 2 : 178 4; 179 } 180 } 181 | Popular Tags |