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; |