1 /*
2 * Copyright (c) 1997, 2016, 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 *
34 #include "runtime/compilationPolicy.hpp"
35 #include "runtime/mutexLocker.hpp"
36 #include "runtime/orderAccess.inline.hpp"
37 #include "runtime/os.hpp"
38 #include "runtime/sweeper.hpp"
39 #include "runtime/thread.inline.hpp"
40 #include "runtime/vm_operations.hpp"
41 #include "trace/tracing.hpp"
42 #include "utilities/events.hpp"
43 #include "utilities/ticks.inline.hpp"
44 #include "utilities/xmlstream.hpp"
45
46 #ifdef ASSERT
47
48 #define SWEEP(nm) record_sweep(nm, __LINE__)
49 // Sweeper logging code
50 class SweeperRecord {
51 public:
52 int traversal;
53 int compile_id;
54 long traversal_mark;
55 int state;
56 const char* kind;
57 address vep;
58 address uep;
59 int line;
60
61 void print() {
62 tty->print_cr("traversal = %d compile_id = %d %s uep = " PTR_FORMAT " vep = "
63 PTR_FORMAT " state = %d traversal_mark %ld line = %d",
64 traversal,
65 compile_id,
66 kind == NULL ? "" : kind,
67 p2i(uep),
68 p2i(vep),
69 state,
70 traversal_mark,
71 line);
72 }
73 };
74
75 static int _sweep_index = 0;
76 static SweeperRecord* _records = NULL;
77
78 void NMethodSweeper::report_events(int id, address entry) {
79 if (_records != NULL) {
80 for (int i = _sweep_index; i < SweeperLogEntries; i++) {
81 if (_records[i].uep == entry ||
82 _records[i].vep == entry ||
83 _records[i].compile_id == id) {
95 }
96
97 void NMethodSweeper::report_events() {
98 if (_records != NULL) {
99 for (int i = _sweep_index; i < SweeperLogEntries; i++) {
100 // skip empty records
101 if (_records[i].vep == NULL) continue;
102 _records[i].print();
103 }
104 for (int i = 0; i < _sweep_index; i++) {
105 // skip empty records
106 if (_records[i].vep == NULL) continue;
107 _records[i].print();
108 }
109 }
110 }
111
112 void NMethodSweeper::record_sweep(CompiledMethod* nm, int line) {
113 if (_records != NULL) {
114 _records[_sweep_index].traversal = _traversals;
115 _records[_sweep_index].traversal_mark = nm->is_nmethod() ? ((nmethod*)nm)->_stack_traversal_mark : 0;
116 _records[_sweep_index].compile_id = nm->compile_id();
117 _records[_sweep_index].kind = nm->compile_kind();
118 _records[_sweep_index].state = nm->get_state();
119 _records[_sweep_index].vep = nm->verified_entry_point();
120 _records[_sweep_index].uep = nm->entry_point();
121 _records[_sweep_index].line = line;
122 _sweep_index = (_sweep_index + 1) % SweeperLogEntries;
123 }
124 }
125
126 void NMethodSweeper::init_sweeper_log() {
127 if (LogSweeper && _records == NULL) {
128 // Create the ring buffer for the logging code
129 _records = NEW_C_HEAP_ARRAY(SweeperRecord, SweeperLogEntries, mtGC);
130 memset(_records, 0, sizeof(SweeperRecord) * SweeperLogEntries);
131 }
132 }
133 #else
134 #define SWEEP(nm)
135 #endif
182 };
183 static SetHotnessClosure set_hotness_closure;
184
185
186 int NMethodSweeper::hotness_counter_reset_val() {
187 if (_hotness_counter_reset_val == 0) {
188 _hotness_counter_reset_val = (ReservedCodeCacheSize < M) ? 1 : (ReservedCodeCacheSize / M) * 2;
189 }
190 return _hotness_counter_reset_val;
191 }
192 bool NMethodSweeper::wait_for_stack_scanning() {
193 return _current.end();
194 }
195
196 /**
197 * Scans the stacks of all Java threads and marks activations of not-entrant methods.
198 * No need to synchronize access, since 'mark_active_nmethods' is always executed at a
199 * safepoint.
200 */
201 void NMethodSweeper::mark_active_nmethods() {
202 assert(SafepointSynchronize::is_at_safepoint(), "must be executed at a safepoint");
203 // If we do not want to reclaim not-entrant or zombie methods there is no need
204 // to scan stacks
205 if (!MethodFlushing) {
206 return;
207 }
208
209 // Increase time so that we can estimate when to invoke the sweeper again.
210 _time_counter++;
211
212 // Check for restart
213 if (_current.method() != NULL) {
214 if (_current.method()->is_nmethod()) {
215 assert(CodeCache::find_blob_unsafe(_current.method()) == _current.method(), "Sweeper nmethod cached state invalid");
216 } else if (_current.method()->is_aot()) {
217 assert(CodeCache::find_blob_unsafe(_current.method()->code_begin()) == _current.method(), "Sweeper AOT method cached state invalid");
218 } else {
219 ShouldNotReachHere();
220 }
221 }
222
223 if (wait_for_stack_scanning()) {
224 _seen = 0;
225 _current = CompiledMethodIterator();
226 // Initialize to first nmethod
227 _current.next();
228 _traversals += 1;
229 _total_time_this_sweep = Tickspan();
230
231 if (PrintMethodFlushing) {
232 tty->print_cr("### Sweep: stack traversal %ld", _traversals);
233 }
234 Threads::nmethods_do(&mark_activation_closure);
235
236 } else {
237 // Only set hotness counter
238 Threads::nmethods_do(&set_hotness_closure);
239 }
240
241 OrderAccess::storestore();
242 }
243
244 /**
245 * This function triggers a VM operation that does stack scanning of active
246 * methods. Stack scanning is mandatory for the sweeper to make progress.
247 */
248 void NMethodSweeper::do_stack_scanning() {
249 assert(!CodeCache_lock->owned_by_self(), "just checking");
250 if (wait_for_stack_scanning()) {
251 VM_MarkActiveNMethods op;
252 VMThread::execute(&op);
253 _should_sweep = true;
254 }
255 }
256
257 void NMethodSweeper::sweeper_loop() {
258 bool timeout;
259 while (true) {
260 {
261 ThreadBlockInVM tbivm(JavaThread::current());
|
1 /*
2 * Copyright (c) 1997, 2017, 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 *
34 #include "runtime/compilationPolicy.hpp"
35 #include "runtime/mutexLocker.hpp"
36 #include "runtime/orderAccess.inline.hpp"
37 #include "runtime/os.hpp"
38 #include "runtime/sweeper.hpp"
39 #include "runtime/thread.inline.hpp"
40 #include "runtime/vm_operations.hpp"
41 #include "trace/tracing.hpp"
42 #include "utilities/events.hpp"
43 #include "utilities/ticks.inline.hpp"
44 #include "utilities/xmlstream.hpp"
45
46 #ifdef ASSERT
47
48 #define SWEEP(nm) record_sweep(nm, __LINE__)
49 // Sweeper logging code
50 class SweeperRecord {
51 public:
52 int traversal;
53 int compile_id;
54 jlong traversal_mark;
55 int state;
56 const char* kind;
57 address vep;
58 address uep;
59 int line;
60
61 void print() {
62 tty->print_cr("traversal = %d compile_id = %d %s uep = " PTR_FORMAT " vep = "
63 PTR_FORMAT " state = %d traversal_mark "JLONG_FORMAT" line = %d",
64 traversal,
65 compile_id,
66 kind == NULL ? "" : kind,
67 p2i(uep),
68 p2i(vep),
69 state,
70 traversal_mark,
71 line);
72 }
73 };
74
75 static int _sweep_index = 0;
76 static SweeperRecord* _records = NULL;
77
78 void NMethodSweeper::report_events(int id, address entry) {
79 if (_records != NULL) {
80 for (int i = _sweep_index; i < SweeperLogEntries; i++) {
81 if (_records[i].uep == entry ||
82 _records[i].vep == entry ||
83 _records[i].compile_id == id) {
95 }
96
97 void NMethodSweeper::report_events() {
98 if (_records != NULL) {
99 for (int i = _sweep_index; i < SweeperLogEntries; i++) {
100 // skip empty records
101 if (_records[i].vep == NULL) continue;
102 _records[i].print();
103 }
104 for (int i = 0; i < _sweep_index; i++) {
105 // skip empty records
106 if (_records[i].vep == NULL) continue;
107 _records[i].print();
108 }
109 }
110 }
111
112 void NMethodSweeper::record_sweep(CompiledMethod* nm, int line) {
113 if (_records != NULL) {
114 _records[_sweep_index].traversal = _traversals;
115 _records[_sweep_index].traversal_mark = nm->is_nmethod() ? ((nmethod*)nm)->stack_traversal_mark() : 0;
116 _records[_sweep_index].compile_id = nm->compile_id();
117 _records[_sweep_index].kind = nm->compile_kind();
118 _records[_sweep_index].state = nm->get_state();
119 _records[_sweep_index].vep = nm->verified_entry_point();
120 _records[_sweep_index].uep = nm->entry_point();
121 _records[_sweep_index].line = line;
122 _sweep_index = (_sweep_index + 1) % SweeperLogEntries;
123 }
124 }
125
126 void NMethodSweeper::init_sweeper_log() {
127 if (LogSweeper && _records == NULL) {
128 // Create the ring buffer for the logging code
129 _records = NEW_C_HEAP_ARRAY(SweeperRecord, SweeperLogEntries, mtGC);
130 memset(_records, 0, sizeof(SweeperRecord) * SweeperLogEntries);
131 }
132 }
133 #else
134 #define SWEEP(nm)
135 #endif
182 };
183 static SetHotnessClosure set_hotness_closure;
184
185
186 int NMethodSweeper::hotness_counter_reset_val() {
187 if (_hotness_counter_reset_val == 0) {
188 _hotness_counter_reset_val = (ReservedCodeCacheSize < M) ? 1 : (ReservedCodeCacheSize / M) * 2;
189 }
190 return _hotness_counter_reset_val;
191 }
192 bool NMethodSweeper::wait_for_stack_scanning() {
193 return _current.end();
194 }
195
196 /**
197 * Scans the stacks of all Java threads and marks activations of not-entrant methods.
198 * No need to synchronize access, since 'mark_active_nmethods' is always executed at a
199 * safepoint.
200 */
201 void NMethodSweeper::mark_active_nmethods() {
202 CodeBlobClosure* cl = prepare_mark_active_nmethods();
203 if (cl != NULL) {
204 Threads::nmethods_do(cl);
205 }
206 }
207
208 CodeBlobClosure* NMethodSweeper::prepare_mark_active_nmethods() {
209 assert(SafepointSynchronize::is_at_safepoint(), "must be executed at a safepoint");
210 // If we do not want to reclaim not-entrant or zombie methods there is no need
211 // to scan stacks
212 if (!MethodFlushing) {
213 return NULL;
214 }
215
216 // Increase time so that we can estimate when to invoke the sweeper again.
217 _time_counter++;
218
219 // Check for restart
220 if (_current.method() != NULL) {
221 if (_current.method()->is_nmethod()) {
222 assert(CodeCache::find_blob_unsafe(_current.method()) == _current.method(), "Sweeper nmethod cached state invalid");
223 } else if (_current.method()->is_aot()) {
224 assert(CodeCache::find_blob_unsafe(_current.method()->code_begin()) == _current.method(), "Sweeper AOT method cached state invalid");
225 } else {
226 ShouldNotReachHere();
227 }
228 }
229
230 if (wait_for_stack_scanning()) {
231 _seen = 0;
232 _current = CompiledMethodIterator();
233 // Initialize to first nmethod
234 _current.next();
235 _traversals += 1;
236 _total_time_this_sweep = Tickspan();
237
238 if (PrintMethodFlushing) {
239 tty->print_cr("### Sweep: stack traversal %ld", _traversals);
240 }
241 return &mark_activation_closure;
242
243 } else {
244 // Only set hotness counter
245 return &set_hotness_closure;
246 }
247
248 }
249
250 /**
251 * This function triggers a VM operation that does stack scanning of active
252 * methods. Stack scanning is mandatory for the sweeper to make progress.
253 */
254 void NMethodSweeper::do_stack_scanning() {
255 assert(!CodeCache_lock->owned_by_self(), "just checking");
256 if (wait_for_stack_scanning()) {
257 VM_MarkActiveNMethods op;
258 VMThread::execute(&op);
259 _should_sweep = true;
260 }
261 }
262
263 void NMethodSweeper::sweeper_loop() {
264 bool timeout;
265 while (true) {
266 {
267 ThreadBlockInVM tbivm(JavaThread::current());
|