/* * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. * */ #include "ci/ciField.hpp" #include "ci/ciValueKlass.hpp" #include "oops/fieldStreams.hpp" #include "oops/valueKlass.hpp" int ciValueKlass::compute_field_index_map() { assert(is_loaded(), "value class must be loaded to compute mapping of field indeces"); if (_field_index_map != NULL) { return _field_index_map->length(); } Arena* arena = CURRENT_ENV->arena(); guarantee(has_nonstatic_fields(), "value types without fields currently not supported"); // 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); GUARDED_VM_ENTRY( valueKlassHandle vklass_h(ValueKlass::cast(get_Klass())); methodHandle factory_h(vklass_h->factory_method()); if (factory_h.is_null()) { // Value parameter mapping not defined for (JavaFieldStream fs(vklass_h); !fs.done(); fs.next()) { if (fs.access_flags().is_static()) { continue; } _field_index_map->append(fs.field_descriptor().index()); } } else { int valuefactory_length = factory_h->constMethod()->valuefactory_parameter_mapping_length(); assert(valuefactory_length == nof_declared_nonstatic_fields(), "value factory length must be the same as the number of nonstatic declared for the value type"); for (int i = 0; i < nof_declared_nonstatic_fields(); i++) { _field_index_map->append(factory_h->constMethod()->valuefactory_parameter_mapping_start()[i].data.field_index); } } ) return _field_index_map->length(); } // Number of value type fields int ciValueKlass::field_count() { if (_field_index_map == NULL) { return compute_field_index_map(); } else { return _field_index_map->length(); } } // Size of value type fields in words int ciValueKlass::field_size() { int size = 0; for (int i = 0; i < field_count(); ++i) { size += field_type_by_index(i)->size(); } return size; } // Returns the 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 field // in the flattened value type. int ciValueKlass::field_index_by_offset(int offset) { assert(contains_field_offset(offset), "invalid field offset"); int best_offset = 0; int best_index = -1; // Search the field with the given offset for (int i = 0; i < field_count(); ++i) { int field_offset = field_offset_by_index(i); if (field_offset == offset) { // Exact match return i; } else if (field_offset < offset && field_offset > best_offset) { // No exact match. Save the index of the field with the closest offset that // is smaller than the given field offset. This index corresponds to the // flattened value type field that holds the field we are looking for. best_offset = field_offset; best_index = i; } } assert(best_index >= 0, "field not found"); assert(best_offset == offset || field_type_by_index(best_index)->is_valuetype(), "offset should match for non-VTs"); return best_index; } // Returns the field offset of the field with the given index int ciValueKlass::field_offset_by_index(int index) { if (_field_index_map == NULL) { compute_field_index_map(); } GUARDED_VM_ENTRY( valueKlassHandle vklass_h(ValueKlass::cast(get_Klass())); return vklass_h->field_offset(_field_index_map->at(index)); ) } // Returns the field type of the field with the given index ciType* ciValueKlass::field_type_by_index(int index) { int offset = 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::first_field_offset() const { GUARDED_VM_ENTRY( valueKlassHandle vklass_h(ValueKlass::cast(get_Klass())); return vklass_h()->first_field_offset(); ) } bool ciValueKlass::flatten_array() const { GUARDED_VM_ENTRY( valueKlassHandle vklass_h(ValueKlass::cast(get_Klass())); return vklass_h()->flatten_array(); ) } // When passing a value type's fields as arguments, count the number // of argument slots that are needed int ciValueKlass::value_arg_slots() { int slots = nof_nonstatic_fields(); for (int j = 0; j < nof_nonstatic_fields(); j++) { ciField* f = nonstatic_field_at(j); BasicType bt = f->type()->basic_type(); assert(bt != T_VALUETYPE, "embedded"); if (bt == T_LONG || bt == T_DOUBLE) { slots++; } } return slots; }