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]; } 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(const constantPoolHandle& 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(const constantPoolHandle& 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 | 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]; } 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 |