1 /*
2 * Copyright (c) 2017, 2018, Red Hat, Inc. and/or its affiliates.
3 *
4 * This code is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 only, as
6 * published by the Free Software Foundation.
7 *
8 * This code is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11 * version 2 for more details (a copy is included in the LICENSE file that
12 * accompanied this code).
13 *
14 * You should have received a copy of the GNU General Public License version
15 * 2 along with this work; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
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
25 #ifndef SHARE_VM_GC_SHENANDOAH_SHENANDOAHCODEROOTS_HPP
26 #define SHARE_VM_GC_SHENANDOAH_SHENANDOAHCODEROOTS_HPP
27
28 #include "code/codeCache.hpp"
29 #include "memory/allocation.hpp"
30 #include "memory/iterator.hpp"
31 #include "gc_implementation/shenandoah/shenandoahSharedVariables.hpp"
32
33 class ShenandoahHeap;
34 class ShenandoahHeapRegion;
35 class ShenandoahCodeRootsLock;
36
37 class ShenandoahParallelCodeCacheIterator VALUE_OBJ_CLASS_SPEC {
38 friend class CodeCache;
39 private:
40 volatile int _claimed_idx;
41 volatile bool _finished;
42 public:
43 ShenandoahParallelCodeCacheIterator();
44 void parallel_blobs_do(CodeBlobClosure* f);
45 };
46
47 // ShenandoahNMethod tuple records the internal locations of oop slots within the nmethod.
48 // This allows us to quickly scan the oops without doing the nmethod-internal scans, that
49 // sometimes involves parsing the machine code. Note it does not record the oops themselves,
50 // because it would then require handling these tuples as the new class of roots.
51 class ShenandoahNMethod : public CHeapObj<mtGC> {
52 private:
53 nmethod* _nm;
54 oop** _oops;
55 int _oops_count;
56
57 public:
58 ShenandoahNMethod(nmethod *nm, GrowableArray<oop*>* oops);
59 ~ShenandoahNMethod();
60
61 nmethod* nm() {
62 return _nm;
63 }
64
65 bool has_cset_oops(ShenandoahHeap* heap);
66
67 void assert_alive_and_correct() PRODUCT_RETURN;
68 void assert_same_oops(GrowableArray<oop*>* oops) PRODUCT_RETURN;
69
70 static bool find_with_nmethod(void* nm, ShenandoahNMethod* other) {
71 return other->_nm == nm;
72 }
73 };
74
75 class ShenandoahCodeRootsIterator VALUE_OBJ_CLASS_SPEC {
76 friend class ShenandoahCodeRoots;
77 protected:
78 ShenandoahHeap* _heap;
79 ShenandoahParallelCodeCacheIterator _par_iterator;
80 ShenandoahSharedFlag _seq_claimed;
81 volatile jlong _claimed;
82 protected:
83 ShenandoahCodeRootsIterator();
84 ~ShenandoahCodeRootsIterator();
85
86 template<bool CSET_FILTER>
87 void dispatch_parallel_blobs_do(CodeBlobClosure *f);
88
89 template<bool CSET_FILTER>
90 void fast_parallel_blobs_do(CodeBlobClosure *f);
91 };
92
93 class ShenandoahAllCodeRootsIterator : public ShenandoahCodeRootsIterator {
94 public:
95 ShenandoahAllCodeRootsIterator() : ShenandoahCodeRootsIterator() {};
96 void possibly_parallel_blobs_do(CodeBlobClosure *f);
97 };
98
99 class ShenandoahCsetCodeRootsIterator : public ShenandoahCodeRootsIterator {
100 public:
101 ShenandoahCsetCodeRootsIterator() : ShenandoahCodeRootsIterator() {};
108 friend class ShenandoahCodeRootsIterator;
109
110 public:
111 static void initialize();
112 static void add_nmethod(nmethod* nm);
113 static void remove_nmethod(nmethod* nm);
114
115 /**
116 * Provides the iterator over all nmethods in the code cache that have oops.
117 * @return
118 */
119 static ShenandoahAllCodeRootsIterator iterator();
120
121 /**
122 * Provides the iterator over nmethods that have at least one oop in collection set.
123 * @return
124 */
125 static ShenandoahCsetCodeRootsIterator cset_iterator();
126
127 private:
128 static volatile jint _recorded_nms_lock;
129 static GrowableArray<ShenandoahNMethod*>* _recorded_nms;
130
131 static void acquire_lock(bool write) {
132 volatile jint* loc = &_recorded_nms_lock;
133 if (write) {
134 while ((OrderAccess::load_acquire(loc) != 0) ||
135 Atomic::cmpxchg(-1, loc, 0) != 0) {
136 SpinPause();
137 }
138 assert (*loc == -1, "acquired for write");
139 } else {
140 while (true) {
141 jint cur = OrderAccess::load_acquire(loc);
142 if (cur >= 0) {
143 if (Atomic::cmpxchg(cur + 1, loc, cur) == cur) {
144 // Success!
145 assert (*loc > 0, "acquired for read");
146 return;
147 }
148 }
149 SpinPause();
150 }
151 }
152 }
153
154 static void release_lock(bool write) {
155 volatile jint* loc = &ShenandoahCodeRoots::_recorded_nms_lock;
156 if (write) {
157 OrderAccess::release_store_fence(loc, 0);
158 } else {
159 Atomic::dec(loc);
160 }
161 }
162 };
163
164 // Very simple unranked read-write lock
165 class ShenandoahCodeRootsLock : public StackObj {
166 friend class ShenandoahCodeRoots;
167 private:
168 const bool _write;
169 public:
170 ShenandoahCodeRootsLock(bool write) : _write(write) {
171 ShenandoahCodeRoots::acquire_lock(write);
172 }
173
174 ~ShenandoahCodeRootsLock() {
175 ShenandoahCodeRoots::release_lock(_write);
|
1 /*
2 * Copyright (c) 2017, 2018, Red Hat, Inc. All rights reserved.
3 *
4 * This code is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 only, as
6 * published by the Free Software Foundation.
7 *
8 * This code is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11 * version 2 for more details (a copy is included in the LICENSE file that
12 * accompanied this code).
13 *
14 * You should have received a copy of the GNU General Public License version
15 * 2 along with this work; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
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 #ifndef SHARE_VM_GC_SHENANDOAH_SHENANDOAHCODEROOTS_HPP
25 #define SHARE_VM_GC_SHENANDOAH_SHENANDOAHCODEROOTS_HPP
26
27 #include "code/codeCache.hpp"
28 #include "gc_implementation/shenandoah/shenandoahSharedVariables.hpp"
29 #include "memory/allocation.hpp"
30 #include "memory/iterator.hpp"
31
32 class ShenandoahHeap;
33 class ShenandoahHeapRegion;
34 class ShenandoahCodeRootsLock;
35
36 class ShenandoahParallelCodeCacheIterator VALUE_OBJ_CLASS_SPEC {
37 friend class CodeCache;
38 private:
39 char _pad0[DEFAULT_CACHE_LINE_SIZE];
40 volatile int _claimed_idx;
41 volatile bool _finished;
42 char _pad1[DEFAULT_CACHE_LINE_SIZE];
43 public:
44 ShenandoahParallelCodeCacheIterator();
45 void parallel_blobs_do(CodeBlobClosure* f);
46 };
47
48 // ShenandoahNMethod tuple records the internal locations of oop slots within the nmethod.
49 // This allows us to quickly scan the oops without doing the nmethod-internal scans, that
50 // sometimes involves parsing the machine code. Note it does not record the oops themselves,
51 // because it would then require handling these tuples as the new class of roots.
52 class ShenandoahNMethod : public CHeapObj<mtGC> {
53 private:
54 nmethod* _nm;
55 oop** _oops;
56 int _oops_count;
57
58 public:
59 ShenandoahNMethod(nmethod *nm, GrowableArray<oop*>* oops);
60 ~ShenandoahNMethod();
61
62 nmethod* nm() {
63 return _nm;
64 }
65
66 bool has_cset_oops(ShenandoahHeap* heap);
67
68 void assert_alive_and_correct() PRODUCT_RETURN;
69 void assert_same_oops(GrowableArray<oop*>* oops) PRODUCT_RETURN;
70
71 static bool find_with_nmethod(void* nm, ShenandoahNMethod* other) {
72 return other->_nm == nm;
73 }
74 };
75
76 class ShenandoahCodeRootsIterator VALUE_OBJ_CLASS_SPEC {
77 friend class ShenandoahCodeRoots;
78 protected:
79 ShenandoahHeap* _heap;
80 ShenandoahParallelCodeCacheIterator _par_iterator;
81 ShenandoahSharedFlag _seq_claimed;
82 char _pad0[DEFAULT_CACHE_LINE_SIZE];
83 volatile jlong _claimed;
84 char _pad1[DEFAULT_CACHE_LINE_SIZE];
85 protected:
86 ShenandoahCodeRootsIterator();
87 ~ShenandoahCodeRootsIterator();
88
89 template<bool CSET_FILTER>
90 void dispatch_parallel_blobs_do(CodeBlobClosure *f);
91
92 template<bool CSET_FILTER>
93 void fast_parallel_blobs_do(CodeBlobClosure *f);
94 };
95
96 class ShenandoahAllCodeRootsIterator : public ShenandoahCodeRootsIterator {
97 public:
98 ShenandoahAllCodeRootsIterator() : ShenandoahCodeRootsIterator() {};
99 void possibly_parallel_blobs_do(CodeBlobClosure *f);
100 };
101
102 class ShenandoahCsetCodeRootsIterator : public ShenandoahCodeRootsIterator {
103 public:
104 ShenandoahCsetCodeRootsIterator() : ShenandoahCodeRootsIterator() {};
111 friend class ShenandoahCodeRootsIterator;
112
113 public:
114 static void initialize();
115 static void add_nmethod(nmethod* nm);
116 static void remove_nmethod(nmethod* nm);
117
118 /**
119 * Provides the iterator over all nmethods in the code cache that have oops.
120 * @return
121 */
122 static ShenandoahAllCodeRootsIterator iterator();
123
124 /**
125 * Provides the iterator over nmethods that have at least one oop in collection set.
126 * @return
127 */
128 static ShenandoahCsetCodeRootsIterator cset_iterator();
129
130 private:
131 struct PaddedLock {
132 char _pad0[DEFAULT_CACHE_LINE_SIZE];
133 volatile int _lock;
134 char _pad1[DEFAULT_CACHE_LINE_SIZE];
135 };
136
137 static PaddedLock _recorded_nms_lock;
138 static GrowableArray<ShenandoahNMethod*>* _recorded_nms;
139
140 static void acquire_lock(bool write) {
141 volatile int* loc = &_recorded_nms_lock._lock;
142 if (write) {
143 while ((OrderAccess::load_acquire(loc) != 0) ||
144 Atomic::cmpxchg(-1, loc, 0) != 0) {
145 SpinPause();
146 }
147 assert (*loc == -1, "acquired for write");
148 } else {
149 while (true) {
150 jint cur = OrderAccess::load_acquire(loc);
151 if (cur >= 0) {
152 if (Atomic::cmpxchg(cur + 1, loc, cur) == cur) {
153 // Success!
154 assert (*loc > 0, "acquired for read");
155 return;
156 }
157 }
158 SpinPause();
159 }
160 }
161 }
162
163 static void release_lock(bool write) {
164 volatile int* loc = &ShenandoahCodeRoots::_recorded_nms_lock._lock;
165 if (write) {
166 OrderAccess::release_store_fence(loc, 0);
167 } else {
168 Atomic::dec(loc);
169 }
170 }
171 };
172
173 // Very simple unranked read-write lock
174 class ShenandoahCodeRootsLock : public StackObj {
175 friend class ShenandoahCodeRoots;
176 private:
177 const bool _write;
178 public:
179 ShenandoahCodeRootsLock(bool write) : _write(write) {
180 ShenandoahCodeRoots::acquire_lock(write);
181 }
182
183 ~ShenandoahCodeRootsLock() {
184 ShenandoahCodeRoots::release_lock(_write);
|