< prev index next >

src/hotspot/share/oops/klass.hpp

Print this page
@@ -38,15 +38,17 @@
  #endif
  
  // Klass Kinds for all subclasses of Klass
  enum KlassKind {
    InstanceKlassKind,
+   InlineKlassKind,
    InstanceRefKlassKind,
    InstanceMirrorKlassKind,
    InstanceClassLoaderKlassKind,
    InstanceStackChunkKlassKind,
    TypeArrayKlassKind,
+   FlatArrayKlassKind,
    ObjArrayKlassKind
  };
  
  const uint KLASS_KIND_COUNT = ObjArrayKlassKind + 1;
  

@@ -97,11 +99,11 @@
    //
    // For arrays, layout helper is a negative number, containing four
    // distinct bytes, as follows:
    //    MSB:[tag, hsz, ebt, log2(esz)]:LSB
    // where:
-   //    tag is 0x80 if the elements are oops, 0xC0 if non-oops
+   //    tag is 0x80 if the elements are oops, 0xC0 if non-oops, 0xA0 if value types
    //    hsz is array header size in bytes (i.e., offset of first element)
    //    ebt is the BasicType of the elements
    //    esz is the element size in bytes
    // This packed word is arranged so as to be quickly unpacked by the
    // various fast paths that use the various subfields.

@@ -163,10 +165,11 @@
                                  // contention that may happen when a nearby object is modified.
    AccessFlags _access_flags;    // Access flags. The class/interface distinction is stored here.
  
    JFR_ONLY(DEFINE_TRACE_ID_FIELD;)
  
+   markWord _prototype_header;  // inline type and inline array mark patterns
  private:
    // This is an index into FileMapHeader::_shared_path_table[], to
    // associate this class with the JAR file where it's loaded from during
    // dump time. If a class is not loaded from the shared archive, this field is
    // -1.

@@ -391,15 +394,23 @@
    static const int _lh_log2_element_size_mask  = BitsPerLong-1;
    static const int _lh_element_type_shift      = BitsPerByte*1;
    static const int _lh_element_type_mask       = right_n_bits(BitsPerByte);  // shifted mask
    static const int _lh_header_size_shift       = BitsPerByte*2;
    static const int _lh_header_size_mask        = right_n_bits(BitsPerByte);  // shifted mask
-   static const int _lh_array_tag_bits          = 2;
+   static const int _lh_array_tag_bits          = 3;
    static const int _lh_array_tag_shift         = BitsPerInt - _lh_array_tag_bits;
-   static const int _lh_array_tag_obj_value     = ~0x01;   // 0x80000000 >> 30
  
-   static const unsigned int _lh_array_tag_type_value = 0Xffffffff; // ~0x00,  // 0xC0000000 >> 30
+   static const unsigned int _lh_array_tag_type_value = 0Xfffffffc;
+   static const unsigned int _lh_array_tag_vt_value   = 0Xfffffffd;
+   static const unsigned int _lh_array_tag_obj_value  = 0Xfffffffe;
+ 
+   // null-free array flag bit under the array tag bits, shift one more to get array tag value
+   static const int _lh_null_free_shift = _lh_array_tag_shift - 1;
+   static const int _lh_null_free_mask  = 1;
+ 
+   static const jint _lh_array_tag_flat_value_bit_inplace = (jint) (1 << _lh_array_tag_shift);
+   static const jint _lh_null_free_array_bit_inplace = (jint) (_lh_null_free_mask << _lh_null_free_shift);
  
    static int layout_helper_size_in_bytes(jint lh) {
      assert(lh > (jint)_lh_neutral_value, "must be instance");
      return (int) lh & ~_lh_instance_slow_path_bit;
    }

