package s3.services.simplejit.bytecode;

import ovm.core.repository.TypeName;
import ovm.core.domain.Blueprint;
import ovm.core.domain.Type;
import ovm.services.bytecode.analysis.AbstractValue;
import ovm.util.OVMError;
import s3.core.domain.S3Blueprint;
import s3.services.bootimage.Driver;

public abstract class SimpleJITValue implements AbstractValue {

    public int getId() { throw new OVMError.UnsupportedOperation(); }
    public boolean includes (AbstractValue v) {
	throw new OVMError.UnsupportedOperation();
    }
    public AbstractValue merge (AbstractValue e) {
	throw new OVMError.UnsupportedOperation();
    }
    public boolean isJumpTarget() {
	throw new OVMError.UnsupportedOperation();
    }
    public AbstractValue.JumpTarget getJumpTarget() {
	throw new OVMError.UnsupportedOperation();
    }
    public boolean isWidePrimitive() {
	throw new OVMError.UnsupportedOperation();
    }
    public AbstractValue.WidePrimitive getWidePrimitive() {
	throw new OVMError.UnsupportedOperation();
    }   
    public boolean isPrimitive() {
	throw new OVMError.UnsupportedOperation();
    }
    public AbstractValue.Primitive getPrimitive() {
	throw new OVMError.UnsupportedOperation();
    }
    public boolean isReference() {
	throw new OVMError.UnsupportedOperation();
    }
    public AbstractValue.Reference getReference() {
	throw new OVMError.UnsupportedOperation();
    }
    public boolean isInvalid() {
	return false;
    }
    public AbstractValue.Invalid getInvalid() {
	throw new OVMError.UnsupportedOperation();
    }
    public boolean equals(AbstractValue v) {
	throw new OVMError.UnsupportedOperation();
    }

    /**
     * @return the Java language-level fully qualified name of this
     * value. Null if there is no appropriate qualified name.
     * Example: "Ljava/lang/Object;", "I".
     */
    public String getName() {
	return null;
    }

    public static final Factory bogusFactory = new Factory() {
	    public Int    makePrimitiveBool()
	    { return null; }
	    public Int    makePrimitiveByte()
	    { return null; }
	    public Int    makePrimitiveShort()
	    { return null; }
	    public Int    makePrimitiveChar()
	    { return null; }
	    public Int    makePrimitiveInt()
	    { return null; }
	    public Float  makePrimitiveFloat()
	    { return null; }
	    public Long   makePrimitiveLong()
	    { return null; }
	    public Double makePrimitiveDouble()
	    { return null; }
	    public Reference makeReference(TypeName.Compound _)
	    { return null; }
	    public Array  makeArray(AbstractValue _)
	    { return null; }
	    public Reference makeUninitialized(TypeName.Compound _)
	    { return null; }
	    public AbstractValue makeNull()
	    { return null; }
	    public Invalid makeInvalid()
	    { return null; }
	    public JumpTarget makeJumpTarget(int pc)
	    { return new SimpleJITJumpTarget(pc); }
	    public AbstractValue typeName2AbstractValue(TypeName _)
	    { return null; }
	};

    public static final SimpleJITDead DEAD = new SimpleJITDead();
    public static final class SimpleJITDead 
	extends SimpleJITValue {
	private SimpleJITDead() {
	}
	public boolean includes(AbstractValue v) {
	    return true;
	}
	public AbstractValue merge(AbstractValue v) {
	    return DEAD;
	}
	public String toString() {
	    return "[DEAD]";
	}
	public boolean equals(AbstractValue other) {
	    return other == DEAD;
	}
    }

    public static final class SimpleJITJumpTarget 
	extends SimpleJITValue 
	implements AbstractValue.JumpTarget {
	int pc = -1;
	public SimpleJITJumpTarget(int pc) {
	    this.pc = pc;
	}
	public AbstractValue.JumpTarget getJumpTarget() {
	    return this;
	}
	public boolean isPrimitive() { return false; }
	public boolean isWidePrimitive() { return false; }
	public boolean isReference() { return false; }
	public int getTarget() {
	    return pc;
	}
	public boolean includes(AbstractValue v) {
	    if (v == null)
		return false;
	    return (v instanceof SimpleJITJumpTarget)
		&& ((SimpleJITJumpTarget)v).pc == this.pc;
	}
	public AbstractValue merge(AbstractValue v) {
	    if (v == null)
		return null;
	    if (this == v
		|| (v instanceof SimpleJITJumpTarget
		    && this.pc == ((SimpleJITJumpTarget)v).pc))
		return new SimpleJITJumpTarget(pc);
	    else
		return null;
	}
	public String toString() {
	    return "[JUMPTARGET PC:" + pc + "]";
	}
	public boolean equals(AbstractValue other) {
	    if (other == null)
		return false;
	    if (other instanceof SimpleJITJumpTarget) {
		SimpleJITJumpTarget otherj = 
		    (SimpleJITJumpTarget)other;
		return this.pc == otherj.pc;
	    }
	    return false;
	}
    }

