mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 07:14:30 +02:00
187 lines
7.1 KiB
C++
187 lines
7.1 KiB
C++
/*
|
|
* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
* Copyright (c) 2020, 2021, Red Hat, Inc. and/or its affiliates.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
* accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU General Public License version
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*
|
|
*/
|
|
|
|
#ifndef SHARE_VM_GC_SHENANDOAH_SHENANDOAHREFERENCEPROCESSOR_HPP
|
|
#define SHARE_VM_GC_SHENANDOAH_SHENANDOAHREFERENCEPROCESSOR_HPP
|
|
|
|
#include "gc/shared/referenceDiscoverer.hpp"
|
|
#include "gc/shenandoah/shenandoahPhaseTimings.hpp"
|
|
#include "memory/allocation.hpp"
|
|
|
|
class ShenandoahMarkRefsSuperClosure;
|
|
class WorkGang;
|
|
|
|
static const size_t reference_type_count = REF_PHANTOM + 1;
|
|
typedef size_t Counters[reference_type_count];
|
|
|
|
/*
|
|
* Shenandoah concurrent reference processing
|
|
*
|
|
* Concurrent reference processing is made up of two main phases:
|
|
* 1. Concurrent reference marking: Discover all j.l.r.Reference objects and determine reachability of all live objects.
|
|
* 2. Concurrent reference processing: For all discoved j.l.r.References, determine whether to keep them alive or clean
|
|
* them. Also, clean and enqueue relevant references concurrently.
|
|
*
|
|
* Concurrent reference marking:
|
|
* The goal here is to establish the kind of reachability for all objects on the heap. We distinguish two kinds of
|
|
* reachability:
|
|
* - An object is 'strongly reachable' if it can be found by searching transitively from GC roots.
|
|
* - An object is 'finalizably reachable' if it is not strongly reachable, but can be found by searching
|
|
* from the referents of FinalReferences.
|
|
*
|
|
* These reachabilities are implemented in shenandoahMarkBitMap.*
|
|
* Conceptually, marking starts with a strong wavefront at the GC roots. Whenever a Reference object is encountered,
|
|
* it may be discovered by the ShenandoahReferenceProcessor. If it is discovered, it
|
|
* gets added to the discovered list, and that wavefront stops there, except when it's a FinalReference, in which
|
|
* case the wavefront switches to finalizable marking and marks through the referent. When a Reference is not
|
|
* discovered, e.g. if it's a SoftReference that is not eligible for discovery, then marking continues as if the
|
|
* Reference was a regular object. Whenever a strong wavefront encounters an object that is already marked
|
|
* finalizable, then the object's reachability is upgraded to strong.
|
|
*
|
|
* Concurrent reference processing:
|
|
* This happens after the concurrent marking phase and the final marking pause, when reachability for all objects
|
|
* has been established.
|
|
* The discovered list is scanned and for each reference is decided what to do:
|
|
* - If the referent is reachable (finalizable for PhantomReference, strong for all others), then the Reference
|
|
* is dropped from the discovered list and otherwise ignored
|
|
* - Otherwise its referent becomes cleared and the Reference added to the pending list, from which it will later
|
|
* be processed (e.g. enqueued in its ReferenceQueue) by the Java ReferenceHandler thread.
|
|
*
|
|
* In order to prevent resurrection by Java threads calling Reference.get() concurrently while we are clearing
|
|
* referents, we employ a special barrier, the native LRB, which returns NULL when the referent is unreachable.
|
|
*/
|
|
|
|
class ShenandoahRefProcThreadLocal : public CHeapObj<mtGC> {
|
|
private:
|
|
void* _discovered_list;
|
|
ShenandoahMarkRefsSuperClosure* _mark_closure;
|
|
Counters _encountered_count;
|
|
Counters _discovered_count;
|
|
Counters _enqueued_count;
|
|
|
|
public:
|
|
ShenandoahRefProcThreadLocal();
|
|
|
|
ShenandoahRefProcThreadLocal(const ShenandoahRefProcThreadLocal&) = delete; // non construction-copyable
|
|
ShenandoahRefProcThreadLocal& operator=(const ShenandoahRefProcThreadLocal&) = delete; // non copyable
|
|
|
|
void reset();
|
|
|
|
ShenandoahMarkRefsSuperClosure* mark_closure() const {
|
|
return _mark_closure;
|
|
}
|
|
|
|
void set_mark_closure(ShenandoahMarkRefsSuperClosure* mark_closure) {
|
|
_mark_closure = mark_closure;
|
|
}
|
|
|
|
template<typename T>
|
|
T* discovered_list_addr();
|
|
template<typename T>
|
|
oop discovered_list_head() const;
|
|
template<typename T>
|
|
void set_discovered_list_head(oop head);
|
|
|
|
size_t encountered(ReferenceType type) const {
|
|
return _encountered_count[type];
|
|
}
|
|
size_t discovered(ReferenceType type) const {
|
|
return _discovered_count[type];
|
|
}
|
|
size_t enqueued(ReferenceType type) const {
|
|
return _enqueued_count[type];
|
|
}
|
|
|
|
void inc_encountered(ReferenceType type) {
|
|
_encountered_count[type]++;
|
|
}
|
|
void inc_discovered(ReferenceType type) {
|
|
_discovered_count[type]++;
|
|
}
|
|
void inc_enqueued(ReferenceType type) {
|
|
_enqueued_count[type]++;
|
|
}
|
|
};
|
|
|
|
class ShenandoahReferenceProcessor : public ReferenceDiscoverer {
|
|
private:
|
|
ReferencePolicy* _soft_reference_policy;
|
|
|
|
ShenandoahRefProcThreadLocal* _ref_proc_thread_locals;
|
|
|
|
oop _pending_list;
|
|
void* _pending_list_tail; // T*
|
|
|
|
volatile uint _iterate_discovered_list_id;
|
|
|
|
template <typename T>
|
|
bool is_inactive(oop reference, oop referent, ReferenceType type) const;
|
|
bool is_strongly_live(oop referent) const;
|
|
bool is_softly_live(oop reference, ReferenceType type) const;
|
|
|
|
template <typename T>
|
|
bool should_discover(oop reference, ReferenceType type) const;
|
|
template <typename T>
|
|
bool should_drop(oop reference, ReferenceType type) const;
|
|
|
|
template <typename T>
|
|
void make_inactive(oop reference, ReferenceType type) const;
|
|
|
|
template <typename T>
|
|
bool discover(oop reference, ReferenceType type, uint worker_id);
|
|
|
|
template <typename T>
|
|
oop drop(oop reference, ReferenceType type);
|
|
template <typename T>
|
|
T* keep(oop reference, ReferenceType type, uint worker_id);
|
|
|
|
template <typename T>
|
|
void process_references(ShenandoahRefProcThreadLocal& refproc_data, uint worker_id);
|
|
void enqueue_references_locked();
|
|
void enqueue_references(bool concurrent);
|
|
|
|
void collect_statistics();
|
|
|
|
template<typename T>
|
|
void clean_discovered_list(T* list);
|
|
|
|
public:
|
|
ShenandoahReferenceProcessor(uint max_workers);
|
|
|
|
void reset_thread_locals();
|
|
void set_mark_closure(uint worker_id, ShenandoahMarkRefsSuperClosure* mark_closure);
|
|
|
|
void set_soft_reference_policy(bool clear);
|
|
|
|
bool discover_reference(oop obj, ReferenceType type) override;
|
|
|
|
void process_references(ShenandoahPhaseTimings::Phase phase, WorkGang* workers, bool concurrent);
|
|
|
|
void work();
|
|
|
|
void abandon_partial_discovery();
|
|
};
|
|
|
|
#endif // SHARE_VM_GC_SHENANDOAH_SHENANDOAHREFERENCEPROCESSOR_HPP
|