@@ -412,27 +423,37 @@
    }
    static bool layout_helper_is_array(jint lh) {
      return (jint)lh < (jint)_lh_neutral_value;
    }
    static bool layout_helper_is_typeArray(jint lh) {
-     // _lh_array_tag_type_value == (lh >> _lh_array_tag_shift);
-     return (juint)lh >= (juint)(_lh_array_tag_type_value << _lh_array_tag_shift);
+     return (juint) _lh_array_tag_type_value == (juint)(lh >> _lh_array_tag_shift);
    }
    static bool layout_helper_is_objArray(jint lh) {
-     // _lh_array_tag_obj_value == (lh >> _lh_array_tag_shift);
-     return (jint)lh < (jint)(_lh_array_tag_type_value << _lh_array_tag_shift);
+     return (juint)_lh_array_tag_obj_value == (juint)(lh >> _lh_array_tag_shift);
+   }
+   static bool layout_helper_is_flatArray(jint lh) {
+     return (juint)_lh_array_tag_vt_value == (juint)(lh >> _lh_array_tag_shift);
+   }
+   static bool layout_helper_is_null_free(jint lh) {
+     assert(layout_helper_is_flatArray(lh) || layout_helper_is_objArray(lh), "must be array of inline types");
+     return ((lh >> _lh_null_free_shift) & _lh_null_free_mask);
+   }
+   static jint layout_helper_set_null_free(jint lh) {
+     lh |= (_lh_null_free_mask << _lh_null_free_shift);
+     assert(layout_helper_is_null_free(lh), "Bad encoding");
+     return lh;
    }
    static int layout_helper_header_size(jint lh) {
      assert(lh < (jint)_lh_neutral_value, "must be array");
      int hsize = (lh >> _lh_header_size_shift) & _lh_header_size_mask;
      assert(hsize > 0 && hsize < (int)sizeof(oopDesc)*3, "sanity");
      return hsize;
    }
    static BasicType layout_helper_element_type(jint lh) {
      assert(lh < (jint)_lh_neutral_value, "must be array");
      int btvalue = (lh >> _lh_element_type_shift) & _lh_element_type_mask;
-     assert(btvalue >= T_BOOLEAN && btvalue <= T_OBJECT, "sanity");
+     assert((btvalue >= T_BOOLEAN && btvalue <= T_OBJECT) || btvalue == T_PRIMITIVE_OBJECT, "sanity");
      return (BasicType) btvalue;
    }
  
    // Want a pattern to quickly diff against layout header in register
    // find something less clever!

