8138659: Speed up InstanceKlass subclass discrimination
authorkbarrett
Fri, 09 Oct 2015 14:08:15 -0400
changeset 33151 686d694f5c6a
parent 33150 9e514d10a7bf
child 33154 00ff03917bd4
8138659: Speed up InstanceKlass subclass discrimination Summary: Add _misc_kind field and flags, move around predicates. Reviewed-by: coleenp, stefank
hotspot/src/share/vm/oops/instanceClassLoaderKlass.hpp
hotspot/src/share/vm/oops/instanceKlass.cpp
hotspot/src/share/vm/oops/instanceKlass.hpp
hotspot/src/share/vm/oops/instanceMirrorKlass.hpp
hotspot/src/share/vm/oops/instanceRefKlass.hpp
hotspot/src/share/vm/oops/klass.cpp
hotspot/src/share/vm/oops/klass.hpp
hotspot/src/share/vm/oops/oop.inline.hpp
hotspot/src/share/vm/prims/jvmtiTagMap.cpp
--- 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());
   }