< prev index next >
src/hotspot/share/code/dependencyContext.hpp
//
class nmethodBucket: public CHeapObj<mtClass> {
friend class VMStructs;
private:
nmethod* _nmethod;
! int _count;
! nmethodBucket* _next;
public:
nmethodBucket(nmethod* nmethod, nmethodBucket* next) :
! _nmethod(nmethod), _count(1), _next(next) {}
! int count() { return _count; }
! int increment() { _count += 1; return _count; }
int decrement();
! nmethodBucket* next() { return _next; }
! void set_next(nmethodBucket* b) { _next = b; }
! nmethod* get_nmethod() { return _nmethod; }
};
//
// Utility class to manipulate nmethod dependency context.
- // The context consists of nmethodBucket* (a head of a linked list)
- // and a boolean flag (does the list contains stale entries). The structure is
- // encoded as an intptr_t: lower bit is used for the flag. It is possible since
- // nmethodBucket* is aligned - the structure is malloc'ed in C heap.
// Dependency context can be attached either to an InstanceKlass (_dep_context field)
// or CallSiteContext oop for call_site_target dependencies (see javaClasses.hpp).
! // DependencyContext class operates on some location which holds a intptr_t value.
//
class DependencyContext : public StackObj {
friend class VMStructs;
friend class TestDependencyContext;
private:
! enum TagBits { _has_stale_entries_bit = 1, _has_stale_entries_mask = 1 };
! intptr_t* _dependency_context_addr;
!
! void set_dependencies(nmethodBucket* b) {
! assert((intptr_t(b) & _has_stale_entries_mask) == 0, "should be aligned");
! if (has_stale_entries()) {
! *_dependency_context_addr = intptr_t(b) | _has_stale_entries_mask;
! } else {
! *_dependency_context_addr = intptr_t(b);
! }
! }
!
! void set_has_stale_entries(bool x) {
! if (x) {
! *_dependency_context_addr |= _has_stale_entries_mask;
! } else {
! *_dependency_context_addr &= ~_has_stale_entries_mask;
! }
! }
!
! nmethodBucket* dependencies() {
! intptr_t value = *_dependency_context_addr;
! return (nmethodBucket*) (value & ~_has_stale_entries_mask);
! }
!
! bool has_stale_entries() const {
! intptr_t value = *_dependency_context_addr;
! return (value & _has_stale_entries_mask) != 0;
! }
static PerfCounter* _perf_total_buckets_allocated_count;
static PerfCounter* _perf_total_buckets_deallocated_count;
static PerfCounter* _perf_total_buckets_stale_count;
static PerfCounter* _perf_total_buckets_stale_acc_count;
public:
#ifdef ASSERT
// Safepoints are forbidden during DC lifetime. GC can invalidate
// _dependency_context_addr if it relocates the holder
// (e.g. CallSiteContext Java object).
uint64_t _safepoint_counter;
! DependencyContext(intptr_t* addr) : _dependency_context_addr(addr),
! _safepoint_counter(SafepointSynchronize::safepoint_counter()) {}
~DependencyContext() {
assert(_safepoint_counter == SafepointSynchronize::safepoint_counter(), "safepoint happened");
}
#else
! DependencyContext(intptr_t* addr) : _dependency_context_addr(addr) {}
#endif // ASSERT
- static const intptr_t EMPTY = 0; // dependencies = NULL, has_stale_entries = false
-
static void init();
int mark_dependent_nmethods(DepChange& changes);
! void add_dependent_nmethod(nmethod* nm, bool expunge_stale_entries = false);
! void remove_dependent_nmethod(nmethod* nm, bool expunge_stale_entries = false);
int remove_all_dependents();
!
! void expunge_stale_entries();
#ifndef PRODUCT
void print_dependent_nmethods(bool verbose);
bool is_dependent_nmethod(nmethod* nm);
- bool find_stale_entries();
#endif //PRODUCT
};
#endif // SHARE_VM_CODE_DEPENDENCYCONTEXT_HPP
//
class nmethodBucket: public CHeapObj<mtClass> {
friend class VMStructs;
private:
nmethod* _nmethod;
! volatile int _count;
! nmethodBucket* volatile _next;
! nmethodBucket* volatile _purge_list_next;
public:
nmethodBucket(nmethod* nmethod, nmethodBucket* next) :
! _nmethod(nmethod), _count(1), _next(next), _purge_list_next(NULL) {}
! int count() { return _count; }
! int increment() { _count += 1; return _count; }
int decrement();
! nmethodBucket* next();
! nmethodBucket* next_not_unloading();
! void set_next(nmethodBucket* b);
! nmethodBucket* purge_list_next();
! void set_purge_list_next(nmethodBucket* b);
! nmethod* get_nmethod() { return _nmethod; }
};
//
// Utility class to manipulate nmethod dependency context.
// Dependency context can be attached either to an InstanceKlass (_dep_context field)
// or CallSiteContext oop for call_site_target dependencies (see javaClasses.hpp).
! // DependencyContext class operates on some location which holds a nmethodBucket* value
! // and uint64_t integer recording the safepoint counter at the last cleanup.
//
class DependencyContext : public StackObj {
friend class VMStructs;
friend class TestDependencyContext;
private:
! nmethodBucket* volatile* _dependency_context_addr;
! volatile uint64_t* _last_cleanup_addr;
! bool claim_cleanup();
! void set_dependencies(nmethodBucket* b);
! nmethodBucket* dependencies();
! nmethodBucket* dependencies_not_unloading();
static PerfCounter* _perf_total_buckets_allocated_count;
static PerfCounter* _perf_total_buckets_deallocated_count;
static PerfCounter* _perf_total_buckets_stale_count;
static PerfCounter* _perf_total_buckets_stale_acc_count;
+ static nmethodBucket* volatile _purge_list;
+ static volatile uint64_t _cleaning_epoch;
public:
#ifdef ASSERT
// Safepoints are forbidden during DC lifetime. GC can invalidate
// _dependency_context_addr if it relocates the holder
// (e.g. CallSiteContext Java object).
uint64_t _safepoint_counter;
! DependencyContext(nmethodBucket* volatile* bucket_addr, volatile uint64_t* last_cleanup_addr)
! : _dependency_context_addr(bucket_addr),
! _last_cleanup_addr(last_cleanup_addr),
! _safepoint_counter(SafepointSynchronize::safepoint_counter()) {}
~DependencyContext() {
assert(_safepoint_counter == SafepointSynchronize::safepoint_counter(), "safepoint happened");
}
#else
! DependencyContext(nmethodBucket* volatile* bucket_addr, volatile uint64_t* last_cleanup_addr)
! : _dependency_context_addr(bucket_addr),
! _last_cleanup_addr(last_cleanup_addr) {}
#endif // ASSERT
static void init();
int mark_dependent_nmethods(DepChange& changes);
! void add_dependent_nmethod(nmethod* nm);
! void remove_dependent_nmethod(nmethod* nm);
int remove_all_dependents();
! void clean_unloading_dependents();
! static void purge_dependency_contexts();
! static void release(nmethodBucket* b);
! static void cleaning_start();
! static void cleaning_end();
#ifndef PRODUCT
void print_dependent_nmethods(bool verbose);
bool is_dependent_nmethod(nmethod* nm);
#endif //PRODUCT
};
#endif // SHARE_VM_CODE_DEPENDENCYCONTEXT_HPP
< prev index next >