#include "AST.h" #include "compiler.h" #include "optimize-monitors.h" struct MonitorStats { unsigned unchanged; unsigned simplified; unsigned eliminated; // If PR #327 ever gets fixed, remove the "eliminated" field MonitorStats() : unchanged( 0 ), simplified( 0 ), eliminated( 0 ) { } }; bool opt_monitors = false; // DOB: off by default because it's unsafe bool stat_monitors = false; //////////////////////////////////////////////////////////////////////// // // some monitors can never be contested // bool MonitorFetchClassNode::superfluous() const { // If PR #327 ever gets fixed, change this to "false". return true; } bool MonitorFetchInstanceNode::superfluous() const { const TypeNode &exprType = *expr()->type(); return exprType.isLocal() && exprType.sharing() == Nonshared; } bool MonitorUseNode::superfluous() const { return fetcher()->superfluous(); } //////////////////////////////////////////////////////////////////////// // // eliminate superfluous monitor operations // TreeNode *MonitorFetchClassNode::optimizeMonitors( MonitorStats &stats ) { // If PR #327 ever gets fixed, remove this method entirely. if (superfluous()) { ++stats.eliminated; return new EmptyStmtNode(); } else { ++stats.unchanged; return TreeNode::optimizeMonitors( stats ); } } TreeNode *MonitorFetchInstanceNode::optimizeMonitors( MonitorStats &stats ) { if (superfluous()) { ++stats.simplified; return new CheckNullNode(expr()); } else { ++stats.unchanged; return TreeNode::optimizeMonitors( stats ); } } TreeNode *MonitorUseNode::optimizeMonitors( MonitorStats &stats ) { return superfluous() ? new EmptyStmtNode() : TreeNode::optimizeMonitors( stats ); } //////////////////////////////////////////////////////////////////////// // // generic traversal // TreeNode *ClassDeclNode::optimizeMonitors( MonitorStats &stats ) { return selectedForCodeGen( false ) ? TreeNode::optimizeMonitors( stats ) : this; } TreeNode *CompileUnitNode::optimizeMonitors( MonitorStats &stats ) { return selectedForCodeGen( false ) ? TreeNode::optimizeMonitors( stats ) : this; } TreeNode *TemplateDeclNode::optimizeMonitors( MonitorStats &stats ) { return this; } TreeNode *TreeNode::optimizeMonitors( MonitorStats &stats ) { const int count = arity(); for (int sweep = 0; sweep < count; ++sweep) child( sweep, child(sweep)->optimizeMonitors( stats ) ); return this; } //////////////////////////////////////////////////////////////////////// // // published interface // void optimizeMonitors() { if (opt_monitors) { MonitorStats stats; foreach (file, llist< CompileUnitNode * >, *allFiles) (*file)->optimizeMonitors( stats ); if (stat_monitors) cerr << "monitor optimization statistics: " << stats.eliminated << " eliminated, " << stats.simplified << " simplified, " << stats.unchanged << " unchanged" << endl; } }