17 *
18 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
19 * or visit www.oracle.com if you need additional information or have any
20 * questions.
21 *
22 */
23
24 #include "precompiled.hpp"
25 #include "code/nmethod.hpp"
26 #include "code/dependencies.hpp"
27 #include "code/dependencyContext.hpp"
28 #include "memory/resourceArea.hpp"
29 #include "runtime/atomic.hpp"
30 #include "runtime/perfData.hpp"
31 #include "utilities/exceptions.hpp"
32
33 PerfCounter* DependencyContext::_perf_total_buckets_allocated_count = NULL;
34 PerfCounter* DependencyContext::_perf_total_buckets_deallocated_count = NULL;
35 PerfCounter* DependencyContext::_perf_total_buckets_stale_count = NULL;
36 PerfCounter* DependencyContext::_perf_total_buckets_stale_acc_count = NULL;
37 nmethodBucket* volatile DependencyContext::_purge_list = NULL;
38 volatile uint64_t DependencyContext::_cleaning_epoch = 0;
39
40 void dependencyContext_init() {
41 DependencyContext::init();
42 }
43
44 void DependencyContext::init() {
45 if (UsePerfData) {
46 EXCEPTION_MARK;
47 _perf_total_buckets_allocated_count =
48 PerfDataManager::create_counter(SUN_CI, "nmethodBucketsAllocated", PerfData::U_Events, CHECK);
49 _perf_total_buckets_deallocated_count =
50 PerfDataManager::create_counter(SUN_CI, "nmethodBucketsDeallocated", PerfData::U_Events, CHECK);
51 _perf_total_buckets_stale_count =
52 PerfDataManager::create_counter(SUN_CI, "nmethodBucketsStale", PerfData::U_Events, CHECK);
53 _perf_total_buckets_stale_acc_count =
54 PerfDataManager::create_counter(SUN_CI, "nmethodBucketsStaleAccumulated", PerfData::U_Events, CHECK);
55 }
56 }
57
|
17 *
18 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
19 * or visit www.oracle.com if you need additional information or have any
20 * questions.
21 *
22 */
23
24 #include "precompiled.hpp"
25 #include "code/nmethod.hpp"
26 #include "code/dependencies.hpp"
27 #include "code/dependencyContext.hpp"
28 #include "memory/resourceArea.hpp"
29 #include "runtime/atomic.hpp"
30 #include "runtime/perfData.hpp"
31 #include "utilities/exceptions.hpp"
32
33 PerfCounter* DependencyContext::_perf_total_buckets_allocated_count = NULL;
34 PerfCounter* DependencyContext::_perf_total_buckets_deallocated_count = NULL;
35 PerfCounter* DependencyContext::_perf_total_buckets_stale_count = NULL;
36 PerfCounter* DependencyContext::_perf_total_buckets_stale_acc_count = NULL;
37 nmethodBucket* volatile DependencyContext::_purge_list = NULL;
38 volatile uint64_t DependencyContext::_cleaning_epoch = 0;
39 uint64_t DependencyContext::_cleaning_epoch_monotonic = 0;
40
41 void dependencyContext_init() {
42 DependencyContext::init();
43 }
44
45 void DependencyContext::init() {
46 if (UsePerfData) {
47 EXCEPTION_MARK;
48 _perf_total_buckets_allocated_count =
49 PerfDataManager::create_counter(SUN_CI, "nmethodBucketsAllocated", PerfData::U_Events, CHECK);
50 _perf_total_buckets_deallocated_count =
51 PerfDataManager::create_counter(SUN_CI, "nmethodBucketsDeallocated", PerfData::U_Events, CHECK);
52 _perf_total_buckets_stale_count =
53 PerfDataManager::create_counter(SUN_CI, "nmethodBucketsStale", PerfData::U_Events, CHECK);
54 _perf_total_buckets_stale_acc_count =
55 PerfDataManager::create_counter(SUN_CI, "nmethodBucketsStaleAccumulated", PerfData::U_Events, CHECK);
56 }
57 }
58
|
293 // Release is_unloading entries if unlinking was claimed
294 DependencyContext::release(head);
295 }
296 }
297 }
298
299 // Relaxed accessors
300 void DependencyContext::set_dependencies(nmethodBucket* b) {
301 Atomic::store(b, _dependency_context_addr);
302 }
303
304 nmethodBucket* DependencyContext::dependencies() {
305 return Atomic::load(_dependency_context_addr);
306 }
307
308 // After the gc_prologue, the dependency contexts may be claimed by the GC
309 // and releasing of nmethodBucket entries will be deferred and placed on
310 // a purge list to be deleted later.
311 void DependencyContext::cleaning_start() {
312 assert(SafepointSynchronize::is_at_safepoint(), "must be");
313 uint64_t epoch = SafepointSynchronize::safepoint_counter();
314 Atomic::store(epoch, &_cleaning_epoch);
315 }
316
317 // The epilogue marks the end of dependency context cleanup by the GC,
318 // and also makes subsequent releases of nmethodBuckets case immediate
319 // deletion. It is admitted to end the cleanup in a concurrent phase.
320 void DependencyContext::cleaning_end() {
321 uint64_t epoch = 0;
322 Atomic::store(epoch, &_cleaning_epoch);
323 }
324
325 // This function skips over nmethodBuckets in the list corresponding to
326 // nmethods that are is_unloading. This allows exposing a view of the
327 // dependents as-if they were already cleaned, despite being cleaned
328 // concurrently. Any entry observed that is_unloading() will be unlinked
329 // and placed on the purge list.
330 nmethodBucket* nmethodBucket::next_not_unloading() {
331 for (;;) {
332 // Do not need acquire because the loaded entry can never be
|
294 // Release is_unloading entries if unlinking was claimed
295 DependencyContext::release(head);
296 }
297 }
298 }
299
300 // Relaxed accessors
301 void DependencyContext::set_dependencies(nmethodBucket* b) {
302 Atomic::store(b, _dependency_context_addr);
303 }
304
305 nmethodBucket* DependencyContext::dependencies() {
306 return Atomic::load(_dependency_context_addr);
307 }
308
309 // After the gc_prologue, the dependency contexts may be claimed by the GC
310 // and releasing of nmethodBucket entries will be deferred and placed on
311 // a purge list to be deleted later.
312 void DependencyContext::cleaning_start() {
313 assert(SafepointSynchronize::is_at_safepoint(), "must be");
314 uint64_t epoch = ++_cleaning_epoch_monotonic;
315 Atomic::store(epoch, &_cleaning_epoch);
316 }
317
318 // The epilogue marks the end of dependency context cleanup by the GC,
319 // and also makes subsequent releases of nmethodBuckets case immediate
320 // deletion. It is admitted to end the cleanup in a concurrent phase.
321 void DependencyContext::cleaning_end() {
322 uint64_t epoch = 0;
323 Atomic::store(epoch, &_cleaning_epoch);
324 }
325
326 // This function skips over nmethodBuckets in the list corresponding to
327 // nmethods that are is_unloading. This allows exposing a view of the
328 // dependents as-if they were already cleaned, despite being cleaned
329 // concurrently. Any entry observed that is_unloading() will be unlinked
330 // and placed on the purge list.
331 nmethodBucket* nmethodBucket::next_not_unloading() {
332 for (;;) {
333 // Do not need acquire because the loaded entry can never be
|