Example #1
0
  /**
   * Collapse <code>structECR</code> by merge it with all its element ECRs, and set its type as the
   * cell type (simple type might with top size)
   *
   * @param structECR
   * @param structT
   * @param ECRCache avoid structure cycle
   * @return
   */
  private ValueType collapseStruct(ECR structECR, StructType structT, Collection<ECR> ECRCache) {
    // Ensure collapsed type to be simple
    ValueType unionType = null;

    // join components
    Collection<ECR> elems = structT.getFieldMap().asMapOfRanges().values();
    Collection<ECR> cjoins = Sets.newHashSet();
    Collection<Pair<Size, ECR>> ccjoins = Sets.newHashSet();

    for (ECR elem : elems) {
      ECR elemLoc = getLoc(elem);
      ValueType elemLocType = getType(elemLoc);
      Parent parent = elemLocType.getParent().removeECR(structECR);
      elemLocType.setParent(parent);

      if (!ECRCache.add(elemLoc)) continue; // ECRCache has elemLoc

      cjoins.addAll(getCjoins(elemLoc));
      elemLoc.clearCCjoins(ccjoins);
      ccjoins.addAll(getCCjoins(elemLoc));
      elemLoc.clearCCjoins(ccjoins);

      if (elemLocType.isStruct()) {
        elemLocType = collapseStruct(elemLoc, elemLocType.asStruct(), ECRCache);
      }

      union(structECR, elemLoc);
      unionType = unionType == null ? elemLocType : unify(unionType, elemLocType);
    }
    unionType = unionType == null ? ValueType.bottom() : unionType;

    setType(structECR, unionType);
    ECR root = findRoot(structECR);

    for (Pair<Size, ECR> cjoinPair : ccjoins) ccjoin(cjoinPair.fst(), root, cjoinPair.snd());

    for (ECR joinECR : cjoins) cjoin(root, joinECR);

    return unionType;
  }
Example #2
0
  ECR cjoin(ECR e1, ECR e2) {
    if (e1.equals(e2)) return findRoot(e1);

    if (getType(e1).isBottom()) {

      Collection<ECR> joins2 = getCjoins(e2);
      Collection<Pair<Size, ECR>> cjoins2 = getCCjoins(e2);

      addCjoin(e1, e2);
      addCjoins(e1, joins2);
      addCCjoins(e1, cjoins2);

      return findRoot(e1);
    }

    return join(e1, e2);
  }
Example #3
0
  /**
   * Set type <code>e</code> as <code>type</code>
   *
   * @param e
   * @param type
   */
  void setType(ECR e, ValueType type) {
    ECR root = findRoot(e);
    root.setType(type);

    Collection<Pair<Size, ECR>> ccjoins = ImmutableList.copyOf(root.getCCjoins());
    root.clearCCjoins(ccjoins);
    for (Pair<Size, ECR> cjoinPair : ccjoins) ccjoin(cjoinPair.fst(), root, cjoinPair.snd());

    Collection<ECR> cjoins = ImmutableList.copyOf(root.getCjoins());
    root.clearCjoins(cjoins);
    for (ECR joinECR : cjoins) cjoin(root, joinECR);
  }
Example #4
0
  ECR join(ECR e1, ECR e2) {
    if (e1.equals(e2)) return e1;

    checkStructCollapse(e1, e2);

    ValueType t1 = getType(e1);
    ValueType t2 = getType(e2);

    Collection<Pair<Size, ECR>> ccjoins1 = ImmutableList.copyOf(getCCjoins(e1));
    Collection<Pair<Size, ECR>> ccjoins2 = ImmutableList.copyOf(getCCjoins(e2));

    Collection<ECR> cjoins1 = ImmutableList.copyOf(getCjoins(e1));
    Collection<ECR> cjoins2 = ImmutableList.copyOf(getCjoins(e2));

    ECR root = union(e1, e2);

    switch (t1.getKind()) {
      case BOTTOM:
        {
          switch (t2.getKind()) {
            case BOTTOM:
              {
                Collection<ECR> cjoins = Sets.newHashSet();
                cjoins.addAll(cjoins1);
                cjoins.addAll(cjoins2);
                root.addCjoins(cjoins);

                Collection<Pair<Size, ECR>> ccjoins = Sets.newHashSet();
                ccjoins.addAll(ccjoins1);
                ccjoins.addAll(ccjoins2);
                root.addCCjoins(ccjoins);

                break;
              }
            default:
              {
                root.setType(t2);

                root.clearCCjoins(ccjoins1);
                for (Pair<Size, ECR> pair : ccjoins1) ccjoin(pair.fst(), root, pair.snd());

                root.clearCjoins(cjoins1);
                for (ECR cjoin : cjoins1) cjoin(root, cjoin);

                break;
              }
          }
          break;
        }
      default:
        {
          switch (t2.getKind()) {
            case BOTTOM:
              {
                root.setType(t1);

                root.clearCCjoins(ccjoins2);
                for (Pair<Size, ECR> pair : ccjoins2) ccjoin(pair.fst(), root, pair.snd());

                root.clearCjoins(cjoins2);
                for (ECR cjoin : cjoins2) cjoin(root, cjoin);

                break;
              }
            default:
              {
                root.setType(t1);
                ValueType unionType = unify(t1, t2);

                ValueType freshType = getType(root);
                if (!freshType.equals(t1)) {
                  unionType = resolveType(root, unionType, freshType);
                }

                root.setType(unionType);

                root.clearCCjoins(ccjoins1);
                root.clearCCjoins(ccjoins2);

                for (Pair<Size, ECR> pair : ccjoins1) ccjoin(pair.fst(), root, pair.snd());
                for (Pair<Size, ECR> pair : ccjoins2) ccjoin(pair.fst(), root, pair.snd());
                break;
              }
          }
          break;
        }
    }

    return root;
  }
