mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-26 22:34:27 +02:00
6845368: large objects cause a crash or unexpected exception
Reviewed-by: jmasa, iveresov
This commit is contained in:
parent
662adda5e6
commit
e7c70c499b
10 changed files with 65640 additions and 65 deletions
|
@ -766,16 +766,16 @@ enum FieldAllocationType {
|
||||||
|
|
||||||
|
|
||||||
struct FieldAllocationCount {
|
struct FieldAllocationCount {
|
||||||
int static_oop_count;
|
unsigned int static_oop_count;
|
||||||
int static_byte_count;
|
unsigned int static_byte_count;
|
||||||
int static_short_count;
|
unsigned int static_short_count;
|
||||||
int static_word_count;
|
unsigned int static_word_count;
|
||||||
int static_double_count;
|
unsigned int static_double_count;
|
||||||
int nonstatic_oop_count;
|
unsigned int nonstatic_oop_count;
|
||||||
int nonstatic_byte_count;
|
unsigned int nonstatic_byte_count;
|
||||||
int nonstatic_short_count;
|
unsigned int nonstatic_short_count;
|
||||||
int nonstatic_word_count;
|
unsigned int nonstatic_word_count;
|
||||||
int nonstatic_double_count;
|
unsigned int nonstatic_double_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
typeArrayHandle ClassFileParser::parse_fields(constantPoolHandle cp, bool is_interface,
|
typeArrayHandle ClassFileParser::parse_fields(constantPoolHandle cp, bool is_interface,
|
||||||
|
@ -2908,11 +2908,11 @@ instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name,
|
||||||
}
|
}
|
||||||
// end of "discovered" field compactibility fix
|
// end of "discovered" field compactibility fix
|
||||||
|
|
||||||
int nonstatic_double_count = fac.nonstatic_double_count;
|
unsigned int nonstatic_double_count = fac.nonstatic_double_count;
|
||||||
int nonstatic_word_count = fac.nonstatic_word_count;
|
unsigned int nonstatic_word_count = fac.nonstatic_word_count;
|
||||||
int nonstatic_short_count = fac.nonstatic_short_count;
|
unsigned int nonstatic_short_count = fac.nonstatic_short_count;
|
||||||
int nonstatic_byte_count = fac.nonstatic_byte_count;
|
unsigned int nonstatic_byte_count = fac.nonstatic_byte_count;
|
||||||
int nonstatic_oop_count = fac.nonstatic_oop_count;
|
unsigned int nonstatic_oop_count = fac.nonstatic_oop_count;
|
||||||
|
|
||||||
bool super_has_nonstatic_fields =
|
bool super_has_nonstatic_fields =
|
||||||
(super_klass() != NULL && super_klass->has_nonstatic_fields());
|
(super_klass() != NULL && super_klass->has_nonstatic_fields());
|
||||||
|
@ -2922,26 +2922,26 @@ instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name,
|
||||||
nonstatic_oop_count) != 0);
|
nonstatic_oop_count) != 0);
|
||||||
|
|
||||||
|
|
||||||
// Prepare list of oops for oop maps generation.
|
// Prepare list of oops for oop map generation.
|
||||||
u2* nonstatic_oop_offsets;
|
int* nonstatic_oop_offsets;
|
||||||
u2* nonstatic_oop_counts;
|
unsigned int* nonstatic_oop_counts;
|
||||||
int nonstatic_oop_map_count = 0;
|
unsigned int nonstatic_oop_map_count = 0;
|
||||||
|
|
||||||
nonstatic_oop_offsets = NEW_RESOURCE_ARRAY_IN_THREAD(
|
nonstatic_oop_offsets = NEW_RESOURCE_ARRAY_IN_THREAD(
|
||||||
THREAD, u2, nonstatic_oop_count+1);
|
THREAD, int, nonstatic_oop_count + 1);
|
||||||
nonstatic_oop_counts = NEW_RESOURCE_ARRAY_IN_THREAD(
|
nonstatic_oop_counts = NEW_RESOURCE_ARRAY_IN_THREAD(
|
||||||
THREAD, u2, nonstatic_oop_count+1);
|
THREAD, unsigned int, nonstatic_oop_count + 1);
|
||||||
|
|
||||||
// Add fake fields for java.lang.Class instances (also see above).
|
// Add fake fields for java.lang.Class instances (also see above).
|
||||||
// FieldsAllocationStyle and CompactFields values will be reset to default.
|
// FieldsAllocationStyle and CompactFields values will be reset to default.
|
||||||
if(class_name() == vmSymbols::java_lang_Class() && class_loader.is_null()) {
|
if(class_name() == vmSymbols::java_lang_Class() && class_loader.is_null()) {
|
||||||
java_lang_Class_fix_post(&next_nonstatic_field_offset);
|
java_lang_Class_fix_post(&next_nonstatic_field_offset);
|
||||||
nonstatic_oop_offsets[0] = (u2)first_nonstatic_field_offset;
|
nonstatic_oop_offsets[0] = first_nonstatic_field_offset;
|
||||||
int fake_oop_count = (( next_nonstatic_field_offset -
|
const uint fake_oop_count = (next_nonstatic_field_offset -
|
||||||
first_nonstatic_field_offset ) / heapOopSize);
|
first_nonstatic_field_offset) / heapOopSize;
|
||||||
nonstatic_oop_counts [0] = (u2)fake_oop_count;
|
nonstatic_oop_counts[0] = fake_oop_count;
|
||||||
nonstatic_oop_map_count = 1;
|
nonstatic_oop_map_count = 1;
|
||||||
nonstatic_oop_count -= fake_oop_count;
|
nonstatic_oop_count -= fake_oop_count;
|
||||||
first_nonstatic_oop_offset = first_nonstatic_field_offset;
|
first_nonstatic_oop_offset = first_nonstatic_field_offset;
|
||||||
} else {
|
} else {
|
||||||
first_nonstatic_oop_offset = 0; // will be set for first oop field
|
first_nonstatic_oop_offset = 0; // will be set for first oop field
|
||||||
|
@ -3119,12 +3119,14 @@ instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name,
|
||||||
// Update oop maps
|
// Update oop maps
|
||||||
if( nonstatic_oop_map_count > 0 &&
|
if( nonstatic_oop_map_count > 0 &&
|
||||||
nonstatic_oop_offsets[nonstatic_oop_map_count - 1] ==
|
nonstatic_oop_offsets[nonstatic_oop_map_count - 1] ==
|
||||||
(u2)(real_offset - nonstatic_oop_counts[nonstatic_oop_map_count - 1] * heapOopSize) ) {
|
real_offset -
|
||||||
|
int(nonstatic_oop_counts[nonstatic_oop_map_count - 1]) *
|
||||||
|
heapOopSize ) {
|
||||||
// Extend current oop map
|
// Extend current oop map
|
||||||
nonstatic_oop_counts[nonstatic_oop_map_count - 1] += 1;
|
nonstatic_oop_counts[nonstatic_oop_map_count - 1] += 1;
|
||||||
} else {
|
} else {
|
||||||
// Create new oop map
|
// Create new oop map
|
||||||
nonstatic_oop_offsets[nonstatic_oop_map_count] = (u2)real_offset;
|
nonstatic_oop_offsets[nonstatic_oop_map_count] = real_offset;
|
||||||
nonstatic_oop_counts [nonstatic_oop_map_count] = 1;
|
nonstatic_oop_counts [nonstatic_oop_map_count] = 1;
|
||||||
nonstatic_oop_map_count += 1;
|
nonstatic_oop_map_count += 1;
|
||||||
if( first_nonstatic_oop_offset == 0 ) { // Undefined
|
if( first_nonstatic_oop_offset == 0 ) { // Undefined
|
||||||
|
@ -3183,9 +3185,9 @@ instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name,
|
||||||
assert(instance_size == align_object_size(align_size_up((instanceOopDesc::base_offset_in_bytes() + nonstatic_field_size*heapOopSize), wordSize) / wordSize), "consistent layout helper value");
|
assert(instance_size == align_object_size(align_size_up((instanceOopDesc::base_offset_in_bytes() + nonstatic_field_size*heapOopSize), wordSize) / wordSize), "consistent layout helper value");
|
||||||
|
|
||||||
// Number of non-static oop map blocks allocated at end of klass.
|
// Number of non-static oop map blocks allocated at end of klass.
|
||||||
int total_oop_map_count = compute_oop_map_count(super_klass,
|
const unsigned int total_oop_map_count =
|
||||||
nonstatic_oop_map_count,
|
compute_oop_map_count(super_klass, nonstatic_oop_map_count,
|
||||||
first_nonstatic_oop_offset);
|
first_nonstatic_oop_offset);
|
||||||
|
|
||||||
// Compute reference type
|
// Compute reference type
|
||||||
ReferenceType rt;
|
ReferenceType rt;
|
||||||
|
@ -3196,10 +3198,10 @@ instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name,
|
||||||
}
|
}
|
||||||
|
|
||||||
// We can now create the basic klassOop for this klass
|
// We can now create the basic klassOop for this klass
|
||||||
klassOop ik = oopFactory::new_instanceKlass(
|
klassOop ik = oopFactory::new_instanceKlass(vtable_size, itable_size,
|
||||||
vtable_size, itable_size,
|
static_field_size,
|
||||||
static_field_size, total_oop_map_count,
|
total_oop_map_count,
|
||||||
rt, CHECK_(nullHandle));
|
rt, CHECK_(nullHandle));
|
||||||
instanceKlassHandle this_klass (THREAD, ik);
|
instanceKlassHandle this_klass (THREAD, ik);
|
||||||
|
|
||||||
assert(this_klass->static_field_size() == static_field_size, "sanity");
|
assert(this_klass->static_field_size() == static_field_size, "sanity");
|
||||||
|
@ -3378,10 +3380,12 @@ instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int ClassFileParser::compute_oop_map_count(instanceKlassHandle super,
|
unsigned int
|
||||||
int nonstatic_oop_map_count,
|
ClassFileParser::compute_oop_map_count(instanceKlassHandle super,
|
||||||
int first_nonstatic_oop_offset) {
|
unsigned int nonstatic_oop_map_count,
|
||||||
int map_count = super.is_null() ? 0 : super->nonstatic_oop_map_count();
|
int first_nonstatic_oop_offset) {
|
||||||
|
unsigned int map_count =
|
||||||
|
super.is_null() ? 0 : super->nonstatic_oop_map_count();
|
||||||
if (nonstatic_oop_map_count > 0) {
|
if (nonstatic_oop_map_count > 0) {
|
||||||
// We have oops to add to map
|
// We have oops to add to map
|
||||||
if (map_count == 0) {
|
if (map_count == 0) {
|
||||||
|
@ -3409,16 +3413,16 @@ int ClassFileParser::compute_oop_map_count(instanceKlassHandle super,
|
||||||
|
|
||||||
|
|
||||||
void ClassFileParser::fill_oop_maps(instanceKlassHandle k,
|
void ClassFileParser::fill_oop_maps(instanceKlassHandle k,
|
||||||
int nonstatic_oop_map_count,
|
unsigned int nonstatic_oop_map_count,
|
||||||
u2* nonstatic_oop_offsets,
|
int* nonstatic_oop_offsets,
|
||||||
u2* nonstatic_oop_counts) {
|
unsigned int* nonstatic_oop_counts) {
|
||||||
OopMapBlock* this_oop_map = k->start_of_nonstatic_oop_maps();
|
OopMapBlock* this_oop_map = k->start_of_nonstatic_oop_maps();
|
||||||
const instanceKlass* const super = k->superklass();
|
const instanceKlass* const super = k->superklass();
|
||||||
const int super_count = super != NULL ? super->nonstatic_oop_map_count() : 0;
|
const unsigned int super_count = super ? super->nonstatic_oop_map_count() : 0;
|
||||||
if (super_count > 0) {
|
if (super_count > 0) {
|
||||||
// Copy maps from superklass
|
// Copy maps from superklass
|
||||||
OopMapBlock* super_oop_map = super->start_of_nonstatic_oop_maps();
|
OopMapBlock* super_oop_map = super->start_of_nonstatic_oop_maps();
|
||||||
for (int i = 0; i < super_count; ++i) {
|
for (unsigned int i = 0; i < super_count; ++i) {
|
||||||
*this_oop_map++ = *super_oop_map++;
|
*this_oop_map++ = *super_oop_map++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,10 +125,13 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
|
||||||
int runtime_invisible_annotations_length, TRAPS);
|
int runtime_invisible_annotations_length, TRAPS);
|
||||||
|
|
||||||
// Final setup
|
// Final setup
|
||||||
int compute_oop_map_count(instanceKlassHandle super, int nonstatic_oop_count,
|
unsigned int compute_oop_map_count(instanceKlassHandle super,
|
||||||
int first_nonstatic_oop_offset);
|
unsigned int nonstatic_oop_count,
|
||||||
void fill_oop_maps(instanceKlassHandle k, int nonstatic_oop_map_count,
|
int first_nonstatic_oop_offset);
|
||||||
u2* nonstatic_oop_offsets, u2* nonstatic_oop_counts);
|
void fill_oop_maps(instanceKlassHandle k,
|
||||||
|
unsigned int nonstatic_oop_map_count,
|
||||||
|
int* nonstatic_oop_offsets,
|
||||||
|
unsigned int* nonstatic_oop_counts);
|
||||||
void set_precomputed_flags(instanceKlassHandle k);
|
void set_precomputed_flags(instanceKlassHandle k);
|
||||||
objArrayHandle compute_transitive_interfaces(instanceKlassHandle super,
|
objArrayHandle compute_transitive_interfaces(instanceKlassHandle super,
|
||||||
objArrayHandle local_ifs, TRAPS);
|
objArrayHandle local_ifs, TRAPS);
|
||||||
|
|
|
@ -98,8 +98,10 @@ constantPoolCacheOop oopFactory::new_constantPoolCache(int length,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
klassOop oopFactory::new_instanceKlass(int vtable_len, int itable_len, int static_field_size,
|
klassOop oopFactory::new_instanceKlass(int vtable_len, int itable_len,
|
||||||
int nonstatic_oop_map_count, ReferenceType rt, TRAPS) {
|
int static_field_size,
|
||||||
|
unsigned int nonstatic_oop_map_count,
|
||||||
|
ReferenceType rt, TRAPS) {
|
||||||
instanceKlassKlass* ikk = instanceKlassKlass::cast(Universe::instanceKlassKlassObj());
|
instanceKlassKlass* ikk = instanceKlassKlass::cast(Universe::instanceKlassKlassObj());
|
||||||
return ikk->allocate_instance_klass(vtable_len, itable_len, static_field_size, nonstatic_oop_map_count, rt, CHECK_NULL);
|
return ikk->allocate_instance_klass(vtable_len, itable_len, static_field_size, nonstatic_oop_map_count, rt, CHECK_NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,8 +89,10 @@ class oopFactory: AllStatic {
|
||||||
TRAPS);
|
TRAPS);
|
||||||
|
|
||||||
// Instance classes
|
// Instance classes
|
||||||
static klassOop new_instanceKlass(int vtable_len, int itable_len, int static_field_size,
|
static klassOop new_instanceKlass(int vtable_len, int itable_len,
|
||||||
int nonstatic_oop_map_count, ReferenceType rt, TRAPS);
|
int static_field_size,
|
||||||
|
unsigned int nonstatic_oop_map_count,
|
||||||
|
ReferenceType rt, TRAPS);
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -2223,7 +2223,8 @@ void instanceKlass::verify_class_klass_nonstatic_oop_maps(klassOop k) {
|
||||||
int offset = java_lang_Class::klass_offset;
|
int offset = java_lang_Class::klass_offset;
|
||||||
|
|
||||||
OopMapBlock* map = ik->start_of_nonstatic_oop_maps();
|
OopMapBlock* map = ik->start_of_nonstatic_oop_maps();
|
||||||
guarantee(map->offset() == offset && map->count() == extra, "sanity");
|
guarantee(map->offset() == offset && map->count() == (unsigned int) extra,
|
||||||
|
"sanity");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -103,12 +103,12 @@ class FieldPrinter: public FieldClosure {
|
||||||
class OopMapBlock VALUE_OBJ_CLASS_SPEC {
|
class OopMapBlock VALUE_OBJ_CLASS_SPEC {
|
||||||
public:
|
public:
|
||||||
// Byte offset of the first oop mapped by this block.
|
// Byte offset of the first oop mapped by this block.
|
||||||
jushort offset() const { return _offset; }
|
int offset() const { return _offset; }
|
||||||
void set_offset(jushort offset) { _offset = offset; }
|
void set_offset(int offset) { _offset = offset; }
|
||||||
|
|
||||||
// Number of oops in this block.
|
// Number of oops in this block.
|
||||||
jushort count() const { return _count; }
|
uint count() const { return _count; }
|
||||||
void set_count(jushort count) { _count = count; }
|
void set_count(uint count) { _count = count; }
|
||||||
|
|
||||||
// sizeof(OopMapBlock) in HeapWords.
|
// sizeof(OopMapBlock) in HeapWords.
|
||||||
static const int size_in_words() {
|
static const int size_in_words() {
|
||||||
|
@ -117,8 +117,8 @@ class OopMapBlock VALUE_OBJ_CLASS_SPEC {
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
jushort _offset;
|
int _offset;
|
||||||
jushort _count;
|
uint _count;
|
||||||
};
|
};
|
||||||
|
|
||||||
class instanceKlass: public Klass {
|
class instanceKlass: public Klass {
|
||||||
|
@ -446,10 +446,10 @@ class instanceKlass: public Klass {
|
||||||
void set_source_debug_extension(symbolOop n){ oop_store_without_check((oop*) &_source_debug_extension, (oop) n); }
|
void set_source_debug_extension(symbolOop n){ oop_store_without_check((oop*) &_source_debug_extension, (oop) n); }
|
||||||
|
|
||||||
// nonstatic oop-map blocks
|
// nonstatic oop-map blocks
|
||||||
static int nonstatic_oop_map_size(int oop_map_count) {
|
static int nonstatic_oop_map_size(unsigned int oop_map_count) {
|
||||||
return oop_map_count * OopMapBlock::size_in_words();
|
return oop_map_count * OopMapBlock::size_in_words();
|
||||||
}
|
}
|
||||||
int nonstatic_oop_map_count() const {
|
unsigned int nonstatic_oop_map_count() const {
|
||||||
return _nonstatic_oop_map_size / OopMapBlock::size_in_words();
|
return _nonstatic_oop_map_size / OopMapBlock::size_in_words();
|
||||||
}
|
}
|
||||||
int nonstatic_oop_map_size() const { return _nonstatic_oop_map_size; }
|
int nonstatic_oop_map_size() const { return _nonstatic_oop_map_size; }
|
||||||
|
|
|
@ -405,7 +405,7 @@ int instanceKlassKlass::oop_update_pointers(ParCompactionManager* cm, oop obj,
|
||||||
klassOop
|
klassOop
|
||||||
instanceKlassKlass::allocate_instance_klass(int vtable_len, int itable_len,
|
instanceKlassKlass::allocate_instance_klass(int vtable_len, int itable_len,
|
||||||
int static_field_size,
|
int static_field_size,
|
||||||
int nonstatic_oop_map_count,
|
unsigned nonstatic_oop_map_count,
|
||||||
ReferenceType rt, TRAPS) {
|
ReferenceType rt, TRAPS) {
|
||||||
|
|
||||||
const int nonstatic_oop_map_size =
|
const int nonstatic_oop_map_size =
|
||||||
|
|
|
@ -39,7 +39,7 @@ class instanceKlassKlass : public klassKlass {
|
||||||
klassOop allocate_instance_klass(int vtable_len,
|
klassOop allocate_instance_klass(int vtable_len,
|
||||||
int itable_len,
|
int itable_len,
|
||||||
int static_field_size,
|
int static_field_size,
|
||||||
int nonstatic_oop_map_count,
|
unsigned int nonstatic_oop_map_count,
|
||||||
ReferenceType rt,
|
ReferenceType rt,
|
||||||
TRAPS);
|
TRAPS);
|
||||||
|
|
||||||
|
|
|
@ -407,7 +407,7 @@ void instanceRefKlass::update_nonstatic_oop_maps(klassOop k) {
|
||||||
// Check that the current map is (2,4) - currently points at field with
|
// Check that the current map is (2,4) - currently points at field with
|
||||||
// offset 2 (words) and has 4 map entries.
|
// offset 2 (words) and has 4 map entries.
|
||||||
debug_only(int offset = java_lang_ref_Reference::referent_offset);
|
debug_only(int offset = java_lang_ref_Reference::referent_offset);
|
||||||
debug_only(int count = ((java_lang_ref_Reference::discovered_offset -
|
debug_only(unsigned int count = ((java_lang_ref_Reference::discovered_offset -
|
||||||
java_lang_ref_Reference::referent_offset)/heapOopSize) + 1);
|
java_lang_ref_Reference::referent_offset)/heapOopSize) + 1);
|
||||||
|
|
||||||
if (UseSharedSpaces) {
|
if (UseSharedSpaces) {
|
||||||
|
|
65563
hotspot/test/gc/6845368/bigobj.java
Normal file
65563
hotspot/test/gc/6845368/bigobj.java
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue