1 /* 2 * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #include "precompiled.hpp" 26 #include "ci/ciField.hpp" 27 #include "ci/ciInlineKlass.hpp" 28 #include "ci/ciUtilities.inline.hpp" 29 #include "oops/inlineKlass.inline.hpp" 30 31 int ciInlineKlass::compute_nonstatic_fields() { 32 int result = ciInstanceKlass::compute_nonstatic_fields(); 33 34 // Abstract value classes can also have declared fields. 35 ciInstanceKlass* super_klass = super(); 36 GrowableArray<ciField*>* super_klass_fields = nullptr; 37 if (super_klass != nullptr && super_klass->has_nonstatic_fields()) { 38 int super_flen = super_klass->nof_nonstatic_fields(); 39 super_klass_fields = super_klass->_nonstatic_fields; 40 assert(super_flen == 0 || super_klass_fields != nullptr, "first get nof_fields"); 41 } 42 43 // Compute declared non-static fields (without flattening of inline type fields) 44 GrowableArray<ciField*>* fields = nullptr; 45 GUARDED_VM_ENTRY(fields = compute_nonstatic_fields_impl(super_klass_fields, false /* no flattening */);) 46 Arena* arena = CURRENT_ENV->arena(); 47 _declared_nonstatic_fields = (fields != nullptr) ? fields : new (arena) GrowableArray<ciField*>(arena, 0, 0, 0); 48 return result; 49 } 50 51 // Offset of the first field in the inline type 52 int ciInlineKlass::first_field_offset() const { 53 GUARDED_VM_ENTRY(return to_InlineKlass()->first_field_offset();) 54 } 55 56 // Returns the index of the field with the given offset. If the field at 'offset' 57 // belongs to a flat field, return the index of the field in the inline type of the flat field. 58 int ciInlineKlass::field_index_by_offset(int offset) { 59 assert(contains_field_offset(offset), "invalid field offset"); 60 int best_offset = 0; 61 int best_index = -1; 62 // Search the field with the given offset 63 for (int i = 0; i < nof_declared_nonstatic_fields(); ++i) { 64 int field_offset = _declared_nonstatic_fields->at(i)->offset_in_bytes(); 65 if (field_offset == offset) { 66 // Exact match 67 return i; 68 } else if (field_offset < offset && field_offset > best_offset) { 69 // No exact match. Save the index of the field with the closest offset that 70 // is smaller than the given field offset. This index corresponds to the 71 // flat field that holds the field we are looking for. 72 best_offset = field_offset; 73 best_index = i; 74 } 75 } 76 assert(best_index >= 0, "field not found"); 77 assert(best_offset == offset || _declared_nonstatic_fields->at(best_index)->type()->is_inlinetype(), "offset should match for non-inline types"); 78 return best_index; 79 } 80 81 // Are arrays containing this inline type flat arrays? 82 bool ciInlineKlass::flat_in_array() const { 83 GUARDED_VM_ENTRY(return to_InlineKlass()->flat_array();) 84 } 85 86 // Can this inline type be passed as multiple values? 87 bool ciInlineKlass::can_be_passed_as_fields() const { 88 GUARDED_VM_ENTRY(return to_InlineKlass()->can_be_passed_as_fields();) 89 } 90 91 // Can this inline type be returned as multiple values? 92 bool ciInlineKlass::can_be_returned_as_fields() const { 93 GUARDED_VM_ENTRY(return to_InlineKlass()->can_be_returned_as_fields();) 94 } 95 96 bool ciInlineKlass::is_empty() { 97 // Do not use InlineKlass::is_empty_inline_type here because it does 98 // consider the container empty even if fields of empty inline types 99 // are not flat 100 return nof_nonstatic_fields() == 0; 101 } 102 103 // When passing an inline type's fields as arguments, count the number 104 // of argument slots that are needed 105 int ciInlineKlass::inline_arg_slots() { 106 int slots = 0; 107 for (int j = 0; j < nof_nonstatic_fields(); j++) { 108 ciField* field = nonstatic_field_at(j); 109 slots += type2size[field->type()->basic_type()]; 110 } 111 return slots; 112 } 113 114 ciInstance* ciInlineKlass::default_instance() const { 115 GUARDED_VM_ENTRY( 116 oop default_value = to_InlineKlass()->default_value(); 117 return CURRENT_ENV->get_instance(default_value); 118 ) 119 } 120 121 bool ciInlineKlass::contains_oops() const { 122 GUARDED_VM_ENTRY(return get_InlineKlass()->contains_oops();) 123 } 124 125 int ciInlineKlass::oop_count() const { 126 GUARDED_VM_ENTRY(return get_InlineKlass()->nonstatic_oop_count();) 127 } 128 129 address ciInlineKlass::pack_handler() const { 130 GUARDED_VM_ENTRY(return get_InlineKlass()->pack_handler();) 131 } 132 133 address ciInlineKlass::unpack_handler() const { 134 GUARDED_VM_ENTRY(return get_InlineKlass()->unpack_handler();) 135 } 136 137 InlineKlass* ciInlineKlass::get_InlineKlass() const { 138 GUARDED_VM_ENTRY(return to_InlineKlass();) 139 } 140