    public static class SimpleJITReference extends SimpleJITValue {
	protected TypeName typename;
	protected Blueprint bp;
	protected boolean isNull;

	public SimpleJITReference() { // for unknown type
	    isNull = false;
	}
	public SimpleJITReference(TypeName.Compound tn) {
	    this.typename = tn;
	    isNull = false;
	}
	public SimpleJITReference(Blueprint bp) {
	    this.bp = bp;
	    if (bp != null)
		this.typename = (TypeName.Compound)bp.getName();
	    isNull = false;
	}
	public String getName() {
	    if (typename != null)
		return typename.toString();
	    else
		return null;
	}
	public boolean isPrimitive() { return false; }
	public boolean isWidePrimitive() { return false; }
	public boolean isReference() { return true; }
	public boolean isNull() { return isNull; }
	public boolean isUnknownType() { return typename == null; }
	public boolean isNullOrUnknownType() {
	    return isNull || typename == null;
	}
	public boolean isArray() { return false; }
	public SimpleJITReference declareNull() { 
	    isNull = true; 
	    return this;
	}
	public TypeName getTypeName() { 
	    return typename; 
	}
	public Type getType() {
	    if (bp != null)
		return bp.getType();
	    return null;
	}
	public Blueprint getBlueprint() {
	    return bp;
	}
	public boolean typeUnknown() {
	    return typename == null;
	}
	public boolean resolved() {
	    return bp != null;
	}
	public boolean includes(AbstractValue other) {
	    if (other == null 
		|| (! (other instanceof SimpleJITReference)))
		return false;
	    if (this == other)
		return true;
	    SimpleJITReference otherref =
		(SimpleJITReference)other;
	    if (this.isNull && (! otherref.isNull))
		return false;
	    boolean thisbpnull = (this.bp == null);
	    boolean otherbpnull = (otherref.bp == null);
	    boolean thistnnull = (this.typename == null);
	    boolean othertnnull = (otherref.typename == null);

	    if (thisbpnull && (! otherbpnull)) {
		// othertnnull must be false
		if (thistnnull)
		    return true;
		else
		    return this.typename.equals(otherref.typename);
	    } else if ((! thisbpnull) && otherbpnull) {
		return false;
	    } else if (thisbpnull && otherbpnull) {
		if (thistnnull && (! othertnnull))
		    return true;
		else if ((! thistnnull) && othertnnull)
		    return false;
		else if (thistnnull && othertnnull)
		    return true;
		else
		    return this.typename.equals(otherref.typename);
	    } else {
		return otherref.bp.getType()
		    .isSubtypeOf(this.bp.getType());
	    }
	}
	public AbstractValue merge(AbstractValue other) {
	    if (other == null)
		return DEAD;
	    if (! (other instanceof SimpleJITReference)
		&& (! (other instanceof SimpleJITArray)))
		return DEAD;
	    if (this == other)
		return this;
	    SimpleJITReference otherref =
		(SimpleJITReference)other;
	    boolean mergedIsNull = this.isNull && otherref.isNull;
	    Blueprint mergedBP;
	    TypeName mergedTypeName;
	    if (this.bp == null || otherref.bp == null) {
		mergedBP = null;
		if (this.typename == null 
		    || otherref.typename == null)
		    mergedTypeName = null;
		else if (this.typename.equals(otherref.typename))
		    mergedTypeName = this.typename;
		else
		    mergedTypeName = null;
	    } else {
		Blueprint[] leastCommonSupertypes =
		    Driver.leastCommonSupertypes(this.bp, otherref.bp);
		if (leastCommonSupertypes.length == 0) {
		    mergedBP = null;
		    if (this.typename.equals(otherref.typename))
			mergedTypeName = this.typename;
		    else
			mergedTypeName = null;
		} else {
		    // arbitrarily take the first one
		    mergedBP = leastCommonSupertypes[0];
		    mergedTypeName = mergedBP.getName();
		}
	    }
	    if (mergedBP != null) {
		return (mergedIsNull
			? new SimpleJITReference(mergedBP).declareNull()
			: new SimpleJITReference(mergedBP));
	    } else if (mergedTypeName != null) {
		return (mergedIsNull
			? new SimpleJITReference
			(mergedTypeName.asCompound()).declareNull()
			: new SimpleJITReference
			(mergedTypeName.asCompound()));
	    } else {
		return (mergedIsNull
			? new SimpleJITReference().declareNull()
			: new SimpleJITReference());
	    }
	}
	public boolean equals(AbstractValue other) {
	    if (other == null 
		|| (! (other instanceof SimpleJITReference)))
		return false;
	    if (this == other)
		return true;
	    SimpleJITReference otherref =
		(SimpleJITReference)other;
	    if (this.isNull != otherref.isNull)
		return false;
	    boolean thisbpnull = (this.bp == null);
	    boolean otherbpnull = (otherref.bp == null);
	    boolean thistnnull = (this.typename == null);
	    boolean othertnnull = (otherref.typename == null);

	    if (thisbpnull != otherbpnull) {
		return false;
	    } else if (thisbpnull && otherbpnull) {
		if (thistnnull != othertnnull)
		    return false;
		else if (thistnnull && othertnnull)
		    return true;
		else
		    return this.typename.equals(otherref.typename);
	    } else {
		return this.bp == otherref.bp;
	    }
	}
	public String toString() {
	    String s;
	    if (isNull)
		s = "NULL";
	    else if (bp != null)
		s = bp.getName() + ", R";
	    else if (typename != null)
		s = typename + ", U";
	    else
		s = "U";
	    return "[REF(" + s + ")]";
	}
    }