Example #5
0
 /**
  * Create a pair of location ECR and function ECR, both with bottome type
  *
  * @return
  */
 private Pair<ECR, ECR> createBottomLocFunc() {
   ECR loc = ECR.createBottom();
   ECR func = ECR.createBottom();
   return Pair.of(loc, func);
 }
Example #6
0
 /**
  * Get the root of ECR <code>e</code>
  *
  * @param e
  * @return
  */
 ECR findRoot(ECR e) {
   return (ECR) e.findRoot();
 }
Example #7
0
  void ccjoin(Size rangeSize, ECR e1, ECR e2) {
    ValueType type1 = getType(e1);
    if (type1.isBottom()) {
      addCCjoin(rangeSize, e1, e2);
      return;
    }

    Size size1 = type1.getSize();
    if (!Size.isLessThan(rangeSize, size1)) {
      addCCjoin(rangeSize, e1, e2);
      expand(e1, rangeSize); // expand(e1) would call setType(e1, ...) and thus ccjoin(e1, e2)
      return;
    }

    if (e1.equals(e2)) return;

    switch (type1.getKind()) {
      case BLANK:
        {
          addCCjoin(rangeSize, e1, e2);
          ValueType type2 = getType(e2);
          switch (type2.getKind()) {
            case BOTTOM:
              setType(e2, ValueType.blank(rangeSize, Parent.getBottom()));
              return;
            default:
              Size size2 = type2.getSize();
              if (!Size.isLessThan(rangeSize, size2)) expand(e2, rangeSize);
              return;
          }
        }
      case SIMPLE:
        {
          ValueType type2 = getType(e2);
          switch (type2.getKind()) {
            case BOTTOM:
              setType(
                  e2,
                  ValueType.simple(
                      type1.asSimple().getLoc(),
                      type1.asSimple().getFunc(),
                      rangeSize,
                      Parent.getBottom(),
                      type2.hasOpTag()));
              return;
            case BLANK:
              {
                setType(
                    e2,
                    ValueType.simple(
                        type1.asSimple().getLoc(),
                        type1.asSimple().getFunc(),
                        type2.getSize(),
                        type2.getParent(),
                        type2.hasOpTag()));
                Size size2 = type2.getSize();
                if (!Size.isLessThan(rangeSize, size2)) expand(e2, rangeSize);
                return;
              }
            case SIMPLE:
              {
                cjoin(type1.asSimple().getLoc(), type2.asSimple().getLoc());
                cjoin(type1.asSimple().getFunc(), type2.asSimple().getFunc());
                Size size2 = type2.getSize();
                if (!Size.isLessThan(rangeSize, size2)) expand(e2, rangeSize);
                return;
              }
            case STRUCT:
              {
                addCCjoin(rangeSize, e1, e2);
                collapseStruct(e2, type2.asStruct());
                return;
              }
            default: // lambda
              return;
          }
        }
      case STRUCT:
        {
          ValueType type2 = getType(e2);
          switch (type2.getKind()) {
            case BOTTOM:
              {
                RangeMap<Long, ECR> fieldMapCopy = FieldRangeMap.create();
                fieldMapCopy.putAll(type1.asStruct().getFieldMap());
                setType(
                    e2,
                    ValueType.struct(
                        fieldMapCopy, rangeSize, Parent.getBottom(), type2.hasOpTag()));
                return;
              }
            case BLANK:
              {
                RangeMap<Long, ECR> fieldMapCopy = FieldRangeMap.create();
                fieldMapCopy.putAll(type1.asStruct().getFieldMap());
                Size size2 = type2.getSize();
                setType(
                    e2, ValueType.struct(fieldMapCopy, size2, type2.getParent(), type2.hasOpTag()));
                if (!Size.isLessThan(rangeSize, size2)) expand(e2, rangeSize);
                return;
              }
            case SIMPLE:
              {
                addCCjoin(rangeSize, e1, e2);
                Size size2 = type2.getSize();
                if (!Size.isLessThan(rangeSize, size2)) expand(e2, rangeSize);
                for (ECR elemECR : type1.asStruct().getFieldMap().asMapOfRanges().values()) {
                  ValueType elemType = getType(elemECR);
                  Size elemSize = elemType.getSize();
                  ccjoin(elemSize, elemECR, e2);
                }
                return;
              }
            case STRUCT:
              {
                throw new IllegalArgumentException();
                //				Size size2 = type2.getSize();
                //				if(!Size.isLessThan(rangeSize, size2)) {
                //					addCCjoin(rangeSize, e1, e2);
                //					expand(e2, rangeSize); return;
                //				}
                //
                //				ValueType unifyStructType = unify(type1, type2); // unify structure type
                // eagerly
                //				setType(e1, unifyStructType);
                //				setType(e2, unifyStructType);
                //				return;
              }
            default:
              return; // lambda
          }
        }
      default:
        return; // lambda
    }
  }