< prev index next >

src/hotspot/share/ci/ciInstanceKlass.cpp

Print this page
@@ -22,22 +22,25 @@
   *
   */
  
  #include "precompiled.hpp"
  #include "ci/ciField.hpp"
+ #include "ci/ciInlineKlass.hpp"
  #include "ci/ciInstance.hpp"
  #include "ci/ciInstanceKlass.hpp"
  #include "ci/ciUtilities.inline.hpp"
  #include "classfile/javaClasses.hpp"
+ #include "classfile/systemDictionary.hpp"
  #include "classfile/vmClasses.hpp"
  #include "memory/allocation.hpp"
  #include "memory/allocation.inline.hpp"
  #include "memory/resourceArea.hpp"
  #include "oops/instanceKlass.inline.hpp"
  #include "oops/klass.inline.hpp"
  #include "oops/oop.inline.hpp"
  #include "oops/fieldStreams.inline.hpp"
+ #include "oops/inlineKlass.inline.hpp"
  #include "runtime/fieldDescriptor.inline.hpp"
  #include "runtime/handles.inline.hpp"
  #include "runtime/jniHandles.inline.hpp"
  
  // ciInstanceKlass

@@ -117,17 +120,18 @@
    _field_cache = nullptr;
  }
  
  // Version for unloaded classes:
  ciInstanceKlass::ciInstanceKlass(ciSymbol* name,
-                                  jobject loader, jobject protection_domain)
-   : ciKlass(name, T_OBJECT)
+                                  jobject loader, jobject protection_domain,
+                                  BasicType bt)
+   : ciKlass(name, bt)
  {
    assert(name->char_at(0) != JVM_SIGNATURE_ARRAY, "not an instance klass");
    _init_state = (InstanceKlass::ClassState)0;
    _has_nonstatic_fields = false;
-   _nonstatic_fields = nullptr;
+   _nonstatic_fields = nullptr;         // initialized lazily by compute_nonstatic_fields
    _has_injected_fields = -1;
    _is_hidden = false;
    _is_record = false;
    _loader = loader;
    _protection_domain = protection_domain;

@@ -335,15 +339,15 @@
                bool_to_str(is_initialized()),
                bool_to_str(has_finalizer()),
                bool_to_str(has_subklass()),
                layout_helper());
  
-     _flags.print_klass_flags();
+     _flags.print_klass_flags(st);
  
      if (_super) {
        st->print(" super=");
-       _super->print_name();
+       _super->print_name_on(st);
      }
      if (_java_mirror) {
        st->print(" mirror=PRESENT");
      }
    }

@@ -433,10 +437,33 @@
    }
    ciField* field = new (CURRENT_THREAD_ENV->arena()) ciField(&fd);
    return field;
  }
  
+ ciField* ciInstanceKlass::get_non_flat_field_by_offset(int field_offset) {
+   if (super() != nullptr && super()->has_nonstatic_fields()) {
+     ciField* f = super()->get_non_flat_field_by_offset(field_offset);
+     if (f != nullptr) {
+       return f;
+     }
+   }
+ 
+   VM_ENTRY_MARK;
+   InstanceKlass* k = get_instanceKlass();
+   Arena* arena = CURRENT_ENV->arena();
+   for (JavaFieldStream fs(k); !fs.done(); fs.next()) {
+     if (fs.access_flags().is_static())  continue;
+     fieldDescriptor& fd = fs.field_descriptor();
+     if (fd.offset() == field_offset) {
+       ciField* f = new (arena) ciField(&fd);
+       return f;
+     }
+   }
+ 
+   return nullptr;
+ }
+ 
  // ------------------------------------------------------------------
  // ciInstanceKlass::get_field_by_name
  ciField* ciInstanceKlass::get_field_by_name(ciSymbol* name, ciSymbol* signature, bool is_static) {
    VM_ENTRY_MARK;
    InstanceKlass* k = get_instanceKlass();

@@ -491,22 +518,15 @@
      } else {
        return 0;
      }
    }
  
