--- a/jaxp/src/com/sun/org/apache/bcel/internal/generic/LocalVariableGen.java Fri May 10 09:23:22 2013 -0700
+++ b/jaxp/src/com/sun/org/apache/bcel/internal/generic/LocalVariableGen.java Fri May 17 10:40:21 2013 +0200
@@ -60,6 +60,7 @@
import com.sun.org.apache.bcel.internal.Constants;
import com.sun.org.apache.bcel.internal.classfile.*;
+import java.util.Objects;
/**
* This class represents a local variable within a method. It contains its
@@ -75,7 +76,7 @@
implements InstructionTargeter, NamedAndTyped, Cloneable,
java.io.Serializable
{
- private int index;
+ private final int index;
private String name;
private Type type;
private InstructionHandle start, end;
@@ -131,30 +132,96 @@
signature_index, index, cp.getConstantPool());
}
- public void setIndex(int index) { this.index = index; }
- public int getIndex() { return index; }
+ public int getIndex() { return index; }
+ @Override
public void setName(String name) { this.name = name; }
+ @Override
public String getName() { return name; }
+ @Override
public void setType(Type type) { this.type = type; }
+ @Override
public Type getType() { return type; }
public InstructionHandle getStart() { return start; }
public InstructionHandle getEnd() { return end; }
- public void setStart(InstructionHandle start) {
- BranchInstruction.notifyTarget(this.start, start, this);
- this.start = start;
+ /**
+ * Remove this from any known HashSet in which it might be registered.
+ */
+ void notifyTargetChanging() {
+ // hashCode depends on 'index', 'start', and 'end'.
+ // Therefore before changing any of these values we
+ // need to unregister 'this' from any HashSet where
+ // this is registered, and then we need to add it
+ // back...
+
+ // Unregister 'this' from the HashSet held by 'start'.
+ BranchInstruction.notifyTargetChanging(this.start, this);
+ if (this.end != this.start) {
+ // Since hashCode() is going to change we need to unregister
+ // 'this' both form 'start' and 'end'.
+ // Unregister 'this' from the HashSet held by 'end'.
+ BranchInstruction.notifyTargetChanging(this.end, this);
+ }
}
- public void setEnd(InstructionHandle end) {
- BranchInstruction.notifyTarget(this.end, end, this);
+ /**
+ * Add back 'this' in all HashSet in which it should be registered.
+ **/
+ void notifyTargetChanged() {
+ // hashCode depends on 'index', 'start', and 'end'.
+ // Therefore before changing any of these values we
+ // need to unregister 'this' from any HashSet where
+ // this is registered, and then we need to add it
+ // back...
+
+ // Register 'this' in the HashSet held by start.
+ BranchInstruction.notifyTargetChanged(this.start, this);
+ if (this.end != this.start) {
+ // Since hashCode() has changed we need to register
+ // 'this' again in 'end'.
+ // Add back 'this' in the HashSet held by 'end'.
+ BranchInstruction.notifyTargetChanged(this.end, this);
+ }
+ }
+
+ public final void setStart(InstructionHandle start) {
+
+ // Call notifyTargetChanging *before* modifying this,
+ // as the code triggered by notifyTargetChanging
+ // depends on this pointing to the 'old' start.
+ notifyTargetChanging();
+
+ this.start = start;
+
+ // call notifyTargetChanged *after* modifying this,
+ // as the code triggered by notifyTargetChanged
+ // depends on this pointing to the 'new' start.
+ notifyTargetChanged();
+ }
+
+ public final void setEnd(InstructionHandle end) {
+ // call notifyTargetChanging *before* modifying this,
+ // as the code triggered by notifyTargetChanging
+ // depends on this pointing to the 'old' end.
+ // Unregister 'this' from the HashSet held by the 'old' end.
+ notifyTargetChanging();
+
this.end = end;
+
+ // call notifyTargetChanged *after* modifying this,
+ // as the code triggered by notifyTargetChanged
+ // depends on this pointing to the 'new' end.
+ // Register 'this' in the HashSet held by the 'new' end.
+ notifyTargetChanged();
+
}
/**
* @param old_ih old target, either start or end
* @param new_ih new target
*/
+ @Override
public void updateTarget(InstructionHandle old_ih, InstructionHandle new_ih) {
boolean targeted = false;
@@ -176,15 +243,20 @@
/**
* @return true, if ih is target of this variable
*/
+ @Override
public boolean containsTarget(InstructionHandle ih) {
return (start == ih) || (end == ih);
}
/**
- * We consider to local variables to be equal, if the use the same index and
+ * We consider two local variables to be equal, if they use the same index and
* are valid in the same range.
*/
+ @Override
public boolean equals(Object o) {
+ if (o==this)
+ return true;
+
if(!(o instanceof LocalVariableGen))
return false;
@@ -192,10 +264,21 @@
return (l.index == index) && (l.start == start) && (l.end == end);
}
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 59 * hash + this.index;
+ hash = 59 * hash + Objects.hashCode(this.start);
+ hash = 59 * hash + Objects.hashCode(this.end);
+ return hash;
+ }
+
+ @Override
public String toString() {
return "LocalVariableGen(" + name + ", " + type + ", " + start + ", " + end + ")";
}
+ @Override
public Object clone() {
try {
return super.clone();