提交 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 @@ ...@@ -90,8 +90,7 @@
// Extension method support. // Extension method support.
#define JAVA_8_VERSION 52 #define JAVA_8_VERSION 52
void ClassFileParser::parse_constant_pool_entries(int length, TRAPS) {
void ClassFileParser::parse_constant_pool_entries(ClassLoaderData* loader_data, constantPoolHandle cp, int length, TRAPS) {
// Use a local copy of ClassFileStream. It helps the C++ compiler to optimize // Use a local copy of ClassFileStream. It helps the C++ compiler to optimize
// this function (_current can be allocated in a register, with scalar // this function (_current can be allocated in a register, with scalar
// replacement of aggregates). The _current pointer is copied back to // replacement of aggregates). The _current pointer is copied back to
...@@ -104,7 +103,7 @@ void ClassFileParser::parse_constant_pool_entries(ClassLoaderData* loader_data, ...@@ -104,7 +103,7 @@ void ClassFileParser::parse_constant_pool_entries(ClassLoaderData* loader_data,
assert(cfs->allocated_on_stack(),"should be local"); assert(cfs->allocated_on_stack(),"should be local");
u1* old_current = cfs0->current(); u1* old_current = cfs0->current();
#endif #endif
Handle class_loader(THREAD, loader_data->class_loader()); Handle class_loader(THREAD, _loader_data->class_loader());
// Used for batching symbol allocations. // Used for batching symbol allocations.
const char* names[SymbolTable::symbol_alloc_batch_size]; const char* names[SymbolTable::symbol_alloc_batch_size];
...@@ -124,7 +123,7 @@ void ClassFileParser::parse_constant_pool_entries(ClassLoaderData* loader_data, ...@@ -124,7 +123,7 @@ void ClassFileParser::parse_constant_pool_entries(ClassLoaderData* loader_data,
{ {
cfs->guarantee_more(3, CHECK); // name_index, tag/access_flags cfs->guarantee_more(3, CHECK); // name_index, tag/access_flags
u2 name_index = cfs->get_u2_fast(); u2 name_index = cfs->get_u2_fast();
cp->klass_index_at_put(index, name_index); _cp->klass_index_at_put(index, name_index);
} }
break; break;
case JVM_CONSTANT_Fieldref : case JVM_CONSTANT_Fieldref :
...@@ -132,7 +131,7 @@ void ClassFileParser::parse_constant_pool_entries(ClassLoaderData* loader_data, ...@@ -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 cfs->guarantee_more(5, CHECK); // class_index, name_and_type_index, tag/access_flags
u2 class_index = cfs->get_u2_fast(); u2 class_index = cfs->get_u2_fast();
u2 name_and_type_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; break;
case JVM_CONSTANT_Methodref : case JVM_CONSTANT_Methodref :
...@@ -140,7 +139,7 @@ void ClassFileParser::parse_constant_pool_entries(ClassLoaderData* loader_data, ...@@ -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 cfs->guarantee_more(5, CHECK); // class_index, name_and_type_index, tag/access_flags
u2 class_index = cfs->get_u2_fast(); u2 class_index = cfs->get_u2_fast();
u2 name_and_type_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; break;
case JVM_CONSTANT_InterfaceMethodref : case JVM_CONSTANT_InterfaceMethodref :
...@@ -148,14 +147,14 @@ void ClassFileParser::parse_constant_pool_entries(ClassLoaderData* loader_data, ...@@ -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 cfs->guarantee_more(5, CHECK); // class_index, name_and_type_index, tag/access_flags
u2 class_index = cfs->get_u2_fast(); u2 class_index = cfs->get_u2_fast();
u2 name_and_type_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; break;
case JVM_CONSTANT_String : case JVM_CONSTANT_String :
{ {
cfs->guarantee_more(3, CHECK); // string_index, tag/access_flags cfs->guarantee_more(3, CHECK); // string_index, tag/access_flags
u2 string_index = cfs->get_u2_fast(); u2 string_index = cfs->get_u2_fast();
cp->string_index_at_put(index, string_index); _cp->string_index_at_put(index, string_index);
} }
break; break;
case JVM_CONSTANT_MethodHandle : case JVM_CONSTANT_MethodHandle :
...@@ -174,11 +173,11 @@ void ClassFileParser::parse_constant_pool_entries(ClassLoaderData* loader_data, ...@@ -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 cfs->guarantee_more(4, CHECK); // ref_kind, method_index, tag/access_flags
u1 ref_kind = cfs->get_u1_fast(); u1 ref_kind = cfs->get_u1_fast();
u2 method_index = cfs->get_u2_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) { } else if (tag == JVM_CONSTANT_MethodType) {
cfs->guarantee_more(3, CHECK); // signature_index, tag/access_flags cfs->guarantee_more(3, CHECK); // signature_index, tag/access_flags
u2 signature_index = cfs->get_u2_fast(); 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 { } else {
ShouldNotReachHere(); ShouldNotReachHere();
} }
...@@ -200,21 +199,21 @@ void ClassFileParser::parse_constant_pool_entries(ClassLoaderData* loader_data, ...@@ -200,21 +199,21 @@ void ClassFileParser::parse_constant_pool_entries(ClassLoaderData* loader_data,
u2 name_and_type_index = cfs->get_u2_fast(); u2 name_and_type_index = cfs->get_u2_fast();
if (_max_bootstrap_specifier_index < (int) bootstrap_specifier_index) if (_max_bootstrap_specifier_index < (int) bootstrap_specifier_index)
_max_bootstrap_specifier_index = (int) bootstrap_specifier_index; // collect for later _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; break;
case JVM_CONSTANT_Integer : case JVM_CONSTANT_Integer :
{ {
cfs->guarantee_more(5, CHECK); // bytes, tag/access_flags cfs->guarantee_more(5, CHECK); // bytes, tag/access_flags
u4 bytes = cfs->get_u4_fast(); u4 bytes = cfs->get_u4_fast();
cp->int_at_put(index, (jint) bytes); _cp->int_at_put(index, (jint) bytes);
} }
break; break;
case JVM_CONSTANT_Float : case JVM_CONSTANT_Float :
{ {
cfs->guarantee_more(5, CHECK); // bytes, tag/access_flags cfs->guarantee_more(5, CHECK); // bytes, tag/access_flags
u4 bytes = cfs->get_u4_fast(); u4 bytes = cfs->get_u4_fast();
cp->float_at_put(index, *(jfloat*)&bytes); _cp->float_at_put(index, *(jfloat*)&bytes);
} }
break; break;
case JVM_CONSTANT_Long : case JVM_CONSTANT_Long :
...@@ -225,7 +224,7 @@ void ClassFileParser::parse_constant_pool_entries(ClassLoaderData* loader_data, ...@@ -225,7 +224,7 @@ void ClassFileParser::parse_constant_pool_entries(ClassLoaderData* loader_data,
{ {
cfs->guarantee_more(9, CHECK); // bytes, tag/access_flags cfs->guarantee_more(9, CHECK); // bytes, tag/access_flags
u8 bytes = cfs->get_u8_fast(); 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 index++; // Skip entry following eigth-byte constant, see JVM book p. 98
break; break;
...@@ -237,7 +236,7 @@ void ClassFileParser::parse_constant_pool_entries(ClassLoaderData* loader_data, ...@@ -237,7 +236,7 @@ void ClassFileParser::parse_constant_pool_entries(ClassLoaderData* loader_data,
{ {
cfs->guarantee_more(9, CHECK); // bytes, tag/access_flags cfs->guarantee_more(9, CHECK); // bytes, tag/access_flags
u8 bytes = cfs->get_u8_fast(); 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 index++; // Skip entry following eigth-byte constant, see JVM book p. 98
break; break;
...@@ -246,7 +245,7 @@ void ClassFileParser::parse_constant_pool_entries(ClassLoaderData* loader_data, ...@@ -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 cfs->guarantee_more(5, CHECK); // name_index, signature_index, tag/access_flags
u2 name_index = cfs->get_u2_fast(); u2 name_index = cfs->get_u2_fast();
u2 signature_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; break;
case JVM_CONSTANT_Utf8 : case JVM_CONSTANT_Utf8 :
...@@ -283,11 +282,11 @@ void ClassFileParser::parse_constant_pool_entries(ClassLoaderData* loader_data, ...@@ -283,11 +282,11 @@ void ClassFileParser::parse_constant_pool_entries(ClassLoaderData* loader_data,
indices[names_count] = index; indices[names_count] = index;
hashValues[names_count++] = hash; hashValues[names_count++] = hash;
if (names_count == SymbolTable::symbol_alloc_batch_size) { 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; names_count = 0;
} }
} else { } else {
cp->symbol_at_put(index, result); _cp->symbol_at_put(index, result);
} }
} }
break; break;
...@@ -300,7 +299,7 @@ void ClassFileParser::parse_constant_pool_entries(ClassLoaderData* loader_data, ...@@ -300,7 +299,7 @@ void ClassFileParser::parse_constant_pool_entries(ClassLoaderData* loader_data,
// Allocate the remaining symbols // Allocate the remaining symbols
if (names_count > 0) { 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(). // Copy _current pointer of local copy back to stream().
...@@ -310,23 +309,6 @@ void ClassFileParser::parse_constant_pool_entries(ClassLoaderData* loader_data, ...@@ -310,23 +309,6 @@ void ClassFileParser::parse_constant_pool_entries(ClassLoaderData* loader_data,
cfs0->set_current(cfs1.current()); 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); } bool inline valid_cp_range(int index, int length) { return (index > 0 && index < length); }
inline Symbol* check_symbol_at(constantPoolHandle cp, int index) { inline Symbol* check_symbol_at(constantPoolHandle cp, int index) {
...@@ -336,7 +318,7 @@ inline Symbol* check_symbol_at(constantPoolHandle cp, int index) { ...@@ -336,7 +318,7 @@ inline Symbol* check_symbol_at(constantPoolHandle cp, int index) {
return NULL; return NULL;
} }
constantPoolHandle ClassFileParser::parse_constant_pool(ClassLoaderData* loader_data, TRAPS) { constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) {
ClassFileStream* cfs = stream(); ClassFileStream* cfs = stream();
constantPoolHandle nullHandle; constantPoolHandle nullHandle;
...@@ -345,16 +327,13 @@ constantPoolHandle ClassFileParser::parse_constant_pool(ClassLoaderData* loader_ ...@@ -345,16 +327,13 @@ constantPoolHandle ClassFileParser::parse_constant_pool(ClassLoaderData* loader_
guarantee_property( guarantee_property(
length >= 1, "Illegal constant pool size %u in class file %s", length >= 1, "Illegal constant pool size %u in class file %s",
length, CHECK_(nullHandle)); length, CHECK_(nullHandle));
ConstantPool* constant_pool = ConstantPool* constant_pool = ConstantPool::allocate(_loader_data, length,
ConstantPool::allocate(loader_data, CHECK_(nullHandle));
length, _cp = constant_pool; // save in case of errors
CHECK_(nullHandle));
constantPoolHandle cp (THREAD, constant_pool); constantPoolHandle cp (THREAD, constant_pool);
ConstantPoolCleaner cp_in_error(cp); // set constant pool to be cleaned up.
// parsing constant pool entries // 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 int index = 1; // declared outside of loops for portability
...@@ -373,8 +352,7 @@ constantPoolHandle ClassFileParser::parse_constant_pool(ClassLoaderData* loader_ ...@@ -373,8 +352,7 @@ constantPoolHandle ClassFileParser::parse_constant_pool(ClassLoaderData* loader_
if (!_need_verify) break; if (!_need_verify) break;
int klass_ref_index = cp->klass_ref_index_at(index); int klass_ref_index = cp->klass_ref_index_at(index);
int name_and_type_ref_index = cp->name_and_type_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) && check_property(valid_klass_reference_at(klass_ref_index),
is_klass_reference(cp, klass_ref_index),
"Invalid constant pool index %u in class file %s", "Invalid constant pool index %u in class file %s",
klass_ref_index, klass_ref_index,
CHECK_(nullHandle)); CHECK_(nullHandle));
...@@ -404,16 +382,12 @@ constantPoolHandle ClassFileParser::parse_constant_pool(ClassLoaderData* loader_ ...@@ -404,16 +382,12 @@ constantPoolHandle ClassFileParser::parse_constant_pool(ClassLoaderData* loader_
if (!_need_verify) break; if (!_need_verify) break;
int name_ref_index = cp->name_ref_index_at(index); int name_ref_index = cp->name_ref_index_at(index);
int signature_ref_index = cp->signature_ref_index_at(index); int signature_ref_index = cp->signature_ref_index_at(index);
check_property( check_property(valid_symbol_at(name_ref_index),
valid_cp_range(name_ref_index, length) && "Invalid constant pool index %u in class file %s",
cp->tag_at(name_ref_index).is_utf8(), name_ref_index, CHECK_(nullHandle));
"Invalid constant pool index %u in class file %s", check_property(valid_symbol_at(signature_ref_index),
name_ref_index, CHECK_(nullHandle)); "Invalid constant pool index %u in class file %s",
check_property( signature_ref_index, CHECK_(nullHandle));
valid_cp_range(signature_ref_index, length) &&
cp->tag_at(signature_ref_index).is_utf8(),
"Invalid constant pool index %u in class file %s",
signature_ref_index, CHECK_(nullHandle));
break; break;
} }
case JVM_CONSTANT_Utf8 : case JVM_CONSTANT_Utf8 :
...@@ -425,22 +399,18 @@ constantPoolHandle ClassFileParser::parse_constant_pool(ClassLoaderData* loader_ ...@@ -425,22 +399,18 @@ constantPoolHandle ClassFileParser::parse_constant_pool(ClassLoaderData* loader_
case JVM_CONSTANT_ClassIndex : case JVM_CONSTANT_ClassIndex :
{ {
int class_index = cp->klass_index_at(index); int class_index = cp->klass_index_at(index);
check_property( check_property(valid_symbol_at(class_index),
valid_cp_range(class_index, length) && "Invalid constant pool index %u in class file %s",
cp->tag_at(class_index).is_utf8(), class_index, CHECK_(nullHandle));
"Invalid constant pool index %u in class file %s",
class_index, CHECK_(nullHandle));
cp->unresolved_klass_at_put(index, cp->symbol_at(class_index)); cp->unresolved_klass_at_put(index, cp->symbol_at(class_index));
} }
break; break;
case JVM_CONSTANT_StringIndex : case JVM_CONSTANT_StringIndex :
{ {
int string_index = cp->string_index_at(index); int string_index = cp->string_index_at(index);
check_property( check_property(valid_symbol_at(string_index),
valid_cp_range(string_index, length) && "Invalid constant pool index %u in class file %s",
cp->tag_at(string_index).is_utf8(), string_index, CHECK_(nullHandle));
"Invalid constant pool index %u in class file %s",
string_index, CHECK_(nullHandle));
Symbol* sym = cp->symbol_at(string_index); Symbol* sym = cp->symbol_at(string_index);
cp->unresolved_string_at_put(index, sym); cp->unresolved_string_at_put(index, sym);
} }
...@@ -491,12 +461,9 @@ constantPoolHandle ClassFileParser::parse_constant_pool(ClassLoaderData* loader_ ...@@ -491,12 +461,9 @@ constantPoolHandle ClassFileParser::parse_constant_pool(ClassLoaderData* loader_
case JVM_CONSTANT_MethodType : case JVM_CONSTANT_MethodType :
{ {
int ref_index = cp->method_type_index_at(index); int ref_index = cp->method_type_index_at(index);
check_property( check_property(valid_symbol_at(ref_index) && EnableInvokeDynamic,
valid_cp_range(ref_index, length) && "Invalid constant pool index %u in class file %s",
cp->tag_at(ref_index).is_utf8() && ref_index, CHECK_(nullHandle));
EnableInvokeDynamic,
"Invalid constant pool index %u in class file %s",
ref_index, CHECK_(nullHandle));
} }
break; break;
case JVM_CONSTANT_InvokeDynamic : case JVM_CONSTANT_InvokeDynamic :
...@@ -541,7 +508,6 @@ constantPoolHandle ClassFileParser::parse_constant_pool(ClassLoaderData* loader_ ...@@ -541,7 +508,6 @@ constantPoolHandle ClassFileParser::parse_constant_pool(ClassLoaderData* loader_
} }
if (!_need_verify) { if (!_need_verify) {
cp_in_error.set_in_error(false);
return cp; return cp;
} }
...@@ -664,7 +630,6 @@ constantPoolHandle ClassFileParser::parse_constant_pool(ClassLoaderData* loader_ ...@@ -664,7 +630,6 @@ constantPoolHandle ClassFileParser::parse_constant_pool(ClassLoaderData* loader_
} // end of switch } // end of switch
} // end of for } // end of for
cp_in_error.set_in_error(false);
return cp; return cp;
} }
...@@ -786,93 +751,92 @@ bool put_after_lookup(Symbol* name, Symbol* sig, NameSigHash** table) { ...@@ -786,93 +751,92 @@ bool put_after_lookup(Symbol* name, Symbol* sig, NameSigHash** table) {
} }
Array<Klass*>* ClassFileParser::parse_interfaces(constantPoolHandle cp, Array<Klass*>* ClassFileParser::parse_interfaces(int length,
int length,
ClassLoaderData* loader_data,
Handle protection_domain, Handle protection_domain,
Symbol* class_name, Symbol* class_name,
bool* has_default_methods, bool* has_default_methods,
TRAPS) { TRAPS) {
ClassFileStream* cfs = stream(); if (length == 0) {
assert(length > 0, "only called for length>0"); _local_interfaces = Universe::the_empty_klass_array();
// FIXME: Leak at later OOM. } else {
Array<Klass*>* interfaces = MetadataFactory::new_array<Klass*>(loader_data, length, NULL, CHECK_NULL); ClassFileStream* cfs = stream();
assert(length > 0, "only called for length>0");
int index; _local_interfaces = MetadataFactory::new_array<Klass*>(_loader_data, length, NULL, CHECK_NULL);
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),
"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));
} else {
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());
// Call resolve_super so classcircularity is checked
Klass* k = SystemDictionary::resolve_super_or_fail(class_name,
unresolved_klass, class_loader, protection_domain,
false, CHECK_NULL);
interf = KlassHandle(THREAD, k);
}
if (!interf()->is_interface()) { int index;
THROW_MSG_(vmSymbols::java_lang_IncompatibleClassChangeError(), "Implementing class", NULL); for (index = 0; index < length; index++) {
} u2 interface_index = cfs->get_u2(CHECK_NULL);
if (InstanceKlass::cast(interf())->has_default_methods()) { KlassHandle interf;
*has_default_methods = true; check_property(
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));
} else {
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());
// Call resolve_super so classcircularity is checked
Klass* k = SystemDictionary::resolve_super_or_fail(class_name,
unresolved_klass, class_loader, protection_domain,
false, CHECK_NULL);
interf = KlassHandle(THREAD, k);
}
if (!interf()->is_interface()) {
THROW_MSG_(vmSymbols::java_lang_IncompatibleClassChangeError(), "Implementing class", NULL);
}
if (InstanceKlass::cast(interf())->has_default_methods()) {
*has_default_methods = true;
}
_local_interfaces->at_put(index, interf());
} }
interfaces->at_put(index, interf());
}
if (!_need_verify || length <= 1) { if (!_need_verify || length <= 1) {
return interfaces; return _local_interfaces;
} }
// Check if there's any duplicates in interfaces // Check if there's any duplicates in interfaces
ResourceMark rm(THREAD); ResourceMark rm(THREAD);
NameSigHash** interface_names = NEW_RESOURCE_ARRAY_IN_THREAD( NameSigHash** interface_names = NEW_RESOURCE_ARRAY_IN_THREAD(
THREAD, NameSigHash*, HASH_ROW_SIZE); THREAD, NameSigHash*, HASH_ROW_SIZE);
initialize_hashtable(interface_names); initialize_hashtable(interface_names);
bool dup = false; bool dup = false;
{ {
debug_only(No_Safepoint_Verifier nsv;) debug_only(No_Safepoint_Verifier nsv;)
for (index = 0; index < length; index++) { for (index = 0; index < length; index++) {
Klass* k = interfaces->at(index); Klass* k = _local_interfaces->at(index);
Symbol* name = InstanceKlass::cast(k)->name(); Symbol* name = InstanceKlass::cast(k)->name();
// If no duplicates, add (name, NULL) in hashtable interface_names. // If no duplicates, add (name, NULL) in hashtable interface_names.
if (!put_after_lookup(name, NULL, interface_names)) { if (!put_after_lookup(name, NULL, interface_names)) {
dup = true; dup = true;
break; break;
}
} }
} }
if (dup) {
classfile_parse_error("Duplicate interface name in class file %s", CHECK_NULL);
}
} }
if (dup) { return _local_interfaces;
classfile_parse_error("Duplicate interface name in class file %s", CHECK_NULL);
}
return 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 // Make sure the constant pool entry is of a type appropriate to this field
guarantee_property( guarantee_property(
(constantvalue_index > 0 && (constantvalue_index > 0 &&
constantvalue_index < cp->length()), constantvalue_index < _cp->length()),
"Bad initial value index %u in ConstantValue attribute in class file %s", "Bad initial value index %u in ConstantValue attribute in class file %s",
constantvalue_index, CHECK); constantvalue_index, CHECK);
constantTag value_type = cp->tag_at(constantvalue_index); constantTag value_type = _cp->tag_at(constantvalue_index);
switch ( cp->basic_type_for_signature_at(signature_index) ) { switch ( _cp->basic_type_for_signature_at(signature_index) ) {
case T_LONG: case T_LONG:
guarantee_property(value_type.is_long(), "Inconsistent constant value type in class file %s", CHECK); guarantee_property(value_type.is_long(), "Inconsistent constant value type in class file %s", CHECK);
break; break;
...@@ -886,7 +850,7 @@ void ClassFileParser::verify_constantvalue(int constantvalue_index, int signatur ...@@ -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); guarantee_property(value_type.is_int(), "Inconsistent constant value type in class file %s", CHECK);
break; break;
case T_OBJECT: 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()), && value_type.is_string()),
"Bad string initial value in class file %s", CHECK); "Bad string initial value in class file %s", CHECK);
break; break;
...@@ -899,15 +863,11 @@ void ClassFileParser::verify_constantvalue(int constantvalue_index, int signatur ...@@ -899,15 +863,11 @@ void ClassFileParser::verify_constantvalue(int constantvalue_index, int signatur
// Parse attributes for a field. // Parse attributes for a field.
void ClassFileParser::parse_field_attributes(ClassLoaderData* loader_data, void ClassFileParser::parse_field_attributes(u2 attributes_count,
constantPoolHandle cp,
u2 attributes_count,
bool is_static, u2 signature_index, bool is_static, u2 signature_index,
u2* constantvalue_index_addr, u2* constantvalue_index_addr,
bool* is_synthetic_addr, bool* is_synthetic_addr,
u2* generic_signature_index_addr, u2* generic_signature_index_addr,
AnnotationArray** field_annotations,
AnnotationArray** field_type_annotations,
ClassFileParser::FieldAnnotationCollector* parsed_annotations, ClassFileParser::FieldAnnotationCollector* parsed_annotations,
TRAPS) { TRAPS) {
ClassFileStream* cfs = stream(); ClassFileStream* cfs = stream();
...@@ -927,12 +887,11 @@ void ClassFileParser::parse_field_attributes(ClassLoaderData* loader_data, ...@@ -927,12 +887,11 @@ void ClassFileParser::parse_field_attributes(ClassLoaderData* loader_data,
cfs->guarantee_more(6, CHECK); // attribute_name_index, attribute_length cfs->guarantee_more(6, CHECK); // attribute_name_index, attribute_length
u2 attribute_name_index = cfs->get_u2_fast(); u2 attribute_name_index = cfs->get_u2_fast();
u4 attribute_length = cfs->get_u4_fast(); u4 attribute_length = cfs->get_u4_fast();
check_property(valid_cp_range(attribute_name_index, cp->length()) && check_property(valid_symbol_at(attribute_name_index),
cp->tag_at(attribute_name_index).is_utf8(),
"Invalid field attribute index %u in class file %s", "Invalid field attribute index %u in class file %s",
attribute_name_index, attribute_name_index,
CHECK); 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()) { if (is_static && attribute_name == vmSymbols::tag_constant_value()) {
// ignore if non-static // ignore if non-static
if (constantvalue_index != 0) { if (constantvalue_index != 0) {
...@@ -944,7 +903,7 @@ void ClassFileParser::parse_field_attributes(ClassLoaderData* loader_data, ...@@ -944,7 +903,7 @@ void ClassFileParser::parse_field_attributes(ClassLoaderData* loader_data,
attribute_length, CHECK); attribute_length, CHECK);
constantvalue_index = cfs->get_u2(CHECK); constantvalue_index = cfs->get_u2(CHECK);
if (_need_verify) { 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()) { } else if (attribute_name == vmSymbols::tag_synthetic()) {
if (attribute_length != 0) { if (attribute_length != 0) {
...@@ -971,10 +930,8 @@ void ClassFileParser::parse_field_attributes(ClassLoaderData* loader_data, ...@@ -971,10 +930,8 @@ void ClassFileParser::parse_field_attributes(ClassLoaderData* loader_data,
runtime_visible_annotations_length = attribute_length; runtime_visible_annotations_length = attribute_length;
runtime_visible_annotations = cfs->get_u1_buffer(); runtime_visible_annotations = cfs->get_u1_buffer();
assert(runtime_visible_annotations != NULL, "null visible annotations"); assert(runtime_visible_annotations != NULL, "null visible annotations");
parse_annotations(loader_data, parse_annotations(runtime_visible_annotations,
runtime_visible_annotations,
runtime_visible_annotations_length, runtime_visible_annotations_length,
cp,
parsed_annotations, parsed_annotations,
CHECK); CHECK);
cfs->skip_u1(runtime_visible_annotations_length, CHECK); cfs->skip_u1(runtime_visible_annotations_length, CHECK);
...@@ -1004,18 +961,18 @@ void ClassFileParser::parse_field_attributes(ClassLoaderData* loader_data, ...@@ -1004,18 +961,18 @@ void ClassFileParser::parse_field_attributes(ClassLoaderData* loader_data,
*constantvalue_index_addr = constantvalue_index; *constantvalue_index_addr = constantvalue_index;
*is_synthetic_addr = is_synthetic; *is_synthetic_addr = is_synthetic;
*generic_signature_index_addr = generic_signature_index; *generic_signature_index_addr = generic_signature_index;
*field_annotations = assemble_annotations(loader_data, AnnotationArray* a = assemble_annotations(runtime_visible_annotations,
runtime_visible_annotations,
runtime_visible_annotations_length, runtime_visible_annotations_length,
runtime_invisible_annotations, runtime_invisible_annotations,
runtime_invisible_annotations_length, runtime_invisible_annotations_length,
CHECK); CHECK);
*field_type_annotations = assemble_annotations(loader_data, parsed_annotations->set_field_annotations(a);
runtime_visible_type_annotations, a = assemble_annotations(runtime_visible_type_annotations,
runtime_visible_type_annotations_length, runtime_visible_type_annotations_length,
runtime_invisible_type_annotations, runtime_invisible_type_annotations,
runtime_invisible_type_annotations_length, runtime_invisible_type_annotations_length,
CHECK); CHECK);
parsed_annotations->set_field_type_annotations(a);
return; return;
} }
...@@ -1106,13 +1063,9 @@ class FieldAllocationCount: public ResourceObj { ...@@ -1106,13 +1063,9 @@ class FieldAllocationCount: public ResourceObj {
} }
}; };
Array<u2>* ClassFileParser::parse_fields(ClassLoaderData* loader_data, Array<u2>* ClassFileParser::parse_fields(Symbol* class_name,
Symbol* class_name,
constantPoolHandle cp,
bool is_interface, bool is_interface,
FieldAllocationCount *fac, FieldAllocationCount *fac,
Array<AnnotationArray*>** fields_annotations,
Array<AnnotationArray*>** fields_type_annotations,
u2* java_fields_count_ptr, TRAPS) { u2* java_fields_count_ptr, TRAPS) {
ClassFileStream* cfs = stream(); ClassFileStream* cfs = stream();
cfs->guarantee_more(2, CHECK_NULL); // length cfs->guarantee_more(2, CHECK_NULL); // length
...@@ -1147,8 +1100,6 @@ Array<u2>* ClassFileParser::parse_fields(ClassLoaderData* loader_data, ...@@ -1147,8 +1100,6 @@ Array<u2>* ClassFileParser::parse_fields(ClassLoaderData* loader_data,
u2* fa = NEW_RESOURCE_ARRAY_IN_THREAD( u2* fa = NEW_RESOURCE_ARRAY_IN_THREAD(
THREAD, u2, total_fields * (FieldInfo::field_slots + 1)); 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. // The generic signature slots start after all other fields' data.
int generic_signature_slot = total_fields * FieldInfo::field_slots; int generic_signature_slot = total_fields * FieldInfo::field_slots;
int num_generic_signature = 0; int num_generic_signature = 0;
...@@ -1161,53 +1112,52 @@ Array<u2>* ClassFileParser::parse_fields(ClassLoaderData* loader_data, ...@@ -1161,53 +1112,52 @@ Array<u2>* ClassFileParser::parse_fields(ClassLoaderData* loader_data,
access_flags.set_flags(flags); access_flags.set_flags(flags);
u2 name_index = cfs->get_u2_fast(); u2 name_index = cfs->get_u2_fast();
int cp_size = cp->length(); int cp_size = _cp->length();
check_property( check_property(valid_symbol_at(name_index),
valid_cp_range(name_index, cp_size) && cp->tag_at(name_index).is_utf8(),
"Invalid constant pool index %u for field name in class file %s", "Invalid constant pool index %u for field name in class file %s",
name_index, CHECK_NULL); name_index,
Symbol* name = cp->symbol_at(name_index); CHECK_NULL);
Symbol* name = _cp->symbol_at(name_index);
verify_legal_field_name(name, CHECK_NULL); verify_legal_field_name(name, CHECK_NULL);
u2 signature_index = cfs->get_u2_fast(); u2 signature_index = cfs->get_u2_fast();
check_property( check_property(valid_symbol_at(signature_index),
valid_cp_range(signature_index, cp_size) &&
cp->tag_at(signature_index).is_utf8(),
"Invalid constant pool index %u for field signature in class file %s", "Invalid constant pool index %u for field signature in class file %s",
signature_index, CHECK_NULL); 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); verify_legal_field_signature(name, sig, CHECK_NULL);
u2 constantvalue_index = 0; u2 constantvalue_index = 0;
bool is_synthetic = false; bool is_synthetic = false;
u2 generic_signature_index = 0; u2 generic_signature_index = 0;
bool is_static = access_flags.is_static(); bool is_static = access_flags.is_static();
FieldAnnotationCollector parsed_annotations; FieldAnnotationCollector parsed_annotations(_loader_data);
u2 attributes_count = cfs->get_u2_fast(); u2 attributes_count = cfs->get_u2_fast();
if (attributes_count > 0) { if (attributes_count > 0) {
parse_field_attributes(loader_data, parse_field_attributes(attributes_count, is_static, signature_index,
cp, attributes_count, is_static, signature_index,
&constantvalue_index, &is_synthetic, &constantvalue_index, &is_synthetic,
&generic_signature_index, &field_annotations, &generic_signature_index, &parsed_annotations,
&field_type_annotations, &parsed_annotations,
CHECK_NULL); CHECK_NULL);
if (field_annotations != NULL) { if (parsed_annotations.field_annotations() != NULL) {
if (*fields_annotations == NULL) { if (_fields_annotations == NULL) {
*fields_annotations = MetadataFactory::new_array<AnnotationArray*>( _fields_annotations = MetadataFactory::new_array<AnnotationArray*>(
loader_data, length, NULL, _loader_data, length, NULL,
CHECK_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 (parsed_annotations.field_type_annotations() != NULL) {
if (*fields_type_annotations == NULL) { if (_fields_type_annotations == NULL) {
*fields_type_annotations = MetadataFactory::new_array<AnnotationArray*>( _fields_type_annotations = MetadataFactory::new_array<AnnotationArray*>(
loader_data, length, NULL, _loader_data, length, NULL,
CHECK_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) { if (is_synthetic) {
access_flags.set_is_synthetic(); access_flags.set_is_synthetic();
} }
...@@ -1224,7 +1174,7 @@ Array<u2>* ClassFileParser::parse_fields(ClassLoaderData* loader_data, ...@@ -1224,7 +1174,7 @@ Array<u2>* ClassFileParser::parse_fields(ClassLoaderData* loader_data,
name_index, name_index,
signature_index, signature_index,
constantvalue_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 // Remember how many oops we encountered and compute allocation type
FieldAllocationType atype = fac->update(is_static, type); FieldAllocationType atype = fac->update(is_static, type);
...@@ -1245,8 +1195,8 @@ Array<u2>* ClassFileParser::parse_fields(ClassLoaderData* loader_data, ...@@ -1245,8 +1195,8 @@ Array<u2>* ClassFileParser::parse_fields(ClassLoaderData* loader_data,
bool duplicate = false; bool duplicate = false;
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
FieldInfo* f = FieldInfo::from_field_array(fa, i); FieldInfo* f = FieldInfo::from_field_array(fa, i);
if (name == cp->symbol_at(f->name_index()) && if (name == _cp->symbol_at(f->name_index()) &&
signature == cp->symbol_at(f->signature_index())) { signature == _cp->symbol_at(f->signature_index())) {
// Symbol is desclared in Java so skip this one // Symbol is desclared in Java so skip this one
duplicate = true; duplicate = true;
break; break;
...@@ -1280,8 +1230,9 @@ Array<u2>* ClassFileParser::parse_fields(ClassLoaderData* loader_data, ...@@ -1280,8 +1230,9 @@ Array<u2>* ClassFileParser::parse_fields(ClassLoaderData* loader_data,
// fields array is trimed. Also unused slots that were reserved // fields array is trimed. Also unused slots that were reserved
// for generic signature indexes are discarded. // for generic signature indexes are discarded.
Array<u2>* fields = MetadataFactory::new_array<u2>( 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); CHECK_NULL);
_fields = fields; // save in case of error
{ {
int i = 0; int i = 0;
for (; i < index * FieldInfo::field_slots; i++) { for (; i < index * FieldInfo::field_slots; i++) {
...@@ -1303,7 +1254,7 @@ Array<u2>* ClassFileParser::parse_fields(ClassLoaderData* loader_data, ...@@ -1303,7 +1254,7 @@ Array<u2>* ClassFileParser::parse_fields(ClassLoaderData* loader_data,
bool dup = false; bool dup = false;
{ {
debug_only(No_Safepoint_Verifier nsv;) 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* name = fs.name();
Symbol* sig = fs.signature(); Symbol* sig = fs.signature();
// If no duplicates, add name/signature in hashtable names_and_sigs. // 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) { ...@@ -1330,10 +1281,8 @@ static void copy_u2_with_conversion(u2* dest, u2* src, int length) {
} }
u2* ClassFileParser::parse_exception_table(ClassLoaderData* loader_data, u2* ClassFileParser::parse_exception_table(u4 code_length,
u4 code_length,
u4 exception_table_length, u4 exception_table_length,
constantPoolHandle cp,
TRAPS) { TRAPS) {
ClassFileStream* cfs = stream(); ClassFileStream* cfs = stream();
...@@ -1354,8 +1303,7 @@ u2* ClassFileParser::parse_exception_table(ClassLoaderData* loader_data, ...@@ -1354,8 +1303,7 @@ u2* ClassFileParser::parse_exception_table(ClassLoaderData* loader_data,
"Illegal exception table handler in class file %s", "Illegal exception table handler in class file %s",
CHECK_NULL); CHECK_NULL);
if (catch_type_index != 0) { if (catch_type_index != 0) {
guarantee_property(valid_cp_range(catch_type_index, cp->length()) && guarantee_property(valid_klass_reference_at(catch_type_index),
is_klass_reference(cp, catch_type_index),
"Catch type in exception table has bad constant type in class file %s", CHECK_NULL); "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 ...@@ -1506,7 +1454,6 @@ void copy_lvt_element(Classfile_LVT_Element *src, LocalVariableTableElement *lvt
u2* ClassFileParser::parse_localvariable_table(u4 code_length, u2* ClassFileParser::parse_localvariable_table(u4 code_length,
u2 max_locals, u2 max_locals,
u4 code_attribute_length, u4 code_attribute_length,
constantPoolHandle cp,
u2* localvariable_table_length, u2* localvariable_table_length,
bool isLVTT, bool isLVTT,
TRAPS) { TRAPS) {
...@@ -1544,20 +1491,16 @@ u2* ClassFileParser::parse_localvariable_table(u4 code_length, ...@@ -1544,20 +1491,16 @@ u2* ClassFileParser::parse_localvariable_table(u4 code_length,
"Invalid length %u in %s in class file %s", "Invalid length %u in %s in class file %s",
length, tbl_name, CHECK_NULL); length, tbl_name, CHECK_NULL);
} }
int cp_size = cp->length(); int cp_size = _cp->length();
guarantee_property( guarantee_property(valid_symbol_at(name_index),
valid_cp_range(name_index, cp_size) &&
cp->tag_at(name_index).is_utf8(),
"Name index %u in %s has bad constant type in class file %s", "Name index %u in %s has bad constant type in class file %s",
name_index, tbl_name, CHECK_NULL); name_index, tbl_name, CHECK_NULL);
guarantee_property( guarantee_property(valid_symbol_at(descriptor_index),
valid_cp_range(descriptor_index, cp_size) &&
cp->tag_at(descriptor_index).is_utf8(),
"Signature index %u in %s has bad constant type in class file %s", "Signature index %u in %s has bad constant type in class file %s",
descriptor_index, tbl_name, CHECK_NULL); descriptor_index, tbl_name, CHECK_NULL);
Symbol* name = cp->symbol_at(name_index); Symbol* name = _cp->symbol_at(name_index);
Symbol* sig = cp->symbol_at(descriptor_index); Symbol* sig = _cp->symbol_at(descriptor_index);
verify_legal_field_name(name, CHECK_NULL); verify_legal_field_name(name, CHECK_NULL);
u2 extra_slot = 0; u2 extra_slot = 0;
if (!isLVTT) { if (!isLVTT) {
...@@ -1579,7 +1522,7 @@ u2* ClassFileParser::parse_localvariable_table(u4 code_length, ...@@ -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, 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(); ClassFileStream* cfs = stream();
u2 index = 0; // index in the array with long/double occupying two slots u2 index = 0; // index in the array with long/double occupying two slots
u4 i1 = *u1_index; u4 i1 = *u1_index;
...@@ -1591,8 +1534,7 @@ void ClassFileParser::parse_type_array(u2 array_length, u4 code_length, u4* u1_i ...@@ -1591,8 +1534,7 @@ void ClassFileParser::parse_type_array(u2 array_length, u4 code_length, u4* u1_i
index++; index++;
} else if (tag == ITEM_Object) { } else if (tag == ITEM_Object) {
u2 class_index = u2_array[i2++] = cfs->get_u2(CHECK); u2 class_index = u2_array[i2++] = cfs->get_u2(CHECK);
guarantee_property(valid_cp_range(class_index, cp->length()) && guarantee_property(valid_klass_reference_at(class_index),
is_klass_reference(cp, class_index),
"Bad class index %u in StackMap in class file %s", "Bad class index %u in StackMap in class file %s",
class_index, CHECK); class_index, CHECK);
} else if (tag == ITEM_Uninitialized) { } else if (tag == ITEM_Uninitialized) {
...@@ -1613,8 +1555,7 @@ void ClassFileParser::parse_type_array(u2 array_length, u4 code_length, u4* u1_i ...@@ -1613,8 +1555,7 @@ void ClassFileParser::parse_type_array(u2 array_length, u4 code_length, u4* u1_i
*u2_index = i2; *u2_index = i2;
} }
Array<u1>* ClassFileParser::parse_stackmap_table( u1* ClassFileParser::parse_stackmap_table(
ClassLoaderData* loader_data,
u4 code_attribute_length, TRAPS) { u4 code_attribute_length, TRAPS) {
if (code_attribute_length == 0) if (code_attribute_length == 0)
return NULL; return NULL;
...@@ -1629,18 +1570,12 @@ Array<u1>* ClassFileParser::parse_stackmap_table( ...@@ -1629,18 +1570,12 @@ Array<u1>* ClassFileParser::parse_stackmap_table(
if (!_need_verify && !DumpSharedSpaces) { if (!_need_verify && !DumpSharedSpaces) {
return NULL; return NULL;
} }
return stackmap_table_start;
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;
} }
u2* ClassFileParser::parse_checked_exceptions(u2* checked_exceptions_length, u2* ClassFileParser::parse_checked_exceptions(u2* checked_exceptions_length,
u4 method_attribute_length, u4 method_attribute_length,
constantPoolHandle cp, TRAPS) { TRAPS) {
ClassFileStream* cfs = stream(); ClassFileStream* cfs = stream();
cfs->guarantee_more(2, CHECK_NULL); // checked_exceptions_length cfs->guarantee_more(2, CHECK_NULL); // checked_exceptions_length
*checked_exceptions_length = cfs->get_u2_fast(); *checked_exceptions_length = cfs->get_u2_fast();
...@@ -1657,8 +1592,7 @@ u2* ClassFileParser::parse_checked_exceptions(u2* checked_exceptions_length, ...@@ -1657,8 +1592,7 @@ u2* ClassFileParser::parse_checked_exceptions(u2* checked_exceptions_length,
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
checked_exception = cfs->get_u2_fast(); checked_exception = cfs->get_u2_fast();
check_property( check_property(
valid_cp_range(checked_exception, cp->length()) && valid_klass_reference_at(checked_exception),
is_klass_reference(cp, checked_exception),
"Exception name has bad type at constant pool %u in class file %s", "Exception name has bad type at constant pool %u in class file %s",
checked_exception, CHECK_NULL); checked_exception, CHECK_NULL);
} }
...@@ -1735,9 +1669,7 @@ int ClassFileParser::skip_annotation_value(u1* buffer, int limit, int index) { ...@@ -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: // Sift through annotations, looking for those significant to the VM:
void ClassFileParser::parse_annotations(ClassLoaderData* loader_data, void ClassFileParser::parse_annotations(u1* buffer, int limit,
u1* buffer, int limit,
constantPoolHandle cp,
ClassFileParser::AnnotationCollector* coll, ClassFileParser::AnnotationCollector* coll,
TRAPS) { TRAPS) {
// annotations := do(nann:u2) {annotation} // annotations := do(nann:u2) {annotation}
...@@ -1767,17 +1699,17 @@ void ClassFileParser::parse_annotations(ClassLoaderData* loader_data, ...@@ -1767,17 +1699,17 @@ void ClassFileParser::parse_annotations(ClassLoaderData* loader_data,
u1* abase = buffer + index0; u1* abase = buffer + index0;
int atype = Bytes::get_Java_u2(abase + atype_off); int atype = Bytes::get_Java_u2(abase + atype_off);
int count = Bytes::get_Java_u2(abase + count_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 if (aname == NULL) break; // invalid annotation name
Symbol* member = NULL; Symbol* member = NULL;
if (count >= 1) { if (count >= 1) {
int member_index = Bytes::get_Java_u2(abase + member_off); 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 if (member == NULL) break; // invalid member name
} }
// Here is where parsing particular annotations will take place. // 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; if (id == AnnotationCollector::_unknown) continue;
coll->set_annotation(id); coll->set_annotation(id);
...@@ -1836,6 +1768,12 @@ void ClassFileParser::FieldAnnotationCollector::apply_to(FieldInfo* f) { ...@@ -1836,6 +1768,12 @@ void ClassFileParser::FieldAnnotationCollector::apply_to(FieldInfo* f) {
f->set_contended_group(contended_group()); 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) { void ClassFileParser::MethodAnnotationCollector::apply_to(methodHandle m) {
if (has_annotation(_method_ForceInline)) if (has_annotation(_method_ForceInline))
m->set_force_inline(true); m->set_force_inline(true);
...@@ -1894,10 +1832,9 @@ void ClassFileParser::copy_localvariable_table(ConstMethod* cm, ...@@ -1894,10 +1832,9 @@ void ClassFileParser::copy_localvariable_table(ConstMethod* cm,
&& _need_verify && _need_verify
&& _major_version >= JAVA_1_5_VERSION) { && _major_version >= JAVA_1_5_VERSION) {
clear_hashtable(lvt_Hash); clear_hashtable(lvt_Hash);
ConstantPool* cp = cm->constants();
classfile_parse_error("Duplicated LocalVariableTable attribute " classfile_parse_error("Duplicated LocalVariableTable attribute "
"entry for '%s' in class file %s", "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); CHECK);
} }
} }
...@@ -1916,18 +1853,16 @@ void ClassFileParser::copy_localvariable_table(ConstMethod* cm, ...@@ -1916,18 +1853,16 @@ void ClassFileParser::copy_localvariable_table(ConstMethod* cm,
if (entry == NULL) { if (entry == NULL) {
if (_need_verify) { if (_need_verify) {
clear_hashtable(lvt_Hash); clear_hashtable(lvt_Hash);
ConstantPool* cp = cm->constants();
classfile_parse_error("LVTT entry for '%s' in class file %s " classfile_parse_error("LVTT entry for '%s' in class file %s "
"does not match any LVT entry", "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); CHECK);
} }
} else if (entry->_elem->signature_cp_index != 0 && _need_verify) { } else if (entry->_elem->signature_cp_index != 0 && _need_verify) {
clear_hashtable(lvt_Hash); clear_hashtable(lvt_Hash);
ConstantPool* cp = cm->constants();
classfile_parse_error("Duplicated LocalVariableTypeTable attribute " classfile_parse_error("Duplicated LocalVariableTypeTable attribute "
"entry for '%s' in class file %s", "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); CHECK);
} else { } else {
// to add generic signatures into LocalVariableTable // to add generic signatures into LocalVariableTable
...@@ -1939,8 +1874,7 @@ void ClassFileParser::copy_localvariable_table(ConstMethod* cm, ...@@ -1939,8 +1874,7 @@ void ClassFileParser::copy_localvariable_table(ConstMethod* cm,
} }
void ClassFileParser::copy_method_annotations(ClassLoaderData* loader_data, void ClassFileParser::copy_method_annotations(ConstMethod* cm,
ConstMethod* cm,
u1* runtime_visible_annotations, u1* runtime_visible_annotations,
int runtime_visible_annotations_length, int runtime_visible_annotations_length,
u1* runtime_invisible_annotations, u1* runtime_invisible_annotations,
...@@ -1961,8 +1895,7 @@ void ClassFileParser::copy_method_annotations(ClassLoaderData* loader_data, ...@@ -1961,8 +1895,7 @@ void ClassFileParser::copy_method_annotations(ClassLoaderData* loader_data,
if (runtime_visible_annotations_length + if (runtime_visible_annotations_length +
runtime_invisible_annotations_length > 0) { runtime_invisible_annotations_length > 0) {
a = assemble_annotations(loader_data, a = assemble_annotations(runtime_visible_annotations,
runtime_visible_annotations,
runtime_visible_annotations_length, runtime_visible_annotations_length,
runtime_invisible_annotations, runtime_invisible_annotations,
runtime_invisible_annotations_length, runtime_invisible_annotations_length,
...@@ -1972,8 +1905,7 @@ void ClassFileParser::copy_method_annotations(ClassLoaderData* loader_data, ...@@ -1972,8 +1905,7 @@ void ClassFileParser::copy_method_annotations(ClassLoaderData* loader_data,
if (runtime_visible_parameter_annotations_length + if (runtime_visible_parameter_annotations_length +
runtime_invisible_parameter_annotations_length > 0) { runtime_invisible_parameter_annotations_length > 0) {
a = assemble_annotations(loader_data, a = assemble_annotations(runtime_visible_parameter_annotations,
runtime_visible_parameter_annotations,
runtime_visible_parameter_annotations_length, runtime_visible_parameter_annotations_length,
runtime_invisible_parameter_annotations, runtime_invisible_parameter_annotations,
runtime_invisible_parameter_annotations_length, runtime_invisible_parameter_annotations_length,
...@@ -1982,8 +1914,7 @@ void ClassFileParser::copy_method_annotations(ClassLoaderData* loader_data, ...@@ -1982,8 +1914,7 @@ void ClassFileParser::copy_method_annotations(ClassLoaderData* loader_data,
} }
if (annotation_default_length > 0) { if (annotation_default_length > 0) {
a = assemble_annotations(loader_data, a = assemble_annotations(annotation_default,
annotation_default,
annotation_default_length, annotation_default_length,
NULL, NULL,
0, 0,
...@@ -1993,8 +1924,7 @@ void ClassFileParser::copy_method_annotations(ClassLoaderData* loader_data, ...@@ -1993,8 +1924,7 @@ void ClassFileParser::copy_method_annotations(ClassLoaderData* loader_data,
if (runtime_visible_type_annotations_length + if (runtime_visible_type_annotations_length +
runtime_invisible_type_annotations_length > 0) { runtime_invisible_type_annotations_length > 0) {
a = assemble_annotations(loader_data, a = assemble_annotations(runtime_visible_type_annotations,
runtime_visible_type_annotations,
runtime_visible_type_annotations_length, runtime_visible_type_annotations_length,
runtime_invisible_type_annotations, runtime_invisible_type_annotations,
runtime_invisible_type_annotations_length, runtime_invisible_type_annotations_length,
...@@ -2013,9 +1943,7 @@ void ClassFileParser::copy_method_annotations(ClassLoaderData* loader_data, ...@@ -2013,9 +1943,7 @@ void ClassFileParser::copy_method_annotations(ClassLoaderData* loader_data,
// from the method back up to the containing klass. These flag values // from the method back up to the containing klass. These flag values
// are added to klass's access_flags. // are added to klass's access_flags.
methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data, methodHandle ClassFileParser::parse_method(bool is_interface,
constantPoolHandle cp,
bool is_interface,
AccessFlags *promoted_flags, AccessFlags *promoted_flags,
TRAPS) { TRAPS) {
ClassFileStream* cfs = stream(); ClassFileStream* cfs = stream();
...@@ -2026,22 +1954,20 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data, ...@@ -2026,22 +1954,20 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
int flags = cfs->get_u2_fast(); int flags = cfs->get_u2_fast();
u2 name_index = cfs->get_u2_fast(); u2 name_index = cfs->get_u2_fast();
int cp_size = cp->length(); int cp_size = _cp->length();
check_property( check_property(
valid_cp_range(name_index, cp_size) && valid_symbol_at(name_index),
cp->tag_at(name_index).is_utf8(),
"Illegal constant pool index %u for method name in class file %s", "Illegal constant pool index %u for method name in class file %s",
name_index, CHECK_(nullHandle)); 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)); verify_legal_method_name(name, CHECK_(nullHandle));
u2 signature_index = cfs->get_u2_fast(); u2 signature_index = cfs->get_u2_fast();
guarantee_property( guarantee_property(
valid_cp_range(signature_index, cp_size) && valid_symbol_at(signature_index),
cp->tag_at(signature_index).is_utf8(),
"Illegal constant pool index %u for method signature in class file %s", "Illegal constant pool index %u for method signature in class file %s",
signature_index, CHECK_(nullHandle)); signature_index, CHECK_(nullHandle));
Symbol* signature = cp->symbol_at(signature_index); Symbol* signature = _cp->symbol_at(signature_index);
AccessFlags access_flags; AccessFlags access_flags;
if (name == vmSymbols::class_initializer_name()) { if (name == vmSymbols::class_initializer_name()) {
...@@ -2097,7 +2023,8 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data, ...@@ -2097,7 +2023,8 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
bool parsed_checked_exceptions_attribute = false; bool parsed_checked_exceptions_attribute = false;
bool parsed_stackmap_attribute = false; bool parsed_stackmap_attribute = false;
// stackmap attribute - JDK1.5 // stackmap attribute - JDK1.5
Array<u1>* stackmap_data = NULL; u1* stackmap_data = NULL;
int stackmap_data_length = 0;
u2 generic_signature_index = 0; u2 generic_signature_index = 0;
MethodAnnotationCollector parsed_annotations; MethodAnnotationCollector parsed_annotations;
u1* runtime_visible_annotations = NULL; u1* runtime_visible_annotations = NULL;
...@@ -2122,12 +2049,11 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data, ...@@ -2122,12 +2049,11 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
u2 method_attribute_name_index = cfs->get_u2_fast(); u2 method_attribute_name_index = cfs->get_u2_fast();
u4 method_attribute_length = cfs->get_u4_fast(); u4 method_attribute_length = cfs->get_u4_fast();
check_property( check_property(
valid_cp_range(method_attribute_name_index, cp_size) && valid_symbol_at(method_attribute_name_index),
cp->tag_at(method_attribute_name_index).is_utf8(),
"Invalid method attribute name index %u in class file %s", "Invalid method attribute name index %u in class file %s",
method_attribute_name_index, CHECK_(nullHandle)); 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()) { if (method_attribute_name == vmSymbols::tag_code()) {
// Parse Code attribute // Parse Code attribute
if (_need_verify) { if (_need_verify) {
...@@ -2171,7 +2097,7 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data, ...@@ -2171,7 +2097,7 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
exception_table_length = cfs->get_u2_fast(); exception_table_length = cfs->get_u2_fast();
if (exception_table_length > 0) { if (exception_table_length > 0) {
exception_table_start = 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 // Parse additional attributes in code attribute
...@@ -2204,19 +2130,18 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data, ...@@ -2204,19 +2130,18 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
calculated_attribute_length += code_attribute_length + calculated_attribute_length += code_attribute_length +
sizeof(code_attribute_name_index) + sizeof(code_attribute_name_index) +
sizeof(code_attribute_length); sizeof(code_attribute_length);
check_property(valid_cp_range(code_attribute_name_index, cp_size) && check_property(valid_symbol_at(code_attribute_name_index),
cp->tag_at(code_attribute_name_index).is_utf8(),
"Invalid code attribute name index %u in class file %s", "Invalid code attribute name index %u in class file %s",
code_attribute_name_index, code_attribute_name_index,
CHECK_(nullHandle)); CHECK_(nullHandle));
if (LoadLineNumberTables && 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 and compress line number table
parse_linenumber_table(code_attribute_length, code_length, parse_linenumber_table(code_attribute_length, code_length,
&linenumber_table, CHECK_(nullHandle)); &linenumber_table, CHECK_(nullHandle));
} else if (LoadLocalVariableTables && } 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 // Parse local variable table
if (!lvt_allocated) { if (!lvt_allocated) {
localvariable_table_length = NEW_RESOURCE_ARRAY_IN_THREAD( localvariable_table_length = NEW_RESOURCE_ARRAY_IN_THREAD(
...@@ -2238,7 +2163,6 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data, ...@@ -2238,7 +2163,6 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
parse_localvariable_table(code_length, parse_localvariable_table(code_length,
max_locals, max_locals,
code_attribute_length, code_attribute_length,
cp,
&localvariable_table_length[lvt_cnt], &localvariable_table_length[lvt_cnt],
false, // is not LVTT false, // is not LVTT
CHECK_(nullHandle)); CHECK_(nullHandle));
...@@ -2246,7 +2170,7 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data, ...@@ -2246,7 +2170,7 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
lvt_cnt++; lvt_cnt++;
} else if (LoadLocalVariableTypeTables && } else if (LoadLocalVariableTypeTables &&
_major_version >= JAVA_1_5_VERSION && _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) { if (!lvt_allocated) {
localvariable_table_length = NEW_RESOURCE_ARRAY_IN_THREAD( localvariable_table_length = NEW_RESOURCE_ARRAY_IN_THREAD(
THREAD, u2, INITIAL_MAX_LVT_NUMBER); THREAD, u2, INITIAL_MAX_LVT_NUMBER);
...@@ -2268,19 +2192,19 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data, ...@@ -2268,19 +2192,19 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
parse_localvariable_table(code_length, parse_localvariable_table(code_length,
max_locals, max_locals,
code_attribute_length, code_attribute_length,
cp,
&localvariable_type_table_length[lvtt_cnt], &localvariable_type_table_length[lvtt_cnt],
true, // is LVTT true, // is LVTT
CHECK_(nullHandle)); CHECK_(nullHandle));
lvtt_cnt++; lvtt_cnt++;
} else if (UseSplitVerifier && } else if (UseSplitVerifier &&
_major_version >= Verifier::STACKMAP_ATTRIBUTE_MAJOR_VERSION && _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. // Stack map is only needed by the new verifier in JDK1.5.
if (parsed_stackmap_attribute) { if (parsed_stackmap_attribute) {
classfile_parse_error("Multiple StackMapTable attributes in class file %s", CHECK_(nullHandle)); 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; parsed_stackmap_attribute = true;
} else { } else {
// Skip unknown attributes // Skip unknown attributes
...@@ -2301,7 +2225,7 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data, ...@@ -2301,7 +2225,7 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
checked_exceptions_start = checked_exceptions_start =
parse_checked_exceptions(&checked_exceptions_length, parse_checked_exceptions(&checked_exceptions_length,
method_attribute_length, method_attribute_length,
cp, CHECK_(nullHandle)); CHECK_(nullHandle));
} else if (method_attribute_name == vmSymbols::tag_method_parameters()) { } else if (method_attribute_name == vmSymbols::tag_method_parameters()) {
// reject multiple method parameters // reject multiple method parameters
if (method_parameters_seen) { if (method_parameters_seen) {
...@@ -2359,9 +2283,8 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data, ...@@ -2359,9 +2283,8 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
runtime_visible_annotations_length = method_attribute_length; runtime_visible_annotations_length = method_attribute_length;
runtime_visible_annotations = cfs->get_u1_buffer(); runtime_visible_annotations = cfs->get_u1_buffer();
assert(runtime_visible_annotations != NULL, "null visible annotations"); assert(runtime_visible_annotations != NULL, "null visible annotations");
parse_annotations(loader_data, parse_annotations(runtime_visible_annotations,
runtime_visible_annotations, runtime_visible_annotations_length, &parsed_annotations,
runtime_visible_annotations_length, cp, &parsed_annotations,
CHECK_(nullHandle)); CHECK_(nullHandle));
cfs->skip_u1(runtime_visible_annotations_length, CHECK_(nullHandle)); cfs->skip_u1(runtime_visible_annotations_length, CHECK_(nullHandle));
} else if (PreserveAllAnnotations && method_attribute_name == vmSymbols::tag_runtime_invisible_annotations()) { } else if (PreserveAllAnnotations && method_attribute_name == vmSymbols::tag_runtime_invisible_annotations()) {
...@@ -2434,18 +2357,18 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data, ...@@ -2434,18 +2357,18 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
0); 0);
Method* m = Method::allocate( Method* m = Method::allocate(
loader_data, code_length, access_flags, &sizes, _loader_data, code_length, access_flags, &sizes,
ConstMethod::NORMAL, CHECK_(nullHandle)); ConstMethod::NORMAL, CHECK_(nullHandle));
ClassLoadingService::add_class_method_size(m->size()*HeapWordSize); ClassLoadingService::add_class_method_size(m->size()*HeapWordSize);
// Fill in information from fixed part (access_flags already set) // 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_name_index(name_index);
m->set_signature_index(signature_index); m->set_signature_index(signature_index);
#ifdef CC_INTERP #ifdef CC_INTERP
// hmm is there a gc issue here?? // 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()); m->set_result_index(rtf.type());
#endif #endif
...@@ -2464,7 +2387,10 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data, ...@@ -2464,7 +2387,10 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
// Fill in code attribute information // Fill in code attribute information
m->set_max_stack(max_stack); m->set_max_stack(max_stack);
m->set_max_locals(max_locals); 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 // Copy byte codes
m->set_code(code_start); m->set_code(code_start);
...@@ -2520,7 +2446,7 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data, ...@@ -2520,7 +2446,7 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
parsed_annotations.apply_to(m); parsed_annotations.apply_to(m);
// Copy annotations // Copy annotations
copy_method_annotations(loader_data, m->constMethod(), copy_method_annotations(m->constMethod(),
runtime_visible_annotations, runtime_visible_annotations,
runtime_visible_annotations_length, runtime_visible_annotations_length,
runtime_invisible_annotations, runtime_invisible_annotations,
...@@ -2560,9 +2486,7 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data, ...@@ -2560,9 +2486,7 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
// from the methods back up to the containing klass. These flag values // from the methods back up to the containing klass. These flag values
// are added to klass's access_flags. // are added to klass's access_flags.
Array<Method*>* ClassFileParser::parse_methods(ClassLoaderData* loader_data, Array<Method*>* ClassFileParser::parse_methods(bool is_interface,
constantPoolHandle cp,
bool is_interface,
AccessFlags* promoted_flags, AccessFlags* promoted_flags,
bool* has_final_method, bool* has_final_method,
bool* has_default_methods, bool* has_default_methods,
...@@ -2571,15 +2495,13 @@ Array<Method*>* ClassFileParser::parse_methods(ClassLoaderData* loader_data, ...@@ -2571,15 +2495,13 @@ Array<Method*>* ClassFileParser::parse_methods(ClassLoaderData* loader_data,
cfs->guarantee_more(2, CHECK_NULL); // length cfs->guarantee_more(2, CHECK_NULL); // length
u2 length = cfs->get_u2_fast(); u2 length = cfs->get_u2_fast();
if (length == 0) { if (length == 0) {
return Universe::the_empty_method_array(); _methods = Universe::the_empty_method_array();
} else { } else {
// FIXME: Handle leaks at later failures. _methods = MetadataFactory::new_array<Method*>(_loader_data, length, NULL, CHECK_NULL);
Array<Method*>* methods = MetadataFactory::new_array<Method*>(loader_data, length, NULL, CHECK_NULL);
HandleMark hm(THREAD); HandleMark hm(THREAD);
for (int index = 0; index < length; index++) { for (int index = 0; index < length; index++) {
methodHandle method = parse_method(loader_data, methodHandle method = parse_method(is_interface,
cp, is_interface,
promoted_flags, promoted_flags,
CHECK_NULL); CHECK_NULL);
...@@ -2590,7 +2512,7 @@ Array<Method*>* ClassFileParser::parse_methods(ClassLoaderData* loader_data, ...@@ -2590,7 +2512,7 @@ Array<Method*>* ClassFileParser::parse_methods(ClassLoaderData* loader_data,
// default method // default method
*has_default_methods = true; *has_default_methods = true;
} }
methods->at_put(index, method()); _methods->at_put(index, method());
} }
if (_need_verify && length > 1) { if (_need_verify && length > 1) {
...@@ -2603,7 +2525,7 @@ Array<Method*>* ClassFileParser::parse_methods(ClassLoaderData* loader_data, ...@@ -2603,7 +2525,7 @@ Array<Method*>* ClassFileParser::parse_methods(ClassLoaderData* loader_data,
{ {
debug_only(No_Safepoint_Verifier nsv;) debug_only(No_Safepoint_Verifier nsv;)
for (int i = 0; i < length; i++) { 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 no duplicates, add name/signature in hashtable names_and_sigs.
if (!put_after_lookup(m->name(), m->signature(), names_and_sigs)) { if (!put_after_lookup(m->name(), m->signature(), names_and_sigs)) {
dup = true; dup = true;
...@@ -2616,14 +2538,12 @@ Array<Method*>* ClassFileParser::parse_methods(ClassLoaderData* loader_data, ...@@ -2616,14 +2538,12 @@ Array<Method*>* ClassFileParser::parse_methods(ClassLoaderData* loader_data,
CHECK_NULL); CHECK_NULL);
} }
} }
return methods;
} }
return _methods;
} }
Array<int>* ClassFileParser::sort_methods(ClassLoaderData* loader_data, intArray* ClassFileParser::sort_methods(Array<Method*>* methods) {
Array<Method*>* methods,
TRAPS) {
int length = methods->length(); int length = methods->length();
// If JVMTI original method ordering or sharing is enabled we have to // If JVMTI original method ordering or sharing is enabled we have to
// remember the original class file ordering. // remember the original class file ordering.
...@@ -2641,10 +2561,11 @@ Array<int>* ClassFileParser::sort_methods(ClassLoaderData* loader_data, ...@@ -2641,10 +2561,11 @@ Array<int>* ClassFileParser::sort_methods(ClassLoaderData* loader_data,
// Note that the ordering is not alphabetical, see Symbol::fast_compare // Note that the ordering is not alphabetical, see Symbol::fast_compare
Method::sort_methods(methods); Method::sort_methods(methods);
intArray* method_ordering = NULL;
// If JVMTI original method ordering or sharing is enabled construct int // If JVMTI original method ordering or sharing is enabled construct int
// array remembering the original ordering // array remembering the original ordering
if (JvmtiExport::can_maintain_original_method_order() || DumpSharedSpaces) { 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++) { for (int index = 0; index < length; index++) {
Method* m = methods->at(index); Method* m = methods->at(index);
int old_index = m->vtable_index(); int old_index = m->vtable_index();
...@@ -2652,29 +2573,25 @@ Array<int>* ClassFileParser::sort_methods(ClassLoaderData* loader_data, ...@@ -2652,29 +2573,25 @@ Array<int>* ClassFileParser::sort_methods(ClassLoaderData* loader_data,
method_ordering->at_put(index, old_index); method_ordering->at_put(index, old_index);
m->set_vtable_index(Method::invalid_vtable_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(); ClassFileStream* cfs = stream();
cfs->guarantee_more(2, CHECK); // sourcefile_index cfs->guarantee_more(2, CHECK); // sourcefile_index
u2 sourcefile_index = cfs->get_u2_fast(); u2 sourcefile_index = cfs->get_u2_fast();
check_property( check_property(
valid_cp_range(sourcefile_index, cp->length()) && valid_symbol_at(sourcefile_index),
cp->tag_at(sourcefile_index).is_utf8(),
"Invalid SourceFile attribute at constant pool index %u in class file %s", "Invalid SourceFile attribute at constant pool index %u in class file %s",
sourcefile_index, CHECK); 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, void ClassFileParser::parse_classfile_source_debug_extension_attribute(int length, TRAPS) {
int length, TRAPS) {
ClassFileStream* cfs = stream(); ClassFileStream* cfs = stream();
u1* sde_buffer = cfs->get_u1_buffer(); u1* sde_buffer = cfs->get_u1_buffer();
assert(sde_buffer != NULL, "null sde buffer"); assert(sde_buffer != NULL, "null sde buffer");
...@@ -2698,12 +2615,10 @@ void ClassFileParser::parse_classfile_source_debug_extension_attribute(constantP ...@@ -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) #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 // Return number of classes in the inner classes attribute table
u2 ClassFileParser::parse_classfile_inner_classes_attribute(ClassLoaderData* loader_data, u2 ClassFileParser::parse_classfile_inner_classes_attribute(u1* inner_classes_attribute_start,
u1* inner_classes_attribute_start,
bool parsed_enclosingmethod_attribute, bool parsed_enclosingmethod_attribute,
u2 enclosing_method_class_index, u2 enclosing_method_class_index,
u2 enclosing_method_method_index, u2 enclosing_method_method_index,
constantPoolHandle cp,
TRAPS) { TRAPS) {
ClassFileStream* cfs = stream(); ClassFileStream* cfs = stream();
u1* current_mark = cfs->current(); u1* current_mark = cfs->current();
...@@ -2724,33 +2639,31 @@ u2 ClassFileParser::parse_classfile_inner_classes_attribute(ClassLoaderData* loa ...@@ -2724,33 +2639,31 @@ u2 ClassFileParser::parse_classfile_inner_classes_attribute(ClassLoaderData* loa
// enclosing_method_class_index, // enclosing_method_class_index,
// enclosing_method_method_index] // enclosing_method_method_index]
int size = length * 4 + (parsed_enclosingmethod_attribute ? 2 : 0); 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 index = 0;
int cp_size = cp->length(); int cp_size = _cp->length();
cfs->guarantee_more(8 * length, CHECK_0); // 4-tuples of u2 cfs->guarantee_more(8 * length, CHECK_0); // 4-tuples of u2
for (int n = 0; n < length; n++) { for (int n = 0; n < length; n++) {
// Inner class index // Inner class index
u2 inner_class_info_index = cfs->get_u2_fast(); u2 inner_class_info_index = cfs->get_u2_fast();
check_property( check_property(
inner_class_info_index == 0 || inner_class_info_index == 0 ||
(valid_cp_range(inner_class_info_index, cp_size) && valid_klass_reference_at(inner_class_info_index),
is_klass_reference(cp, inner_class_info_index)),
"inner_class_info_index %u has bad constant type in class file %s", "inner_class_info_index %u has bad constant type in class file %s",
inner_class_info_index, CHECK_0); inner_class_info_index, CHECK_0);
// Outer class index // Outer class index
u2 outer_class_info_index = cfs->get_u2_fast(); u2 outer_class_info_index = cfs->get_u2_fast();
check_property( check_property(
outer_class_info_index == 0 || outer_class_info_index == 0 ||
(valid_cp_range(outer_class_info_index, cp_size) && valid_klass_reference_at(outer_class_info_index),
is_klass_reference(cp, outer_class_info_index)),
"outer_class_info_index %u has bad constant type in class file %s", "outer_class_info_index %u has bad constant type in class file %s",
outer_class_info_index, CHECK_0); outer_class_info_index, CHECK_0);
// Inner class name // Inner class name
u2 inner_name_index = cfs->get_u2_fast(); u2 inner_name_index = cfs->get_u2_fast();
check_property( check_property(
inner_name_index == 0 || (valid_cp_range(inner_name_index, cp_size) && inner_name_index == 0 || valid_symbol_at(inner_name_index),
cp->tag_at(inner_name_index).is_utf8()),
"inner_name_index %u has bad constant type in class file %s", "inner_name_index %u has bad constant type in class file %s",
inner_name_index, CHECK_0); inner_name_index, CHECK_0);
if (_need_verify) { if (_need_verify) {
...@@ -2794,33 +2707,27 @@ u2 ClassFileParser::parse_classfile_inner_classes_attribute(ClassLoaderData* loa ...@@ -2794,33 +2707,27 @@ u2 ClassFileParser::parse_classfile_inner_classes_attribute(ClassLoaderData* loa
} }
assert(index == size, "wrong size"); assert(index == size, "wrong size");
// Update InstanceKlass with inner class info.
set_class_inner_classes(inner_classes);
// Restore buffer's current position. // Restore buffer's current position.
cfs->set_current(current_mark); cfs->set_current(current_mark);
return length; return length;
} }
void ClassFileParser::parse_classfile_synthetic_attribute(constantPoolHandle cp, TRAPS) { void ClassFileParser::parse_classfile_synthetic_attribute(TRAPS) {
set_class_synthetic_flag(true); set_class_synthetic_flag(true);
} }
void ClassFileParser::parse_classfile_signature_attribute(constantPoolHandle cp, TRAPS) { void ClassFileParser::parse_classfile_signature_attribute(TRAPS) {
ClassFileStream* cfs = stream(); ClassFileStream* cfs = stream();
u2 signature_index = cfs->get_u2(CHECK); u2 signature_index = cfs->get_u2(CHECK);
check_property( check_property(
valid_cp_range(signature_index, cp->length()) && valid_symbol_at(signature_index),
cp->tag_at(signature_index).is_utf8(),
"Invalid constant pool index %u in Signature attribute in class file %s", "Invalid constant pool index %u in Signature attribute in class file %s",
signature_index, CHECK); 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, void ClassFileParser::parse_classfile_bootstrap_methods_attribute(u4 attribute_byte_length, TRAPS) {
constantPoolHandle cp,
u4 attribute_byte_length, TRAPS) {
ClassFileStream* cfs = stream(); ClassFileStream* cfs = stream();
u1* current_start = cfs->current(); u1* current_start = cfs->current();
...@@ -2841,10 +2748,14 @@ void ClassFileParser::parse_classfile_bootstrap_methods_attribute(ClassLoaderDat ...@@ -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. // The array begins with a series of short[2] pairs, one for each tuple.
int index_size = (attribute_array_length * 2); 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 operand_fill_index = index_size;
int cp_size = cp->length(); int cp_size = _cp->length();
for (int n = 0; n < attribute_array_length; n++) { for (int n = 0; n < attribute_array_length; n++) {
// Store a 32-bit offset into the header of the operand array. // Store a 32-bit offset into the header of the operand array.
...@@ -2856,7 +2767,7 @@ void ClassFileParser::parse_classfile_bootstrap_methods_attribute(ClassLoaderDat ...@@ -2856,7 +2767,7 @@ void ClassFileParser::parse_classfile_bootstrap_methods_attribute(ClassLoaderDat
u2 argument_count = cfs->get_u2_fast(); u2 argument_count = cfs->get_u2_fast();
check_property( check_property(
valid_cp_range(bootstrap_method_index, cp_size) && 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 %u has bad constant type in class file %s",
bootstrap_method_index, bootstrap_method_index,
CHECK); CHECK);
...@@ -2868,7 +2779,7 @@ void ClassFileParser::parse_classfile_bootstrap_methods_attribute(ClassLoaderDat ...@@ -2868,7 +2779,7 @@ void ClassFileParser::parse_classfile_bootstrap_methods_attribute(ClassLoaderDat
u2 argument_index = cfs->get_u2_fast(); u2 argument_index = cfs->get_u2_fast();
check_property( check_property(
valid_cp_range(argument_index, cp_size) && 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 %u has bad constant type in class file %s",
argument_index, argument_index,
CHECK); CHECK);
...@@ -2883,17 +2794,13 @@ void ClassFileParser::parse_classfile_bootstrap_methods_attribute(ClassLoaderDat ...@@ -2883,17 +2794,13 @@ void ClassFileParser::parse_classfile_bootstrap_methods_attribute(ClassLoaderDat
guarantee_property(current_end == current_start + attribute_byte_length, guarantee_property(current_end == current_start + attribute_byte_length,
"Bad length on BootstrapMethods in class file %s", "Bad length on BootstrapMethods in class file %s",
CHECK); CHECK);
cp->set_operands(operands);
} }
void ClassFileParser::parse_classfile_attributes(ClassLoaderData* loader_data, void ClassFileParser::parse_classfile_attributes(ClassFileParser::ClassAnnotationCollector* parsed_annotations,
constantPoolHandle cp,
ClassFileParser::ClassAnnotationCollector* parsed_annotations,
TRAPS) { TRAPS) {
ClassFileStream* cfs = stream(); ClassFileStream* cfs = stream();
// Set inner classes attribute to default sentinel // 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 cfs->guarantee_more(2, CHECK); // attributes_count
u2 attributes_count = cfs->get_u2_fast(); u2 attributes_count = cfs->get_u2_fast();
bool parsed_sourcefile_attribute = false; bool parsed_sourcefile_attribute = false;
...@@ -2918,11 +2825,10 @@ void ClassFileParser::parse_classfile_attributes(ClassLoaderData* loader_data, ...@@ -2918,11 +2825,10 @@ void ClassFileParser::parse_classfile_attributes(ClassLoaderData* loader_data,
u2 attribute_name_index = cfs->get_u2_fast(); u2 attribute_name_index = cfs->get_u2_fast();
u4 attribute_length = cfs->get_u4_fast(); u4 attribute_length = cfs->get_u4_fast();
check_property( check_property(
valid_cp_range(attribute_name_index, cp->length()) && valid_symbol_at(attribute_name_index),
cp->tag_at(attribute_name_index).is_utf8(),
"Attribute name has bad constant pool index %u in class file %s", "Attribute name has bad constant pool index %u in class file %s",
attribute_name_index, CHECK); 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()) { if (tag == vmSymbols::tag_source_file()) {
// Check for SourceFile tag // Check for SourceFile tag
if (_need_verify) { if (_need_verify) {
...@@ -2933,10 +2839,10 @@ void ClassFileParser::parse_classfile_attributes(ClassLoaderData* loader_data, ...@@ -2933,10 +2839,10 @@ void ClassFileParser::parse_classfile_attributes(ClassLoaderData* loader_data,
} else { } else {
parsed_sourcefile_attribute = true; parsed_sourcefile_attribute = true;
} }
parse_classfile_sourcefile_attribute(cp, CHECK); parse_classfile_sourcefile_attribute(CHECK);
} else if (tag == vmSymbols::tag_source_debug_extension()) { } else if (tag == vmSymbols::tag_source_debug_extension()) {
// Check for SourceDebugExtension tag // 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()) { } else if (tag == vmSymbols::tag_inner_classes()) {
// Check for InnerClasses tag // Check for InnerClasses tag
if (parsed_innerclasses_attribute) { if (parsed_innerclasses_attribute) {
...@@ -2955,7 +2861,7 @@ void ClassFileParser::parse_classfile_attributes(ClassLoaderData* loader_data, ...@@ -2955,7 +2861,7 @@ void ClassFileParser::parse_classfile_attributes(ClassLoaderData* loader_data,
"Invalid Synthetic classfile attribute length %u in class file %s", "Invalid Synthetic classfile attribute length %u in class file %s",
attribute_length, CHECK); attribute_length, CHECK);
} }
parse_classfile_synthetic_attribute(cp, CHECK); parse_classfile_synthetic_attribute(CHECK);
} else if (tag == vmSymbols::tag_deprecated()) { } else if (tag == vmSymbols::tag_deprecated()) {
// Check for Deprecatd tag - 4276120 // Check for Deprecatd tag - 4276120
if (attribute_length != 0) { if (attribute_length != 0) {
...@@ -2970,15 +2876,13 @@ void ClassFileParser::parse_classfile_attributes(ClassLoaderData* loader_data, ...@@ -2970,15 +2876,13 @@ void ClassFileParser::parse_classfile_attributes(ClassLoaderData* loader_data,
"Wrong Signature attribute length %u in class file %s", "Wrong Signature attribute length %u in class file %s",
attribute_length, CHECK); attribute_length, CHECK);
} }
parse_classfile_signature_attribute(cp, CHECK); parse_classfile_signature_attribute(CHECK);
} else if (tag == vmSymbols::tag_runtime_visible_annotations()) { } else if (tag == vmSymbols::tag_runtime_visible_annotations()) {
runtime_visible_annotations_length = attribute_length; runtime_visible_annotations_length = attribute_length;
runtime_visible_annotations = cfs->get_u1_buffer(); runtime_visible_annotations = cfs->get_u1_buffer();
assert(runtime_visible_annotations != NULL, "null visible annotations"); assert(runtime_visible_annotations != NULL, "null visible annotations");
parse_annotations(loader_data, parse_annotations(runtime_visible_annotations,
runtime_visible_annotations,
runtime_visible_annotations_length, runtime_visible_annotations_length,
cp,
parsed_annotations, parsed_annotations,
CHECK); CHECK);
cfs->skip_u1(runtime_visible_annotations_length, CHECK); cfs->skip_u1(runtime_visible_annotations_length, CHECK);
...@@ -3000,13 +2904,11 @@ void ClassFileParser::parse_classfile_attributes(ClassLoaderData* loader_data, ...@@ -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); classfile_parse_error("Invalid class index in EnclosingMethod attribute in class file %s", CHECK);
} }
// Validate the constant pool indices and types // Validate the constant pool indices and types
if (!cp->is_within_bounds(enclosing_method_class_index) || check_property(valid_klass_reference_at(enclosing_method_class_index),
!is_klass_reference(cp, enclosing_method_class_index)) { "Invalid or out-of-bounds class index in EnclosingMethod attribute in class file %s", CHECK);
classfile_parse_error("Invalid or out-of-bounds class index in EnclosingMethod attribute in class file %s", CHECK);
}
if (enclosing_method_method_index != 0 && if (enclosing_method_method_index != 0 &&
(!cp->is_within_bounds(enclosing_method_method_index) || (!_cp->is_within_bounds(enclosing_method_method_index) ||
!cp->tag_at(enclosing_method_method_index).is_name_and_type())) { !_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); 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() && } else if (tag == vmSymbols::tag_bootstrap_methods() &&
...@@ -3014,7 +2916,7 @@ void ClassFileParser::parse_classfile_attributes(ClassLoaderData* loader_data, ...@@ -3014,7 +2916,7 @@ void ClassFileParser::parse_classfile_attributes(ClassLoaderData* loader_data,
if (parsed_bootstrap_methods_attribute) if (parsed_bootstrap_methods_attribute)
classfile_parse_error("Multiple BootstrapMethods attributes in class file %s", CHECK); classfile_parse_error("Multiple BootstrapMethods attributes in class file %s", CHECK);
parsed_bootstrap_methods_attribute = true; 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()) { } else if (tag == vmSymbols::tag_runtime_visible_type_annotations()) {
runtime_visible_type_annotations_length = attribute_length; runtime_visible_type_annotations_length = attribute_length;
runtime_visible_type_annotations = cfs->get_u1_buffer(); runtime_visible_type_annotations = cfs->get_u1_buffer();
...@@ -3035,29 +2937,24 @@ void ClassFileParser::parse_classfile_attributes(ClassLoaderData* loader_data, ...@@ -3035,29 +2937,24 @@ void ClassFileParser::parse_classfile_attributes(ClassLoaderData* loader_data,
cfs->skip_u1(attribute_length, CHECK); cfs->skip_u1(attribute_length, CHECK);
} }
} }
AnnotationArray* annotations = assemble_annotations(loader_data, _annotations = assemble_annotations(runtime_visible_annotations,
runtime_visible_annotations, runtime_visible_annotations_length,
runtime_visible_annotations_length, runtime_invisible_annotations,
runtime_invisible_annotations, runtime_invisible_annotations_length,
runtime_invisible_annotations_length, CHECK);
CHECK); _type_annotations = assemble_annotations(runtime_visible_type_annotations,
set_class_annotations(annotations); runtime_visible_type_annotations_length,
AnnotationArray* type_annotations = assemble_annotations(loader_data, runtime_invisible_type_annotations,
runtime_visible_type_annotations, runtime_invisible_type_annotations_length,
runtime_visible_type_annotations_length, CHECK);
runtime_invisible_type_annotations,
runtime_invisible_type_annotations_length,
CHECK);
set_class_type_annotations(type_annotations);
if (parsed_innerclasses_attribute || parsed_enclosingmethod_attribute) { if (parsed_innerclasses_attribute || parsed_enclosingmethod_attribute) {
u2 num_of_classes = parse_classfile_inner_classes_attribute( u2 num_of_classes = parse_classfile_inner_classes_attribute(
loader_data,
inner_classes_attribute_start, inner_classes_attribute_start,
parsed_innerclasses_attribute, parsed_innerclasses_attribute,
enclosing_method_class_index, enclosing_method_class_index,
enclosing_method_method_index, enclosing_method_method_index,
cp, CHECK); CHECK);
if (parsed_innerclasses_attribute &&_need_verify && _major_version >= JAVA_1_5_VERSION) { if (parsed_innerclasses_attribute &&_need_verify && _major_version >= JAVA_1_5_VERSION) {
guarantee_property( guarantee_property(
inner_classes_attribute_length == sizeof(num_of_classes) + 4 * sizeof(u2) * num_of_classes, 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) { ...@@ -3085,18 +2982,43 @@ void ClassFileParser::apply_parsed_class_attributes(instanceKlassHandle k) {
if (_sde_buffer != NULL) { if (_sde_buffer != NULL) {
k->set_source_debug_extension(_sde_buffer, _sde_length); k->set_source_debug_extension(_sde_buffer, _sde_length);
} }
k->set_inner_classes(_inner_classes);
} }
AnnotationArray* ClassFileParser::assemble_annotations(ClassLoaderData* loader_data, // Transfer ownership of metadata allocated to the InstanceKlass.
u1* runtime_visible_annotations, 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, int runtime_visible_annotations_length,
u1* runtime_invisible_annotations, u1* runtime_invisible_annotations,
int runtime_invisible_annotations_length, TRAPS) { int runtime_invisible_annotations_length, TRAPS) {
AnnotationArray* annotations = NULL; AnnotationArray* annotations = NULL;
if (runtime_visible_annotations != NULL || if (runtime_visible_annotations != NULL ||
runtime_invisible_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_visible_annotations_length +
runtime_invisible_annotations_length, runtime_invisible_annotations_length,
CHECK_(annotations)); CHECK_(annotations));
...@@ -3144,6 +3066,581 @@ static void parseAndPrintGenericSignatures( ...@@ -3144,6 +3066,581 @@ static void parseAndPrintGenericSignatures(
#endif // ndef PRODUCT #endif // ndef PRODUCT
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;
}
// 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;
};
// 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) {
// get the padding width from the option
// TODO: Ask VM about specific CPU we are running on
int pad_size = ContendedPaddingWidth;
// Field size and offset computation
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;
// 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;
}
next_nonstatic_field_offset = first_nonstatic_field_offset;
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];
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);
// Prepare list of oops for oop map generation.
int* nonstatic_oop_offsets;
unsigned int* nonstatic_oop_counts;
unsigned int nonstatic_oop_map_count = 0;
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);
first_nonstatic_oop_offset = 0; // will be set for first oop field
#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
}
// 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
}
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( allocation_style == 2 ) {
allocation_style = 1; // allocate oops last
next_nonstatic_double_offset = next_nonstatic_field_offset;
}
} else {
ShouldNotReachHere();
}
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;
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;
}
// 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;
}
}
}
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;
// 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()) {
// skip already laid out fields
if (fs.is_offset_set()) continue;
// contended instance fields are handled below
if (fs.is_contended() && !fs.access_flags().is_static()) continue;
int real_offset;
FieldAllocationType atype = (FieldAllocationType) fs.allocation_type();
// 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);
}
// Handle the contended cases.
//
// Each contended field should not intersect the cache line with another contended field.
// In the absence of alignment information, we end up with pessimistically separating
// the fields with full-width padding.
//
// Additionally, this should not break alignment for the fields, so we round the alignment up
// for each field.
if (contended_count > 0) {
// if there is at least one contended field, we need to have pre-padding for them
if (nonstatic_contended_count > 0) {
next_nonstatic_padded_offset += pad_size;
}
// collect all contended groups
BitMap bm(_cp->size());
for (AllFieldStream fs(_fields, _cp); !fs.done(); fs.next()) {
// skip already laid out fields
if (fs.is_offset_set()) continue;
if (fs.is_contended()) {
bm.set_bit(fs.contended_group());
}
}
int current_group = -1;
while ((current_group = (int)bm.get_next_one_offset(current_group + 1)) != (int)bm.size()) {
for (AllFieldStream fs(_fields, _cp); !fs.done(); fs.next()) {
// skip already laid out fields
if (fs.is_offset_set()) continue;
// skip non-contended fields and fields from different group
if (!fs.is_contended() || (fs.contended_group() != current_group)) continue;
// handle statics below
if (fs.access_flags().is_static()) continue;
int real_offset;
FieldAllocationType atype = (FieldAllocationType) fs.allocation_type();
switch (atype) {
case NONSTATIC_BYTE:
next_nonstatic_padded_offset = align_size_up(next_nonstatic_padded_offset, 1);
real_offset = next_nonstatic_padded_offset;
next_nonstatic_padded_offset += 1;
break;
case NONSTATIC_SHORT:
next_nonstatic_padded_offset = align_size_up(next_nonstatic_padded_offset, BytesPerShort);
real_offset = next_nonstatic_padded_offset;
next_nonstatic_padded_offset += BytesPerShort;
break;
case NONSTATIC_WORD:
next_nonstatic_padded_offset = align_size_up(next_nonstatic_padded_offset, BytesPerInt);
real_offset = next_nonstatic_padded_offset;
next_nonstatic_padded_offset += BytesPerInt;
break;
case NONSTATIC_DOUBLE:
next_nonstatic_padded_offset = align_size_up(next_nonstatic_padded_offset, BytesPerLong);
real_offset = next_nonstatic_padded_offset;
next_nonstatic_padded_offset += BytesPerLong;
break;
case NONSTATIC_OOP:
next_nonstatic_padded_offset = align_size_up(next_nonstatic_padded_offset, heapOopSize);
real_offset = next_nonstatic_padded_offset;
next_nonstatic_padded_offset += heapOopSize;
// Create new oop map
nonstatic_oop_offsets[nonstatic_oop_map_count] = real_offset;
nonstatic_oop_counts [nonstatic_oop_map_count] = 1;
nonstatic_oop_map_count += 1;
if( first_nonstatic_oop_offset == 0 ) { // Undefined
first_nonstatic_oop_offset = real_offset;
}
break;
default:
ShouldNotReachHere();
}
if (fs.contended_group() == 0) {
// Contended group defines the equivalence class over the fields:
// the fields within the same contended group are not inter-padded.
// The only exception is default group, which does not incur the
// equivalence, and so requires intra-padding.
next_nonstatic_padded_offset += pad_size;
}
fs.set_offset(real_offset);
} // for
// Start laying out the next group.
// Note that this will effectively pad the last group in the back;
// this is expected to alleviate memory contention effects for
// subclass fields and/or adjacent object.
// If this was the default group, the padding is already in place.
if (current_group != 0) {
next_nonstatic_padded_offset += pad_size;
}
}
// handle static fields
}
// Size of instances
int notaligned_offset = next_nonstatic_padded_offset;
// Entire class is contended, pad in the back.
// This helps to alleviate memory contention effects for subclass fields
// and/or adjacent object.
if (parsed_annotations->is_contended()) {
notaligned_offset += pad_size;
}
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);
}
#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;
}
instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
ClassLoaderData* loader_data, ClassLoaderData* loader_data,
Handle protection_domain, Handle protection_domain,
...@@ -3176,7 +3673,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, ...@@ -3176,7 +3673,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
jt->get_thread_stat()->perf_timers_addr(), jt->get_thread_stat()->perf_timers_addr(),
PerfClassTraceTime::PARSE_CLASS); PerfClassTraceTime::PARSE_CLASS);
init_parsed_class_attributes(); init_parsed_class_attributes(loader_data);
if (JvmtiExport::should_post_class_file_load_hook()) { if (JvmtiExport::should_post_class_file_load_hook()) {
// Get the cached class file bytes (if any) from the class that // Get the cached class file bytes (if any) from the class that
...@@ -3271,8 +3768,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, ...@@ -3271,8 +3768,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
_relax_verify = Verifier::relax_verify_for(class_loader()); _relax_verify = Verifier::relax_verify_for(class_loader());
// Constant pool // Constant pool
constantPoolHandle cp = parse_constant_pool(loader_data, CHECK_(nullHandle)); constantPoolHandle cp = parse_constant_pool(CHECK_(nullHandle));
ConstantPoolCleaner error_handler(cp); // set constant pool to be cleaned up.
int cp_size = cp->length(); int cp_size = cp->length();
...@@ -3290,7 +3786,6 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, ...@@ -3290,7 +3786,6 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
access_flags.set_flags(flags); access_flags.set_flags(flags);
// This class and superclass // This class and superclass
instanceKlassHandle super_klass;
u2 this_class_index = cfs->get_u2_fast(); u2 this_class_index = cfs->get_u2_fast();
check_property( check_property(
valid_cp_range(this_class_index, cp_size) && valid_cp_range(this_class_index, cp_size) &&
...@@ -3345,59 +3840,27 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, ...@@ -3345,59 +3840,27 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
} }
u2 super_class_index = cfs->get_u2_fast(); u2 super_class_index = cfs->get_u2_fast();
if (super_class_index == 0) { instanceKlassHandle super_klass = parse_super_class(super_class_index,
check_property(class_name == vmSymbols::java_lang_Object(), CHECK_NULL);
"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 (_need_verify) {
guarantee_property(!is_array,
"Bad superclass name in class file %s", CHECK_(nullHandle));
}
}
// Interfaces // Interfaces
u2 itfs_len = cfs->get_u2_fast(); u2 itfs_len = cfs->get_u2_fast();
Array<Klass*>* local_interfaces; Array<Klass*>* local_interfaces =
if (itfs_len == 0) { parse_interfaces(itfs_len, protection_domain, _class_name,
local_interfaces = Universe::the_empty_klass_array(); &has_default_methods, CHECK_(nullHandle));
} else {
local_interfaces = parse_interfaces(
cp, itfs_len, loader_data, protection_domain, _class_name,
&has_default_methods, CHECK_(nullHandle));
}
u2 java_fields_count = 0; u2 java_fields_count = 0;
// Fields (offsets are filled in later) // Fields (offsets are filled in later)
FieldAllocationCount fac; FieldAllocationCount fac;
Array<AnnotationArray*>* fields_annotations = NULL; Array<u2>* fields = parse_fields(class_name,
Array<AnnotationArray*>* fields_type_annotations = NULL; access_flags.is_interface(),
Array<u2>* fields = parse_fields(loader_data, class_name, cp, access_flags.is_interface(), &fac, &fields_annotations, &fac, &java_fields_count,
&fields_type_annotations, CHECK_(nullHandle));
&java_fields_count,
CHECK_(nullHandle));
// Methods // Methods
bool has_final_method = false; bool has_final_method = false;
AccessFlags promoted_flags; AccessFlags promoted_flags;
promoted_flags.set_flags(0); promoted_flags.set_flags(0);
Array<Method*>* methods = parse_methods(loader_data, Array<Method*>* methods = parse_methods(access_flags.is_interface(),
cp, access_flags.is_interface(),
&promoted_flags, &promoted_flags,
&has_final_method, &has_final_method,
&has_default_methods, &has_default_methods,
...@@ -3405,7 +3868,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, ...@@ -3405,7 +3868,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
// Additional attributes // Additional attributes
ClassAnnotationCollector parsed_annotations; ClassAnnotationCollector parsed_annotations;
parse_classfile_attributes(loader_data, cp, &parsed_annotations, CHECK_(nullHandle)); parse_classfile_attributes(&parsed_annotations, CHECK_(nullHandle));
// Make sure this is the end of class file stream // 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)); guarantee_property(cfs->at_eos(), "Extra bytes at the end of class file %s", CHECK_(nullHandle));
...@@ -3452,13 +3915,15 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, ...@@ -3452,13 +3915,15 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
} }
} }
// save super klass for error handling.
_super_klass = super_klass;
// Compute the transitive list of all unique interfaces implemented by this class // 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)); _transitive_interfaces =
compute_transitive_interfaces(super_klass, local_interfaces, CHECK_(nullHandle));
// sort methods // sort methods
Array<int>* method_ordering = sort_methods(loader_data, intArray* method_ordering = sort_methods(methods);
methods,
CHECK_(nullHandle));
// promote flags from parse_methods() to the klass' flags // promote flags from parse_methods() to the klass' flags
access_flags.add_promoted_flags(promoted_flags.as_int()); access_flags.add_promoted_flags(promoted_flags.as_int());
...@@ -3476,495 +3941,14 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, ...@@ -3476,495 +3941,14 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
CHECK_(nullHandle)); CHECK_(nullHandle));
// Size of Java itable (in words) // Size of Java itable (in words)
itable_size = access_flags.is_interface() ? 0 : klassItable::compute_itable_size(transitive_interfaces); itable_size = access_flags.is_interface() ? 0 : klassItable::compute_itable_size(_transitive_interfaces);
// get the padding width from the option
// TODO: Ask VM about specific CPU we are running on
int pad_size = ContendedPaddingWidth;
// Field size and offset computation
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;
// 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;
}
next_nonstatic_field_offset = first_nonstatic_field_offset;
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];
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);
// Prepare list of oops for oop map generation.
int* nonstatic_oop_offsets;
unsigned int* nonstatic_oop_counts;
unsigned int nonstatic_oop_map_count = 0;
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);
first_nonstatic_oop_offset = 0; // will be set for first oop field
#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
}
// 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
}
if( allocation_style == 0 ) { FieldLayoutInfo info;
// Fields order: oops, longs/doubles, ints, shorts/chars, bytes, padded fields layout_fields(class_loader, &fac, &parsed_annotations, &info, CHECK_NULL);
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( allocation_style == 2 ) {
allocation_style = 1; // allocate oops last
next_nonstatic_double_offset = next_nonstatic_field_offset;
}
} else {
ShouldNotReachHere();
}
int nonstatic_oop_space_count = 0; int total_oop_map_size2 =
int nonstatic_word_space_count = 0; InstanceKlass::nonstatic_oop_map_size(info.total_oop_map_count);
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;
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;
}
// 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;
}
}
}
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;
// 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()) {
// skip already laid out fields
if (fs.is_offset_set()) continue;
// contended instance fields are handled below
if (fs.is_contended() && !fs.access_flags().is_static()) continue;
int real_offset;
FieldAllocationType atype = (FieldAllocationType) fs.allocation_type();
// 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);
}
// Handle the contended cases.
//
// Each contended field should not intersect the cache line with another contended field.
// In the absence of alignment information, we end up with pessimistically separating
// the fields with full-width padding.
//
// Additionally, this should not break alignment for the fields, so we round the alignment up
// for each field.
if (contended_count > 0) {
// if there is at least one contended field, we need to have pre-padding for them
if (nonstatic_contended_count > 0) {
next_nonstatic_padded_offset += pad_size;
}
// collect all contended groups
BitMap bm(cp->size());
for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) {
// skip already laid out fields
if (fs.is_offset_set()) continue;
if (fs.is_contended()) {
bm.set_bit(fs.contended_group());
}
}
int current_group = -1;
while ((current_group = (int)bm.get_next_one_offset(current_group + 1)) != (int)bm.size()) {
for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) {
// skip already laid out fields
if (fs.is_offset_set()) continue;
// skip non-contended fields and fields from different group
if (!fs.is_contended() || (fs.contended_group() != current_group)) continue;
// handle statics below
if (fs.access_flags().is_static()) continue;
int real_offset;
FieldAllocationType atype = (FieldAllocationType) fs.allocation_type();
switch (atype) {
case NONSTATIC_BYTE:
next_nonstatic_padded_offset = align_size_up(next_nonstatic_padded_offset, 1);
real_offset = next_nonstatic_padded_offset;
next_nonstatic_padded_offset += 1;
break;
case NONSTATIC_SHORT:
next_nonstatic_padded_offset = align_size_up(next_nonstatic_padded_offset, BytesPerShort);
real_offset = next_nonstatic_padded_offset;
next_nonstatic_padded_offset += BytesPerShort;
break;
case NONSTATIC_WORD:
next_nonstatic_padded_offset = align_size_up(next_nonstatic_padded_offset, BytesPerInt);
real_offset = next_nonstatic_padded_offset;
next_nonstatic_padded_offset += BytesPerInt;
break;
case NONSTATIC_DOUBLE:
next_nonstatic_padded_offset = align_size_up(next_nonstatic_padded_offset, BytesPerLong);
real_offset = next_nonstatic_padded_offset;
next_nonstatic_padded_offset += BytesPerLong;
break;
case NONSTATIC_OOP:
next_nonstatic_padded_offset = align_size_up(next_nonstatic_padded_offset, heapOopSize);
real_offset = next_nonstatic_padded_offset;
next_nonstatic_padded_offset += heapOopSize;
// Create new oop map
nonstatic_oop_offsets[nonstatic_oop_map_count] = real_offset;
nonstatic_oop_counts [nonstatic_oop_map_count] = 1;
nonstatic_oop_map_count += 1;
if( first_nonstatic_oop_offset == 0 ) { // Undefined
first_nonstatic_oop_offset = real_offset;
}
break;
default:
ShouldNotReachHere();
}
if (fs.contended_group() == 0) {
// Contended group defines the equivalence class over the fields:
// the fields within the same contended group are not inter-padded.
// The only exception is default group, which does not incur the
// equivalence, and so requires intra-padding.
next_nonstatic_padded_offset += pad_size;
}
fs.set_offset(real_offset);
} // for
// Start laying out the next group.
// Note that this will effectively pad the last group in the back;
// this is expected to alleviate memory contention effects for
// subclass fields and/or adjacent object.
// If this was the default group, the padding is already in place.
if (current_group != 0) {
next_nonstatic_padded_offset += pad_size;
}
}
// handle static fields
} // handle contended
// Size of instances
int instance_size;
int notaligned_offset = next_nonstatic_padded_offset;
// Entire class is contended, pad in the back.
// This helps to alleviate memory contention effects for subclass fields
// and/or adjacent object.
if (parsed_annotations.is_contended()) {
notaligned_offset += pad_size;
}
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 );
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);
// Compute reference type // Compute reference type
ReferenceType rt; ReferenceType rt;
if (super_klass() == NULL) { if (super_klass() == NULL) {
...@@ -3974,53 +3958,42 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, ...@@ -3974,53 +3958,42 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
} }
// We can now create the basic Klass* for this klass // We can now create the basic Klass* for this klass
int total_oop_map_size2 = _klass = InstanceKlass::allocate_instance_klass(loader_data,
InstanceKlass::nonstatic_oop_map_size(total_oop_map_count); vtable_size,
itable_size,
Klass* ik = InstanceKlass::allocate_instance_klass(loader_data, info.static_field_size,
vtable_size, total_oop_map_size2,
itable_size, rt,
static_field_size, access_flags,
total_oop_map_size2, name,
rt, super_klass(),
access_flags, !host_klass.is_null(),
name, CHECK_(nullHandle));
super_klass(), instanceKlassHandle this_klass (THREAD, _klass);
!host_klass.is_null(),
CHECK_(nullHandle)); assert(this_klass->static_field_size() == info.static_field_size, "sanity");
assert(this_klass->nonstatic_oop_map_count() == info.total_oop_map_count,
// 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,
"sanity"); "sanity");
// Fill in information already parsed // Fill in information already parsed
this_klass->set_should_verify_class(verify); 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); this_klass->set_layout_helper(lh);
assert(this_klass->oop_is_instance(), "layout is correct"); 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 // Not yet: supers are done below to support the new subtype-checking fields
//this_klass->set_super(super_klass()); //this_klass->set_super(super_klass());
this_klass->set_class_loader_data(loader_data); this_klass->set_class_loader_data(loader_data);
this_klass->set_nonstatic_field_size(nonstatic_field_size); this_klass->set_nonstatic_field_size(info.nonstatic_field_size);
this_klass->set_has_nonstatic_fields(has_nonstatic_fields); this_klass->set_has_nonstatic_fields(info.has_nonstatic_fields);
this_klass->set_static_oop_field_count(fac.count[STATIC_OOP]); 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 apply_parsed_class_metadata(this_klass, java_fields_count, CHECK_NULL);
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);
if (has_final_method) { if (has_final_method) {
this_klass->set_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 // The InstanceKlass::_methods_jmethod_ids cache and the
// InstanceKlass::_methods_cached_itable_indices cache are // InstanceKlass::_methods_cached_itable_indices cache are
// both managed on the assumption that the initial cache // both managed on the assumption that the initial cache
...@@ -4032,17 +4005,6 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, ...@@ -4032,17 +4005,6 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
if (is_anonymous()) // I am well known to myself if (is_anonymous()) // I am well known to myself
cp->klass_at_put(this_class_index, this_klass()); // eagerly resolve 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_minor_version(minor_version);
this_klass->set_major_version(major_version); this_klass->set_major_version(major_version);
this_klass->set_has_default_methods(has_default_methods); this_klass->set_has_default_methods(has_default_methods);
...@@ -4077,8 +4039,6 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, ...@@ -4077,8 +4039,6 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
this_klass->set_has_miranda_methods(); // then set a flag this_klass->set_has_miranda_methods(); // then set a flag
} }
this_klass->set_transitive_interfaces(transitive_interfaces);
// Fill in information needed to compute superclasses. // Fill in information needed to compute superclasses.
this_klass->initialize_supers(super_klass(), CHECK_(nullHandle)); this_klass->initialize_supers(super_klass(), CHECK_(nullHandle));
...@@ -4087,7 +4047,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, ...@@ -4087,7 +4047,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
// Compute transitive closure of interfaces this class implements // Compute transitive closure of interfaces this class implements
// Do final class setup // 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 // Fill in has_finalizer, has_vanilla_constructor, and layout_helper
set_precomputed_flags(this_klass); set_precomputed_flags(this_klass);
...@@ -4186,35 +4146,6 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, ...@@ -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 result across HandleMark
preserve_this_klass = this_klass(); preserve_this_klass = this_klass();
} }
...@@ -4224,9 +4155,40 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, ...@@ -4224,9 +4155,40 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
instanceKlassHandle this_klass (THREAD, preserve_this_klass); instanceKlassHandle this_klass (THREAD, preserve_this_klass);
debug_only(this_klass->verify();) debug_only(this_klass->verify();)
// Clear class if no error has occurred so destructor doesn't deallocate it
_klass = NULL;
return this_klass; 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, void ClassFileParser::print_field_layout(Symbol* name,
Array<u2>* fields, Array<u2>* fields,
constantPoolHandle cp, constantPoolHandle cp,
...@@ -4418,7 +4380,7 @@ void ClassFileParser::record_defined_class_dependencies(instanceKlassHandle defi ...@@ -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) { void append_interfaces(GrowableArray<Klass*>* result, Array<Klass*>* ifs) {
// iterate over new interfaces // iterate over new interfaces
...@@ -4430,8 +4392,9 @@ void append_interfaces(GrowableArray<Klass*>* result, Array<Klass*>* ifs) { ...@@ -4430,8 +4392,9 @@ void append_interfaces(GrowableArray<Klass*>* result, Array<Klass*>* ifs) {
} }
} }
Array<Klass*>* ClassFileParser::compute_transitive_interfaces(
Array<Klass*>* ClassFileParser::compute_transitive_interfaces(ClassLoaderData* loader_data, instanceKlassHandle super, Array<Klass*>* local_ifs, TRAPS) { instanceKlassHandle super,
Array<Klass*>* local_ifs, TRAPS) {
// Compute maximum size for transitive interfaces // Compute maximum size for transitive interfaces
int max_transitive_size = 0; int max_transitive_size = 0;
int super_size = 0; int super_size = 0;
...@@ -4478,7 +4441,7 @@ Array<Klass*>* ClassFileParser::compute_transitive_interfaces(ClassLoaderData* l ...@@ -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 // length will be less than the max_transitive_size if duplicates were removed
int length = result->length(); int length = result->length();
assert(length <= max_transitive_size, "just checking"); 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++) { for (int i = 0; i < length; i++) {
Klass* e = result->at(i); Klass* e = result->at(i);
assert(e != NULL, "just checking"); assert(e != NULL, "just checking");
...@@ -4488,7 +4451,6 @@ Array<Klass*>* ClassFileParser::compute_transitive_interfaces(ClassLoaderData* l ...@@ -4488,7 +4451,6 @@ Array<Klass*>* ClassFileParser::compute_transitive_interfaces(ClassLoaderData* l
} }
} }
void ClassFileParser::check_super_class_access(instanceKlassHandle this_klass, TRAPS) { void ClassFileParser::check_super_class_access(instanceKlassHandle this_klass, TRAPS) {
Klass* super = this_klass->super(); Klass* super = this_klass->super();
if ((super != NULL) && if ((super != NULL) &&
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include "classfile/symbolTable.hpp" #include "classfile/symbolTable.hpp"
class FieldAllocationCount; class FieldAllocationCount;
class FieldLayoutInfo;
// Parser for for .class files // Parser for for .class files
...@@ -47,6 +48,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { ...@@ -47,6 +48,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
u2 _major_version; u2 _major_version;
u2 _minor_version; u2 _minor_version;
Symbol* _class_name; Symbol* _class_name;
ClassLoaderData* _loader_data;
KlassHandle _host_klass; KlassHandle _host_klass;
GrowableArray<Handle>* _cp_patches; // overrides for CP entries GrowableArray<Handle>* _cp_patches; // overrides for CP entries
...@@ -58,33 +60,59 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { ...@@ -58,33 +60,59 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
// class attributes parsed before the instance klass is created: // class attributes parsed before the instance klass is created:
bool _synthetic_flag; bool _synthetic_flag;
int _sde_length;
char* _sde_buffer;
Symbol* _sourcefile; Symbol* _sourcefile;
Symbol* _generic_signature; Symbol* _generic_signature;
char* _sde_buffer;
int _sde_length; // Metadata created before the instance klass is created. Must be deallocated
Array<u2>* _inner_classes; // 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* _annotations;
AnnotationArray* _type_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_synthetic_flag(bool x) { _synthetic_flag = x; }
void set_class_sourcefile(Symbol* x) { _sourcefile = x; } void set_class_sourcefile(Symbol* x) { _sourcefile = x; }
void set_class_generic_signature(Symbol* x) { _generic_signature = 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_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 init_parsed_class_attributes(ClassLoaderData* loader_data) {
void set_class_type_annotations(AnnotationArray* x) { _type_annotations = x; } _loader_data = loader_data;
void init_parsed_class_attributes() {
_synthetic_flag = false; _synthetic_flag = false;
_sourcefile = NULL; _sourcefile = NULL;
_generic_signature = NULL; _generic_signature = NULL;
_sde_buffer = NULL; _sde_buffer = NULL;
_sde_length = 0; _sde_length = 0;
_annotations = _type_annotations = NULL;
// initialize the other flags too: // initialize the other flags too:
_has_finalizer = _has_empty_finalizer = _has_vanilla_constructor = false; _has_finalizer = _has_empty_finalizer = _has_vanilla_constructor = false;
_max_bootstrap_specifier_index = -1; _max_bootstrap_specifier_index = -1;
clear_class_metadata();
_klass = NULL;
} }
void apply_parsed_class_attributes(instanceKlassHandle k); // update k 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 { class AnnotationCollector {
public: public:
...@@ -124,11 +152,27 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { ...@@ -124,11 +152,27 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
void set_contended(bool contended) { set_annotation(_sun_misc_Contended); } void set_contended(bool contended) { set_annotation(_sun_misc_Contended); }
bool is_contended() { return has_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 { class FieldAnnotationCollector: public AnnotationCollector {
ClassLoaderData* _loader_data;
AnnotationArray* _field_annotations;
AnnotationArray* _field_type_annotations;
public: 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); 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 { class MethodAnnotationCollector: public AnnotationCollector {
public: public:
MethodAnnotationCollector() : AnnotationCollector(_in_method) { } MethodAnnotationCollector() : AnnotationCollector(_in_method) { }
...@@ -152,38 +196,30 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { ...@@ -152,38 +196,30 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
void set_stream(ClassFileStream* st) { _stream = st; } void set_stream(ClassFileStream* st) { _stream = st; }
// Constant pool parsing // Constant pool parsing
void parse_constant_pool_entries(ClassLoaderData* loader_data, void parse_constant_pool_entries(int length, TRAPS);
constantPoolHandle cp, int length, TRAPS);
constantPoolHandle parse_constant_pool(ClassLoaderData* loader_data, TRAPS); constantPoolHandle parse_constant_pool(TRAPS);
// Interface parsing // Interface parsing
Array<Klass*>* parse_interfaces(constantPoolHandle cp, Array<Klass*>* parse_interfaces(int length,
int length,
ClassLoaderData* loader_data,
Handle protection_domain, Handle protection_domain,
Symbol* class_name, Symbol* class_name,
bool* has_default_methods, bool* has_default_methods,
TRAPS); TRAPS);
void record_defined_class_dependencies(instanceKlassHandle defined_klass, TRAPS); void record_defined_class_dependencies(instanceKlassHandle defined_klass, TRAPS);
instanceKlassHandle parse_super_class(int super_class_index, TRAPS);
// Field parsing // Field parsing
void parse_field_attributes(ClassLoaderData* loader_data, void parse_field_attributes(u2 attributes_count,
constantPoolHandle cp, u2 attributes_count,
bool is_static, u2 signature_index, bool is_static, u2 signature_index,
u2* constantvalue_index_addr, u2* constantvalue_index_addr,
bool* is_synthetic_addr, bool* is_synthetic_addr,
u2* generic_signature_index_addr, u2* generic_signature_index_addr,
AnnotationArray** field_annotations,
AnnotationArray** field_type_annotations,
FieldAnnotationCollector* parsed_annotations, FieldAnnotationCollector* parsed_annotations,
TRAPS); TRAPS);
Array<u2>* parse_fields(ClassLoaderData* loader_data, Array<u2>* parse_fields(Symbol* class_name,
Symbol* class_name, bool is_interface,
constantPoolHandle cp, bool is_interface,
FieldAllocationCount *fac, FieldAllocationCount *fac,
Array<AnnotationArray*>** fields_annotations,
Array<AnnotationArray*>** fields_type_annotations,
u2* java_fields_count_ptr, TRAPS); u2* java_fields_count_ptr, TRAPS);
void print_field_layout(Symbol* name, void print_field_layout(Symbol* name,
...@@ -195,65 +231,52 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { ...@@ -195,65 +231,52 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
int static_fields_end); int static_fields_end);
// Method parsing // Method parsing
methodHandle parse_method(ClassLoaderData* loader_data, methodHandle parse_method(bool is_interface,
constantPoolHandle cp,
bool is_interface,
AccessFlags* promoted_flags, AccessFlags* promoted_flags,
TRAPS); TRAPS);
Array<Method*>* parse_methods(ClassLoaderData* loader_data, Array<Method*>* parse_methods(bool is_interface,
constantPoolHandle cp,
bool is_interface,
AccessFlags* promoted_flags, AccessFlags* promoted_flags,
bool* has_final_method, bool* has_final_method,
bool* has_default_method, bool* has_default_method,
TRAPS); TRAPS);
Array<int>* sort_methods(ClassLoaderData* loader_data, intArray* sort_methods(Array<Method*>* methods);
Array<Method*>* methods,
TRAPS); u2* parse_exception_table(u4 code_length, u4 exception_table_length,
u2* parse_exception_table(ClassLoaderData* loader_data, TRAPS);
u4 code_length, u4 exception_table_length,
constantPoolHandle cp, TRAPS);
void parse_linenumber_table( void parse_linenumber_table(
u4 code_attribute_length, u4 code_length, u4 code_attribute_length, u4 code_length,
CompressedLineNumberWriteStream** write_stream, TRAPS); CompressedLineNumberWriteStream** write_stream, TRAPS);
u2* parse_localvariable_table(u4 code_length, u2 max_locals, u4 code_attribute_length, 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); bool isLVTT, TRAPS);
u2* parse_checked_exceptions(u2* checked_exceptions_length, u4 method_attribute_length, 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, 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); u1* u1_array, u2* u2_array, TRAPS);
Array<u1>* parse_stackmap_table(ClassLoaderData* loader_data, u4 code_attribute_length, TRAPS); u1* parse_stackmap_table(u4 code_attribute_length, TRAPS);
// Classfile attribute parsing // Classfile attribute parsing
void parse_classfile_sourcefile_attribute(constantPoolHandle cp, TRAPS); void parse_classfile_sourcefile_attribute(TRAPS);
void parse_classfile_source_debug_extension_attribute(constantPoolHandle cp, void parse_classfile_source_debug_extension_attribute(int length, TRAPS);
int length, TRAPS); u2 parse_classfile_inner_classes_attribute(u1* inner_classes_attribute_start,
u2 parse_classfile_inner_classes_attribute(ClassLoaderData* loader_data,
u1* inner_classes_attribute_start,
bool parsed_enclosingmethod_attribute, bool parsed_enclosingmethod_attribute,
u2 enclosing_method_class_index, u2 enclosing_method_class_index,
u2 enclosing_method_method_index, u2 enclosing_method_method_index,
constantPoolHandle cp,
TRAPS); TRAPS);
void parse_classfile_attributes(ClassLoaderData* loader_data, void parse_classfile_attributes(ClassAnnotationCollector* parsed_annotations,
constantPoolHandle cp,
ClassAnnotationCollector* parsed_annotations,
TRAPS); TRAPS);
void parse_classfile_synthetic_attribute(constantPoolHandle cp, TRAPS); void parse_classfile_synthetic_attribute(TRAPS);
void parse_classfile_signature_attribute(constantPoolHandle cp, TRAPS); void parse_classfile_signature_attribute(TRAPS);
void parse_classfile_bootstrap_methods_attribute(ClassLoaderData* loader_data, constantPoolHandle cp, u4 attribute_length, TRAPS); void parse_classfile_bootstrap_methods_attribute(u4 attribute_length, TRAPS);
// Annotations handling // Annotations handling
AnnotationArray* assemble_annotations(ClassLoaderData* loader_data, AnnotationArray* assemble_annotations(u1* runtime_visible_annotations,
u1* runtime_visible_annotations,
int runtime_visible_annotations_length, int runtime_visible_annotations_length,
u1* runtime_invisible_annotations, u1* runtime_invisible_annotations,
int runtime_invisible_annotations_length, TRAPS); int runtime_invisible_annotations_length, TRAPS);
int skip_annotation(u1* buffer, int limit, int index); int skip_annotation(u1* buffer, int limit, int index);
int skip_annotation_value(u1* buffer, int limit, int index); int skip_annotation_value(u1* buffer, int limit, int index);
void parse_annotations(ClassLoaderData* loader_data, void parse_annotations(u1* buffer, int limit,
u1* buffer, int limit, constantPoolHandle cp,
/* Results (currently, only one result is supported): */ /* Results (currently, only one result is supported): */
AnnotationCollector* result, AnnotationCollector* result,
TRAPS); TRAPS);
...@@ -267,8 +290,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { ...@@ -267,8 +290,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
int* nonstatic_oop_offsets, int* nonstatic_oop_offsets,
unsigned int* nonstatic_oop_counts); unsigned int* nonstatic_oop_counts);
void set_precomputed_flags(instanceKlassHandle k); void set_precomputed_flags(instanceKlassHandle k);
Array<Klass*>* compute_transitive_interfaces(ClassLoaderData* loader_data, Array<Klass*>* compute_transitive_interfaces(instanceKlassHandle super,
instanceKlassHandle super,
Array<Klass*>* local_ifs, TRAPS); Array<Klass*>* local_ifs, TRAPS);
// Format checker methods // Format checker methods
...@@ -318,7 +340,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { ...@@ -318,7 +340,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
bool is_supported_version(u2 major, u2 minor); bool is_supported_version(u2 major, u2 minor);
bool has_illegal_visibility(jint flags); 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_utf8(const unsigned char* buffer, int length, TRAPS);
void verify_legal_class_name(Symbol* name, TRAPS); void verify_legal_class_name(Symbol* name, TRAPS);
void verify_legal_field_name(Symbol* name, TRAPS); void verify_legal_field_name(Symbol* name, TRAPS);
...@@ -359,10 +381,17 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { ...@@ -359,10 +381,17 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
// In older versions of the VM, Klass*s cannot sneak into early phases of // In older versions of the VM, Klass*s cannot sneak into early phases of
// constant pool construction, but in later versions they can. // constant pool construction, but in later versions they can.
// %%% Let's phase out the old is_klass_reference. // %%% Let's phase out the old is_klass_reference.
bool is_klass_reference(constantPoolHandle cp, int index) { bool valid_klass_reference_at(int index) {
return (EnableInvokeDynamic return _cp->is_within_bounds(index) &&
? cp->tag_at(index).is_klass_or_reference() (EnableInvokeDynamic
: cp->tag_at(index).is_klass_reference()); ? _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, void copy_localvariable_table(ConstMethod* cm, int lvt_cnt,
...@@ -373,8 +402,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { ...@@ -373,8 +402,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
u2** localvariable_type_table_start, u2** localvariable_type_table_start,
TRAPS); TRAPS);
void copy_method_annotations(ClassLoaderData* loader_data, void copy_method_annotations(ConstMethod* cm,
ConstMethod* cm,
u1* runtime_visible_annotations, u1* runtime_visible_annotations,
int runtime_visible_annotations_length, int runtime_visible_annotations_length,
u1* runtime_invisible_annotations, u1* runtime_invisible_annotations,
...@@ -391,9 +419,15 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { ...@@ -391,9 +419,15 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
int annotation_default_length, int annotation_default_length,
TRAPS); 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: public:
// Constructor // Constructor
ClassFileParser(ClassFileStream* st) { set_stream(st); } ClassFileParser(ClassFileStream* st) { set_stream(st); }
~ClassFileParser();
// Parse .class file and return new Klass*. The Klass* is not hooked up // 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 // to the system dictionary or any other structures, so a .class file can
......
...@@ -67,6 +67,12 @@ ConstMethod::ConstMethod(int byte_code_size, ...@@ -67,6 +67,12 @@ ConstMethod::ConstMethod(int byte_code_size,
set_size_of_parameters(0); 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* // Deallocate metadata fields associated with ConstMethod*
void ConstMethod::deallocate_contents(ClassLoaderData* loader_data) { void ConstMethod::deallocate_contents(ClassLoaderData* loader_data) {
......
...@@ -280,6 +280,7 @@ public: ...@@ -280,6 +280,7 @@ public:
// stackmap table data // stackmap table data
Array<u1>* stackmap_data() const { return _stackmap_data; } Array<u1>* stackmap_data() const { return _stackmap_data; }
void set_stackmap_data(Array<u1>* sd) { _stackmap_data = sd; } 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; } bool has_stackmap_table() const { return _stackmap_data != NULL; }
void init_fingerprint() { void init_fingerprint() {
......
...@@ -165,7 +165,8 @@ HS_DTRACE_PROBE_DECL5(hotspot, class__initialization__end, ...@@ -165,7 +165,8 @@ HS_DTRACE_PROBE_DECL5(hotspot, class__initialization__end,
volatile int InstanceKlass::_total_instanceKlass_count = 0; 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 vtable_len,
int itable_len, int itable_len,
int static_field_size, int static_field_size,
...@@ -207,10 +208,35 @@ Klass* InstanceKlass::allocate_instance_klass(ClassLoaderData* loader_data, ...@@ -207,10 +208,35 @@ Klass* InstanceKlass::allocate_instance_klass(ClassLoaderData* loader_data,
access_flags, is_anonymous); 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); Atomic::inc(&_total_instanceKlass_count);
return ik; 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, InstanceKlass::InstanceKlass(int vtable_len,
int itable_len, int itable_len,
int static_field_size, int static_field_size,
...@@ -223,9 +249,6 @@ InstanceKlass::InstanceKlass(int vtable_len, ...@@ -223,9 +249,6 @@ InstanceKlass::InstanceKlass(int vtable_len,
int iksize = InstanceKlass::size(vtable_len, itable_len, nonstatic_oop_map_size, int iksize = InstanceKlass::size(vtable_len, itable_len, nonstatic_oop_map_size,
access_flags.is_interface(), is_anonymous); 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_vtable_length(vtable_len);
set_itable_length(itable_len); set_itable_length(itable_len);
set_static_field_size(static_field_size); set_static_field_size(static_field_size);
...@@ -288,12 +311,51 @@ InstanceKlass::InstanceKlass(int vtable_len, ...@@ -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 // This function deallocates the metadata and C heap pointers that the
// InstanceKlass points to. // InstanceKlass points to.
void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) { void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) {
// Orphan the mirror first, CMS thinks it's still live. // Orphan the mirror first, CMS thinks it's still live.
java_lang_Class::set_klass(java_mirror(), NULL); if (java_mirror() != NULL) {
java_lang_Class::set_klass(java_mirror(), NULL);
}
// Need to take this class off the class loader data list. // Need to take this class off the class loader data list.
loader_data->remove_class(this); loader_data->remove_class(this);
...@@ -308,17 +370,7 @@ void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) { ...@@ -308,17 +370,7 @@ void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) {
// reference counting symbol names. // reference counting symbol names.
release_C_heap_structures(); release_C_heap_structures();
Array<Method*>* ms = methods(); deallocate_methods(loader_data, 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());
}
set_methods(NULL); set_methods(NULL);
if (method_ordering() != Universe::the_empty_int_array()) { if (method_ordering() != Universe::the_empty_int_array()) {
...@@ -335,24 +387,8 @@ void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) { ...@@ -335,24 +387,8 @@ void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) {
} }
set_secondary_supers(NULL); set_secondary_supers(NULL);
// Only deallocate transitive interfaces if not empty, same as super class deallocate_interfaces(loader_data, super(), local_interfaces(), transitive_interfaces());
// 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);
}
}
set_transitive_interfaces(NULL); 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); set_local_interfaces(NULL);
MetadataFactory::free_array<jushort>(loader_data, fields()); MetadataFactory::free_array<jushort>(loader_data, fields());
...@@ -360,9 +396,11 @@ void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) { ...@@ -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 // 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. // delete it, yet. The new class's previous version will point to this.
assert (!constants()->on_stack(), "shouldn't be called if anything is onstack"); if (constants() != NULL) {
MetadataFactory::free_metadata(loader_data, constants()); assert (!constants()->on_stack(), "shouldn't be called if anything is onstack");
set_constants(NULL); MetadataFactory::free_metadata(loader_data, constants());
set_constants(NULL);
}
if (inner_classes() != Universe::the_empty_short_array()) { if (inner_classes() != Universe::the_empty_short_array()) {
MetadataFactory::free_array<jushort>(loader_data, inner_classes()); MetadataFactory::free_array<jushort>(loader_data, inner_classes());
......
...@@ -147,7 +147,8 @@ class InstanceKlass: public Klass { ...@@ -147,7 +147,8 @@ class InstanceKlass: public Klass {
AccessFlags access_flags, AccessFlags access_flags,
bool is_anonymous); bool is_anonymous);
public: public:
static Klass* allocate_instance_klass(ClassLoaderData* loader_data, static InstanceKlass* allocate_instance_klass(
ClassLoaderData* loader_data,
int vtable_len, int vtable_len,
int itable_len, int itable_len,
int static_field_size, int static_field_size,
...@@ -266,7 +267,6 @@ class InstanceKlass: public Klass { ...@@ -266,7 +267,6 @@ class InstanceKlass: public Klass {
u1 _init_state; // state of class u1 _init_state; // state of class
u1 _reference_type; // reference type u1 _reference_type; // reference type
JvmtiCachedClassFieldMap* _jvmti_cached_class_field_map; // JVMTI: used during heap iteration JvmtiCachedClassFieldMap* _jvmti_cached_class_field_map; // JVMTI: used during heap iteration
NOT_PRODUCT(int _verify_count;) // to avoid redundant verifies NOT_PRODUCT(int _verify_count;) // to avoid redundant verifies
...@@ -358,16 +358,19 @@ class InstanceKlass: public Klass { ...@@ -358,16 +358,19 @@ class InstanceKlass: public Klass {
// method ordering // method ordering
Array<int>* method_ordering() const { return _method_ordering; } Array<int>* method_ordering() const { return _method_ordering; }
void set_method_ordering(Array<int>* m) { _method_ordering = m; } void set_method_ordering(Array<int>* m) { _method_ordering = m; }
void copy_method_ordering(intArray* m, TRAPS);
// interfaces // interfaces
Array<Klass*>* local_interfaces() const { return _local_interfaces; } Array<Klass*>* local_interfaces() const { return _local_interfaces; }
void set_local_interfaces(Array<Klass*>* a) { void set_local_interfaces(Array<Klass*>* a) {
guarantee(_local_interfaces == NULL || a == NULL, "Just checking"); guarantee(_local_interfaces == NULL || a == NULL, "Just checking");
_local_interfaces = a; } _local_interfaces = a; }
Array<Klass*>* transitive_interfaces() const { return _transitive_interfaces; } Array<Klass*>* transitive_interfaces() const { return _transitive_interfaces; }
void set_transitive_interfaces(Array<Klass*>* a) { void set_transitive_interfaces(Array<Klass*>* a) {
guarantee(_transitive_interfaces == NULL || a == NULL, "Just checking"); guarantee(_transitive_interfaces == NULL || a == NULL, "Just checking");
_transitive_interfaces = a; } _transitive_interfaces = a;
}
private: private:
friend class fieldDescriptor; friend class fieldDescriptor;
...@@ -383,10 +386,9 @@ class InstanceKlass: public Klass { ...@@ -383,10 +386,9 @@ class InstanceKlass: public Klass {
int java_fields_count() const { return (int)_java_fields_count; } int java_fields_count() const { return (int)_java_fields_count; }
Array<u2>* fields() const { return _fields; } Array<u2>* fields() const { return _fields; }
void set_fields(Array<u2>* f, u2 java_fields_count) { void set_fields(Array<u2>* f, u2 java_fields_count) {
guarantee(_fields == NULL || f == NULL, "Just checking"); guarantee(_fields == NULL || f == NULL, "Just checking");
_fields = f; _fields = f;
_java_fields_count = java_fields_count; _java_fields_count = java_fields_count;
} }
...@@ -916,8 +918,15 @@ class InstanceKlass: public Klass { ...@@ -916,8 +918,15 @@ class InstanceKlass: public Klass {
void clean_method_data(BoolObjectClosure* is_alive); void clean_method_data(BoolObjectClosure* is_alive);
// Explicit metaspace deallocation of fields // 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); 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 // The constant pool is on stack if any of the methods are executing or
// referenced by handles. // referenced by handles.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册