8138659: Speed up InstanceKlass subclass discrimination

Add _misc_kind field and flags, move around predicates.

Reviewed-by: coleenp, stefank
This commit is contained in:
Kim Barrett 2015-10-09 14:08:15 -04:00
parent aeffdfc249
commit 37125920a7
9 changed files with 88 additions and 40 deletions

View File

@ -41,11 +41,10 @@ class InstanceClassLoaderKlass: public InstanceKlass {
// 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

View File

@ -145,8 +145,8 @@ InstanceKlass* InstanceKlass::allocate_instance_klass(
} 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 @@ InstanceKlass::InstanceKlass(int vtable_len,
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 @@ InstanceKlass::InstanceKlass(int vtable_len,
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");

View File

@ -117,6 +117,7 @@ class InstanceKlass: public Klass {
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 @@ class InstanceKlass: public Klass {
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 @@ class InstanceKlass: public Klass {
_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 @@ class InstanceKlass: public Klass {
// 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 {

View File

@ -48,17 +48,17 @@ class InstanceMirrorKlass: public InstanceKlass {
// 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.

View File

@ -51,18 +51,11 @@ class InstanceRefKlass: public InstanceKlass {
// 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
//

View File

@ -715,8 +715,14 @@ bool Klass::verify_itable_index(int i) {
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");
}
};

View File

@ -480,9 +480,6 @@ protected:
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

View File

@ -126,10 +126,25 @@ inline void oopDesc::init_mark() { set_mark(markOopDesc::proto
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(); }

View File

@ -588,7 +588,7 @@ class CallbackWrapper : public StackObj {
_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());
}