< prev index next >

src/share/vm/ci/ciInstanceKlass.cpp

Print this page

        

@@ -395,10 +395,33 @@
   ciField* field = new (CURRENT_THREAD_ENV->arena()) ciField(&fd);
   return field;
 }
 
 // ------------------------------------------------------------------
+// ciInstanceKlass::get_field_type_by_offset
+ciType* ciInstanceKlass::get_field_type_by_offset(int field_offset) {
+  ASSERT_IN_VM;
+  fieldDescriptor fd;
+  InstanceKlass* klass = get_instanceKlass();
+  // Important: We cannot get the field type via get_field_by_offset() because if the field
+  // is another value type, the offset would refer to the first field of that value type due
+  // to flattening. Instead, do a SystemDictionary lookup for the type of the declared field.
+  bool found = klass->find_field_from_offset(field_offset, false, &fd);
+  assert(found, "field not found");
+  BasicType field_type = fd.field_type();
+  if (is_java_primitive(field_type)) {
+    // Primitive type
+    return ciType::make(field_type);
+  } else {
+    // Do a SystemDictionary lookup for the type
+    ciEnv* env = CURRENT_ENV;
+    ciSymbol* signature = env->get_symbol(fd.signature());
+    return env->get_klass_by_name_impl(this, constantPoolHandle(), signature, false);
+  }
+}
+
+// ------------------------------------------------------------------
 // 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();
   fieldDescriptor fd;

@@ -498,13 +521,30 @@
   }
 
   for (JavaFieldStream fs(k); !fs.done(); fs.next()) {
     if (fs.access_flags().is_static())  continue;
     fieldDescriptor& fd = fs.field_descriptor();
+    if (fd.field_type() == T_VALUETYPE) {
+      // Value type fields are embedded
+      int field_offset = fd.offset();
+      // Get ValueKlass and adjust number of fields
+      ciValueKlass* vk = get_field_type_by_offset(field_offset)->as_value_klass();
+      flen += vk->get_field_count() - 1;
+      // Iterate over fields of 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->get_first_field_offset());
+        bool is_final = is_valuetype(); // flattened fields are final if holder is a value type
+        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");
   return fields;
 }
 
 bool ciInstanceKlass::compute_injected_fields_helper() {
< prev index next >