Mercurial > hg > truffle
comparison src/share/vm/interpreter/bytecodeTracer.cpp @ 6725:da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
Summary: Remove PermGen, allocate meta-data in metaspace linked to class loaders, rewrite GC walking, rewrite and rename metadata to be C++ classes
Reviewed-by: jmasa, stefank, never, coleenp, kvn, brutisso, mgerdin, dholmes, jrose, twisti, roland
Contributed-by: jmasa <jon.masamitsu@oracle.com>, stefank <stefan.karlsson@oracle.com>, mgerdin <mikael.gerdin@oracle.com>, never <tom.rodriguez@oracle.com>
author | coleenp |
---|---|
date | Sat, 01 Sep 2012 13:25:18 -0400 |
parents | b20d64f83668 |
children | f16e75e0cf11 |
comparison
equal
deleted
inserted
replaced
6724:36d1d483d5d6 | 6725:da91efe96a93 |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. | 2 * Copyright (c) 1997, 2012, 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. |
27 #include "interpreter/bytecodeTracer.hpp" | 27 #include "interpreter/bytecodeTracer.hpp" |
28 #include "interpreter/bytecodes.hpp" | 28 #include "interpreter/bytecodes.hpp" |
29 #include "interpreter/interpreter.hpp" | 29 #include "interpreter/interpreter.hpp" |
30 #include "interpreter/interpreterRuntime.hpp" | 30 #include "interpreter/interpreterRuntime.hpp" |
31 #include "memory/resourceArea.hpp" | 31 #include "memory/resourceArea.hpp" |
32 #include "oops/methodDataOop.hpp" | 32 #include "oops/methodData.hpp" |
33 #include "oops/methodOop.hpp" | 33 #include "oops/method.hpp" |
34 #include "runtime/mutexLocker.hpp" | 34 #include "runtime/mutexLocker.hpp" |
35 #include "runtime/timer.hpp" | 35 #include "runtime/timer.hpp" |
36 | 36 |
37 | 37 |
38 #ifndef PRODUCT | 38 #ifndef PRODUCT |
44 private: | 44 private: |
45 // %%% This field is not GC-ed, and so can contain garbage | 45 // %%% This field is not GC-ed, and so can contain garbage |
46 // between critical sections. Use only pointer-comparison | 46 // between critical sections. Use only pointer-comparison |
47 // operations on the pointer, except within a critical section. | 47 // operations on the pointer, except within a critical section. |
48 // (Also, ensure that occasional false positives are benign.) | 48 // (Also, ensure that occasional false positives are benign.) |
49 methodOop _current_method; | 49 Method* _current_method; |
50 bool _is_wide; | 50 bool _is_wide; |
51 Bytecodes::Code _code; | 51 Bytecodes::Code _code; |
52 address _next_pc; // current decoding position | 52 address _next_pc; // current decoding position |
53 | 53 |
54 void align() { _next_pc = (address)round_to((intptr_t)_next_pc, sizeof(jint)); } | 54 void align() { _next_pc = (address)round_to((intptr_t)_next_pc, sizeof(jint)); } |
56 short get_short() { short i=Bytes::get_Java_u2(_next_pc); _next_pc+=2; return i; } | 56 short get_short() { short i=Bytes::get_Java_u2(_next_pc); _next_pc+=2; return i; } |
57 int get_int() { int i=Bytes::get_Java_u4(_next_pc); _next_pc+=4; return i; } | 57 int get_int() { int i=Bytes::get_Java_u4(_next_pc); _next_pc+=4; return i; } |
58 | 58 |
59 int get_index_u1() { return *(address)_next_pc++; } | 59 int get_index_u1() { return *(address)_next_pc++; } |
60 int get_index_u2() { int i=Bytes::get_Java_u2(_next_pc); _next_pc+=2; return i; } | 60 int get_index_u2() { int i=Bytes::get_Java_u2(_next_pc); _next_pc+=2; return i; } |
61 int get_index_u1_cpcache() { return get_index_u1() + constantPoolOopDesc::CPCACHE_INDEX_TAG; } | 61 int get_index_u1_cpcache() { return get_index_u1() + ConstantPool::CPCACHE_INDEX_TAG; } |
62 int get_index_u2_cpcache() { int i=Bytes::get_native_u2(_next_pc); _next_pc+=2; return i + constantPoolOopDesc::CPCACHE_INDEX_TAG; } | 62 int get_index_u2_cpcache() { int i=Bytes::get_native_u2(_next_pc); _next_pc+=2; return i + ConstantPool::CPCACHE_INDEX_TAG; } |
63 int get_index_u4() { int i=Bytes::get_native_u4(_next_pc); _next_pc+=4; return i; } | 63 int get_index_u4() { int i=Bytes::get_native_u4(_next_pc); _next_pc+=4; return i; } |
64 int get_index_special() { return (is_wide()) ? get_index_u2() : get_index_u1(); } | 64 int get_index_special() { return (is_wide()) ? get_index_u2() : get_index_u1(); } |
65 methodOop method() { return _current_method; } | 65 Method* method() { return _current_method; } |
66 bool is_wide() { return _is_wide; } | 66 bool is_wide() { return _is_wide; } |
67 Bytecodes::Code raw_code() { return Bytecodes::Code(_code); } | 67 Bytecodes::Code raw_code() { return Bytecodes::Code(_code); } |
68 | 68 |
69 | 69 |
70 bool check_index(int i, int& cp_index, outputStream* st = tty); | 70 bool check_index(int i, int& cp_index, outputStream* st = tty); |
71 bool check_cp_cache_index(int i, int& cp_index, outputStream* st = tty); | |
72 bool check_obj_index(int i, int& cp_index, outputStream* st = tty); | |
73 bool check_invokedynamic_index(int i, int& cp_index, outputStream* st = tty); | |
71 void print_constant(int i, outputStream* st = tty); | 74 void print_constant(int i, outputStream* st = tty); |
72 void print_field_or_method(int i, outputStream* st = tty); | 75 void print_field_or_method(int i, outputStream* st = tty); |
73 void print_field_or_method(int orig_i, int i, outputStream* st = tty); | 76 void print_field_or_method(int orig_i, int i, outputStream* st = tty); |
74 void print_attributes(int bci, outputStream* st = tty); | 77 void print_attributes(int bci, outputStream* st = tty); |
75 void bytecode_epilog(int bci, outputStream* st = tty); | 78 void bytecode_epilog(int bci, outputStream* st = tty); |
120 // the next bytecode. | 123 // the next bytecode. |
121 _is_wide = (code == Bytecodes::_wide); | 124 _is_wide = (code == Bytecodes::_wide); |
122 _code = Bytecodes::_illegal; | 125 _code = Bytecodes::_illegal; |
123 } | 126 } |
124 | 127 |
125 // Used for methodOop::print_codes(). The input bcp comes from | 128 // Used for Method*::print_codes(). The input bcp comes from |
126 // BytecodeStream, which will skip wide bytecodes. | 129 // BytecodeStream, which will skip wide bytecodes. |
127 void trace(methodHandle method, address bcp, outputStream* st) { | 130 void trace(methodHandle method, address bcp, outputStream* st) { |
128 _current_method = method(); | 131 _current_method = method(); |
129 ResourceMark rm; | 132 ResourceMark rm; |
130 Bytecodes::Code code = Bytecodes::code_at(method(), bcp); | 133 Bytecodes::Code code = Bytecodes::code_at(method(), bcp); |
150 | 153 |
151 // Implementation of BytecodeTracer | 154 // Implementation of BytecodeTracer |
152 | 155 |
153 // %%% This set_closure thing seems overly general, given that | 156 // %%% This set_closure thing seems overly general, given that |
154 // nobody uses it. Also, if BytecodePrinter weren't hidden | 157 // nobody uses it. Also, if BytecodePrinter weren't hidden |
155 // then methodOop could use instances of it directly and it | 158 // then Method* could use instances of it directly and it |
156 // would be easier to remove races on _current_method and bcp. | 159 // would be easier to remove races on _current_method and bcp. |
157 // Since this is not product functionality, we can defer cleanup. | 160 // Since this is not product functionality, we can defer cleanup. |
158 | 161 |
159 BytecodeClosure* BytecodeTracer::_closure = NULL; | 162 BytecodeClosure* BytecodeTracer::_closure = NULL; |
160 | 163 |
168 if (TraceBytecodes && BytecodeCounter::counter_value() >= TraceBytecodesAt) { | 171 if (TraceBytecodes && BytecodeCounter::counter_value() >= TraceBytecodesAt) { |
169 ttyLocker ttyl; // 5065316: keep the following output coherent | 172 ttyLocker ttyl; // 5065316: keep the following output coherent |
170 // The ttyLocker also prevents races between two threads | 173 // The ttyLocker also prevents races between two threads |
171 // trying to use the single instance of BytecodePrinter. | 174 // trying to use the single instance of BytecodePrinter. |
172 // Using the ttyLocker prevents the system from coming to | 175 // Using the ttyLocker prevents the system from coming to |
173 // a safepoint within this code, which is sensitive to methodOop | 176 // a safepoint within this code, which is sensitive to Method* |
174 // movement. | 177 // movement. |
175 // | 178 // |
176 // There used to be a leaf mutex here, but the ttyLocker will | 179 // There used to be a leaf mutex here, but the ttyLocker will |
177 // work just as well, as long as the printing operations never block. | 180 // work just as well, as long as the printing operations never block. |
178 // | 181 // |
215 st->print_cr(" " PTR_FORMAT, (intptr_t) value); | 218 st->print_cr(" " PTR_FORMAT, (intptr_t) value); |
216 } | 219 } |
217 } | 220 } |
218 | 221 |
219 bool BytecodePrinter::check_index(int i, int& cp_index, outputStream* st) { | 222 bool BytecodePrinter::check_index(int i, int& cp_index, outputStream* st) { |
220 constantPoolOop constants = method()->constants(); | 223 ConstantPool* constants = method()->constants(); |
224 int ilimit = constants->length(); | |
225 Bytecodes::Code code = raw_code(); | |
226 | |
227 ConstantPoolCache* cache = NULL; | |
228 if (Bytecodes::uses_cp_cache(code)) { | |
229 bool okay = true; | |
230 switch (code) { | |
231 case Bytecodes::_fast_aldc: | |
232 case Bytecodes::_fast_aldc_w: | |
233 okay = check_obj_index(i, cp_index, st); | |
234 break; | |
235 case Bytecodes::_invokedynamic: | |
236 okay = check_invokedynamic_index(i, cp_index, st); | |
237 break; | |
238 default: | |
239 okay = check_cp_cache_index(i, cp_index, st); | |
240 break; | |
241 } | |
242 if (!okay) return false; | |
243 } | |
244 | |
245 | |
246 // check cp index | |
247 if (cp_index >= 0 && cp_index < ilimit) { | |
248 if (WizardMode) st->print(" cp[%d]", cp_index); | |
249 return true; | |
250 } | |
251 | |
252 st->print_cr(" CP[%d] not in CP", cp_index); | |
253 return false; | |
254 } | |
255 | |
256 bool BytecodePrinter::check_cp_cache_index(int i, int& cp_index, outputStream* st) { | |
257 ConstantPool* constants = method()->constants(); | |
221 int ilimit = constants->length(), climit = 0; | 258 int ilimit = constants->length(), climit = 0; |
222 Bytecodes::Code code = raw_code(); | 259 Bytecodes::Code code = raw_code(); |
223 | 260 |
224 constantPoolCacheOop cache = NULL; | 261 ConstantPoolCache* cache = constants->cache(); |
225 if (Bytecodes::uses_cp_cache(code)) { | 262 // If rewriter hasn't run, the index is the cp_index |
226 cache = constants->cache(); | 263 if (cache == NULL) { |
227 if (cache != NULL) { | |
228 //climit = cache->length(); // %%% private! | |
229 size_t size = cache->size() * HeapWordSize; | |
230 size -= sizeof(constantPoolCacheOopDesc); | |
231 size /= sizeof(ConstantPoolCacheEntry); | |
232 climit = (int) size; | |
233 } | |
234 } | |
235 | |
236 if (cache != NULL && constantPoolCacheOopDesc::is_secondary_index(i)) { | |
237 i = constantPoolCacheOopDesc::decode_secondary_index(i); | |
238 st->print(" secondary cache[%d] of", i); | |
239 if (i >= 0 && i < climit) { | |
240 if (!cache->entry_at(i)->is_secondary_entry()) { | |
241 st->print_cr(" not secondary entry?", i); | |
242 return false; | |
243 } | |
244 i = cache->entry_at(i)->main_entry_index() + constantPoolOopDesc::CPCACHE_INDEX_TAG; | |
245 goto check_cache_index; | |
246 } else { | |
247 st->print_cr(" not in cache[*]?", i); | |
248 return false; | |
249 } | |
250 } | |
251 | |
252 if (cache != NULL) { | |
253 goto check_cache_index; | |
254 } | |
255 | |
256 check_cp_index: | |
257 if (i >= 0 && i < ilimit) { | |
258 if (WizardMode) st->print(" cp[%d]", i); | |
259 cp_index = i; | 264 cp_index = i; |
260 return true; | 265 return true; |
261 } | 266 } |
262 | 267 //climit = cache->length(); // %%% private! |
263 st->print_cr(" CP[%d] not in CP", i); | 268 size_t size = cache->size() * HeapWordSize; |
264 return false; | 269 size -= sizeof(ConstantPoolCache); |
265 | 270 size /= sizeof(ConstantPoolCacheEntry); |
266 check_cache_index: | 271 climit = (int) size; |
272 | |
267 #ifdef ASSERT | 273 #ifdef ASSERT |
268 { | 274 { |
269 const int CPCACHE_INDEX_TAG = constantPoolOopDesc::CPCACHE_INDEX_TAG; | 275 const int CPCACHE_INDEX_TAG = ConstantPool::CPCACHE_INDEX_TAG; |
270 if (i >= CPCACHE_INDEX_TAG && i < climit + CPCACHE_INDEX_TAG) { | 276 if (i >= CPCACHE_INDEX_TAG && i < climit + CPCACHE_INDEX_TAG) { |
271 i -= CPCACHE_INDEX_TAG; | 277 i -= CPCACHE_INDEX_TAG; |
272 } else { | 278 } else { |
273 st->print_cr(" CP[%d] missing bias?", i); | 279 st->print_cr(" CP[%d] missing bias?", i); |
274 return false; | 280 return false; |
275 } | 281 } |
276 } | 282 } |
277 #endif //ASSERT | 283 #endif //ASSERT |
278 if (i >= 0 && i < climit) { | 284 if (i >= 0 && i < climit) { |
279 if (cache->entry_at(i)->is_secondary_entry()) { | 285 cp_index = cache->entry_at(i)->constant_pool_index(); |
280 st->print_cr(" secondary entry?"); | 286 } else { |
287 st->print_cr(" not in CP[*]?", i); | |
281 return false; | 288 return false; |
282 } | 289 } |
283 i = cache->entry_at(i)->constant_pool_index(); | 290 return true; |
284 goto check_cp_index; | 291 } |
285 } | 292 |
286 st->print_cr(" not in CP[*]?", i); | 293 |
294 bool BytecodePrinter::check_obj_index(int i, int& cp_index, outputStream* st) { | |
295 ConstantPool* constants = method()->constants(); | |
296 i -= ConstantPool::CPCACHE_INDEX_TAG; | |
297 | |
298 if (i >= 0 && i < constants->resolved_references()->length()) { | |
299 cp_index = constants->object_to_cp_index(i); | |
300 return true; | |
301 } else { | |
302 st->print_cr(" not in OBJ[*]?", i); | |
287 return false; | 303 return false; |
304 } | |
305 } | |
306 | |
307 | |
308 bool BytecodePrinter::check_invokedynamic_index(int i, int& cp_index, outputStream* st) { | |
309 ConstantPool* constants = method()->constants(); | |
310 assert(ConstantPool::is_invokedynamic_index(i), "not secondary index?"); | |
311 i = ConstantPool::decode_invokedynamic_index(i) + ConstantPool::CPCACHE_INDEX_TAG; | |
312 | |
313 return check_cp_cache_index(i, cp_index, st); | |
288 } | 314 } |
289 | 315 |
290 void BytecodePrinter::print_constant(int i, outputStream* st) { | 316 void BytecodePrinter::print_constant(int i, outputStream* st) { |
291 int orig_i = i; | 317 int orig_i = i; |
292 if (!check_index(orig_i, i, st)) return; | 318 if (!check_index(orig_i, i, st)) return; |
293 | 319 |
294 constantPoolOop constants = method()->constants(); | 320 ConstantPool* constants = method()->constants(); |
295 constantTag tag = constants->tag_at(i); | 321 constantTag tag = constants->tag_at(i); |
296 | 322 |
297 if (tag.is_int()) { | 323 if (tag.is_int()) { |
298 st->print_cr(" " INT32_FORMAT, constants->int_at(i)); | 324 st->print_cr(" " INT32_FORMAT, constants->int_at(i)); |
299 } else if (tag.is_long()) { | 325 } else if (tag.is_long()) { |
301 } else if (tag.is_float()) { | 327 } else if (tag.is_float()) { |
302 st->print_cr(" %f", constants->float_at(i)); | 328 st->print_cr(" %f", constants->float_at(i)); |
303 } else if (tag.is_double()) { | 329 } else if (tag.is_double()) { |
304 st->print_cr(" %f", constants->double_at(i)); | 330 st->print_cr(" %f", constants->double_at(i)); |
305 } else if (tag.is_string()) { | 331 } else if (tag.is_string()) { |
306 oop string = constants->pseudo_string_at(i); | |
307 print_oop(string, st); | |
308 } else if (tag.is_unresolved_string()) { | |
309 const char* string = constants->string_at_noresolve(i); | 332 const char* string = constants->string_at_noresolve(i); |
310 st->print_cr(" %s", string); | 333 st->print_cr(" %s", string); |
311 } else if (tag.is_klass()) { | 334 } else if (tag.is_klass()) { |
312 st->print_cr(" %s", constants->resolved_klass_at(i)->klass_part()->external_name()); | 335 st->print_cr(" %s", constants->resolved_klass_at(i)->external_name()); |
313 } else if (tag.is_unresolved_klass()) { | 336 } else if (tag.is_unresolved_klass()) { |
314 st->print_cr(" <unresolved klass at %d>", i); | 337 st->print_cr(" <unresolved klass at %d>", i); |
315 } else if (tag.is_object()) { | 338 } else if (tag.is_object()) { |
316 st->print(" <Object>"); | 339 st->print(" <Object>"); |
317 print_oop(constants->object_at(i), st); | 340 print_oop(constants->object_at(i), st); |
334 if (!check_index(orig_i, i, st)) return; | 357 if (!check_index(orig_i, i, st)) return; |
335 print_field_or_method(orig_i, i, st); | 358 print_field_or_method(orig_i, i, st); |
336 } | 359 } |
337 | 360 |
338 void BytecodePrinter::print_field_or_method(int orig_i, int i, outputStream* st) { | 361 void BytecodePrinter::print_field_or_method(int orig_i, int i, outputStream* st) { |
339 constantPoolOop constants = method()->constants(); | 362 ConstantPool* constants = method()->constants(); |
340 constantTag tag = constants->tag_at(i); | 363 constantTag tag = constants->tag_at(i); |
341 | 364 |
342 bool has_klass = true; | 365 bool has_klass = true; |
343 | 366 |
344 switch (tag.value()) { | 367 switch (tag.value()) { |
436 st->print_cr(" %s", str); | 459 st->print_cr(" %s", str); |
437 } | 460 } |
438 break; | 461 break; |
439 case Bytecodes::_anewarray: { | 462 case Bytecodes::_anewarray: { |
440 int klass_index = get_index_u2(); | 463 int klass_index = get_index_u2(); |
441 constantPoolOop constants = method()->constants(); | 464 ConstantPool* constants = method()->constants(); |
442 Symbol* name = constants->klass_name_at(klass_index); | 465 Symbol* name = constants->klass_name_at(klass_index); |
443 st->print_cr(" %s ", name->as_C_string()); | 466 st->print_cr(" %s ", name->as_C_string()); |
444 } | 467 } |
445 break; | 468 break; |
446 case Bytecodes::_multianewarray: { | 469 case Bytecodes::_multianewarray: { |
447 int klass_index = get_index_u2(); | 470 int klass_index = get_index_u2(); |
448 int nof_dims = get_index_u1(); | 471 int nof_dims = get_index_u1(); |
449 constantPoolOop constants = method()->constants(); | 472 ConstantPool* constants = method()->constants(); |
450 Symbol* name = constants->klass_name_at(klass_index); | 473 Symbol* name = constants->klass_name_at(klass_index); |
451 st->print_cr(" %s %d", name->as_C_string(), nof_dims); | 474 st->print_cr(" %s %d", name->as_C_string(), nof_dims); |
452 } | 475 } |
453 break; | 476 break; |
454 | 477 |
550 | 573 |
551 case Bytecodes::_new: | 574 case Bytecodes::_new: |
552 case Bytecodes::_checkcast: | 575 case Bytecodes::_checkcast: |
553 case Bytecodes::_instanceof: | 576 case Bytecodes::_instanceof: |
554 { int i = get_index_u2(); | 577 { int i = get_index_u2(); |
555 constantPoolOop constants = method()->constants(); | 578 ConstantPool* constants = method()->constants(); |
556 Symbol* name = constants->klass_name_at(i); | 579 Symbol* name = constants->klass_name_at(i); |
557 st->print_cr(" %d <%s>", i, name->as_C_string()); | 580 st->print_cr(" %d <%s>", i, name->as_C_string()); |
558 } | 581 } |
559 break; | 582 break; |
560 | 583 |
568 } | 591 } |
569 } | 592 } |
570 | 593 |
571 | 594 |
572 void BytecodePrinter::bytecode_epilog(int bci, outputStream* st) { | 595 void BytecodePrinter::bytecode_epilog(int bci, outputStream* st) { |
573 methodDataOop mdo = method()->method_data(); | 596 MethodData* mdo = method()->method_data(); |
574 if (mdo != NULL) { | 597 if (mdo != NULL) { |
575 ProfileData* data = mdo->bci_to_data(bci); | 598 ProfileData* data = mdo->bci_to_data(bci); |
576 if (data != NULL) { | 599 if (data != NULL) { |
577 st->print(" %d", mdo->dp_to_di(data->dp())); | 600 st->print(" %d", mdo->dp_to_di(data->dp())); |
578 st->fill_to(6); | 601 st->fill_to(6); |