1 /* 2 * Copyright (c) 2011, 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 #ifndef SHARE_OOPS_FIELDINFO_HPP 26 #define SHARE_OOPS_FIELDINFO_HPP 27 28 #include "oops/constantPool.hpp" 29 #include "oops/typeArrayOop.hpp" 30 #include "classfile/vmSymbols.hpp" 31 32 // This class represents the field information contained in the fields 33 // array of an InstanceKlass. Currently it's laid on top an array of 34 // Java shorts but in the future it could simply be used as a real 35 // array type. FieldInfo generally shouldn't be used directly. 36 // Fields should be queried either through InstanceKlass or through 37 // the various FieldStreams. 38 class FieldInfo { 39 friend class fieldDescriptor; 40 friend class JavaFieldStream; 41 friend class ClassFileParser; 42 43 public: 44 // fields 45 // Field info extracted from the class file and stored 46 // as an array of 6 shorts. 47 48 #define FIELDINFO_TAG_SIZE 2 49 #define FIELDINFO_TAG_BLANK 0 50 #define FIELDINFO_TAG_OFFSET 1 51 #define FIELDINFO_TAG_TYPE_PLAIN 2 52 #define FIELDINFO_TAG_TYPE_CONTENDED 3 53 #define FIELDINFO_TAG_MASK 3 54 55 // Packed field has the tag, and can be either of: 56 // hi bits <--------------------------- lo bits 57 // |---------high---------|---------low---------| 58 // ..........................................00 - blank 59 // [------------------offset----------------]01 - real field offset 60 // ......................[-------type-------]10 - plain field with type 61 // [--contention_group--][-------type-------]11 - contended field with type and contention group 62 enum FieldOffset { 63 access_flags_offset = 0, 64 name_index_offset = 1, 65 signature_index_offset = 2, 66 initval_index_offset = 3, 67 low_packed_offset = 4, 68 high_packed_offset = 5, 69 field_slots = 6 70 }; 71 72 private: 73 u2 _shorts[field_slots]; 74 75 void set_name_index(u2 val) { _shorts[name_index_offset] = val; } 76 void set_signature_index(u2 val) { _shorts[signature_index_offset] = val; } 77 void set_initval_index(u2 val) { _shorts[initval_index_offset] = val; } 78 79 u2 name_index() const { return _shorts[name_index_offset]; } 80 u2 signature_index() const { return _shorts[signature_index_offset]; } 81 u2 initval_index() const { return _shorts[initval_index_offset]; } 82 83 public: 84 static FieldInfo* from_field_array(Array<u2>* fields, int index) { 85 return ((FieldInfo*)fields->adr_at(index * field_slots)); 86 } 87 static FieldInfo* from_field_array(u2* fields, int index) { 88 return ((FieldInfo*)(fields + index * field_slots)); 89 } 90 91 void initialize(u2 access_flags, 92 u2 name_index, 93 u2 signature_index, 94 u2 initval_index) { 95 _shorts[access_flags_offset] = access_flags; 96 _shorts[name_index_offset] = name_index; 97 _shorts[signature_index_offset] = signature_index; 98 _shorts[initval_index_offset] = initval_index; 99 _shorts[low_packed_offset] = 0; 100 _shorts[high_packed_offset] = 0; 101 } 102 103 u2 access_flags() const { return _shorts[access_flags_offset]; } 104 u4 offset() const { 105 u2 lo = _shorts[low_packed_offset]; 106 switch(lo & FIELDINFO_TAG_MASK) { 107 case FIELDINFO_TAG_OFFSET: 108 return build_int_from_shorts(_shorts[low_packed_offset], _shorts[high_packed_offset]) >> FIELDINFO_TAG_SIZE; 109 #ifndef PRODUCT 110 case FIELDINFO_TAG_TYPE_PLAIN: 111 fatal("Asking offset for the plain type field"); 112 case FIELDINFO_TAG_TYPE_CONTENDED: 113 fatal("Asking offset for the contended type field"); 114 case FIELDINFO_TAG_BLANK: 115 fatal("Asking offset for the blank field"); 116 #endif 117 } 118 ShouldNotReachHere(); 119 return 0; 120 } 121 122 bool is_contended() const { 123 u2 lo = _shorts[low_packed_offset]; 124 switch(lo & FIELDINFO_TAG_MASK) { 125 case FIELDINFO_TAG_TYPE_PLAIN: 126 return false; 127 case FIELDINFO_TAG_TYPE_CONTENDED: 128 return true; 129 #ifndef PRODUCT 130 case FIELDINFO_TAG_OFFSET: 131 fatal("Asking contended flag for the field with offset"); 132 case FIELDINFO_TAG_BLANK: 133 fatal("Asking contended flag for the blank field"); 134 #endif 135 } 136 ShouldNotReachHere(); 137 return false; 138 } 139 140 u2 contended_group() const { 141 u2 lo = _shorts[low_packed_offset]; 142 switch(lo & FIELDINFO_TAG_MASK) { 143 case FIELDINFO_TAG_TYPE_PLAIN: 144 return 0; 145 case FIELDINFO_TAG_TYPE_CONTENDED: 146 return _shorts[high_packed_offset]; 147 #ifndef PRODUCT 148 case FIELDINFO_TAG_OFFSET: 149 fatal("Asking the contended group for the field with offset"); 150 case FIELDINFO_TAG_BLANK: 151 fatal("Asking the contended group for the blank field"); 152 #endif 153 } 154 ShouldNotReachHere(); 155 return 0; 156 } 157 158 u2 allocation_type() const { 159 u2 lo = _shorts[low_packed_offset]; 160 switch(lo & FIELDINFO_TAG_MASK) { 161 case FIELDINFO_TAG_TYPE_PLAIN: 162 case FIELDINFO_TAG_TYPE_CONTENDED: 163 return (lo >> FIELDINFO_TAG_SIZE); 164 #ifndef PRODUCT 165 case FIELDINFO_TAG_OFFSET: 166 fatal("Asking the field type for field with offset"); 167 case FIELDINFO_TAG_BLANK: 168 fatal("Asking the field type for the blank field"); 169 #endif 170 } 171 ShouldNotReachHere(); 172 return 0; 173 } 174 175 bool is_offset_set() const { 176 return (_shorts[low_packed_offset] & FIELDINFO_TAG_MASK) == FIELDINFO_TAG_OFFSET; 177 } 178 179 Symbol* name(ConstantPool* cp) const { 180 int index = name_index(); 181 if (is_internal()) { 182 return lookup_symbol(index); 183 } 184 return cp->symbol_at(index); 185 } 186 187 Symbol* signature(ConstantPool* cp) const { 188 int index = signature_index(); 189 if (is_internal()) { 190 return lookup_symbol(index); 191 } 192 return cp->symbol_at(index); 193 } 194 195 void set_access_flags(u2 val) { _shorts[access_flags_offset] = val; } 196 void set_offset(u4 val) { 197 val = val << FIELDINFO_TAG_SIZE; // make room for tag 198 _shorts[low_packed_offset] = extract_low_short_from_int(val) | FIELDINFO_TAG_OFFSET; 199 _shorts[high_packed_offset] = extract_high_short_from_int(val); 200 } 201 202 void set_allocation_type(int type) { 203 u2 lo = _shorts[low_packed_offset]; 204 switch(lo & FIELDINFO_TAG_MASK) { 205 case FIELDINFO_TAG_BLANK: 206 _shorts[low_packed_offset] = ((type << FIELDINFO_TAG_SIZE)) & 0xFFFF; 207 _shorts[low_packed_offset] &= ~FIELDINFO_TAG_MASK; 208 _shorts[low_packed_offset] |= FIELDINFO_TAG_TYPE_PLAIN; 209 return; 210 #ifndef PRODUCT 211 case FIELDINFO_TAG_TYPE_PLAIN: 212 case FIELDINFO_TAG_TYPE_CONTENDED: 213 case FIELDINFO_TAG_OFFSET: 214 fatal("Setting the field type with overwriting"); 215 #endif 216 } 217 ShouldNotReachHere(); 218 } 219 220 void set_contended_group(u2 val) { 221 u2 lo = _shorts[low_packed_offset]; 222 switch(lo & FIELDINFO_TAG_MASK) { 223 case FIELDINFO_TAG_TYPE_PLAIN: 224 _shorts[low_packed_offset] |= FIELDINFO_TAG_TYPE_CONTENDED; 225 _shorts[high_packed_offset] = val; 226 return; 227 #ifndef PRODUCT 228 case FIELDINFO_TAG_TYPE_CONTENDED: 229 fatal("Overwriting contended group"); 230 case FIELDINFO_TAG_BLANK: 231 fatal("Setting contended group for the blank field"); 232 case FIELDINFO_TAG_OFFSET: 233 fatal("Setting contended group for field with offset"); 234 #endif 235 } 236 ShouldNotReachHere(); 237 } 238 239 bool is_internal() const { 240 return (access_flags() & JVM_ACC_FIELD_INTERNAL) != 0; 241 } 242 243 bool is_stable() const { 244 return (access_flags() & JVM_ACC_FIELD_STABLE) != 0; 245 } 246 void set_stable(bool z) { 247 if (z) _shorts[access_flags_offset] |= JVM_ACC_FIELD_STABLE; 248 else _shorts[access_flags_offset] &= ~JVM_ACC_FIELD_STABLE; 249 } 250 251 Symbol* lookup_symbol(int symbol_index) const { 252 assert(is_internal(), "only internal fields"); 253 return vmSymbols::symbol_at((vmSymbols::SID)symbol_index); 254 } 255 }; 256 257 #endif // SHARE_OOPS_FIELDINFO_HPP