--- old/src/hotspot/share/classfile/classFileParser.cpp 2017-10-20 11:21:48.164056020 -0400 +++ new/src/hotspot/share/classfile/classFileParser.cpp 2017-10-20 11:21:47.936054890 -0400 @@ -4584,14 +4584,9 @@ } } - for (FieldStream st((InstanceKlass*)defined_klass, false, false); !st.eos(); st.next()) { - Symbol* signature = st.signature(); - if (signature->starts_with("Q")) { - Klass* klass = SystemDictionary::resolve_or_fail(signature, - Handle(THREAD, defined_klass->class_loader()), - Handle(THREAD, defined_klass->protection_domain()), true, CHECK); - assert(klass != NULL, "Sanity check"); - assert(klass->access_flags().is_value_type(), "Value type expected"); + for(int i = 0; i < defined_klass->java_fields_count(); i++) { + if (defined_klass->field_signature(i)->starts_with("Q") && (((defined_klass->field_access_flags(i) & JVM_ACC_STATIC)) == 0)) { + const Klass* klass = defined_klass->get_value_field_klass(i); defining_loader_data->record_dependency(klass, CHECK); } } @@ -5740,11 +5735,8 @@ } } - // Update the loader_data graph. - record_defined_class_dependencies(ik, CHECK); - for(int i = 0; i < ik->java_fields_count(); i++) { - if (ik->field_signature(i)->starts_with("Q")) { + if (ik->field_signature(i)->starts_with("Q") && (((ik->field_access_flags(i) & JVM_ACC_STATIC)) == 0)) { Klass* klass = SystemDictionary::resolve_or_fail(ik->field_signature(i), Handle(THREAD, ik->class_loader()), Handle(THREAD, ik->protection_domain()), true, CHECK); @@ -5754,6 +5746,9 @@ } } + // Update the loader_data graph. + record_defined_class_dependencies(ik, CHECK); + ClassLoadingService::notify_class_loaded(ik, false /* not shared class */); if (!is_internal()) { --- old/src/hotspot/share/interpreter/interpreterRuntime.cpp 2017-10-20 11:21:48.932059829 -0400 +++ new/src/hotspot/share/interpreter/interpreterRuntime.cpp 2017-10-20 11:21:48.720058778 -0400 @@ -369,7 +369,15 @@ int offset = klass->field_offset(index); assert(mirror->obj_field(offset) == NULL,"Field must not be initialized twice"); - Klass* field_k = klass->get_value_field_klass(index); + Klass* field_k = klass->get_value_field_klass_or_null(index); + if (field_k == NULL) { + field_k = SystemDictionary::resolve_or_fail(klass->field_signature(index), + Handle(THREAD, klass->class_loader()), + Handle(THREAD, klass->protection_domain()), true, CHECK); + assert(field_k != NULL, "Sanity check"); + assert(field_k->access_flags().is_value_type(), "Value type expected"); + klass->set_value_field_klass(index, field_k); + } ValueKlass* field_vklass = ValueKlass::cast(field_k); // allocate instance, because it is going to be assigned to a static field // it must not be a buffered value --- old/src/hotspot/share/oops/instanceKlass.hpp 2017-10-20 11:21:49.612063201 -0400 +++ new/src/hotspot/share/oops/instanceKlass.hpp 2017-10-20 11:21:49.340061852 -0400 @@ -1239,7 +1239,7 @@ } } - Klass* get_value_field_klass(int idx) { + 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"); @@ -1247,6 +1247,13 @@ 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"); --- old/test/hotspot/jtreg/runtime/valhalla/valuetypes/ValueTypeCreation.java 2017-10-20 11:21:50.260066414 -0400 +++ new/test/hotspot/jtreg/runtime/valhalla/valuetypes/ValueTypeCreation.java 2017-10-20 11:21:50.024065244 -0400 @@ -43,6 +43,7 @@ testLong8(); // Embedded oops not yet supported //testPerson(); + StaticSelf.test(); } void testPoint() { @@ -72,4 +73,24 @@ Asserts.assertEquals(person.getFirstName(), "John", "First name incorrect"); Asserts.assertEquals(person.getLastName(), "Smith", "Last name incorrect"); } + + static final __ByValue class StaticSelf { + + static final StaticSelf DEFAULT = create(0); + final int f1; + + private StaticSelf() { f1 = 0; } + public String toString() { return "StaticSelf f1=" + f1; } + + __ValueFactory static StaticSelf create(int f1) { + StaticSelf s = __MakeDefault StaticSelf(); + s.f1 = f1; + return s; + } + + public static void test() { + String s = DEFAULT.toString(); + } + + } }