    public static final class SimpleJITArray
	extends SimpleJITReference {
	protected int constantLength;
	protected final boolean isLengthConstant;
	public SimpleJITArray() { // for unknown type
	    super();
	    isLengthConstant = false;
	}
	public SimpleJITArray(int length) { // for unknown type
	    super();
	    isLengthConstant = true;
	    constantLength = length;
	}
	public SimpleJITArray(TypeName.Array tn) {
	    super(tn);
	    isLengthConstant = false;
	}
	public SimpleJITArray(TypeName.Array tn, int length) {
	    super(tn);
	    this.constantLength = length;
	    isLengthConstant = true;
	}
	public SimpleJITArray(Blueprint.Array bp) {
	    super(bp);
	    isLengthConstant = false;
	}
	public SimpleJITArray(Blueprint.Array bp, int length) {
	    super(bp);
	    this.constantLength = length;
	    isLengthConstant = true;
	}
	public boolean isArray() { return true; }
	public boolean isLengthConstant() {
	    return isLengthConstant;
	}
	public int getConstantLength() {
	    if (isLengthConstant)
		return constantLength;
	    else
		throw new Error();
	}
	public boolean includes(AbstractValue other) {
	    if (other == null)
		return false;
	    if (this == other)
		return true;
	    if (! (other instanceof SimpleJITArray))
		return false;
	    // Now other is a SimpleJITArray
	    SimpleJITArray otherref =
		(SimpleJITArray)other;
	    if (this.isNull && (! otherref.isNull))
		return false;
	    boolean thisbpnull = (this.bp == null);
	    boolean otherbpnull = (otherref.bp == null);
	    boolean thistnnull = (this.typename == null);
	    boolean othertnnull = (otherref.typename == null);

	    boolean thislengthconstant = this.isLengthConstant;
	    boolean otherlengthconstant 
		= otherref.isLengthConstant;
	    boolean includesInTermsOfLength =
		(thislengthconstant && (! otherlengthconstant))
		? false
		: ((! thislengthconstant) && otherlengthconstant)
		? true
		: (thislengthconstant && otherlengthconstant)
		? this.constantLength == otherref.constantLength
		: true;

	    if (thisbpnull && (! otherbpnull)) {
		// othertnnull must be false
		if (thistnnull)
		    return includesInTermsOfLength;
		else
		    return this.typename.equals(otherref.typename)
			&& includesInTermsOfLength;
	    } else if ((! thisbpnull) && otherbpnull) {
		return false;
	    } else if (thisbpnull && otherbpnull) {
		if (thistnnull && (! othertnnull))
		    return includesInTermsOfLength;
		else if ((! thistnnull) && othertnnull)
		    return false;
		else if (thistnnull && othertnnull)
		    return includesInTermsOfLength;
		else
		    return this.typename.equals(otherref.typename)
			&& includesInTermsOfLength;
	    } else {
		return otherref.bp.getType()
		    .isSubtypeOf(this.bp.getType())
		    && includesInTermsOfLength;
	    }
	}
	public AbstractValue merge(AbstractValue other) {
	    if (other == null)
		return DEAD;
	    if (this == other)
		return this;
	    if (! (other instanceof SimpleJITReference)
		&& (! (other instanceof SimpleJITArray)))
		return DEAD;
	    if (other instanceof SimpleJITReference
		&& (! (other instanceof SimpleJITArray)))
		return super.merge(other);
	    // Now other is a SimpleJITArray
	    SimpleJITArray otherref =
		(SimpleJITArray)other;
	    boolean mergedIsNull = this.isNull && otherref.isNull;
	    Blueprint mergedBP;
	    TypeName mergedTypeName;
	    if (this.bp == null || otherref.bp == null) {
		mergedBP = null;
		if (this.typename == null 
		    || otherref.typename == null)
		    mergedTypeName = null;
		else if (this.typename.equals(otherref.typename))
		    mergedTypeName = this.typename;
		else
		    mergedTypeName = null;
	    } else {
		Blueprint[] leastCommonSupertypes =
		    Driver.leastCommonSupertypes(this.bp,
						 otherref.bp);
		if (leastCommonSupertypes.length == 0) {
		    mergedBP = null;
		    if (this.typename.equals(otherref.typename))
			mergedTypeName = this.typename;
		    else
			mergedTypeName = null;
		} else {
		    // arbitrarily take the first one
		    mergedBP = leastCommonSupertypes[0];
		    mergedTypeName = mergedBP.getName();
		}
	    }
	    boolean mergedLengthConstant = false;
	    int mergedConstantLength = -1;
	    if (this.isLengthConstant && otherref.isLengthConstant
		&& this.constantLength == otherref.constantLength) {
		mergedLengthConstant = true;
		mergedConstantLength = this.constantLength;
	    }
	    if (mergedBP != null) {
		// In case of merging arrays of different primitive
		// arrays : java.lang.Object
		if (! mergedBP.isArray())
		    return new SimpleJITReference(mergedBP);
		return (mergedIsNull
			? (mergedLengthConstant 
			   ? new SimpleJITArray
			   (mergedBP.asArray(), 
			    mergedConstantLength).declareNull()
			   : new SimpleJITArray
			   (mergedBP.asArray()).declareNull())
			: (mergedLengthConstant 
			   ? new SimpleJITArray
			   (mergedBP.asArray(), mergedConstantLength)
			   : new SimpleJITArray
			   (mergedBP.asArray())));
	    } else if (mergedTypeName != null) {
		// In case of merging arrays of different primitive
		// arrays : java.lang.Object
		if (! mergedTypeName.isArray())
		    return new SimpleJITReference(mergedTypeName.asCompound());
		return (mergedIsNull
			? (mergedLengthConstant 
			   ? new SimpleJITArray
			   (mergedTypeName.asArray(), 
			    mergedConstantLength).declareNull()
			   : new SimpleJITArray
			   (mergedTypeName.asArray()).declareNull())
			: (mergedLengthConstant 
			   ? new SimpleJITArray
			   (mergedTypeName.asArray(), mergedConstantLength)
			   : new SimpleJITArray
			   (mergedTypeName.asArray())));
	    } else {
		return (mergedIsNull
			? (mergedLengthConstant 
			   ? new SimpleJITArray
			   (mergedConstantLength).declareNull()
			   : new SimpleJITArray().declareNull())
			: (mergedLengthConstant 
			   ? new SimpleJITArray(mergedConstantLength)
			   : new SimpleJITArray()));
	    }
	}
	public String toString() {
	    String s;
	    if (isNull)
		s = "NULL";
	    else if (bp != null)
		s = bp.getName() + ", R";
	    else if (typename != null)
		s = typename + ", U";
	    else
		s = "U";
	    if (isLengthConstant)
		s += ", " + constantLength;
	    return "[ARR(" + s + ")]";
	}
	public boolean equals(AbstractValue other) {
	    if (other == null)
		return false;
	    if (this == other)
		return true;
	    if (! (other instanceof SimpleJITArray))
		return false;
	    // Now other is a SimpleJITArray
	    SimpleJITArray otherref =
		(SimpleJITArray)other;
	    if (this.isNull != otherref.isNull)
		return false;
	    boolean thisbpnull = (this.bp == null);
	    boolean otherbpnull = (otherref.bp == null);
	    boolean thistnnull = (this.typename == null);
	    boolean othertnnull = (otherref.typename == null);

	    boolean sameConstantLength =
		(this.isLengthConstant
		 == otherref.isLengthConstant)
		? (this.constantLength
		   == otherref.constantLength)
		: true;

	    if (thisbpnull != otherbpnull) {
		return false;
	    } else if (thisbpnull && otherbpnull) {
		if (thistnnull != othertnnull)
		    return false;
		else if (thistnnull && othertnnull)
		    return sameConstantLength;
		else
		    return (this.typename.equals(otherref.typename)
			    && sameConstantLength);
	    } else {
		return (this.bp == otherref.bp
			&& sameConstantLength);
	    }
	}
    }

