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 3 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_TYPE_MASK 3 54 #define FIELDINFO_TAG_MASK 7 55 #define FIELDINFO_TAG_FLATTENED 4 56 57 // Packed field has the tag, and can be either of: 58 // hi bits <--------------------------- lo bits 59 // |---------high---------|---------low---------| 60 // ..........................................00 - blank 61 // [------------------offset---------------]F01 - real field offset 62 // ......................[-------type------]F10 - plain field with type 63 // [--contention_group--][-------type------]F11 - contended field with type and contention group 64 // 65 // Bit F indicates if the field has been flattened (F=1) or nor (F=0) 66 67 enum FieldOffset { 68 access_flags_offset = 0, 69 name_index_offset = 1, 70 signature_index_offset = 2, 71 initval_index_offset = 3, 72 low_packed_offset = 4, 73 high_packed_offset = 5, 74 field_slots = 6 75 }; 76 77 private: 78 u2 _shorts[field_slots]; 79 80 void set_name_index(u2 val) { _shorts[name_index_offset] = val; } 81 void set_signature_index(u2 val) { _shorts[signature_index_offset] = val; } 82 void set_initval_index(u2 val) { _shorts[initval_index_offset] = val; } 83 84 u2 name_index() const { return _shorts[name_index_offset]; } 85 u2 signature_index() const { return _shorts[signature_index_offset]; } 86 u2 initval_index() const { return _shorts[initval_index_offset]; } 87 88 public: 89 static FieldInfo* from_field_array(Array<u2>* fields, int index) { 90 return ((FieldInfo*)fields->adr_at(index * field_slots)); 91 } 92 static FieldInfo* from_field_array(u2* fields, int index) { 93 return ((FieldInfo*)(fields + index * field_slots)); 94 } 95 96 void initialize(u2 access_flags, 97 u2 name_index, 98 u2 signature_index, 99 u2 initval_index) { 100 _shorts[access_flags_offset] = access_flags; 101 _shorts[name_index_offset] = name_index; 102 _shorts[signature_index_offset] = signature_index; 103 _shorts[initval_index_offset] = initval_index; 104 _shorts[low_packed_offset] = 0; 105 _shorts[high_packed_offset] = 0; 106 } 107 108 u2 access_flags() const { return _shorts[access_flags_offset]; } 109 u4 offset() const { 110 u2 lo = _shorts[low_packed_offset]; 111 switch(lo & FIELDINFO_TAG_TYPE_MASK) { 112 case FIELDINFO_TAG_OFFSET: 113 return build_int_from_shorts(_shorts[low_packed_offset], _shorts[high_packed_offset]) >> FIELDINFO_TAG_SIZE; 114 #ifndef PRODUCT 115 case FIELDINFO_TAG_TYPE_PLAIN: 116 fatal("Asking offset for the plain type field"); 117 case FIELDINFO_TAG_TYPE_CONTENDED: 118 fatal("Asking offset for the contended type field"); 119 case FIELDINFO_TAG_BLANK: 120 fatal("Asking offset for the blank field"); 121 #endif 122 } 123 ShouldNotReachHere(); 124 return 0; 125 } 126 127 bool is_contended() const { 128 u2 lo = _shorts[low_packed_offset]; 129 switch(lo & FIELDINFO_TAG_TYPE_MASK) { 130 case FIELDINFO_TAG_TYPE_PLAIN: 131 return false; 132 case FIELDINFO_TAG_TYPE_CONTENDED: 133 return true; 134 #ifndef PRODUCT 135 case FIELDINFO_TAG_OFFSET: 136 fatal("Asking contended flag for the field with offset"); 137 case FIELDINFO_TAG_BLANK: 138 fatal("Asking contended flag for the blank field"); 139 #endif 140 } 141 ShouldNotReachHere(); 142 return false; 143 } 144 145 u2 contended_group() const { 146 u2 lo = _shorts[low_packed_offset]; 147 switch(lo & FIELDINFO_TAG_TYPE_MASK) { 148 case FIELDINFO_TAG_TYPE_PLAIN: 149 return 0; 150 case FIELDINFO_TAG_TYPE_CONTENDED: 151 return _shorts[high_packed_offset]; 152 #ifndef PRODUCT 153 case FIELDINFO_TAG_OFFSET: 154 fatal("Asking the contended group for the field with offset"); 155 case FIELDINFO_TAG_BLANK: 156 fatal("Asking the contended group for the blank field"); 157 #endif 158 } 159 ShouldNotReachHere(); 160 return 0; 161 } 162 163 u2 allocation_type() const { 164 u2 lo = _shorts[low_packed_offset]; 165 switch(lo & FIELDINFO_TAG_TYPE_MASK) { 166 case FIELDINFO_TAG_TYPE_PLAIN: 167 case FIELDINFO_TAG_TYPE_CONTENDED: 168 return (lo >> FIELDINFO_TAG_SIZE); 169 #ifndef PRODUCT 170 case FIELDINFO_TAG_OFFSET: 171 fatal("Asking the field type for field with offset"); 172 case FIELDINFO_TAG_BLANK: 173 fatal("Asking the field type for the blank field"); 174 #endif 175 } 176 ShouldNotReachHere(); 177 return 0; 178 } 179 180 bool is_offset_set() const { 181 return (_shorts[low_packed_offset] & FIELDINFO_TAG_TYPE_MASK) == FIELDINFO_TAG_OFFSET; 182 } 183 184 Symbol* name(const constantPoolHandle& cp) const { 185 int index = name_index(); 186 if (is_internal()) { 187 return lookup_symbol(index); 188 } 189 return cp->symbol_at(index); 190 } 191 192 Symbol* signature(const constantPoolHandle& cp) const { 193 int index = signature_index(); 194 if (is_internal()) { 195 return lookup_symbol(index); 196 } 197 return cp->symbol_at(index); 198 } 199 200 void set_access_flags(u2 val) { _shorts[access_flags_offset] = val; } 201 void set_offset(u4 val) { 202 val = val << FIELDINFO_TAG_SIZE; // make room for tag 203 bool flattened = is_flattened(); 204 _shorts[low_packed_offset] = extract_low_short_from_int(val) | FIELDINFO_TAG_OFFSET; 205 if (flattened) set_flattened(true); 206 _shorts[high_packed_offset] = extract_high_short_from_int(val); 207 assert(is_flattened() || !flattened, "just checking"); 208 } 209 210 void set_allocation_type(int type) { 211 bool b = is_flattened(); 212 u2 lo = _shorts[low_packed_offset]; 213 switch(lo & FIELDINFO_TAG_TYPE_MASK) { 214 case FIELDINFO_TAG_BLANK: 215 _shorts[low_packed_offset] |= ((type << FIELDINFO_TAG_SIZE)) & 0xFFFF; 216 _shorts[low_packed_offset] &= ~FIELDINFO_TAG_TYPE_MASK; 217 _shorts[low_packed_offset] |= FIELDINFO_TAG_TYPE_PLAIN; 218 assert(is_flattened() || !b, "Just checking"); 219 return; 220 #ifndef PRODUCT 221 case FIELDINFO_TAG_TYPE_PLAIN: 222 case FIELDINFO_TAG_TYPE_CONTENDED: 223 case FIELDINFO_TAG_OFFSET: 224 fatal("Setting the field type with overwriting"); 225 #endif 226 } 227 ShouldNotReachHere(); 228 } 229 230 void set_flattened(bool b) { 231 if (b) { 232 _shorts[low_packed_offset] |= FIELDINFO_TAG_FLATTENED; 233 } else { 234 _shorts[low_packed_offset] &= ~FIELDINFO_TAG_FLATTENED; 235 } 236 } 237 238 bool is_flattened() { 239 return (_shorts[low_packed_offset] & FIELDINFO_TAG_FLATTENED) != 0; 240 } 241 242 void set_contended_group(u2 val) { 243 u2 lo = _shorts[low_packed_offset]; 244 switch(lo & FIELDINFO_TAG_TYPE_MASK) { 245 case FIELDINFO_TAG_TYPE_PLAIN: 246 _shorts[low_packed_offset] |= FIELDINFO_TAG_TYPE_CONTENDED; 247 _shorts[high_packed_offset] = val; 248 return; 249 #ifndef PRODUCT 250 case FIELDINFO_TAG_TYPE_CONTENDED: 251 fatal("Overwriting contended group"); 252 case FIELDINFO_TAG_BLANK: 253 fatal("Setting contended group for the blank field"); 254 case FIELDINFO_TAG_OFFSET: 255 fatal("Setting contended group for field with offset"); 256 #endif 257 } 258 ShouldNotReachHere(); 259 } 260 261 bool is_internal() const { 262 return (access_flags() & JVM_ACC_FIELD_INTERNAL) != 0; 263 } 264 265 bool is_stable() const { 266 return (access_flags() & JVM_ACC_FIELD_STABLE) != 0; 267 } 268 void set_stable(bool z) { 269 if (z) _shorts[access_flags_offset] |= JVM_ACC_FIELD_STABLE; 270 else _shorts[access_flags_offset] &= ~JVM_ACC_FIELD_STABLE; 271 } 272 273 bool is_flattenable() const { 274 return (access_flags() & JVM_ACC_FLATTENABLE) != 0; 275 } 276 277 Symbol* lookup_symbol(int symbol_index) const { 278 assert(is_internal(), "only internal fields"); 279 return vmSymbols::symbol_at((vmSymbols::SID)symbol_index); 280 } 281 }; 282 283 #endif // SHARE_OOPS_FIELDINFO_HPP