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