1 /* 2 * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 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 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #include "incls/_precompiled.incl" 26 #include "incls/_permGen.cpp.incl" 27 28 HeapWord* PermGen::mem_allocate_in_gen(size_t size, Generation* gen) { 29 GCCause::Cause next_cause = GCCause::_permanent_generation_full; 30 GCCause::Cause prev_cause = GCCause::_no_gc; 31 unsigned int gc_count_before, full_gc_count_before; 32 HeapWord* obj; 33 34 for (;;) { 35 { 36 MutexLocker ml(Heap_lock); 37 if ((obj = gen->allocate(size, false)) != NULL) { 38 return obj; 39 } 40 if (gen->capacity() < _capacity_expansion_limit || 41 prev_cause != GCCause::_no_gc) { 42 obj = gen->expand_and_allocate(size, false); 43 } 44 if (obj != NULL || prev_cause == GCCause::_last_ditch_collection) { 45 return obj; 46 } 47 if (GC_locker::is_active_and_needs_gc()) { 48 // If this thread is not in a jni critical section, we stall 49 // the requestor until the critical section has cleared and 50 // GC allowed. When the critical section clears, a GC is 51 // initiated by the last thread exiting the critical section; so 52 // we retry the allocation sequence from the beginning of the loop, 53 // rather than causing more, now probably unnecessary, GC attempts. 54 JavaThread* jthr = JavaThread::current(); 55 if (!jthr->in_critical()) { 56 MutexUnlocker mul(Heap_lock); 57 // Wait for JNI critical section to be exited 58 GC_locker::stall_until_clear(); 59 continue; 60 } else { 61 if (CheckJNICalls) { 62 fatal("Possible deadlock due to allocating while" 63 " in jni critical section"); 64 } 65 return NULL; 66 } 67 } 68 // Read the GC count while holding the Heap_lock 69 gc_count_before = SharedHeap::heap()->total_collections(); 70 full_gc_count_before = SharedHeap::heap()->total_full_collections(); 71 } 72 73 // Give up heap lock above, VMThread::execute below gets it back 74 VM_GenCollectForPermanentAllocation op(size, gc_count_before, full_gc_count_before, 75 next_cause); 76 VMThread::execute(&op); 77 if (!op.prologue_succeeded() || op.gc_locked()) { 78 assert(op.result() == NULL, "must be NULL if gc_locked() is true"); 79 continue; // retry and/or stall as necessary 80 } 81 obj = op.result(); 82 assert(obj == NULL || SharedHeap::heap()->is_in_reserved(obj), 83 "result not in heap"); 84 if (obj != NULL) { 85 return obj; 86 } 87 prev_cause = next_cause; 88 next_cause = GCCause::_last_ditch_collection; 89 } 90 } 91 92 CompactingPermGen::CompactingPermGen(ReservedSpace rs, 93 ReservedSpace shared_rs, 94 size_t initial_byte_size, 95 GenRemSet* remset, 96 PermanentGenerationSpec* perm_spec) 97 { 98 CompactingPermGenGen* g = 99 new CompactingPermGenGen(rs, shared_rs, initial_byte_size, -1, remset, 100 NULL, perm_spec); 101 if (g == NULL) 102 vm_exit_during_initialization("Could not allocate a CompactingPermGen"); 103 _gen = g; 104 105 g->initialize_performance_counters(); 106 107 _capacity_expansion_limit = g->capacity() + MaxPermHeapExpansion; 108 } 109 110 HeapWord* CompactingPermGen::mem_allocate(size_t size) { 111 return mem_allocate_in_gen(size, _gen); 112 } 113 114 void CompactingPermGen::compute_new_size() { 115 size_t desired_capacity = align_size_up(_gen->used(), MinPermHeapExpansion); 116 if (desired_capacity < PermSize) { 117 desired_capacity = PermSize; 118 } 119 if (_gen->capacity() > desired_capacity) { 120 _gen->shrink(_gen->capacity() - desired_capacity); 121 } 122 _capacity_expansion_limit = _gen->capacity() + MaxPermHeapExpansion; 123 }