| /* |
| * 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_OOPS_COMPRESSEDKLASS_INLINE_HPP |
| #define SHARE_OOPS_COMPRESSEDKLASS_INLINE_HPP |
| |
| #include "oops/compressedKlass.hpp" |
| |
| #include "memory/universe.hpp" |
| #include "oops/oop.hpp" |
| #include "utilities/align.hpp" |
| #include "utilities/globalDefinitions.hpp" |
| |
| inline Klass* CompressedKlassPointers::decode_not_null_without_asserts(narrowKlass v, address narrow_base_base, int shift) { |
| return (Klass*)((uintptr_t)narrow_base_base +((uintptr_t)v << shift)); |
| } |
| |
| inline narrowKlass CompressedKlassPointers::encode_not_null_without_asserts(Klass* k, address narrow_base, int shift) { |
| return (narrowKlass)(pointer_delta(k, narrow_base, 1) >> shift); |
| } |
| |
| inline Klass* CompressedKlassPointers::decode_not_null_without_asserts(narrowKlass v) { |
| return decode_not_null_without_asserts(v, base(), shift()); |
| } |
| |
| inline Klass* CompressedKlassPointers::decode_without_asserts(narrowKlass v) { |
| return is_null(v) ? nullptr : decode_not_null_without_asserts(v, base(), shift()); |
| } |
| |
| inline Klass* CompressedKlassPointers::decode_not_null(narrowKlass v) { |
| assert(!is_null(v), "narrow klass value can never be zero"); |
| DEBUG_ONLY(check_valid_narrow_klass_id(v);) |
| Klass* const k = decode_not_null_without_asserts(v, base(), shift()); |
| DEBUG_ONLY(check_encodable(k)); |
| return k; |
| } |
| |
| inline Klass* CompressedKlassPointers::decode(narrowKlass v) { |
| return is_null(v) ? nullptr : decode_not_null(v); |
| } |
| |
| inline narrowKlass CompressedKlassPointers::encode_not_null(Klass* v) { |
| assert(!is_null(v), "klass value can never be zero"); |
| DEBUG_ONLY(check_encodable(v);) |
| const narrowKlass nk = encode_not_null_without_asserts(v, base(), shift()); |
| assert(decode_not_null_without_asserts(nk, base(), shift()) == v, "reversibility"); |
| DEBUG_ONLY(check_valid_narrow_klass_id(nk);) |
| return nk; |
| } |
| |
| inline narrowKlass CompressedKlassPointers::encode(Klass* v) { |
| return is_null(v) ? (narrowKlass)0 : encode_not_null(v); |
| } |
| |
| #ifdef ASSERT |
| inline void CompressedKlassPointers::check_encodable(const void* addr) { |
| assert(UseCompressedClassPointers, "Only call for +UseCCP"); |
| assert(addr != nullptr, "Null Klass?"); |
| assert(is_encodable(addr), |
| "Address " PTR_FORMAT " is not encodable (Klass range: " RANGEFMT ", klass alignment: %d)", |
| p2i(addr), RANGE2FMTARGS(_klass_range_start, _klass_range_end), klass_alignment_in_bytes()); |
| } |
| |
| inline void CompressedKlassPointers::check_valid_narrow_klass_id(narrowKlass nk) { |
| check_init(_base); |
| assert(UseCompressedClassPointers, "Only call for +UseCCP"); |
| assert(nk > 0, "narrow Klass ID is 0"); |
| const uint64_t nk_mask = ~right_n_bits(narrow_klass_pointer_bits()); |
| assert(((uint64_t)nk & nk_mask) == 0, "narrow klass id bit spillover (%u)", nk); |
| assert(nk >= _lowest_valid_narrow_klass_id && |
| nk <= _highest_valid_narrow_klass_id, "narrowKlass ID out of range (%u)", nk); |
| } |
| #endif // ASSERT |
| |
| inline address CompressedKlassPointers::encoding_range_end() { |
| const int max_bits = narrow_klass_pointer_bits() + _shift; |
| return (address)((uintptr_t)_base + nth_bit(max_bits)); |
| } |
| |
| #endif // SHARE_OOPS_COMPRESSEDKLASS_INLINE_HPP |