Mercurial > hg > truffle
comparison src/share/vm/runtime/os.cpp @ 20318:fa62fb12cdca
6311046: -Xcheck:jni should support checking of GetPrimitiveArrayCritical.
Summary: Wrapped memory with standard bounds checking "GuardedMemory".
Reviewed-by: zgu, fparain, dcubed
author | dsimms |
---|---|
date | Thu, 14 Aug 2014 15:16:07 +0200 |
parents | 78bbf4d43a14 |
children | 833b0f92429a |
comparison
equal
deleted
inserted
replaced
20317:ee019285a52c | 20318:fa62fb12cdca |
---|---|
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" |
522 return dup_str; | 525 return dup_str; |
523 } | 526 } |
524 | 527 |
525 | 528 |
526 | 529 |
530 #define paranoid 0 /* only set to 1 if you suspect checking code has bug */ | |
531 | |
527 #ifdef ASSERT | 532 #ifdef ASSERT |
528 #define space_before (MallocCushion + sizeof(double)) | 533 static void verify_memory(void* ptr) { |
529 #define space_after MallocCushion | 534 GuardedMemory guarded(ptr); |
530 #define size_addr_from_base(p) (size_t*)(p + space_before - sizeof(size_t)) | 535 if (!guarded.verify_guards()) { |
531 #define size_addr_from_obj(p) ((size_t*)p - 1) | 536 tty->print_cr("## nof_mallocs = " UINT64_FORMAT ", nof_frees = " UINT64_FORMAT, os::num_mallocs, os::num_frees); |
532 // MallocCushion: size of extra cushion allocated around objects with +UseMallocOnly | 537 tty->print_cr("## memory stomp:"); |
533 // NB: cannot be debug variable, because these aren't set from the command line until | 538 guarded.print_on(tty); |
534 // *after* the first few allocs already happened | 539 fatal("memory stomping error"); |
535 #define MallocCushion 16 | |
536 #else | |
537 #define space_before 0 | |
538 #define space_after 0 | |
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; mayhave been confused by OS data inbetween 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 } | 540 } |
640 } | 541 } |
641 #endif | 542 #endif |
642 | 543 |
643 // | 544 // |
684 // return a valid pointer if size is zero | 585 // return a valid pointer if size is zero |
685 // if NULL is returned the calling functions assume out of memory. | 586 // if NULL is returned the calling functions assume out of memory. |
686 size = 1; | 587 size = 1; |
687 } | 588 } |
688 | 589 |
689 const size_t alloc_size = size + space_before + space_after; | 590 #ifndef ASSERT |
690 | 591 const size_t alloc_size = size; |
592 #else | |
593 const size_t alloc_size = GuardedMemory::get_total_size(size); | |
691 if (size > alloc_size) { // Check for rollover. | 594 if (size > alloc_size) { // Check for rollover. |
692 return NULL; | 595 return NULL; |
693 } | 596 } |
597 #endif | |
694 | 598 |
695 NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap()); | 599 NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap()); |
696 | 600 |
697 u_char* ptr; | 601 u_char* ptr; |
698 | |
699 if (MallocMaxTestWords > 0) { | 602 if (MallocMaxTestWords > 0) { |
700 ptr = testMalloc(alloc_size); | 603 ptr = testMalloc(alloc_size); |
701 } else { | 604 } else { |
702 ptr = (u_char*)::malloc(alloc_size); | 605 ptr = (u_char*)::malloc(alloc_size); |
703 } | 606 } |
704 | 607 |
705 #ifdef ASSERT | 608 #ifdef ASSERT |
706 if (ptr == NULL) return NULL; | 609 if (ptr == NULL) { |
707 if (MallocCushion) { | 610 return NULL; |
708 for (u_char* p = ptr; p < ptr + MallocCushion; p++) *p = (u_char)badResourceValue; | 611 } |
709 u_char* end = ptr + space_before + size; | 612 // Wrap memory with guard |
710 for (u_char* pq = ptr+MallocCushion; pq < end; pq++) *pq = (u_char)uninitBlockPad; | 613 GuardedMemory guarded(ptr, size); |
711 for (u_char* q = end; q < end + MallocCushion; q++) *q = (u_char)badResourceValue; | 614 ptr = guarded.get_user_ptr(); |
712 } | 615 #endif |
713 // put size just before data | 616 if ((intptr_t)ptr == (intptr_t)MallocCatchPtr) { |
714 *size_addr_from_base(ptr) = size; | 617 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(); | 618 breakpoint(); |
720 } | 619 } |
721 debug_only(if (paranoid) verify_block(memblock)); | 620 debug_only(if (paranoid) verify_memory(ptr)); |
722 if (PrintMalloc && tty != NULL) tty->print_cr("os::malloc " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, memblock); | 621 if (PrintMalloc && tty != NULL) { |
723 | 622 tty->print_cr("os::malloc " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, ptr); |
724 // we do not track MallocCushion memory | 623 } |
725 MemTracker::record_malloc((address)memblock, size, memflags, caller == 0 ? CALLER_PC : caller); | 624 |
726 | 625 // we do not track guard memory |
727 return memblock; | 626 MemTracker::record_malloc((address)ptr, size, memflags, caller == 0 ? CALLER_PC : caller); |
627 | |
628 return ptr; | |
728 } | 629 } |
729 | 630 |
730 | 631 |
731 void* os::realloc(void *memblock, size_t size, MEMFLAGS memflags, address caller) { | 632 void* os::realloc(void *memblock, size_t size, MEMFLAGS memflags, address caller) { |
732 #ifndef ASSERT | 633 #ifndef ASSERT |
741 tkr.discard(); | 642 tkr.discard(); |
742 } | 643 } |
743 return ptr; | 644 return ptr; |
744 #else | 645 #else |
745 if (memblock == NULL) { | 646 if (memblock == NULL) { |
746 return malloc(size, memflags, (caller == 0 ? CALLER_PC : caller)); | 647 return os::malloc(size, memflags, (caller == 0 ? CALLER_PC : caller)); |
747 } | 648 } |
748 if ((intptr_t)memblock == (intptr_t)MallocCatchPtr) { | 649 if ((intptr_t)memblock == (intptr_t)MallocCatchPtr) { |
749 tty->print_cr("os::realloc caught " PTR_FORMAT, memblock); | 650 tty->print_cr("os::realloc caught " PTR_FORMAT, memblock); |
750 breakpoint(); | 651 breakpoint(); |
751 } | 652 } |
752 verify_block(memblock); | 653 verify_memory(memblock); |
753 NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap()); | 654 NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap()); |
754 if (size == 0) return NULL; | 655 if (size == 0) { |
656 return NULL; | |
657 } | |
755 // always move the block | 658 // always move the block |
756 void* ptr = malloc(size, memflags, caller == 0 ? CALLER_PC : caller); | 659 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); | 660 if (PrintMalloc) { |
661 tty->print_cr("os::remalloc " SIZE_FORMAT " bytes, " PTR_FORMAT " --> " PTR_FORMAT, size, memblock, ptr); | |
662 } | |
758 // Copy to new memory if malloc didn't fail | 663 // Copy to new memory if malloc didn't fail |
759 if ( ptr != NULL ) { | 664 if ( ptr != NULL ) { |
760 memcpy(ptr, memblock, MIN2(size, get_size(memblock))); | 665 GuardedMemory guarded(memblock); |
761 if (paranoid) verify_block(ptr); | 666 memcpy(ptr, memblock, MIN2(size, guarded.get_user_size())); |
667 if (paranoid) verify_memory(ptr); | |
762 if ((intptr_t)ptr == (intptr_t)MallocCatchPtr) { | 668 if ((intptr_t)ptr == (intptr_t)MallocCatchPtr) { |
763 tty->print_cr("os::realloc caught, " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, ptr); | 669 tty->print_cr("os::realloc caught, " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, ptr); |
764 breakpoint(); | 670 breakpoint(); |
765 } | 671 } |
766 free(memblock); | 672 os::free(memblock); |
767 } | 673 } |
768 return ptr; | 674 return ptr; |
769 #endif | 675 #endif |
770 } | 676 } |
771 | 677 |
772 | 678 |
773 void os::free(void *memblock, MEMFLAGS memflags) { | 679 void os::free(void *memblock, MEMFLAGS memflags) { |
680 address trackp = (address) memblock; | |
774 NOT_PRODUCT(inc_stat_counter(&num_frees, 1)); | 681 NOT_PRODUCT(inc_stat_counter(&num_frees, 1)); |
775 #ifdef ASSERT | 682 #ifdef ASSERT |
776 if (memblock == NULL) return; | 683 if (memblock == NULL) return; |
777 if ((intptr_t)memblock == (intptr_t)MallocCatchPtr) { | 684 if ((intptr_t)memblock == (intptr_t)MallocCatchPtr) { |
778 if (tty != NULL) tty->print_cr("os::free caught " PTR_FORMAT, memblock); | 685 if (tty != NULL) tty->print_cr("os::free caught " PTR_FORMAT, memblock); |
779 breakpoint(); | 686 breakpoint(); |
780 } | 687 } |
781 verify_block(memblock); | 688 verify_memory(memblock); |
782 NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap()); | 689 NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap()); |
783 // Added by detlefs. | 690 |
784 if (MallocCushion) { | 691 GuardedMemory guarded(memblock); |
785 u_char* ptr = (u_char*)memblock - space_before; | 692 size_t size = guarded.get_user_size(); |
786 for (u_char* p = ptr; p < ptr + MallocCushion; p++) { | 693 inc_stat_counter(&free_bytes, size); |
787 guarantee(*p == badResourceValue, | 694 memblock = guarded.release_for_freeing(); |
788 "Thing freed should be malloc result."); | 695 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); | 696 fprintf(stderr, "os::free " SIZE_FORMAT " bytes --> " PTR_FORMAT "\n", size, (uintptr_t)memblock); |
801 } else if (PrintMalloc && tty != NULL) { | 697 } |
802 // tty->print_cr("os::free %p", memblock); | 698 #endif |
803 fprintf(stderr, "os::free " PTR_FORMAT "\n", (uintptr_t)memblock); | 699 MemTracker::record_free(trackp, memflags); |
804 } | 700 |
805 #endif | 701 ::free(memblock); |
806 MemTracker::record_free((address)memblock, memflags); | |
807 | |
808 ::free((char*)memblock - space_before); | |
809 } | 702 } |
810 | 703 |
811 void os::init_random(long initval) { | 704 void os::init_random(long initval) { |
812 _rand_seed = initval; | 705 _rand_seed = initval; |
813 } | 706 } |