Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp
38921 views
/*1* Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#ifndef SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PSPROMOTIONMANAGER_INLINE_HPP25#define SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PSPROMOTIONMANAGER_INLINE_HPP2627#include "gc_implementation/parallelScavenge/psOldGen.hpp"28#include "gc_implementation/parallelScavenge/psPromotionManager.hpp"29#include "gc_implementation/parallelScavenge/psPromotionLAB.inline.hpp"30#include "gc_implementation/parallelScavenge/psScavenge.hpp"31#include "oops/oop.psgc.inline.hpp"3233inline PSPromotionManager* PSPromotionManager::manager_array(int index) {34assert(_manager_array != NULL, "access of NULL manager_array");35assert(index >= 0 && index <= (int)ParallelGCThreads, "out of range manager_array access");36return &_manager_array[index];37}3839template <class T>40inline void PSPromotionManager::claim_or_forward_internal_depth(T* p) {41if (p != NULL) { // XXX: error if p != NULL here42oop o = oopDesc::load_decode_heap_oop_not_null(p);43if (o->is_forwarded()) {44o = o->forwardee();45// Card mark46if (PSScavenge::is_obj_in_young(o)) {47PSScavenge::card_table()->inline_write_ref_field_gc(p, o);48}49oopDesc::encode_store_heap_oop_not_null(p, o);50} else {51push_depth(p);52}53}54}5556template <class T>57inline void PSPromotionManager::claim_or_forward_depth(T* p) {58assert(PSScavenge::should_scavenge(p, true), "revisiting object?");59assert(Universe::heap()->kind() == CollectedHeap::ParallelScavengeHeap,60"Sanity");61assert(Universe::heap()->is_in(p), "pointer outside heap");6263claim_or_forward_internal_depth(p);64}6566inline void PSPromotionManager::promotion_trace_event(oop new_obj, oop old_obj,67size_t obj_size,68uint age, bool tenured,69const PSPromotionLAB* lab) {70// Skip if memory allocation failed71if (new_obj != NULL) {72const ParallelScavengeTracer* gc_tracer = PSScavenge::gc_tracer();7374if (lab != NULL) {75// Promotion of object through newly allocated PLAB76if (gc_tracer->should_report_promotion_in_new_plab_event()) {77size_t obj_bytes = obj_size * HeapWordSize;78size_t lab_size = lab->capacity();79gc_tracer->report_promotion_in_new_plab_event(old_obj->klass(), obj_bytes,80age, tenured, lab_size);81}82} else {83// Promotion of object directly to heap84if (gc_tracer->should_report_promotion_outside_plab_event()) {85size_t obj_bytes = obj_size * HeapWordSize;86gc_tracer->report_promotion_outside_plab_event(old_obj->klass(), obj_bytes,87age, tenured);88}89}90}91}9293//94// This method is pretty bulky. It would be nice to split it up95// into smaller submethods, but we need to be careful not to hurt96// performance.97//98template<bool promote_immediately>99oop PSPromotionManager::copy_to_survivor_space(oop o) {100assert(PSScavenge::should_scavenge(&o), "Sanity");101102oop new_obj = NULL;103104// NOTE! We must be very careful with any methods that access the mark105// in o. There may be multiple threads racing on it, and it may be forwarded106// at any time. Do not use oop methods for accessing the mark!107markOop test_mark = o->mark();108109// The same test as "o->is_forwarded()"110if (!test_mark->is_marked()) {111bool new_obj_is_tenured = false;112size_t new_obj_size = o->size();113114// Find the objects age, MT safe.115uint age = (test_mark->has_displaced_mark_helper() /* o->has_displaced_mark() */) ?116test_mark->displaced_mark_helper()->age() : test_mark->age();117118if (!promote_immediately) {119// Try allocating obj in to-space (unless too old)120if (age < PSScavenge::tenuring_threshold()) {121new_obj = (oop) _young_lab.allocate(new_obj_size);122if (new_obj == NULL && !_young_gen_is_full) {123// Do we allocate directly, or flush and refill?124if (new_obj_size > (YoungPLABSize / 2)) {125// Allocate this object directly126new_obj = (oop)young_space()->cas_allocate(new_obj_size);127promotion_trace_event(new_obj, o, new_obj_size, age, false, NULL);128} else {129// Flush and fill130_young_lab.flush();131132HeapWord* lab_base = young_space()->cas_allocate(YoungPLABSize);133if (lab_base != NULL) {134_young_lab.initialize(MemRegion(lab_base, YoungPLABSize));135// Try the young lab allocation again.136new_obj = (oop) _young_lab.allocate(new_obj_size);137promotion_trace_event(new_obj, o, new_obj_size, age, false, &_young_lab);138} else {139_young_gen_is_full = true;140}141}142}143}144}145146// Otherwise try allocating obj tenured147if (new_obj == NULL) {148#ifndef PRODUCT149if (Universe::heap()->promotion_should_fail()) {150return oop_promotion_failed(o, test_mark);151}152#endif // #ifndef PRODUCT153154new_obj = (oop) _old_lab.allocate(new_obj_size);155new_obj_is_tenured = true;156157if (new_obj == NULL) {158if (!_old_gen_is_full) {159// Do we allocate directly, or flush and refill?160if (new_obj_size > (OldPLABSize / 2)) {161// Allocate this object directly162new_obj = (oop)old_gen()->cas_allocate(new_obj_size);163promotion_trace_event(new_obj, o, new_obj_size, age, true, NULL);164} else {165// Flush and fill166_old_lab.flush();167168HeapWord* lab_base = old_gen()->cas_allocate(OldPLABSize);169if(lab_base != NULL) {170#ifdef ASSERT171// Delay the initialization of the promotion lab (plab).172// This exposes uninitialized plabs to card table processing.173if (GCWorkerDelayMillis > 0) {174os::sleep(Thread::current(), GCWorkerDelayMillis, false);175}176#endif177_old_lab.initialize(MemRegion(lab_base, OldPLABSize));178// Try the old lab allocation again.179new_obj = (oop) _old_lab.allocate(new_obj_size);180promotion_trace_event(new_obj, o, new_obj_size, age, true, &_old_lab);181}182}183}184185// This is the promotion failed test, and code handling.186// The code belongs here for two reasons. It is slightly187// different than the code below, and cannot share the188// CAS testing code. Keeping the code here also minimizes189// the impact on the common case fast path code.190191if (new_obj == NULL) {192_old_gen_is_full = true;193return oop_promotion_failed(o, test_mark);194}195}196}197198assert(new_obj != NULL, "allocation should have succeeded");199200// Copy obj201Copy::aligned_disjoint_words((HeapWord*)o, (HeapWord*)new_obj, new_obj_size);202203// Now we have to CAS in the header.204if (o->cas_forward_to(new_obj, test_mark)) {205// We won any races, we "own" this object.206assert(new_obj == o->forwardee(), "Sanity");207208// Increment age if obj still in new generation. Now that209// we're dealing with a markOop that cannot change, it is210// okay to use the non mt safe oop methods.211if (!new_obj_is_tenured) {212new_obj->incr_age();213assert(young_space()->contains(new_obj), "Attempt to push non-promoted obj");214}215216// Do the size comparison first with new_obj_size, which we217// already have. Hopefully, only a few objects are larger than218// _min_array_size_for_chunking, and most of them will be arrays.219// So, the is->objArray() test would be very infrequent.220if (new_obj_size > _min_array_size_for_chunking &&221new_obj->is_objArray() &&222PSChunkLargeArrays) {223// we'll chunk it224oop* const masked_o = mask_chunked_array_oop(o);225push_depth(masked_o);226TASKQUEUE_STATS_ONLY(++_arrays_chunked; ++_masked_pushes);227} else {228// we'll just push its contents229new_obj->push_contents(this);230}231} else {232// We lost, someone else "owns" this object233guarantee(o->is_forwarded(), "Object must be forwarded if the cas failed.");234235// Try to deallocate the space. If it was directly allocated we cannot236// deallocate it, so we have to test. If the deallocation fails,237// overwrite with a filler object.238if (new_obj_is_tenured) {239if (!_old_lab.unallocate_object((HeapWord*) new_obj, new_obj_size)) {240CollectedHeap::fill_with_object((HeapWord*) new_obj, new_obj_size);241}242} else if (!_young_lab.unallocate_object((HeapWord*) new_obj, new_obj_size)) {243CollectedHeap::fill_with_object((HeapWord*) new_obj, new_obj_size);244}245246// don't update this before the unallocation!247new_obj = o->forwardee();248}249} else {250assert(o->is_forwarded(), "Sanity");251new_obj = o->forwardee();252}253254#ifndef PRODUCT255// This code must come after the CAS test, or it will print incorrect256// information.257if (TraceScavenge) {258gclog_or_tty->print_cr("{%s %s " PTR_FORMAT " -> " PTR_FORMAT " (%d)}",259PSScavenge::should_scavenge(&new_obj) ? "copying" : "tenuring",260new_obj->klass()->internal_name(), p2i((void *)o), p2i((void *)new_obj), new_obj->size());261}262#endif263264return new_obj;265}266267268inline void PSPromotionManager::process_popped_location_depth(StarTask p) {269if (is_oop_masked(p)) {270assert(PSChunkLargeArrays, "invariant");271oop const old = unmask_chunked_array_oop(p);272process_array_chunk(old);273} else {274if (p.is_narrow()) {275assert(UseCompressedOops, "Error");276PSScavenge::copy_and_push_safe_barrier<narrowOop, /*promote_immediately=*/false>(this, p);277} else {278PSScavenge::copy_and_push_safe_barrier<oop, /*promote_immediately=*/false>(this, p);279}280}281}282283#if TASKQUEUE_STATS284void PSPromotionManager::record_steal(StarTask& p) {285if (is_oop_masked(p)) {286++_masked_steals;287}288}289#endif // TASKQUEUE_STATS290291#endif // SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PSPROMOTIONMANAGER_INLINE_HPP292293294