mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
8003985: Support @Contended Annotation - JEP 142
HotSpot changes to support @Contended annotation. Reviewed-by: coleenp, kvn, jrose
This commit is contained in:
parent
ae35dfeeec
commit
0614ed6542
11 changed files with 617 additions and 92 deletions
|
@ -52,6 +52,8 @@ public class InstanceKlass extends Klass {
|
||||||
private static int LOW_OFFSET;
|
private static int LOW_OFFSET;
|
||||||
private static int HIGH_OFFSET;
|
private static int HIGH_OFFSET;
|
||||||
private static int FIELD_SLOTS;
|
private static int FIELD_SLOTS;
|
||||||
|
private static short FIELDINFO_TAG_SIZE;
|
||||||
|
private static short FIELDINFO_TAG_OFFSET;
|
||||||
|
|
||||||
// ClassState constants
|
// ClassState constants
|
||||||
private static int CLASS_STATE_ALLOCATED;
|
private static int CLASS_STATE_ALLOCATED;
|
||||||
|
@ -96,9 +98,12 @@ public class InstanceKlass extends Klass {
|
||||||
NAME_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::name_index_offset").intValue();
|
NAME_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::name_index_offset").intValue();
|
||||||
SIGNATURE_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::signature_index_offset").intValue();
|
SIGNATURE_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::signature_index_offset").intValue();
|
||||||
INITVAL_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::initval_index_offset").intValue();
|
INITVAL_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::initval_index_offset").intValue();
|
||||||
LOW_OFFSET = db.lookupIntConstant("FieldInfo::low_offset").intValue();
|
LOW_OFFSET = db.lookupIntConstant("FieldInfo::low_packed_offset").intValue();
|
||||||
HIGH_OFFSET = db.lookupIntConstant("FieldInfo::high_offset").intValue();
|
HIGH_OFFSET = db.lookupIntConstant("FieldInfo::high_packed_offset").intValue();
|
||||||
FIELD_SLOTS = db.lookupIntConstant("FieldInfo::field_slots").intValue();
|
FIELD_SLOTS = db.lookupIntConstant("FieldInfo::field_slots").intValue();
|
||||||
|
FIELDINFO_TAG_SIZE = db.lookupIntConstant("FIELDINFO_TAG_SIZE").shortValue();
|
||||||
|
FIELDINFO_TAG_OFFSET = db.lookupIntConstant("FIELDINFO_TAG_OFFSET").shortValue();
|
||||||
|
|
||||||
// read ClassState constants
|
// read ClassState constants
|
||||||
CLASS_STATE_ALLOCATED = db.lookupIntConstant("InstanceKlass::allocated").intValue();
|
CLASS_STATE_ALLOCATED = db.lookupIntConstant("InstanceKlass::allocated").intValue();
|
||||||
CLASS_STATE_LOADED = db.lookupIntConstant("InstanceKlass::loaded").intValue();
|
CLASS_STATE_LOADED = db.lookupIntConstant("InstanceKlass::loaded").intValue();
|
||||||
|
@ -314,8 +319,12 @@ public class InstanceKlass extends Klass {
|
||||||
|
|
||||||
public int getFieldOffset(int index) {
|
public int getFieldOffset(int index) {
|
||||||
U2Array fields = getFields();
|
U2Array fields = getFields();
|
||||||
return VM.getVM().buildIntFromShorts(fields.at(index * FIELD_SLOTS + LOW_OFFSET),
|
short lo = fields.at(index * FIELD_SLOTS + LOW_OFFSET);
|
||||||
fields.at(index * FIELD_SLOTS + HIGH_OFFSET));
|
short hi = fields.at(index * FIELD_SLOTS + HIGH_OFFSET);
|
||||||
|
if ((lo & FIELDINFO_TAG_SIZE) == FIELDINFO_TAG_OFFSET) {
|
||||||
|
return VM.getVM().buildIntFromShorts(lo, hi) >> FIELDINFO_TAG_SIZE;
|
||||||
|
}
|
||||||
|
throw new RuntimeException("should not reach here");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Accessors for declared fields
|
// Accessors for declared fields
|
||||||
|
|
|
@ -259,6 +259,10 @@ void VM_Version::initialize() {
|
||||||
if (!has_vis1()) // Drop to 0 if no VIS1 support
|
if (!has_vis1()) // Drop to 0 if no VIS1 support
|
||||||
UseVIS = 0;
|
UseVIS = 0;
|
||||||
|
|
||||||
|
if (FLAG_IS_DEFAULT(ContendedPaddingWidth) &&
|
||||||
|
(cache_line_size > ContendedPaddingWidth))
|
||||||
|
ContendedPaddingWidth = cache_line_size;
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
if (PrintMiscellaneous && Verbose) {
|
if (PrintMiscellaneous && Verbose) {
|
||||||
tty->print("Allocation");
|
tty->print("Allocation");
|
||||||
|
@ -286,6 +290,9 @@ void VM_Version::initialize() {
|
||||||
if (PrefetchFieldsAhead > 0) {
|
if (PrefetchFieldsAhead > 0) {
|
||||||
tty->print_cr("PrefetchFieldsAhead %d", PrefetchFieldsAhead);
|
tty->print_cr("PrefetchFieldsAhead %d", PrefetchFieldsAhead);
|
||||||
}
|
}
|
||||||
|
if (ContendedPaddingWidth > 0) {
|
||||||
|
tty->print_cr("ContendedPaddingWidth %d", ContendedPaddingWidth);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif // PRODUCT
|
#endif // PRODUCT
|
||||||
}
|
}
|
||||||
|
|
|
@ -734,6 +734,10 @@ void VM_Version::get_processor_features() {
|
||||||
PrefetchFieldsAhead = prefetch_fields_ahead();
|
PrefetchFieldsAhead = prefetch_fields_ahead();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (FLAG_IS_DEFAULT(ContendedPaddingWidth) &&
|
||||||
|
(cache_line_size > ContendedPaddingWidth))
|
||||||
|
ContendedPaddingWidth = cache_line_size;
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
if (PrintMiscellaneous && Verbose) {
|
if (PrintMiscellaneous && Verbose) {
|
||||||
tty->print_cr("Logical CPUs per core: %u",
|
tty->print_cr("Logical CPUs per core: %u",
|
||||||
|
@ -780,6 +784,9 @@ void VM_Version::get_processor_features() {
|
||||||
if (PrefetchFieldsAhead > 0) {
|
if (PrefetchFieldsAhead > 0) {
|
||||||
tty->print_cr("PrefetchFieldsAhead %d", PrefetchFieldsAhead);
|
tty->print_cr("PrefetchFieldsAhead %d", PrefetchFieldsAhead);
|
||||||
}
|
}
|
||||||
|
if (ContendedPaddingWidth > 0) {
|
||||||
|
tty->print_cr("ContendedPaddingWidth %d", ContendedPaddingWidth);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif // !PRODUCT
|
#endif // !PRODUCT
|
||||||
}
|
}
|
||||||
|
|
|
@ -970,6 +970,12 @@ void ClassFileParser::parse_field_attributes(ClassLoaderData* loader_data,
|
||||||
runtime_visible_annotations_length = attribute_length;
|
runtime_visible_annotations_length = attribute_length;
|
||||||
runtime_visible_annotations = cfs->get_u1_buffer();
|
runtime_visible_annotations = cfs->get_u1_buffer();
|
||||||
assert(runtime_visible_annotations != NULL, "null visible annotations");
|
assert(runtime_visible_annotations != NULL, "null visible annotations");
|
||||||
|
parse_annotations(loader_data,
|
||||||
|
runtime_visible_annotations,
|
||||||
|
runtime_visible_annotations_length,
|
||||||
|
cp,
|
||||||
|
parsed_annotations,
|
||||||
|
CHECK);
|
||||||
cfs->skip_u1(runtime_visible_annotations_length, CHECK);
|
cfs->skip_u1(runtime_visible_annotations_length, CHECK);
|
||||||
} else if (PreserveAllAnnotations && attribute_name == vmSymbols::tag_runtime_invisible_annotations()) {
|
} else if (PreserveAllAnnotations && attribute_name == vmSymbols::tag_runtime_invisible_annotations()) {
|
||||||
runtime_invisible_annotations_length = attribute_length;
|
runtime_invisible_annotations_length = attribute_length;
|
||||||
|
@ -1216,19 +1222,16 @@ Array<u2>* ClassFileParser::parse_fields(ClassLoaderData* loader_data,
|
||||||
field->initialize(access_flags.as_short(),
|
field->initialize(access_flags.as_short(),
|
||||||
name_index,
|
name_index,
|
||||||
signature_index,
|
signature_index,
|
||||||
constantvalue_index,
|
constantvalue_index);
|
||||||
0);
|
|
||||||
if (parsed_annotations.has_any_annotations())
|
|
||||||
parsed_annotations.apply_to(field);
|
|
||||||
|
|
||||||
BasicType type = cp->basic_type_for_signature_at(signature_index);
|
BasicType type = cp->basic_type_for_signature_at(signature_index);
|
||||||
|
|
||||||
// Remember how many oops we encountered and compute allocation type
|
// Remember how many oops we encountered and compute allocation type
|
||||||
FieldAllocationType atype = fac->update(is_static, type);
|
FieldAllocationType atype = fac->update(is_static, type);
|
||||||
|
field->set_allocation_type(atype);
|
||||||
|
|
||||||
// The correct offset is computed later (all oop fields will be located together)
|
// After field is initialized with type, we can augment it with aux info
|
||||||
// We temporarily store the allocation type in the offset field
|
if (parsed_annotations.has_any_annotations())
|
||||||
field->set_offset(atype);
|
parsed_annotations.apply_to(field);
|
||||||
}
|
}
|
||||||
|
|
||||||
int index = length;
|
int index = length;
|
||||||
|
@ -1259,17 +1262,13 @@ Array<u2>* ClassFileParser::parse_fields(ClassLoaderData* loader_data,
|
||||||
field->initialize(JVM_ACC_FIELD_INTERNAL,
|
field->initialize(JVM_ACC_FIELD_INTERNAL,
|
||||||
injected[n].name_index,
|
injected[n].name_index,
|
||||||
injected[n].signature_index,
|
injected[n].signature_index,
|
||||||
0,
|
|
||||||
0);
|
0);
|
||||||
|
|
||||||
BasicType type = FieldType::basic_type(injected[n].signature());
|
BasicType type = FieldType::basic_type(injected[n].signature());
|
||||||
|
|
||||||
// Remember how many oops we encountered and compute allocation type
|
// Remember how many oops we encountered and compute allocation type
|
||||||
FieldAllocationType atype = fac->update(false, type);
|
FieldAllocationType atype = fac->update(false, type);
|
||||||
|
field->set_allocation_type(atype);
|
||||||
// The correct offset is computed later (all oop fields will be located together)
|
|
||||||
// We temporarily store the allocation type in the offset field
|
|
||||||
field->set_offset(atype);
|
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1735,7 +1734,8 @@ int ClassFileParser::skip_annotation_value(u1* buffer, int limit, int index) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sift through annotations, looking for those significant to the VM:
|
// Sift through annotations, looking for those significant to the VM:
|
||||||
void ClassFileParser::parse_annotations(u1* buffer, int limit,
|
void ClassFileParser::parse_annotations(ClassLoaderData* loader_data,
|
||||||
|
u1* buffer, int limit,
|
||||||
constantPoolHandle cp,
|
constantPoolHandle cp,
|
||||||
ClassFileParser::AnnotationCollector* coll,
|
ClassFileParser::AnnotationCollector* coll,
|
||||||
TRAPS) {
|
TRAPS) {
|
||||||
|
@ -1752,9 +1752,12 @@ void ClassFileParser::parse_annotations(u1* buffer, int limit,
|
||||||
e_type_off = 7, // utf8 such as 'Ljava/lang/annotation/RetentionPolicy;'
|
e_type_off = 7, // utf8 such as 'Ljava/lang/annotation/RetentionPolicy;'
|
||||||
e_con_off = 9, // utf8 payload, such as 'SOURCE', 'CLASS', 'RUNTIME'
|
e_con_off = 9, // utf8 payload, such as 'SOURCE', 'CLASS', 'RUNTIME'
|
||||||
e_size = 11, // end of 'e' annotation
|
e_size = 11, // end of 'e' annotation
|
||||||
c_tag_val = 'c',
|
c_tag_val = 'c', // payload is type
|
||||||
c_con_off = 7, // utf8 payload, such as 'I' or 'Ljava/lang/String;'
|
c_con_off = 7, // utf8 payload, such as 'I'
|
||||||
c_size = 9, // end of 'c' annotation
|
c_size = 9, // end of 'c' annotation
|
||||||
|
s_tag_val = 's', // payload is String
|
||||||
|
s_con_off = 7, // utf8 payload, such as 'Ljava/lang/String;'
|
||||||
|
s_size = 9,
|
||||||
min_size = 6 // smallest possible size (zero members)
|
min_size = 6 // smallest possible size (zero members)
|
||||||
};
|
};
|
||||||
while ((--nann) >= 0 && (index-2 + min_size <= limit)) {
|
while ((--nann) >= 0 && (index-2 + min_size <= limit)) {
|
||||||
|
@ -1773,57 +1776,65 @@ void ClassFileParser::parse_annotations(u1* buffer, int limit,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Here is where parsing particular annotations will take place.
|
// Here is where parsing particular annotations will take place.
|
||||||
AnnotationCollector::ID id = coll->annotation_index(aname);
|
AnnotationCollector::ID id = coll->annotation_index(loader_data, aname);
|
||||||
if (id == AnnotationCollector::_unknown) continue;
|
if (id == AnnotationCollector::_unknown) continue;
|
||||||
coll->set_annotation(id);
|
coll->set_annotation(id);
|
||||||
// If there are no values, just set the bit and move on:
|
|
||||||
if (count == 0) continue;
|
|
||||||
|
|
||||||
// For the record, here is how annotation payloads can be collected.
|
if (id == AnnotationCollector::_sun_misc_Contended) {
|
||||||
// Suppose we want to capture @Retention.value. Here is how:
|
if (count == 1
|
||||||
//if (id == AnnotationCollector::_class_Retention) {
|
&& s_size == (index - index0) // match size
|
||||||
// Symbol* payload = NULL;
|
&& s_tag_val == *(abase + tag_off)
|
||||||
// if (count == 1
|
&& member == vmSymbols::value_name()) {
|
||||||
// && e_size == (index0 - index) // match size
|
u2 group_index = Bytes::get_Java_u2(abase + s_con_off);
|
||||||
// && e_tag_val == *(abase + tag_off)
|
coll->set_contended_group(group_index);
|
||||||
// && (check_symbol_at(cp, Bytes::get_Java_u2(abase + e_type_off))
|
} else {
|
||||||
// == vmSymbols::RetentionPolicy_signature())
|
coll->set_contended_group(0); // default contended group
|
||||||
// && member == vmSymbols::value_name()) {
|
}
|
||||||
// payload = check_symbol_at(cp, Bytes::get_Java_u2(abase + e_con_off));
|
coll->set_contended(true);
|
||||||
// }
|
} else {
|
||||||
// check_property(payload != NULL,
|
coll->set_contended(false);
|
||||||
// "Invalid @Retention annotation at offset %u in class file %s",
|
}
|
||||||
// index0, CHECK);
|
|
||||||
// if (payload != NULL) {
|
|
||||||
// payload->increment_refcount();
|
|
||||||
// coll->_class_RetentionPolicy = payload;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ClassFileParser::AnnotationCollector::ID ClassFileParser::AnnotationCollector::annotation_index(Symbol* name) {
|
ClassFileParser::AnnotationCollector::ID
|
||||||
|
ClassFileParser::AnnotationCollector::annotation_index(ClassLoaderData* loader_data,
|
||||||
|
Symbol* name) {
|
||||||
vmSymbols::SID sid = vmSymbols::find_sid(name);
|
vmSymbols::SID sid = vmSymbols::find_sid(name);
|
||||||
|
bool privileged = false;
|
||||||
|
if (loader_data->is_the_null_class_loader_data()) {
|
||||||
|
// Privileged code can use all annotations. Other code silently drops some.
|
||||||
|
privileged = true;
|
||||||
|
}
|
||||||
switch (sid) {
|
switch (sid) {
|
||||||
case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_ForceInline_signature):
|
case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_ForceInline_signature):
|
||||||
if (_location != _in_method) break; // only allow for methods
|
if (_location != _in_method) break; // only allow for methods
|
||||||
|
if (!privileged) break; // only allow in privileged code
|
||||||
return _method_ForceInline;
|
return _method_ForceInline;
|
||||||
case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_DontInline_signature):
|
case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_DontInline_signature):
|
||||||
if (_location != _in_method) break; // only allow for methods
|
if (_location != _in_method) break; // only allow for methods
|
||||||
|
if (!privileged) break; // only allow in privileged code
|
||||||
return _method_DontInline;
|
return _method_DontInline;
|
||||||
case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_LambdaForm_Compiled_signature):
|
case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_LambdaForm_Compiled_signature):
|
||||||
if (_location != _in_method) break; // only allow for methods
|
if (_location != _in_method) break; // only allow for methods
|
||||||
|
if (!privileged) break; // only allow in privileged code
|
||||||
return _method_LambdaForm_Compiled;
|
return _method_LambdaForm_Compiled;
|
||||||
case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_LambdaForm_Hidden_signature):
|
case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_LambdaForm_Hidden_signature):
|
||||||
if (_location != _in_method) break; // only allow for methods
|
if (_location != _in_method) break; // only allow for methods
|
||||||
|
if (!privileged) break; // only allow in privileged code
|
||||||
return _method_LambdaForm_Hidden;
|
return _method_LambdaForm_Hidden;
|
||||||
|
case vmSymbols::VM_SYMBOL_ENUM_NAME(sun_misc_Contended_signature):
|
||||||
|
if (_location != _in_field && _location != _in_class) break; // only allow for fields and classes
|
||||||
|
if (!EnableContended || (RestrictContended && !privileged)) break; // honor privileges
|
||||||
|
return _sun_misc_Contended;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
return AnnotationCollector::_unknown;
|
return AnnotationCollector::_unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClassFileParser::FieldAnnotationCollector::apply_to(FieldInfo* f) {
|
void ClassFileParser::FieldAnnotationCollector::apply_to(FieldInfo* f) {
|
||||||
fatal("no field annotations yet");
|
if (is_contended())
|
||||||
|
f->set_contended_group(contended_group());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClassFileParser::MethodAnnotationCollector::apply_to(methodHandle m) {
|
void ClassFileParser::MethodAnnotationCollector::apply_to(methodHandle m) {
|
||||||
|
@ -1838,7 +1849,7 @@ void ClassFileParser::MethodAnnotationCollector::apply_to(methodHandle m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClassFileParser::ClassAnnotationCollector::apply_to(instanceKlassHandle k) {
|
void ClassFileParser::ClassAnnotationCollector::apply_to(instanceKlassHandle k) {
|
||||||
fatal("no class annotations yet");
|
k->set_is_contended(is_contended());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2181,7 +2192,8 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
|
||||||
runtime_visible_annotations_length = method_attribute_length;
|
runtime_visible_annotations_length = method_attribute_length;
|
||||||
runtime_visible_annotations = cfs->get_u1_buffer();
|
runtime_visible_annotations = cfs->get_u1_buffer();
|
||||||
assert(runtime_visible_annotations != NULL, "null visible annotations");
|
assert(runtime_visible_annotations != NULL, "null visible annotations");
|
||||||
parse_annotations(runtime_visible_annotations,
|
parse_annotations(loader_data,
|
||||||
|
runtime_visible_annotations,
|
||||||
runtime_visible_annotations_length, cp, &parsed_annotations,
|
runtime_visible_annotations_length, cp, &parsed_annotations,
|
||||||
CHECK_(nullHandle));
|
CHECK_(nullHandle));
|
||||||
cfs->skip_u1(runtime_visible_annotations_length, CHECK_(nullHandle));
|
cfs->skip_u1(runtime_visible_annotations_length, CHECK_(nullHandle));
|
||||||
|
@ -2886,7 +2898,8 @@ void ClassFileParser::parse_classfile_attributes(ClassLoaderData* loader_data,
|
||||||
runtime_visible_annotations_length = attribute_length;
|
runtime_visible_annotations_length = attribute_length;
|
||||||
runtime_visible_annotations = cfs->get_u1_buffer();
|
runtime_visible_annotations = cfs->get_u1_buffer();
|
||||||
assert(runtime_visible_annotations != NULL, "null visible annotations");
|
assert(runtime_visible_annotations != NULL, "null visible annotations");
|
||||||
parse_annotations(runtime_visible_annotations,
|
parse_annotations(loader_data,
|
||||||
|
runtime_visible_annotations,
|
||||||
runtime_visible_annotations_length,
|
runtime_visible_annotations_length,
|
||||||
cp,
|
cp,
|
||||||
parsed_annotations,
|
parsed_annotations,
|
||||||
|
@ -3405,18 +3418,21 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||||
// Size of Java itable (in words)
|
// Size of Java itable (in words)
|
||||||
itable_size = access_flags.is_interface() ? 0 : klassItable::compute_itable_size(transitive_interfaces);
|
itable_size = access_flags.is_interface() ? 0 : klassItable::compute_itable_size(transitive_interfaces);
|
||||||
|
|
||||||
|
// get the padding width from the option
|
||||||
|
// TODO: Ask VM about specific CPU we are running on
|
||||||
|
int pad_size = ContendedPaddingWidth;
|
||||||
|
|
||||||
// Field size and offset computation
|
// Field size and offset computation
|
||||||
int nonstatic_field_size = super_klass() == NULL ? 0 : super_klass->nonstatic_field_size();
|
int nonstatic_field_size = super_klass() == NULL ? 0 : super_klass->nonstatic_field_size();
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
int orig_nonstatic_field_size = 0;
|
int orig_nonstatic_field_size = 0;
|
||||||
#endif
|
#endif
|
||||||
int static_field_size = 0;
|
|
||||||
int next_static_oop_offset;
|
int next_static_oop_offset;
|
||||||
int next_static_double_offset;
|
int next_static_double_offset;
|
||||||
int next_static_word_offset;
|
int next_static_word_offset;
|
||||||
int next_static_short_offset;
|
int next_static_short_offset;
|
||||||
int next_static_byte_offset;
|
int next_static_byte_offset;
|
||||||
int next_static_type_offset;
|
int next_static_padded_offset;
|
||||||
int next_nonstatic_oop_offset;
|
int next_nonstatic_oop_offset;
|
||||||
int next_nonstatic_double_offset;
|
int next_nonstatic_double_offset;
|
||||||
int next_nonstatic_word_offset;
|
int next_nonstatic_word_offset;
|
||||||
|
@ -3426,11 +3442,36 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||||
int first_nonstatic_oop_offset;
|
int first_nonstatic_oop_offset;
|
||||||
int first_nonstatic_field_offset;
|
int first_nonstatic_field_offset;
|
||||||
int next_nonstatic_field_offset;
|
int next_nonstatic_field_offset;
|
||||||
|
int next_nonstatic_padded_offset;
|
||||||
|
|
||||||
|
// Count the contended fields by type.
|
||||||
|
int static_contended_count = 0;
|
||||||
|
int nonstatic_contended_count = 0;
|
||||||
|
FieldAllocationCount fac_contended;
|
||||||
|
for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) {
|
||||||
|
FieldAllocationType atype = (FieldAllocationType) fs.allocation_type();
|
||||||
|
if (fs.is_contended()) {
|
||||||
|
fac_contended.count[atype]++;
|
||||||
|
if (fs.access_flags().is_static()) {
|
||||||
|
static_contended_count++;
|
||||||
|
} else {
|
||||||
|
nonstatic_contended_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int contended_count = static_contended_count + nonstatic_contended_count;
|
||||||
|
|
||||||
|
|
||||||
// Calculate the starting byte offsets
|
// Calculate the starting byte offsets
|
||||||
next_static_oop_offset = InstanceMirrorKlass::offset_of_static_fields();
|
next_static_oop_offset = InstanceMirrorKlass::offset_of_static_fields();
|
||||||
|
|
||||||
|
// class is contended, pad before all the fields
|
||||||
|
if (parsed_annotations.is_contended()) {
|
||||||
|
next_static_oop_offset += pad_size;
|
||||||
|
}
|
||||||
|
|
||||||
next_static_double_offset = next_static_oop_offset +
|
next_static_double_offset = next_static_oop_offset +
|
||||||
(fac.count[STATIC_OOP] * heapOopSize);
|
((fac.count[STATIC_OOP] - fac_contended.count[STATIC_OOP]) * heapOopSize);
|
||||||
if ( fac.count[STATIC_DOUBLE] &&
|
if ( fac.count[STATIC_DOUBLE] &&
|
||||||
(Universe::field_type_should_be_aligned(T_DOUBLE) ||
|
(Universe::field_type_should_be_aligned(T_DOUBLE) ||
|
||||||
Universe::field_type_should_be_aligned(T_LONG)) ) {
|
Universe::field_type_should_be_aligned(T_LONG)) ) {
|
||||||
|
@ -3438,25 +3479,29 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||||
}
|
}
|
||||||
|
|
||||||
next_static_word_offset = next_static_double_offset +
|
next_static_word_offset = next_static_double_offset +
|
||||||
(fac.count[STATIC_DOUBLE] * BytesPerLong);
|
((fac.count[STATIC_DOUBLE] - fac_contended.count[STATIC_DOUBLE]) * BytesPerLong);
|
||||||
next_static_short_offset = next_static_word_offset +
|
next_static_short_offset = next_static_word_offset +
|
||||||
(fac.count[STATIC_WORD] * BytesPerInt);
|
((fac.count[STATIC_WORD] - fac_contended.count[STATIC_WORD]) * BytesPerInt);
|
||||||
next_static_byte_offset = next_static_short_offset +
|
next_static_byte_offset = next_static_short_offset +
|
||||||
(fac.count[STATIC_SHORT] * BytesPerShort);
|
((fac.count[STATIC_SHORT] - fac_contended.count[STATIC_SHORT]) * BytesPerShort);
|
||||||
next_static_type_offset = align_size_up((next_static_byte_offset +
|
next_static_padded_offset = next_static_byte_offset +
|
||||||
fac.count[STATIC_BYTE] ), wordSize );
|
((fac.count[STATIC_BYTE] - fac_contended.count[STATIC_BYTE]) * 1);
|
||||||
static_field_size = (next_static_type_offset -
|
|
||||||
next_static_oop_offset) / wordSize;
|
|
||||||
|
|
||||||
first_nonstatic_field_offset = instanceOopDesc::base_offset_in_bytes() +
|
first_nonstatic_field_offset = instanceOopDesc::base_offset_in_bytes() +
|
||||||
nonstatic_field_size * heapOopSize;
|
nonstatic_field_size * heapOopSize;
|
||||||
|
|
||||||
|
// class is contended, pad before all the fields
|
||||||
|
if (parsed_annotations.is_contended()) {
|
||||||
|
first_nonstatic_field_offset += pad_size;
|
||||||
|
}
|
||||||
|
|
||||||
next_nonstatic_field_offset = first_nonstatic_field_offset;
|
next_nonstatic_field_offset = first_nonstatic_field_offset;
|
||||||
|
|
||||||
unsigned int nonstatic_double_count = fac.count[NONSTATIC_DOUBLE];
|
unsigned int nonstatic_double_count = fac.count[NONSTATIC_DOUBLE] - fac_contended.count[NONSTATIC_DOUBLE];
|
||||||
unsigned int nonstatic_word_count = fac.count[NONSTATIC_WORD];
|
unsigned int nonstatic_word_count = fac.count[NONSTATIC_WORD] - fac_contended.count[NONSTATIC_WORD];
|
||||||
unsigned int nonstatic_short_count = fac.count[NONSTATIC_SHORT];
|
unsigned int nonstatic_short_count = fac.count[NONSTATIC_SHORT] - fac_contended.count[NONSTATIC_SHORT];
|
||||||
unsigned int nonstatic_byte_count = fac.count[NONSTATIC_BYTE];
|
unsigned int nonstatic_byte_count = fac.count[NONSTATIC_BYTE] - fac_contended.count[NONSTATIC_BYTE];
|
||||||
unsigned int nonstatic_oop_count = fac.count[NONSTATIC_OOP];
|
unsigned int nonstatic_oop_count = fac.count[NONSTATIC_OOP] - fac_contended.count[NONSTATIC_OOP];
|
||||||
|
|
||||||
bool super_has_nonstatic_fields =
|
bool super_has_nonstatic_fields =
|
||||||
(super_klass() != NULL && super_klass->has_nonstatic_fields());
|
(super_klass() != NULL && super_klass->has_nonstatic_fields());
|
||||||
|
@ -3529,12 +3574,12 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||||
}
|
}
|
||||||
|
|
||||||
if( allocation_style == 0 ) {
|
if( allocation_style == 0 ) {
|
||||||
// Fields order: oops, longs/doubles, ints, shorts/chars, bytes
|
// Fields order: oops, longs/doubles, ints, shorts/chars, bytes, padded fields
|
||||||
next_nonstatic_oop_offset = next_nonstatic_field_offset;
|
next_nonstatic_oop_offset = next_nonstatic_field_offset;
|
||||||
next_nonstatic_double_offset = next_nonstatic_oop_offset +
|
next_nonstatic_double_offset = next_nonstatic_oop_offset +
|
||||||
(nonstatic_oop_count * heapOopSize);
|
(nonstatic_oop_count * heapOopSize);
|
||||||
} else if( allocation_style == 1 ) {
|
} else if( allocation_style == 1 ) {
|
||||||
// Fields order: longs/doubles, ints, shorts/chars, bytes, oops
|
// Fields order: longs/doubles, ints, shorts/chars, bytes, oops, padded fields
|
||||||
next_nonstatic_double_offset = next_nonstatic_field_offset;
|
next_nonstatic_double_offset = next_nonstatic_field_offset;
|
||||||
} else if( allocation_style == 2 ) {
|
} else if( allocation_style == 2 ) {
|
||||||
// Fields allocation: oops fields in super and sub classes are together.
|
// Fields allocation: oops fields in super and sub classes are together.
|
||||||
|
@ -3613,27 +3658,33 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||||
(nonstatic_word_count * BytesPerInt);
|
(nonstatic_word_count * BytesPerInt);
|
||||||
next_nonstatic_byte_offset = next_nonstatic_short_offset +
|
next_nonstatic_byte_offset = next_nonstatic_short_offset +
|
||||||
(nonstatic_short_count * BytesPerShort);
|
(nonstatic_short_count * BytesPerShort);
|
||||||
|
next_nonstatic_padded_offset = next_nonstatic_byte_offset +
|
||||||
|
nonstatic_byte_count;
|
||||||
|
|
||||||
int notaligned_offset;
|
// let oops jump before padding with this allocation style
|
||||||
if( allocation_style == 0 ) {
|
if( allocation_style == 1 ) {
|
||||||
notaligned_offset = next_nonstatic_byte_offset + nonstatic_byte_count;
|
next_nonstatic_oop_offset = next_nonstatic_padded_offset;
|
||||||
} else { // allocation_style == 1
|
|
||||||
next_nonstatic_oop_offset = next_nonstatic_byte_offset + nonstatic_byte_count;
|
|
||||||
if( nonstatic_oop_count > 0 ) {
|
if( nonstatic_oop_count > 0 ) {
|
||||||
next_nonstatic_oop_offset = align_size_up(next_nonstatic_oop_offset, heapOopSize);
|
next_nonstatic_oop_offset = align_size_up(next_nonstatic_oop_offset, heapOopSize);
|
||||||
}
|
}
|
||||||
notaligned_offset = next_nonstatic_oop_offset + (nonstatic_oop_count * heapOopSize);
|
next_nonstatic_padded_offset = next_nonstatic_oop_offset + (nonstatic_oop_count * heapOopSize);
|
||||||
}
|
}
|
||||||
next_nonstatic_type_offset = align_size_up(notaligned_offset, heapOopSize );
|
|
||||||
nonstatic_field_size = nonstatic_field_size + ((next_nonstatic_type_offset
|
|
||||||
- first_nonstatic_field_offset)/heapOopSize);
|
|
||||||
|
|
||||||
// Iterate over fields again and compute correct offsets.
|
// Iterate over fields again and compute correct offsets.
|
||||||
// The field allocation type was temporarily stored in the offset slot.
|
// The field allocation type was temporarily stored in the offset slot.
|
||||||
// oop fields are located before non-oop fields (static and non-static).
|
// oop fields are located before non-oop fields (static and non-static).
|
||||||
for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) {
|
for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) {
|
||||||
|
|
||||||
|
// skip already laid out fields
|
||||||
|
if (fs.is_offset_set()) continue;
|
||||||
|
|
||||||
|
// contended fields are handled below
|
||||||
|
if (fs.is_contended()) continue;
|
||||||
|
|
||||||
int real_offset;
|
int real_offset;
|
||||||
FieldAllocationType atype = (FieldAllocationType) fs.offset();
|
FieldAllocationType atype = (FieldAllocationType) fs.allocation_type();
|
||||||
|
|
||||||
|
// pack the rest of the fields
|
||||||
switch (atype) {
|
switch (atype) {
|
||||||
case STATIC_OOP:
|
case STATIC_OOP:
|
||||||
real_offset = next_static_oop_offset;
|
real_offset = next_static_oop_offset;
|
||||||
|
@ -3722,13 +3773,225 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||||
fs.set_offset(real_offset);
|
fs.set_offset(real_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Handle the contended cases.
|
||||||
|
//
|
||||||
|
// Each contended field should not intersect the cache line with another contended field.
|
||||||
|
// In the absence of alignment information, we end up with pessimistically separating
|
||||||
|
// the fields with full-width padding.
|
||||||
|
//
|
||||||
|
// Additionally, this should not break alignment for the fields, so we round the alignment up
|
||||||
|
// for each field.
|
||||||
|
if (contended_count > 0) {
|
||||||
|
|
||||||
|
// if there is at least one contended field, we need to have pre-padding for them
|
||||||
|
if (nonstatic_contended_count > 0) {
|
||||||
|
next_nonstatic_padded_offset += pad_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// collect all contended groups
|
||||||
|
BitMap bm(cp->size());
|
||||||
|
for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) {
|
||||||
|
// skip already laid out fields
|
||||||
|
if (fs.is_offset_set()) continue;
|
||||||
|
|
||||||
|
if (fs.is_contended()) {
|
||||||
|
bm.set_bit(fs.contended_group());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int current_group = -1;
|
||||||
|
while ((current_group = (int)bm.get_next_one_offset(current_group + 1)) != (int)bm.size()) {
|
||||||
|
|
||||||
|
for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) {
|
||||||
|
|
||||||
|
// skip already laid out fields
|
||||||
|
if (fs.is_offset_set()) continue;
|
||||||
|
|
||||||
|
// skip non-contended fields and fields from different group
|
||||||
|
if (!fs.is_contended() || (fs.contended_group() != current_group)) continue;
|
||||||
|
|
||||||
|
// handle statics below
|
||||||
|
if (fs.access_flags().is_static()) continue;
|
||||||
|
|
||||||
|
int real_offset;
|
||||||
|
FieldAllocationType atype = (FieldAllocationType) fs.allocation_type();
|
||||||
|
|
||||||
|
switch (atype) {
|
||||||
|
case NONSTATIC_BYTE:
|
||||||
|
next_nonstatic_padded_offset = align_size_up(next_nonstatic_padded_offset, 1);
|
||||||
|
real_offset = next_nonstatic_padded_offset;
|
||||||
|
next_nonstatic_padded_offset += 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NONSTATIC_SHORT:
|
||||||
|
next_nonstatic_padded_offset = align_size_up(next_nonstatic_padded_offset, BytesPerShort);
|
||||||
|
real_offset = next_nonstatic_padded_offset;
|
||||||
|
next_nonstatic_padded_offset += BytesPerShort;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NONSTATIC_WORD:
|
||||||
|
next_nonstatic_padded_offset = align_size_up(next_nonstatic_padded_offset, BytesPerInt);
|
||||||
|
real_offset = next_nonstatic_padded_offset;
|
||||||
|
next_nonstatic_padded_offset += BytesPerInt;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NONSTATIC_DOUBLE:
|
||||||
|
next_nonstatic_padded_offset = align_size_up(next_nonstatic_padded_offset, BytesPerLong);
|
||||||
|
real_offset = next_nonstatic_padded_offset;
|
||||||
|
next_nonstatic_padded_offset += BytesPerLong;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NONSTATIC_OOP:
|
||||||
|
next_nonstatic_padded_offset = align_size_up(next_nonstatic_padded_offset, heapOopSize);
|
||||||
|
real_offset = next_nonstatic_padded_offset;
|
||||||
|
next_nonstatic_padded_offset += heapOopSize;
|
||||||
|
|
||||||
|
// Create new oop map
|
||||||
|
nonstatic_oop_offsets[nonstatic_oop_map_count] = real_offset;
|
||||||
|
nonstatic_oop_counts [nonstatic_oop_map_count] = 1;
|
||||||
|
nonstatic_oop_map_count += 1;
|
||||||
|
if( first_nonstatic_oop_offset == 0 ) { // Undefined
|
||||||
|
first_nonstatic_oop_offset = real_offset;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ShouldNotReachHere();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fs.contended_group() == 0) {
|
||||||
|
// Contended group defines the equivalence class over the fields:
|
||||||
|
// the fields within the same contended group are not inter-padded.
|
||||||
|
// The only exception is default group, which does not incur the
|
||||||
|
// equivalence, and so requires intra-padding.
|
||||||
|
next_nonstatic_padded_offset += pad_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.set_offset(real_offset);
|
||||||
|
} // for
|
||||||
|
|
||||||
|
// Start laying out the next group.
|
||||||
|
// Note that this will effectively pad the last group in the back;
|
||||||
|
// this is expected to alleviate memory contention effects for
|
||||||
|
// subclass fields and/or adjacent object.
|
||||||
|
// If this was the default group, the padding is already in place.
|
||||||
|
if (current_group != 0) {
|
||||||
|
next_nonstatic_padded_offset += pad_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle static fields
|
||||||
|
|
||||||
|
// if there is at least one contended field, we need to have pre-padding for them
|
||||||
|
if (static_contended_count > 0) {
|
||||||
|
next_static_padded_offset += pad_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
current_group = -1;
|
||||||
|
while ((current_group = (int)bm.get_next_one_offset(current_group + 1)) != (int)bm.size()) {
|
||||||
|
|
||||||
|
for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) {
|
||||||
|
|
||||||
|
// skip already laid out fields
|
||||||
|
if (fs.is_offset_set()) continue;
|
||||||
|
|
||||||
|
// skip non-contended fields and fields from different group
|
||||||
|
if (!fs.is_contended() || (fs.contended_group() != current_group)) continue;
|
||||||
|
|
||||||
|
// non-statics already handled above
|
||||||
|
if (!fs.access_flags().is_static()) continue;
|
||||||
|
|
||||||
|
int real_offset;
|
||||||
|
FieldAllocationType atype = (FieldAllocationType) fs.allocation_type();
|
||||||
|
|
||||||
|
switch (atype) {
|
||||||
|
|
||||||
|
case STATIC_BYTE:
|
||||||
|
next_static_padded_offset = align_size_up(next_static_padded_offset, 1);
|
||||||
|
real_offset = next_static_padded_offset;
|
||||||
|
next_static_padded_offset += 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATIC_SHORT:
|
||||||
|
next_static_padded_offset = align_size_up(next_static_padded_offset, BytesPerShort);
|
||||||
|
real_offset = next_static_padded_offset;
|
||||||
|
next_static_padded_offset += BytesPerShort;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATIC_WORD:
|
||||||
|
next_static_padded_offset = align_size_up(next_static_padded_offset, BytesPerInt);
|
||||||
|
real_offset = next_static_padded_offset;
|
||||||
|
next_static_padded_offset += BytesPerInt;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATIC_DOUBLE:
|
||||||
|
next_static_padded_offset = align_size_up(next_static_padded_offset, BytesPerLong);
|
||||||
|
real_offset = next_static_padded_offset;
|
||||||
|
next_static_padded_offset += BytesPerLong;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATIC_OOP:
|
||||||
|
next_static_padded_offset = align_size_up(next_static_padded_offset, heapOopSize);
|
||||||
|
real_offset = next_static_padded_offset;
|
||||||
|
next_static_padded_offset += heapOopSize;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ShouldNotReachHere();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fs.contended_group() == 0) {
|
||||||
|
// Contended group defines the equivalence class over the fields:
|
||||||
|
// the fields within the same contended group are not inter-padded.
|
||||||
|
// The only exception is default group, which does not incur the
|
||||||
|
// equivalence, and so requires intra-padding.
|
||||||
|
next_static_padded_offset += pad_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.set_offset(real_offset);
|
||||||
|
} // for
|
||||||
|
|
||||||
|
// Start laying out the next group.
|
||||||
|
// Note that this will effectively pad the last group in the back;
|
||||||
|
// this is expected to alleviate memory contention effects for
|
||||||
|
// subclass fields and/or adjacent object.
|
||||||
|
// If this was the default group, the padding is already in place.
|
||||||
|
if (current_group != 0) {
|
||||||
|
next_static_padded_offset += pad_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // handle contended
|
||||||
|
|
||||||
// Size of instances
|
// Size of instances
|
||||||
int instance_size;
|
int instance_size;
|
||||||
|
|
||||||
|
int notaligned_offset = next_nonstatic_padded_offset;
|
||||||
|
|
||||||
|
// Entire class is contended, pad in the back.
|
||||||
|
// This helps to alleviate memory contention effects for subclass fields
|
||||||
|
// and/or adjacent object.
|
||||||
|
if (parsed_annotations.is_contended()) {
|
||||||
|
notaligned_offset += pad_size;
|
||||||
|
next_static_padded_offset += pad_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
int next_static_type_offset = align_size_up(next_static_padded_offset, wordSize);
|
||||||
|
int static_field_size = (next_static_type_offset -
|
||||||
|
InstanceMirrorKlass::offset_of_static_fields()) / wordSize;
|
||||||
|
|
||||||
|
next_nonstatic_type_offset = align_size_up(notaligned_offset, heapOopSize );
|
||||||
|
nonstatic_field_size = nonstatic_field_size + ((next_nonstatic_type_offset
|
||||||
|
- first_nonstatic_field_offset)/heapOopSize);
|
||||||
|
|
||||||
next_nonstatic_type_offset = align_size_up(notaligned_offset, wordSize );
|
next_nonstatic_type_offset = align_size_up(notaligned_offset, wordSize );
|
||||||
instance_size = align_object_size(next_nonstatic_type_offset / wordSize);
|
instance_size = align_object_size(next_nonstatic_type_offset / wordSize);
|
||||||
|
|
||||||
assert(instance_size == align_object_size(align_size_up((instanceOopDesc::base_offset_in_bytes() + nonstatic_field_size*heapOopSize), wordSize) / wordSize), "consistent layout helper value");
|
assert(instance_size == align_object_size(align_size_up(
|
||||||
|
(instanceOopDesc::base_offset_in_bytes() + nonstatic_field_size*heapOopSize + ((parsed_annotations.is_contended()) ? pad_size : 0)),
|
||||||
|
wordSize) / wordSize), "consistent layout helper value");
|
||||||
|
|
||||||
// Number of non-static oop map blocks allocated at end of klass.
|
// Number of non-static oop map blocks allocated at end of klass.
|
||||||
const unsigned int total_oop_map_count =
|
const unsigned int total_oop_map_count =
|
||||||
|
@ -4008,6 +4271,18 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef PRODUCT
|
||||||
|
if (PrintFieldLayout) {
|
||||||
|
print_field_layout(name,
|
||||||
|
fields,
|
||||||
|
cp,
|
||||||
|
instance_size,
|
||||||
|
first_nonstatic_field_offset,
|
||||||
|
next_nonstatic_field_offset,
|
||||||
|
next_static_type_offset);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// preserve result across HandleMark
|
// preserve result across HandleMark
|
||||||
preserve_this_klass = this_klass();
|
preserve_this_klass = this_klass();
|
||||||
}
|
}
|
||||||
|
@ -4020,6 +4295,38 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||||
return this_klass;
|
return this_klass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ClassFileParser::print_field_layout(Symbol* name,
|
||||||
|
Array<u2>* fields,
|
||||||
|
constantPoolHandle cp,
|
||||||
|
int instance_size,
|
||||||
|
int instance_fields_start,
|
||||||
|
int instance_fields_end,
|
||||||
|
int static_fields_end) {
|
||||||
|
tty->print("%s: field layout\n", name->as_klass_external_name());
|
||||||
|
tty->print(" @%3d %s\n", instance_fields_start, "--- instance fields start ---");
|
||||||
|
for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) {
|
||||||
|
if (!fs.access_flags().is_static()) {
|
||||||
|
tty->print(" @%3d \"%s\" %s\n",
|
||||||
|
fs.offset(),
|
||||||
|
fs.name()->as_klass_external_name(),
|
||||||
|
fs.signature()->as_klass_external_name());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tty->print(" @%3d %s\n", instance_fields_end, "--- instance fields end ---");
|
||||||
|
tty->print(" @%3d %s\n", instance_size * wordSize, "--- instance ends ---");
|
||||||
|
tty->print(" @%3d %s\n", InstanceMirrorKlass::offset_of_static_fields(), "--- static fields start ---");
|
||||||
|
for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) {
|
||||||
|
if (fs.access_flags().is_static()) {
|
||||||
|
tty->print(" @%3d \"%s\" %s\n",
|
||||||
|
fs.offset(),
|
||||||
|
fs.name()->as_klass_external_name(),
|
||||||
|
fs.signature()->as_klass_external_name());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tty->print(" @%3d %s\n", static_fields_end, "--- static fields end ---");
|
||||||
|
tty->print("\n");
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int
|
unsigned int
|
||||||
ClassFileParser::compute_oop_map_count(instanceKlassHandle super,
|
ClassFileParser::compute_oop_map_count(instanceKlassHandle super,
|
||||||
unsigned int nonstatic_oop_map_count,
|
unsigned int nonstatic_oop_map_count,
|
||||||
|
|
|
@ -95,17 +95,20 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
|
||||||
_method_DontInline,
|
_method_DontInline,
|
||||||
_method_LambdaForm_Compiled,
|
_method_LambdaForm_Compiled,
|
||||||
_method_LambdaForm_Hidden,
|
_method_LambdaForm_Hidden,
|
||||||
|
_sun_misc_Contended,
|
||||||
_annotation_LIMIT
|
_annotation_LIMIT
|
||||||
};
|
};
|
||||||
const Location _location;
|
const Location _location;
|
||||||
int _annotations_present;
|
int _annotations_present;
|
||||||
|
u2 _contended_group;
|
||||||
|
|
||||||
AnnotationCollector(Location location)
|
AnnotationCollector(Location location)
|
||||||
: _location(location), _annotations_present(0)
|
: _location(location), _annotations_present(0)
|
||||||
{
|
{
|
||||||
assert((int)_annotation_LIMIT <= (int)sizeof(_annotations_present) * BitsPerByte, "");
|
assert((int)_annotation_LIMIT <= (int)sizeof(_annotations_present) * BitsPerByte, "");
|
||||||
}
|
}
|
||||||
// If this annotation name has an ID, report it (or _none).
|
// If this annotation name has an ID, report it (or _none).
|
||||||
ID annotation_index(Symbol* name);
|
ID annotation_index(ClassLoaderData* loader_data, Symbol* name);
|
||||||
// Set the annotation name:
|
// Set the annotation name:
|
||||||
void set_annotation(ID id) {
|
void set_annotation(ID id) {
|
||||||
assert((int)id >= 0 && (int)id < (int)_annotation_LIMIT, "oob");
|
assert((int)id >= 0 && (int)id < (int)_annotation_LIMIT, "oob");
|
||||||
|
@ -114,6 +117,12 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
|
||||||
// Report if the annotation is present.
|
// Report if the annotation is present.
|
||||||
bool has_any_annotations() { return _annotations_present != 0; }
|
bool has_any_annotations() { return _annotations_present != 0; }
|
||||||
bool has_annotation(ID id) { return (nth_bit((int)id) & _annotations_present) != 0; }
|
bool has_annotation(ID id) { return (nth_bit((int)id) & _annotations_present) != 0; }
|
||||||
|
|
||||||
|
void set_contended_group(u2 group) { _contended_group = group; }
|
||||||
|
u2 contended_group() { return _contended_group; }
|
||||||
|
|
||||||
|
void set_contended(bool contended) { set_annotation(_sun_misc_Contended); }
|
||||||
|
bool is_contended() { return has_annotation(_sun_misc_Contended); }
|
||||||
};
|
};
|
||||||
class FieldAnnotationCollector: public AnnotationCollector {
|
class FieldAnnotationCollector: public AnnotationCollector {
|
||||||
public:
|
public:
|
||||||
|
@ -177,6 +186,14 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
|
||||||
Array<AnnotationArray*>** fields_type_annotations,
|
Array<AnnotationArray*>** fields_type_annotations,
|
||||||
u2* java_fields_count_ptr, TRAPS);
|
u2* java_fields_count_ptr, TRAPS);
|
||||||
|
|
||||||
|
void print_field_layout(Symbol* name,
|
||||||
|
Array<u2>* fields,
|
||||||
|
constantPoolHandle cp,
|
||||||
|
int instance_size,
|
||||||
|
int instance_fields_start,
|
||||||
|
int instance_fields_end,
|
||||||
|
int static_fields_end);
|
||||||
|
|
||||||
// Method parsing
|
// Method parsing
|
||||||
methodHandle parse_method(ClassLoaderData* loader_data,
|
methodHandle parse_method(ClassLoaderData* loader_data,
|
||||||
constantPoolHandle cp,
|
constantPoolHandle cp,
|
||||||
|
@ -247,7 +264,8 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
|
||||||
int runtime_invisible_annotations_length, TRAPS);
|
int runtime_invisible_annotations_length, TRAPS);
|
||||||
int skip_annotation(u1* buffer, int limit, int index);
|
int skip_annotation(u1* buffer, int limit, int index);
|
||||||
int skip_annotation_value(u1* buffer, int limit, int index);
|
int skip_annotation_value(u1* buffer, int limit, int index);
|
||||||
void parse_annotations(u1* buffer, int limit, constantPoolHandle cp,
|
void parse_annotations(ClassLoaderData* loader_data,
|
||||||
|
u1* buffer, int limit, constantPoolHandle cp,
|
||||||
/* Results (currently, only one result is supported): */
|
/* Results (currently, only one result is supported): */
|
||||||
AnnotationCollector* result,
|
AnnotationCollector* result,
|
||||||
TRAPS);
|
TRAPS);
|
||||||
|
|
|
@ -194,7 +194,10 @@
|
||||||
template(java_lang_VirtualMachineError, "java/lang/VirtualMachineError") \
|
template(java_lang_VirtualMachineError, "java/lang/VirtualMachineError") \
|
||||||
template(java_lang_StackOverflowError, "java/lang/StackOverflowError") \
|
template(java_lang_StackOverflowError, "java/lang/StackOverflowError") \
|
||||||
template(java_lang_StackTraceElement, "java/lang/StackTraceElement") \
|
template(java_lang_StackTraceElement, "java/lang/StackTraceElement") \
|
||||||
|
\
|
||||||
|
/* Concurrency support */ \
|
||||||
template(java_util_concurrent_locks_AbstractOwnableSynchronizer, "java/util/concurrent/locks/AbstractOwnableSynchronizer") \
|
template(java_util_concurrent_locks_AbstractOwnableSynchronizer, "java/util/concurrent/locks/AbstractOwnableSynchronizer") \
|
||||||
|
template(sun_misc_Contended_signature, "Lsun/misc/Contended;") \
|
||||||
\
|
\
|
||||||
/* class symbols needed by intrinsics */ \
|
/* class symbols needed by intrinsics */ \
|
||||||
VM_INTRINSICS_DO(VM_INTRINSIC_IGNORE, template, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE) \
|
VM_INTRINSICS_DO(VM_INTRINSIC_IGNORE, template, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE) \
|
||||||
|
|
|
@ -43,14 +43,29 @@ class FieldInfo VALUE_OBJ_CLASS_SPEC {
|
||||||
public:
|
public:
|
||||||
// fields
|
// fields
|
||||||
// Field info extracted from the class file and stored
|
// 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 {
|
enum FieldOffset {
|
||||||
access_flags_offset = 0,
|
access_flags_offset = 0,
|
||||||
name_index_offset = 1,
|
name_index_offset = 1,
|
||||||
signature_index_offset = 2,
|
signature_index_offset = 2,
|
||||||
initval_index_offset = 3,
|
initval_index_offset = 3,
|
||||||
low_offset = 4,
|
low_packed_offset = 4,
|
||||||
high_offset = 5,
|
high_packed_offset = 5,
|
||||||
field_slots = 6
|
field_slots = 6
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -76,17 +91,90 @@ class FieldInfo VALUE_OBJ_CLASS_SPEC {
|
||||||
void initialize(u2 access_flags,
|
void initialize(u2 access_flags,
|
||||||
u2 name_index,
|
u2 name_index,
|
||||||
u2 signature_index,
|
u2 signature_index,
|
||||||
u2 initval_index,
|
u2 initval_index) {
|
||||||
u4 offset) {
|
|
||||||
_shorts[access_flags_offset] = access_flags;
|
_shorts[access_flags_offset] = access_flags;
|
||||||
_shorts[name_index_offset] = name_index;
|
_shorts[name_index_offset] = name_index;
|
||||||
_shorts[signature_index_offset] = signature_index;
|
_shorts[signature_index_offset] = signature_index;
|
||||||
_shorts[initval_index_offset] = initval_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]; }
|
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 {
|
Symbol* name(constantPoolHandle cp) const {
|
||||||
int index = name_index();
|
int index = name_index();
|
||||||
|
@ -106,8 +194,46 @@ class FieldInfo VALUE_OBJ_CLASS_SPEC {
|
||||||
|
|
||||||
void set_access_flags(u2 val) { _shorts[access_flags_offset] = val; }
|
void set_access_flags(u2 val) { _shorts[access_flags_offset] = val; }
|
||||||
void set_offset(u4 val) {
|
void set_offset(u4 val) {
|
||||||
_shorts[low_offset] = extract_low_short_from_int(val);
|
val = val << FIELDINFO_TAG_SIZE; // make room for tag
|
||||||
_shorts[high_offset] = extract_high_short_from_int(val);
|
_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 {
|
bool is_internal() const {
|
||||||
|
|
|
@ -160,9 +160,26 @@ class FieldStreamBase : public StackObj {
|
||||||
return field()->offset();
|
return field()->offset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int allocation_type() const {
|
||||||
|
return field()->allocation_type();
|
||||||
|
}
|
||||||
|
|
||||||
void set_offset(int offset) {
|
void set_offset(int offset) {
|
||||||
field()->set_offset(offset);
|
field()->set_offset(offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_offset_set() const {
|
||||||
|
return field()->is_offset_set();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_contended() const {
|
||||||
|
return field()->is_contended();
|
||||||
|
}
|
||||||
|
|
||||||
|
int contended_group() const {
|
||||||
|
return field()->contended_group();
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Iterate over only the internal fields
|
// Iterate over only the internal fields
|
||||||
|
|
|
@ -230,7 +230,8 @@ class InstanceKlass: public Klass {
|
||||||
_misc_rewritten = 1 << 0, // methods rewritten.
|
_misc_rewritten = 1 << 0, // methods rewritten.
|
||||||
_misc_has_nonstatic_fields = 1 << 1, // for sizing with UseCompressedOops
|
_misc_has_nonstatic_fields = 1 << 1, // for sizing with UseCompressedOops
|
||||||
_misc_should_verify_class = 1 << 2, // allow caching of preverification
|
_misc_should_verify_class = 1 << 2, // allow caching of preverification
|
||||||
_misc_is_anonymous = 1 << 3 // has embedded _inner_classes field
|
_misc_is_anonymous = 1 << 3, // has embedded _inner_classes field
|
||||||
|
_misc_is_contended = 1 << 4 // marked with contended annotation
|
||||||
};
|
};
|
||||||
u2 _misc_flags;
|
u2 _misc_flags;
|
||||||
u2 _minor_version; // minor version number of class file
|
u2 _minor_version; // minor version number of class file
|
||||||
|
@ -550,6 +551,17 @@ class InstanceKlass: public Klass {
|
||||||
return is_anonymous() ? java_mirror() : class_loader();
|
return is_anonymous() ? java_mirror() : class_loader();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_contended() const {
|
||||||
|
return (_misc_flags & _misc_is_contended) != 0;
|
||||||
|
}
|
||||||
|
void set_is_contended(bool value) {
|
||||||
|
if (value) {
|
||||||
|
_misc_flags |= _misc_is_contended;
|
||||||
|
} else {
|
||||||
|
_misc_flags &= ~_misc_is_contended;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// signers
|
// signers
|
||||||
objArrayOop signers() const { return _signers; }
|
objArrayOop signers() const { return _signers; }
|
||||||
void set_signers(objArrayOop s) { klass_oop_store((oop*)&_signers, s); }
|
void set_signers(objArrayOop s) { klass_oop_store((oop*)&_signers, s); }
|
||||||
|
|
|
@ -1075,7 +1075,7 @@ class CommandLineFlags {
|
||||||
\
|
\
|
||||||
product(intx, ClearFPUAtPark, 0, "(Unsafe,Unstable)" ) \
|
product(intx, ClearFPUAtPark, 0, "(Unsafe,Unstable)" ) \
|
||||||
\
|
\
|
||||||
product(intx, hashCode, 0, \
|
product(intx, hashCode, 5, \
|
||||||
"(Unstable) select hashCode generation algorithm" ) \
|
"(Unstable) select hashCode generation algorithm" ) \
|
||||||
\
|
\
|
||||||
product(intx, WorkAroundNPTLTimedWaitHang, 1, \
|
product(intx, WorkAroundNPTLTimedWaitHang, 1, \
|
||||||
|
@ -1173,6 +1173,18 @@ class CommandLineFlags {
|
||||||
notproduct(bool, PrintCompactFieldsSavings, false, \
|
notproduct(bool, PrintCompactFieldsSavings, false, \
|
||||||
"Print how many words were saved with CompactFields") \
|
"Print how many words were saved with CompactFields") \
|
||||||
\
|
\
|
||||||
|
notproduct(bool, PrintFieldLayout, false, \
|
||||||
|
"Print field layout for each class") \
|
||||||
|
\
|
||||||
|
product(intx, ContendedPaddingWidth, 128, \
|
||||||
|
"How many bytes to pad the fields/classes marked @Contended with")\
|
||||||
|
\
|
||||||
|
product(bool, EnableContended, true, \
|
||||||
|
"Enable @Contended annotation support") \
|
||||||
|
\
|
||||||
|
product(bool, RestrictContended, true, \
|
||||||
|
"Restrict @Contended to trusted classes") \
|
||||||
|
\
|
||||||
product(bool, UseBiasedLocking, true, \
|
product(bool, UseBiasedLocking, true, \
|
||||||
"Enable biased locking in JVM") \
|
"Enable biased locking in JVM") \
|
||||||
\
|
\
|
||||||
|
|
|
@ -2284,10 +2284,17 @@ typedef BinaryTreeDictionary<Metablock, FreeList> MetablockTreeDictionary;
|
||||||
declare_constant(FieldInfo::name_index_offset) \
|
declare_constant(FieldInfo::name_index_offset) \
|
||||||
declare_constant(FieldInfo::signature_index_offset) \
|
declare_constant(FieldInfo::signature_index_offset) \
|
||||||
declare_constant(FieldInfo::initval_index_offset) \
|
declare_constant(FieldInfo::initval_index_offset) \
|
||||||
declare_constant(FieldInfo::low_offset) \
|
declare_constant(FieldInfo::low_packed_offset) \
|
||||||
declare_constant(FieldInfo::high_offset) \
|
declare_constant(FieldInfo::high_packed_offset) \
|
||||||
declare_constant(FieldInfo::field_slots) \
|
declare_constant(FieldInfo::field_slots) \
|
||||||
\
|
\
|
||||||
|
/*************************************/ \
|
||||||
|
/* FieldInfo tag constants */ \
|
||||||
|
/*************************************/ \
|
||||||
|
\
|
||||||
|
declare_preprocessor_constant("FIELDINFO_TAG_SIZE", FIELDINFO_TAG_SIZE) \
|
||||||
|
declare_preprocessor_constant("FIELDINFO_TAG_OFFSET", FIELDINFO_TAG_OFFSET) \
|
||||||
|
\
|
||||||
/************************************************/ \
|
/************************************************/ \
|
||||||
/* InstanceKlass InnerClassAttributeOffset enum */ \
|
/* InstanceKlass InnerClassAttributeOffset enum */ \
|
||||||
/************************************************/ \
|
/************************************************/ \
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue