src/share/vm/utilities/xmlstream.cpp

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

author
ysr
date
Thu, 20 Nov 2008 16:56:09 -0800
changeset 888
c96030fff130
parent 657
2a1a77d3458f
child 1844
cff162798819
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 2002-2007 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/_xmlstream.cpp.incl"
    28 void xmlStream::initialize(outputStream* out) {
    29   _out = out;
    30   _last_flush = 0;
    31   _markup_state = BODY;
    32   _text_init._outer_xmlStream = this;
    33   _text = &_text_init;
    35 #ifdef ASSERT
    36   _element_depth = 0;
    37   int   init_len = 100;
    38   char* init_buf = NEW_C_HEAP_ARRAY(char, init_len);
    39   _element_close_stack_low  = init_buf;
    40   _element_close_stack_high = init_buf + init_len;
    41   _element_close_stack_ptr  = init_buf + init_len - 1;
    42   _element_close_stack_ptr[0] = '\0';
    43 #endif
    45   // Make sure each log uses the same base for time stamps.
    46   if (is_open()) {
    47     _out->time_stamp().update_to(1);
    48   }
    49 }
    51 #ifdef ASSERT
    52 xmlStream::~xmlStream() {
    53   FREE_C_HEAP_ARRAY(char, _element_close_stack_low);
    54 }
    55 #endif
    57 // Pass the given chars directly to _out.
    58 void xmlStream::write(const char* s, size_t len) {
    59   if (!is_open())  return;
    61   out()->write(s, len);
    62   update_position(s, len);
    63 }
    66 // Pass the given chars directly to _out, except that
    67 // we watch for special "<&>" chars.
    68 // This is suitable for either attribute text or for body text.
    69 // We don't fool with "<![CDATA[" quotes, just single-character entities.
    70 // This makes it easier for dumb tools to parse the output.
    71 void xmlStream::write_text(const char* s, size_t len) {
    72   if (!is_open())  return;
    74   size_t written = 0;
    75   // All normally printed material goes inside XML quotes.
    76   // This leaves the output free to include markup also.
    77   // Scan the string looking for inadvertant "<&>" chars
    78   for (size_t i = 0; i < len; i++) {
    79     char ch = s[i];
    80     // Escape special chars.
    81     const char* esc = NULL;
    82     switch (ch) {
    83       // These are important only in attrs, but we do them always:
    84     case '\'': esc = "&apos;"; break;
    85     case '"':  esc = "&quot;"; break;
    86     case '<':  esc = "&lt;";   break;
    87     case '&':  esc = "&amp;";  break;
    88       // This is a freebie.
    89     case '>':  esc = "&gt;";   break;
    90     }
    91     if (esc != NULL) {
    92       if (written < i) {
    93         out()->write(&s[written], i - written);
    94         written = i;
    95       }
    96       out()->print_raw(esc);
    97       written++;
    98     }
    99   }
   101   // Print the clean remainder.  Usually, it is all of s.
   102   if (written < len) {
   103     out()->write(&s[written], len - written);
   104   }
   105 }
   107 // ------------------------------------------------------------------
   108 // Outputs XML text, with special characters quoted.
   109 void xmlStream::text(const char* format, ...) {
   110   va_list ap;
   111   va_start(ap, format);
   112   va_text(format, ap);
   113   va_end(ap);
   114 }
   116 #define BUFLEN 2*K   /* max size of output of individual print methods */
   118 // ------------------------------------------------------------------
   119 void xmlStream::va_tag(bool push, const char* format, va_list ap) {
   120   assert_if_no_error(!inside_attrs(), "cannot print tag inside attrs");
   121   char buffer[BUFLEN];
   122   size_t len;
   123   const char* kind = do_vsnprintf(buffer, BUFLEN, format, ap, false, len);
   124   see_tag(kind, push);
   125   print_raw("<");
   126   write(kind, len);
   127   _markup_state = (push ? HEAD : ELEM);
   128 }
   130 #ifdef ASSERT
   131 /// Debugging goo to make sure element tags nest properly.
   133 // ------------------------------------------------------------------
   134 void xmlStream::see_tag(const char* tag, bool push) {
   135   assert_if_no_error(!inside_attrs(), "cannot start new element inside attrs");
   136   if (!push)  return;
   138   // tag goes up until either null or space:
   139   const char* tag_end = strchr(tag, ' ');
   140   size_t tag_len = (tag_end == NULL) ? strlen(tag) : tag_end - tag;
   141   assert(tag_len > 0, "tag must not be empty");
   142   // push the tag onto the stack, pulling down the pointer
   143   char* old_ptr  = _element_close_stack_ptr;
   144   char* old_low  = _element_close_stack_low;
   145   char* push_ptr = old_ptr - (tag_len+1);
   146   if (push_ptr < old_low) {
   147     int old_len = _element_close_stack_high - old_ptr;
   148     int new_len = old_len * 2;
   149     if (new_len < 100)  new_len = 100;
   150     char* new_low  = NEW_C_HEAP_ARRAY(char, new_len);
   151     char* new_high = new_low + new_len;
   152     char* new_ptr  = new_high - old_len;
   153     memcpy(new_ptr, old_ptr, old_len);
   154     _element_close_stack_high = new_high;
   155     _element_close_stack_low  = new_low;
   156     _element_close_stack_ptr  = new_ptr;
   157     FREE_C_HEAP_ARRAY(char, old_low);
   158     push_ptr = new_ptr - (tag_len+1);
   159   }
   160   assert(push_ptr >= _element_close_stack_low, "in range");
   161   memcpy(push_ptr, tag, tag_len);
   162   push_ptr[tag_len] = 0;
   163   _element_close_stack_ptr = push_ptr;
   164   _element_depth += 1;
   165 }
   167 // ------------------------------------------------------------------
   168 void xmlStream::pop_tag(const char* tag) {
   169   assert_if_no_error(!inside_attrs(), "cannot close element inside attrs");
   170   assert(_element_depth > 0, "must be in an element to close");
   171   assert(*tag != 0, "tag must not be empty");
   172   char* cur_tag = _element_close_stack_ptr;
   173   bool  bad_tag = false;
   174   while (*cur_tag != 0 && strcmp(cur_tag, tag) != 0) {
   175     this->print_cr("</%s> <!-- missing closing tag -->", cur_tag);
   176     _element_close_stack_ptr = (cur_tag += strlen(cur_tag) + 1);
   177     _element_depth -= 1;
   178     bad_tag = true;
   179   }
   180   if (*cur_tag == 0) {
   181     bad_tag = true;
   182   } else {
   183     // Pop the stack, by skipping over the tag and its null.
   184     _element_close_stack_ptr = cur_tag + strlen(cur_tag) + 1;
   185     _element_depth -= 1;
   186   }
   187   if (bad_tag && !VMThread::should_terminate() && !is_error_reported())
   188     assert(false, "bad tag in log");
   189 }
   190 #endif
   193 // ------------------------------------------------------------------
   194 // First word in formatted string is element kind, and any subsequent
   195 // words must be XML attributes.  Outputs "<kind .../>".
   196 void xmlStream::elem(const char* format, ...) {
   197   va_list ap;
   198   va_start(ap, format);
   199   va_elem(format, ap);
   200   va_end(ap);
   201 }
   203 // ------------------------------------------------------------------
   204 void xmlStream::va_elem(const char* format, va_list ap) {
   205   va_begin_elem(format, ap);
   206   end_elem();
   207 }
   210 // ------------------------------------------------------------------
   211 // First word in formatted string is element kind, and any subsequent
   212 // words must be XML attributes.  Outputs "<kind ...", not including "/>".
   213 void xmlStream::begin_elem(const char* format, ...) {
   214   va_list ap;
   215   va_start(ap, format);
   216   va_tag(false, format, ap);
   217   va_end(ap);
   218 }
   220 // ------------------------------------------------------------------
   221 void xmlStream::va_begin_elem(const char* format, va_list ap) {
   222   va_tag(false, format, ap);
   223 }
   225 // ------------------------------------------------------------------
   226 // Outputs "/>".
   227 void xmlStream::end_elem() {
   228   assert(_markup_state == ELEM, "misplaced end_elem");
   229   print_raw("/>\n");
   230   _markup_state = BODY;
   231 }
   233 // ------------------------------------------------------------------
   234 // Outputs formatted text, followed by "/>".
   235 void xmlStream::end_elem(const char* format, ...) {
   236   va_list ap;
   237   va_start(ap, format);
   238   out()->vprint(format, ap);
   239   va_end(ap);
   240   end_elem();
   241 }
   244 // ------------------------------------------------------------------
   245 // First word in formatted string is element kind, and any subsequent
   246 // words must be XML attributes.  Outputs "<kind ...>".
   247 void xmlStream::head(const char* format, ...) {
   248   va_list ap;
   249   va_start(ap, format);
   250   va_head(format, ap);
   251   va_end(ap);
   252 }
   254 // ------------------------------------------------------------------
   255 void xmlStream::va_head(const char* format, va_list ap) {
   256   va_begin_head(format, ap);
   257   end_head();
   258 }
   260 // ------------------------------------------------------------------
   261 // First word in formatted string is element kind, and any subsequent
   262 // words must be XML attributes.  Outputs "<kind ...", not including ">".
   263 void xmlStream::begin_head(const char* format, ...) {
   264   va_list ap;
   265   va_start(ap, format);
   266   va_tag(true, format, ap);
   267   va_end(ap);
   268 }
   270 // ------------------------------------------------------------------
   271 void xmlStream::va_begin_head(const char* format, va_list ap) {
   272   va_tag(true, format, ap);
   273 }
   275 // ------------------------------------------------------------------
   276 // Outputs ">".
   277 void xmlStream::end_head() {
   278   assert(_markup_state == HEAD, "misplaced end_head");
   279   print_raw(">\n");
   280   _markup_state = BODY;
   281 }
   284 // ------------------------------------------------------------------
   285 // Outputs formatted text, followed by ">".
   286 void xmlStream::end_head(const char* format, ...) {
   287   va_list ap;
   288   va_start(ap, format);
   289   out()->vprint(format, ap);
   290   va_end(ap);
   291   end_head();
   292 }
   295 // ------------------------------------------------------------------
   296 // Outputs "</kind>".
   297 void xmlStream::tail(const char* kind) {
   298   pop_tag(kind);
   299   print_raw("</");
   300   print_raw(kind);
   301   print_raw(">\n");
   302 }
   304 // ------------------------------------------------------------------
   305 // Outputs "<kind_done ... stamp='D.DD'/> </kind>".
   306 void xmlStream::done(const char* format, ...) {
   307   va_list ap;
   308   va_start(ap, format);
   309   va_done(format, ap);
   310   va_end(ap);
   311 }
   313 // ------------------------------------------------------------------
   314 // Outputs "<kind_done stamp='D.DD'/> </kind>".
   315 // Because done_raw() doesn't need to format strings, it's simpler than
   316 // done(), and can be called safely by fatal error handler.
   317 void xmlStream::done_raw(const char* kind) {
   318   print_raw("<");
   319   print_raw(kind);
   320   print_raw("_done stamp='");
   321   out()->stamp();
   322   print_raw_cr("'/>");
   323   print_raw("</");
   324   print_raw(kind);
   325   print_raw_cr(">");
   326 }
   328 // ------------------------------------------------------------------
   329 void xmlStream::va_done(const char* format, va_list ap) {
   330   char buffer[200];
   331   guarantee(strlen(format) + 10 < sizeof(buffer), "bigger format buffer")
   332   const char* kind = format;
   333   const char* kind_end = strchr(kind, ' ');
   334   size_t kind_len = (kind_end != NULL) ? (kind_end - kind) : strlen(kind);
   335   strncpy(buffer, kind, kind_len);
   336   strcpy(buffer + kind_len, "_done");
   337   strcat(buffer, format + kind_len);
   338   // Output the trailing event with the timestamp.
   339   va_begin_elem(buffer, ap);
   340   stamp();
   341   end_elem();
   342   // Output the tail-tag of the enclosing element.
   343   buffer[kind_len] = 0;
   344   tail(buffer);
   345 }
   347 // Output a timestamp attribute.
   348 void xmlStream::stamp() {
   349   assert_if_no_error(inside_attrs(), "stamp must be an attribute");
   350   print_raw(" stamp='");
   351   out()->stamp();
   352   print_raw("'");
   353 }
   356 // ------------------------------------------------------------------
   357 // Output a method attribute, in the form " method='pkg/cls name sig'".
   358 // This is used only when there is no ciMethod available.
   359 void xmlStream::method(methodHandle method) {
   360   assert_if_no_error(inside_attrs(), "printing attributes");
   361   if (method.is_null())  return;
   362   print_raw(" method='");
   363   method_text(method);
   364   print("' bytes='%d'", method->code_size());
   365   print(" count='%d'", method->invocation_count());
   366   int bec = method->backedge_count();
   367   if (bec != 0)  print(" backedge_count='%d'", bec);
   368   print(" iicount='%d'", method->interpreter_invocation_count());
   369   int throwouts = method->interpreter_throwout_count();
   370   if (throwouts != 0)  print(" throwouts='%d'", throwouts);
   371   methodDataOop mdo = method->method_data();
   372   if (mdo != NULL) {
   373     uint cnt;
   374     cnt = mdo->decompile_count();
   375     if (cnt != 0)  print(" decompiles='%d'", cnt);
   376     for (uint reason = 0; reason < mdo->trap_reason_limit(); reason++) {
   377       cnt = mdo->trap_count(reason);
   378       if (cnt != 0)  print(" %s_traps='%d'", Deoptimization::trap_reason_name(reason), cnt);
   379     }
   380     cnt = mdo->overflow_trap_count();
   381     if (cnt != 0)  print(" overflow_traps='%d'", cnt);
   382     cnt = mdo->overflow_recompile_count();
   383     if (cnt != 0)  print(" overflow_recompiles='%d'", cnt);
   384   }
   385 }
   387 void xmlStream::method_text(methodHandle method) {
   388   assert_if_no_error(inside_attrs(), "printing attributes");
   389   if (method.is_null())  return;
   390   //method->print_short_name(text());
   391   method->method_holder()->klass_part()->name()->print_symbol_on(text());
   392   print_raw(" ");  // " " is easier for tools to parse than "::"
   393   method->name()->print_symbol_on(text());
   394   print_raw(" ");  // separator
   395   method->signature()->print_symbol_on(text());
   396 }
   399 // ------------------------------------------------------------------
   400 // Output a klass attribute, in the form " klass='pkg/cls'".
   401 // This is used only when there is no ciKlass available.
   402 void xmlStream::klass(KlassHandle klass) {
   403   assert_if_no_error(inside_attrs(), "printing attributes");
   404   if (klass.is_null())  return;
   405   print_raw(" klass='");
   406   klass_text(klass);
   407   print_raw("'");
   408 }
   410 void xmlStream::klass_text(KlassHandle klass) {
   411   assert_if_no_error(inside_attrs(), "printing attributes");
   412   if (klass.is_null())  return;
   413   //klass->print_short_name(log->out());
   414   klass->name()->print_symbol_on(out());
   415 }
   417 void xmlStream::name(symbolHandle name) {
   418   assert_if_no_error(inside_attrs(), "printing attributes");
   419   if (name.is_null())  return;
   420   print_raw(" name='");
   421   name_text(name);
   422   print_raw("'");
   423 }
   425 void xmlStream::name_text(symbolHandle name) {
   426   assert_if_no_error(inside_attrs(), "printing attributes");
   427   if (name.is_null())  return;
   428   //name->print_short_name(text());
   429   name->print_symbol_on(text());
   430 }
   432 void xmlStream::object(const char* attr, Handle x) {
   433   assert_if_no_error(inside_attrs(), "printing attributes");
   434   if (x.is_null())  return;
   435   print_raw(" ");
   436   print_raw(attr);
   437   print_raw("='");
   438   object_text(x);
   439   print_raw("'");
   440 }
   442 void xmlStream::object_text(Handle x) {
   443   assert_if_no_error(inside_attrs(), "printing attributes");
   444   if (x.is_null())  return;
   445   //x->print_value_on(text());
   446   if (x->is_method())
   447     method_text(methodOop(x()));
   448   else if (x->is_klass())
   449     klass_text(klassOop(x()));
   450   else if (x->is_symbol())
   451     name_text(symbolOop(x()));
   452   else
   453     x->print_value_on(text());
   454 }
   457 void xmlStream::flush() {
   458   out()->flush();
   459   _last_flush = count();
   460 }
   462 void xmlTextStream::flush() {
   463   if (_outer_xmlStream == NULL)  return;
   464   _outer_xmlStream->flush();
   465 }
   467 void xmlTextStream::write(const char* str, size_t len) {
   468   if (_outer_xmlStream == NULL)  return;
   469   _outer_xmlStream->write_text(str, len);
   470   update_position(str, len);
   471 }

mercurial