< prev index next >
src/hotspot/share/code/codeHeapState.cpp
Print this page
@@ -2068,10 +2068,22 @@
}
}
}
+bool blob_access_is_safe(CodeBlob* this_blob, CodeBlob* prev_blob) {
+ return (this_blob != NULL) && // a blob must have been found, obviously
+ ((this_blob == prev_blob) || (prev_blob == NULL)) && // when re-checking, the same blob must have been found
+ (this_blob->header_size() >= 0) &&
+ (this_blob->relocation_size() >= 0) &&
+ ((address)this_blob + this_blob->header_size() == (address)(this_blob->relocation_begin())) &&
+ ((address)this_blob + CodeBlob::align_code_offset(this_blob->header_size() + this_blob->relocation_size()) == (address)(this_blob->content_begin())) &&
+ os::is_readable_pointer((address)(this_blob->relocation_begin())) &&
+ os::is_readable_pointer(this_blob->content_begin());
+}
+
+
void CodeHeapState::print_names(outputStream* out, CodeHeap* heap) {
if (!initialization_complete) {
return;
}
@@ -2119,20 +2131,18 @@
// Only check granule if it contains at least one blob.
unsigned int nBlobs = StatArray[ix].t1_count + StatArray[ix].t2_count + StatArray[ix].tx_count +
StatArray[ix].stub_count + StatArray[ix].dead_count;
if (nBlobs > 0 ) {
for (unsigned int is = 0; is < granule_size; is+=(unsigned int)seg_size) {
- // heap->find_start() is safe. Only working with _segmap. Returns NULL or void*. Returned CodeBlob may be uninitialized.
- CodeBlob* this_blob = (CodeBlob *)(heap->find_start(low_bound+ix*granule_size+is));
- bool blob_initialized = (this_blob != NULL) && (this_blob->header_size() >= 0) && (this_blob->relocation_size() >= 0) &&
- ((address)this_blob + this_blob->header_size() == (address)(this_blob->relocation_begin())) &&
- ((address)this_blob + CodeBlob::align_code_offset(this_blob->header_size() + this_blob->relocation_size()) == (address)(this_blob->content_begin())) &&
- os::is_readable_pointer((address)(this_blob->relocation_begin())) &&
- os::is_readable_pointer(this_blob->content_begin());
+ // heap->find_start() is safe. Only working with _segmap.
+ // Returns NULL or void*. Returned CodeBlob may be uninitialized.
+ char * this_seg = low_bound + ix*granule_size + is;
+ CodeBlob* this_blob = (CodeBlob*)(heap->find_start(this_seg));
+ bool blob_is_safe = blob_access_is_safe(this_blob, NULL);
// blob could have been flushed, freed, and merged.
// this_blob < last_blob is an indicator for that.
- if (blob_initialized && (this_blob > last_blob)) {
+ if (blob_is_safe && (this_blob > last_blob)) {
last_blob = this_blob;
//---< get type and name >---
blobType cbType = noType;
if (segment_granules) {
@@ -2161,12 +2171,24 @@
ast->print(INTPTR_FORMAT, p2i(this_blob));
ast->fill_to(19);
ast->print("(+" PTR32_FORMAT ")", (unsigned int)((char*)this_blob-low_bound));
ast->fill_to(33);
- // this_blob->as_nmethod_or_null() is safe. Inlined, maybe invisible on stack.
- nmethod* nm = this_blob->as_nmethod_or_null();
+ // Re-check blob consistency. It might have been destroyed.
+ this_blob = (CodeBlob*)(heap->find_start(this_seg));
+ blob_is_safe = blob_access_is_safe(this_blob, last_blob);
+ nmethod* nm = NULL;
+ if (blob_is_safe) {
+ // this_blob->as_nmethod_or_null() is not safe.
+ // On MacOS, the virtual call is_nmethod() may lose it's vtable entry.
+ nm = this_blob->as_nmethod_or_null();
+ }
+ // Debugging. Remove before push!
+ else {
+ ast->print(" blob unsafe");
+ }
+
if (CompiledMethod::nmethod_access_is_safe(nm)) {
Method* method = nm->method();
ResourceMark rm;
//---< collect all data to locals as quickly as possible >---
unsigned int total_size = nm->total_size();
@@ -2199,18 +2221,21 @@
ast->print("%s", methNameS);
ast->print("%s", methSigS);
} else {
ast->print("%s", blob_name);
}
- } else {
+ } else if (blob_is_safe) {
ast->fill_to(62+6);
ast->print("%s", blobTypeName[cbType]);
ast->fill_to(82+6);
ast->print("%s", blob_name);
+ } else {
+ ast->fill_to(62+6);
+ ast->print("<stale blob>");
}
STRINGSTREAM_FLUSH_LOCKED("\n")
- } else if (!blob_initialized && (this_blob != last_blob) && (this_blob != NULL)) {
+ } else if (!blob_is_safe && (this_blob != last_blob) && (this_blob != NULL)) {
last_blob = this_blob;
STRINGSTREAM_FLUSH_LOCKED("\n")
}
}
} // nBlobs > 0
< prev index next >