From: jjenista Date: Tue, 11 Nov 2008 04:44:34 +0000 (+0000) Subject: added concept of method context X-Git-Tag: buildscript^7~42 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=364cc0bf5d273612803787228601fc8b584f6e1b;p=IRC.git added concept of method context --- diff --git a/Robust/src/Analysis/OwnershipAnalysis/OwnershipAnalysis.java b/Robust/src/Analysis/OwnershipAnalysis/OwnershipAnalysis.java index 7de280a5..2b960642 100644 --- a/Robust/src/Analysis/OwnershipAnalysis/OwnershipAnalysis.java +++ b/Robust/src/Analysis/OwnershipAnalysis/OwnershipAnalysis.java @@ -27,11 +27,12 @@ public class OwnershipAnalysis { return getAllocationSiteFromFlatNewPRIVATE(fn); } + public boolean createsPotentialAliases(Descriptor taskOrMethod, int paramIndex1, int paramIndex2) { - OwnershipGraph og = mapDescriptorToCompleteOwnershipGraph.get(taskOrMethod); + OwnershipGraph og = getGraphOfAllContextsFromDescriptor(taskOrMethod); assert(og != null); return og.hasPotentialAlias(paramIndex1, paramIndex2); } @@ -40,7 +41,7 @@ public class OwnershipAnalysis { int paramIndex, AllocationSite alloc) { - OwnershipGraph og = mapDescriptorToCompleteOwnershipGraph.get(taskOrMethod); + OwnershipGraph og = getGraphOfAllContextsFromDescriptor(taskOrMethod); assert(og != null); return og.hasPotentialAlias(paramIndex, alloc); } @@ -49,7 +50,7 @@ public class OwnershipAnalysis { AllocationSite alloc, int paramIndex) { - OwnershipGraph og = mapDescriptorToCompleteOwnershipGraph.get(taskOrMethod); + OwnershipGraph og = getGraphOfAllContextsFromDescriptor(taskOrMethod); assert(og != null); return og.hasPotentialAlias(paramIndex, alloc); } @@ -58,11 +59,33 @@ public class OwnershipAnalysis { AllocationSite alloc1, AllocationSite alloc2) { - OwnershipGraph og = mapDescriptorToCompleteOwnershipGraph.get(taskOrMethod); + OwnershipGraph og = getGraphOfAllContextsFromDescriptor(taskOrMethod); assert(og != null); return og.hasPotentialAlias(alloc1, alloc2); } + + protected OwnershipGraph getGraphOfAllContextsFromDescriptor(Descriptor d) { + assert d != null; + + OwnershipGraph og = new OwnershipGraph( allocationDepth, typeUtil ); + + assert mapDescriptorToAllMethodContexts.containsKey( d ); + HashSet contexts = mapDescriptorToAllMethodContexts.get( d ); + Iterator mcItr = contexts.iterator(); + while( mcItr.hasNext() ) { + MethodContext mc = mcItr.next(); + + OwnershipGraph ogContext = mapMethodContextToCompleteOwnershipGraph.get(mc); + assert ogContext != null; + + og.merge( ogContext ); + } + + return og; + } + + // use the methods given above to check every possible alias // between task parameters and flagged allocation sites reachable // from the task @@ -174,11 +197,12 @@ public class OwnershipAnalysis { // processing all methods in the program, and by methods // TaskDescriptor and MethodDescriptor are combined // together, with a common parent class Descriptor - private Hashtable mapFlatMethodToInitialParamAllocGraph; - private Hashtable mapDescriptorToCompleteOwnershipGraph; - private Hashtable mapFlatNewToAllocationSite; - private Hashtable > mapDescriptorToAllocationSiteSet; - private Hashtable mapDescriptorToNumUpdates; + private Hashtable mapMethodContextToInitialParamAllocGraph; + private Hashtable mapMethodContextToCompleteOwnershipGraph; + private Hashtable mapFlatNewToAllocationSite; + private Hashtable > mapDescriptorToAllocationSiteSet; + private Hashtable mapMethodContextToNumUpdates; + private Hashtable > mapDescriptorToAllMethodContexts; // Use these data structures to track progress of one pass of // processing the FlatNodes of a particular method @@ -195,7 +219,7 @@ public class OwnershipAnalysis { // reduced by visiting a descriptor during analysis. When dependents // must be scheduled, only those contained in descriptorsToAnalyze // should be re-added to this set - private HashSet descriptorsToVisit; + private HashSet methodContextsToVisit; // a special field descriptor for all array elements private static FieldDescriptor fdElement = new FieldDescriptor(new Modifiers(Modifiers.PUBLIC), @@ -203,6 +227,12 @@ public class OwnershipAnalysis { "elements", null, false); + + // a special temp descriptor for setting more than one parameter label + // to the all-aliased-parameters heap region node + protected static TempDescriptor tdAliasedParams = new TempDescriptor("_AllAliasedParams___"); + + // for controlling DOT file output private boolean writeDOTs; private boolean writeAllDOTs; @@ -228,11 +258,11 @@ public class OwnershipAnalysis { descriptorsToAnalyze = new HashSet(); - mapFlatMethodToInitialParamAllocGraph = - new Hashtable(); + mapMethodContextToInitialParamAllocGraph = + new Hashtable(); - mapDescriptorToCompleteOwnershipGraph = - new Hashtable(); + mapMethodContextToCompleteOwnershipGraph = + new Hashtable(); mapFlatNewToAllocationSite = new Hashtable(); @@ -240,8 +270,12 @@ public class OwnershipAnalysis { mapDescriptorToAllocationSiteSet = new Hashtable >(); + mapDescriptorToAllMethodContexts = + new Hashtable >(); + + if( writeAllDOTs ) { - mapDescriptorToNumUpdates = new Hashtable(); + mapMethodContextToNumUpdates = new Hashtable(); } // initialize methods to visit as the set of all tasks in the @@ -269,10 +303,16 @@ public class OwnershipAnalysis { fm = state.getMethodFlat( (TaskDescriptor) d); } - System.out.println("Previsiting " + d); + MethodContext mc = new MethodContext( d ); + assert !mapDescriptorToAllMethodContexts.containsKey( d ); + HashSet s = new HashSet(); + s.add( mc ); + mapDescriptorToAllMethodContexts.put( d, s ); + + System.out.println("Previsiting " + mc); - og = analyzeFlatNode(d, fm, null, og); - setGraphForDescriptor(d, og); + og = analyzeFlatNode(mc, fm, null, og); + setGraphForMethodContext(mc, og); } System.out.println(""); @@ -320,11 +360,22 @@ public class OwnershipAnalysis { // they call are updated private void analyzeMethods() throws java.io.IOException { - descriptorsToVisit = (HashSet)descriptorsToAnalyze.clone(); + methodContextsToVisit = new HashSet(); + Iterator itrd2a = descriptorsToAnalyze.iterator(); + while( itrd2a.hasNext() ) { + HashSet mcs = mapDescriptorToAllMethodContexts.get( itrd2a.next() ); + assert mcs != null; + + Iterator itrmc = mcs.iterator(); + while( itrmc.hasNext() ) { + methodContextsToVisit.add( itrmc.next() ); + } + } + + while( !methodContextsToVisit.isEmpty() ) { + MethodContext mc = methodContextsToVisit.iterator().next(); + methodContextsToVisit.remove(mc); - while( !descriptorsToVisit.isEmpty() ) { - Descriptor d = (Descriptor) descriptorsToVisit.iterator().next(); - descriptorsToVisit.remove(d); // because the task or method descriptor just extracted // was in the "to visit" set it either hasn't been analyzed @@ -334,8 +385,9 @@ public class OwnershipAnalysis { // If there is a change detected, add any methods/tasks // that depend on this one to the "to visit" set. - System.out.println("Analyzing " + d); + System.out.println("Analyzing " + mc); + Descriptor d = mc.getDescriptor(); FlatMethod fm; if( d instanceof MethodDescriptor ) { fm = state.getMethodFlat( (MethodDescriptor) d); @@ -344,10 +396,10 @@ public class OwnershipAnalysis { fm = state.getMethodFlat( (TaskDescriptor) d); } - OwnershipGraph og = analyzeFlatMethod(d, fm); - OwnershipGraph ogPrev = mapDescriptorToCompleteOwnershipGraph.get(d); + OwnershipGraph og = analyzeFlatMethod(mc, fm); + OwnershipGraph ogPrev = mapMethodContextToCompleteOwnershipGraph.get(mc); if( !og.equals(ogPrev) ) { - setGraphForDescriptor(d, og); + setGraphForMethodContext(mc, og); // only methods have dependents, tasks cannot // be invoked by any user program calls @@ -359,7 +411,14 @@ public class OwnershipAnalysis { while( depItr.hasNext() ) { Descriptor dependent = (Descriptor) depItr.next(); if( descriptorsToAnalyze.contains(dependent) ) { - descriptorsToVisit.add(dependent); + + HashSet mcs = mapDescriptorToAllMethodContexts.get( dependent ); + assert mcs != null; + + Iterator itrmc = mcs.iterator(); + while( itrmc.hasNext() ) { + methodContextsToVisit.add( itrmc.next() ); + } } } } @@ -373,12 +432,11 @@ public class OwnershipAnalysis { // keep passing the Descriptor of the method along for debugging // and dot file writing private OwnershipGraph - analyzeFlatMethod(Descriptor mDesc, + analyzeFlatMethod(MethodContext mc, FlatMethod flatm) throws java.io.IOException { // initialize flat nodes to visit as the flat method - // because all other nodes in this flat method are - // decendents of the flat method itself + // because it is the entry point flatNodesToVisit = new HashSet(); flatNodesToVisit.add(flatm); @@ -415,7 +473,7 @@ public class OwnershipAnalysis { // apply the analysis of the flat node to the // ownership graph made from the merge of the // parent graphs - og = analyzeFlatNode(mDesc, + og = analyzeFlatNode(mc, fn, returnNodesToCombineForCompleteOwnershipGraph, og); @@ -457,7 +515,7 @@ public class OwnershipAnalysis { private OwnershipGraph - analyzeFlatNode(Descriptor methodDesc, + analyzeFlatNode(MethodContext mc, FlatNode fn, HashSet setRetNodes, OwnershipGraph og) throws java.io.IOException { @@ -481,21 +539,41 @@ public class OwnershipAnalysis { // parameter IDs are consistent between analysis // iterations, so if this step has been done already // just merge in the cached version - OwnershipGraph ogInitParamAlloc = mapFlatMethodToInitialParamAllocGraph.get(fm); + OwnershipGraph ogInitParamAlloc = mapMethodContextToInitialParamAllocGraph.get(mc); if( ogInitParamAlloc == null ) { - // analyze this node one time globally - for( int i = 0; i < fm.numParameters(); ++i ) { - TempDescriptor tdParam = fm.getParameter(i); - og.assignTempEqualToParamAlloc(tdParam, - methodDesc instanceof TaskDescriptor, - new Integer(i) ); + // if the method context has aliased parameters, make sure + // there is a blob region for all those param labels to + // reference + Set aliasedParamIndices = mc.getAliasedParamIndices(); + if( !aliasedParamIndices.isEmpty() ) { + og.makeAliasedParamHeapRegionNode( tdAliasedParams ); } - // then remember it + // set up each parameter + for( int i = 0; i < fm.numParameters(); ++i ) { + TempDescriptor tdParam = fm.getParameter( i ); + Integer paramIndex = new Integer( i ); + + if( aliasedParamIndices.contains( paramIndex ) ) { + // just point this one to the alias blob + og.assignTempEqualToAliasedParam( tdParam, + tdAliasedParams, + paramIndex ); + } else { + // this parameter is not aliased to others, give it + // a fresh parameter heap region + + og.assignTempEqualToParamAlloc(tdParam, + mc.getDescriptor() instanceof TaskDescriptor, + paramIndex ); + } + } + + // cache the graph OwnershipGraph ogResult = new OwnershipGraph(allocationDepth, typeUtil); ogResult.merge(og); - mapFlatMethodToInitialParamAllocGraph.put(fm, ogResult); + mapMethodContextToInitialParamAllocGraph.put(mc, ogResult); } else { // or just leverage the cached copy @@ -567,9 +645,22 @@ public class OwnershipAnalysis { if( md.isStatic() ) { // a static method is simply always the same, makes life easy - OwnershipGraph onlyPossibleCallee = mapDescriptorToCompleteOwnershipGraph.get(md); ogMergeOfAllPossibleCalleeResults = og; - ogMergeOfAllPossibleCalleeResults.resolveMethodCall(fc, md.isStatic(), flatm, onlyPossibleCallee); + + Set aliasedParamIndices = + ogMergeOfAllPossibleCalleeResults.calculateAliasedParamSet(fc, md.isStatic(), flatm); + MethodContext mcNew = new MethodContext( md, aliasedParamIndices ); + OwnershipGraph onlyPossibleCallee = mapMethodContextToCompleteOwnershipGraph.get( mcNew ); + + if( onlyPossibleCallee == null ) { + // if this method context has never been analyzed just schedule it for analysis + // and skip over this call site for now + methodContextsToVisit.add( mcNew ); + + } else { + ogMergeOfAllPossibleCalleeResults.resolveMethodCall(fc, md.isStatic(), flatm, onlyPossibleCallee); + } + } else { // if the method descriptor is virtual, then there could be a // set of possible methods that will actually be invoked, so @@ -580,14 +671,27 @@ public class OwnershipAnalysis { Iterator i = possibleCallees.iterator(); while( i.hasNext() ) { MethodDescriptor possibleMd = (MethodDescriptor) i.next(); + FlatMethod pflatm = state.getMethodFlat(possibleMd); // don't alter the working graph (og) until we compute a result for every // possible callee, merge them all together, then set og to that OwnershipGraph ogCopy = new OwnershipGraph(allocationDepth, typeUtil); ogCopy.merge(og); - OwnershipGraph ogPotentialCallee = mapDescriptorToCompleteOwnershipGraph.get(possibleMd); - ogCopy.resolveMethodCall(fc, md.isStatic(), flatm, ogPotentialCallee); + Set aliasedParamIndices = + ogCopy.calculateAliasedParamSet(fc, possibleMd.isStatic(), pflatm); + MethodContext mcNew = new MethodContext( possibleMd, aliasedParamIndices ); + OwnershipGraph ogPotentialCallee = mapMethodContextToCompleteOwnershipGraph.get( mcNew ); + + if( ogPotentialCallee == null ) { + // if this method context has never been analyzed just schedule it for analysis + // and skip over this call site for now + methodContextsToVisit.add( mcNew ); + + } else { + ogCopy.resolveMethodCall(fc, possibleMd.isStatic(), pflatm, ogPotentialCallee); + } + ogMergeOfAllPossibleCalleeResults.merge(ogCopy); } } @@ -652,10 +756,10 @@ public class OwnershipAnalysis { } - private void setGraphForDescriptor(Descriptor d, OwnershipGraph og) + private void setGraphForMethodContext(MethodContext mc, OwnershipGraph og) throws IOException { - mapDescriptorToCompleteOwnershipGraph.put(d, og); + mapMethodContextToCompleteOwnershipGraph.put(mc, og); // arguments to writeGraph are: // boolean writeLabels, @@ -667,15 +771,15 @@ public class OwnershipAnalysis { if( writeDOTs ) { if( !writeAllDOTs ) { - og.writeGraph(d, true, true, true, false, false); + og.writeGraph(mc, true, true, true, false, false); } else { - if( !mapDescriptorToNumUpdates.containsKey(d) ) { - mapDescriptorToNumUpdates.put(d, new Integer(0) ); + if( !mapMethodContextToNumUpdates.containsKey(mc) ) { + mapMethodContextToNumUpdates.put(mc, new Integer(0) ); } - Integer n = mapDescriptorToNumUpdates.get(d); - og.writeGraph(d, n, true, true, true, false, false); - mapDescriptorToNumUpdates.put(d, n + 1); + Integer n = mapMethodContextToNumUpdates.get(mc); + og.writeGraph(mc, n, true, true, true, false, false); + mapMethodContextToNumUpdates.put(mc, n + 1); } } } diff --git a/Robust/src/Analysis/OwnershipAnalysis/OwnershipGraph.java b/Robust/src/Analysis/OwnershipAnalysis/OwnershipGraph.java index fa51004e..851b3e70 100644 --- a/Robust/src/Analysis/OwnershipAnalysis/OwnershipGraph.java +++ b/Robust/src/Analysis/OwnershipAnalysis/OwnershipGraph.java @@ -19,10 +19,12 @@ public class OwnershipGraph { protected static TempDescriptor tdReturn = new TempDescriptor("_Return___"); + protected static final int bogusParamIndexInt = -2; + public Hashtable id2hrn; public Hashtable td2ln; - public Hashtable id2paramIndex; + public Hashtable > id2paramIndexSet; public Hashtable paramIndex2id; public Hashtable paramIndex2tdQ; @@ -35,11 +37,11 @@ public class OwnershipGraph { this.allocationDepth = allocationDepth; this.typeUtil = typeUtil; - id2hrn = new Hashtable(); - td2ln = new Hashtable(); - id2paramIndex = new Hashtable(); - paramIndex2id = new Hashtable(); - paramIndex2tdQ = new Hashtable(); + id2hrn = new Hashtable(); + td2ln = new Hashtable(); + id2paramIndexSet = new Hashtable >(); + paramIndex2id = new Hashtable(); + paramIndex2tdQ = new Hashtable(); allocationSites = new HashSet (); } @@ -567,9 +569,10 @@ public class OwnershipGraph { // parameter labels, the index of the parameter they // are for is important when resolving method calls Integer newID = hrn.getID(); - assert !id2paramIndex.containsKey(newID); - assert !id2paramIndex.containsValue(paramIndex); - id2paramIndex.put(newID, paramIndex); + assert !id2paramIndexSet.containsKey(newID); + Set s = new HashSet(); + s.add( paramIndex ); + id2paramIndexSet.put(newID, s); paramIndex2id.put(paramIndex, newID); paramIndex2tdQ.put(paramIndex, tdParamQ); @@ -597,6 +600,94 @@ public class OwnershipGraph { addReferenceEdge(hrn, hrn, edgeReflexive); } + public void makeAliasedParamHeapRegionNode(TempDescriptor td) { + assert td != null; + + LabelNode lnParam = getLabelNodeFromTemp(td); + HeapRegionNode hrn = createNewHeapRegionNode(null, + false, + false, + false, + true, + null, + null, + "aliasedParams"); + + + ReachabilitySet beta = new ReachabilitySet(new TokenTuple(hrn.getID(), + true, + TokenTuple.ARITY_ONE).makeCanonical() + ).makeCanonical(); + + // heap regions for parameters are always multiple object (see above) + // and have a reference to themselves, because we can't know the + // structure of memory that is passed into the method. We're assuming + // the worst here. + + ReferenceEdge edgeFromLabel = + new ReferenceEdge(lnParam, hrn, null, false, beta); + + ReferenceEdge edgeReflexive = + new ReferenceEdge(hrn, hrn, null, true, beta); + + addReferenceEdge(lnParam, hrn, edgeFromLabel); + addReferenceEdge(hrn, hrn, edgeReflexive); + } + + public void assignTempEqualToAliasedParam(TempDescriptor tdParam, + TempDescriptor tdAliased, + Integer paramIndex ) { + + assert tdParam != null; + assert tdAliased != null; + + LabelNode lnParam = getLabelNodeFromTemp(tdParam); + LabelNode lnAliased = getLabelNodeFromTemp(tdAliased); + + // this is a non-program-accessible label that picks up beta + // info to be used for fixing a caller of this method + TempDescriptor tdParamQ = new TempDescriptor(tdParam+"specialQ"); + LabelNode lnParamQ = getLabelNodeFromTemp(tdParamQ); + + // the lnAliased should always only reference one node, and that + // heap region node is the aliased param blob + assert lnAliased.getNumReferencees() == 1; + HeapRegionNode hrnAliasBlob = lnAliased.iteratorToReferencees().next().getDst(); + + // keep track of heap regions that were created for + // parameter labels, the index of the parameter they + // are for is important when resolving method calls + Integer idAliased = hrnAliasBlob.getID(); + Set s = id2paramIndexSet.get( idAliased ); + if( s == null ) { + s = new HashSet(); + } + s.add( paramIndex ); + id2paramIndexSet.put(idAliased, s); + paramIndex2id.put(paramIndex, idAliased); + paramIndex2tdQ.put(paramIndex, tdParamQ); + + ReachabilitySet beta = new ReachabilitySet(new TokenTuple(idAliased, + true, + TokenTuple.ARITY_ONE).makeCanonical() + ).makeCanonical(); + + // heap regions for parameters are always multiple object (see above) + // and have a reference to themselves, because we can't know the + // structure of memory that is passed into the method. We're assuming + // the worst here. + + ReferenceEdge edgeFromLabel = + new ReferenceEdge(lnParam, hrnAliasBlob, null, false, beta); + + ReferenceEdge edgeFromLabelQ = + new ReferenceEdge(lnParamQ, hrnAliasBlob, null, false, beta); + + addReferenceEdge(lnParam, hrnAliasBlob, edgeFromLabel); + addReferenceEdge(lnParamQ, hrnAliasBlob, edgeFromLabelQ); + } + + public void assignReturnEqualToTemp(TempDescriptor x) { @@ -921,6 +1012,104 @@ public class OwnershipGraph { } + public Set calculateAliasedParamSet(FlatCall fc, + boolean isStatic, + FlatMethod fm) { + + Hashtable paramIndex2ln = + new Hashtable(); + + Hashtable > paramIndex2reachableCallerNodes = + new Hashtable >(); + + for( int i = 0; i < fm.numParameters(); ++i ) { + Integer paramIndex = new Integer(i); + + // now depending on whether the callee is static or not + // we need to account for a "this" argument in order to + // find the matching argument in the caller context + TempDescriptor argTemp_i; + if( isStatic ) { + argTemp_i = fc.getArg(paramIndex); + } else { + if( paramIndex.equals(0) ) { + argTemp_i = fc.getThis(); + } else { + argTemp_i = fc.getArg(paramIndex - 1); + } + } + + // in non-static methods there is a "this" pointer + // that should be taken into account + if( isStatic ) { + assert fc.numArgs() == fm.numParameters(); + } else { + assert fc.numArgs() + 1 == fm.numParameters(); + } + + LabelNode argLabel_i = getLabelNodeFromTemp(argTemp_i); + paramIndex2ln.put(paramIndex, argLabel_i); + } + + Iterator lnArgItr = paramIndex2ln.entrySet().iterator(); + while( lnArgItr.hasNext() ) { + Map.Entry me = (Map.Entry)lnArgItr.next(); + Integer index = (Integer) me.getKey(); + LabelNode lnArg_i = (LabelNode) me.getValue(); + + // rewrite alpha for the nodes reachable from argument label i + HashSet reachableNodes = new HashSet(); + HashSet todoNodes = new HashSet(); + + // to find all reachable nodes, start with label referencees + Iterator edgeArgItr = lnArg_i.iteratorToReferencees(); + while( edgeArgItr.hasNext() ) { + ReferenceEdge edge = edgeArgItr.next(); + todoNodes.add(edge.getDst() ); + } + + // then follow links until all reachable nodes have been found + while( !todoNodes.isEmpty() ) { + HeapRegionNode hrn = todoNodes.iterator().next(); + todoNodes.remove(hrn); + reachableNodes.add(hrn); + + Iterator edgeItr = hrn.iteratorToReferencees(); + while( edgeItr.hasNext() ) { + ReferenceEdge edge = edgeItr.next(); + + if( !reachableNodes.contains(edge.getDst() ) ) { + todoNodes.add(edge.getDst() ); + } + } + } + + // save for later + paramIndex2reachableCallerNodes.put(index, reachableNodes); + } + + Set aliasedIndices = new HashSet(); + + // check for arguments that are aliased + for( int i = 0; i < fm.numParameters(); ++i ) { + for( int j = 0; j < i; ++j ) { + HashSet s1 = paramIndex2reachableCallerNodes.get( i ); + HashSet s2 = paramIndex2reachableCallerNodes.get( j ); + + Set intersection = new HashSet(s1); + intersection.retainAll(s2); + + if( !intersection.isEmpty() ) { + aliasedIndices.add( new Integer( i ) ); + aliasedIndices.add( new Integer( j ) ); + } + } + } + + return aliasedIndices; + } + + public void resolveMethodCall(FlatCall fc, boolean isStatic, FlatMethod fm, @@ -965,8 +1154,8 @@ public class OwnershipGraph { // add a bogus entry with the identity rule for easy rewrite // of new callee nodes and edges, doesn't belong to any parameter - Integer bogusID = new Integer(-1); - Integer bogusIndex = new Integer(-1); + Integer bogusID = new Integer(bogusParamIndexInt); + Integer bogusIndex = new Integer(bogusParamIndexInt); TokenTuple bogusToken = new TokenTuple(bogusID, true, TokenTuple.ARITY_ONE).makeCanonical(); TokenTuple bogusTokenPlus = new TokenTuple(bogusID, true, TokenTuple.ARITY_ONEORMORE).makeCanonical(); ReachabilitySet rsIdentity = @@ -1215,31 +1404,6 @@ public class OwnershipGraph { } - - - // check for parameters that are aliased prior to this call site - // if so, come to a grinding halt. Later, we should move this - // up before doing any alpha/beta updates - for( int i = 0; i < fm.numParameters(); ++i ) { - for( int j = 0; j < i; ++j ) { - HashSet s1 = paramIndex2reachableCallerNodes.get( i ); - HashSet s2 = paramIndex2reachableCallerNodes.get( j ); - - Set intersection = new HashSet(s1); - intersection.retainAll(s2); - - if( !intersection.isEmpty() ) { - // uh oh - System.out.println( " Arguments "+j+" and "+i+" are aliased just before" ); - System.out.println( " "+fc+" calls "+fm+"\n" ); - //System.exit( -1 ); - } - } - } - - - - // verify the existence of allocation sites and their // shadows from the callee in the context of this caller graph // then map allocated nodes of callee onto the caller shadows @@ -1810,9 +1974,9 @@ public class OwnershipGraph { HashSet possibleCallerHRNs = new HashSet(); - Integer paramIndexCallee = ogCallee.id2paramIndex.get(hrnCallee.getID() ); + Set paramIndicesCallee = ogCallee.id2paramIndexSet.get( hrnCallee.getID() ); - if( paramIndexCallee == null ) { + if( paramIndicesCallee == null ) { // this is a node allocated in the callee then and it has // exactly one shadow node in the caller to map to AllocationSite as = hrnCallee.getAllocationSite(); @@ -1842,8 +2006,12 @@ public class OwnershipGraph { } else { // this is a node that was created to represent a parameter // so it maps to a whole mess of heap regions - assert paramIndex2reachableCallerNodes.containsKey(paramIndexCallee); - possibleCallerHRNs = paramIndex2reachableCallerNodes.get(paramIndexCallee); + Iterator itrIndex = paramIndicesCallee.iterator(); + while( itrIndex.hasNext() ) { + Integer paramIndexCallee = itrIndex.next(); + assert paramIndex2reachableCallerNodes.containsKey(paramIndexCallee); + possibleCallerHRNs.addAll( paramIndex2reachableCallerNodes.get(paramIndexCallee) ); + } } return possibleCallerHRNs; @@ -2244,18 +2412,18 @@ public class OwnershipGraph { // same number of parameters, or if one or both parameter // index tables are empty protected void mergeId2paramIndex(OwnershipGraph og) { - if( id2paramIndex.size() == 0 ) { - id2paramIndex = og.id2paramIndex; - paramIndex2id = og.paramIndex2id; - paramIndex2tdQ = og.paramIndex2tdQ; + if( id2paramIndexSet.size() == 0 ) { + id2paramIndexSet = og.id2paramIndexSet; + paramIndex2id = og.paramIndex2id; + paramIndex2tdQ = og.paramIndex2tdQ; return; } - if( og.id2paramIndex.size() == 0 ) { + if( og.id2paramIndexSet.size() == 0 ) { return; } - assert id2paramIndex.size() == og.id2paramIndex.size(); + assert id2paramIndexSet.size() == og.id2paramIndexSet.size(); } protected void mergeAllocationSites(OwnershipGraph og) { @@ -2490,7 +2658,7 @@ public class OwnershipGraph { protected boolean areId2paramIndexEqual(OwnershipGraph og) { - return id2paramIndex.size() == og.id2paramIndex.size(); + return id2paramIndexSet.size() == og.id2paramIndexSet.size(); } public boolean hasPotentialAlias(Integer paramIndex1, Integer paramIndex2) { @@ -2879,7 +3047,7 @@ public class OwnershipGraph { // for writing ownership graphs to dot files - public void writeGraph(Descriptor methodDesc, + public void writeGraph(MethodContext mc, FlatNode fn, boolean writeLabels, boolean labelSelect, @@ -2888,8 +3056,7 @@ public class OwnershipGraph { boolean writeParamMappings ) throws java.io.IOException { writeGraph( - methodDesc.getSymbol() + - methodDesc.getNum() + + mc.toString() + fn.toString(), writeLabels, labelSelect, @@ -2899,7 +3066,7 @@ public class OwnershipGraph { ); } - public void writeGraph(Descriptor methodDesc, + public void writeGraph(MethodContext mc, boolean writeLabels, boolean labelSelect, boolean pruneGarbage, @@ -2907,7 +3074,7 @@ public class OwnershipGraph { boolean writeParamMappings ) throws java.io.IOException { - writeGraph(methodDesc+"COMPLETE", + writeGraph(mc+"COMPLETE", writeLabels, labelSelect, pruneGarbage, @@ -2916,7 +3083,7 @@ public class OwnershipGraph { ); } - public void writeGraph(Descriptor methodDesc, + public void writeGraph(MethodContext mc, Integer numUpdate, boolean writeLabels, boolean labelSelect, @@ -2925,7 +3092,7 @@ public class OwnershipGraph { boolean writeParamMappings ) throws java.io.IOException { - writeGraph(methodDesc+"COMPLETE"+String.format("%05d", numUpdate), + writeGraph(mc+"COMPLETE"+String.format("%05d", numUpdate), writeLabels, labelSelect, pruneGarbage, diff --git a/Robust/src/Makefile b/Robust/src/Makefile index 91de7309..5f81b007 100644 --- a/Robust/src/Makefile +++ b/Robust/src/Makefile @@ -86,6 +86,7 @@ Analysis/OwnershipAnalysis/ReachabilitySet.class \ Analysis/OwnershipAnalysis/ChangeTuple.class \ Analysis/OwnershipAnalysis/ChangeTupleSet.class \ Analysis/OwnershipAnalysis/Canonical.class \ +Analysis/OwnershipAnalysis/MethodContext.class \ Util/GraphNode.class Util/Namer.class Util/Relation.class \ Interface/HTTPHeader.class Interface/HTTPResponse.class \ Interface/HTTPServices.class Interface/HashStrings.class \ diff --git a/Robust/src/Tests/OwnershipAnalysisTest/testMethodContexts/makefile b/Robust/src/Tests/OwnershipAnalysisTest/testMethodContexts/makefile new file mode 100644 index 00000000..0d630669 --- /dev/null +++ b/Robust/src/Tests/OwnershipAnalysisTest/testMethodContexts/makefile @@ -0,0 +1,30 @@ +PROGRAM=testMethodContexts + +SOURCE_FILES=$(PROGRAM).java + +BUILDSCRIPT=~/research/Robust/src/buildscript +BSFLAGS= -recover -ownership -ownaliasfile aliases.txt -enable-assertions -ownwritedots final -ownallocdepth 1 #-flatirtasks + + +all: $(PROGRAM).bin + +view: PNGs + eog *.png & + +PNGs: DOTs + d2p *COMPLETE*.dot + +DOTs: $(PROGRAM).bin + +$(PROGRAM).bin: $(SOURCE_FILES) + $(BUILDSCRIPT) $(BSFLAGS) -o $(PROGRAM) $(SOURCE_FILES) + +clean: + rm -f $(PROGRAM).bin + rm -fr tmpbuilddirectory + rm -f *~ + rm -f *.dot + rm -f *.png + rm -f *.ps + rm -f *.eps + rm -f aliases.txt diff --git a/Robust/src/Tests/OwnershipAnalysisTest/testMethodContexts/testMethodContexts.java b/Robust/src/Tests/OwnershipAnalysisTest/testMethodContexts/testMethodContexts.java new file mode 100644 index 00000000..3305312a --- /dev/null +++ b/Robust/src/Tests/OwnershipAnalysisTest/testMethodContexts/testMethodContexts.java @@ -0,0 +1,81 @@ +public class Foo { flag f; Foo x; public Foo(){} } + +public class Plane { + public Plane(){} + + public void fly( Foo p0, Foo p1 ) { + p0.x = new Foo(){f}; + } +} + +public class SpitFire extends Plane { + public SpitFire(){} + + public void fly( Foo p0, Foo p1 ) { + p1.x = new Foo(){f}; + } +} + +public class Jet extends Plane { + public Jet(){} + + public void fly( Foo p0, Foo p1 ) { + Foo jet = new Foo(){f}; + jet.x = p0; + } +} + +public class F14 extends Jet { + public F14(){} + + public void fly( Foo p0, Foo p1 ) { + Foo f14 = new Foo(){f}; + f14.x = p1; + } +} + +task Startup( StartupObject s{ initialstate } ) { + + Foo a0 = new Foo(){f}; + Foo a1 = new Foo(){f}; + + Plane p; + + if( false ) { + p = new Plane(); + } else if( false ) { + p = new SpitFire(); + } else if( false ) { + p = new Jet(); + } else { + p = new F14(); + } + + p.fly( a0, a1 ); + + taskexit( s{ !initialstate } ); +} + + +task SomeOtherTask( Foo foo{f} ) { + + Foo a0 = new Foo(){f}; + Foo a1 = new Foo(){f}; + + Plane p; + + if( false ) { + p = new Plane(); + } else if( false ) { + p = new SpitFire(); + } else if( false ) { + p = new Jet(); + } else { + p = new F14(); + } + + a0.x = a1; + p.fly( a0, a1 ); + + taskexit( foo{!f} ); +}