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 assert(super() == nullptr || !super()->has_nonstatic_fields(), "an inline type must not inherit fields from its superclass"); 34 35 // Compute declared non-static fields (without flattening of inline type fields) 36 GrowableArray<ciField*>* fields = nullptr; 37 GUARDED_VM_ENTRY(fields = compute_nonstatic_fields_impl(nullptr, false /* no flattening */);) 38 Arena* arena = CURRENT_ENV->arena(); 39 _declared_nonstatic_fields = (fields != nullptr) ? fields : new (arena) GrowableArray<ciField*>(arena, 0, 0, 0); 40 return result; 41 } 42 43 // Offset of the first field in the inline type 44 int ciInlineKlass::first_field_offset() const { 45 GUARDED_VM_ENTRY(return to_InlineKlass()->first_field_offset();) 46 } 47 48 // Returns the index of the field with the given offset. If the field at 'offset' 49 // belongs to a flat field, return the index of the field in the inline type of the flat field. 50 int ciInlineKlass::field_index_by_offset(int offset) { 51 assert(contains_field_offset(offset), "invalid field offset"); 52 int best_offset = 0; 53 int best_index = -1; 54 // Search the field with the given offset 55 for (int i = 0; i < nof_declared_nonstatic_fields(); ++i) { 56 int field_offset = _declared_nonstatic_fields->at(i)->offset_in_bytes(); 57 if (field_offset == offset) { 58 // Exact match 59 return i; 60 } else if (field_offset < offset && field_offset > best_offset) { 61 // No exact match. Save the index of the field with the closest offset that 62 // is smaller than the given field offset. This index corresponds to the 63 // flat field that holds the field we are looking for. 64 best_offset = field_offset; 65 best_index = i; 66 } 67 } 68 assert(best_index >= 0, "field not found"); 69 assert(best_offset == offset || _declared_nonstatic_fields->at(best_index)->type()->is_inlinetype(), "offset should match for non-inline types"); 70 return best_index; 71 } 72 73 // Are arrays containing this inline type flat arrays? 74 bool ciInlineKlass::flat_in_array() const { 75 GUARDED_VM_ENTRY(return to_InlineKlass()->flat_array();) 76 } 77 78 // Can this inline type be passed as multiple values? 79 bool ciInlineKlass::can_be_passed_as_fields() const { 80 GUARDED_VM_ENTRY(return to_InlineKlass()->can_be_passed_as_fields();) 81 } 82 83 // Can this inline type be returned as multiple values? 84 bool ciInlineKlass::can_be_returned_as_fields() const { 85 GUARDED_VM_ENTRY(return to_InlineKlass()->can_be_returned_as_fields();) 86 } 87 88 bool ciInlineKlass::is_empty() { 89 // Do not use InlineKlass::is_empty_inline_type here because it does 90 // consider the container empty even if fields of empty inline types 91 // are not flat 92 return nof_nonstatic_fields() == 0; 93 } 94 95 // When passing an inline type's fields as arguments, count the number 96 // of argument slots that are needed 97 int ciInlineKlass::inline_arg_slots() { 98 int slots = 0; 99 for (int j = 0; j < nof_nonstatic_fields(); j++) { 100 ciField* field = nonstatic_field_at(j); 101 slots += type2size[field->type()->basic_type()]; 102 } 103 return slots; 104 } 105 106 // Offset of the default oop in the mirror 107 int ciInlineKlass::default_value_offset() const { 108 GUARDED_VM_ENTRY(return to_InlineKlass()->default_value_offset();) 109 } 110 111 ciInstance* ciInlineKlass::default_instance() const { 112 GUARDED_VM_ENTRY( 113 oop default_value = to_InlineKlass()->default_value(); 114 return CURRENT_ENV->get_instance(default_value); 115 ) 116 } 117 118 bool ciInlineKlass::contains_oops() const { 119 GUARDED_VM_ENTRY(return get_InlineKlass()->contains_oops();) 120 } 121 122 int ciInlineKlass::oop_count() const { 123 GUARDED_VM_ENTRY(return get_InlineKlass()->nonstatic_oop_count();) 124 } 125 126 address ciInlineKlass::pack_handler() const { 127 GUARDED_VM_ENTRY(return get_InlineKlass()->pack_handler();) 128 } 129 130 address ciInlineKlass::unpack_handler() const { 131 GUARDED_VM_ENTRY(return get_InlineKlass()->unpack_handler();) 132 } 133 134 InlineKlass* ciInlineKlass::get_InlineKlass() const { 135 GUARDED_VM_ENTRY(return to_InlineKlass();) 136 } 137