8153254: Delegate (v)write from Log to LogTagSet
authorrehn
Mon, 04 Apr 2016 15:05:52 +0200
changeset 37247 bdbfe42632cb
parent 37246 55d19e96f149
child 37248 11a660dbbb8e
8153254: Delegate (v)write from Log to LogTagSet Reviewed-by: stefank, kbarrett
hotspot/src/share/vm/logging/log.cpp
hotspot/src/share/vm/logging/log.hpp
hotspot/src/share/vm/logging/logTagSet.cpp
hotspot/src/share/vm/logging/logTagSet.hpp
--- 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