jaxp/src/com/sun/org/apache/bcel/internal/generic/LocalVariableGen.java
changeset 17538 d8d911c4e5d4
parent 12457 c348e06f0e82
equal deleted inserted replaced
17537:50528ec0ea37 17538:d8d911c4e5d4
    58  * <http://www.apache.org/>.
    58  * <http://www.apache.org/>.
    59  */
    59  */
    60 
    60 
    61 import com.sun.org.apache.bcel.internal.Constants;
    61 import com.sun.org.apache.bcel.internal.Constants;
    62 import com.sun.org.apache.bcel.internal.classfile.*;
    62 import com.sun.org.apache.bcel.internal.classfile.*;
       
    63 import java.util.Objects;
    63 
    64 
    64 /**
    65 /**
    65  * This class represents a local variable within a method. It contains its
    66  * This class represents a local variable within a method. It contains its
    66  * scope, name and type. The generated LocalVariable object can be obtained
    67  * scope, name and type. The generated LocalVariable object can be obtained
    67  * with getLocalVariable which needs the instruction list and the constant
    68  * with getLocalVariable which needs the instruction list and the constant
    73  */
    74  */
    74 public class LocalVariableGen
    75 public class LocalVariableGen
    75   implements InstructionTargeter, NamedAndTyped, Cloneable,
    76   implements InstructionTargeter, NamedAndTyped, Cloneable,
    76              java.io.Serializable
    77              java.io.Serializable
    77 {
    78 {
    78   private int         index;
    79   private final int   index;
    79   private String      name;
    80   private String      name;
    80   private Type        type;
    81   private Type        type;
    81   private InstructionHandle start, end;
    82   private InstructionHandle start, end;
    82 
    83 
    83   /**
    84   /**
   129 
   130 
   130     return new LocalVariable(start_pc, length, name_index,
   131     return new LocalVariable(start_pc, length, name_index,
   131                              signature_index, index, cp.getConstantPool());
   132                              signature_index, index, cp.getConstantPool());
   132   }
   133   }
   133 
   134 
   134   public void        setIndex(int index)           { this.index = index; }
   135   public int         getIndex()                  { return index; }
   135   public int         getIndex()                   { return index; }
   136   @Override
   136   public void        setName(String name)        { this.name = name; }
   137   public void        setName(String name)        { this.name = name; }
       
   138   @Override
   137   public String      getName()                   { return name; }
   139   public String      getName()                   { return name; }
       
   140   @Override
   138   public void        setType(Type type)          { this.type = type; }
   141   public void        setType(Type type)          { this.type = type; }
       
   142   @Override
   139   public Type        getType()                   { return type; }
   143   public Type        getType()                   { return type; }
   140 
   144 
   141   public InstructionHandle getStart()                  { return start; }
   145   public InstructionHandle getStart()                  { return start; }
   142   public InstructionHandle getEnd()                    { return end; }
   146   public InstructionHandle getEnd()                    { return end; }
   143 
   147 
   144   public void setStart(InstructionHandle start) {
   148   /**
   145     BranchInstruction.notifyTarget(this.start, start, this);
   149    * Remove this from any known HashSet in which it might be registered.
       
   150    */
       
   151   void notifyTargetChanging() {
       
   152     // hashCode depends on 'index', 'start', and 'end'.
       
   153     // Therefore before changing any of these values we
       
   154     // need to unregister 'this' from any HashSet where
       
   155     // this is registered, and then we need to add it
       
   156     // back...
       
   157 
       
   158     // Unregister 'this' from the HashSet held by 'start'.
       
   159     BranchInstruction.notifyTargetChanging(this.start, this);
       
   160     if (this.end != this.start) {
       
   161         // Since hashCode() is going to change we need to unregister
       
   162         // 'this' both form 'start' and 'end'.
       
   163         // Unregister 'this' from the HashSet held by 'end'.
       
   164         BranchInstruction.notifyTargetChanging(this.end, this);
       
   165     }
       
   166   }
       
   167 
       
   168   /**
       
   169    * Add back 'this' in all HashSet in which it should be registered.
       
   170    **/
       
   171   void notifyTargetChanged() {
       
   172     // hashCode depends on 'index', 'start', and 'end'.
       
   173     // Therefore before changing any of these values we
       
   174     // need to unregister 'this' from any HashSet where
       
   175     // this is registered, and then we need to add it
       
   176     // back...
       
   177 
       
   178     // Register 'this' in the HashSet held by start.
       
   179     BranchInstruction.notifyTargetChanged(this.start, this);
       
   180     if (this.end != this.start) {
       
   181         // Since hashCode() has changed we need to register
       
   182         // 'this' again in 'end'.
       
   183         // Add back 'this' in the HashSet held by 'end'.
       
   184         BranchInstruction.notifyTargetChanged(this.end, this);
       
   185     }
       
   186   }
       
   187 
       
   188   public final void setStart(InstructionHandle start) {
       
   189 
       
   190     // Call notifyTargetChanging *before* modifying this,
       
   191     // as the code triggered by notifyTargetChanging
       
   192     // depends on this pointing to the 'old' start.
       
   193     notifyTargetChanging();
       
   194 
   146     this.start = start;
   195     this.start = start;
   147   }
   196 
   148 
   197     // call notifyTargetChanged *after* modifying this,
   149   public void setEnd(InstructionHandle end) {
   198     // as the code triggered by notifyTargetChanged
   150     BranchInstruction.notifyTarget(this.end, end, this);
   199     // depends on this pointing to the 'new' start.
       
   200     notifyTargetChanged();
       
   201   }
       
   202 
       
   203   public final void setEnd(InstructionHandle end) {
       
   204     // call notifyTargetChanging *before* modifying this,
       
   205     // as the code triggered by notifyTargetChanging
       
   206     // depends on this pointing to the 'old' end.
       
   207     // Unregister 'this' from the HashSet held by the 'old' end.
       
   208     notifyTargetChanging();
       
   209 
   151     this.end = end;
   210     this.end = end;
       
   211 
       
   212     // call notifyTargetChanged *after* modifying this,
       
   213     // as the code triggered by notifyTargetChanged
       
   214     // depends on this pointing to the 'new' end.
       
   215     // Register 'this' in the HashSet held by the 'new' end.
       
   216     notifyTargetChanged();
       
   217 
   152   }
   218   }
   153 
   219 
   154   /**
   220   /**
   155    * @param old_ih old target, either start or end
   221    * @param old_ih old target, either start or end
   156    * @param new_ih new target
   222    * @param new_ih new target
   157    */
   223    */
       
   224   @Override
   158   public void updateTarget(InstructionHandle old_ih, InstructionHandle new_ih) {
   225   public void updateTarget(InstructionHandle old_ih, InstructionHandle new_ih) {
   159     boolean targeted = false;
   226     boolean targeted = false;
   160 
   227 
   161     if(start == old_ih) {
   228     if(start == old_ih) {
   162       targeted = true;
   229       targeted = true;
   174   }
   241   }
   175 
   242 
   176   /**
   243   /**
   177    * @return true, if ih is target of this variable
   244    * @return true, if ih is target of this variable
   178    */
   245    */
       
   246   @Override
   179   public boolean containsTarget(InstructionHandle ih) {
   247   public boolean containsTarget(InstructionHandle ih) {
   180     return (start == ih) || (end == ih);
   248     return (start == ih) || (end == ih);
   181   }
   249   }
   182 
   250 
   183   /**
   251   /**
   184    * We consider to local variables to be equal, if the use the same index and
   252    * We consider two local variables to be equal, if they use the same index and
   185    * are valid in the same range.
   253    * are valid in the same range.
   186    */
   254    */
       
   255   @Override
   187   public boolean equals(Object o) {
   256   public boolean equals(Object o) {
       
   257     if (o==this)
       
   258       return true;
       
   259 
   188     if(!(o instanceof LocalVariableGen))
   260     if(!(o instanceof LocalVariableGen))
   189       return false;
   261       return false;
   190 
   262 
   191     LocalVariableGen l = (LocalVariableGen)o;
   263     LocalVariableGen l = (LocalVariableGen)o;
   192     return (l.index == index) && (l.start == start) && (l.end == end);
   264     return (l.index == index) && (l.start == start) && (l.end == end);
   193   }
   265   }
   194 
   266 
       
   267   @Override
       
   268   public int hashCode() {
       
   269     int hash = 7;
       
   270     hash = 59 * hash + this.index;
       
   271     hash = 59 * hash + Objects.hashCode(this.start);
       
   272     hash = 59 * hash + Objects.hashCode(this.end);
       
   273     return hash;
       
   274   }
       
   275 
       
   276   @Override
   195   public String toString() {
   277   public String toString() {
   196     return "LocalVariableGen(" + name +  ", " + type +  ", " + start + ", " + end + ")";
   278     return "LocalVariableGen(" + name +  ", " + type +  ", " + start + ", " + end + ")";
   197   }
   279   }
   198 
   280 
       
   281   @Override
   199   public Object clone() {
   282   public Object clone() {
   200     try {
   283     try {
   201       return super.clone();
   284       return super.clone();
   202     } catch(CloneNotSupportedException e) {
   285     } catch(CloneNotSupportedException e) {
   203       System.err.println(e);
   286       System.err.println(e);