src/share/vm/utilities/xmlstream.cpp

changeset 0
f90c822e73f8
child 6876
710a3c8b516e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/share/vm/utilities/xmlstream.cpp	Wed Apr 27 01:25:04 2016 +0800
     1.3 @@ -0,0 +1,500 @@
     1.4 +/*
     1.5 + * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.
    1.11 + *
    1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.15 + * version 2 for more details (a copy is included in the LICENSE file that
    1.16 + * accompanied this code).
    1.17 + *
    1.18 + * You should have received a copy of the GNU General Public License version
    1.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.21 + *
    1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    1.23 + * or visit www.oracle.com if you need additional information or have any
    1.24 + * questions.
    1.25 + *
    1.26 + */
    1.27 +
    1.28 +#include "precompiled.hpp"
    1.29 +#include "code/nmethod.hpp"
    1.30 +#include "memory/allocation.hpp"
    1.31 +#include "memory/allocation.inline.hpp"
    1.32 +#include "oops/methodData.hpp"
    1.33 +#include "oops/method.hpp"
    1.34 +#include "oops/oop.inline.hpp"
    1.35 +#include "runtime/deoptimization.hpp"
    1.36 +#include "runtime/vmThread.hpp"
    1.37 +#include "utilities/xmlstream.hpp"
    1.38 +
    1.39 +void xmlStream::initialize(outputStream* out) {
    1.40 +  _out = out;
    1.41 +  _last_flush = 0;
    1.42 +  _markup_state = BODY;
    1.43 +  _text_init._outer_xmlStream = this;
    1.44 +  _text = &_text_init;
    1.45 +
    1.46 +#ifdef ASSERT
    1.47 +  _element_depth = 0;
    1.48 +  int   init_len = 100;
    1.49 +  char* init_buf = NEW_C_HEAP_ARRAY(char, init_len, mtInternal);
    1.50 +  _element_close_stack_low  = init_buf;
    1.51 +  _element_close_stack_high = init_buf + init_len;
    1.52 +  _element_close_stack_ptr  = init_buf + init_len - 1;
    1.53 +  _element_close_stack_ptr[0] = '\0';
    1.54 +#endif
    1.55 +
    1.56 +  // Make sure each log uses the same base for time stamps.
    1.57 +  if (is_open()) {
    1.58 +    _out->time_stamp().update_to(1);
    1.59 +  }
    1.60 +}
    1.61 +
    1.62 +#ifdef ASSERT
    1.63 +xmlStream::~xmlStream() {
    1.64 +  FREE_C_HEAP_ARRAY(char, _element_close_stack_low, mtInternal);
    1.65 +}
    1.66 +#endif
    1.67 +
    1.68 +// Pass the given chars directly to _out.
    1.69 +void xmlStream::write(const char* s, size_t len) {
    1.70 +  if (!is_open())  return;
    1.71 +
    1.72 +  out()->write(s, len);
    1.73 +  update_position(s, len);
    1.74 +}
    1.75 +
    1.76 +
    1.77 +// Pass the given chars directly to _out, except that
    1.78 +// we watch for special "<&>" chars.
    1.79 +// This is suitable for either attribute text or for body text.
    1.80 +// We don't fool with "<![CDATA[" quotes, just single-character entities.
    1.81 +// This makes it easier for dumb tools to parse the output.
    1.82 +void xmlStream::write_text(const char* s, size_t len) {
    1.83 +  if (!is_open())  return;
    1.84 +
    1.85 +  size_t written = 0;
    1.86 +  // All normally printed material goes inside XML quotes.
    1.87 +  // This leaves the output free to include markup also.
    1.88 +  // Scan the string looking for inadvertant "<&>" chars
    1.89 +  for (size_t i = 0; i < len; i++) {
    1.90 +    char ch = s[i];
    1.91 +    // Escape special chars.
    1.92 +    const char* esc = NULL;
    1.93 +    switch (ch) {
    1.94 +      // These are important only in attrs, but we do them always:
    1.95 +    case '\'': esc = "&apos;"; break;
    1.96 +    case '"':  esc = "&quot;"; break;
    1.97 +    case '<':  esc = "&lt;";   break;
    1.98 +    case '&':  esc = "&amp;";  break;
    1.99 +      // This is a freebie.
   1.100 +    case '>':  esc = "&gt;";   break;
   1.101 +    }
   1.102 +    if (esc != NULL) {
   1.103 +      if (written < i) {
   1.104 +        out()->write(&s[written], i - written);
   1.105 +        written = i;
   1.106 +      }
   1.107 +      out()->print_raw(esc);
   1.108 +      written++;
   1.109 +    }
   1.110 +  }
   1.111 +
   1.112 +  // Print the clean remainder.  Usually, it is all of s.
   1.113 +  if (written < len) {
   1.114 +    out()->write(&s[written], len - written);
   1.115 +  }
   1.116 +}
   1.117 +
   1.118 +// ------------------------------------------------------------------
   1.119 +// Outputs XML text, with special characters quoted.
   1.120 +void xmlStream::text(const char* format, ...) {
   1.121 +  va_list ap;
   1.122 +  va_start(ap, format);
   1.123 +  va_text(format, ap);
   1.124 +  va_end(ap);
   1.125 +}
   1.126 +
   1.127 +#define BUFLEN 2*K   /* max size of output of individual print methods */
   1.128 +
   1.129 +// ------------------------------------------------------------------
   1.130 +void xmlStream::va_tag(bool push, const char* format, va_list ap) {
   1.131 +  assert_if_no_error(!inside_attrs(), "cannot print tag inside attrs");
   1.132 +  char buffer[BUFLEN];
   1.133 +  size_t len;
   1.134 +  const char* kind = do_vsnprintf(buffer, BUFLEN, format, ap, false, len);
   1.135 +  see_tag(kind, push);
   1.136 +  print_raw("<");
   1.137 +  write(kind, len);
   1.138 +  _markup_state = (push ? HEAD : ELEM);
   1.139 +}
   1.140 +
   1.141 +#ifdef ASSERT
   1.142 +/// Debugging goo to make sure element tags nest properly.
   1.143 +
   1.144 +// ------------------------------------------------------------------
   1.145 +void xmlStream::see_tag(const char* tag, bool push) {
   1.146 +  assert_if_no_error(!inside_attrs(), "cannot start new element inside attrs");
   1.147 +  if (!push)  return;
   1.148 +
   1.149 +  // tag goes up until either null or space:
   1.150 +  const char* tag_end = strchr(tag, ' ');
   1.151 +  size_t tag_len = (tag_end == NULL) ? strlen(tag) : tag_end - tag;
   1.152 +  assert(tag_len > 0, "tag must not be empty");
   1.153 +  // push the tag onto the stack, pulling down the pointer
   1.154 +  char* old_ptr  = _element_close_stack_ptr;
   1.155 +  char* old_low  = _element_close_stack_low;
   1.156 +  char* push_ptr = old_ptr - (tag_len+1);
   1.157 +  if (push_ptr < old_low) {
   1.158 +    int old_len = _element_close_stack_high - old_ptr;
   1.159 +    int new_len = old_len * 2;
   1.160 +    if (new_len < 100)  new_len = 100;
   1.161 +    char* new_low  = NEW_C_HEAP_ARRAY(char, new_len, mtInternal);
   1.162 +    char* new_high = new_low + new_len;
   1.163 +    char* new_ptr  = new_high - old_len;
   1.164 +    memcpy(new_ptr, old_ptr, old_len);
   1.165 +    _element_close_stack_high = new_high;
   1.166 +    _element_close_stack_low  = new_low;
   1.167 +    _element_close_stack_ptr  = new_ptr;
   1.168 +    FREE_C_HEAP_ARRAY(char, old_low, mtInternal);
   1.169 +    push_ptr = new_ptr - (tag_len+1);
   1.170 +  }
   1.171 +  assert(push_ptr >= _element_close_stack_low, "in range");
   1.172 +  memcpy(push_ptr, tag, tag_len);
   1.173 +  push_ptr[tag_len] = 0;
   1.174 +  _element_close_stack_ptr = push_ptr;
   1.175 +  _element_depth += 1;
   1.176 +}
   1.177 +
   1.178 +// ------------------------------------------------------------------
   1.179 +void xmlStream::pop_tag(const char* tag) {
   1.180 +  assert_if_no_error(!inside_attrs(), "cannot close element inside attrs");
   1.181 +  assert(_element_depth > 0, "must be in an element to close");
   1.182 +  assert(*tag != 0, "tag must not be empty");
   1.183 +  char* cur_tag = _element_close_stack_ptr;
   1.184 +  bool  bad_tag = false;
   1.185 +  while (*cur_tag != 0 && strcmp(cur_tag, tag) != 0) {
   1.186 +    this->print_cr("</%s> <!-- missing closing tag -->", cur_tag);
   1.187 +    _element_close_stack_ptr = (cur_tag += strlen(cur_tag) + 1);
   1.188 +    _element_depth -= 1;
   1.189 +    bad_tag = true;
   1.190 +  }
   1.191 +  if (*cur_tag == 0) {
   1.192 +    bad_tag = true;
   1.193 +  } else {
   1.194 +    // Pop the stack, by skipping over the tag and its null.
   1.195 +    _element_close_stack_ptr = cur_tag + strlen(cur_tag) + 1;
   1.196 +    _element_depth -= 1;
   1.197 +  }
   1.198 +  if (bad_tag && !VMThread::should_terminate() && !VM_Exit::vm_exited() &&
   1.199 +      !is_error_reported())
   1.200 +  {
   1.201 +    assert(false, "bad tag in log");
   1.202 +  }
   1.203 +}
   1.204 +#endif
   1.205 +
   1.206 +
   1.207 +// ------------------------------------------------------------------
   1.208 +// First word in formatted string is element kind, and any subsequent
   1.209 +// words must be XML attributes.  Outputs "<kind .../>".
   1.210 +void xmlStream::elem(const char* format, ...) {
   1.211 +  va_list ap;
   1.212 +  va_start(ap, format);
   1.213 +  va_elem(format, ap);
   1.214 +  va_end(ap);
   1.215 +}
   1.216 +
   1.217 +// ------------------------------------------------------------------
   1.218 +void xmlStream::va_elem(const char* format, va_list ap) {
   1.219 +  va_begin_elem(format, ap);
   1.220 +  end_elem();
   1.221 +}
   1.222 +
   1.223 +
   1.224 +// ------------------------------------------------------------------
   1.225 +// First word in formatted string is element kind, and any subsequent
   1.226 +// words must be XML attributes.  Outputs "<kind ...", not including "/>".
   1.227 +void xmlStream::begin_elem(const char* format, ...) {
   1.228 +  va_list ap;
   1.229 +  va_start(ap, format);
   1.230 +  va_tag(false, format, ap);
   1.231 +  va_end(ap);
   1.232 +}
   1.233 +
   1.234 +// ------------------------------------------------------------------
   1.235 +void xmlStream::va_begin_elem(const char* format, va_list ap) {
   1.236 +  va_tag(false, format, ap);
   1.237 +}
   1.238 +
   1.239 +// ------------------------------------------------------------------
   1.240 +// Outputs "/>".
   1.241 +void xmlStream::end_elem() {
   1.242 +  assert(_markup_state == ELEM, "misplaced end_elem");
   1.243 +  print_raw("/>\n");
   1.244 +  _markup_state = BODY;
   1.245 +}
   1.246 +
   1.247 +// ------------------------------------------------------------------
   1.248 +// Outputs formatted text, followed by "/>".
   1.249 +void xmlStream::end_elem(const char* format, ...) {
   1.250 +  va_list ap;
   1.251 +  va_start(ap, format);
   1.252 +  out()->vprint(format, ap);
   1.253 +  va_end(ap);
   1.254 +  end_elem();
   1.255 +}
   1.256 +
   1.257 +
   1.258 +// ------------------------------------------------------------------
   1.259 +// First word in formatted string is element kind, and any subsequent
   1.260 +// words must be XML attributes.  Outputs "<kind ...>".
   1.261 +void xmlStream::head(const char* format, ...) {
   1.262 +  va_list ap;
   1.263 +  va_start(ap, format);
   1.264 +  va_head(format, ap);
   1.265 +  va_end(ap);
   1.266 +}
   1.267 +
   1.268 +// ------------------------------------------------------------------
   1.269 +void xmlStream::va_head(const char* format, va_list ap) {
   1.270 +  va_begin_head(format, ap);
   1.271 +  end_head();
   1.272 +}
   1.273 +
   1.274 +// ------------------------------------------------------------------
   1.275 +// First word in formatted string is element kind, and any subsequent
   1.276 +// words must be XML attributes.  Outputs "<kind ...", not including ">".
   1.277 +void xmlStream::begin_head(const char* format, ...) {
   1.278 +  va_list ap;
   1.279 +  va_start(ap, format);
   1.280 +  va_tag(true, format, ap);
   1.281 +  va_end(ap);
   1.282 +}
   1.283 +
   1.284 +// ------------------------------------------------------------------
   1.285 +void xmlStream::va_begin_head(const char* format, va_list ap) {
   1.286 +  va_tag(true, format, ap);
   1.287 +}
   1.288 +
   1.289 +// ------------------------------------------------------------------
   1.290 +// Outputs ">".
   1.291 +void xmlStream::end_head() {
   1.292 +  assert(_markup_state == HEAD, "misplaced end_head");
   1.293 +  print_raw(">\n");
   1.294 +  _markup_state = BODY;
   1.295 +}
   1.296 +
   1.297 +
   1.298 +// ------------------------------------------------------------------
   1.299 +// Outputs formatted text, followed by ">".
   1.300 +void xmlStream::end_head(const char* format, ...) {
   1.301 +  va_list ap;
   1.302 +  va_start(ap, format);
   1.303 +  out()->vprint(format, ap);
   1.304 +  va_end(ap);
   1.305 +  end_head();
   1.306 +}
   1.307 +
   1.308 +
   1.309 +// ------------------------------------------------------------------
   1.310 +// Outputs "</kind>".
   1.311 +void xmlStream::tail(const char* kind) {
   1.312 +  pop_tag(kind);
   1.313 +  print_raw("</");
   1.314 +  print_raw(kind);
   1.315 +  print_raw(">\n");
   1.316 +}
   1.317 +
   1.318 +// ------------------------------------------------------------------
   1.319 +// Outputs "<kind_done ... stamp='D.DD'/> </kind>".
   1.320 +void xmlStream::done(const char* format, ...) {
   1.321 +  va_list ap;
   1.322 +  va_start(ap, format);
   1.323 +  va_done(format, ap);
   1.324 +  va_end(ap);
   1.325 +}
   1.326 +
   1.327 +// ------------------------------------------------------------------
   1.328 +// Outputs "<kind_done stamp='D.DD'/> </kind>".
   1.329 +// Because done_raw() doesn't need to format strings, it's simpler than
   1.330 +// done(), and can be called safely by fatal error handler.
   1.331 +void xmlStream::done_raw(const char* kind) {
   1.332 +  print_raw("<");
   1.333 +  print_raw(kind);
   1.334 +  print_raw("_done stamp='");
   1.335 +  out()->stamp();
   1.336 +  print_raw_cr("'/>");
   1.337 +  print_raw("</");
   1.338 +  print_raw(kind);
   1.339 +  print_raw_cr(">");
   1.340 +}
   1.341 +
   1.342 +PRAGMA_DIAG_PUSH
   1.343 +PRAGMA_FORMAT_NONLITERAL_IGNORED
   1.344 +// ------------------------------------------------------------------
   1.345 +void xmlStream::va_done(const char* format, va_list ap) {
   1.346 +  char buffer[200];
   1.347 +  guarantee(strlen(format) + 10 < sizeof(buffer), "bigger format buffer");
   1.348 +  const char* kind = format;
   1.349 +  const char* kind_end = strchr(kind, ' ');
   1.350 +  size_t kind_len = (kind_end != NULL) ? (kind_end - kind) : strlen(kind);
   1.351 +  strncpy(buffer, kind, kind_len);
   1.352 +  strcpy(buffer + kind_len, "_done");
   1.353 +  strcat(buffer, format + kind_len);
   1.354 +  // Output the trailing event with the timestamp.
   1.355 +  va_begin_elem(buffer, ap);
   1.356 +  stamp();
   1.357 +  end_elem();
   1.358 +  // Output the tail-tag of the enclosing element.
   1.359 +  buffer[kind_len] = 0;
   1.360 +  tail(buffer);
   1.361 +}
   1.362 +PRAGMA_DIAG_POP
   1.363 +
   1.364 +// Output a timestamp attribute.
   1.365 +void xmlStream::stamp() {
   1.366 +  assert_if_no_error(inside_attrs(), "stamp must be an attribute");
   1.367 +  print_raw(" stamp='");
   1.368 +  out()->stamp();
   1.369 +  print_raw("'");
   1.370 +}
   1.371 +
   1.372 +
   1.373 +// ------------------------------------------------------------------
   1.374 +// Output a method attribute, in the form " method='pkg/cls name sig'".
   1.375 +// This is used only when there is no ciMethod available.
   1.376 +void xmlStream::method(methodHandle method) {
   1.377 +  assert_if_no_error(inside_attrs(), "printing attributes");
   1.378 +  if (method.is_null())  return;
   1.379 +  print_raw(" method='");
   1.380 +  method_text(method);
   1.381 +  print("' bytes='%d'", method->code_size());
   1.382 +  print(" count='%d'", method->invocation_count());
   1.383 +  int bec = method->backedge_count();
   1.384 +  if (bec != 0)  print(" backedge_count='%d'", bec);
   1.385 +  print(" iicount='%d'", method->interpreter_invocation_count());
   1.386 +  int throwouts = method->interpreter_throwout_count();
   1.387 +  if (throwouts != 0)  print(" throwouts='%d'", throwouts);
   1.388 +  MethodData* mdo = method->method_data();
   1.389 +  if (mdo != NULL) {
   1.390 +    uint cnt;
   1.391 +    cnt = mdo->decompile_count();
   1.392 +    if (cnt != 0)  print(" decompiles='%d'", cnt);
   1.393 +    for (uint reason = 0; reason < mdo->trap_reason_limit(); reason++) {
   1.394 +      cnt = mdo->trap_count(reason);
   1.395 +      if (cnt != 0)  print(" %s_traps='%d'", Deoptimization::trap_reason_name(reason), cnt);
   1.396 +    }
   1.397 +    cnt = mdo->overflow_trap_count();
   1.398 +    if (cnt != 0)  print(" overflow_traps='%d'", cnt);
   1.399 +    cnt = mdo->overflow_recompile_count();
   1.400 +    if (cnt != 0)  print(" overflow_recompiles='%d'", cnt);
   1.401 +  }
   1.402 +}
   1.403 +
   1.404 +void xmlStream::method_text(methodHandle method) {
   1.405 +  assert_if_no_error(inside_attrs(), "printing attributes");
   1.406 +  if (method.is_null())  return;
   1.407 +  //method->print_short_name(text());
   1.408 +  method->method_holder()->name()->print_symbol_on(text());
   1.409 +  print_raw(" ");  // " " is easier for tools to parse than "::"
   1.410 +  method->name()->print_symbol_on(text());
   1.411 +  print_raw(" ");  // separator
   1.412 +  method->signature()->print_symbol_on(text());
   1.413 +}
   1.414 +
   1.415 +
   1.416 +// ------------------------------------------------------------------
   1.417 +// Output a klass attribute, in the form " klass='pkg/cls'".
   1.418 +// This is used only when there is no ciKlass available.
   1.419 +void xmlStream::klass(KlassHandle klass) {
   1.420 +  assert_if_no_error(inside_attrs(), "printing attributes");
   1.421 +  if (klass.is_null())  return;
   1.422 +  print_raw(" klass='");
   1.423 +  klass_text(klass);
   1.424 +  print_raw("'");
   1.425 +}
   1.426 +
   1.427 +void xmlStream::klass_text(KlassHandle klass) {
   1.428 +  assert_if_no_error(inside_attrs(), "printing attributes");
   1.429 +  if (klass.is_null())  return;
   1.430 +  //klass->print_short_name(log->out());
   1.431 +  klass->name()->print_symbol_on(out());
   1.432 +}
   1.433 +
   1.434 +void xmlStream::name(const Symbol* name) {
   1.435 +  assert_if_no_error(inside_attrs(), "printing attributes");
   1.436 +  if (name == NULL)  return;
   1.437 +  print_raw(" name='");
   1.438 +  name_text(name);
   1.439 +  print_raw("'");
   1.440 +}
   1.441 +
   1.442 +void xmlStream::name_text(const Symbol* name) {
   1.443 +  assert_if_no_error(inside_attrs(), "printing attributes");
   1.444 +  if (name == NULL)  return;
   1.445 +  //name->print_short_name(text());
   1.446 +  name->print_symbol_on(text());
   1.447 +}
   1.448 +
   1.449 +void xmlStream::object(const char* attr, Handle x) {
   1.450 +  assert_if_no_error(inside_attrs(), "printing attributes");
   1.451 +  if (x == NULL)  return;
   1.452 +  print_raw(" ");
   1.453 +  print_raw(attr);
   1.454 +  print_raw("='");
   1.455 +  object_text(x);
   1.456 +  print_raw("'");
   1.457 +}
   1.458 +
   1.459 +void xmlStream::object_text(Handle x) {
   1.460 +  assert_if_no_error(inside_attrs(), "printing attributes");
   1.461 +  if (x == NULL)  return;
   1.462 +  x->print_value_on(text());
   1.463 +}
   1.464 +
   1.465 +
   1.466 +void xmlStream::object(const char* attr, Metadata* x) {
   1.467 +  assert_if_no_error(inside_attrs(), "printing attributes");
   1.468 +  if (x == NULL)  return;
   1.469 +  print_raw(" ");
   1.470 +  print_raw(attr);
   1.471 +  print_raw("='");
   1.472 +  object_text(x);
   1.473 +  print_raw("'");
   1.474 +}
   1.475 +
   1.476 +void xmlStream::object_text(Metadata* x) {
   1.477 +  assert_if_no_error(inside_attrs(), "printing attributes");
   1.478 +  if (x == NULL)  return;
   1.479 +  //x->print_value_on(text());
   1.480 +  if (x->is_method())
   1.481 +    method_text((Method*)x);
   1.482 +  else if (x->is_klass())
   1.483 +    klass_text((Klass*)x);
   1.484 +  else
   1.485 +    ShouldNotReachHere(); // Add impl if this is reached.
   1.486 +}
   1.487 +
   1.488 +
   1.489 +void xmlStream::flush() {
   1.490 +  out()->flush();
   1.491 +  _last_flush = count();
   1.492 +}
   1.493 +
   1.494 +void xmlTextStream::flush() {
   1.495 +  if (_outer_xmlStream == NULL)  return;
   1.496 +  _outer_xmlStream->flush();
   1.497 +}
   1.498 +
   1.499 +void xmlTextStream::write(const char* str, size_t len) {
   1.500 +  if (_outer_xmlStream == NULL)  return;
   1.501 +  _outer_xmlStream->write_text(str, len);
   1.502 +  update_position(str, len);
   1.503 +}

mercurial