Mercurial > hg > truffle
annotate src/share/vm/compiler/compileLog.cpp @ 9126:bc26f978b0ce
HotSpotResolvedObjectType: implement hasFinalizeSubclass() correctly
don't use the (wrong) cached value, but ask the runtime on each request.
Fixes regression on xml.* benchmarks @ specjvm2008. The problem was:
After the constructor of Object was deoptimized due to an assumption violation,
it was recompiled again after some time. However, on recompilation, the value
of hasFinalizeSubclass for the class was not updated and it was compiled again
with a, now wrong, assumption, which then triggers deoptimization again.
This was repeated until it hit the recompilation limit (defined by
PerMethodRecompilationCutoff), and therefore only executed by the interpreter
from now on, causing the performance regression.
author | Bernhard Urban <bernhard.urban@jku.at> |
---|---|
date | Mon, 15 Apr 2013 19:54:58 +0200 |
parents | cc32ccaaf47f |
children | 813f26e34135 |
rev | line source |
---|---|
0 | 1 /* |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
2 * Copyright (c) 2002, 2012, 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" | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
29 #include "oops/method.hpp" |
1972 | 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 { | |
6197 | 40 initialize(new(ResourceObj::C_HEAP, mtCompiler) fileStream(fp)); |
0 | 41 _file = file; |
42 _file_end = 0; | |
43 _thread_id = thread_id; | |
44 | |
45 _identities_limit = 0; | |
46 _identities_capacity = 400; | |
6197 | 47 _identities = NEW_C_HEAP_ARRAY(char, _identities_capacity, mtCompiler); |
0 | 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; | |
6197 | 59 FREE_C_HEAP_ARRAY(char, _identities, mtCompiler); |
0 | 60 } |
61 | |
62 | |
63 // see_tag, pop_tag: Override the default do-nothing methods on xmlStream. | |
64 // These methods provide a hook for managing the the extra context markup. | |
65 void CompileLog::see_tag(const char* tag, bool push) { | |
66 if (_context.size() > 0 && _out != NULL) { | |
67 _out->write(_context.base(), _context.size()); | |
68 _context.reset(); | |
69 } | |
70 xmlStream::see_tag(tag, push); | |
71 } | |
72 void CompileLog::pop_tag(const char* tag) { | |
73 _context.reset(); // toss any context info. | |
74 xmlStream::pop_tag(tag); | |
75 } | |
76 | |
77 | |
78 // ------------------------------------------------------------------ | |
79 // CompileLog::identify | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
80 int CompileLog::identify(ciBaseObject* obj) { |
0 | 81 if (obj == NULL) return 0; |
82 int id = obj->ident(); | |
83 if (id < 0) return id; | |
84 // If it has already been identified, just return the id. | |
85 if (id < _identities_limit && _identities[id] != 0) return id; | |
86 // Lengthen the array, if necessary. | |
87 if (id >= _identities_capacity) { | |
88 int new_cap = _identities_capacity * 2; | |
89 if (new_cap <= id) new_cap = id + 100; | |
6197 | 90 _identities = REALLOC_C_HEAP_ARRAY(char, _identities, new_cap, mtCompiler); |
0 | 91 _identities_capacity = new_cap; |
92 } | |
93 while (id >= _identities_limit) { | |
94 _identities[_identities_limit++] = 0; | |
95 } | |
96 assert(id < _identities_limit, "oob"); | |
97 // Mark this id as processed. | |
98 // (Be sure to do this before any recursive calls to identify.) | |
99 _identities[id] = 1; // mark | |
100 | |
101 // Now, print the object's identity once, in detail. | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
102 if (obj->is_metadata()) { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
103 ciMetadata* mobj = obj->as_metadata(); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
104 if (mobj->is_klass()) { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
105 ciKlass* klass = mobj->as_klass(); |
6800
9191895df19d
7200001: failed C1 OSR compile doesn't get recompiled with C2
twisti
parents:
6725
diff
changeset
|
106 begin_elem("klass id='%d'", id); |
9191895df19d
7200001: failed C1 OSR compile doesn't get recompiled with C2
twisti
parents:
6725
diff
changeset
|
107 name(klass->name()); |
9191895df19d
7200001: failed C1 OSR compile doesn't get recompiled with C2
twisti
parents:
6725
diff
changeset
|
108 if (!klass->is_loaded()) { |
9191895df19d
7200001: failed C1 OSR compile doesn't get recompiled with C2
twisti
parents:
6725
diff
changeset
|
109 print(" unloaded='1'"); |
9191895df19d
7200001: failed C1 OSR compile doesn't get recompiled with C2
twisti
parents:
6725
diff
changeset
|
110 } else { |
9191895df19d
7200001: failed C1 OSR compile doesn't get recompiled with C2
twisti
parents:
6725
diff
changeset
|
111 print(" flags='%d'", klass->modifier_flags()); |
9191895df19d
7200001: failed C1 OSR compile doesn't get recompiled with C2
twisti
parents:
6725
diff
changeset
|
112 } |
9191895df19d
7200001: failed C1 OSR compile doesn't get recompiled with C2
twisti
parents:
6725
diff
changeset
|
113 end_elem(); |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
114 } else if (mobj->is_method()) { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
115 ciMethod* method = mobj->as_method(); |
6800
9191895df19d
7200001: failed C1 OSR compile doesn't get recompiled with C2
twisti
parents:
6725
diff
changeset
|
116 ciSignature* sig = method->signature(); |
9191895df19d
7200001: failed C1 OSR compile doesn't get recompiled with C2
twisti
parents:
6725
diff
changeset
|
117 // Pre-identify items that we will need! |
9191895df19d
7200001: failed C1 OSR compile doesn't get recompiled with C2
twisti
parents:
6725
diff
changeset
|
118 identify(sig->return_type()); |
0 | 119 for (int i = 0; i < sig->count(); i++) { |
6800
9191895df19d
7200001: failed C1 OSR compile doesn't get recompiled with C2
twisti
parents:
6725
diff
changeset
|
120 identify(sig->type_at(i)); |
0 | 121 } |
6800
9191895df19d
7200001: failed C1 OSR compile doesn't get recompiled with C2
twisti
parents:
6725
diff
changeset
|
122 begin_elem("method id='%d' holder='%d'", |
9191895df19d
7200001: failed C1 OSR compile doesn't get recompiled with C2
twisti
parents:
6725
diff
changeset
|
123 id, identify(method->holder())); |
9191895df19d
7200001: failed C1 OSR compile doesn't get recompiled with C2
twisti
parents:
6725
diff
changeset
|
124 name(method->name()); |
9191895df19d
7200001: failed C1 OSR compile doesn't get recompiled with C2
twisti
parents:
6725
diff
changeset
|
125 print(" return='%d'", identify(sig->return_type())); |
9191895df19d
7200001: failed C1 OSR compile doesn't get recompiled with C2
twisti
parents:
6725
diff
changeset
|
126 if (sig->count() > 0) { |
9191895df19d
7200001: failed C1 OSR compile doesn't get recompiled with C2
twisti
parents:
6725
diff
changeset
|
127 print(" arguments='"); |
9191895df19d
7200001: failed C1 OSR compile doesn't get recompiled with C2
twisti
parents:
6725
diff
changeset
|
128 for (int i = 0; i < sig->count(); i++) { |
9191895df19d
7200001: failed C1 OSR compile doesn't get recompiled with C2
twisti
parents:
6725
diff
changeset
|
129 print((i == 0) ? "%d" : " %d", identify(sig->type_at(i))); |
9191895df19d
7200001: failed C1 OSR compile doesn't get recompiled with C2
twisti
parents:
6725
diff
changeset
|
130 } |
9191895df19d
7200001: failed C1 OSR compile doesn't get recompiled with C2
twisti
parents:
6725
diff
changeset
|
131 print("'"); |
9191895df19d
7200001: failed C1 OSR compile doesn't get recompiled with C2
twisti
parents:
6725
diff
changeset
|
132 } |
9191895df19d
7200001: failed C1 OSR compile doesn't get recompiled with C2
twisti
parents:
6725
diff
changeset
|
133 if (!method->is_loaded()) { |
9191895df19d
7200001: failed C1 OSR compile doesn't get recompiled with C2
twisti
parents:
6725
diff
changeset
|
134 print(" unloaded='1'"); |
9191895df19d
7200001: failed C1 OSR compile doesn't get recompiled with C2
twisti
parents:
6725
diff
changeset
|
135 } else { |
9191895df19d
7200001: failed C1 OSR compile doesn't get recompiled with C2
twisti
parents:
6725
diff
changeset
|
136 print(" flags='%d'", (jchar) method->flags().as_int()); |
9191895df19d
7200001: failed C1 OSR compile doesn't get recompiled with C2
twisti
parents:
6725
diff
changeset
|
137 // output a few metrics |
9191895df19d
7200001: failed C1 OSR compile doesn't get recompiled with C2
twisti
parents:
6725
diff
changeset
|
138 print(" bytes='%d'", method->code_size()); |
9191895df19d
7200001: failed C1 OSR compile doesn't get recompiled with C2
twisti
parents:
6725
diff
changeset
|
139 method->log_nmethod_identity(this); |
9191895df19d
7200001: failed C1 OSR compile doesn't get recompiled with C2
twisti
parents:
6725
diff
changeset
|
140 //print(" count='%d'", method->invocation_count()); |
9191895df19d
7200001: failed C1 OSR compile doesn't get recompiled with C2
twisti
parents:
6725
diff
changeset
|
141 //int bec = method->backedge_count(); |
9191895df19d
7200001: failed C1 OSR compile doesn't get recompiled with C2
twisti
parents:
6725
diff
changeset
|
142 //if (bec != 0) print(" backedge_count='%d'", bec); |
9191895df19d
7200001: failed C1 OSR compile doesn't get recompiled with C2
twisti
parents:
6725
diff
changeset
|
143 print(" iicount='%d'", method->interpreter_invocation_count()); |
9191895df19d
7200001: failed C1 OSR compile doesn't get recompiled with C2
twisti
parents:
6725
diff
changeset
|
144 } |
9191895df19d
7200001: failed C1 OSR compile doesn't get recompiled with C2
twisti
parents:
6725
diff
changeset
|
145 end_elem(); |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
146 } else if (mobj->is_type()) { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
147 BasicType type = mobj->as_type()->basic_type(); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
148 elem("type id='%d' name='%s'", id, type2name(type)); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
149 } else { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
150 // Should not happen. |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
151 elem("unknown id='%d'", id); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
152 ShouldNotReachHere(); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
153 } |
0 | 154 } else if (obj->is_symbol()) { |
155 begin_elem("symbol id='%d'", id); | |
156 name(obj->as_symbol()); | |
157 end_elem(); | |
158 } else { | |
159 // Should not happen. | |
160 elem("unknown id='%d'", id); | |
161 } | |
162 return id; | |
163 } | |
164 | |
165 void CompileLog::name(ciSymbol* name) { | |
166 if (name == NULL) return; | |
167 print(" name='"); | |
168 name->print_symbol_on(text()); // handles quoting conventions | |
169 print("'"); | |
170 } | |
171 | |
172 | |
173 // ------------------------------------------------------------------ | |
174 // CompileLog::clear_identities | |
175 // Forget which identities have been printed. | |
176 void CompileLog::clear_identities() { | |
177 _identities_limit = 0; | |
178 } | |
179 | |
180 // ------------------------------------------------------------------ | |
181 // CompileLog::finish_log_on_error | |
182 // | |
183 // Note: This function is called after fatal error, avoid unnecessary memory | |
184 // or stack allocation, use only async-safe functions. It's possible JVM is | |
185 // only partially initialized. | |
186 void CompileLog::finish_log_on_error(outputStream* file, char* buf, int buflen) { | |
187 static bool called_exit = false; | |
188 if (called_exit) return; | |
189 called_exit = true; | |
190 | |
191 for (CompileLog* log = _first; log != NULL; log = log->_next) { | |
192 log->flush(); | |
193 const char* partial_file = log->file(); | |
194 int partial_fd = open(partial_file, O_RDONLY); | |
195 if (partial_fd != -1) { | |
196 // print/print_cr may need to allocate large stack buffer to format | |
197 // strings, here we use snprintf() and print_raw() instead. | |
198 file->print_raw("<compilation_log thread='"); | |
199 jio_snprintf(buf, buflen, UINTX_FORMAT, log->thread_id()); | |
200 file->print_raw(buf); | |
201 file->print_raw_cr("'>"); | |
202 | |
203 size_t nr; // number read into buf from partial log | |
204 // Copy data up to the end of the last <event> element: | |
205 julong to_read = log->_file_end; | |
206 while (to_read > 0) { | |
207 if (to_read < (julong)buflen) | |
208 nr = (size_t)to_read; | |
209 else nr = buflen; | |
210 nr = read(partial_fd, buf, (int)nr); | |
211 if (nr <= 0) break; | |
212 to_read -= (julong)nr; | |
213 file->write(buf, nr); | |
214 } | |
215 | |
216 // Copy any remaining data inside a quote: | |
217 bool saw_slop = false; | |
218 int end_cdata = 0; // state machine [0..2] watching for too many "]]" | |
219 while ((nr = read(partial_fd, buf, buflen)) > 0) { | |
220 if (!saw_slop) { | |
221 file->print_raw_cr("<fragment>"); | |
222 file->print_raw_cr("<![CDATA["); | |
223 saw_slop = true; | |
224 } | |
225 // The rest of this loop amounts to a simple copy operation: | |
226 // { file->write(buf, nr); } | |
227 // However, it must sometimes output the buffer in parts, | |
228 // in case there is a CDATA quote embedded in the fragment. | |
229 const char* bufp; // pointer into buf | |
230 size_t nw; // number written in each pass of the following loop: | |
231 for (bufp = buf; nr > 0; nr -= nw, bufp += nw) { | |
232 // Write up to any problematic CDATA delimiter (usually all of nr). | |
233 for (nw = 0; nw < nr; nw++) { | |
234 // First, scan ahead into the buf, checking the state machine. | |
235 switch (bufp[nw]) { | |
236 case ']': | |
237 if (end_cdata < 2) end_cdata += 1; // saturating counter | |
238 continue; // keep scanning | |
239 case '>': | |
240 if (end_cdata == 2) break; // found CDATA delimiter! | |
241 // else fall through: | |
242 default: | |
243 end_cdata = 0; | |
244 continue; // keep scanning | |
245 } | |
246 // If we get here, nw is pointing at a bad '>'. | |
247 // It is very rare for this to happen. | |
248 // However, this code has been tested by introducing | |
249 // CDATA sequences into the compilation log. | |
250 break; | |
251 } | |
252 // Now nw is the number of characters to write, usually == nr. | |
253 file->write(bufp, nw); | |
254 if (nw < nr) { | |
255 // We are about to go around the loop again. | |
256 // But first, disrupt the ]]> by closing and reopening the quote. | |
257 file->print_raw("]]><![CDATA["); | |
258 end_cdata = 0; // reset state machine | |
259 } | |
260 } | |
261 } | |
262 if (saw_slop) { | |
263 file->print_raw_cr("]]>"); | |
264 file->print_raw_cr("</fragment>"); | |
265 } | |
266 file->print_raw_cr("</compilation_log>"); | |
267 close(partial_fd); | |
268 unlink(partial_file); | |
269 } | |
270 } | |
271 } | |
272 | |
273 // ------------------------------------------------------------------ | |
274 // CompileLog::finish_log | |
275 // | |
276 // Called during normal shutdown. For now, any clean-up needed in normal | |
277 // shutdown is also needed in VM abort, so is covered by finish_log_on_error(). | |
278 // Just allocate a buffer and call finish_log_on_error(). | |
279 void CompileLog::finish_log(outputStream* file) { | |
280 char buf[4 * K]; | |
281 finish_log_on_error(file, buf, sizeof(buf)); | |
282 } | |
6843 | 283 |
284 // ------------------------------------------------------------------ | |
285 // CompileLog::inline_success | |
286 // | |
287 // Print about successful method inlining. | |
288 void CompileLog::inline_success(const char* reason) { | |
289 begin_elem("inline_success reason='"); | |
290 text(reason); | |
291 end_elem("'"); | |
292 } | |
293 | |
294 // ------------------------------------------------------------------ | |
295 // CompileLog::inline_fail | |
296 // | |
297 // Print about failed method inlining. | |
298 void CompileLog::inline_fail(const char* reason) { | |
299 begin_elem("inline_fail reason='"); | |
300 text(reason); | |
301 end_elem("'"); | |
302 } | |
303 | |
304 // ------------------------------------------------------------------ | |
305 // CompileLog::set_context | |
306 // | |
307 // Set XML tag as an optional marker - it is printed only if | |
308 // there are other entries after until it is reset. | |
309 void CompileLog::set_context(const char* format, ...) { | |
310 va_list ap; | |
311 va_start(ap, format); | |
312 clear_context(); | |
313 _context.print("<"); | |
314 _context.vprint(format, ap); | |
315 _context.print_cr("/>"); | |
316 va_end(ap); | |
317 } | |
318 | |
319 // ------------------------------------------------------------------ | |
320 // CompileLog::code_cache_state | |
321 // | |
322 // Print code cache state. | |
323 void CompileLog::code_cache_state() { | |
324 begin_elem("code_cache"); | |
325 CodeCache::log_state(this); | |
326 end_elem(""); | |
327 } |