8138659: Speed up InstanceKlass subclass discrimination
Summary: Add _misc_kind field and flags, move around predicates.
Reviewed-by: coleenp, stefank
--- a/hotspot/src/share/vm/oops/instanceClassLoaderKlass.hpp Fri Oct 09 15:48:30 2015 +0200
+++ b/hotspot/src/share/vm/oops/instanceClassLoaderKlass.hpp Fri Oct 09 14:08:15 2015 -0400
@@ -41,11 +41,10 @@
// Constructor
InstanceClassLoaderKlass(int vtable_len, int itable_len, int static_field_size, int nonstatic_oop_map_size, ReferenceType rt, AccessFlags access_flags, bool is_anonymous)
- : InstanceKlass(vtable_len, itable_len, static_field_size, nonstatic_oop_map_size, rt, access_flags, is_anonymous) {}
+ : InstanceKlass(vtable_len, itable_len, static_field_size, nonstatic_oop_map_size,
+ InstanceKlass::_misc_kind_class_loader, rt, access_flags, is_anonymous) {}
public:
- virtual bool oop_is_instanceClassLoader() const { return true; }
-
InstanceClassLoaderKlass() { assert(DumpSharedSpaces || UseSharedSpaces, "only for CDS"); }
// GC specific object visitors
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp Fri Oct 09 15:48:30 2015 +0200
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp Fri Oct 09 14:08:15 2015 -0400
@@ -145,8 +145,8 @@
} else {
// normal class
ik = new (loader_data, size, THREAD) InstanceKlass(
- vtable_len, itable_len, static_field_size, nonstatic_oop_map_size, rt,
- access_flags, is_anonymous);
+ vtable_len, itable_len, static_field_size, nonstatic_oop_map_size,
+ InstanceKlass::_misc_kind_other, rt, access_flags, is_anonymous);
}
} else {
// reference klass
@@ -195,6 +195,7 @@
int itable_len,
int static_field_size,
int nonstatic_oop_map_size,
+ unsigned kind,
ReferenceType rt,
AccessFlags access_flags,
bool is_anonymous) {
@@ -209,6 +210,7 @@
set_nonstatic_oop_map_size(nonstatic_oop_map_size);
set_access_flags(access_flags);
_misc_flags = 0; // initialize to zero
+ set_kind(kind);
set_is_anonymous(is_anonymous);
assert(size() == iksize, "wrong size for object");
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp Fri Oct 09 15:48:30 2015 +0200
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp Fri Oct 09 14:08:15 2015 -0400
@@ -117,6 +117,7 @@
int itable_len,
int static_field_size,
int nonstatic_oop_map_size,
+ unsigned kind,
ReferenceType rt,
AccessFlags access_flags,
bool is_anonymous);
@@ -199,16 +200,30 @@
bool _is_marked_dependent; // used for marking during flushing and deoptimization
bool _has_unloaded_dependent;
+ // The low two bits of _misc_flags contains the kind field.
+ // This can be used to quickly discriminate among the four kinds of
+ // InstanceKlass.
+
+ static const unsigned _misc_kind_field_size = 2;
+ static const unsigned _misc_kind_field_pos = 0;
+ static const unsigned _misc_kind_field_mask = (1u << _misc_kind_field_size) - 1u;
+
+ static const unsigned _misc_kind_other = 0; // concrete InstanceKlass
+ static const unsigned _misc_kind_reference = 1; // InstanceRefKlass
+ static const unsigned _misc_kind_class_loader = 2; // InstanceClassLoaderKlass
+ static const unsigned _misc_kind_mirror = 3; // InstanceMirrorKlass
+
+ // Start after _misc_kind field.
enum {
- _misc_rewritten = 1 << 0, // methods rewritten.
- _misc_has_nonstatic_fields = 1 << 1, // for sizing with UseCompressedOops
- _misc_should_verify_class = 1 << 2, // allow caching of preverification
- _misc_is_anonymous = 1 << 3, // has embedded _host_klass field
- _misc_is_contended = 1 << 4, // marked with contended annotation
- _misc_has_default_methods = 1 << 5, // class/superclass/implemented interfaces has default methods
- _misc_declares_default_methods = 1 << 6, // directly declares default methods (any access)
- _misc_has_been_redefined = 1 << 7, // class has been redefined
- _misc_is_scratch_class = 1 << 8 // class is the redefined scratch class
+ _misc_rewritten = 1 << 2, // methods rewritten.
+ _misc_has_nonstatic_fields = 1 << 3, // for sizing with UseCompressedOops
+ _misc_should_verify_class = 1 << 4, // allow caching of preverification
+ _misc_is_anonymous = 1 << 5, // has embedded _host_klass field
+ _misc_is_contended = 1 << 6, // marked with contended annotation
+ _misc_has_default_methods = 1 << 7, // class/superclass/implemented interfaces has default methods
+ _misc_declares_default_methods = 1 << 8, // directly declares default methods (any access)
+ _misc_has_been_redefined = 1 << 9, // class has been redefined
+ _misc_is_scratch_class = 1 << 10 // class is the redefined scratch class
};
u2 _misc_flags;
u2 _minor_version; // minor version number of class file
@@ -667,6 +682,28 @@
_misc_flags |= _misc_is_scratch_class;
}
+private:
+
+ void set_kind(unsigned kind) {
+ assert(kind <= _misc_kind_field_mask, "Invalid InstanceKlass kind");
+ unsigned fmask = _misc_kind_field_mask << _misc_kind_field_pos;
+ unsigned flags = _misc_flags & ~fmask;
+ _misc_flags = (flags | (kind << _misc_kind_field_pos));
+ }
+
+ bool is_kind(unsigned desired) const {
+ unsigned kind = (_misc_flags >> _misc_kind_field_pos) & _misc_kind_field_mask;
+ return kind == desired;
+ }
+
+public:
+
+ // Other is anything that is not one of the more specialized kinds of InstanceKlass.
+ bool is_other_instance_klass() const { return is_kind(_misc_kind_other); }
+ bool is_reference_instance_klass() const { return is_kind(_misc_kind_reference); }
+ bool is_mirror_instance_klass() const { return is_kind(_misc_kind_mirror); }
+ bool is_class_loader_instance_klass() const { return is_kind(_misc_kind_class_loader); }
+
void init_previous_versions() {
_previous_versions = NULL;
}
@@ -885,9 +922,8 @@
// Casting from Klass*
static InstanceKlass* cast(Klass* k) {
- assert(k == NULL || k->is_klass(), "must be");
assert(k == NULL || k->oop_is_instance(), "cast to InstanceKlass");
- return (InstanceKlass*) k;
+ return static_cast<InstanceKlass*>(k);
}
InstanceKlass* java_super() const {
--- a/hotspot/src/share/vm/oops/instanceMirrorKlass.hpp Fri Oct 09 15:48:30 2015 +0200
+++ b/hotspot/src/share/vm/oops/instanceMirrorKlass.hpp Fri Oct 09 14:08:15 2015 -0400
@@ -48,17 +48,17 @@
// Constructor
InstanceMirrorKlass(int vtable_len, int itable_len, int static_field_size, int nonstatic_oop_map_size, ReferenceType rt, AccessFlags access_flags, bool is_anonymous)
- : InstanceKlass(vtable_len, itable_len, static_field_size, nonstatic_oop_map_size, rt, access_flags, is_anonymous) {}
+ : InstanceKlass(vtable_len, itable_len, static_field_size, nonstatic_oop_map_size,
+ InstanceKlass::_misc_kind_mirror, rt, access_flags, is_anonymous) {}
public:
InstanceMirrorKlass() { assert(DumpSharedSpaces || UseSharedSpaces, "only for CDS"); }
- // Type testing
- bool oop_is_instanceMirror() const { return true; }
// Casting from Klass*
static InstanceMirrorKlass* cast(Klass* k) {
- assert(k->oop_is_instanceMirror(), "cast to InstanceMirrorKlass");
- return (InstanceMirrorKlass*) k;
+ assert(InstanceKlass::cast(k)->is_mirror_instance_klass(),
+ "cast to InstanceMirrorKlass");
+ return static_cast<InstanceMirrorKlass*>(k);
}
// Returns the size of the instance including the extra static fields.
--- a/hotspot/src/share/vm/oops/instanceRefKlass.hpp Fri Oct 09 15:48:30 2015 +0200
+++ b/hotspot/src/share/vm/oops/instanceRefKlass.hpp Fri Oct 09 14:08:15 2015 -0400
@@ -51,18 +51,11 @@
// Constructor
InstanceRefKlass(int vtable_len, int itable_len, int static_field_size, int nonstatic_oop_map_size, ReferenceType rt, AccessFlags access_flags, bool is_anonymous)
- : InstanceKlass(vtable_len, itable_len, static_field_size, nonstatic_oop_map_size, rt, access_flags, is_anonymous) {}
+ : InstanceKlass(vtable_len, itable_len, static_field_size, nonstatic_oop_map_size,
+ InstanceKlass::_misc_kind_reference, rt, access_flags, is_anonymous) {}
public:
InstanceRefKlass() { assert(DumpSharedSpaces || UseSharedSpaces, "only for CDS"); }
- // Type testing
- bool oop_is_instanceRef() const { return true; }
-
- // Casting from Klass*
- static InstanceRefKlass* cast(Klass* k) {
- assert(k->oop_is_instanceRef(), "cast to InstanceRefKlass");
- return (InstanceRefKlass*) k;
- }
// GC specific object visitors
//
--- a/hotspot/src/share/vm/oops/klass.cpp Fri Oct 09 15:48:30 2015 +0200
+++ b/hotspot/src/share/vm/oops/klass.cpp Fri Oct 09 14:08:15 2015 -0400
@@ -715,8 +715,14 @@
class TestKlass {
public:
static void test_oop_is_instanceClassLoader() {
- assert(SystemDictionary::ClassLoader_klass()->oop_is_instanceClassLoader(), "assert");
- assert(!SystemDictionary::String_klass()->oop_is_instanceClassLoader(), "assert");
+ Klass* klass = SystemDictionary::ClassLoader_klass();
+ guarantee(klass->oop_is_instance(), "assert");
+ guarantee(InstanceKlass::cast(klass)->is_class_loader_instance_klass(), "test failed");
+
+ klass = SystemDictionary::String_klass();
+ guarantee(!klass->oop_is_instance() ||
+ !InstanceKlass::cast(klass)->is_class_loader_instance_klass(),
+ "test failed");
}
};
--- a/hotspot/src/share/vm/oops/klass.hpp Fri Oct 09 15:48:30 2015 +0200
+++ b/hotspot/src/share/vm/oops/klass.hpp Fri Oct 09 14:08:15 2015 -0400
@@ -480,9 +480,6 @@
virtual bool oop_is_objArray_slow() const { return false; }
virtual bool oop_is_typeArray_slow() const { return false; }
public:
- virtual bool oop_is_instanceClassLoader() const { return false; }
- virtual bool oop_is_instanceMirror() const { return false; }
- virtual bool oop_is_instanceRef() const { return false; }
// Fast non-virtual versions
#ifndef ASSERT
--- a/hotspot/src/share/vm/oops/oop.inline.hpp Fri Oct 09 15:48:30 2015 +0200
+++ b/hotspot/src/share/vm/oops/oop.inline.hpp Fri Oct 09 14:08:15 2015 -0400
@@ -126,10 +126,25 @@
inline bool oopDesc::is_a(Klass* k) const { return klass()->is_subtype_of(k); }
-inline bool oopDesc::is_instance() const { return klass()->oop_is_instance(); }
-inline bool oopDesc::is_instanceClassLoader() const { return klass()->oop_is_instanceClassLoader(); }
-inline bool oopDesc::is_instanceMirror() const { return klass()->oop_is_instanceMirror(); }
-inline bool oopDesc::is_instanceRef() const { return klass()->oop_is_instanceRef(); }
+inline bool oopDesc::is_instance() const {
+ return klass()->oop_is_instance();
+}
+
+inline bool oopDesc::is_instanceClassLoader() const {
+ Klass* k = klass();
+ return k->oop_is_instance() && InstanceKlass::cast(k)->is_class_loader_instance_klass();
+}
+
+inline bool oopDesc::is_instanceMirror() const {
+ Klass* k = klass();
+ return k->oop_is_instance() && InstanceKlass::cast(k)->is_mirror_instance_klass();
+}
+
+inline bool oopDesc::is_instanceRef() const {
+ Klass* k = klass();
+ return k->oop_is_instance() && InstanceKlass::cast(k)->is_reference_instance_klass();
+}
+
inline bool oopDesc::is_array() const { return klass()->oop_is_array(); }
inline bool oopDesc::is_objArray() const { return klass()->oop_is_objArray(); }
inline bool oopDesc::is_typeArray() const { return klass()->oop_is_typeArray(); }
--- a/hotspot/src/share/vm/prims/jvmtiTagMap.cpp Fri Oct 09 15:48:30 2015 +0200
+++ b/hotspot/src/share/vm/prims/jvmtiTagMap.cpp Fri Oct 09 14:08:15 2015 -0400
@@ -588,7 +588,7 @@
_obj_tag = (_entry == NULL) ? 0 : _entry->tag();
// get the class and the class's tag value
- assert(SystemDictionary::Class_klass()->oop_is_instanceMirror(), "Is not?");
+ assert(InstanceKlass::cast(SystemDictionary::Class_klass())->is_mirror_instance_klass(), "Is not?");
_klass_tag = tag_for(tag_map, _o->klass()->java_mirror());
}