Mercurial > hg > graal-compiler
comparison src/share/vm/code/nmethod.cpp @ 12675:7fedc59e2cdc
Split code cache stats for the different compilers
author | Gilles Duboscq <duboscq@ssw.jku.at> |
---|---|
date | Tue, 05 Nov 2013 12:19:10 +0100 |
parents | 98031e66de15 |
children | 0e998f0daddf |
comparison
equal
deleted
inserted
replaced
12674:ecd519b39f10 | 12675:7fedc59e2cdc |
---|---|
127 // PrintC1Statistics, PrintOptoStatistics, LogVMOutput, and LogCompilation. | 127 // PrintC1Statistics, PrintOptoStatistics, LogVMOutput, and LogCompilation. |
128 // (In the latter two cases, they like other stats are printed to the log only.) | 128 // (In the latter two cases, they like other stats are printed to the log only.) |
129 | 129 |
130 // These variables are put into one block to reduce relocations | 130 // These variables are put into one block to reduce relocations |
131 // and make it simpler to print from the debugger. | 131 // and make it simpler to print from the debugger. |
132 static | 132 struct java_nmethod_stats_struct { |
133 struct nmethod_stats_struct { | |
134 int nmethod_count; | 133 int nmethod_count; |
135 int total_size; | 134 int total_size; |
136 int relocation_size; | 135 int relocation_size; |
137 int consts_size; | 136 int consts_size; |
138 int insts_size; | 137 int insts_size; |
156 scopes_pcs_size += nm->scopes_pcs_size(); | 155 scopes_pcs_size += nm->scopes_pcs_size(); |
157 dependencies_size += nm->dependencies_size(); | 156 dependencies_size += nm->dependencies_size(); |
158 handler_table_size += nm->handler_table_size(); | 157 handler_table_size += nm->handler_table_size(); |
159 nul_chk_table_size += nm->nul_chk_table_size(); | 158 nul_chk_table_size += nm->nul_chk_table_size(); |
160 } | 159 } |
161 void print_nmethod_stats() { | 160 void print_nmethod_stats(const char* name) { |
162 if (nmethod_count == 0) return; | 161 if (nmethod_count == 0) return; |
163 tty->print_cr("Statistics for %d bytecoded nmethods:", nmethod_count); | 162 tty->print_cr("Statistics for %d bytecoded nmethods for %s:", nmethod_count, name); |
164 if (total_size != 0) tty->print_cr(" total in heap = %d", total_size); | 163 if (total_size != 0) tty->print_cr(" total in heap = %d", total_size); |
165 if (relocation_size != 0) tty->print_cr(" relocation = %d", relocation_size); | 164 if (relocation_size != 0) tty->print_cr(" relocation = %d", relocation_size); |
166 if (consts_size != 0) tty->print_cr(" constants = %d", consts_size); | 165 if (consts_size != 0) tty->print_cr(" constants = %d", consts_size); |
167 if (insts_size != 0) tty->print_cr(" main code = %d", insts_size); | 166 if (insts_size != 0) tty->print_cr(" main code = %d", insts_size); |
168 if (stub_size != 0) tty->print_cr(" stub code = %d", stub_size); | 167 if (stub_size != 0) tty->print_cr(" stub code = %d", stub_size); |
171 if (scopes_pcs_size != 0) tty->print_cr(" scopes pcs = %d", scopes_pcs_size); | 170 if (scopes_pcs_size != 0) tty->print_cr(" scopes pcs = %d", scopes_pcs_size); |
172 if (dependencies_size != 0) tty->print_cr(" dependencies = %d", dependencies_size); | 171 if (dependencies_size != 0) tty->print_cr(" dependencies = %d", dependencies_size); |
173 if (handler_table_size != 0) tty->print_cr(" handler table = %d", handler_table_size); | 172 if (handler_table_size != 0) tty->print_cr(" handler table = %d", handler_table_size); |
174 if (nul_chk_table_size != 0) tty->print_cr(" nul chk table = %d", nul_chk_table_size); | 173 if (nul_chk_table_size != 0) tty->print_cr(" nul chk table = %d", nul_chk_table_size); |
175 } | 174 } |
176 | 175 }; |
176 | |
177 struct native_nmethod_stats_struct { | |
177 int native_nmethod_count; | 178 int native_nmethod_count; |
178 int native_total_size; | 179 int native_total_size; |
179 int native_relocation_size; | 180 int native_relocation_size; |
180 int native_insts_size; | 181 int native_insts_size; |
181 int native_oops_size; | 182 int native_oops_size; |
192 if (native_total_size != 0) tty->print_cr(" N. total size = %d", native_total_size); | 193 if (native_total_size != 0) tty->print_cr(" N. total size = %d", native_total_size); |
193 if (native_relocation_size != 0) tty->print_cr(" N. relocation = %d", native_relocation_size); | 194 if (native_relocation_size != 0) tty->print_cr(" N. relocation = %d", native_relocation_size); |
194 if (native_insts_size != 0) tty->print_cr(" N. main code = %d", native_insts_size); | 195 if (native_insts_size != 0) tty->print_cr(" N. main code = %d", native_insts_size); |
195 if (native_oops_size != 0) tty->print_cr(" N. oops = %d", native_oops_size); | 196 if (native_oops_size != 0) tty->print_cr(" N. oops = %d", native_oops_size); |
196 } | 197 } |
197 | 198 }; |
199 | |
200 struct pc_nmethod_stats_struct { | |
198 int pc_desc_resets; // number of resets (= number of caches) | 201 int pc_desc_resets; // number of resets (= number of caches) |
199 int pc_desc_queries; // queries to nmethod::find_pc_desc | 202 int pc_desc_queries; // queries to nmethod::find_pc_desc |
200 int pc_desc_approx; // number of those which have approximate true | 203 int pc_desc_approx; // number of those which have approximate true |
201 int pc_desc_repeats; // number of _pc_descs[0] hits | 204 int pc_desc_repeats; // number of _pc_descs[0] hits |
202 int pc_desc_hits; // number of LRU cache hits | 205 int pc_desc_hits; // number of LRU cache hits |
213 pc_desc_resets, | 216 pc_desc_resets, |
214 pc_desc_queries, pc_desc_approx, | 217 pc_desc_queries, pc_desc_approx, |
215 pc_desc_repeats, pc_desc_hits, | 218 pc_desc_repeats, pc_desc_hits, |
216 pc_desc_tests, pc_desc_searches, pc_desc_adds); | 219 pc_desc_tests, pc_desc_searches, pc_desc_adds); |
217 } | 220 } |
218 } nmethod_stats; | 221 }; |
222 | |
223 #ifdef COMPILER1 | |
224 static java_nmethod_stats_struct c1_java_nmethod_stats; | |
225 #endif | |
226 #ifdef COMPILER2 | |
227 static java_nmethod_stats_struct c2_java_nmethod_stats; | |
228 #endif | |
229 #ifdef GRAAL | |
230 static java_nmethod_stats_struct graal_java_nmethod_stats; | |
231 #endif | |
232 | |
233 static native_nmethod_stats_struct native_nmethod_stats; | |
234 static pc_nmethod_stats_struct pc_nmethod_stats; | |
235 | |
236 static void note_java_nmethod(nmethod* nm) { | |
237 #ifdef COMPILER1 | |
238 if (nm->is_compiled_by_c1()) { | |
239 c1_java_nmethod_stats.note_nmethod(nm); | |
240 } | |
241 #endif | |
242 #ifdef COMPILER2 | |
243 if (nm->is_compiled_by_c2()) { | |
244 c2_java_nmethod_stats.note_nmethod(nm); | |
245 } | |
246 #endif | |
247 #ifdef GRAAL | |
248 if (nm->is_compiled_by_graal()) { | |
249 graal_java_nmethod_stats.note_nmethod(nm); | |
250 } | |
251 #endif | |
252 } | |
219 | 253 |
220 | 254 |
221 //--------------------------------------------------------------------------------- | 255 //--------------------------------------------------------------------------------- |
222 | 256 |
223 | 257 |
294 //----------------------------------------------------------------------------- | 328 //----------------------------------------------------------------------------- |
295 | 329 |
296 | 330 |
297 // Helper used by both find_pc_desc methods. | 331 // Helper used by both find_pc_desc methods. |
298 static inline bool match_desc(PcDesc* pc, int pc_offset, bool approximate) { | 332 static inline bool match_desc(PcDesc* pc, int pc_offset, bool approximate) { |
299 NOT_PRODUCT(++nmethod_stats.pc_desc_tests); | 333 NOT_PRODUCT(++pc_nmethod_stats.pc_desc_tests); |
300 if (!approximate) | 334 if (!approximate) |
301 return pc->pc_offset() == pc_offset; | 335 return pc->pc_offset() == pc_offset; |
302 else | 336 else |
303 return (pc-1)->pc_offset() < pc_offset && pc_offset <= pc->pc_offset(); | 337 return (pc-1)->pc_offset() < pc_offset && pc_offset <= pc->pc_offset(); |
304 } | 338 } |
306 void PcDescCache::reset_to(PcDesc* initial_pc_desc) { | 340 void PcDescCache::reset_to(PcDesc* initial_pc_desc) { |
307 if (initial_pc_desc == NULL) { | 341 if (initial_pc_desc == NULL) { |
308 _pc_descs[0] = NULL; // native method; no PcDescs at all | 342 _pc_descs[0] = NULL; // native method; no PcDescs at all |
309 return; | 343 return; |
310 } | 344 } |
311 NOT_PRODUCT(++nmethod_stats.pc_desc_resets); | 345 NOT_PRODUCT(++pc_nmethod_stats.pc_desc_resets); |
312 // reset the cache by filling it with benign (non-null) values | 346 // reset the cache by filling it with benign (non-null) values |
313 assert(initial_pc_desc->pc_offset() < 0, "must be sentinel"); | 347 assert(initial_pc_desc->pc_offset() < 0, "must be sentinel"); |
314 for (int i = 0; i < cache_size; i++) | 348 for (int i = 0; i < cache_size; i++) |
315 _pc_descs[i] = initial_pc_desc; | 349 _pc_descs[i] = initial_pc_desc; |
316 } | 350 } |
317 | 351 |
318 PcDesc* PcDescCache::find_pc_desc(int pc_offset, bool approximate) { | 352 PcDesc* PcDescCache::find_pc_desc(int pc_offset, bool approximate) { |
319 NOT_PRODUCT(++nmethod_stats.pc_desc_queries); | 353 NOT_PRODUCT(++pc_nmethod_stats.pc_desc_queries); |
320 NOT_PRODUCT(if (approximate) ++nmethod_stats.pc_desc_approx); | 354 NOT_PRODUCT(if (approximate) ++pc_nmethod_stats.pc_desc_approx); |
321 | 355 |
322 // Note: one might think that caching the most recently | 356 // Note: one might think that caching the most recently |
323 // read value separately would be a win, but one would be | 357 // read value separately would be a win, but one would be |
324 // wrong. When many threads are updating it, the cache | 358 // wrong. When many threads are updating it, the cache |
325 // line it's in would bounce between caches, negating | 359 // line it's in would bounce between caches, negating |
331 | 365 |
332 // Step one: Check the most recently added value. | 366 // Step one: Check the most recently added value. |
333 res = _pc_descs[0]; | 367 res = _pc_descs[0]; |
334 if (res == NULL) return NULL; // native method; no PcDescs at all | 368 if (res == NULL) return NULL; // native method; no PcDescs at all |
335 if (match_desc(res, pc_offset, approximate)) { | 369 if (match_desc(res, pc_offset, approximate)) { |
336 NOT_PRODUCT(++nmethod_stats.pc_desc_repeats); | 370 NOT_PRODUCT(++pc_nmethod_stats.pc_desc_repeats); |
337 return res; | 371 return res; |
338 } | 372 } |
339 | 373 |
340 // Step two: Check the rest of the LRU cache. | 374 // Step two: Check the rest of the LRU cache. |
341 for (int i = 1; i < cache_size; ++i) { | 375 for (int i = 1; i < cache_size; ++i) { |
342 res = _pc_descs[i]; | 376 res = _pc_descs[i]; |
343 if (res->pc_offset() < 0) break; // optimization: skip empty cache | 377 if (res->pc_offset() < 0) break; // optimization: skip empty cache |
344 if (match_desc(res, pc_offset, approximate)) { | 378 if (match_desc(res, pc_offset, approximate)) { |
345 NOT_PRODUCT(++nmethod_stats.pc_desc_hits); | 379 NOT_PRODUCT(++pc_nmethod_stats.pc_desc_hits); |
346 return res; | 380 return res; |
347 } | 381 } |
348 } | 382 } |
349 | 383 |
350 // Report failure. | 384 // Report failure. |
351 return NULL; | 385 return NULL; |
352 } | 386 } |
353 | 387 |
354 void PcDescCache::add_pc_desc(PcDesc* pc_desc) { | 388 void PcDescCache::add_pc_desc(PcDesc* pc_desc) { |
355 NOT_PRODUCT(++nmethod_stats.pc_desc_adds); | 389 NOT_PRODUCT(++pc_nmethod_stats.pc_desc_adds); |
356 // Update the LRU cache by shifting pc_desc forward. | 390 // Update the LRU cache by shifting pc_desc forward. |
357 for (int i = 0; i < cache_size; i++) { | 391 for (int i = 0; i < cache_size; i++) { |
358 PcDesc* next = _pc_descs[i]; | 392 PcDesc* next = _pc_descs[i]; |
359 _pc_descs[i] = pc_desc; | 393 _pc_descs[i] = pc_desc; |
360 pc_desc = next; | 394 pc_desc = next; |
517 nm = new (native_nmethod_size) nmethod(method(), native_nmethod_size, | 551 nm = new (native_nmethod_size) nmethod(method(), native_nmethod_size, |
518 compile_id, &offsets, | 552 compile_id, &offsets, |
519 code_buffer, frame_size, | 553 code_buffer, frame_size, |
520 basic_lock_owner_sp_offset, | 554 basic_lock_owner_sp_offset, |
521 basic_lock_sp_offset, oop_maps); | 555 basic_lock_sp_offset, oop_maps); |
522 if (nm != NULL) nmethod_stats.note_native_nmethod(nm); | 556 if (nm != NULL) native_nmethod_stats.note_native_nmethod(nm); |
523 if (PrintAssembly && nm != NULL) { | 557 if (PrintAssembly && nm != NULL) { |
524 Disassembler::decode(nm); | 558 Disassembler::decode(nm); |
525 } | 559 } |
526 } | 560 } |
527 // verify nmethod | 561 // verify nmethod |
553 offsets.set_value(CodeOffsets::Frame_Complete, frame_complete); | 587 offsets.set_value(CodeOffsets::Frame_Complete, frame_complete); |
554 | 588 |
555 nm = new (nmethod_size) nmethod(method(), nmethod_size, | 589 nm = new (nmethod_size) nmethod(method(), nmethod_size, |
556 &offsets, code_buffer, frame_size); | 590 &offsets, code_buffer, frame_size); |
557 | 591 |
558 if (nm != NULL) nmethod_stats.note_nmethod(nm); | 592 if (nm != NULL) note_java_nmethod(nm); |
559 if (PrintAssembly && nm != NULL) { | 593 if (PrintAssembly && nm != NULL) { |
560 Disassembler::decode(nm); | 594 Disassembler::decode(nm); |
561 } | 595 } |
562 } | 596 } |
563 // verify nmethod | 597 // verify nmethod |
638 | 672 |
639 // record this nmethod as dependent on this klass | 673 // record this nmethod as dependent on this klass |
640 InstanceKlass::cast(klass)->add_dependent_nmethod(nm); | 674 InstanceKlass::cast(klass)->add_dependent_nmethod(nm); |
641 } | 675 } |
642 } | 676 } |
643 if (nm != NULL) nmethod_stats.note_nmethod(nm); | 677 if (nm != NULL) note_java_nmethod(nm); |
644 if (PrintAssembly && nm != NULL) { | 678 if (PrintAssembly && nm != NULL) { |
645 Disassembler::decode(nm); | 679 Disassembler::decode(nm); |
646 } | 680 } |
647 } | 681 } |
648 | 682 |
2166 PcDesc* lower = nm->scopes_pcs_begin(); | 2200 PcDesc* lower = nm->scopes_pcs_begin(); |
2167 PcDesc* upper = nm->scopes_pcs_end(); | 2201 PcDesc* upper = nm->scopes_pcs_end(); |
2168 lower += 1; // exclude initial sentinel | 2202 lower += 1; // exclude initial sentinel |
2169 PcDesc* res = NULL; | 2203 PcDesc* res = NULL; |
2170 for (PcDesc* p = lower; p < upper; p++) { | 2204 for (PcDesc* p = lower; p < upper; p++) { |
2171 NOT_PRODUCT(--nmethod_stats.pc_desc_tests); // don't count this call to match_desc | 2205 NOT_PRODUCT(--pc_nmethod_stats.pc_desc_tests); // don't count this call to match_desc |
2172 if (match_desc(p, pc_offset, approximate)) { | 2206 if (match_desc(p, pc_offset, approximate)) { |
2173 if (res == NULL) | 2207 if (res == NULL) |
2174 res = p; | 2208 res = p; |
2175 else | 2209 else |
2176 res = (PcDesc*) badAddress; | 2210 res = (PcDesc*) badAddress; |
2213 assert(upper->pc_offset() >= pc_offset, "sanity") | 2247 assert(upper->pc_offset() >= pc_offset, "sanity") |
2214 assert_LU_OK; | 2248 assert_LU_OK; |
2215 | 2249 |
2216 // Use the last successful return as a split point. | 2250 // Use the last successful return as a split point. |
2217 PcDesc* mid = _pc_desc_cache.last_pc_desc(); | 2251 PcDesc* mid = _pc_desc_cache.last_pc_desc(); |
2218 NOT_PRODUCT(++nmethod_stats.pc_desc_searches); | 2252 NOT_PRODUCT(++pc_nmethod_stats.pc_desc_searches); |
2219 if (mid->pc_offset() < pc_offset) { | 2253 if (mid->pc_offset() < pc_offset) { |
2220 lower = mid; | 2254 lower = mid; |
2221 } else { | 2255 } else { |
2222 upper = mid; | 2256 upper = mid; |
2223 } | 2257 } |
2226 const int LOG2_RADIX = 4 /*smaller steps in debug mode:*/ debug_only(-1); | 2260 const int LOG2_RADIX = 4 /*smaller steps in debug mode:*/ debug_only(-1); |
2227 const int RADIX = (1 << LOG2_RADIX); | 2261 const int RADIX = (1 << LOG2_RADIX); |
2228 for (int step = (1 << (LOG2_RADIX*3)); step > 1; step >>= LOG2_RADIX) { | 2262 for (int step = (1 << (LOG2_RADIX*3)); step > 1; step >>= LOG2_RADIX) { |
2229 while ((mid = lower + step) < upper) { | 2263 while ((mid = lower + step) < upper) { |
2230 assert_LU_OK; | 2264 assert_LU_OK; |
2231 NOT_PRODUCT(++nmethod_stats.pc_desc_searches); | 2265 NOT_PRODUCT(++pc_nmethod_stats.pc_desc_searches); |
2232 if (mid->pc_offset() < pc_offset) { | 2266 if (mid->pc_offset() < pc_offset) { |
2233 lower = mid; | 2267 lower = mid; |
2234 } else { | 2268 } else { |
2235 upper = mid; | 2269 upper = mid; |
2236 break; | 2270 break; |
2241 | 2275 |
2242 // Sneak up on the value with a linear search of length ~16. | 2276 // Sneak up on the value with a linear search of length ~16. |
2243 while (true) { | 2277 while (true) { |
2244 assert_LU_OK; | 2278 assert_LU_OK; |
2245 mid = lower + 1; | 2279 mid = lower + 1; |
2246 NOT_PRODUCT(++nmethod_stats.pc_desc_searches); | 2280 NOT_PRODUCT(++pc_nmethod_stats.pc_desc_searches); |
2247 if (mid->pc_offset() < pc_offset) { | 2281 if (mid->pc_offset() < pc_offset) { |
2248 lower = mid; | 2282 lower = mid; |
2249 } else { | 2283 } else { |
2250 upper = mid; | 2284 upper = mid; |
2251 break; | 2285 break; |
3041 #endif // PRODUCT | 3075 #endif // PRODUCT |
3042 | 3076 |
3043 void nmethod::print_statistics() { | 3077 void nmethod::print_statistics() { |
3044 ttyLocker ttyl; | 3078 ttyLocker ttyl; |
3045 if (xtty != NULL) xtty->head("statistics type='nmethod'"); | 3079 if (xtty != NULL) xtty->head("statistics type='nmethod'"); |
3046 nmethod_stats.print_native_nmethod_stats(); | 3080 native_nmethod_stats.print_native_nmethod_stats(); |
3047 nmethod_stats.print_nmethod_stats(); | 3081 #ifdef COMPILER1 |
3082 c1_java_nmethod_stats.print_nmethod_stats("C1"); | |
3083 #endif | |
3084 #ifdef COMPILER2 | |
3085 c2_java_nmethod_stats.print_nmethod_stats("C2"); | |
3086 #endif | |
3087 #ifdef GRAAL | |
3088 graal_java_nmethod_stats.print_nmethod_stats("Graal"); | |
3089 #endif | |
3048 DebugInformationRecorder::print_statistics(); | 3090 DebugInformationRecorder::print_statistics(); |
3049 nmethod_stats.print_pc_stats(); | 3091 pc_nmethod_stats.print_pc_stats(); |
3050 Dependencies::print_statistics(); | 3092 Dependencies::print_statistics(); |
3051 if (xtty != NULL) xtty->tail("statistics"); | 3093 if (xtty != NULL) xtty->tail("statistics"); |
3052 } | 3094 } |