CallerScopeBuilder.java

Go to the documentation of this file.
00001 package edu.rice.cs.hpc.data.experiment.scope;
00002 
00003 import java.util.LinkedList;
00004 
00005 import edu.rice.cs.hpc.data.experiment.metric.AbstractCombineMetric;
00006 import edu.rice.cs.hpc.data.experiment.scope.filters.MetricValuePropagationFilter;
00007 
00008 public class CallerScopeBuilder {
00009     
00010     // number of maximum "descendants" in callers tree
00011     static private final int MAX_DESC = 2;
00012 
00013     
00014     /******
00015      * create caller tree, return the list of call path of this scope_cct
00016      * @param scope_cct: scope in CCT
00017      * @param scope_cost: the scope for cost reference. All nodes will be assigned with this cost
00018      * @param combine: the combine method
00019      * @param inclusiveOnly
00020      * @param exclusiveOnly
00021      * 
00022      * @return list of call path
00023      */
00024     static public LinkedList<CallSiteScopeCallerView> createCallChain(
00025             Scope scope_cct, Scope scope_cost, AbstractCombineMetric combine, 
00026             MetricValuePropagationFilter inclusiveOnly, MetricValuePropagationFilter exclusiveOnly ) {
00027         //-----------------------------------------------------------------------
00028         // compute callPath: a chain of my callers
00029         //
00030         // we build a chain of callers  by tracing the path from a procedure
00031         // up to the root of the calling context tree. notice that 
00032         // this isn't simply a reversal of the path. in the chain of callers,
00033         // we associate the call site with the caller. in the calling context
00034         // tree, the call site is paired with the callee. that's why we
00035         // work with a pair of CallSiteScopes at a time (innerCS and enclosingCS)
00036         //-----------------------------------------------------------------------
00037         Scope innerCS = scope_cct;
00038         LinkedList<CallSiteScopeCallerView> callPathList = new LinkedList<CallSiteScopeCallerView>();
00039         Scope next = scope_cct.getParentScope();
00040         int numKids = 0;
00041         CallSiteScopeCallerView prev_scope = null;
00042         while ( (next != null) && !(next instanceof RootScope) && (numKids<MAX_DESC) )
00043         {
00044             // Laksono 2009.01.14: we only deal with call site OR pure procedure scope (no alien)
00045             if ( isCallSiteCandidate(next, innerCS)) {
00046 
00047                 Scope enclosingCS = null;
00048                 ProcedureScope mycaller = null;
00049                 
00050                 if (next instanceof ProcedureScope) {
00051                     mycaller = (ProcedureScope) next;
00052                     if (((ProcedureScope)next).isAlien()) {
00053                         // hack for alien procedure: use the current scope
00054                         //  for the enclosing call site
00055                         enclosingCS = next;
00056                     }
00057                     
00058                 }   else if (next instanceof CallSiteScope) {
00059                     enclosingCS = (CallSiteScope) next;
00060                     mycaller = ((CallSiteScope)enclosingCS).getProcedureScope(); 
00061                 }
00062                 
00063                 LineScope lineScope = null;
00064                 
00065                 if (innerCS instanceof CallSiteScope) {
00066                     // normal call site
00067                     lineScope = ((CallSiteScope)innerCS).getLineScope();
00068                 } else {
00069                     // hack for alien procedure: create a new line scope
00070                     lineScope = new LineScope(innerCS.getExperiment(), innerCS.getSourceFile(),
00071                             innerCS.getFirstLineNumber(), innerCS.getCCTIndex(),
00072                             innerCS.getFlatIndex());
00073                 }
00074                 
00075                 if(lineScope != null) {
00076                     numKids++;
00077                     if (prev_scope != null)
00078                         prev_scope.markScopeHasChildren(); //numChildren = 1;
00079 
00080                     //--------------------------------------------------------------
00081                     // creating a new child scope if the path is not too long (< MAX_DESC)
00082                     //--------------------------------------------------------------
00083                     if (numKids<MAX_DESC) {
00084                         CallSiteScopeCallerView callerScope =
00085                             new CallSiteScopeCallerView( lineScope, mycaller,
00086                                     CallSiteScopeType.CALL_FROM_PROCEDURE, lineScope.hashCode(), next, scope_cost);
00087 
00088                         // set the value of the new scope
00089                         combine.combine(callerScope, scope_cost, inclusiveOnly, exclusiveOnly);
00090                         callPathList.addLast(callerScope);
00091                         
00092                         innerCS = enclosingCS;
00093                         prev_scope = callerScope;
00094                     }
00095                 }
00096             }
00097             next = next.getParentScope();
00098         }
00099 
00100         return callPathList;
00101     }
00102     
00103     
00104     /****
00105      * Merge the same path in the caller path (if exist)
00106      * @param callee
00107      * @param callerPathList
00108      * @param combine
00109      * @param inclusiveOnly
00110      * @param exclusiveOnly
00111      */
00112     static public void mergeCallerPath(IMergedScope.MergingStatus status, int counter_to_assign, Scope callee, 
00113             LinkedList<CallSiteScopeCallerView> callerPathList, AbstractCombineMetric combine,
00114             MetricValuePropagationFilter inclusiveOnly, MetricValuePropagationFilter exclusiveOnly) 
00115     {
00116         if (callerPathList.size() == 0) return; // merging an empty path is trivial
00117 
00118         CallSiteScopeCallerView first = callerPathList.removeFirst();
00119 
00120         // -------------------------------------------------------------------------
00121         // attempt to merge first node on caller path with existing caller of callee  
00122         //--------------------------------------------------------------------------
00123         int nCallers = callee.getSubscopeCount();
00124         for (int i = 0; i < nCallers; i++) {
00125             CallSiteScopeCallerView existingCaller = (CallSiteScopeCallerView) callee.getSubscope(i);
00126 
00127             //------------------------------------------------------------------------
00128             // we check if the scope is identical with the existing scope in the path
00129             // if it is the case, we should merge them
00130             //------------------------------------------------------------------------
00131             if (first.getCCTIndex() == existingCaller.getCCTIndex()) {
00132 
00133                 //------------------------------------------------------------------------
00134                 // combine metric values for first to those of existingCaller.
00135                 //------------------------------------------------------------------------
00136                 combine.combine(existingCaller, first, inclusiveOnly, exclusiveOnly);
00137 
00138                 //------------------------------------------------------------------------
00139                 // We found the same CCT in the path. let's merge them
00140                 //------------------------------------------------------------------------
00141                 existingCaller.merge(status, first, counter_to_assign);
00142 
00143                 //------------------------------------------------------------------------
00144                 // merge rest of call path as a child of existingCaller.
00145                 //------------------------------------------------------------------------
00146                 mergeCallerPath(status, counter_to_assign, existingCaller, callerPathList, combine, inclusiveOnly, exclusiveOnly);
00147 
00148                 return; // merged with existing child. nothing left to do.
00149             }
00150         }
00151 
00152         //----------------------------------------------
00153         // no merge possible. add new path into tree.
00154         //----------------------------------------------
00155         addNewPathIntoTree(callee, first, callerPathList);
00156     }
00157 
00158     
00159     
00160     /**********
00161      * add children 
00162      * @param callee: the parent
00163      * @param first: the first child
00164      * @param callerPathList: list of children (excluding the first child)
00165      */
00166     static public void addNewPathIntoTree(Scope callee, CallSiteScopeCallerView first,
00167             LinkedList<CallSiteScopeCallerView> callerPathList) {
00168         
00169         callee.addSubscope(first);
00170         first.setParentScope(callee);
00171         for (Scope prev = first; callerPathList.size() > 0; ) {
00172             Scope next = callerPathList.removeFirst();
00173             prev.addSubscope(next);
00174             next.setParentScope(prev);
00175             prev = next;
00176         }
00177     }
00178     
00179     
00180     /******
00181      * 
00182      * @param scope
00183      * @param innerCS
00184      * @return
00185      */
00186     static private boolean isCallSiteCandidate(Scope scope, Scope innerCS) {
00187         return ( ((scope instanceof CallSiteScope) || 
00188                 // laks 2013.12.2 original code: (scope instanceof ProcedureScope && !((ProcedureScope)scope).isAlien()) )
00189                 (scope instanceof ProcedureScope) )
00190                 && (innerCS != null) );
00191     }
00192 }

Generated on 5 May 2015 for HPCVIEWER by  doxygen 1.6.1