--- a/hotspot/src/share/vm/oops/fieldInfo.hpp Fri Jan 11 09:53:24 2013 -0800
+++ b/hotspot/src/share/vm/oops/fieldInfo.hpp Mon Jan 14 15:17:47 2013 +0100
@@ -43,14 +43,29 @@
public:
// fields
// Field info extracted from the class file and stored
- // as an array of 7 shorts
+ // as an array of 6 shorts.
+
+#define FIELDINFO_TAG_SIZE 2
+#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
+
+ // 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
enum FieldOffset {
access_flags_offset = 0,
name_index_offset = 1,
signature_index_offset = 2,
initval_index_offset = 3,
- low_offset = 4,
- high_offset = 5,
+ low_packed_offset = 4,
+ high_packed_offset = 5,
field_slots = 6
};
@@ -76,17 +91,90 @@
void initialize(u2 access_flags,
u2 name_index,
u2 signature_index,
- u2 initval_index,
- u4 offset) {
+ u2 initval_index) {
_shorts[access_flags_offset] = access_flags;
_shorts[name_index_offset] = name_index;
_shorts[signature_index_offset] = signature_index;
_shorts[initval_index_offset] = initval_index;
- set_offset(offset);
+ _shorts[low_packed_offset] = 0;
+ _shorts[high_packed_offset] = 0;
}
u2 access_flags() const { return _shorts[access_flags_offset]; }
- u4 offset() const { return build_int_from_shorts(_shorts[low_offset], _shorts[high_offset]); }
+ u4 offset() const {
+ u2 lo = _shorts[low_packed_offset];
+ switch(lo & FIELDINFO_TAG_MASK) {
+ case FIELDINFO_TAG_OFFSET:
+ return build_int_from_shorts(_shorts[low_packed_offset], _shorts[high_packed_offset]) >> FIELDINFO_TAG_SIZE;
+#ifndef PRODUCT
+ case FIELDINFO_TAG_TYPE_PLAIN:
+ ShouldNotReachHere2("Asking offset for the plain type field");
+ case FIELDINFO_TAG_TYPE_CONTENDED:
+ ShouldNotReachHere2("Asking offset for the contended type field");
+ case FIELDINFO_TAG_BLANK:
+ ShouldNotReachHere2("Asking offset for the blank field");
+#endif
+ }
+ ShouldNotReachHere();
+ return 0;
+ }
+
+ bool is_contended() const {
+ u2 lo = _shorts[low_packed_offset];
+ switch(lo & FIELDINFO_TAG_MASK) {
+ case FIELDINFO_TAG_TYPE_PLAIN:
+ return false;
+ case FIELDINFO_TAG_TYPE_CONTENDED:
+ return true;
+#ifndef PRODUCT
+ case FIELDINFO_TAG_OFFSET:
+ ShouldNotReachHere2("Asking contended flag for the field with offset");
+ case FIELDINFO_TAG_BLANK:
+ ShouldNotReachHere2("Asking contended flag for the blank field");
+#endif
+ }
+ ShouldNotReachHere();
+ return false;
+ }
+
+ u2 contended_group() const {
+ u2 lo = _shorts[low_packed_offset];
+ switch(lo & FIELDINFO_TAG_MASK) {
+ case FIELDINFO_TAG_TYPE_PLAIN:
+ return 0;
+ case FIELDINFO_TAG_TYPE_CONTENDED:
+ return _shorts[high_packed_offset];
+#ifndef PRODUCT
+ case FIELDINFO_TAG_OFFSET:
+ ShouldNotReachHere2("Asking the contended group for the field with offset");
+ case FIELDINFO_TAG_BLANK:
+ ShouldNotReachHere2("Asking the contended group for the blank field");
+#endif
+ }
+ ShouldNotReachHere();
+ return 0;
+ }
+
+ u2 allocation_type() const {
+ u2 lo = _shorts[low_packed_offset];
+ switch(lo & FIELDINFO_TAG_MASK) {
+ case FIELDINFO_TAG_TYPE_PLAIN:
+ case FIELDINFO_TAG_TYPE_CONTENDED:
+ return (lo >> FIELDINFO_TAG_SIZE);
+#ifndef PRODUCT
+ case FIELDINFO_TAG_OFFSET:
+ ShouldNotReachHere2("Asking the field type for field with offset");
+ case FIELDINFO_TAG_BLANK:
+ ShouldNotReachHere2("Asking the field type for the blank field");
+#endif
+ }
+ ShouldNotReachHere();
+ return 0;
+ }
+
+ bool is_offset_set() const {
+ return (_shorts[low_packed_offset] & FIELDINFO_TAG_MASK) == FIELDINFO_TAG_OFFSET;
+ }
Symbol* name(constantPoolHandle cp) const {
int index = name_index();
@@ -106,8 +194,46 @@
void set_access_flags(u2 val) { _shorts[access_flags_offset] = val; }
void set_offset(u4 val) {
- _shorts[low_offset] = extract_low_short_from_int(val);
- _shorts[high_offset] = extract_high_short_from_int(val);
+ val = val << FIELDINFO_TAG_SIZE; // make room for tag
+ _shorts[low_packed_offset] = extract_low_short_from_int(val) | FIELDINFO_TAG_OFFSET;
+ _shorts[high_packed_offset] = extract_high_short_from_int(val);
+ }
+
+ void set_allocation_type(int type) {
+ u2 lo = _shorts[low_packed_offset];
+ switch(lo & FIELDINFO_TAG_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] |= FIELDINFO_TAG_TYPE_PLAIN;
+ return;
+#ifndef PRODUCT
+ case FIELDINFO_TAG_TYPE_PLAIN:
+ case FIELDINFO_TAG_TYPE_CONTENDED:
+ case FIELDINFO_TAG_OFFSET:
+ ShouldNotReachHere2("Setting the field type with overwriting");
+#endif
+ }
+ ShouldNotReachHere();
+ }
+
+ void set_contended_group(u2 val) {
+ u2 lo = _shorts[low_packed_offset];
+ switch(lo & FIELDINFO_TAG_MASK) {
+ case FIELDINFO_TAG_TYPE_PLAIN:
+ _shorts[low_packed_offset] |= FIELDINFO_TAG_TYPE_CONTENDED;
+ _shorts[high_packed_offset] = val;
+ return;
+#ifndef PRODUCT
+ case FIELDINFO_TAG_TYPE_CONTENDED:
+ ShouldNotReachHere2("Overwriting contended group");
+ case FIELDINFO_TAG_BLANK:
+ ShouldNotReachHere2("Setting contended group for the blank field");
+ case FIELDINFO_TAG_OFFSET:
+ ShouldNotReachHere2("Setting contended group for field with offset");
+#endif
+ }
+ ShouldNotReachHere();
}
bool is_internal() const {