8146905: cleanup ostream, staticBufferStream
authorstuefe
Wed, 27 Jan 2016 11:51:56 +0100
changeset 35869 cd7df4cdaa1a
parent 35867 e20281e87b93
child 35870 3a406827dde4
8146905: cleanup ostream, staticBufferStream Summary: get rid of staticBufferStream and implement the use-caller-provided-scratch-buffer feature in a simpler way. Reviewed-by: simonis, dholmes
hotspot/src/share/vm/utilities/ostream.cpp
hotspot/src/share/vm/utilities/ostream.hpp
hotspot/src/share/vm/utilities/vmError.cpp
--- a/hotspot/src/share/vm/utilities/ostream.cpp	Thu Jan 28 02:30:57 2016 +0100
+++ b/hotspot/src/share/vm/utilities/ostream.cpp	Wed Jan 27 11:51:56 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -44,6 +44,8 @@
   _newlines    = 0;
   _precount    = 0;
   _indentation = 0;
+  _scratch     = NULL;
+  _scratch_len = 0;
 }
 
 outputStream::outputStream(int width, bool has_time_stamps) {
@@ -52,6 +54,8 @@
   _newlines    = 0;
   _precount    = 0;
   _indentation = 0;
+  _scratch     = NULL;
+  _scratch_len = 0;
   if (has_time_stamps)  _stamp.update();
 }
 
@@ -119,38 +123,47 @@
   return result;
 }
 
+void outputStream::do_vsnprintf_and_write_with_automatic_buffer(const char* format, va_list ap, bool add_cr) {
+  char buffer[O_BUFLEN];
+  size_t len;
+  const char* str = do_vsnprintf(buffer, sizeof(buffer), format, ap, add_cr, len);
+  write(str, len);
+}
+
+void outputStream::do_vsnprintf_and_write_with_scratch_buffer(const char* format, va_list ap, bool add_cr) {
+  size_t len;
+  const char* str = do_vsnprintf(_scratch, _scratch_len, format, ap, add_cr, len);
+  write(str, len);
+}
+
+void outputStream::do_vsnprintf_and_write(const char* format, va_list ap, bool add_cr) {
+  if (_scratch) {
+    do_vsnprintf_and_write_with_scratch_buffer(format, ap, add_cr);
+  } else {
+    do_vsnprintf_and_write_with_automatic_buffer(format, ap, add_cr);
+  }
+}
+
 void outputStream::print(const char* format, ...) {
-  char buffer[O_BUFLEN];
   va_list ap;
   va_start(ap, format);
-  size_t len;
-  const char* str = do_vsnprintf(buffer, O_BUFLEN, format, ap, false, len);
-  write(str, len);
+  do_vsnprintf_and_write(format, ap, false);
   va_end(ap);
 }
 
 void outputStream::print_cr(const char* format, ...) {
-  char buffer[O_BUFLEN];
   va_list ap;
   va_start(ap, format);
-  size_t len;
-  const char* str = do_vsnprintf(buffer, O_BUFLEN, format, ap, true, len);
-  write(str, len);
+  do_vsnprintf_and_write(format, ap, true);
   va_end(ap);
 }
 
 void outputStream::vprint(const char *format, va_list argptr) {
-  char buffer[O_BUFLEN];
-  size_t len;
-  const char* str = do_vsnprintf(buffer, O_BUFLEN, format, argptr, false, len);
-  write(str, len);
+  do_vsnprintf_and_write(format, argptr, false);
 }
 
 void outputStream::vprint_cr(const char* format, va_list argptr) {
-  char buffer[O_BUFLEN];
-  size_t len;
-  const char* str = do_vsnprintf(buffer, O_BUFLEN, format, argptr, true, len);
-  write(str, len);
+  do_vsnprintf_and_write(format, argptr, true);
 }
 
 void outputStream::fill_to(int col) {
@@ -958,53 +971,6 @@
   }
 }
 
