Skip to content

Commit

Permalink
Faster Klass* access
Browse files Browse the repository at this point in the history
  • Loading branch information
rkennke committed Oct 9, 2024
1 parent 4035bb6 commit afd55b5
Show file tree
Hide file tree
Showing 5 changed files with 194 additions and 25 deletions.
39 changes: 39 additions & 0 deletions src/hotspot/share/oops/klassMode.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* 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/klassMode.hpp"

KlassMode::Mode KlassMode::_klass_mode = KlassMode::Undefined;

void KlassMode::init_klass_mode() {
assert(_klass_mode == Undefined, "KlassMode initialized twice");
if (UseCompactObjectHeaders) {
_klass_mode = Compact;
} else if (UseCompressedClassPointers) {
_klass_mode = Compressed;
} else {
_klass_mode = Uncompressed;
}
}
74 changes: 74 additions & 0 deletions src/hotspot/share/oops/klassMode.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* 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_KLASSMODE_HPP
#define SHARE_OOPS_KLASSMODE_HPP

/*
* This class helps to avoid loading more than one flag when
* accessing the Klass* in oopDesc::klass(). This is important
* on some performance critical paths where the Klass* is
* accessed frequently, especially by GC oop iterators.
*
* Instead of doing:
* if (UseCompactObjectHeaders) { // Load first flag
* ..
* } else if (UseCompressedClassPointers) { // Load second flag
* ..
* } else {
* ..
* }
*
* we can do:
* switch (KlassMode::klass_mode()) {
* case Compact:
* ..
* case Compressed:
* ..
* case Uncompressed:
* ..
* }
*/
class KlassMode {
public:
enum Mode {
// +UseCompactObjectHeaders (implies +UseCompressedClassPointers)
Compact,
// +UseCompressedClassPointers (-UseCompactObjectHeaders)
Compressed,
// -UseCompressedClassPointers (-UseCompactObjectHeaders)
Uncompressed,
// Not yet initialized
Undefined
};

private:
static Mode _klass_mode;

public:
static void init_klass_mode();
static inline Mode klass_mode();
};

#endif // SHARE_OOPS_KLASSMODE_HPP
48 changes: 48 additions & 0 deletions src/hotspot/share/oops/klassMode.inline.hpp
Original file line number Diff line number Diff line change
@@ -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_KLASSMODE_INLINE_HPP
#define SHARE_OOPS_KLASSMODE_INLINE_HPP

#include "oops/klassMode.hpp"

inline KlassMode::Mode KlassMode::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_KLASSMODE_INLINE_HPP
56 changes: 31 additions & 25 deletions src/hotspot/share/oops/oop.inline.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "oops/arrayOop.hpp"
#include "oops/compressedKlass.inline.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/klassMode.inline.hpp"
#include "oops/markWord.inline.hpp"
#include "oops/oopsHierarchy.hpp"
#include "runtime/atomic.hpp"
Expand Down Expand Up @@ -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 (KlassMode::klass_mode()) {
case KlassMode::Compact:
return mark().klass();
case KlassMode::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 (KlassMode::klass_mode()) {
case KlassMode::Compact:
return mark().klass_or_null();
case KlassMode::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 (KlassMode::klass_mode()) {
case KlassMode::Compact:
return mark_acquire().klass();
case KlassMode::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 (KlassMode::klass_mode()) {
case KlassMode::Compact:
return mark().klass_without_asserts();
case KlassMode::Compressed:
return CompressedKlassPointers::decode_without_asserts(_metadata._compressed_klass);
default:
return _metadata._klass;
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/hotspot/share/runtime/arguments.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
#include "nmt/nmtCommon.hpp"
#include "oops/compressedKlass.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/klassMode.hpp"
#include "oops/oop.inline.hpp"
#include "prims/jvmtiAgentList.hpp"
#include "prims/jvmtiExport.hpp"
Expand Down Expand Up @@ -3670,6 +3671,7 @@ jint Arguments::parse(const JavaVMInitArgs* initial_cmd_args) {
if (UseCompactObjectHeaders && !UseCompressedClassPointers) {
FLAG_SET_DEFAULT(UseCompressedClassPointers, true);
}
KlassMode::init_klass_mode();
#endif

return JNI_OK;
Expand Down

0 comments on commit afd55b5

Please sign in to comment.