--- old/src/share/vm/logging/logMessage.hpp 2016-02-16 16:50:51.385004234 +0100 +++ new/src/share/vm/logging/logMessage.hpp 2016-02-16 16:50:51.228338416 +0100 @@ -24,16 +24,10 @@ #ifndef SHARE_VM_LOGGING_LOGMESSAGE_HPP #define SHARE_VM_LOGGING_LOGMESSAGE_HPP +#include "precompiled.hpp" #include "logging/logDecorations.hpp" #include "logging/logLevel.hpp" -#include "logging/logPrefix.hpp" -#include "logging/logTagSet.hpp" -#include "logging/logTag.hpp" #include "memory/allocation.hpp" -#include "runtime/os.hpp" -#include "runtime/thread.hpp" -#include "utilities/debug.hpp" -#include "utilities/ostream.hpp" // The LogMessage class represents a multi-part/multi-line message // that is guaranteed to be sent and written to the log outputs @@ -73,6 +67,7 @@ static const size_t InitialLineCapacity = 10; static const size_t InitialMessageBufferCapacity = 1024; bool _c_heap_allocated; + mutable bool _used; size_t _message_buffer_size; size_t _message_buffer_capacity; @@ -86,20 +81,6 @@ size_t (*_prefix_fn)(char*, size_t); - template - void grow(T*& buffer, size_t& capacity, size_t minimum_length = 0) { - size_t new_size = capacity * 2; - if (new_size < minimum_length) { - new_size = minimum_length; - } - if (_c_heap_allocated) { - buffer = REALLOC_C_HEAP_ARRAY(T, buffer, new_size, mtLogging); - } else { - buffer = REALLOC_RESOURCE_ARRAY(T, buffer, capacity, new_size); - } - capacity = new_size; - } - // Forbid copy assignment and copy constructor. void operator=(const LogMessage& ref) {} LogMessage(const LogMessage& ref) {} @@ -146,37 +127,15 @@ } }; - LogMessage() : _message_buffer_size(0), - _message_buffer_capacity(InitialMessageBufferCapacity), - _line_count(0), - _line_capacity(InitialLineCapacity), - _c_heap_allocated(Thread::current_or_null() == NULL), - _prefix_fn(NULL), - _least_detailed_level(LogLevel::Off) { - if (_c_heap_allocated) { - _lines = NEW_C_HEAP_ARRAY(LogLine, _message_buffer_capacity, mtLogging); - _message_buffer = NEW_C_HEAP_ARRAY(char, InitialMessageBufferCapacity, mtLogging); - } else { - _lines = NEW_RESOURCE_ARRAY(LogLine, _message_buffer_capacity); - _message_buffer = NEW_RESOURCE_ARRAY(char, InitialMessageBufferCapacity); - } - } - - ~LogMessage() { - if (_c_heap_allocated) { - FREE_C_HEAP_ARRAY(LogLine, _lines); - FREE_C_HEAP_ARRAY(char, _message_buffer); - } else { - FREE_RESOURCE_ARRAY(LogLine, _lines, _line_capacity); - FREE_RESOURCE_ARRAY(char, _message_buffer, _message_buffer_capacity); - } - } + LogMessage(); + ~LogMessage(); LogLevelType least_detailed_level() const { return _least_detailed_level; } Iterator iterator(LogLevelType level, LogDecorations& decorations) const { + _used = true; return Iterator(*this, level, decorations); } @@ -191,68 +150,14 @@ } ATTRIBUTE_PRINTF(3, 4) - void write(LogLevelType level, const char* fmt, ...) { - va_list args; - va_start(args, fmt); - vwrite(level, fmt, args); - va_end(args); - }; + void write(LogLevelType level, const char* fmt, ...); ATTRIBUTE_PRINTF(3, 0) - void vwrite(LogLevelType level, const char* fmt, va_list args) { - - if (level > _least_detailed_level) { - _least_detailed_level = level; - } + void vwrite(LogLevelType level, const char* fmt, va_list args); - size_t written; - for (int attempts = 0; attempts < 2; attempts++) { - written = 0; - size_t remaining_buffer_length = _message_buffer_capacity - _message_buffer_size; - char* current_buffer_position = _message_buffer + _message_buffer_size; - if (_prefix_fn != NULL) { - written += _prefix_fn(current_buffer_position, remaining_buffer_length); - current_buffer_position += written; - if (remaining_buffer_length < written) { - remaining_buffer_length = 0; - } else { - remaining_buffer_length -= written; - } - } - va_list copy; - va_copy(copy, args); - written += (size_t)os::log_vsnprintf(current_buffer_position, remaining_buffer_length, fmt, copy) + 1; - va_end(copy); - if (written > _message_buffer_capacity - _message_buffer_size) { - assert(attempts == 0, "Second attempt should always have a sufficiently large buffer (resized to fit)."); - grow(_message_buffer, _message_buffer_capacity, _message_buffer_size + written); - continue; - } - break; - } - - if (_line_count == _line_capacity) { - grow(_lines, _line_capacity); - } - - _lines[_line_count].level = level; - _lines[_line_count].message_offset = _message_buffer_size; - _message_buffer_size += written; - _line_count++; - } - -#define LOG_LEVEL(level, name) ATTRIBUTE_PRINTF(2, 0) \ - LogMessage& v##name(const char* fmt, va_list args) { \ - vwrite(LogLevel::level, fmt, args); \ - return *this; \ - } \ - LogMessage& name(const char* fmt, ...) ATTRIBUTE_PRINTF(2, 3) { \ - va_list args; \ - va_start(args, fmt); \ - vwrite(LogLevel::level, fmt, args); \ - va_end(args); \ - return *this; \ - } +#define LOG_LEVEL(level, name) \ + LogMessage& v##name(const char* fmt, va_list args) ATTRIBUTE_PRINTF(2, 0); \ + LogMessage& name(const char* fmt, ...) ATTRIBUTE_PRINTF(2, 3); LOG_LEVEL_LIST #undef LOG_LEVEL }; --- old/src/share/vm/precompiled/precompiled.hpp 2016-02-16 16:50:52.194999846 +0100 +++ new/src/share/vm/precompiled/precompiled.hpp 2016-02-16 16:50:52.038334028 +0100 @@ -127,6 +127,7 @@ # include "interpreter/templateTable.hpp" # include "jvmtifiles/jvmti.h" # include "logging/log.hpp" +# include "logging/logMessage.hpp" # include "memory/allocation.hpp" # include "memory/allocation.inline.hpp" # include "memory/heap.hpp" --- /dev/null 2016-02-02 10:14:57.236657258 +0100 +++ new/src/share/vm/logging/logMessage.cpp 2016-02-16 16:50:52.824996433 +0100 @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2016, 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. + * + */ +#include "precompiled.hpp" +#include "logging/logMessage.hpp" +#include "memory/allocation.inline.hpp" +#include "runtime/thread.inline.hpp" + +template +static void grow(T*& buffer, size_t& capacity, bool c_heap, size_t minimum_length = 0) { + size_t new_size = capacity * 2; + if (new_size < minimum_length) { + new_size = minimum_length; + } + if (c_heap) { + buffer = REALLOC_C_HEAP_ARRAY(T, buffer, new_size, mtLogging); + } else { + buffer = REALLOC_RESOURCE_ARRAY(T, buffer, capacity, new_size); + } + capacity = new_size; +} + +LogMessage::LogMessage() : _message_buffer_size(0), + _message_buffer_capacity(InitialMessageBufferCapacity), + _line_count(0), + _line_capacity(InitialLineCapacity), + _c_heap_allocated(Thread::current_or_null() == NULL), + _prefix_fn(NULL), + _least_detailed_level(LogLevel::Off), + _used(false) { + if (_c_heap_allocated) { + _lines = NEW_C_HEAP_ARRAY(LogLine, _message_buffer_capacity, mtLogging); + _message_buffer = NEW_C_HEAP_ARRAY(char, InitialMessageBufferCapacity, mtLogging); + } else { + _lines = NEW_RESOURCE_ARRAY(LogLine, _message_buffer_capacity); + _message_buffer = NEW_RESOURCE_ARRAY(char, InitialMessageBufferCapacity); + } +} + +LogMessage::~LogMessage() { + guarantee(_used || _line_count == 0, "log message filled in but never written/used"); + if (_c_heap_allocated) { + FREE_C_HEAP_ARRAY(LogLine, _lines); + FREE_C_HEAP_ARRAY(char, _message_buffer); + } else { + FREE_RESOURCE_ARRAY(LogLine, _lines, _line_capacity); + FREE_RESOURCE_ARRAY(char, _message_buffer, _message_buffer_capacity); + } +} + +void LogMessage::write(LogLevelType level, const char* fmt, ...) { + va_list args; + va_start(args, fmt); + vwrite(level, fmt, args); + va_end(args); +} + +void LogMessage::vwrite(LogLevelType level, const char* fmt, va_list args) { + + if (level > _least_detailed_level) { + _least_detailed_level = level; + } + + size_t written; + for (int attempts = 0; attempts < 2; attempts++) { + written = 0; + size_t remaining_buffer_length = _message_buffer_capacity - _message_buffer_size; + char* current_buffer_position = _message_buffer + _message_buffer_size; + if (_prefix_fn != NULL) { + written += _prefix_fn(current_buffer_position, remaining_buffer_length); + current_buffer_position += written; + if (remaining_buffer_length < written) { + remaining_buffer_length = 0; + } else { + remaining_buffer_length -= written; + } + } + va_list copy; + va_copy(copy, args); + written += (size_t)os::log_vsnprintf(current_buffer_position, remaining_buffer_length, fmt, copy) + 1; + va_end(copy); + if (written > _message_buffer_capacity - _message_buffer_size) { + assert(attempts == 0, "Second attempt should always have a sufficiently large buffer (resized to fit)."); + grow(_message_buffer, _message_buffer_capacity, _c_heap_allocated, _message_buffer_size + written); + continue; + } + break; + } + + if (_line_count == _line_capacity) { + grow(_lines, _line_capacity, _c_heap_allocated); + } + + _lines[_line_count].level = level; + _lines[_line_count].message_offset = _message_buffer_size; + _message_buffer_size += written; + _line_count++; +} + +#define LOG_LEVEL(level, name) \ +LogMessage& LogMessage::v##name(const char* fmt, va_list args) { \ + vwrite(LogLevel::level, fmt, args); \ + return *this; \ +} \ +LogMessage& LogMessage::name(const char* fmt, ...) { \ + va_list args; \ + va_start(args, fmt); \ + vwrite(LogLevel::level, fmt, args); \ + va_end(args); \ + return *this; \ +} +LOG_LEVEL_LIST +#undef LOG_LEVEL