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 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]; 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 | 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]; 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 |