< prev index next >

src/hotspot/share/oops/instanceKlass.hpp

Print this page

        

@@ -24,10 +24,11 @@
 
 #ifndef SHARE_OOPS_INSTANCEKLASS_HPP
 #define SHARE_OOPS_INSTANCEKLASS_HPP
 
 #include "classfile/classLoaderData.hpp"
+#include "code/vmreg.hpp"
 #include "memory/referenceType.hpp"
 #include "oops/annotations.hpp"
 #include "oops/constMethod.hpp"
 #include "oops/fieldInfo.hpp"
 #include "oops/instanceOop.hpp"

@@ -51,10 +52,11 @@
 //      The embedded nonstatic oop-map blocks are short pairs (offset, length)
 //      indicating where oops are located in instances of this klass.
 //    [EMBEDDED implementor of the interface] only exist for interface
 //    [EMBEDDED unsafe_anonymous_host klass] only exist for an unsafe anonymous class (JSR 292 enabled)
 //    [EMBEDDED fingerprint       ] only if should_store_fingerprint()==true
+//    [EMBEDDED ValueKlassFixedBlock] only if is a ValueKlass instance
 
 
 // forward declaration for class -- see below for definition
 #if INCLUDE_JVMTI
 class BreakpointInfo;

@@ -67,10 +69,11 @@
 class jniIdMapBase;
 class JNIid;
 class JvmtiCachedClassFieldMap;
 class nmethodBucket;
 class OopMapCache;
+class BufferedValueTypeBlob;
 class InterpreterOopMap;
 class PackageEntry;
 class ModuleEntry;
 
 // This is used in iterators below.

@@ -100,23 +103,61 @@
 
   // Number of oops in this block.
   uint count() const         { return _count; }
   void set_count(uint count) { _count = count; }
 
+  void increment_count(int diff)     { _count += diff; }
+
+  int offset_span() const { return _count * heapOopSize; }
+
+  int end_offset() const {
+    return offset() + offset_span();
+  }
+
+  bool is_contiguous(int another_offset) const {
+    return another_offset == end_offset();
+  }
+
   // sizeof(OopMapBlock) in words.
   static const int size_in_words() {
     return align_up((int)sizeof(OopMapBlock), wordSize) >>
       LogBytesPerWord;
   }
 
+  static int compare_offset(const OopMapBlock* a, const OopMapBlock* b) {
+    return a->offset() - b->offset();
+  }
+
  private:
   int  _offset;
   uint _count;
 };
 
 struct JvmtiCachedClassFileData;
 
