1 /*
  2  * Copyright (c) 2021, Red Hat, Inc. All rights reserved.
  3  * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
  4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  5  *
  6  * This code is free software; you can redistribute it and/or modify it
  7  * under the terms of the GNU General Public License version 2 only, as
  8  * published by the Free Software Foundation.
  9  *
 10  * This code is distributed in the hope that it will be useful, but WITHOUT
 11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 13  * version 2 for more details (a copy is included in the LICENSE file that
 14  * accompanied this code).
 15  *
 16  * You should have received a copy of the GNU General Public License version
 17  * 2 along with this work; if not, write to the Free Software Foundation,
 18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 19  *
 20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 21  * or visit www.oracle.com if you need additional information or have any
 22  * questions.
 23  *
 24  */
 25 
 26 #ifndef SHARE_GC_SHARED_SLIDINGFORWARDING_HPP
 27 #define SHARE_GC_SHARED_SLIDINGFORWARDING_HPP
 28 
 29 #include "memory/allocation.hpp"
 30 #include "memory/memRegion.hpp"
 31 #include "oops/markWord.hpp"
 32 #include "oops/oopsHierarchy.hpp"
 33 #include "utilities/fastHash.hpp"
 34 #include "utilities/resourceHash.hpp"
 35 
 36 /**
 37  * SlidingForwarding is a method to store forwarding information in a compressed form into the object header,
 38  * that has been specifically designed for sliding compaction GCs and compact object headers. With compact object
 39  * headers, we store the compressed class pointer in the header, which would be overwritten by full forwarding
 40  * pointer, if we allow the legacy forwarding code to act. This would lose the class information for the object,
 41  * which is required later in GC cycle to iterate the reference fields and get the object size for copying.
 42  *
 43  * SlidingForwarding requires only small side tables and guarantees constant-time access and modification.
 44  *
 45  * The idea is to use a pointer compression scheme very similar to the one that is used for compressed oops.
 46  * We divide the heap into number of logical regions. Each region spans maximum of 2^NUM_OFFSET_BITS words.
 47  *
 48  * The key advantage of sliding compaction for encoding efficiency: it can forward objects from one region to a
 49  * maximum of two regions. This is an intuitive property: when we slide the compact region full of data, it can
 50  * only span two adjacent regions. This property allows us to use the off-side table to record the addresses of
 51  * two target regions. The table holds N*2 entries for N logical regions. For each region, it gives the base
 52  * address of the two target regions, or a special placeholder if not used. A single bit in forwarding would
 53  * indicate to which of the two "to" regions the object is forwarded into.
 54  *
 55  * This encoding efficiency allows to store the forwarding information in the object header _together_ with the
 56  * compressed class pointer.
 57  *
 58  * When recording the sliding forwarding, the mark word would look roughly like this:
 59  *
 60  *   64                              32                                0
 61  *    [................................OOOOOOOOOOOOOOOOOOOOOOOOOOOOAFTT]
 62  *                                                                    ^----- normal lock bits, would record "object is forwarded"
 63  *                                                                  ^------- fallback bit (explained below)
 64  *                                                                 ^-------- alternate region select
 65  *                                     ^------------------------------------ in-region offset
 66  *     ^-------------------------------------------------------------------- protected area, *not touched* by this code, useful for
 67  *                                                                           compressed class pointer with compact object headers
 68  *
 69  * Adding a forwarding then generally works as follows:
 70  *   1. Compute the "to" offset in the "to" region, this gives "offset".
 71  *   2. Check if the primary "from" offset at base table contains "to" region base, use it.
 72  *      If not usable, continue to next step. If usable, set "alternate" = "false" and jump to (4).
 73  *   3. Check if the alternate "from" offset at base table contains "to" region base, use it.
 74  *      This gives us "alternate" = "true". This should always complete for sliding forwarding.
 75  *   4. Compute the mark word from "offset" and "alternate", write it out
 76  *
 77  * Similarly, looking up the target address, given an original object address generally works as follows:
 78  *   1. Load the mark from object, and decode "offset" and "alternate" from there
 79  *   2. Compute the "from" base offset from the object
 80  *   3. Look up "to" region base from the base table either at primary or alternate indices, using "alternate" flag
 81  *   4. Compute the "to" address from "to" region base and "offset"
 82  *
 83  * This algorithm is broken by G1 last-ditch serial compaction: there, object from a single region can be
 84  * forwarded to multiple, more than two regions. To deal with that, we initialize a fallback-hashtable for
 85  * storing those extra forwardings, and set another bit in the header to indicate that the forwardee is not
 86  * encoded but should be looked-up in the hashtable. G1 serial compaction is not very common - it is the
 87  * last-last-ditch GC that is used when the JVM is scrambling to squeeze more space out of the heap, and at
 88  * that point, ultimate performance is no longer the main concern.
 89  */
 90 class SlidingForwarding : public AllStatic {
 91 private:
 92 
 93   /*
 94    * A simple hash-table that acts as fallback for the sliding forwarding.
 95    * This is used in the case of G1 serial compaction, which violates the
 96    * assumption of sliding forwarding that each object of any region is only
 97    * ever forwarded to one of two target regions. At this point, the GC is
 98    * scrambling to free up more Java heap memory, and therefore performance
 99    * is not the major concern.
100    *
101    * The implementation is a straightforward open hashtable.
102    * It is a single-threaded (not thread-safe) implementation, and that
103    * is sufficient because G1 serial compaction is single-threaded.
104    */
105   inline static unsigned hash(HeapWord* const& from) {
106     uint64_t val = reinterpret_cast<uint64_t>(from);
107     uint64_t hash = FastHash::get_hash64(val, UCONST64(0xAAAAAAAAAAAAAAAA));
108     return checked_cast<unsigned>(hash >> 32);
109   }
110   inline static bool equals(HeapWord* const& lhs, HeapWord* const& rhs) {
111     return lhs == rhs;
112   }
113   typedef ResourceHashtable<HeapWord* /* key-type */, HeapWord* /* value-type */,
114                             1024 /* size */, AnyObj::C_HEAP /* alloc-type */, mtGC,
115                             SlidingForwarding::hash, SlidingForwarding::equals> FallbackTable;
116 
117   static const uintptr_t MARK_LOWER_HALF_MASK = right_n_bits(32);
118 
119   // We need the lowest two bits to indicate a forwarded object.
120   // The next bit indicates that the forwardee should be looked-up in a fallback-table.
121   static const int FALLBACK_SHIFT = markWord::lock_bits;
122   static const int FALLBACK_BITS = 1;
123   static const int FALLBACK_MASK = right_n_bits(FALLBACK_BITS) << FALLBACK_SHIFT;
124 
125   // Next bit selects the target region
126   static const int ALT_REGION_SHIFT = FALLBACK_SHIFT + FALLBACK_BITS;
127   static const int ALT_REGION_BITS = 1;
128   // This will be "2" always, but expose it as named constant for clarity
129   static const size_t NUM_TARGET_REGIONS = 1 << ALT_REGION_BITS;
130 
131   // The offset bits start then
132   static const int OFFSET_BITS_SHIFT = ALT_REGION_SHIFT + ALT_REGION_BITS;
133 
134   // How many bits we use for the offset
135   static const int NUM_OFFSET_BITS = 32 - OFFSET_BITS_SHIFT;
136 
137   // Indicates an unused base address in the target base table.
138   static HeapWord* const UNUSED_BASE;
139 
140   static HeapWord*      _heap_start;
141   static size_t         _region_size_words;
142 
143   static size_t         _heap_start_region_bias;
144   static size_t         _num_regions;
145   static uint           _region_size_bytes_shift;
146   static uintptr_t      _region_mask;
147 
148   // The target base table memory.
149   static HeapWord**     _bases_table;
150   // Entries into the target base tables, biased to the start of the heap.
151   static HeapWord**     _biased_bases[NUM_TARGET_REGIONS];
152 
153   static FallbackTable* _fallback_table;
154 
155   static inline size_t biased_region_index_containing(HeapWord* addr);
156 
157   static inline uintptr_t encode_forwarding(HeapWord* from, HeapWord* to);
158   static inline HeapWord* decode_forwarding(HeapWord* from, uintptr_t encoded);
159 
160   static void fallback_forward_to(HeapWord* from, HeapWord* to);
161   static HeapWord* fallback_forwardee(HeapWord* from);
162 
163   static inline void forward_to_impl(oop from, oop to);
164   static inline oop forwardee_impl(oop from);
165 
166 public:
167   static void initialize(MemRegion heap, size_t region_size_words);
168 
169   static void begin();
170   static void end();
171 
172   static inline bool is_forwarded(oop obj);
173   static inline bool is_not_forwarded(oop obj);
174 
175   static inline void forward_to(oop from, oop to);
176   static inline oop forwardee(oop from);
177 };
178 
179 #endif // SHARE_GC_SHARED_SLIDINGFORWARDING_HPP