< prev index next >

src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LocalVariableGen.java

Print this page


   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 
  22 package com.sun.org.apache.bcel.internal.generic;
  23 
  24 
  25 import com.sun.org.apache.bcel.internal.Constants;
  26 import com.sun.org.apache.bcel.internal.classfile.*;
  27 import java.util.Objects;
  28 
  29 /**
  30  * This class represents a local variable within a method. It contains its
  31  * scope, name and type. The generated LocalVariable object can be obtained
  32  * with getLocalVariable which needs the instruction list and the constant
  33  * pool as parameters.
  34  *
  35  * @author  <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
  36  * @see     LocalVariable
  37  * @see     MethodGen
  38  */
  39 public class LocalVariableGen
  40   implements InstructionTargeter, NamedAndTyped, Cloneable,
  41              java.io.Serializable
  42 {
  43   private final int   index;
  44   private String      name;
  45   private Type        type;
  46   private InstructionHandle start, end;

  47 
  48   /**
  49    * Generate a local variable that with index `index'. Note that double and long
  50    * variables need two indexs. Index indices have to be provided by the user.

  51    *
  52    * @param index index of local variable
  53    * @param name its name
  54    * @param type its type
  55    * @param start from where the instruction is valid (null means from the start)

  56    * @param end until where the instruction is valid (null means to the end)
  57    */
  58   public LocalVariableGen(int index, String name, Type type,
  59                           InstructionHandle start, InstructionHandle end) {
  60     if((index < 0) || (index > Constants.MAX_SHORT))
  61       throw new ClassGenException("Invalid index index: " + index);
  62 
  63     this.name  = name;
  64     this.type  = type;
  65     this.index  = index;
  66     setStart(start);
  67     setEnd(end);
  68   }
  69 
  70   /**
  71    * Get LocalVariable object.
  72    *
  73    * This relies on that the instruction list has already been dumped to byte code or
  74    * or that the `setPositions' methods has been called for the instruction list.

  75    *
  76    * Note that for local variables whose scope end at the last
  77    * instruction of the method's code, the JVM specification is ambiguous:
  78    * both a start_pc+length ending at the last instruction and
  79    * start_pc+length ending at first index beyond the end of the code are
  80    * valid.
  81    *
  82    * @param il instruction list (byte code) which this variable belongs to
  83    * @param cp constant pool
  84    */
  85   public LocalVariable getLocalVariable(ConstantPoolGen cp) {
  86     int start_pc        = start.getPosition();
  87     int length          = end.getPosition() - start_pc;
  88 
  89     if(length > 0)


  90       length += end.getInstruction().getLength();







  91 
  92     int name_index      = cp.addUtf8(name);
  93     int signature_index = cp.addUtf8(type.getSignature());

  94 
  95     return new LocalVariable(start_pc, length, name_index,
  96                              signature_index, index, cp.getConstantPool());
  97   }
  98 
  99   public int         getIndex()                  { return index; }
 100   @Override
 101   public void        setName(String name)        { this.name = name; }
 102   @Override
 103   public String      getName()                   { return name; }
 104   @Override
 105   public void        setType(Type type)          { this.type = type; }
 106   @Override
 107   public Type        getType()                   { return type; }
 108 
 109   public InstructionHandle getStart()                  { return start; }
 110   public InstructionHandle getEnd()                    { return end; }
 111 
 112   /**
 113    * Remove this from any known HashSet in which it might be registered.
 114    */
 115   void notifyTargetChanging() {
 116     // hashCode depends on 'index', 'start', and 'end'.
 117     // Therefore before changing any of these values we
 118     // need to unregister 'this' from any HashSet where
 119     // this is registered, and then we need to add it
 120     // back...
 121 
 122     // Unregister 'this' from the HashSet held by 'start'.
 123     BranchInstruction.notifyTargetChanging(this.start, this);
 124     if (this.end != this.start) {
 125         // Since hashCode() is going to change we need to unregister
 126         // 'this' both form 'start' and 'end'.
 127         // Unregister 'this' from the HashSet held by 'end'.
 128         BranchInstruction.notifyTargetChanging(this.end, this);
 129     }
 130   }
 131 
 132   /**
 133    * Add back 'this' in all HashSet in which it should be registered.
 134    **/
 135   void notifyTargetChanged() {
 136     // hashCode depends on 'index', 'start', and 'end'.
 137     // Therefore before changing any of these values we
 138     // need to unregister 'this' from any HashSet where
 139     // this is registered, and then we need to add it
 140     // back...
 141 
 142     // Register 'this' in the HashSet held by start.
 143     BranchInstruction.notifyTargetChanged(this.start, this);
 144     if (this.end != this.start) {
 145         // Since hashCode() has changed we need to register
 146         // 'this' again in 'end'.
 147         // Add back 'this' in the HashSet held by 'end'.
 148         BranchInstruction.notifyTargetChanged(this.end, this);
 149     }




 150   }
 151 
 152   public final void setStart(InstructionHandle start) {


 153 
 154     // Call notifyTargetChanging *before* modifying this,
 155     // as the code triggered by notifyTargetChanging
 156     // depends on this pointing to the 'old' start.
 157     notifyTargetChanging();
 158 


 159     this.start = start;
 160 
 161     // call notifyTargetChanged *after* modifying this,
 162     // as the code triggered by notifyTargetChanged
 163     // depends on this pointing to the 'new' start.
 164     notifyTargetChanged();
 165   }
 166 
 167   public final void setEnd(InstructionHandle end) {
 168     // call notifyTargetChanging *before* modifying this,
 169     // as the code triggered by notifyTargetChanging
 170     // depends on this pointing to the 'old' end.
 171     // Unregister 'this' from the HashSet held by the 'old' end.
 172     notifyTargetChanging();
 173 
 174     this.end = end;
 175 
 176     // call notifyTargetChanged *after* modifying this,
 177     // as the code triggered by notifyTargetChanged
 178     // depends on this pointing to the 'new' end.
 179     // Register 'this' in the HashSet held by the 'new' end.
 180     notifyTargetChanged();
 181 
 182   }
 183 
 184   /**
 185    * @param old_ih old target, either start or end
 186    * @param new_ih new target
 187    */
 188   @Override
 189   public void updateTarget(InstructionHandle old_ih, InstructionHandle new_ih) {
 190     boolean targeted = false;
 191 
 192     if(start == old_ih) {
 193       targeted = true;
 194       setStart(new_ih);
 195     }
 196 
 197     if(end == old_ih) {
 198       targeted = true;
 199       setEnd(new_ih);
 200     }





 201 
 202     if(!targeted)
 203       throw new ClassGenException("Not targeting " + old_ih + ", but {" + start + ", " +
 204                                   end + "}");



 205   }
 206 
 207   /**
 208    * @return true, if ih is target of this variable
 209    */
 210   @Override
 211   public boolean containsTarget(InstructionHandle ih) {
 212     return (start == ih) || (end == ih);
 213   }
 214 







 215   /**
 216    * We consider two local variables to be equal, if they use the same index and
 217    * are valid in the same range.
 218    */
 219   @Override
 220   public boolean equals(Object o) {
 221     if (o==this)
 222       return true;
 223 
 224     if(!(o instanceof LocalVariableGen))
 225       return false;
 226 
 227     LocalVariableGen l = (LocalVariableGen)o;
 228     return (l.index == index) && (l.start == start) && (l.end == end);
 229   }
 230 
 231   @Override
 232   public int hashCode() {
 233     int hash = 7;
 234     hash = 59 * hash + this.index;
 235     hash = 59 * hash + Objects.hashCode(this.start);
 236     hash = 59 * hash + Objects.hashCode(this.end);
 237     return hash;
 238   }
 239 
 240   @Override
 241   public String toString() {
 242     return "LocalVariableGen(" + name +  ", " + type +  ", " + start + ", " + end + ")";
 243   }
 244 
 245   @Override
 246   public Object clone() {
 247     try {
 248       return super.clone();
 249     } catch(CloneNotSupportedException e) {
 250       System.err.println(e);
 251       return null;
 252     }
 253   }
 254 }
   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  * This class represents a local variable within a method. It contains its
  28  * scope, name and type. The generated LocalVariable object can be obtained with
  29  * getLocalVariable which needs the instruction list and the constant pool as
  30  * parameters.
  31  *
  32  * @version $Id: LocalVariableGen.java 1749603 2016-06-21 20:50:19Z ggregory $
  33  * @see LocalVariable
  34  * @see MethodGen
  35  */
  36 public class LocalVariableGen implements InstructionTargeter, NamedAndTyped, Cloneable {
  37 
  38     private int index;


  39     private String name;
  40     private Type type;
  41     private InstructionHandle start;
  42     private InstructionHandle end;
  43 
  44     /**
  45      * Generate a local variable that with index `index'. Note that double and
  46      * long variables need two indexs. Index indices have to be provided by the
  47      * user.
  48      *
  49      * @param index index of local variable
  50      * @param name its name
  51      * @param type its type
  52      * @param start from where the instruction is valid (null means from the
  53      * start)
  54      * @param end until where the instruction is valid (null means to the end)
  55      */
  56     public LocalVariableGen(final int index, final String name, final Type type,
  57             final InstructionHandle start, 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     }
  67 
  68     /**
  69      * Get LocalVariable object.
  70      *
  71      * This relies on that the instruction list has already been dumped to byte
  72      * code or or that the `setPositions' methods has been called for the
  73      * instruction list.
  74      *
  75      * Note that for local variables whose scope end at the last instruction of
  76      * the method's code, the JVM specification is ambiguous: both a
  77      * start_pc+length ending at the last instruction and start_pc+length ending
  78      * at first index beyond the end of the code are valid.

  79      *

  80      * @param cp constant pool
  81      */
  82     public LocalVariable getLocalVariable(final ConstantPoolGen cp) {
  83         int start_pc = 0;
  84         int length = 0;
  85         if ((start != null) && (end != null)) {
  86             start_pc = start.getPosition();
  87             length = end.getPosition() - start_pc;
  88             if (end.getNext() == null) {
  89                 length += end.getInstruction().getLength();
  90             }
  91         }
  92         final int name_index = cp.addUtf8(name);
  93         final int signature_index = cp.addUtf8(type.getSignature());
  94         return new LocalVariable(start_pc, length, name_index, signature_index, index, cp
  95                 .getConstantPool());
  96     }
  97 
  98     public void setIndex(final int index) {
  99         this.index = index;
 100     }
 101 
 102     public int getIndex() {
 103         return index;
 104     }
 105 





 106     @Override
 107     public void setName(final String name) {
 108         this.name = name;























 109     }
 110 
 111     @Override
 112     public String getName() {
 113         return name;
 114     }





 115 
 116     @Override
 117     public void setType(final Type type) {
 118         this.type = type;




 119     }
 120 
 121     @Override
 122     public Type getType() {
 123         return type;
 124     }
 125 
 126     public InstructionHandle getStart() {
 127         return start;
 128     }
 129 
 130     public InstructionHandle getEnd() {
 131         return end;
 132     }

 133 
 134     public void setStart(final InstructionHandle start) { // TODO could be package-protected?
 135         BranchInstruction.notifyTarget(this.start, start, this);
 136         this.start = start;





 137     }
 138 
 139     public void setEnd(final InstructionHandle end) { // TODO could be package-protected?
 140         BranchInstruction.notifyTarget(this.end, end, this);





 141         this.end = end;







 142     }
 143 
 144     /**
 145      * @param old_ih old target, either start or end
 146      * @param new_ih new target
 147      */
 148     @Override
 149     public void updateTarget(final InstructionHandle old_ih, final InstructionHandle new_ih) {
 150         boolean targeted = false;
 151         if (start == old_ih) {

 152             targeted = true;
 153             setStart(new_ih);
 154         }
 155         if (end == old_ih) {

 156             targeted = true;
 157             setEnd(new_ih);
 158         }
 159         if (!targeted) {
 160             throw new ClassGenException("Not targeting " + old_ih + ", but {" + start + ", " + end
 161                     + "}");
 162         }
 163     }
 164 
 165     /**
 166      * Clear the references from and to this variable when it's removed.
 167      */
 168     void dispose() {
 169         setStart(null);
 170         setEnd(null);
 171     }
 172 
 173     /**
 174      * @return true, if ih is target of this variable
 175      */
 176     @Override
 177     public boolean containsTarget(final InstructionHandle ih) {
 178         return (start == ih) || (end == ih);
 179     }
 180 
 181     @Override
 182     public int hashCode() {
 183         // If the user changes the name or type, problems with the targeter hashmap will occur.
 184         // Note: index cannot be part of hash as it may be changed by the user.
 185         return name.hashCode() ^ type.hashCode();
 186     }
 187 
 188     /**
 189      * We consider to local variables to be equal, if the use the same index and
 190      * are valid in the same range.
 191      */
 192     @Override
 193     public boolean equals(final Object o) {
 194         if (!(o instanceof LocalVariableGen)) {



 195             return false;



 196         }
 197         final LocalVariableGen l = (LocalVariableGen) o;
 198         return (l.index == index) && (l.start == start) && (l.end == end);






 199     }
 200 
 201     @Override
 202     public String toString() {
 203         return "LocalVariableGen(" + name + ", " + type + ", " + start + ", " + end + ")";
 204     }
 205 
 206     @Override
 207     public Object clone() {
 208         try {
 209             return super.clone();
 210         } catch (final CloneNotSupportedException e) {
 211             throw new Error("Clone Not Supported"); // never happens

 212         }
 213     }
 214 }
< prev index next >