+class SigEntry;
+
+class ValueKlassFixedBlock {
+  Array<SigEntry>** _extended_sig;
+  Array<VMRegPair>** _return_regs;
+  address* _pack_handler;
+  address* _unpack_handler;
+  int* _default_value_offset;
+  Klass** _value_array_klass;
+  int _alignment;
+  int _first_field_offset;
+  int _exact_size_in_bytes;
+
+  friend class ValueKlass;
+};
+
+class ValueTypes {
+public:
+  u2 _class_info_index;
+  Symbol* _class_name;
+};
+
 class InstanceKlass: public Klass {
   friend class VMStructs;
   friend class JVMCIVMStructs;
   friend class ClassFileParser;
   friend class CompileReplay;

@@ -135,11 +176,11 @@
   enum ClassState {
     allocated,                          // allocated (but not yet linked)
     loaded,                             // loaded and inserted in class hierarchy (but not linked yet)
     linked,                             // successfully linked/verified (but not initialized yet)
     being_initialized,                  // currently running class initializer
-    fully_initialized,                  // initialized (successfull final state)
+    fully_initialized,                  // initialized (successful final state)
     initialization_error                // error happened during initialization
   };
 
  private:
   static InstanceKlass* allocate_instance_klass(const ClassFileParser& parser, TRAPS);

@@ -180,10 +221,12 @@
 
   // Resolved nest-host klass: either true nest-host or self if we are not nested.
   // By always being set it makes nest-member access checks simpler.
   InstanceKlass* _nest_host;
 
+  Array<ValueTypes>* _value_types;
+
   // the source debug extension for this klass, NULL if not specified.
   // Specified as UTF-8 string without terminating zero byte in the classfile,
   // it is stored in the instanceklass as a NULL-terminated UTF-8 string
   const char*     _source_debug_extension;
   // Array name derived from this class which needs unreferencing

@@ -206,42 +249,54 @@
 
   int             _itable_len;           // length of Java itable (in words)
   // _is_marked_dependent can be set concurrently, thus cannot be part of the
   // _misc_flags.
   bool            _is_marked_dependent;  // used for marking during flushing and deoptimization
-  bool            _is_being_redefined;   // used for locking redefinition
 
-  // The low two bits of _misc_flags contains the kind field.
-  // This can be used to quickly discriminate among the four kinds of
+ public:
+  enum {
+    _extra_is_being_redefined   = 1 << 0, // used for locking redefinition
+    _extra_has_resolved_methods = 1 << 1, // resolved methods table entries added for this class
+    _extra_has_value_fields     = 1 << 2, // has value fields and related embedded section is not empty
+    _extra_is_bufferable        = 1 << 3, // value can be buffered out side of the Java heap
+    _extra_is_empty_value       = 1 << 4  // empty value type
+  };
+
+ protected:
+  u1              _extra_flags;
+
+  // The low three bits of _misc_flags contains the kind field.
+  // This can be used to quickly discriminate among the five kinds of
   // InstanceKlass.
 
-  static const unsigned _misc_kind_field_size = 2;
+  static const unsigned _misc_kind_field_size = 3;
   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
+  static const unsigned _misc_kind_value_type   = 4; // ValueKlass
 
   // Start after _misc_kind field.
   enum {
-    _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_unsafe_anonymous                 = 1 << 5,  // has embedded _unsafe_anonymous_host field
-    _misc_is_contended                        = 1 << 6,  // marked with contended annotation
-    _misc_has_nonstatic_concrete_methods      = 1 << 7,  // class/superclass/implemented interfaces has non-static, concrete methods
-    _misc_declares_nonstatic_concrete_methods = 1 << 8,  // directly declares non-static, concrete methods
-    _misc_has_been_redefined                  = 1 << 9,  // class has been redefined
-    _misc_has_passed_fingerprint_check        = 1 << 10, // when this class was loaded, the fingerprint computed from its
+    _misc_rewritten                           = 1 << 3,  // methods rewritten.
+    _misc_has_nonstatic_fields                = 1 << 4,  // for sizing with UseCompressedOops
+    _misc_should_verify_class                 = 1 << 5,  // allow caching of preverification
+    _misc_is_unsafe_anonymous                 = 1 << 6,  // has embedded _unsafe_anonymous_host field
+    _misc_is_contended                        = 1 << 7,  // marked with contended annotation
+    _misc_has_nonstatic_concrete_methods      = 1 << 8,  // class/superclass/implemented interfaces has non-static, concrete methods
+    _misc_declares_nonstatic_concrete_methods = 1 << 9,  // directly declares non-static, concrete methods
+    _misc_has_been_redefined                  = 1 << 10,  // class has been redefined
+    _misc_has_passed_fingerprint_check        = 1 << 11, // when this class was loaded, the fingerprint computed from its
                                                          // code source was found to be matching the value recorded by AOT.
-    _misc_is_scratch_class                    = 1 << 11, // class is the redefined scratch class
-    _misc_is_shared_boot_class                = 1 << 12, // defining class loader is boot class loader
-    _misc_is_shared_platform_class            = 1 << 13, // defining class loader is platform class loader
-    _misc_is_shared_app_class                 = 1 << 14, // defining class loader is app class loader
-    _misc_has_resolved_methods                = 1 << 15  // resolved methods table entries added for this class
+    _misc_is_scratch_class                    = 1 << 12, // class is the redefined scratch class
+    _misc_is_shared_boot_class                = 1 << 13, // defining class loader is boot class loader
+    _misc_is_shared_platform_class            = 1 << 14, // defining class loader is platform class loader
+    _misc_is_shared_app_class                 = 1 << 15  // defining class loader is app class loader
+    // u2 _misc_flags full (see _extra_flags)
   };
   u2 loader_type_bits() {
     return _misc_is_shared_boot_class|_misc_is_shared_platform_class|_misc_is_shared_app_class;
   }
   u2              _misc_flags;

@@ -305,10 +360,12 @@
   //     [generic signature index]
   //     [generic signature index]
   //     ...
   Array<u2>*      _fields;
 
+  const ValueKlassFixedBlock* _adr_valueklass_fixed_block;
+
   // embedded Java vtable follows here
   // embedded Java itables follows here
   // embedded static fields follows here
   // embedded nonstatic oop-map blocks follows here
   // embedded implementor of this interface follows here

@@ -359,10 +416,24 @@
     } else {
       _misc_flags &= ~_misc_has_nonstatic_fields;
     }
   }
 
