--- a/hotspot/src/share/vm/logging/log.cpp Mon Apr 04 13:36:27 2016 +0200
+++ b/hotspot/src/share/vm/logging/log.cpp Mon Apr 04 15:05:52 2016 +0200
@@ -23,24 +23,6 @@
*/
#include "precompiled.hpp"
-#include "logging/log.hpp"
-#include "memory/allocation.inline.hpp"
-
-void LogWriteHelper::write_large(LogTagSet& lts,
- LogLevelType level,
- const char* prefix,
- size_t prefix_len,
- size_t msg_len,
- const char* fmt,
- va_list args) {
- size_t newbuf_len = prefix_len + msg_len + 1;
- char* newbuf = NEW_C_HEAP_ARRAY(char, newbuf_len, mtLogging);
- memcpy(newbuf, prefix, prefix_len);
- int ret = os::log_vsnprintf(newbuf + prefix_len, newbuf_len - prefix_len, fmt, args);
- assert(ret >= 0, "Log message buffer issue");
- lts.log(level, newbuf);
- FREE_C_HEAP_ARRAY(char, newbuf);
-}
/////////////// Unit tests ///////////////
--- a/hotspot/src/share/vm/logging/log.hpp Mon Apr 04 13:36:27 2016 +0200
+++ b/hotspot/src/share/vm/logging/log.hpp Mon Apr 04 15:05:52 2016 +0200
@@ -86,26 +86,6 @@
//
#define Log(...) LogImpl<LOG_TAGS(__VA_ARGS__)>
-template <LogTagType T0, LogTagType T1, LogTagType T2, LogTagType T3, LogTagType T4, LogTagType GuardTag>
-class LogImpl;
-
-// Non-template helper class for implementing write-slowpath in cpp
-class LogWriteHelper : AllStatic {
- private:
-
- template <LogTagType T0, LogTagType T1, LogTagType T2, LogTagType T3, LogTagType T4, LogTagType GuardTag>
- friend class LogImpl;
-
- ATTRIBUTE_PRINTF(6, 0)
- static void write_large(LogTagSet& lts,
- LogLevelType level,
- const char* prefix,
- size_t prefix_len,
- size_t msg_len,
- const char* fmt,
- va_list args);
-};
-
//
// Log class that embeds both log tags and a log level.
//
@@ -150,7 +130,7 @@
va_start(args, fmt);
vwrite(level, fmt, args);
va_end(args);
- };
+ }
template <LogLevelType Level>
ATTRIBUTE_PRINTF(1, 2)
@@ -159,25 +139,11 @@
va_start(args, fmt);
vwrite(Level, fmt, args);
va_end(args);
- };
+ }
ATTRIBUTE_PRINTF(2, 0)
static void vwrite(LogLevelType level, const char* fmt, va_list args) {
- char buf[LogBufferSize];
- va_list saved_args; // For re-format on buf overflow.
- va_copy(saved_args, args);
- size_t prefix_len = LogPrefix<T0, T1, T2, T3, T4>::prefix(buf, sizeof(buf));
- // Check that string fits in buffer; resize buffer if necessary
- int ret = os::log_vsnprintf(buf + prefix_len, sizeof(buf) - prefix_len, fmt, args);
- assert(ret >= 0, "Log message buffer issue");
- size_t msg_len = ret;
- LogTagSet& lts = LogTagSetMapping<T0, T1, T2, T3, T4>::tagset();
- if (msg_len >= sizeof(buf)) {
- LogWriteHelper::write_large(lts, level, buf, prefix_len, msg_len, fmt, saved_args);
- } else {
- lts.log(level, buf);
- }
- va_end(saved_args);
+ LogTagSetMapping<T0, T1, T2, T3, T4>::tagset().vwrite(level, fmt, args);
}
#define LOG_LEVEL(level, name) ATTRIBUTE_PRINTF(2, 0) \
--- a/hotspot/src/share/vm/logging/logTagSet.cpp Mon Apr 04 13:36:27 2016 +0200
+++ b/hotspot/src/share/vm/logging/logTagSet.cpp Mon Apr 04 15:05:52 2016 +0200
@@ -27,14 +27,15 @@
#include "logging/logOutput.hpp"
#include "logging/logTag.hpp"
#include "logging/logTagSet.hpp"
+#include "memory/allocation.inline.hpp"
LogTagSet* LogTagSet::_list = NULL;
size_t LogTagSet::_ntagsets = 0;
// This constructor is called only during static initialization.
// See the declaration in logTagSet.hpp for more information.
-LogTagSet::LogTagSet(LogTagType t0, LogTagType t1, LogTagType t2, LogTagType t3, LogTagType t4)
- : _next(_list) {
+LogTagSet::LogTagSet(PrefixWriter prefix_writer, LogTagType t0, LogTagType t1, LogTagType t2, LogTagType t3, LogTagType t4)
+ : _next(_list), _write_prefix(prefix_writer) {
_tag[0] = t0;
_tag[1] = t1;
_tag[2] = t2;
@@ -86,3 +87,34 @@
}
return tot_written;
}
+
+void LogTagSet::write(LogLevelType level, const char* fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ vwrite(level, fmt, args);
+ va_end(args);
+}
+
+const size_t vwrite_buffer_size = 512;
+
+void LogTagSet::vwrite(LogLevelType level, const char* fmt, va_list args) {
+ char buf[vwrite_buffer_size];
+ va_list saved_args; // For re-format on buf overflow.
+ va_copy(saved_args, args);
+ size_t prefix_len = _write_prefix(buf, sizeof(buf));
+ // Check that string fits in buffer; resize buffer if necessary
+ int ret = os::log_vsnprintf(buf + prefix_len, sizeof(buf) - prefix_len, fmt, args);
+ assert(ret >= 0, "Log message buffer issue");
+ if ((size_t)ret >= sizeof(buf)) {
+ size_t newbuf_len = prefix_len + ret + 1;
+ char* newbuf = NEW_C_HEAP_ARRAY(char, newbuf_len, mtLogging);
+ memcpy(newbuf, buf, prefix_len);
+ ret = os::log_vsnprintf(newbuf + prefix_len, newbuf_len - prefix_len, fmt, saved_args);
+ assert(ret >= 0, "Log message buffer issue");
+ log(level, newbuf);
+ FREE_C_HEAP_ARRAY(char, newbuf);
+ } else {
+ log(level, buf);
+ }
+ va_end(saved_args);
+}
--- a/hotspot/src/share/vm/logging/logTagSet.hpp Mon Apr 04 13:36:27 2016 +0200
+++ b/hotspot/src/share/vm/logging/logTagSet.hpp Mon Apr 04 15:05:52 2016 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -27,6 +27,7 @@
#include "logging/logDecorators.hpp"
#include "logging/logLevel.hpp"
#include "logging/logOutputList.hpp"
+#include "logging/logPrefix.hpp"
#include "logging/logTag.hpp"
#include "utilities/globalDefinitions.hpp"
@@ -45,14 +46,17 @@
LogOutputList _output_list;
LogDecorators _decorators;
+ typedef size_t (*PrefixWriter)(char* buf, size_t size);
+ PrefixWriter _write_prefix;
+
// Keep constructor private to prevent incorrect instantiations of this class.
// Only LogTagSetMappings can create/contain instances of this class.
// The constructor links all tagsets together in a global list of tagsets.
// This list is used during configuration to be able to update all tagsets
// and their configurations to reflect the new global log configuration.
- LogTagSet(LogTagType t0, LogTagType t1, LogTagType t2, LogTagType t3, LogTagType t4);
+ LogTagSet(PrefixWriter prefix_writer, LogTagType t0, LogTagType t1, LogTagType t2, LogTagType t3, LogTagType t4);
- template <LogTagType T0, LogTagType T1, LogTagType T2, LogTagType T3, LogTagType T4>
+ template <LogTagType T0, LogTagType T1, LogTagType T2, LogTagType T3, LogTagType T4, LogTagType GuardTag>
friend class LogTagSetMapping;
public:
@@ -102,12 +106,30 @@
return _output_list.is_level(level);
}
void log(LogLevelType level, const char* msg);
+
+ ATTRIBUTE_PRINTF(3, 4)
+ void write(LogLevelType level, const char* fmt, ...);
+
+ template <LogLevelType Level>
+ ATTRIBUTE_PRINTF(2, 3)
+ void write(const char* fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ vwrite(Level, fmt, args);
+ va_end(args);
+ }
+
+ ATTRIBUTE_PRINTF(3, 0)
+ void vwrite(LogLevelType level, const char* fmt, va_list args);
};
template <LogTagType T0, LogTagType T1 = LogTag::__NO_TAG, LogTagType T2 = LogTag::__NO_TAG,
- LogTagType T3 = LogTag::__NO_TAG, LogTagType T4 = LogTag::__NO_TAG>
+ LogTagType T3 = LogTag::__NO_TAG, LogTagType T4 = LogTag::__NO_TAG,
+ LogTagType GuardTag = LogTag::__NO_TAG>
class LogTagSetMapping : public AllStatic {
private:
+ // Verify number of logging tags does not exceed maximum supported.
+ STATIC_ASSERT(GuardTag == LogTag::__NO_TAG);
static LogTagSet _tagset;
public:
@@ -121,7 +143,7 @@
// Each combination of tags used as template arguments to the Log class somewhere (via macro or not)
// will instantiate the LogTagSetMapping template, which in turn creates the static field for that
// tagset. This _tagset contains the configuration for those tags.
-template <LogTagType T0, LogTagType T1, LogTagType T2, LogTagType T3, LogTagType T4>
-LogTagSet LogTagSetMapping<T0, T1, T2, T3, T4>::_tagset(T0, T1, T2, T3, T4);
+template <LogTagType T0, LogTagType T1, LogTagType T2, LogTagType T3, LogTagType T4, LogTagType GuardTag>
+LogTagSet LogTagSetMapping<T0, T1, T2, T3, T4, GuardTag>::_tagset(&LogPrefix<T0, T1, T2, T3, T4>::prefix, T0, T1, T2, T3, T4);
#endif // SHARE_VM_LOGGING_LOGTAGSET_HPP