From 276251c44a1a5b9dc36b27ecbaed37de62fc7558 Mon Sep 17 00:00:00 2001 From: Roman Kennke Date: Fri, 15 Nov 2024 21:21:03 +0000 Subject: [PATCH] 8342826: Improve performance of oopDesc::klass() after JDK-8305895 Reviewed-by: coleenp, shade, mli --- src/hotspot/share/oops/objLayout.cpp | 50 ++++++++++++++++ src/hotspot/share/oops/objLayout.hpp | 66 +++++++++++++++++++++ src/hotspot/share/oops/objLayout.inline.hpp | 48 +++++++++++++++ src/hotspot/share/oops/oop.cpp | 4 -- src/hotspot/share/oops/oop.hpp | 15 ++--- src/hotspot/share/oops/oop.inline.hpp | 56 +++++++++-------- src/hotspot/share/runtime/arguments.cpp | 2 + 7 files changed, 202 insertions(+), 39 deletions(-) create mode 100644 src/hotspot/share/oops/objLayout.cpp create mode 100644 src/hotspot/share/oops/objLayout.hpp create mode 100644 src/hotspot/share/oops/objLayout.inline.hpp diff --git a/src/hotspot/share/oops/objLayout.cpp b/src/hotspot/share/oops/objLayout.cpp new file mode 100644 index 00000000000..3d18d319ed2 --- /dev/null +++ b/src/hotspot/share/oops/objLayout.cpp @@ -0,0 +1,50 @@ +/* + * Copyright Amazon.com Inc. 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. + * + */ + +#include "precompiled.hpp" +#include "oops/markWord.hpp" +#include "oops/objLayout.hpp" +#include "runtime/globals.hpp" +#include "utilities/debug.hpp" + +ObjLayout::Mode ObjLayout::_klass_mode = ObjLayout::Undefined; +int ObjLayout::_oop_base_offset_in_bytes = 0; +bool ObjLayout::_oop_has_klass_gap = false; + +void ObjLayout::initialize() { + assert(_klass_mode == Undefined, "ObjLayout initialized twice"); + if (UseCompactObjectHeaders) { + _klass_mode = Compact; + _oop_base_offset_in_bytes = sizeof(markWord); + _oop_has_klass_gap = false; + } else if (UseCompressedClassPointers) { + _klass_mode = Compressed; + _oop_base_offset_in_bytes = sizeof(markWord) + sizeof(narrowKlass); + _oop_has_klass_gap = true; + } else { + _klass_mode = Uncompressed; + _oop_base_offset_in_bytes = sizeof(markWord) + sizeof(Klass*); + _oop_has_klass_gap = false; + } +} diff --git a/src/hotspot/share/oops/objLayout.hpp b/src/hotspot/share/oops/objLayout.hpp new file mode 100644 index 00000000000..e434524d4b0 --- /dev/null +++ b/src/hotspot/share/oops/objLayout.hpp @@ -0,0 +1,66 @@ +/* + * Copyright Amazon.com Inc. 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_OBJLAYOUT_HPP +#define SHARE_OOPS_OBJLAYOUT_HPP + +/* + * This class helps to avoid loading more than one flag in some + * operations that require checking UseCompressedClassPointers, + * UseCompactObjectHeaders and possibly more. + * + * This is important on some performance critical paths, e.g. where + * the Klass* is accessed frequently, especially by GC oop iterators + * and stack-trace builders. + */ +class ObjLayout { +public: + enum Mode { + // +UseCompactObjectHeaders (implies +UseCompressedClassPointers) + Compact, + // +UseCompressedClassPointers (-UseCompactObjectHeaders) + Compressed, + // -UseCompressedClassPointers (-UseCompactObjectHeaders) + Uncompressed, + // Not yet initialized + Undefined + }; + +private: + static Mode _klass_mode; + static int _oop_base_offset_in_bytes; + static bool _oop_has_klass_gap; + +public: + static void initialize(); + static inline Mode klass_mode(); + static inline int oop_base_offset_in_bytes() { + return _oop_base_offset_in_bytes; + } + static inline bool oop_has_klass_gap() { + return _oop_has_klass_gap; + } +}; + +#endif // SHARE_OOPS_OBJLAYOUT_HPP diff --git a/src/hotspot/share/oops/objLayout.inline.hpp b/src/hotspot/share/oops/objLayout.inline.hpp new file mode 100644 index 00000000000..677c1a933bd --- /dev/null +++ b/src/hotspot/share/oops/objLayout.inline.hpp @@ -0,0 +1,48 @@ +/* + * Copyright Amazon.com Inc. 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_OBJLAYOUT_INLINE_HPP +#define SHARE_OOPS_OBJLAYOUT_INLINE_HPP + +#include "oops/objLayout.hpp" + +inline ObjLayout::Mode ObjLayout::klass_mode() { +#ifdef ASSERT + assert(_klass_mode != Undefined, "KlassMode not yet initialized"); + if (UseCompactObjectHeaders) { + assert(_klass_mode == Compact, "Klass mode does not match flags"); + } else if (UseCompressedClassPointers) { + assert(_klass_mode == Compressed, "Klass mode does not match flags"); + } else { + assert(_klass_mode == Uncompressed, "Klass mode does not match flags"); + } +#endif +#ifdef _LP64 + return _klass_mode; +#else + return Uncompressed; +#endif +} + +#endif // SHARE_OOPS_OBJLAYOUT_INLINE_HPP diff --git a/src/hotspot/share/oops/oop.cpp b/src/hotspot/share/oops/oop.cpp index 9385379a617..11cab4c043b 100644 --- a/src/hotspot/share/oops/oop.cpp +++ b/src/hotspot/share/oops/oop.cpp @@ -152,10 +152,6 @@ bool oopDesc::is_array_noinline() const { return is_array(); } bool oopDesc::is_objArray_noinline() const { return is_objArray(); } bool oopDesc::is_typeArray_noinline() const { return is_typeArray(); } -bool oopDesc::has_klass_gap() { - return UseCompressedClassPointers && !UseCompactObjectHeaders; -} - #if INCLUDE_CDS_JAVA_HEAP void oopDesc::set_narrow_klass(narrowKlass nk) { assert(CDSConfig::is_dumping_heap(), "Used by CDS only. Do not abuse!"); diff --git a/src/hotspot/share/oops/oop.hpp b/src/hotspot/share/oops/oop.hpp index 18e421d620c..f52baab0de6 100644 --- a/src/hotspot/share/oops/oop.hpp +++ b/src/hotspot/share/oops/oop.hpp @@ -31,6 +31,7 @@ #include "oops/accessDecorators.hpp" #include "oops/markWord.hpp" #include "oops/metadata.hpp" +#include "oops/objLayout.hpp" #include "runtime/atomic.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/macros.hpp" @@ -324,7 +325,9 @@ class oopDesc { inline bool mark_must_be_preserved() const; inline bool mark_must_be_preserved(markWord m) const; - static bool has_klass_gap(); + inline static bool has_klass_gap() { + return ObjLayout::oop_has_klass_gap(); + } // for code generation static int mark_offset_in_bytes() { return (int)offset_of(oopDesc, _mark); } @@ -346,15 +349,7 @@ class oopDesc { } static int base_offset_in_bytes() { - if (UseCompactObjectHeaders) { - // With compact headers, the Klass* field is not used for the Klass* - // and is used for the object fields instead. - return sizeof(markWord); - } else if (UseCompressedClassPointers) { - return sizeof(markWord) + sizeof(narrowKlass); - } else { - return sizeof(markWord) + sizeof(Klass*); - } + return ObjLayout::oop_base_offset_in_bytes(); } // for error reporting diff --git a/src/hotspot/share/oops/oop.inline.hpp b/src/hotspot/share/oops/oop.inline.hpp index 098e6bfa90f..45902e63147 100644 --- a/src/hotspot/share/oops/oop.inline.hpp +++ b/src/hotspot/share/oops/oop.inline.hpp @@ -34,6 +34,7 @@ #include "oops/arrayOop.hpp" #include "oops/compressedKlass.inline.hpp" #include "oops/instanceKlass.hpp" +#include "oops/objLayout.inline.hpp" #include "oops/markWord.inline.hpp" #include "oops/oopsHierarchy.hpp" #include "runtime/atomic.hpp" @@ -95,43 +96,48 @@ void oopDesc::init_mark() { } Klass* oopDesc::klass() const { - if (UseCompactObjectHeaders) { - return mark().klass(); - } else if (UseCompressedClassPointers) { - return CompressedKlassPointers::decode_not_null(_metadata._compressed_klass); - } else { - return _metadata._klass; + switch (ObjLayout::klass_mode()) { + case ObjLayout::Compact: + return mark().klass(); + case ObjLayout::Compressed: + return CompressedKlassPointers::decode_not_null(_metadata._compressed_klass); + default: + return _metadata._klass; } } Klass* oopDesc::klass_or_null() const { - if (UseCompactObjectHeaders) { - return mark().klass_or_null(); - } else if (UseCompressedClassPointers) { - return CompressedKlassPointers::decode(_metadata._compressed_klass); - } else { - return _metadata._klass; + switch (ObjLayout::klass_mode()) { + case ObjLayout::Compact: + return mark().klass_or_null(); + case ObjLayout::Compressed: + return CompressedKlassPointers::decode(_metadata._compressed_klass); + default: + return _metadata._klass; } } Klass* oopDesc::klass_or_null_acquire() const { - if (UseCompactObjectHeaders) { - return mark_acquire().klass(); - } else if (UseCompressedClassPointers) { - narrowKlass narrow_klass = Atomic::load_acquire(&_metadata._compressed_klass); - return CompressedKlassPointers::decode(narrow_klass); - } else { - return Atomic::load_acquire(&_metadata._klass); + switch (ObjLayout::klass_mode()) { + case ObjLayout::Compact: + return mark_acquire().klass(); + case ObjLayout::Compressed: { + narrowKlass narrow_klass = Atomic::load_acquire(&_metadata._compressed_klass); + return CompressedKlassPointers::decode(narrow_klass); + } + default: + return Atomic::load_acquire(&_metadata._klass); } } Klass* oopDesc::klass_without_asserts() const { - if (UseCompactObjectHeaders) { - return mark().klass_without_asserts(); - } else if (UseCompressedClassPointers) { - return CompressedKlassPointers::decode_without_asserts(_metadata._compressed_klass); - } else { - return _metadata._klass; + switch (ObjLayout::klass_mode()) { + case ObjLayout::Compact: + return mark().klass_without_asserts(); + case ObjLayout::Compressed: + return CompressedKlassPointers::decode_without_asserts(_metadata._compressed_klass); + default: + return _metadata._klass; } } diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index e9262a48086..7b8604659a0 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -46,6 +46,7 @@ #include "nmt/nmtCommon.hpp" #include "oops/compressedKlass.hpp" #include "oops/instanceKlass.hpp" +#include "oops/objLayout.hpp" #include "oops/oop.inline.hpp" #include "prims/jvmtiAgentList.hpp" #include "prims/jvmtiExport.hpp" @@ -3673,6 +3674,7 @@ jint Arguments::parse(const JavaVMInitArgs* initial_cmd_args) { if (UseCompactObjectHeaders && !UseCompressedClassPointers) { FLAG_SET_DEFAULT(UseCompressedClassPointers, true); } + ObjLayout::initialize(); #endif return JNI_OK;