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