< prev index next >

src/hotspot/share/code/codeHeapState.cpp

Print this page

        

*** 611,630 **** blobType cbType = noType; //---< some sanity checks >--- // Do not assert here, just check, print error message and return. // This is a diagnostic function. It is not supposed to tear down the VM. ! if ((char*)h < low_bound ) { insane = true; ast->print_cr("Sanity check: HeapBlock @%p below low bound (%p)", (char*)h, low_bound); } ! if (ix_end >= granules ) { insane = true; ast->print_cr("Sanity check: end index (%d) out of bounds (" SIZE_FORMAT ")", ix_end, granules); } if (size != heap->capacity()) { insane = true; ast->print_cr("Sanity check: code heap capacity has changed (" SIZE_FORMAT "K to " SIZE_FORMAT "K)", size/(size_t)K, heap->capacity()/(size_t)K); } ! if (ix_beg > ix_end ) { insane = true; ast->print_cr("Sanity check: end index (%d) lower than begin index (%d)", ix_end, ix_beg); } if (insane) { STRINGSTREAM_FLUSH("") continue; --- 611,636 ---- blobType cbType = noType; //---< some sanity checks >--- // Do not assert here, just check, print error message and return. // This is a diagnostic function. It is not supposed to tear down the VM. ! if ((char*)h < low_bound) { insane = true; ast->print_cr("Sanity check: HeapBlock @%p below low bound (%p)", (char*)h, low_bound); } ! if ((char*)h > (low_bound + res_size)) { ! insane = true; ast->print_cr("Sanity check: HeapBlock @%p outside reserved range (%p)", (char*)h, low_bound + res_size); ! } ! if ((char*)h > (low_bound + size)) { ! insane = true; ast->print_cr("Sanity check: HeapBlock @%p outside used range (%p)", (char*)h, low_bound + size); ! } ! if (ix_end >= granules) { insane = true; ast->print_cr("Sanity check: end index (%d) out of bounds (" SIZE_FORMAT ")", ix_end, granules); } if (size != heap->capacity()) { insane = true; ast->print_cr("Sanity check: code heap capacity has changed (" SIZE_FORMAT "K to " SIZE_FORMAT "K)", size/(size_t)K, heap->capacity()/(size_t)K); } ! if (ix_beg > ix_end) { insane = true; ast->print_cr("Sanity check: end index (%d) lower than begin index (%d)", ix_end, ix_beg); } if (insane) { STRINGSTREAM_FLUSH("") continue;
*** 986,995 **** --- 992,1006 ---- ast->print_cr(" not entrant = " SIZE_FORMAT_W(8) "k, nBlocks_notentr = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", notentrSpace/(size_t)K, nBlocks_notentr, (100.0*notentrSpace)/size, (100.0*notentrSpace)/res_size); ast->print_cr(" unloadedSpace = " SIZE_FORMAT_W(8) "k, nBlocks_unloaded = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", unloadedSpace/(size_t)K, nBlocks_unloaded, (100.0*unloadedSpace)/size, (100.0*unloadedSpace)/res_size); ast->print_cr(" deadSpace = " SIZE_FORMAT_W(8) "k, nBlocks_dead = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", deadSpace/(size_t)K, nBlocks_dead, (100.0*deadSpace)/size, (100.0*deadSpace)/res_size); ast->print_cr(" stubSpace = " SIZE_FORMAT_W(8) "k, nBlocks_stub = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", stubSpace/(size_t)K, nBlocks_stub, (100.0*stubSpace)/size, (100.0*stubSpace)/res_size); ast->print_cr("ZombieBlocks = %8d. These are HeapBlocks which could not be identified as CodeBlobs.", nBlocks_zomb); + ast->cr(); + ast->print_cr("Segment start = " INTPTR_FORMAT ", used space = " SIZE_FORMAT_W(8)"k", p2i(low_bound), size/K); + ast->print_cr("Segment end (used) = " INTPTR_FORMAT ", remaining space = " SIZE_FORMAT_W(8)"k", p2i(low_bound) + size, (res_size - size)/K); + ast->print_cr("Segment end (reserved) = " INTPTR_FORMAT ", reserved space = " SIZE_FORMAT_W(8)"k", p2i(low_bound) + res_size, res_size/K); + ast->cr(); ast->print_cr("latest allocated compilation id = %d", latest_compilation_id); ast->print_cr("highest observed compilation id = %d", highest_compilation_id); ast->print_cr("Building TopSizeList iterations = %ld", total_iterations); ast->cr();
*** 1216,1233 **** const char* blob_name = "unnamed blob"; if (this_blob != NULL) { blob_name = this_blob->name(); nm = this_blob->as_nmethod_or_null(); //---< blob address >--- ! ast->print("%p", this_blob); ast->fill_to(19); //---< blob offset from CodeHeap begin >--- ast->print("(+" PTR32_FORMAT ")", (unsigned int)((char*)this_blob-low_bound)); ast->fill_to(33); } else { //---< block address >--- ! ast->print("%p", TopSizeArray[i].start); ast->fill_to(19); //---< block offset from CodeHeap begin >--- ast->print("(+" PTR32_FORMAT ")", (unsigned int)((char*)TopSizeArray[i].start-low_bound)); ast->fill_to(33); } --- 1227,1244 ---- const char* blob_name = "unnamed blob"; if (this_blob != NULL) { blob_name = this_blob->name(); nm = this_blob->as_nmethod_or_null(); //---< blob address >--- ! ast->print(INTPTR_FORMAT, p2i(this_blob)); ast->fill_to(19); //---< blob offset from CodeHeap begin >--- ast->print("(+" PTR32_FORMAT ")", (unsigned int)((char*)this_blob-low_bound)); ast->fill_to(33); } else { //---< block address >--- ! ast->print(INTPTR_FORMAT, p2i(TopSizeArray[i].start)); ast->fill_to(19); //---< block offset from CodeHeap begin >--- ast->print("(+" PTR32_FORMAT ")", (unsigned int)((char*)TopSizeArray[i].start-low_bound)); ast->fill_to(33); }
*** 1402,1422 **** printBox(ast, '-', "List of all Free Blocks in ", heapName); STRINGSTREAM_FLUSH_LOCKED("") unsigned int ix = 0; for (ix = 0; ix < alloc_freeBlocks-1; ix++) { ! ast->print("%p: Len[%4d] = " HEX32_FORMAT ",", FreeArray[ix].start, ix, FreeArray[ix].len); ast->fill_to(38); ast->print("Gap[%4d..%4d]: " HEX32_FORMAT " bytes,", ix, ix+1, FreeArray[ix].gap); ast->fill_to(71); ast->print("block count: %6d", FreeArray[ix].n_gapBlocks); if (FreeArray[ix].stubs_in_gap) { ast->print(" !! permanent gap, contains stubs and/or blobs !!"); } STRINGSTREAM_FLUSH_LOCKED("\n") } ! ast->print_cr("%p: Len[%4d] = " HEX32_FORMAT, FreeArray[ix].start, ix, FreeArray[ix].len); STRINGSTREAM_FLUSH_LOCKED("\n\n") } //----------------------------------------- --- 1413,1433 ---- printBox(ast, '-', "List of all Free Blocks in ", heapName); STRINGSTREAM_FLUSH_LOCKED("") unsigned int ix = 0; for (ix = 0; ix < alloc_freeBlocks-1; ix++) { ! ast->print(INTPTR_FORMAT ": Len[%4d] = " HEX32_FORMAT ",", p2i(FreeArray[ix].start), ix, FreeArray[ix].len); ast->fill_to(38); ast->print("Gap[%4d..%4d]: " HEX32_FORMAT " bytes,", ix, ix+1, FreeArray[ix].gap); ast->fill_to(71); ast->print("block count: %6d", FreeArray[ix].n_gapBlocks); if (FreeArray[ix].stubs_in_gap) { ast->print(" !! permanent gap, contains stubs and/or blobs !!"); } STRINGSTREAM_FLUSH_LOCKED("\n") } ! ast->print_cr(INTPTR_FORMAT ": Len[%4d] = " HEX32_FORMAT, p2i(FreeArray[ix].start), ix, FreeArray[ix].len); STRINGSTREAM_FLUSH_LOCKED("\n\n") } //-----------------------------------------
*** 2037,2050 **** --- 2048,2067 ---- } } } + #define JDK8200450_REMEDY + #define JDK8200450_TRACE void CodeHeapState::print_names(outputStream* out, CodeHeap* heap) { if (!initialization_complete) { return; } + #ifdef JDK8200450_TRACE + out->print_cr("print_names() entered for heap @ " INTPTR_FORMAT, p2i(heap)); + out->flush(); + #endif const char* heapName = get_heapName(heap); get_HeapStatGlobals(out, heapName); if ((StatArray == NULL) || (alloc_granules == 0)) {
*** 2055,2171 **** unsigned int granules_per_line = 128; char* low_bound = heap->low_boundary(); CodeBlob* last_blob = NULL; bool name_in_addr_range = true; ! //---< print at least 128K per block >--- if (granules_per_line*granule_size < 128*K) { granules_per_line = (unsigned int)((128*K)/granule_size); } printBox(ast, '=', "M E T H O D N A M E S for ", heapName); ast->print_cr(" Method names are dynamically retrieved from the code cache at print time.\n" " Due to the living nature of the code heap and because the CodeCache_lock\n" " is not continuously held, the displayed name might be wrong or no name\n" " might be found at all. The likelihood for that to happen increases\n" ! " over time passed between analysis and print step.\n"); STRINGSTREAM_FLUSH_LOCKED("") for (unsigned int ix = 0; ix < alloc_granules; ix++) { //---< print a new blob on a new line >--- if (ix%granules_per_line == 0) { if (!name_in_addr_range) { ast->print_cr("No methods, blobs, or stubs found in this address range"); } name_in_addr_range = false; ast->cr(); ast->print_cr("--------------------------------------------------------------------"); ! ast->print_cr("Address range [%p,%p), " SIZE_FORMAT "k", low_bound+ix*granule_size, low_bound+(ix+granules_per_line)*granule_size, granules_per_line*granule_size/(size_t)K); ast->print_cr("--------------------------------------------------------------------"); STRINGSTREAM_FLUSH_LOCKED("") } // 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) && ! ((char*)this_blob + this_blob->header_size() == (char*)(this_blob->relocation_begin())) && ! ((char*)this_blob + CodeBlob::align_code_offset(this_blob->header_size() + this_blob->relocation_size()) == (char*)(this_blob->content_begin())); if (blob_initialized && (this_blob != last_blob)) { if (!name_in_addr_range) { name_in_addr_range = true; ast->fill_to(51); ast->print("%9s", "compiler"); ast->fill_to(61); ast->print_cr("%6s", "method"); ast->print_cr("%18s %13s %17s %9s %5s %18s %s", "Addr(module) ", "offset", "size", " type lvl", " temp", "blobType ", "Name"); } ! //---< Print blobTypeName as recorded during analysis >--- ! ast->print("%p", this_blob); ast->fill_to(19); ast->print("(+" PTR32_FORMAT ")", (unsigned int)((char*)this_blob-low_bound)); ast->fill_to(33); ! //---< print size, name, and signature (for nMethods) >--- ! // this_blob->name() could return NULL if no name is given to CTOR. Inlined, maybe not visible on stack ! const char* blob_name = this_blob->name(); ! if (blob_name == 0) { ! blob_name = "<unavailable>"; ! } ! // this_blob->as_nmethod_or_null() is safe. Inlined, maybe not visible on stack. nmethod* nm = this_blob->as_nmethod_or_null(); ! blobType cbType = noType; ! if (segment_granules) { ! cbType = (blobType)StatArray[ix].type; ! } else { ! cbType = get_cbType(this_blob); ! } ! if ((nm != NULL) && (nm->method() != NULL)) { ResourceMark rm; ! //---< nMethod size in hex >--- unsigned int total_size = nm->total_size(); ast->print(PTR32_FORMAT, total_size); ast->print("(" SIZE_FORMAT_W(4) "K)", total_size/K); //---< compiler information >--- ast->fill_to(51); ast->print("%5s %3d", compTypeName[StatArray[ix].compiler], StatArray[ix].level); //---< method temperature >--- ast->fill_to(62); ! ast->print("%5d", nm->hotness_counter()); //---< name and signature >--- ast->fill_to(62+6); ast->print("%s", blobTypeName[cbType]); ast->fill_to(82+6); ! if (nm->is_in_use()) { ! blob_name = nm->method()->name_and_sig_as_C_string(); ! } ! if (nm->is_not_entrant()) { ! blob_name = nm->method()->name_and_sig_as_C_string(); ! } ! if (nm->is_zombie()) { ast->print("%14s", " zombie method"); } ast->print("%s", blob_name); } else { ast->fill_to(62+6); ast->print("%s", blobTypeName[cbType]); ast->fill_to(82+6); ast->print("%s", blob_name); } STRINGSTREAM_FLUSH_LOCKED("\n") last_blob = this_blob; ! } else if (!blob_initialized && (this_blob != NULL)) { ! last_blob = this_blob; } } } } STRINGSTREAM_FLUSH_LOCKED("\n\n") } void CodeHeapState::printBox(outputStream* ast, const char border, const char* text1, const char* text2) { --- 2072,2287 ---- unsigned int granules_per_line = 128; char* low_bound = heap->low_boundary(); CodeBlob* last_blob = NULL; bool name_in_addr_range = true; ! //---< print at least 128K per block (i.e. between headers) >--- if (granules_per_line*granule_size < 128*K) { granules_per_line = (unsigned int)((128*K)/granule_size); } printBox(ast, '=', "M E T H O D N A M E S for ", heapName); ast->print_cr(" Method names are dynamically retrieved from the code cache at print time.\n" " Due to the living nature of the code heap and because the CodeCache_lock\n" " is not continuously held, the displayed name might be wrong or no name\n" " might be found at all. The likelihood for that to happen increases\n" ! " over time passed between aggregtion and print steps.\n"); STRINGSTREAM_FLUSH_LOCKED("") for (unsigned int ix = 0; ix < alloc_granules; ix++) { //---< print a new blob on a new line >--- if (ix%granules_per_line == 0) { if (!name_in_addr_range) { ast->print_cr("No methods, blobs, or stubs found in this address range"); } name_in_addr_range = false; + size_t end_ix = (ix+granules_per_line <= alloc_granules) ? ix+granules_per_line : alloc_granules; ast->cr(); ast->print_cr("--------------------------------------------------------------------"); ! 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); ast->print_cr("--------------------------------------------------------------------"); STRINGSTREAM_FLUSH_LOCKED("") } // 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; ! #ifdef JDK8200450_REMEDY ! if (nBlobs > 0 ) ! #endif ! { 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)); ! #ifndef JDK8200450_REMEDY ! bool blob_initialized = (this_blob != NULL) ! #else ! #ifndef JDK8200450_TRACE ! 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()) && ! is_readable_pointer((address)(this_blob->relocation_begin()) && ! is_readable_pointer(this_blob->content_begin()); ! #else ! int hdr_size = 0; ! int reloc_size = 0; ! address reloc_begin = NULL; ! address cntnt_begin = NULL; ! if (this_blob != NULL) { ! hdr_size = this_blob->header_size(); ! reloc_size = this_blob->relocation_size(); ! reloc_begin = (address)(this_blob->relocation_begin()); ! cntnt_begin = this_blob->content_begin(); ! } ! bool blob_initialized = (this_blob != NULL) && (hdr_size >= 0) && (reloc_size >= 0) && ! ((address)this_blob + hdr_size == reloc_begin) && ! ((address)this_blob + CodeBlob::align_code_offset(hdr_size + reloc_size) == cntnt_begin) && ! is_readable_pointer(reloc_begin) && ! is_readable_pointer(cntnt_begin); ! #endif ! #endif if (blob_initialized && (this_blob != last_blob)) { + last_blob = this_blob; + + //---< get type and name >--- + blobType cbType = noType; + if (segment_granules) { + cbType = (blobType)StatArray[ix].type; + } else { + cbType = get_cbType(this_blob); // Is this here safe? + } + // this_blob->name() could return NULL if no name is given to CTOR. Inlined, maybe invisible on stack + const char* blob_name = this_blob->name(); + #ifdef JDK8200450_REMEDY + if (blob_name == NULL) { + blob_name = "<unavailable>"; + } + #endif + + //---< print table header for new print range >--- if (!name_in_addr_range) { name_in_addr_range = true; ast->fill_to(51); ast->print("%9s", "compiler"); ast->fill_to(61); ast->print_cr("%6s", "method"); ast->print_cr("%18s %13s %17s %9s %5s %18s %s", "Addr(module) ", "offset", "size", " type lvl", " temp", "blobType ", "Name"); + STRINGSTREAM_FLUSH_LOCKED("") } ! //---< print line prefix (address and offset from CodeHeap start) >--- ! 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); ! #ifdef JDK8200450_TRACE ! STRINGSTREAM_FLUSH_LOCKED("") // Remove before push!!! ! #endif ! ! // this_blob->as_nmethod_or_null() is safe. Inlined, maybe invisible on stack. nmethod* nm = this_blob->as_nmethod_or_null(); ! Method* method = (nm == NULL) ? NULL : nm->method(); // may be uninitialized, i.e. != NULL, but invalid ! #ifdef JDK8200450_REMEDY ! if ((nm != NULL) && (method != NULL) && is_readable_pointer(method) && is_readable_pointer(method->constants())) { ! #else ! if ((nm != NULL) && (method != NULL)) { ! #endif ResourceMark rm; ! //---< collect all data to locals as quickly as possible >--- unsigned int total_size = nm->total_size(); + int hotness = nm->hotness_counter(); + bool nm_zombie = nm->is_zombie(); + bool get_name = nm->is_in_use() || nm->is_not_entrant(); + //---< nMethod size in hex >--- ast->print(PTR32_FORMAT, total_size); ast->print("(" SIZE_FORMAT_W(4) "K)", total_size/K); //---< compiler information >--- ast->fill_to(51); ast->print("%5s %3d", compTypeName[StatArray[ix].compiler], StatArray[ix].level); //---< method temperature >--- ast->fill_to(62); ! ast->print("%5d", hotness); //---< name and signature >--- ast->fill_to(62+6); ast->print("%s", blobTypeName[cbType]); ast->fill_to(82+6); ! if (nm_zombie) { ast->print("%14s", " zombie method"); } + + #ifdef JDK8200450_TRACE + STRINGSTREAM_FLUSH_LOCKED("") // Remove before push!!! + #endif + + if (get_name) { + #ifdef JDK8200450_REMEDY + Symbol* methName = method->name(); + const char* methNameS = (methName == NULL) ? NULL : methName->as_C_string(); + methNameS = (methNameS == NULL) ? "<method name unavailable>" : methNameS; + Symbol* methSig = method->signature(); + const char* methSigS = (methSig == NULL) ? NULL : methSig->as_C_string(); + methSigS = (methSigS == NULL) ? "<method signature unavailable>" : methSigS; + ast->print("%s", methNameS); + ast->print("%s", methSigS); + #else + blob_name = method->name_and_sig_as_C_string(); + ast->print("%s", blob_name); + #endif + } else { ast->print("%s", blob_name); + } } else { ast->fill_to(62+6); ast->print("%s", blobTypeName[cbType]); ast->fill_to(82+6); ast->print("%s", blob_name); } STRINGSTREAM_FLUSH_LOCKED("\n") + #ifdef JDK8200450_TRACE + if ((nm != NULL) && (method != NULL) && !(is_readable_pointer(method) && is_readable_pointer(method->constants()))) { + ast->print("Potential CodeHeap State Analytics issue found.\n"); + if (is_readable_pointer(method)) { + ast->print(" Issue would have been detected by is_readable_pointer(" INTPTR_FORMAT "(method->constants())) check.\n", p2i(method->constants())); + } else { + ast->print(" Issue would have been detected by is_readable_pointer(" INTPTR_FORMAT "(method)) check.\n", p2i(method)); + } + STRINGSTREAM_FLUSH_LOCKED("\n") + } + #endif + } else if (!blob_initialized && (this_blob != last_blob) && (this_blob != NULL)) { last_blob = this_blob; ! #ifdef JDK8200450_TRACE ! ast->print("Potential CodeHeap State Analytics issue found.\n"); ! if (nBlobs == 0) { ! ast->print(" Issue would have been detected by (nBlobs > 0) check.\n"); ! } else { ! if (!((address)this_blob + hdr_size == reloc_begin)) { ! ast->print(" Issue would have been detected by (this(" INTPTR_FORMAT ") + header(%d) == relocation_begin(" INTPTR_FORMAT ")) check.\n", p2i(this_blob), hdr_size, p2i(reloc_begin)); ! } ! if (!((address)this_blob + CodeBlob::align_code_offset(hdr_size + reloc_size) == cntnt_begin)) { ! ast->print(" Issue would have been detected by (this(" INTPTR_FORMAT ") + header(%d) + relocation(%d) == content_begin(" INTPTR_FORMAT ")) check.\n", p2i(this_blob), hdr_size, reloc_size, p2i(cntnt_begin)); ! } ! if (hdr_size != this_blob->header_size()) { ! ast->print(" header_size meanwhile changed from %d to %d\n", hdr_size, this_blob->header_size()); ! } ! if (reloc_size != this_blob->relocation_size()) { ! ast->print(" relocation_size meanwhile changed from %d to %d\n", reloc_size, this_blob->relocation_size()); } + if (reloc_begin != (address)(this_blob->relocation_begin())) { + ast->print(" relocation_begin meanwhile changed from " INTPTR_FORMAT " to " INTPTR_FORMAT "\n", p2i(reloc_begin), p2i(this_blob->relocation_begin())); } + if (cntnt_begin != this_blob->content_begin()) { + ast->print(" relocation_begin meanwhile changed from " INTPTR_FORMAT " to " INTPTR_FORMAT "\n", p2i(cntnt_begin), p2i(this_blob->content_begin())); } } + STRINGSTREAM_FLUSH_LOCKED("\n") + #endif + } + } + } // nBlobs > 0 + } STRINGSTREAM_FLUSH_LOCKED("\n\n") } void CodeHeapState::printBox(outputStream* ast, const char border, const char* text1, const char* text2) {
*** 2285,2295 **** ast->print("|"); } ast->cr(); assert(out == ast, "must use the same stream!"); ! ast->print("%p", low_bound + ix*granule_size); ast->fill_to(19); ast->print("(+" PTR32_FORMAT "): |", (unsigned int)(ix*granule_size)); } } --- 2401,2411 ---- ast->print("|"); } ast->cr(); assert(out == ast, "must use the same stream!"); ! ast->print(INTPTR_FORMAT, p2i(low_bound + ix*granule_size)); ast->fill_to(19); ast->print("(+" PTR32_FORMAT "): |", (unsigned int)(ix*granule_size)); } }
*** 2305,2315 **** ttyLocker ttyl; out->print("%s", ast->as_string()); ast->reset(); } ! ast->print("%p", low_bound + ix*granule_size); ast->fill_to(19); ast->print("(+" PTR32_FORMAT "): |", (unsigned int)(ix*granule_size)); } } --- 2421,2431 ---- ttyLocker ttyl; out->print("%s", ast->as_string()); ast->reset(); } ! ast->print(INTPTR_FORMAT, p2i(low_bound + ix*granule_size)); ast->fill_to(19); ast->print("(+" PTR32_FORMAT "): |", (unsigned int)(ix*granule_size)); } }
*** 2334,2338 **** --- 2450,2468 ---- return nMethod_dead; } } return noType; } + + // Check if pointer can be read from (4-byte read access). + // Helps to prove validity of a not-NULL pointer. + // Returns true in very early stages of VM life when stub is not yet generated. + #define SAFEFETCH_DEFAULT true + bool CodeHeapState::is_readable_pointer(const void* p) { + if (!CanUseSafeFetch32()) { + return SAFEFETCH_DEFAULT; + } + int* const aligned = (int*) align_down((intptr_t)p, 4); + int cafebabe = 0xcafebabe; // tester value 1 + int deadbeef = 0xdeadbeef; // tester value 2 + return (SafeFetch32(aligned, cafebabe) != cafebabe) || (SafeFetch32(aligned, deadbeef) != deadbeef); + }
< prev index next >