8153659: Create a CHeap backed LogStream class
authorstefank
Mon, 11 Apr 2016 08:51:53 +0200
changeset 37461 b5c955296b75
parent 37460 bda48699fd11
child 37462 58bb9394a98b
8153659: Create a CHeap backed LogStream class Reviewed-by: brutisso, mlarsson
hotspot/src/share/vm/logging/log.cpp
hotspot/src/share/vm/logging/logHandle.hpp
hotspot/src/share/vm/logging/logStream.cpp
hotspot/src/share/vm/logging/logStream.hpp
hotspot/src/share/vm/logging/logStream.inline.hpp
--- a/hotspot/src/share/vm/logging/log.cpp	Mon Apr 11 08:51:53 2016 +0200
+++ b/hotspot/src/share/vm/logging/log.cpp	Mon Apr 11 08:51:53 2016 +0200
@@ -361,11 +361,32 @@
   Test_logstream_helper(stream);
 }
 
+static void Test_logstreamcheap_log() {
+  Log(gc) log;
+  LogStreamCHeap stream(log.debug());
+
+  Test_logstream_helper(&stream);
+}
+
+static void Test_logstreamcheap_logtarget() {
+  LogTarget(Debug, gc) log;
+  LogStreamCHeap stream(log);
+
+  Test_logstream_helper(&stream);
+}
+
 void Test_logstream() {
+  // Test LogStreams with embedded ResourceMark.
   Test_logstream_log();
   Test_logstream_logtarget();
   Test_logstream_logstreamhandle();
+
+  // Test LogStreams without embedded ResourceMark.
   Test_logstream_no_rm();
+
+  // Test LogStreams backed by CHeap memory.
+  Test_logstreamcheap_log();
+  Test_logstreamcheap_logtarget();
 }
 
 void Test_loghandle_on() {
--- a/hotspot/src/share/vm/logging/logHandle.hpp	Mon Apr 11 08:51:53 2016 +0200
+++ b/hotspot/src/share/vm/logging/logHandle.hpp	Mon Apr 11 08:51:53 2016 +0200
@@ -67,13 +67,13 @@
 // This can be used to pass a Log instance as a parameter without
 // polluting the surrounding API with template functions.
 class LogTargetHandle {
-  friend class LogStream;
-
 private:
   const LogLevelType _level;
   LogTagSet*         _tagset;
 
 public:
+  LogTargetHandle(LogLevelType level, LogTagSet* tagset) : _level(level), _tagset(tagset) {}
+
   template <LogLevelType level, LogTagType T0, LogTagType T1, LogTagType T2, LogTagType T3, LogTagType T4, LogTagType GuardTag>
   LogTargetHandle(const LogTargetImpl<level, T0, T1, T2, T3, T4, GuardTag>& type_carrier) :
       _level(level),
--- a/hotspot/src/share/vm/logging/logStream.cpp	Mon Apr 11 08:51:53 2016 +0200
+++ b/hotspot/src/share/vm/logging/logStream.cpp	Mon Apr 11 08:51:53 2016 +0200
@@ -24,7 +24,7 @@
 
 #include "precompiled.hpp"
 #include "logging/log.hpp"
-#include "logging/logStream.hpp"
+#include "logging/logStream.inline.hpp"
 
 // Create a log stream without an embedded ResourceMark.
 // The function is placed here to be called out-of-line in log.hpp.
--- a/hotspot/src/share/vm/logging/logStream.hpp	Mon Apr 11 08:51:53 2016 +0200
+++ b/hotspot/src/share/vm/logging/logStream.hpp	Mon Apr 11 08:51:53 2016 +0200
@@ -26,23 +26,100 @@
 #define SHARE_VM_LOGGING_LOGSTREAM_HPP
 
 #include "logging/log.hpp"
+#include "logging/logHandle.hpp"
+#include "memory/resourceArea.hpp"
 #include "utilities/ostream.hpp"
 
-// An output stream that logs to the logging framework.
-// Requires a ResourceMark on the stack.
-class LogStreamNoResourceMark : public outputStream {
-private:
-  stringStream _current_line;
-  LogLevelType _level;
-  LogTagSet*   _tagset;
+// The base class of an output stream that logs to the logging framework.
+template <class streamClass>
+class LogStreamBase : public outputStream {
+  streamClass     _current_line;
+  LogTargetHandle _log_handle;
 
 public:
-  LogStreamNoResourceMark(LogLevelType level, LogTagSet* tagset) : _level(level), _tagset(tagset) {}
-  ~LogStreamNoResourceMark() {
+  // Constructor to support creation from a LogTarget instance.
+  //
+  // LogTarget(Debug, gc) log;
+  // LogStreamBase(log) stream;
+  template <LogLevelType level, LogTagType T0, LogTagType T1, LogTagType T2, LogTagType T3, LogTagType T4, LogTagType GuardTag>
+  LogStreamBase(const LogTargetImpl<level, T0, T1, T2, T3, T4, GuardTag>& type_carrier) :
+      _log_handle(level, &LogTagSetMapping<T0, T1, T2, T3, T4>::tagset()) {}
+
+  // Constructor to support creation from typed (likely NULL) pointer. Mostly used by the logging framework.
+  //
+  // LogStreamBase stream(log.debug());
+  //  or
+  // LogStreamBase stream((LogTargetImpl<level, T0, T1, T2, T3, T4, GuardTag>*)NULL);
+  template <LogLevelType level, LogTagType T0, LogTagType T1, LogTagType T2, LogTagType T3, LogTagType T4, LogTagType GuardTag>
+  LogStreamBase(const LogTargetImpl<level, T0, T1, T2, T3, T4, GuardTag>* type_carrier) :
+      _log_handle(level, &LogTagSetMapping<T0, T1, T2, T3, T4>::tagset()) {}
+
+  // Constructor to support creation from a LogTargetHandle.
+  //
+  // LogTarget(Debug, gc) log;
+  // LogTargetHandle(log) handle;
+  // LogStreamBase stream(handle);
+  LogStreamBase(LogTargetHandle handle) : _log_handle(handle) {}
+
+  // Constructor to support creation from a log level and tagset.
+  //
+  // LogStreamBase(level, tageset);
+  LogStreamBase(LogLevelType level, LogTagSet* tagset) : _log_handle(level, tagset) {}
+
+  ~LogStreamBase() {
     guarantee(_current_line.size() == 0, "Buffer not flushed. Missing call to print_cr()?");
   }
 
+public:
   void write(const char* s, size_t len);
 };
 
+// A stringStream with an embedded ResourceMark.
+class stringStreamWithResourceMark : outputStream {
+ private:
+  // The stringStream Resource allocate in the constructor,
+  // so the order of the fields is important.
+  ResourceMark _embedded_resource_mark;
+  stringStream _stream;
+
+ public:
+  stringStreamWithResourceMark(size_t initial_bufsize = 256) :
+      _embedded_resource_mark(),
+      _stream(initial_bufsize) {}
+
+  virtual void write(const char* c, size_t len) { _stream.write(c, len); }
+  size_t      size()                            { return _stream.size(); }
+  const char* base()                            { return _stream.base(); }
+  void  reset()                                 { _stream.reset(); }
+  char* as_string()                             { return _stream.as_string(); }
+};
+
+// An output stream that logs to the logging framework.
+//
+// The backing buffer is allocated in Resource memory.
+// The caller is required to have a ResourceMark on the stack.
+typedef LogStreamBase<stringStream> LogStreamNoResourceMark;
+
+// An output stream that logs to the logging framework.
+//
+// The backing buffer is allocated in CHeap memory.
+typedef LogStreamBase<bufferedStream> LogStreamCHeap;
+
+// An output stream that logs to the logging framework, and embeds a ResourceMark.
+//
+// The backing buffer is allocated in Resource memory.
+// The class is intended to be stack allocated.
+// The class provides its own ResourceMark,
+//  so care needs to be taken when nested ResourceMarks are used.
+typedef LogStreamBase<stringStreamWithResourceMark> LogStream;
+
+// Support creation of a LogStream without having to provide a LogTarget pointer.
+#define LogStreamHandle(level, ...) LogStreamTemplate<LogLevel::level, LOG_TAGS(__VA_ARGS__)>
+
+template <LogLevelType level, LogTagType T0, LogTagType T1, LogTagType T2, LogTagType T3, LogTagType T4, LogTagType GuardTag>
+class LogStreamTemplate : public LogStream {
+public:
+  LogStreamTemplate() : LogStream((LogTargetImpl<level, T0, T1, T2, T3, T4, GuardTag>*)NULL) {}
+};
+
 #endif // SHARE_VM_LOGGING_LOGSTREAM_HPP
--- a/hotspot/src/share/vm/logging/logStream.inline.hpp	Mon Apr 11 08:51:53 2016 +0200
+++ b/hotspot/src/share/vm/logging/logStream.inline.hpp	Mon Apr 11 08:51:53 2016 +0200
@@ -30,11 +30,12 @@
 #include "memory/resourceArea.hpp"
 #include "utilities/ostream.hpp"
 
-inline void LogStreamNoResourceMark::write(const char* s, size_t len) {
+template <class streamClass>
+inline void LogStreamBase<streamClass>::write(const char* s, size_t len) {
   if (len > 0 && s[len - 1] == '\n') {
     _current_line.write(s, len - 1);
     _current_line.write("\0", 1);
-    _tagset->write(_level, "%s", _current_line.base());
+    _log_handle.print("%s", _current_line.base());
     _current_line.reset();
   } else {
     _current_line.write(s, len);
@@ -42,54 +43,4 @@
   update_position(s, len);
 }
 
-// An output stream that logs to the logging framework, and embeds a ResourceMark.
-//
-//  The class is intended to be stack allocated.
-//  Care needs to be taken when nested ResourceMarks are used.
-class LogStream : public outputStream {
-private:
-  ResourceMark            _embedded_resource_mark;
-  LogStreamNoResourceMark _stream;
-
-public:
-  // Constructor to support creation from a LogTarget instance.
-  //
-  // LogTarget(Debug, gc) log;
-  // LogStream(log) stream;
-  template <LogLevelType level, LogTagType T0, LogTagType T1, LogTagType T2, LogTagType T3, LogTagType T4, LogTagType GuardTag>
-  LogStream(const LogTargetImpl<level, T0, T1, T2, T3, T4, GuardTag>& type_carrier) :
-      _embedded_resource_mark(),
-      _stream(level, &LogTagSetMapping<T0, T1, T2, T3, T4>::tagset()) {}
-
-  // Constructor to support creation from typed (likely NULL) pointer. Mostly used by the logging framework.
-  //
-  // LogStream stream(log.debug());
-  // LogStream stream((LogTargetImpl<level, T0, T1, T2, T3, T4, GuardTag>*)NULL);
-  template <LogLevelType level, LogTagType T0, LogTagType T1, LogTagType T2, LogTagType T3, LogTagType T4, LogTagType GuardTag>
-  LogStream(const LogTargetImpl<level, T0, T1, T2, T3, T4, GuardTag>* type_carrier) :
-      _embedded_resource_mark(),
-      _stream(level, &LogTagSetMapping<T0, T1, T2, T3, T4>::tagset()) {}
-
-  // Constructor to support creation from a LogTargetHandle.
-  //
-  // LogTarget(Debug, gc) log;
-  // LogTargetHandle(log) handle;
-  // LogStream stream(handle);
-  LogStream(LogTargetHandle handle) :
-      _embedded_resource_mark(),
-      _stream(handle._level, handle._tagset) {}
-
-  // Override of outputStream::write.
-  void write(const char* s, size_t len) { _stream.write(s, len); }
-};
-
-// Support creation of a LogStream without having to provide a LogTarget pointer.
-#define LogStreamHandle(level, ...) LogStreamTemplate<LogLevel::level, LOG_TAGS(__VA_ARGS__)>
-
-template <LogLevelType level, LogTagType T0, LogTagType T1, LogTagType T2, LogTagType T3, LogTagType T4, LogTagType GuardTag>
-class LogStreamTemplate : public LogStream {
-public:
-  LogStreamTemplate() : LogStream((LogTargetImpl<level, T0, T1, T2, T3, T4, GuardTag>*)NULL) {}
-};
-
 #endif // SHARE_VM_LOGGING_LOGSTREAM_INLINE_HPP