--- 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