--- old/src/share/vm/ci/ciInstanceKlass.cpp 2016-11-16 09:06:09.786498515 +0100 +++ new/src/share/vm/ci/ciInstanceKlass.cpp 2016-11-16 09:06:09.714498513 +0100 @@ -397,6 +397,29 @@ } // ------------------------------------------------------------------ +// 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; @@ -500,8 +523,25 @@ 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.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;