src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionHandle.java
changeset 55496 8e0ae3830fca
parent 47216 71c04702a3d5
equal deleted inserted replaced
55495:badfa812b82a 55496:8e0ae3830fca
     1 /*
     1 /*
     2  * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
     3  */
     3  */
     4 /*
     4 /*
     5  * Licensed to the Apache Software Foundation (ASF) under one or more
     5  * Licensed to the Apache Software Foundation (ASF) under one or more
     6  * contributor license agreements.  See the NOTICE file distributed with
     6  * contributor license agreements.  See the NOTICE file distributed with
     7  * this work for additional information regarding copyright ownership.
     7  * this work for additional information regarding copyright ownership.
    30 /**
    30 /**
    31  * Instances of this class give users a handle to the instructions contained in
    31  * Instances of this class give users a handle to the instructions contained in
    32  * an InstructionList. Instruction objects may be used more than once within a
    32  * an InstructionList. Instruction objects may be used more than once within a
    33  * list, this is useful because it saves memory and may be much faster.
    33  * list, this is useful because it saves memory and may be much faster.
    34  *
    34  *
    35  * Within an InstructionList an InstructionHandle object is wrapped around all
    35  * Within an InstructionList an InstructionHandle object is wrapped
    36  * instructions, i.e., it implements a cell in a doubly-linked list. From the
    36  * around all instructions, i.e., it implements a cell in a
    37  * outside only the next and the previous instruction (handle) are accessible.
    37  * doubly-linked list. From the outside only the next and the
    38  * One can traverse the list via an Enumeration returned by
    38  * previous instruction (handle) are accessible. One
       
    39  * can traverse the list via an Enumeration returned by
    39  * InstructionList.elements().
    40  * InstructionList.elements().
    40  *
    41  *
    41  * @version $Id: InstructionHandle.java 1749603 2016-06-21 20:50:19Z ggregory $
    42  * @version $Id$
    42  * @see Instruction
    43  * @see Instruction
    43  * @see BranchHandle
    44  * @see BranchHandle
    44  * @see InstructionList
    45  * @see InstructionList
    45  */
    46  */
    46 public class InstructionHandle {
    47 public class InstructionHandle {
    52     private int i_position = -1; // byte code offset of instruction
    53     private int i_position = -1; // byte code offset of instruction
    53 
    54 
    54     private Set<InstructionTargeter> targeters;
    55     private Set<InstructionTargeter> targeters;
    55     private Map<Object, Object> attributes;
    56     private Map<Object, Object> attributes;
    56 
    57 
       
    58 
       
    59     /**
       
    60      * Does nothing.
       
    61      *
       
    62      * @deprecated Does nothing as of 6.3.1.
       
    63      */
       
    64     @Deprecated
       
    65     protected void addHandle() {
       
    66         // noop
       
    67     }
       
    68 
    57     public final InstructionHandle getNext() {
    69     public final InstructionHandle getNext() {
    58         return next;
    70         return next;
    59     }
    71     }
    60 
    72 
       
    73 
    61     public final InstructionHandle getPrev() {
    74     public final InstructionHandle getPrev() {
    62         return prev;
    75         return prev;
    63     }
    76     }
    64 
    77 
       
    78 
    65     public final Instruction getInstruction() {
    79     public final Instruction getInstruction() {
    66         return instruction;
    80         return instruction;
    67     }
    81     }
    68 
    82 
    69     /**
    83 
    70      * Replace current instruction contained in this handle. Old instruction is
    84     /**
    71      * disposed using Instruction.dispose().
    85      * Replace current instruction contained in this handle.
    72      */
    86      * Old instruction is disposed using Instruction.dispose().
    73     public void setInstruction(final Instruction i) { // Overridden in BranchHandle TODO could be package-protected?
    87      */
       
    88     public void setInstruction( final Instruction i ) { // Overridden in BranchHandle TODO could be package-protected?
    74         if (i == null) {
    89         if (i == null) {
    75             throw new ClassGenException("Assigning null to handle");
    90             throw new ClassGenException("Assigning null to handle");
    76         }
    91         }
    77         if ((this.getClass() != BranchHandle.class) && (i instanceof BranchInstruction)) {
    92         if ((this.getClass() != BranchHandle.class) && (i instanceof BranchInstruction)) {
    78             throw new ClassGenException("Assigning branch instruction " + i + " to plain handle");
    93             throw new ClassGenException("Assigning branch instruction " + i + " to plain handle");
    81             instruction.dispose();
    96             instruction.dispose();
    82         }
    97         }
    83         instruction = i;
    98         instruction = i;
    84     }
    99     }
    85 
   100 
    86     /**
   101 
    87      * Temporarily swap the current instruction, without disturbing anything.
   102     /**
    88      * Meant to be used by a debugger, implementing breakpoints. Current
   103      * Temporarily swap the current instruction, without disturbing
    89      * instruction is returned.
   104      * anything. Meant to be used by a debugger, implementing
       
   105      * breakpoints. Current instruction is returned.
    90      * <p>
   106      * <p>
    91      * Warning: if this is used on a BranchHandle then some methods such as
   107      * Warning: if this is used on a BranchHandle then some methods such as
    92      * getPosition() will still refer to the original cached instruction,
   108      * getPosition() will still refer to the original cached instruction, whereas
    93      * whereas other BH methods may affect the cache and the replacement
   109      * other BH methods may affect the cache and the replacement instruction.
    94      * instruction.
       
    95      */
   110      */
    96     // See BCEL-273
   111     // See BCEL-273
    97     // TODO remove this method in any redesign of BCEL
   112     // TODO remove this method in any redesign of BCEL
    98     public Instruction swapInstruction(final Instruction i) {
   113     public Instruction swapInstruction( final Instruction i ) {
    99         final Instruction oldInstruction = instruction;
   114         final Instruction oldInstruction = instruction;
   100         instruction = i;
   115         instruction = i;
   101         return oldInstruction;
   116         return oldInstruction;
   102     }
   117     }
   103 
   118 
   104 
   119 
   105     /*private*/
   120     /*private*/protected InstructionHandle(final Instruction i) {
   106     protected InstructionHandle(final Instruction i) {
       
   107         setInstruction(i);
   121         setInstruction(i);
   108     }
   122     }
   109 
   123 
   110     private static InstructionHandle ih_list = null; // List of reusable handles
   124     /** Factory method.
   111 
   125      */
   112     /**
   126     static InstructionHandle getInstructionHandle( final Instruction i ) {
   113      * Factory method.
   127         return new InstructionHandle(i);
   114      */
   128     }
   115     static InstructionHandle getInstructionHandle(final Instruction i) {
   129 
   116         if (ih_list == null) {
   130 
   117             return new InstructionHandle(i);
   131     /**
   118         }
   132      * Called by InstructionList.setPositions when setting the position for every
   119         final InstructionHandle ih = ih_list;
   133      * instruction. In the presence of variable length instructions `setPositions()'
   120         ih_list = ih.next;
   134      * performs multiple passes over the instruction list to calculate the
   121         ih.setInstruction(i);
   135      * correct (byte) positions and offsets by calling this function.
   122         return ih;
   136      *
   123     }
   137      * @param offset additional offset caused by preceding (variable length) instructions
   124 
   138      * @param max_offset the maximum offset that may be caused by these instructions
   125     /**
   139      * @return additional offset caused by possible change of this instruction's length
   126      * Called by InstructionList.setPositions when setting the position for
   140      */
   127      * every instruction. In the presence of variable length instructions
   141     protected int updatePosition( final int offset, final int max_offset ) {
   128      * `setPositions()' performs multiple passes over the instruction list to
       
   129      * calculate the correct (byte) positions and offsets by calling this
       
   130      * function.
       
   131      *
       
   132      * @param offset additional offset caused by preceding (variable length)
       
   133      * instructions
       
   134      * @param max_offset the maximum offset that may be caused by these
       
   135      * instructions
       
   136      * @return additional offset caused by possible change of this instruction's
       
   137      * length
       
   138      */
       
   139     protected int updatePosition(final int offset, final int max_offset) {
       
   140         i_position += offset;
   142         i_position += offset;
   141         return 0;
   143         return 0;
   142     }
   144     }
   143 
   145 
   144     /**
   146 
   145      * @return the position, i.e., the byte code offset of the contained
   147     /** @return the position, i.e., the byte code offset of the contained
   146      * instruction. This is accurate only after InstructionList.setPositions()
   148      * instruction. This is accurate only after
   147      * has been called.
   149      * InstructionList.setPositions() has been called.
   148      */
   150      */
   149     public int getPosition() {
   151     public int getPosition() {
   150         return i_position;
   152         return i_position;
   151     }
   153     }
   152 
   154 
   153     /**
   155 
   154      * Set the position, i.e., the byte code offset of the contained
   156     /** Set the position, i.e., the byte code offset of the contained
   155      * instruction.
   157      * instruction.
   156      */
   158      */
   157     void setPosition(final int pos) {
   159     void setPosition( final int pos ) {
   158         i_position = pos;
   160         i_position = pos;
   159     }
   161     }
   160 
   162 
   161     /**
   163 
   162      * Overridden in BranchHandle
   164     /**
   163      */
   165      * Delete contents, i.e., remove user access.
   164     protected void addHandle() {
       
   165         next = ih_list;
       
   166         ih_list = this;
       
   167     }
       
   168 
       
   169     /**
       
   170      * Delete contents, i.e., remove user access and make handle reusable.
       
   171      */
   166      */
   172     void dispose() {
   167     void dispose() {
   173         next = prev = null;
   168         next = prev = null;
   174         instruction.dispose();
   169         instruction.dispose();
   175         instruction = null;
   170         instruction = null;
   176         i_position = -1;
   171         i_position = -1;
   177         attributes = null;
   172         attributes = null;
   178         removeAllTargeters();
   173         removeAllTargeters();
   179         addHandle();
   174     }
   180     }
   175 
   181 
   176 
   182     /**
   177     /** Remove all targeters, if any.
   183      * Remove all targeters, if any.
       
   184      */
   178      */
   185     public void removeAllTargeters() {
   179     public void removeAllTargeters() {
   186         if (targeters != null) {
   180         if (targeters != null) {
   187             targeters.clear();
   181             targeters.clear();
   188         }
   182         }
   189     }
   183     }
   190 
   184 
       
   185 
   191     /**
   186     /**
   192      * Denote this handle isn't referenced anymore by t.
   187      * Denote this handle isn't referenced anymore by t.
   193      */
   188      */
   194     public void removeTargeter(final InstructionTargeter t) {
   189     public void removeTargeter( final InstructionTargeter t ) {
   195         if (targeters != null) {
   190         if (targeters != null) {
   196             targeters.remove(t);
   191             targeters.remove(t);
   197         }
   192         }
   198     }
   193     }
   199 
   194 
       
   195 
   200     /**
   196     /**
   201      * Denote this handle is being referenced by t.
   197      * Denote this handle is being referenced by t.
   202      */
   198      */
   203     public void addTargeter(final InstructionTargeter t) {
   199     public void addTargeter( final InstructionTargeter t ) {
   204         if (targeters == null) {
   200         if (targeters == null) {
   205             targeters = new HashSet<>();
   201             targeters = new HashSet<>();
   206         }
   202         }
   207         //if(!targeters.contains(t))
   203         //if(!targeters.contains(t))
   208         targeters.add(t);
   204         targeters.add(t);
   209     }
   205     }
   210 
   206 
       
   207 
   211     public boolean hasTargeters() {
   208     public boolean hasTargeters() {
   212         return (targeters != null) && (targeters.size() > 0);
   209         return (targeters != null) && (targeters.size() > 0);
   213     }
   210     }
       
   211 
   214 
   212 
   215     /**
   213     /**
   216      * @return null, if there are no targeters
   214      * @return null, if there are no targeters
   217      */
   215      */
   218     public InstructionTargeter[] getTargeters() {
   216     public InstructionTargeter[] getTargeters() {
   222         final InstructionTargeter[] t = new InstructionTargeter[targeters.size()];
   220         final InstructionTargeter[] t = new InstructionTargeter[targeters.size()];
   223         targeters.toArray(t);
   221         targeters.toArray(t);
   224         return t;
   222         return t;
   225     }
   223     }
   226 
   224 
   227     /**
   225 
   228      * @return a (verbose) string representation of the contained instruction.
   226     /** @return a (verbose) string representation of the contained instruction.
   229      */
   227      */
   230     public String toString(final boolean verbose) {
   228     public String toString( final boolean verbose ) {
   231         return Utility.format(i_position, 4, false, ' ') + ": " + instruction.toString(verbose);
   229         return Utility.format(i_position, 4, false, ' ') + ": " + instruction.toString(verbose);
   232     }
   230     }
   233 
   231 
   234     /**
   232 
   235      * @return a string representation of the contained instruction.
   233     /** @return a string representation of the contained instruction.
   236      */
   234      */
   237     @Override
   235     @Override
   238     public String toString() {
   236     public String toString() {
   239         return toString(true);
   237         return toString(true);
   240     }
   238     }
   241 
   239 
   242     /**
   240 
   243      * Add an attribute to an instruction handle.
   241     /** Add an attribute to an instruction handle.
   244      *
   242      *
   245      * @param key the key object to store/retrieve the attribute
   243      * @param key the key object to store/retrieve the attribute
   246      * @param attr the attribute to associate with this handle
   244      * @param attr the attribute to associate with this handle
   247      */
   245      */
   248     public void addAttribute(final Object key, final Object attr) {
   246     public void addAttribute( final Object key, final Object attr ) {
   249         if (attributes == null) {
   247         if (attributes == null) {
   250             attributes = new HashMap<>(3);
   248             attributes = new HashMap<>(3);
   251         }
   249         }
   252         attributes.put(key, attr);
   250         attributes.put(key, attr);
   253     }
   251     }
   254 
   252 
   255     /**
   253 
   256      * Delete an attribute of an instruction handle.
   254     /** Delete an attribute of an instruction handle.
   257      *
   255      *
   258      * @param key the key object to retrieve the attribute
   256      * @param key the key object to retrieve the attribute
   259      */
   257      */
   260     public void removeAttribute(final Object key) {
   258     public void removeAttribute( final Object key ) {
   261         if (attributes != null) {
   259         if (attributes != null) {
   262             attributes.remove(key);
   260             attributes.remove(key);
   263         }
   261         }
   264     }
   262     }
   265 
   263 
   266     /**
   264 
   267      * Get attribute of an instruction handle.
   265     /** Get attribute of an instruction handle.
   268      *
   266      *
   269      * @param key the key object to store/retrieve the attribute
   267      * @param key the key object to store/retrieve the attribute
   270      */
   268      */
   271     public Object getAttribute(final Object key) {
   269     public Object getAttribute( final Object key ) {
   272         if (attributes != null) {
   270         if (attributes != null) {
   273             return attributes.get(key);
   271             return attributes.get(key);
   274         }
   272         }
   275         return null;
   273         return null;
   276     }
   274     }
   277 
   275 
   278     /**
   276 
   279      * @return all attributes associated with this handle
   277     /** @return all attributes associated with this handle
   280      */
   278      */
   281     public Collection<Object> getAttributes() {
   279     public Collection<Object> getAttributes() {
   282         if (attributes == null) {
   280         if (attributes == null) {
   283             attributes = new HashMap<>(3);
   281             attributes = new HashMap<>(3);
   284         }
   282         }
   285         return attributes.values();
   283         return attributes.values();
   286     }
   284     }
   287 
   285 
   288     /**
   286 
   289      * Convenience method, simply calls accept() on the contained instruction.
   287     /** Convenience method, simply calls accept() on the contained instruction.
   290      *
   288      *
   291      * @param v Visitor object
   289      * @param v Visitor object
   292      */
   290      */
   293     public void accept(final Visitor v) {
   291     public void accept( final Visitor v ) {
   294         instruction.accept(v);
   292         instruction.accept(v);
   295     }
   293     }
       
   294 
   296 
   295 
   297     /**
   296     /**
   298      * @param next the next to set
   297      * @param next the next to set
   299      * @ since 6.0
   298      * @ since 6.0
   300      */
   299      */
   301     final InstructionHandle setNext(final InstructionHandle next) {
   300     final InstructionHandle setNext(final InstructionHandle next) {
   302         this.next = next;
   301         this.next = next;
   303         return next;
   302         return next;
   304     }
   303     }
   305 
   304 
       
   305 
   306     /**
   306     /**
   307      * @param prev the prev to set
   307      * @param prev the prev to set
   308      * @ since 6.0
   308      * @ since 6.0
   309      */
   309      */
   310     final InstructionHandle setPrev(final InstructionHandle prev) {
   310     final InstructionHandle setPrev(final InstructionHandle prev) {