30 #include "code/icBuffer.hpp" |
30 #include "code/icBuffer.hpp" |
31 #include "code/vtableStubs.hpp" |
31 #include "code/vtableStubs.hpp" |
32 #include "gc_implementation/shared/vmGCOperations.hpp" |
32 #include "gc_implementation/shared/vmGCOperations.hpp" |
33 #include "interpreter/interpreter.hpp" |
33 #include "interpreter/interpreter.hpp" |
34 #include "memory/allocation.inline.hpp" |
34 #include "memory/allocation.inline.hpp" |
|
35 #ifdef ASSERT |
|
36 #include "memory/guardedMemory.hpp" |
|
37 #endif |
35 #include "oops/oop.inline.hpp" |
38 #include "oops/oop.inline.hpp" |
36 #include "prims/jvm.h" |
39 #include "prims/jvm.h" |
37 #include "prims/jvm_misc.hpp" |
40 #include "prims/jvm_misc.hpp" |
38 #include "prims/privilegedStack.hpp" |
41 #include "prims/privilegedStack.hpp" |
39 #include "runtime/arguments.hpp" |
42 #include "runtime/arguments.hpp" |
521 strcpy(dup_str, str); |
524 strcpy(dup_str, str); |
522 return dup_str; |
525 return dup_str; |
523 } |
526 } |
524 |
527 |
525 |
528 |
|
529 #define paranoid 0 /* only set to 1 if you suspect checking code has bug */ |
526 |
530 |
527 #ifdef ASSERT |
531 #ifdef ASSERT |
528 #define space_before (MallocCushion + sizeof(double)) |
532 |
529 #define space_after MallocCushion |
533 static void verify_memory(void* ptr) { |
530 #define size_addr_from_base(p) (size_t*)(p + space_before - sizeof(size_t)) |
534 GuardedMemory guarded(ptr); |
531 #define size_addr_from_obj(p) ((size_t*)p - 1) |
535 if (!guarded.verify_guards()) { |
532 // MallocCushion: size of extra cushion allocated around objects with +UseMallocOnly |
536 tty->print_cr("## nof_mallocs = " UINT64_FORMAT ", nof_frees = " UINT64_FORMAT, os::num_mallocs, os::num_frees); |
533 // NB: cannot be debug variable, because these aren't set from the command line until |
537 tty->print_cr("## memory stomp:"); |
534 // *after* the first few allocs already happened |
538 guarded.print_on(tty); |
535 #define MallocCushion 16 |
539 fatal("memory stomping error"); |
536 #else |
540 } |
537 #define space_before 0 |
541 } |
538 #define space_after 0 |
542 |
539 #define size_addr_from_base(p) should not use w/o ASSERT |
|
540 #define size_addr_from_obj(p) should not use w/o ASSERT |
|
541 #define MallocCushion 0 |
|
542 #endif |
|
543 #define paranoid 0 /* only set to 1 if you suspect checking code has bug */ |
|
544 |
|
545 #ifdef ASSERT |
|
546 inline size_t get_size(void* obj) { |
|
547 size_t size = *size_addr_from_obj(obj); |
|
548 if (size < 0) { |
|
549 fatal(err_msg("free: size field of object #" PTR_FORMAT " was overwritten (" |
|
550 SIZE_FORMAT ")", obj, size)); |
|
551 } |
|
552 return size; |
|
553 } |
|
554 |
|
555 u_char* find_cushion_backwards(u_char* start) { |
|
556 u_char* p = start; |
|
557 while (p[ 0] != badResourceValue || p[-1] != badResourceValue || |
|
558 p[-2] != badResourceValue || p[-3] != badResourceValue) p--; |
|
559 // ok, we have four consecutive marker bytes; find start |
|
560 u_char* q = p - 4; |
|
561 while (*q == badResourceValue) q--; |
|
562 return q + 1; |
|
563 } |
|
564 |
|
565 u_char* find_cushion_forwards(u_char* start) { |
|
566 u_char* p = start; |
|
567 while (p[0] != badResourceValue || p[1] != badResourceValue || |
|
568 p[2] != badResourceValue || p[3] != badResourceValue) p++; |
|
569 // ok, we have four consecutive marker bytes; find end of cushion |
|
570 u_char* q = p + 4; |
|
571 while (*q == badResourceValue) q++; |
|
572 return q - MallocCushion; |
|
573 } |
|
574 |
|
575 void print_neighbor_blocks(void* ptr) { |
|
576 // find block allocated before ptr (not entirely crash-proof) |
|
577 if (MallocCushion < 4) { |
|
578 tty->print_cr("### cannot find previous block (MallocCushion < 4)"); |
|
579 return; |
|
580 } |
|
581 u_char* start_of_this_block = (u_char*)ptr - space_before; |
|
582 u_char* end_of_prev_block_data = start_of_this_block - space_after -1; |
|
583 // look for cushion in front of prev. block |
|
584 u_char* start_of_prev_block = find_cushion_backwards(end_of_prev_block_data); |
|
585 ptrdiff_t size = *size_addr_from_base(start_of_prev_block); |
|
586 u_char* obj = start_of_prev_block + space_before; |
|
587 if (size <= 0 ) { |
|
588 // start is bad; may have been confused by OS data in between objects |
|
589 // search one more backwards |
|
590 start_of_prev_block = find_cushion_backwards(start_of_prev_block); |
|
591 size = *size_addr_from_base(start_of_prev_block); |
|
592 obj = start_of_prev_block + space_before; |
|
593 } |
|
594 |
|
595 if (start_of_prev_block + space_before + size + space_after == start_of_this_block) { |
|
596 tty->print_cr("### previous object: " PTR_FORMAT " (" SSIZE_FORMAT " bytes)", obj, size); |
|
597 } else { |
|
598 tty->print_cr("### previous object (not sure if correct): " PTR_FORMAT " (" SSIZE_FORMAT " bytes)", obj, size); |
|
599 } |
|
600 |
|
601 // now find successor block |
|
602 u_char* start_of_next_block = (u_char*)ptr + *size_addr_from_obj(ptr) + space_after; |
|
603 start_of_next_block = find_cushion_forwards(start_of_next_block); |
|
604 u_char* next_obj = start_of_next_block + space_before; |
|
605 ptrdiff_t next_size = *size_addr_from_base(start_of_next_block); |
|
606 if (start_of_next_block[0] == badResourceValue && |
|
607 start_of_next_block[1] == badResourceValue && |
|
608 start_of_next_block[2] == badResourceValue && |
|
609 start_of_next_block[3] == badResourceValue) { |
|
610 tty->print_cr("### next object: " PTR_FORMAT " (" SSIZE_FORMAT " bytes)", next_obj, next_size); |
|
611 } else { |
|
612 tty->print_cr("### next object (not sure if correct): " PTR_FORMAT " (" SSIZE_FORMAT " bytes)", next_obj, next_size); |
|
613 } |
|
614 } |
|
615 |
|
616 |
|
617 void report_heap_error(void* memblock, void* bad, const char* where) { |
|
618 tty->print_cr("## nof_mallocs = " UINT64_FORMAT ", nof_frees = " UINT64_FORMAT, os::num_mallocs, os::num_frees); |
|
619 tty->print_cr("## memory stomp: byte at " PTR_FORMAT " %s object " PTR_FORMAT, bad, where, memblock); |
|
620 print_neighbor_blocks(memblock); |
|
621 fatal("memory stomping error"); |
|
622 } |
|
623 |
|
624 void verify_block(void* memblock) { |
|
625 size_t size = get_size(memblock); |
|
626 if (MallocCushion) { |
|
627 u_char* ptr = (u_char*)memblock - space_before; |
|
628 for (int i = 0; i < MallocCushion; i++) { |
|
629 if (ptr[i] != badResourceValue) { |
|
630 report_heap_error(memblock, ptr+i, "in front of"); |
|
631 } |
|
632 } |
|
633 u_char* end = (u_char*)memblock + size + space_after; |
|
634 for (int j = -MallocCushion; j < 0; j++) { |
|
635 if (end[j] != badResourceValue) { |
|
636 report_heap_error(memblock, end+j, "after"); |
|
637 } |
|
638 } |
|
639 } |
|
640 } |
|
641 #endif |
543 #endif |
642 |
544 |
643 // |
545 // |
644 // This function supports testing of the malloc out of memory |
546 // This function supports testing of the malloc out of memory |
645 // condition without really running the system out of memory. |
547 // condition without really running the system out of memory. |
684 // return a valid pointer if size is zero |
586 // return a valid pointer if size is zero |
685 // if NULL is returned the calling functions assume out of memory. |
587 // if NULL is returned the calling functions assume out of memory. |
686 size = 1; |
588 size = 1; |
687 } |
589 } |
688 |
590 |
689 const size_t alloc_size = size + space_before + space_after; |
591 #ifndef ASSERT |
690 |
592 const size_t alloc_size = size; |
|
593 #else |
|
594 const size_t alloc_size = GuardedMemory::get_total_size(size); |
691 if (size > alloc_size) { // Check for rollover. |
595 if (size > alloc_size) { // Check for rollover. |
692 return NULL; |
596 return NULL; |
693 } |
597 } |
|
598 #endif |
694 |
599 |
695 NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap()); |
600 NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap()); |
696 |
601 |
697 u_char* ptr; |
602 u_char* ptr; |
698 |
|
699 if (MallocMaxTestWords > 0) { |
603 if (MallocMaxTestWords > 0) { |
700 ptr = testMalloc(alloc_size); |
604 ptr = testMalloc(alloc_size); |
701 } else { |
605 } else { |
702 ptr = (u_char*)::malloc(alloc_size); |
606 ptr = (u_char*)::malloc(alloc_size); |
703 } |
607 } |
704 |
608 |
705 #ifdef ASSERT |
609 #ifdef ASSERT |
706 if (ptr == NULL) return NULL; |
610 if (ptr == NULL) { |
707 if (MallocCushion) { |
611 return NULL; |
708 for (u_char* p = ptr; p < ptr + MallocCushion; p++) *p = (u_char)badResourceValue; |
612 } |
709 u_char* end = ptr + space_before + size; |
613 // Wrap memory with guard |
710 for (u_char* pq = ptr+MallocCushion; pq < end; pq++) *pq = (u_char)uninitBlockPad; |
614 GuardedMemory guarded(ptr, size); |
711 for (u_char* q = end; q < end + MallocCushion; q++) *q = (u_char)badResourceValue; |
615 ptr = guarded.get_user_ptr(); |
712 } |
616 #endif |
713 // put size just before data |
617 if ((intptr_t)ptr == (intptr_t)MallocCatchPtr) { |
714 *size_addr_from_base(ptr) = size; |
618 tty->print_cr("os::malloc caught, " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, ptr); |
715 #endif |
|
716 u_char* memblock = ptr + space_before; |
|
717 if ((intptr_t)memblock == (intptr_t)MallocCatchPtr) { |
|
718 tty->print_cr("os::malloc caught, " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, memblock); |
|
719 breakpoint(); |
619 breakpoint(); |
720 } |
620 } |
721 debug_only(if (paranoid) verify_block(memblock)); |
621 debug_only(if (paranoid) verify_memory(ptr)); |
722 if (PrintMalloc && tty != NULL) tty->print_cr("os::malloc " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, memblock); |
622 if (PrintMalloc && tty != NULL) { |
723 |
623 tty->print_cr("os::malloc " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, ptr); |
724 // we do not track MallocCushion memory |
624 } |
725 MemTracker::record_malloc((address)memblock, size, memflags, caller == 0 ? CALLER_PC : caller); |
625 |
726 |
626 // we do not track guard memory |
727 return memblock; |
627 MemTracker::record_malloc((address)ptr, size, memflags, caller == 0 ? CALLER_PC : caller); |
|
628 |
|
629 return ptr; |
728 } |
630 } |
729 |
631 |
730 |
632 |
731 void* os::realloc(void *memblock, size_t size, MEMFLAGS memflags, address caller) { |
633 void* os::realloc(void *memblock, size_t size, MEMFLAGS memflags, address caller) { |
732 #ifndef ASSERT |
634 #ifndef ASSERT |
741 tkr.discard(); |
643 tkr.discard(); |
742 } |
644 } |
743 return ptr; |
645 return ptr; |
744 #else |
646 #else |
745 if (memblock == NULL) { |
647 if (memblock == NULL) { |
746 return malloc(size, memflags, (caller == 0 ? CALLER_PC : caller)); |
648 return os::malloc(size, memflags, (caller == 0 ? CALLER_PC : caller)); |
747 } |
649 } |
748 if ((intptr_t)memblock == (intptr_t)MallocCatchPtr) { |
650 if ((intptr_t)memblock == (intptr_t)MallocCatchPtr) { |
749 tty->print_cr("os::realloc caught " PTR_FORMAT, memblock); |
651 tty->print_cr("os::realloc caught " PTR_FORMAT, memblock); |
750 breakpoint(); |
652 breakpoint(); |
751 } |
653 } |
752 verify_block(memblock); |
654 verify_memory(memblock); |
753 NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap()); |
655 NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap()); |
754 if (size == 0) return NULL; |
656 if (size == 0) { |
|
657 return NULL; |
|
658 } |
755 // always move the block |
659 // always move the block |
756 void* ptr = malloc(size, memflags, caller == 0 ? CALLER_PC : caller); |
660 void* ptr = os::malloc(size, memflags, caller == 0 ? CALLER_PC : caller); |
757 if (PrintMalloc) tty->print_cr("os::remalloc " SIZE_FORMAT " bytes, " PTR_FORMAT " --> " PTR_FORMAT, size, memblock, ptr); |
661 if (PrintMalloc) { |
|
662 tty->print_cr("os::remalloc " SIZE_FORMAT " bytes, " PTR_FORMAT " --> " PTR_FORMAT, size, memblock, ptr); |
|
663 } |
758 // Copy to new memory if malloc didn't fail |
664 // Copy to new memory if malloc didn't fail |
759 if ( ptr != NULL ) { |
665 if ( ptr != NULL ) { |
760 memcpy(ptr, memblock, MIN2(size, get_size(memblock))); |
666 GuardedMemory guarded(memblock); |
761 if (paranoid) verify_block(ptr); |
667 memcpy(ptr, memblock, MIN2(size, guarded.get_user_size())); |
|
668 if (paranoid) verify_memory(ptr); |
762 if ((intptr_t)ptr == (intptr_t)MallocCatchPtr) { |
669 if ((intptr_t)ptr == (intptr_t)MallocCatchPtr) { |
763 tty->print_cr("os::realloc caught, " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, ptr); |
670 tty->print_cr("os::realloc caught, " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, ptr); |
764 breakpoint(); |
671 breakpoint(); |
765 } |
672 } |
766 free(memblock); |
673 os::free(memblock); |
767 } |
674 } |
768 return ptr; |
675 return ptr; |
769 #endif |
676 #endif |
770 } |
677 } |
771 |
678 |
772 |
679 |
773 void os::free(void *memblock, MEMFLAGS memflags) { |
680 void os::free(void *memblock, MEMFLAGS memflags) { |
|
681 address trackp = (address) memblock; |
774 NOT_PRODUCT(inc_stat_counter(&num_frees, 1)); |
682 NOT_PRODUCT(inc_stat_counter(&num_frees, 1)); |
775 #ifdef ASSERT |
683 #ifdef ASSERT |
776 if (memblock == NULL) return; |
684 if (memblock == NULL) return; |
777 if ((intptr_t)memblock == (intptr_t)MallocCatchPtr) { |
685 if ((intptr_t)memblock == (intptr_t)MallocCatchPtr) { |
778 if (tty != NULL) tty->print_cr("os::free caught " PTR_FORMAT, memblock); |
686 if (tty != NULL) tty->print_cr("os::free caught " PTR_FORMAT, memblock); |
779 breakpoint(); |
687 breakpoint(); |
780 } |
688 } |
781 verify_block(memblock); |
689 verify_memory(memblock); |
782 NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap()); |
690 NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap()); |
783 // Added by detlefs. |
691 |
784 if (MallocCushion) { |
692 GuardedMemory guarded(memblock); |
785 u_char* ptr = (u_char*)memblock - space_before; |
693 size_t size = guarded.get_user_size(); |
786 for (u_char* p = ptr; p < ptr + MallocCushion; p++) { |
694 inc_stat_counter(&free_bytes, size); |
787 guarantee(*p == badResourceValue, |
695 memblock = guarded.release_for_freeing(); |
788 "Thing freed should be malloc result."); |
696 if (PrintMalloc && tty != NULL) { |
789 *p = (u_char)freeBlockPad; |
|
790 } |
|
791 size_t size = get_size(memblock); |
|
792 inc_stat_counter(&free_bytes, size); |
|
793 u_char* end = ptr + space_before + size; |
|
794 for (u_char* q = end; q < end + MallocCushion; q++) { |
|
795 guarantee(*q == badResourceValue, |
|
796 "Thing freed should be malloc result."); |
|
797 *q = (u_char)freeBlockPad; |
|
798 } |
|
799 if (PrintMalloc && tty != NULL) |
|
800 fprintf(stderr, "os::free " SIZE_FORMAT " bytes --> " PTR_FORMAT "\n", size, (uintptr_t)memblock); |
697 fprintf(stderr, "os::free " SIZE_FORMAT " bytes --> " PTR_FORMAT "\n", size, (uintptr_t)memblock); |
801 } else if (PrintMalloc && tty != NULL) { |
698 } |
802 // tty->print_cr("os::free %p", memblock); |
699 #endif |
803 fprintf(stderr, "os::free " PTR_FORMAT "\n", (uintptr_t)memblock); |
700 MemTracker::record_free(trackp, memflags); |
804 } |
701 |
805 #endif |
702 ::free(memblock); |
806 MemTracker::record_free((address)memblock, memflags); |
|
807 |
|
808 ::free((char*)memblock - space_before); |
|
809 } |
703 } |
810 |
704 |
811 void os::init_random(long initval) { |
705 void os::init_random(long initval) { |
812 _rand_seed = initval; |
706 _rand_seed = initval; |
813 } |
707 } |