    public static abstract class SimpleJITPrimitive
	extends SimpleJITValue {
    }

    public static final class SimpleJITInt
	extends SimpleJITPrimitive {
	protected int value;
	protected boolean constant;
	public SimpleJITInt() {
	    constant = false;
	}
	public SimpleJITInt(int v) {
	    this.value = v;
	    constant = true;
	}
	public boolean isConstant() {
	    return constant;
	}
	public boolean isPrimitive() { return true; }
	public boolean isWidePrimitive() { return false; }
	public String getName() {
	    return "I";
	}
	public String toString() {
	    if (constant)
		return "[INT(" + value + ")]";
	    else
		return "[INT]";
	}
	public int getConstantInt() { 
	    if (isConstant())
		return value; 
	    else
		throw new Error();
	}
	public boolean includes (AbstractValue v) {
	    if (v == null)
		return false;
	    if (this == v)
		return true;
	    if (v instanceof SimpleJITInt) {
		SimpleJITInt vr = (SimpleJITInt)v;
		return (constant && (! vr.constant))
		    ? false
		    : ((! constant) && vr.constant)
		    ? true
		    : (constant && vr.constant)
		    ? value == vr.value
		    : true;
	    } else
		return false;
	}
	public AbstractValue merge(AbstractValue v) {
	    if (v == null)
		return DEAD;
	    if (this == v)
		return this;
	    else if (v instanceof SimpleJITInt) {
		SimpleJITInt vr = (SimpleJITInt)v;
		if (constant
		    && vr.constant
		    && value == vr.value)
		    return new SimpleJITInt(value);
		else
		    return new SimpleJITInt();
	    } else
		return DEAD;
	}
	public boolean equals(AbstractValue v) {
	    if (v == null)
		return false;
	    if (this == v)
		return true;
	    else if (v instanceof SimpleJITInt) {
		SimpleJITInt vr = (SimpleJITInt)v;
		return 
		    ((constant && vr.constant
		      &&value == vr.value) 
		     || ((! constant) && (! vr.constant)));
	    } else
		return false;
	}
    }

