< 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 >