8060215: per-method PrintIdealGraphLevel

Use CompileCommand=option to set PrintIdealGraphLevel on a per-method level. Introduce the PrintIdealGraph develop to control/check if printing the graph is enabled for any method

Reviewed-by: kvn, dlong, thartmann
diff --git a/hotspot/src/share/vm/opto/c2_globals.hpp b/hotspot/src/share/vm/opto/c2_globals.hpp
index 31cdc6d..4c7c92a 100644
--- a/hotspot/src/share/vm/opto/c2_globals.hpp
+++ b/hotspot/src/share/vm/opto/c2_globals.hpp
@@ -343,10 +343,16 @@
   product(bool, UseRDPCForConstantTableBase, false,                         \
           "Use Sparc RDPC instruction for the constant table base.")        \
                                                                             \
-  develop(intx, PrintIdealGraphLevel, 0,                                    \
+  develop(bool, PrintIdealGraph, false,                                     \
           "Print ideal graph to XML file / network interface. "             \
           "By default attempts to connect to the visualizer on a socket.")  \
                                                                             \
+  develop(intx, PrintIdealGraphLevel, 0,                                    \
+          "Level of detail of the ideal graph printout. "                   \
+          "System-wide value, 0=nothing is printed, 3=all details printed. "\
+          "Level of detail of printouts can be set on a per-method level "  \
+          "as well by using CompileCommand=option.")                        \
+                                                                            \
   develop(intx, PrintIdealGraphPort, 4444,                                  \
           "Ideal graph printer to network port")                            \
                                                                             \
diff --git a/hotspot/src/share/vm/opto/compile.cpp b/hotspot/src/share/vm/opto/compile.cpp
index 0163dce..6304ff2 100644
--- a/hotspot/src/share/vm/opto/compile.cpp
+++ b/hotspot/src/share/vm/opto/compile.cpp
@@ -827,7 +827,7 @@
   // Drain the list.
   Finish_Warm();
 #ifndef PRODUCT
-  if (_printer) {
+  if (_printer && _printer->should_print(_method)) {
     _printer->print_inlining(this);
   }
 #endif
diff --git a/hotspot/src/share/vm/opto/compile.hpp b/hotspot/src/share/vm/opto/compile.hpp
index 2ac0232..137ba6b 100644
--- a/hotspot/src/share/vm/opto/compile.hpp
+++ b/hotspot/src/share/vm/opto/compile.hpp
@@ -622,7 +622,9 @@
 
   void begin_method() {
 #ifndef PRODUCT
-    if (_printer) _printer->begin_method(this);
+    if (_printer && _printer->should_print(_method)) {
+      _printer->begin_method(this);
+    }
 #endif
     C->_latest_stage_start_counter.stamp();
   }
@@ -639,7 +641,9 @@
 
 
 #ifndef PRODUCT
-    if (_printer) _printer->print_method(this, CompilerPhaseTypeHelper::to_string(cpt), level);
+    if (_printer && _printer->should_print(_method)) {
+      _printer->print_method(this, CompilerPhaseTypeHelper::to_string(cpt), level);
+    }
 #endif
     C->_latest_stage_start_counter.stamp();
   }
@@ -654,7 +658,9 @@
       event.commit();
     }
 #ifndef PRODUCT
-    if (_printer) _printer->end_method();
+    if (_printer && _printer->should_print(_method)) {
+      _printer->end_method();
+    }
 #endif
   }
 
diff --git a/hotspot/src/share/vm/opto/idealGraphPrinter.cpp b/hotspot/src/share/vm/opto/idealGraphPrinter.cpp
index b222526..ade4cde 100644
--- a/hotspot/src/share/vm/opto/idealGraphPrinter.cpp
+++ b/hotspot/src/share/vm/opto/idealGraphPrinter.cpp
@@ -73,7 +73,9 @@
 int IdealGraphPrinter::_file_count = 0;
 
 IdealGraphPrinter *IdealGraphPrinter::printer() {
-  if (PrintIdealGraphLevel == 0) return NULL;
+  if (!PrintIdealGraph) {
+    return NULL;
+  }
 
   JavaThread *thread = JavaThread::current();
   if (!thread->is_Compiler_thread()) return NULL;
@@ -193,7 +195,6 @@
   }
 }
 
-
 void IdealGraphPrinter::begin_elem(const char *s) {
   _xml->begin_elem("%s", s);
 }
@@ -680,7 +681,7 @@
 // Print current ideal graph
 void IdealGraphPrinter::print(Compile* compile, const char *name, Node *node, int level, bool clear_nodes) {
 
-  if (!_current_method || !_should_send_method || level > PrintIdealGraphLevel) return;
+  if (!_current_method || !_should_send_method || !should_print(_current_method, level)) return;
 
   this->C = compile;
 
@@ -732,6 +733,13 @@
   output()->flush();
 }
 
+// Should method be printed?
+bool IdealGraphPrinter::should_print(ciMethod* method, int level) {
+  intx ideal_graph_level = PrintIdealGraphLevel;
+  method->has_option_value("PrintIdealGraphLevel", ideal_graph_level); // update value with per-method value (if available)
+  return ideal_graph_level >= level;
+}
+
 extern const char *NodeClassNames[];
 
 outputStream *IdealGraphPrinter::output() {
diff --git a/hotspot/src/share/vm/opto/idealGraphPrinter.hpp b/hotspot/src/share/vm/opto/idealGraphPrinter.hpp
index f2892d5..c8622a1 100644
--- a/hotspot/src/share/vm/opto/idealGraphPrinter.hpp
+++ b/hotspot/src/share/vm/opto/idealGraphPrinter.hpp
@@ -134,6 +134,7 @@
   void print_method(Compile* compile, const char *name, int level=1, bool clear_nodes = false);
   void print(Compile* compile, const char *name, Node *root, int level=1, bool clear_nodes = false);
   void print_xml(const char *name);
+  static bool should_print(ciMethod* method, int level = 1);
 };
 
 #endif
diff --git a/hotspot/src/share/vm/opto/parse2.cpp b/hotspot/src/share/vm/opto/parse2.cpp
index 7ed28ea..8a319f8 100644
--- a/hotspot/src/share/vm/opto/parse2.cpp
+++ b/hotspot/src/share/vm/opto/parse2.cpp
@@ -2344,7 +2344,7 @@
 
 #ifndef PRODUCT
   IdealGraphPrinter *printer = IdealGraphPrinter::printer();
-  if(printer) {
+  if (printer && printer->should_print(_method)) {
     char buffer[256];
     sprintf(buffer, "Bytecode %d: %s", bci(), Bytecodes::name(bc()));
     bool old = printer->traverse_outs();
diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp
index 7f0399b..e8ea4d3 100644
--- a/hotspot/src/share/vm/runtime/arguments.cpp
+++ b/hotspot/src/share/vm/runtime/arguments.cpp
@@ -3922,6 +3922,15 @@
         "Incompatible compilation policy selected", NULL);
     }
   }
+
+#ifdef COMPILER2
+#ifndef PRODUCT
+  if (PrintIdealGraphLevel > 0) {
+    FLAG_SET_ERGO(bool, PrintIdealGraph, true);
+  }
+#endif
+#endif
+
   // Set NmethodSweepFraction after the size of the code cache is adapted (in case of tiered)
   if (FLAG_IS_DEFAULT(NmethodSweepFraction)) {
     FLAG_SET_DEFAULT(NmethodSweepFraction, 1 + ReservedCodeCacheSize / (16 * M));