-   int flen = fields->length();
- 
-   // Now sort them by offset, ascending.
-   // (In principle, they could mix with superclass fields.)
-   fields->sort(sort_field_by_offset);
    _nonstatic_fields = fields;
-   return flen;
+   return fields->length();
  }
  
- GrowableArray<ciField*>*
- ciInstanceKlass::compute_nonstatic_fields_impl(GrowableArray<ciField*>*
-                                                super_fields) {
+ GrowableArray<ciField*>* ciInstanceKlass::compute_nonstatic_fields_impl(GrowableArray<ciField*>* super_fields, bool is_flat) {
    ASSERT_IN_VM;
    Arena* arena = CURRENT_ENV->arena();
    int flen = 0;
    GrowableArray<ciField*>* fields = nullptr;
    InstanceKlass* k = get_instanceKlass();

@@ -528,14 +548,37 @@
    }
  
    for (JavaFieldStream fs(k); !fs.done(); fs.next()) {
      if (fs.access_flags().is_static())  continue;
      fieldDescriptor& fd = fs.field_descriptor();
-     ciField* field = new (arena) ciField(&fd);
-     fields->append(field);
+     if (fd.is_flat() && is_flat) {
+       // Inline type fields are embedded
+       int field_offset = fd.offset();
+       // Get InlineKlass and adjust number of fields
+       Klass* k = get_instanceKlass()->get_inline_type_field_klass(fd.index());
+       ciInlineKlass* vk = CURRENT_ENV->get_klass(k)->as_inline_klass();
+       flen += vk->nof_nonstatic_fields() - 1;
+       // Iterate over fields of the flat inline type and copy them to 'this'
+       for (int i = 0; i < vk->nof_nonstatic_fields(); ++i) {
+         ciField* flat_field = vk->nonstatic_field_at(i);
+         // Adjust offset to account for missing oop header
+         int offset = field_offset + (flat_field->offset_in_bytes() - vk->first_field_offset());
+         // A flat field can be treated as final if the non-flat
+         // field is declared final or the holder klass is an inline type itself.
+         bool is_final = fd.is_final() || is_inlinetype();
+         ciField* field = new (arena) ciField(flat_field, this, offset, is_final);
+         fields->append(field);
+       }
+     } else {
+       ciField* field = new (arena) ciField(&fd);
+       fields->append(field);
+     }
    }
    assert(fields->length() == flen, "sanity");
+   // Now sort them by offset, ascending.
+   // (In principle, they could mix with superclass fields.)
+   fields->sort(sort_field_by_offset);
    return fields;
  }
  
  bool ciInstanceKlass::compute_injected_fields_helper() {
    ASSERT_IN_VM;

@@ -638,86 +681,156 @@
      _implementor = impl;
    }
    return impl;
  }
  
+ bool ciInstanceKlass::can_be_inline_klass(bool is_exact) {
+   if (!EnableValhalla) {
+     return false;
+   }
+   if (!is_loaded() || is_inlinetype()) {
+     // Not loaded or known to be an inline klass
+     return true;
+   }
+   if (!is_exact) {
+     // Not exact, check if this is a valid super for an inline klass
+     VM_ENTRY_MARK;
+     return !get_instanceKlass()->access_flags().is_identity_class() || is_java_lang_Object() ;
+   }
+   return false;
+ }
+ 
  // Utility class for printing of the contents of the static fields for
  // use by compilation replay.  It only prints out the information that
  // could be consumed by the compiler, so for primitive types it prints
  // out the actual value.  For Strings it's the actual string value.
  // For array types it it's first level array size since that's the
  // only value which statically unchangeable.  For all other reference
  // types it simply prints out the dynamic type.
  
