File: | jdk/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp |
Warning: | line 246, column 24 Division by zero |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* | |||
2 | * Copyright (c) 2001, 2021, 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 | #include "precompiled.hpp" | |||
26 | #include "gc/g1/g1BarrierSet.hpp" | |||
27 | #include "gc/g1/g1ConcurrentRefine.hpp" | |||
28 | #include "gc/g1/g1ConcurrentRefineThread.hpp" | |||
29 | #include "gc/g1/g1DirtyCardQueue.hpp" | |||
30 | #include "logging/log.hpp" | |||
31 | #include "memory/allocation.inline.hpp" | |||
32 | #include "memory/iterator.hpp" | |||
33 | #include "runtime/globals_extension.hpp" | |||
34 | #include "runtime/java.hpp" | |||
35 | #include "runtime/thread.hpp" | |||
36 | #include "utilities/debug.hpp" | |||
37 | #include "utilities/formatBuffer.hpp" | |||
38 | #include "utilities/globalDefinitions.hpp" | |||
39 | #include "utilities/pair.hpp" | |||
40 | #include <math.h> | |||
41 | ||||
42 | G1ConcurrentRefineThread* G1ConcurrentRefineThreadControl::create_refinement_thread(uint worker_id, bool initializing) { | |||
43 | G1ConcurrentRefineThread* result = NULL__null; | |||
44 | if (initializing || !InjectGCWorkerCreationFailure) { | |||
45 | result = new G1ConcurrentRefineThread(_cr, worker_id); | |||
46 | } | |||
47 | if (result == NULL__null || result->osthread() == NULL__null) { | |||
48 | log_warning(gc)(!(LogImpl<(LogTag::_gc), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Warning))) ? (void)0 : LogImpl<(LogTag ::_gc), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Warning>("Failed to create refinement thread %u, no more %s", | |||
49 | worker_id, | |||
50 | result == NULL__null ? "memory" : "OS threads"); | |||
51 | } | |||
52 | return result; | |||
53 | } | |||
54 | ||||
55 | G1ConcurrentRefineThreadControl::G1ConcurrentRefineThreadControl() : | |||
56 | _cr(NULL__null), | |||
57 | _threads(NULL__null), | |||
58 | _num_max_threads(0) | |||
59 | { | |||
60 | } | |||
61 | ||||
62 | G1ConcurrentRefineThreadControl::~G1ConcurrentRefineThreadControl() { | |||
63 | for (uint i = 0; i < _num_max_threads; i++) { | |||
64 | G1ConcurrentRefineThread* t = _threads[i]; | |||
65 | if (t != NULL__null) { | |||
66 | delete t; | |||
67 | } | |||
68 | } | |||
69 | FREE_C_HEAP_ARRAY(G1ConcurrentRefineThread*, _threads)FreeHeap((char*)(_threads)); | |||
70 | } | |||
71 | ||||
72 | jint G1ConcurrentRefineThreadControl::initialize(G1ConcurrentRefine* cr, uint num_max_threads) { | |||
73 | assert(cr != NULL, "G1ConcurrentRefine must not be NULL")do { if (!(cr != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp" , 73, "assert(" "cr != __null" ") failed", "G1ConcurrentRefine must not be NULL" ); ::breakpoint(); } } while (0); | |||
74 | _cr = cr; | |||
75 | _num_max_threads = num_max_threads; | |||
76 | ||||
77 | _threads = NEW_C_HEAP_ARRAY(G1ConcurrentRefineThread*, num_max_threads, mtGC)(G1ConcurrentRefineThread**) (AllocateHeap((num_max_threads) * sizeof(G1ConcurrentRefineThread*), mtGC)); | |||
78 | ||||
79 | for (uint i = 0; i < num_max_threads; i++) { | |||
80 | if (UseDynamicNumberOfGCThreads && i != 0 /* Always start first thread. */) { | |||
81 | _threads[i] = NULL__null; | |||
82 | } else { | |||
83 | _threads[i] = create_refinement_thread(i, true); | |||
84 | if (_threads[i] == NULL__null) { | |||
85 | vm_shutdown_during_initialization("Could not allocate refinement threads."); | |||
86 | return JNI_ENOMEM(-4); | |||
87 | } | |||
88 | } | |||
89 | } | |||
90 | ||||
91 | if (num_max_threads > 0) { | |||
92 | G1BarrierSet::dirty_card_queue_set().set_primary_refinement_thread(_threads[0]); | |||
93 | } | |||
94 | ||||
95 | return JNI_OK0; | |||
96 | } | |||
97 | ||||
98 | void G1ConcurrentRefineThreadControl::maybe_activate_next(uint cur_worker_id) { | |||
99 | assert(cur_worker_id < _num_max_threads,do { if (!(cur_worker_id < _num_max_threads)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp" , 101, "assert(" "cur_worker_id < _num_max_threads" ") failed" , "Activating another thread from %u not allowed since there can be at most %u" , cur_worker_id, _num_max_threads); ::breakpoint(); } } while (0) | |||
100 | "Activating another thread from %u not allowed since there can be at most %u",do { if (!(cur_worker_id < _num_max_threads)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp" , 101, "assert(" "cur_worker_id < _num_max_threads" ") failed" , "Activating another thread from %u not allowed since there can be at most %u" , cur_worker_id, _num_max_threads); ::breakpoint(); } } while (0) | |||
101 | cur_worker_id, _num_max_threads)do { if (!(cur_worker_id < _num_max_threads)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp" , 101, "assert(" "cur_worker_id < _num_max_threads" ") failed" , "Activating another thread from %u not allowed since there can be at most %u" , cur_worker_id, _num_max_threads); ::breakpoint(); } } while (0); | |||
102 | if (cur_worker_id == (_num_max_threads - 1)) { | |||
103 | // Already the last thread, there is no more thread to activate. | |||
104 | return; | |||
105 | } | |||
106 | ||||
107 | uint worker_id = cur_worker_id + 1; | |||
108 | G1ConcurrentRefineThread* thread_to_activate = _threads[worker_id]; | |||
109 | if (thread_to_activate == NULL__null) { | |||
110 | // Still need to create the thread... | |||
111 | _threads[worker_id] = create_refinement_thread(worker_id, false); | |||
112 | thread_to_activate = _threads[worker_id]; | |||
113 | } | |||
114 | if (thread_to_activate != NULL__null) { | |||
115 | thread_to_activate->activate(); | |||
116 | } | |||
117 | } | |||
118 | ||||
119 | void G1ConcurrentRefineThreadControl::worker_threads_do(ThreadClosure* tc) { | |||
120 | for (uint i = 0; i < _num_max_threads; i++) { | |||
121 | if (_threads[i] != NULL__null) { | |||
122 | tc->do_thread(_threads[i]); | |||
123 | } | |||
124 | } | |||
125 | } | |||
126 | ||||
127 | void G1ConcurrentRefineThreadControl::stop() { | |||
128 | for (uint i = 0; i < _num_max_threads; i++) { | |||
129 | if (_threads[i] != NULL__null) { | |||
130 | _threads[i]->stop(); | |||
131 | } | |||
132 | } | |||
133 | } | |||
134 | ||||
135 | // Arbitrary but large limits, to simplify some of the zone calculations. | |||
136 | // The general idea is to allow expressions like | |||
137 | // MIN2(x OP y, max_XXX_zone) | |||
138 | // without needing to check for overflow in "x OP y", because the | |||
139 | // ranges for x and y have been restricted. | |||
140 | STATIC_ASSERT(sizeof(LP64_ONLY(jint) NOT_LP64(jshort)) <= (sizeof(size_t)/2))static_assert((sizeof(jint ) <= (sizeof(size_t)/2)), "sizeof(LP64_ONLY(jint) NOT_LP64(jshort)) <= (sizeof(size_t)/2)" ); | |||
141 | const size_t max_yellow_zone = LP64_ONLY(max_jint)max_jint NOT_LP64(max_jshort); | |||
142 | const size_t max_green_zone = max_yellow_zone / 2; | |||
143 | const size_t max_red_zone = INT_MAX2147483647; // For dcqs.set_max_cards. | |||
144 | STATIC_ASSERT(max_yellow_zone <= max_red_zone)static_assert((max_yellow_zone <= max_red_zone), "max_yellow_zone <= max_red_zone" ); | |||
145 | ||||
146 | // Range check assertions for green zone values. | |||
147 | #define assert_zone_constraints_g(green)do { size_t azc_g_green = (green); do { if (!(azc_g_green <= max_green_zone)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp" , 147, "assert(" "azc_g_green <= max_green_zone" ") failed" , "green exceeds max: " "%" "l" "u", azc_g_green); ::breakpoint (); } } while (0); } while (0) \ | |||
148 | do { \ | |||
149 | size_t azc_g_green = (green); \ | |||
150 | assert(azc_g_green <= max_green_zone, \do { if (!(azc_g_green <= max_green_zone)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp" , 151, "assert(" "azc_g_green <= max_green_zone" ") failed" , "green exceeds max: " "%" "l" "u", azc_g_green); ::breakpoint (); } } while (0) | |||
151 | "green exceeds max: " SIZE_FORMAT, azc_g_green)do { if (!(azc_g_green <= max_green_zone)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp" , 151, "assert(" "azc_g_green <= max_green_zone" ") failed" , "green exceeds max: " "%" "l" "u", azc_g_green); ::breakpoint (); } } while (0); \ | |||
152 | } while (0) | |||
153 | ||||
154 | // Range check assertions for green and yellow zone values. | |||
155 | #define assert_zone_constraints_gy(green, yellow)do { size_t azc_gy_green = (green); size_t azc_gy_yellow = (yellow ); do { size_t azc_g_green = (azc_gy_green); do { if (!(azc_g_green <= max_green_zone)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp" , 155, "assert(" "azc_g_green <= max_green_zone" ") failed" , "green exceeds max: " "%" "l" "u", azc_g_green); ::breakpoint (); } } while (0); } while (0); do { if (!(azc_gy_yellow <= max_yellow_zone)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp" , 155, "assert(" "azc_gy_yellow <= max_yellow_zone" ") failed" , "yellow exceeds max: " "%" "l" "u", azc_gy_yellow); ::breakpoint (); } } while (0); do { if (!(azc_gy_green <= azc_gy_yellow )) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp" , 155, "assert(" "azc_gy_green <= azc_gy_yellow" ") failed" , "green (" "%" "l" "u" ") exceeds yellow (" "%" "l" "u" ")", azc_gy_green, azc_gy_yellow); ::breakpoint(); } } while (0); } while (0) \ | |||
156 | do { \ | |||
157 | size_t azc_gy_green = (green); \ | |||
158 | size_t azc_gy_yellow = (yellow); \ | |||
159 | assert_zone_constraints_g(azc_gy_green)do { size_t azc_g_green = (azc_gy_green); do { if (!(azc_g_green <= max_green_zone)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp" , 159, "assert(" "azc_g_green <= max_green_zone" ") failed" , "green exceeds max: " "%" "l" "u", azc_g_green); ::breakpoint (); } } while (0); } while (0); \ | |||
160 | assert(azc_gy_yellow <= max_yellow_zone, \do { if (!(azc_gy_yellow <= max_yellow_zone)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp" , 161, "assert(" "azc_gy_yellow <= max_yellow_zone" ") failed" , "yellow exceeds max: " "%" "l" "u", azc_gy_yellow); ::breakpoint (); } } while (0) | |||
161 | "yellow exceeds max: " SIZE_FORMAT, azc_gy_yellow)do { if (!(azc_gy_yellow <= max_yellow_zone)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp" , 161, "assert(" "azc_gy_yellow <= max_yellow_zone" ") failed" , "yellow exceeds max: " "%" "l" "u", azc_gy_yellow); ::breakpoint (); } } while (0); \ | |||
162 | assert(azc_gy_green <= azc_gy_yellow, \do { if (!(azc_gy_green <= azc_gy_yellow)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp" , 164, "assert(" "azc_gy_green <= azc_gy_yellow" ") failed" , "green (" "%" "l" "u" ") exceeds yellow (" "%" "l" "u" ")", azc_gy_green, azc_gy_yellow); ::breakpoint(); } } while (0) | |||
163 | "green (" SIZE_FORMAT ") exceeds yellow (" SIZE_FORMAT ")", \do { if (!(azc_gy_green <= azc_gy_yellow)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp" , 164, "assert(" "azc_gy_green <= azc_gy_yellow" ") failed" , "green (" "%" "l" "u" ") exceeds yellow (" "%" "l" "u" ")", azc_gy_green, azc_gy_yellow); ::breakpoint(); } } while (0) | |||
164 | azc_gy_green, azc_gy_yellow)do { if (!(azc_gy_green <= azc_gy_yellow)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp" , 164, "assert(" "azc_gy_green <= azc_gy_yellow" ") failed" , "green (" "%" "l" "u" ") exceeds yellow (" "%" "l" "u" ")", azc_gy_green, azc_gy_yellow); ::breakpoint(); } } while (0); \ | |||
165 | } while (0) | |||
166 | ||||
167 | // Range check assertions for green, yellow, and red zone values. | |||
168 | #define assert_zone_constraints_gyr(green, yellow, red)do { size_t azc_gyr_green = (green); size_t azc_gyr_yellow = ( yellow); size_t azc_gyr_red = (red); do { size_t azc_gy_green = (azc_gyr_green); size_t azc_gy_yellow = (azc_gyr_yellow); do { size_t azc_g_green = (azc_gy_green); do { if (!(azc_g_green <= max_green_zone)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp" , 168, "assert(" "azc_g_green <= max_green_zone" ") failed" , "green exceeds max: " "%" "l" "u", azc_g_green); ::breakpoint (); } } while (0); } while (0); do { if (!(azc_gy_yellow <= max_yellow_zone)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp" , 168, "assert(" "azc_gy_yellow <= max_yellow_zone" ") failed" , "yellow exceeds max: " "%" "l" "u", azc_gy_yellow); ::breakpoint (); } } while (0); do { if (!(azc_gy_green <= azc_gy_yellow )) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp" , 168, "assert(" "azc_gy_green <= azc_gy_yellow" ") failed" , "green (" "%" "l" "u" ") exceeds yellow (" "%" "l" "u" ")", azc_gy_green, azc_gy_yellow); ::breakpoint(); } } while (0); } while (0); do { if (!(azc_gyr_red <= max_red_zone)) { ( *g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp" , 168, "assert(" "azc_gyr_red <= max_red_zone" ") failed", "red exceeds max: " "%" "l" "u", azc_gyr_red); ::breakpoint( ); } } while (0); do { if (!(azc_gyr_yellow <= azc_gyr_red )) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp" , 168, "assert(" "azc_gyr_yellow <= azc_gyr_red" ") failed" , "yellow (" "%" "l" "u" ") exceeds red (" "%" "l" "u" ")", azc_gyr_yellow , azc_gyr_red); ::breakpoint(); } } while (0); } while (0) \ | |||
169 | do { \ | |||
170 | size_t azc_gyr_green = (green); \ | |||
171 | size_t azc_gyr_yellow = (yellow); \ | |||
172 | size_t azc_gyr_red = (red); \ | |||
173 | assert_zone_constraints_gy(azc_gyr_green, azc_gyr_yellow)do { size_t azc_gy_green = (azc_gyr_green); size_t azc_gy_yellow = (azc_gyr_yellow); do { size_t azc_g_green = (azc_gy_green) ; do { if (!(azc_g_green <= max_green_zone)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp" , 173, "assert(" "azc_g_green <= max_green_zone" ") failed" , "green exceeds max: " "%" "l" "u", azc_g_green); ::breakpoint (); } } while (0); } while (0); do { if (!(azc_gy_yellow <= max_yellow_zone)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp" , 173, "assert(" "azc_gy_yellow <= max_yellow_zone" ") failed" , "yellow exceeds max: " "%" "l" "u", azc_gy_yellow); ::breakpoint (); } } while (0); do { if (!(azc_gy_green <= azc_gy_yellow )) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp" , 173, "assert(" "azc_gy_green <= azc_gy_yellow" ") failed" , "green (" "%" "l" "u" ") exceeds yellow (" "%" "l" "u" ")", azc_gy_green, azc_gy_yellow); ::breakpoint(); } } while (0); } while (0); \ | |||
174 | assert(azc_gyr_red <= max_red_zone, \do { if (!(azc_gyr_red <= max_red_zone)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp" , 175, "assert(" "azc_gyr_red <= max_red_zone" ") failed", "red exceeds max: " "%" "l" "u", azc_gyr_red); ::breakpoint( ); } } while (0) | |||
175 | "red exceeds max: " SIZE_FORMAT, azc_gyr_red)do { if (!(azc_gyr_red <= max_red_zone)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp" , 175, "assert(" "azc_gyr_red <= max_red_zone" ") failed", "red exceeds max: " "%" "l" "u", azc_gyr_red); ::breakpoint( ); } } while (0); \ | |||
176 | assert(azc_gyr_yellow <= azc_gyr_red, \do { if (!(azc_gyr_yellow <= azc_gyr_red)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp" , 178, "assert(" "azc_gyr_yellow <= azc_gyr_red" ") failed" , "yellow (" "%" "l" "u" ") exceeds red (" "%" "l" "u" ")", azc_gyr_yellow , azc_gyr_red); ::breakpoint(); } } while (0) | |||
177 | "yellow (" SIZE_FORMAT ") exceeds red (" SIZE_FORMAT ")", \do { if (!(azc_gyr_yellow <= azc_gyr_red)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp" , 178, "assert(" "azc_gyr_yellow <= azc_gyr_red" ") failed" , "yellow (" "%" "l" "u" ") exceeds red (" "%" "l" "u" ")", azc_gyr_yellow , azc_gyr_red); ::breakpoint(); } } while (0) | |||
178 | azc_gyr_yellow, azc_gyr_red)do { if (!(azc_gyr_yellow <= azc_gyr_red)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp" , 178, "assert(" "azc_gyr_yellow <= azc_gyr_red" ") failed" , "yellow (" "%" "l" "u" ") exceeds red (" "%" "l" "u" ")", azc_gyr_yellow , azc_gyr_red); ::breakpoint(); } } while (0); \ | |||
179 | } while (0) | |||
180 | ||||
181 | // Logging tag sequence for refinement control updates. | |||
182 | #define CTRL_TAGSgc, ergo, refine gc, ergo, refine | |||
183 | ||||
184 | // For logging zone values, ensuring consistency of level and tags. | |||
185 | #define LOG_ZONES(...)(!(LogImpl<(LogTag::_gc), (LogTag::_ergo), (LogTag::_refine ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Debug))) ? (void)0 : LogImpl<(LogTag ::_gc), (LogTag::_ergo), (LogTag::_refine), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Debug>(...) log_debug( CTRL_TAGS )(!(LogImpl<(LogTag::_gc), (LogTag::_ergo), (LogTag::_refine ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Debug))) ? (void)0 : LogImpl<(LogTag ::_gc), (LogTag::_ergo), (LogTag::_refine), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Debug>(__VA_ARGS__) | |||
186 | ||||
187 | // Convert configuration values in units of buffers to number of cards. | |||
188 | static size_t configuration_buffers_to_cards(size_t value, const char* value_name) { | |||
189 | if (value == 0) return 0; | |||
190 | size_t res = value * G1UpdateBufferSize; | |||
191 | ||||
192 | if (res / value != G1UpdateBufferSize) { // Check overflow | |||
193 | vm_exit_during_initialization(err_msg("configuration_buffers_to_cards: " | |||
194 | "(%s = " SIZE_FORMAT"%" "l" "u" ") * (G1UpdateBufferSize = " SIZE_FORMAT"%" "l" "u" ") overflow!", value_name, value, G1UpdateBufferSize)); | |||
195 | } | |||
196 | return res; | |||
197 | } | |||
198 | ||||
199 | // Package for pair of refinement thread activation and deactivation | |||
200 | // thresholds. The activation and deactivation levels are resp. the first | |||
201 | // and second values of the pair. | |||
202 | typedef Pair<size_t, size_t> Thresholds; | |||
203 | inline size_t activation_level(const Thresholds& t) { return t.first; } | |||
204 | inline size_t deactivation_level(const Thresholds& t) { return t.second; } | |||
205 | ||||
206 | static Thresholds calc_thresholds(size_t green_zone, | |||
207 | size_t yellow_zone, | |||
208 | uint worker_id) { | |||
209 | double yellow_size = yellow_zone - green_zone; | |||
210 | double step = yellow_size / G1ConcurrentRefine::max_num_threads(); | |||
211 | if (worker_id == 0) { | |||
212 | // Potentially activate worker 0 more aggressively, to keep | |||
213 | // available buffers near green_zone value. When yellow_size is | |||
214 | // large we don't want to allow a full step to accumulate before | |||
215 | // doing any processing, as that might lead to significantly more | |||
216 | // than green_zone buffers to be processed during pause. So limit | |||
217 | // to an extra half buffer per pause-time processing thread. | |||
218 | step = MIN2(step, configuration_buffers_to_cards(ParallelGCThreads, "ParallelGCThreads") / 2.0); | |||
219 | } | |||
220 | size_t activate_offset = static_cast<size_t>(ceil(step * (worker_id + 1))); | |||
221 | size_t deactivate_offset = static_cast<size_t>(floor(step * worker_id)); | |||
222 | return Thresholds(green_zone + activate_offset, | |||
223 | green_zone + deactivate_offset); | |||
224 | } | |||
225 | ||||
226 | G1ConcurrentRefine::G1ConcurrentRefine(size_t green_zone, | |||
227 | size_t yellow_zone, | |||
228 | size_t red_zone, | |||
229 | size_t min_yellow_zone_size) : | |||
230 | _thread_control(), | |||
231 | _green_zone(green_zone), | |||
232 | _yellow_zone(yellow_zone), | |||
233 | _red_zone(red_zone), | |||
234 | _min_yellow_zone_size(min_yellow_zone_size) | |||
235 | { | |||
236 | assert_zone_constraints_gyr(green_zone, yellow_zone, red_zone)do { size_t azc_gyr_green = (green_zone); size_t azc_gyr_yellow = (yellow_zone); size_t azc_gyr_red = (red_zone); do { size_t azc_gy_green = (azc_gyr_green); size_t azc_gy_yellow = (azc_gyr_yellow ); do { size_t azc_g_green = (azc_gy_green); do { if (!(azc_g_green <= max_green_zone)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp" , 236, "assert(" "azc_g_green <= max_green_zone" ") failed" , "green exceeds max: " "%" "l" "u", azc_g_green); ::breakpoint (); } } while (0); } while (0); do { if (!(azc_gy_yellow <= max_yellow_zone)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp" , 236, "assert(" "azc_gy_yellow <= max_yellow_zone" ") failed" , "yellow exceeds max: " "%" "l" "u", azc_gy_yellow); ::breakpoint (); } } while (0); do { if (!(azc_gy_green <= azc_gy_yellow )) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp" , 236, "assert(" "azc_gy_green <= azc_gy_yellow" ") failed" , "green (" "%" "l" "u" ") exceeds yellow (" "%" "l" "u" ")", azc_gy_green, azc_gy_yellow); ::breakpoint(); } } while (0); } while (0); do { if (!(azc_gyr_red <= max_red_zone)) { ( *g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp" , 236, "assert(" "azc_gyr_red <= max_red_zone" ") failed", "red exceeds max: " "%" "l" "u", azc_gyr_red); ::breakpoint( ); } } while (0); do { if (!(azc_gyr_yellow <= azc_gyr_red )) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp" , 236, "assert(" "azc_gyr_yellow <= azc_gyr_red" ") failed" , "yellow (" "%" "l" "u" ") exceeds red (" "%" "l" "u" ")", azc_gyr_yellow , azc_gyr_red); ::breakpoint(); } } while (0); } while (0); | |||
237 | } | |||
238 | ||||
239 | jint G1ConcurrentRefine::initialize() { | |||
240 | return _thread_control.initialize(this, max_num_threads()); | |||
241 | } | |||
242 | ||||
243 | static size_t calc_min_yellow_zone_size() { | |||
244 | size_t step = configuration_buffers_to_cards(G1ConcRefinementThresholdStep, "G1ConcRefinementThresholdStep"); | |||
245 | uint n_workers = G1ConcurrentRefine::max_num_threads(); | |||
246 | if ((max_yellow_zone / step) < n_workers) { | |||
| ||||
247 | return max_yellow_zone; | |||
248 | } else { | |||
249 | return step * n_workers; | |||
250 | } | |||
251 | } | |||
252 | ||||
253 | // An initial guess at the rate for pause-time card refinement for one | |||
254 | // thread, used when computing the default initial green zone value. | |||
255 | const double InitialPauseTimeCardRefinementRate = 200.0; | |||
256 | ||||
257 | static size_t calc_init_green_zone() { | |||
258 | size_t green; | |||
259 | if (FLAG_IS_DEFAULT(G1ConcRefinementGreenZone)(JVMFlag::is_default(Flag_G1ConcRefinementGreenZone_enum))) { | |||
260 | const double rate = InitialPauseTimeCardRefinementRate * ParallelGCThreads; | |||
261 | // The time budget for pause-time card refinement. | |||
262 | const double ms = MaxGCPauseMillis * (G1RSetUpdatingPauseTimePercent / 100.0); | |||
263 | green = rate * ms; | |||
264 | } else { | |||
265 | green = configuration_buffers_to_cards(G1ConcRefinementGreenZone, | |||
266 | "G1ConcRefinementGreenZone"); | |||
267 | } | |||
268 | return MIN2(green, max_green_zone); | |||
269 | } | |||
270 | ||||
271 | static size_t calc_init_yellow_zone(size_t green, size_t min_size) { | |||
272 | size_t config = configuration_buffers_to_cards(G1ConcRefinementYellowZone, "G1ConcRefinementYellowZone"); | |||
273 | size_t size = 0; | |||
274 | if (FLAG_IS_DEFAULT(G1ConcRefinementYellowZone)(JVMFlag::is_default(Flag_G1ConcRefinementYellowZone_enum))) { | |||
275 | size = green * 2; | |||
276 | } else if (green < config) { | |||
277 | size = config - green; | |||
278 | } | |||
279 | size = MAX2(size, min_size); | |||
280 | size = MIN2(size, max_yellow_zone); | |||
281 | return MIN2(green + size, max_yellow_zone); | |||
282 | } | |||
283 | ||||
284 | static size_t calc_init_red_zone(size_t green, size_t yellow) { | |||
285 | size_t size = yellow - green; | |||
286 | if (!FLAG_IS_DEFAULT(G1ConcRefinementRedZone)(JVMFlag::is_default(Flag_G1ConcRefinementRedZone_enum))) { | |||
287 | size_t config = configuration_buffers_to_cards(G1ConcRefinementRedZone, "G1ConcRefinementRedZone"); | |||
288 | if (yellow < config) { | |||
289 | size = MAX2(size, config - yellow); | |||
290 | } | |||
291 | } | |||
292 | return MIN2(yellow + size, max_red_zone); | |||
293 | } | |||
294 | ||||
295 | G1ConcurrentRefine* G1ConcurrentRefine::create(jint* ecode) { | |||
296 | size_t min_yellow_zone_size = calc_min_yellow_zone_size(); | |||
| ||||
297 | size_t green_zone = calc_init_green_zone(); | |||
298 | size_t yellow_zone = calc_init_yellow_zone(green_zone, min_yellow_zone_size); | |||
299 | size_t red_zone = calc_init_red_zone(green_zone, yellow_zone); | |||
300 | ||||
301 | LOG_ZONES("Initial Refinement Zones: "(!(LogImpl<(LogTag::_gc), (LogTag::_ergo), (LogTag::_refine ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Debug))) ? (void)0 : LogImpl<(LogTag ::_gc), (LogTag::_ergo), (LogTag::_refine), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Debug>("Initial Refinement Zones: " "green: " "%" "l" "u" ", " "yellow: " "%" "l" "u" ", " "red: " "%" "l" "u" ", " "min yellow size: " "%" "l" "u", green_zone, yellow_zone, red_zone, min_yellow_zone_size ) | |||
302 | "green: " SIZE_FORMAT ", "(!(LogImpl<(LogTag::_gc), (LogTag::_ergo), (LogTag::_refine ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Debug))) ? (void)0 : LogImpl<(LogTag ::_gc), (LogTag::_ergo), (LogTag::_refine), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Debug>("Initial Refinement Zones: " "green: " "%" "l" "u" ", " "yellow: " "%" "l" "u" ", " "red: " "%" "l" "u" ", " "min yellow size: " "%" "l" "u", green_zone, yellow_zone, red_zone, min_yellow_zone_size ) | |||
303 | "yellow: " SIZE_FORMAT ", "(!(LogImpl<(LogTag::_gc), (LogTag::_ergo), (LogTag::_refine ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Debug))) ? (void)0 : LogImpl<(LogTag ::_gc), (LogTag::_ergo), (LogTag::_refine), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Debug>("Initial Refinement Zones: " "green: " "%" "l" "u" ", " "yellow: " "%" "l" "u" ", " "red: " "%" "l" "u" ", " "min yellow size: " "%" "l" "u", green_zone, yellow_zone, red_zone, min_yellow_zone_size ) | |||
304 | "red: " SIZE_FORMAT ", "(!(LogImpl<(LogTag::_gc), (LogTag::_ergo), (LogTag::_refine ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Debug))) ? (void)0 : LogImpl<(LogTag ::_gc), (LogTag::_ergo), (LogTag::_refine), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Debug>("Initial Refinement Zones: " "green: " "%" "l" "u" ", " "yellow: " "%" "l" "u" ", " "red: " "%" "l" "u" ", " "min yellow size: " "%" "l" "u", green_zone, yellow_zone, red_zone, min_yellow_zone_size ) | |||
305 | "min yellow size: " SIZE_FORMAT,(!(LogImpl<(LogTag::_gc), (LogTag::_ergo), (LogTag::_refine ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Debug))) ? (void)0 : LogImpl<(LogTag ::_gc), (LogTag::_ergo), (LogTag::_refine), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Debug>("Initial Refinement Zones: " "green: " "%" "l" "u" ", " "yellow: " "%" "l" "u" ", " "red: " "%" "l" "u" ", " "min yellow size: " "%" "l" "u", green_zone, yellow_zone, red_zone, min_yellow_zone_size ) | |||
306 | green_zone, yellow_zone, red_zone, min_yellow_zone_size)(!(LogImpl<(LogTag::_gc), (LogTag::_ergo), (LogTag::_refine ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Debug))) ? (void)0 : LogImpl<(LogTag ::_gc), (LogTag::_ergo), (LogTag::_refine), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Debug>("Initial Refinement Zones: " "green: " "%" "l" "u" ", " "yellow: " "%" "l" "u" ", " "red: " "%" "l" "u" ", " "min yellow size: " "%" "l" "u", green_zone, yellow_zone, red_zone, min_yellow_zone_size ); | |||
307 | ||||
308 | G1ConcurrentRefine* cr = new G1ConcurrentRefine(green_zone, | |||
309 | yellow_zone, | |||
310 | red_zone, | |||
311 | min_yellow_zone_size); | |||
312 | *ecode = cr->initialize(); | |||
313 | return cr; | |||
314 | } | |||
315 | ||||
316 | void G1ConcurrentRefine::stop() { | |||
317 | _thread_control.stop(); | |||
318 | } | |||
319 | ||||
320 | G1ConcurrentRefine::~G1ConcurrentRefine() { | |||
321 | } | |||
322 | ||||
323 | void G1ConcurrentRefine::threads_do(ThreadClosure *tc) { | |||
324 | _thread_control.worker_threads_do(tc); | |||
325 | } | |||
326 | ||||
327 | uint G1ConcurrentRefine::max_num_threads() { | |||
328 | return G1ConcRefinementThreads; | |||
329 | } | |||
330 | ||||
331 | static size_t calc_new_green_zone(size_t green, | |||
332 | double logged_cards_scan_time, | |||
333 | size_t processed_logged_cards, | |||
334 | double goal_ms) { | |||
335 | // Adjust green zone based on whether we're meeting the time goal. | |||
336 | // Limit to max_green_zone. | |||
337 | const double inc_k = 1.1, dec_k = 0.9; | |||
338 | if (logged_cards_scan_time > goal_ms) { | |||
339 | if (green > 0) { | |||
340 | green = static_cast<size_t>(green * dec_k); | |||
341 | } | |||
342 | } else if (logged_cards_scan_time < goal_ms && | |||
343 | processed_logged_cards > green) { | |||
344 | green = static_cast<size_t>(MAX2(green * inc_k, green + 1.0)); | |||
345 | green = MIN2(green, max_green_zone); | |||
346 | } | |||
347 | return green; | |||
348 | } | |||
349 | ||||
350 | static size_t calc_new_yellow_zone(size_t green, size_t min_yellow_size) { | |||
351 | size_t size = green * 2; | |||
352 | size = MAX2(size, min_yellow_size); | |||
353 | return MIN2(green + size, max_yellow_zone); | |||
354 | } | |||
355 | ||||
356 | static size_t calc_new_red_zone(size_t green, size_t yellow) { | |||
357 | return MIN2(yellow + (yellow - green), max_red_zone); | |||
358 | } | |||
359 | ||||
360 | void G1ConcurrentRefine::update_zones(double logged_cards_scan_time, | |||
361 | size_t processed_logged_cards, | |||
362 | double goal_ms) { | |||
363 | log_trace( CTRL_TAGS )(!(LogImpl<(LogTag::_gc), (LogTag::_ergo), (LogTag::_refine ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Trace))) ? (void)0 : LogImpl<(LogTag ::_gc), (LogTag::_ergo), (LogTag::_refine), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Trace>("Updating Refinement Zones: " | |||
364 | "logged cards scan time: %.3fms, " | |||
365 | "processed cards: " SIZE_FORMAT"%" "l" "u" ", " | |||
366 | "goal time: %.3fms", | |||
367 | logged_cards_scan_time, | |||
368 | processed_logged_cards, | |||
369 | goal_ms); | |||
370 | ||||
371 | _green_zone = calc_new_green_zone(_green_zone, | |||
372 | logged_cards_scan_time, | |||
373 | processed_logged_cards, | |||
374 | goal_ms); | |||
375 | _yellow_zone = calc_new_yellow_zone(_green_zone, _min_yellow_zone_size); | |||
376 | _red_zone = calc_new_red_zone(_green_zone, _yellow_zone); | |||
377 | ||||
378 | assert_zone_constraints_gyr(_green_zone, _yellow_zone, _red_zone)do { size_t azc_gyr_green = (_green_zone); size_t azc_gyr_yellow = (_yellow_zone); size_t azc_gyr_red = (_red_zone); do { size_t azc_gy_green = (azc_gyr_green); size_t azc_gy_yellow = (azc_gyr_yellow ); do { size_t azc_g_green = (azc_gy_green); do { if (!(azc_g_green <= max_green_zone)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp" , 378, "assert(" "azc_g_green <= max_green_zone" ") failed" , "green exceeds max: " "%" "l" "u", azc_g_green); ::breakpoint (); } } while (0); } while (0); do { if (!(azc_gy_yellow <= max_yellow_zone)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp" , 378, "assert(" "azc_gy_yellow <= max_yellow_zone" ") failed" , "yellow exceeds max: " "%" "l" "u", azc_gy_yellow); ::breakpoint (); } } while (0); do { if (!(azc_gy_green <= azc_gy_yellow )) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp" , 378, "assert(" "azc_gy_green <= azc_gy_yellow" ") failed" , "green (" "%" "l" "u" ") exceeds yellow (" "%" "l" "u" ")", azc_gy_green, azc_gy_yellow); ::breakpoint(); } } while (0); } while (0); do { if (!(azc_gyr_red <= max_red_zone)) { ( *g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp" , 378, "assert(" "azc_gyr_red <= max_red_zone" ") failed", "red exceeds max: " "%" "l" "u", azc_gyr_red); ::breakpoint( ); } } while (0); do { if (!(azc_gyr_yellow <= azc_gyr_red )) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp" , 378, "assert(" "azc_gyr_yellow <= azc_gyr_red" ") failed" , "yellow (" "%" "l" "u" ") exceeds red (" "%" "l" "u" ")", azc_gyr_yellow , azc_gyr_red); ::breakpoint(); } } while (0); } while (0); | |||
379 | LOG_ZONES("Updated Refinement Zones: "(!(LogImpl<(LogTag::_gc), (LogTag::_ergo), (LogTag::_refine ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Debug))) ? (void)0 : LogImpl<(LogTag ::_gc), (LogTag::_ergo), (LogTag::_refine), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Debug>("Updated Refinement Zones: " "green: " "%" "l" "u" ", " "yellow: " "%" "l" "u" ", " "red: " "%" "l" "u", _green_zone , _yellow_zone, _red_zone) | |||
380 | "green: " SIZE_FORMAT ", "(!(LogImpl<(LogTag::_gc), (LogTag::_ergo), (LogTag::_refine ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Debug))) ? (void)0 : LogImpl<(LogTag ::_gc), (LogTag::_ergo), (LogTag::_refine), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Debug>("Updated Refinement Zones: " "green: " "%" "l" "u" ", " "yellow: " "%" "l" "u" ", " "red: " "%" "l" "u", _green_zone , _yellow_zone, _red_zone) | |||
381 | "yellow: " SIZE_FORMAT ", "(!(LogImpl<(LogTag::_gc), (LogTag::_ergo), (LogTag::_refine ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Debug))) ? (void)0 : LogImpl<(LogTag ::_gc), (LogTag::_ergo), (LogTag::_refine), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Debug>("Updated Refinement Zones: " "green: " "%" "l" "u" ", " "yellow: " "%" "l" "u" ", " "red: " "%" "l" "u", _green_zone , _yellow_zone, _red_zone) | |||
382 | "red: " SIZE_FORMAT,(!(LogImpl<(LogTag::_gc), (LogTag::_ergo), (LogTag::_refine ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Debug))) ? (void)0 : LogImpl<(LogTag ::_gc), (LogTag::_ergo), (LogTag::_refine), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Debug>("Updated Refinement Zones: " "green: " "%" "l" "u" ", " "yellow: " "%" "l" "u" ", " "red: " "%" "l" "u", _green_zone , _yellow_zone, _red_zone) | |||
383 | _green_zone, _yellow_zone, _red_zone)(!(LogImpl<(LogTag::_gc), (LogTag::_ergo), (LogTag::_refine ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Debug))) ? (void)0 : LogImpl<(LogTag ::_gc), (LogTag::_ergo), (LogTag::_refine), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Debug>("Updated Refinement Zones: " "green: " "%" "l" "u" ", " "yellow: " "%" "l" "u" ", " "red: " "%" "l" "u", _green_zone , _yellow_zone, _red_zone); | |||
384 | } | |||
385 | ||||
386 | void G1ConcurrentRefine::adjust(double logged_cards_scan_time, | |||
387 | size_t processed_logged_cards, | |||
388 | double goal_ms) { | |||
389 | G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set(); | |||
390 | ||||
391 | if (G1UseAdaptiveConcRefinement) { | |||
392 | update_zones(logged_cards_scan_time, processed_logged_cards, goal_ms); | |||
393 | ||||
394 | // Change the barrier params | |||
395 | if (max_num_threads() == 0) { | |||
396 | // Disable dcqs notification when there are no threads to notify. | |||
397 | dcqs.set_process_cards_threshold(G1DirtyCardQueueSet::ProcessCardsThresholdNever); | |||
398 | } else { | |||
399 | // Worker 0 is the primary; wakeup is via dcqs notification. | |||
400 | STATIC_ASSERT(max_yellow_zone <= INT_MAX)static_assert((max_yellow_zone <= 2147483647), "max_yellow_zone <= INT_MAX" ); | |||
401 | size_t activate = activation_threshold(0); | |||
402 | dcqs.set_process_cards_threshold(activate); | |||
403 | } | |||
404 | dcqs.set_max_cards(red_zone()); | |||
405 | } | |||
406 | ||||
407 | size_t curr_queue_size = dcqs.num_cards(); | |||
408 | if ((dcqs.max_cards() > 0) && | |||
409 | (curr_queue_size >= yellow_zone())) { | |||
410 | dcqs.set_max_cards_padding(curr_queue_size); | |||
411 | } else { | |||
412 | dcqs.set_max_cards_padding(0); | |||
413 | } | |||
414 | dcqs.notify_if_necessary(); | |||
415 | } | |||
416 | ||||
417 | G1ConcurrentRefineStats G1ConcurrentRefine::get_and_reset_refinement_stats() { | |||
418 | struct CollectStats : public ThreadClosure { | |||
419 | G1ConcurrentRefineStats _total_stats; | |||
420 | virtual void do_thread(Thread* t) { | |||
421 | G1ConcurrentRefineThread* crt = static_cast<G1ConcurrentRefineThread*>(t); | |||
422 | G1ConcurrentRefineStats& stats = *crt->refinement_stats(); | |||
423 | _total_stats += stats; | |||
424 | stats.reset(); | |||
425 | } | |||
426 | } collector; | |||
427 | threads_do(&collector); | |||
428 | return collector._total_stats; | |||
429 | } | |||
430 | ||||
431 | size_t G1ConcurrentRefine::activation_threshold(uint worker_id) const { | |||
432 | Thresholds thresholds = calc_thresholds(_green_zone, _yellow_zone, worker_id); | |||
433 | return activation_level(thresholds); | |||
434 | } | |||
435 | ||||
436 | size_t G1ConcurrentRefine::deactivation_threshold(uint worker_id) const { | |||
437 | Thresholds thresholds = calc_thresholds(_green_zone, _yellow_zone, worker_id); | |||
438 | return deactivation_level(thresholds); | |||
439 | } | |||
440 | ||||
441 | uint G1ConcurrentRefine::worker_id_offset() { | |||
442 | return G1DirtyCardQueueSet::num_par_ids(); | |||
443 | } | |||
444 | ||||
445 | void G1ConcurrentRefine::maybe_activate_more_threads(uint worker_id, size_t num_cur_cards) { | |||
446 | if (num_cur_cards > activation_threshold(worker_id + 1)) { | |||
447 | _thread_control.maybe_activate_next(worker_id); | |||
448 | } | |||
449 | } | |||
450 | ||||
451 | bool G1ConcurrentRefine::do_refinement_step(uint worker_id, | |||
452 | G1ConcurrentRefineStats* stats) { | |||
453 | G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set(); | |||
454 | ||||
455 | size_t curr_cards = dcqs.num_cards(); | |||
456 | // If the number of the cards falls down into the yellow zone, | |||
457 | // that means that the transition period after the evacuation pause has ended. | |||
458 | if (curr_cards <= yellow_zone()) { | |||
459 | dcqs.discard_max_cards_padding(); | |||
460 | } | |||
461 | ||||
462 | maybe_activate_more_threads(worker_id, curr_cards); | |||
463 | ||||
464 | // Process the next buffer, if there are enough left. | |||
465 | return dcqs.refine_completed_buffer_concurrently(worker_id + worker_id_offset(), | |||
466 | deactivation_threshold(worker_id), | |||
467 | stats); | |||
468 | } |