8235912: JvmtiBreakpoint remove oops_do and metadata_do

Reviewed-by: coleenp, sspitsyn
This commit is contained in:
Robbin Ehn 2019-12-19 16:47:59 +01:00
parent 18bc0214db
commit e4c96dea46
4 changed files with 29 additions and 141 deletions

View File

@ -70,7 +70,6 @@ MetadataOnStackMark::MetadataOnStackMark(bool walk_all_metadata, bool redefiniti
CodeCache::old_nmethods_do(&md_on_stack);
}
CompileBroker::mark_on_stack();
JvmtiCurrentBreakpoints::metadata_do(Metadata::mark_on_stack);
ThreadService::metadata_do(Metadata::mark_on_stack);
#if INCLUDE_JVMCI
JVMCI::metadata_do(Metadata::mark_on_stack);

View File

@ -2600,7 +2600,6 @@ void JvmtiExport::clear_detected_exception(JavaThread* thread) {
}
void JvmtiExport::oops_do(OopClosure* f) {
JvmtiCurrentBreakpoints::oops_do(f);
JvmtiObjectAllocEventCollector::oops_do_for_all_threads(f);
}

View File

@ -26,6 +26,8 @@
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "code/nmethod.hpp"
#include "gc/shared/oopStorage.hpp"
#include "gc/shared/oopStorageSet.hpp"
#include "interpreter/interpreter.hpp"
#include "interpreter/oopMapCache.hpp"
#include "jvmtifiles/jvmtiEnv.hpp"
@ -171,24 +173,6 @@ void GrowableCache::append(GrowableElement* e) {
recache();
}
// insert a copy of the element using lessthan()
void GrowableCache::insert(GrowableElement* e) {
GrowableElement *new_e = e->clone();
_elements->append(new_e);
int n = length()-2;
for (int i=n; i>=0; i--) {
GrowableElement *e1 = _elements->at(i);
GrowableElement *e2 = _elements->at(i+1);
if (e2->lessThan(e1)) {
_elements->at_put(i+1, e1);
_elements->at_put(i, e2);
}
}
recache();
}
// remove the element at index
void GrowableCache::remove (int index) {
GrowableElement *e = _elements->at(index);
@ -209,58 +193,40 @@ void GrowableCache::clear() {
recache();
}
void GrowableCache::oops_do(OopClosure* f) {
int len = _elements->length();
for (int i=0; i<len; i++) {
GrowableElement *e = _elements->at(i);
e->oops_do(f);
}
}
void GrowableCache::metadata_do(void f(Metadata*)) {
int len = _elements->length();
for (int i=0; i<len; i++) {
GrowableElement *e = _elements->at(i);
e->metadata_do(f);
}
}
//
// class JvmtiBreakpoint
//
JvmtiBreakpoint::JvmtiBreakpoint() {
_method = NULL;
_bci = 0;
_class_holder = NULL;
JvmtiBreakpoint::JvmtiBreakpoint(Method* m_method, jlocation location)
: _method(m_method), _bci((int)location), _class_holder(NULL) {
assert(_method != NULL, "No method for breakpoint.");
assert(_bci >= 0, "Negative bci for breakpoint.");
oop class_holder_oop = _method->method_holder()->klass_holder();
_class_holder = OopStorageSet::vm_global()->allocate();
if (_class_holder == NULL) {
vm_exit_out_of_memory(sizeof(oop), OOM_MALLOC_ERROR,
"Cannot create breakpoint oop handle");
}
NativeAccess<>::oop_store(_class_holder, class_holder_oop);
}
JvmtiBreakpoint::JvmtiBreakpoint(Method* m_method, jlocation location) {
_method = m_method;
_class_holder = _method->method_holder()->klass_holder();
#ifdef CHECK_UNHANDLED_OOPS
// _class_holder can't be wrapped in a Handle, because JvmtiBreakpoints are
// sometimes allocated on the heap.
//
// The code handling JvmtiBreakpoints allocated on the stack can't be
// interrupted by a GC until _class_holder is reachable by the GC via the
// oops_do method.
Thread::current()->allow_unhandled_oop(&_class_holder);
#endif // CHECK_UNHANDLED_OOPS
assert(_method != NULL, "_method != NULL");
_bci = (int) location;
assert(_bci >= 0, "_bci >= 0");
JvmtiBreakpoint::~JvmtiBreakpoint() {
if (_class_holder != NULL) {
NativeAccess<>::oop_store(_class_holder, (oop)NULL);
OopStorageSet::vm_global()->release(_class_holder);
}
}
void JvmtiBreakpoint::copy(JvmtiBreakpoint& bp) {
_method = bp._method;
_bci = bp._bci;
_class_holder = bp._class_holder;
}
bool JvmtiBreakpoint::lessThan(JvmtiBreakpoint& bp) {
Unimplemented();
return false;
_class_holder = OopStorageSet::vm_global()->allocate();
if (_class_holder == NULL) {
vm_exit_out_of_memory(sizeof(oop), OOM_MALLOC_ERROR,
"Cannot create breakpoint oop handle");
}
oop resolved_ch = NativeAccess<>::oop_load(bp._class_holder);
NativeAccess<>::oop_store(_class_holder, resolved_ch);
}
bool JvmtiBreakpoint::equals(JvmtiBreakpoint& bp) {
@ -268,12 +234,6 @@ bool JvmtiBreakpoint::equals(JvmtiBreakpoint& bp) {
&& _bci == bp._bci;
}
bool JvmtiBreakpoint::is_valid() {
// class loader can be NULL
return _method != NULL &&
_bci >= 0;
}
address JvmtiBreakpoint::getBcp() const {
return _method->bcp_from(_bci);
}
@ -347,21 +307,6 @@ void VM_ChangeBreakpoints::doit() {
}
}
void VM_ChangeBreakpoints::oops_do(OopClosure* f) {
// The JvmtiBreakpoints in _breakpoints will be visited via
// JvmtiExport::oops_do.
if (_bp != NULL) {
_bp->oops_do(f);
}
}
void VM_ChangeBreakpoints::metadata_do(void f(Metadata*)) {
// Walk metadata in breakpoints to keep from being deallocated with RedefineClasses
if (_bp != NULL) {
_bp->metadata_do(f);
}
}
//
// class JvmtiBreakpoints
//
@ -374,14 +319,6 @@ JvmtiBreakpoints::JvmtiBreakpoints(void listener_fun(void *,address *)) {
JvmtiBreakpoints:: ~JvmtiBreakpoints() {}
void JvmtiBreakpoints::oops_do(OopClosure* f) {
_bps.oops_do(f);
}
void JvmtiBreakpoints::metadata_do(void f(Metadata*)) {
_bps.metadata_do(f);
}
void JvmtiBreakpoints::print() {
#ifndef PRODUCT
LogTarget(Trace, jvmti) log;
@ -490,19 +427,6 @@ void JvmtiCurrentBreakpoints::listener_fun(void *this_obj, address *cache) {
set_breakpoint_list(cache);
}
void JvmtiCurrentBreakpoints::oops_do(OopClosure* f) {
if (_jvmti_breakpoints != NULL) {
_jvmti_breakpoints->oops_do(f);
}
}
void JvmtiCurrentBreakpoints::metadata_do(void f(Metadata*)) {
if (_jvmti_breakpoints != NULL) {
_jvmti_breakpoints->metadata_do(f);
}
}
///////////////////////////////////////////////////////////////
//
// class VM_GetOrSetLocal

View File

@ -68,10 +68,7 @@ public:
virtual ~GrowableElement() {}
virtual address getCacheValue() =0;
virtual bool equals(GrowableElement* e) =0;
virtual bool lessThan(GrowableElement *e)=0;
virtual GrowableElement *clone() =0;
virtual void oops_do(OopClosure* f) =0;
virtual void metadata_do(void f(Metadata*)) =0;
};
class GrowableCache {
@ -110,16 +107,10 @@ public:
int find(GrowableElement* e);
// append a copy of the element to the end of the collection, notify listener
void append(GrowableElement* e);
// insert a copy of the element using lessthan(), notify listener
void insert(GrowableElement* e);
// remove the element at index, notify listener
void remove (int index);
// clear out all elements and release all heap space, notify listener
void clear();
// apply f to every element and update the cache
void oops_do(OopClosure* f);
// walk metadata to preserve for RedefineClasses
void metadata_do(void f(Metadata*));
};
@ -141,7 +132,7 @@ public:
~JvmtiBreakpointCache() {}
void initialize(void *this_obj, void listener_fun(void *, address*) ) {
_cache.initialize(this_obj,listener_fun);
_cache.initialize(this_obj, listener_fun);
}
int length() { return _cache.length(); }
@ -149,9 +140,6 @@ public:
int find(JvmtiBreakpoint& e) { return _cache.find((GrowableElement *) &e); }
void append(JvmtiBreakpoint& e) { _cache.append((GrowableElement *) &e); }
void remove (int index) { _cache.remove(index); }
void clear() { _cache.clear(); }
void oops_do(OopClosure* f) { _cache.oops_do(f); }
void metadata_do(void f(Metadata*)) { _cache.metadata_do(f); }
};
@ -171,16 +159,14 @@ class JvmtiBreakpoint : public GrowableElement {
private:
Method* _method;
int _bci;
Bytecodes::Code _orig_bytecode;
oop _class_holder; // keeps _method memory from being deallocated
oop* _class_holder; // keeps _method memory from being deallocated
public:
JvmtiBreakpoint();
JvmtiBreakpoint() : _method(NULL), _bci(0), _class_holder(NULL) {}
JvmtiBreakpoint(Method* m_method, jlocation location);
virtual ~JvmtiBreakpoint();
bool equals(JvmtiBreakpoint& bp);
bool lessThan(JvmtiBreakpoint &bp);
void copy(JvmtiBreakpoint& bp);
bool is_valid();
address getBcp() const;
void each_method_version_do(method_action meth_act);
void set();
@ -191,17 +177,7 @@ public:
// GrowableElement implementation
address getCacheValue() { return getBcp(); }
bool lessThan(GrowableElement* e) { Unimplemented(); return false; }
bool equals(GrowableElement* e) { return equals((JvmtiBreakpoint&) *e); }
void oops_do(OopClosure* f) {
// Mark the method loader as live so the Method* class loader doesn't get
// unloaded and Method* memory reclaimed.
f->do_oop(&_class_holder);
}
void metadata_do(void f(Metadata*)) {
// walk metadata to preserve for RedefineClasses
f(_method);
}
GrowableElement *clone() {
JvmtiBreakpoint *bp = new JvmtiBreakpoint();
@ -240,15 +216,11 @@ private:
void set_at_safepoint(JvmtiBreakpoint& bp);
void clear_at_safepoint(JvmtiBreakpoint& bp);
static void do_element(GrowableElement *e);
public:
JvmtiBreakpoints(void listener_fun(void *, address *));
~JvmtiBreakpoints();
int length();
void oops_do(OopClosure* f);
void metadata_do(void f(Metadata*));
void print();
int set(JvmtiBreakpoint& bp);
@ -281,7 +253,6 @@ private:
// It exists only to make is_breakpoint fast.
static address *_breakpoint_list;
static inline void set_breakpoint_list(address *breakpoint_list) { _breakpoint_list = breakpoint_list; }
static inline address *get_breakpoint_list() { return _breakpoint_list; }
// Listener for the GrowableCache in _jvmti_breakpoints, updates _breakpoint_list.
static void listener_fun(void *this_obj, address *cache);
@ -292,9 +263,6 @@ public:
// lazily create _jvmti_breakpoints and _breakpoint_list
static JvmtiBreakpoints& get_jvmti_breakpoints();
static void oops_do(OopClosure* f);
static void metadata_do(void f(Metadata*)) NOT_JVMTI_RETURN;
};
///////////////////////////////////////////////////////////////
@ -326,8 +294,6 @@ public:
VMOp_Type type() const { return VMOp_ChangeBreakpoints; }
void doit();
void oops_do(OopClosure* f);
void metadata_do(void f(Metadata*));
};