1 /* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5 /* 6 * Licensed to the Apache Software Foundation (ASF) under one or more 7 * contributor license agreements. See the NOTICE file distributed with 8 * this work for additional information regarding copyright ownership. 9 * The ASF licenses this file to You under the Apache License, Version 2.0 10 * (the "License"); you may not use this file except in compliance with 11 * the License. You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 */ 21 package com.sun.org.apache.bcel.internal.generic; 22 23 import com.sun.org.apache.bcel.internal.Const; 24 import com.sun.org.apache.bcel.internal.classfile.LocalVariable; 25 26 /** 27 * Represents a local variable within a method. It contains its 28 * scope, name and type. The generated LocalVariable object can be obtained 29 * with getLocalVariable which needs the instruction list and the constant 30 * pool as parameters. 31 * 32 * @see LocalVariable 33 * @see MethodGen 34 */ 35 public class LocalVariableGen implements InstructionTargeter, NamedAndTyped, Cloneable { 36 37 private int index; 38 private String name; 39 private Type type; 40 private InstructionHandle start; 41 private InstructionHandle end; 42 private int orig_index; // never changes; used to match up with LocalVariableTypeTable entries 43 private boolean live_to_end; 44 45 46 /** 47 * Generate a local variable that with index `index'. Note that double and long 48 * variables need two indexs. Index indices have to be provided by the user. 49 * 50 * @param index index of local variable 51 * @param name its name 52 * @param type its type 53 * @param start from where the instruction is valid (null means from the start) 54 * @param end until where the instruction is valid (null means to the end) 55 */ LocalVariableGen(final int index, final String name, final Type type, final InstructionHandle start, final InstructionHandle end)56 public LocalVariableGen(final int index, final String name, final Type type, final InstructionHandle start, 57 final InstructionHandle end) { 58 if ((index < 0) || (index > Const.MAX_SHORT)) { 59 throw new ClassGenException("Invalid index index: " + index); 60 } 61 this.name = name; 62 this.type = type; 63 this.index = index; 64 setStart(start); 65 setEnd(end); 66 this.orig_index = index; 67 this.live_to_end = end == null; 68 } 69 70 71 /** 72 * Generates a local variable that with index `index'. Note that double and long 73 * variables need two indexs. Index indices have to be provided by the user. 74 * 75 * @param index index of local variable 76 * @param name its name 77 * @param type its type 78 * @param start from where the instruction is valid (null means from the start) 79 * @param end until where the instruction is valid (null means to the end) 80 * @param orig_index index of local variable prior to any changes to index 81 */ LocalVariableGen(final int index, final String name, final Type type, final InstructionHandle start, final InstructionHandle end, final int orig_index)82 public LocalVariableGen(final int index, final String name, final Type type, final InstructionHandle start, 83 final InstructionHandle end, final int orig_index) { 84 this(index, name, type, start, end); 85 this.orig_index = orig_index; 86 } 87 88 89 /** 90 * Gets LocalVariable object. 91 * 92 * This relies on that the instruction list has already been dumped to byte code or 93 * or that the `setPositions' methods has been called for the instruction list. 94 * 95 * Note that due to the conversion from byte code offset to InstructionHandle, 96 * it is impossible to tell the difference between a live range that ends BEFORE 97 * the last insturction of the method or a live range that ends AFTER the last 98 * instruction of the method. Hence the live_to_end flag to differentiate 99 * between these two cases. 100 * 101 * @param cp constant pool 102 */ getLocalVariable( final ConstantPoolGen cp )103 public LocalVariable getLocalVariable( final ConstantPoolGen cp ) { 104 int start_pc = 0; 105 int length = 0; 106 if ((start != null) && (end != null)) { 107 start_pc = start.getPosition(); 108 length = end.getPosition() - start_pc; 109 if ((end.getNext() == null) && live_to_end) { 110 length += end.getInstruction().getLength(); 111 } 112 } 113 final int name_index = cp.addUtf8(name); 114 final int signature_index = cp.addUtf8(type.getSignature()); 115 return new LocalVariable(start_pc, length, name_index, signature_index, index, cp 116 .getConstantPool(), orig_index); 117 } 118 119 setIndex( final int index )120 public void setIndex( final int index ) { 121 this.index = index; 122 } 123 124 getIndex()125 public int getIndex() { 126 return index; 127 } 128 129 getOrigIndex()130 public int getOrigIndex() { 131 return orig_index; 132 } 133 134 setLiveToEnd( final boolean live_to_end)135 public void setLiveToEnd( final boolean live_to_end) { 136 this.live_to_end = live_to_end; 137 } 138 139 getLiveToEnd()140 public boolean getLiveToEnd() { 141 return live_to_end; 142 } 143 144 145 @Override setName( final String name )146 public void setName( final String name ) { 147 this.name = name; 148 } 149 150 151 @Override getName()152 public String getName() { 153 return name; 154 } 155 156 157 @Override setType( final Type type )158 public void setType( final Type type ) { 159 this.type = type; 160 } 161 162 163 @Override getType()164 public Type getType() { 165 return type; 166 } 167 168 getStart()169 public InstructionHandle getStart() { 170 return start; 171 } 172 173 getEnd()174 public InstructionHandle getEnd() { 175 return end; 176 } 177 178 setStart( final InstructionHandle start )179 public void setStart( final InstructionHandle start ) { // TODO could be package-protected? 180 BranchInstruction.notifyTarget(this.start, start, this); 181 this.start = start; 182 } 183 184 setEnd( final InstructionHandle end )185 public void setEnd( final InstructionHandle end ) { // TODO could be package-protected? 186 BranchInstruction.notifyTarget(this.end, end, this); 187 this.end = end; 188 } 189 190 191 /** 192 * @param old_ih old target, either start or end 193 * @param new_ih new target 194 */ 195 @Override updateTarget( final InstructionHandle old_ih, final InstructionHandle new_ih )196 public void updateTarget( final InstructionHandle old_ih, final InstructionHandle new_ih ) { 197 boolean targeted = false; 198 if (start == old_ih) { 199 targeted = true; 200 setStart(new_ih); 201 } 202 if (end == old_ih) { 203 targeted = true; 204 setEnd(new_ih); 205 } 206 if (!targeted) { 207 throw new ClassGenException("Not targeting " + old_ih + ", but {" + start + ", " + end 208 + "}"); 209 } 210 } 211 212 /** 213 * Clear the references from and to this variable when it's removed. 214 */ dispose()215 void dispose() { 216 setStart(null); 217 setEnd(null); 218 } 219 220 /** 221 * @return true, if ih is target of this variable 222 */ 223 @Override containsTarget( final InstructionHandle ih )224 public boolean containsTarget( final InstructionHandle ih ) { 225 return (start == ih) || (end == ih); 226 } 227 228 229 @Override hashCode()230 public int hashCode() { 231 // If the user changes the name or type, problems with the targeter hashmap will occur. 232 // Note: index cannot be part of hash as it may be changed by the user. 233 return name.hashCode() ^ type.hashCode(); 234 } 235 236 237 /** 238 * We consider to local variables to be equal, if the use the same index and 239 * are valid in the same range. 240 */ 241 @Override equals( final Object o )242 public boolean equals( final Object o ) { 243 if (!(o instanceof LocalVariableGen)) { 244 return false; 245 } 246 final LocalVariableGen l = (LocalVariableGen) o; 247 return (l.index == index) && (l.start == start) && (l.end == end); 248 } 249 250 251 @Override toString()252 public String toString() { 253 return "LocalVariableGen(" + name + ", " + type + ", " + start + ", " + end + ")"; 254 } 255 256 257 @Override clone()258 public Object clone() { 259 try { 260 return super.clone(); 261 } catch (final CloneNotSupportedException e) { 262 throw new Error("Clone Not Supported"); // never happens 263 } 264 } 265 } 266