8220512: Deoptimize redefinition functions that have dirty ICs
Walk ICs to determine whether nmethods are dependent on redefined classes. Reviewed-by: sspitsyn, eosterlund
This commit is contained in:
parent
f0b707b94b
commit
5c5089b0a2
@ -931,13 +931,13 @@ void AOTCodeHeap::oops_do(OopClosure* f) {
|
|||||||
// Scan only klasses_got cells which should have only Klass*,
|
// Scan only klasses_got cells which should have only Klass*,
|
||||||
// metadata_got cells are scanned only for alive AOT methods
|
// metadata_got cells are scanned only for alive AOT methods
|
||||||
// by AOTCompiledMethod::metadata_do().
|
// by AOTCompiledMethod::metadata_do().
|
||||||
void AOTCodeHeap::got_metadata_do(void f(Metadata*)) {
|
void AOTCodeHeap::got_metadata_do(MetadataClosure* f) {
|
||||||
for (int i = 1; i < _klasses_got_size; i++) {
|
for (int i = 1; i < _klasses_got_size; i++) {
|
||||||
Metadata** p = &_klasses_got[i];
|
Metadata** p = &_klasses_got[i];
|
||||||
Metadata* md = *p;
|
Metadata* md = *p;
|
||||||
if (md == NULL) continue; // skip non-oops
|
if (md == NULL) continue; // skip non-oops
|
||||||
if (Metaspace::contains(md)) {
|
if (Metaspace::contains(md)) {
|
||||||
f(md);
|
f->do_metadata(md);
|
||||||
} else {
|
} else {
|
||||||
intptr_t meta = (intptr_t)md;
|
intptr_t meta = (intptr_t)md;
|
||||||
fatal("Invalid value in _klasses_got[%d] = " INTPTR_FORMAT, i, meta);
|
fatal("Invalid value in _klasses_got[%d] = " INTPTR_FORMAT, i, meta);
|
||||||
@ -969,7 +969,7 @@ int AOTCodeHeap::verify_icholder_relocations() {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void AOTCodeHeap::metadata_do(void f(Metadata*)) {
|
void AOTCodeHeap::metadata_do(MetadataClosure* f) {
|
||||||
for (int index = 0; index < _method_count; index++) {
|
for (int index = 0; index < _method_count; index++) {
|
||||||
if (_code_to_aot[index]._state != in_use) {
|
if (_code_to_aot[index]._state != in_use) {
|
||||||
continue; // Skip uninitialized entries.
|
continue; // Skip uninitialized entries.
|
||||||
|
@ -252,8 +252,8 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
void oops_do(OopClosure* f);
|
void oops_do(OopClosure* f);
|
||||||
void metadata_do(void f(Metadata*));
|
void metadata_do(MetadataClosure* f);
|
||||||
void got_metadata_do(void f(Metadata*));
|
void got_metadata_do(MetadataClosure* f);
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
bool got_contains(Metadata **p) {
|
bool got_contains(Metadata **p) {
|
||||||
|
@ -246,7 +246,7 @@ bool AOTCompiledMethod::make_entrant() {
|
|||||||
|
|
||||||
// Iterate over metadata calling this function. Used by RedefineClasses
|
// Iterate over metadata calling this function. Used by RedefineClasses
|
||||||
// Copied from nmethod::metadata_do
|
// Copied from nmethod::metadata_do
|
||||||
void AOTCompiledMethod::metadata_do(void f(Metadata*)) {
|
void AOTCompiledMethod::metadata_do(MetadataClosure* f) {
|
||||||
address low_boundary = verified_entry_point();
|
address low_boundary = verified_entry_point();
|
||||||
{
|
{
|
||||||
// Visit all immediate references that are embedded in the instruction stream.
|
// Visit all immediate references that are embedded in the instruction stream.
|
||||||
@ -262,7 +262,7 @@ void AOTCompiledMethod::metadata_do(void f(Metadata*)) {
|
|||||||
"metadata must be found in exactly one place");
|
"metadata must be found in exactly one place");
|
||||||
if (r->metadata_is_immediate() && r->metadata_value() != NULL) {
|
if (r->metadata_is_immediate() && r->metadata_value() != NULL) {
|
||||||
Metadata* md = r->metadata_value();
|
Metadata* md = r->metadata_value();
|
||||||
if (md != _method) f(md);
|
if (md != _method) f->do_metadata(md);
|
||||||
}
|
}
|
||||||
} else if (iter.type() == relocInfo::virtual_call_type) {
|
} else if (iter.type() == relocInfo::virtual_call_type) {
|
||||||
ResourceMark rm;
|
ResourceMark rm;
|
||||||
@ -270,13 +270,13 @@ void AOTCompiledMethod::metadata_do(void f(Metadata*)) {
|
|||||||
CompiledIC *ic = CompiledIC_at(&iter);
|
CompiledIC *ic = CompiledIC_at(&iter);
|
||||||
if (ic->is_icholder_call()) {
|
if (ic->is_icholder_call()) {
|
||||||
CompiledICHolder* cichk = ic->cached_icholder();
|
CompiledICHolder* cichk = ic->cached_icholder();
|
||||||
f(cichk->holder_metadata());
|
f->do_metadata(cichk->holder_metadata());
|
||||||
f(cichk->holder_klass());
|
f->do_metadata(cichk->holder_klass());
|
||||||
} else {
|
} else {
|
||||||
// Get Klass* or NULL (if value is -1) from GOT cell of virtual call PLT stub.
|
// Get Klass* or NULL (if value is -1) from GOT cell of virtual call PLT stub.
|
||||||
Metadata* ic_oop = ic->cached_metadata();
|
Metadata* ic_oop = ic->cached_metadata();
|
||||||
if (ic_oop != NULL) {
|
if (ic_oop != NULL) {
|
||||||
f(ic_oop);
|
f->do_metadata(ic_oop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (iter.type() == relocInfo::static_call_type ||
|
} else if (iter.type() == relocInfo::static_call_type ||
|
||||||
@ -284,7 +284,7 @@ void AOTCompiledMethod::metadata_do(void f(Metadata*)) {
|
|||||||
// Check Method* in AOT c2i stub for other calls.
|
// Check Method* in AOT c2i stub for other calls.
|
||||||
Metadata* meta = (Metadata*)nativeLoadGot_at(nativePltCall_at(iter.addr())->plt_c2i_stub())->data();
|
Metadata* meta = (Metadata*)nativeLoadGot_at(nativePltCall_at(iter.addr())->plt_c2i_stub())->data();
|
||||||
if (meta != NULL) {
|
if (meta != NULL) {
|
||||||
f(meta);
|
f->do_metadata(meta);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -302,11 +302,11 @@ void AOTCompiledMethod::metadata_do(void f(Metadata*)) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
assert(Metaspace::contains(m), "");
|
assert(Metaspace::contains(m), "");
|
||||||
f(m);
|
f->do_metadata(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Visit metadata not embedded in the other places.
|
// Visit metadata not embedded in the other places.
|
||||||
if (_method != NULL) f(_method);
|
if (_method != NULL) f->do_metadata(_method);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AOTCompiledMethod::print() const {
|
void AOTCompiledMethod::print() const {
|
||||||
|
@ -241,7 +241,7 @@ private:
|
|||||||
address get_original_pc(const frame* fr) { return *orig_pc_addr(fr); }
|
address get_original_pc(const frame* fr) { return *orig_pc_addr(fr); }
|
||||||
void set_original_pc(const frame* fr, address pc) { *orig_pc_addr(fr) = pc; }
|
void set_original_pc(const frame* fr, address pc) { *orig_pc_addr(fr) = pc; }
|
||||||
|
|
||||||
virtual void metadata_do(void f(Metadata*));
|
virtual void metadata_do(MetadataClosure* f);
|
||||||
|
|
||||||
bool metadata_got_contains(Metadata **p) {
|
bool metadata_got_contains(Metadata **p) {
|
||||||
return p >= &_metadata_got[0] && p < &_metadata_got[_metadata_size];
|
return p >= &_metadata_got[0] && p < &_metadata_got[_metadata_size];
|
||||||
|
@ -78,7 +78,7 @@ void AOTLoader::oops_do(OopClosure* f) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AOTLoader::metadata_do(void f(Metadata*)) {
|
void AOTLoader::metadata_do(MetadataClosure* f) {
|
||||||
if (UseAOT) {
|
if (UseAOT) {
|
||||||
FOR_ALL_AOT_HEAPS(heap) {
|
FOR_ALL_AOT_HEAPS(heap) {
|
||||||
(*heap)->metadata_do(f);
|
(*heap)->metadata_do(f);
|
||||||
|
@ -62,7 +62,7 @@ public:
|
|||||||
static void load_for_klass(InstanceKlass* ik, Thread* thread) NOT_AOT_RETURN;
|
static void load_for_klass(InstanceKlass* ik, Thread* thread) NOT_AOT_RETURN;
|
||||||
static uint64_t get_saved_fingerprint(InstanceKlass* ik) NOT_AOT({ return 0; });
|
static uint64_t get_saved_fingerprint(InstanceKlass* ik) NOT_AOT({ return 0; });
|
||||||
static void oops_do(OopClosure* f) NOT_AOT_RETURN;
|
static void oops_do(OopClosure* f) NOT_AOT_RETURN;
|
||||||
static void metadata_do(void f(Metadata*)) NOT_AOT_RETURN;
|
static void metadata_do(MetadataClosure* f) NOT_AOT_RETURN;
|
||||||
static void mark_evol_dependent_methods(InstanceKlass* dependee) NOT_AOT_RETURN;
|
static void mark_evol_dependent_methods(InstanceKlass* dependee) NOT_AOT_RETURN;
|
||||||
|
|
||||||
NOT_PRODUCT( static void print_statistics() NOT_AOT_RETURN; )
|
NOT_PRODUCT( static void print_statistics() NOT_AOT_RETURN; )
|
||||||
|
@ -465,7 +465,7 @@ public:
|
|||||||
void record_out_of_memory_failure();
|
void record_out_of_memory_failure();
|
||||||
|
|
||||||
// RedefineClasses support
|
// RedefineClasses support
|
||||||
void metadata_do(void f(Metadata*)) { _factory->metadata_do(f); }
|
void metadata_do(MetadataClosure* f) { _factory->metadata_do(f); }
|
||||||
|
|
||||||
// Dump the compilation replay data for the ciEnv to the stream.
|
// Dump the compilation replay data for the ciEnv to the stream.
|
||||||
void dump_replay_data(int compile_id);
|
void dump_replay_data(int compile_id);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -689,11 +689,11 @@ ciSymbol* ciObjectFactory::vm_symbol_at(int index) {
|
|||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
// ciObjectFactory::metadata_do
|
// ciObjectFactory::metadata_do
|
||||||
void ciObjectFactory::metadata_do(void f(Metadata*)) {
|
void ciObjectFactory::metadata_do(MetadataClosure* f) {
|
||||||
if (_ci_metadata == NULL) return;
|
if (_ci_metadata == NULL) return;
|
||||||
for (int j = 0; j< _ci_metadata->length(); j++) {
|
for (int j = 0; j< _ci_metadata->length(); j++) {
|
||||||
Metadata* o = _ci_metadata->at(j)->constant_encoding();
|
Metadata* o = _ci_metadata->at(j)->constant_encoding();
|
||||||
f(o);
|
f->do_metadata(o);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,7 +140,7 @@ public:
|
|||||||
|
|
||||||
GrowableArray<ciMetadata*>* get_ci_metadata() const { return _ci_metadata; }
|
GrowableArray<ciMetadata*>* get_ci_metadata() const { return _ci_metadata; }
|
||||||
// RedefineClasses support
|
// RedefineClasses support
|
||||||
void metadata_do(void f(Metadata*));
|
void metadata_do(MetadataClosure* f);
|
||||||
|
|
||||||
void print_contents();
|
void print_contents();
|
||||||
void print();
|
void print();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -42,6 +42,10 @@ MetadataOnStackBuffer* MetadataOnStackMark::_free_buffers = NULL;
|
|||||||
MetadataOnStackBuffer* MetadataOnStackMark::_current_buffer = NULL;
|
MetadataOnStackBuffer* MetadataOnStackMark::_current_buffer = NULL;
|
||||||
NOT_PRODUCT(bool MetadataOnStackMark::_is_active = false;)
|
NOT_PRODUCT(bool MetadataOnStackMark::_is_active = false;)
|
||||||
|
|
||||||
|
class MetadataOnStackClosure : public MetadataClosure {
|
||||||
|
void do_metadata(Metadata* m) { Metadata::mark_on_stack(m); }
|
||||||
|
};
|
||||||
|
|
||||||
// Walk metadata on the stack and mark it so that redefinition doesn't delete
|
// Walk metadata on the stack and mark it so that redefinition doesn't delete
|
||||||
// it. Class unloading only deletes in-error class files, methods created by
|
// it. Class unloading only deletes in-error class files, methods created by
|
||||||
// the relocator and dummy constant pools. None of these appear anywhere except
|
// the relocator and dummy constant pools. None of these appear anywhere except
|
||||||
@ -55,8 +59,9 @@ MetadataOnStackMark::MetadataOnStackMark(bool redefinition_walk) {
|
|||||||
Threads::metadata_handles_do(Metadata::mark_on_stack);
|
Threads::metadata_handles_do(Metadata::mark_on_stack);
|
||||||
|
|
||||||
if (redefinition_walk) {
|
if (redefinition_walk) {
|
||||||
Threads::metadata_do(Metadata::mark_on_stack);
|
MetadataOnStackClosure md_on_stack;
|
||||||
CodeCache::metadata_do(Metadata::mark_on_stack);
|
Threads::metadata_do(&md_on_stack);
|
||||||
|
CodeCache::metadata_do(&md_on_stack);
|
||||||
CompileBroker::mark_on_stack();
|
CompileBroker::mark_on_stack();
|
||||||
JvmtiCurrentBreakpoints::metadata_do(Metadata::mark_on_stack);
|
JvmtiCurrentBreakpoints::metadata_do(Metadata::mark_on_stack);
|
||||||
ThreadService::metadata_do(Metadata::mark_on_stack);
|
ThreadService::metadata_do(Metadata::mark_on_stack);
|
||||||
|
@ -667,7 +667,7 @@ void CodeCache::nmethods_do(void f(nmethod* nm)) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeCache::metadata_do(void f(Metadata* m)) {
|
void CodeCache::metadata_do(MetadataClosure* f) {
|
||||||
assert_locked_or_safepoint(CodeCache_lock);
|
assert_locked_or_safepoint(CodeCache_lock);
|
||||||
NMethodIterator iter(NMethodIterator::only_alive_and_not_unloading);
|
NMethodIterator iter(NMethodIterator::only_alive_and_not_unloading);
|
||||||
while(iter.next()) {
|
while(iter.next()) {
|
||||||
@ -1061,13 +1061,14 @@ int CodeCache::mark_dependents_for_evol_deoptimization() {
|
|||||||
// ...Already marked in the previous pass; count it here.
|
// ...Already marked in the previous pass; count it here.
|
||||||
// Also counts AOT compiled methods, already marked.
|
// Also counts AOT compiled methods, already marked.
|
||||||
number_of_marked_CodeBlobs++;
|
number_of_marked_CodeBlobs++;
|
||||||
} else if (nm->is_evol_dependent()) {
|
} else if (nm->has_evol_metadata()) {
|
||||||
ResourceMark rm;
|
ResourceMark rm;
|
||||||
nm->mark_for_deoptimization();
|
nm->mark_for_deoptimization();
|
||||||
number_of_marked_CodeBlobs++;
|
number_of_marked_CodeBlobs++;
|
||||||
} else {
|
} else {
|
||||||
// flush caches in case they refer to a redefined Method*
|
// Inline caches that refer to an nmethod are deoptimized already, because
|
||||||
nm->clear_inline_caches();
|
// the Method* is walked in the metadata section of the nmethod.
|
||||||
|
assert(!nm->is_evol_dependent(), "should no longer be necessary");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,7 +147,7 @@ class CodeCache : AllStatic {
|
|||||||
static void blobs_do(void f(CodeBlob* cb)); // iterates over all CodeBlobs
|
static void blobs_do(void f(CodeBlob* cb)); // iterates over all CodeBlobs
|
||||||
static void blobs_do(CodeBlobClosure* f); // iterates over all CodeBlobs
|
static void blobs_do(CodeBlobClosure* f); // iterates over all CodeBlobs
|
||||||
static void nmethods_do(void f(nmethod* nm)); // iterates over all nmethods
|
static void nmethods_do(void f(nmethod* nm)); // iterates over all nmethods
|
||||||
static void metadata_do(void f(Metadata* m)); // iterates over metadata in alive nmethods
|
static void metadata_do(MetadataClosure* f); // iterates over metadata in alive nmethods
|
||||||
|
|
||||||
// Lookup
|
// Lookup
|
||||||
static CodeBlob* find_blob(void* start); // Returns the CodeBlob containing the given address
|
static CodeBlob* find_blob(void* start); // Returns the CodeBlob containing the given address
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -415,20 +415,22 @@ void CompiledMethod::clear_ic_callsites() {
|
|||||||
|
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
// Check class_loader is alive for this bit of metadata.
|
// Check class_loader is alive for this bit of metadata.
|
||||||
static void check_class(Metadata* md) {
|
class CheckClass : public MetadataClosure {
|
||||||
Klass* klass = NULL;
|
void do_metadata(Metadata* md) {
|
||||||
if (md->is_klass()) {
|
Klass* klass = NULL;
|
||||||
klass = ((Klass*)md);
|
if (md->is_klass()) {
|
||||||
} else if (md->is_method()) {
|
klass = ((Klass*)md);
|
||||||
klass = ((Method*)md)->method_holder();
|
} else if (md->is_method()) {
|
||||||
} else if (md->is_methodData()) {
|
klass = ((Method*)md)->method_holder();
|
||||||
klass = ((MethodData*)md)->method()->method_holder();
|
} else if (md->is_methodData()) {
|
||||||
} else {
|
klass = ((MethodData*)md)->method()->method_holder();
|
||||||
md->print();
|
} else {
|
||||||
ShouldNotReachHere();
|
md->print();
|
||||||
}
|
ShouldNotReachHere();
|
||||||
assert(klass->is_loader_alive(), "must be alive");
|
}
|
||||||
}
|
assert(klass->is_loader_alive(), "must be alive");
|
||||||
|
}
|
||||||
|
};
|
||||||
#endif // ASSERT
|
#endif // ASSERT
|
||||||
|
|
||||||
|
|
||||||
@ -550,8 +552,11 @@ bool CompiledMethod::unload_nmethod_caches(bool unloading_occurred) {
|
|||||||
// All static stubs need to be cleaned.
|
// All static stubs need to be cleaned.
|
||||||
clean_ic_stubs();
|
clean_ic_stubs();
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
// Check that the metadata embedded in the nmethod is alive
|
// Check that the metadata embedded in the nmethod is alive
|
||||||
DEBUG_ONLY(metadata_do(check_class));
|
CheckClass check_class;
|
||||||
|
metadata_do(&check_class);
|
||||||
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -628,3 +633,35 @@ bool CompiledMethod::nmethod_access_is_safe(nmethod* nm) {
|
|||||||
os::is_readable_pointer(method->constants()) &&
|
os::is_readable_pointer(method->constants()) &&
|
||||||
os::is_readable_pointer(method->signature());
|
os::is_readable_pointer(method->signature());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class HasEvolDependency : public MetadataClosure {
|
||||||
|
bool _has_evol_dependency;
|
||||||
|
public:
|
||||||
|
HasEvolDependency() : _has_evol_dependency(false) {}
|
||||||
|
void do_metadata(Metadata* md) {
|
||||||
|
if (md->is_method()) {
|
||||||
|
Method* method = (Method*)md;
|
||||||
|
if (method->is_old()) {
|
||||||
|
_has_evol_dependency = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool has_evol_dependency() const { return _has_evol_dependency; }
|
||||||
|
};
|
||||||
|
|
||||||
|
bool CompiledMethod::has_evol_metadata() {
|
||||||
|
// Check the metadata in relocIter and CompiledIC and also deoptimize
|
||||||
|
// any nmethod that has reference to old methods.
|
||||||
|
HasEvolDependency check_evol;
|
||||||
|
metadata_do(&check_evol);
|
||||||
|
if (check_evol.has_evol_dependency() && log_is_enabled(Debug, redefine, class, nmethod)) {
|
||||||
|
ResourceMark rm;
|
||||||
|
log_debug(redefine, class, nmethod)
|
||||||
|
("Found evol dependency of nmethod %s.%s(%s) compile_id=%d on in nmethod metadata",
|
||||||
|
_method->method_holder()->external_name(),
|
||||||
|
_method->name()->as_C_string(),
|
||||||
|
_method->signature()->as_C_string(),
|
||||||
|
compile_id());
|
||||||
|
}
|
||||||
|
return check_evol.has_evol_dependency();
|
||||||
|
}
|
||||||
|
@ -38,6 +38,7 @@ class CompiledStaticCall;
|
|||||||
class NativeCallWrapper;
|
class NativeCallWrapper;
|
||||||
class ScopeDesc;
|
class ScopeDesc;
|
||||||
class CompiledIC;
|
class CompiledIC;
|
||||||
|
class MetadataClosure;
|
||||||
|
|
||||||
// This class is used internally by nmethods, to cache
|
// This class is used internally by nmethods, to cache
|
||||||
// exception/pc/handler information.
|
// exception/pc/handler information.
|
||||||
@ -368,6 +369,8 @@ public:
|
|||||||
void verify_oop_relocations();
|
void verify_oop_relocations();
|
||||||
|
|
||||||
virtual bool is_evol_dependent() = 0;
|
virtual bool is_evol_dependent() = 0;
|
||||||
|
bool has_evol_metadata();
|
||||||
|
|
||||||
// Fast breakpoint support. Tells if this compiled method is
|
// Fast breakpoint support. Tells if this compiled method is
|
||||||
// dependent on the given method. Returns true if this nmethod
|
// dependent on the given method. Returns true if this nmethod
|
||||||
// corresponds to the given method as well.
|
// corresponds to the given method as well.
|
||||||
@ -384,7 +387,7 @@ public:
|
|||||||
Method* attached_method(address call_pc);
|
Method* attached_method(address call_pc);
|
||||||
Method* attached_method_before_pc(address pc);
|
Method* attached_method_before_pc(address pc);
|
||||||
|
|
||||||
virtual void metadata_do(void f(Metadata*)) = 0;
|
virtual void metadata_do(MetadataClosure* f) = 0;
|
||||||
|
|
||||||
// GC support
|
// GC support
|
||||||
protected:
|
protected:
|
||||||
|
@ -1499,7 +1499,7 @@ void nmethod::post_compiled_method_unload() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Iterate over metadata calling this function. Used by RedefineClasses
|
// Iterate over metadata calling this function. Used by RedefineClasses
|
||||||
void nmethod::metadata_do(void f(Metadata*)) {
|
void nmethod::metadata_do(MetadataClosure* f) {
|
||||||
{
|
{
|
||||||
// Visit all immediate references that are embedded in the instruction stream.
|
// Visit all immediate references that are embedded in the instruction stream.
|
||||||
RelocIterator iter(this, oops_reloc_begin());
|
RelocIterator iter(this, oops_reloc_begin());
|
||||||
@ -1514,7 +1514,7 @@ void nmethod::metadata_do(void f(Metadata*)) {
|
|||||||
"metadata must be found in exactly one place");
|
"metadata must be found in exactly one place");
|
||||||
if (r->metadata_is_immediate() && r->metadata_value() != NULL) {
|
if (r->metadata_is_immediate() && r->metadata_value() != NULL) {
|
||||||
Metadata* md = r->metadata_value();
|
Metadata* md = r->metadata_value();
|
||||||
if (md != _method) f(md);
|
if (md != _method) f->do_metadata(md);
|
||||||
}
|
}
|
||||||
} else if (iter.type() == relocInfo::virtual_call_type) {
|
} else if (iter.type() == relocInfo::virtual_call_type) {
|
||||||
// Check compiledIC holders associated with this nmethod
|
// Check compiledIC holders associated with this nmethod
|
||||||
@ -1522,12 +1522,12 @@ void nmethod::metadata_do(void f(Metadata*)) {
|
|||||||
CompiledIC *ic = CompiledIC_at(&iter);
|
CompiledIC *ic = CompiledIC_at(&iter);
|
||||||
if (ic->is_icholder_call()) {
|
if (ic->is_icholder_call()) {
|
||||||
CompiledICHolder* cichk = ic->cached_icholder();
|
CompiledICHolder* cichk = ic->cached_icholder();
|
||||||
f(cichk->holder_metadata());
|
f->do_metadata(cichk->holder_metadata());
|
||||||
f(cichk->holder_klass());
|
f->do_metadata(cichk->holder_klass());
|
||||||
} else {
|
} else {
|
||||||
Metadata* ic_oop = ic->cached_metadata();
|
Metadata* ic_oop = ic->cached_metadata();
|
||||||
if (ic_oop != NULL) {
|
if (ic_oop != NULL) {
|
||||||
f(ic_oop);
|
f->do_metadata(ic_oop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1538,11 +1538,11 @@ void nmethod::metadata_do(void f(Metadata*)) {
|
|||||||
for (Metadata** p = metadata_begin(); p < metadata_end(); p++) {
|
for (Metadata** p = metadata_begin(); p < metadata_end(); p++) {
|
||||||
if (*p == Universe::non_oop_word() || *p == NULL) continue; // skip non-oops
|
if (*p == Universe::non_oop_word() || *p == NULL) continue; // skip non-oops
|
||||||
Metadata* md = *p;
|
Metadata* md = *p;
|
||||||
f(md);
|
f->do_metadata(md);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Visit metadata not embedded in the other places.
|
// Visit metadata not embedded in the other places.
|
||||||
if (_method != NULL) f(_method);
|
if (_method != NULL) f->do_metadata(_method);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The _is_unloading_state encodes a tuple comprising the unloading cycle
|
// The _is_unloading_state encodes a tuple comprising the unloading cycle
|
||||||
|
@ -591,7 +591,7 @@ public:
|
|||||||
static int osr_entry_point_offset() { return offset_of(nmethod, _osr_entry_point); }
|
static int osr_entry_point_offset() { return offset_of(nmethod, _osr_entry_point); }
|
||||||
static int state_offset() { return offset_of(nmethod, _state); }
|
static int state_offset() { return offset_of(nmethod, _state); }
|
||||||
|
|
||||||
virtual void metadata_do(void f(Metadata*));
|
virtual void metadata_do(MetadataClosure* f);
|
||||||
|
|
||||||
NativeCallWrapper* call_wrapper_at(address call) const;
|
NativeCallWrapper* call_wrapper_at(address call) const;
|
||||||
NativeCallWrapper* call_wrapper_before(address return_pc) const;
|
NativeCallWrapper* call_wrapper_before(address return_pc) const;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -197,13 +197,13 @@ bool CompileTask::is_unloaded() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RedefineClasses support
|
// RedefineClasses support
|
||||||
void CompileTask::metadata_do(void f(Metadata*)) {
|
void CompileTask::metadata_do(MetadataClosure* f) {
|
||||||
if (is_unloaded()) {
|
if (is_unloaded()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
f(method());
|
f->do_metadata(method());
|
||||||
if (hot_method() != NULL && hot_method() != method()) {
|
if (hot_method() != NULL && hot_method() != method()) {
|
||||||
f(hot_method());
|
f->do_metadata(hot_method());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,7 +177,7 @@ class CompileTask : public CHeapObj<mtCompiler> {
|
|||||||
bool is_unloaded() const;
|
bool is_unloaded() const;
|
||||||
|
|
||||||
// RedefineClasses support
|
// RedefineClasses support
|
||||||
void metadata_do(void f(Metadata*));
|
void metadata_do(MetadataClosure* f);
|
||||||
void mark_on_stack();
|
void mark_on_stack();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -36,6 +36,7 @@ class DataLayout;
|
|||||||
class KlassClosure;
|
class KlassClosure;
|
||||||
class ClassLoaderData;
|
class ClassLoaderData;
|
||||||
class Symbol;
|
class Symbol;
|
||||||
|
class Metadata;
|
||||||
|
|
||||||
// The following classes are C++ `closures` for iterating over objects, roots and spaces
|
// The following classes are C++ `closures` for iterating over objects, roots and spaces
|
||||||
|
|
||||||
@ -124,6 +125,11 @@ class CLDClosure : public Closure {
|
|||||||
virtual void do_cld(ClassLoaderData* cld) = 0;
|
virtual void do_cld(ClassLoaderData* cld) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MetadataClosure : public Closure {
|
||||||
|
public:
|
||||||
|
virtual void do_metadata(Metadata* md) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class CLDToOopClosure : public CLDClosure {
|
class CLDToOopClosure : public CLDClosure {
|
||||||
OopClosure* _oop_closure;
|
OopClosure* _oop_closure;
|
||||||
|
@ -1115,13 +1115,13 @@ void frame::nmethods_do(CodeBlobClosure* cf) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// call f() on the interpreted Method*s in the stack.
|
// Call f closure on the interpreted Method*s in the stack.
|
||||||
// Have to walk the entire code cache for the compiled frames Yuck.
|
void frame::metadata_do(MetadataClosure* f) {
|
||||||
void frame::metadata_do(void f(Metadata*)) {
|
ResourceMark rm;
|
||||||
if (is_interpreted_frame()) {
|
if (is_interpreted_frame()) {
|
||||||
Method* m = this->interpreter_frame_method();
|
Method* m = this->interpreter_frame_method();
|
||||||
assert(m != NULL, "expecting a method in this frame");
|
assert(m != NULL, "expecting a method in this frame");
|
||||||
f(m);
|
f->do_metadata(m);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -378,7 +378,7 @@ class frame {
|
|||||||
void nmethods_do(CodeBlobClosure* cf);
|
void nmethods_do(CodeBlobClosure* cf);
|
||||||
|
|
||||||
// RedefineClasses support for finding live interpreted methods on the stack
|
// RedefineClasses support for finding live interpreted methods on the stack
|
||||||
void metadata_do(void f(Metadata*));
|
void metadata_do(MetadataClosure* f);
|
||||||
|
|
||||||
// Verification
|
// Verification
|
||||||
void verify(const RegisterMap* map);
|
void verify(const RegisterMap* map);
|
||||||
|
@ -2960,7 +2960,7 @@ void JavaThread::nmethods_do(CodeBlobClosure* cf) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JavaThread::metadata_do(void f(Metadata*)) {
|
void JavaThread::metadata_do(MetadataClosure* f) {
|
||||||
if (has_last_Java_frame()) {
|
if (has_last_Java_frame()) {
|
||||||
// Traverse the execution stack to call f() on the methods in the stack
|
// Traverse the execution stack to call f() on the methods in the stack
|
||||||
for (StackFrameStream fst(this); !fst.is_done(); fst.next()) {
|
for (StackFrameStream fst(this); !fst.is_done(); fst.next()) {
|
||||||
@ -4574,7 +4574,7 @@ void Threads::nmethods_do(CodeBlobClosure* cf) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Threads::metadata_do(void f(Metadata*)) {
|
void Threads::metadata_do(MetadataClosure* f) {
|
||||||
ALL_JAVA_THREADS(p) {
|
ALL_JAVA_THREADS(p) {
|
||||||
p->metadata_do(f);
|
p->metadata_do(f);
|
||||||
}
|
}
|
||||||
|
@ -1866,7 +1866,7 @@ class JavaThread: public Thread {
|
|||||||
virtual void nmethods_do(CodeBlobClosure* cf);
|
virtual void nmethods_do(CodeBlobClosure* cf);
|
||||||
|
|
||||||
// RedefineClasses Support
|
// RedefineClasses Support
|
||||||
void metadata_do(void f(Metadata*));
|
void metadata_do(MetadataClosure* f);
|
||||||
|
|
||||||
// Misc. operations
|
// Misc. operations
|
||||||
char* name() const { return (char*)get_thread_name(); }
|
char* name() const { return (char*)get_thread_name(); }
|
||||||
@ -2281,7 +2281,7 @@ class Threads: AllStatic {
|
|||||||
static void nmethods_do(CodeBlobClosure* cf);
|
static void nmethods_do(CodeBlobClosure* cf);
|
||||||
|
|
||||||
// RedefineClasses support
|
// RedefineClasses support
|
||||||
static void metadata_do(void f(Metadata*));
|
static void metadata_do(MetadataClosure* f);
|
||||||
static void metadata_handles_do(void f(Metadata*));
|
static void metadata_handles_do(void f(Metadata*));
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
|
Loading…
Reference in New Issue
Block a user