Mercurial > hg > truffle
annotate src/share/vm/compiler/compileLog.cpp @ 1994:6cd6d394f280
7001033: assert(gch->gc_cause() == GCCause::_scavenge_alot || !gch->incremental_collection_failed())
7002546: regression on SpecJbb2005 on 7b118 comparing to 7b117 on small heaps
Summary: Relaxed assertion checking related to incremental_collection_failed flag to allow for ExplicitGCInvokesConcurrent behaviour where we do not want a failing scavenge to bail to a stop-world collection. Parameterized incremental_collection_will_fail() so we can selectively use, or not use, as appropriate, the statistical prediction at specific use sites. This essentially reverts the scavenge bail-out logic to what it was prior to some recent changes that had inadvertently started using the statistical prediction which can be noisy in the presence of bursty loads. Added some associated verbose non-product debugging messages.
Reviewed-by: johnc, tonyp
author | ysr |
---|---|
date | Tue, 07 Dec 2010 21:55:53 -0800 |
parents | f95d63e2154a |
children | d2a62e0f25eb |
rev | line source |
---|---|
0 | 1 /* |
1972 | 2 * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. |
0 | 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1489
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1489
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1489
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "ci/ciMethod.hpp" | |
27 #include "compiler/compileLog.hpp" | |
28 #include "memory/allocation.inline.hpp" | |
29 #include "oops/methodOop.hpp" | |
30 #include "runtime/mutexLocker.hpp" | |
31 #include "runtime/os.hpp" | |
0 | 32 |
33 CompileLog* CompileLog::_first = NULL; | |
34 | |
35 // ------------------------------------------------------------------ | |
36 // CompileLog::CompileLog | |
37 CompileLog::CompileLog(const char* file, FILE* fp, intx thread_id) | |
38 : _context(_context_buffer, sizeof(_context_buffer)) | |
39 { | |
40 initialize(new(ResourceObj::C_HEAP) fileStream(fp)); | |
41 _file = file; | |
42 _file_end = 0; | |
43 _thread_id = thread_id; | |
44 | |
45 _identities_limit = 0; | |
46 _identities_capacity = 400; | |
47 _identities = NEW_C_HEAP_ARRAY(char, _identities_capacity); | |
48 | |
49 // link into the global list | |
50 { MutexLocker locker(CompileTaskAlloc_lock); | |
51 _next = _first; | |
52 _first = this; | |
53 } | |
54 } | |
55 | |
56 CompileLog::~CompileLog() { | |
57 delete _out; | |
58 _out = NULL; | |
59 FREE_C_HEAP_ARRAY(char, _identities); | |
60 } | |
61 | |
62 | |
63 // Advance kind up to a null or space, return this tail. | |
64 // Make sure kind is null-terminated, not space-terminated. | |
65 // Use the buffer if necessary. | |
66 static const char* split_attrs(const char* &kind, char* buffer) { | |
67 const char* attrs = strchr(kind, ' '); | |
68 // Tease apart the first word from the rest: | |
69 if (attrs == NULL) { | |
70 return ""; // no attrs, no split | |
71 } else if (kind == buffer) { | |
72 ((char*) attrs)[-1] = 0; | |
73 return attrs; | |
74 } else { | |
75 // park it in the buffer, so we can put a null on the end | |
1489
cff162798819
6888953: some calls to function-like macros are missing semicolons
jcoomes
parents:
0
diff
changeset
|
76 assert(!(kind >= buffer && kind < buffer+100), "not obviously in buffer"); |
0 | 77 int klen = attrs - kind; |
78 strncpy(buffer, kind, klen); | |
79 buffer[klen] = 0; | |
80 kind = buffer; // return by reference | |
81 return attrs; | |
82 } | |
83 } | |
84 | |
85 // see_tag, pop_tag: Override the default do-nothing methods on xmlStream. | |
86 // These methods provide a hook for managing the the extra context markup. | |
87 void CompileLog::see_tag(const char* tag, bool push) { | |
88 if (_context.size() > 0 && _out != NULL) { | |
89 _out->write(_context.base(), _context.size()); | |
90 _context.reset(); | |
91 } | |
92 xmlStream::see_tag(tag, push); | |
93 } | |
94 void CompileLog::pop_tag(const char* tag) { | |
95 _context.reset(); // toss any context info. | |
96 xmlStream::pop_tag(tag); | |
97 } | |
98 | |
99 | |
100 // ------------------------------------------------------------------ | |
101 // CompileLog::identify | |
102 int CompileLog::identify(ciObject* obj) { | |
103 if (obj == NULL) return 0; | |
104 int id = obj->ident(); | |
105 if (id < 0) return id; | |
106 // If it has already been identified, just return the id. | |
107 if (id < _identities_limit && _identities[id] != 0) return id; | |
108 // Lengthen the array, if necessary. | |
109 if (id >= _identities_capacity) { | |
110 int new_cap = _identities_capacity * 2; | |
111 if (new_cap <= id) new_cap = id + 100; | |
112 _identities = REALLOC_C_HEAP_ARRAY(char, _identities, new_cap); | |
113 _identities_capacity = new_cap; | |
114 } | |
115 while (id >= _identities_limit) { | |
116 _identities[_identities_limit++] = 0; | |
117 } | |
118 assert(id < _identities_limit, "oob"); | |
119 // Mark this id as processed. | |
120 // (Be sure to do this before any recursive calls to identify.) | |
121 _identities[id] = 1; // mark | |
122 | |
123 // Now, print the object's identity once, in detail. | |
124 if (obj->is_klass()) { | |
125 ciKlass* klass = obj->as_klass(); | |
126 begin_elem("klass id='%d'", id); | |
127 name(klass->name()); | |
128 if (!klass->is_loaded()) { | |
129 print(" unloaded='1'"); | |
130 } else { | |
131 print(" flags='%d'", klass->modifier_flags()); | |
132 } | |
133 end_elem(); | |
134 } else if (obj->is_method()) { | |
135 ciMethod* method = obj->as_method(); | |
136 ciSignature* sig = method->signature(); | |
137 // Pre-identify items that we will need! | |
138 identify(sig->return_type()); | |
139 for (int i = 0; i < sig->count(); i++) { | |
140 identify(sig->type_at(i)); | |
141 } | |
142 begin_elem("method id='%d' holder='%d'", | |
143 id, identify(method->holder())); | |
144 name(method->name()); | |
145 print(" return='%d'", identify(sig->return_type())); | |
146 if (sig->count() > 0) { | |
147 print(" arguments='"); | |
148 for (int i = 0; i < sig->count(); i++) { | |
149 print((i == 0) ? "%d" : " %d", identify(sig->type_at(i))); | |
150 } | |
151 print("'"); | |
152 } | |
153 if (!method->is_loaded()) { | |
154 print(" unloaded='1'"); | |
155 } else { | |
156 print(" flags='%d'", (jchar) method->flags().as_int()); | |
157 // output a few metrics | |
158 print(" bytes='%d'", method->code_size()); | |
159 method->log_nmethod_identity(this); | |
160 //print(" count='%d'", method->invocation_count()); | |
161 //int bec = method->backedge_count(); | |
162 //if (bec != 0) print(" backedge_count='%d'", bec); | |
163 print(" iicount='%d'", method->interpreter_invocation_count()); | |
164 } | |
165 end_elem(); | |
166 } else if (obj->is_symbol()) { | |
167 begin_elem("symbol id='%d'", id); | |
168 name(obj->as_symbol()); | |
169 end_elem(); | |
170 } else if (obj->is_null_object()) { | |
171 elem("null_object id='%d'", id); | |
172 } else if (obj->is_type()) { | |
173 BasicType type = obj->as_type()->basic_type(); | |
174 elem("type id='%d' name='%s'", id, type2name(type)); | |
175 } else { | |
176 // Should not happen. | |
177 elem("unknown id='%d'", id); | |
178 } | |
179 return id; | |
180 } | |
181 | |
182 void CompileLog::name(ciSymbol* name) { | |
183 if (name == NULL) return; | |
184 print(" name='"); | |
185 name->print_symbol_on(text()); // handles quoting conventions | |
186 print("'"); | |
187 } | |
188 | |
189 | |
190 // ------------------------------------------------------------------ | |
191 // CompileLog::clear_identities | |
192 // Forget which identities have been printed. | |
193 void CompileLog::clear_identities() { | |
194 _identities_limit = 0; | |
195 } | |
196 | |
197 // ------------------------------------------------------------------ | |
198 // CompileLog::finish_log_on_error | |
199 // | |
200 // Note: This function is called after fatal error, avoid unnecessary memory | |
201 // or stack allocation, use only async-safe functions. It's possible JVM is | |
202 // only partially initialized. | |
203 void CompileLog::finish_log_on_error(outputStream* file, char* buf, int buflen) { | |
204 static bool called_exit = false; | |
205 if (called_exit) return; | |
206 called_exit = true; | |
207 | |
208 for (CompileLog* log = _first; log != NULL; log = log->_next) { | |
209 log->flush(); | |
210 const char* partial_file = log->file(); | |
211 int partial_fd = open(partial_file, O_RDONLY); | |
212 if (partial_fd != -1) { | |
213 // print/print_cr may need to allocate large stack buffer to format | |
214 // strings, here we use snprintf() and print_raw() instead. | |
215 file->print_raw("<compilation_log thread='"); | |
216 jio_snprintf(buf, buflen, UINTX_FORMAT, log->thread_id()); | |
217 file->print_raw(buf); | |
218 file->print_raw_cr("'>"); | |
219 | |
220 size_t nr; // number read into buf from partial log | |
221 // Copy data up to the end of the last <event> element: | |
222 julong to_read = log->_file_end; | |
223 while (to_read > 0) { | |
224 if (to_read < (julong)buflen) | |
225 nr = (size_t)to_read; | |
226 else nr = buflen; | |
227 nr = read(partial_fd, buf, (int)nr); | |
228 if (nr <= 0) break; | |
229 to_read -= (julong)nr; | |
230 file->write(buf, nr); | |
231 } | |
232 | |
233 // Copy any remaining data inside a quote: | |
234 bool saw_slop = false; | |
235 int end_cdata = 0; // state machine [0..2] watching for too many "]]" | |
236 while ((nr = read(partial_fd, buf, buflen)) > 0) { | |
237 if (!saw_slop) { | |
238 file->print_raw_cr("<fragment>"); | |
239 file->print_raw_cr("<![CDATA["); | |
240 saw_slop = true; | |
241 } | |
242 // The rest of this loop amounts to a simple copy operation: | |
243 // { file->write(buf, nr); } | |
244 // However, it must sometimes output the buffer in parts, | |
245 // in case there is a CDATA quote embedded in the fragment. | |
246 const char* bufp; // pointer into buf | |
247 size_t nw; // number written in each pass of the following loop: | |
248 for (bufp = buf; nr > 0; nr -= nw, bufp += nw) { | |
249 // Write up to any problematic CDATA delimiter (usually all of nr). | |
250 for (nw = 0; nw < nr; nw++) { | |
251 // First, scan ahead into the buf, checking the state machine. | |
252 switch (bufp[nw]) { | |
253 case ']': | |
254 if (end_cdata < 2) end_cdata += 1; // saturating counter | |
255 continue; // keep scanning | |
256 case '>': | |
257 if (end_cdata == 2) break; // found CDATA delimiter! | |
258 // else fall through: | |
259 default: | |
260 end_cdata = 0; | |
261 continue; // keep scanning | |
262 } | |
263 // If we get here, nw is pointing at a bad '>'. | |
264 // It is very rare for this to happen. | |
265 // However, this code has been tested by introducing | |
266 // CDATA sequences into the compilation log. | |
267 break; | |
268 } | |
269 // Now nw is the number of characters to write, usually == nr. | |
270 file->write(bufp, nw); | |
271 if (nw < nr) { | |
272 // We are about to go around the loop again. | |
273 // But first, disrupt the ]]> by closing and reopening the quote. | |
274 file->print_raw("]]><![CDATA["); | |
275 end_cdata = 0; // reset state machine | |
276 } | |
277 } | |
278 } | |
279 if (saw_slop) { | |
280 file->print_raw_cr("]]>"); | |
281 file->print_raw_cr("</fragment>"); | |
282 } | |
283 file->print_raw_cr("</compilation_log>"); | |
284 close(partial_fd); | |
285 unlink(partial_file); | |
286 } | |
287 } | |
288 } | |
289 | |
290 // ------------------------------------------------------------------ | |
291 // CompileLog::finish_log | |
292 // | |
293 // Called during normal shutdown. For now, any clean-up needed in normal | |
294 // shutdown is also needed in VM abort, so is covered by finish_log_on_error(). | |
295 // Just allocate a buffer and call finish_log_on_error(). | |
296 void CompileLog::finish_log(outputStream* file) { | |
297 char buf[4 * K]; | |
298 finish_log_on_error(file, buf, sizeof(buf)); | |
299 } |