View Javadoc
1 package org.apache.bcel.generic; 2 3 /* ==================================================================== 4 * The Apache Software License, Version 1.1 5 * 6 * Copyright (c) 2001 The Apache Software Foundation. All rights 7 * reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in 18 * the documentation and/or other materials provided with the 19 * distribution. 20 * 21 * 3. The end-user documentation included with the redistribution, 22 * if any, must include the following acknowledgment: 23 * "This product includes software developed by the 24 * Apache Software Foundation (http://www.apache.org/)." 25 * Alternately, this acknowledgment may appear in the software itself, 26 * if and wherever such third-party acknowledgments normally appear. 27 * 28 * 4. The names "Apache" and "Apache Software Foundation" and 29 * "Apache BCEL" must not be used to endorse or promote products 30 * derived from this software without prior written permission. For 31 * written permission, please contact apache@apache.org. 32 * 33 * 5. Products derived from this software may not be called "Apache", 34 * "Apache BCEL", nor may "Apache" appear in their name, without 35 * prior written permission of the Apache Software Foundation. 36 * 37 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 38 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 39 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 40 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 41 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 43 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 44 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 45 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 46 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 47 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 48 * SUCH DAMAGE. 49 * ==================================================================== 50 * 51 * This software consists of voluntary contributions made by many 52 * individuals on behalf of the Apache Software Foundation. For more 53 * information on the Apache Software Foundation, please see 54 * <http://www.apache.org/>;. 55 */ 56 57 import org.apache.bcel.classfile.Utility; 58 import java.util.HashSet; 59 import java.util.Collection; 60 import java.util.HashMap; 61 62 /*** 63 * Instances of this class give users a handle to the instructions contained in 64 * an InstructionList. Instruction objects may be used more than once within a 65 * list, this is useful because it saves memory and may be much faster. 66 * 67 * Within an InstructionList an InstructionHandle object is wrapped 68 * around all instructions, i.e., it implements a cell in a 69 * doubly-linked list. From the outside only the next and the 70 * previous instruction (handle) are accessible. One 71 * can traverse the list via an Enumeration returned by 72 * InstructionList.elements(). 73 * 74 * @version $Id: InstructionHandle.java,v 1.1.1.1 2001/10/29 20:00:19 jvanzyl Exp $ 75 * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> 76 * @see Instruction 77 * @see BranchHandle 78 * @see InstructionList 79 */ 80 public class InstructionHandle implements java.io.Serializable { 81 InstructionHandle next, prev; // Will be set from the outside 82 Instruction instruction; 83 protected int i_position = -1; // byte code offset of instruction 84 private HashSet targeters; 85 private HashMap attributes; 86 87 public final InstructionHandle getNext() { return next; } 88 public final InstructionHandle getPrev() { return prev; } 89 public final Instruction getInstruction() { return instruction; } 90 91 /*** 92 * Replace current instruction contained in this handle. 93 * Old instruction is disposed using Instruction.dispose(). 94 */ 95 public void setInstruction(Instruction i) { // Overridden in BranchHandle 96 if(i == null) 97 throw new ClassGenException("Assigning null to handle"); 98 99 if((this.getClass() != BranchHandle.class) && (i instanceof BranchInstruction)) 100 throw new ClassGenException("Assigning branch instruction " + i + " to plain handle"); 101 102 if(instruction != null) 103 instruction.dispose(); 104 105 instruction = i; 106 } 107 108 /*** 109 * Temporarily swap the current instruction, without disturbing 110 * anything. Meant to be used by a debugger, implementing 111 * breakpoints. Current instruction is returned. 112 */ 113 public Instruction swapInstruction(Instruction i) { 114 Instruction oldInstruction = instruction; 115 instruction = i; 116 return oldInstruction; 117 } 118 119 /*private*/ protected InstructionHandle(Instruction i) { 120 setInstruction(i); 121 } 122 123 private static InstructionHandle ih_list = null; // List of reusable handles 124 125 /*** Factory method. 126 */ 127 static final InstructionHandle getInstructionHandle(Instruction i) { 128 if(ih_list == null) 129 return new InstructionHandle(i); 130 else { 131 InstructionHandle ih = ih_list; 132 ih_list = ih.next; 133 134 ih.setInstruction(i); 135 136 return ih; 137 } 138 } 139 140 /*** 141 * Called by InstructionList.setPositions when setting the position for every 142 * instruction. In the presence of variable length instructions `setPositions()' 143 * performs multiple passes over the instruction list to calculate the 144 * correct (byte) positions and offsets by calling this function. 145 * 146 * @param offset additional offset caused by preceding (variable length) instructions 147 * @param max_offset the maximum offset that may be caused by these instructions 148 * @return additional offset caused by possible change of this instruction's length 149 */ 150 protected int updatePosition(int offset, int max_offset) { 151 i_position += offset; 152 return 0; 153 } 154 155 /*** @return the position, i.e., the byte code offset of the contained 156 * instruction. This is accurate only after 157 * InstructionList.setPositions() has been called. 158 */ 159 public int getPosition() { return i_position; } 160 161 /*** Set the position, i.e., the byte code offset of the contained 162 * instruction. 163 */ 164 void setPosition(int pos) { i_position = pos; } 165 166 /*** Overridden in BranchHandle 167 */ 168 protected void addHandle() { 169 next = ih_list; 170 ih_list = this; 171 } 172 173 /*** 174 * Delete contents, i.e., remove user access and make handle reusable. 175 */ 176 void dispose() { 177 next = prev = null; 178 instruction.dispose(); 179 instruction = null; 180 i_position = -1; 181 attributes = null; 182 removeAllTargeters(); 183 addHandle(); 184 } 185 186 /*** Remove all targeters, if any. 187 */ 188 public void removeAllTargeters() { 189 if(targeters != null) 190 targeters.clear(); 191 } 192 193 /*** 194 * Denote this handle isn't referenced anymore by t. 195 */ 196 public void removeTargeter(InstructionTargeter t) { 197 targeters.remove(t); 198 } 199 200 /*** 201 * Denote this handle is being referenced by t. 202 */ 203 public void addTargeter(InstructionTargeter t) { 204 if(targeters == null) 205 targeters = new HashSet(); 206 207 //if(!targeters.contains(t)) 208 targeters.add(t); 209 } 210 211 public boolean hasTargeters() { 212 return (targeters != null) && (targeters.size() > 0); 213 } 214 215 /*** 216 * @return null, if there are no targeters 217 */ 218 public InstructionTargeter[] getTargeters() { 219 if(!hasTargeters()) 220 return null; 221 222 InstructionTargeter[] t = new InstructionTargeter[targeters.size()]; 223 targeters.toArray(t); 224 return t; 225 } 226 227 /*** @return a (verbose) string representation of the contained instruction. 228 */ 229 public String toString(boolean verbose) { 230 return Utility.format(i_position, 4, false, ' ') + ": " + instruction.toString(verbose); 231 } 232 233 /*** @return a string representation of the contained instruction. 234 */ 235 public String toString() { 236 return toString(true); 237 } 238 239 /*** Add an attribute to an instruction handle. 240 * 241 * @param key the key object to store/retrieve the attribute 242 * @param attr the attribute to associate with this handle 243 */ 244 public void addAttribute(Object key, Object attr) { 245 if(attributes == null) 246 attributes = new HashMap(3); 247 248 attributes.put(key, attr); 249 } 250 251 /*** Delete an attribute of an instruction handle. 252 * 253 * @param key the key object to retrieve the attribute 254 */ 255 public void removeAttribute(Object key) { 256 if(attributes != null) 257 attributes.remove(key); 258 } 259 260 /*** Get attribute of an instruction handle. 261 * 262 * @param key the key object to store/retrieve the attribute 263 */ 264 public Object getAttribute(Object key) { 265 if(attributes != null) 266 return attributes.get(key); 267 268 return null; 269 } 270 271 /*** @return all attributes associated with this handle 272 */ 273 public Collection getAttributes() { 274 return attributes.values(); 275 } 276 277 /*** Convenience method, simply calls accept() on the contained instruction. 278 * 279 * @param v Visitor object 280 */ 281 public void accept(Visitor v) { 282 instruction.accept(v); 283 } 284 }

This page was automatically generated by Maven