blob: 34c79ac0a185531937ac08133922b8b4378432bb [file] [edit]
/*
* Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
* 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_GC_SERIAL_SERIALHEAP_HPP
#define SHARE_GC_SERIAL_SERIALHEAP_HPP
#include "gc/serial/defNewGeneration.hpp"
#include "gc/serial/generation.hpp"
#include "gc/serial/tenuredGeneration.hpp"
#include "gc/shared/collectedHeap.hpp"
#include "gc/shared/oopStorageParState.hpp"
#include "gc/shared/preGCValues.hpp"
#include "gc/shared/softRefPolicy.hpp"
#include "utilities/growableArray.hpp"
class CardTableRS;
class GCPolicyCounters;
class GCMemoryManager;
class MemoryPool;
class OopIterateClosure;
class TenuredGeneration;
// SerialHeap is the implementation of CollectedHeap for Serial GC.
//
// The heap is reserved up-front in a single contiguous block, split into two
// parts, the young and old generation. The young generation resides at lower
// addresses, the old generation at higher addresses. The boundary address
// between the generations is fixed. Within a generation, committed memory
// grows towards higher addresses.
//
//
// low high
//
// +-- generation boundary (fixed after startup)
// |
// |<- young gen (reserved MaxNewSize) ->|<- old gen (reserved MaxOldSize) ->|
// +-----------------+--------+--------+--------+---------------+-------------------+
// | eden | from | to | | old | |
// | | (to) | (from) | | | |
// +-----------------+--------+--------+--------+---------------+-------------------+
// |<- committed ->| |<- committed ->|
//
class SerialHeap : public CollectedHeap {
friend class Generation;
friend class DefNewGeneration;
friend class TenuredGeneration;
friend class SerialFullGC;
friend class VM_GC_HeapInspection;
friend class VM_HeapDumper;
friend class HeapInspection;
friend class GCCauseSetter;
friend class VMStructs;
friend class VM_PopulateDumpSharedSpace;
private:
DefNewGeneration* _young_gen;
TenuredGeneration* _old_gen;
HeapWord* _young_gen_saved_top;
HeapWord* _old_gen_saved_top;
// The singleton CardTable Remembered Set.
CardTableRS* _rem_set;
GCPolicyCounters* _gc_policy_counters;
bool do_young_collection(bool clear_soft_refs);
// Reserve aligned space for the heap as needed by the contained generations.
ReservedHeapSpace allocate(size_t alignment);
PreGenGCValues get_pre_gc_values() const;
GCMemoryManager* _young_manager;
GCMemoryManager* _old_manager;
// Indicate whether heap is almost or approaching full.
// Usually, there is some memory headroom for application/gc to run properly.
// However, in extreme cases, e.g. young-gen is non-empty after a full gc, we
// will attempt some uncommon measures, e.g. alllocating small objs in
// old-gen.
bool _is_heap_almost_full;
// Helper functions for allocation
HeapWord* attempt_allocation(size_t size,
bool is_tlab,
bool first_only);
void do_full_collection(bool clear_all_soft_refs) override;
// Does the "cause" of GC indicate that
// we absolutely __must__ clear soft refs?
bool must_clear_all_soft_refs();
bool is_young_gc_safe() const;
void gc_prologue();
void gc_epilogue(bool full);
public:
// Returns JNI_OK on success
jint initialize() override;
// Does operations required after initialization has been done.
void post_initialize() override;
bool is_in_reserved(const void* addr) const { return _reserved.contains(addr); }
// Performance Counter support
GCPolicyCounters* counters() { return _gc_policy_counters; }
size_t capacity() const override;
size_t used() const override;
size_t max_capacity() const override;
HeapWord* mem_allocate(size_t size, bool* gc_overhead_limit_was_exceeded) override;
// Callback from VM_SerialCollectForAllocation operation.
// This function does everything necessary/possible to satisfy an
// allocation request that failed in the youngest generation that should
// have handled it (including collection, expansion, etc.)
HeapWord* satisfy_failed_allocation(size_t size, bool is_tlab);
// Callback from VM_SerialGCCollect.
void collect_at_safepoint(bool full);
// Perform a full collection of the heap; intended for use in implementing
// "System.gc". This implies as full a collection as the CollectedHeap
// supports. Caller does not hold the Heap_lock on entry.
void collect(GCCause::Cause cause) override;
// Returns "TRUE" iff "p" points into the committed areas of the heap.
// The methods is_in() and is_in_youngest() may be expensive to compute
// in general, so, to prevent their inadvertent use in product jvm's, we
// restrict their use to assertion checking or verification only.
bool is_in(const void* p) const override;
// Returns true if p points into the reserved space for the young generation.
// Assumes the young gen address range is less than that of the old gen.
bool is_in_young(const void* p) const;
bool requires_barriers(stackChunkOop obj) const override;
// Optimized nmethod scanning support routines
void register_nmethod(nmethod* nm) override;
void unregister_nmethod(nmethod* nm) override;
void verify_nmethod(nmethod* nm) override;
void prune_scavengable_nmethods();
void prune_unlinked_nmethods();
// Iteration functions.
void object_iterate(ObjectClosure* cl) override;
// A CollectedHeap is divided into a dense sequence of "blocks"; that is,
// each address in the (reserved) heap is a member of exactly
// one block. The defining characteristic of a block is that it is
// possible to find its size, and thus to progress forward to the next
// block. (Blocks may be of different sizes.) Thus, blocks may
// represent Java objects, or they might be free blocks in a
// free-list-based heap (or subheap), as long as the two kinds are
// distinguishable and the size of each is determinable.
// Returns the address of the start of the "block" that contains the
// address "addr". We say "blocks" instead of "object" since some heaps
// may not pack objects densely; a chunk may either be an object or a
// non-object.
HeapWord* block_start(const void* addr) const;
// Requires "addr" to be the start of a block, and returns "TRUE" iff
// the block is an object. Assumes (and verifies in non-product
// builds) that addr is in the allocated part of the heap and is
// the start of a chunk.
bool block_is_obj(const HeapWord* addr) const;
// Section on TLAB's.
size_t tlab_capacity(Thread* thr) const override;
size_t tlab_used(Thread* thr) const override;
size_t unsafe_max_tlab_alloc(Thread* thr) const override;
HeapWord* allocate_new_tlab(size_t min_size,
size_t requested_size,
size_t* actual_size) override;
void prepare_for_verify() override;
void verify(VerifyOption option) override;
void print_heap_on(outputStream* st) const override;
void print_gc_on(outputStream* st) const override;
void gc_threads_do(ThreadClosure* tc) const override;
void print_tracing_info() const override;
// Used to print information about locations in the hs_err file.
bool print_location(outputStream* st, void* addr) const override;
void print_heap_change(const PreGenGCValues& pre_gc_values) const;
// This function returns the CardTableRS object that allows us to scan
// generations in a fully generational heap.
CardTableRS* rem_set() { return _rem_set; }
// The ScanningOption determines which of the roots
// the closure is applied to:
// "SO_None" does none;
enum ScanningOption {
SO_None = 0x0,
SO_AllCodeCache = 0x8,
SO_ScavengeCodeCache = 0x10
};
public:
// Apply closures on various roots in Young GC or marking/adjust phases of Full GC.
void process_roots(ScanningOption so,
OopClosure* strong_roots,
CLDClosure* strong_cld_closure,
CLDClosure* weak_cld_closure,
NMethodToOopClosure* code_roots);
// Set the saved marks of generations, if that makes sense.
// In particular, if any generation might iterate over the oops
// in other generations, it should call this method.
void save_marks();
private:
// Return true if an allocation should be attempted in the older generation
// if it fails in the younger generation. Return false, otherwise.
bool should_try_older_generation_allocation(size_t word_size) const;
// Try to allocate space by expanding the heap.
HeapWord* expand_heap_and_allocate(size_t size, bool is_tlab);
HeapWord* mem_allocate_work(size_t size, bool is_tlab);
MemoryPool* _eden_pool;
MemoryPool* _survivor_pool;
MemoryPool* _old_pool;
void initialize_serviceability() override;
public:
static SerialHeap* heap();
SerialHeap();
Name kind() const override {
return CollectedHeap::Serial;
}
const char* name() const override {
return "Serial";
}
GrowableArray<GCMemoryManager*> memory_managers() override;
GrowableArray<MemoryPool*> memory_pools() override;
DefNewGeneration* young_gen() const {
return _young_gen;
}
TenuredGeneration* old_gen() const {
return _old_gen;
}
void scan_evacuated_objs(YoungGenScanClosure* young_cl,
OldGenScanClosure* old_cl);
void safepoint_synchronize_begin() override;
void safepoint_synchronize_end() override;
// Support for loading objects from CDS archive into the heap
bool can_load_archived_objects() const override { return true; }
HeapWord* allocate_loaded_archive_space(size_t size) override;
void complete_loaded_archive_space(MemRegion archive_space) override;
void pin_object(JavaThread* thread, oop obj) override;
void unpin_object(JavaThread* thread, oop obj) override;
};
#endif // SHARE_GC_SERIAL_SERIALHEAP_HPP