8139564: Convert TraceDefaultMethods to Unified Logging
authorrprotacio
Fri, 30 Oct 2015 16:39:37 -0400
changeset 33736 1b3950243443
parent 33735 b6b92fae32c0
child 33737 a1bd57411686
8139564: Convert TraceDefaultMethods to Unified Logging Summary: The former -XX:+TraceDefaultMethods flag is updated to the unified logging framework and is now replaced with -Xlog:defaultmethods. Reviewed-by: acorn, coleenp, hseigel
hotspot/src/share/vm/classfile/defaultMethods.cpp
hotspot/src/share/vm/logging/logTag.hpp
hotspot/src/share/vm/runtime/globals.hpp
hotspot/src/share/vm/utilities/ostream.cpp
hotspot/test/runtime/logging/DefaultMethodsTest.java
--- a/hotspot/src/share/vm/classfile/defaultMethods.cpp	Fri Oct 30 08:29:19 2015 -0700
+++ b/hotspot/src/share/vm/classfile/defaultMethods.cpp	Fri Oct 30 16:39:37 2015 -0400
@@ -26,6 +26,7 @@
 #include "classfile/bytecodeAssembler.hpp"
 #include "classfile/defaultMethods.hpp"
 #include "classfile/symbolTable.hpp"
+#include "logging/log.hpp"
 #include "memory/allocation.hpp"
 #include "memory/metadataFactory.hpp"
 #include "memory/resourceArea.hpp"
@@ -74,7 +75,6 @@
   }
 };
 
-#ifndef PRODUCT
 static void print_slot(outputStream* str, Symbol* name, Symbol* signature) {
   ResourceMark rm;
   str->print("%s%s", name->as_C_string(), signature->as_C_string());
@@ -87,7 +87,6 @@
   }
   print_slot(str, mo->name(), mo->signature());
 }
