--- a/src/hotspot/share/runtime/os.cpp Thu Oct 04 14:03:13 2018 +0200
+++ b/src/hotspot/share/runtime/os.cpp Thu Oct 04 16:39:07 2018 +0200
@@ -1010,6 +1010,15 @@
return (SafeFetch32(aligned, cafebabe) != cafebabe) || (SafeFetch32(aligned, deadbeef) != deadbeef);
}
+bool os::is_readable_range(const void* from, const void* to) {
+ for (address p = align_down((address)from, min_page_size()); p < to; p += min_page_size()) {
+ if (!is_readable_pointer(p)) {
+ return false;
+ }
+ }
+ return true;
+}
+
// moved from debug.cpp (used to be find()) but still called from there
// The verbose parameter is only set by the debug code in one case
@@ -1020,99 +1029,48 @@
st->print_cr("0x0 is NULL");
return;
}
+
+ // Check if addr points into a code blob.
CodeBlob* b = CodeCache::find_blob_unsafe(addr);
if (b != NULL) {
- if (b->is_buffer_blob()) {
- // the interpreter is generated into a buffer blob
- InterpreterCodelet* i = Interpreter::codelet_containing(addr);
- if (i != NULL) {
- st->print_cr(INTPTR_FORMAT " is at code_begin+%d in an Interpreter codelet", p2i(addr), (int)(addr - i->code_begin()));
- i->print_on(st);
- return;
- }
- if (Interpreter::contains(addr)) {
- st->print_cr(INTPTR_FORMAT " is pointing into interpreter code"
- " (not bytecode specific)", p2i(addr));
- return;
- }
- //
- if (AdapterHandlerLibrary::contains(b)) {
- st->print_cr(INTPTR_FORMAT " is at code_begin+%d in an AdapterHandler", p2i(addr), (int)(addr - b->code_begin()));
- AdapterHandlerLibrary::print_handler_on(st, b);
- }
- // the stubroutines are generated into a buffer blob
- StubCodeDesc* d = StubCodeDesc::desc_for(addr);
- if (d != NULL) {
- st->print_cr(INTPTR_FORMAT " is at begin+%d in a stub", p2i(addr), (int)(addr - d->begin()));
- d->print_on(st);
- st->cr();
- return;
- }
- if (StubRoutines::contains(addr)) {
- st->print_cr(INTPTR_FORMAT " is pointing to an (unnamed) stub routine", p2i(addr));
- return;
- }
- // the InlineCacheBuffer is using stubs generated into a buffer blob
- if (InlineCacheBuffer::contains(addr)) {
- st->print_cr(INTPTR_FORMAT " is pointing into InlineCacheBuffer", p2i(addr));
- return;
- }
- VtableStub* v = VtableStubs::stub_containing(addr);
- if (v != NULL) {
- st->print_cr(INTPTR_FORMAT " is at entry_point+%d in a vtable stub", p2i(addr), (int)(addr - v->entry_point()));
- v->print_on(st);
- st->cr();
- return;
- }
- }
- nmethod* nm = b->as_nmethod_or_null();
- if (nm != NULL) {
- ResourceMark rm;
- st->print(INTPTR_FORMAT " is at entry_point+%d in (nmethod*)" INTPTR_FORMAT,
- p2i(addr), (int)(addr - nm->entry_point()), p2i(nm));
- if (verbose) {
- st->print(" for ");
- nm->method()->print_value_on(st);
- }
- st->cr();
- nm->print_nmethod(verbose);
- return;
- }
- st->print_cr(INTPTR_FORMAT " is at code_begin+%d in ", p2i(addr), (int)(addr - b->code_begin()));
- b->print_on(st);
+ b->dump_for_addr(addr, st, verbose);
return;
}
+ // Check if addr points into Java heap.
if (Universe::heap()->is_in(addr)) {
- HeapWord* p = Universe::heap()->block_start(addr);
- bool print = false;
- // If we couldn't find it it just may mean that heap wasn't parsable
- // See if we were just given an oop directly
- if (p != NULL && Universe::heap()->block_is_obj(p)) {
- print = true;
- } else if (p == NULL && oopDesc::is_oop(oop(addr))) {
- p = (HeapWord*) addr;
- print = true;
- }
- if (print) {
- if (p == (HeapWord*) addr) {
- st->print_cr(INTPTR_FORMAT " is an oop", p2i(addr));
+ oop o = oopDesc::oop_or_null(addr);
+ if (o != NULL) {
+ if ((HeapWord*)o == (HeapWord*)addr) {
+ st->print(INTPTR_FORMAT " is an oop: ", p2i(addr));
} else {
- st->print_cr(INTPTR_FORMAT " is pointing into object: " INTPTR_FORMAT, p2i(addr), p2i(p));
+ st->print(INTPTR_FORMAT " is pointing into object: " , p2i(addr));
}
- oop(p)->print_on(st);
+ o->print_on(st);
return;
}
- } else {
- if (Universe::heap()->is_in_reserved(addr)) {
- st->print_cr(INTPTR_FORMAT " is an unallocated location "
- "in the heap", p2i(addr));
+ } else if (Universe::heap()->is_in_reserved(addr)) {
+ st->print_cr(INTPTR_FORMAT " is an unallocated location in the heap", p2i(addr));
+ return;
+ }
+
+ // Compressed oop needs to be decoded first.
+#ifdef _LP64
+ if (UseCompressedOops && ((uintptr_t)addr &~ (uintptr_t)max_juint) == 0) {
+ narrowOop narrow_oop = (narrowOop)(uintptr_t)addr;
+ oop o = oopDesc::decode_oop_raw(narrow_oop);
+
+ if (oopDesc::is_valid(o)) {
+ st->print(UINT32_FORMAT " is a compressed pointer to object: ", narrow_oop);
+ o->print_on(st);
return;
}
}
+#endif
bool accessible = is_readable_pointer(addr);
+ // Check if addr is a JNI handle.
if (align_down((intptr_t)addr, sizeof(intptr_t)) != 0 && accessible) {
if (JNIHandles::is_global_handle((jobject) addr)) {
st->print_cr(INTPTR_FORMAT " is a global jni handle", p2i(addr));
@@ -1131,6 +1089,7 @@
#endif
}
+ // Check if addr belongs to a Java thread.
for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thread = jtiwh.next(); ) {
// Check for privilege stack
if (thread->privileged_stack_top() != NULL &&
@@ -1159,9 +1118,12 @@
}
}
- // Check if in metaspace and print types that have vptrs (only method now)
+ // Check if in metaspace and print types that have vptrs
if (Metaspace::contains(addr)) {
- if (Method::has_method_vptr((const void*)addr)) {
+ if (Klass::is_valid((Klass*)addr)) {
+ st->print_cr(INTPTR_FORMAT " is a pointer to class: ", p2i(addr));
+ ((Klass*)addr)->print_on(st);
+ } else if (Method::is_valid_method((const Method*)addr)) {
((Method*)addr)->print_value_on(st);
st->cr();
} else {
@@ -1171,6 +1133,20 @@
return;
}
+ // Compressed klass needs to be decoded first.
+#ifdef _LP64
+ if (UseCompressedClassPointers && ((uintptr_t)addr &~ (uintptr_t)max_juint) == 0) {
+ narrowKlass narrow_klass = (narrowKlass)(uintptr_t)addr;
+ Klass* k = Klass::decode_klass_raw(narrow_klass);
+
+ if (Klass::is_valid(k)) {
+ st->print_cr(UINT32_FORMAT " is a compressed pointer to class: " INTPTR_FORMAT, narrow_klass, p2i((HeapWord*)k));
+ k->print_on(st);
+ return;
+ }
+ }
+#endif
+
// Try an OS specific find
if (os::find(addr, st)) {
return;