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

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

mercurial