tonyp@3114: /* tonyp@3713: * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. tonyp@3114: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. tonyp@3114: * tonyp@3114: * This code is free software; you can redistribute it and/or modify it tonyp@3114: * under the terms of the GNU General Public License version 2 only, as tonyp@3114: * published by the Free Software Foundation. tonyp@3114: * tonyp@3114: * This code is distributed in the hope that it will be useful, but WITHOUT tonyp@3114: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or tonyp@3114: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License tonyp@3114: * version 2 for more details (a copy is included in the LICENSE file that tonyp@3114: * accompanied this code). tonyp@3114: * tonyp@3114: * You should have received a copy of the GNU General Public License version tonyp@3114: * 2 along with this work; if not, write to the Free Software Foundation, tonyp@3114: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. tonyp@3114: * tonyp@3114: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA tonyp@3114: * or visit www.oracle.com if you need additional information or have any tonyp@3114: * questions. tonyp@3114: * tonyp@3114: */ tonyp@3114: tonyp@3114: #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1ERGOVERBOSE_HPP tonyp@3114: #define SHARE_VM_GC_IMPLEMENTATION_G1_G1ERGOVERBOSE_HPP tonyp@3114: tonyp@3114: #include "memory/allocation.hpp" tonyp@3114: #include "utilities/debug.hpp" tonyp@3114: tonyp@3114: // The log of G1's heuristic decisions comprises of a series of tonyp@3114: // records which have a similar format in order to maintain tonyp@3114: // consistency across records and ultimately easier parsing of the tonyp@3114: // output, if we ever choose to do that. Each record consists of: tonyp@3114: // * A time stamp to be able to easily correlate each record with tonyp@3114: // other events. tonyp@3114: // * A unique string to allow us to easily identify such records. tonyp@3114: // * The name of the heuristic the record corresponds to. tonyp@3114: // * An action string which describes the action that G1 did or is tonyp@3114: // about to do. tonyp@3114: // * An optional reason string which describes the reason for the tonyp@3114: // action. tonyp@3114: // * An optional number of name/value pairs which contributed to the tonyp@3114: // decision to take the action described in the record. tonyp@3114: // tonyp@3114: // Each record is associated with a "tag" which is the combination of tonyp@3114: // the heuristic the record corresponds to, as well as the min level tonyp@3114: // of verboseness at which the record should be printed. The tag is tonyp@3114: // checked against the current settings to determine whether the record tonyp@3114: // should be printed or not. tonyp@3114: tonyp@3114: // The available verboseness levels. tonyp@3114: typedef enum { tonyp@3114: // Determine which part of the tag is occupied by the level. tonyp@3114: ErgoLevelShift = 8, tonyp@3114: ErgoLevelMask = ~((1 << ErgoLevelShift) - 1), tonyp@3114: tonyp@3114: // ErgoLow is 0 so that we don't have to explicitly or a heuristic tonyp@3114: // id with ErgoLow to keep its use simpler. tonyp@3114: ErgoLow = 0, tonyp@3126: ErgoHigh = 1 << ErgoLevelShift tonyp@3114: } ErgoLevel; tonyp@3114: tonyp@3114: // The available heuristics. tonyp@3114: typedef enum { tonyp@3114: // Determines which part of the tag is occupied by the heuristic id. tonyp@3114: ErgoHeuristicMask = ~ErgoLevelMask, tonyp@3114: tonyp@3114: ErgoHeapSizing = 0, tonyp@3114: ErgoCSetConstruction, tonyp@3114: ErgoConcCycles, tonyp@3337: ErgoMixedGCs, tonyp@3114: tonyp@3114: ErgoHeuristicNum tonyp@3114: } ErgoHeuristic; tonyp@3114: tonyp@3114: class G1ErgoVerbose : AllStatic { tonyp@3114: private: tonyp@3114: // Determines the minimum verboseness level at which records will be tonyp@3114: // printed. tonyp@3114: static ErgoLevel _level; tonyp@3114: // Determines which heuristics are currently enabled. tonyp@3114: static bool _enabled[ErgoHeuristicNum]; tonyp@3114: tonyp@3114: static ErgoLevel extract_level(int tag) { tonyp@3114: return (ErgoLevel) (tag & ErgoLevelMask); tonyp@3114: } tonyp@3114: tonyp@3114: static ErgoHeuristic extract_heuristic(int tag) { tonyp@3114: return (ErgoHeuristic) (tag & ErgoHeuristicMask); tonyp@3114: } tonyp@3114: tonyp@3114: public: tonyp@3114: // Needs to be explicitly called at GC initialization. tonyp@3114: static void initialize(); tonyp@3114: tonyp@3114: static void set_level(ErgoLevel level); tonyp@3114: static void set_enabled(ErgoHeuristic h, bool enabled); tonyp@3114: // It is applied to all heuristics. tonyp@3114: static void set_enabled(bool enabled); tonyp@3114: tonyp@3114: static bool enabled(int tag) { tonyp@3114: ErgoLevel level = extract_level(tag); tonyp@3114: ErgoHeuristic n = extract_heuristic(tag); tonyp@3114: return level <= _level && _enabled[n]; tonyp@3114: } tonyp@3114: tonyp@3114: // Extract the heuristic id from the tag and return a string with tonyp@3114: // its name. tonyp@3114: static const char* to_string(int tag); tonyp@3114: }; tonyp@3114: tonyp@3114: // The macros below generate the format string for values of different tonyp@3114: // types and/or metrics. tonyp@3114: tonyp@3114: // The reason for the action is optional and is handled specially: the tonyp@3114: // reason string is concatenated here so it's not necessary to pass it tonyp@3114: // as a parameter. tonyp@3114: #define ergo_format_reason(_reason_) ", reason: " _reason_ tonyp@3114: tonyp@3114: // Single parameter format strings tonyp@3114: #define ergo_format_str(_name_) ", " _name_ ": %s" tonyp@3713: #define ergo_format_region(_name_) ", " _name_ ": %u regions" tonyp@3114: #define ergo_format_byte(_name_) ", " _name_ ": "SIZE_FORMAT" bytes" tonyp@3114: #define ergo_format_double(_name_) ", " _name_ ": %1.2f" tonyp@3114: #define ergo_format_perc(_name_) ", " _name_ ": %1.2f %%" tonyp@3114: #define ergo_format_ms(_name_) ", " _name_ ": %1.2f ms" johnc@3998: #define ergo_format_size(_name_) ", " _name_ ": "SIZE_FORMAT tonyp@3114: tonyp@3114: // Double parameter format strings tonyp@3114: #define ergo_format_byte_perc(_name_) \ tonyp@3114: ", " _name_ ": "SIZE_FORMAT" bytes (%1.2f %%)" tonyp@3114: tonyp@3114: // Generates the format string tonyp@3539: #define ergo_format(_extra_format_) \ tonyp@3539: " %1.3f: [G1Ergonomics (%s) %s" _extra_format_ "]" tonyp@3114: tonyp@3114: // Conditionally, prints an ergonomic decision record. _extra_format_ tonyp@3114: // is the format string for the optional items we'd like to print tonyp@3114: // (i.e., the decision's reason and any associated values). This tonyp@3114: // string should be built up using the ergo_*_format macros (see tonyp@3114: // above) to ensure consistency. tonyp@3114: // tonyp@3114: // Since we cannot rely on the compiler supporting variable argument tonyp@3114: // macros, this macro accepts a fixed number of arguments and passes tonyp@3114: // them to the print method. For convenience, we have wrapper macros tonyp@3114: // below which take a specific number of arguments and set the rest to tonyp@3114: // a default value. tonyp@3539: #define ergo_verbose_common(_tag_, _action_, _extra_format_, \ tonyp@3114: _arg0_, _arg1_, _arg2_, _arg3_, _arg4_, _arg5_) \ tonyp@3539: do { \ tonyp@3539: if (G1ErgoVerbose::enabled((_tag_))) { \ tonyp@3539: gclog_or_tty->print_cr(ergo_format(_extra_format_), \ tonyp@3539: os::elapsedTime(), \ tonyp@3539: G1ErgoVerbose::to_string((_tag_)), \ tonyp@3539: (_action_), \ tonyp@3539: (_arg0_), (_arg1_), (_arg2_), \ tonyp@3539: (_arg3_), (_arg4_), (_arg5_)); \ tonyp@3539: } \ tonyp@3114: } while (0) tonyp@3114: tonyp@3114: tonyp@3539: #define ergo_verbose(_tag_, _action_) \ tonyp@3114: ergo_verbose_common(_tag_, _action_, "", 0, 0, 0, 0, 0, 0) tonyp@3114: tonyp@3114: #define ergo_verbose0(_tag_, _action_, _extra_format_) \ tonyp@3114: ergo_verbose_common(_tag_, _action_, _extra_format_, 0, 0, 0, 0, 0, 0) tonyp@3114: tonyp@3114: #define ergo_verbose1(_tag_, _action_, _extra_format_, \ tonyp@3114: _arg0_) \ tonyp@3114: ergo_verbose_common(_tag_, _action_, _extra_format_, \ tonyp@3114: _arg0_, 0, 0, 0, 0, 0) tonyp@3114: tonyp@3114: #define ergo_verbose2(_tag_, _action_, _extra_format_, \ tonyp@3114: _arg0_, _arg1_) \ tonyp@3114: ergo_verbose_common(_tag_, _action_, _extra_format_, \ tonyp@3114: _arg0_, _arg1_, 0, 0, 0, 0) tonyp@3114: tonyp@3114: #define ergo_verbose3(_tag_, _action_, _extra_format_, \ tonyp@3114: _arg0_, _arg1_, _arg2_) \ tonyp@3114: ergo_verbose_common(_tag_, _action_, _extra_format_, \ tonyp@3114: _arg0_, _arg1_, _arg2_, 0, 0, 0) tonyp@3114: tonyp@3114: #define ergo_verbose4(_tag_, _action_, _extra_format_, \ tonyp@3114: _arg0_, _arg1_, _arg2_, _arg3_) \ tonyp@3114: ergo_verbose_common(_tag_, _action_, _extra_format_, \ tonyp@3114: _arg0_, _arg1_, _arg2_, _arg3_, 0, 0) tonyp@3114: tonyp@3114: #define ergo_verbose5(_tag_, _action_, _extra_format_, \ tonyp@3114: _arg0_, _arg1_, _arg2_, _arg3_, _arg4_) \ tonyp@3114: ergo_verbose_common(_tag_, _action_, _extra_format_, \ tonyp@3114: _arg0_, _arg1_, _arg2_, _arg3_, _arg4_, 0) tonyp@3114: tonyp@3114: #define ergo_verbose6(_tag_, _action_, _extra_format_, \ tonyp@3114: _arg0_, _arg1_, _arg2_, _arg3_, _arg4_, _arg5_) \ tonyp@3114: ergo_verbose_common(_tag_, _action_, _extra_format_, \ tonyp@3114: _arg0_, _arg1_, _arg2_, _arg3_, _arg4_, _arg5_) tonyp@3114: tonyp@3114: #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1ERGOVERBOSE_HPP