-#endif // ndef PRODUCT
 
 /**
  * Perform a depth-first iteration over the class hierarchy, applying
@@ -246,21 +245,22 @@
   }
 };
 
-#ifndef PRODUCT
 class PrintHierarchy : public HierarchyVisitor<PrintHierarchy> {
+ private:
+   outputStream* _st;
  public:
-
   bool visit() {
     InstanceKlass* cls = current_class();
-    streamIndentor si(tty, current_depth() * 2);
-    tty->indent().print_cr("%s", cls->name()->as_C_string());
+    streamIndentor si(_st, current_depth() * 2);
+    _st->indent().print_cr("%s", cls->name()->as_C_string());
     return true;
   }
 
   void* new_node_data(InstanceKlass* cls) { return NULL; }
   void free_node_data(void* data) { return; }
+
+  PrintHierarchy(outputStream* st = tty) : _st(st) {}
 };
-#endif // ndef PRODUCT
 
 // Used to register InstanceKlass objects and all related metadata structures
 // (Methods, ConstantPools) as "in-use" by the current thread so that they can't
@@ -434,9 +434,11 @@
     } else if (num_defaults > 1) {
       _exception_message = generate_conflicts_message(&qualified_methods,CHECK);
       _exception_name = vmSymbols::java_lang_IncompatibleClassChangeError();
-      if (TraceDefaultMethods) {
-        _exception_message->print_value_on(tty);
-        tty->cr();
+      if (log_is_enabled(Debug, defaultmethods)) {
+        ResourceMark rm;
+        outputStream* logstream = LogHandle(defaultmethods)::debug_stream();
+        _exception_message->print_value_on(logstream);
+        logstream->cr();
       }
     }
   }
@@ -450,27 +452,6 @@
     return false;
   }
 
-#ifndef PRODUCT
-  void print_sig_on(outputStream* str, Symbol* signature, int indent) const {
-    streamIndentor si(str, indent * 2);
-
-    str->indent().print_cr("Logical Method %s:", signature->as_C_string());
-
-    streamIndentor si2(str);
-    for (int i = 0; i < _members.length(); ++i) {
-      str->indent();
-      print_method(str, _members.at(i).first);
-      if (_members.at(i).second == DISQUALIFIED) {
-        str->print(" (disqualified)");
-      }
-      str->cr();
-    }
-
-    if (_selected_target != NULL) {
-      print_selected(str, 1);
-    }
-  }
-
   void print_selected(outputStream* str, int indent) const {
     assert(has_target(), "Should be called otherwise");
     streamIndentor si(str, indent * 2);
@@ -478,7 +459,7 @@
     print_method(str, _selected_target);
     Klass* method_holder = _selected_target->method_holder();
     if (!method_holder->is_interface()) {
-      tty->print(" : in superclass");
+      str->print(" : in superclass");
     }
     str->cr();
   }
@@ -489,7 +470,6 @@
     streamIndentor si(str, indent * 2);
     str->indent().print_cr("%s: %s", _exception_name->as_C_string(), _exception_message->as_C_string());
   }
-#endif // ndef PRODUCT
 };
 
 Symbol* MethodFamily::generate_no_defaults_message(TRAPS) const {
@@ -608,11 +588,9 @@
   bool is_bound() { return _binding != NULL; }
   MethodFamily* get_binding() { return _binding; }
 
-#ifndef PRODUCT
   void print_on(outputStream* str) const {
     print_slot(str, name(), signature());
   }
-#endif // ndef PRODUCT
 };
 
 static bool already_in_vtable_slots(GrowableArray<EmptyVtableSlot*>* slots, Method* m) {
@@ -681,17 +659,18 @@
     super = super->java_super();
   }
 
-#ifndef PRODUCT
-  if (TraceDefaultMethods) {
-    tty->print_cr("Slots that need filling:");
-    streamIndentor si(tty);
+  if (log_is_enabled(Debug, defaultmethods)) {
+    log_debug(defaultmethods)("Slots that need filling:");
+    ResourceMark rm;
+    outputStream* logstream = LogHandle(defaultmethods)::debug_stream();
+    streamIndentor si(logstream);
     for (int i = 0; i < slots->length(); ++i) {
-      tty->indent();
-      slots->at(i)->print_on(tty);
-      tty->cr();
+      logstream->indent();
+      slots->at(i)->print_on(logstream);
+      logstream->cr();
     }
   }
-#endif // ndef PRODUCT
+
   return slots;
 }
 
@@ -812,46 +791,32 @@
   KeepAliveVisitor loadKeepAlive(&keepAlive);
   loadKeepAlive.run(klass);
 
-#ifndef PRODUCT
-  if (TraceDefaultMethods) {
-    ResourceMark rm;  // be careful with these!
-    tty->print_cr("%s %s requires default method processing",
-        klass->is_interface() ? "Interface" : "Class",
-        klass->name()->as_klass_external_name());
-    PrintHierarchy printer;
+  if (log_is_enabled(Debug, defaultmethods)) {
+    ResourceMark rm;
+    log_debug(defaultmethods)("%s %s requires default method processing",
+                              klass->is_interface() ? "Interface" : "Class",
+                              klass->name()->as_klass_external_name());
+    PrintHierarchy printer(LogHandle(defaultmethods)::debug_stream());
     printer.run(klass);
   }
-#endif // ndef PRODUCT
 
   GrowableArray<EmptyVtableSlot*>* empty_slots =
       find_empty_vtable_slots(klass, mirandas, CHECK);
 
   for (int i = 0; i < empty_slots->length(); ++i) {
     EmptyVtableSlot* slot = empty_slots->at(i);
-#ifndef PRODUCT
-    if (TraceDefaultMethods) {
-      streamIndentor si(tty, 2);
-      tty->indent().print("Looking for default methods for slot ");
-      slot->print_on(tty);
-      tty->cr();
+    if (log_is_enabled(Debug, defaultmethods)) {
+      outputStream* logstream = LogHandle(defaultmethods)::debug_stream();
+      streamIndentor si(logstream, 2);
+      logstream->indent().print("Looking for default methods for slot ");
+      slot->print_on(logstream);
+      logstream->cr();
     }
-#endif // ndef PRODUCT
-
     generate_erased_defaults(klass, empty_slots, slot, CHECK);
- }
-#ifndef PRODUCT
-  if (TraceDefaultMethods) {
-    tty->print_cr("Creating defaults and overpasses...");
   }
-#endif // ndef PRODUCT
-
+  log_debug(defaultmethods)("Creating defaults and overpasses...");
   create_defaults_and_exceptions(empty_slots, klass, CHECK);
-
-#ifndef PRODUCT
-  if (TraceDefaultMethods) {
-    tty->print_cr("Default method processing complete");
-  }
-#endif // ndef PRODUCT
+  log_debug(defaultmethods)("Default method processing complete");
 }
 
 static int assemble_method_error(
@@ -947,18 +912,18 @@
       MethodFamily* method = slot->get_binding();
       BytecodeBuffer buffer;
 
-#ifndef PRODUCT
-      if (TraceDefaultMethods) {
-        tty->print("for slot: ");
-        slot->print_on(tty);
-        tty->cr();
+      if (log_is_enabled(Debug, defaultmethods)) {
+        ResourceMark rm;
+        outputStream* logstream = LogHandle(defaultmethods)::debug_stream();
+        logstream->print("for slot: ");
+        slot->print_on(logstream);
+        logstream->cr();
         if (method->has_target()) {
-          method->print_selected(tty, 1);
+          method->print_selected(logstream, 1);
         } else if (method->throws_exception()) {
-          method->print_exception(tty, 1);
+          method->print_exception(logstream, 1);
         }
       }
-#endif // ndef PRODUCT
 
       if (method->has_target()) {
         Method* selected = method->get_selected_target();
@@ -982,12 +947,9 @@
     }
   }
 
-#ifndef PRODUCT
-  if (TraceDefaultMethods) {
-    tty->print_cr("Created %d overpass methods", overpasses.length());
-    tty->print_cr("Created %d default  methods", defaults.length());
-  }
-#endif // ndef PRODUCT
+
+  log_debug(defaultmethods)("Created %d overpass methods", overpasses.length());
+  log_debug(defaultmethods)("Created %d default  methods", defaults.length());
 
   if (overpasses.length() > 0) {
     switchover_constant_pool(&bpool, klass, &overpasses, CHECK);
--- a/hotspot/src/share/vm/logging/logTag.hpp	Fri Oct 30 08:29:19 2015 -0700
+++ b/hotspot/src/share/vm/logging/logTag.hpp	Fri Oct 30 16:39:37 2015 -0400
@@ -31,6 +31,7 @@
 // (The tags 'all', 'disable' and 'help' are special tags that can
 // not be used in log calls, and should not be listed below.)
 #define LOG_TAG_LIST \
+  LOG_TAG(defaultmethods) \
   LOG_TAG(logging)
 
 #define PREFIX_LOG_TAG(T) (LogTag::T)
--- a/hotspot/src/share/vm/runtime/globals.hpp	Fri Oct 30 08:29:19 2015 -0700
+++ b/hotspot/src/share/vm/runtime/globals.hpp	Fri Oct 30 16:39:37 2015 -0400
@@ -4194,9 +4194,6 @@
   diagnostic(bool, StringDeduplicationRehashALot, false,                    \
           "Force table rehash every time the table is scanned")             \
                                                                             \
-  develop(bool, TraceDefaultMethods, false,                                 \
-          "Trace the default method processing steps")                      \
-                                                                            \
   diagnostic(bool, WhiteBoxAPI, false,                                      \
           "Enable internal testing APIs")                                   \
                                                                             \
--- a/hotspot/src/share/vm/utilities/ostream.cpp	Fri Oct 30 08:29:19 2015 -0700
+++ b/hotspot/src/share/vm/utilities/ostream.cpp	Fri Oct 30 16:39:37 2015 -0400
@@ -1449,6 +1449,6 @@
     _current_line.reset();
   } else {
     _current_line.write(s, len);
-    update_position(s, len);
   }
+  update_position(s, len);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/logging/DefaultMethodsTest.java	Fri Oct 30 16:39:37 2015 -0400
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.    See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8139564
+ * @summary defaultmethods=debug should have logging from each of the statements in the code
+ * @library /testlibrary
+ * @modules java.base/sun.misc
+ *          java.management
+ * @run main DefaultMethodsTest
+ */
+
+import jdk.test.lib.*;
+
+public class DefaultMethodsTest {
+    public static void main(String[] args) throws Exception {
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+            "-Xlog:defaultmethods=debug", "-version");
+        OutputAnalyzer output = new OutputAnalyzer(pb.start());
+        output.shouldContain("Slots that need filling:");
+        output.shouldContain("requires default method processing");
+        output.shouldContain("Looking for default methods for slot ");
+        output.shouldContain("Creating defaults and overpasses...");
+        output.shouldContain("for slot: ");
+        output.shouldContain("Default method processing complete");
+        output.shouldContain("overpass methods");
+        output.shouldContain("default methods");
+        output.shouldHaveExitValue(0);
+    }
+}
+