+  bool has_value_fields() const          {
+    return (_extra_flags & _extra_has_value_fields) != 0;
+  }
+  void set_has_value_fields()  {
+    _extra_flags |= _extra_has_value_fields;
+  }
+
+  bool is_empty_value() const {
+    return (_extra_flags & _extra_is_empty_value) != 0;
+  }
+  void set_is_empty_value() {
+    _extra_flags |= _extra_is_empty_value;
+  }
+
   // field sizes
   int nonstatic_field_size() const         { return _nonstatic_field_size; }
   void set_nonstatic_field_size(int size)  { _nonstatic_field_size = size; }
 
   int static_field_size() const            { return _static_field_size; }

@@ -421,10 +492,12 @@
  public:
   int     field_offset      (int index) const { return field(index)->offset(); }
   int     field_access_flags(int index) const { return field(index)->access_flags(); }
   Symbol* field_name        (int index) const { return field(index)->name(constants()); }
   Symbol* field_signature   (int index) const { return field(index)->signature(constants()); }
+  bool    field_is_flattened(int index) const { return field(index)->is_flattened(); }
+  bool    field_is_flattenable(int index) const { return field(index)->is_flattenable(); }
 
   // Number of Java declared fields
   int java_fields_count() const           { return (int)_java_fields_count; }
 
   Array<u2>* fields() const            { return _fields; }

@@ -520,10 +593,12 @@
 
   // marking
   bool is_marked_dependent() const         { return _is_marked_dependent; }
   void set_is_marked_dependent(bool value) { _is_marked_dependent = value; }
 
+  static ByteSize extra_flags_offset() { return in_ByteSize(offset_of(InstanceKlass, _extra_flags)); }
+
   // initialization (virtuals from Klass)
   bool should_be_initialized() const;  // means that initialize should be called
   void initialize(TRAPS);
   void link_class(TRAPS);
   bool link_class_or_fail(TRAPS); // returns false on failure

@@ -556,11 +631,11 @@
   // find instance or static fields according to JVM spec 5.4.3.2, returns the klass in which the field is defined
   Klass* find_field(Symbol* name, Symbol* sig, bool is_static, fieldDescriptor* fd) const;
 
   // find a non-static or static field given its offset within the class.
   bool contains_field_offset(int offset) {
-    return instanceOopDesc::contains_field_offset(offset, nonstatic_field_size());
+    return instanceOopDesc::contains_field_offset(offset, nonstatic_field_size(), is_value());
   }
 
   bool find_local_field_from_offset(int offset, bool is_static, fieldDescriptor* fd) const;
   bool find_field_from_offset(int offset, bool is_static, fieldDescriptor* fd) const;
 

@@ -713,12 +788,20 @@
     _nonstatic_oop_map_size = words;
   }
 
 #if INCLUDE_JVMTI
   // Redefinition locking.  Class can only be redefined by one thread at a time.
-  bool is_being_redefined() const          { return _is_being_redefined; }
-  void set_is_being_redefined(bool value)  { _is_being_redefined = value; }
+  bool is_being_redefined() const          {
+    return (_extra_flags & _extra_is_being_redefined);
+  }
+  void set_is_being_redefined(bool value)  {
+    if (value) {
+      _extra_flags |= _extra_is_being_redefined;
+    } else {
+      _extra_flags &= ~_extra_is_being_redefined;
+    }
+  }
 
   // RedefineClasses() support for previous versions:
   void add_previous_version(InstanceKlass* ik, int emcp_method_count);
   void purge_previous_version_list();
 

