1311 static inline int version_at(unsigned int merged) { |
1311 static inline int version_at(unsigned int merged) { |
1312 return extract_low_short_from_int(merged); |
1312 return extract_low_short_from_int(merged); |
1313 } |
1313 } |
1314 |
1314 |
1315 static inline bool version_matches(Method* method, int version) { |
1315 static inline bool version_matches(Method* method, int version) { |
1316 return (method->constants()->version() == version && version < MAX_VERSION); |
1316 assert(version < MAX_VERSION, "version is too big"); |
|
1317 return method != NULL && (method->constants()->version() == version); |
1317 } |
1318 } |
1318 |
1319 |
1319 static inline int get_line_number(Method* method, int bci) { |
1320 static inline int get_line_number(Method* method, int bci) { |
1320 int line_number = 0; |
1321 int line_number = 0; |
1321 if (method->is_native()) { |
1322 if (method->is_native()) { |
1341 Handle _backtrace; |
1342 Handle _backtrace; |
1342 objArrayOop _head; |
1343 objArrayOop _head; |
1343 typeArrayOop _methods; |
1344 typeArrayOop _methods; |
1344 typeArrayOop _bcis; |
1345 typeArrayOop _bcis; |
1345 objArrayOop _mirrors; |
1346 objArrayOop _mirrors; |
|
1347 typeArrayOop _cprefs; // needed to insulate method name against redefinition |
1346 int _index; |
1348 int _index; |
1347 No_Safepoint_Verifier _nsv; |
1349 No_Safepoint_Verifier _nsv; |
1348 |
1350 |
1349 public: |
1351 public: |
1350 |
1352 |
1351 enum { |
1353 enum { |
1352 trace_methods_offset = java_lang_Throwable::trace_methods_offset, |
1354 trace_methods_offset = java_lang_Throwable::trace_methods_offset, |
1353 trace_bcis_offset = java_lang_Throwable::trace_bcis_offset, |
1355 trace_bcis_offset = java_lang_Throwable::trace_bcis_offset, |
1354 trace_mirrors_offset = java_lang_Throwable::trace_mirrors_offset, |
1356 trace_mirrors_offset = java_lang_Throwable::trace_mirrors_offset, |
|
1357 trace_cprefs_offset = java_lang_Throwable::trace_cprefs_offset, |
1355 trace_next_offset = java_lang_Throwable::trace_next_offset, |
1358 trace_next_offset = java_lang_Throwable::trace_next_offset, |
1356 trace_size = java_lang_Throwable::trace_size, |
1359 trace_size = java_lang_Throwable::trace_size, |
1357 trace_chunk_size = java_lang_Throwable::trace_chunk_size |
1360 trace_chunk_size = java_lang_Throwable::trace_chunk_size |
1358 }; |
1361 }; |
1359 |
1362 |
1371 static objArrayOop get_mirrors(objArrayHandle chunk) { |
1374 static objArrayOop get_mirrors(objArrayHandle chunk) { |
1372 objArrayOop mirrors = objArrayOop(chunk->obj_at(trace_mirrors_offset)); |
1375 objArrayOop mirrors = objArrayOop(chunk->obj_at(trace_mirrors_offset)); |
1373 assert(mirrors != NULL, "mirror array should be initialized in backtrace"); |
1376 assert(mirrors != NULL, "mirror array should be initialized in backtrace"); |
1374 return mirrors; |
1377 return mirrors; |
1375 } |
1378 } |
|
1379 static typeArrayOop get_cprefs(objArrayHandle chunk) { |
|
1380 typeArrayOop cprefs = typeArrayOop(chunk->obj_at(trace_cprefs_offset)); |
|
1381 assert(cprefs != NULL, "cprefs array should be initialized in backtrace"); |
|
1382 return cprefs; |
|
1383 } |
1376 |
1384 |
1377 // constructor for new backtrace |
1385 // constructor for new backtrace |
1378 BacktraceBuilder(TRAPS): _methods(NULL), _bcis(NULL), _head(NULL), _mirrors(NULL) { |
1386 BacktraceBuilder(TRAPS): _methods(NULL), _bcis(NULL), _head(NULL), _mirrors(NULL), _cprefs(NULL) { |
1379 expand(CHECK); |
1387 expand(CHECK); |
1380 _backtrace = _head; |
1388 _backtrace = _head; |
1381 _index = 0; |
1389 _index = 0; |
1382 } |
1390 } |
1383 |
1391 |
1384 BacktraceBuilder(objArrayHandle backtrace) { |
1392 BacktraceBuilder(objArrayHandle backtrace) { |
1385 _methods = get_methods(backtrace); |
1393 _methods = get_methods(backtrace); |
1386 _bcis = get_bcis(backtrace); |
1394 _bcis = get_bcis(backtrace); |
1387 _mirrors = get_mirrors(backtrace); |
1395 _mirrors = get_mirrors(backtrace); |
|
1396 _cprefs = get_cprefs(backtrace); |
1388 assert(_methods->length() == _bcis->length() && |
1397 assert(_methods->length() == _bcis->length() && |
1389 _methods->length() == _mirrors->length(), |
1398 _methods->length() == _mirrors->length(), |
1390 "method and source information arrays should match"); |
1399 "method and source information arrays should match"); |
1391 |
1400 |
1392 // head is the preallocated backtrace |
1401 // head is the preallocated backtrace |
1408 typeArrayHandle new_bcis(THREAD, bcis); |
1417 typeArrayHandle new_bcis(THREAD, bcis); |
1409 |
1418 |
1410 objArrayOop mirrors = oopFactory::new_objectArray(trace_chunk_size, CHECK); |
1419 objArrayOop mirrors = oopFactory::new_objectArray(trace_chunk_size, CHECK); |
1411 objArrayHandle new_mirrors(THREAD, mirrors); |
1420 objArrayHandle new_mirrors(THREAD, mirrors); |
1412 |
1421 |
|
1422 typeArrayOop cprefs = oopFactory::new_shortArray(trace_chunk_size, CHECK); |
|
1423 typeArrayHandle new_cprefs(THREAD, cprefs); |
|
1424 |
1413 if (!old_head.is_null()) { |
1425 if (!old_head.is_null()) { |
1414 old_head->obj_at_put(trace_next_offset, new_head()); |
1426 old_head->obj_at_put(trace_next_offset, new_head()); |
1415 } |
1427 } |
1416 new_head->obj_at_put(trace_methods_offset, new_methods()); |
1428 new_head->obj_at_put(trace_methods_offset, new_methods()); |
1417 new_head->obj_at_put(trace_bcis_offset, new_bcis()); |
1429 new_head->obj_at_put(trace_bcis_offset, new_bcis()); |
1418 new_head->obj_at_put(trace_mirrors_offset, new_mirrors()); |
1430 new_head->obj_at_put(trace_mirrors_offset, new_mirrors()); |
|
1431 new_head->obj_at_put(trace_cprefs_offset, new_cprefs()); |
1419 |
1432 |
1420 _head = new_head(); |
1433 _head = new_head(); |
1421 _methods = new_methods(); |
1434 _methods = new_methods(); |
1422 _bcis = new_bcis(); |
1435 _bcis = new_bcis(); |
1423 _mirrors = new_mirrors(); |
1436 _mirrors = new_mirrors(); |
|
1437 _cprefs = new_cprefs(); |
1424 _index = 0; |
1438 _index = 0; |
1425 } |
1439 } |
1426 |
1440 |
1427 oop backtrace() { |
1441 oop backtrace() { |
1428 return _backtrace(); |
1442 return _backtrace(); |
1438 methodHandle mhandle(THREAD, method); |
1452 methodHandle mhandle(THREAD, method); |
1439 expand(CHECK); |
1453 expand(CHECK); |
1440 method = mhandle(); |
1454 method = mhandle(); |
1441 } |
1455 } |
1442 |
1456 |
1443 _methods->short_at_put(_index, method->method_idnum()); |
1457 _methods->short_at_put(_index, method->orig_method_idnum()); |
1444 _bcis->int_at_put(_index, merge_bci_and_version(bci, method->constants()->version())); |
1458 _bcis->int_at_put(_index, merge_bci_and_version(bci, method->constants()->version())); |
|
1459 _cprefs->short_at_put(_index, method->name_index()); |
1445 |
1460 |
1446 // We need to save the mirrors in the backtrace to keep the class |
1461 // We need to save the mirrors in the backtrace to keep the class |
1447 // from being unloaded while we still have this stack trace. |
1462 // from being unloaded while we still have this stack trace. |
1448 assert(method->method_holder()->java_mirror() != NULL, "never push null for mirror"); |
1463 assert(method->method_holder()->java_mirror() != NULL, "never push null for mirror"); |
1449 _mirrors->obj_at_put(_index, method->method_holder()->java_mirror()); |
1464 _mirrors->obj_at_put(_index, method->method_holder()->java_mirror()); |
1452 |
1467 |
1453 }; |
1468 }; |
1454 |
1469 |
1455 // Print stack trace element to resource allocated buffer |
1470 // Print stack trace element to resource allocated buffer |
1456 char* java_lang_Throwable::print_stack_element_to_buffer(Handle mirror, |
1471 char* java_lang_Throwable::print_stack_element_to_buffer(Handle mirror, |
1457 int method_id, int version, int bci) { |
1472 int method_id, int version, int bci, int cpref) { |
1458 |
1473 |
1459 // Get strings and string lengths |
1474 // Get strings and string lengths |
1460 InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(mirror())); |
1475 InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(mirror())); |
1461 const char* klass_name = holder->external_name(); |
1476 const char* klass_name = holder->external_name(); |
1462 int buf_len = (int)strlen(klass_name); |
1477 int buf_len = (int)strlen(klass_name); |
1463 |
1478 |
1464 // The method id may point to an obsolete method, can't get more stack information |
1479 Method* method = holder->method_with_orig_idnum(method_id, version); |
1465 Method* method = holder->method_with_idnum(method_id); |
1480 |
1466 if (method == NULL) { |
1481 // The method can be NULL if the requested class version is gone |
1467 char* buf = NEW_RESOURCE_ARRAY(char, buf_len + 64); |
1482 Symbol* sym = (method != NULL) ? method->name() : holder->constants()->symbol_at(cpref); |
1468 // This is what the java code prints in this case - added Redefined |
1483 char* method_name = sym->as_C_string(); |
1469 sprintf(buf, "\tat %s.null (Redefined)", klass_name); |
|
1470 return buf; |
|
1471 } |
|
1472 |
|
1473 char* method_name = method->name()->as_C_string(); |
|
1474 buf_len += (int)strlen(method_name); |
1484 buf_len += (int)strlen(method_name); |
1475 |
1485 |
|
1486 // Use specific ik version as a holder since the mirror might |
|
1487 // refer to version that is now obsolete and no longer accessible |
|
1488 // via the previous versions list. |
|
1489 holder = holder->get_klass_version(version); |
1476 char* source_file_name = NULL; |
1490 char* source_file_name = NULL; |
1477 if (version_matches(method, version)) { |
1491 if (holder != NULL) { |
1478 Symbol* source = holder->source_file_name(); |
1492 Symbol* source = holder->source_file_name(); |
1479 if (source != NULL) { |
1493 if (source != NULL) { |
1480 source_file_name = source->as_C_string(); |
1494 source_file_name = source->as_C_string(); |
1481 buf_len += (int)strlen(source_file_name); |
1495 buf_len += (int)strlen(source_file_name); |
1482 } |
1496 } |
1514 |
1528 |
1515 return buf; |
1529 return buf; |
1516 } |
1530 } |
1517 |
1531 |
1518 void java_lang_Throwable::print_stack_element(outputStream *st, Handle mirror, |
1532 void java_lang_Throwable::print_stack_element(outputStream *st, Handle mirror, |
1519 int method_id, int version, int bci) { |
1533 int method_id, int version, int bci, int cpref) { |
1520 ResourceMark rm; |
1534 ResourceMark rm; |
1521 char* buf = print_stack_element_to_buffer(mirror, method_id, version, bci); |
1535 char* buf = print_stack_element_to_buffer(mirror, method_id, version, bci, cpref); |
1522 st->print_cr("%s", buf); |
1536 st->print_cr("%s", buf); |
1523 } |
1537 } |
1524 |
1538 |
1525 void java_lang_Throwable::print_stack_element(outputStream *st, methodHandle method, int bci) { |
1539 void java_lang_Throwable::print_stack_element(outputStream *st, methodHandle method, int bci) { |
1526 Handle mirror = method->method_holder()->java_mirror(); |
1540 Handle mirror = method->method_holder()->java_mirror(); |
1527 int method_id = method->method_idnum(); |
1541 int method_id = method->orig_method_idnum(); |
1528 int version = method->constants()->version(); |
1542 int version = method->constants()->version(); |
1529 print_stack_element(st, mirror, method_id, version, bci); |
1543 int cpref = method->name_index(); |
|
1544 print_stack_element(st, mirror, method_id, version, bci, cpref); |
1530 } |
1545 } |
1531 |
1546 |
1532 const char* java_lang_Throwable::no_stack_trace_message() { |
1547 const char* java_lang_Throwable::no_stack_trace_message() { |
1533 return "\t<<no stack trace available>>"; |
1548 return "\t<<no stack trace available>>"; |
1534 } |
1549 } |
1549 |
1564 |
1550 // Get method id, bci, version and mirror from chunk |
1565 // Get method id, bci, version and mirror from chunk |
1551 typeArrayHandle methods (THREAD, BacktraceBuilder::get_methods(result)); |
1566 typeArrayHandle methods (THREAD, BacktraceBuilder::get_methods(result)); |
1552 typeArrayHandle bcis (THREAD, BacktraceBuilder::get_bcis(result)); |
1567 typeArrayHandle bcis (THREAD, BacktraceBuilder::get_bcis(result)); |
1553 objArrayHandle mirrors (THREAD, BacktraceBuilder::get_mirrors(result)); |
1568 objArrayHandle mirrors (THREAD, BacktraceBuilder::get_mirrors(result)); |
|
1569 typeArrayHandle cprefs (THREAD, BacktraceBuilder::get_cprefs(result)); |
1554 |
1570 |
1555 int length = methods()->length(); |
1571 int length = methods()->length(); |
1556 for (int index = 0; index < length; index++) { |
1572 for (int index = 0; index < length; index++) { |
1557 Handle mirror(THREAD, mirrors->obj_at(index)); |
1573 Handle mirror(THREAD, mirrors->obj_at(index)); |
1558 // NULL mirror means end of stack trace |
1574 // NULL mirror means end of stack trace |
1559 if (mirror.is_null()) goto handle_cause; |
1575 if (mirror.is_null()) goto handle_cause; |
1560 int method = methods->short_at(index); |
1576 int method = methods->short_at(index); |
1561 int version = version_at(bcis->int_at(index)); |
1577 int version = version_at(bcis->int_at(index)); |
1562 int bci = bci_at(bcis->int_at(index)); |
1578 int bci = bci_at(bcis->int_at(index)); |
1563 print_stack_element(st, mirror, method, version, bci); |
1579 int cpref = cprefs->short_at(index); |
|
1580 print_stack_element(st, mirror, method, version, bci, cpref); |
1564 } |
1581 } |
1565 result = objArrayHandle(THREAD, objArrayOop(result->obj_at(trace_next_offset))); |
1582 result = objArrayHandle(THREAD, objArrayOop(result->obj_at(trace_next_offset))); |
1566 } |
1583 } |
1567 handle_cause: |
1584 handle_cause: |
1568 { |
1585 { |
1835 skip_chunks--; |
1852 skip_chunks--; |
1836 } |
1853 } |
1837 if (chunk == NULL) { |
1854 if (chunk == NULL) { |
1838 THROW_(vmSymbols::java_lang_IndexOutOfBoundsException(), NULL); |
1855 THROW_(vmSymbols::java_lang_IndexOutOfBoundsException(), NULL); |
1839 } |
1856 } |
1840 // Get method id, bci, version and mirror from chunk |
1857 // Get method id, bci, version, mirror and cpref from chunk |
1841 typeArrayOop methods = BacktraceBuilder::get_methods(chunk); |
1858 typeArrayOop methods = BacktraceBuilder::get_methods(chunk); |
1842 typeArrayOop bcis = BacktraceBuilder::get_bcis(chunk); |
1859 typeArrayOop bcis = BacktraceBuilder::get_bcis(chunk); |
1843 objArrayOop mirrors = BacktraceBuilder::get_mirrors(chunk); |
1860 objArrayOop mirrors = BacktraceBuilder::get_mirrors(chunk); |
|
1861 typeArrayOop cprefs = BacktraceBuilder::get_cprefs(chunk); |
1844 |
1862 |
1845 assert(methods != NULL && bcis != NULL && mirrors != NULL, "sanity check"); |
1863 assert(methods != NULL && bcis != NULL && mirrors != NULL, "sanity check"); |
1846 |
1864 |
1847 int method = methods->short_at(chunk_index); |
1865 int method = methods->short_at(chunk_index); |
1848 int version = version_at(bcis->int_at(chunk_index)); |
1866 int version = version_at(bcis->int_at(chunk_index)); |
1849 int bci = bci_at(bcis->int_at(chunk_index)); |
1867 int bci = bci_at(bcis->int_at(chunk_index)); |
|
1868 int cpref = cprefs->short_at(chunk_index); |
1850 Handle mirror(THREAD, mirrors->obj_at(chunk_index)); |
1869 Handle mirror(THREAD, mirrors->obj_at(chunk_index)); |
1851 |
1870 |
1852 // Chunk can be partial full |
1871 // Chunk can be partial full |
1853 if (mirror.is_null()) { |
1872 if (mirror.is_null()) { |
1854 THROW_(vmSymbols::java_lang_IndexOutOfBoundsException(), NULL); |
1873 THROW_(vmSymbols::java_lang_IndexOutOfBoundsException(), NULL); |
1855 } |
1874 } |
1856 |
1875 oop element = java_lang_StackTraceElement::create(mirror, method, version, bci, cpref, CHECK_0); |
1857 oop element = java_lang_StackTraceElement::create(mirror, method, version, bci, CHECK_0); |
|
1858 return element; |
1876 return element; |
1859 } |
1877 } |
1860 |
1878 |
1861 oop java_lang_StackTraceElement::create(Handle mirror, int method_id, |
1879 oop java_lang_StackTraceElement::create(Handle mirror, int method_id, |
1862 int version, int bci, TRAPS) { |
1880 int version, int bci, int cpref, TRAPS) { |
1863 // Allocate java.lang.StackTraceElement instance |
1881 // Allocate java.lang.StackTraceElement instance |
1864 Klass* k = SystemDictionary::StackTraceElement_klass(); |
1882 Klass* k = SystemDictionary::StackTraceElement_klass(); |
1865 assert(k != NULL, "must be loaded in 1.4+"); |
1883 assert(k != NULL, "must be loaded in 1.4+"); |
1866 instanceKlassHandle ik (THREAD, k); |
1884 instanceKlassHandle ik (THREAD, k); |
1867 if (ik->should_be_initialized()) { |
1885 if (ik->should_be_initialized()) { |
1874 InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(mirror())); |
1892 InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(mirror())); |
1875 const char* str = holder->external_name(); |
1893 const char* str = holder->external_name(); |
1876 oop classname = StringTable::intern((char*) str, CHECK_0); |
1894 oop classname = StringTable::intern((char*) str, CHECK_0); |
1877 java_lang_StackTraceElement::set_declaringClass(element(), classname); |
1895 java_lang_StackTraceElement::set_declaringClass(element(), classname); |
1878 |
1896 |
1879 Method* method = holder->method_with_idnum(method_id); |
1897 Method* method = holder->method_with_orig_idnum(method_id, version); |
1880 // Method on stack may be obsolete because it was redefined so cannot be |
1898 |
1881 // found by idnum. |
1899 // The method can be NULL if the requested class version is gone |
1882 if (method == NULL) { |
1900 Symbol* sym = (method != NULL) ? method->name() : holder->constants()->symbol_at(cpref); |
1883 // leave name and fileName null |
|
1884 java_lang_StackTraceElement::set_lineNumber(element(), -1); |
|
1885 return element(); |
|
1886 } |
|
1887 |
1901 |
1888 // Fill in method name |
1902 // Fill in method name |
1889 oop methodname = StringTable::intern(method->name(), CHECK_0); |
1903 oop methodname = StringTable::intern(sym, CHECK_0); |
1890 java_lang_StackTraceElement::set_methodName(element(), methodname); |
1904 java_lang_StackTraceElement::set_methodName(element(), methodname); |
1891 |
1905 |
1892 if (!version_matches(method, version)) { |
1906 if (!version_matches(method, version)) { |
1893 // The method was redefined, accurate line number information isn't available |
1907 // The method was redefined, accurate line number information isn't available |
1894 java_lang_StackTraceElement::set_fileName(element(), NULL); |
1908 java_lang_StackTraceElement::set_fileName(element(), NULL); |
1895 java_lang_StackTraceElement::set_lineNumber(element(), -1); |
1909 java_lang_StackTraceElement::set_lineNumber(element(), -1); |
1896 } else { |
1910 } else { |
1897 // Fill in source file name and line number. |
1911 // Fill in source file name and line number. |
|
1912 // Use specific ik version as a holder since the mirror might |
|
1913 // refer to version that is now obsolete and no longer accessible |
|
1914 // via the previous versions list. |
|
1915 holder = holder->get_klass_version(version); |
|
1916 assert(holder != NULL, "sanity check"); |
1898 Symbol* source = holder->source_file_name(); |
1917 Symbol* source = holder->source_file_name(); |
1899 if (ShowHiddenFrames && source == NULL) |
1918 if (ShowHiddenFrames && source == NULL) |
1900 source = vmSymbols::unknown_class_name(); |
1919 source = vmSymbols::unknown_class_name(); |
1901 oop filename = StringTable::intern(source, CHECK_0); |
1920 oop filename = StringTable::intern(source, CHECK_0); |
1902 java_lang_StackTraceElement::set_fileName(element(), filename); |
1921 java_lang_StackTraceElement::set_fileName(element(), filename); |
1907 return element(); |
1926 return element(); |
1908 } |
1927 } |
1909 |
1928 |
1910 oop java_lang_StackTraceElement::create(methodHandle method, int bci, TRAPS) { |
1929 oop java_lang_StackTraceElement::create(methodHandle method, int bci, TRAPS) { |
1911 Handle mirror (THREAD, method->method_holder()->java_mirror()); |
1930 Handle mirror (THREAD, method->method_holder()->java_mirror()); |
1912 int method_id = method->method_idnum(); |
1931 int method_id = method->orig_method_idnum(); |
1913 return create(mirror, method_id, method->constants()->version(), bci, THREAD); |
1932 int cpref = method->name_index(); |
|
1933 return create(mirror, method_id, method->constants()->version(), bci, cpref, THREAD); |
1914 } |
1934 } |
1915 |
1935 |
1916 void java_lang_reflect_AccessibleObject::compute_offsets() { |
1936 void java_lang_reflect_AccessibleObject::compute_offsets() { |
1917 Klass* k = SystemDictionary::reflect_AccessibleObject_klass(); |
1937 Klass* k = SystemDictionary::reflect_AccessibleObject_klass(); |
1918 compute_offset(override_offset, k, vmSymbols::override_name(), vmSymbols::bool_signature()); |
1938 compute_offset(override_offset, k, vmSymbols::override_name(), vmSymbols::bool_signature()); |