Mercurial > hg > graal-compiler
comparison src/share/vm/memory/collectorPolicy.cpp @ 1387:0bfd3fb24150
6858496: Clear all SoftReferences before an out-of-memory due to GC overhead limit.
Summary: Ensure a full GC that clears SoftReferences before throwing an out-of-memory
Reviewed-by: ysr, jcoomes
author | jmasa |
---|---|
date | Tue, 13 Apr 2010 13:52:10 -0700 |
parents | 473cce303f13 |
children | c18cbe5936b8 |
comparison
equal
deleted
inserted
replaced
1361:6b73e879f1c2 | 1387:0bfd3fb24150 |
---|---|
1 /* | 1 /* |
2 * Copyright 2001-2008 Sun Microsystems, Inc. All Rights Reserved. | 2 * Copyright 2001-2010 Sun Microsystems, Inc. All Rights Reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | 4 * |
5 * This code is free software; you can redistribute it and/or modify it | 5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as | 6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
110 if (_permanent_generation == NULL) { | 110 if (_permanent_generation == NULL) { |
111 vm_exit_during_initialization("Unable to allocate gen spec"); | 111 vm_exit_during_initialization("Unable to allocate gen spec"); |
112 } | 112 } |
113 } | 113 } |
114 | 114 |
115 bool CollectorPolicy::use_should_clear_all_soft_refs(bool v) { | |
116 bool result = _should_clear_all_soft_refs; | |
117 set_should_clear_all_soft_refs(false); | |
118 return result; | |
119 } | |
115 | 120 |
116 GenRemSet* CollectorPolicy::create_rem_set(MemRegion whole_heap, | 121 GenRemSet* CollectorPolicy::create_rem_set(MemRegion whole_heap, |
117 int max_covered_regions) { | 122 int max_covered_regions) { |
118 switch (rem_set_name()) { | 123 switch (rem_set_name()) { |
119 case GenRemSet::CardTable: { | 124 case GenRemSet::CardTable: { |
123 default: | 128 default: |
124 guarantee(false, "unrecognized GenRemSet::Name"); | 129 guarantee(false, "unrecognized GenRemSet::Name"); |
125 return NULL; | 130 return NULL; |
126 } | 131 } |
127 } | 132 } |
133 | |
134 void CollectorPolicy::cleared_all_soft_refs() { | |
135 // If near gc overhear limit, continue to clear SoftRefs. SoftRefs may | |
136 // have been cleared in the last collection but if the gc overhear | |
137 // limit continues to be near, SoftRefs should still be cleared. | |
138 if (size_policy() != NULL) { | |
139 _should_clear_all_soft_refs = size_policy()->gc_overhead_limit_near(); | |
140 } | |
141 _all_soft_refs_clear = true; | |
142 } | |
143 | |
128 | 144 |
129 // GenCollectorPolicy methods. | 145 // GenCollectorPolicy methods. |
130 | 146 |
131 size_t GenCollectorPolicy::scale_by_NewRatio_aligned(size_t base_size) { | 147 size_t GenCollectorPolicy::scale_by_NewRatio_aligned(size_t base_size) { |
132 size_t x = base_size / (NewRatio+1); | 148 size_t x = base_size / (NewRatio+1); |
487 bool* gc_overhead_limit_was_exceeded) { | 503 bool* gc_overhead_limit_was_exceeded) { |
488 GenCollectedHeap *gch = GenCollectedHeap::heap(); | 504 GenCollectedHeap *gch = GenCollectedHeap::heap(); |
489 | 505 |
490 debug_only(gch->check_for_valid_allocation_state()); | 506 debug_only(gch->check_for_valid_allocation_state()); |
491 assert(gch->no_gc_in_progress(), "Allocation during gc not allowed"); | 507 assert(gch->no_gc_in_progress(), "Allocation during gc not allowed"); |
508 | |
509 // In general gc_overhead_limit_was_exceeded should be false so | |
510 // set it so here and reset it to true only if the gc time | |
511 // limit is being exceeded as checked below. | |
512 *gc_overhead_limit_was_exceeded = false; | |
513 | |
492 HeapWord* result = NULL; | 514 HeapWord* result = NULL; |
493 | 515 |
494 // Loop until the allocation is satisified, | 516 // Loop until the allocation is satisified, |
495 // or unsatisfied after GC. | 517 // or unsatisfied after GC. |
496 for (int try_count = 1; /* return or throw */; try_count += 1) { | 518 for (int try_count = 1; /* return or throw */; try_count += 1) { |
521 result = gch->attempt_allocation(size, is_tlab, first_only); | 543 result = gch->attempt_allocation(size, is_tlab, first_only); |
522 if (result != NULL) { | 544 if (result != NULL) { |
523 assert(gch->is_in_reserved(result), "result not in heap"); | 545 assert(gch->is_in_reserved(result), "result not in heap"); |
524 return result; | 546 return result; |
525 } | 547 } |
526 | |
527 // There are NULL's returned for different circumstances below. | |
528 // In general gc_overhead_limit_was_exceeded should be false so | |
529 // set it so here and reset it to true only if the gc time | |
530 // limit is being exceeded as checked below. | |
531 *gc_overhead_limit_was_exceeded = false; | |
532 | 548 |
533 if (GC_locker::is_active_and_needs_gc()) { | 549 if (GC_locker::is_active_and_needs_gc()) { |
534 if (is_tlab) { | 550 if (is_tlab) { |
535 return NULL; // Caller will retry allocating individual object | 551 return NULL; // Caller will retry allocating individual object |
536 } | 552 } |
566 | 582 |
567 // Read the gc count while the heap lock is held. | 583 // Read the gc count while the heap lock is held. |
568 gc_count_before = Universe::heap()->total_collections(); | 584 gc_count_before = Universe::heap()->total_collections(); |
569 } | 585 } |
570 | 586 |
571 // Allocation has failed and a collection is about | |
572 // to be done. If the gc time limit was exceeded the | |
573 // last time a collection was done, return NULL so | |
574 // that an out-of-memory will be thrown. Clear | |
575 // gc_time_limit_exceeded so that subsequent attempts | |
576 // at a collection will be made. | |
577 if (size_policy()->gc_time_limit_exceeded()) { | |
578 *gc_overhead_limit_was_exceeded = true; | |
579 size_policy()->set_gc_time_limit_exceeded(false); | |
580 return NULL; | |
581 } | |
582 | |
583 VM_GenCollectForAllocation op(size, | 587 VM_GenCollectForAllocation op(size, |
584 is_tlab, | 588 is_tlab, |
585 gc_count_before); | 589 gc_count_before); |
586 VMThread::execute(&op); | 590 VMThread::execute(&op); |
587 if (op.prologue_succeeded()) { | 591 if (op.prologue_succeeded()) { |
588 result = op.result(); | 592 result = op.result(); |
589 if (op.gc_locked()) { | 593 if (op.gc_locked()) { |
590 assert(result == NULL, "must be NULL if gc_locked() is true"); | 594 assert(result == NULL, "must be NULL if gc_locked() is true"); |
591 continue; // retry and/or stall as necessary | 595 continue; // retry and/or stall as necessary |
596 } | |
597 | |
598 // Allocation has failed and a collection | |
599 // has been done. If the gc time limit was exceeded the | |
600 // this time, return NULL so that an out-of-memory | |
601 // will be thrown. Clear gc_overhead_limit_exceeded | |
602 // so that the overhead exceeded does not persist. | |
603 | |
604 const bool limit_exceeded = size_policy()->gc_overhead_limit_exceeded(); | |
605 const bool softrefs_clear = all_soft_refs_clear(); | |
606 assert(!limit_exceeded || softrefs_clear, "Should have been cleared"); | |
607 if (limit_exceeded && softrefs_clear) { | |
608 *gc_overhead_limit_was_exceeded = true; | |
609 size_policy()->set_gc_overhead_limit_exceeded(false); | |
610 if (op.result() != NULL) { | |
611 CollectedHeap::fill_with_object(op.result(), size); | |
612 } | |
613 return NULL; | |
592 } | 614 } |
593 assert(result == NULL || gch->is_in_reserved(result), | 615 assert(result == NULL || gch->is_in_reserved(result), |
594 "result not in heap"); | 616 "result not in heap"); |
595 return result; | 617 return result; |
596 } | 618 } |
686 if (result != NULL) { | 708 if (result != NULL) { |
687 assert(gch->is_in_reserved(result), "result not in heap"); | 709 assert(gch->is_in_reserved(result), "result not in heap"); |
688 return result; | 710 return result; |
689 } | 711 } |
690 | 712 |
713 assert(!should_clear_all_soft_refs(), | |
714 "Flag should have been handled and cleared prior to this point"); | |
715 | |
691 // What else? We might try synchronous finalization later. If the total | 716 // What else? We might try synchronous finalization later. If the total |
692 // space available is large enough for the allocation, then a more | 717 // space available is large enough for the allocation, then a more |
693 // complete compaction phase than we've tried so far might be | 718 // complete compaction phase than we've tried so far might be |
694 // appropriate. | 719 // appropriate. |
695 return NULL; | 720 return NULL; |