|
1 /* |
|
2 * Copyright 2001-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
|
20 * CA 95054 USA or visit www.sun.com if you need additional information or |
|
21 * have any questions. |
|
22 * |
|
23 */ |
|
24 |
|
25 // Inline allocation implementations. |
|
26 |
|
27 void CollectedHeap::post_allocation_setup_common(KlassHandle klass, |
|
28 HeapWord* obj, |
|
29 size_t size) { |
|
30 post_allocation_setup_no_klass_install(klass, obj, size); |
|
31 post_allocation_install_obj_klass(klass, oop(obj), (int) size); |
|
32 } |
|
33 |
|
34 void CollectedHeap::post_allocation_setup_no_klass_install(KlassHandle klass, |
|
35 HeapWord* objPtr, |
|
36 size_t size) { |
|
37 |
|
38 oop obj = (oop)objPtr; |
|
39 |
|
40 assert(obj != NULL, "NULL object pointer"); |
|
41 if (UseBiasedLocking && (klass() != NULL)) { |
|
42 obj->set_mark(klass->prototype_header()); |
|
43 } else { |
|
44 // May be bootstrapping |
|
45 obj->set_mark(markOopDesc::prototype()); |
|
46 } |
|
47 |
|
48 // support low memory notifications (no-op if not enabled) |
|
49 LowMemoryDetector::detect_low_memory_for_collected_pools(); |
|
50 } |
|
51 |
|
52 void CollectedHeap::post_allocation_install_obj_klass(KlassHandle klass, |
|
53 oop obj, |
|
54 int size) { |
|
55 // These asserts are kind of complicated because of klassKlass |
|
56 // and the beginning of the world. |
|
57 assert(klass() != NULL || !Universe::is_fully_initialized(), "NULL klass"); |
|
58 assert(klass() == NULL || klass()->is_klass(), "not a klass"); |
|
59 assert(klass() == NULL || klass()->klass_part() != NULL, "not a klass"); |
|
60 assert(obj != NULL, "NULL object pointer"); |
|
61 obj->set_klass(klass()); |
|
62 assert(!Universe::is_fully_initialized() || obj->blueprint() != NULL, |
|
63 "missing blueprint"); |
|
64 |
|
65 // support for JVMTI VMObjectAlloc event (no-op if not enabled) |
|
66 JvmtiExport::vm_object_alloc_event_collector(obj); |
|
67 |
|
68 if (DTraceAllocProbes) { |
|
69 // support for Dtrace object alloc event (no-op most of the time) |
|
70 if (klass() != NULL && klass()->klass_part()->name() != NULL) { |
|
71 SharedRuntime::dtrace_object_alloc(obj); |
|
72 } |
|
73 } |
|
74 } |
|
75 |
|
76 void CollectedHeap::post_allocation_setup_obj(KlassHandle klass, |
|
77 HeapWord* obj, |
|
78 size_t size) { |
|
79 post_allocation_setup_common(klass, obj, size); |
|
80 assert(Universe::is_bootstrapping() || |
|
81 !((oop)obj)->blueprint()->oop_is_array(), "must not be an array"); |
|
82 } |
|
83 |
|
84 void CollectedHeap::post_allocation_setup_array(KlassHandle klass, |
|
85 HeapWord* obj, |
|
86 size_t size, |
|
87 int length) { |
|
88 // Set array length before posting jvmti object alloc event |
|
89 // in post_allocation_setup_common() |
|
90 assert(length >= 0, "length should be non-negative"); |
|
91 ((arrayOop)obj)->set_length(length); |
|
92 post_allocation_setup_common(klass, obj, size); |
|
93 assert(((oop)obj)->blueprint()->oop_is_array(), "must be an array"); |
|
94 } |
|
95 |
|
96 HeapWord* CollectedHeap::common_mem_allocate_noinit(size_t size, bool is_noref, TRAPS) { |
|
97 |
|
98 // Clear unhandled oops for memory allocation. Memory allocation might |
|
99 // not take out a lock if from tlab, so clear here. |
|
100 CHECK_UNHANDLED_OOPS_ONLY(THREAD->clear_unhandled_oops();) |
|
101 |
|
102 if (HAS_PENDING_EXCEPTION) { |
|
103 NOT_PRODUCT(guarantee(false, "Should not allocate with exception pending")); |
|
104 return NULL; // caller does a CHECK_0 too |
|
105 } |
|
106 |
|
107 // We may want to update this, is_noref objects might not be allocated in TLABs. |
|
108 HeapWord* result = NULL; |
|
109 if (UseTLAB) { |
|
110 result = CollectedHeap::allocate_from_tlab(THREAD, size); |
|
111 if (result != NULL) { |
|
112 assert(!HAS_PENDING_EXCEPTION, |
|
113 "Unexpected exception, will result in uninitialized storage"); |
|
114 return result; |
|
115 } |
|
116 } |
|
117 bool gc_overhead_limit_was_exceeded; |
|
118 result = Universe::heap()->mem_allocate(size, |
|
119 is_noref, |
|
120 false, |
|
121 &gc_overhead_limit_was_exceeded); |
|
122 if (result != NULL) { |
|
123 NOT_PRODUCT(Universe::heap()-> |
|
124 check_for_non_bad_heap_word_value(result, size)); |
|
125 assert(!HAS_PENDING_EXCEPTION, |
|
126 "Unexpected exception, will result in uninitialized storage"); |
|
127 return result; |
|
128 } |
|
129 |
|
130 |
|
131 if (!gc_overhead_limit_was_exceeded) { |
|
132 // -XX:+HeapDumpOnOutOfMemoryError and -XX:OnOutOfMemoryError support |
|
133 report_java_out_of_memory("Java heap space"); |
|
134 |
|
135 if (JvmtiExport::should_post_resource_exhausted()) { |
|
136 JvmtiExport::post_resource_exhausted( |
|
137 JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR | JVMTI_RESOURCE_EXHAUSTED_JAVA_HEAP, |
|
138 "Java heap space"); |
|
139 } |
|
140 |
|
141 THROW_OOP_0(Universe::out_of_memory_error_java_heap()); |
|
142 } else { |
|
143 // -XX:+HeapDumpOnOutOfMemoryError and -XX:OnOutOfMemoryError support |
|
144 report_java_out_of_memory("GC overhead limit exceeded"); |
|
145 |
|
146 if (JvmtiExport::should_post_resource_exhausted()) { |
|
147 JvmtiExport::post_resource_exhausted( |
|
148 JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR | JVMTI_RESOURCE_EXHAUSTED_JAVA_HEAP, |
|
149 "GC overhead limit exceeded"); |
|
150 } |
|
151 |
|
152 THROW_OOP_0(Universe::out_of_memory_error_gc_overhead_limit()); |
|
153 } |
|
154 } |
|
155 |
|
156 HeapWord* CollectedHeap::common_mem_allocate_init(size_t size, bool is_noref, TRAPS) { |
|
157 HeapWord* obj = common_mem_allocate_noinit(size, is_noref, CHECK_NULL); |
|
158 init_obj(obj, size); |
|
159 return obj; |
|
160 } |
|
161 |
|
162 // Need to investigate, do we really want to throw OOM exception here? |
|
163 HeapWord* CollectedHeap::common_permanent_mem_allocate_noinit(size_t size, TRAPS) { |
|
164 if (HAS_PENDING_EXCEPTION) { |
|
165 NOT_PRODUCT(guarantee(false, "Should not allocate with exception pending")); |
|
166 return NULL; // caller does a CHECK_NULL too |
|
167 } |
|
168 |
|
169 #ifdef ASSERT |
|
170 if (CIFireOOMAt > 0 && THREAD->is_Compiler_thread() && |
|
171 ++_fire_out_of_memory_count >= CIFireOOMAt) { |
|
172 // For testing of OOM handling in the CI throw an OOM and see how |
|
173 // it does. Historically improper handling of these has resulted |
|
174 // in crashes which we really don't want to have in the CI. |
|
175 THROW_OOP_0(Universe::out_of_memory_error_perm_gen()); |
|
176 } |
|
177 #endif |
|
178 |
|
179 HeapWord* result = Universe::heap()->permanent_mem_allocate(size); |
|
180 if (result != NULL) { |
|
181 NOT_PRODUCT(Universe::heap()-> |
|
182 check_for_non_bad_heap_word_value(result, size)); |
|
183 assert(!HAS_PENDING_EXCEPTION, |
|
184 "Unexpected exception, will result in uninitialized storage"); |
|
185 return result; |
|
186 } |
|
187 // -XX:+HeapDumpOnOutOfMemoryError and -XX:OnOutOfMemoryError support |
|
188 report_java_out_of_memory("PermGen space"); |
|
189 |
|
190 if (JvmtiExport::should_post_resource_exhausted()) { |
|
191 JvmtiExport::post_resource_exhausted( |
|
192 JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR, |
|
193 "PermGen space"); |
|
194 } |
|
195 |
|
196 THROW_OOP_0(Universe::out_of_memory_error_perm_gen()); |
|
197 } |
|
198 |
|
199 HeapWord* CollectedHeap::common_permanent_mem_allocate_init(size_t size, TRAPS) { |
|
200 HeapWord* obj = common_permanent_mem_allocate_noinit(size, CHECK_NULL); |
|
201 init_obj(obj, size); |
|
202 return obj; |
|
203 } |
|
204 |
|
205 HeapWord* CollectedHeap::allocate_from_tlab(Thread* thread, size_t size) { |
|
206 assert(UseTLAB, "should use UseTLAB"); |
|
207 |
|
208 HeapWord* obj = thread->tlab().allocate(size); |
|
209 if (obj != NULL) { |
|
210 return obj; |
|
211 } |
|
212 // Otherwise... |
|
213 return allocate_from_tlab_slow(thread, size); |
|
214 } |
|
215 |
|
216 void CollectedHeap::init_obj(HeapWord* obj, size_t size) { |
|
217 assert(obj != NULL, "cannot initialize NULL object"); |
|
218 const size_t hs = oopDesc::header_size(); |
|
219 assert(size >= hs, "unexpected object size"); |
|
220 Copy::fill_to_aligned_words(obj + hs, size - hs); |
|
221 } |
|
222 |
|
223 oop CollectedHeap::obj_allocate(KlassHandle klass, int size, TRAPS) { |
|
224 debug_only(check_for_valid_allocation_state()); |
|
225 assert(!Universe::heap()->is_gc_active(), "Allocation during gc not allowed"); |
|
226 assert(size >= 0, "int won't convert to size_t"); |
|
227 HeapWord* obj = common_mem_allocate_init(size, false, CHECK_NULL); |
|
228 post_allocation_setup_obj(klass, obj, size); |
|
229 NOT_PRODUCT(Universe::heap()->check_for_bad_heap_word_value(obj, size)); |
|
230 return (oop)obj; |
|
231 } |
|
232 |
|
233 oop CollectedHeap::array_allocate(KlassHandle klass, |
|
234 int size, |
|
235 int length, |
|
236 TRAPS) { |
|
237 debug_only(check_for_valid_allocation_state()); |
|
238 assert(!Universe::heap()->is_gc_active(), "Allocation during gc not allowed"); |
|
239 assert(size >= 0, "int won't convert to size_t"); |
|
240 HeapWord* obj = common_mem_allocate_init(size, false, CHECK_NULL); |
|
241 post_allocation_setup_array(klass, obj, size, length); |
|
242 NOT_PRODUCT(Universe::heap()->check_for_bad_heap_word_value(obj, size)); |
|
243 return (oop)obj; |
|
244 } |
|
245 |
|
246 oop CollectedHeap::large_typearray_allocate(KlassHandle klass, |
|
247 int size, |
|
248 int length, |
|
249 TRAPS) { |
|
250 debug_only(check_for_valid_allocation_state()); |
|
251 assert(!Universe::heap()->is_gc_active(), "Allocation during gc not allowed"); |
|
252 assert(size >= 0, "int won't convert to size_t"); |
|
253 HeapWord* obj = common_mem_allocate_init(size, true, CHECK_NULL); |
|
254 post_allocation_setup_array(klass, obj, size, length); |
|
255 NOT_PRODUCT(Universe::heap()->check_for_bad_heap_word_value(obj, size)); |
|
256 return (oop)obj; |
|
257 } |
|
258 |
|
259 oop CollectedHeap::permanent_obj_allocate(KlassHandle klass, int size, TRAPS) { |
|
260 oop obj = permanent_obj_allocate_no_klass_install(klass, size, CHECK_NULL); |
|
261 post_allocation_install_obj_klass(klass, obj, size); |
|
262 NOT_PRODUCT(Universe::heap()->check_for_bad_heap_word_value((HeapWord*) obj, |
|
263 size)); |
|
264 return obj; |
|
265 } |
|
266 |
|
267 oop CollectedHeap::permanent_obj_allocate_no_klass_install(KlassHandle klass, |
|
268 int size, |
|
269 TRAPS) { |
|
270 debug_only(check_for_valid_allocation_state()); |
|
271 assert(!Universe::heap()->is_gc_active(), "Allocation during gc not allowed"); |
|
272 assert(size >= 0, "int won't convert to size_t"); |
|
273 HeapWord* obj = common_permanent_mem_allocate_init(size, CHECK_NULL); |
|
274 post_allocation_setup_no_klass_install(klass, obj, size); |
|
275 NOT_PRODUCT(Universe::heap()->check_for_bad_heap_word_value(obj, size)); |
|
276 return (oop)obj; |
|
277 } |
|
278 |
|
279 oop CollectedHeap::permanent_array_allocate(KlassHandle klass, |
|
280 int size, |
|
281 int length, |
|
282 TRAPS) { |
|
283 debug_only(check_for_valid_allocation_state()); |
|
284 assert(!Universe::heap()->is_gc_active(), "Allocation during gc not allowed"); |
|
285 assert(size >= 0, "int won't convert to size_t"); |
|
286 HeapWord* obj = common_permanent_mem_allocate_init(size, CHECK_NULL); |
|
287 post_allocation_setup_array(klass, obj, size, length); |
|
288 NOT_PRODUCT(Universe::heap()->check_for_bad_heap_word_value(obj, size)); |
|
289 return (oop)obj; |
|
290 } |
|
291 |
|
292 // Returns "TRUE" if "p" is a method oop in the |
|
293 // current heap with high probability. NOTE: The main |
|
294 // current consumers of this interface are Forte:: |
|
295 // and ThreadProfiler::. In these cases, the |
|
296 // interpreter frame from which "p" came, may be |
|
297 // under construction when sampled asynchronously, so |
|
298 // the clients want to check that it represents a |
|
299 // valid method before using it. Nonetheless since |
|
300 // the clients do not typically lock out GC, the |
|
301 // predicate is_valid_method() is not stable, so |
|
302 // it is possible that by the time "p" is used, it |
|
303 // is no longer valid. |
|
304 inline bool CollectedHeap::is_valid_method(oop p) const { |
|
305 return |
|
306 p != NULL && |
|
307 |
|
308 // Check whether it is aligned at a HeapWord boundary. |
|
309 Space::is_aligned(p) && |
|
310 |
|
311 // Check whether "method" is in the allocated part of the |
|
312 // permanent generation -- this needs to be checked before |
|
313 // p->klass() below to avoid a SEGV (but see below |
|
314 // for a potential window of vulnerability). |
|
315 is_permanent((void*)p) && |
|
316 |
|
317 // See if GC is active; however, there is still an |
|
318 // apparently unavoidable window after this call |
|
319 // and before the client of this interface uses "p". |
|
320 // If the client chooses not to lock out GC, then |
|
321 // it's a risk the client must accept. |
|
322 !is_gc_active() && |
|
323 |
|
324 // Check that p is a methodOop. |
|
325 p->klass() == Universe::methodKlassObj(); |
|
326 } |
|
327 |
|
328 |
|
329 #ifndef PRODUCT |
|
330 |
|
331 inline bool |
|
332 CollectedHeap::promotion_should_fail(volatile size_t* count) { |
|
333 // Access to count is not atomic; the value does not have to be exact. |
|
334 if (PromotionFailureALot) { |
|
335 const size_t gc_num = total_collections(); |
|
336 const size_t elapsed_gcs = gc_num - _promotion_failure_alot_gc_number; |
|
337 if (elapsed_gcs >= PromotionFailureALotInterval) { |
|
338 // Test for unsigned arithmetic wrap-around. |
|
339 if (++*count >= PromotionFailureALotCount) { |
|
340 *count = 0; |
|
341 return true; |
|
342 } |
|
343 } |
|
344 } |
|
345 return false; |
|
346 } |
|
347 |
|
348 inline bool CollectedHeap::promotion_should_fail() { |
|
349 return promotion_should_fail(&_promotion_failure_alot_count); |
|
350 } |
|
351 |
|
352 inline void CollectedHeap::reset_promotion_should_fail(volatile size_t* count) { |
|
353 if (PromotionFailureALot) { |
|
354 _promotion_failure_alot_gc_number = total_collections(); |
|
355 *count = 0; |
|
356 } |
|
357 } |
|
358 |
|
359 inline void CollectedHeap::reset_promotion_should_fail() { |
|
360 reset_promotion_should_fail(&_promotion_failure_alot_count); |
|
361 } |
|
362 #endif // #ifndef PRODUCT |