FlatViewScopeVisitor.java

Go to the documentation of this file.
00001 package edu.rice.cs.hpc.data.experiment.scope.visitors;
00002 
00003 import java.util.*;
00004 
00005 import edu.rice.cs.hpc.data.experiment.Experiment;
00006 import edu.rice.cs.hpc.data.experiment.scope.AlienScope;
00007 import edu.rice.cs.hpc.data.experiment.scope.CallSiteScope;
00008 import edu.rice.cs.hpc.data.experiment.scope.FileScope;
00009 import edu.rice.cs.hpc.data.experiment.scope.GroupScope;
00010 import edu.rice.cs.hpc.data.experiment.scope.LineScope;
00011 import edu.rice.cs.hpc.data.experiment.scope.LoadModuleScope;
00012 import edu.rice.cs.hpc.data.experiment.scope.LoopScope;
00013 import edu.rice.cs.hpc.data.experiment.scope.ProcedureScope;
00014 import edu.rice.cs.hpc.data.experiment.scope.RootScope;
00015 import edu.rice.cs.hpc.data.experiment.scope.Scope;
00016 import edu.rice.cs.hpc.data.experiment.scope.ScopeVisitType;
00017 import edu.rice.cs.hpc.data.experiment.scope.StatementRangeScope;
00018 import edu.rice.cs.hpc.data.experiment.scope.filters.ExclusiveOnlyMetricPropagationFilter;
00019 import edu.rice.cs.hpc.data.experiment.scope.filters.InclusiveOnlyMetricPropagationFilter;
00020 import edu.rice.cs.hpc.data.experiment.source.SourceFile;
00021 
00022 
00023 /*************************************************************************************************
00024  * Class to create Flat tree based on calling context tree
00025  * 
00026  * REMARK: THIS CODE IS NOT COMPATIBLE WITH OLD DATABASE !!!
00027  *  
00028  *
00029  *************************************************************************************************/
00030 
00031 public class FlatViewScopeVisitor implements IScopeVisitor {
00032     private Hashtable<Integer, LoadModuleScope> htFlatLoadModuleScope;
00033     private Hashtable<String, FileScope> htFlatFileScope;
00034     private HashMap<String, FlatScopeInfo> htFlatScope;
00035     private HashMap<String, Scope[]> htFlatCostAdded;
00036     
00037     private Experiment experiment;
00038     private RootScope root_ft;
00039     
00040     private InclusiveOnlyMetricPropagationFilter inclusive_filter;
00041     private ExclusiveOnlyMetricPropagationFilter exclusive_filter;
00042     
00043     //final private boolean debug = false;
00044     
00045     /******************************************************************
00046      * Constructor
00047      * @param exp: experiment
00048      * @param root: the root of the tree
00049      ******************************************************************/
00050     public FlatViewScopeVisitor( Experiment exp, RootScope root) {
00051         this.experiment = exp;
00052         
00053         this.htFlatLoadModuleScope = new Hashtable<Integer, LoadModuleScope>();
00054         this.htFlatFileScope = new Hashtable<String, FileScope>();
00055         this.htFlatScope     = new HashMap<String, FlatScopeInfo>();
00056         this.htFlatCostAdded = new HashMap<String, Scope[]>();
00057         
00058         this.root_ft = root;
00059         
00060         this.inclusive_filter = new InclusiveOnlyMetricPropagationFilter( exp );
00061         this.exclusive_filter = new ExclusiveOnlyMetricPropagationFilter( exp );
00062     }
00063     
00064     
00065     public void visit(Scope scope, ScopeVisitType vt)               { }
00066     public void visit(RootScope scope, ScopeVisitType vt)           { }
00067     public void visit(LoadModuleScope scope, ScopeVisitType vt)     { }
00068     public void visit(FileScope scope, ScopeVisitType vt)           { }
00069     public void visit(AlienScope scope, ScopeVisitType vt)          { }
00070     public void visit(StatementRangeScope scope, ScopeVisitType vt) { }
00071     public void visit(GroupScope scope, ScopeVisitType vt)          { }
00072 
00073     public void visit(CallSiteScope scope, ScopeVisitType vt)       { 
00074         add(scope,vt, true, false); 
00075     }
00076     public void visit(LineScope scope, ScopeVisitType vt)           { 
00077         add(scope,vt, true, true); 
00078     }
00079     public void visit(LoopScope scope, ScopeVisitType vt)           {
00080         add(scope,vt, true, false); 
00081     }
00082     public void visit(ProcedureScope scope, ScopeVisitType vt)      {
00083         add(scope,vt, true, false); 
00084     }
00085 
00086     
00087     /******************************************************************
00088      * Create or add a flat scope based on the scope from CCT
00089      * @param scope
00090      * @param vt
00091      * @param add_inclusive: flag if an inclusive cost had to be combined in flat/module scope
00092      * @param add_exclusive: flag if an exclusive cost had to be combined in flat/module scope
00093      ******************************************************************/
00094     private void add( Scope scope, ScopeVisitType vt, boolean add_inclusive, boolean add_exclusive ) {
00095         
00096         String id = this.getID(scope); 
00097 
00098         if (vt == ScopeVisitType.PreVisit ) {
00099             //--------------------------------------------------------------------------
00100             // Pre-visit
00101             //--------------------------------------------------------------------------
00102             Scope flat_info[] = this.htFlatCostAdded.get( id );
00103             if (flat_info != null) {
00104                 this.htFlatCostAdded.remove(id);
00105             }
00106             
00107             FlatScopeInfo objFlat = this.getFlatCounterPart(scope, scope, id);
00108             
00109             //--------------------------------------------------------------------------
00110             // Aggregating metrics to load module and flat scope
00111             // Notes: this is not correct for Derived incremental metrics
00112             //--------------------------------------------------------------------------
00113             addCostIfNecessary(id, objFlat.flat_lm, scope, add_inclusive, add_exclusive);
00114             addCostIfNecessary(id, objFlat.flat_file, scope, add_inclusive, add_exclusive);
00115 
00116             //--------------------------------------------------------------------------
00117             // For call site, we need also to create its procedure scope
00118             //--------------------------------------------------------------------------
00119             if (scope instanceof CallSiteScope) {
00120                 ProcedureScope proc_cct_s = ((CallSiteScope) scope).getProcedureScope();
00121                 this.getFlatCounterPart(proc_cct_s, scope, id);
00122             }
00123 
00124         } else {
00125             
00126             //--------------------------------------------------------------------------
00127             // Post visit
00128             //--------------------------------------------------------------------------
00129             Scope flat_info[] = this.htFlatCostAdded.get( id );
00130             if (flat_info != null)
00131                 for (int i=0; i<flat_info.length; i++) {
00132                     this.decrementCounter(flat_info[i]);
00133                 }
00134         }
00135     }
00136     
00137     
00138     /****************************************************************************
00139      * decrement scope's counter
00140      * @param flat_s
00141      ****************************************************************************/
00142     private void decrementCounter(Scope flat_s) {
00143         if (flat_s != null) {
00144             flat_s.decrementCounter();
00145         }
00146     }
00147     
00148 
00149     /****************************************************************************
00150      * Get the flat counterpart of the scope cct:
00151      * - check if the flat counter part already exist
00152      * -- if not, create a new one
00153      * - get the flat file counter part exists
00154      * 
00155      * @param scopeCCT
00156      * @return
00157      ****************************************************************************/
00158     private FlatScopeInfo getFlatScope( Scope cct_s ) {
00159         //-----------------------------------------------------------------------------
00160         // get the flat scope
00161         //-----------------------------------------------------------------------------
00162         String id = this.getID(cct_s);
00163         
00164         FlatScopeInfo flat_info_s = this.htFlatScope.get( id );
00165         
00166         if (flat_info_s == null) {
00167 
00168             //-----------------------------------------------------------------------------
00169             // Initialize the flat scope
00170             //-----------------------------------------------------------------------------
00171             flat_info_s = new FlatScopeInfo();
00172             
00173             //-----------------------------------------------------------------------------
00174             // finding enclosing procedure of this cct scope:
00175             // if it is a call site, then the file and the module can be found in the scope
00176             // for others, we need to find the enclosing procedure iteratively
00177             //-----------------------------------------------------------------------------
00178             ProcedureScope proc_cct_s;
00179             if (cct_s instanceof CallSiteScope) {
00180                 proc_cct_s = ((CallSiteScope)cct_s).getProcedureScope();
00181             } else {
00182                 proc_cct_s = findEnclosingProcedure(cct_s);
00183             }
00184 
00185             if (proc_cct_s == null) {
00186                 throw new RuntimeException("Cannot find the enclosing procedure for " + cct_s);
00187             }
00188             
00189             //-----------------------------------------------------------------------------
00190             // Initialize the flat scope of this cct
00191             //-----------------------------------------------------------------------------
00192             flat_info_s.flat_s = cct_s.duplicate();
00193             
00194             //-----------------------------------------------------------------------------
00195             // Initialize the load module scope
00196             //-----------------------------------------------------------------------------
00197             flat_info_s.flat_lm = this.createFlatModuleScope(proc_cct_s);
00198 
00199             //-----------------------------------------------------------------------------
00200             // Initialize the flat file scope
00201             //-----------------------------------------------------------------------------
00202             flat_info_s.flat_file = this.createFlatFileScope(proc_cct_s, flat_info_s.flat_lm);
00203             
00204             //-----------------------------------------------------------------------------
00205             // Attach the scope to the file if it is a procedure
00206             //-----------------------------------------------------------------------------
00207             if (flat_info_s.flat_s instanceof ProcedureScope) {
00208                 this.addToTree(flat_info_s.flat_file, flat_info_s.flat_s);
00209             }
00210 
00211             //-----------------------------------------------------------------------------
00212             // save the info into hashtable
00213             //-----------------------------------------------------------------------------
00214             this.htFlatScope.put( id, flat_info_s);
00215         }
00216         
00217         return flat_info_s;
00218     }
00219 
00220     
00221     
00222     /*****************************************************************
00223      * Create the flat view of a load module
00224      * @param proc_cct_s
00225      * @return
00226      *****************************************************************/
00227     private LoadModuleScope createFlatModuleScope(ProcedureScope proc_cct_s) {
00228         LoadModuleScope lm = proc_cct_s.getLoadModule();
00229         LoadModuleScope lm_flat_s = null;
00230         
00231         // some old database do not provide load module information
00232         if (lm != null)  {
00233             lm_flat_s = this.htFlatLoadModuleScope.get(lm.hashCode());
00234             if (lm_flat_s == null) {
00235                 // no load module has been created. we allocate a new one
00236                 lm_flat_s = (LoadModuleScope) lm.duplicate();
00237                 // attach the load module to the root scope
00238                 this.addToTree(root_ft, lm_flat_s);
00239                 // store this module into our dictionary
00240                 this.htFlatLoadModuleScope.put(lm.hashCode(), lm_flat_s);
00241             }
00242         }
00243         return lm_flat_s;
00244     }
00245     
00246     /*****************************************************************
00247      * generate a unique file ID which depends on the load module:
00248      * unique file ID = load_module_ID + file_ID 
00249      * 
00250      * @param file
00251      * @param lm
00252      * 
00253      * @return
00254      *****************************************************************/
00255     private String getUniqueFileID(SourceFile file, LoadModuleScope lm)
00256     {
00257         return lm.getFlatIndex() + "/" + file.getFileID();
00258     }
00259     
00260     /*****************************************************************
00261      * Create the flat view of a file scope
00262      * @param cct_s
00263      * @param flat_lm
00264      * @return
00265      *****************************************************************/
00266     private FileScope createFlatFileScope(Scope cct_s, LoadModuleScope flat_lm) {
00267         SourceFile src_file = cct_s.getSourceFile();    
00268         String unique_file_id = getUniqueFileID(src_file, flat_lm);
00269         FileScope flat_file = this.htFlatFileScope.get( unique_file_id );
00270         
00271         //-----------------------------------------------------------------------------
00272         // ATTENTION: it is possible that a file can be included into more than one load module
00273         //-----------------------------------------------------------------------------
00274         if ( (flat_file == null) ){
00275             flat_file = createFileScope(src_file, flat_lm, unique_file_id);
00276             
00277         } else {
00278             
00279             Scope parent_lm = flat_file.getParentScope();
00280             if (parent_lm instanceof LoadModuleScope) {
00281                 LoadModuleScope flat_parent_lm = (LoadModuleScope) parent_lm;
00282 
00283                 // check if the load module the existing file is the same with the scope's load module
00284                 if (flat_parent_lm.hashCode() != flat_lm.hashCode() ) {
00285                     // the same file in different load module scope !!!
00286                     flat_file = createFileScope(src_file, flat_lm, unique_file_id);
00287                 }
00288             }
00289 
00290         }
00291         return flat_file;
00292     }
00293     
00294     
00295     /*****************************************************************
00296      * Create a new file scope (this procedure will NOT check if the file already exists or not) !
00297      * @param src_file
00298      * @param lm_s
00299      * @return
00300      *****************************************************************/
00301     private FileScope createFileScope(SourceFile src_file, LoadModuleScope lm_s, String unique_file_id) {
00302         int fileID = src_file.getFileID();
00303         FileScope file_s =  new FileScope( this.experiment, src_file, fileID );
00304         //------------------------------------------------------------------------------
00305         // if load module is undefined, then we attach the file scope to the root scope
00306         //------------------------------------------------------------------------------
00307         if (lm_s == null)
00308             this.addToTree(root_ft, file_s);
00309         else
00310             this.addToTree(lm_s, file_s);
00311         this.htFlatFileScope.put( unique_file_id, file_s);
00312 
00313         return file_s;
00314     }
00315     
00316     
00317     /*****************************************************************
00318      * construct the flat view of a cct scope
00319      * @param cct_s
00320      * @param proc_cct_s
00321      * @return
00322      *****************************************************************/
00323     private FlatScopeInfo getFlatCounterPart( Scope cct_s, Scope cct_s_metrics, String id) {
00324         // -----------------------------------------------------------------------------
00325         // Get the flat scope of the parent     
00326         // -----------------------------------------------------------------------------
00327         Scope cct_parent_s = cct_s.getParentScope() ;
00328         Scope flat_enc_s = null;
00329 
00330         if (cct_parent_s != null) {
00331             if (cct_parent_s instanceof RootScope) {
00332                 // ----------------------------------------------
00333                 // main procedure
00334                 // ----------------------------------------------
00335                 flat_enc_s = null;
00336             } else {
00337                 if ( cct_parent_s instanceof CallSiteScope ) {
00338                     // ----------------------------------------------
00339                     // parent is a call site
00340                     // ----------------------------------------------
00341                     ProcedureScope proc_cct_s = ((CallSiteScope)cct_parent_s).getProcedureScope(); 
00342                     FlatScopeInfo flat_enc_info = this.getFlatScope(proc_cct_s);
00343                     flat_enc_s = flat_enc_info.flat_s;
00344 
00345                 } else {                    
00346                     // ----------------------------------------------
00347                     // parent is a line scope or loop scope or procedure scope
00348                     // ----------------------------------------------
00349                     FlatScopeInfo flat_enc_info = this.getFlatScope(cct_parent_s);
00350                     flat_enc_s = flat_enc_info.flat_s;
00351                 }
00352 
00353             }
00354         }
00355 
00356         FlatScopeInfo objFlat = this.getFlatScope(cct_s);
00357 
00358         if (flat_enc_s != null)
00359             this.addToTree(flat_enc_s, objFlat.flat_s);
00360 
00361         this.addCostIfNecessary(id, objFlat.flat_s, cct_s_metrics, true, true);
00362         return objFlat;
00363         
00364     }
00365     
00366     
00367     /***********************************************************
00368      * Retrieve the ID given a scope
00369      * a flat ID is the name of the class class concatenated by its hashcode
00370      * This is to force to have different ID for different classes
00371      * @param scope
00372      * @return
00373      ***********************************************************/
00374     private String getID( Scope scope ) {
00375         int id = scope.hashCode();
00376         String hash_id = scope.getClass().getSimpleName();
00377         if (hash_id != null) {
00378             hash_id = hash_id.substring(0, 2) + id;
00379         } else {
00380             hash_id = String.valueOf(id);
00381         }
00382         return hash_id;
00383     }
00384     
00385     
00386     /***********************************************************
00387      * Add a child as the subscope of a parent
00388      * @param parent
00389      * @param child
00390      ***********************************************************/
00391     private void addToTree( Scope parent, Scope child ) {
00392         int nkids = parent.getSubscopeCount();
00393         
00394         //-------------------------------------------------------------------------------
00395         // search for the existing kids. If the kid is already added, then we don't need
00396         //  to add it again
00397         //-------------------------------------------------------------------------------
00398         for (int i=0; i<nkids; i++) {
00399             Scope kid = parent.getSubscope(i);
00400             if ( this.isTheSameScope(kid, child) )
00401                 return;
00402         }
00403         this.addChild(parent, child);
00404     }
00405     
00406 
00407     /***********************************************************
00408      * check if two scopes have the same "content"
00409      * @param s1
00410      * @param s2
00411      * @return
00412      ***********************************************************/
00413     private boolean isTheSameScope(Scope s1, Scope s2) {
00414         
00415         // are s1 and s2 the same class ?
00416         if ( s1.getClass() != s2.getClass() )
00417             return false;
00418         
00419         return (s1.hashCode() == s2.hashCode());
00420     }
00421     
00422     
00423     /***********************************************************
00424      * add a child to the parent
00425      * @param parent
00426      * @param child
00427      ***********************************************************/
00428     private void addChild(Scope parent, Scope child) {
00429         if (parent.hashCode() == child.hashCode()) 
00430             System.err.println("ERROR: Same ID "+parent.hashCode()+": "+parent + " - " + child);
00431         parent.addSubscope(child);
00432         child.setParentScope(parent);
00433     }
00434     
00435     
00436     /***********************************************************
00437      * Iteratively finding an enclosing procedure of a CCT scope
00438      * @param cct_s
00439      * @return
00440      ***********************************************************/
00441     private ProcedureScope findEnclosingProcedure(Scope cct_s)
00442     {
00443         if (cct_s instanceof ProcedureScope) 
00444             return (ProcedureScope) cct_s;
00445         Scope parent = cct_s.getParentScope();
00446         while(parent != null) {
00447             if (parent instanceof CallSiteScope) {
00448                 ProcedureScope proc = ((CallSiteScope) parent).getProcedureScope();
00449                 if (!proc.isAlien()) return proc;
00450             }
00451             if (parent instanceof ProcedureScope) {
00452                 ProcedureScope proc = (ProcedureScope) parent;
00453                 if (!proc.isAlien()) return proc;
00454             }
00455             if (parent instanceof RootScope) return null;
00456             parent = parent.getParentScope();
00457         }
00458         return null;
00459     }
00460 
00461     
00462     /***********************************************************
00463      * check if a scope has been assigned as the outermost instance
00464      * @param scope
00465      * @return
00466      ***********************************************************/
00467     private boolean isOutermostInstance(Scope scope) {
00468         return scope.getCounter() == 1;
00469     }
00470 
00471     
00472     /***********************************************************
00473      * add the cost of the cct into the flat scope if "necessary"
00474      * Necessary means: add the inclusive cost if the cct scope if the outermost scope
00475      * @param flat_s
00476      * @param cct_s
00477      ***********************************************************/
00478     private void addCostIfNecessary( String objCode, Scope flat_s, Scope cct_s, boolean add_inclusive, boolean add_exclusive ) {
00479         if (flat_s == null)
00480             return;
00481         
00482         flat_s.incrementCounter();
00483             
00484         if (isOutermostInstance(flat_s)) {
00485             if (add_inclusive)
00486                 flat_s.combine(cct_s, inclusive_filter);
00487         }
00488         if (add_exclusive)
00489             flat_s.combine(cct_s, exclusive_filter);
00490 
00491         //-----------------------------------------------------------------------
00492         // store the flat scopes that have been updated  
00493         //-----------------------------------------------------------------------
00494         Scope arr_new_scopes[]; 
00495         Scope scope_added[] = htFlatCostAdded.get( objCode );
00496         if (scope_added != null) {
00497             int nb_scopes = scope_added.length;
00498             arr_new_scopes = new Scope[nb_scopes+1];
00499             System.arraycopy(scope_added, 0, arr_new_scopes, 0, nb_scopes);
00500             arr_new_scopes[nb_scopes] = flat_s;
00501         } else {
00502             arr_new_scopes = new Scope[1];
00503             arr_new_scopes[0] = flat_s;
00504         }
00505         htFlatCostAdded.put(objCode, arr_new_scopes);
00506 
00507     }
00508     //int iline = 0; 
00509 
00510     
00511     /*************************************************************************
00512      * Each scope in the flat view has to be linked with 3 enclosing scopes:
00513      * - load module
00514      * - file
00515      * - procedure
00516      * @author laksonoadhianto
00517      *************************************************************************/
00518     private class FlatScopeInfo {
00519         LoadModuleScope flat_lm;
00520         FileScope flat_file;
00521         Scope flat_s;
00522     }
00523 }

Generated on 5 May 2015 for HPCVIEWER by  doxygen 1.6.1