1 /*
2  * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  *
23  */
24 
25 #ifndef SHARE_CODE_DEPENDENCYCONTEXT_HPP
26 #define SHARE_CODE_DEPENDENCYCONTEXT_HPP
27 
28 #include "memory/allocation.hpp"
29 #include "oops/oop.hpp"
30 #include "runtime/handles.hpp"
31 #include "runtime/perfData.hpp"
32 #include "runtime/safepoint.hpp"
33 
34 class nmethod;
35 class DepChange;
36 
37 //
38 // nmethodBucket is used to record dependent nmethods for
39 // deoptimization.  nmethod dependencies are actually <klass, method>
40 // pairs but we really only care about the klass part for purposes of
41 // finding nmethods which might need to be deoptimized.  Instead of
42 // recording the method, a count of how many times a particular nmethod
43 // was recorded is kept.  This ensures that any recording errors are
44 // noticed since an nmethod should be removed as many times are it's
45 // added.
46 //
47 class nmethodBucket: public CHeapObj<mtClass> {
48   friend class VMStructs;
49  private:
50   nmethod*       _nmethod;
51   volatile int   _count;
52   nmethodBucket* volatile _next;
53   nmethodBucket* volatile _purge_list_next;
54 
55  public:
nmethodBucket(nmethod * nmethod,nmethodBucket * next)56   nmethodBucket(nmethod* nmethod, nmethodBucket* next) :
57     _nmethod(nmethod), _count(1), _next(next), _purge_list_next(NULL) {}
58 
count()59   int count()                                { return _count; }
increment()60   int increment()                            { _count += 1; return _count; }
61   int decrement();
62   nmethodBucket* next();
63   nmethodBucket* next_not_unloading();
64   void set_next(nmethodBucket* b);
65   nmethodBucket* purge_list_next();
66   void set_purge_list_next(nmethodBucket* b);
get_nmethod()67   nmethod* get_nmethod()                     { return _nmethod; }
68 };
69 
70 //
71 // Utility class to manipulate nmethod dependency context.
72 // Dependency context can be attached either to an InstanceKlass (_dep_context field)
73 // or CallSiteContext oop for call_site_target dependencies (see javaClasses.hpp).
74 // DependencyContext class operates on some location which holds a nmethodBucket* value
75 // and uint64_t integer recording the safepoint counter at the last cleanup.
76 //
77 class DependencyContext : public StackObj {
78   friend class VMStructs;
79   friend class TestDependencyContext;
80  private:
81   nmethodBucket* volatile* _dependency_context_addr;
82   volatile uint64_t*       _last_cleanup_addr;
83 
84   bool claim_cleanup();
85   void set_dependencies(nmethodBucket* b);
86   nmethodBucket* dependencies();
87   nmethodBucket* dependencies_not_unloading();
88 
89   static PerfCounter*            _perf_total_buckets_allocated_count;
90   static PerfCounter*            _perf_total_buckets_deallocated_count;
91   static PerfCounter*            _perf_total_buckets_stale_count;
92   static PerfCounter*            _perf_total_buckets_stale_acc_count;
93   static nmethodBucket* volatile _purge_list;
94   static uint64_t                _cleaning_epoch_monotonic;
95   static volatile uint64_t       _cleaning_epoch;
96 
97  public:
98 #ifdef ASSERT
99   // Safepoints are forbidden during DC lifetime. GC can invalidate
100   // _dependency_context_addr if it relocates the holder
101   // (e.g. CallSiteContext Java object).
102   SafepointStateTracker _safepoint_tracker;
103 
DependencyContext(nmethodBucket * volatile * bucket_addr,volatile uint64_t * last_cleanup_addr)104   DependencyContext(nmethodBucket* volatile* bucket_addr, volatile uint64_t* last_cleanup_addr)
105     : _dependency_context_addr(bucket_addr),
106       _last_cleanup_addr(last_cleanup_addr),
107       _safepoint_tracker(SafepointSynchronize::safepoint_state_tracker()) {}
108 
~DependencyContext()109   ~DependencyContext() {
110     assert(!_safepoint_tracker.safepoint_state_changed(), "must be the same safepoint");
111   }
112 #else
113   DependencyContext(nmethodBucket* volatile* bucket_addr, volatile uint64_t* last_cleanup_addr)
114     : _dependency_context_addr(bucket_addr),
115       _last_cleanup_addr(last_cleanup_addr) {}
116 #endif // ASSERT
117 
118   static void init();
119 
120   int  mark_dependent_nmethods(DepChange& changes);
121   void add_dependent_nmethod(nmethod* nm);
122   void remove_dependent_nmethod(nmethod* nm);
123   int  remove_all_dependents();
124   void clean_unloading_dependents();
125   static void purge_dependency_contexts();
126   static void release(nmethodBucket* b);
127   static void cleaning_start();
128   static void cleaning_end();
129 
130 #ifndef PRODUCT
131   void print_dependent_nmethods(bool verbose);
132   bool is_dependent_nmethod(nmethod* nm);
133 #endif //PRODUCT
134 };
135 #endif // SHARE_CODE_DEPENDENCYCONTEXT_HPP
136