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 *
23 */
24
25#ifndef SHARE_GC_G1_G1HEAPREGIONATTR_HPP
26#define SHARE_GC_G1_G1HEAPREGIONATTR_HPP
27
28#include "gc/g1/g1BiasedArray.hpp"
29#include "gc/g1/heapRegion.hpp"
30
31// Per-region attributes often used during garbage collection to avoid costly
32// lookups for that information all over the place.
33struct G1HeapRegionAttr {
34public:
35 // We use different types to represent the state value depending on platform as
36 // some have issues loading parts of words.
37#ifdef SPARC
38 typedef int32_t region_type_t;
39 typedef uint32_t needs_remset_update_t;
40#else
41 typedef int8_t region_type_t;
42 typedef uint8_t needs_remset_update_t;
43#endif
44
45private:
46 needs_remset_update_t _needs_remset_update;
47 region_type_t _type;
48
49public:
50 // Selection of the values for the _type field were driven to micro-optimize the
51 // encoding and frequency of the checks.
52 // The most common check for a given reference is whether the region is in the
53 // collection set or not, and which generation this region is in.
54 // The selected encoding allows us to use a single check (> NotInCSet) for the
55 // former.
56 //
57 // The other values are used for objects in regions requiring various special handling,
58 // eager reclamation of humongous objects or optional regions.
59 static const region_type_t Optional = -3; // The region is optional not in the current collection set.
60 static const region_type_t Humongous = -2; // The region is a humongous candidate not in the current collection set.
61 static const region_type_t NotInCSet = -1; // The region is not in the collection set.
62 static const region_type_t Young = 0; // The region is in the collection set and a young region.
63 static const region_type_t Old = 1; // The region is in the collection set and an old region.
64 static const region_type_t Num = 2;
65
66 G1HeapRegionAttr(region_type_t type = NotInCSet, bool needs_remset_update = false) :
67 _needs_remset_update(needs_remset_update), _type(type) {
68
69 assert(is_valid(), "Invalid type %d", _type);
70 }
71
72 region_type_t type() const { return _type; }
73
74 const char* get_type_str() const {
75 switch (type()) {
76 case Optional: return "Optional";
77 case Humongous: return "Humongous";
78 case NotInCSet: return "NotInCSet";
79 case Young: return "Young";
80 case Old: return "Old";
81 default: ShouldNotReachHere(); return "";
82 }
83 }
84
85 bool needs_remset_update() const { return _needs_remset_update != 0; }
86
87 void set_old() { _type = Old; }
88 void clear_humongous() {
89 assert(is_humongous() || !is_in_cset(), "must be");
90 _type = NotInCSet;
91 }
92 void set_has_remset(bool value) { _needs_remset_update = value ? 1 : 0; }
93
94 bool is_in_cset_or_humongous() const { return is_in_cset() || is_humongous(); }
95 bool is_in_cset() const { return type() >= Young; }
96
97 bool is_humongous() const { return type() == Humongous; }
98 bool is_young() const { return type() == Young; }
99 bool is_old() const { return type() == Old; }
100 bool is_optional() const { return type() == Optional; }
101
102#ifdef ASSERT
103 bool is_default() const { return type() == NotInCSet; }
104 bool is_valid() const { return (type() >= Optional && type() < Num); }
105 bool is_valid_gen() const { return (type() >= Young && type() <= Old); }
106#endif
107};
108
109// Table for all regions in the heap for above.
110//
111// We use this to speed up reference processing during young collection and
112// quickly reclaim humongous objects. For the latter, at the start of GC, by adding
113// it as a humongous region we enable special handling for that region. During the
114// reference iteration closures, when we see a humongous region, we then simply mark
115// it as referenced, i.e. live, and remove it from this table to prevent further
116// processing on it.
117//
118// This means that this does NOT completely correspond to the information stored
119// in a HeapRegion, but only to what is interesting for the current young collection.
120class G1HeapRegionAttrBiasedMappedArray : public G1BiasedMappedArray<G1HeapRegionAttr> {
121 protected:
122 G1HeapRegionAttr default_value() const { return G1HeapRegionAttr(G1HeapRegionAttr::NotInCSet); }
123 public:
124 void set_optional(uintptr_t index, bool needs_remset_update) {
125 assert(get_by_index(index).is_default(),
126 "Region attributes at index " INTPTR_FORMAT " should be default but is %s", index, get_by_index(index).get_type_str());
127 set_by_index(index, G1HeapRegionAttr(G1HeapRegionAttr::Optional, needs_remset_update));
128 }
129
130 void set_humongous(uintptr_t index, bool needs_remset_update) {
131 assert(get_by_index(index).is_default(),
132 "Region attributes at index " INTPTR_FORMAT " should be default but is %s", index, get_by_index(index).get_type_str());
133 set_by_index(index, G1HeapRegionAttr(G1HeapRegionAttr::Humongous, needs_remset_update));
134 }
135
136 void clear_humongous(uintptr_t index) {
137 get_ref_by_index(index)->clear_humongous();
138 }
139
140 void set_has_remset(uintptr_t index, bool needs_remset_update) {
141 get_ref_by_index(index)->set_has_remset(needs_remset_update);
142 }
143
144 void set_in_young(uintptr_t index) {
145 assert(get_by_index(index).is_default(),
146 "Region attributes at index " INTPTR_FORMAT " should be default but is %s", index, get_by_index(index).get_type_str());
147 set_by_index(index, G1HeapRegionAttr(G1HeapRegionAttr::Young, true));
148 }
149
150 void set_in_old(uintptr_t index, bool needs_remset_update) {
151 assert(get_by_index(index).is_default(),
152 "Region attributes at index " INTPTR_FORMAT " should be default but is %s", index, get_by_index(index).get_type_str());
153 set_by_index(index, G1HeapRegionAttr(G1HeapRegionAttr::Old, needs_remset_update));
154 }
155
156 bool is_in_cset_or_humongous(HeapWord* addr) const { return at(addr).is_in_cset_or_humongous(); }
157 bool is_in_cset(HeapWord* addr) const { return at(addr).is_in_cset(); }
158 bool is_in_cset(const HeapRegion* hr) const { return get_by_index(hr->hrm_index()).is_in_cset(); }
159 G1HeapRegionAttr at(HeapWord* addr) const { return get_by_address(addr); }
160 void clear() { G1BiasedMappedArray<G1HeapRegionAttr>::clear(); }
161 void clear(const HeapRegion* hr) { return set_by_index(hr->hrm_index(), G1HeapRegionAttr(G1HeapRegionAttr::NotInCSet)); }
162};
163
164#endif // SHARE_GC_G1_G1HEAPREGIONATTR_HPP
165