    public static final class SimpleJITFloat 
	extends SimpleJITPrimitive {
	protected float value;
	protected boolean constant;
	public SimpleJITFloat() {
	    constant = false;
	}
	public SimpleJITFloat(float v) {
	    this.value = v;
	    constant = true;
	}
	public String getName() {
	    return "F";
	}
	public boolean isConstant() {
	    return constant;
	}
	public float getConstantFloat() {
	    return value;
	}
	public boolean isPrimitive() { return true; }
	public boolean isWidePrimitive() { return false; }
	public String toString() {
	    if (isConstant())
		return "[FLOAT(" + value + ")]";
	    else
		return "[FLOAT]";
	}
	public boolean includes (AbstractValue v) {
	    if (v == null)
		return false;
	    if (this == v)
		return true;
	    if (v instanceof SimpleJITFloat) {
		SimpleJITFloat vr = (SimpleJITFloat)v;
		return (constant && (! vr.constant))
		    ? false
		    : ((! constant) && vr.constant)
		    ? true
		    : (constant && vr.constant)
		    ? value == vr.value
		    : true;
	    } else
		return false;
	}
	public AbstractValue merge(AbstractValue v) {
	    if (v == null)
		return DEAD;
	    if (this == v)
		return this;
	    else if (v instanceof SimpleJITFloat) {
		SimpleJITFloat vr = (SimpleJITFloat)v;
		if (constant
		    && vr.constant
		    && value == vr.value)
		    return new SimpleJITFloat(value);
		else
		    return new SimpleJITFloat();
	    } else
		return DEAD;
	}
	public boolean equals(AbstractValue v) {
	    if (v == null)
		return false;
	    if (this == v)
		return true;
	    else if (v instanceof SimpleJITFloat) {
		SimpleJITFloat vr = (SimpleJITFloat)v;
		return 
		    ((constant && vr.constant
		      &&value == vr.value) 
		     || ((! constant) && (! vr.constant)));
	    } else
		return false;
	}
    }

