< prev index next >

src/hotspot/share/code/codeHeapState.cpp

Print this page
rev 51015 : 8207342: error occurred during error reporting (printing register info)
Summary: os::print_location misses a check if the pointer is readable.
Reviewed-by:


2089       }
2090       name_in_addr_range = false;
2091 
2092       size_t end_ix = (ix+granules_per_line <= alloc_granules) ? ix+granules_per_line : alloc_granules;
2093       ast->cr();
2094       ast->print_cr("--------------------------------------------------------------------");
2095       ast->print_cr("Address range [" INTPTR_FORMAT "," INTPTR_FORMAT "), " SIZE_FORMAT "k", p2i(low_bound+ix*granule_size), p2i(low_bound + end_ix*granule_size), (end_ix - ix)*granule_size/(size_t)K);
2096       ast->print_cr("--------------------------------------------------------------------");
2097       STRINGSTREAM_FLUSH_LOCKED("")
2098     }
2099     // Only check granule if it contains at least one blob.
2100     unsigned int nBlobs  = StatArray[ix].t1_count   + StatArray[ix].t2_count + StatArray[ix].tx_count +
2101                            StatArray[ix].stub_count + StatArray[ix].dead_count;
2102     if (nBlobs > 0 ) {
2103     for (unsigned int is = 0; is < granule_size; is+=(unsigned int)seg_size) {
2104       // heap->find_start() is safe. Only working with _segmap. Returns NULL or void*. Returned CodeBlob may be uninitialized.
2105       CodeBlob* this_blob = (CodeBlob *)(heap->find_start(low_bound+ix*granule_size+is));
2106       bool blob_initialized = (this_blob != NULL) && (this_blob->header_size() >= 0) && (this_blob->relocation_size() >= 0) &&
2107                               ((address)this_blob + this_blob->header_size() == (address)(this_blob->relocation_begin())) &&
2108                               ((address)this_blob + CodeBlob::align_code_offset(this_blob->header_size() + this_blob->relocation_size()) == (address)(this_blob->content_begin())) &&
2109                               is_readable_pointer((address)(this_blob->relocation_begin())) &&
2110                               is_readable_pointer(this_blob->content_begin());
2111       // blob could have been flushed, freed, and merged.
2112       // this_blob < last_blob is an indicator for that.
2113       if (blob_initialized && (this_blob > last_blob)) {
2114         last_blob          = this_blob;
2115 
2116         //---<  get type and name  >---
2117         blobType       cbType = noType;
2118         if (segment_granules) {
2119           cbType = (blobType)StatArray[ix].type;
2120         } else {
2121           cbType = get_cbType(this_blob);
2122         }
2123         // this_blob->name() could return NULL if no name was given to CTOR. Inlined, maybe invisible on stack
2124         const char* blob_name = this_blob->name();
2125         if ((blob_name == NULL) || !is_readable_pointer(blob_name)) {
2126           blob_name = "<unavailable>";
2127         }
2128 
2129         //---<  print table header for new print range  >---
2130         if (!name_in_addr_range) {
2131           name_in_addr_range = true;
2132           ast->fill_to(51);
2133           ast->print("%9s", "compiler");
2134           ast->fill_to(61);
2135           ast->print_cr("%6s", "method");
2136           ast->print_cr("%18s %13s %17s %9s  %5s %18s  %s", "Addr(module)      ", "offset", "size", " type lvl", " temp", "blobType          ", "Name");
2137           STRINGSTREAM_FLUSH_LOCKED("")
2138         }
2139 
2140         //---<  print line prefix (address and offset from CodeHeap start)  >---
2141         ast->print(INTPTR_FORMAT, p2i(this_blob));
2142         ast->fill_to(19);
2143         ast->print("(+" PTR32_FORMAT ")", (unsigned int)((char*)this_blob-low_bound));
2144         ast->fill_to(33);
2145 
2146         // this_blob->as_nmethod_or_null() is safe. Inlined, maybe invisible on stack.
2147         nmethod*    nm     = this_blob->as_nmethod_or_null();
2148         Method*     method = (nm == NULL) ? NULL : nm->method();  // may be uninitialized, i.e. != NULL, but invalid
2149         if ((nm != NULL) && (method != NULL) && (cbType != nMethod_dead) &&
2150             is_readable_pointer(method) && is_readable_pointer(method->constants())) {
2151           ResourceMark rm;
2152           //---<  collect all data to locals as quickly as possible  >---
2153           unsigned int total_size = nm->total_size();
2154           int          hotness    = nm->hotness_counter();
2155           bool         get_name   = (cbType == nMethod_inuse) || (cbType == nMethod_notused);
2156           //---<  nMethod size in hex  >---
2157           ast->print(PTR32_FORMAT, total_size);
2158           ast->print("(" SIZE_FORMAT_W(4) "K)", total_size/K);
2159           //---<  compiler information  >---
2160           ast->fill_to(51);
2161           ast->print("%5s %3d", compTypeName[StatArray[ix].compiler], StatArray[ix].level);
2162           //---<  method temperature  >---
2163           ast->fill_to(62);
2164           ast->print("%5d", hotness);
2165           //---<  name and signature  >---
2166           ast->fill_to(62+6);
2167           ast->print("%s", blobTypeName[cbType]);
2168           ast->fill_to(82+6);
2169           if (cbType == nMethod_dead) {
2170             ast->print("%14s", " zombie method");


2329   assert(out != ast, "must not use the same stream!");
2330   if (ix % gpl == 0) {
2331     if (ix > 0) {
2332       ast->print("|");
2333     }
2334     ast->cr();
2335 
2336     { // can't use STRINGSTREAM_FLUSH_LOCKED("") here.
2337       ttyLocker ttyl;
2338       out->print("%s", ast->as_string());
2339       ast->reset();
2340     }
2341 
2342     ast->print(INTPTR_FORMAT, p2i(low_bound + ix*granule_size));
2343     ast->fill_to(19);
2344     ast->print("(+" PTR32_FORMAT "): |", (unsigned int)(ix*granule_size));
2345   }
2346 }
2347 
2348 CodeHeapState::blobType CodeHeapState::get_cbType(CodeBlob* cb) {
2349   if ((cb != NULL) && is_readable_pointer(cb)) {
2350     if (cb->is_runtime_stub())                return runtimeStub;
2351     if (cb->is_deoptimization_stub())         return deoptimizationStub;
2352     if (cb->is_uncommon_trap_stub())          return uncommonTrapStub;
2353     if (cb->is_exception_stub())              return exceptionStub;
2354     if (cb->is_safepoint_stub())              return safepointStub;
2355     if (cb->is_adapter_blob())                return adapterBlob;
2356     if (cb->is_method_handles_adapter_blob()) return mh_adapterBlob;
2357     if (cb->is_buffer_blob())                 return bufferBlob;
2358 
2359     nmethod*  nm = cb->as_nmethod_or_null();
2360     if (nm != NULL) { // no is_readable check required, nm = (nmethod*)cb.
2361       if (nm->is_zombie())        return nMethod_dead;
2362       if (nm->is_unloaded())      return nMethod_unloaded;
2363       if (nm->is_alive() && !(nm->is_not_entrant()))   return nMethod_notused;
2364       if (nm->is_alive())         return nMethod_alive;
2365       if (nm->is_in_use())        return nMethod_inuse;
2366       return nMethod_dead;
2367     }
2368   }
2369   return noType;
2370 }
2371 
2372 // Check if pointer can be read from (4-byte read access).
2373 // Helps to prove validity of a not-NULL pointer.
2374 // Returns true in very early stages of VM life when stub is not yet generated.
2375 #define SAFEFETCH_DEFAULT true
2376 bool CodeHeapState::is_readable_pointer(const void* p) {
2377   if (!CanUseSafeFetch32()) {
2378     return SAFEFETCH_DEFAULT;
2379   }
2380   int* const aligned = (int*) align_down((intptr_t)p, 4);
2381   int cafebabe = 0xcafebabe;  // tester value 1
2382   int deadbeef = 0xdeadbeef;  // tester value 2
2383   return (SafeFetch32(aligned, cafebabe) != cafebabe) || (SafeFetch32(aligned, deadbeef) != deadbeef);
2384 }


2089       }
2090       name_in_addr_range = false;
2091 
2092       size_t end_ix = (ix+granules_per_line <= alloc_granules) ? ix+granules_per_line : alloc_granules;
2093       ast->cr();
2094       ast->print_cr("--------------------------------------------------------------------");
2095       ast->print_cr("Address range [" INTPTR_FORMAT "," INTPTR_FORMAT "), " SIZE_FORMAT "k", p2i(low_bound+ix*granule_size), p2i(low_bound + end_ix*granule_size), (end_ix - ix)*granule_size/(size_t)K);
2096       ast->print_cr("--------------------------------------------------------------------");
2097       STRINGSTREAM_FLUSH_LOCKED("")
2098     }
2099     // Only check granule if it contains at least one blob.
2100     unsigned int nBlobs  = StatArray[ix].t1_count   + StatArray[ix].t2_count + StatArray[ix].tx_count +
2101                            StatArray[ix].stub_count + StatArray[ix].dead_count;
2102     if (nBlobs > 0 ) {
2103     for (unsigned int is = 0; is < granule_size; is+=(unsigned int)seg_size) {
2104       // heap->find_start() is safe. Only working with _segmap. Returns NULL or void*. Returned CodeBlob may be uninitialized.
2105       CodeBlob* this_blob = (CodeBlob *)(heap->find_start(low_bound+ix*granule_size+is));
2106       bool blob_initialized = (this_blob != NULL) && (this_blob->header_size() >= 0) && (this_blob->relocation_size() >= 0) &&
2107                               ((address)this_blob + this_blob->header_size() == (address)(this_blob->relocation_begin())) &&
2108                               ((address)this_blob + CodeBlob::align_code_offset(this_blob->header_size() + this_blob->relocation_size()) == (address)(this_blob->content_begin())) &&
2109                               os::is_readable_pointer((address)(this_blob->relocation_begin())) &&
2110                               os::is_readable_pointer(this_blob->content_begin());
2111       // blob could have been flushed, freed, and merged.
2112       // this_blob < last_blob is an indicator for that.
2113       if (blob_initialized && (this_blob > last_blob)) {
2114         last_blob          = this_blob;
2115 
2116         //---<  get type and name  >---
2117         blobType       cbType = noType;
2118         if (segment_granules) {
2119           cbType = (blobType)StatArray[ix].type;
2120         } else {
2121           cbType = get_cbType(this_blob);
2122         }
2123         // this_blob->name() could return NULL if no name was given to CTOR. Inlined, maybe invisible on stack
2124         const char* blob_name = this_blob->name();
2125         if ((blob_name == NULL) || !os::is_readable_pointer(blob_name)) {
2126           blob_name = "<unavailable>";
2127         }
2128 
2129         //---<  print table header for new print range  >---
2130         if (!name_in_addr_range) {
2131           name_in_addr_range = true;
2132           ast->fill_to(51);
2133           ast->print("%9s", "compiler");
2134           ast->fill_to(61);
2135           ast->print_cr("%6s", "method");
2136           ast->print_cr("%18s %13s %17s %9s  %5s %18s  %s", "Addr(module)      ", "offset", "size", " type lvl", " temp", "blobType          ", "Name");
2137           STRINGSTREAM_FLUSH_LOCKED("")
2138         }
2139 
2140         //---<  print line prefix (address and offset from CodeHeap start)  >---
2141         ast->print(INTPTR_FORMAT, p2i(this_blob));
2142         ast->fill_to(19);
2143         ast->print("(+" PTR32_FORMAT ")", (unsigned int)((char*)this_blob-low_bound));
2144         ast->fill_to(33);
2145 
2146         // this_blob->as_nmethod_or_null() is safe. Inlined, maybe invisible on stack.
2147         nmethod*    nm     = this_blob->as_nmethod_or_null();
2148         Method*     method = (nm == NULL) ? NULL : nm->method();  // may be uninitialized, i.e. != NULL, but invalid
2149         if ((nm != NULL) && (method != NULL) && (cbType != nMethod_dead) &&
2150             os::is_readable_pointer(method) && os::is_readable_pointer(method->constants())) {
2151           ResourceMark rm;
2152           //---<  collect all data to locals as quickly as possible  >---
2153           unsigned int total_size = nm->total_size();
2154           int          hotness    = nm->hotness_counter();
2155           bool         get_name   = (cbType == nMethod_inuse) || (cbType == nMethod_notused);
2156           //---<  nMethod size in hex  >---
2157           ast->print(PTR32_FORMAT, total_size);
2158           ast->print("(" SIZE_FORMAT_W(4) "K)", total_size/K);
2159           //---<  compiler information  >---
2160           ast->fill_to(51);
2161           ast->print("%5s %3d", compTypeName[StatArray[ix].compiler], StatArray[ix].level);
2162           //---<  method temperature  >---
2163           ast->fill_to(62);
2164           ast->print("%5d", hotness);
2165           //---<  name and signature  >---
2166           ast->fill_to(62+6);
2167           ast->print("%s", blobTypeName[cbType]);
2168           ast->fill_to(82+6);
2169           if (cbType == nMethod_dead) {
2170             ast->print("%14s", " zombie method");


2329   assert(out != ast, "must not use the same stream!");
2330   if (ix % gpl == 0) {
2331     if (ix > 0) {
2332       ast->print("|");
2333     }
2334     ast->cr();
2335 
2336     { // can't use STRINGSTREAM_FLUSH_LOCKED("") here.
2337       ttyLocker ttyl;
2338       out->print("%s", ast->as_string());
2339       ast->reset();
2340     }
2341 
2342     ast->print(INTPTR_FORMAT, p2i(low_bound + ix*granule_size));
2343     ast->fill_to(19);
2344     ast->print("(+" PTR32_FORMAT "): |", (unsigned int)(ix*granule_size));
2345   }
2346 }
2347 
2348 CodeHeapState::blobType CodeHeapState::get_cbType(CodeBlob* cb) {
2349   if ((cb != NULL) && os::is_readable_pointer(cb)) {
2350     if (cb->is_runtime_stub())                return runtimeStub;
2351     if (cb->is_deoptimization_stub())         return deoptimizationStub;
2352     if (cb->is_uncommon_trap_stub())          return uncommonTrapStub;
2353     if (cb->is_exception_stub())              return exceptionStub;
2354     if (cb->is_safepoint_stub())              return safepointStub;
2355     if (cb->is_adapter_blob())                return adapterBlob;
2356     if (cb->is_method_handles_adapter_blob()) return mh_adapterBlob;
2357     if (cb->is_buffer_blob())                 return bufferBlob;
2358 
2359     nmethod*  nm = cb->as_nmethod_or_null();
2360     if (nm != NULL) { // no is_readable check required, nm = (nmethod*)cb.
2361       if (nm->is_zombie())        return nMethod_dead;
2362       if (nm->is_unloaded())      return nMethod_unloaded;
2363       if (nm->is_alive() && !(nm->is_not_entrant()))   return nMethod_notused;
2364       if (nm->is_alive())         return nMethod_alive;
2365       if (nm->is_in_use())        return nMethod_inuse;
2366       return nMethod_dead;
2367     }
2368   }
2369   return noType;














2370 }
< prev index next >