8059340: ConstantPool::_resolved_references is missing in heap dump

Reviewed-by: sspitsyn, stefank, twisti
This commit is contained in:
Vladimir Ivanov 2015-05-21 18:22:33 +03:00
parent e5a92a9fb9
commit 3f096651f3
17 changed files with 101 additions and 77 deletions

View file

@ -229,16 +229,21 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index(
Register tmp = index; // reuse
lslw(tmp, tmp, LogBytesPerHeapOop);
get_constant_pool(result);
// load pointer for resolved_references[] objArray
ldr(result, Address(result, ConstantPool::resolved_references_offset_in_bytes()));
// JNIHandles::resolve(obj);
ldr(result, Address(result, 0));
get_resolved_references(result);
// Add in the index
add(result, result, tmp);
load_heap_oop(result, Address(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
}
void InterpreterMacroAssembler::get_resolved_references(Register reg) {
get_constant_pool(reg);
ldr(reg, Address(reg, ConstantPool::pool_holder_offset_in_bytes()));
ldr(reg, Address(reg, Klass::java_mirror_offset()));
assert(java_lang_Class::resolved_references_offset_in_bytes() > 0, "");
load_heap_oop(reg, Address(reg, java_lang_Class::resolved_references_offset_in_bytes()));
}
// Generate a subtype check: branch to ok_is_subtype if sub_klass is a
// subtype of super_klass.
//

View file

@ -121,6 +121,8 @@ class InterpreterMacroAssembler: public MacroAssembler {
ldr(tags, Address(cpool, ConstantPool::tags_offset_in_bytes()));
}
void get_resolved_references(Register reg);
void get_unsigned_2_byte_index_at_bcp(Register reg, int bcp_offset);
void get_cache_and_index_at_bcp(Register cache, Register index, int bcp_offset, size_t index_size = sizeof(u2));
void get_cache_and_index_and_bytecode_at_bcp(Register cache, Register index, Register bytecode, int byte_no, int bcp_offset, size_t index_size = sizeof(u2));

View file

@ -798,11 +798,8 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index(
// word index to byte offset. Since this is a java object, it can be compressed
Register tmp = index; // reuse
sll(index, LogBytesPerHeapOop, tmp);
get_constant_pool(result);
// load pointer for resolved_references[] objArray
ld_ptr(result, ConstantPool::resolved_references_offset_in_bytes(), result);
// JNIHandles::resolve(result)
ld_ptr(result, 0, result);
get_resolved_references(result);
// Add in the index
add(result, tmp, result);
load_heap_oop(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT), result);
@ -973,6 +970,13 @@ void InterpreterMacroAssembler::get_cpool_and_tags(Register Rcpool, Register Rta
ld_ptr(Rcpool, ConstantPool::tags_offset_in_bytes(), Rtags);
}
void InterpreterMacroAssembler::get_resolved_references(Register Rdst) {
get_constant_pool(Rdst);
ld_ptr(Rdst, ConstantPool::pool_holder_offset_in_bytes(), Rdst);
ld_ptr(Rdst, Klass::java_mirror_offset(), Rdst);
assert(java_lang_Class::resolved_references_offset_in_bytes() > 0, "");
load_heap_oop(Rdst, java_lang_Class::resolved_references_offset_in_bytes(), Rdst);
}
// unlock if synchronized method
//

View file

@ -212,6 +212,7 @@ class InterpreterMacroAssembler: public MacroAssembler {
void get_constant_pool(Register Rdst);
void get_constant_pool_cache(Register Rdst);
void get_cpool_and_tags(Register Rcpool, Register Rtags);
void get_resolved_references(Register Rdst);
void is_a(Label& L);
// Load compiled (i2c) or interpreter entry and call from interpreted

View file

@ -482,6 +482,14 @@ void InterpreterMacroAssembler::get_cache_and_index_and_bytecode_at_bcp(Register
andl(bytecode, ConstantPoolCacheEntry::bytecode_1_mask);
}
void InterpreterMacroAssembler::get_resolved_references(Register reg) {
get_constant_pool(reg);
movptr(reg, Address(reg, ConstantPool::pool_holder_offset_in_bytes()));
movptr(reg, Address(reg, Klass::java_mirror_offset()));
assert(java_lang_Class::resolved_references_offset_in_bytes() > 0, "");
load_heap_oop(reg, Address(reg, java_lang_Class::resolved_references_offset_in_bytes()));
}
void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache,
Register tmp,
int bcp_offset,
@ -499,20 +507,16 @@ void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache,
addptr(cache, tmp); // construct pointer to cache entry
}
// Load object from cpool->resolved_references(index)
void InterpreterMacroAssembler::load_resolved_reference_at_index(
Register result, Register index) {
// Load object from cpool->pool_holder->mirror->resolved_references(index)
void InterpreterMacroAssembler::load_resolved_reference_at_index(Register result, Register index) {
assert_different_registers(result, index);
// convert from field index to resolved_references() index and from
// word index to byte offset. Since this is a java object, it can be compressed
Register tmp = index; // reuse
shll(tmp, LogBytesPerHeapOop);
get_constant_pool(result);
// load pointer for resolved_references[] objArray
movptr(result, Address(result, ConstantPool::resolved_references_offset_in_bytes()));
// JNIHandles::resolve(obj);
movptr(result, Address(result, 0));
get_resolved_references(result);
// Add in the index
addptr(result, tmp);
load_heap_oop(result, Address(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT)));

View file

@ -109,6 +109,8 @@ class InterpreterMacroAssembler: public MacroAssembler {
movptr(tags, Address(cpool, ConstantPool::tags_offset_in_bytes()));
}
void get_resolved_references(Register reg);
void get_unsigned_2_byte_index_at_bcp(Register reg, int bcp_offset);
void get_cache_and_index_at_bcp(Register cache,
Register index,

View file

@ -477,10 +477,8 @@ int ciBytecodeStream::get_method_signature_index() {
// ------------------------------------------------------------------
// ciBytecodeStream::get_resolved_references
ciObjArray* ciBytecodeStream::get_resolved_references() {
VM_ENTRY_MARK;
// Get the constant pool.
ConstantPool* cpool = _holder->get_instanceKlass()->constants();
VM_ENTRY_MARK;
objArrayOop resolved_references = _holder->get_instanceKlass()->resolved_references();
// Create a resolved references array and return it.
return CURRENT_ENV->get_object(cpool->resolved_references())->as_obj_array();
}
return CURRENT_ENV->get_object(resolved_references)->as_obj_array();
}

View file

@ -60,7 +60,6 @@
#include "oops/objArrayOop.inline.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/atomic.inline.hpp"
#include "runtime/jniHandles.hpp"
#include "runtime/mutex.hpp"
#include "runtime/safepoint.hpp"
#include "runtime/synchronizer.hpp"
@ -81,7 +80,7 @@ ClassLoaderData::ClassLoaderData(Handle h_class_loader, bool is_anonymous, Depen
// The null-class-loader should always be kept alive.
_keep_alive(is_anonymous || h_class_loader.is_null()),
_metaspace(NULL), _unloading(false), _klasses(NULL),
_claimed(0), _jmethod_ids(NULL), _handles(NULL), _deallocate_list(NULL),
_claimed(0), _jmethod_ids(NULL), _deallocate_list(NULL),
_next(NULL), _dependencies(dependencies),
_metaspace_lock(new Mutex(Monitor::leaf+1, "Metaspace allocation lock", true,
Monitor::_safepoint_check_never)) {
@ -115,7 +114,6 @@ void ClassLoaderData::oops_do(OopClosure* f, KlassClosure* klass_closure, bool m
f->do_oop(&_class_loader);
_dependencies.oops_do(f);
_handles->oops_do(f);
if (klass_closure != NULL) {
classes_do(klass_closure);
}
@ -356,11 +354,6 @@ ClassLoaderData::~ClassLoaderData() {
_metaspace = NULL;
// release the metaspace
delete m;
// release the handles
if (_handles != NULL) {
JNIHandleBlock::release_block(_handles);
_handles = NULL;
}
}
// Clear all the JNI handles for methods
@ -420,17 +413,6 @@ Metaspace* ClassLoaderData::metaspace_non_null() {
return _metaspace;
}
JNIHandleBlock* ClassLoaderData::handles() const { return _handles; }
void ClassLoaderData::set_handles(JNIHandleBlock* handles) { _handles = handles; }
jobject ClassLoaderData::add_handle(Handle h) {
MutexLockerEx ml(metaspace_lock(), Mutex::_no_safepoint_check_flag);
if (handles() == NULL) {
set_handles(JNIHandleBlock::allocate_block());
}
return handles()->allocate_handle(h());
}
// Add this metadata pointer to be freed when it's safe. This is only during
// class unloading because Handles might point to this metadata field.
void ClassLoaderData::add_to_deallocate_list(Metadata* m) {
@ -499,7 +481,6 @@ void ClassLoaderData::dump(outputStream * const out) {
p2i(class_loader() != NULL ? class_loader()->klass() : NULL), loader_name());
if (claimed()) out->print(" claimed ");
if (is_unloading()) out->print(" unloading ");
out->print(" handles " INTPTR_FORMAT, p2i(handles()));
out->cr();
if (metaspace_or_null() != NULL) {
out->print_cr("metaspace: " INTPTR_FORMAT, p2i(metaspace_or_null()));

View file

@ -51,7 +51,6 @@
class ClassLoaderData;
class JNIMethodBlock;
class JNIHandleBlock;
class Metadebug;
// GC root for walking class loader data created
@ -173,8 +172,6 @@ class ClassLoaderData : public CHeapObj<mtClass> {
// Has to be an int because we cas it.
Klass* _klasses; // The classes defined by the class loader.
JNIHandleBlock* _handles; // Handles to constant pool arrays
// These method IDs are created for the class loader and set to NULL when the
// class loader is unloaded. They are rarely freed, only for redefine classes
// and if they lose a data race in InstanceKlass.
@ -200,9 +197,6 @@ class ClassLoaderData : public CHeapObj<mtClass> {
void set_metaspace(Metaspace* m) { _metaspace = m; }
JNIHandleBlock* handles() const;
void set_handles(JNIHandleBlock* handles);
// GC interface.
void clear_claimed() { _claimed = 0; }
bool claimed() const { return _claimed == 1; }
@ -290,7 +284,6 @@ class ClassLoaderData : public CHeapObj<mtClass> {
void verify();
const char* loader_name();
jobject add_handle(Handle h);
void add_class(Klass* k);
void remove_class(Klass* k);
bool contains_klass(Klass* k);

View file

@ -567,6 +567,12 @@ void java_lang_Class::fixup_mirror(KlassHandle k, TRAPS) {
}
}
create_mirror(k, Handle(NULL), Handle(NULL), CHECK);
if (UseSharedSpaces && k->oop_is_instance()) {
// Create resolved_references array in the fresh mirror.
instanceKlassHandle ik(k());
ik->constants()->restore_unshareable_info(CHECK);
}
}
void java_lang_Class::initialize_mirror_fields(KlassHandle k,
@ -924,6 +930,17 @@ void java_lang_Class::set_classRedefinedCount(oop the_class_mirror, int value) {
the_class_mirror->int_field_put(classRedefinedCount_offset, value);
}
objArrayOop java_lang_Class::resolved_references(oop java_class) {
assert(java_lang_Class::is_instance(java_class), "");
assert(resolvedReferences_offset > 0, "must be set");
return objArrayOop(java_class->obj_field(resolvedReferences_offset));
}
void java_lang_Class::set_resolved_references(oop java_class, objArrayOop a) {
assert(java_lang_Class::is_instance(java_class), "");
assert(resolvedReferences_offset > 0, "must be set");
java_class->obj_field_put(resolvedReferences_offset, a);
}
// Note: JDK1.1 and before had a privateInfo_offset field which was used for the
// platform thread structure, and a eetop offset which was used for thread
@ -3181,6 +3198,7 @@ bool java_lang_System::has_security_manager() {
}
}
int java_lang_Class::resolvedReferences_offset;
int java_lang_Class::_klass_offset;
int java_lang_Class::_array_klass_offset;
int java_lang_Class::_oop_size_offset;
@ -3336,6 +3354,9 @@ void JavaClasses::compute_hard_coded_offsets() {
const int x = heapOopSize;
const int header = instanceOopDesc::base_offset_in_bytes();
// Class
java_lang_Class::resolvedReferences_offset = java_lang_Class::hc_resolvedReferences_offset * x + header;
// Throwable Class
java_lang_Throwable::backtrace_offset = java_lang_Throwable::hc_backtrace_offset * x + header;
java_lang_Throwable::detailMessage_offset = java_lang_Throwable::hc_detailMessage_offset * x + header;
@ -3534,9 +3555,7 @@ void JavaClasses::check_offsets() {
// java.lang.Class
// Fake fields
// CHECK_OFFSET("java/lang/Class", java_lang_Class, klass); // %%% this needs to be checked
// CHECK_OFFSET("java/lang/Class", java_lang_Class, array_klass); // %%% this needs to be checked
CHECK_OFFSET("java/lang/Class", java_lang_Class, resolvedReferences, "[Ljava/lang/Object;");
// java.lang.Throwable

View file

@ -226,6 +226,10 @@ class java_lang_String : AllStatic {
class java_lang_Class : AllStatic {
friend class VMStructs;
enum {
hc_resolvedReferences_offset = 12
};
private:
// The fake offsets are added by the class loader when java.lang.Class is loaded
@ -243,6 +247,7 @@ class java_lang_Class : AllStatic {
static bool offsets_computed;
static int classRedefinedCount_offset;
static int resolvedReferences_offset;
static GrowableArray<Klass*>* _fixup_mirror_list;
@ -301,6 +306,10 @@ class java_lang_Class : AllStatic {
static int static_oop_field_count(oop java_class);
static void set_static_oop_field_count(oop java_class, int size);
static objArrayOop resolved_references(oop java_class);
static void set_resolved_references(oop java_class, objArrayOop a);
static int resolved_references_offset_in_bytes() { return resolvedReferences_offset; }
static GrowableArray<Klass*>* fixup_mirror_list() {
return _fixup_mirror_list;
}

View file

@ -67,7 +67,6 @@ ConstantPool::ConstantPool(Array<u1>* tags) {
set_tags(NULL);
set_cache(NULL);
set_reference_map(NULL);
set_resolved_references(NULL);
set_operands(NULL);
set_pool_holder(NULL);
set_flags(0);
@ -104,10 +103,6 @@ void ConstantPool::release_C_heap_structures() {
unreference_symbols();
}
objArrayOop ConstantPool::resolved_references() const {
return (objArrayOop)JNIHandles::resolve(_resolved_references);
}
// Create resolved_references array and mapping array for original cp indexes
// The ldc bytecode was rewritten to have the resolved reference array index so need a way
// to map it back for resolving and some unlikely miscellaneous uses.
@ -136,30 +131,31 @@ void ConstantPool::initialize_resolved_references(ClassLoaderData* loader_data,
// Create Java array for holding resolved strings, methodHandles,
// methodTypes, invokedynamic and invokehandle appendix objects, etc.
objArrayOop stom = oopFactory::new_objArray(SystemDictionary::Object_klass(), map_length, CHECK);
Handle refs_handle (THREAD, (oop)stom); // must handleize.
set_resolved_references(loader_data->add_handle(refs_handle));
objArrayOop obj_arr = oopFactory::new_objArray(SystemDictionary::Object_klass(), map_length, CHECK);
pool_holder()->set_resolved_references(obj_arr);
}
}
objArrayOop ConstantPool::resolved_references() const {
return pool_holder()->resolved_references();
}
// CDS support. Create a new resolved_references array.
void ConstantPool::restore_unshareable_info(TRAPS) {
// Only create the new resolved references array if it hasn't been attempted before
if (resolved_references() != NULL) return;
// restore the C++ vtable from the shared archive
restore_vtable();
if (pool_holder()->java_mirror() == NULL) return;
// Only create the new resolved references array if it hasn't been attempted before
if (pool_holder()->resolved_references() != NULL) return;
if (SystemDictionary::Object_klass_loaded()) {
// Recreate the object array and add to ClassLoaderData.
int map_length = resolved_reference_length();
if (map_length > 0) {
objArrayOop stom = oopFactory::new_objArray(SystemDictionary::Object_klass(), map_length, CHECK);
Handle refs_handle (THREAD, (oop)stom); // must handleize.
ClassLoaderData* loader_data = pool_holder()->class_loader_data();
set_resolved_references(loader_data->add_handle(refs_handle));
objArrayOop resolved_references = oopFactory::new_objArray(SystemDictionary::Object_klass(), map_length, CHECK);
pool_holder()->set_resolved_references(resolved_references);
}
}
}
@ -168,9 +164,8 @@ void ConstantPool::remove_unshareable_info() {
// Resolved references are not in the shared archive.
// Save the length for restoration. It is not necessarily the same length
// as reference_map.length() if invokedynamic is saved.
set_resolved_reference_length(
resolved_references() != NULL ? resolved_references()->length() : 0);
set_resolved_references(NULL);
objArrayOop resolved_references = pool_holder()->resolved_references();
set_resolved_reference_length(resolved_references != NULL ? resolved_references->length() : 0);
}
int ConstantPool::cp_to_object_index(int cp_index) {
@ -1871,7 +1866,6 @@ void ConstantPool::print_on(outputStream* st) const {
st->print_cr(" - holder: " INTPTR_FORMAT, pool_holder());
}
st->print_cr(" - cache: " INTPTR_FORMAT, cache());
st->print_cr(" - resolved_references: " INTPTR_FORMAT, (void *)resolved_references());
st->print_cr(" - reference_map: " INTPTR_FORMAT, reference_map());
for (int index = 1; index < length(); index++) { // Index 0 is unused

View file

@ -84,7 +84,6 @@ class ConstantPool : public Metadata {
// Array of resolved objects from the constant pool and map from resolved
// object index to original constant pool index
jobject _resolved_references;
Array<u2>* _reference_map;
enum {
@ -191,6 +190,7 @@ class ConstantPool : public Metadata {
// resolved strings, methodHandles and callsite objects from the constant pool
objArrayOop resolved_references() const;
// mapping resolved object array indexes to cp indexes and back.
int object_to_cp_index(int index) { return _reference_map->at(index); }
int cp_to_object_index(int index);
@ -222,7 +222,6 @@ class ConstantPool : public Metadata {
static int tags_offset_in_bytes() { return offset_of(ConstantPool, _tags); }
static int cache_offset_in_bytes() { return offset_of(ConstantPool, _cache); }
static int pool_holder_offset_in_bytes() { return offset_of(ConstantPool, _pool_holder); }
static int resolved_references_offset_in_bytes() { return offset_of(ConstantPool, _resolved_references); }
// Storing constants
@ -771,7 +770,6 @@ class ConstantPool : public Metadata {
private:
void set_resolved_references(jobject s) { _resolved_references = s; }
Array<u2>* reference_map() const { return _reference_map; }
void set_reference_map(Array<u2>* o) { _reference_map = o; }

View file

@ -2032,7 +2032,6 @@ static void remove_unshareable_in_class(Klass* k) {
}
void InstanceKlass::remove_unshareable_info() {
Klass::remove_unshareable_info();
// Unlink the class
if (is_linked()) {
unlink_class();
@ -2048,6 +2047,8 @@ void InstanceKlass::remove_unshareable_info() {
// do array classes also.
array_klasses_do(remove_unshareable_in_class);
Klass::remove_unshareable_info();
}
static void restore_unshareable_in_class(Klass* k, TRAPS) {
@ -3512,3 +3513,11 @@ jint InstanceKlass::get_cached_class_file_len() {
unsigned char * InstanceKlass::get_cached_class_file_bytes() {
return VM_RedefineClasses::get_cached_class_file_bytes(_cached_class_file);
}
objArrayOop InstanceKlass::resolved_references() const {
return java_lang_Class::resolved_references(java_mirror());
}
void InstanceKlass::set_resolved_references(objArrayOop obj_arr) {
return java_lang_Class::set_resolved_references(java_mirror(), obj_arr);
}

View file

@ -532,6 +532,9 @@ class InstanceKlass: public Klass {
ConstantPool* constants() const { return _constants; }
void set_constants(ConstantPool* c) { _constants = c; }
objArrayOop resolved_references() const;
void set_resolved_references(objArrayOop obj_arr);
// protection domain
oop protection_domain() const;

View file

@ -3885,7 +3885,10 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass,
// Attach new constant pool to the original klass. The original
// klass still refers to the old constant pool (for now).
// resolved_references array should be moved as well, since it is located
// in klass mirror.
scratch_class->constants()->set_pool_holder(the_class());
the_class->set_resolved_references(scratch_class->resolved_references());
#if 0
// In theory, with constant pool merging in place we should be able

View file

@ -288,7 +288,6 @@ typedef CompactHashtable<Symbol*, char> SymbolCompactHashTable;
nonstatic_field(ConstantPool, _pool_holder, InstanceKlass*) \
nonstatic_field(ConstantPool, _operands, Array<u2>*) \
nonstatic_field(ConstantPool, _length, int) \
nonstatic_field(ConstantPool, _resolved_references, jobject) \
nonstatic_field(ConstantPool, _reference_map, Array<u2>*) \
nonstatic_field(ConstantPoolCache, _length, int) \
nonstatic_field(ConstantPoolCache, _constant_pool, ConstantPool*) \