# HG changeset patch # User rprotacio # Date 1446237577 14400 # Node ID 1b39502434438c3b34b3bbde5e8f6d030eb9868f # Parent b6b92fae32c0fdfef4b607c0b4cd1c712bb0bda8 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 diff -r b6b92fae32c0 -r 1b3950243443 hotspot/src/share/vm/classfile/defaultMethods.cpp --- 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 { + 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* 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* 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); diff -r b6b92fae32c0 -r 1b3950243443 hotspot/src/share/vm/logging/logTag.hpp --- 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) diff -r b6b92fae32c0 -r 1b3950243443 hotspot/src/share/vm/runtime/globals.hpp --- 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") \ \ diff -r b6b92fae32c0 -r 1b3950243443 hotspot/src/share/vm/utilities/ostream.cpp --- 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); } diff -r b6b92fae32c0 -r 1b3950243443 hotspot/test/runtime/logging/DefaultMethodsTest.java --- /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); + } +} +