src/share/vm/utilities/ostream.cpp

Thu, 20 Nov 2008 16:56:09 -0800

author
ysr
date
Thu, 20 Nov 2008 16:56:09 -0800
changeset 888
c96030fff130
parent 791
1ee8caae33af
child 948
2328d1d3f8cf
permissions
-rw-r--r--

6684579: SoftReference processing can be made more efficient
Summary: For current soft-ref clearing policies, we can decide at marking time if a soft-reference will definitely not be cleared, postponing the decision of whether it will definitely be cleared to the final reference processing phase. This can be especially beneficial in the case of concurrent collectors where the marking is usually concurrent but reference processing is usually not.
Reviewed-by: jmasa

     1 /*
     2  * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    20  * CA 95054 USA or visit www.sun.com if you need additional information or
    21  * have any questions.
    22  *
    23  */
    25 # include "incls/_precompiled.incl"
    26 # include "incls/_ostream.cpp.incl"
    28 extern "C" void jio_print(const char* s); // Declarationtion of jvm method
    30 outputStream::outputStream(int width) {
    31   _width       = width;
    32   _position    = 0;
    33   _newlines    = 0;
    34   _precount    = 0;
    35   _indentation = 0;
    36 }
    38 outputStream::outputStream(int width, bool has_time_stamps) {
    39   _width       = width;
    40   _position    = 0;
    41   _newlines    = 0;
    42   _precount    = 0;
    43   _indentation = 0;
    44   if (has_time_stamps)  _stamp.update();
    45 }
    47 void outputStream::update_position(const char* s, size_t len) {
    48   for (size_t i = 0; i < len; i++) {
    49     char ch = s[i];
    50     if (ch == '\n') {
    51       _newlines += 1;
    52       _precount += _position + 1;
    53       _position = 0;
    54     } else if (ch == '\t') {
    55       int tw = 8 - (_position & 7);
    56       _position += tw;
    57       _precount -= tw-1;  // invariant:  _precount + _position == total count
    58     } else {
    59       _position += 1;
    60     }
    61   }
    62 }
    64 // Execute a vsprintf, using the given buffer if necessary.
    65 // Return a pointer to the formatted string.
    66 const char* outputStream::do_vsnprintf(char* buffer, size_t buflen,
    67                                        const char* format, va_list ap,
    68                                        bool add_cr,
    69                                        size_t& result_len) {
    70   const char* result;
    71   if (add_cr)  buflen--;
    72   if (!strchr(format, '%')) {
    73     // constant format string
    74     result = format;
    75     result_len = strlen(result);
    76     if (add_cr && result_len >= buflen)  result_len = buflen-1;  // truncate
    77   } else if (format[0] == '%' && format[1] == 's' && format[2] == '\0') {
    78     // trivial copy-through format string
    79     result = va_arg(ap, const char*);
    80     result_len = strlen(result);
    81     if (add_cr && result_len >= buflen)  result_len = buflen-1;  // truncate
    82   } else if (vsnprintf(buffer, buflen, format, ap) >= 0) {
    83     result = buffer;
    84     result_len = strlen(result);
    85   } else {
    86     DEBUG_ONLY(warning("increase O_BUFLEN in ostream.hpp -- output truncated");)
    87     result = buffer;
    88     result_len = buflen - 1;
    89     buffer[result_len] = 0;
    90   }
    91   if (add_cr) {
    92     if (result != buffer) {
    93       strncpy(buffer, result, buflen);
    94       result = buffer;
    95     }
    96     buffer[result_len++] = '\n';
    97     buffer[result_len] = 0;
    98   }
    99   return result;
   100 }
   102 void outputStream::print(const char* format, ...) {
   103   char buffer[O_BUFLEN];
   104   va_list ap;
   105   va_start(ap, format);
   106   size_t len;
   107   const char* str = do_vsnprintf(buffer, O_BUFLEN, format, ap, false, len);
   108   write(str, len);
   109   va_end(ap);
   110 }
   112 void outputStream::print_cr(const char* format, ...) {
   113   char buffer[O_BUFLEN];
   114   va_list ap;
   115   va_start(ap, format);
   116   size_t len;
   117   const char* str = do_vsnprintf(buffer, O_BUFLEN, format, ap, true, len);
   118   write(str, len);
   119   va_end(ap);
   120 }
   122 void outputStream::vprint(const char *format, va_list argptr) {
   123   char buffer[O_BUFLEN];
   124   size_t len;
   125   const char* str = do_vsnprintf(buffer, O_BUFLEN, format, argptr, false, len);
   126   write(str, len);
   127 }
   129 void outputStream::vprint_cr(const char* format, va_list argptr) {
   130   char buffer[O_BUFLEN];
   131   size_t len;
   132   const char* str = do_vsnprintf(buffer, O_BUFLEN, format, argptr, true, len);
   133   write(str, len);
   134 }
   136 void outputStream::fill_to(int col) {
   137   int need_fill = col - position();
   138   sp(need_fill);
   139 }
   141 void outputStream::move_to(int col, int slop, int min_space) {
   142   if (position() >= col + slop)
   143     cr();
   144   int need_fill = col - position();
   145   if (need_fill < min_space)
   146     need_fill = min_space;
   147   sp(need_fill);
   148 }
   150 void outputStream::put(char ch) {
   151   assert(ch != 0, "please fix call site");
   152   char buf[] = { ch, '\0' };
   153   write(buf, 1);
   154 }
   156 #define SP_USE_TABS false
   158 void outputStream::sp(int count) {
   159   if (count < 0)  return;
   160   if (SP_USE_TABS && count >= 8) {
   161     int target = position() + count;
   162     while (count >= 8) {
   163       this->write("\t", 1);
   164       count -= 8;
   165     }
   166     count = target - position();
   167   }
   168   while (count > 0) {
   169     int nw = (count > 8) ? 8 : count;
   170     this->write("        ", nw);
   171     count -= nw;
   172   }
   173 }
   175 void outputStream::cr() {
   176   this->write("\n", 1);
   177 }
   179 void outputStream::stamp() {
   180   if (! _stamp.is_updated()) {
   181     _stamp.update(); // start at 0 on first call to stamp()
   182   }
   184   // outputStream::stamp() may get called by ostream_abort(), use snprintf
   185   // to avoid allocating large stack buffer in print().
   186   char buf[40];
   187   jio_snprintf(buf, sizeof(buf), "%.3f", _stamp.seconds());
   188   print_raw(buf);
   189 }
   191 void outputStream::stamp(bool guard,
   192                          const char* prefix,
   193                          const char* suffix) {
   194   if (!guard) {
   195     return;
   196   }
   197   print_raw(prefix);
   198   stamp();
   199   print_raw(suffix);
   200 }
   202 void outputStream::date_stamp(bool guard,
   203                               const char* prefix,
   204                               const char* suffix) {
   205   if (!guard) {
   206     return;
   207   }
   208   print_raw(prefix);
   209   static const char error_time[] = "yyyy-mm-ddThh:mm:ss.mmm+zzzz";
   210   static const int buffer_length = 32;
   211   char buffer[buffer_length];
   212   const char* iso8601_result = os::iso8601_time(buffer, buffer_length);
   213   if (iso8601_result != NULL) {
   214     print_raw(buffer);
   215   } else {
   216     print_raw(error_time);
   217   }
   218   print_raw(suffix);
   219   return;
   220 }
   222 void outputStream::indent() {
   223   while (_position < _indentation) sp();
   224 }
   226 void outputStream::print_jlong(jlong value) {
   227   // N.B. Same as INT64_FORMAT
   228   print(os::jlong_format_specifier(), value);
   229 }
   231 void outputStream::print_julong(julong value) {
   232   // N.B. Same as UINT64_FORMAT
   233   print(os::julong_format_specifier(), value);
   234 }
   236 stringStream::stringStream(size_t initial_size) : outputStream() {
   237   buffer_length = initial_size;
   238   buffer        = NEW_RESOURCE_ARRAY(char, buffer_length);
   239   buffer_pos    = 0;
   240   buffer_fixed  = false;
   241 }
   243 // useful for output to fixed chunks of memory, such as performance counters
   244 stringStream::stringStream(char* fixed_buffer, size_t fixed_buffer_size) : outputStream() {
   245   buffer_length = fixed_buffer_size;
   246   buffer        = fixed_buffer;
   247   buffer_pos    = 0;
   248   buffer_fixed  = true;
   249 }
   251 void stringStream::write(const char* s, size_t len) {
   252   size_t write_len = len;               // number of non-null bytes to write
   253   size_t end = buffer_pos + len + 1;    // position after write and final '\0'
   254   if (end > buffer_length) {
   255     if (buffer_fixed) {
   256       // if buffer cannot resize, silently truncate
   257       end = buffer_length;
   258       write_len = end - buffer_pos - 1; // leave room for the final '\0'
   259     } else {
   260       // For small overruns, double the buffer.  For larger ones,
   261       // increase to the requested size.
   262       if (end < buffer_length * 2) {
   263         end = buffer_length * 2;
   264       }
   265       char* oldbuf = buffer;
   266       buffer = NEW_RESOURCE_ARRAY(char, end);
   267       strncpy(buffer, oldbuf, buffer_pos);
   268       buffer_length = end;
   269     }
   270   }
   271   // invariant: buffer is always null-terminated
   272   guarantee(buffer_pos + write_len + 1 <= buffer_length, "stringStream oob");
   273   buffer[buffer_pos + write_len] = 0;
   274   strncpy(buffer + buffer_pos, s, write_len);
   275   buffer_pos += write_len;
   277   // Note that the following does not depend on write_len.
   278   // This means that position and count get updated
   279   // even when overflow occurs.
   280   update_position(s, len);
   281 }
   283 char* stringStream::as_string() {
   284   char* copy = NEW_RESOURCE_ARRAY(char, buffer_pos+1);
   285   strncpy(copy, buffer, buffer_pos);
   286   copy[buffer_pos] = 0;  // terminating null
   287   return copy;
   288 }
   290 stringStream::~stringStream() {}
   292 xmlStream*   xtty;
   293 outputStream* tty;
   294 outputStream* gclog_or_tty;
   295 extern Mutex* tty_lock;
   297 fileStream::fileStream(const char* file_name) {
   298   _file = fopen(file_name, "w");
   299   _need_close = true;
   300 }
   302 void fileStream::write(const char* s, size_t len) {
   303   if (_file != NULL)  fwrite(s, 1, len, _file);
   304   update_position(s, len);
   305 }
   307 fileStream::~fileStream() {
   308   if (_file != NULL) {
   309     if (_need_close) fclose(_file);
   310     _file = NULL;
   311   }
   312 }
   314 void fileStream::flush() {
   315   fflush(_file);
   316 }
   318 fdStream::fdStream(const char* file_name) {
   319   _fd = open(file_name, O_WRONLY | O_CREAT | O_TRUNC, 0666);
   320   _need_close = true;
   321 }
   323 fdStream::~fdStream() {
   324   if (_fd != -1) {
   325     if (_need_close) close(_fd);
   326     _fd = -1;
   327   }
   328 }
   330 void fdStream::write(const char* s, size_t len) {
   331   if (_fd != -1) ::write(_fd, s, (int)len);
   332   update_position(s, len);
   333 }
   335 defaultStream* defaultStream::instance = NULL;
   336 int defaultStream::_output_fd = 1;
   337 int defaultStream::_error_fd  = 2;
   338 FILE* defaultStream::_output_stream = stdout;
   339 FILE* defaultStream::_error_stream  = stderr;
   341 #define LOG_MAJOR_VERSION 160
   342 #define LOG_MINOR_VERSION 1
   344 void defaultStream::init() {
   345   _inited = true;
   346   if (LogVMOutput || LogCompilation) {
   347     init_log();
   348   }
   349 }
   351 bool defaultStream::has_log_file() {
   352   // lazily create log file (at startup, LogVMOutput is false even
   353   // if +LogVMOutput is used, because the flags haven't been parsed yet)
   354   // For safer printing during fatal error handling, do not init logfile
   355   // if a VM error has been reported.
   356   if (!_inited && !is_error_reported())  init();
   357   return _log_file != NULL;
   358 }
   360 static const char* make_log_name(const char* log_name, const char* force_directory, char* buf) {
   361   const char* basename = log_name;
   362   char file_sep = os::file_separator()[0];
   363   const char* cp;
   364   for (cp = log_name; *cp != '\0'; cp++) {
   365     if (*cp == '/' || *cp == file_sep) {
   366       basename = cp+1;
   367     }
   368   }
   369   const char* nametail = log_name;
   371   strcpy(buf, "");
   372   if (force_directory != NULL) {
   373     strcat(buf, force_directory);
   374     strcat(buf, os::file_separator());
   375     nametail = basename;       // completely skip directory prefix
   376   }
   378   const char* star = strchr(basename, '*');
   379   int star_pos = (star == NULL) ? -1 : (star - nametail);
   381   if (star_pos >= 0) {
   382     // convert foo*bar.log to foo123bar.log
   383     int buf_pos = (int) strlen(buf);
   384     strncpy(&buf[buf_pos], nametail, star_pos);
   385     sprintf(&buf[buf_pos + star_pos], "%u", os::current_process_id());
   386     nametail += star_pos + 1;  // skip prefix and star
   387   }
   389   strcat(buf, nametail);      // append rest of name, or all of name
   390   return buf;
   391 }
   393 void defaultStream::init_log() {
   394   // %%% Need a MutexLocker?
   395   const char* log_name = LogFile != NULL ? LogFile : "hotspot.log";
   396   char buf[O_BUFLEN*2];
   397   const char* try_name = make_log_name(log_name, NULL, buf);
   398   fileStream* file = new(ResourceObj::C_HEAP) fileStream(try_name);
   399   if (!file->is_open()) {
   400     // Try again to open the file.
   401     char warnbuf[O_BUFLEN*2];
   402     sprintf(warnbuf, "Warning:  Cannot open log file: %s\n", try_name);
   403     // Note:  This feature is for maintainer use only.  No need for L10N.
   404     jio_print(warnbuf);
   405     try_name = make_log_name("hs_pid*.log", os::get_temp_directory(), buf);
   406     sprintf(warnbuf, "Warning:  Forcing option -XX:LogFile=%s\n", try_name);
   407     jio_print(warnbuf);
   408     delete file;
   409     file = new(ResourceObj::C_HEAP) fileStream(try_name);
   410   }
   411   if (file->is_open()) {
   412     _log_file = file;
   413     xmlStream* xs = new(ResourceObj::C_HEAP) xmlStream(file);
   414     _outer_xmlStream = xs;
   415     if (this == tty)  xtty = xs;
   416     // Write XML header.
   417     xs->print_cr("<?xml version='1.0' encoding='UTF-8'?>");
   418     // (For now, don't bother to issue a DTD for this private format.)
   419     jlong time_ms = os::javaTimeMillis() - tty->time_stamp().milliseconds();
   420     // %%% Should be: jlong time_ms = os::start_time_milliseconds(), if
   421     // we ever get round to introduce that method on the os class
   422     xs->head("hotspot_log version='%d %d'"
   423              " process='%d' time_ms='"INT64_FORMAT"'",
   424              LOG_MAJOR_VERSION, LOG_MINOR_VERSION,
   425              os::current_process_id(), time_ms);
   426     // Write VM version header immediately.
   427     xs->head("vm_version");
   428     xs->head("name"); xs->text("%s", VM_Version::vm_name()); xs->cr();
   429     xs->tail("name");
   430     xs->head("release"); xs->text("%s", VM_Version::vm_release()); xs->cr();
   431     xs->tail("release");
   432     xs->head("info"); xs->text("%s", VM_Version::internal_vm_info_string()); xs->cr();
   433     xs->tail("info");
   434     xs->tail("vm_version");
   435     // Record information about the command-line invocation.
   436     xs->head("vm_arguments");  // Cf. Arguments::print_on()
   437     if (Arguments::num_jvm_flags() > 0) {
   438       xs->head("flags");
   439       Arguments::print_jvm_flags_on(xs->text());
   440       xs->tail("flags");
   441     }
   442     if (Arguments::num_jvm_args() > 0) {
   443       xs->head("args");
   444       Arguments::print_jvm_args_on(xs->text());
   445       xs->tail("args");
   446     }
   447     if (Arguments::java_command() != NULL) {
   448       xs->head("command"); xs->text()->print_cr("%s", Arguments::java_command());
   449       xs->tail("command");
   450     }
   451     if (Arguments::sun_java_launcher() != NULL) {
   452       xs->head("launcher"); xs->text()->print_cr("%s", Arguments::sun_java_launcher());
   453       xs->tail("launcher");
   454     }
   455     if (Arguments::system_properties() !=  NULL) {
   456       xs->head("properties");
   457       // Print it as a java-style property list.
   458       // System properties don't generally contain newlines, so don't bother with unparsing.
   459       for (SystemProperty* p = Arguments::system_properties(); p != NULL; p = p->next()) {
   460         xs->text()->print_cr("%s=%s", p->key(), p->value());
   461       }
   462       xs->tail("properties");
   463     }
   464     xs->tail("vm_arguments");
   465     // tty output per se is grouped under the <tty>...</tty> element.
   466     xs->head("tty");
   467     // All further non-markup text gets copied to the tty:
   468     xs->_text = this;  // requires friend declaration!
   469   } else {
   470     delete(file);
   471     // and leave xtty as NULL
   472     LogVMOutput = false;
   473     DisplayVMOutput = true;
   474     LogCompilation = false;
   475   }
   476 }
   478 // finish_log() is called during normal VM shutdown. finish_log_on_error() is
   479 // called by ostream_abort() after a fatal error.
   480 //
   481 void defaultStream::finish_log() {
   482   xmlStream* xs = _outer_xmlStream;
   483   xs->done("tty");
   485   // Other log forks are appended here, at the End of Time:
   486   CompileLog::finish_log(xs->out());  // write compile logging, if any, now
   488   xs->done("hotspot_log");
   489   xs->flush();
   491   fileStream* file = _log_file;
   492   _log_file = NULL;
   494   delete _outer_xmlStream;
   495   _outer_xmlStream = NULL;
   497   file->flush();
   498   delete file;
   499 }
   501 void defaultStream::finish_log_on_error(char *buf, int buflen) {
   502   xmlStream* xs = _outer_xmlStream;
   504   if (xs && xs->out()) {
   506     xs->done_raw("tty");
   508     // Other log forks are appended here, at the End of Time:
   509     CompileLog::finish_log_on_error(xs->out(), buf, buflen);  // write compile logging, if any, now
   511     xs->done_raw("hotspot_log");
   512     xs->flush();
   514     fileStream* file = _log_file;
   515     _log_file = NULL;
   516     _outer_xmlStream = NULL;
   518     if (file) {
   519       file->flush();
   521       // Can't delete or close the file because delete and fclose aren't
   522       // async-safe. We are about to die, so leave it to the kernel.
   523       // delete file;
   524     }
   525   }
   526 }
   528 intx defaultStream::hold(intx writer_id) {
   529   bool has_log = has_log_file();  // check before locking
   530   if (// impossible, but who knows?
   531       writer_id == NO_WRITER ||
   533       // bootstrap problem
   534       tty_lock == NULL ||
   536       // can't grab a lock or call Thread::current() if TLS isn't initialized
   537       ThreadLocalStorage::thread() == NULL ||
   539       // developer hook
   540       !SerializeVMOutput ||
   542       // VM already unhealthy
   543       is_error_reported() ||
   545       // safepoint == global lock (for VM only)
   546       (SafepointSynchronize::is_synchronizing() &&
   547        Thread::current()->is_VM_thread())
   548       ) {
   549     // do not attempt to lock unless we know the thread and the VM is healthy
   550     return NO_WRITER;
   551   }
   552   if (_writer == writer_id) {
   553     // already held, no need to re-grab the lock
   554     return NO_WRITER;
   555   }
   556   tty_lock->lock_without_safepoint_check();
   557   // got the lock
   558   if (writer_id != _last_writer) {
   559     if (has_log) {
   560       _log_file->bol();
   561       // output a hint where this output is coming from:
   562       _log_file->print_cr("<writer thread='"INTX_FORMAT"'/>", writer_id);
   563     }
   564     _last_writer = writer_id;
   565   }
   566   _writer = writer_id;
   567   return writer_id;
   568 }
   570 void defaultStream::release(intx holder) {
   571   if (holder == NO_WRITER) {
   572     // nothing to release:  either a recursive lock, or we scribbled (too bad)
   573     return;
   574   }
   575   if (_writer != holder) {
   576     return;  // already unlocked, perhaps via break_tty_lock_for_safepoint
   577   }
   578   _writer = NO_WRITER;
   579   tty_lock->unlock();
   580 }
   583 // Yuck:  jio_print does not accept char*/len.
   584 static void call_jio_print(const char* s, size_t len) {
   585   char buffer[O_BUFLEN+100];
   586   if (len > sizeof(buffer)-1) {
   587     warning("increase O_BUFLEN in ostream.cpp -- output truncated");
   588     len = sizeof(buffer)-1;
   589   }
   590   strncpy(buffer, s, len);
   591   buffer[len] = '\0';
   592   jio_print(buffer);
   593 }
   596 void defaultStream::write(const char* s, size_t len) {
   597   intx thread_id = os::current_thread_id();
   598   intx holder = hold(thread_id);
   600   if (DisplayVMOutput &&
   601       (_outer_xmlStream == NULL || !_outer_xmlStream->inside_attrs())) {
   602     // print to output stream. It can be redirected by a vfprintf hook
   603     if (s[len] == '\0') {
   604       jio_print(s);
   605     } else {
   606       call_jio_print(s, len);
   607     }
   608   }
   610   // print to log file
   611   if (has_log_file()) {
   612     int nl0 = _newlines;
   613     xmlTextStream::write(s, len);
   614     // flush the log file too, if there were any newlines
   615     if (nl0 != _newlines){
   616       flush();
   617     }
   618   } else {
   619     update_position(s, len);
   620   }
   622   release(holder);
   623 }
   625 intx ttyLocker::hold_tty() {
   626   if (defaultStream::instance == NULL)  return defaultStream::NO_WRITER;
   627   intx thread_id = os::current_thread_id();
   628   return defaultStream::instance->hold(thread_id);
   629 }
   631 void ttyLocker::release_tty(intx holder) {
   632   if (holder == defaultStream::NO_WRITER)  return;
   633   defaultStream::instance->release(holder);
   634 }
   636 void ttyLocker::break_tty_lock_for_safepoint(intx holder) {
   637   if (defaultStream::instance != NULL &&
   638       defaultStream::instance->writer() == holder) {
   639     if (xtty != NULL) {
   640       xtty->print_cr("<!-- safepoint while printing -->");
   641     }
   642     defaultStream::instance->release(holder);
   643   }
   644   // (else there was no lock to break)
   645 }
   647 void ostream_init() {
   648   if (defaultStream::instance == NULL) {
   649     defaultStream::instance = new(ResourceObj::C_HEAP) defaultStream();
   650     tty = defaultStream::instance;
   652     // We want to ensure that time stamps in GC logs consider time 0
   653     // the time when the JVM is initialized, not the first time we ask
   654     // for a time stamp. So, here, we explicitly update the time stamp
   655     // of tty.
   656     tty->time_stamp().update_to(1);
   657   }
   658 }
   660 void ostream_init_log() {
   661   // For -Xloggc:<file> option - called in runtime/thread.cpp
   662   // Note : this must be called AFTER ostream_init()
   664   gclog_or_tty = tty; // default to tty
   665   if (Arguments::gc_log_filename() != NULL) {
   666     fileStream * gclog = new(ResourceObj::C_HEAP)
   667                            fileStream(Arguments::gc_log_filename());
   668     if (gclog->is_open()) {
   669       // now we update the time stamp of the GC log to be synced up
   670       // with tty.
   671       gclog->time_stamp().update_to(tty->time_stamp().ticks());
   672       gclog_or_tty = gclog;
   673     }
   674   }
   676   // If we haven't lazily initialized the logfile yet, do it now,
   677   // to avoid the possibility of lazy initialization during a VM
   678   // crash, which can affect the stability of the fatal error handler.
   679   defaultStream::instance->has_log_file();
   680 }
   682 // ostream_exit() is called during normal VM exit to finish log files, flush
   683 // output and free resource.
   684 void ostream_exit() {
   685   static bool ostream_exit_called = false;
   686   if (ostream_exit_called)  return;
   687   ostream_exit_called = true;
   688   if (gclog_or_tty != tty) {
   689       delete gclog_or_tty;
   690   }
   691   {
   692       // we temporaly disable PrintMallocFree here
   693       // as otherwise it'll lead to using of almost deleted
   694       // tty or defaultStream::instance in logging facility
   695       // of HeapFree(), see 6391258
   696       DEBUG_ONLY(FlagSetting fs(PrintMallocFree, false);)
   697       if (tty != defaultStream::instance) {
   698           delete tty;
   699       }
   700       if (defaultStream::instance != NULL) {
   701           delete defaultStream::instance;
   702       }
   703   }
   704   tty = NULL;
   705   xtty = NULL;
   706   gclog_or_tty = NULL;
   707   defaultStream::instance = NULL;
   708 }
   710 // ostream_abort() is called by os::abort() when VM is about to die.
   711 void ostream_abort() {
   712   // Here we can't delete gclog_or_tty and tty, just flush their output
   713   if (gclog_or_tty) gclog_or_tty->flush();
   714   if (tty) tty->flush();
   716   if (defaultStream::instance != NULL) {
   717     static char buf[4096];
   718     defaultStream::instance->finish_log_on_error(buf, sizeof(buf));
   719   }
   720 }
   722 staticBufferStream::staticBufferStream(char* buffer, size_t buflen,
   723                                        outputStream *outer_stream) {
   724   _buffer = buffer;
   725   _buflen = buflen;
   726   _outer_stream = outer_stream;
   727 }
   729 void staticBufferStream::write(const char* c, size_t len) {
   730   _outer_stream->print_raw(c, (int)len);
   731 }
   733 void staticBufferStream::flush() {
   734   _outer_stream->flush();
   735 }
   737 void staticBufferStream::print(const char* format, ...) {
   738   va_list ap;
   739   va_start(ap, format);
   740   size_t len;
   741   const char* str = do_vsnprintf(_buffer, _buflen, format, ap, false, len);
   742   write(str, len);
   743   va_end(ap);
   744 }
   746 void staticBufferStream::print_cr(const char* format, ...) {
   747   va_list ap;
   748   va_start(ap, format);
   749   size_t len;
   750   const char* str = do_vsnprintf(_buffer, _buflen, format, ap, true, len);
   751   write(str, len);
   752   va_end(ap);
   753 }
   755 void staticBufferStream::vprint(const char *format, va_list argptr) {
   756   size_t len;
   757   const char* str = do_vsnprintf(_buffer, _buflen, format, argptr, false, len);
   758   write(str, len);
   759 }
   761 void staticBufferStream::vprint_cr(const char* format, va_list argptr) {
   762   size_t len;
   763   const char* str = do_vsnprintf(_buffer, _buflen, format, argptr, true, len);
   764   write(str, len);
   765 }
   767 bufferedStream::bufferedStream(size_t initial_size, size_t bufmax) : outputStream() {
   768   buffer_length = initial_size;
   769   buffer        = NEW_C_HEAP_ARRAY(char, buffer_length);
   770   buffer_pos    = 0;
   771   buffer_fixed  = false;
   772   buffer_max    = bufmax;
   773 }
   775 bufferedStream::bufferedStream(char* fixed_buffer, size_t fixed_buffer_size, size_t bufmax) : outputStream() {
   776   buffer_length = fixed_buffer_size;
   777   buffer        = fixed_buffer;
   778   buffer_pos    = 0;
   779   buffer_fixed  = true;
   780   buffer_max    = bufmax;
   781 }
   783 void bufferedStream::write(const char* s, size_t len) {
   785   if(buffer_pos + len > buffer_max) {
   786     flush();
   787   }
   789   size_t end = buffer_pos + len;
   790   if (end >= buffer_length) {
   791     if (buffer_fixed) {
   792       // if buffer cannot resize, silently truncate
   793       len = buffer_length - buffer_pos - 1;
   794     } else {
   795       // For small overruns, double the buffer.  For larger ones,
   796       // increase to the requested size.
   797       if (end < buffer_length * 2) {
   798         end = buffer_length * 2;
   799       }
   800       buffer = REALLOC_C_HEAP_ARRAY(char, buffer, end);
   801       buffer_length = end;
   802     }
   803   }
   804   memcpy(buffer + buffer_pos, s, len);
   805   buffer_pos += len;
   806   update_position(s, len);
   807 }
   809 char* bufferedStream::as_string() {
   810   char* copy = NEW_RESOURCE_ARRAY(char, buffer_pos+1);
   811   strncpy(copy, buffer, buffer_pos);
   812   copy[buffer_pos] = 0;  // terminating null
   813   return copy;
   814 }
   816 bufferedStream::~bufferedStream() {
   817   if (!buffer_fixed) {
   818     FREE_C_HEAP_ARRAY(char, buffer);
   819   }
   820 }
   822 #ifndef PRODUCT
   824 #if defined(SOLARIS) || defined(LINUX)
   825 #include <sys/types.h>
   826 #include <sys/socket.h>
   827 #include <netinet/in.h>
   828 #include <arpa/inet.h>
   829 #endif
   831 // Network access
   832 networkStream::networkStream() : bufferedStream(1024*10, 1024*10) {
   834   _socket = -1;
   836   hpi::initialize_socket_library();
   838   int result = hpi::socket(AF_INET, SOCK_STREAM, 0);
   839   if (result <= 0) {
   840     assert(false, "Socket could not be created!");
   841   } else {
   842     _socket = result;
   843   }
   844 }
   846 int networkStream::read(char *buf, size_t len) {
   847   return hpi::recv(_socket, buf, (int)len, 0);
   848 }
   850 void networkStream::flush() {
   851   if (size() != 0) {
   852     int result = hpi::raw_send(_socket, (char *)base(), (int)size(), 0);
   853     assert(result != -1, "connection error");
   854     assert(result == (int)size(), "didn't send enough data");
   855   }
   856   reset();
   857 }
   859 networkStream::~networkStream() {
   860   close();
   861 }
   863 void networkStream::close() {
   864   if (_socket != -1) {
   865     flush();
   866     hpi::socket_close(_socket);
   867     _socket = -1;
   868   }
   869 }
   871 bool networkStream::connect(const char *ip, short port) {
   873   struct sockaddr_in server;
   874   server.sin_family = AF_INET;
   875   server.sin_port = htons(port);
   877   server.sin_addr.s_addr = inet_addr(ip);
   878   if (server.sin_addr.s_addr == (uint32_t)-1) {
   879 #ifdef _WINDOWS
   880     struct hostent* host = hpi::get_host_by_name((char*)ip);
   881 #else
   882     struct hostent* host = gethostbyname(ip);
   883 #endif
   884     if (host != NULL) {
   885       memcpy(&server.sin_addr, host->h_addr_list[0], host->h_length);
   886     } else {
   887       return false;
   888     }
   889   }
   892   int result = hpi::connect(_socket, (struct sockaddr*)&server, sizeof(struct sockaddr_in));
   893   return (result >= 0);
   894 }
   896 #endif

mercurial