1 package Analysis.OwnershipAnalysis;
3 import Analysis.CallGraph.*;
10 public class OwnershipAnalysis {
14 private CallGraph callGraph;
15 private int allocationDepth;
18 static private int uniqueIDcount = 0;
21 // Use these data structures to track progress of
22 // processing all methods in the program, and by methods
23 // TaskDescriptor and MethodDescriptor are combined
24 // together, with a common parent class Descriptor
25 private HashSet <Descriptor> descriptorsToVisit;
26 private Hashtable<Descriptor, OwnershipGraph> mapDescriptorToCompleteOwnershipGraph;
27 private Hashtable<FlatNew, AllocationSite> mapFlatNewToAllocationSite;
30 // Use these data structures to track progress of one pass of
31 // processing the FlatNodes of a particular method
32 private HashSet <FlatNode> flatNodesToVisit;
33 private Hashtable<FlatNode, OwnershipGraph> mapFlatNodeToOwnershipGraph;
34 private HashSet <FlatReturnNode> returnNodesToCombineForCompleteOwnershipGraph;
37 // this analysis generates an ownership graph for every task
39 public OwnershipAnalysis( State state,
41 int allocationDepth ) throws java.io.IOException {
43 this.callGraph = callGraph;
44 this.allocationDepth = allocationDepth;
46 mapDescriptorToCompleteOwnershipGraph =
47 new Hashtable<Descriptor, OwnershipGraph>();
49 mapFlatNewToAllocationSite =
50 new Hashtable<FlatNew, AllocationSite>();
52 // initialize methods to visit as the set of all tasks
53 descriptorsToVisit = new HashSet<Descriptor>();
54 Iterator taskItr = state.getTaskSymbolTable().getDescriptorsIterator();
55 while( taskItr.hasNext() ) {
56 Descriptor d = (Descriptor) taskItr.next();
57 descriptorsToVisit.add( d );
60 // as mentioned above, analyze methods one-by-one, possibly revisiting
61 // a method if the methods that it calls are updated
66 // manage the set of tasks and methods to be analyzed
67 // and be sure to reschedule tasks/methods when the methods
68 // they call are updated
69 private void analyzeMethods() throws java.io.IOException {
71 while( !descriptorsToVisit.isEmpty() ) {
72 Descriptor d = (Descriptor) descriptorsToVisit.iterator().next();
73 descriptorsToVisit.remove( d );
75 // because the task or method descriptor just extracted
76 // was in the "to visit" set it either hasn't been analyzed
77 // yet, or some method that it depends on has been
78 // updated. Recompute a complete ownership graph for
79 // this task/method and compare it to any previous result.
80 // If there is a change detected, add any methods/tasks
81 // that depend on this one to the "to visit" set.
83 System.out.println( "Analyzing " + d );
87 if( d instanceof MethodDescriptor ) {
89 fm = state.getMethodFlat( (MethodDescriptor) d );
91 assert d instanceof TaskDescriptor;
93 fm = state.getMethodFlat( (TaskDescriptor) d );
96 OwnershipGraph og = analyzeFlatMethod( isTask, fm );
97 OwnershipGraph ogPrev = mapDescriptorToCompleteOwnershipGraph.get( d );
99 if( !og.equals( ogPrev ) ) {
100 mapDescriptorToCompleteOwnershipGraph.put( d, og );
102 // only methods have dependents, tasks cannot
103 // be invoked by any user program calls
104 if( d instanceof MethodDescriptor ) {
105 MethodDescriptor md = (MethodDescriptor) d;
106 Set dependents = callGraph.getCallerSet( md );
107 System.out.println( " Caller set is: " + dependents );
108 descriptorsToVisit.addAll( dependents );
116 private OwnershipGraph
117 analyzeFlatMethod( boolean isTask,
118 FlatMethod flatm ) throws java.io.IOException {
120 // initialize flat nodes to visit as the flat method
121 // because all other nodes in this flat method are
122 // decendents of the flat method itself
123 flatNodesToVisit = new HashSet<FlatNode>();
124 flatNodesToVisit.add( flatm );
126 // initilize the mapping of flat nodes in this flat method to
127 // ownership graph results to an empty mapping
128 mapFlatNodeToOwnershipGraph = new Hashtable<FlatNode, OwnershipGraph>();
130 // initialize the set of return nodes that will be combined as
131 // the final ownership graph result to return as an empty set
132 returnNodesToCombineForCompleteOwnershipGraph = new HashSet<FlatReturnNode>();
134 while( !flatNodesToVisit.isEmpty() ) {
135 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
136 flatNodesToVisit.remove( fn );
138 // perform this node's contributions to the ownership
139 // graph on a new copy, then compare it to the old graph
140 // at this node to see if anything was updated.
141 OwnershipGraph og = new OwnershipGraph( allocationDepth );
143 // start by merging all node's parents' graphs
144 for( int i = 0; i < fn.numPrev(); ++i ) {
145 FlatNode pn = fn.getPrev( i );
146 OwnershipGraph ogParent = getGraphFromFlatNode( pn );
147 og.merge( ogParent );
150 // apply the analysis of the flat node to the
151 // ownership graph made from the merge of the
153 analyzeFlatNode( isTask, fn, og );
155 // if the results of the new graph are different from
156 // the current graph at this node, replace the graph
157 // with the update and enqueue the children for
159 OwnershipGraph ogPrev = getGraphFromFlatNode( fn );
161 if( !og.equals( ogPrev ) ) {
162 setGraphForFlatNode( fn, og );
164 for( int i = 0; i < fn.numNext(); i++ ) {
165 FlatNode nn = fn.getNext( i );
166 flatNodesToVisit.add( nn );
171 // end by merging all return nodes into a complete
172 // ownership graph that represents all possible heap
173 // states after the flat method returns
174 OwnershipGraph completeGraph = new OwnershipGraph( allocationDepth );
175 Iterator retItr = returnNodesToCombineForCompleteOwnershipGraph.iterator();
176 while( retItr.hasNext() ) {
177 FlatReturnNode frn = (FlatReturnNode) retItr.next();
178 OwnershipGraph ogr = getGraphFromFlatNode( frn );
179 completeGraph.merge( ogr );
181 return completeGraph;
186 analyzeFlatNode( boolean isTask,
188 OwnershipGraph og ) throws java.io.IOException {
190 //System.out.println( "Analyszing a flat node" );
195 //String nodeDescription = "No description";
196 //boolean writeGraph = false;
198 // use node type to decide what alterations to make
199 // to the ownership graph
200 switch( fn.kind() ) {
202 case FKind.FlatMethod:
203 FlatMethod fm = (FlatMethod) fn;
206 // add method parameters to the list of heap regions
207 // and remember names for analysis
208 for( int i = 0; i < fm.numParameters(); ++i ) {
209 TempDescriptor tdParam = fm.getParameter( i );
210 og.taskParameterAllocation( tdParam );
211 //og.addAnalysisRegion( tdParam );
217 case FKind.FlatOpNode:
218 FlatOpNode fon = (FlatOpNode) fn;
219 if( fon.getOp().getOp() == Operation.ASSIGN ) {
222 og.assignTempToTemp( src, dst );
223 //nodeDescription = "Op";
229 case FKind.FlatFieldNode:
230 FlatFieldNode ffn = (FlatFieldNode) fn;
233 fld = ffn.getField();
234 if( !fld.getType().isPrimitive() ) {
235 og.assignTempToField( src, dst, fld );
236 //nodeDescription = "Field";
242 case FKind.FlatSetFieldNode:
243 FlatSetFieldNode fsfn = (FlatSetFieldNode) fn;
246 fld = fsfn.getField();
247 og.assignFieldToTemp( src, dst, fld );
248 //nodeDescription = "SetField";
254 FlatNew fnn = (FlatNew) fn;
256 og.assignTempToNewAllocation( dst, fnn );
259 // do this if the new object is a flagged type
260 //og.addAnalysisRegion( tdParam );
262 //nodeDescription = "New";
271 FlatCall fc = (FlatCall) fn;
272 MethodDescriptor md = fc.getMethod();
273 descriptorsToVisit.add( md );
276 case FKind.FlatReturnNode:
277 //nodeDescription = "Return";
279 //og.writeCondensedAnalysis( makeCondensedAnalysisName( methodname, flatnodetolabel.get(fn) ) );
280 //og.writeGraph( fn );
286 og.writeGraph( makeNodeName( methodname,
287 flatnodetolabel.get( fn ),
293 static public Integer generateUniqueHeapRegionNodeID() {
295 return new Integer( uniqueIDcount );
298 private OwnershipGraph getGraphFromFlatNode( FlatNode fn ) {
299 if( !mapFlatNodeToOwnershipGraph.containsKey( fn ) ) {
300 mapFlatNodeToOwnershipGraph.put( fn, new OwnershipGraph( allocationDepth ) );
303 return mapFlatNodeToOwnershipGraph.get( fn );
306 private void setGraphForFlatNode( FlatNode fn, OwnershipGraph og ) {
307 mapFlatNodeToOwnershipGraph.put( fn, og );
310 private AllocationSite getAllocationSiteFromFlatNew( FlatNew fn ) {
311 if( !mapFlatNewToAllocationSite.containsKey( fn ) ) {
312 AllocationSite as = new AllocationSite( allocationDepth );
314 // the first k-1 nodes are single objects
315 for( int i = 0; i < allocationDepth - 1; ++i ) {
316 //HeapRegionNode hrn = createNewHeapRegionNode( null, true, false, false );
317 Integer id = generateUniqueHeapRegionNodeID();
318 as.setIthOldest( i, id );
321 // the kth node is a summary node
322 //HeapRegionNode hrnNewSummary = createNewHeapRegionNode( null, false, false, true );
323 Integer id2 = generateUniqueHeapRegionNodeID();
324 as.setIthOldest( allocationDepth - 1, id2 );
326 mapFlatNewToAllocationSite.put( fn, as );
329 return mapFlatNewToAllocationSite.get( fn );