8138659: Speed up InstanceKlass subclass discrimination
Add _misc_kind field and flags, move around predicates. Reviewed-by: coleenp, stefank
This commit is contained in:
parent
aeffdfc249
commit
37125920a7
@ -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
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
//
|
||||
|
@ -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");
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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(); }
|
||||
|
@ -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());
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user