| /* |
| * Copyright (c) 2011, 2012, 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. |
| * |
| */ |
| |
| #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1ERGOVERBOSE_HPP |
| #define SHARE_VM_GC_IMPLEMENTATION_G1_G1ERGOVERBOSE_HPP |
| |
| #include "memory/allocation.hpp" |
| #include "utilities/debug.hpp" |
| |
| // The log of G1's heuristic decisions comprises of a series of |
| // records which have a similar format in order to maintain |
| // consistency across records and ultimately easier parsing of the |
| // output, if we ever choose to do that. Each record consists of: |
| // * A time stamp to be able to easily correlate each record with |
| // other events. |
| // * A unique string to allow us to easily identify such records. |
| // * The name of the heuristic the record corresponds to. |
| // * An action string which describes the action that G1 did or is |
| // about to do. |
| // * An optional reason string which describes the reason for the |
| // action. |
| // * An optional number of name/value pairs which contributed to the |
| // decision to take the action described in the record. |
| // |
| // Each record is associated with a "tag" which is the combination of |
| // the heuristic the record corresponds to, as well as the min level |
| // of verboseness at which the record should be printed. The tag is |
| // checked against the current settings to determine whether the record |
| // should be printed or not. |
| |
| // The available verboseness levels. |
| typedef enum { |
| // Determine which part of the tag is occupied by the level. |
| ErgoLevelShift = 8, |
| ErgoLevelMask = ~((1 << ErgoLevelShift) - 1), |
| |
| // ErgoLow is 0 so that we don't have to explicitly or a heuristic |
| // id with ErgoLow to keep its use simpler. |
| ErgoLow = 0, |
| ErgoHigh = 1 << ErgoLevelShift |
| } ErgoLevel; |
| |
| // The available heuristics. |
| typedef enum { |
| // Determines which part of the tag is occupied by the heuristic id. |
| ErgoHeuristicMask = ~ErgoLevelMask, |
| |
| ErgoHeapSizing = 0, |
| ErgoCSetConstruction, |
| ErgoConcCycles, |
| ErgoMixedGCs, |
| |
| ErgoHeuristicNum |
| } ErgoHeuristic; |
| |
| class G1ErgoVerbose : AllStatic { |
| private: |
| // Determines the minimum verboseness level at which records will be |
| // printed. |
| static ErgoLevel _level; |
| // Determines which heuristics are currently enabled. |
| static bool _enabled[ErgoHeuristicNum]; |
| |
| static ErgoLevel extract_level(int tag) { |
| return (ErgoLevel) (tag & ErgoLevelMask); |
| } |
| |
| static ErgoHeuristic extract_heuristic(int tag) { |
| return (ErgoHeuristic) (tag & ErgoHeuristicMask); |
| } |
| |
| public: |
| // Needs to be explicitly called at GC initialization. |
| static void initialize(); |
| |
| static void set_level(ErgoLevel level); |
| static void set_enabled(ErgoHeuristic h, bool enabled); |
| // It is applied to all heuristics. |
| static void set_enabled(bool enabled); |
| |
| static bool enabled(int tag) { |
| ErgoLevel level = extract_level(tag); |
| ErgoHeuristic n = extract_heuristic(tag); |
| return level <= _level && _enabled[n]; |
| } |
| |
| // Extract the heuristic id from the tag and return a string with |
| // its name. |
| static const char* to_string(int tag); |
| }; |
| |
| // The macros below generate the format string for values of different |
| // types and/or metrics. |
| |
| // The reason for the action is optional and is handled specially: the |
| // reason string is concatenated here so it's not necessary to pass it |
| // as a parameter. |
| #define ergo_format_reason(_reason_) ", reason: " _reason_ |
| |
| // Single parameter format strings |
| #define ergo_format_str(_name_) ", " _name_ ": %s" |
| #define ergo_format_region(_name_) ", " _name_ ": %u regions" |
| #define ergo_format_byte(_name_) ", " _name_ ": "SIZE_FORMAT" bytes" |
| #define ergo_format_double(_name_) ", " _name_ ": %1.2f" |
| #define ergo_format_perc(_name_) ", " _name_ ": %1.2f %%" |
| #define ergo_format_ms(_name_) ", " _name_ ": %1.2f ms" |
| #define ergo_format_size(_name_) ", " _name_ ": "SIZE_FORMAT |
| |
| // Double parameter format strings |
| #define ergo_format_byte_perc(_name_) \ |
| ", " _name_ ": "SIZE_FORMAT" bytes (%1.2f %%)" |
| |
| // Generates the format string |
| #define ergo_format(_extra_format_) \ |
| " %1.3f: [G1Ergonomics (%s) %s" _extra_format_ "]" |
| |
| // Conditionally, prints an ergonomic decision record. _extra_format_ |
| // is the format string for the optional items we'd like to print |
| // (i.e., the decision's reason and any associated values). This |
| // string should be built up using the ergo_*_format macros (see |
| // above) to ensure consistency. |
| // |
| // Since we cannot rely on the compiler supporting variable argument |
| // macros, this macro accepts a fixed number of arguments and passes |
| // them to the print method. For convenience, we have wrapper macros |
| // below which take a specific number of arguments and set the rest to |
| // a default value. |
| #define ergo_verbose_common(_tag_, _action_, _extra_format_, \ |
| _arg0_, _arg1_, _arg2_, _arg3_, _arg4_, _arg5_) \ |
| do { \ |
| if (G1ErgoVerbose::enabled((_tag_))) { \ |
| gclog_or_tty->print_cr(ergo_format(_extra_format_), \ |
| os::elapsedTime(), \ |
| G1ErgoVerbose::to_string((_tag_)), \ |
| (_action_), \ |
| (_arg0_), (_arg1_), (_arg2_), \ |
| (_arg3_), (_arg4_), (_arg5_)); \ |
| } \ |
| } while (0) |
| |
| |
| #define ergo_verbose(_tag_, _action_) \ |
| ergo_verbose_common(_tag_, _action_, "", 0, 0, 0, 0, 0, 0) |
| |
| #define ergo_verbose0(_tag_, _action_, _extra_format_) \ |
| ergo_verbose_common(_tag_, _action_, _extra_format_, 0, 0, 0, 0, 0, 0) |
| |
| #define ergo_verbose1(_tag_, _action_, _extra_format_, \ |
| _arg0_) \ |
| ergo_verbose_common(_tag_, _action_, _extra_format_, \ |
| _arg0_, 0, 0, 0, 0, 0) |
| |
| #define ergo_verbose2(_tag_, _action_, _extra_format_, \ |
| _arg0_, _arg1_) \ |
| ergo_verbose_common(_tag_, _action_, _extra_format_, \ |
| _arg0_, _arg1_, 0, 0, 0, 0) |
| |
| #define ergo_verbose3(_tag_, _action_, _extra_format_, \ |
| _arg0_, _arg1_, _arg2_) \ |
| ergo_verbose_common(_tag_, _action_, _extra_format_, \ |
| _arg0_, _arg1_, _arg2_, 0, 0, 0) |
| |
| #define ergo_verbose4(_tag_, _action_, _extra_format_, \ |
| _arg0_, _arg1_, _arg2_, _arg3_) \ |
| ergo_verbose_common(_tag_, _action_, _extra_format_, \ |
| _arg0_, _arg1_, _arg2_, _arg3_, 0, 0) |
| |
| #define ergo_verbose5(_tag_, _action_, _extra_format_, \ |
| _arg0_, _arg1_, _arg2_, _arg3_, _arg4_) \ |
| ergo_verbose_common(_tag_, _action_, _extra_format_, \ |
| _arg0_, _arg1_, _arg2_, _arg3_, _arg4_, 0) |
| |
| #define ergo_verbose6(_tag_, _action_, _extra_format_, \ |
| _arg0_, _arg1_, _arg2_, _arg3_, _arg4_, _arg5_) \ |
| ergo_verbose_common(_tag_, _action_, _extra_format_, \ |
| _arg0_, _arg1_, _arg2_, _arg3_, _arg4_, _arg5_) |
| |
| #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1ERGOVERBOSE_HPP |