< prev index next >

src/hotspot/share/ci/ciInstanceKlass.cpp

Print this page

        

@@ -25,16 +25,18 @@
 #include "precompiled.hpp"
 #include "ci/ciField.hpp"
 #include "ci/ciInstance.hpp"
 #include "ci/ciInstanceKlass.hpp"
 #include "ci/ciUtilities.inline.hpp"
+#include "ci/ciValueKlass.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "memory/allocation.hpp"
 #include "memory/allocation.inline.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/oop.inline.hpp"
 #include "oops/fieldStreams.hpp"
+#include "oops/valueKlass.hpp"
 #include "runtime/fieldDescriptor.inline.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/jniHandles.inline.hpp"
 
 // ciInstanceKlass

@@ -61,12 +63,13 @@
   _init_state = ik->init_state();
   _nonstatic_field_size = ik->nonstatic_field_size();
   _has_nonstatic_fields = ik->has_nonstatic_fields();
   _has_nonstatic_concrete_methods = ik->has_nonstatic_concrete_methods();
   _is_unsafe_anonymous = ik->is_unsafe_anonymous();
-  _nonstatic_fields = NULL; // initialized lazily by compute_nonstatic_fields:
+  _nonstatic_fields = NULL;            // initialized lazily by compute_nonstatic_fields
   _has_injected_fields = -1;
+  _vcc_klass = NULL;
   _implementor = NULL; // we will fill these lazily
 
   // Ensure that the metadata wrapped by the ciMetadata is kept alive by GC.
   // This is primarily useful for metadata which is considered as weak roots
   // by the GC but need to be strong roots if reachable from a current compilation.

@@ -111,19 +114,21 @@
   _field_cache = NULL;
 }
 
 // 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) != '[', "not an instance klass");
   _init_state = (InstanceKlass::ClassState)0;
   _nonstatic_field_size = -1;
   _has_nonstatic_fields = false;
-  _nonstatic_fields = NULL;
+  _nonstatic_fields = NULL;            // initialized lazily by compute_nonstatic_fields
   _has_injected_fields = -1;
+  _vcc_klass = NULL;
   _is_unsafe_anonymous = false;
   _loader = loader;
   _protection_domain = protection_domain;
   _is_shared = false;
   _super = NULL;

@@ -414,10 +419,33 @@
   }
   ciField* field = new (CURRENT_THREAD_ENV->arena()) ciField(&fd);
   return field;
 }
 
+ciField* ciInstanceKlass::get_non_flattened_field_by_offset(int field_offset) {
+  if (super() != NULL && super()->has_nonstatic_fields()) {
+    ciField* f = super()->get_non_flattened_field_by_offset(field_offset);
+    if (f != NULL) {
+      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 NULL;
+}
+
 // ------------------------------------------------------------------
 // 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();

@@ -481,22 +509,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 flatten) {
   ASSERT_IN_VM;
   Arena* arena = CURRENT_ENV->arena();
   int flen = 0;
   GrowableArray<ciField*>* fields = NULL;
   InstanceKlass* k = get_instanceKlass();

@@ -510,22 +531,46 @@
     return NULL;  // return nothing if none are locally declared
   }
   if (super_fields != NULL) {
     flen += super_fields->length();
   }
+
   fields = new (arena) GrowableArray<ciField*>(arena, flen, 0, NULL);
   if (super_fields != NULL) {
     fields->appendAll(super_fields);
   }
 
   for (JavaFieldStream fs(k); !fs.done(); fs.next()) {
     if (fs.access_flags().is_static())  continue;
     fieldDescriptor& fd = fs.field_descriptor();
+    if (fd.is_flattened() && flatten) {
+      // Value type fields are embedded
+      int field_offset = fd.offset();
+      // Get ValueKlass and adjust number of fields
+      Klass* k = get_instanceKlass()->get_value_field_klass(fd.index());
+      ciValueKlass* vk = CURRENT_ENV->get_klass(k)->as_value_klass();
+      flen += vk->nof_nonstatic_fields() - 1;
+      // Iterate over fields of the flattened value type and copy them to 'this'
+      for (int i = 0; i < vk->nof_nonstatic_fields(); ++i) {
+        ciField* flattened_field = vk->nonstatic_field_at(i);
+        // Adjust offset to account for missing oop header
+        int offset = field_offset + (flattened_field->offset() - vk->first_field_offset());
+        // A flattened field can be treated as final if the non-flattened
+        // field is declared final or the holder klass is a value type itself.
+        bool is_final = fd.is_final() || is_valuetype();
+        ciField* field = new (arena) ciField(flattened_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;

@@ -629,46 +674,83 @@
     return CURRENT_ENV->get_instance_klass(unsafe_anonymous_host);
   }
   return NULL;
 }
 
+ciInstanceKlass* ciInstanceKlass::vcc_klass() {
+  return NULL;
+}
+
 // 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 flattened);
+};
+
+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());
-      switch (fd->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;
+      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 ValueTypeFieldPrinter : public StaticFieldPrinter {
+  oop _obj;
+public:
+  ValueTypeFieldPrinter(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 flattened) {
+  BasicType bt = fd->field_type();
+  switch (bt) {
+    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_cr("%d", *(int*)&f);
+      _out->print("%d", *(int*)&f);
           break;
         }
         case T_DOUBLE: {
           double d = mirror->double_field(fd->offset());
-          _out->print_cr(INT64_FORMAT, *(int64_t*)&d);
+      _out->print(INT64_FORMAT, *(int64_t*)&d);
           break;
         }
         case T_ARRAY:  // fall-through
         case T_OBJECT: {
           oop value =  mirror->obj_field_acquire(fd->offset());

@@ -684,27 +766,47 @@
               _out->print_cr("%s", klass_name);
             }
           } else if (value->is_array()) {
             typeArrayOop ta = (typeArrayOop)value;
             _out->print("%d", ta->length());
-            if (value->is_objArray()) {
+        if (value->is_objArray() || value->is_valueArray()) {
               objArrayOop oa = (objArrayOop)value;
               const char* klass_name  = value->klass()->name()->as_quoted_ascii();
               _out->print(" %s", klass_name);
             }
             _out->cr();
           } else {
             ShouldNotReachHere();
           }
           break;
         }
-        default:
-          ShouldNotReachHere();
+    case T_VALUETYPE: {
+      ResetNoHandleMark rnhm;
+      Thread* THREAD = Thread::current();
+      SignatureStream ss(fd->signature(), false);
+      Symbol* name = ss.as_symbol(THREAD);
+      assert(!HAS_PENDING_EXCEPTION, "can resolve klass?");
+      InstanceKlass* holder = fd->field_holder();
+      Klass* k = SystemDictionary::find(name, Handle(THREAD, holder->class_loader()),
+                                        Handle(THREAD, holder->protection_domain()), THREAD);
+      assert(k != NULL && !HAS_PENDING_EXCEPTION, "can resolve klass?");
+      ValueKlass* vk = ValueKlass::cast(k);
+      oop obj;
+      if (flattened) {
+        int field_offset = fd->offset() - vk->first_field_offset();
+        obj = (oop)((address)mirror + field_offset);
+      } else {
+        obj =  mirror->obj_field_acquire(fd->offset());
         }
+      ValueTypeFieldPrinter print_field(_out, obj);
+      vk->do_nonstatic_fields(&print_field);
+      break;
     }
+    default:
+      ShouldNotReachHere();
   }
-};
+}
 
 
 void ciInstanceKlass::dump_replay_data(outputStream* out) {
   ResourceMark rm;
 
< prev index next >