30 #include "runtime/perfData.hpp"
31 #include "runtime/safepoint.hpp"
32
33 class nmethod;
34 class DepChange;
35
36 //
37 // nmethodBucket is used to record dependent nmethods for
38 // deoptimization. nmethod dependencies are actually <klass, method>
39 // pairs but we really only care about the klass part for purposes of
40 // finding nmethods which might need to be deoptimized. Instead of
41 // recording the method, a count of how many times a particular nmethod
42 // was recorded is kept. This ensures that any recording errors are
43 // noticed since an nmethod should be removed as many times are it's
44 // added.
45 //
46 class nmethodBucket: public CHeapObj<mtClass> {
47 friend class VMStructs;
48 private:
49 nmethod* _nmethod;
50 int _count;
51 nmethodBucket* _next;
52
53 public:
54 nmethodBucket(nmethod* nmethod, nmethodBucket* next) :
55 _nmethod(nmethod), _count(1), _next(next) {}
56
57 int count() { return _count; }
58 int increment() { _count += 1; return _count; }
59 int decrement();
60 nmethodBucket* next() { return _next; }
61 void set_next(nmethodBucket* b) { _next = b; }
62 nmethod* get_nmethod() { return _nmethod; }
63 };
64
65 //
66 // Utility class to manipulate nmethod dependency context.
67 // The context consists of nmethodBucket* (a head of a linked list)
68 // and a boolean flag (does the list contains stale entries). The structure is
69 // encoded as an intptr_t: lower bit is used for the flag. It is possible since
70 // nmethodBucket* is aligned - the structure is malloc'ed in C heap.
71 // Dependency context can be attached either to an InstanceKlass (_dep_context field)
72 // or CallSiteContext oop for call_site_target dependencies (see javaClasses.hpp).
73 // DependencyContext class operates on some location which holds a intptr_t value.
74 //
75 class DependencyContext : public StackObj {
76 friend class VMStructs;
77 friend class TestDependencyContext;
78 private:
79 enum TagBits { _has_stale_entries_bit = 1, _has_stale_entries_mask = 1 };
80
81 intptr_t* _dependency_context_addr;
82
83 void set_dependencies(nmethodBucket* b) {
84 assert((intptr_t(b) & _has_stale_entries_mask) == 0, "should be aligned");
85 if (has_stale_entries()) {
86 *_dependency_context_addr = intptr_t(b) | _has_stale_entries_mask;
87 } else {
88 *_dependency_context_addr = intptr_t(b);
89 }
90 }
91
92 void set_has_stale_entries(bool x) {
93 if (x) {
94 *_dependency_context_addr |= _has_stale_entries_mask;
95 } else {
96 *_dependency_context_addr &= ~_has_stale_entries_mask;
97 }
98 }
99
100 nmethodBucket* dependencies() {
101 intptr_t value = *_dependency_context_addr;
102 return (nmethodBucket*) (value & ~_has_stale_entries_mask);
103 }
104
105 bool has_stale_entries() const {
106 intptr_t value = *_dependency_context_addr;
107 return (value & _has_stale_entries_mask) != 0;
108 }
109
110 static PerfCounter* _perf_total_buckets_allocated_count;
111 static PerfCounter* _perf_total_buckets_deallocated_count;
112 static PerfCounter* _perf_total_buckets_stale_count;
113 static PerfCounter* _perf_total_buckets_stale_acc_count;
114
115 public:
116 #ifdef ASSERT
117 // Safepoints are forbidden during DC lifetime. GC can invalidate
118 // _dependency_context_addr if it relocates the holder
119 // (e.g. CallSiteContext Java object).
120 uint64_t _safepoint_counter;
121
122 DependencyContext(intptr_t* addr) : _dependency_context_addr(addr),
123 _safepoint_counter(SafepointSynchronize::safepoint_counter()) {}
124
125 ~DependencyContext() {
126 assert(_safepoint_counter == SafepointSynchronize::safepoint_counter(), "safepoint happened");
127 }
128 #else
129 DependencyContext(intptr_t* addr) : _dependency_context_addr(addr) {}
130 #endif // ASSERT
131
132 static const intptr_t EMPTY = 0; // dependencies = NULL, has_stale_entries = false
133
134 static void init();
135
136 int mark_dependent_nmethods(DepChange& changes);
137 void add_dependent_nmethod(nmethod* nm, bool expunge_stale_entries = false);
138 void remove_dependent_nmethod(nmethod* nm, bool expunge_stale_entries = false);
139 int remove_all_dependents();
140
141 void expunge_stale_entries();
142
143 #ifndef PRODUCT
144 void print_dependent_nmethods(bool verbose);
145 bool is_dependent_nmethod(nmethod* nm);
146 bool find_stale_entries();
147 #endif //PRODUCT
148 };
149 #endif // SHARE_VM_CODE_DEPENDENCYCONTEXT_HPP
|
30 #include "runtime/perfData.hpp"
31 #include "runtime/safepoint.hpp"
32
33 class nmethod;
34 class DepChange;
35
36 //
37 // nmethodBucket is used to record dependent nmethods for
38 // deoptimization. nmethod dependencies are actually <klass, method>
39 // pairs but we really only care about the klass part for purposes of
40 // finding nmethods which might need to be deoptimized. Instead of
41 // recording the method, a count of how many times a particular nmethod
42 // was recorded is kept. This ensures that any recording errors are
43 // noticed since an nmethod should be removed as many times are it's
44 // added.
45 //
46 class nmethodBucket: public CHeapObj<mtClass> {
47 friend class VMStructs;
48 private:
49 nmethod* _nmethod;
50 volatile int _count;
51 nmethodBucket* volatile _next;
52 nmethodBucket* volatile _purge_list_next;
53
54 public:
55 nmethodBucket(nmethod* nmethod, nmethodBucket* next) :
56 _nmethod(nmethod), _count(1), _next(next), _purge_list_next(NULL) {}
57
58 int count() { return _count; }
59 int increment() { _count += 1; return _count; }
60 int decrement();
61 nmethodBucket* next();
62 nmethodBucket* next_not_unloading();
63 void set_next(nmethodBucket* b);
64 nmethodBucket* purge_list_next();
65 void set_purge_list_next(nmethodBucket* b);
66 nmethod* get_nmethod() { return _nmethod; }
67 };
68
69 //
70 // Utility class to manipulate nmethod dependency context.
71 // Dependency context can be attached either to an InstanceKlass (_dep_context field)
72 // or CallSiteContext oop for call_site_target dependencies (see javaClasses.hpp).
73 // DependencyContext class operates on some location which holds a nmethodBucket* value
74 // and uint64_t integer recording the safepoint counter at the last cleanup.
75 //
76 class DependencyContext : public StackObj {
77 friend class VMStructs;
78 friend class TestDependencyContext;
79 private:
80 nmethodBucket* volatile* _dependency_context_addr;
81 volatile uint64_t* _last_cleanup_addr;
82
83 bool claim_cleanup();
84 void set_dependencies(nmethodBucket* b);
85 nmethodBucket* dependencies();
86 nmethodBucket* dependencies_not_unloading();
87
88 static PerfCounter* _perf_total_buckets_allocated_count;
89 static PerfCounter* _perf_total_buckets_deallocated_count;
90 static PerfCounter* _perf_total_buckets_stale_count;
91 static PerfCounter* _perf_total_buckets_stale_acc_count;
92 static nmethodBucket* volatile _purge_list;
93 static volatile uint64_t _cleaning_epoch;
94
95 public:
96 #ifdef ASSERT
97 // Safepoints are forbidden during DC lifetime. GC can invalidate
98 // _dependency_context_addr if it relocates the holder
99 // (e.g. CallSiteContext Java object).
100 uint64_t _safepoint_counter;
101
102 DependencyContext(nmethodBucket* volatile* bucket_addr, volatile uint64_t* last_cleanup_addr)
103 : _dependency_context_addr(bucket_addr),
104 _last_cleanup_addr(last_cleanup_addr),
105 _safepoint_counter(SafepointSynchronize::safepoint_counter()) {}
106
107 ~DependencyContext() {
108 assert(_safepoint_counter == SafepointSynchronize::safepoint_counter(), "safepoint happened");
109 }
110 #else
111 DependencyContext(nmethodBucket* volatile* bucket_addr, volatile uint64_t* last_cleanup_addr)
112 : _dependency_context_addr(bucket_addr),
113 _last_cleanup_addr(last_cleanup_addr) {}
114 #endif // ASSERT
115
116 static void init();
117
118 int mark_dependent_nmethods(DepChange& changes);
119 void add_dependent_nmethod(nmethod* nm);
120 void remove_dependent_nmethod(nmethod* nm);
121 int remove_all_dependents();
122 void clean_unloading_dependents();
123 static void purge_dependency_contexts();
124 static void release(nmethodBucket* b);
125 static void cleaning_start();
126 static void cleaning_end();
127
128 #ifndef PRODUCT
129 void print_dependent_nmethods(bool verbose);
130 bool is_dependent_nmethod(nmethod* nm);
131 #endif //PRODUCT
132 };
133 #endif // SHARE_VM_CODE_DEPENDENCYCONTEXT_HPP
|