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 = "'"; break; 1.96 + case '"': esc = """; break; 1.97 + case '<': esc = "<"; break; 1.98 + case '&': esc = "&"; break; 1.99 + // This is a freebie. 1.100 + case '>': esc = ">"; 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 +}