-staticBufferStream::staticBufferStream(char* buffer, size_t buflen,
-                                       outputStream *outer_stream) {
-  _buffer = buffer;
-  _buflen = buflen;
-  _outer_stream = outer_stream;
-  // compile task prints time stamp relative to VM start
-  _stamp.update_to(1);
-}
-
-void staticBufferStream::write(const char* c, size_t len) {
-  _outer_stream->print_raw(c, (int)len);
-}
-
-void staticBufferStream::flush() {
-  _outer_stream->flush();
-}
-
-void staticBufferStream::print(const char* format, ...) {
-  va_list ap;
-  va_start(ap, format);
-  size_t len;
-  const char* str = do_vsnprintf(_buffer, _buflen, format, ap, false, len);
-  write(str, len);
-  va_end(ap);
-}
-
-void staticBufferStream::print_cr(const char* format, ...) {
-  va_list ap;
-  va_start(ap, format);
-  size_t len;
-  const char* str = do_vsnprintf(_buffer, _buflen, format, ap, true, len);
-  write(str, len);
-  va_end(ap);
-}
-
-void staticBufferStream::vprint(const char *format, va_list argptr) {
-  size_t len;
-  const char* str = do_vsnprintf(_buffer, _buflen, format, argptr, false, len);
-  write(str, len);
-}
-
-void staticBufferStream::vprint_cr(const char* format, va_list argptr) {
-  size_t len;
-  const char* str = do_vsnprintf(_buffer, _buflen, format, argptr, true, len);
-  write(str, len);
-}
-
 bufferedStream::bufferedStream(size_t initial_size, size_t bufmax) : outputStream() {
   buffer_length = initial_size;
   buffer        = NEW_C_HEAP_ARRAY(char, buffer_length, mtInternal);
--- a/hotspot/src/share/vm/utilities/ostream.hpp	Thu Jan 28 02:30:57 2016 +0100
+++ b/hotspot/src/share/vm/utilities/ostream.hpp	Wed Jan 27 11:51:56 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -49,6 +49,8 @@
    int _newlines;    // number of '\n' output so far
    julong _precount; // number of chars output, less _position
    TimeStamp _stamp; // for time stamps
+   char* _scratch;   // internal scratch buffer for printf
+   size_t _scratch_len; // size of internal scratch buffer
 
    void update_position(const char* s, size_t len);
    static const char* do_vsnprintf(char* buffer, size_t buflen,
@@ -56,6 +58,13 @@
                                    bool add_cr,
                                    size_t& result_len)  ATTRIBUTE_PRINTF(3, 0);
 
+   // calls do_vsnprintf and writes output to stream; uses an on-stack buffer.
+   void do_vsnprintf_and_write_with_automatic_buffer(const char* format, va_list ap, bool add_cr) ATTRIBUTE_PRINTF(2, 0);
+   // calls do_vsnprintf and writes output to stream; uses the user-provided buffer;
+   void do_vsnprintf_and_write_with_scratch_buffer(const char* format, va_list ap, bool add_cr) ATTRIBUTE_PRINTF(2, 0);
+   // calls do_vsnprintf, then writes output to stream.
+   void do_vsnprintf_and_write(const char* format, va_list ap, bool add_cr) ATTRIBUTE_PRINTF(2, 0);
+
  public:
    // creation
    outputStream(int width = 80);
@@ -119,6 +128,10 @@
    virtual void rotate_log(bool force, outputStream* out = NULL) {} // GC log rotation
    virtual ~outputStream() {}   // close properly on deletion
 
+   // Caller may specify their own scratch buffer to use for printing; otherwise,
+   // an automatic buffer on the stack (with O_BUFLEN len) is used.
+   void set_scratch_buffer(char* p, size_t len) { _scratch = p; _scratch_len = len; }
+
    void dec_cr() { dec(); cr(); }
    void inc_cr() { inc(); cr(); }
 };
@@ -250,26 +263,6 @@
 void ostream_exit();
 void ostream_abort();
 
-// staticBufferStream uses a user-supplied buffer for all formatting.
-// Used for safe formatting during fatal error handling.  Not MT safe.
-// Do not share the stream between multiple threads.
-class staticBufferStream : public outputStream {
- private:
-  char* _buffer;
-  size_t _buflen;
-  outputStream* _outer_stream;
- public:
-  staticBufferStream(char* buffer, size_t buflen,
-                     outputStream *outer_stream);
-  ~staticBufferStream() {};
-  virtual void write(const char* c, size_t len);
-  void flush();
-  void print(const char* format, ...) ATTRIBUTE_PRINTF(2, 3);
-  void print_cr(const char* format, ...) ATTRIBUTE_PRINTF(2, 3);
-  void vprint(const char *format, va_list argptr) ATTRIBUTE_PRINTF(2, 0);
-  void vprint_cr(const char* format, va_list argptr) ATTRIBUTE_PRINTF(2, 0);
-};
-
 // In the non-fixed buffer case an underlying buffer will be created and
 // managed in C heap. Not MT-safe.
 class bufferedStream : public outputStream {
--- a/hotspot/src/share/vm/utilities/vmError.cpp	Thu Jan 28 02:30:57 2016 +0100
+++ b/hotspot/src/share/vm/utilities/vmError.cpp	Wed Jan 27 11:51:56 2016 +0100
@@ -987,10 +987,12 @@
 volatile intptr_t VMError::first_error_tid = -1;
 
 // An error could happen before tty is initialized or after it has been
-// destroyed. Here we use a very simple unbuffered fdStream for printing.
-// Only out.print_raw() and out.print_raw_cr() should be used, as other
-// printing methods need to allocate large buffer on stack. To format a
-// string, use jio_snprintf() with a static buffer or use staticBufferStream.
+// destroyed.
+// Please note: to prevent large stack allocations, the log- and
+// output-stream use a global scratch buffer for format printing.
+// (see VmError::report_and_die(). Access to those streams is synchronized
+// in  VmError::report_and_die() - there is only one reporting thread at
+// any given time.
 fdStream VMError::out(defaultStream::output_fd());
 fdStream VMError::log; // error log used by VMError::report_and_die()
 
@@ -1100,6 +1102,8 @@
 {
   // Don't allocate large buffer on stack
   static char buffer[O_BUFLEN];
+  out.set_scratch_buffer(buffer, sizeof(buffer));
+  log.set_scratch_buffer(buffer, sizeof(buffer));
 
   // How many errors occurred in error handler when reporting first_error.
   static int recursive_error_count;
@@ -1186,8 +1190,7 @@
 
   // print to screen
   if (!out_done) {
-    staticBufferStream sbs(buffer, sizeof(buffer), &out);
-    report(&sbs, false);
+    report(&out, false);
 
     out_done = true;
 
@@ -1215,8 +1218,7 @@
       }
     }
 
-    staticBufferStream sbs(buffer, O_BUFLEN, &log);
-    report(&sbs, true);
+    report(&log, true);
     _current_step = 0;
     _current_step_info = "";