@@ -449,16 +470,17 @@
    }
  
    static int layout_helper_log2_element_size(jint lh) {
      assert(lh < (jint)_lh_neutral_value, "must be array");
      int l2esz = (lh >> _lh_log2_element_size_shift) & _lh_log2_element_size_mask;
-     assert(l2esz <= LogBytesPerLong,
+     assert(layout_helper_element_type(lh) == T_PRIMITIVE_OBJECT || l2esz <= LogBytesPerLong,
             "sanity. l2esz: 0x%x for lh: 0x%x", (uint)l2esz, (uint)lh);
      return l2esz;
    }
-   static jint array_layout_helper(jint tag, int hsize, BasicType etype, int log2_esize) {
+   static jint array_layout_helper(jint tag, bool null_free, int hsize, BasicType etype, int log2_esize) {
      return (tag        << _lh_array_tag_shift)
+       |    ((null_free ? 1 : 0) <<  _lh_null_free_shift)
        |    (hsize      << _lh_header_size_shift)
        |    ((int)etype << _lh_element_type_shift)
        |    (log2_esize << _lh_log2_element_size_shift);
    }
    static jint instance_layout_helper(jint size, bool slow_path_flag) {

@@ -607,11 +629,14 @@
   protected:
    virtual bool is_instance_klass_slow()     const { return false; }
    virtual bool is_array_klass_slow()        const { return false; }
    virtual bool is_objArray_klass_slow()     const { return false; }
    virtual bool is_typeArray_klass_slow()    const { return false; }
+   virtual bool is_flatArray_klass_slow()    const { return false; }
  #endif // ASSERT
+   // current implementation uses this method even in non debug builds
+   virtual bool is_inline_klass_slow()       const { return false; }
   public:
  
    // Fast non-virtual versions
    #ifndef ASSERT
    #define assert_same_query(xval, xcheck) xval

@@ -623,31 +648,36 @@
    }
   public:
    #endif
  
    bool is_instance_klass()              const { return assert_same_query(_kind <= InstanceStackChunkKlassKind, is_instance_klass_slow()); }
+   bool is_inline_klass()                const { return is_inline_klass_slow(); } //temporary hack
    // Other is anything that is not one of the more specialized kinds of InstanceKlass.
-   bool is_other_instance_klass()        const { return _kind == InstanceKlassKind; }
+   bool is_other_instance_klass()        const { return _kind <= InlineKlassKind; }
    bool is_reference_instance_klass()    const { return _kind == InstanceRefKlassKind; }
    bool is_mirror_instance_klass()       const { return _kind == InstanceMirrorKlassKind; }
    bool is_class_loader_instance_klass() const { return _kind == InstanceClassLoaderKlassKind; }
    bool is_array_klass()                 const { return assert_same_query( _kind >= TypeArrayKlassKind, is_array_klass_slow()); }
    bool is_stack_chunk_instance_klass()  const { return _kind == InstanceStackChunkKlassKind; }
+   bool is_flatArray_klass()             const { return assert_same_query( _kind == FlatArrayKlassKind, is_flatArray_klass_slow()); }
    bool is_objArray_klass()              const { return assert_same_query( _kind == ObjArrayKlassKind,  is_objArray_klass_slow()); }
    bool is_typeArray_klass()             const { return assert_same_query( _kind == TypeArrayKlassKind, is_typeArray_klass_slow()); }
    #undef assert_same_query
  
+   inline bool is_null_free_array_klass()      const { return layout_helper_is_null_free(layout_helper()); }
+ 
    // Access flags
    AccessFlags access_flags() const         { return _access_flags;  }
    void set_access_flags(AccessFlags flags) { _access_flags = flags; }
  
    bool is_public() const                { return _access_flags.is_public(); }
    bool is_final() const                 { return _access_flags.is_final(); }
    bool is_interface() const             { return _access_flags.is_interface(); }
    bool is_abstract() const              { return _access_flags.is_abstract(); }
-   bool is_super() const                 { return _access_flags.is_super(); }
    bool is_synthetic() const             { return _access_flags.is_synthetic(); }
+   bool is_value_class() const           { return _access_flags.is_value_class(); }
+   bool is_identity_class() const        { return _access_flags.is_identity_class(); }
    void set_is_synthetic()               { _access_flags.set_is_synthetic(); }
    bool has_finalizer() const            { return _access_flags.has_finalizer(); }
    bool has_final_method() const         { return _access_flags.has_final_method(); }
    void set_has_finalizer()              { _access_flags.set_has_finalizer(); }
    void set_has_final_method()           { _access_flags.set_has_final_method(); }

@@ -665,10 +695,21 @@
    inline bool is_non_strong_hidden() const;
  
    bool is_cloneable() const;
    void set_is_cloneable();
  
+   // inline types and inline type array patterns
+   markWord prototype_header() const {
+     return _prototype_header;
+   }
+   static inline markWord default_prototype_header(Klass* k) {
+     return (k == NULL) ? markWord::prototype() : k->prototype_header();
+   }
+ 
+   inline void set_prototype_header(markWord header);
+   static ByteSize prototype_header_offset() { return in_ByteSize(offset_of(Klass, _prototype_header)); }
+ 
    JFR_ONLY(DEFINE_TRACE_ID_METHODS;)
  
    virtual void metaspace_pointers_do(MetaspaceClosure* iter);
    virtual MetaspaceObj::Type type() const { return ClassType; }
  
< prev index next >