private Hashtable < FlatNode, ParentChildConflictsMap > conflictsResults;
private ParentChildConflictsMap currentConflictsMap;
private Hashtable < ReferenceEdge, StallSite > stallEdgeMapping;
+ private Hashtable< FlatMethod, MethodSummary > methodSummaryResults;
+
+ // temporal data structures to track analysis progress.
+ private MethodSummary currentMethodSummary;
+ private HashSet<PreEffectsKey> preeffectsSet;
public static int maxSESEage = -1;
conflictsResults = new Hashtable < FlatNode, ParentChildConflictsMap >();
stallEdgeMapping = new Hashtable < ReferenceEdge, StallSite >();
+ methodSummaryResults=new Hashtable<FlatMethod, MethodSummary>();
FlatMethod fmMain = state.getMethodFlat( typeUtil.getMain() );
HashSet<MethodContext> mcSet = ownAnalysis
.getAllMethodContextSetByDescriptor(md);
Iterator<MethodContext> mcIter = mcSet.iterator();
-
+
+ currentMethodSummary=new MethodSummary();
+ preeffectsSet=new HashSet<PreEffectsKey>();
+
while (mcIter.hasNext()) {
MethodContext mc = mcIter.next();
Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
flatNodesToVisit.add(fm);
+ currentConflictsMap=null;
while (!flatNodesToVisit.isEmpty()) {
FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
flatNodesToVisit.remove(fn);
- conflicts_nodeAction(mc, fn, callGraph);
+ conflicts_nodeAction(mc, fn, callGraph, preeffectsSet);
flatNodesToVisit.remove(fn);
visited.add(fn);
}
}
}
+ methodSummaryResults.put(fm, currentMethodSummary);
}
}
private void conflicts_nodeAction(MethodContext mc, FlatNode fn,
- CallGraph callGraph) {
+ CallGraph callGraph, HashSet<PreEffectsKey> preeffectsSet) {
OwnershipGraph og = ownAnalysis.getOwnvershipGraphByMethodContext(mc);
switch (fn.kind()) {
+ case FKind.FlatSESEEnterNode: {
+
+ FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
+ if (!fsen.getIsCallerSESEplaceholder()) {
+ currentMethodSummary.increaseChildSESECount();
+ }
+
+ if (currentMethodSummary.getChildSESECount() == 1) {
+ // need to store pre-effects
+ currentMethodSummary.getEffectsSet().addAll(preeffectsSet);
+
+ for (Iterator iterator = currentMethodSummary.getEffectsSet()
+ .iterator(); iterator.hasNext();) {
+ PreEffectsKey preEffectsKey = (PreEffectsKey) iterator
+ .next();
+ }
+
+ preeffectsSet.clear();
+ }
+
+ }
+ break;
+
case FKind.FlatSESEExitNode: {
- // all object variables are inaccessible
+ // all object variables are inaccessible.
currentConflictsMap = new ParentChildConflictsMap();
}
break;
case FKind.FlatFieldNode: {
- if (currentConflictsMap != null) {
+ FlatFieldNode ffn = (FlatFieldNode) fn;
+ TempDescriptor dst = ffn.getDst();
+ TempDescriptor src = ffn.getSrc();
+ FieldDescriptor field = ffn.getField();
- FlatFieldNode ffn = (FlatFieldNode) fn;
- TempDescriptor dst = ffn.getDst();
- TempDescriptor src = ffn.getSrc();
- FieldDescriptor field = ffn.getField();
+ if (currentConflictsMap != null) {
HashSet<TempDescriptor> srcTempSet = getTempDescSetReferenceToSameHRN(
og, src);
.next();
currentConflictsMap.addAccessibleVar(possibleDst);
}
+ }
+ if (currentMethodSummary.getChildSESECount() == 0) {
+ // analyze preeffects
+ preEffectAnalysis(og, src, field, PreEffectsKey.READ_EFFECT);
}
}
case FKind.FlatSetFieldNode: {
- if (currentConflictsMap != null) {
+ FlatSetFieldNode fsen = (FlatSetFieldNode) fn;
+ TempDescriptor dst = fsen.getDst();
+ FieldDescriptor field = fsen.getField();
+ TempDescriptor src = fsen.getSrc();
- FlatSetFieldNode fsen = (FlatSetFieldNode) fn;
- TempDescriptor dst = fsen.getDst();
- FieldDescriptor field = fsen.getField();
- TempDescriptor src = fsen.getSrc();
+ if (currentConflictsMap != null) {
HashSet<TempDescriptor> srcTempSet = getTempDescSetReferenceToSameHRN(
og, src);
}
}
}
+
+ if (currentMethodSummary.getChildSESECount() == 0) {
+ // analyze preeffects
+ preEffectAnalysis(og, dst, field, PreEffectsKey.WRITE_EFFECT);
+ }
+
}
break;
currentConflictsMap.addAccessibleVar(possibleDst);
} else {
currentConflictsMap.addInaccessibleVar(possibleDst);
+
}
}
FlatCall fc = (FlatCall) fn;
- // look at all possible context, and then take all of them into one
- // context
+ FlatMethod calleeFM = state.getMethodFlat(fc.getMethod());
+
+ // retrieve callee's method summary
+ MethodSummary calleeMethodSummary = methodSummaryResults
+ .get(calleeFM);
+
+ if (calleeMethodSummary != null
+ && calleeMethodSummary.getChildSESECount() > 0) {
+
+ // when parameter variable is accessible,
+ // use callee's preeffects to figure out about how it affects
+ // caller's stall site
+
+ for (int i = 0; i < fc.numArgs(); i++) {
+ TempDescriptor paramTemp = fc.getArg(i);
+
+ if (currentConflictsMap != null) {
+ if (currentConflictsMap.isAccessible(paramTemp)
+ && currentConflictsMap.hasStallSite(paramTemp)) {
+ // preeffect contribute its effect to caller's stall
+ // site
+
+ int offset = 0;
+ if (!fc.getMethod().isStatic()) {
+ offset = 1;
+ }
+
+ HashSet<PreEffectsKey> preeffectSet = calleeMethodSummary
+ .getEffectsSetByParamIdx(i + offset);
+
+ for (Iterator iterator = preeffectSet.iterator(); iterator
+ .hasNext();) {
+ PreEffectsKey preEffectsKey = (PreEffectsKey) iterator
+ .next();
+ currentConflictsMap.contributeEffect(paramTemp,
+ preEffectsKey.getType(), preEffectsKey
+ .getField(), preEffectsKey
+ .getEffectType());
+ }
+ }
+ }
+ // in other cases, child SESE has not been discovered,
+ // assumes that all variables are accessible
+
+ }
+
+ // If callee has at least one child sese, all parent object
+ // is going to be inaccessible.
+ currentConflictsMap = new ParentChildConflictsMap();
+
+ TempDescriptor returnTemp = fc.getReturnTemp();
+
+ if (calleeMethodSummary.getReturnValueAccessibility().equals(
+ MethodSummary.ACCESSIBLE)) {
+ // when return value is accessible, associate with its
+ // stall site
+ currentConflictsMap.addAccessibleVar(returnTemp);
+ currentConflictsMap.addStallSite(returnTemp,
+ calleeMethodSummary.getReturnStallSite());
+ } else if (calleeMethodSummary.getReturnValueAccessibility()
+ .equals(MethodSummary.INACCESSIBLE)) {
+ // when return value is inaccessible
+ currentConflictsMap.addInaccessibleVar(returnTemp);
+ }
+ }
+
+ // TODO: need to handle edge mappings from callee
+
+ }
+ break;
+
+ case FKind.FlatReturnNode: {
+
+ FlatReturnNode frn = (FlatReturnNode) fn;
+ TempDescriptor returnTD = frn.getReturnTemp();
+
+ if (returnTD != null) {
+ if (currentConflictsMap == null) {
+ // in this case, all variables is accessible. There are no
+ // child SESEs.
+ } else {
+ if (currentConflictsMap.isAccessible(returnTD)) {
+ currentMethodSummary
+ .setReturnValueAccessibility(MethodSummary.ACCESSIBLE);
+ StallSite returnStallSite = currentConflictsMap
+ .getStallMap().get(returnTD);
+ currentMethodSummary
+ .setReturnStallSite(returnStallSite);
+ } else {
+ currentMethodSummary
+ .setReturnValueAccessibility(MethodSummary.INACCESSIBLE);
+ }
+ }
+ }
+ }
+ break;
+
+ case FKind.FlatExit: {
+
+ // store method summary when it has at least one child SESE
+ if (currentMethodSummary.getChildSESECount() > 0) {
+ FlatMethod fm = state.getMethodFlat(mc.getDescriptor()); // current
+ // flat
+ // method
+ methodSummaryResults.put(fm, currentMethodSummary);
+ }
}
break;
}
+ private void preEffectAnalysis(OwnershipGraph og, TempDescriptor td,
+ FieldDescriptor field, Integer effectType) {
+
+ // analyze preeffects
+ HashSet<HeapRegionNode> hrnSet = getReferenceHeapIDSet(og, td);
+ for (Iterator iterator = hrnSet.iterator(); iterator.hasNext();) {
+ HeapRegionNode hrn = (HeapRegionNode) iterator.next();
+ if (hrn.isParameter()) {
+ // effects on param heap region
+
+ Set<Integer> paramSet = og.idPrimary2paramIndexSet.get(hrn
+ .getID());
+
+ if (paramSet != null) {
+ Iterator<Integer> paramIter = paramSet.iterator();
+ while (paramIter.hasNext()) {
+ Integer paramID = paramIter.next();
+ PreEffectsKey effectKey = new PreEffectsKey(paramID,
+ field.toString(), field.getType()
+ .getSafeSymbol(), effectType);
+ preeffectsSet.add(effectKey);
+ }
+ }
+
+ // check weather this heap region is parameter
+ // reachable...
+
+ paramSet = og.idSecondary2paramIndexSet.get(hrn.getID());
+ if (paramSet != null) {
+ Iterator<Integer> paramIter = paramSet.iterator();
+
+ while (paramIter.hasNext()) {
+ Integer paramID = paramIter.next();
+ PreEffectsKey effectKey = new PreEffectsKey(paramID,
+ field.toString(), field.getType()
+ .getSafeSymbol(), effectType);
+ preeffectsSet.add(effectKey);
+ }
+ }
+
+ }
+ }
+ }
+
+ private MethodSummary analysisMethodCall(FlatMethod fm, OwnershipGraph calleeOG){
+
+ MethodSummary methodSummary=new MethodSummary();
+
+ Set<FlatNode> visited = new HashSet<FlatNode>();
+ Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
+ flatNodesToVisit.add(fm);
+
+ while (!flatNodesToVisit.isEmpty()) {
+ FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
+ flatNodesToVisit.remove(fn);
+
+// conflicts_nodeAction(mc, fn, callGraph);
+
+ flatNodesToVisit.remove(fn);
+ visited.add(fn);
+
+ for (int i = 0; i < fn.numNext(); i++) {
+ FlatNode nn = fn.getNext(i);
+ if (!visited.contains(nn)) {
+ flatNodesToVisit.add(nn);
+ }
+ }
+ }
+
+
+
+ return methodSummary;
+
+ }
+
private void codePlansForward( FlatMethod fm ) {
--- /dev/null
+package Analysis.MLP;
+
+import java.util.HashSet;
+import java.util.Iterator;
+
+import IR.TypeDescriptor;
+
+public class MethodSummary {
+
+ public static final Integer VOID=new Integer(0);
+ public static final Integer ACCESSIBLE = new Integer(1);
+ public static final Integer INACCESSIBLE=new Integer(2);
+
+ private int childSESECount;
+ private HashSet<PreEffectsKey> effectsSet;
+ private Integer accessibility;
+ private StallSite returnStallSite;
+
+ public MethodSummary() {
+ effectsSet = new HashSet<PreEffectsKey>();
+ accessibility = MethodSummary.VOID;
+ childSESECount = 0;
+ returnStallSite=null;
+ }
+
+ public void setReturnStallSite(StallSite ss){
+ returnStallSite=ss;
+ }
+
+ public StallSite getReturnStallSite(){
+ return returnStallSite;
+ }
+
+ public void increaseChildSESECount() {
+ childSESECount++;
+ }
+
+ public int getChildSESECount() {
+ return childSESECount;
+ }
+
+ public Integer getReturnValueAccessibility() {
+ return accessibility;
+ }
+
+ public void setReturnValueAccessibility(Integer accessibility) {
+ this.accessibility = accessibility;
+ }
+
+ public HashSet<PreEffectsKey> getEffectsSet() {
+ return effectsSet;
+ }
+
+ @Override
+ public String toString() {
+ return "MethodSummary [accessibility=" + accessibility
+ + ", childSESECount=" + childSESECount + ", effectsSet="
+ + effectsSet + "]";
+ }
+
+ public HashSet<PreEffectsKey> getEffectsSetByParamIdx(int paramIdx){
+
+ HashSet<PreEffectsKey> returnSet=new HashSet<PreEffectsKey>();
+
+ for (Iterator iterator = effectsSet.iterator(); iterator.hasNext();) {
+ PreEffectsKey preEffectsKey = (PreEffectsKey) iterator.next();
+ if(preEffectsKey.getParamIndex().equals(new Integer(paramIdx))){
+ returnSet.add(preEffectsKey);
+ }
+ }
+
+ return returnSet;
+ }
+
+}
+
+class PreEffectsKey {
+
+ public static final Integer READ_EFFECT = new Integer(1);
+ public static final Integer WRITE_EFFECT = new Integer(2);
+
+ private String type;
+ private String field;
+ private Integer effectType;
+ private Integer paramIndex;
+
+ public PreEffectsKey(Integer paramIndex, String field, String type,
+ Integer effectType) {
+ this.paramIndex = paramIndex;
+ this.field = field;
+ this.type = type;
+ this.effectType = effectType;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public String getField() {
+ return field;
+ }
+
+ public Integer getEffectType() {
+ return effectType;
+ }
+
+ public Integer getParamIndex() {
+ return paramIndex;
+ }
+
+ public String toString() {
+ return "PreEffectsKey [effectType=" + effectType + ", field=" + field
+ + ", paramIndex=" + paramIndex + ", type=" + type + "]";
+ }
+
+ public boolean equals(Object o) {
+
+ if (o == null) {
+ return false;
+ }
+
+ if (!(o instanceof PreEffectsKey)) {
+ return false;
+ }
+
+ PreEffectsKey in = (PreEffectsKey) o;
+
+ this.paramIndex = paramIndex;
+ this.field = field;
+ this.type = type;
+ this.effectType = effectType;
+
+ if (paramIndex.equals(in.getParamIndex())
+ && field.equals(in.getField()) && type.equals(in.getType())
+ && effectType.equals(in.getEffectType())) {
+ return true;
+ } else {
+ return false;
+ }
+
+ }
+
+}