From: jjenista Date: Tue, 25 Mar 2008 20:36:06 +0000 (+0000) Subject: Got clarification on how to resolve method calls, introduced concept of X-Git-Tag: preEdgeChange~200 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=55cc968e42e2106be90306929aa8e88849a63951;p=IRC.git Got clarification on how to resolve method calls, introduced concept of a set of possible callees on virtual dispatch, have to take the merge of those ownership graphs and allocation sites to be correct. Stable, but only a draft of the OwnershipAnalysis portion. OwnershipGraph mechanics to determine mapping of references in callee merge-o-tron to caller graph not added yet. --- diff --git a/Robust/src/Analysis/OwnershipAnalysis/OwnershipAnalysis.java b/Robust/src/Analysis/OwnershipAnalysis/OwnershipAnalysis.java index 685ac580..aa53286d 100644 --- a/Robust/src/Analysis/OwnershipAnalysis/OwnershipAnalysis.java +++ b/Robust/src/Analysis/OwnershipAnalysis/OwnershipAnalysis.java @@ -27,10 +27,10 @@ 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 HashSet descriptorsToVisit; - private Hashtable mapDescriptorToCompleteOwnershipGraph; - private Hashtable mapFlatNewToAllocationSite; - + private HashSet descriptorsToVisit; + private Hashtable mapDescriptorToCompleteOwnershipGraph; + private Hashtable mapFlatNewToAllocationSite; + private Hashtable > mapDescriptorToAllocationSiteSet; // Use these data structures to track progress of one pass of // processing the FlatNodes of a particular method @@ -48,13 +48,16 @@ public class OwnershipAnalysis { this.callGraph = callGraph; this.allocationDepth = allocationDepth; + descriptorsToVisit = new HashSet(); + mapDescriptorToCompleteOwnershipGraph = new Hashtable(); mapFlatNewToAllocationSite = new Hashtable(); - descriptorsToVisit = new HashSet(); + mapDescriptorToAllocationSiteSet = + new Hashtable >(); // use this set to prevent infinite recursion when // traversing the call graph @@ -287,20 +290,59 @@ public class OwnershipAnalysis { case FKind.FlatNew: FlatNew fnn = (FlatNew) fn; - dst = fnn.getDst(); + dst = fnn.getDst(); AllocationSite as = getAllocationSiteFromFlatNew( fnn ); + og.assignTempToNewAllocation( dst, as ); - - // !!!!!!!!!!!!!! - // do this if the new object is a flagged type - //og.addAnalysisRegion( tdParam ); break; case FKind.FlatCall: - //FlatCall fc = (FlatCall) fn; - //MethodDescriptor md = fc.getMethod(); - //descriptorsToVisit.add( md ); - //System.out.println( " Descs to visit: " + descriptorsToVisit ); + FlatCall fc = (FlatCall) fn; + MethodDescriptor md = fc.getMethod(); + FlatMethod flatm = state.getMethodFlat( md ); + HashSet allocSiteSet = getAllocationSiteSet( md ); + OwnershipGraph ogAllPossibleCallees = new OwnershipGraph( allocationDepth ); + + if( md.isStatic() ) { + // a static method is simply always the same, makes life easy + OwnershipGraph onlyPossibleCallee = mapDescriptorToCompleteOwnershipGraph.get( md ); + ogAllPossibleCallees.merge( onlyPossibleCallee ); + + } else { + // if the method descriptor is virtual, then there could be a + // set of possible methods that will actually be invoked, so + // find all of them and merge all of their graphs together + TypeDescriptor typeDesc = fc.getThis().getType(); + Set possibleCallees = callGraph.getMethods( md, typeDesc ); + + Iterator i = possibleCallees.iterator(); + while( i.hasNext() ) { + MethodDescriptor possibleMd = (MethodDescriptor) i.next(); + allocSiteSet.addAll( getAllocationSiteSet( possibleMd ) ); + OwnershipGraph ogPotentialCallee = mapDescriptorToCompleteOwnershipGraph.get( possibleMd ); + ogAllPossibleCallees.merge( ogPotentialCallee ); + } + } + + // now we should have the following information to resolve this method call: + // + // 1. A FlatCall fc to query for the caller's context (argument labels, etc) + // + // 2. Whether the method is static; if not we need to deal with the "this" pointer + // + // ******************************************************************************************* + // 3. The original FlatMethod flatm to query for callee's context (paramter labels) + // NOTE! I assume FlatMethod before virtual dispatch accurately describes all possible methods! + // ******************************************************************************************* + // + // 4. The OwnershipGraph ogAllPossibleCallees is a merge of every ownership graph of all the possible + // methods to capture any possible references made. + // + // 5. The Set of AllocationSite objects, allocSiteSet that is the set of allocation sites from + // every possible method we might have chosen + // + og.resolveMethodCall( fc, md.isStatic(), flatm, ogAllPossibleCallees, allocSiteSet ); + //og.writeGraph( methodDesc, fn ); break; @@ -332,6 +374,7 @@ public class OwnershipAnalysis { } + // return just the allocation site associated with one FlatNew node private AllocationSite getAllocationSiteFromFlatNew( FlatNew fn ) { if( !mapFlatNewToAllocationSite.containsKey( fn ) ) { AllocationSite as = new AllocationSite( allocationDepth ); @@ -351,4 +394,55 @@ public class OwnershipAnalysis { return mapFlatNewToAllocationSite.get( fn ); } + + + // return all allocation sites in the method (there is one allocation + // site per FlatNew node in a method) + private HashSet getAllocationSiteSet( Descriptor d ) { + if( !mapDescriptorToAllocationSiteSet.containsKey( d ) ) { + buildAllocationSiteSet( d ); + } + + return mapDescriptorToAllocationSiteSet.get( d ); + + } + + private void buildAllocationSiteSet( Descriptor d ) { + HashSet s = new HashSet(); + + FlatMethod fm; + if( d instanceof MethodDescriptor ) { + fm = state.getMethodFlat( (MethodDescriptor) d ); + } else { + assert d instanceof TaskDescriptor; + fm = state.getMethodFlat( (TaskDescriptor) d ); + } + + // visit every node in this FlatMethod's IR graph + // and make a set of the allocation sites from the + // FlatNew node's visited + HashSet visited = new HashSet(); + HashSet toVisit = new HashSet(); + toVisit.add( fm ); + + while( !toVisit.isEmpty() ) { + FlatNode n = toVisit.iterator().next(); + + if( n instanceof FlatNew ) { + s.add( getAllocationSiteFromFlatNew( (FlatNew) n ) ); + } + + toVisit.remove( n ); + visited.add( n ); + + for( int i = 0; i < n.numNext(); ++i ) { + FlatNode child = n.getNext( i ); + if( !visited.contains( child ) ) { + toVisit.add( child ); + } + } + } + + mapDescriptorToAllocationSiteSet.put( d, s ); + } } diff --git a/Robust/src/Analysis/OwnershipAnalysis/OwnershipGraph.java b/Robust/src/Analysis/OwnershipAnalysis/OwnershipGraph.java index ba53898e..f84c9c66 100644 --- a/Robust/src/Analysis/OwnershipAnalysis/OwnershipGraph.java +++ b/Robust/src/Analysis/OwnershipAnalysis/OwnershipGraph.java @@ -433,6 +433,88 @@ public class OwnershipGraph { } + + // some notes: + // the heap regions that are specially allocated as multiple-object + // regions for method parameters need to be remembered in order to + // resolve a function call. So actually, we need a mapping from + // caller argument descriptors to the callee parameter heap regions + // to apply reference edges in the callee to the caller graph. + // + // also, Constructors and virtual dispatch methods have a "this" + // argument that make the mapping of arguments to parameters a little + // tricky. What happens to that this region? + + + public void resolveMethodCall( FlatCall fc, + boolean isStatic, + FlatMethod fm, + OwnershipGraph ogCallee, + HashSet allocSiteSet ) { + + // first age all of the allocation sites from + // the callee graph in this graph + Iterator i = allocSiteSet.iterator(); + while( i.hasNext() ) { + this.age( (AllocationSite) i.next() ); + } + + // the heap regions represented by the arguments (caller graph) + // and heap regions for the parameters (callee graph) + // don't correspond to each other by heap region ID. In fact, + // an argument label node can be referencing several heap regions + // so the parameter label always references a multiple-object + // heap region in order to handle the range of possible contexts + // for a method call. This means we need to make a special mapping + // of argument->parameter regions in order to update the caller graph, + // then remember which heap regions were used so we can ignore them + // in the more general algorithm below that includes all heap regions + // of the callee graph + HashSet calleeParameterIDs = new HashSet(); + + if( isStatic ) { + assert fc.numArgs() == fm.numParameters(); + } else { + assert fc.numArgs() + 1 == fm.numParameters(); + } + + for( int a = 0; a < fc.numArgs(); ++a ) { + + } + + // for every heap region->heap region edge in the + // callee graph, create the matching edge or edges + // in the caller graph + Set sCallee = ogCallee.id2hrn.entrySet(); + Iterator iCallee = sCallee.iterator(); + while( iCallee.hasNext() ) { + Map.Entry meCallee = (Map.Entry) iCallee.next(); + Integer idCallee = (Integer) meCallee.getKey(); + HeapRegionNode hrnCallee = (HeapRegionNode) meCallee.getValue(); + + HeapRegionNode hrnChildCallee = null; + Iterator heapRegionsItrCallee = hrnCallee.setIteratorToReferencedRegions(); + while( heapRegionsItrCallee.hasNext() ) { + Map.Entry me = (Map.Entry) heapRegionsItrCallee.next(); + hrnChildCallee = (HeapRegionNode) me.getKey(); + ReferenceEdgeProperties repC = (ReferenceEdgeProperties) me.getValue(); + + Integer idChildCallee = hrnChildCallee.getID(); + + // now we know that in the callee method's ownership graph + // there is a heap region->heap region reference edge given + // by the ownership-graph independent ID's: + // idCallee->idChildCallee + // + + + // at this point we know an edge in graph A exists + // idA -> idChildA, does this exist in B? + } + } + } + + //////////////////////////////////////////////////// // in merge() and equals() methods the suffix A