1 /* 2 * Copyright (c) 2011, 2020, 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 #ifndef SHARE_OOPS_FIELDINFO_HPP 26 #define SHARE_OOPS_FIELDINFO_HPP 27 28 #include "oops/constantPool.hpp" 29 #include "oops/symbol.hpp" 30 #include "oops/typeArrayOop.hpp" 31 #include "utilities/vmEnums.hpp" 32 33 // This class represents the field information contained in the fields 34 // array of an InstanceKlass. Currently it's laid on top an array of 35 // Java shorts but in the future it could simply be used as a real 36 // array type. FieldInfo generally shouldn't be used directly. 37 // Fields should be queried either through InstanceKlass or through 38 // the various FieldStreams. 39 class FieldInfo { 40 friend class fieldDescriptor; 41 friend class JavaFieldStream; 42 friend class ClassFileParser; 43 44 public: 45 // fields 46 // Field info extracted from the class file and stored 47 // as an array of 6 shorts. 48 49 #define FIELDINFO_TAG_SIZE 2 50 #define FIELDINFO_TAG_OFFSET 1 << 0 51 #define FIELDINFO_TAG_CONTENDED 1 << 1 52 53 // Packed field has the tag, and can be either of: 54 // hi bits <--------------------------- lo bits 55 // |---------high---------|---------low---------| 56 // ..........................................CO 57 // ..........................................00 - non-contended field 58 // [--contention_group--]....................10 - contended field with contention group 59 // [------------------offset----------------]01 - real field offset 60 61 // Bit O indicates if the packed field contains an offset (O=1) or not (O=0) 62 // Bit C indicates if the field is contended (C=1) or not (C=0) 63 // (if it is contended, the high packed field contains the contention group) 64 65 enum FieldOffset { 66 access_flags_offset = 0, 67 name_index_offset = 1, 68 signature_index_offset = 2, 69 initval_index_offset = 3, 70 low_packed_offset = 4, 71 high_packed_offset = 5, 72 field_slots = 6 73 }; 74 75 private: 76 u2 _shorts[field_slots]; 77 78 void set_name_index(u2 val) { _shorts[name_index_offset] = val; } 79 void set_signature_index(u2 val) { _shorts[signature_index_offset] = val; } 80 void set_initval_index(u2 val) { _shorts[initval_index_offset] = val; } 81 82 u2 name_index() const { return _shorts[name_index_offset]; } 83 u2 signature_index() const { return _shorts[signature_index_offset]; } 84 u2 initval_index() const { return _shorts[initval_index_offset]; } 85 86 public: 87 static FieldInfo* from_field_array(Array<u2>* fields, int index) { 88 return ((FieldInfo*)fields->adr_at(index * field_slots)); 89 } 90 static FieldInfo* from_field_array(u2* fields, int index) { 91 return ((FieldInfo*)(fields + index * field_slots)); 92 } 93 94 void initialize(u2 access_flags, 95 u2 name_index, 96 u2 signature_index, 97 u2 initval_index) { 98 _shorts[access_flags_offset] = access_flags; 99 _shorts[name_index_offset] = name_index; 100 _shorts[signature_index_offset] = signature_index; 101 _shorts[initval_index_offset] = initval_index; 102 _shorts[low_packed_offset] = 0; 103 _shorts[high_packed_offset] = 0; 104 } 105 106 u2 access_flags() const { return _shorts[access_flags_offset]; } 107 u4 offset() const { 108 assert((_shorts[low_packed_offset] & FIELDINFO_TAG_OFFSET) != 0, "Offset must have been set"); 109 return build_int_from_shorts(_shorts[low_packed_offset], _shorts[high_packed_offset]) >> FIELDINFO_TAG_SIZE; 110 } 111 112 bool is_contended() const { 113 return (_shorts[low_packed_offset] & FIELDINFO_TAG_CONTENDED) != 0; 114 } 115 116 u2 contended_group() const { 117 assert((_shorts[low_packed_offset] & FIELDINFO_TAG_OFFSET) == 0, "Offset must not have been set"); 118 assert((_shorts[low_packed_offset] & FIELDINFO_TAG_CONTENDED) != 0, "Field must be contended"); 119 return _shorts[high_packed_offset]; 120 } 121 122 bool is_offset_set() const { 123 return (_shorts[low_packed_offset] & FIELDINFO_TAG_OFFSET)!= 0; 124 } 125 126 Symbol* name(ConstantPool* cp) const { 127 int index = name_index(); 128 if (is_internal()) { 129 return lookup_symbol(index); 130 } 131 return cp->symbol_at(index); 132 } 133 134 Symbol* signature(ConstantPool* cp) const { 135 int index = signature_index(); 136 if (is_internal()) { 137 return lookup_symbol(index); 138 } 139 return cp->symbol_at(index); 140 } 141 142 void set_access_flags(u2 val) { _shorts[access_flags_offset] = val; } 143 void set_offset(u4 val) { 144 val = val << FIELDINFO_TAG_SIZE; // make room for tag 145 _shorts[low_packed_offset] = extract_low_short_from_int(val) | FIELDINFO_TAG_OFFSET; 146 _shorts[high_packed_offset] = extract_high_short_from_int(val); 147 } 148 149 void set_contended_group(u2 val) { 150 assert((_shorts[low_packed_offset] & FIELDINFO_TAG_OFFSET) == 0, "Offset must not have been set"); 151 assert((_shorts[low_packed_offset] & FIELDINFO_TAG_CONTENDED) == 0, "Overwritting contended group"); 152 _shorts[low_packed_offset] |= FIELDINFO_TAG_CONTENDED; 153 _shorts[high_packed_offset] = val; 154 } 155 156 bool is_internal() const { 157 return (access_flags() & JVM_ACC_FIELD_INTERNAL) != 0; 158 } 159 160 bool is_stable() const { 161 return (access_flags() & JVM_ACC_FIELD_STABLE) != 0; 162 } 163 void set_stable(bool z) { 164 if (z) _shorts[access_flags_offset] |= JVM_ACC_FIELD_STABLE; 165 else _shorts[access_flags_offset] &= ~JVM_ACC_FIELD_STABLE; 166 } 167 168 Symbol* lookup_symbol(int symbol_index) const { 169 assert(is_internal(), "only internal fields"); 170 return Symbol::vm_symbol_at(static_cast<vmSymbolID>(symbol_index)); 171 } 172 }; 173 174 #endif // SHARE_OOPS_FIELDINFO_HPP