--- old/src/share/vm/ci/ciClassList.hpp 2016-12-02 14:22:05.487886103 +0100 +++ new/src/share/vm/ci/ciClassList.hpp 2016-12-02 14:22:05.127886092 +0100 @@ -115,6 +115,7 @@ friend class ciReturnAddress; \ friend class ciKlass; \ friend class ciInstanceKlass; \ +friend class ciValueKlass; \ friend class ciArrayKlass; \ friend class ciObjArrayKlass; \ friend class ciTypeArrayKlass; \ --- old/src/share/vm/ci/ciInstanceKlass.cpp 2016-12-02 14:22:05.699886110 +0100 +++ new/src/share/vm/ci/ciInstanceKlass.cpp 2016-12-02 14:22:05.515886104 +0100 @@ -59,7 +59,8 @@ _has_nonstatic_fields = ik->has_nonstatic_fields(); _has_default_methods = ik->has_default_methods(); _is_anonymous = ik->is_anonymous(); - _nonstatic_fields = NULL; // initialized lazily by compute_nonstatic_fields: + _nonstatic_fields = NULL; // initialized lazily by compute_nonstatic_fields + _nof_declared_nonstatic_fields = -1; // initialized lazily by compute_nonstatic_fields _has_injected_fields = -1; _implementor = NULL; // we will fill these lazily @@ -100,7 +101,8 @@ _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 + _nof_declared_nonstatic_fields = -1; // initialized lazily by compute_nonstatic_fields _has_injected_fields = -1; _is_anonymous = false; _loader = loader; @@ -450,6 +452,7 @@ if (!has_nonstatic_fields()) { Arena* arena = CURRENT_ENV->arena(); _nonstatic_fields = new (arena) GrowableArray(arena, 0, 0, NULL); + _nof_declared_nonstatic_fields = 0; return 0; } assert(!is_java_lang_Object(), "bootstrap OK"); @@ -467,6 +470,7 @@ // See if I am no larger than my super; if so, I can use his fields. if (fsize == super_fsize) { _nonstatic_fields = super_fields; + _nof_declared_nonstatic_fields = super->nof_declared_nonstatic_fields(); return super_fields->length(); } } @@ -480,8 +484,10 @@ // This can happen if this class (java.lang.Class) has invisible fields. if (super_fields != NULL) { _nonstatic_fields = super_fields; + _nof_declared_nonstatic_fields = super->nof_declared_nonstatic_fields(); return super_fields->length(); } else { + _nof_declared_nonstatic_fields = 0; return 0; } } @@ -510,11 +516,15 @@ // allocate the array: if (flen == 0) { + _nof_declared_nonstatic_fields = flen; return NULL; // return nothing if none are locally declared } + if (super_fields != NULL) { flen += super_fields->length(); } + _nof_declared_nonstatic_fields = flen; + fields = new (arena) GrowableArray(arena, flen, 0, NULL); if (super_fields != NULL) { fields->appendAll(super_fields); --- old/src/share/vm/opto/type.cpp 2016-12-02 14:22:05.895886116 +0100 +++ new/src/share/vm/opto/type.cpp 2016-12-02 14:22:05.427886101 +0100 @@ -2210,9 +2210,9 @@ //------------------------------dump2------------------------------------------ #ifndef PRODUCT void TypeValueType::dump2(Dict &d, uint depth, outputStream* st) const { - st->print("valuetype[%d]:{", _vk->param_count()); + st->print("valuetype[%d]:{", _vk->nof_declared_nonstatic_fields()); st->print("%s", _vk->get_field_type_by_index(0)->name()); - for (int i = 1; i < _vk->param_count(); ++i) { + for (int i = 1; i < _vk->nof_declared_nonstatic_fields(); ++i) { st->print(", %s", _vk->get_field_type_by_index(i)->name()); } st->print("}"); --- old/src/share/vm/ci/ciInstanceKlass.hpp 2016-12-02 14:22:05.947886118 +0100 +++ new/src/share/vm/ci/ciInstanceKlass.hpp 2016-12-02 14:22:05.615886107 +0100 @@ -65,6 +65,8 @@ ciConstantPoolCache* _field_cache; // cached map index->field GrowableArray* _nonstatic_fields; + int _nof_declared_nonstatic_fields; // Number of nonstatic fields declared in the bytecode + // i.e., without value types flattened into the instance. int _has_injected_fields; // any non static injected fields? lazily initialized. // The possible values of the _implementor fall into following three cases: @@ -196,6 +198,14 @@ return _nonstatic_fields->length(); } + int nof_declared_nonstatic_fields() { + if (_nonstatic_fields == NULL) { + compute_nonstatic_fields(); + } + assert(_nof_declared_nonstatic_fields >= 0, "after lazy initialization _nof_declared_nonstatic_fields must be at least 0"); + return _nof_declared_nonstatic_fields; + } + bool has_injected_fields() { if (_has_injected_fields == -1) { compute_injected_fields(); --- old/src/share/vm/ci/ciValueKlass.hpp 2016-12-02 14:22:05.959886118 +0100 +++ new/src/share/vm/ci/ciValueKlass.hpp 2016-12-02 14:22:05.675886109 +0100 @@ -48,7 +48,13 @@ int param_count() const; int param_size(); - // Value type fields ('index' refers to the value factory parameter index) + // Value type fields + // + // The term index refers to the index in the VM's constant pool + // (i.e., to the value returned by fieldDescriptor::index()). + // Argument index refers to a field's index in the value factory + // parameter mapping. + int field_index_for_argument(int arg_index); int get_field_count() { return nof_nonstatic_fields(); } int get_field_index_by_offset(int offset); int get_field_offset_by_index(int index) const; --- old/src/share/vm/ci/ciValueKlass.cpp 2016-12-02 14:22:05.927886117 +0100 +++ new/src/share/vm/ci/ciValueKlass.cpp 2016-12-02 14:22:05.487886103 +0100 @@ -28,20 +28,29 @@ // Number of value type factory parameters int ciValueKlass::param_count() const { + VM_ENTRY_MARK valueKlassHandle vklass_h(ValueKlass::cast(get_Klass())); methodHandle factory_h(vklass_h->factory_method()); - return factory_h->constMethod()->valuefactory_parameter_mapping_length(); + int count = factory_h->constMethod()->valuefactory_parameter_mapping_length(); + return count; } // Size of value type factory parameters in words int ciValueKlass::param_size() { int size = 0; - for (int i = 0; i < param_count(); ++i) { + for (int i = 0; i < nof_declared_nonstatic_fields(); ++i) { size += get_field_type_by_index(i)->size(); } return size; } +int ciValueKlass::field_index_for_argument(int argument) { + VM_ENTRY_MARK + valueKlassHandle vklass_h(ValueKlass::cast(get_Klass())); + methodHandle factory_h(vklass_h->factory_method()); + return factory_h->constMethod()->valuefactory_parameter_mapping_start()[argument].data.field_index; +} + // Returns the value factory parameter index of the field with the given offset. // If the field at 'offset' belongs to a flattened value type field, return the // index of the ValueType parameter corresponding to this flattened value type. @@ -50,7 +59,7 @@ int best_offset = 0; int best_index = -1; // Search the field with the given offset - for (int i = 0; i < param_count(); ++i) { + for (int i = 0; i < nof_declared_nonstatic_fields(); ++i) { int field_offset = get_field_offset_by_index(i); if (field_offset == offset) { // Exact match @@ -71,22 +80,23 @@ // Returns the field offset of the value factory parameter with the given index int ciValueKlass::get_field_offset_by_index(int index) const { // Compute the field index from the factory parameter index - valueKlassHandle vklass_h(ValueKlass::cast(get_Klass())); - methodHandle factory_h(vklass_h->factory_method()); - int field_index = factory_h->constMethod()->valuefactory_parameter_mapping_start()[index].data.field_index; - // Get the field offset - return vklass_h->field_offset(field_index); + GUARDED_VM_ENTRY( + valueKlassHandle vklass_h(ValueKlass::cast(get_Klass())); + return vklass_h->field_offset(index); + ) } -// Returns the field type of the value factory parameter with the given index +// Returns the field type of the field with the given index ciType* ciValueKlass::get_field_type_by_index(int index) { + VM_ENTRY_MARK int offset = get_field_offset_by_index(index); - VM_ENTRY_MARK; return get_field_type_by_offset(offset); } // Offset of the first field in the value type int ciValueKlass::get_first_field_offset() const { - valueKlassHandle vklass_h(ValueKlass::cast(get_Klass())); - return vklass_h()->first_field_offset(); + GUARDED_VM_ENTRY( + valueKlassHandle vklass_h(ValueKlass::cast(get_Klass())); + return vklass_h()->first_field_offset(); + ) } --- old/src/share/vm/opto/valuetypenode.hpp 2016-12-02 14:22:05.987886119 +0100 +++ new/src/share/vm/opto/valuetypenode.hpp 2016-12-02 14:22:05.431886101 +0100 @@ -35,7 +35,7 @@ class ValueTypeNode : public TypeNode { private: ValueTypeNode(const TypeValueType* t, Node* oop) - : TypeNode(t, Values + t->value_klass()->param_count()) { + : TypeNode(t, Values + t->value_klass()->nof_declared_nonstatic_fields()) { init_class_id(Class_ValueType); init_req(Oop, oop); } @@ -50,6 +50,8 @@ enum { Control, // Control input Oop, // Oop of TypeValueTypePtr Values // Nodes corresponding to field values + // Field values are connected in increasing order of the index of their VM-internal field + // representation (the index returned by fieldDescriptor::index() for a field). }; public: --- old/src/share/vm/opto/parseHelper.cpp 2016-12-02 14:22:06.063886122 +0100 +++ new/src/share/vm/opto/parseHelper.cpp 2016-12-02 14:22:05.615886107 +0100 @@ -329,10 +329,11 @@ // Pop values from stack (last argument is first) and // connect them to the ValueTypeNode in reverse order. - for (int i = vk->param_count() - 1; i >= 0 ; --i) { - ciType* field_type = vt->get_field_type(i); + for (int arg_index = vk->param_count() - 1; arg_index >= 0 ; --arg_index) { + int field_index = vk->field_index_for_argument(arg_index); + ciType* field_type = vt->get_field_type(field_index); Node* value = field_type->size() == 1 ? pop() : pop_pair(); - vt->set_field_value(i, value); + vt->set_field_value(field_index, value); } push(_gvn.transform(vt)); } --- old/src/share/vm/oops/constMethod.hpp 2016-12-02 14:22:06.091886122 +0100 +++ new/src/share/vm/oops/constMethod.hpp 2016-12-02 14:22:05.619886107 +0100 @@ -129,10 +129,10 @@ class ValueFactoryParameterMappingElement VALUE_OBJ_CLASS_SPEC{ public: union data_t { - u4 field_index; + u4 field_index; // VM-internal field index as returned by fieldDescriptor::index() struct temp_t { - u2 arg_index; - u2 field_index; + u2 arg_index; // Index of argument in the attached factory method + u2 field_index; // Index in the class file's constant pool } temp; } data; };