--- old/src/hotspot/share/oops/fieldInfo.hpp 2019-03-11 14:26:15.298355029 +0100 +++ new/src/hotspot/share/oops/fieldInfo.hpp 2019-03-11 14:26:14.950355034 +0100 @@ -45,20 +45,25 @@ // Field info extracted from the class file and stored // as an array of 6 shorts. -#define FIELDINFO_TAG_SIZE 2 +#define FIELDINFO_TAG_SIZE 3 #define FIELDINFO_TAG_BLANK 0 #define FIELDINFO_TAG_OFFSET 1 #define FIELDINFO_TAG_TYPE_PLAIN 2 #define FIELDINFO_TAG_TYPE_CONTENDED 3 -#define FIELDINFO_TAG_MASK 3 +#define FIELDINFO_TAG_TYPE_MASK 3 +#define FIELDINFO_TAG_MASK 7 +#define FIELDINFO_TAG_FLATTENED 4 // Packed field has the tag, and can be either of: // hi bits <--------------------------- lo bits // |---------high---------|---------low---------| // ..........................................00 - blank - // [------------------offset----------------]01 - real field offset - // ......................[-------type-------]10 - plain field with type - // [--contention_group--][-------type-------]11 - contended field with type and contention group + // [------------------offset---------------]F01 - real field offset + // ......................[-------type------]F10 - plain field with type + // [--contention_group--][-------type------]F11 - contended field with type and contention group + // + // Bit F indicates if the field has been flattened (F=1) or nor (F=0) + enum FieldOffset { access_flags_offset = 0, name_index_offset = 1, @@ -103,7 +108,7 @@ u2 access_flags() const { return _shorts[access_flags_offset]; } u4 offset() const { u2 lo = _shorts[low_packed_offset]; - switch(lo & FIELDINFO_TAG_MASK) { + switch(lo & FIELDINFO_TAG_TYPE_MASK) { case FIELDINFO_TAG_OFFSET: return build_int_from_shorts(_shorts[low_packed_offset], _shorts[high_packed_offset]) >> FIELDINFO_TAG_SIZE; #ifndef PRODUCT @@ -121,7 +126,7 @@ bool is_contended() const { u2 lo = _shorts[low_packed_offset]; - switch(lo & FIELDINFO_TAG_MASK) { + switch(lo & FIELDINFO_TAG_TYPE_MASK) { case FIELDINFO_TAG_TYPE_PLAIN: return false; case FIELDINFO_TAG_TYPE_CONTENDED: @@ -139,7 +144,7 @@ u2 contended_group() const { u2 lo = _shorts[low_packed_offset]; - switch(lo & FIELDINFO_TAG_MASK) { + switch(lo & FIELDINFO_TAG_TYPE_MASK) { case FIELDINFO_TAG_TYPE_PLAIN: return 0; case FIELDINFO_TAG_TYPE_CONTENDED: @@ -157,7 +162,7 @@ u2 allocation_type() const { u2 lo = _shorts[low_packed_offset]; - switch(lo & FIELDINFO_TAG_MASK) { + switch(lo & FIELDINFO_TAG_TYPE_MASK) { case FIELDINFO_TAG_TYPE_PLAIN: case FIELDINFO_TAG_TYPE_CONTENDED: return (lo >> FIELDINFO_TAG_SIZE); @@ -173,7 +178,7 @@ } bool is_offset_set() const { - return (_shorts[low_packed_offset] & FIELDINFO_TAG_MASK) == FIELDINFO_TAG_OFFSET; + return (_shorts[low_packed_offset] & FIELDINFO_TAG_TYPE_MASK) == FIELDINFO_TAG_OFFSET; } Symbol* name(const constantPoolHandle& cp) const { @@ -195,17 +200,22 @@ void set_access_flags(u2 val) { _shorts[access_flags_offset] = val; } void set_offset(u4 val) { val = val << FIELDINFO_TAG_SIZE; // make room for tag + bool flattened = is_flattened(); _shorts[low_packed_offset] = extract_low_short_from_int(val) | FIELDINFO_TAG_OFFSET; + if (flattened) set_flattened(true); _shorts[high_packed_offset] = extract_high_short_from_int(val); + assert(is_flattened() || !flattened, "just checking"); } void set_allocation_type(int type) { + bool b = is_flattened(); u2 lo = _shorts[low_packed_offset]; - switch(lo & FIELDINFO_TAG_MASK) { + switch(lo & FIELDINFO_TAG_TYPE_MASK) { case FIELDINFO_TAG_BLANK: - _shorts[low_packed_offset] = ((type << FIELDINFO_TAG_SIZE)) & 0xFFFF; - _shorts[low_packed_offset] &= ~FIELDINFO_TAG_MASK; + _shorts[low_packed_offset] |= ((type << FIELDINFO_TAG_SIZE)) & 0xFFFF; + _shorts[low_packed_offset] &= ~FIELDINFO_TAG_TYPE_MASK; _shorts[low_packed_offset] |= FIELDINFO_TAG_TYPE_PLAIN; + assert(is_flattened() || !b, "Just checking"); return; #ifndef PRODUCT case FIELDINFO_TAG_TYPE_PLAIN: @@ -217,9 +227,21 @@ ShouldNotReachHere(); } + void set_flattened(bool b) { + if (b) { + _shorts[low_packed_offset] |= FIELDINFO_TAG_FLATTENED; + } else { + _shorts[low_packed_offset] &= ~FIELDINFO_TAG_FLATTENED; + } + } + + bool is_flattened() { + return (_shorts[low_packed_offset] & FIELDINFO_TAG_FLATTENED) != 0; + } + void set_contended_group(u2 val) { u2 lo = _shorts[low_packed_offset]; - switch(lo & FIELDINFO_TAG_MASK) { + switch(lo & FIELDINFO_TAG_TYPE_MASK) { case FIELDINFO_TAG_TYPE_PLAIN: _shorts[low_packed_offset] |= FIELDINFO_TAG_TYPE_CONTENDED; _shorts[high_packed_offset] = val; @@ -248,6 +270,10 @@ else _shorts[access_flags_offset] &= ~JVM_ACC_FIELD_STABLE; } + bool is_flattenable() const { + return (access_flags() & JVM_ACC_FLATTENABLE) != 0; + } + Symbol* lookup_symbol(int symbol_index) const { assert(is_internal(), "only internal fields"); return vmSymbols::symbol_at((vmSymbols::SID)symbol_index);