From: yeom Date: Sat, 9 Jul 2011 01:13:22 +0000 (+0000) Subject: changes. X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=f7d7d8aff5cfc5e0462c687d2b2c6815d5d202b3;p=IRC.git changes. --- diff --git a/Robust/src/Analysis/SSJava/DefinitelyWrittenCheck.java b/Robust/src/Analysis/SSJava/DefinitelyWrittenCheck.java index 7cc86f16..437c22ba 100644 --- a/Robust/src/Analysis/SSJava/DefinitelyWrittenCheck.java +++ b/Robust/src/Analysis/SSJava/DefinitelyWrittenCheck.java @@ -6,7 +6,6 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.Set; import java.util.Stack; -import java.util.Vector; import Analysis.CallGraph.CallGraph; import Analysis.Loops.LoopFinder; @@ -25,6 +24,7 @@ import IR.Flat.FlatNode; import IR.Flat.FlatOpNode; import IR.Flat.FlatSetFieldNode; import IR.Flat.TempDescriptor; +import Util.Pair; public class DefinitelyWrittenCheck { @@ -63,14 +63,21 @@ public class DefinitelyWrittenCheck { // maps a method descriptor to its current summary during the analysis // then analysis reaches fixed-point, this mapping will have the final summary // for each method descriptor - private Hashtable, Set>> mapMethodDescriptorToCompleteClearingSummary; + private Hashtable, SharedLocState>> mapMethodDescriptorToCompleteClearingSummary; // maps a method descriptor to the merged incoming caller's current // overwritten status - private Hashtable, Set>> mapMethodDescriptorToInitialClearingSummary; + private Hashtable, SharedLocState>> mapMethodDescriptorToInitialClearingSummary; // maps a flat node to current partial results - private Hashtable, Set>> mapFlatNodeToClearingSummary; + private Hashtable, SharedLocState>> mapFlatNodeToClearingSummary; + + // maps shared location to the set of descriptors which belong to the shared + // location + private Hashtable, Location>, Set> mapSharedLocation2DescriptorSet; + + // data structure for merging current state + private Hashtable, Location>, Boolean> mapHeapPathLocation2Flag; private FlatNode ssjavaLoopEntrance; private LoopFinder ssjavaLoop; @@ -96,11 +103,14 @@ public class DefinitelyWrittenCheck { this.calleeIntersectBoundOverWriteSet = new HashSet>(); this.mapMethodDescriptorToCompleteClearingSummary = - new Hashtable, Set>>(); + new Hashtable, SharedLocState>>(); this.mapMethodDescriptorToInitialClearingSummary = - new Hashtable, Set>>(); + new Hashtable, SharedLocState>>(); this.mapFlatNodeToClearingSummary = - new Hashtable, Set>>(); + new Hashtable, SharedLocState>>(); + this.mapSharedLocation2DescriptorSet = + new Hashtable, Location>, Set>(); + this.mapHeapPathLocation2Flag = new Hashtable, Location>, Boolean>(); this.LOCAL = new TempDescriptor("LOCAL"); } @@ -109,13 +119,37 @@ public class DefinitelyWrittenCheck { methodReadOverWriteAnalysis(); writtenAnalyis(); sharedLocationAnalysis(); + checkSharedLocationResult(); + } + } + + private void checkSharedLocationResult() { + + Hashtable, SharedLocState> result = + mapFlatNodeToClearingSummary.get(ssjavaLoopEntrance); + System.out.println("checkSharedLocationResult=" + result); + Set> hpKeySet = result.keySet(); + for (Iterator iterator = hpKeySet.iterator(); iterator.hasNext();) { + NTuple hpKey = (NTuple) iterator.next(); + SharedLocState state = result.get(hpKey); + Set locKeySet = state.getLocationSet(); + for (Iterator iterator2 = locKeySet.iterator(); iterator2.hasNext();) { + Location locKey = (Location) iterator2.next(); + if (!state.getFlag(locKey)) { + throw new Error( + "Some concrete locations of the shared abstract location are not cleared at the same time."); + } + } } + } private void sharedLocationAnalysis() { // verify that all concrete locations of shared location are cleared out at // the same time once per the out-most loop + computeReadSharedDescriptorSet(); + Set methodDescriptorsToAnalyze = new HashSet(); methodDescriptorsToAnalyze.addAll(ssjava.getAnnotationRequireSet()); @@ -169,7 +203,6 @@ public class DefinitelyWrittenCheck { // intraprocedural analysis Set flatNodesToVisit = new HashSet(); - Set visited = new HashSet(); if (onlyVisitSSJavaLoop) { flatNodesToVisit.add(ssjavaLoopEntrance); @@ -181,21 +214,38 @@ public class DefinitelyWrittenCheck { FlatNode fn = flatNodesToVisit.iterator().next(); flatNodesToVisit.remove(fn); - Hashtable, Set> curr = - new Hashtable, Set>(); + Hashtable, SharedLocState> curr = + new Hashtable, SharedLocState>(); + mapHeapPathLocation2Flag.clear(); for (int i = 0; i < fn.numPrev(); i++) { FlatNode prevFn = fn.getPrev(i); - Hashtable, Set> in = - mapFlatNodeToClearingSummary.get(prevFn); + Hashtable, SharedLocState> in = mapFlatNodeToClearingSummary.get(prevFn); if (in != null) { mergeSharedAnaylsis(curr, in); } } + // merge flag status + Set> hpKeySet = curr.keySet(); + for (Iterator iterator = hpKeySet.iterator(); iterator.hasNext();) { + NTuple hpKey = (NTuple) iterator.next(); + SharedLocState currState = curr.get(hpKey); + Set locKeySet = currState.getMap().keySet(); + for (Iterator iterator2 = locKeySet.iterator(); iterator2.hasNext();) { + Location locKey = (Location) iterator2.next(); + Pair, Boolean> pair = currState.getMap().get(locKey); + boolean currentFlag = pair.getSecond().booleanValue(); + Boolean inFlag = mapHeapPathLocation2Flag.get(new Pair(hpKey, locKey)); + boolean newFlag = currentFlag | inFlag.booleanValue(); + if (currentFlag != newFlag) { + currState.getMap().put(locKey, new Pair(pair.getFirst(), new Boolean(newFlag))); + } + } + } sharedLocation_nodeActions(fn, curr, onlyVisitSSJavaLoop); - Hashtable, Set> clearingPrev = + Hashtable, SharedLocState> clearingPrev = mapFlatNodeToClearingSummary.get(fn); if (!curr.equals(clearingPrev)) { @@ -216,7 +266,7 @@ public class DefinitelyWrittenCheck { } private void sharedLocation_nodeActions(FlatNode fn, - Hashtable, Set> curr, boolean isSSJavaLoop) { + Hashtable, SharedLocState> curr, boolean isSSJavaLoop) { TempDescriptor lhs; TempDescriptor rhs; @@ -235,8 +285,10 @@ public class DefinitelyWrittenCheck { NTuple lhsHeapPath = new NTuple(); rhsHeapPath.add(LOCAL); lhsHeapPath.add(LOCAL); - readLocation(curr, rhsHeapPath, rhs); - writeLocation(curr, lhsHeapPath, lhs); + if (!lhs.getSymbol().startsWith("neverused")) { + readLocation(curr, rhsHeapPath, rhs); + writeLocation(curr, lhsHeapPath, lhs); + } } } @@ -254,15 +306,11 @@ public class DefinitelyWrittenCheck { // read field NTuple srcHeapPath = mapHeapPath.get(rhs); NTuple fldHeapPath = new NTuple(srcHeapPath.getList()); - fldHeapPath.add(fld); if (fld.getType().isImmutable()) { - // readLocation(f curr); + readLocation(curr, fldHeapPath, fld); } - // propagate rhs's heap path to the lhs - mapHeapPath.put(lhs, fldHeapPath); - } break; @@ -276,7 +324,10 @@ public class DefinitelyWrittenCheck { // write(field) NTuple lhsHeapPath = computePath(lhs); NTuple fldHeapPath = new NTuple(lhsHeapPath.getList()); - // writeLocation(curr, fldHeapPath, fld, getLocation(fld)); + + if (fld.getType().isImmutable()) { + writeLocation(curr, fldHeapPath, fld); + } } break; @@ -289,63 +340,186 @@ public class DefinitelyWrittenCheck { } - private Location getLocation(Descriptor d) { + private void computeReadSharedDescriptorSet() { + Set methodDescriptorsToAnalyze = new HashSet(); + methodDescriptorsToAnalyze.addAll(ssjava.getAnnotationRequireSet()); - if (d instanceof FieldDescriptor) { - return (Location) ((FieldDescriptor) d).getType().getExtension(); + for (Iterator iterator = methodDescriptorsToAnalyze.iterator(); iterator.hasNext();) { + MethodDescriptor md = (MethodDescriptor) iterator.next(); + FlatMethod fm = state.getMethodFlat(md); + computeReadSharedDescriptorSet_analyzeMethod(fm, md.equals(methodContainingSSJavaLoop)); + } + + } + + private void computeReadSharedDescriptorSet_analyzeMethod(FlatMethod fm, + boolean onlyVisitSSJavaLoop) { + + Set flatNodesToVisit = new HashSet(); + Set visited = new HashSet(); + + if (onlyVisitSSJavaLoop) { + flatNodesToVisit.add(ssjavaLoopEntrance); } else { - assert d instanceof TempDescriptor; - CompositeLocation comp = (CompositeLocation) ((TempDescriptor) d).getType().getExtension(); - return comp.get(comp.getSize() - 1); + flatNodesToVisit.add(fm); + } + + while (!flatNodesToVisit.isEmpty()) { + FlatNode fn = flatNodesToVisit.iterator().next(); + flatNodesToVisit.remove(fn); + visited.add(fn); + + computeReadSharedDescriptorSet_nodeActions(fn, onlyVisitSSJavaLoop); + + for (int i = 0; i < fn.numNext(); i++) { + FlatNode nn = fn.getNext(i); + if (!visited.contains(nn)) { + if (!onlyVisitSSJavaLoop || (onlyVisitSSJavaLoop && loopIncElements.contains(nn))) { + flatNodesToVisit.add(nn); + } + } + } + } } - private SharedLocState getSharedLocState(Hashtable, Set> curr, - NTuple hp, Location loc) { + private void computeReadSharedDescriptorSet_nodeActions(FlatNode fn, boolean isSSJavaLoop) { + + TempDescriptor lhs; + TempDescriptor rhs; + FieldDescriptor fld; + + switch (fn.kind()) { + case FKind.FlatOpNode: { + FlatOpNode fon = (FlatOpNode) fn; + lhs = fon.getDest(); + rhs = fon.getLeft(); + + if (fon.getOp().getOp() == Operation.ASSIGN) { + if (rhs.getType().isImmutable() && isSSJavaLoop && (!rhs.getSymbol().startsWith("srctmp"))) { + // in ssjavaloop, we need to take care about reading local variables! + NTuple rhsHeapPath = new NTuple(); + NTuple lhsHeapPath = new NTuple(); + rhsHeapPath.add(LOCAL); + addReadDescriptor(rhsHeapPath, rhs); + } + } - Set set = curr.get(hp); - if (set == null) { - set = new HashSet(); - curr.put(hp, set); } + break; - SharedLocState state = null; - for (Iterator iterator = set.iterator(); iterator.hasNext();) { - SharedLocState e = (SharedLocState) iterator.next(); - if (e.getLoc().equals(loc)) { - state = e; - break; + case FKind.FlatFieldNode: + case FKind.FlatElementNode: { + + FlatFieldNode ffn = (FlatFieldNode) fn; + lhs = ffn.getDst(); + rhs = ffn.getSrc(); + fld = ffn.getField(); + + // read field + NTuple srcHeapPath = mapHeapPath.get(rhs); + NTuple fldHeapPath = new NTuple(srcHeapPath.getList()); + // fldHeapPath.add(fld); + + if (fld.getType().isImmutable()) { + addReadDescriptor(fldHeapPath, fld); } + + // propagate rhs's heap path to the lhs + mapHeapPath.put(lhs, fldHeapPath); + } + break; + + case FKind.FlatSetFieldNode: + case FKind.FlatSetElementNode: { + + FlatSetFieldNode fsfn = (FlatSetFieldNode) fn; + lhs = fsfn.getDst(); + fld = fsfn.getField(); + + // write(field) + NTuple lhsHeapPath = computePath(lhs); + NTuple fldHeapPath = new NTuple(lhsHeapPath.getList()); + // writeLocation(curr, fldHeapPath, fld, getLocation(fld)); - if (state == null) { - state = new SharedLocState(loc); - set.add(state); } + break; - return state; + } } - private void writeLocation(Hashtable, Set> curr, - NTuple hp, Descriptor d) { + private void addReadDescriptor(NTuple hp, Descriptor d) { Location loc = getLocation(d); - if (ssjava.isSharedLocation(loc)) { - SharedLocState state = getSharedLocState(curr, hp, loc); - state.addVar(d); + + if (loc != null && ssjava.isSharedLocation(loc)) { + + Pair key = new Pair(hp, loc); + Set set = mapSharedLocation2DescriptorSet.get(key); + if (set == null) { + set = new HashSet(); + mapSharedLocation2DescriptorSet.put(key, set); + } + set.add(d); } + } - private void readLocation(Hashtable, Set> curr, + private Location getLocation(Descriptor d) { + + if (d instanceof FieldDescriptor) { + return (Location) ((FieldDescriptor) d).getType().getExtension(); + } else { + assert d instanceof TempDescriptor; + CompositeLocation comp = (CompositeLocation) ((TempDescriptor) d).getType().getExtension(); + if (comp == null) { + return null; + } else { + return comp.get(comp.getSize() - 1); + } + } + + } + + private void writeLocation(Hashtable, SharedLocState> curr, NTuple hp, Descriptor d) { - // remove reading var x from written set + Location loc = getLocation(d); + if (loc != null && ssjava.isSharedLocation(loc)) { + SharedLocState state = getState(curr, hp); + state.addVar(loc, d); + // if the set v contains all of variables belonging to the shared + // location, set flag to true + + Set sharedVarSet = + mapSharedLocation2DescriptorSet.get(new Pair, Location>(hp, loc)); + + if (state.getVarSet(loc).containsAll(sharedVarSet)) { + state.updateFlag(loc, true); + } + } + } + + private void readLocation(Hashtable, SharedLocState> curr, + NTuple hp, Descriptor d) { + // remove reading var x from written set Location loc = getLocation(d); - if (ssjava.isSharedLocation(loc)) { - SharedLocState state = getSharedLocState(curr, hp, loc); - state.removeVar(d); + if (loc != null && ssjava.isSharedLocation(loc)) { + SharedLocState state = getState(curr, hp); + state.removeVar(loc, d); + } + } + + private SharedLocState getState(Hashtable, SharedLocState> curr, + NTuple hp) { + SharedLocState state = curr.get(hp); + if (state == null) { + state = new SharedLocState(); + curr.put(hp, state); } + return state; } private void writtenAnalyis() { @@ -953,8 +1127,38 @@ public class DefinitelyWrittenCheck { } - private void mergeSharedAnaylsis(Hashtable, Set> curr, - Hashtable, Set> in) { + private void mergeSharedAnaylsis(Hashtable, SharedLocState> curr, + Hashtable, SharedLocState> in) { + + Set> keySet = in.keySet(); + for (Iterator iterator = keySet.iterator(); iterator.hasNext();) { + NTuple hpKey = (NTuple) iterator.next(); + SharedLocState inState = in.get(hpKey); + + SharedLocState currState = curr.get(hpKey); + if (currState == null) { + currState = new SharedLocState(); + curr.put(hpKey, currState); + } + currState.merge(inState); + + Set locSet = inState.getMap().keySet(); + for (Iterator iterator2 = locSet.iterator(); iterator2.hasNext();) { + Location loc = (Location) iterator2.next(); + Pair, Boolean> pair = inState.getMap().get(loc); + boolean inFlag = pair.getSecond().booleanValue(); + + Pair, Location> flagKey = + new Pair, Location>(hpKey, loc); + Boolean current = mapHeapPathLocation2Flag.get(flagKey); + if (current == null) { + current = new Boolean(true); + } + boolean newInFlag = current.booleanValue() & inFlag; + mapHeapPathLocation2Flag.put(flagKey, Boolean.valueOf(newInFlag)); + } + + } } diff --git a/Robust/src/Analysis/SSJava/SharedLocState.java b/Robust/src/Analysis/SSJava/SharedLocState.java index d55bd573..f49a33f8 100644 --- a/Robust/src/Analysis/SSJava/SharedLocState.java +++ b/Robust/src/Analysis/SSJava/SharedLocState.java @@ -1,56 +1,104 @@ package Analysis.SSJava; import java.util.HashSet; +import java.util.Hashtable; +import java.util.Iterator; import java.util.Set; import IR.Descriptor; +import Util.Pair; public class SharedLocState { - Location loc; - Set varSet; - boolean flag; + // maps location to its current writing var set and flag + Hashtable, Boolean>> mapLocation2Status; - public SharedLocState(Location loc) { - this.loc = loc; - this.varSet = new HashSet(); - this.flag = false; + public SharedLocState() { + mapLocation2Status = new Hashtable, Boolean>>(); } - public void addVar(Descriptor d) { - varSet.add(d); + private Pair, Boolean> getStatus(Location loc) { + Pair, Boolean> pair = mapLocation2Status.get(loc); + if (pair == null) { + pair = new Pair, Boolean>(new HashSet(), new Boolean(false)); + mapLocation2Status.put(loc, pair); + } + return pair; } - public void removeVar(Descriptor d) { - varSet.remove(d); + public void addVar(Location loc, Descriptor d) { + getStatus(loc).getFirst().add(d); } - public Location getLoc() { - return loc; + public void removeVar(Location loc, Descriptor d) { + getStatus(loc).getFirst().remove(d); } public String toString() { - return "<" + loc + "," + varSet + "," + flag + ">"; + return mapLocation2Status.toString(); } - public void setLoc(Location loc) { - this.loc = loc; + public Set getLocationSet() { + return mapLocation2Status.keySet(); } - public Set getVarSet() { - return varSet; + public void merge(SharedLocState inState) { + Set keySet = inState.getLocationSet(); + for (Iterator iterator = keySet.iterator(); iterator.hasNext();) { + Location inLoc = (Location) iterator.next(); + + Pair, Boolean> inPair = inState.getStatus(inLoc); + Pair, Boolean> currPair = mapLocation2Status.get(inLoc); + + if (currPair == null) { + currPair = + new Pair, Boolean>(new HashSet(), new Boolean(false)); + mapLocation2Status.put(inLoc, currPair); + } + mergeSet(currPair.getFirst(), inPair.getFirst()); + } } - public void setVarSet(Set varSet) { - this.varSet = varSet; + public void mergeSet(Set curr, Set in) { + if (curr.isEmpty()) { + // Varset has a special initial value which covers all possible + // elements + // For the first time of intersection, we can take all previous set + curr.addAll(in); + } else { + curr.retainAll(in); + } } - public boolean isFlag() { - return flag; + public int hashCode() { + return mapLocation2Status.hashCode(); } - public void setFlag(boolean flag) { - this.flag = flag; + public Hashtable, Boolean>> getMap() { + return mapLocation2Status; } + public boolean equals(Object o) { + if (!(o instanceof SharedLocState)) { + return false; + } + SharedLocState in = (SharedLocState) o; + return in.getMap().equals(mapLocation2Status); + } + + public Set getVarSet(Location loc) { + return mapLocation2Status.get(loc).getFirst(); + } + + public void updateFlag(Location loc, boolean b) { + Pair, Boolean> pair = mapLocation2Status.get(loc); + if (pair.getSecond() != b) { + mapLocation2Status.put(loc, + new Pair, Boolean>(pair.getFirst(), Boolean.valueOf(b))); + } + } + + public boolean getFlag(Location loc) { + return mapLocation2Status.get(loc).getSecond().booleanValue(); + } }