src/share/vm/runtime/os.cpp

Print this page
rev 6359 : 6311046: -Xcheck:jni should support checking of GetPrimitiveArrayCritical
Summary: Unified memory bounds checking, introducted to checked JNI.
Reviewed-by: rbackman

*** 519,643 **** strcpy(dup_str, str); return dup_str; } - - #ifdef ASSERT - #define space_before (MallocCushion + sizeof(double)) - #define space_after MallocCushion - #define size_addr_from_base(p) (size_t*)(p + space_before - sizeof(size_t)) - #define size_addr_from_obj(p) ((size_t*)p - 1) - // MallocCushion: size of extra cushion allocated around objects with +UseMallocOnly - // NB: cannot be debug variable, because these aren't set from the command line until - // *after* the first few allocs already happened - #define MallocCushion 16 - #else - #define space_before 0 - #define space_after 0 - #define size_addr_from_base(p) should not use w/o ASSERT - #define size_addr_from_obj(p) should not use w/o ASSERT - #define MallocCushion 0 - #endif #define paranoid 0 /* only set to 1 if you suspect checking code has bug */ #ifdef ASSERT ! inline size_t get_size(void* obj) { ! size_t size = *size_addr_from_obj(obj); ! if (size < 0) { ! fatal(err_msg("free: size field of object #" PTR_FORMAT " was overwritten (" ! SIZE_FORMAT ")", obj, size)); ! } ! return size; ! } ! ! u_char* find_cushion_backwards(u_char* start) { ! u_char* p = start; ! while (p[ 0] != badResourceValue || p[-1] != badResourceValue || ! p[-2] != badResourceValue || p[-3] != badResourceValue) p--; ! // ok, we have four consecutive marker bytes; find start ! u_char* q = p - 4; ! while (*q == badResourceValue) q--; ! return q + 1; ! } ! ! u_char* find_cushion_forwards(u_char* start) { ! u_char* p = start; ! while (p[0] != badResourceValue || p[1] != badResourceValue || ! p[2] != badResourceValue || p[3] != badResourceValue) p++; ! // ok, we have four consecutive marker bytes; find end of cushion ! u_char* q = p + 4; ! while (*q == badResourceValue) q++; ! return q - MallocCushion; ! } ! ! void print_neighbor_blocks(void* ptr) { ! // find block allocated before ptr (not entirely crash-proof) ! if (MallocCushion < 4) { ! tty->print_cr("### cannot find previous block (MallocCushion < 4)"); ! return; ! } ! u_char* start_of_this_block = (u_char*)ptr - space_before; ! u_char* end_of_prev_block_data = start_of_this_block - space_after -1; ! // look for cushion in front of prev. block ! u_char* start_of_prev_block = find_cushion_backwards(end_of_prev_block_data); ! ptrdiff_t size = *size_addr_from_base(start_of_prev_block); ! u_char* obj = start_of_prev_block + space_before; ! if (size <= 0 ) { ! // start is bad; may have been confused by OS data in between objects ! // search one more backwards ! start_of_prev_block = find_cushion_backwards(start_of_prev_block); ! size = *size_addr_from_base(start_of_prev_block); ! obj = start_of_prev_block + space_before; ! } ! ! if (start_of_prev_block + space_before + size + space_after == start_of_this_block) { ! tty->print_cr("### previous object: " PTR_FORMAT " (" SSIZE_FORMAT " bytes)", obj, size); ! } else { ! tty->print_cr("### previous object (not sure if correct): " PTR_FORMAT " (" SSIZE_FORMAT " bytes)", obj, size); ! } ! // now find successor block ! u_char* start_of_next_block = (u_char*)ptr + *size_addr_from_obj(ptr) + space_after; ! start_of_next_block = find_cushion_forwards(start_of_next_block); ! u_char* next_obj = start_of_next_block + space_before; ! ptrdiff_t next_size = *size_addr_from_base(start_of_next_block); ! if (start_of_next_block[0] == badResourceValue && ! start_of_next_block[1] == badResourceValue && ! start_of_next_block[2] == badResourceValue && ! start_of_next_block[3] == badResourceValue) { ! tty->print_cr("### next object: " PTR_FORMAT " (" SSIZE_FORMAT " bytes)", next_obj, next_size); ! } else { ! tty->print_cr("### next object (not sure if correct): " PTR_FORMAT " (" SSIZE_FORMAT " bytes)", next_obj, next_size); ! } ! } ! ! ! void report_heap_error(void* memblock, void* bad, const char* where) { tty->print_cr("## nof_mallocs = " UINT64_FORMAT ", nof_frees = " UINT64_FORMAT, os::num_mallocs, os::num_frees); ! tty->print_cr("## memory stomp: byte at " PTR_FORMAT " %s object " PTR_FORMAT, bad, where, memblock); ! print_neighbor_blocks(memblock); fatal("memory stomping error"); - } - - void verify_block(void* memblock) { - size_t size = get_size(memblock); - if (MallocCushion) { - u_char* ptr = (u_char*)memblock - space_before; - for (int i = 0; i < MallocCushion; i++) { - if (ptr[i] != badResourceValue) { - report_heap_error(memblock, ptr+i, "in front of"); - } - } - u_char* end = (u_char*)memblock + size + space_after; - for (int j = -MallocCushion; j < 0; j++) { - if (end[j] != badResourceValue) { - report_heap_error(memblock, end+j, "after"); - } - } } } #endif // // This function supports testing of the malloc out of memory // condition without really running the system out of memory. --- 519,543 ---- strcpy(dup_str, str); return dup_str; } #define paranoid 0 /* only set to 1 if you suspect checking code has bug */ #ifdef ASSERT ! #include "memory/fencedMemory.hpp" ! static void verify_memory(void* ptr) { ! FencedMemory fenced(ptr); ! if (!fenced.verify_fences()) { tty->print_cr("## nof_mallocs = " UINT64_FORMAT ", nof_frees = " UINT64_FORMAT, os::num_mallocs, os::num_frees); ! tty->print_cr("## memory stomp:"); ! fenced.print_on(tty); fatal("memory stomping error"); } } + #endif // // This function supports testing of the malloc out of memory // condition without really running the system out of memory.
*** 682,730 **** // return a valid pointer if size is zero // if NULL is returned the calling functions assume out of memory. size = 1; } ! const size_t alloc_size = size + space_before + space_after; ! if (size > alloc_size) { // Check for rollover. return NULL; } NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap()); u_char* ptr; - if (MallocMaxTestWords > 0) { ptr = testMalloc(alloc_size); } else { ptr = (u_char*)::malloc(alloc_size); } #ifdef ASSERT ! if (ptr == NULL) return NULL; ! if (MallocCushion) { ! for (u_char* p = ptr; p < ptr + MallocCushion; p++) *p = (u_char)badResourceValue; ! u_char* end = ptr + space_before + size; ! for (u_char* pq = ptr+MallocCushion; pq < end; pq++) *pq = (u_char)uninitBlockPad; ! for (u_char* q = end; q < end + MallocCushion; q++) *q = (u_char)badResourceValue; } ! // put size just before data ! *size_addr_from_base(ptr) = size; #endif ! u_char* memblock = ptr + space_before; ! if ((intptr_t)memblock == (intptr_t)MallocCatchPtr) { ! tty->print_cr("os::malloc caught, " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, memblock); breakpoint(); } ! debug_only(if (paranoid) verify_block(memblock)); ! if (PrintMalloc && tty != NULL) tty->print_cr("os::malloc " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, memblock); ! // we do not track MallocCushion memory ! MemTracker::record_malloc((address)memblock, size, memflags, caller == 0 ? CALLER_PC : caller); ! return memblock; } void* os::realloc(void *memblock, size_t size, MEMFLAGS memflags, address caller) { #ifndef ASSERT --- 582,630 ---- // return a valid pointer if size is zero // if NULL is returned the calling functions assume out of memory. size = 1; } ! #ifndef ASSERT ! const size_t alloc_size = size; ! #else ! const size_t alloc_size = FencedMemory::get_total_size(size); if (size > alloc_size) { // Check for rollover. return NULL; } + #endif NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap()); u_char* ptr; if (MallocMaxTestWords > 0) { ptr = testMalloc(alloc_size); } else { ptr = (u_char*)::malloc(alloc_size); } #ifdef ASSERT ! if (ptr == NULL) { ! return NULL; } ! // Wrap memory with fence ! FencedMemory fenced(ptr, size); ! ptr = fenced.get_user_ptr(); #endif ! if ((intptr_t)ptr == (intptr_t)MallocCatchPtr) { ! tty->print_cr("os::malloc caught, " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, ptr); breakpoint(); } ! debug_only(if (paranoid) verify_memory(ptr)); ! if (PrintMalloc && tty != NULL) { ! tty->print_cr("os::malloc " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, ptr); ! } ! // we do not track fence memory ! MemTracker::record_malloc((address)ptr, size, memflags, caller == 0 ? CALLER_PC : caller); ! return ptr; } void* os::realloc(void *memblock, size_t size, MEMFLAGS memflags, address caller) { #ifndef ASSERT
*** 739,811 **** tkr.discard(); } return ptr; #else if (memblock == NULL) { ! return malloc(size, memflags, (caller == 0 ? CALLER_PC : caller)); } if ((intptr_t)memblock == (intptr_t)MallocCatchPtr) { tty->print_cr("os::realloc caught " PTR_FORMAT, memblock); breakpoint(); } ! verify_block(memblock); NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap()); ! if (size == 0) return NULL; // always move the block ! void* ptr = malloc(size, memflags, caller == 0 ? CALLER_PC : caller); ! if (PrintMalloc) tty->print_cr("os::remalloc " SIZE_FORMAT " bytes, " PTR_FORMAT " --> " PTR_FORMAT, size, memblock, ptr); // Copy to new memory if malloc didn't fail if ( ptr != NULL ) { ! memcpy(ptr, memblock, MIN2(size, get_size(memblock))); ! if (paranoid) verify_block(ptr); if ((intptr_t)ptr == (intptr_t)MallocCatchPtr) { tty->print_cr("os::realloc caught, " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, ptr); breakpoint(); } ! free(memblock); } return ptr; #endif } void os::free(void *memblock, MEMFLAGS memflags) { NOT_PRODUCT(inc_stat_counter(&num_frees, 1)); #ifdef ASSERT if (memblock == NULL) return; if ((intptr_t)memblock == (intptr_t)MallocCatchPtr) { if (tty != NULL) tty->print_cr("os::free caught " PTR_FORMAT, memblock); breakpoint(); } ! verify_block(memblock); NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap()); ! // Added by detlefs. ! if (MallocCushion) { ! u_char* ptr = (u_char*)memblock - space_before; ! for (u_char* p = ptr; p < ptr + MallocCushion; p++) { ! guarantee(*p == badResourceValue, ! "Thing freed should be malloc result."); ! *p = (u_char)freeBlockPad; ! } ! size_t size = get_size(memblock); inc_stat_counter(&free_bytes, size); ! u_char* end = ptr + space_before + size; ! for (u_char* q = end; q < end + MallocCushion; q++) { ! guarantee(*q == badResourceValue, ! "Thing freed should be malloc result."); ! *q = (u_char)freeBlockPad; ! } ! if (PrintMalloc && tty != NULL) fprintf(stderr, "os::free " SIZE_FORMAT " bytes --> " PTR_FORMAT "\n", size, (uintptr_t)memblock); - } else if (PrintMalloc && tty != NULL) { - // tty->print_cr("os::free %p", memblock); - fprintf(stderr, "os::free " PTR_FORMAT "\n", (uintptr_t)memblock); } #endif ! MemTracker::record_free((address)memblock, memflags); ! ::free((char*)memblock - space_before); } void os::init_random(long initval) { _rand_seed = initval; } --- 639,703 ---- tkr.discard(); } return ptr; #else if (memblock == NULL) { ! return os::malloc(size, memflags, (caller == 0 ? CALLER_PC : caller)); } if ((intptr_t)memblock == (intptr_t)MallocCatchPtr) { tty->print_cr("os::realloc caught " PTR_FORMAT, memblock); breakpoint(); } ! verify_memory(memblock); NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap()); ! if (size == 0) { ! return NULL; ! } // always move the block ! void* ptr = os::malloc(size, memflags, caller == 0 ? CALLER_PC : caller); ! if (PrintMalloc) { ! tty->print_cr("os::remalloc " SIZE_FORMAT " bytes, " PTR_FORMAT " --> " PTR_FORMAT, size, memblock, ptr); ! } // Copy to new memory if malloc didn't fail if ( ptr != NULL ) { ! FencedMemory fenced(memblock); ! memcpy(ptr, memblock, MIN2(size, fenced.get_user_size())); ! if (paranoid) verify_memory(ptr); if ((intptr_t)ptr == (intptr_t)MallocCatchPtr) { tty->print_cr("os::realloc caught, " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, ptr); breakpoint(); } ! os::free(memblock); } return ptr; #endif } void os::free(void *memblock, MEMFLAGS memflags) { + address trackp = (address) memblock; NOT_PRODUCT(inc_stat_counter(&num_frees, 1)); #ifdef ASSERT if (memblock == NULL) return; if ((intptr_t)memblock == (intptr_t)MallocCatchPtr) { if (tty != NULL) tty->print_cr("os::free caught " PTR_FORMAT, memblock); breakpoint(); } ! verify_memory(memblock); NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap()); ! ! FencedMemory fenced(memblock); ! size_t size = fenced.get_user_size(); inc_stat_counter(&free_bytes, size); ! memblock = fenced.release_for_freeing(); ! if (PrintMalloc && tty != NULL) { fprintf(stderr, "os::free " SIZE_FORMAT " bytes --> " PTR_FORMAT "\n", size, (uintptr_t)memblock); } #endif ! MemTracker::record_free(trackp, memflags); ! ::free(memblock); } void os::init_random(long initval) { _rand_seed = initval; }