提交 cdc18c13 编写于 作者: C coleenp

8003419: NPG: Clean up metadata created during class loading if failure

Summary: Store metadata on ClassFileParser instance to be cleaned up by destructor.  This enabled some refactoring of the enormous parseClassFile function.
Reviewed-by: jmasa, acorn
上级 ea32fa70
......@@ -90,8 +90,7 @@
// Extension method support.
#define JAVA_8_VERSION 52
void ClassFileParser::parse_constant_pool_entries(ClassLoaderData* loader_data, constantPoolHandle cp, int length, TRAPS) {
void ClassFileParser::parse_constant_pool_entries(int length, TRAPS) {
// Use a local copy of ClassFileStream. It helps the C++ compiler to optimize
// this function (_current can be allocated in a register, with scalar
// replacement of aggregates). The _current pointer is copied back to
......@@ -104,7 +103,7 @@ void ClassFileParser::parse_constant_pool_entries(ClassLoaderData* loader_data,
assert(cfs->allocated_on_stack(),"should be local");
u1* old_current = cfs0->current();
#endif
Handle class_loader(THREAD, loader_data->class_loader());
Handle class_loader(THREAD, _loader_data->class_loader());
// Used for batching symbol allocations.
const char* names[SymbolTable::symbol_alloc_batch_size];
......@@ -124,7 +123,7 @@ void ClassFileParser::parse_constant_pool_entries(ClassLoaderData* loader_data,
{
cfs->guarantee_more(3, CHECK); // name_index, tag/access_flags
u2 name_index = cfs->get_u2_fast();
cp->klass_index_at_put(index, name_index);
_cp->klass_index_at_put(index, name_index);
}
break;
case JVM_CONSTANT_Fieldref :
......@@ -132,7 +131,7 @@ void ClassFileParser::parse_constant_pool_entries(ClassLoaderData* loader_data,
cfs->guarantee_more(5, CHECK); // class_index, name_and_type_index, tag/access_flags
u2 class_index = cfs->get_u2_fast();
u2 name_and_type_index = cfs->get_u2_fast();
cp->field_at_put(index, class_index, name_and_type_index);
_cp->field_at_put(index, class_index, name_and_type_index);
}
break;
case JVM_CONSTANT_Methodref :
......@@ -140,7 +139,7 @@ void ClassFileParser::parse_constant_pool_entries(ClassLoaderData* loader_data,
cfs->guarantee_more(5, CHECK); // class_index, name_and_type_index, tag/access_flags
u2 class_index = cfs->get_u2_fast();
u2 name_and_type_index = cfs->get_u2_fast();
cp->method_at_put(index, class_index, name_and_type_index);
_cp->method_at_put(index, class_index, name_and_type_index);
}
break;
case JVM_CONSTANT_InterfaceMethodref :
......@@ -148,14 +147,14 @@ void ClassFileParser::parse_constant_pool_entries(ClassLoaderData* loader_data,
cfs->guarantee_more(5, CHECK); // class_index, name_and_type_index, tag/access_flags
u2 class_index = cfs->get_u2_fast();
u2 name_and_type_index = cfs->get_u2_fast();
cp->interface_method_at_put(index, class_index, name_and_type_index);
_cp->interface_method_at_put(index, class_index, name_and_type_index);
}
break;
case JVM_CONSTANT_String :
{
cfs->guarantee_more(3, CHECK); // string_index, tag/access_flags
u2 string_index = cfs->get_u2_fast();
cp->string_index_at_put(index, string_index);
_cp->string_index_at_put(index, string_index);
}
break;
case JVM_CONSTANT_MethodHandle :
......@@ -174,11 +173,11 @@ void ClassFileParser::parse_constant_pool_entries(ClassLoaderData* loader_data,
cfs->guarantee_more(4, CHECK); // ref_kind, method_index, tag/access_flags
u1 ref_kind = cfs->get_u1_fast();
u2 method_index = cfs->get_u2_fast();
cp->method_handle_index_at_put(index, ref_kind, method_index);
_cp->method_handle_index_at_put(index, ref_kind, method_index);
} else if (tag == JVM_CONSTANT_MethodType) {
cfs->guarantee_more(3, CHECK); // signature_index, tag/access_flags
u2 signature_index = cfs->get_u2_fast();
cp->method_type_index_at_put(index, signature_index);
_cp->method_type_index_at_put(index, signature_index);
} else {
ShouldNotReachHere();
}
......@@ -200,21 +199,21 @@ void ClassFileParser::parse_constant_pool_entries(ClassLoaderData* loader_data,
u2 name_and_type_index = cfs->get_u2_fast();
if (_max_bootstrap_specifier_index < (int) bootstrap_specifier_index)
_max_bootstrap_specifier_index = (int) bootstrap_specifier_index; // collect for later
cp->invoke_dynamic_at_put(index, bootstrap_specifier_index, name_and_type_index);
_cp->invoke_dynamic_at_put(index, bootstrap_specifier_index, name_and_type_index);
}
break;
case JVM_CONSTANT_Integer :
{
cfs->guarantee_more(5, CHECK); // bytes, tag/access_flags
u4 bytes = cfs->get_u4_fast();
cp->int_at_put(index, (jint) bytes);
_cp->int_at_put(index, (jint) bytes);
}
break;
case JVM_CONSTANT_Float :
{
cfs->guarantee_more(5, CHECK); // bytes, tag/access_flags
u4 bytes = cfs->get_u4_fast();
cp->float_at_put(index, *(jfloat*)&bytes);
_cp->float_at_put(index, *(jfloat*)&bytes);
}
break;
case JVM_CONSTANT_Long :
......@@ -225,7 +224,7 @@ void ClassFileParser::parse_constant_pool_entries(ClassLoaderData* loader_data,
{
cfs->guarantee_more(9, CHECK); // bytes, tag/access_flags
u8 bytes = cfs->get_u8_fast();
cp->long_at_put(index, bytes);
_cp->long_at_put(index, bytes);
}
index++; // Skip entry following eigth-byte constant, see JVM book p. 98
break;
......@@ -237,7 +236,7 @@ void ClassFileParser::parse_constant_pool_entries(ClassLoaderData* loader_data,
{
cfs->guarantee_more(9, CHECK); // bytes, tag/access_flags
u8 bytes = cfs->get_u8_fast();
cp->double_at_put(index, *(jdouble*)&bytes);
_cp->double_at_put(index, *(jdouble*)&bytes);
}
index++; // Skip entry following eigth-byte constant, see JVM book p. 98
break;
......@@ -246,7 +245,7 @@ void ClassFileParser::parse_constant_pool_entries(ClassLoaderData* loader_data,
cfs->guarantee_more(5, CHECK); // name_index, signature_index, tag/access_flags
u2 name_index = cfs->get_u2_fast();
u2 signature_index = cfs->get_u2_fast();
cp->name_and_type_at_put(index, name_index, signature_index);
_cp->name_and_type_at_put(index, name_index, signature_index);
}
break;
case JVM_CONSTANT_Utf8 :
......@@ -283,11 +282,11 @@ void ClassFileParser::parse_constant_pool_entries(ClassLoaderData* loader_data,
indices[names_count] = index;
hashValues[names_count++] = hash;
if (names_count == SymbolTable::symbol_alloc_batch_size) {
SymbolTable::new_symbols(loader_data, cp, names_count, names, lengths, indices, hashValues, CHECK);
SymbolTable::new_symbols(_loader_data, _cp, names_count, names, lengths, indices, hashValues, CHECK);
names_count = 0;
}
} else {
cp->symbol_at_put(index, result);
_cp->symbol_at_put(index, result);
}
}
break;
......@@ -300,7 +299,7 @@ void ClassFileParser::parse_constant_pool_entries(ClassLoaderData* loader_data,
// Allocate the remaining symbols
if (names_count > 0) {
SymbolTable::new_symbols(loader_data, cp, names_count, names, lengths, indices, hashValues, CHECK);
SymbolTable::new_symbols(_loader_data, _cp, names_count, names, lengths, indices, hashValues, CHECK);
}
// Copy _current pointer of local copy back to stream().
......@@ -310,23 +309,6 @@ void ClassFileParser::parse_constant_pool_entries(ClassLoaderData* loader_data,
cfs0->set_current(cfs1.current());
}
// This class unreferences constant pool symbols if an error has occurred
// while parsing the class before it is assigned into the class.
// If it gets an error after that it is unloaded and the constant pool will
// be cleaned up then.
class ConstantPoolCleaner : public StackObj {
constantPoolHandle _cphandle;
bool _in_error;
public:
ConstantPoolCleaner(constantPoolHandle cp) : _cphandle(cp), _in_error(true) {}
~ConstantPoolCleaner() {
if (_in_error && _cphandle.not_null()) {
_cphandle->unreference_symbols();
}
}
void set_in_error(bool clean) { _in_error = clean; }
};
bool inline valid_cp_range(int index, int length) { return (index > 0 && index < length); }
inline Symbol* check_symbol_at(constantPoolHandle cp, int index) {
......@@ -336,7 +318,7 @@ inline Symbol* check_symbol_at(constantPoolHandle cp, int index) {
return NULL;
}
constantPoolHandle ClassFileParser::parse_constant_pool(ClassLoaderData* loader_data, TRAPS) {
constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) {
ClassFileStream* cfs = stream();
constantPoolHandle nullHandle;
......@@ -345,16 +327,13 @@ constantPoolHandle ClassFileParser::parse_constant_pool(ClassLoaderData* loader_
guarantee_property(
length >= 1, "Illegal constant pool size %u in class file %s",
length, CHECK_(nullHandle));
ConstantPool* constant_pool =
ConstantPool::allocate(loader_data,
length,
ConstantPool* constant_pool = ConstantPool::allocate(_loader_data, length,
CHECK_(nullHandle));
_cp = constant_pool; // save in case of errors
constantPoolHandle cp (THREAD, constant_pool);
ConstantPoolCleaner cp_in_error(cp); // set constant pool to be cleaned up.
// parsing constant pool entries
parse_constant_pool_entries(loader_data, cp, length, CHECK_(nullHandle));
parse_constant_pool_entries(length, CHECK_(nullHandle));
int index = 1; // declared outside of loops for portability
......@@ -373,8 +352,7 @@ constantPoolHandle ClassFileParser::parse_constant_pool(ClassLoaderData* loader_
if (!_need_verify) break;
int klass_ref_index = cp->klass_ref_index_at(index);
int name_and_type_ref_index = cp->name_and_type_ref_index_at(index);
check_property(valid_cp_range(klass_ref_index, length) &&
is_klass_reference(cp, klass_ref_index),
check_property(valid_klass_reference_at(klass_ref_index),
"Invalid constant pool index %u in class file %s",
klass_ref_index,
CHECK_(nullHandle));
......@@ -404,14 +382,10 @@ constantPoolHandle ClassFileParser::parse_constant_pool(ClassLoaderData* loader_
if (!_need_verify) break;
int name_ref_index = cp->name_ref_index_at(index);
int signature_ref_index = cp->signature_ref_index_at(index);
check_property(
valid_cp_range(name_ref_index, length) &&
cp->tag_at(name_ref_index).is_utf8(),
check_property(valid_symbol_at(name_ref_index),
"Invalid constant pool index %u in class file %s",
name_ref_index, CHECK_(nullHandle));
check_property(
valid_cp_range(signature_ref_index, length) &&
cp->tag_at(signature_ref_index).is_utf8(),
check_property(valid_symbol_at(signature_ref_index),
"Invalid constant pool index %u in class file %s",
signature_ref_index, CHECK_(nullHandle));
break;
......@@ -425,9 +399,7 @@ constantPoolHandle ClassFileParser::parse_constant_pool(ClassLoaderData* loader_
case JVM_CONSTANT_ClassIndex :
{
int class_index = cp->klass_index_at(index);
check_property(
valid_cp_range(class_index, length) &&
cp->tag_at(class_index).is_utf8(),
check_property(valid_symbol_at(class_index),
"Invalid constant pool index %u in class file %s",
class_index, CHECK_(nullHandle));
cp->unresolved_klass_at_put(index, cp->symbol_at(class_index));
......@@ -436,9 +408,7 @@ constantPoolHandle ClassFileParser::parse_constant_pool(ClassLoaderData* loader_
case JVM_CONSTANT_StringIndex :
{
int string_index = cp->string_index_at(index);
check_property(
valid_cp_range(string_index, length) &&
cp->tag_at(string_index).is_utf8(),
check_property(valid_symbol_at(string_index),
"Invalid constant pool index %u in class file %s",
string_index, CHECK_(nullHandle));
Symbol* sym = cp->symbol_at(string_index);
......@@ -491,10 +461,7 @@ constantPoolHandle ClassFileParser::parse_constant_pool(ClassLoaderData* loader_
case JVM_CONSTANT_MethodType :
{
int ref_index = cp->method_type_index_at(index);
check_property(
valid_cp_range(ref_index, length) &&
cp->tag_at(ref_index).is_utf8() &&
EnableInvokeDynamic,
check_property(valid_symbol_at(ref_index) && EnableInvokeDynamic,
"Invalid constant pool index %u in class file %s",
ref_index, CHECK_(nullHandle));
}
......@@ -541,7 +508,6 @@ constantPoolHandle ClassFileParser::parse_constant_pool(ClassLoaderData* loader_
}
if (!_need_verify) {
cp_in_error.set_in_error(false);
return cp;
}
......@@ -664,7 +630,6 @@ constantPoolHandle ClassFileParser::parse_constant_pool(ClassLoaderData* loader_
} // end of switch
} // end of for
cp_in_error.set_in_error(false);
return cp;
}
......@@ -786,37 +751,36 @@ bool put_after_lookup(Symbol* name, Symbol* sig, NameSigHash** table) {
}
Array<Klass*>* ClassFileParser::parse_interfaces(constantPoolHandle cp,
int length,
ClassLoaderData* loader_data,
Array<Klass*>* ClassFileParser::parse_interfaces(int length,
Handle protection_domain,
Symbol* class_name,
bool* has_default_methods,
TRAPS) {
if (length == 0) {
_local_interfaces = Universe::the_empty_klass_array();
} else {
ClassFileStream* cfs = stream();
assert(length > 0, "only called for length>0");
// FIXME: Leak at later OOM.
Array<Klass*>* interfaces = MetadataFactory::new_array<Klass*>(loader_data, length, NULL, CHECK_NULL);
_local_interfaces = MetadataFactory::new_array<Klass*>(_loader_data, length, NULL, CHECK_NULL);
int index;
for (index = 0; index < length; index++) {
u2 interface_index = cfs->get_u2(CHECK_NULL);
KlassHandle interf;
check_property(
valid_cp_range(interface_index, cp->length()) &&
is_klass_reference(cp, interface_index),
valid_klass_reference_at(interface_index),
"Interface name has bad constant pool index %u in class file %s",
interface_index, CHECK_NULL);
if (cp->tag_at(interface_index).is_klass()) {
interf = KlassHandle(THREAD, cp->resolved_klass_at(interface_index));
if (_cp->tag_at(interface_index).is_klass()) {
interf = KlassHandle(THREAD, _cp->resolved_klass_at(interface_index));
} else {
Symbol* unresolved_klass = cp->klass_name_at(interface_index);
Symbol* unresolved_klass = _cp->klass_name_at(interface_index);
// Don't need to check legal name because it's checked when parsing constant pool.
// But need to make sure it's not an array type.
guarantee_property(unresolved_klass->byte_at(0) != JVM_SIGNATURE_ARRAY,
"Bad interface name in class file %s", CHECK_NULL);
Handle class_loader(THREAD, loader_data->class_loader());
Handle class_loader(THREAD, _loader_data->class_loader());
// Call resolve_super so classcircularity is checked
Klass* k = SystemDictionary::resolve_super_or_fail(class_name,
......@@ -831,11 +795,11 @@ Array<Klass*>* ClassFileParser::parse_interfaces(constantPoolHandle cp,
if (InstanceKlass::cast(interf())->has_default_methods()) {
*has_default_methods = true;
}
interfaces->at_put(index, interf());
_local_interfaces->at_put(index, interf());
}
if (!_need_verify || length <= 1) {
return interfaces;
return _local_interfaces;
}
// Check if there's any duplicates in interfaces
......@@ -847,7 +811,7 @@ Array<Klass*>* ClassFileParser::parse_interfaces(constantPoolHandle cp,
{
debug_only(No_Safepoint_Verifier nsv;)
for (index = 0; index < length; index++) {
Klass* k = interfaces->at(index);
Klass* k = _local_interfaces->at(index);
Symbol* name = InstanceKlass::cast(k)->name();
// If no duplicates, add (name, NULL) in hashtable interface_names.
if (!put_after_lookup(name, NULL, interface_names)) {
......@@ -859,20 +823,20 @@ Array<Klass*>* ClassFileParser::parse_interfaces(constantPoolHandle cp,
if (dup) {
classfile_parse_error("Duplicate interface name in class file %s", CHECK_NULL);
}
return interfaces;
}
return _local_interfaces;
}
void ClassFileParser::verify_constantvalue(int constantvalue_index, int signature_index, constantPoolHandle cp, TRAPS) {
void ClassFileParser::verify_constantvalue(int constantvalue_index, int signature_index, TRAPS) {
// Make sure the constant pool entry is of a type appropriate to this field
guarantee_property(
(constantvalue_index > 0 &&
constantvalue_index < cp->length()),
constantvalue_index < _cp->length()),
"Bad initial value index %u in ConstantValue attribute in class file %s",
constantvalue_index, CHECK);
constantTag value_type = cp->tag_at(constantvalue_index);
switch ( cp->basic_type_for_signature_at(signature_index) ) {
constantTag value_type = _cp->tag_at(constantvalue_index);
switch ( _cp->basic_type_for_signature_at(signature_index) ) {
case T_LONG:
guarantee_property(value_type.is_long(), "Inconsistent constant value type in class file %s", CHECK);
break;
......@@ -886,7 +850,7 @@ void ClassFileParser::verify_constantvalue(int constantvalue_index, int signatur
guarantee_property(value_type.is_int(), "Inconsistent constant value type in class file %s", CHECK);
break;
case T_OBJECT:
guarantee_property((cp->symbol_at(signature_index)->equals("Ljava/lang/String;")
guarantee_property((_cp->symbol_at(signature_index)->equals("Ljava/lang/String;")
&& value_type.is_string()),
"Bad string initial value in class file %s", CHECK);
break;
......@@ -899,15 +863,11 @@ void ClassFileParser::verify_constantvalue(int constantvalue_index, int signatur
// Parse attributes for a field.
void ClassFileParser::parse_field_attributes(ClassLoaderData* loader_data,
constantPoolHandle cp,
u2 attributes_count,
void ClassFileParser::parse_field_attributes(u2 attributes_count,
bool is_static, u2 signature_index,
u2* constantvalue_index_addr,
bool* is_synthetic_addr,
u2* generic_signature_index_addr,
AnnotationArray** field_annotations,
AnnotationArray** field_type_annotations,
ClassFileParser::FieldAnnotationCollector* parsed_annotations,
TRAPS) {
ClassFileStream* cfs = stream();
......@@ -927,12 +887,11 @@ void ClassFileParser::parse_field_attributes(ClassLoaderData* loader_data,
cfs->guarantee_more(6, CHECK); // attribute_name_index, attribute_length
u2 attribute_name_index = cfs->get_u2_fast();
u4 attribute_length = cfs->get_u4_fast();
check_property(valid_cp_range(attribute_name_index, cp->length()) &&
cp->tag_at(attribute_name_index).is_utf8(),
check_property(valid_symbol_at(attribute_name_index),
"Invalid field attribute index %u in class file %s",
attribute_name_index,
CHECK);
Symbol* attribute_name = cp->symbol_at(attribute_name_index);
Symbol* attribute_name = _cp->symbol_at(attribute_name_index);
if (is_static && attribute_name == vmSymbols::tag_constant_value()) {
// ignore if non-static
if (constantvalue_index != 0) {
......@@ -944,7 +903,7 @@ void ClassFileParser::parse_field_attributes(ClassLoaderData* loader_data,
attribute_length, CHECK);
constantvalue_index = cfs->get_u2(CHECK);
if (_need_verify) {
verify_constantvalue(constantvalue_index, signature_index, cp, CHECK);
verify_constantvalue(constantvalue_index, signature_index, CHECK);
}
} else if (attribute_name == vmSymbols::tag_synthetic()) {
if (attribute_length != 0) {
......@@ -971,10 +930,8 @@ void ClassFileParser::parse_field_attributes(ClassLoaderData* loader_data,
runtime_visible_annotations_length = attribute_length;
runtime_visible_annotations = cfs->get_u1_buffer();
assert(runtime_visible_annotations != NULL, "null visible annotations");
parse_annotations(loader_data,
runtime_visible_annotations,
parse_annotations(runtime_visible_annotations,
runtime_visible_annotations_length,
cp,
parsed_annotations,
CHECK);
cfs->skip_u1(runtime_visible_annotations_length, CHECK);
......@@ -1004,18 +961,18 @@ void ClassFileParser::parse_field_attributes(ClassLoaderData* loader_data,
*constantvalue_index_addr = constantvalue_index;
*is_synthetic_addr = is_synthetic;
*generic_signature_index_addr = generic_signature_index;
*field_annotations = assemble_annotations(loader_data,
runtime_visible_annotations,
AnnotationArray* a = assemble_annotations(runtime_visible_annotations,
runtime_visible_annotations_length,
runtime_invisible_annotations,
runtime_invisible_annotations_length,
CHECK);
*field_type_annotations = assemble_annotations(loader_data,
runtime_visible_type_annotations,
parsed_annotations->set_field_annotations(a);
a = assemble_annotations(runtime_visible_type_annotations,
runtime_visible_type_annotations_length,
runtime_invisible_type_annotations,
runtime_invisible_type_annotations_length,
CHECK);
parsed_annotations->set_field_type_annotations(a);
return;
}
......@@ -1106,13 +1063,9 @@ class FieldAllocationCount: public ResourceObj {
}
};
Array<u2>* ClassFileParser::parse_fields(ClassLoaderData* loader_data,
Symbol* class_name,
constantPoolHandle cp,
Array<u2>* ClassFileParser::parse_fields(Symbol* class_name,
bool is_interface,
FieldAllocationCount *fac,
Array<AnnotationArray*>** fields_annotations,
Array<AnnotationArray*>** fields_type_annotations,
u2* java_fields_count_ptr, TRAPS) {
ClassFileStream* cfs = stream();
cfs->guarantee_more(2, CHECK_NULL); // length
......@@ -1147,8 +1100,6 @@ Array<u2>* ClassFileParser::parse_fields(ClassLoaderData* loader_data,
u2* fa = NEW_RESOURCE_ARRAY_IN_THREAD(
THREAD, u2, total_fields * (FieldInfo::field_slots + 1));
AnnotationArray* field_annotations = NULL;
AnnotationArray* field_type_annotations = NULL;
// The generic signature slots start after all other fields' data.
int generic_signature_slot = total_fields * FieldInfo::field_slots;
int num_generic_signature = 0;
......@@ -1161,53 +1112,52 @@ Array<u2>* ClassFileParser::parse_fields(ClassLoaderData* loader_data,
access_flags.set_flags(flags);
u2 name_index = cfs->get_u2_fast();
int cp_size = cp->length();
check_property(
valid_cp_range(name_index, cp_size) && cp->tag_at(name_index).is_utf8(),
int cp_size = _cp->length();
check_property(valid_symbol_at(name_index),
"Invalid constant pool index %u for field name in class file %s",
name_index, CHECK_NULL);
Symbol* name = cp->symbol_at(name_index);
name_index,
CHECK_NULL);
Symbol* name = _cp->symbol_at(name_index);
verify_legal_field_name(name, CHECK_NULL);
u2 signature_index = cfs->get_u2_fast();
check_property(
valid_cp_range(signature_index, cp_size) &&
cp->tag_at(signature_index).is_utf8(),
check_property(valid_symbol_at(signature_index),
"Invalid constant pool index %u for field signature in class file %s",
signature_index, CHECK_NULL);
Symbol* sig = cp->symbol_at(signature_index);
Symbol* sig = _cp->symbol_at(signature_index);
verify_legal_field_signature(name, sig, CHECK_NULL);
u2 constantvalue_index = 0;
bool is_synthetic = false;
u2 generic_signature_index = 0;
bool is_static = access_flags.is_static();
FieldAnnotationCollector parsed_annotations;
FieldAnnotationCollector parsed_annotations(_loader_data);
u2 attributes_count = cfs->get_u2_fast();
if (attributes_count > 0) {
parse_field_attributes(loader_data,
cp, attributes_count, is_static, signature_index,
parse_field_attributes(attributes_count, is_static, signature_index,
&constantvalue_index, &is_synthetic,
&generic_signature_index, &field_annotations,
&field_type_annotations, &parsed_annotations,
&generic_signature_index, &parsed_annotations,
CHECK_NULL);
if (field_annotations != NULL) {
if (*fields_annotations == NULL) {
*fields_annotations = MetadataFactory::new_array<AnnotationArray*>(
loader_data, length, NULL,
if (parsed_annotations.field_annotations() != NULL) {
if (_fields_annotations == NULL) {
_fields_annotations = MetadataFactory::new_array<AnnotationArray*>(
_loader_data, length, NULL,
CHECK_NULL);
}
(*fields_annotations)->at_put(n, field_annotations);
_fields_annotations->at_put(n, parsed_annotations.field_annotations());
parsed_annotations.set_field_annotations(NULL);
}
if (field_type_annotations != NULL) {
if (*fields_type_annotations == NULL) {
*fields_type_annotations = MetadataFactory::new_array<AnnotationArray*>(
loader_data, length, NULL,
if (parsed_annotations.field_type_annotations() != NULL) {
if (_fields_type_annotations == NULL) {
_fields_type_annotations = MetadataFactory::new_array<AnnotationArray*>(
_loader_data, length, NULL,
CHECK_NULL);
}
(*fields_type_annotations)->at_put(n, field_type_annotations);
_fields_type_annotations->at_put(n, parsed_annotations.field_type_annotations());
parsed_annotations.set_field_type_annotations(NULL);
}
if (is_synthetic) {
access_flags.set_is_synthetic();
}
......@@ -1224,7 +1174,7 @@ Array<u2>* ClassFileParser::parse_fields(ClassLoaderData* loader_data,
name_index,
signature_index,
constantvalue_index);
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
FieldAllocationType atype = fac->update(is_static, type);
......@@ -1245,8 +1195,8 @@ Array<u2>* ClassFileParser::parse_fields(ClassLoaderData* loader_data,
bool duplicate = false;
for (int i = 0; i < length; i++) {
FieldInfo* f = FieldInfo::from_field_array(fa, i);
if (name == cp->symbol_at(f->name_index()) &&
signature == cp->symbol_at(f->signature_index())) {
if (name == _cp->symbol_at(f->name_index()) &&
signature == _cp->symbol_at(f->signature_index())) {
// Symbol is desclared in Java so skip this one
duplicate = true;
break;
......@@ -1280,8 +1230,9 @@ Array<u2>* ClassFileParser::parse_fields(ClassLoaderData* loader_data,
// fields array is trimed. Also unused slots that were reserved
// for generic signature indexes are discarded.
Array<u2>* fields = MetadataFactory::new_array<u2>(
loader_data, index * FieldInfo::field_slots + num_generic_signature,
_loader_data, index * FieldInfo::field_slots + num_generic_signature,
CHECK_NULL);
_fields = fields; // save in case of error
{
int i = 0;
for (; i < index * FieldInfo::field_slots; i++) {
......@@ -1303,7 +1254,7 @@ Array<u2>* ClassFileParser::parse_fields(ClassLoaderData* loader_data,
bool dup = false;
{
debug_only(No_Safepoint_Verifier nsv;)
for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) {
for (AllFieldStream fs(fields, _cp); !fs.done(); fs.next()) {
Symbol* name = fs.name();
Symbol* sig = fs.signature();
// If no duplicates, add name/signature in hashtable names_and_sigs.
......@@ -1330,10 +1281,8 @@ static void copy_u2_with_conversion(u2* dest, u2* src, int length) {
}
u2* ClassFileParser::parse_exception_table(ClassLoaderData* loader_data,
u4 code_length,
u2* ClassFileParser::parse_exception_table(u4 code_length,
u4 exception_table_length,
constantPoolHandle cp,
TRAPS) {
ClassFileStream* cfs = stream();
......@@ -1354,8 +1303,7 @@ u2* ClassFileParser::parse_exception_table(ClassLoaderData* loader_data,
"Illegal exception table handler in class file %s",
CHECK_NULL);
if (catch_type_index != 0) {
guarantee_property(valid_cp_range(catch_type_index, cp->length()) &&
is_klass_reference(cp, catch_type_index),
guarantee_property(valid_klass_reference_at(catch_type_index),
"Catch type in exception table has bad constant type in class file %s", CHECK_NULL);
}
}
......@@ -1506,7 +1454,6 @@ void copy_lvt_element(Classfile_LVT_Element *src, LocalVariableTableElement *lvt
u2* ClassFileParser::parse_localvariable_table(u4 code_length,
u2 max_locals,
u4 code_attribute_length,
constantPoolHandle cp,
u2* localvariable_table_length,
bool isLVTT,
TRAPS) {
......@@ -1544,20 +1491,16 @@ u2* ClassFileParser::parse_localvariable_table(u4 code_length,
"Invalid length %u in %s in class file %s",
length, tbl_name, CHECK_NULL);
}
int cp_size = cp->length();
guarantee_property(
valid_cp_range(name_index, cp_size) &&
cp->tag_at(name_index).is_utf8(),
int cp_size = _cp->length();
guarantee_property(valid_symbol_at(name_index),
"Name index %u in %s has bad constant type in class file %s",
name_index, tbl_name, CHECK_NULL);
guarantee_property(
valid_cp_range(descriptor_index, cp_size) &&
cp->tag_at(descriptor_index).is_utf8(),
guarantee_property(valid_symbol_at(descriptor_index),
"Signature index %u in %s has bad constant type in class file %s",
descriptor_index, tbl_name, CHECK_NULL);
Symbol* name = cp->symbol_at(name_index);
Symbol* sig = cp->symbol_at(descriptor_index);
Symbol* name = _cp->symbol_at(name_index);
Symbol* sig = _cp->symbol_at(descriptor_index);
verify_legal_field_name(name, CHECK_NULL);
u2 extra_slot = 0;
if (!isLVTT) {
......@@ -1579,7 +1522,7 @@ u2* ClassFileParser::parse_localvariable_table(u4 code_length,
void ClassFileParser::parse_type_array(u2 array_length, u4 code_length, u4* u1_index, u4* u2_index,
u1* u1_array, u2* u2_array, constantPoolHandle cp, TRAPS) {
u1* u1_array, u2* u2_array, TRAPS) {
ClassFileStream* cfs = stream();
u2 index = 0; // index in the array with long/double occupying two slots
u4 i1 = *u1_index;
......@@ -1591,8 +1534,7 @@ void ClassFileParser::parse_type_array(u2 array_length, u4 code_length, u4* u1_i
index++;
} else if (tag == ITEM_Object) {
u2 class_index = u2_array[i2++] = cfs->get_u2(CHECK);
guarantee_property(valid_cp_range(class_index, cp->length()) &&
is_klass_reference(cp, class_index),
guarantee_property(valid_klass_reference_at(class_index),
"Bad class index %u in StackMap in class file %s",
class_index, CHECK);
} else if (tag == ITEM_Uninitialized) {
......@@ -1613,8 +1555,7 @@ void ClassFileParser::parse_type_array(u2 array_length, u4 code_length, u4* u1_i
*u2_index = i2;
}
Array<u1>* ClassFileParser::parse_stackmap_table(
ClassLoaderData* loader_data,
u1* ClassFileParser::parse_stackmap_table(
u4 code_attribute_length, TRAPS) {
if (code_attribute_length == 0)
return NULL;
......@@ -1629,18 +1570,12 @@ Array<u1>* ClassFileParser::parse_stackmap_table(
if (!_need_verify && !DumpSharedSpaces) {
return NULL;
}
Array<u1>* stackmap_data =
MetadataFactory::new_array<u1>(loader_data, code_attribute_length, 0, CHECK_NULL);
memcpy((void*)stackmap_data->adr_at(0),
(void*)stackmap_table_start, code_attribute_length);
return stackmap_data;
return stackmap_table_start;
}
u2* ClassFileParser::parse_checked_exceptions(u2* checked_exceptions_length,
u4 method_attribute_length,
constantPoolHandle cp, TRAPS) {
TRAPS) {
ClassFileStream* cfs = stream();
cfs->guarantee_more(2, CHECK_NULL); // checked_exceptions_length
*checked_exceptions_length = cfs->get_u2_fast();
......@@ -1657,8 +1592,7 @@ u2* ClassFileParser::parse_checked_exceptions(u2* checked_exceptions_length,
for (int i = 0; i < len; i++) {
checked_exception = cfs->get_u2_fast();
check_property(
valid_cp_range(checked_exception, cp->length()) &&
is_klass_reference(cp, checked_exception),
valid_klass_reference_at(checked_exception),
"Exception name has bad type at constant pool %u in class file %s",
checked_exception, CHECK_NULL);
}
......@@ -1735,9 +1669,7 @@ int ClassFileParser::skip_annotation_value(u1* buffer, int limit, int index) {
}
// Sift through annotations, looking for those significant to the VM:
void ClassFileParser::parse_annotations(ClassLoaderData* loader_data,
u1* buffer, int limit,
constantPoolHandle cp,
void ClassFileParser::parse_annotations(u1* buffer, int limit,
ClassFileParser::AnnotationCollector* coll,
TRAPS) {
// annotations := do(nann:u2) {annotation}
......@@ -1767,17 +1699,17 @@ void ClassFileParser::parse_annotations(ClassLoaderData* loader_data,
u1* abase = buffer + index0;
int atype = Bytes::get_Java_u2(abase + atype_off);
int count = Bytes::get_Java_u2(abase + count_off);
Symbol* aname = check_symbol_at(cp, atype);
Symbol* aname = check_symbol_at(_cp, atype);
if (aname == NULL) break; // invalid annotation name
Symbol* member = NULL;
if (count >= 1) {
int member_index = Bytes::get_Java_u2(abase + member_off);
member = check_symbol_at(cp, member_index);
member = check_symbol_at(_cp, member_index);
if (member == NULL) break; // invalid member name
}
// Here is where parsing particular annotations will take place.
AnnotationCollector::ID id = coll->annotation_index(loader_data, aname);
AnnotationCollector::ID id = coll->annotation_index(_loader_data, aname);
if (id == AnnotationCollector::_unknown) continue;
coll->set_annotation(id);
......@@ -1836,6 +1768,12 @@ void ClassFileParser::FieldAnnotationCollector::apply_to(FieldInfo* f) {
f->set_contended_group(contended_group());
}
ClassFileParser::FieldAnnotationCollector::~FieldAnnotationCollector() {
// If there's an error deallocate metadata for field annotations
MetadataFactory::free_array<u1>(_loader_data, _field_annotations);
MetadataFactory::free_array<u1>(_loader_data, _field_type_annotations);
}
void ClassFileParser::MethodAnnotationCollector::apply_to(methodHandle m) {
if (has_annotation(_method_ForceInline))
m->set_force_inline(true);
......@@ -1894,10 +1832,9 @@ void ClassFileParser::copy_localvariable_table(ConstMethod* cm,
&& _need_verify
&& _major_version >= JAVA_1_5_VERSION) {
clear_hashtable(lvt_Hash);
ConstantPool* cp = cm->constants();
classfile_parse_error("Duplicated LocalVariableTable attribute "
"entry for '%s' in class file %s",
cp->symbol_at(lvt->name_cp_index)->as_utf8(),
_cp->symbol_at(lvt->name_cp_index)->as_utf8(),
CHECK);
}
}
......@@ -1916,18 +1853,16 @@ void ClassFileParser::copy_localvariable_table(ConstMethod* cm,
if (entry == NULL) {
if (_need_verify) {
clear_hashtable(lvt_Hash);
ConstantPool* cp = cm->constants();
classfile_parse_error("LVTT entry for '%s' in class file %s "
"does not match any LVT entry",
cp->symbol_at(lvtt_elem.name_cp_index)->as_utf8(),
_cp->symbol_at(lvtt_elem.name_cp_index)->as_utf8(),
CHECK);
}
} else if (entry->_elem->signature_cp_index != 0 && _need_verify) {
clear_hashtable(lvt_Hash);
ConstantPool* cp = cm->constants();
classfile_parse_error("Duplicated LocalVariableTypeTable attribute "
"entry for '%s' in class file %s",
cp->symbol_at(lvtt_elem.name_cp_index)->as_utf8(),
_cp->symbol_at(lvtt_elem.name_cp_index)->as_utf8(),
CHECK);
} else {
// to add generic signatures into LocalVariableTable
......@@ -1939,8 +1874,7 @@ void ClassFileParser::copy_localvariable_table(ConstMethod* cm,
}
void ClassFileParser::copy_method_annotations(ClassLoaderData* loader_data,
ConstMethod* cm,
void ClassFileParser::copy_method_annotations(ConstMethod* cm,
u1* runtime_visible_annotations,
int runtime_visible_annotations_length,
u1* runtime_invisible_annotations,
......@@ -1961,8 +1895,7 @@ void ClassFileParser::copy_method_annotations(ClassLoaderData* loader_data,
if (runtime_visible_annotations_length +
runtime_invisible_annotations_length > 0) {
a = assemble_annotations(loader_data,
runtime_visible_annotations,
a = assemble_annotations(runtime_visible_annotations,
runtime_visible_annotations_length,
runtime_invisible_annotations,
runtime_invisible_annotations_length,
......@@ -1972,8 +1905,7 @@ void ClassFileParser::copy_method_annotations(ClassLoaderData* loader_data,
if (runtime_visible_parameter_annotations_length +
runtime_invisible_parameter_annotations_length > 0) {
a = assemble_annotations(loader_data,
runtime_visible_parameter_annotations,
a = assemble_annotations(runtime_visible_parameter_annotations,
runtime_visible_parameter_annotations_length,
runtime_invisible_parameter_annotations,
runtime_invisible_parameter_annotations_length,
......@@ -1982,8 +1914,7 @@ void ClassFileParser::copy_method_annotations(ClassLoaderData* loader_data,
}
if (annotation_default_length > 0) {
a = assemble_annotations(loader_data,
annotation_default,
a = assemble_annotations(annotation_default,
annotation_default_length,
NULL,
0,
......@@ -1993,8 +1924,7 @@ void ClassFileParser::copy_method_annotations(ClassLoaderData* loader_data,
if (runtime_visible_type_annotations_length +
runtime_invisible_type_annotations_length > 0) {
a = assemble_annotations(loader_data,
runtime_visible_type_annotations,
a = assemble_annotations(runtime_visible_type_annotations,
runtime_visible_type_annotations_length,
runtime_invisible_type_annotations,
runtime_invisible_type_annotations_length,
......@@ -2013,9 +1943,7 @@ void ClassFileParser::copy_method_annotations(ClassLoaderData* loader_data,
// from the method back up to the containing klass. These flag values
// are added to klass's access_flags.
methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
constantPoolHandle cp,
bool is_interface,
methodHandle ClassFileParser::parse_method(bool is_interface,
AccessFlags *promoted_flags,
TRAPS) {
ClassFileStream* cfs = stream();
......@@ -2026,22 +1954,20 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
int flags = cfs->get_u2_fast();
u2 name_index = cfs->get_u2_fast();
int cp_size = cp->length();
int cp_size = _cp->length();
check_property(
valid_cp_range(name_index, cp_size) &&
cp->tag_at(name_index).is_utf8(),
valid_symbol_at(name_index),
"Illegal constant pool index %u for method name in class file %s",
name_index, CHECK_(nullHandle));
Symbol* name = cp->symbol_at(name_index);
Symbol* name = _cp->symbol_at(name_index);
verify_legal_method_name(name, CHECK_(nullHandle));
u2 signature_index = cfs->get_u2_fast();
guarantee_property(
valid_cp_range(signature_index, cp_size) &&
cp->tag_at(signature_index).is_utf8(),
valid_symbol_at(signature_index),
"Illegal constant pool index %u for method signature in class file %s",
signature_index, CHECK_(nullHandle));
Symbol* signature = cp->symbol_at(signature_index);
Symbol* signature = _cp->symbol_at(signature_index);
AccessFlags access_flags;
if (name == vmSymbols::class_initializer_name()) {
......@@ -2097,7 +2023,8 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
bool parsed_checked_exceptions_attribute = false;
bool parsed_stackmap_attribute = false;
// stackmap attribute - JDK1.5
Array<u1>* stackmap_data = NULL;
u1* stackmap_data = NULL;
int stackmap_data_length = 0;
u2 generic_signature_index = 0;
MethodAnnotationCollector parsed_annotations;
u1* runtime_visible_annotations = NULL;
......@@ -2122,12 +2049,11 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
u2 method_attribute_name_index = cfs->get_u2_fast();
u4 method_attribute_length = cfs->get_u4_fast();
check_property(
valid_cp_range(method_attribute_name_index, cp_size) &&
cp->tag_at(method_attribute_name_index).is_utf8(),
valid_symbol_at(method_attribute_name_index),
"Invalid method attribute name index %u in class file %s",
method_attribute_name_index, CHECK_(nullHandle));
Symbol* method_attribute_name = cp->symbol_at(method_attribute_name_index);
Symbol* method_attribute_name = _cp->symbol_at(method_attribute_name_index);
if (method_attribute_name == vmSymbols::tag_code()) {
// Parse Code attribute
if (_need_verify) {
......@@ -2171,7 +2097,7 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
exception_table_length = cfs->get_u2_fast();
if (exception_table_length > 0) {
exception_table_start =
parse_exception_table(loader_data, code_length, exception_table_length, cp, CHECK_(nullHandle));
parse_exception_table(code_length, exception_table_length, CHECK_(nullHandle));
}
// Parse additional attributes in code attribute
......@@ -2204,19 +2130,18 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
calculated_attribute_length += code_attribute_length +
sizeof(code_attribute_name_index) +
sizeof(code_attribute_length);
check_property(valid_cp_range(code_attribute_name_index, cp_size) &&
cp->tag_at(code_attribute_name_index).is_utf8(),
check_property(valid_symbol_at(code_attribute_name_index),
"Invalid code attribute name index %u in class file %s",
code_attribute_name_index,
CHECK_(nullHandle));
if (LoadLineNumberTables &&
cp->symbol_at(code_attribute_name_index) == vmSymbols::tag_line_number_table()) {
_cp->symbol_at(code_attribute_name_index) == vmSymbols::tag_line_number_table()) {
// Parse and compress line number table
parse_linenumber_table(code_attribute_length, code_length,
&linenumber_table, CHECK_(nullHandle));
} else if (LoadLocalVariableTables &&
cp->symbol_at(code_attribute_name_index) == vmSymbols::tag_local_variable_table()) {
_cp->symbol_at(code_attribute_name_index) == vmSymbols::tag_local_variable_table()) {
// Parse local variable table
if (!lvt_allocated) {
localvariable_table_length = NEW_RESOURCE_ARRAY_IN_THREAD(
......@@ -2238,7 +2163,6 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
parse_localvariable_table(code_length,
max_locals,
code_attribute_length,
cp,
&localvariable_table_length[lvt_cnt],
false, // is not LVTT
CHECK_(nullHandle));
......@@ -2246,7 +2170,7 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
lvt_cnt++;
} else if (LoadLocalVariableTypeTables &&
_major_version >= JAVA_1_5_VERSION &&
cp->symbol_at(code_attribute_name_index) == vmSymbols::tag_local_variable_type_table()) {
_cp->symbol_at(code_attribute_name_index) == vmSymbols::tag_local_variable_type_table()) {
if (!lvt_allocated) {
localvariable_table_length = NEW_RESOURCE_ARRAY_IN_THREAD(
THREAD, u2, INITIAL_MAX_LVT_NUMBER);
......@@ -2268,19 +2192,19 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
parse_localvariable_table(code_length,
max_locals,
code_attribute_length,
cp,
&localvariable_type_table_length[lvtt_cnt],
true, // is LVTT
CHECK_(nullHandle));
lvtt_cnt++;
} else if (UseSplitVerifier &&
_major_version >= Verifier::STACKMAP_ATTRIBUTE_MAJOR_VERSION &&
cp->symbol_at(code_attribute_name_index) == vmSymbols::tag_stack_map_table()) {
_cp->symbol_at(code_attribute_name_index) == vmSymbols::tag_stack_map_table()) {
// Stack map is only needed by the new verifier in JDK1.5.
if (parsed_stackmap_attribute) {
classfile_parse_error("Multiple StackMapTable attributes in class file %s", CHECK_(nullHandle));
}
stackmap_data = parse_stackmap_table(loader_data, code_attribute_length, CHECK_(nullHandle));
stackmap_data = parse_stackmap_table(code_attribute_length, CHECK_(nullHandle));
stackmap_data_length = code_attribute_length;
parsed_stackmap_attribute = true;
} else {
// Skip unknown attributes
......@@ -2301,7 +2225,7 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
checked_exceptions_start =
parse_checked_exceptions(&checked_exceptions_length,
method_attribute_length,
cp, CHECK_(nullHandle));
CHECK_(nullHandle));
} else if (method_attribute_name == vmSymbols::tag_method_parameters()) {
// reject multiple method parameters
if (method_parameters_seen) {
......@@ -2359,9 +2283,8 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
runtime_visible_annotations_length = method_attribute_length;
runtime_visible_annotations = cfs->get_u1_buffer();
assert(runtime_visible_annotations != NULL, "null visible annotations");
parse_annotations(loader_data,
runtime_visible_annotations,
runtime_visible_annotations_length, cp, &parsed_annotations,
parse_annotations(runtime_visible_annotations,
runtime_visible_annotations_length, &parsed_annotations,
CHECK_(nullHandle));
cfs->skip_u1(runtime_visible_annotations_length, CHECK_(nullHandle));
} else if (PreserveAllAnnotations && method_attribute_name == vmSymbols::tag_runtime_invisible_annotations()) {
......@@ -2434,18 +2357,18 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
0);
Method* m = Method::allocate(
loader_data, code_length, access_flags, &sizes,
_loader_data, code_length, access_flags, &sizes,
ConstMethod::NORMAL, CHECK_(nullHandle));
ClassLoadingService::add_class_method_size(m->size()*HeapWordSize);
// Fill in information from fixed part (access_flags already set)
m->set_constants(cp());
m->set_constants(_cp);
m->set_name_index(name_index);
m->set_signature_index(signature_index);
#ifdef CC_INTERP
// hmm is there a gc issue here??
ResultTypeFinder rtf(cp->symbol_at(signature_index));
ResultTypeFinder rtf(_cp->symbol_at(signature_index));
m->set_result_index(rtf.type());
#endif
......@@ -2464,7 +2387,10 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
// Fill in code attribute information
m->set_max_stack(max_stack);
m->set_max_locals(max_locals);
m->constMethod()->set_stackmap_data(stackmap_data);
if (stackmap_data != NULL) {
m->constMethod()->copy_stackmap_data(_loader_data, stackmap_data,
stackmap_data_length, CHECK_NULL);
}
// Copy byte codes
m->set_code(code_start);
......@@ -2520,7 +2446,7 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
parsed_annotations.apply_to(m);
// Copy annotations
copy_method_annotations(loader_data, m->constMethod(),
copy_method_annotations(m->constMethod(),
runtime_visible_annotations,
runtime_visible_annotations_length,
runtime_invisible_annotations,
......@@ -2560,9 +2486,7 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
// from the methods back up to the containing klass. These flag values
// are added to klass's access_flags.
Array<Method*>* ClassFileParser::parse_methods(ClassLoaderData* loader_data,
constantPoolHandle cp,
bool is_interface,
Array<Method*>* ClassFileParser::parse_methods(bool is_interface,
AccessFlags* promoted_flags,
bool* has_final_method,
bool* has_default_methods,
......@@ -2571,15 +2495,13 @@ Array<Method*>* ClassFileParser::parse_methods(ClassLoaderData* loader_data,
cfs->guarantee_more(2, CHECK_NULL); // length
u2 length = cfs->get_u2_fast();
if (length == 0) {
return Universe::the_empty_method_array();
_methods = Universe::the_empty_method_array();
} else {
// FIXME: Handle leaks at later failures.
Array<Method*>* methods = MetadataFactory::new_array<Method*>(loader_data, length, NULL, CHECK_NULL);
_methods = MetadataFactory::new_array<Method*>(_loader_data, length, NULL, CHECK_NULL);
HandleMark hm(THREAD);
for (int index = 0; index < length; index++) {
methodHandle method = parse_method(loader_data,
cp, is_interface,
methodHandle method = parse_method(is_interface,
promoted_flags,
CHECK_NULL);
......@@ -2590,7 +2512,7 @@ Array<Method*>* ClassFileParser::parse_methods(ClassLoaderData* loader_data,
// default method
*has_default_methods = true;
}
methods->at_put(index, method());
_methods->at_put(index, method());
}
if (_need_verify && length > 1) {
......@@ -2603,7 +2525,7 @@ Array<Method*>* ClassFileParser::parse_methods(ClassLoaderData* loader_data,
{
debug_only(No_Safepoint_Verifier nsv;)
for (int i = 0; i < length; i++) {
Method* m = methods->at(i);
Method* m = _methods->at(i);
// If no duplicates, add name/signature in hashtable names_and_sigs.
if (!put_after_lookup(m->name(), m->signature(), names_and_sigs)) {
dup = true;
......@@ -2616,14 +2538,12 @@ Array<Method*>* ClassFileParser::parse_methods(ClassLoaderData* loader_data,
CHECK_NULL);
}
}
return methods;
}
return _methods;
}
Array<int>* ClassFileParser::sort_methods(ClassLoaderData* loader_data,
Array<Method*>* methods,
TRAPS) {
intArray* ClassFileParser::sort_methods(Array<Method*>* methods) {
int length = methods->length();
// If JVMTI original method ordering or sharing is enabled we have to
// remember the original class file ordering.
......@@ -2641,10 +2561,11 @@ Array<int>* ClassFileParser::sort_methods(ClassLoaderData* loader_data,
// Note that the ordering is not alphabetical, see Symbol::fast_compare
Method::sort_methods(methods);
intArray* method_ordering = NULL;
// If JVMTI original method ordering or sharing is enabled construct int
// array remembering the original ordering
if (JvmtiExport::can_maintain_original_method_order() || DumpSharedSpaces) {
Array<int>* method_ordering = MetadataFactory::new_array<int>(loader_data, length, CHECK_NULL);
method_ordering = new intArray(length);
for (int index = 0; index < length; index++) {
Method* m = methods->at(index);
int old_index = m->vtable_index();
......@@ -2652,29 +2573,25 @@ Array<int>* ClassFileParser::sort_methods(ClassLoaderData* loader_data,
method_ordering->at_put(index, old_index);
m->set_vtable_index(Method::invalid_vtable_index);
}
return method_ordering;
} else {
return Universe::the_empty_int_array();
}
return method_ordering;
}
void ClassFileParser::parse_classfile_sourcefile_attribute(constantPoolHandle cp, TRAPS) {
void ClassFileParser::parse_classfile_sourcefile_attribute(TRAPS) {
ClassFileStream* cfs = stream();
cfs->guarantee_more(2, CHECK); // sourcefile_index
u2 sourcefile_index = cfs->get_u2_fast();
check_property(
valid_cp_range(sourcefile_index, cp->length()) &&
cp->tag_at(sourcefile_index).is_utf8(),
valid_symbol_at(sourcefile_index),
"Invalid SourceFile attribute at constant pool index %u in class file %s",
sourcefile_index, CHECK);
set_class_sourcefile(cp->symbol_at(sourcefile_index));
set_class_sourcefile(_cp->symbol_at(sourcefile_index));
}
void ClassFileParser::parse_classfile_source_debug_extension_attribute(constantPoolHandle cp,
int length, TRAPS) {
void ClassFileParser::parse_classfile_source_debug_extension_attribute(int length, TRAPS) {
ClassFileStream* cfs = stream();
u1* sde_buffer = cfs->get_u1_buffer();
assert(sde_buffer != NULL, "null sde buffer");
......@@ -2698,12 +2615,10 @@ void ClassFileParser::parse_classfile_source_debug_extension_attribute(constantP
#define RECOGNIZED_INNER_CLASS_MODIFIERS (JVM_RECOGNIZED_CLASS_MODIFIERS | JVM_ACC_PRIVATE | JVM_ACC_PROTECTED | JVM_ACC_STATIC)
// Return number of classes in the inner classes attribute table
u2 ClassFileParser::parse_classfile_inner_classes_attribute(ClassLoaderData* loader_data,
u1* inner_classes_attribute_start,
u2 ClassFileParser::parse_classfile_inner_classes_attribute(u1* inner_classes_attribute_start,
bool parsed_enclosingmethod_attribute,
u2 enclosing_method_class_index,
u2 enclosing_method_method_index,
constantPoolHandle cp,
TRAPS) {
ClassFileStream* cfs = stream();
u1* current_mark = cfs->current();
......@@ -2724,33 +2639,31 @@ u2 ClassFileParser::parse_classfile_inner_classes_attribute(ClassLoaderData* loa
// enclosing_method_class_index,
// enclosing_method_method_index]
int size = length * 4 + (parsed_enclosingmethod_attribute ? 2 : 0);
// FIXME: Will leak on exceptions.
Array<u2>* inner_classes = MetadataFactory::new_array<u2>(loader_data, size, CHECK_0);
Array<u2>* inner_classes = MetadataFactory::new_array<u2>(_loader_data, size, CHECK_0);
_inner_classes = inner_classes;
int index = 0;
int cp_size = cp->length();
int cp_size = _cp->length();
cfs->guarantee_more(8 * length, CHECK_0); // 4-tuples of u2
for (int n = 0; n < length; n++) {
// Inner class index
u2 inner_class_info_index = cfs->get_u2_fast();
check_property(
inner_class_info_index == 0 ||
(valid_cp_range(inner_class_info_index, cp_size) &&
is_klass_reference(cp, inner_class_info_index)),
valid_klass_reference_at(inner_class_info_index),
"inner_class_info_index %u has bad constant type in class file %s",
inner_class_info_index, CHECK_0);
// Outer class index
u2 outer_class_info_index = cfs->get_u2_fast();
check_property(
outer_class_info_index == 0 ||
(valid_cp_range(outer_class_info_index, cp_size) &&
is_klass_reference(cp, outer_class_info_index)),
valid_klass_reference_at(outer_class_info_index),
"outer_class_info_index %u has bad constant type in class file %s",
outer_class_info_index, CHECK_0);
// Inner class name
u2 inner_name_index = cfs->get_u2_fast();
check_property(
inner_name_index == 0 || (valid_cp_range(inner_name_index, cp_size) &&
cp->tag_at(inner_name_index).is_utf8()),
inner_name_index == 0 || valid_symbol_at(inner_name_index),
"inner_name_index %u has bad constant type in class file %s",
inner_name_index, CHECK_0);
if (_need_verify) {
......@@ -2794,33 +2707,27 @@ u2 ClassFileParser::parse_classfile_inner_classes_attribute(ClassLoaderData* loa
}
assert(index == size, "wrong size");
// Update InstanceKlass with inner class info.
set_class_inner_classes(inner_classes);
// Restore buffer's current position.
cfs->set_current(current_mark);
return length;
}
void ClassFileParser::parse_classfile_synthetic_attribute(constantPoolHandle cp, TRAPS) {
void ClassFileParser::parse_classfile_synthetic_attribute(TRAPS) {
set_class_synthetic_flag(true);
}
void ClassFileParser::parse_classfile_signature_attribute(constantPoolHandle cp, TRAPS) {
void ClassFileParser::parse_classfile_signature_attribute(TRAPS) {
ClassFileStream* cfs = stream();
u2 signature_index = cfs->get_u2(CHECK);
check_property(
valid_cp_range(signature_index, cp->length()) &&
cp->tag_at(signature_index).is_utf8(),
valid_symbol_at(signature_index),
"Invalid constant pool index %u in Signature attribute in class file %s",
signature_index, CHECK);
set_class_generic_signature(cp->symbol_at(signature_index));
set_class_generic_signature(_cp->symbol_at(signature_index));
}
void ClassFileParser::parse_classfile_bootstrap_methods_attribute(ClassLoaderData* loader_data,
constantPoolHandle cp,
u4 attribute_byte_length, TRAPS) {
void ClassFileParser::parse_classfile_bootstrap_methods_attribute(u4 attribute_byte_length, TRAPS) {
ClassFileStream* cfs = stream();
u1* current_start = cfs->current();
......@@ -2841,10 +2748,14 @@ void ClassFileParser::parse_classfile_bootstrap_methods_attribute(ClassLoaderDat
// The array begins with a series of short[2] pairs, one for each tuple.
int index_size = (attribute_array_length * 2);
Array<u2>* operands = MetadataFactory::new_array<u2>(loader_data, index_size + operand_count, CHECK);
Array<u2>* operands = MetadataFactory::new_array<u2>(_loader_data, index_size + operand_count, CHECK);
// Eagerly assign operands so they will be deallocated with the constant
// pool if there is an error.
_cp->set_operands(operands);
int operand_fill_index = index_size;
int cp_size = cp->length();
int cp_size = _cp->length();
for (int n = 0; n < attribute_array_length; n++) {
// Store a 32-bit offset into the header of the operand array.
......@@ -2856,7 +2767,7 @@ void ClassFileParser::parse_classfile_bootstrap_methods_attribute(ClassLoaderDat
u2 argument_count = cfs->get_u2_fast();
check_property(
valid_cp_range(bootstrap_method_index, cp_size) &&
cp->tag_at(bootstrap_method_index).is_method_handle(),
_cp->tag_at(bootstrap_method_index).is_method_handle(),
"bootstrap_method_index %u has bad constant type in class file %s",
bootstrap_method_index,
CHECK);
......@@ -2868,7 +2779,7 @@ void ClassFileParser::parse_classfile_bootstrap_methods_attribute(ClassLoaderDat
u2 argument_index = cfs->get_u2_fast();
check_property(
valid_cp_range(argument_index, cp_size) &&
cp->tag_at(argument_index).is_loadable_constant(),
_cp->tag_at(argument_index).is_loadable_constant(),
"argument_index %u has bad constant type in class file %s",
argument_index,
CHECK);
......@@ -2883,17 +2794,13 @@ void ClassFileParser::parse_classfile_bootstrap_methods_attribute(ClassLoaderDat
guarantee_property(current_end == current_start + attribute_byte_length,
"Bad length on BootstrapMethods in class file %s",
CHECK);
cp->set_operands(operands);
}
void ClassFileParser::parse_classfile_attributes(ClassLoaderData* loader_data,
constantPoolHandle cp,
ClassFileParser::ClassAnnotationCollector* parsed_annotations,
void ClassFileParser::parse_classfile_attributes(ClassFileParser::ClassAnnotationCollector* parsed_annotations,
TRAPS) {
ClassFileStream* cfs = stream();
// Set inner classes attribute to default sentinel
set_class_inner_classes(Universe::the_empty_short_array());
_inner_classes = Universe::the_empty_short_array();
cfs->guarantee_more(2, CHECK); // attributes_count
u2 attributes_count = cfs->get_u2_fast();
bool parsed_sourcefile_attribute = false;
......@@ -2918,11 +2825,10 @@ void ClassFileParser::parse_classfile_attributes(ClassLoaderData* loader_data,
u2 attribute_name_index = cfs->get_u2_fast();
u4 attribute_length = cfs->get_u4_fast();
check_property(
valid_cp_range(attribute_name_index, cp->length()) &&
cp->tag_at(attribute_name_index).is_utf8(),
valid_symbol_at(attribute_name_index),
"Attribute name has bad constant pool index %u in class file %s",
attribute_name_index, CHECK);
Symbol* tag = cp->symbol_at(attribute_name_index);
Symbol* tag = _cp->symbol_at(attribute_name_index);
if (tag == vmSymbols::tag_source_file()) {
// Check for SourceFile tag
if (_need_verify) {
......@@ -2933,10 +2839,10 @@ void ClassFileParser::parse_classfile_attributes(ClassLoaderData* loader_data,
} else {
parsed_sourcefile_attribute = true;
}
parse_classfile_sourcefile_attribute(cp, CHECK);
parse_classfile_sourcefile_attribute(CHECK);
} else if (tag == vmSymbols::tag_source_debug_extension()) {
// Check for SourceDebugExtension tag
parse_classfile_source_debug_extension_attribute(cp, (int)attribute_length, CHECK);
parse_classfile_source_debug_extension_attribute((int)attribute_length, CHECK);
} else if (tag == vmSymbols::tag_inner_classes()) {
// Check for InnerClasses tag
if (parsed_innerclasses_attribute) {
......@@ -2955,7 +2861,7 @@ void ClassFileParser::parse_classfile_attributes(ClassLoaderData* loader_data,
"Invalid Synthetic classfile attribute length %u in class file %s",
attribute_length, CHECK);
}
parse_classfile_synthetic_attribute(cp, CHECK);
parse_classfile_synthetic_attribute(CHECK);
} else if (tag == vmSymbols::tag_deprecated()) {
// Check for Deprecatd tag - 4276120
if (attribute_length != 0) {
......@@ -2970,15 +2876,13 @@ void ClassFileParser::parse_classfile_attributes(ClassLoaderData* loader_data,
"Wrong Signature attribute length %u in class file %s",
attribute_length, CHECK);
}
parse_classfile_signature_attribute(cp, CHECK);
parse_classfile_signature_attribute(CHECK);
} else if (tag == vmSymbols::tag_runtime_visible_annotations()) {
runtime_visible_annotations_length = attribute_length;
runtime_visible_annotations = cfs->get_u1_buffer();
assert(runtime_visible_annotations != NULL, "null visible annotations");
parse_annotations(loader_data,
runtime_visible_annotations,
parse_annotations(runtime_visible_annotations,
runtime_visible_annotations_length,
cp,
parsed_annotations,
CHECK);
cfs->skip_u1(runtime_visible_annotations_length, CHECK);
......@@ -3000,13 +2904,11 @@ void ClassFileParser::parse_classfile_attributes(ClassLoaderData* loader_data,
classfile_parse_error("Invalid class index in EnclosingMethod attribute in class file %s", CHECK);
}
// Validate the constant pool indices and types
if (!cp->is_within_bounds(enclosing_method_class_index) ||
!is_klass_reference(cp, enclosing_method_class_index)) {
classfile_parse_error("Invalid or out-of-bounds class index in EnclosingMethod attribute in class file %s", CHECK);
}
check_property(valid_klass_reference_at(enclosing_method_class_index),
"Invalid or out-of-bounds class index in EnclosingMethod attribute in class file %s", CHECK);
if (enclosing_method_method_index != 0 &&
(!cp->is_within_bounds(enclosing_method_method_index) ||
!cp->tag_at(enclosing_method_method_index).is_name_and_type())) {
(!_cp->is_within_bounds(enclosing_method_method_index) ||
!_cp->tag_at(enclosing_method_method_index).is_name_and_type())) {
classfile_parse_error("Invalid or out-of-bounds method index in EnclosingMethod attribute in class file %s", CHECK);
}
} else if (tag == vmSymbols::tag_bootstrap_methods() &&
......@@ -3014,7 +2916,7 @@ void ClassFileParser::parse_classfile_attributes(ClassLoaderData* loader_data,
if (parsed_bootstrap_methods_attribute)
classfile_parse_error("Multiple BootstrapMethods attributes in class file %s", CHECK);
parsed_bootstrap_methods_attribute = true;
parse_classfile_bootstrap_methods_attribute(loader_data, cp, attribute_length, CHECK);
parse_classfile_bootstrap_methods_attribute(attribute_length, CHECK);
} else if (tag == vmSymbols::tag_runtime_visible_type_annotations()) {
runtime_visible_type_annotations_length = attribute_length;
runtime_visible_type_annotations = cfs->get_u1_buffer();
......@@ -3035,29 +2937,24 @@ void ClassFileParser::parse_classfile_attributes(ClassLoaderData* loader_data,
cfs->skip_u1(attribute_length, CHECK);
}
}
AnnotationArray* annotations = assemble_annotations(loader_data,
runtime_visible_annotations,
_annotations = assemble_annotations(runtime_visible_annotations,
runtime_visible_annotations_length,
runtime_invisible_annotations,
runtime_invisible_annotations_length,
CHECK);
set_class_annotations(annotations);
AnnotationArray* type_annotations = assemble_annotations(loader_data,
runtime_visible_type_annotations,
_type_annotations = assemble_annotations(runtime_visible_type_annotations,
runtime_visible_type_annotations_length,
runtime_invisible_type_annotations,
runtime_invisible_type_annotations_length,
CHECK);
set_class_type_annotations(type_annotations);
if (parsed_innerclasses_attribute || parsed_enclosingmethod_attribute) {
u2 num_of_classes = parse_classfile_inner_classes_attribute(
loader_data,
inner_classes_attribute_start,
parsed_innerclasses_attribute,
enclosing_method_class_index,
enclosing_method_method_index,
cp, CHECK);
CHECK);
if (parsed_innerclasses_attribute &&_need_verify && _major_version >= JAVA_1_5_VERSION) {
guarantee_property(
inner_classes_attribute_length == sizeof(num_of_classes) + 4 * sizeof(u2) * num_of_classes,
......@@ -3085,18 +2982,43 @@ void ClassFileParser::apply_parsed_class_attributes(instanceKlassHandle k) {
if (_sde_buffer != NULL) {
k->set_source_debug_extension(_sde_buffer, _sde_length);
}
k->set_inner_classes(_inner_classes);
}
AnnotationArray* ClassFileParser::assemble_annotations(ClassLoaderData* loader_data,
u1* runtime_visible_annotations,
// Transfer ownership of metadata allocated to the InstanceKlass.
void ClassFileParser::apply_parsed_class_metadata(
instanceKlassHandle this_klass,
int java_fields_count, TRAPS) {
// Assign annotations if needed
if (_annotations != NULL || _type_annotations != NULL ||
_fields_annotations != NULL || _fields_type_annotations != NULL) {
Annotations* annotations = Annotations::allocate(_loader_data, CHECK);
annotations->set_class_annotations(_annotations);
annotations->set_class_type_annotations(_type_annotations);
annotations->set_fields_annotations(_fields_annotations);
annotations->set_fields_type_annotations(_fields_type_annotations);
this_klass->set_annotations(annotations);
}
_cp->set_pool_holder(this_klass());
this_klass->set_constants(_cp);
this_klass->set_fields(_fields, java_fields_count);
this_klass->set_methods(_methods);
this_klass->set_inner_classes(_inner_classes);
this_klass->set_local_interfaces(_local_interfaces);
this_klass->set_transitive_interfaces(_transitive_interfaces);
// Clear out these fields so they don't get deallocated by the destructor
clear_class_metadata();
}
AnnotationArray* ClassFileParser::assemble_annotations(u1* runtime_visible_annotations,
int runtime_visible_annotations_length,
u1* runtime_invisible_annotations,
int runtime_invisible_annotations_length, TRAPS) {
AnnotationArray* annotations = NULL;
if (runtime_visible_annotations != NULL ||
runtime_invisible_annotations != NULL) {
annotations = MetadataFactory::new_array<u1>(loader_data,
annotations = MetadataFactory::new_array<u1>(_loader_data,
runtime_visible_annotations_length +
runtime_invisible_annotations_length,
CHECK_(annotations));
......@@ -3144,827 +3066,889 @@ static void parseAndPrintGenericSignatures(
#endif // ndef PRODUCT
instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
ClassLoaderData* loader_data,
Handle protection_domain,
KlassHandle host_klass,
GrowableArray<Handle>* cp_patches,
TempNewSymbol& parsed_name,
bool verify,
instanceKlassHandle ClassFileParser::parse_super_class(int super_class_index,
TRAPS) {
instanceKlassHandle super_klass;
if (super_class_index == 0) {
check_property(_class_name == vmSymbols::java_lang_Object(),
"Invalid superclass index %u in class file %s",
super_class_index,
CHECK_NULL);
} else {
check_property(valid_klass_reference_at(super_class_index),
"Invalid superclass index %u in class file %s",
super_class_index,
CHECK_NULL);
// The class name should be legal because it is checked when parsing constant pool.
// However, make sure it is not an array type.
bool is_array = false;
if (_cp->tag_at(super_class_index).is_klass()) {
super_klass = instanceKlassHandle(THREAD, _cp->resolved_klass_at(super_class_index));
if (_need_verify)
is_array = super_klass->oop_is_array();
} else if (_need_verify) {
is_array = (_cp->unresolved_klass_at(super_class_index)->byte_at(0) == JVM_SIGNATURE_ARRAY);
}
if (_need_verify) {
guarantee_property(!is_array,
"Bad superclass name in class file %s", CHECK_NULL);
}
}
return super_klass;
}
// When a retransformable agent is attached, JVMTI caches the
// class bytes that existed before the first retransformation.
// If RedefineClasses() was used before the retransformable
// agent attached, then the cached class bytes may not be the
// original class bytes.
unsigned char *cached_class_file_bytes = NULL;
jint cached_class_file_length;
Handle class_loader(THREAD, loader_data->class_loader());
bool has_default_methods = false;
ResourceMark rm(THREAD);
ClassFileStream* cfs = stream();
// Timing
assert(THREAD->is_Java_thread(), "must be a JavaThread");
JavaThread* jt = (JavaThread*) THREAD;
// Values needed for oopmap and InstanceKlass creation
class FieldLayoutInfo : public StackObj {
public:
int* nonstatic_oop_offsets;
unsigned int* nonstatic_oop_counts;
unsigned int nonstatic_oop_map_count;
unsigned int total_oop_map_count;
int instance_size;
int nonstatic_field_size;
int static_field_size;
bool has_nonstatic_fields;
};
PerfClassTraceTime ctimer(ClassLoader::perf_class_parse_time(),
ClassLoader::perf_class_parse_selftime(),
NULL,
jt->get_thread_stat()->perf_recursion_counts_addr(),
jt->get_thread_stat()->perf_timers_addr(),
PerfClassTraceTime::PARSE_CLASS);
// Layout fields and fill in FieldLayoutInfo. Could use more refactoring!
void ClassFileParser::layout_fields(Handle class_loader,
FieldAllocationCount* fac,
ClassAnnotationCollector* parsed_annotations,
FieldLayoutInfo* info,
TRAPS) {
init_parsed_class_attributes();
// get the padding width from the option
// TODO: Ask VM about specific CPU we are running on
int pad_size = ContendedPaddingWidth;
if (JvmtiExport::should_post_class_file_load_hook()) {
// Get the cached class file bytes (if any) from the class that
// is being redefined or retransformed. We use jvmti_thread_state()
// instead of JvmtiThreadState::state_for(jt) so we don't allocate
// a JvmtiThreadState any earlier than necessary. This will help
// avoid the bug described by 7126851.
JvmtiThreadState *state = jt->jvmti_thread_state();
if (state != NULL) {
KlassHandle *h_class_being_redefined =
state->get_class_being_redefined();
if (h_class_being_redefined != NULL) {
instanceKlassHandle ikh_class_being_redefined =
instanceKlassHandle(THREAD, (*h_class_being_redefined)());
cached_class_file_bytes =
ikh_class_being_redefined->get_cached_class_file_bytes();
cached_class_file_length =
ikh_class_being_redefined->get_cached_class_file_len();
// Field size and offset computation
int nonstatic_field_size = _super_klass() == NULL ? 0 : _super_klass()->nonstatic_field_size();
#ifndef PRODUCT
int orig_nonstatic_field_size = 0;
#endif
int next_static_oop_offset;
int next_static_double_offset;
int next_static_word_offset;
int next_static_short_offset;
int next_static_byte_offset;
int next_nonstatic_oop_offset;
int next_nonstatic_double_offset;
int next_nonstatic_word_offset;
int next_nonstatic_short_offset;
int next_nonstatic_byte_offset;
int next_nonstatic_type_offset;
int first_nonstatic_oop_offset;
int first_nonstatic_field_offset;
int next_nonstatic_field_offset;
int next_nonstatic_padded_offset;
// Count the contended fields by type.
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()) {
nonstatic_contended_count++;
}
}
}
int contended_count = nonstatic_contended_count;
unsigned char* ptr = cfs->buffer();
unsigned char* end_ptr = cfs->buffer() + cfs->length();
JvmtiExport::post_class_file_load_hook(name, class_loader(), protection_domain,
&ptr, &end_ptr,
&cached_class_file_bytes,
&cached_class_file_length);
if (ptr != cfs->buffer()) {
// JVMTI agent has modified class file data.
// Set new class file stream using JVMTI agent modified
// class file data.
cfs = new ClassFileStream(ptr, end_ptr - ptr, cfs->source());
set_stream(cfs);
// Calculate the starting byte offsets
next_static_oop_offset = InstanceMirrorKlass::offset_of_static_fields();
next_static_double_offset = next_static_oop_offset +
((fac->count[STATIC_OOP]) * heapOopSize);
if ( fac->count[STATIC_DOUBLE] &&
(Universe::field_type_should_be_aligned(T_DOUBLE) ||
Universe::field_type_should_be_aligned(T_LONG)) ) {
next_static_double_offset = align_size_up(next_static_double_offset, BytesPerLong);
}
next_static_word_offset = next_static_double_offset +
((fac->count[STATIC_DOUBLE]) * BytesPerLong);
next_static_short_offset = next_static_word_offset +
((fac->count[STATIC_WORD]) * BytesPerInt);
next_static_byte_offset = next_static_short_offset +
((fac->count[STATIC_SHORT]) * BytesPerShort);
first_nonstatic_field_offset = instanceOopDesc::base_offset_in_bytes() +
nonstatic_field_size * heapOopSize;
// class is contended, pad before all the fields
if (parsed_annotations->is_contended()) {
first_nonstatic_field_offset += pad_size;
}
_host_klass = host_klass;
_cp_patches = cp_patches;
next_nonstatic_field_offset = first_nonstatic_field_offset;
instanceKlassHandle nullHandle;
unsigned int nonstatic_double_count = fac->count[NONSTATIC_DOUBLE] - fac_contended.count[NONSTATIC_DOUBLE];
unsigned int nonstatic_word_count = fac->count[NONSTATIC_WORD] - fac_contended.count[NONSTATIC_WORD];
unsigned int nonstatic_short_count = fac->count[NONSTATIC_SHORT] - fac_contended.count[NONSTATIC_SHORT];
unsigned int nonstatic_byte_count = fac->count[NONSTATIC_BYTE] - fac_contended.count[NONSTATIC_BYTE];
unsigned int nonstatic_oop_count = fac->count[NONSTATIC_OOP] - fac_contended.count[NONSTATIC_OOP];
// Figure out whether we can skip format checking (matching classic VM behavior)
_need_verify = Verifier::should_verify_for(class_loader(), verify);
bool super_has_nonstatic_fields =
(_super_klass() != NULL && _super_klass->has_nonstatic_fields());
bool has_nonstatic_fields = super_has_nonstatic_fields ||
((nonstatic_double_count + nonstatic_word_count +
nonstatic_short_count + nonstatic_byte_count +
nonstatic_oop_count) != 0);
// Set the verify flag in stream
cfs->set_verify(_need_verify);
// Save the class file name for easier error message printing.
_class_name = (name != NULL) ? name : vmSymbols::unknown_class_name();
// Prepare list of oops for oop map generation.
int* nonstatic_oop_offsets;
unsigned int* nonstatic_oop_counts;
unsigned int nonstatic_oop_map_count = 0;
cfs->guarantee_more(8, CHECK_(nullHandle)); // magic, major, minor
// Magic value
u4 magic = cfs->get_u4_fast();
guarantee_property(magic == JAVA_CLASSFILE_MAGIC,
"Incompatible magic value %u in class file %s",
magic, CHECK_(nullHandle));
nonstatic_oop_offsets = NEW_RESOURCE_ARRAY_IN_THREAD(
THREAD, int, nonstatic_oop_count + 1);
nonstatic_oop_counts = NEW_RESOURCE_ARRAY_IN_THREAD(
THREAD, unsigned int, nonstatic_oop_count + 1);
// Version numbers
u2 minor_version = cfs->get_u2_fast();
u2 major_version = cfs->get_u2_fast();
first_nonstatic_oop_offset = 0; // will be set for first oop field
// Check version numbers - we check this even with verifier off
if (!is_supported_version(major_version, minor_version)) {
if (name == NULL) {
Exceptions::fthrow(
THREAD_AND_LOCATION,
vmSymbols::java_lang_UnsupportedClassVersionError(),
"Unsupported major.minor version %u.%u",
major_version,
minor_version);
} else {
ResourceMark rm(THREAD);
Exceptions::fthrow(
THREAD_AND_LOCATION,
vmSymbols::java_lang_UnsupportedClassVersionError(),
"%s : Unsupported major.minor version %u.%u",
name->as_C_string(),
major_version,
minor_version);
}
return nullHandle;
}
_major_version = major_version;
_minor_version = minor_version;
// Check if verification needs to be relaxed for this class file
// Do not restrict it to jdk1.0 or jdk1.1 to maintain backward compatibility (4982376)
_relax_verify = Verifier::relax_verify_for(class_loader());
// Constant pool
constantPoolHandle cp = parse_constant_pool(loader_data, CHECK_(nullHandle));
ConstantPoolCleaner error_handler(cp); // set constant pool to be cleaned up.
int cp_size = cp->length();
cfs->guarantee_more(8, CHECK_(nullHandle)); // flags, this_class, super_class, infs_len
// Access flags
AccessFlags access_flags;
jint flags = cfs->get_u2_fast() & JVM_RECOGNIZED_CLASS_MODIFIERS;
if ((flags & JVM_ACC_INTERFACE) && _major_version < JAVA_6_VERSION) {
// Set abstract bit for old class files for backward compatibility
flags |= JVM_ACC_ABSTRACT;
#ifndef PRODUCT
if( PrintCompactFieldsSavings ) {
next_nonstatic_double_offset = next_nonstatic_field_offset +
(nonstatic_oop_count * heapOopSize);
if ( nonstatic_double_count > 0 ) {
next_nonstatic_double_offset = align_size_up(next_nonstatic_double_offset, BytesPerLong);
}
verify_legal_class_modifiers(flags, CHECK_(nullHandle));
access_flags.set_flags(flags);
// This class and superclass
instanceKlassHandle super_klass;
u2 this_class_index = cfs->get_u2_fast();
check_property(
valid_cp_range(this_class_index, cp_size) &&
cp->tag_at(this_class_index).is_unresolved_klass(),
"Invalid this class index %u in constant pool in class file %s",
this_class_index, CHECK_(nullHandle));
Symbol* class_name = cp->unresolved_klass_at(this_class_index);
assert(class_name != NULL, "class_name can't be null");
// It's important to set parsed_name *before* resolving the super class.
// (it's used for cleanup by the caller if parsing fails)
parsed_name = class_name;
// parsed_name is returned and can be used if there's an error, so add to
// its reference count. Caller will decrement the refcount.
parsed_name->increment_refcount();
// Update _class_name which could be null previously to be class_name
_class_name = class_name;
// Don't need to check whether this class name is legal or not.
// It has been checked when constant pool is parsed.
// However, make sure it is not an array type.
if (_need_verify) {
guarantee_property(class_name->byte_at(0) != JVM_SIGNATURE_ARRAY,
"Bad class name in class file %s",
CHECK_(nullHandle));
next_nonstatic_word_offset = next_nonstatic_double_offset +
(nonstatic_double_count * BytesPerLong);
next_nonstatic_short_offset = next_nonstatic_word_offset +
(nonstatic_word_count * BytesPerInt);
next_nonstatic_byte_offset = next_nonstatic_short_offset +
(nonstatic_short_count * BytesPerShort);
next_nonstatic_type_offset = align_size_up((next_nonstatic_byte_offset +
nonstatic_byte_count ), heapOopSize );
orig_nonstatic_field_size = nonstatic_field_size +
((next_nonstatic_type_offset - first_nonstatic_field_offset)/heapOopSize);
}
Klass* preserve_this_klass; // for storing result across HandleMark
// release all handles when parsing is done
{ HandleMark hm(THREAD);
// Checks if name in class file matches requested name
if (name != NULL && class_name != name) {
ResourceMark rm(THREAD);
Exceptions::fthrow(
THREAD_AND_LOCATION,
vmSymbols::java_lang_NoClassDefFoundError(),
"%s (wrong name: %s)",
name->as_C_string(),
class_name->as_C_string()
);
return nullHandle;
#endif
bool compact_fields = CompactFields;
int allocation_style = FieldsAllocationStyle;
if( allocation_style < 0 || allocation_style > 2 ) { // Out of range?
assert(false, "0 <= FieldsAllocationStyle <= 2");
allocation_style = 1; // Optimistic
}
if (TraceClassLoadingPreorder) {
tty->print("[Loading %s", name->as_klass_external_name());
if (cfs->source() != NULL) tty->print(" from %s", cfs->source());
tty->print_cr("]");
// The next classes have predefined hard-coded fields offsets
// (see in JavaClasses::compute_hard_coded_offsets()).
// Use default fields allocation order for them.
if( (allocation_style != 0 || compact_fields ) && class_loader.is_null() &&
(_class_name == vmSymbols::java_lang_AssertionStatusDirectives() ||
_class_name == vmSymbols::java_lang_Class() ||
_class_name == vmSymbols::java_lang_ClassLoader() ||
_class_name == vmSymbols::java_lang_ref_Reference() ||
_class_name == vmSymbols::java_lang_ref_SoftReference() ||
_class_name == vmSymbols::java_lang_StackTraceElement() ||
_class_name == vmSymbols::java_lang_String() ||
_class_name == vmSymbols::java_lang_Throwable() ||
_class_name == vmSymbols::java_lang_Boolean() ||
_class_name == vmSymbols::java_lang_Character() ||
_class_name == vmSymbols::java_lang_Float() ||
_class_name == vmSymbols::java_lang_Double() ||
_class_name == vmSymbols::java_lang_Byte() ||
_class_name == vmSymbols::java_lang_Short() ||
_class_name == vmSymbols::java_lang_Integer() ||
_class_name == vmSymbols::java_lang_Long())) {
allocation_style = 0; // Allocate oops first
compact_fields = false; // Don't compact fields
}
u2 super_class_index = cfs->get_u2_fast();
if (super_class_index == 0) {
check_property(class_name == vmSymbols::java_lang_Object(),
"Invalid superclass index %u in class file %s",
super_class_index,
CHECK_(nullHandle));
} else {
check_property(valid_cp_range(super_class_index, cp_size) &&
is_klass_reference(cp, super_class_index),
"Invalid superclass index %u in class file %s",
super_class_index,
CHECK_(nullHandle));
// The class name should be legal because it is checked when parsing constant pool.
// However, make sure it is not an array type.
bool is_array = false;
if (cp->tag_at(super_class_index).is_klass()) {
super_klass = instanceKlassHandle(THREAD, cp->resolved_klass_at(super_class_index));
if (_need_verify)
is_array = super_klass->oop_is_array();
} else if (_need_verify) {
is_array = (cp->unresolved_klass_at(super_class_index)->byte_at(0) == JVM_SIGNATURE_ARRAY);
if( allocation_style == 0 ) {
// Fields order: oops, longs/doubles, ints, shorts/chars, bytes, padded fields
next_nonstatic_oop_offset = next_nonstatic_field_offset;
next_nonstatic_double_offset = next_nonstatic_oop_offset +
(nonstatic_oop_count * heapOopSize);
} else if( allocation_style == 1 ) {
// Fields order: longs/doubles, ints, shorts/chars, bytes, oops, padded fields
next_nonstatic_double_offset = next_nonstatic_field_offset;
} else if( allocation_style == 2 ) {
// Fields allocation: oops fields in super and sub classes are together.
if( nonstatic_field_size > 0 && _super_klass() != NULL &&
_super_klass->nonstatic_oop_map_size() > 0 ) {
unsigned int map_count = _super_klass->nonstatic_oop_map_count();
OopMapBlock* first_map = _super_klass->start_of_nonstatic_oop_maps();
OopMapBlock* last_map = first_map + map_count - 1;
int next_offset = last_map->offset() + (last_map->count() * heapOopSize);
if (next_offset == next_nonstatic_field_offset) {
allocation_style = 0; // allocate oops first
next_nonstatic_oop_offset = next_nonstatic_field_offset;
next_nonstatic_double_offset = next_nonstatic_oop_offset +
(nonstatic_oop_count * heapOopSize);
}
if (_need_verify) {
guarantee_property(!is_array,
"Bad superclass name in class file %s", CHECK_(nullHandle));
}
if( allocation_style == 2 ) {
allocation_style = 1; // allocate oops last
next_nonstatic_double_offset = next_nonstatic_field_offset;
}
// Interfaces
u2 itfs_len = cfs->get_u2_fast();
Array<Klass*>* local_interfaces;
if (itfs_len == 0) {
local_interfaces = Universe::the_empty_klass_array();
} else {
local_interfaces = parse_interfaces(
cp, itfs_len, loader_data, protection_domain, _class_name,
&has_default_methods, CHECK_(nullHandle));
ShouldNotReachHere();
}
u2 java_fields_count = 0;
// Fields (offsets are filled in later)
FieldAllocationCount fac;
Array<AnnotationArray*>* fields_annotations = NULL;
Array<AnnotationArray*>* fields_type_annotations = NULL;
Array<u2>* fields = parse_fields(loader_data, class_name, cp, access_flags.is_interface(), &fac, &fields_annotations,
&fields_type_annotations,
&java_fields_count,
CHECK_(nullHandle));
// Methods
bool has_final_method = false;
AccessFlags promoted_flags;
promoted_flags.set_flags(0);
Array<Method*>* methods = parse_methods(loader_data,
cp, access_flags.is_interface(),
&promoted_flags,
&has_final_method,
&has_default_methods,
CHECK_(nullHandle));
// Additional attributes
ClassAnnotationCollector parsed_annotations;
parse_classfile_attributes(loader_data, cp, &parsed_annotations, CHECK_(nullHandle));
// Make sure this is the end of class file stream
guarantee_property(cfs->at_eos(), "Extra bytes at the end of class file %s", CHECK_(nullHandle));
int nonstatic_oop_space_count = 0;
int nonstatic_word_space_count = 0;
int nonstatic_short_space_count = 0;
int nonstatic_byte_space_count = 0;
int nonstatic_oop_space_offset;
int nonstatic_word_space_offset;
int nonstatic_short_space_offset;
int nonstatic_byte_space_offset;
// We check super class after class file is parsed and format is checked
if (super_class_index > 0 && super_klass.is_null()) {
Symbol* sk = cp->klass_name_at(super_class_index);
if (access_flags.is_interface()) {
// Before attempting to resolve the superclass, check for class format
// errors not checked yet.
guarantee_property(sk == vmSymbols::java_lang_Object(),
"Interfaces must have java.lang.Object as superclass in class file %s",
CHECK_(nullHandle));
if( nonstatic_double_count > 0 ) {
int offset = next_nonstatic_double_offset;
next_nonstatic_double_offset = align_size_up(offset, BytesPerLong);
if( compact_fields && offset != next_nonstatic_double_offset ) {
// Allocate available fields into the gap before double field.
int length = next_nonstatic_double_offset - offset;
assert(length == BytesPerInt, "");
nonstatic_word_space_offset = offset;
if( nonstatic_word_count > 0 ) {
nonstatic_word_count -= 1;
nonstatic_word_space_count = 1; // Only one will fit
length -= BytesPerInt;
offset += BytesPerInt;
}
Klass* k = SystemDictionary::resolve_super_or_fail(class_name, sk,
class_loader,
protection_domain,
true,
CHECK_(nullHandle));
KlassHandle kh (THREAD, k);
super_klass = instanceKlassHandle(THREAD, kh());
nonstatic_short_space_offset = offset;
while( length >= BytesPerShort && nonstatic_short_count > 0 ) {
nonstatic_short_count -= 1;
nonstatic_short_space_count += 1;
length -= BytesPerShort;
offset += BytesPerShort;
}
if (super_klass.not_null()) {
if (super_klass->has_default_methods()) {
has_default_methods = true;
nonstatic_byte_space_offset = offset;
while( length > 0 && nonstatic_byte_count > 0 ) {
nonstatic_byte_count -= 1;
nonstatic_byte_space_count += 1;
length -= 1;
}
if (super_klass->is_interface()) {
ResourceMark rm(THREAD);
Exceptions::fthrow(
THREAD_AND_LOCATION,
vmSymbols::java_lang_IncompatibleClassChangeError(),
"class %s has interface %s as super class",
class_name->as_klass_external_name(),
super_klass->external_name()
);
return nullHandle;
// Allocate oop field in the gap if there are no other fields for that.
nonstatic_oop_space_offset = offset;
if( length >= heapOopSize && nonstatic_oop_count > 0 &&
allocation_style != 0 ) { // when oop fields not first
nonstatic_oop_count -= 1;
nonstatic_oop_space_count = 1; // Only one will fit
length -= heapOopSize;
offset += heapOopSize;
}
// Make sure super class is not final
if (super_klass->is_final()) {
THROW_MSG_(vmSymbols::java_lang_VerifyError(), "Cannot inherit from final class", nullHandle);
}
}
// Compute the transitive list of all unique interfaces implemented by this class
Array<Klass*>* transitive_interfaces = compute_transitive_interfaces(loader_data, super_klass, local_interfaces, CHECK_(nullHandle));
// sort methods
Array<int>* method_ordering = sort_methods(loader_data,
methods,
CHECK_(nullHandle));
// promote flags from parse_methods() to the klass' flags
access_flags.add_promoted_flags(promoted_flags.as_int());
// Size of Java vtable (in words)
int vtable_size = 0;
int itable_size = 0;
int num_miranda_methods = 0;
GrowableArray<Method*> all_mirandas(20);
next_nonstatic_word_offset = next_nonstatic_double_offset +
(nonstatic_double_count * BytesPerLong);
next_nonstatic_short_offset = next_nonstatic_word_offset +
(nonstatic_word_count * BytesPerInt);
next_nonstatic_byte_offset = next_nonstatic_short_offset +
(nonstatic_short_count * BytesPerShort);
next_nonstatic_padded_offset = next_nonstatic_byte_offset +
nonstatic_byte_count;
klassVtable::compute_vtable_size_and_num_mirandas(
&vtable_size, &num_miranda_methods, &all_mirandas, super_klass(), methods,
access_flags, class_loader, class_name, local_interfaces,
CHECK_(nullHandle));
// let oops jump before padding with this allocation style
if( allocation_style == 1 ) {
next_nonstatic_oop_offset = next_nonstatic_padded_offset;
if( nonstatic_oop_count > 0 ) {
next_nonstatic_oop_offset = align_size_up(next_nonstatic_oop_offset, heapOopSize);
}
next_nonstatic_padded_offset = next_nonstatic_oop_offset + (nonstatic_oop_count * heapOopSize);
}
// Size of Java itable (in words)
itable_size = access_flags.is_interface() ? 0 : klassItable::compute_itable_size(transitive_interfaces);
// Iterate over fields again and compute correct offsets.
// The field allocation type was temporarily stored in the offset slot.
// oop fields are located before non-oop fields (static and non-static).
for (AllFieldStream fs(_fields, _cp); !fs.done(); fs.next()) {
// get the padding width from the option
// TODO: Ask VM about specific CPU we are running on
int pad_size = ContendedPaddingWidth;
// skip already laid out fields
if (fs.is_offset_set()) continue;
// Field size and offset computation
int nonstatic_field_size = super_klass() == NULL ? 0 : super_klass->nonstatic_field_size();
#ifndef PRODUCT
int orig_nonstatic_field_size = 0;
#endif
int next_static_oop_offset;
int next_static_double_offset;
int next_static_word_offset;
int next_static_short_offset;
int next_static_byte_offset;
int next_nonstatic_oop_offset;
int next_nonstatic_double_offset;
int next_nonstatic_word_offset;
int next_nonstatic_short_offset;
int next_nonstatic_byte_offset;
int next_nonstatic_type_offset;
int first_nonstatic_oop_offset;
int first_nonstatic_field_offset;
int next_nonstatic_field_offset;
int next_nonstatic_padded_offset;
// contended instance fields are handled below
if (fs.is_contended() && !fs.access_flags().is_static()) continue;
// Count the contended fields by type.
int nonstatic_contended_count = 0;
FieldAllocationCount fac_contended;
for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) {
int real_offset;
FieldAllocationType atype = (FieldAllocationType) fs.allocation_type();
if (fs.is_contended()) {
fac_contended.count[atype]++;
if (!fs.access_flags().is_static()) {
nonstatic_contended_count++;
// pack the rest of the fields
switch (atype) {
case STATIC_OOP:
real_offset = next_static_oop_offset;
next_static_oop_offset += heapOopSize;
break;
case STATIC_BYTE:
real_offset = next_static_byte_offset;
next_static_byte_offset += 1;
break;
case STATIC_SHORT:
real_offset = next_static_short_offset;
next_static_short_offset += BytesPerShort;
break;
case STATIC_WORD:
real_offset = next_static_word_offset;
next_static_word_offset += BytesPerInt;
break;
case STATIC_DOUBLE:
real_offset = next_static_double_offset;
next_static_double_offset += BytesPerLong;
break;
case NONSTATIC_OOP:
if( nonstatic_oop_space_count > 0 ) {
real_offset = nonstatic_oop_space_offset;
nonstatic_oop_space_offset += heapOopSize;
nonstatic_oop_space_count -= 1;
} else {
real_offset = next_nonstatic_oop_offset;
next_nonstatic_oop_offset += heapOopSize;
}
// Update oop maps
if( nonstatic_oop_map_count > 0 &&
nonstatic_oop_offsets[nonstatic_oop_map_count - 1] ==
real_offset -
int(nonstatic_oop_counts[nonstatic_oop_map_count - 1]) *
heapOopSize ) {
// Extend current oop map
nonstatic_oop_counts[nonstatic_oop_map_count - 1] += 1;
} else {
// 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;
case NONSTATIC_BYTE:
if( nonstatic_byte_space_count > 0 ) {
real_offset = nonstatic_byte_space_offset;
nonstatic_byte_space_offset += 1;
nonstatic_byte_space_count -= 1;
} else {
real_offset = next_nonstatic_byte_offset;
next_nonstatic_byte_offset += 1;
}
break;
case NONSTATIC_SHORT:
if( nonstatic_short_space_count > 0 ) {
real_offset = nonstatic_short_space_offset;
nonstatic_short_space_offset += BytesPerShort;
nonstatic_short_space_count -= 1;
} else {
real_offset = next_nonstatic_short_offset;
next_nonstatic_short_offset += BytesPerShort;
}
break;
case NONSTATIC_WORD:
if( nonstatic_word_space_count > 0 ) {
real_offset = nonstatic_word_space_offset;
nonstatic_word_space_offset += BytesPerInt;
nonstatic_word_space_count -= 1;
} else {
real_offset = next_nonstatic_word_offset;
next_nonstatic_word_offset += BytesPerInt;
}
break;
case NONSTATIC_DOUBLE:
real_offset = next_nonstatic_double_offset;
next_nonstatic_double_offset += BytesPerLong;
break;
default:
ShouldNotReachHere();
}
fs.set_offset(real_offset);
}
int contended_count = nonstatic_contended_count;
// Calculate the starting byte offsets
next_static_oop_offset = InstanceMirrorKlass::offset_of_static_fields();
// 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) {
next_static_double_offset = next_static_oop_offset +
((fac.count[STATIC_OOP]) * heapOopSize);
if ( fac.count[STATIC_DOUBLE] &&
(Universe::field_type_should_be_aligned(T_DOUBLE) ||
Universe::field_type_should_be_aligned(T_LONG)) ) {
next_static_double_offset = align_size_up(next_static_double_offset, BytesPerLong);
// 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;
}
next_static_word_offset = next_static_double_offset +
((fac.count[STATIC_DOUBLE]) * BytesPerLong);
next_static_short_offset = next_static_word_offset +
((fac.count[STATIC_WORD]) * BytesPerInt);
next_static_byte_offset = next_static_short_offset +
((fac.count[STATIC_SHORT]) * BytesPerShort);
first_nonstatic_field_offset = instanceOopDesc::base_offset_in_bytes() +
nonstatic_field_size * heapOopSize;
// 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;
// class is contended, pad before all the fields
if (parsed_annotations.is_contended()) {
first_nonstatic_field_offset += pad_size;
if (fs.is_contended()) {
bm.set_bit(fs.contended_group());
}
}
next_nonstatic_field_offset = first_nonstatic_field_offset;
int current_group = -1;
while ((current_group = (int)bm.get_next_one_offset(current_group + 1)) != (int)bm.size()) {
unsigned int nonstatic_double_count = fac.count[NONSTATIC_DOUBLE] - fac_contended.count[NONSTATIC_DOUBLE];
unsigned int nonstatic_word_count = fac.count[NONSTATIC_WORD] - fac_contended.count[NONSTATIC_WORD];
unsigned int nonstatic_short_count = fac.count[NONSTATIC_SHORT] - fac_contended.count[NONSTATIC_SHORT];
unsigned int nonstatic_byte_count = fac.count[NONSTATIC_BYTE] - fac_contended.count[NONSTATIC_BYTE];
unsigned int nonstatic_oop_count = fac.count[NONSTATIC_OOP] - fac_contended.count[NONSTATIC_OOP];
for (AllFieldStream fs(_fields, _cp); !fs.done(); fs.next()) {
bool super_has_nonstatic_fields =
(super_klass() != NULL && super_klass->has_nonstatic_fields());
bool has_nonstatic_fields = super_has_nonstatic_fields ||
((nonstatic_double_count + nonstatic_word_count +
nonstatic_short_count + nonstatic_byte_count +
nonstatic_oop_count) != 0);
// 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;
// Prepare list of oops for oop map generation.
int* nonstatic_oop_offsets;
unsigned int* nonstatic_oop_counts;
unsigned int nonstatic_oop_map_count = 0;
// handle statics below
if (fs.access_flags().is_static()) continue;
nonstatic_oop_offsets = NEW_RESOURCE_ARRAY_IN_THREAD(
THREAD, int, nonstatic_oop_count + 1);
nonstatic_oop_counts = NEW_RESOURCE_ARRAY_IN_THREAD(
THREAD, unsigned int, nonstatic_oop_count + 1);
int real_offset;
FieldAllocationType atype = (FieldAllocationType) fs.allocation_type();
first_nonstatic_oop_offset = 0; // will be set for first oop field
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;
#ifndef PRODUCT
if( PrintCompactFieldsSavings ) {
next_nonstatic_double_offset = next_nonstatic_field_offset +
(nonstatic_oop_count * heapOopSize);
if ( nonstatic_double_count > 0 ) {
next_nonstatic_double_offset = align_size_up(next_nonstatic_double_offset, BytesPerLong);
}
next_nonstatic_word_offset = next_nonstatic_double_offset +
(nonstatic_double_count * BytesPerLong);
next_nonstatic_short_offset = next_nonstatic_word_offset +
(nonstatic_word_count * BytesPerInt);
next_nonstatic_byte_offset = next_nonstatic_short_offset +
(nonstatic_short_count * BytesPerShort);
next_nonstatic_type_offset = align_size_up((next_nonstatic_byte_offset +
nonstatic_byte_count ), heapOopSize );
orig_nonstatic_field_size = nonstatic_field_size +
((next_nonstatic_type_offset - first_nonstatic_field_offset)/heapOopSize);
}
#endif
bool compact_fields = CompactFields;
int allocation_style = FieldsAllocationStyle;
if( allocation_style < 0 || allocation_style > 2 ) { // Out of range?
assert(false, "0 <= FieldsAllocationStyle <= 2");
allocation_style = 1; // Optimistic
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;
// The next classes have predefined hard-coded fields offsets
// (see in JavaClasses::compute_hard_coded_offsets()).
// Use default fields allocation order for them.
if( (allocation_style != 0 || compact_fields ) && class_loader.is_null() &&
(class_name == vmSymbols::java_lang_AssertionStatusDirectives() ||
class_name == vmSymbols::java_lang_Class() ||
class_name == vmSymbols::java_lang_ClassLoader() ||
class_name == vmSymbols::java_lang_ref_Reference() ||
class_name == vmSymbols::java_lang_ref_SoftReference() ||
class_name == vmSymbols::java_lang_StackTraceElement() ||
class_name == vmSymbols::java_lang_String() ||
class_name == vmSymbols::java_lang_Throwable() ||
class_name == vmSymbols::java_lang_Boolean() ||
class_name == vmSymbols::java_lang_Character() ||
class_name == vmSymbols::java_lang_Float() ||
class_name == vmSymbols::java_lang_Double() ||
class_name == vmSymbols::java_lang_Byte() ||
class_name == vmSymbols::java_lang_Short() ||
class_name == vmSymbols::java_lang_Integer() ||
class_name == vmSymbols::java_lang_Long())) {
allocation_style = 0; // Allocate oops first
compact_fields = false; // Don't compact fields
default:
ShouldNotReachHere();
}
if( allocation_style == 0 ) {
// Fields order: oops, longs/doubles, ints, shorts/chars, bytes, padded fields
next_nonstatic_oop_offset = next_nonstatic_field_offset;
next_nonstatic_double_offset = next_nonstatic_oop_offset +
(nonstatic_oop_count * heapOopSize);
} else if( allocation_style == 1 ) {
// Fields order: longs/doubles, ints, shorts/chars, bytes, oops, padded fields
next_nonstatic_double_offset = next_nonstatic_field_offset;
} else if( allocation_style == 2 ) {
// Fields allocation: oops fields in super and sub classes are together.
if( nonstatic_field_size > 0 && super_klass() != NULL &&
super_klass->nonstatic_oop_map_size() > 0 ) {
int map_count = super_klass->nonstatic_oop_map_count();
OopMapBlock* first_map = super_klass->start_of_nonstatic_oop_maps();
OopMapBlock* last_map = first_map + map_count - 1;
int next_offset = last_map->offset() + (last_map->count() * heapOopSize);
if (next_offset == next_nonstatic_field_offset) {
allocation_style = 0; // allocate oops first
next_nonstatic_oop_offset = next_nonstatic_field_offset;
next_nonstatic_double_offset = next_nonstatic_oop_offset +
(nonstatic_oop_count * heapOopSize);
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;
}
if( allocation_style == 2 ) {
allocation_style = 1; // allocate oops last
next_nonstatic_double_offset = next_nonstatic_field_offset;
}
} else {
ShouldNotReachHere();
// handle static fields
}
int nonstatic_oop_space_count = 0;
int nonstatic_word_space_count = 0;
int nonstatic_short_space_count = 0;
int nonstatic_byte_space_count = 0;
int nonstatic_oop_space_offset;
int nonstatic_word_space_offset;
int nonstatic_short_space_offset;
int nonstatic_byte_space_offset;
// Size of instances
int notaligned_offset = next_nonstatic_padded_offset;
if( nonstatic_double_count > 0 ) {
int offset = next_nonstatic_double_offset;
next_nonstatic_double_offset = align_size_up(offset, BytesPerLong);
if( compact_fields && offset != next_nonstatic_double_offset ) {
// Allocate available fields into the gap before double field.
int length = next_nonstatic_double_offset - offset;
assert(length == BytesPerInt, "");
nonstatic_word_space_offset = offset;
if( nonstatic_word_count > 0 ) {
nonstatic_word_count -= 1;
nonstatic_word_space_count = 1; // Only one will fit
length -= BytesPerInt;
offset += BytesPerInt;
}
nonstatic_short_space_offset = offset;
while( length >= BytesPerShort && nonstatic_short_count > 0 ) {
nonstatic_short_count -= 1;
nonstatic_short_space_count += 1;
length -= BytesPerShort;
offset += BytesPerShort;
}
nonstatic_byte_space_offset = offset;
while( length > 0 && nonstatic_byte_count > 0 ) {
nonstatic_byte_count -= 1;
nonstatic_byte_space_count += 1;
length -= 1;
// 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;
}
// Allocate oop field in the gap if there are no other fields for that.
nonstatic_oop_space_offset = offset;
if( length >= heapOopSize && nonstatic_oop_count > 0 &&
allocation_style != 0 ) { // when oop fields not first
nonstatic_oop_count -= 1;
nonstatic_oop_space_count = 1; // Only one will fit
length -= heapOopSize;
offset += heapOopSize;
int next_static_type_offset = align_size_up(next_static_byte_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 );
int 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 + ((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.
const unsigned int total_oop_map_count =
compute_oop_map_count(_super_klass, nonstatic_oop_map_count,
first_nonstatic_oop_offset);
#ifndef PRODUCT
if( PrintCompactFieldsSavings ) {
ResourceMark rm;
if( nonstatic_field_size < orig_nonstatic_field_size ) {
tty->print("[Saved %d of %d bytes in %s]\n",
(orig_nonstatic_field_size - nonstatic_field_size)*heapOopSize,
orig_nonstatic_field_size*heapOopSize,
_class_name);
} else if( nonstatic_field_size > orig_nonstatic_field_size ) {
tty->print("[Wasted %d over %d bytes in %s]\n",
(nonstatic_field_size - orig_nonstatic_field_size)*heapOopSize,
orig_nonstatic_field_size*heapOopSize,
_class_name);
}
}
if (PrintFieldLayout) {
print_field_layout(_class_name,
_fields,
_cp,
instance_size,
first_nonstatic_field_offset,
next_nonstatic_field_offset,
next_static_type_offset);
}
next_nonstatic_word_offset = next_nonstatic_double_offset +
(nonstatic_double_count * BytesPerLong);
next_nonstatic_short_offset = next_nonstatic_word_offset +
(nonstatic_word_count * BytesPerInt);
next_nonstatic_byte_offset = next_nonstatic_short_offset +
(nonstatic_short_count * BytesPerShort);
next_nonstatic_padded_offset = next_nonstatic_byte_offset +
nonstatic_byte_count;
#endif
// Pass back information needed for InstanceKlass creation
info->nonstatic_oop_offsets = nonstatic_oop_offsets;
info->nonstatic_oop_counts = nonstatic_oop_counts;
info->nonstatic_oop_map_count = nonstatic_oop_map_count;
info->total_oop_map_count = total_oop_map_count;
info->instance_size = instance_size;
info->static_field_size = static_field_size;
info->nonstatic_field_size = nonstatic_field_size;
info->has_nonstatic_fields = has_nonstatic_fields;
}
// let oops jump before padding with this allocation style
if( allocation_style == 1 ) {
next_nonstatic_oop_offset = next_nonstatic_padded_offset;
if( nonstatic_oop_count > 0 ) {
next_nonstatic_oop_offset = align_size_up(next_nonstatic_oop_offset, heapOopSize);
}
next_nonstatic_padded_offset = next_nonstatic_oop_offset + (nonstatic_oop_count * heapOopSize);
}
// Iterate over fields again and compute correct offsets.
// The field allocation type was temporarily stored in the offset slot.
// oop fields are located before non-oop fields (static and non-static).
for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) {
instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
ClassLoaderData* loader_data,
Handle protection_domain,
KlassHandle host_klass,
GrowableArray<Handle>* cp_patches,
TempNewSymbol& parsed_name,
bool verify,
TRAPS) {
// skip already laid out fields
if (fs.is_offset_set()) continue;
// When a retransformable agent is attached, JVMTI caches the
// class bytes that existed before the first retransformation.
// If RedefineClasses() was used before the retransformable
// agent attached, then the cached class bytes may not be the
// original class bytes.
unsigned char *cached_class_file_bytes = NULL;
jint cached_class_file_length;
Handle class_loader(THREAD, loader_data->class_loader());
bool has_default_methods = false;
ResourceMark rm(THREAD);
// contended instance fields are handled below
if (fs.is_contended() && !fs.access_flags().is_static()) continue;
ClassFileStream* cfs = stream();
// Timing
assert(THREAD->is_Java_thread(), "must be a JavaThread");
JavaThread* jt = (JavaThread*) THREAD;
int real_offset;
FieldAllocationType atype = (FieldAllocationType) fs.allocation_type();
PerfClassTraceTime ctimer(ClassLoader::perf_class_parse_time(),
ClassLoader::perf_class_parse_selftime(),
NULL,
jt->get_thread_stat()->perf_recursion_counts_addr(),
jt->get_thread_stat()->perf_timers_addr(),
PerfClassTraceTime::PARSE_CLASS);
// pack the rest of the fields
switch (atype) {
case STATIC_OOP:
real_offset = next_static_oop_offset;
next_static_oop_offset += heapOopSize;
break;
case STATIC_BYTE:
real_offset = next_static_byte_offset;
next_static_byte_offset += 1;
break;
case STATIC_SHORT:
real_offset = next_static_short_offset;
next_static_short_offset += BytesPerShort;
break;
case STATIC_WORD:
real_offset = next_static_word_offset;
next_static_word_offset += BytesPerInt;
break;
case STATIC_DOUBLE:
real_offset = next_static_double_offset;
next_static_double_offset += BytesPerLong;
break;
case NONSTATIC_OOP:
if( nonstatic_oop_space_count > 0 ) {
real_offset = nonstatic_oop_space_offset;
nonstatic_oop_space_offset += heapOopSize;
nonstatic_oop_space_count -= 1;
} else {
real_offset = next_nonstatic_oop_offset;
next_nonstatic_oop_offset += heapOopSize;
}
// Update oop maps
if( nonstatic_oop_map_count > 0 &&
nonstatic_oop_offsets[nonstatic_oop_map_count - 1] ==
real_offset -
int(nonstatic_oop_counts[nonstatic_oop_map_count - 1]) *
heapOopSize ) {
// Extend current oop map
nonstatic_oop_counts[nonstatic_oop_map_count - 1] += 1;
} else {
// 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;
init_parsed_class_attributes(loader_data);
if (JvmtiExport::should_post_class_file_load_hook()) {
// Get the cached class file bytes (if any) from the class that
// is being redefined or retransformed. We use jvmti_thread_state()
// instead of JvmtiThreadState::state_for(jt) so we don't allocate
// a JvmtiThreadState any earlier than necessary. This will help
// avoid the bug described by 7126851.
JvmtiThreadState *state = jt->jvmti_thread_state();
if (state != NULL) {
KlassHandle *h_class_being_redefined =
state->get_class_being_redefined();
if (h_class_being_redefined != NULL) {
instanceKlassHandle ikh_class_being_redefined =
instanceKlassHandle(THREAD, (*h_class_being_redefined)());
cached_class_file_bytes =
ikh_class_being_redefined->get_cached_class_file_bytes();
cached_class_file_length =
ikh_class_being_redefined->get_cached_class_file_len();
}
}
break;
case NONSTATIC_BYTE:
if( nonstatic_byte_space_count > 0 ) {
real_offset = nonstatic_byte_space_offset;
nonstatic_byte_space_offset += 1;
nonstatic_byte_space_count -= 1;
} else {
real_offset = next_nonstatic_byte_offset;
next_nonstatic_byte_offset += 1;
unsigned char* ptr = cfs->buffer();
unsigned char* end_ptr = cfs->buffer() + cfs->length();
JvmtiExport::post_class_file_load_hook(name, class_loader(), protection_domain,
&ptr, &end_ptr,
&cached_class_file_bytes,
&cached_class_file_length);
if (ptr != cfs->buffer()) {
// JVMTI agent has modified class file data.
// Set new class file stream using JVMTI agent modified
// class file data.
cfs = new ClassFileStream(ptr, end_ptr - ptr, cfs->source());
set_stream(cfs);
}
break;
case NONSTATIC_SHORT:
if( nonstatic_short_space_count > 0 ) {
real_offset = nonstatic_short_space_offset;
nonstatic_short_space_offset += BytesPerShort;
nonstatic_short_space_count -= 1;
} else {
real_offset = next_nonstatic_short_offset;
next_nonstatic_short_offset += BytesPerShort;
}
break;
case NONSTATIC_WORD:
if( nonstatic_word_space_count > 0 ) {
real_offset = nonstatic_word_space_offset;
nonstatic_word_space_offset += BytesPerInt;
nonstatic_word_space_count -= 1;
_host_klass = host_klass;
_cp_patches = cp_patches;
instanceKlassHandle nullHandle;
// Figure out whether we can skip format checking (matching classic VM behavior)
_need_verify = Verifier::should_verify_for(class_loader(), verify);
// Set the verify flag in stream
cfs->set_verify(_need_verify);
// Save the class file name for easier error message printing.
_class_name = (name != NULL) ? name : vmSymbols::unknown_class_name();
cfs->guarantee_more(8, CHECK_(nullHandle)); // magic, major, minor
// Magic value
u4 magic = cfs->get_u4_fast();
guarantee_property(magic == JAVA_CLASSFILE_MAGIC,
"Incompatible magic value %u in class file %s",
magic, CHECK_(nullHandle));
// Version numbers
u2 minor_version = cfs->get_u2_fast();
u2 major_version = cfs->get_u2_fast();
// Check version numbers - we check this even with verifier off
if (!is_supported_version(major_version, minor_version)) {
if (name == NULL) {
Exceptions::fthrow(
THREAD_AND_LOCATION,
vmSymbols::java_lang_UnsupportedClassVersionError(),
"Unsupported major.minor version %u.%u",
major_version,
minor_version);
} else {
real_offset = next_nonstatic_word_offset;
next_nonstatic_word_offset += BytesPerInt;
}
break;
case NONSTATIC_DOUBLE:
real_offset = next_nonstatic_double_offset;
next_nonstatic_double_offset += BytesPerLong;
break;
default:
ShouldNotReachHere();
ResourceMark rm(THREAD);
Exceptions::fthrow(
THREAD_AND_LOCATION,
vmSymbols::java_lang_UnsupportedClassVersionError(),
"%s : Unsupported major.minor version %u.%u",
name->as_C_string(),
major_version,
minor_version);
}
fs.set_offset(real_offset);
return nullHandle;
}
_major_version = major_version;
_minor_version = minor_version;
// 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;
// Check if verification needs to be relaxed for this class file
// Do not restrict it to jdk1.0 or jdk1.1 to maintain backward compatibility (4982376)
_relax_verify = Verifier::relax_verify_for(class_loader());
// Constant pool
constantPoolHandle cp = parse_constant_pool(CHECK_(nullHandle));
int cp_size = cp->length();
cfs->guarantee_more(8, CHECK_(nullHandle)); // flags, this_class, super_class, infs_len
// Access flags
AccessFlags access_flags;
jint flags = cfs->get_u2_fast() & JVM_RECOGNIZED_CLASS_MODIFIERS;
if ((flags & JVM_ACC_INTERFACE) && _major_version < JAVA_6_VERSION) {
// Set abstract bit for old class files for backward compatibility
flags |= JVM_ACC_ABSTRACT;
}
verify_legal_class_modifiers(flags, CHECK_(nullHandle));
access_flags.set_flags(flags);
// 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;
// This class and superclass
u2 this_class_index = cfs->get_u2_fast();
check_property(
valid_cp_range(this_class_index, cp_size) &&
cp->tag_at(this_class_index).is_unresolved_klass(),
"Invalid this class index %u in constant pool in class file %s",
this_class_index, CHECK_(nullHandle));
if (fs.is_contended()) {
bm.set_bit(fs.contended_group());
}
}
Symbol* class_name = cp->unresolved_klass_at(this_class_index);
assert(class_name != NULL, "class_name can't be null");
int current_group = -1;
while ((current_group = (int)bm.get_next_one_offset(current_group + 1)) != (int)bm.size()) {
// It's important to set parsed_name *before* resolving the super class.
// (it's used for cleanup by the caller if parsing fails)
parsed_name = class_name;
// parsed_name is returned and can be used if there's an error, so add to
// its reference count. Caller will decrement the refcount.
parsed_name->increment_refcount();
for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) {
// Update _class_name which could be null previously to be class_name
_class_name = class_name;
// skip already laid out fields
if (fs.is_offset_set()) continue;
// Don't need to check whether this class name is legal or not.
// It has been checked when constant pool is parsed.
// However, make sure it is not an array type.
if (_need_verify) {
guarantee_property(class_name->byte_at(0) != JVM_SIGNATURE_ARRAY,
"Bad class name in class file %s",
CHECK_(nullHandle));
}
// skip non-contended fields and fields from different group
if (!fs.is_contended() || (fs.contended_group() != current_group)) continue;
Klass* preserve_this_klass; // for storing result across HandleMark
// handle statics below
if (fs.access_flags().is_static()) continue;
// release all handles when parsing is done
{ HandleMark hm(THREAD);
int real_offset;
FieldAllocationType atype = (FieldAllocationType) fs.allocation_type();
// Checks if name in class file matches requested name
if (name != NULL && class_name != name) {
ResourceMark rm(THREAD);
Exceptions::fthrow(
THREAD_AND_LOCATION,
vmSymbols::java_lang_NoClassDefFoundError(),
"%s (wrong name: %s)",
name->as_C_string(),
class_name->as_C_string()
);
return nullHandle;
}
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;
if (TraceClassLoadingPreorder) {
tty->print("[Loading %s", name->as_klass_external_name());
if (cfs->source() != NULL) tty->print(" from %s", cfs->source());
tty->print_cr("]");
}
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;
u2 super_class_index = cfs->get_u2_fast();
instanceKlassHandle super_klass = parse_super_class(super_class_index,
CHECK_NULL);
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;
// Interfaces
u2 itfs_len = cfs->get_u2_fast();
Array<Klass*>* local_interfaces =
parse_interfaces(itfs_len, protection_domain, _class_name,
&has_default_methods, CHECK_(nullHandle));
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;
u2 java_fields_count = 0;
// Fields (offsets are filled in later)
FieldAllocationCount fac;
Array<u2>* fields = parse_fields(class_name,
access_flags.is_interface(),
&fac, &java_fields_count,
CHECK_(nullHandle));
// Methods
bool has_final_method = false;
AccessFlags promoted_flags;
promoted_flags.set_flags(0);
Array<Method*>* methods = parse_methods(access_flags.is_interface(),
&promoted_flags,
&has_final_method,
&has_default_methods,
CHECK_(nullHandle));
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;
// Additional attributes
ClassAnnotationCollector parsed_annotations;
parse_classfile_attributes(&parsed_annotations, CHECK_(nullHandle));
// 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;
// Make sure this is the end of class file stream
guarantee_property(cfs->at_eos(), "Extra bytes at the end of class file %s", CHECK_(nullHandle));
default:
ShouldNotReachHere();
// We check super class after class file is parsed and format is checked
if (super_class_index > 0 && super_klass.is_null()) {
Symbol* sk = cp->klass_name_at(super_class_index);
if (access_flags.is_interface()) {
// Before attempting to resolve the superclass, check for class format
// errors not checked yet.
guarantee_property(sk == vmSymbols::java_lang_Object(),
"Interfaces must have java.lang.Object as superclass in class file %s",
CHECK_(nullHandle));
}
Klass* k = SystemDictionary::resolve_super_or_fail(class_name, sk,
class_loader,
protection_domain,
true,
CHECK_(nullHandle));
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;
KlassHandle kh (THREAD, k);
super_klass = instanceKlassHandle(THREAD, kh());
}
if (super_klass.not_null()) {
fs.set_offset(real_offset);
} // for
if (super_klass->has_default_methods()) {
has_default_methods = true;
}
// 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;
if (super_klass->is_interface()) {
ResourceMark rm(THREAD);
Exceptions::fthrow(
THREAD_AND_LOCATION,
vmSymbols::java_lang_IncompatibleClassChangeError(),
"class %s has interface %s as super class",
class_name->as_klass_external_name(),
super_klass->external_name()
);
return nullHandle;
}
// Make sure super class is not final
if (super_klass->is_final()) {
THROW_MSG_(vmSymbols::java_lang_VerifyError(), "Cannot inherit from final class", nullHandle);
}
}
// handle static fields
// save super klass for error handling.
_super_klass = super_klass;
} // handle contended
// Compute the transitive list of all unique interfaces implemented by this class
_transitive_interfaces =
compute_transitive_interfaces(super_klass, local_interfaces, CHECK_(nullHandle));
// Size of instances
int instance_size;
// sort methods
intArray* method_ordering = sort_methods(methods);
int notaligned_offset = next_nonstatic_padded_offset;
// promote flags from parse_methods() to the klass' flags
access_flags.add_promoted_flags(promoted_flags.as_int());
// 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;
}
// Size of Java vtable (in words)
int vtable_size = 0;
int itable_size = 0;
int num_miranda_methods = 0;
int next_static_type_offset = align_size_up(next_static_byte_offset, wordSize);
int static_field_size = (next_static_type_offset -
InstanceMirrorKlass::offset_of_static_fields()) / wordSize;
GrowableArray<Method*> all_mirandas(20);
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);
klassVtable::compute_vtable_size_and_num_mirandas(
&vtable_size, &num_miranda_methods, &all_mirandas, super_klass(), methods,
access_flags, class_loader, class_name, local_interfaces,
CHECK_(nullHandle));
next_nonstatic_type_offset = align_size_up(notaligned_offset, wordSize );
instance_size = align_object_size(next_nonstatic_type_offset / wordSize);
// Size of Java itable (in words)
itable_size = access_flags.is_interface() ? 0 : klassItable::compute_itable_size(_transitive_interfaces);
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");
FieldLayoutInfo info;
layout_fields(class_loader, &fac, &parsed_annotations, &info, CHECK_NULL);
int total_oop_map_size2 =
InstanceKlass::nonstatic_oop_map_size(info.total_oop_map_count);
// Number of non-static oop map blocks allocated at end of klass.
const unsigned int total_oop_map_count =
compute_oop_map_count(super_klass, nonstatic_oop_map_count,
first_nonstatic_oop_offset);
// Compute reference type
ReferenceType rt;
if (super_klass() == NULL) {
......@@ -3974,13 +3958,10 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
}
// We can now create the basic Klass* for this klass
int total_oop_map_size2 =
InstanceKlass::nonstatic_oop_map_size(total_oop_map_count);
Klass* ik = InstanceKlass::allocate_instance_klass(loader_data,
_klass = InstanceKlass::allocate_instance_klass(loader_data,
vtable_size,
itable_size,
static_field_size,
info.static_field_size,
total_oop_map_size2,
rt,
access_flags,
......@@ -3988,39 +3969,31 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
super_klass(),
!host_klass.is_null(),
CHECK_(nullHandle));
instanceKlassHandle this_klass (THREAD, _klass);
// Add all classes to our internal class loader list here,
// including classes in the bootstrap (NULL) class loader.
loader_data->add_class(ik);
instanceKlassHandle this_klass (THREAD, ik);
assert(this_klass->static_field_size() == static_field_size, "sanity");
assert(this_klass->nonstatic_oop_map_count() == total_oop_map_count,
assert(this_klass->static_field_size() == info.static_field_size, "sanity");
assert(this_klass->nonstatic_oop_map_count() == info.total_oop_map_count,
"sanity");
// Fill in information already parsed
this_klass->set_should_verify_class(verify);
jint lh = Klass::instance_layout_helper(instance_size, false);
jint lh = Klass::instance_layout_helper(info.instance_size, false);
this_klass->set_layout_helper(lh);
assert(this_klass->oop_is_instance(), "layout is correct");
assert(this_klass->size_helper() == instance_size, "correct size_helper");
assert(this_klass->size_helper() == info.instance_size, "correct size_helper");
// Not yet: supers are done below to support the new subtype-checking fields
//this_klass->set_super(super_klass());
this_klass->set_class_loader_data(loader_data);
this_klass->set_nonstatic_field_size(nonstatic_field_size);
this_klass->set_has_nonstatic_fields(has_nonstatic_fields);
this_klass->set_nonstatic_field_size(info.nonstatic_field_size);
this_klass->set_has_nonstatic_fields(info.has_nonstatic_fields);
this_klass->set_static_oop_field_count(fac.count[STATIC_OOP]);
cp->set_pool_holder(this_klass());
error_handler.set_in_error(false); // turn off error handler for cp
this_klass->set_constants(cp());
this_klass->set_local_interfaces(local_interfaces);
this_klass->set_fields(fields, java_fields_count);
this_klass->set_methods(methods);
apply_parsed_class_metadata(this_klass, java_fields_count, CHECK_NULL);
if (has_final_method) {
this_klass->set_has_final_method();
}
this_klass->set_method_ordering(method_ordering);
this_klass->copy_method_ordering(method_ordering, CHECK_NULL);
// The InstanceKlass::_methods_jmethod_ids cache and the
// InstanceKlass::_methods_cached_itable_indices cache are
// both managed on the assumption that the initial cache
......@@ -4032,17 +4005,6 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
if (is_anonymous()) // I am well known to myself
cp->klass_at_put(this_class_index, this_klass()); // eagerly resolve
// Assign allocations if needed
if (_annotations != NULL || _type_annotations != NULL ||
fields_annotations != NULL || fields_type_annotations != NULL) {
Annotations* annotations = Annotations::allocate(loader_data, CHECK_NULL);
annotations->set_class_annotations(_annotations);
annotations->set_class_type_annotations(_type_annotations);
annotations->set_fields_annotations(fields_annotations);
annotations->set_fields_type_annotations(fields_type_annotations);
this_klass->set_annotations(annotations);
}
this_klass->set_minor_version(minor_version);
this_klass->set_major_version(major_version);
this_klass->set_has_default_methods(has_default_methods);
......@@ -4077,8 +4039,6 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
this_klass->set_has_miranda_methods(); // then set a flag
}
this_klass->set_transitive_interfaces(transitive_interfaces);
// Fill in information needed to compute superclasses.
this_klass->initialize_supers(super_klass(), CHECK_(nullHandle));
......@@ -4087,7 +4047,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
// Compute transitive closure of interfaces this class implements
// Do final class setup
fill_oop_maps(this_klass, nonstatic_oop_map_count, nonstatic_oop_offsets, nonstatic_oop_counts);
fill_oop_maps(this_klass, info.nonstatic_oop_map_count, info.nonstatic_oop_offsets, info.nonstatic_oop_counts);
// Fill in has_finalizer, has_vanilla_constructor, and layout_helper
set_precomputed_flags(this_klass);
......@@ -4186,35 +4146,6 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
}
}
#ifndef PRODUCT
if( PrintCompactFieldsSavings ) {
ResourceMark rm;
if( nonstatic_field_size < orig_nonstatic_field_size ) {
tty->print("[Saved %d of %d bytes in %s]\n",
(orig_nonstatic_field_size - nonstatic_field_size)*heapOopSize,
orig_nonstatic_field_size*heapOopSize,
this_klass->external_name());
} else if( nonstatic_field_size > orig_nonstatic_field_size ) {
tty->print("[Wasted %d over %d bytes in %s]\n",
(nonstatic_field_size - orig_nonstatic_field_size)*heapOopSize,
orig_nonstatic_field_size*heapOopSize,
this_klass->external_name());
}
}
#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_this_klass = this_klass();
}
......@@ -4224,9 +4155,40 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
instanceKlassHandle this_klass (THREAD, preserve_this_klass);
debug_only(this_klass->verify();)
// Clear class if no error has occurred so destructor doesn't deallocate it
_klass = NULL;
return this_klass;
}
// Destructor to clean up if there's an error
ClassFileParser::~ClassFileParser() {
MetadataFactory::free_metadata(_loader_data, _cp);
MetadataFactory::free_array<u2>(_loader_data, _fields);
// Free methods
InstanceKlass::deallocate_methods(_loader_data, _methods);
// beware of the Universe::empty_blah_array!!
if (_inner_classes != Universe::the_empty_short_array()) {
MetadataFactory::free_array<u2>(_loader_data, _inner_classes);
}
// Free interfaces
InstanceKlass::deallocate_interfaces(_loader_data, _super_klass(),
_local_interfaces, _transitive_interfaces);
MetadataFactory::free_array<u1>(_loader_data, _annotations);
MetadataFactory::free_array<u1>(_loader_data, _type_annotations);
Annotations::free_contents(_loader_data, _fields_annotations);
Annotations::free_contents(_loader_data, _fields_type_annotations);
clear_class_metadata();
// deallocate the klass if already created.
MetadataFactory::free_metadata(_loader_data, _klass);
_klass = NULL;
}
void ClassFileParser::print_field_layout(Symbol* name,
Array<u2>* fields,
constantPoolHandle cp,
......@@ -4418,7 +4380,7 @@ void ClassFileParser::record_defined_class_dependencies(instanceKlassHandle defi
}
}
// utility method for appending and array with check for duplicates
// utility methods for appending an array with check for duplicates
void append_interfaces(GrowableArray<Klass*>* result, Array<Klass*>* ifs) {
// iterate over new interfaces
......@@ -4430,8 +4392,9 @@ void append_interfaces(GrowableArray<Klass*>* result, Array<Klass*>* ifs) {
}
}
Array<Klass*>* ClassFileParser::compute_transitive_interfaces(ClassLoaderData* loader_data, instanceKlassHandle super, Array<Klass*>* local_ifs, TRAPS) {
Array<Klass*>* ClassFileParser::compute_transitive_interfaces(
instanceKlassHandle super,
Array<Klass*>* local_ifs, TRAPS) {
// Compute maximum size for transitive interfaces
int max_transitive_size = 0;
int super_size = 0;
......@@ -4478,7 +4441,7 @@ Array<Klass*>* ClassFileParser::compute_transitive_interfaces(ClassLoaderData* l
// length will be less than the max_transitive_size if duplicates were removed
int length = result->length();
assert(length <= max_transitive_size, "just checking");
Array<Klass*>* new_result = MetadataFactory::new_array<Klass*>(loader_data, length, CHECK_NULL);
Array<Klass*>* new_result = MetadataFactory::new_array<Klass*>(_loader_data, length, CHECK_NULL);
for (int i = 0; i < length; i++) {
Klass* e = result->at(i);
assert(e != NULL, "just checking");
......@@ -4488,7 +4451,6 @@ Array<Klass*>* ClassFileParser::compute_transitive_interfaces(ClassLoaderData* l
}
}
void ClassFileParser::check_super_class_access(instanceKlassHandle this_klass, TRAPS) {
Klass* super = this_klass->super();
if ((super != NULL) &&
......
......@@ -34,6 +34,7 @@
#include "classfile/symbolTable.hpp"
class FieldAllocationCount;
class FieldLayoutInfo;
// Parser for for .class files
......@@ -47,6 +48,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
u2 _major_version;
u2 _minor_version;
Symbol* _class_name;
ClassLoaderData* _loader_data;
KlassHandle _host_klass;
GrowableArray<Handle>* _cp_patches; // overrides for CP entries
......@@ -58,33 +60,59 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
// class attributes parsed before the instance klass is created:
bool _synthetic_flag;
int _sde_length;
char* _sde_buffer;
Symbol* _sourcefile;
Symbol* _generic_signature;
char* _sde_buffer;
int _sde_length;
// Metadata created before the instance klass is created. Must be deallocated
// if not transferred to the InstanceKlass upon successful class loading
// in which case these pointers have been set to NULL.
instanceKlassHandle _super_klass;
ConstantPool* _cp;
Array<u2>* _fields;
Array<Method*>* _methods;
Array<u2>* _inner_classes;
Array<Klass*>* _local_interfaces;
Array<Klass*>* _transitive_interfaces;
AnnotationArray* _annotations;
AnnotationArray* _type_annotations;
Array<AnnotationArray*>* _fields_annotations;
Array<AnnotationArray*>* _fields_type_annotations;
InstanceKlass* _klass; // InstanceKlass once created.
void set_class_synthetic_flag(bool x) { _synthetic_flag = x; }
void set_class_sourcefile(Symbol* x) { _sourcefile = x; }
void set_class_generic_signature(Symbol* x) { _generic_signature = x; }
void set_class_sde_buffer(char* x, int len) { _sde_buffer = x; _sde_length = len; }
void set_class_inner_classes(Array<u2>* x) { _inner_classes = x; }
void set_class_annotations(AnnotationArray* x) { _annotations = x; }
void set_class_type_annotations(AnnotationArray* x) { _type_annotations = x; }
void init_parsed_class_attributes() {
void init_parsed_class_attributes(ClassLoaderData* loader_data) {
_loader_data = loader_data;
_synthetic_flag = false;
_sourcefile = NULL;
_generic_signature = NULL;
_sde_buffer = NULL;
_sde_length = 0;
_annotations = _type_annotations = NULL;
// initialize the other flags too:
_has_finalizer = _has_empty_finalizer = _has_vanilla_constructor = false;
_max_bootstrap_specifier_index = -1;
clear_class_metadata();
_klass = NULL;
}
void apply_parsed_class_attributes(instanceKlassHandle k); // update k
void apply_parsed_class_metadata(instanceKlassHandle k, int fields_count, TRAPS);
void clear_class_metadata() {
// metadata created before the instance klass is created. Must be
// deallocated if classfile parsing returns an error.
_cp = NULL;
_fields = NULL;
_methods = NULL;
_inner_classes = NULL;
_local_interfaces = NULL;
_transitive_interfaces = NULL;
_annotations = _type_annotations = NULL;
_fields_annotations = _fields_type_annotations = NULL;
}
class AnnotationCollector {
public:
......@@ -124,11 +152,27 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
void set_contended(bool contended) { set_annotation(_sun_misc_Contended); }
bool is_contended() { return has_annotation(_sun_misc_Contended); }
};
// This class also doubles as a holder for metadata cleanup.
class FieldAnnotationCollector: public AnnotationCollector {
ClassLoaderData* _loader_data;
AnnotationArray* _field_annotations;
AnnotationArray* _field_type_annotations;
public:
FieldAnnotationCollector() : AnnotationCollector(_in_field) { }
FieldAnnotationCollector(ClassLoaderData* loader_data) :
AnnotationCollector(_in_field),
_loader_data(loader_data),
_field_annotations(NULL),
_field_type_annotations(NULL) {}
void apply_to(FieldInfo* f);
~FieldAnnotationCollector();
AnnotationArray* field_annotations() { return _field_annotations; }
AnnotationArray* field_type_annotations() { return _field_type_annotations; }
void set_field_annotations(AnnotationArray* a) { _field_annotations = a; }
void set_field_type_annotations(AnnotationArray* a) { _field_type_annotations = a; }
};
class MethodAnnotationCollector: public AnnotationCollector {
public:
MethodAnnotationCollector() : AnnotationCollector(_in_method) { }
......@@ -152,38 +196,30 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
void set_stream(ClassFileStream* st) { _stream = st; }
// Constant pool parsing
void parse_constant_pool_entries(ClassLoaderData* loader_data,
constantPoolHandle cp, int length, TRAPS);
void parse_constant_pool_entries(int length, TRAPS);
constantPoolHandle parse_constant_pool(ClassLoaderData* loader_data, TRAPS);
constantPoolHandle parse_constant_pool(TRAPS);
// Interface parsing
Array<Klass*>* parse_interfaces(constantPoolHandle cp,
int length,
ClassLoaderData* loader_data,
Array<Klass*>* parse_interfaces(int length,
Handle protection_domain,
Symbol* class_name,
bool* has_default_methods,
TRAPS);
void record_defined_class_dependencies(instanceKlassHandle defined_klass, TRAPS);
instanceKlassHandle parse_super_class(int super_class_index, TRAPS);
// Field parsing
void parse_field_attributes(ClassLoaderData* loader_data,
constantPoolHandle cp, u2 attributes_count,
void parse_field_attributes(u2 attributes_count,
bool is_static, u2 signature_index,
u2* constantvalue_index_addr,
bool* is_synthetic_addr,
u2* generic_signature_index_addr,
AnnotationArray** field_annotations,
AnnotationArray** field_type_annotations,
FieldAnnotationCollector* parsed_annotations,
TRAPS);
Array<u2>* parse_fields(ClassLoaderData* loader_data,
Symbol* class_name,
constantPoolHandle cp, bool is_interface,
Array<u2>* parse_fields(Symbol* class_name,
bool is_interface,
FieldAllocationCount *fac,
Array<AnnotationArray*>** fields_annotations,
Array<AnnotationArray*>** fields_type_annotations,
u2* java_fields_count_ptr, TRAPS);
void print_field_layout(Symbol* name,
......@@ -195,65 +231,52 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
int static_fields_end);
// Method parsing
methodHandle parse_method(ClassLoaderData* loader_data,
constantPoolHandle cp,
bool is_interface,
methodHandle parse_method(bool is_interface,
AccessFlags* promoted_flags,
TRAPS);
Array<Method*>* parse_methods(ClassLoaderData* loader_data,
constantPoolHandle cp,
bool is_interface,
Array<Method*>* parse_methods(bool is_interface,
AccessFlags* promoted_flags,
bool* has_final_method,
bool* has_default_method,
TRAPS);
Array<int>* sort_methods(ClassLoaderData* loader_data,
Array<Method*>* methods,
intArray* sort_methods(Array<Method*>* methods);
u2* parse_exception_table(u4 code_length, u4 exception_table_length,
TRAPS);
u2* parse_exception_table(ClassLoaderData* loader_data,
u4 code_length, u4 exception_table_length,
constantPoolHandle cp, TRAPS);
void parse_linenumber_table(
u4 code_attribute_length, u4 code_length,
CompressedLineNumberWriteStream** write_stream, TRAPS);
u2* parse_localvariable_table(u4 code_length, u2 max_locals, u4 code_attribute_length,
constantPoolHandle cp, u2* localvariable_table_length,
u2* localvariable_table_length,
bool isLVTT, TRAPS);
u2* parse_checked_exceptions(u2* checked_exceptions_length, u4 method_attribute_length,
constantPoolHandle cp, TRAPS);
TRAPS);
void parse_type_array(u2 array_length, u4 code_length, u4* u1_index, u4* u2_index,
u1* u1_array, u2* u2_array, constantPoolHandle cp, TRAPS);
Array<u1>* parse_stackmap_table(ClassLoaderData* loader_data, u4 code_attribute_length, TRAPS);
u1* u1_array, u2* u2_array, TRAPS);
u1* parse_stackmap_table(u4 code_attribute_length, TRAPS);
// Classfile attribute parsing
void parse_classfile_sourcefile_attribute(constantPoolHandle cp, TRAPS);
void parse_classfile_source_debug_extension_attribute(constantPoolHandle cp,
int length, TRAPS);
u2 parse_classfile_inner_classes_attribute(ClassLoaderData* loader_data,
u1* inner_classes_attribute_start,
void parse_classfile_sourcefile_attribute(TRAPS);
void parse_classfile_source_debug_extension_attribute(int length, TRAPS);
u2 parse_classfile_inner_classes_attribute(u1* inner_classes_attribute_start,
bool parsed_enclosingmethod_attribute,
u2 enclosing_method_class_index,
u2 enclosing_method_method_index,
constantPoolHandle cp,
TRAPS);
void parse_classfile_attributes(ClassLoaderData* loader_data,
constantPoolHandle cp,
ClassAnnotationCollector* parsed_annotations,
void parse_classfile_attributes(ClassAnnotationCollector* parsed_annotations,
TRAPS);
void parse_classfile_synthetic_attribute(constantPoolHandle cp, TRAPS);
void parse_classfile_signature_attribute(constantPoolHandle cp, TRAPS);
void parse_classfile_bootstrap_methods_attribute(ClassLoaderData* loader_data, constantPoolHandle cp, u4 attribute_length, TRAPS);
void parse_classfile_synthetic_attribute(TRAPS);
void parse_classfile_signature_attribute(TRAPS);
void parse_classfile_bootstrap_methods_attribute(u4 attribute_length, TRAPS);
// Annotations handling
AnnotationArray* assemble_annotations(ClassLoaderData* loader_data,
u1* runtime_visible_annotations,
AnnotationArray* assemble_annotations(u1* runtime_visible_annotations,
int runtime_visible_annotations_length,
u1* runtime_invisible_annotations,
int runtime_invisible_annotations_length, TRAPS);
int skip_annotation(u1* buffer, int limit, int index);
int skip_annotation_value(u1* buffer, int limit, int index);
void parse_annotations(ClassLoaderData* loader_data,
u1* buffer, int limit, constantPoolHandle cp,
void parse_annotations(u1* buffer, int limit,
/* Results (currently, only one result is supported): */
AnnotationCollector* result,
TRAPS);
......@@ -267,8 +290,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
int* nonstatic_oop_offsets,
unsigned int* nonstatic_oop_counts);
void set_precomputed_flags(instanceKlassHandle k);
Array<Klass*>* compute_transitive_interfaces(ClassLoaderData* loader_data,
instanceKlassHandle super,
Array<Klass*>* compute_transitive_interfaces(instanceKlassHandle super,
Array<Klass*>* local_ifs, TRAPS);
// Format checker methods
......@@ -318,7 +340,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
bool is_supported_version(u2 major, u2 minor);
bool has_illegal_visibility(jint flags);
void verify_constantvalue(int constantvalue_index, int signature_index, constantPoolHandle cp, TRAPS);
void verify_constantvalue(int constantvalue_index, int signature_index, TRAPS);
void verify_legal_utf8(const unsigned char* buffer, int length, TRAPS);
void verify_legal_class_name(Symbol* name, TRAPS);
void verify_legal_field_name(Symbol* name, TRAPS);
......@@ -359,10 +381,17 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
// In older versions of the VM, Klass*s cannot sneak into early phases of
// constant pool construction, but in later versions they can.
// %%% Let's phase out the old is_klass_reference.
bool is_klass_reference(constantPoolHandle cp, int index) {
return (EnableInvokeDynamic
? cp->tag_at(index).is_klass_or_reference()
: cp->tag_at(index).is_klass_reference());
bool valid_klass_reference_at(int index) {
return _cp->is_within_bounds(index) &&
(EnableInvokeDynamic
? _cp->tag_at(index).is_klass_or_reference()
: _cp->tag_at(index).is_klass_reference());
}
// Checks that the cpool index is in range and is a utf8
bool valid_symbol_at(int cpool_index) {
return (_cp->is_within_bounds(cpool_index) &&
_cp->tag_at(cpool_index).is_utf8());
}
void copy_localvariable_table(ConstMethod* cm, int lvt_cnt,
......@@ -373,8 +402,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
u2** localvariable_type_table_start,
TRAPS);
void copy_method_annotations(ClassLoaderData* loader_data,
ConstMethod* cm,
void copy_method_annotations(ConstMethod* cm,
u1* runtime_visible_annotations,
int runtime_visible_annotations_length,
u1* runtime_invisible_annotations,
......@@ -391,9 +419,15 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
int annotation_default_length,
TRAPS);
// lays out fields in class and returns the total oopmap count
void layout_fields(Handle class_loader, FieldAllocationCount* fac,
ClassAnnotationCollector* parsed_annotations,
FieldLayoutInfo* info, TRAPS);
public:
// Constructor
ClassFileParser(ClassFileStream* st) { set_stream(st); }
~ClassFileParser();
// Parse .class file and return new Klass*. The Klass* is not hooked up
// to the system dictionary or any other structures, so a .class file can
......
......@@ -67,6 +67,12 @@ ConstMethod::ConstMethod(int byte_code_size,
set_size_of_parameters(0);
}
// Accessor that copies to metadata.
void ConstMethod::copy_stackmap_data(ClassLoaderData* loader_data,
u1* sd, int length, TRAPS) {
_stackmap_data = MetadataFactory::new_array<u1>(loader_data, length, CHECK);
memcpy((void*)_stackmap_data->adr_at(0), (void*)sd, length);
}
// Deallocate metadata fields associated with ConstMethod*
void ConstMethod::deallocate_contents(ClassLoaderData* loader_data) {
......
......@@ -280,6 +280,7 @@ public:
// stackmap table data
Array<u1>* stackmap_data() const { return _stackmap_data; }
void set_stackmap_data(Array<u1>* sd) { _stackmap_data = sd; }
void copy_stackmap_data(ClassLoaderData* loader_data, u1* sd, int length, TRAPS);
bool has_stackmap_table() const { return _stackmap_data != NULL; }
void init_fingerprint() {
......
......@@ -165,7 +165,8 @@ HS_DTRACE_PROBE_DECL5(hotspot, class__initialization__end,
volatile int InstanceKlass::_total_instanceKlass_count = 0;
Klass* InstanceKlass::allocate_instance_klass(ClassLoaderData* loader_data,
InstanceKlass* InstanceKlass::allocate_instance_klass(
ClassLoaderData* loader_data,
int vtable_len,
int itable_len,
int static_field_size,
......@@ -207,10 +208,35 @@ Klass* InstanceKlass::allocate_instance_klass(ClassLoaderData* loader_data,
access_flags, is_anonymous);
}
// Check for pending exception before adding to the loader data and incrementing
// class count. Can get OOM here.
if (HAS_PENDING_EXCEPTION) {
return NULL;
}
// Add all classes to our internal class loader list here,
// including classes in the bootstrap (NULL) class loader.
loader_data->add_class(ik);
Atomic::inc(&_total_instanceKlass_count);
return ik;
}
// copy method ordering from resource area to Metaspace
void InstanceKlass::copy_method_ordering(intArray* m, TRAPS) {
if (m != NULL) {
// allocate a new array and copy contents (memcpy?)
_method_ordering = MetadataFactory::new_array<int>(class_loader_data(), m->length(), CHECK);
for (int i = 0; i < m->length(); i++) {
_method_ordering->at_put(i, m->at(i));
}
} else {
_method_ordering = Universe::the_empty_int_array();
}
}
InstanceKlass::InstanceKlass(int vtable_len,
int itable_len,
int static_field_size,
......@@ -223,9 +249,6 @@ InstanceKlass::InstanceKlass(int vtable_len,
int iksize = InstanceKlass::size(vtable_len, itable_len, nonstatic_oop_map_size,
access_flags.is_interface(), is_anonymous);
// The sizes of these these three variables are used for determining the
// size of the instanceKlassOop. It is critical that these are set to the right
// sizes before the first GC, i.e., when we allocate the mirror.
set_vtable_length(vtable_len);
set_itable_length(itable_len);
set_static_field_size(static_field_size);
......@@ -288,12 +311,51 @@ InstanceKlass::InstanceKlass(int vtable_len,
}
void InstanceKlass::deallocate_methods(ClassLoaderData* loader_data,
Array<Method*>* methods) {
if (methods != NULL && methods != Universe::the_empty_method_array()) {
for (int i = 0; i < methods->length(); i++) {
Method* method = methods->at(i);
if (method == NULL) continue; // maybe null if error processing
// Only want to delete methods that are not executing for RedefineClasses.
// The previous version will point to them so they're not totally dangling
assert (!method->on_stack(), "shouldn't be called with methods on stack");
MetadataFactory::free_metadata(loader_data, method);
}
MetadataFactory::free_array<Method*>(loader_data, methods);
}
}
void InstanceKlass::deallocate_interfaces(ClassLoaderData* loader_data,
Klass* super_klass,
Array<Klass*>* local_interfaces,
Array<Klass*>* transitive_interfaces) {
// Only deallocate transitive interfaces if not empty, same as super class
// or same as local interfaces. See code in parseClassFile.
Array<Klass*>* ti = transitive_interfaces;
if (ti != Universe::the_empty_klass_array() && ti != local_interfaces) {
// check that the interfaces don't come from super class
Array<Klass*>* sti = (super_klass == NULL) ? NULL :
InstanceKlass::cast(super_klass)->transitive_interfaces();
if (ti != sti) {
MetadataFactory::free_array<Klass*>(loader_data, ti);
}
}
// local interfaces can be empty
if (local_interfaces != Universe::the_empty_klass_array()) {
MetadataFactory::free_array<Klass*>(loader_data, local_interfaces);
}
}
// This function deallocates the metadata and C heap pointers that the
// InstanceKlass points to.
void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) {
// Orphan the mirror first, CMS thinks it's still live.
if (java_mirror() != NULL) {
java_lang_Class::set_klass(java_mirror(), NULL);
}
// Need to take this class off the class loader data list.
loader_data->remove_class(this);
......@@ -308,17 +370,7 @@ void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) {
// reference counting symbol names.
release_C_heap_structures();
Array<Method*>* ms = methods();
if (ms != Universe::the_empty_method_array()) {
for (int i = 0; i <= methods()->length() -1 ; i++) {
Method* method = methods()->at(i);
// Only want to delete methods that are not executing for RedefineClasses.
// The previous version will point to them so they're not totally dangling
assert (!method->on_stack(), "shouldn't be called with methods on stack");
MetadataFactory::free_metadata(loader_data, method);
}
MetadataFactory::free_array<Method*>(loader_data, methods());
}
deallocate_methods(loader_data, methods());
set_methods(NULL);
if (method_ordering() != Universe::the_empty_int_array()) {
......@@ -335,24 +387,8 @@ void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) {
}
set_secondary_supers(NULL);
// Only deallocate transitive interfaces if not empty, same as super class
// or same as local interfaces. See code in parseClassFile.
Array<Klass*>* ti = transitive_interfaces();
if (ti != Universe::the_empty_klass_array() && ti != local_interfaces()) {
// check that the interfaces don't come from super class
Array<Klass*>* sti = (super() == NULL) ? NULL :
InstanceKlass::cast(super())->transitive_interfaces();
if (ti != sti) {
MetadataFactory::free_array<Klass*>(loader_data, ti);
}
}
deallocate_interfaces(loader_data, super(), local_interfaces(), transitive_interfaces());
set_transitive_interfaces(NULL);
// local interfaces can be empty
Array<Klass*>* li = local_interfaces();
if (li != Universe::the_empty_klass_array()) {
MetadataFactory::free_array<Klass*>(loader_data, li);
}
set_local_interfaces(NULL);
MetadataFactory::free_array<jushort>(loader_data, fields());
......@@ -360,9 +396,11 @@ void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) {
// If a method from a redefined class is using this constant pool, don't
// delete it, yet. The new class's previous version will point to this.
if (constants() != NULL) {
assert (!constants()->on_stack(), "shouldn't be called if anything is onstack");
MetadataFactory::free_metadata(loader_data, constants());
set_constants(NULL);
}
if (inner_classes() != Universe::the_empty_short_array()) {
MetadataFactory::free_array<jushort>(loader_data, inner_classes());
......
......@@ -147,7 +147,8 @@ class InstanceKlass: public Klass {
AccessFlags access_flags,
bool is_anonymous);
public:
static Klass* allocate_instance_klass(ClassLoaderData* loader_data,
static InstanceKlass* allocate_instance_klass(
ClassLoaderData* loader_data,
int vtable_len,
int itable_len,
int static_field_size,
......@@ -266,7 +267,6 @@ class InstanceKlass: public Klass {
u1 _init_state; // state of class
u1 _reference_type; // reference type
JvmtiCachedClassFieldMap* _jvmti_cached_class_field_map; // JVMTI: used during heap iteration
NOT_PRODUCT(int _verify_count;) // to avoid redundant verifies
......@@ -358,16 +358,19 @@ class InstanceKlass: public Klass {
// method ordering
Array<int>* method_ordering() const { return _method_ordering; }
void set_method_ordering(Array<int>* m) { _method_ordering = m; }
void copy_method_ordering(intArray* m, TRAPS);
// interfaces
Array<Klass*>* local_interfaces() const { return _local_interfaces; }
void set_local_interfaces(Array<Klass*>* a) {
guarantee(_local_interfaces == NULL || a == NULL, "Just checking");
_local_interfaces = a; }
Array<Klass*>* transitive_interfaces() const { return _transitive_interfaces; }
void set_transitive_interfaces(Array<Klass*>* a) {
guarantee(_transitive_interfaces == NULL || a == NULL, "Just checking");
_transitive_interfaces = a; }
_transitive_interfaces = a;
}
private:
friend class fieldDescriptor;
......@@ -383,7 +386,6 @@ class InstanceKlass: public Klass {
int java_fields_count() const { return (int)_java_fields_count; }
Array<u2>* fields() const { return _fields; }
void set_fields(Array<u2>* f, u2 java_fields_count) {
guarantee(_fields == NULL || f == NULL, "Just checking");
_fields = f;
......@@ -916,8 +918,15 @@ class InstanceKlass: public Klass {
void clean_method_data(BoolObjectClosure* is_alive);
// Explicit metaspace deallocation of fields
// For RedefineClasses, we need to deallocate instanceKlasses
// For RedefineClasses and class file parsing errors, we need to deallocate
// instanceKlasses and the metadata they point to.
void deallocate_contents(ClassLoaderData* loader_data);
static void deallocate_methods(ClassLoaderData* loader_data,
Array<Method*>* methods);
void static deallocate_interfaces(ClassLoaderData* loader_data,
Klass* super_klass,
Array<Klass*>* local_interfaces,
Array<Klass*>* transitive_interfaces);
// The constant pool is on stack if any of the methods are executing or
// referenced by handles.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册