@@ -768,15 +851,15 @@
   void set_is_scratch_class() {
     _misc_flags |= _misc_is_scratch_class;
   }
 
   bool has_resolved_methods() const {
-    return (_misc_flags & _misc_has_resolved_methods) != 0;
+    return (_extra_flags & _extra_has_resolved_methods) != 0;
   }
 
   void set_has_resolved_methods() {
-    _misc_flags |= _misc_has_resolved_methods;
+    _extra_flags |= _extra_has_resolved_methods;
   }
 private:
 
   void set_kind(unsigned kind) {
     assert(kind <= _misc_kind_field_mask, "Invalid InstanceKlass kind");

@@ -795,10 +878,11 @@
   // 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); }
+  bool is_value_type_klass()            const { return is_kind(_misc_kind_value_type); }
 
 #if INCLUDE_JVMTI
 
   void init_previous_versions() {
     _previous_versions = NULL;

@@ -970,10 +1054,12 @@
   // support for stub routines
   static ByteSize init_state_offset()  { return in_ByteSize(offset_of(InstanceKlass, _init_state)); }
   JFR_ONLY(DEFINE_KLASS_TRACE_ID_OFFSET;)
   static ByteSize init_thread_offset() { return in_ByteSize(offset_of(InstanceKlass, _init_thread)); }
 
+  static ByteSize adr_valueklass_fixed_block_offset() { return in_ByteSize(offset_of(InstanceKlass, _adr_valueklass_fixed_block)); }
+
   // subclass/subinterface checks
   bool implements_interface(Klass* k) const;
   bool is_same_or_direct_interface(Klass* k) const;
 
 #ifdef ASSERT

@@ -1005,12 +1091,11 @@
   void do_local_static_fields(FieldClosure* cl);
   void do_nonstatic_fields(FieldClosure* cl); // including inherited fields
   void do_local_static_fields(void f(fieldDescriptor*, Handle, TRAPS), Handle, TRAPS);
 
   void methods_do(void f(Method* method));
-  void array_klasses_do(void f(Klass* k));
-  void array_klasses_do(void f(Klass* k, TRAPS), TRAPS);
+  virtual void array_klasses_do(void f(Klass* k));
 
   static InstanceKlass* cast(Klass* k) {
     return const_cast<InstanceKlass*>(cast(const_cast<const Klass*>(k)));
   }
 

@@ -1027,25 +1112,30 @@
   // Sizing (in words)
   static int header_size()            { return sizeof(InstanceKlass)/wordSize; }
 
   static int size(int vtable_length, int itable_length,
                   int nonstatic_oop_map_size,
-                  bool is_interface, bool is_unsafe_anonymous, bool has_stored_fingerprint) {
+                  bool is_interface, bool is_unsafe_anonymous, bool has_stored_fingerprint,
+                  int java_fields, bool is_value_type) {
     return align_metadata_size(header_size() +
            vtable_length +
            itable_length +
            nonstatic_oop_map_size +
            (is_interface ? (int)sizeof(Klass*)/wordSize : 0) +
            (is_unsafe_anonymous ? (int)sizeof(Klass*)/wordSize : 0) +
-           (has_stored_fingerprint ? (int)sizeof(uint64_t*)/wordSize : 0));
+           (has_stored_fingerprint ? (int)sizeof(uint64_t*)/wordSize : 0) +
+           (java_fields * (int)sizeof(Klass*)/wordSize) +
+           (is_value_type ? (int)sizeof(ValueKlassFixedBlock) : 0));
   }
   int size() const                    { return size(vtable_length(),
                                                itable_length(),
                                                nonstatic_oop_map_size(),
                                                is_interface(),
                                                is_unsafe_anonymous(),
-                                               has_stored_fingerprint());
+                                               has_stored_fingerprint(),
+                                               has_value_fields() ? java_fields_count() : 0,
+                                               is_value());
   }
 #if INCLUDE_SERVICES
   virtual void collect_statistics(KlassSizeStats *sz) const;
 #endif
 

