/src/kilim/analysis/Value.java
http://github.com/kilim/kilim · Java · 199 lines · 126 code · 26 blank · 47 comment · 36 complexity · fa17ea5e9ee1dc6b861688f753a85d71 MD5 · raw file
- /* Copyright (c) 2006, Sriram Srinivasan
- *
- * You may distribute this software under the terms of the license
- * specified in the file "License"
- */
- package kilim.analysis;
- import static kilim.Constants.D_UNDEFINED;
- import static kilim.Constants.D_NULL;
- import java.util.Arrays;
- import kilim.mirrors.Detector;
- /**
- * A SSA value that represents all objects produced at a particular
- * location in the code. Value objects are used by dataflow analysis
- * (@see BasicBlock)
- *
- */
- public class Value {
- public static Object NO_VAL = new Object();
- public static Value V_UNDEFINED = new Value(0, D_UNDEFINED, NO_VAL);
-
- private String typeDesc;
-
- private Object constVal;
-
- private int numSites;
- private int[] sites;
-
- public int getNumSites() {return numSites;}
-
- public int[] getCreationSites() {return sites;}
-
- public String getTypeDesc() {return typeDesc;}
-
- public Object getConstVal() {return constVal;}
-
- private Value(int aPos, String aDesc, Object aConst) {
- sites = new int[2];
- numSites = 1;
- sites[0] = aPos;
- typeDesc = aDesc;
- constVal = aConst;
- //System.out.println("V[" + aPos + ":" + aDesc + ((aConst == NO_VAL) ? "" : (": " + aConst)) + "]");
- }
-
- private Value(int newNumSites, int[] newSites, String newType, Object newConst) {
- Arrays.sort(newSites, 0, newNumSites);
- numSites = newNumSites;
- sites = newSites;
- typeDesc = newType;
- constVal = newConst;
- /*//debug
- StringBuilder sb = new StringBuilder(80);
- sb.append("V[");
- for (int i = 0; i < newNumSites; i++) {
- if (i > 0) sb.append(",");
- sb.append(newSites[i]);
- }
- sb.append(":").append(newType).append(":");
- if (newConst != NO_VAL) {
- sb.append(": ").append(newConst.toString());
- }
- sb.append("]");
- System.out.println(sb);
- */
- }
- /**
- * Produces a new value (if necessary), if the instructions are different or
- * the types are different. The types are merged to form a least common
- * upper bound, and the instruction sets are unioned.
- * @param vb
- * @return this if the result of the merge is no different, or the new value
- */
- public Value merge(Detector det,Value other) {
- int[] newSites = new int[this.numSites + other.numSites];
- for (int i = 0; i < newSites.length; i++) newSites[i] = -1;
- int newNumSites = mergeSites(newSites, other);
- String newType;
- try {
- newType = TypeDesc.mergeType(det, this.typeDesc, other.typeDesc);
- } catch (IncompatibleTypesException e) {
- newType = D_UNDEFINED;
- }
- Object newConst = (constVal.equals(other.constVal)) ? constVal : NO_VAL;
- if (newNumSites != numSites || newType != typeDesc || newConst != constVal) {
- return new Value(newNumSites, newSites, newType, newConst);
- } else {
- return this; // no change
- }
- }
-
- private int mergeSites(int[]newSites, Value other) {
- int uniqueNumSites = 0;
- for (int i = 0; i < numSites; i++) {
- uniqueNumSites += addTo(newSites, sites[i]);
- }
- for (int i = 0; i < other.numSites; i++) {
- uniqueNumSites += addTo(newSites, other.sites[i]);
- }
- return uniqueNumSites;
- }
-
-
- private int addTo(int[] newSites, int site) {
- for (int i = 0; i < newSites.length; i++) {
- int s = newSites[i];
- if (s == -1) {
- newSites[i] = site;
- return 1; // added an element
- }
- if (s == site) return 0; // added no elements
- }
- return 0;
- }
- @Override
- public boolean equals(Object obj) {
- if (this == obj) return true;
- Value other = (Value)obj;
- if (this.typeDesc.equals(other.typeDesc) &&
- this.constVal.equals(other.constVal) &&
- this.numSites == other.numSites) {
- // Check sites
- for (int i = 0; i < this.numSites; i++) {
- if (sites[i] != other.sites[i]) {
- return false;
- }
- }
- return true;
- }
- return false;
- }
- @Override
- public int hashCode() {
- int h = typeDesc.hashCode();
- for (int i = 0; i < numSites; i++) {
- h ^= sites[i];
- }
- return h;
- }
- /**
- * create a new Value with the given position and type and no constant value
- * @param pos the position in the method for the corresponding instruction, or a unique value for method params
- * @param desc the type descriptor
- * @return the new Value
- */
- public static Value make(int pos, String desc) {
- return new Value(pos, desc, NO_VAL);
- }
-
- /**
- * create a new Value
- * @param pos the position in the method for the corresponding instruction, or a unique value for method params
- * @param desc the type descriptor
- * @param aConstVal the constant value
- * @return the new Value
- */
- public static Value make(int pos, String desc, Object aConstVal) {
- return new Value(pos, desc, aConstVal);
- }
- public boolean isCategory2() {
- return category() == 2;
- }
-
- public boolean isCategory1() {
- return category() == 1;
- }
-
- @Override
- public String toString() {
- if (numSites == 0 && typeDesc == D_UNDEFINED) return "undef";
- StringBuffer sb = new StringBuffer(40);
- sb.append(typeDesc).append('[');
- for (int i = 0; i < numSites; i++) {
- if (i > 0) sb.append(' ');
- sb.append(sites[i]);
- }
- sb.append(']');
- if (constVal != NO_VAL) {
- sb.append(" == ").append(constVal.toString());
- }
- return sb.toString();
- }
- public boolean isConstant() {
- return constVal != NO_VAL || typeDesc == D_NULL;
- }
- public int category() {
- return TypeDesc.isDoubleWord(typeDesc) ? 2 : 1;
- }
-
- }