Mercurial > hg > truffle
comparison src/share/vm/interpreter/bytecodeTracer.cpp @ 1579:e9ff18c4ace7
Merge
author | jrose |
---|---|
date | Wed, 02 Jun 2010 22:45:42 -0700 |
parents | c18cbe5936b8 ab102d5d923e |
children | 136b78722a08 |
comparison
equal
deleted
inserted
replaced
1562:dfe27f03244a | 1579:e9ff18c4ace7 |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved. | 2 * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | 4 * |
5 * This code is free software; you can redistribute it and/or modify it | 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 | 6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
37 // between critical sections. Use only pointer-comparison | 37 // between critical sections. Use only pointer-comparison |
38 // operations on the pointer, except within a critical section. | 38 // operations on the pointer, except within a critical section. |
39 // (Also, ensure that occasional false positives are benign.) | 39 // (Also, ensure that occasional false positives are benign.) |
40 methodOop _current_method; | 40 methodOop _current_method; |
41 bool _is_wide; | 41 bool _is_wide; |
42 Bytecodes::Code _code; | |
42 address _next_pc; // current decoding position | 43 address _next_pc; // current decoding position |
43 | 44 |
44 void align() { _next_pc = (address)round_to((intptr_t)_next_pc, sizeof(jint)); } | 45 void align() { _next_pc = (address)round_to((intptr_t)_next_pc, sizeof(jint)); } |
45 int get_byte() { return *(jbyte*) _next_pc++; } // signed | 46 int get_byte() { return *(jbyte*) _next_pc++; } // signed |
46 short get_short() { short i=Bytes::get_Java_u2(_next_pc); _next_pc+=2; return i; } | 47 short get_short() { short i=Bytes::get_Java_u2(_next_pc); _next_pc+=2; return i; } |
47 int get_int() { int i=Bytes::get_Java_u4(_next_pc); _next_pc+=4; return i; } | 48 int get_int() { int i=Bytes::get_Java_u4(_next_pc); _next_pc+=4; return i; } |
48 | 49 |
49 int get_index() { return *(address)_next_pc++; } | 50 int get_index_u1() { return *(address)_next_pc++; } |
50 int get_big_index() { int i=Bytes::get_Java_u2(_next_pc); _next_pc+=2; return i; } | 51 int get_index_u2() { int i=Bytes::get_Java_u2(_next_pc); _next_pc+=2; return i; } |
51 int get_giant_index() { int i=Bytes::get_native_u4(_next_pc); _next_pc+=4; return i; } | 52 int get_index_u2_cpcache() { int i=Bytes::get_native_u2(_next_pc); _next_pc+=2; return i + constantPoolOopDesc::CPCACHE_INDEX_TAG; } |
52 int get_index_special() { return (is_wide()) ? get_big_index() : get_index(); } | 53 int get_index_u4() { int i=Bytes::get_native_u4(_next_pc); _next_pc+=4; return i; } |
54 int get_index_special() { return (is_wide()) ? get_index_u2() : get_index_u1(); } | |
53 methodOop method() { return _current_method; } | 55 methodOop method() { return _current_method; } |
54 bool is_wide() { return _is_wide; } | 56 bool is_wide() { return _is_wide; } |
55 | 57 Bytecodes::Code raw_code() { return Bytecodes::Code(_code); } |
56 | 58 |
57 bool check_index(int i, bool in_cp_cache, int& cp_index, outputStream* st = tty); | 59 |
60 bool check_index(int i, int& cp_index, outputStream* st = tty); | |
58 void print_constant(int i, outputStream* st = tty); | 61 void print_constant(int i, outputStream* st = tty); |
59 void print_field_or_method(int i, outputStream* st = tty); | 62 void print_field_or_method(int i, outputStream* st = tty); |
60 void print_attributes(Bytecodes::Code code, int bci, outputStream* st = tty); | 63 void print_attributes(int bci, outputStream* st = tty); |
61 void bytecode_epilog(int bci, outputStream* st = tty); | 64 void bytecode_epilog(int bci, outputStream* st = tty); |
62 | 65 |
63 public: | 66 public: |
64 BytecodePrinter() { | 67 BytecodePrinter() { |
65 _is_wide = false; | 68 _is_wide = false; |
69 _code = Bytecodes::_illegal; | |
66 } | 70 } |
67 | 71 |
68 // This method is called while executing the raw bytecodes, so none of | 72 // This method is called while executing the raw bytecodes, so none of |
69 // the adjustments that BytecodeStream performs applies. | 73 // the adjustments that BytecodeStream performs applies. |
70 void trace(methodHandle method, address bcp, uintptr_t tos, uintptr_t tos2, outputStream* st) { | 74 void trace(methodHandle method, address bcp, uintptr_t tos, uintptr_t tos2, outputStream* st) { |
87 // bcp wasn't advanced if previous bytecode was _wide. | 91 // bcp wasn't advanced if previous bytecode was _wide. |
88 code = Bytecodes::code_at(bcp+1); | 92 code = Bytecodes::code_at(bcp+1); |
89 } else { | 93 } else { |
90 code = Bytecodes::code_at(bcp); | 94 code = Bytecodes::code_at(bcp); |
91 } | 95 } |
92 int bci = bcp - method->code_base(); | 96 _code = code; |
97 int bci = bcp - method->code_base(); | |
93 st->print("[%d] ", (int) Thread::current()->osthread()->thread_id()); | 98 st->print("[%d] ", (int) Thread::current()->osthread()->thread_id()); |
94 if (Verbose) { | 99 if (Verbose) { |
95 st->print("%8d %4d " INTPTR_FORMAT " " INTPTR_FORMAT " %s", | 100 st->print("%8d %4d " INTPTR_FORMAT " " INTPTR_FORMAT " %s", |
96 BytecodeCounter::counter_value(), bci, tos, tos2, Bytecodes::name(code)); | 101 BytecodeCounter::counter_value(), bci, tos, tos2, Bytecodes::name(code)); |
97 } else { | 102 } else { |
98 st->print("%8d %4d %s", | 103 st->print("%8d %4d %s", |
99 BytecodeCounter::counter_value(), bci, Bytecodes::name(code)); | 104 BytecodeCounter::counter_value(), bci, Bytecodes::name(code)); |
100 } | 105 } |
101 _next_pc = is_wide() ? bcp+2 : bcp+1; | 106 _next_pc = is_wide() ? bcp+2 : bcp+1; |
102 print_attributes(code, bci); | 107 print_attributes(bci); |
103 // Set is_wide for the next one, since the caller of this doesn't skip | 108 // Set is_wide for the next one, since the caller of this doesn't skip |
104 // the next bytecode. | 109 // the next bytecode. |
105 _is_wide = (code == Bytecodes::_wide); | 110 _is_wide = (code == Bytecodes::_wide); |
111 _code = Bytecodes::_illegal; | |
106 } | 112 } |
107 | 113 |
108 // Used for methodOop::print_codes(). The input bcp comes from | 114 // Used for methodOop::print_codes(). The input bcp comes from |
109 // BytecodeStream, which will skip wide bytecodes. | 115 // BytecodeStream, which will skip wide bytecodes. |
110 void trace(methodHandle method, address bcp, outputStream* st) { | 116 void trace(methodHandle method, address bcp, outputStream* st) { |
114 // Set is_wide | 120 // Set is_wide |
115 _is_wide = (code == Bytecodes::_wide); | 121 _is_wide = (code == Bytecodes::_wide); |
116 if (is_wide()) { | 122 if (is_wide()) { |
117 code = Bytecodes::code_at(bcp+1); | 123 code = Bytecodes::code_at(bcp+1); |
118 } | 124 } |
125 _code = code; | |
119 int bci = bcp - method->code_base(); | 126 int bci = bcp - method->code_base(); |
120 // Print bytecode index and name | 127 // Print bytecode index and name |
121 if (is_wide()) { | 128 if (is_wide()) { |
122 st->print("%d %s_w", bci, Bytecodes::name(code)); | 129 st->print("%d %s_w", bci, Bytecodes::name(code)); |
123 } else { | 130 } else { |
124 st->print("%d %s", bci, Bytecodes::name(code)); | 131 st->print("%d %s", bci, Bytecodes::name(code)); |
125 } | 132 } |
126 _next_pc = is_wide() ? bcp+2 : bcp+1; | 133 _next_pc = is_wide() ? bcp+2 : bcp+1; |
127 print_attributes(code, bci, st); | 134 print_attributes(bci, st); |
128 bytecode_epilog(bci, st); | 135 bytecode_epilog(bci, st); |
129 } | 136 } |
130 }; | 137 }; |
131 | 138 |
132 | 139 |
183 sym->print_on(st); st->cr(); | 190 sym->print_on(st); st->cr(); |
184 } | 191 } |
185 } | 192 } |
186 } | 193 } |
187 | 194 |
188 bool BytecodePrinter::check_index(int i, bool in_cp_cache, int& cp_index, outputStream* st) { | 195 bool BytecodePrinter::check_index(int i, int& cp_index, outputStream* st) { |
189 constantPoolOop constants = method()->constants(); | 196 constantPoolOop constants = method()->constants(); |
190 int ilimit = constants->length(), climit = 0; | 197 int ilimit = constants->length(), climit = 0; |
198 Bytecodes::Code code = raw_code(); | |
191 | 199 |
192 constantPoolCacheOop cache = NULL; | 200 constantPoolCacheOop cache = NULL; |
193 if (in_cp_cache) { | 201 if (Bytecodes::uses_cp_cache(code)) { |
194 cache = constants->cache(); | 202 cache = constants->cache(); |
195 if (cache != NULL) { | 203 if (cache != NULL) { |
196 //climit = cache->length(); // %%% private! | 204 //climit = cache->length(); // %%% private! |
197 size_t size = cache->size() * HeapWordSize; | 205 size_t size = cache->size() * HeapWordSize; |
198 size -= sizeof(constantPoolCacheOopDesc); | 206 size -= sizeof(constantPoolCacheOopDesc); |
199 size /= sizeof(ConstantPoolCacheEntry); | 207 size /= sizeof(ConstantPoolCacheEntry); |
200 climit = (int) size; | 208 climit = (int) size; |
201 } | 209 } |
202 } | 210 } |
203 | 211 |
204 if (in_cp_cache && constantPoolCacheOopDesc::is_secondary_index(i)) { | 212 if (cache != NULL && constantPoolCacheOopDesc::is_secondary_index(i)) { |
205 i = constantPoolCacheOopDesc::decode_secondary_index(i); | 213 i = constantPoolCacheOopDesc::decode_secondary_index(i); |
206 st->print(" secondary cache[%d] of", i); | 214 st->print(" secondary cache[%d] of", i); |
207 if (i >= 0 && i < climit) { | 215 if (i >= 0 && i < climit) { |
208 if (!cache->entry_at(i)->is_secondary_entry()) { | 216 if (!cache->entry_at(i)->is_secondary_entry()) { |
209 st->print_cr(" not secondary entry?", i); | 217 st->print_cr(" not secondary entry?", i); |
216 return false; | 224 return false; |
217 } | 225 } |
218 } | 226 } |
219 | 227 |
220 if (cache != NULL) { | 228 if (cache != NULL) { |
221 i = Bytes::swap_u2(i); | |
222 if (WizardMode) st->print(" (swap=%d)", i); | |
223 goto check_cache_index; | 229 goto check_cache_index; |
224 } | 230 } |
225 | 231 |
226 check_cp_index: | 232 check_cp_index: |
227 if (i >= 0 && i < ilimit) { | 233 if (i >= 0 && i < ilimit) { |
232 | 238 |
233 st->print_cr(" CP[%d] not in CP", i); | 239 st->print_cr(" CP[%d] not in CP", i); |
234 return false; | 240 return false; |
235 | 241 |
236 check_cache_index: | 242 check_cache_index: |
243 #ifdef ASSERT | |
244 { | |
245 const int CPCACHE_INDEX_TAG = constantPoolOopDesc::CPCACHE_INDEX_TAG; | |
246 if (i >= CPCACHE_INDEX_TAG && i < climit + CPCACHE_INDEX_TAG) { | |
247 i -= CPCACHE_INDEX_TAG; | |
248 } else { | |
249 st->print_cr(" CP[%d] missing bias?", i); | |
250 return false; | |
251 } | |
252 } | |
253 #endif //ASSERT | |
237 if (i >= 0 && i < climit) { | 254 if (i >= 0 && i < climit) { |
238 if (cache->entry_at(i)->is_secondary_entry()) { | 255 if (cache->entry_at(i)->is_secondary_entry()) { |
239 st->print_cr(" secondary entry?"); | 256 st->print_cr(" secondary entry?"); |
240 return false; | 257 return false; |
241 } | 258 } |
246 return false; | 263 return false; |
247 } | 264 } |
248 | 265 |
249 void BytecodePrinter::print_constant(int i, outputStream* st) { | 266 void BytecodePrinter::print_constant(int i, outputStream* st) { |
250 int orig_i = i; | 267 int orig_i = i; |
251 if (!check_index(orig_i, false, i, st)) return; | 268 if (!check_index(orig_i, i, st)) return; |
252 | 269 |
253 constantPoolOop constants = method()->constants(); | 270 constantPoolOop constants = method()->constants(); |
254 constantTag tag = constants->tag_at(i); | 271 constantTag tag = constants->tag_at(i); |
255 | 272 |
256 if (tag.is_int()) { | 273 if (tag.is_int()) { |
277 } | 294 } |
278 } | 295 } |
279 | 296 |
280 void BytecodePrinter::print_field_or_method(int i, outputStream* st) { | 297 void BytecodePrinter::print_field_or_method(int i, outputStream* st) { |
281 int orig_i = i; | 298 int orig_i = i; |
282 if (!check_index(orig_i, true, i, st)) return; | 299 if (!check_index(orig_i, i, st)) return; |
283 | 300 |
284 constantPoolOop constants = method()->constants(); | 301 constantPoolOop constants = method()->constants(); |
285 constantTag tag = constants->tag_at(i); | 302 constantTag tag = constants->tag_at(i); |
286 | 303 |
287 int nt_index = -1; | 304 int nt_index = -1; |
301 symbolOop signature = constants->uncached_signature_ref_at(i); | 318 symbolOop signature = constants->uncached_signature_ref_at(i); |
302 st->print_cr(" %d <%s> <%s> ", i, name->as_C_string(), signature->as_C_string()); | 319 st->print_cr(" %d <%s> <%s> ", i, name->as_C_string(), signature->as_C_string()); |
303 } | 320 } |
304 | 321 |
305 | 322 |
306 void BytecodePrinter::print_attributes(Bytecodes::Code code, int bci, outputStream* st) { | 323 void BytecodePrinter::print_attributes(int bci, outputStream* st) { |
307 // Show attributes of pre-rewritten codes | 324 // Show attributes of pre-rewritten codes |
308 code = Bytecodes::java_code(code); | 325 Bytecodes::Code code = Bytecodes::java_code(raw_code()); |
309 // If the code doesn't have any fields there's nothing to print. | 326 // If the code doesn't have any fields there's nothing to print. |
310 // note this is ==1 because the tableswitch and lookupswitch are | 327 // note this is ==1 because the tableswitch and lookupswitch are |
311 // zero size (for some reason) and we want to print stuff out for them. | 328 // zero size (for some reason) and we want to print stuff out for them. |
312 if (Bytecodes::length_for(code) == 1) { | 329 if (Bytecodes::length_for(code) == 1) { |
313 st->cr(); | 330 st->cr(); |
321 break; | 338 break; |
322 case Bytecodes::_sipush: | 339 case Bytecodes::_sipush: |
323 st->print_cr(" " INT32_FORMAT, get_short()); | 340 st->print_cr(" " INT32_FORMAT, get_short()); |
324 break; | 341 break; |
325 case Bytecodes::_ldc: | 342 case Bytecodes::_ldc: |
326 print_constant(get_index(), st); | 343 print_constant(get_index_u1(), st); |
327 break; | 344 break; |
328 | 345 |
329 case Bytecodes::_ldc_w: | 346 case Bytecodes::_ldc_w: |
330 case Bytecodes::_ldc2_w: | 347 case Bytecodes::_ldc2_w: |
331 print_constant(get_big_index(), st); | 348 print_constant(get_index_u2(), st); |
332 break; | 349 break; |
333 | 350 |
334 case Bytecodes::_iload: | 351 case Bytecodes::_iload: |
335 case Bytecodes::_lload: | 352 case Bytecodes::_lload: |
336 case Bytecodes::_fload: | 353 case Bytecodes::_fload: |
350 st->print_cr(" #%d " INT32_FORMAT, index, offset); | 367 st->print_cr(" #%d " INT32_FORMAT, index, offset); |
351 } | 368 } |
352 break; | 369 break; |
353 | 370 |
354 case Bytecodes::_newarray: { | 371 case Bytecodes::_newarray: { |
355 BasicType atype = (BasicType)get_index(); | 372 BasicType atype = (BasicType)get_index_u1(); |
356 const char* str = type2name(atype); | 373 const char* str = type2name(atype); |
357 if (str == NULL || atype == T_OBJECT || atype == T_ARRAY) { | 374 if (str == NULL || atype == T_OBJECT || atype == T_ARRAY) { |
358 assert(false, "Unidentified basic type"); | 375 assert(false, "Unidentified basic type"); |
359 } | 376 } |
360 st->print_cr(" %s", str); | 377 st->print_cr(" %s", str); |
361 } | 378 } |
362 break; | 379 break; |
363 case Bytecodes::_anewarray: { | 380 case Bytecodes::_anewarray: { |
364 int klass_index = get_big_index(); | 381 int klass_index = get_index_u2(); |
365 constantPoolOop constants = method()->constants(); | 382 constantPoolOop constants = method()->constants(); |
366 symbolOop name = constants->klass_name_at(klass_index); | 383 symbolOop name = constants->klass_name_at(klass_index); |
367 st->print_cr(" %s ", name->as_C_string()); | 384 st->print_cr(" %s ", name->as_C_string()); |
368 } | 385 } |
369 break; | 386 break; |
370 case Bytecodes::_multianewarray: { | 387 case Bytecodes::_multianewarray: { |
371 int klass_index = get_big_index(); | 388 int klass_index = get_index_u2(); |
372 int nof_dims = get_index(); | 389 int nof_dims = get_index_u1(); |
373 constantPoolOop constants = method()->constants(); | 390 constantPoolOop constants = method()->constants(); |
374 symbolOop name = constants->klass_name_at(klass_index); | 391 symbolOop name = constants->klass_name_at(klass_index); |
375 st->print_cr(" %s %d", name->as_C_string(), nof_dims); | 392 st->print_cr(" %s %d", name->as_C_string(), nof_dims); |
376 } | 393 } |
377 break; | 394 break; |
449 | 466 |
450 case Bytecodes::_putstatic: | 467 case Bytecodes::_putstatic: |
451 case Bytecodes::_getstatic: | 468 case Bytecodes::_getstatic: |
452 case Bytecodes::_putfield: | 469 case Bytecodes::_putfield: |
453 case Bytecodes::_getfield: | 470 case Bytecodes::_getfield: |
454 print_field_or_method(get_big_index(), st); | 471 print_field_or_method(get_index_u2_cpcache(), st); |
455 break; | 472 break; |
456 | 473 |
457 case Bytecodes::_invokevirtual: | 474 case Bytecodes::_invokevirtual: |
458 case Bytecodes::_invokespecial: | 475 case Bytecodes::_invokespecial: |
459 case Bytecodes::_invokestatic: | 476 case Bytecodes::_invokestatic: |
460 print_field_or_method(get_big_index(), st); | 477 print_field_or_method(get_index_u2_cpcache(), st); |
461 break; | 478 break; |
462 | 479 |
463 case Bytecodes::_invokeinterface: | 480 case Bytecodes::_invokeinterface: |
464 { int i = get_big_index(); | 481 { int i = get_index_u2_cpcache(); |
465 int n = get_index(); | 482 int n = get_index_u1(); |
466 get_index(); // ignore zero byte | 483 get_byte(); // ignore zero byte |
467 print_field_or_method(i, st); | 484 print_field_or_method(i, st); |
468 } | 485 } |
469 break; | 486 break; |
470 | 487 |
471 case Bytecodes::_invokedynamic: | 488 case Bytecodes::_invokedynamic: |
472 print_field_or_method(get_giant_index(), st); | 489 print_field_or_method(get_index_u4(), st); |
473 break; | 490 break; |
474 | 491 |
475 case Bytecodes::_new: | 492 case Bytecodes::_new: |
476 case Bytecodes::_checkcast: | 493 case Bytecodes::_checkcast: |
477 case Bytecodes::_instanceof: | 494 case Bytecodes::_instanceof: |
478 { int i = get_big_index(); | 495 { int i = get_index_u2(); |
479 constantPoolOop constants = method()->constants(); | 496 constantPoolOop constants = method()->constants(); |
480 symbolOop name = constants->klass_name_at(i); | 497 symbolOop name = constants->klass_name_at(i); |
481 st->print_cr(" %d <%s>", i, name->as_C_string()); | 498 st->print_cr(" %d <%s>", i, name->as_C_string()); |
482 } | 499 } |
483 break; | 500 break; |