@@ -1054,10 +1144,12 @@
 
   int  itable_offset_in_words() const { return start_of_itable() - (intptr_t*)this; }
 
   oop static_field_base_raw() { return java_mirror(); }
 
+  bool bounds_check(address addr, bool edge_ok = false, intptr_t size_in_bytes = -1) const PRODUCT_RETURN0;
+
   OopMapBlock* start_of_nonstatic_oop_maps() const {
     return (OopMapBlock*)(start_of_itable() + itable_length());
   }
 
   Klass** end_of_nonstatic_oop_maps() const {

@@ -1102,12 +1194,57 @@
     } else {
       return NULL;
     }
   }
 
+  address adr_value_fields_klasses() const {
+    if (has_value_fields()) {
+      address adr_fing = adr_fingerprint();
+      if (adr_fing != NULL) {
+        return adr_fingerprint() + sizeof(u8);
+      }
+
+      InstanceKlass** adr_host = adr_unsafe_anonymous_host();
+      if (adr_host != NULL) {
+        return (address)(adr_host + 1);
+      }
+
+      Klass* volatile* adr_impl = adr_implementor();
+      if (adr_impl != NULL) {
+        return (address)(adr_impl + 1);
+      }
+
+      return (address)end_of_nonstatic_oop_maps();
+    } else {
+      return NULL;
+    }
+  }
+
+  Klass* get_value_field_klass(int idx) const {
+    assert(has_value_fields(), "Sanity checking");
+    Klass* k = ((Klass**)adr_value_fields_klasses())[idx];
+    assert(k != NULL, "Should always be set before being read");
+    assert(k->is_value(), "Must be a value type");
+    return k;
+  }
+
+  Klass* get_value_field_klass_or_null(int idx) const {
+    assert(has_value_fields(), "Sanity checking");
+    Klass* k = ((Klass**)adr_value_fields_klasses())[idx];
+    assert(k == NULL || k->is_value(), "Must be a value type");
+    return k;
+  }
+
+  void set_value_field_klass(int idx, Klass* k) {
+    assert(has_value_fields(), "Sanity checking");
+    assert(k != NULL, "Should not be set to NULL");
+    assert(((Klass**)adr_value_fields_klasses())[idx] == NULL, "Should not be set twice");
+    ((Klass**)adr_value_fields_klasses())[idx] = k;
+  }
+
   // Use this to return the size of an instance in heap words:
-  int size_helper() const {
+  virtual int size_helper() const {
     return layout_helper_to_size_helper(layout_helper());
   }
 
   // This bit is initialized in classFileParser.cpp.
   // It is false under any of the following conditions:

@@ -1152,10 +1289,11 @@
   static void unload_class(InstanceKlass* ik);
   static void release_C_heap_structures(InstanceKlass* ik);
 
   // Naming
   const char* signature_name() const;
+  const char* signature_name_of(char c) const;
   static Symbol* package_from_name(const Symbol* name, TRAPS);
 
   // Oop fields (and metadata) iterators
   //
   // The InstanceKlass iterators also visits the Object's klass.

@@ -1245,16 +1383,18 @@
   void initialize_impl                           (TRAPS);
   void initialize_super_interfaces               (TRAPS);
   void eager_initialize_impl                     ();
   /* jni_id_for_impl for jfieldID only */
   JNIid* jni_id_for_impl                         (int offset);
-
+protected:
   // Returns the array class for the n'th dimension
-  Klass* array_klass_impl(bool or_null, int n, TRAPS);
+  virtual Klass* array_klass_impl(ArrayStorageProperties storage_props, bool or_null, int n, TRAPS);
 
   // Returns the array class with this class as element type
-  Klass* array_klass_impl(bool or_null, TRAPS);
+  virtual Klass* array_klass_impl(ArrayStorageProperties storage_props, bool or_null, TRAPS);
+
+private:
 
   // find a local method (returns NULL if not found)
   Method* find_method_impl(const Symbol* name,
                            const Symbol* signature,
                            OverpassLookupMode overpass_mode,
< prev index next >