Mon, 19 Aug 2019 10:11:31 +0200
8229401: Fix JFR code cache test failures
8223689: Add JFR Thread Sampling Support
8223690: Add JFR BiasedLock Event Support
8223691: Add JFR G1 Region Type Change Event Support
8223692: Add JFR G1 Heap Summary Event Support
Summary: Backport JFR from JDK11, additional fixes
Reviewed-by: neugens, apetushkov
Contributed-by: denghui.ddh@alibaba-inc.com
1 /*
2 * Copyright (c) 2001, 2011, 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 */
25 #include "precompiled.hpp"
26 #include "gc_implementation/shared/gcTrace.hpp"
27 #include "gc_implementation/g1/g1MMUTracker.hpp"
28 #include "runtime/mutexLocker.hpp"
29 #include "utilities/ostream.hpp"
31 #define _DISABLE_MMU 0
33 // can't rely on comparing doubles with tolerating a small margin for error
34 #define SMALL_MARGIN 0.0000001
35 #define is_double_leq_0(_value) ( (_value) < SMALL_MARGIN )
36 #define is_double_leq(_val1, _val2) is_double_leq_0((_val1) - (_val2))
37 #define is_double_geq(_val1, _val2) is_double_leq_0((_val2) - (_val1))
39 /***** ALL TIMES ARE IN SECS!!!!!!! *****/
41 G1MMUTracker::G1MMUTracker(double time_slice, double max_gc_time) :
42 _time_slice(time_slice),
43 _max_gc_time(max_gc_time) { }
45 G1MMUTrackerQueue::G1MMUTrackerQueue(double time_slice, double max_gc_time) :
46 G1MMUTracker(time_slice, max_gc_time),
47 _head_index(0),
48 _tail_index(trim_index(_head_index+1)),
49 _no_entries(0) { }
51 void G1MMUTrackerQueue::remove_expired_entries(double current_time) {
52 double limit = current_time - _time_slice;
53 while (_no_entries > 0) {
54 if (is_double_geq(limit, _array[_tail_index].end_time())) {
55 _tail_index = trim_index(_tail_index + 1);
56 --_no_entries;
57 } else
58 return;
59 }
60 guarantee(_no_entries == 0, "should have no entries in the array");
61 }
63 double G1MMUTrackerQueue::calculate_gc_time(double current_time) {
64 double gc_time = 0.0;
65 double limit = current_time - _time_slice;
66 for (int i = 0; i < _no_entries; ++i) {
67 int index = trim_index(_tail_index + i);
68 G1MMUTrackerQueueElem *elem = &_array[index];
69 if (elem->end_time() > limit) {
70 if (elem->start_time() > limit)
71 gc_time += elem->duration();
72 else
73 gc_time += elem->end_time() - limit;
74 }
75 }
76 return gc_time;
77 }
79 void G1MMUTrackerQueue::add_pause(double start, double end, bool gc_thread) {
80 double longest_allowed = longest_pause_internal(start);
81 if (longest_allowed < 0.0)
82 longest_allowed = 0.0;
83 double duration = end - start;
85 remove_expired_entries(end);
86 if (_no_entries == QueueLength) {
87 // OK, we've filled up the queue. There are a few ways
88 // of dealing with this "gracefully"
89 // increase the array size (:-)
90 // remove the oldest entry (this might allow more GC time for
91 // the time slice than what's allowed) - this is what we
92 // currently do
93 // consolidate the two entries with the minimum gap between them
94 // (this might allow less GC time than what's allowed)
96 // In the case where ScavengeALot is true, such overflow is not
97 // uncommon; in such cases, we can, without much loss of precision
98 // or performance (we are GC'ing most of the time anyway!),
99 // simply overwrite the oldest entry in the tracker.
101 _head_index = trim_index(_head_index + 1);
102 assert(_head_index == _tail_index, "Because we have a full circular buffer");
103 _tail_index = trim_index(_tail_index + 1);
104 } else {
105 _head_index = trim_index(_head_index + 1);
106 ++_no_entries;
107 }
108 _array[_head_index] = G1MMUTrackerQueueElem(start, end);
110 double slice_time = calculate_gc_time(end);
111 G1MMUTracer::report_mmu(_time_slice, slice_time, _max_gc_time);
112 }
114 // basically the _internal call does not remove expired entries
115 // this is for trying things out in the future and a couple
116 // of other places (debugging)
118 double G1MMUTrackerQueue::longest_pause(double current_time) {
119 if (_DISABLE_MMU)
120 return _max_gc_time;
122 MutexLockerEx x(MMUTracker_lock, Mutex::_no_safepoint_check_flag);
123 remove_expired_entries(current_time);
125 return longest_pause_internal(current_time);
126 }
128 double G1MMUTrackerQueue::longest_pause_internal(double current_time) {
129 double target_time = _max_gc_time;
131 while( 1 ) {
132 double gc_time =
133 calculate_gc_time(current_time + target_time);
134 double diff = target_time + gc_time - _max_gc_time;
135 if (!is_double_leq_0(diff)) {
136 target_time -= diff;
137 if (is_double_leq_0(target_time)) {
138 target_time = -1.0;
139 break;
140 }
141 } else {
142 break;
143 }
144 }
146 return target_time;
147 }
149 // basically the _internal call does not remove expired entries
150 // this is for trying things out in the future and a couple
151 // of other places (debugging)
153 double G1MMUTrackerQueue::when_sec(double current_time, double pause_time) {
154 if (_DISABLE_MMU)
155 return 0.0;
157 MutexLockerEx x(MMUTracker_lock, Mutex::_no_safepoint_check_flag);
158 remove_expired_entries(current_time);
160 return when_internal(current_time, pause_time);
161 }
163 double G1MMUTrackerQueue::when_internal(double current_time,
164 double pause_time) {
165 // if the pause is over the maximum, just assume that it's the maximum
166 double adjusted_pause_time =
167 (pause_time > max_gc_time()) ? max_gc_time() : pause_time;
168 double earliest_end = current_time + adjusted_pause_time;
169 double limit = earliest_end - _time_slice;
170 double gc_time = calculate_gc_time(earliest_end);
171 double diff = gc_time + adjusted_pause_time - max_gc_time();
172 if (is_double_leq_0(diff))
173 return 0.0;
175 int index = _tail_index;
176 while ( 1 ) {
177 G1MMUTrackerQueueElem *elem = &_array[index];
178 if (elem->end_time() > limit) {
179 if (elem->start_time() > limit)
180 diff -= elem->duration();
181 else
182 diff -= elem->end_time() - limit;
183 if (is_double_leq_0(diff))
184 return elem->end_time() + diff + _time_slice - adjusted_pause_time - current_time;
185 }
186 index = trim_index(index+1);
187 guarantee(index != trim_index(_head_index + 1), "should not go past head");
188 }
189 }