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;