--- old/src/share/vm/ci/ciValueKlass.cpp 2017-06-27 11:16:08.627554814 +0200 +++ new/src/share/vm/ci/ciValueKlass.cpp 2017-06-27 11:16:08.535554818 +0200 @@ -36,12 +36,14 @@ } Arena* arena = CURRENT_ENV->arena(); - guarantee(has_nonstatic_fields(), "value types without fields currently not supported"); + _field_index_map = new (arena) GrowableArray(arena, nof_declared_nonstatic_fields(), 0, 0); + if (!has_nonstatic_fields()) { + return 0; + } // FIXME: Once it is possible to construct class hierarchies with value types. assert(!super()->has_nonstatic_fields(), "a value type must not inherit fields from its superclass"); - _field_index_map = new (arena) GrowableArray(arena, nof_declared_nonstatic_fields(), 0, 0); ValueKlass* vklass = ValueKlass::cast(get_Klass()); for (JavaFieldStream fs(vklass); !fs.done(); fs.next()) { if (fs.access_flags().is_static()) { @@ -54,9 +56,6 @@ // Number of value type fields int ciValueKlass::field_count() { - if (this == ciEnv::current()->___Value_klass()) { - return 0; - } if (_field_index_map == NULL) { return compute_field_index_map(); } else { --- old/src/share/vm/opto/type.cpp 2017-06-27 11:16:08.919554804 +0200 +++ new/src/share/vm/opto/type.cpp 2017-06-27 11:16:08.831554807 +0200 @@ -2452,7 +2452,7 @@ #ifndef PRODUCT void TypeValueType::dump2(Dict &d, uint depth, outputStream* st) const { st->print("valuetype[%d]:{", _vk->field_count()); - st->print("%s", _vk->field_type_by_index(0)->name()); + st->print("%s", _vk->field_count() != 0 ? _vk->field_type_by_index(0)->name() : "empty"); for (int i = 1; i < _vk->field_count(); ++i) { st->print(", %s", _vk->field_type_by_index(i)->name()); } --- old/src/share/vm/opto/valuetypenode.cpp 2017-06-27 11:16:09.295554790 +0200 +++ new/src/share/vm/opto/valuetypenode.cpp 2017-06-27 11:16:09.187554794 +0200 @@ -60,7 +60,7 @@ ValueTypeNode* vt = new ValueTypeNode(type, oop); vt->load(gvn, mem, oop, oop, type->value_klass()); assert(vt->is_allocated(&gvn), "value type should be allocated"); - assert(oop->is_Con() || oop->is_CheckCastPP() || vt->is_loaded(&gvn, type) != NULL, "value type should be loaded"); + assert(oop->is_Con() || oop->is_CheckCastPP() || vt->is_loaded(&gvn, type) == oop, "value type should be loaded"); return gvn.transform(vt); } @@ -72,9 +72,8 @@ // offset of the first field to account for the missing header when loading the values. holder_offset -= vk->first_field_offset(); vt->load(gvn, mem, obj, ptr, holder, holder_offset); - vt = gvn.transform(vt)->as_ValueType(); - assert(!vt->is_allocated(&gvn), "value type should not be allocated"); - return vt; + assert(vt->is_loaded(&gvn, vt->type()->isa_valuetype()) != obj, "holder oop should not be used as flattened value type oop"); + return gvn.transform(vt)->as_ValueType(); } void ValueTypeNode::load(PhaseGVN& gvn, Node* mem, Node* base, Node* ptr, ciInstanceKlass* holder, int holder_offset) { @@ -123,6 +122,11 @@ } Node* ValueTypeNode::is_loaded(PhaseGVN* phase, const TypeValueType* t, Node* base, int holder_offset) { + if (field_count() == 0) { + assert(t->value_klass() == phase->C->env()->___Value_klass(), "unexpected value type klass"); + assert(is_allocated(phase), "must be allocated"); + return get_oop(); + } for (uint i = 0; i < field_count(); ++i) { int offset = holder_offset + field_offset(i); Node* value = field_value(i); @@ -466,6 +470,7 @@ // Save the oop set_oop(base); assert(is_allocated(phase), "should now be allocated"); + return this; } }