- class StaticFinalFieldPrinter : public FieldClosure {
+ class StaticFieldPrinter : public FieldClosure {
+ protected:
    outputStream* _out;
+ public:
+   StaticFieldPrinter(outputStream* out) :
+     _out(out) {
+   }
+   void do_field_helper(fieldDescriptor* fd, oop obj, bool is_flat);
+ };
+ 
+ class StaticFinalFieldPrinter : public StaticFieldPrinter {
    const char*   _holder;
   public:
    StaticFinalFieldPrinter(outputStream* out, const char* holder) :
-     _out(out),
-     _holder(holder) {
+     StaticFieldPrinter(out), _holder(holder) {
    }
    void do_field(fieldDescriptor* fd) {
      if (fd->is_final() && !fd->has_initial_value()) {
        ResourceMark rm;
-       oop mirror = fd->field_holder()->java_mirror();
-       _out->print("staticfield %s %s %s ", _holder, fd->name()->as_quoted_ascii(), fd->signature()->as_quoted_ascii());
-       BasicType field_type = fd->field_type();
-       switch (field_type) {
-         case T_BYTE:    _out->print_cr("%d", mirror->byte_field(fd->offset()));   break;
-         case T_BOOLEAN: _out->print_cr("%d", mirror->bool_field(fd->offset()));   break;
-         case T_SHORT:   _out->print_cr("%d", mirror->short_field(fd->offset()));  break;
-         case T_CHAR:    _out->print_cr("%d", mirror->char_field(fd->offset()));   break;
-         case T_INT:     _out->print_cr("%d", mirror->int_field(fd->offset()));    break;
-         case T_LONG:    _out->print_cr(INT64_FORMAT, (int64_t)(mirror->long_field(fd->offset())));   break;
-         case T_FLOAT: {
-           float f = mirror->float_field(fd->offset());
-           _out->print_cr("%d", *(int*)&f);
-           break;
-         }
-         case T_DOUBLE: {
-           double d = mirror->double_field(fd->offset());
-           _out->print_cr(INT64_FORMAT, *(int64_t*)&d);
-           break;
-         }
-         case T_ARRAY:  // fall-through
-         case T_OBJECT: {
-           oop value =  mirror->obj_field_acquire(fd->offset());
-           if (value == nullptr) {
-             if (field_type == T_ARRAY) {
-               _out->print("%d", -1);
-             }
-             _out->cr();
-           } else if (value->is_instance()) {
-             assert(field_type == T_OBJECT, "");
-             if (value->is_a(vmClasses::String_klass())) {
-               const char* ascii_value = java_lang_String::as_quoted_ascii(value);
-               _out->print_cr("\"%s\"", (ascii_value != nullptr) ? ascii_value : "");
-             } else {
-               const char* klass_name  = value->klass()->name()->as_quoted_ascii();
-               _out->print_cr("%s", klass_name);
-             }
-           } else if (value->is_array()) {
-             typeArrayOop ta = (typeArrayOop)value;
-             _out->print("%d", ta->length());
-             if (value->is_objArray()) {
-               objArrayOop oa = (objArrayOop)value;
-               const char* klass_name  = value->klass()->name()->as_quoted_ascii();
-               _out->print(" %s", klass_name);
-             }
-             _out->cr();
+       InstanceKlass* holder = fd->field_holder();
+       oop mirror = holder->java_mirror();
+       _out->print("staticfield %s %s ", _holder, fd->name()->as_quoted_ascii());
+       BasicType bt = fd->field_type();
+       if (bt != T_OBJECT && bt != T_ARRAY) {
+         _out->print("%s ", fd->signature()->as_quoted_ascii());
+       }
+       do_field_helper(fd, mirror, false);
+       _out->cr();
+     }
+   }
+ };
+ 
+ class InlineTypeFieldPrinter : public StaticFieldPrinter {
+   oop _obj;
+ public:
+   InlineTypeFieldPrinter(outputStream* out, oop obj) :
+     StaticFieldPrinter(out), _obj(obj) {
+   }
+   void do_field(fieldDescriptor* fd) {
+     do_field_helper(fd, _obj, true);
+     _out->print(" ");
+   }
+ };
+ 
+ void StaticFieldPrinter::do_field_helper(fieldDescriptor* fd, oop mirror, bool is_flat) {
+   BasicType field_type = fd->field_type();
+   switch (field_type) {
+     case T_BYTE:    _out->print("%d", mirror->byte_field(fd->offset()));   break;
+     case T_BOOLEAN: _out->print("%d", mirror->bool_field(fd->offset()));   break;
+     case T_SHORT:   _out->print("%d", mirror->short_field(fd->offset()));  break;
+     case T_CHAR:    _out->print("%d", mirror->char_field(fd->offset()));   break;
+     case T_INT:     _out->print("%d", mirror->int_field(fd->offset()));    break;
+     case T_LONG:    _out->print(INT64_FORMAT, (int64_t)(mirror->long_field(fd->offset())));   break;
+     case T_FLOAT: {
+       float f = mirror->float_field(fd->offset());
+       _out->print("%d", *(int*)&f);
+       break;
+     }
+     case T_DOUBLE: {
+       double d = mirror->double_field(fd->offset());
+       _out->print(INT64_FORMAT, *(int64_t*)&d);
+       break;
+     }
+     case T_ARRAY:  // fall-through
+     case T_OBJECT:
+       if (!fd->is_null_free_inline_type()) {
+         _out->print("%s ", fd->signature()->as_quoted_ascii());
+         oop value =  mirror->obj_field_acquire(fd->offset());
+         if (value == nullptr) {
+           if (field_type == T_ARRAY) {
+             _out->print("%d", -1);
+           }
+           _out->cr();
+         } else if (value->is_instance()) {
+           assert(field_type == T_OBJECT, "");
+           if (value->is_a(vmClasses::String_klass())) {
+             const char* ascii_value = java_lang_String::as_quoted_ascii(value);
+             _out->print("\"%s\"", (ascii_value != nullptr) ? ascii_value : "");
            } else {
-             ShouldNotReachHere();
+             const char* klass_name  = value->klass()->name()->as_quoted_ascii();
+             _out->print("%s", klass_name);
            }
-           break;
-         }
-         default:
+         } else if (value->is_array()) {
+           typeArrayOop ta = (typeArrayOop)value;
+           _out->print("%d", ta->length());
+           if (value->is_objArray() || value->is_flatArray()) {
+             objArrayOop oa = (objArrayOop)value;
+             const char* klass_name  = value->klass()->name()->as_quoted_ascii();
+             _out->print(" %s", klass_name);
+           }
+         } else {
            ShouldNotReachHere();
          }
-     }
+         break;
+       } else {
+         // handling of null free inline type
+         ResetNoHandleMark rnhm;
+         Thread* THREAD = Thread::current();
+         SignatureStream ss(fd->signature(), false);
+         Symbol* name = ss.as_symbol();
+         assert(!HAS_PENDING_EXCEPTION, "can resolve klass?");
+         InstanceKlass* holder = fd->field_holder();
+         InstanceKlass* k = SystemDictionary::find_instance_klass(THREAD, name,
+                                                                  Handle(THREAD, holder->class_loader()),
+                                                                  Handle(THREAD, holder->protection_domain()));
+         assert(k != nullptr && !HAS_PENDING_EXCEPTION, "can resolve klass?");
+         InlineKlass* vk = InlineKlass::cast(k);
+         oop obj;
+         if (is_flat) {
+           int field_offset = fd->offset() - vk->first_field_offset();
+           obj = cast_to_oop(cast_from_oop<address>(mirror) + field_offset);
+         } else {
+           obj = mirror->obj_field_acquire(fd->offset());
+         }
+         InlineTypeFieldPrinter print_field(_out, obj);
+         vk->do_nonstatic_fields(&print_field);
+         break;
+       }
+     default:
+       ShouldNotReachHere();
    }
- };
+ }
  
  const char *ciInstanceKlass::replay_name() const {
    return CURRENT_ENV->replay_name(get_instanceKlass());
  }
  
< prev index next >