Thu, 20 Nov 2008 16:56:09 -0800
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 = "'"; break;
85 case '"': esc = """; break;
86 case '<': esc = "<"; break;
87 case '&': esc = "&"; break;
88 // This is a freebie.
89 case '>': esc = ">"; 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 }