    public static final class SimpleJITLong
	extends SimpleJITPrimitive {
	protected long value;
	protected boolean constant;
	public SimpleJITLong() {
	    constant = false;
	}
	public SimpleJITLong(long v) {
	    this.value = v;
	    constant = true;
	}
	public String getName() {
	    return "J";
	}
	public boolean isConstant() {
	    return constant;
	}
	public long getConstantLong() {
	    return value;
	}
	public boolean isWidePrimitive() { return true; }
	public boolean isPrimitive() { return false; }
	public String toString() {
	    if (isConstant())
		return "[LONG(" + value + ")]";
	    else
		return "[LONG]";
	}
	public boolean includes (AbstractValue v) {
	    if (v == null)
		return false;
	    if (this == v)
		return true;
	    if (v instanceof SimpleJITLong) {
		SimpleJITLong vr = (SimpleJITLong)v;
		return (constant && (! vr.constant))
		    ? false
		    : ((! constant) && vr.constant)
		    ? true
		    : (constant && vr.constant)
		    ? value == vr.value
		    : true;
	    } else
		return false;
	}
	public AbstractValue merge(AbstractValue v) {
	    if (v == null)
		return DEAD;
	    if (this == v)
		return this;
	    else if (v instanceof SimpleJITLong) {
		SimpleJITLong vr = (SimpleJITLong)v;
		if (constant
		    && vr.constant
		    && value == vr.value)
		    return new SimpleJITLong(value);
		else
		    return new SimpleJITLong();
	    } else
		return DEAD;
	}
	public boolean equals(AbstractValue v) {
	    if (v == null)
		return false;
	    if (this == v)
		return true;
	    else if (v instanceof SimpleJITLong) {
		SimpleJITLong vr = (SimpleJITLong)v;
		return 
		    ((constant && vr.constant
		      &&value == vr.value) 
		     || ((! constant) && (! vr.constant)));
	    } else
		return false;
	}
    }

    public static final class SimpleJITDouble 
	extends SimpleJITPrimitive {
	protected double value;
	protected boolean constant;
	public SimpleJITDouble() {
	    constant = false;
	}
	public SimpleJITDouble(double v) {
	    this.value = v;
	    constant = true;
	}
	public String getName() {
	    return "D";
	}
	public boolean isConstant() {
	    return constant;
	}
	public double getConstantDouble() {
	    return value;
	}
	public boolean isWidePrimitive() { return true; }
	public boolean isPrimitive() { return false; }
	public String toString() {
	    if (isConstant())
		return "[DOUBLE(" + value + ")]";
	    else
		return "[DOUBLE]";
	}
	public boolean includes (AbstractValue v) {
	    if (v == null)
		return false;
	    if (this == v)
		return true;
	    if (v instanceof SimpleJITDouble) {
		SimpleJITDouble vr = (SimpleJITDouble)v;
		return (constant && (! vr.constant))
		    ? false
		    : ((! constant) && vr.constant)
		    ? true
		    : (constant && vr.constant)
		    ? value == vr.value
		    : true;
	    } else
		return false;
	}
	public AbstractValue merge(AbstractValue v) {
	    if (v == null)
		return DEAD;
	    if (this == v)
		return this;
	    else if (v instanceof SimpleJITDouble) {
		SimpleJITDouble vr = (SimpleJITDouble)v;
		if (constant
		    && vr.constant
		    && value == vr.value)
		    return new SimpleJITDouble(value);
		else
		    return new SimpleJITDouble();
	    } else
		return DEAD;
	}
	public boolean equals(AbstractValue v) {
	    if (v == null)
		return false;
	    if (this == v)
		return true;
	    else if (v instanceof SimpleJITDouble) {
		SimpleJITDouble vr = (SimpleJITDouble)v;
		return 
		    ((constant && vr.constant
		      &&value == vr.value) 
		     || ((! constant) && (! vr.constant)));
	    } else
		return false;
	}
    }

}
