1 /*
2 * Copyright (c) 2014, 2016, 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 *
181 dest->set_old();
182 return obj_ptr;
183 } else {
184 assert(dest->is_old(), err_msg("Unexpected dest: " CSETSTATE_FORMAT, dest->value()));
185 // no other space to try.
186 return NULL;
187 }
188 }
189
190 InCSetState G1ParScanThreadState::next_state(InCSetState const state, markOop const m, uint& age) {
191 if (state.is_young()) {
192 age = !m->has_displaced_mark_helper() ? m->age()
193 : m->displaced_mark_helper()->age();
194 if (age < _tenuring_threshold) {
195 return state;
196 }
197 }
198 return dest(state);
199 }
200
201 oop G1ParScanThreadState::copy_to_survivor_space(InCSetState const state,
202 oop const old,
203 markOop const old_mark) {
204 const size_t word_sz = old->size();
205 HeapRegion* const from_region = _g1h->heap_region_containing_raw(old);
206 // +1 to make the -1 indexes valid...
207 const int young_index = from_region->young_index_in_cset()+1;
208 assert( (from_region->is_young() && young_index > 0) ||
209 (!from_region->is_young() && young_index == 0), "invariant" );
210 const AllocationContext_t context = from_region->allocation_context();
211
212 uint age = 0;
213 InCSetState dest_state = next_state(state, old_mark, age);
214 HeapWord* obj_ptr = _g1_par_allocator->plab_allocate(dest_state, word_sz, context);
215
216 // PLAB allocations should succeed most of the time, so we'll
217 // normally check against NULL once and that's it.
218 if (obj_ptr == NULL) {
219 obj_ptr = _g1_par_allocator->allocate_direct_or_new_plab(dest_state, word_sz, context);
220 if (obj_ptr == NULL) {
221 obj_ptr = allocate_in_next_plab(state, &dest_state, word_sz, context);
222 if (obj_ptr == NULL) {
223 // This will either forward-to-self, or detect that someone else has
224 // installed a forwarding pointer.
225 return _g1h->handle_evacuation_failure_par(this, old);
226 }
227 }
228 }
229
230 assert(obj_ptr != NULL, "when we get here, allocation should have succeeded");
231 #ifndef PRODUCT
232 // Should this evacuation fail?
233 if (_g1h->evacuation_should_fail()) {
234 // Doing this after all the allocation attempts also tests the
235 // undo_allocation() method too.
236 _g1_par_allocator->undo_allocation(dest_state, obj_ptr, word_sz, context);
237 return _g1h->handle_evacuation_failure_par(this, old);
238 }
239 #endif // !PRODUCT
240
241 // We're going to allocate linearly, so might as well prefetch ahead.
242 Prefetch::write(obj_ptr, PrefetchCopyIntervalInBytes);
243
244 const oop obj = oop(obj_ptr);
245 const oop forward_ptr = old->forward_to_atomic(obj);
246 if (forward_ptr == NULL) {
247 Copy::aligned_disjoint_words((HeapWord*) old, obj_ptr, word_sz);
|
1 /*
2 * Copyright (c) 2014, 2019, 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 *
181 dest->set_old();
182 return obj_ptr;
183 } else {
184 assert(dest->is_old(), err_msg("Unexpected dest: " CSETSTATE_FORMAT, dest->value()));
185 // no other space to try.
186 return NULL;
187 }
188 }
189
190 InCSetState G1ParScanThreadState::next_state(InCSetState const state, markOop const m, uint& age) {
191 if (state.is_young()) {
192 age = !m->has_displaced_mark_helper() ? m->age()
193 : m->displaced_mark_helper()->age();
194 if (age < _tenuring_threshold) {
195 return state;
196 }
197 }
198 return dest(state);
199 }
200
201 void G1ParScanThreadState::report_promotion_event(InCSetState const dest_state,
202 oop const old, size_t word_sz, uint age,
203 HeapWord * const obj_ptr, AllocationContext_t context) const {
204 assert(EnableJFR, "sanity check");
205 ParGCAllocBuffer* alloc_buf = _g1_par_allocator->alloc_buffer(dest_state, context);
206 if (alloc_buf->contains(obj_ptr)) {
207 _g1h->_gc_tracer_stw->report_promotion_in_new_plab_event(old->klass(), word_sz, age,
208 dest_state.value() == InCSetState::Old,
209 alloc_buf->word_sz());
210 } else {
211 _g1h->_gc_tracer_stw->report_promotion_outside_plab_event(old->klass(), word_sz, age,
212 dest_state.value() == InCSetState::Old);
213 }
214 }
215
216 oop G1ParScanThreadState::copy_to_survivor_space(InCSetState const state,
217 oop const old,
218 markOop const old_mark) {
219 const size_t word_sz = old->size();
220 HeapRegion* const from_region = _g1h->heap_region_containing_raw(old);
221 // +1 to make the -1 indexes valid...
222 const int young_index = from_region->young_index_in_cset()+1;
223 assert( (from_region->is_young() && young_index > 0) ||
224 (!from_region->is_young() && young_index == 0), "invariant" );
225 const AllocationContext_t context = from_region->allocation_context();
226
227 uint age = 0;
228 InCSetState dest_state = next_state(state, old_mark, age);
229 HeapWord* obj_ptr = _g1_par_allocator->plab_allocate(dest_state, word_sz, context);
230
231 // PLAB allocations should succeed most of the time, so we'll
232 // normally check against NULL once and that's it.
233 if (obj_ptr == NULL) {
234 obj_ptr = _g1_par_allocator->allocate_direct_or_new_plab(dest_state, word_sz, context);
235 if (obj_ptr == NULL) {
236 obj_ptr = allocate_in_next_plab(state, &dest_state, word_sz, context);
237 if (obj_ptr == NULL) {
238 // This will either forward-to-self, or detect that someone else has
239 // installed a forwarding pointer.
240 return _g1h->handle_evacuation_failure_par(this, old);
241 }
242 }
243 if (EnableJFR && _g1h->_gc_tracer_stw->should_report_promotion_events()) {
244 // The events are checked individually as part of the actual commit
245 report_promotion_event(dest_state, old, word_sz, age, obj_ptr, context);
246 }
247 }
248
249 assert(obj_ptr != NULL, "when we get here, allocation should have succeeded");
250 #ifndef PRODUCT
251 // Should this evacuation fail?
252 if (_g1h->evacuation_should_fail()) {
253 // Doing this after all the allocation attempts also tests the
254 // undo_allocation() method too.
255 _g1_par_allocator->undo_allocation(dest_state, obj_ptr, word_sz, context);
256 return _g1h->handle_evacuation_failure_par(this, old);
257 }
258 #endif // !PRODUCT
259
260 // We're going to allocate linearly, so might as well prefetch ahead.
261 Prefetch::write(obj_ptr, PrefetchCopyIntervalInBytes);
262
263 const oop obj = oop(obj_ptr);
264 const oop forward_ptr = old->forward_to_atomic(obj);
265 if (forward_ptr == NULL) {
266 Copy::aligned_disjoint_words((HeapWord*) old, obj_ptr, word_sz);
|