1 /* 2 * Copyright (c) 2019, 2023, 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 #include "precompiled.hpp" 26 #include "logging/log.hpp" 27 #include "memory/metaspace.hpp" 28 #include "oops/compressedKlass.hpp" 29 #include "runtime/globals.hpp" 30 #include "runtime/os.hpp" 31 #include "utilities/debug.hpp" 32 #include "utilities/globalDefinitions.hpp" 33 #include "utilities/ostream.hpp" 34 35 address CompressedKlassPointers::_base = nullptr; 36 int CompressedKlassPointers::_shift = 0; 37 size_t CompressedKlassPointers::_range = 0; 38 39 #ifdef _LP64 40 41 #ifdef ASSERT 42 void CompressedKlassPointers::assert_is_valid_encoding(address addr, size_t len, address base, int shift) { 43 assert(base + nth_bit(32 + shift) >= addr + len, "Encoding (base=" PTR_FORMAT ", shift=%d) does not " 44 "fully cover the class range " PTR_FORMAT "-" PTR_FORMAT, p2i(base), shift, p2i(addr), p2i(addr + len)); 45 } 46 #endif 47 48 // Given a klass range [addr, addr+len) and a given encoding scheme, assert that this scheme covers the range, then 49 // set this encoding scheme. Used by CDS at runtime to re-instate the scheme used to pre-compute klass ids for 50 // archived heap objects. 51 void CompressedKlassPointers::initialize_for_given_encoding(address addr, size_t len, address requested_base, int requested_shift) { 52 address const end = addr + len; 53 54 const int narrow_klasspointer_bits = sizeof(narrowKlass) * 8; 55 const size_t encoding_range_size = nth_bit(narrow_klasspointer_bits + requested_shift); 56 address encoding_range_end = requested_base + encoding_range_size; 57 58 // Note: it would be technically valid for the encoding base to precede the start of the Klass range. But we only call 59 // this function from CDS, and therefore know this to be true. 60 assert(requested_base == addr, "Invalid requested base"); 61 assert(encoding_range_end >= end, "Encoding does not cover the full Klass range"); 62 63 _base = requested_base; 64 _shift = requested_shift; 65 _range = encoding_range_size; 66 67 DEBUG_ONLY(assert_is_valid_encoding(addr, len, _base, _shift);) 68 } 69 70 char* CompressedKlassPointers::reserve_address_space_X(uintptr_t from, uintptr_t to, size_t size, size_t alignment, bool aslr) { 71 alignment = MAX2(Metaspace::reserve_alignment(), alignment); 72 return os::attempt_reserve_memory_between((char*)from, (char*)to, size, alignment, aslr); 73 } 74 75 char* CompressedKlassPointers::reserve_address_space_for_unscaled_encoding(size_t size, bool aslr) { 76 return reserve_address_space_X(0, nth_bit(32), size, Metaspace::reserve_alignment(), aslr); 77 } 78 79 char* CompressedKlassPointers::reserve_address_space_for_zerobased_encoding(size_t size, bool aslr) { 80 return reserve_address_space_X(nth_bit(32), nth_bit(32 + LogKlassAlignmentInBytes), size, Metaspace::reserve_alignment(), aslr); 81 } 82 83 char* CompressedKlassPointers::reserve_address_space_for_16bit_move(size_t size, bool aslr) { 84 return reserve_address_space_X(nth_bit(32), nth_bit(48), size, nth_bit(32), aslr); 85 } 86 87 #if !defined(AARCH64) || defined(ZERO) 88 // On aarch64 we have an own version; all other platforms use the default version 89 void CompressedKlassPointers::initialize(address addr, size_t len) { 90 // The default version of this code tries, in order of preference: 91 // -unscaled (base=0 shift=0) 92 // -zero-based (base=0 shift>0) 93 // -nonzero-base (base>0 shift=0) 94 // Note that base>0 shift>0 should never be needed, since the klass range will 95 // never exceed 4GB. 96 constexpr uintptr_t unscaled_max = nth_bit(32); 97 assert(len <= unscaled_max, "Klass range larger than 32 bits?"); 98 99 constexpr uintptr_t zerobased_max = nth_bit(32 + LogKlassAlignmentInBytes); 100 101 address const end = addr + len; 102 if (end <= (address)unscaled_max) { 103 _base = nullptr; 104 _shift = 0; 105 } else { 106 if (end <= (address)zerobased_max) { 107 _base = nullptr; 108 _shift = LogKlassAlignmentInBytes; 109 } else { 110 _base = addr; 111 _shift = 0; 112 } 113 } 114 _range = end - _base; 115 116 DEBUG_ONLY(assert_is_valid_encoding(addr, len, _base, _shift);) 117 } 118 #endif // !AARCH64 || ZERO 119 120 void CompressedKlassPointers::print_mode(outputStream* st) { 121 st->print_cr("Narrow klass base: " PTR_FORMAT ", Narrow klass shift: %d, " 122 "Narrow klass range: " SIZE_FORMAT_X, p2i(base()), shift(), 123 range()); 124 } 125 126 #endif // _LP64