File: | jdk/src/hotspot/share/gc/g1/heapRegion.cpp |
Warning: | line 713, column 5 Value stored to 'prev_p' is never read |
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 "code/nmethod.hpp" |
27 | #include "gc/g1/g1Allocator.inline.hpp" |
28 | #include "gc/g1/g1BlockOffsetTable.inline.hpp" |
29 | #include "gc/g1/g1CollectedHeap.inline.hpp" |
30 | #include "gc/g1/g1CollectionSet.hpp" |
31 | #include "gc/g1/g1HeapRegionTraceType.hpp" |
32 | #include "gc/g1/g1NUMA.hpp" |
33 | #include "gc/g1/g1OopClosures.inline.hpp" |
34 | #include "gc/g1/heapRegion.inline.hpp" |
35 | #include "gc/g1/heapRegionBounds.inline.hpp" |
36 | #include "gc/g1/heapRegionManager.inline.hpp" |
37 | #include "gc/g1/heapRegionRemSet.inline.hpp" |
38 | #include "gc/g1/heapRegionTracer.hpp" |
39 | #include "gc/shared/genOopClosures.inline.hpp" |
40 | #include "logging/log.hpp" |
41 | #include "logging/logStream.hpp" |
42 | #include "memory/iterator.inline.hpp" |
43 | #include "memory/resourceArea.hpp" |
44 | #include "oops/access.inline.hpp" |
45 | #include "oops/compressedOops.inline.hpp" |
46 | #include "oops/oop.inline.hpp" |
47 | #include "runtime/globals_extension.hpp" |
48 | #include "utilities/powerOfTwo.hpp" |
49 | |
50 | int HeapRegion::LogOfHRGrainBytes = 0; |
51 | int HeapRegion::LogCardsPerRegion = 0; |
52 | size_t HeapRegion::GrainBytes = 0; |
53 | size_t HeapRegion::GrainWords = 0; |
54 | size_t HeapRegion::CardsPerRegion = 0; |
55 | |
56 | size_t HeapRegion::max_region_size() { |
57 | return HeapRegionBounds::max_size(); |
58 | } |
59 | |
60 | size_t HeapRegion::min_region_size_in_words() { |
61 | return HeapRegionBounds::min_size() >> LogHeapWordSize; |
62 | } |
63 | |
64 | void HeapRegion::setup_heap_region_size(size_t max_heap_size) { |
65 | size_t region_size = G1HeapRegionSize; |
66 | // G1HeapRegionSize = 0 means decide ergonomically. |
67 | if (region_size == 0) { |
68 | region_size = clamp(max_heap_size / HeapRegionBounds::target_number(), |
69 | HeapRegionBounds::min_size(), |
70 | HeapRegionBounds::max_ergonomics_size()); |
71 | } |
72 | |
73 | // Make sure region size is a power of 2. Rounding up since this |
74 | // is beneficial in most cases. |
75 | region_size = round_up_power_of_2(region_size); |
76 | |
77 | // Now make sure that we don't go over or under our limits. |
78 | region_size = clamp(region_size, HeapRegionBounds::min_size(), HeapRegionBounds::max_size()); |
79 | |
80 | // Calculate the log for the region size. |
81 | int region_size_log = log2i_exact(region_size); |
82 | |
83 | // Now, set up the globals. |
84 | guarantee(LogOfHRGrainBytes == 0, "we should only set it once")do { if (!(LogOfHRGrainBytes == 0)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/heapRegion.cpp" , 84, "guarantee(" "LogOfHRGrainBytes == 0" ") failed", "we should only set it once" ); ::breakpoint(); } } while (0); |
85 | LogOfHRGrainBytes = region_size_log; |
86 | |
87 | guarantee(GrainBytes == 0, "we should only set it once")do { if (!(GrainBytes == 0)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/heapRegion.cpp" , 87, "guarantee(" "GrainBytes == 0" ") failed", "we should only set it once" ); ::breakpoint(); } } while (0); |
88 | GrainBytes = region_size; |
89 | |
90 | guarantee(GrainWords == 0, "we should only set it once")do { if (!(GrainWords == 0)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/heapRegion.cpp" , 90, "guarantee(" "GrainWords == 0" ") failed", "we should only set it once" ); ::breakpoint(); } } while (0); |
91 | GrainWords = GrainBytes >> LogHeapWordSize; |
92 | |
93 | guarantee(CardsPerRegion == 0, "we should only set it once")do { if (!(CardsPerRegion == 0)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/heapRegion.cpp" , 93, "guarantee(" "CardsPerRegion == 0" ") failed", "we should only set it once" ); ::breakpoint(); } } while (0); |
94 | CardsPerRegion = GrainBytes >> G1CardTable::card_shift(); |
95 | |
96 | LogCardsPerRegion = log2i(CardsPerRegion); |
97 | |
98 | if (G1HeapRegionSize != GrainBytes) { |
99 | FLAG_SET_ERGO(G1HeapRegionSize, GrainBytes)(Flag_G1HeapRegionSize_set((GrainBytes), JVMFlagOrigin::ERGONOMIC )); |
100 | } |
101 | } |
102 | |
103 | void HeapRegion::handle_evacuation_failure() { |
104 | uninstall_surv_rate_group(); |
105 | clear_young_index_in_cset(); |
106 | set_old(); |
107 | _next_marked_bytes = 0; |
108 | } |
109 | |
110 | void HeapRegion::process_and_drop_evac_failure_objs(ObjectClosure* closure) { |
111 | _evac_failure_objs.process_and_drop(closure); |
112 | } |
113 | |
114 | void HeapRegion::unlink_from_list() { |
115 | set_next(NULL__null); |
116 | set_prev(NULL__null); |
117 | set_containing_set(NULL__null); |
118 | } |
119 | |
120 | void HeapRegion::hr_clear(bool clear_space) { |
121 | assert(_humongous_start_region == NULL,do { if (!(_humongous_start_region == __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/heapRegion.cpp" , 122, "assert(" "_humongous_start_region == __null" ") failed" , "we should have already filtered out humongous regions"); :: breakpoint(); } } while (0) |
122 | "we should have already filtered out humongous regions")do { if (!(_humongous_start_region == __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/heapRegion.cpp" , 122, "assert(" "_humongous_start_region == __null" ") failed" , "we should have already filtered out humongous regions"); :: breakpoint(); } } while (0); |
123 | |
124 | clear_young_index_in_cset(); |
125 | clear_index_in_opt_cset(); |
126 | uninstall_surv_rate_group(); |
127 | set_free(); |
128 | reset_pre_dummy_top(); |
129 | |
130 | rem_set()->clear_locked(); |
131 | |
132 | zero_marked_bytes(); |
133 | |
134 | init_top_at_mark_start(); |
135 | if (clear_space) clear(SpaceDecorator::Mangle); |
136 | |
137 | _gc_efficiency = -1.0; |
138 | } |
139 | |
140 | void HeapRegion::clear_cardtable() { |
141 | G1CardTable* ct = G1CollectedHeap::heap()->card_table(); |
142 | ct->clear(MemRegion(bottom(), end())); |
143 | } |
144 | |
145 | void HeapRegion::calc_gc_efficiency() { |
146 | // GC efficiency is the ratio of how much space would be |
147 | // reclaimed over how long we predict it would take to reclaim it. |
148 | G1Policy* policy = G1CollectedHeap::heap()->policy(); |
149 | |
150 | // Retrieve a prediction of the elapsed time for this region for |
151 | // a mixed gc because the region will only be evacuated during a |
152 | // mixed gc. |
153 | double region_elapsed_time_ms = policy->predict_region_total_time_ms(this, false /* for_young_gc */); |
154 | _gc_efficiency = (double) reclaimable_bytes() / region_elapsed_time_ms; |
155 | } |
156 | |
157 | void HeapRegion::set_free() { |
158 | report_region_type_change(G1HeapRegionTraceType::Free); |
159 | _type.set_free(); |
160 | } |
161 | |
162 | void HeapRegion::set_eden() { |
163 | report_region_type_change(G1HeapRegionTraceType::Eden); |
164 | _type.set_eden(); |
165 | } |
166 | |
167 | void HeapRegion::set_eden_pre_gc() { |
168 | report_region_type_change(G1HeapRegionTraceType::Eden); |
169 | _type.set_eden_pre_gc(); |
170 | } |
171 | |
172 | void HeapRegion::set_survivor() { |
173 | report_region_type_change(G1HeapRegionTraceType::Survivor); |
174 | _type.set_survivor(); |
175 | } |
176 | |
177 | void HeapRegion::move_to_old() { |
178 | if (_type.relabel_as_old()) { |
179 | report_region_type_change(G1HeapRegionTraceType::Old); |
180 | } |
181 | } |
182 | |
183 | void HeapRegion::set_old() { |
184 | report_region_type_change(G1HeapRegionTraceType::Old); |
185 | _type.set_old(); |
186 | } |
187 | |
188 | void HeapRegion::set_open_archive() { |
189 | report_region_type_change(G1HeapRegionTraceType::OpenArchive); |
190 | _type.set_open_archive(); |
191 | } |
192 | |
193 | void HeapRegion::set_closed_archive() { |
194 | report_region_type_change(G1HeapRegionTraceType::ClosedArchive); |
195 | _type.set_closed_archive(); |
196 | } |
197 | |
198 | void HeapRegion::set_starts_humongous(HeapWord* obj_top, size_t fill_size) { |
199 | assert(!is_humongous(), "sanity / pre-condition")do { if (!(!is_humongous())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/heapRegion.cpp" , 199, "assert(" "!is_humongous()" ") failed", "sanity / pre-condition" ); ::breakpoint(); } } while (0); |
200 | assert(top() == bottom(), "should be empty")do { if (!(top() == bottom())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/heapRegion.cpp" , 200, "assert(" "top() == bottom()" ") failed", "should be empty" ); ::breakpoint(); } } while (0); |
201 | |
202 | report_region_type_change(G1HeapRegionTraceType::StartsHumongous); |
203 | _type.set_starts_humongous(); |
204 | _humongous_start_region = this; |
205 | |
206 | _bot_part.set_for_starts_humongous(obj_top, fill_size); |
207 | } |
208 | |
209 | void HeapRegion::set_continues_humongous(HeapRegion* first_hr) { |
210 | assert(!is_humongous(), "sanity / pre-condition")do { if (!(!is_humongous())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/heapRegion.cpp" , 210, "assert(" "!is_humongous()" ") failed", "sanity / pre-condition" ); ::breakpoint(); } } while (0); |
211 | assert(top() == bottom(), "should be empty")do { if (!(top() == bottom())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/heapRegion.cpp" , 211, "assert(" "top() == bottom()" ") failed", "should be empty" ); ::breakpoint(); } } while (0); |
212 | assert(first_hr->is_starts_humongous(), "pre-condition")do { if (!(first_hr->is_starts_humongous())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/heapRegion.cpp" , 212, "assert(" "first_hr->is_starts_humongous()" ") failed" , "pre-condition"); ::breakpoint(); } } while (0); |
213 | |
214 | report_region_type_change(G1HeapRegionTraceType::ContinuesHumongous); |
215 | _type.set_continues_humongous(); |
216 | _humongous_start_region = first_hr; |
217 | } |
218 | |
219 | void HeapRegion::clear_humongous() { |
220 | assert(is_humongous(), "pre-condition")do { if (!(is_humongous())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/heapRegion.cpp" , 220, "assert(" "is_humongous()" ") failed", "pre-condition" ); ::breakpoint(); } } while (0); |
221 | |
222 | assert(capacity() == HeapRegion::GrainBytes, "pre-condition")do { if (!(capacity() == HeapRegion::GrainBytes)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/heapRegion.cpp" , 222, "assert(" "capacity() == HeapRegion::GrainBytes" ") failed" , "pre-condition"); ::breakpoint(); } } while (0); |
223 | _humongous_start_region = NULL__null; |
224 | } |
225 | |
226 | HeapRegion::HeapRegion(uint hrm_index, |
227 | G1BlockOffsetTable* bot, |
228 | MemRegion mr, |
229 | G1CardSetConfiguration* config) : |
230 | _bottom(mr.start()), |
231 | _end(mr.end()), |
232 | _top(NULL__null), |
233 | _compaction_top(NULL__null), |
234 | _bot_part(bot, this), |
235 | _pre_dummy_top(NULL__null), |
236 | _rem_set(NULL__null), |
237 | _hrm_index(hrm_index), |
238 | _type(), |
239 | _humongous_start_region(NULL__null), |
240 | _index_in_opt_cset(InvalidCSetIndex), |
241 | _next(NULL__null), _prev(NULL__null), |
242 | #ifdef ASSERT1 |
243 | _containing_set(NULL__null), |
244 | #endif |
245 | _prev_top_at_mark_start(NULL__null), _next_top_at_mark_start(NULL__null), |
246 | _prev_marked_bytes(0), _next_marked_bytes(0), |
247 | _young_index_in_cset(-1), |
248 | _surv_rate_group(NULL__null), _age_index(G1SurvRateGroup::InvalidAgeIndex), _gc_efficiency(-1.0), |
249 | _node_index(G1NUMA::UnknownNodeIndex), |
250 | _evac_failure_objs(hrm_index, _bottom) |
251 | { |
252 | assert(Universe::on_page_boundary(mr.start()) && Universe::on_page_boundary(mr.end()),do { if (!(Universe::on_page_boundary(mr.start()) && Universe ::on_page_boundary(mr.end()))) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/heapRegion.cpp" , 253, "assert(" "Universe::on_page_boundary(mr.start()) && Universe::on_page_boundary(mr.end())" ") failed", "invalid space boundaries"); ::breakpoint(); } } while (0) |
253 | "invalid space boundaries")do { if (!(Universe::on_page_boundary(mr.start()) && Universe ::on_page_boundary(mr.end()))) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/heapRegion.cpp" , 253, "assert(" "Universe::on_page_boundary(mr.start()) && Universe::on_page_boundary(mr.end())" ") failed", "invalid space boundaries"); ::breakpoint(); } } while (0); |
254 | |
255 | _rem_set = new HeapRegionRemSet(this, config); |
256 | initialize(); |
257 | } |
258 | |
259 | void HeapRegion::initialize(bool clear_space, bool mangle_space) { |
260 | assert(_rem_set->is_empty(), "Remembered set must be empty")do { if (!(_rem_set->is_empty())) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/heapRegion.cpp" , 260, "assert(" "_rem_set->is_empty()" ") failed", "Remembered set must be empty" ); ::breakpoint(); } } while (0); |
261 | |
262 | if (clear_space) { |
263 | clear(mangle_space); |
264 | } |
265 | |
266 | set_top(bottom()); |
267 | set_compaction_top(bottom()); |
268 | reset_bot(); |
269 | |
270 | hr_clear(false /*clear_space*/); |
271 | } |
272 | |
273 | void HeapRegion::report_region_type_change(G1HeapRegionTraceType::Type to) { |
274 | HeapRegionTracer::send_region_type_change(_hrm_index, |
275 | get_trace_type(), |
276 | to, |
277 | (uintptr_t)bottom(), |
278 | used()); |
279 | } |
280 | |
281 | void HeapRegion::note_self_forwarding_removal_start(bool during_concurrent_start, |
282 | bool during_conc_mark) { |
283 | // We always recreate the prev marking info and we'll explicitly |
284 | // mark all objects we find to be self-forwarded on the prev |
285 | // bitmap. So all objects need to be below PTAMS. |
286 | _prev_marked_bytes = 0; |
287 | |
288 | if (during_concurrent_start) { |
289 | // During concurrent start, we'll also explicitly mark all objects |
290 | // we find to be self-forwarded on the next bitmap. So all |
291 | // objects need to be below NTAMS. |
292 | _next_top_at_mark_start = top(); |
293 | _next_marked_bytes = 0; |
294 | } else if (during_conc_mark) { |
295 | // During concurrent mark, all objects in the CSet (including |
296 | // the ones we find to be self-forwarded) are implicitly live. |
297 | // So all objects need to be above NTAMS. |
298 | _next_top_at_mark_start = bottom(); |
299 | _next_marked_bytes = 0; |
300 | } |
301 | } |
302 | |
303 | void HeapRegion::note_self_forwarding_removal_end(size_t marked_bytes) { |
304 | assert(marked_bytes <= used(),do { if (!(marked_bytes <= used())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/heapRegion.cpp" , 305, "assert(" "marked_bytes <= used()" ") failed", "marked: " "%" "l" "u" " used: " "%" "l" "u", marked_bytes, used()); :: breakpoint(); } } while (0) |
305 | "marked: " SIZE_FORMAT " used: " SIZE_FORMAT, marked_bytes, used())do { if (!(marked_bytes <= used())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/heapRegion.cpp" , 305, "assert(" "marked_bytes <= used()" ") failed", "marked: " "%" "l" "u" " used: " "%" "l" "u", marked_bytes, used()); :: breakpoint(); } } while (0); |
306 | _prev_top_at_mark_start = top(); |
307 | _prev_marked_bytes = marked_bytes; |
308 | } |
309 | |
310 | // Code roots support |
311 | |
312 | void HeapRegion::add_strong_code_root(nmethod* nm) { |
313 | HeapRegionRemSet* hrrs = rem_set(); |
314 | hrrs->add_strong_code_root(nm); |
315 | } |
316 | |
317 | void HeapRegion::add_strong_code_root_locked(nmethod* nm) { |
318 | assert_locked_or_safepoint(CodeCache_lock); |
319 | HeapRegionRemSet* hrrs = rem_set(); |
320 | hrrs->add_strong_code_root_locked(nm); |
321 | } |
322 | |
323 | void HeapRegion::remove_strong_code_root(nmethod* nm) { |
324 | HeapRegionRemSet* hrrs = rem_set(); |
325 | hrrs->remove_strong_code_root(nm); |
326 | } |
327 | |
328 | void HeapRegion::strong_code_roots_do(CodeBlobClosure* blk) const { |
329 | HeapRegionRemSet* hrrs = rem_set(); |
330 | hrrs->strong_code_roots_do(blk); |
331 | } |
332 | |
333 | class VerifyStrongCodeRootOopClosure: public OopClosure { |
334 | const HeapRegion* _hr; |
335 | bool _failures; |
336 | bool _has_oops_in_region; |
337 | |
338 | template <class T> void do_oop_work(T* p) { |
339 | T heap_oop = RawAccess<>::oop_load(p); |
340 | if (!CompressedOops::is_null(heap_oop)) { |
341 | oop obj = CompressedOops::decode_not_null(heap_oop); |
342 | |
343 | // Note: not all the oops embedded in the nmethod are in the |
344 | // current region. We only look at those which are. |
345 | if (_hr->is_in(obj)) { |
346 | // Object is in the region. Check that its less than top |
347 | if (_hr->top() <= cast_from_oop<HeapWord*>(obj)) { |
348 | // Object is above top |
349 | log_error(gc, verify)(!(LogImpl<(LogTag::_gc), (LogTag::_verify), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Error))) ? (void)0 : LogImpl<(LogTag ::_gc), (LogTag::_verify), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Error>("Object " PTR_FORMAT"0x%016" "l" "x" " in region " HR_FORMAT"%u:(%s)[" "0x%016" "l" "x" "," "0x%016" "l" "x" "," "0x%016" "l" "x" "]" " is above top ", |
350 | p2i(obj), HR_FORMAT_PARAMS(_hr)(_hr)->hrm_index(), (_hr)->get_short_type_str(), p2i((_hr )->bottom()), p2i((_hr)->top()), p2i((_hr)->end())); |
351 | _failures = true; |
352 | return; |
353 | } |
354 | // Nmethod has at least one oop in the current region |
355 | _has_oops_in_region = true; |
356 | } |
357 | } |
358 | } |
359 | |
360 | public: |
361 | VerifyStrongCodeRootOopClosure(const HeapRegion* hr): |
362 | _hr(hr), _failures(false), _has_oops_in_region(false) {} |
363 | |
364 | void do_oop(narrowOop* p) { do_oop_work(p); } |
365 | void do_oop(oop* p) { do_oop_work(p); } |
366 | |
367 | bool failures() { return _failures; } |
368 | bool has_oops_in_region() { return _has_oops_in_region; } |
369 | }; |
370 | |
371 | class VerifyStrongCodeRootCodeBlobClosure: public CodeBlobClosure { |
372 | const HeapRegion* _hr; |
373 | bool _failures; |
374 | public: |
375 | VerifyStrongCodeRootCodeBlobClosure(const HeapRegion* hr) : |
376 | _hr(hr), _failures(false) {} |
377 | |
378 | void do_code_blob(CodeBlob* cb) { |
379 | nmethod* nm = (cb == NULL__null) ? NULL__null : cb->as_compiled_method()->as_nmethod_or_null(); |
380 | if (nm != NULL__null) { |
381 | // Verify that the nemthod is live |
382 | if (!nm->is_alive()) { |
383 | log_error(gc, verify)(!(LogImpl<(LogTag::_gc), (LogTag::_verify), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Error))) ? (void)0 : LogImpl<(LogTag ::_gc), (LogTag::_verify), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Error>("region [" PTR_FORMAT"0x%016" "l" "x" "," PTR_FORMAT"0x%016" "l" "x" "] has dead nmethod " PTR_FORMAT"0x%016" "l" "x" " in its strong code roots", |
384 | p2i(_hr->bottom()), p2i(_hr->end()), p2i(nm)); |
385 | _failures = true; |
386 | } else { |
387 | VerifyStrongCodeRootOopClosure oop_cl(_hr); |
388 | nm->oops_do(&oop_cl); |
389 | if (!oop_cl.has_oops_in_region()) { |
390 | log_error(gc, verify)(!(LogImpl<(LogTag::_gc), (LogTag::_verify), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Error))) ? (void)0 : LogImpl<(LogTag ::_gc), (LogTag::_verify), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Error>("region [" PTR_FORMAT"0x%016" "l" "x" "," PTR_FORMAT"0x%016" "l" "x" "] has nmethod " PTR_FORMAT"0x%016" "l" "x" " in its strong code roots with no pointers into region", |
391 | p2i(_hr->bottom()), p2i(_hr->end()), p2i(nm)); |
392 | _failures = true; |
393 | } else if (oop_cl.failures()) { |
394 | log_error(gc, verify)(!(LogImpl<(LogTag::_gc), (LogTag::_verify), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Error))) ? (void)0 : LogImpl<(LogTag ::_gc), (LogTag::_verify), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Error>("region [" PTR_FORMAT"0x%016" "l" "x" "," PTR_FORMAT"0x%016" "l" "x" "] has other failures for nmethod " PTR_FORMAT"0x%016" "l" "x", |
395 | p2i(_hr->bottom()), p2i(_hr->end()), p2i(nm)); |
396 | _failures = true; |
397 | } |
398 | } |
399 | } |
400 | } |
401 | |
402 | bool failures() { return _failures; } |
403 | }; |
404 | |
405 | void HeapRegion::verify_strong_code_roots(VerifyOption vo, bool* failures) const { |
406 | if (!G1VerifyHeapRegionCodeRoots) { |
407 | // We're not verifying code roots. |
408 | return; |
409 | } |
410 | if (vo == VerifyOption_G1UseFullMarking) { |
411 | // Marking verification during a full GC is performed after class |
412 | // unloading, code cache unloading, etc so the strong code roots |
413 | // attached to each heap region are in an inconsistent state. They won't |
414 | // be consistent until the strong code roots are rebuilt after the |
415 | // actual GC. Skip verifying the strong code roots in this particular |
416 | // time. |
417 | assert(VerifyDuringGC, "only way to get here")do { if (!(VerifyDuringGC)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/heapRegion.cpp" , 417, "assert(" "VerifyDuringGC" ") failed", "only way to get here" ); ::breakpoint(); } } while (0); |
418 | return; |
419 | } |
420 | |
421 | HeapRegionRemSet* hrrs = rem_set(); |
422 | size_t strong_code_roots_length = hrrs->strong_code_roots_list_length(); |
423 | |
424 | // if this region is empty then there should be no entries |
425 | // on its strong code root list |
426 | if (is_empty()) { |
427 | if (strong_code_roots_length > 0) { |
428 | log_error(gc, verify)(!(LogImpl<(LogTag::_gc), (LogTag::_verify), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Error))) ? (void)0 : LogImpl<(LogTag ::_gc), (LogTag::_verify), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Error>("region " HR_FORMAT"%u:(%s)[" "0x%016" "l" "x" "," "0x%016" "l" "x" "," "0x%016" "l" "x" "]" " is empty but has " SIZE_FORMAT"%" "l" "u" " code root entries", |
429 | HR_FORMAT_PARAMS(this)(this)->hrm_index(), (this)->get_short_type_str(), p2i( (this)->bottom()), p2i((this)->top()), p2i((this)->end ()), strong_code_roots_length); |
430 | *failures = true; |
431 | } |
432 | return; |
433 | } |
434 | |
435 | if (is_continues_humongous()) { |
436 | if (strong_code_roots_length > 0) { |
437 | log_error(gc, verify)(!(LogImpl<(LogTag::_gc), (LogTag::_verify), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Error))) ? (void)0 : LogImpl<(LogTag ::_gc), (LogTag::_verify), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Error>("region " HR_FORMAT"%u:(%s)[" "0x%016" "l" "x" "," "0x%016" "l" "x" "," "0x%016" "l" "x" "]" " is a continuation of a humongous region but has " SIZE_FORMAT"%" "l" "u" " code root entries", |
438 | HR_FORMAT_PARAMS(this)(this)->hrm_index(), (this)->get_short_type_str(), p2i( (this)->bottom()), p2i((this)->top()), p2i((this)->end ()), strong_code_roots_length); |
439 | *failures = true; |
440 | } |
441 | return; |
442 | } |
443 | |
444 | VerifyStrongCodeRootCodeBlobClosure cb_cl(this); |
445 | strong_code_roots_do(&cb_cl); |
446 | |
447 | if (cb_cl.failures()) { |
448 | *failures = true; |
449 | } |
450 | } |
451 | |
452 | void HeapRegion::print() const { print_on(tty); } |
453 | |
454 | void HeapRegion::print_on(outputStream* st) const { |
455 | st->print("|%4u", this->_hrm_index); |
456 | st->print("|" PTR_FORMAT"0x%016" "l" "x" ", " PTR_FORMAT"0x%016" "l" "x" ", " PTR_FORMAT"0x%016" "l" "x", |
457 | p2i(bottom()), p2i(top()), p2i(end())); |
458 | st->print("|%3d%%", (int) ((double) used() * 100 / capacity())); |
459 | st->print("|%2s", get_short_type_str()); |
460 | if (in_collection_set()) { |
461 | st->print("|CS"); |
462 | } else { |
463 | st->print("| "); |
464 | } |
465 | st->print("|TAMS " PTR_FORMAT"0x%016" "l" "x" ", " PTR_FORMAT"0x%016" "l" "x" "| %s ", |
466 | p2i(prev_top_at_mark_start()), p2i(next_top_at_mark_start()), rem_set()->get_state_str()); |
467 | if (UseNUMA) { |
468 | G1NUMA* numa = G1NUMA::numa(); |
469 | if (node_index() < numa->num_active_nodes()) { |
470 | st->print("|%d", numa->numa_id(node_index())); |
471 | } else { |
472 | st->print("|-"); |
473 | } |
474 | } |
475 | st->print_cr(""); |
476 | } |
477 | |
478 | class G1VerificationClosure : public BasicOopIterateClosure { |
479 | protected: |
480 | G1CollectedHeap* _g1h; |
481 | G1CardTable *_ct; |
482 | oop _containing_obj; |
483 | bool _failures; |
484 | int _n_failures; |
485 | VerifyOption _vo; |
486 | public: |
487 | // _vo == UsePrevMarking -> use "prev" marking information, |
488 | // _vo == UseNextMarking -> use "next" marking information, |
489 | // _vo == UseFullMarking -> use "next" marking bitmap but no TAMS. |
490 | G1VerificationClosure(G1CollectedHeap* g1h, VerifyOption vo) : |
491 | _g1h(g1h), _ct(g1h->card_table()), |
492 | _containing_obj(NULL__null), _failures(false), _n_failures(0), _vo(vo) { |
493 | } |
494 | |
495 | void set_containing_obj(oop obj) { |
496 | _containing_obj = obj; |
497 | } |
498 | |
499 | bool failures() { return _failures; } |
500 | int n_failures() { return _n_failures; } |
501 | |
502 | void print_object(outputStream* out, oop obj) { |
503 | #ifdef PRODUCT |
504 | Klass* k = obj->klass(); |
505 | const char* class_name = k->external_name(); |
506 | out->print_cr("class name %s", class_name); |
507 | #else // PRODUCT |
508 | obj->print_on(out); |
509 | #endif // PRODUCT |
510 | } |
511 | }; |
512 | |
513 | class VerifyLiveClosure : public G1VerificationClosure { |
514 | public: |
515 | VerifyLiveClosure(G1CollectedHeap* g1h, VerifyOption vo) : G1VerificationClosure(g1h, vo) {} |
516 | virtual void do_oop(narrowOop* p) { do_oop_work(p); } |
517 | virtual void do_oop(oop* p) { do_oop_work(p); } |
518 | |
519 | template <class T> |
520 | void do_oop_work(T* p) { |
521 | assert(_containing_obj != NULL, "Precondition")do { if (!(_containing_obj != __null)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/heapRegion.cpp" , 521, "assert(" "_containing_obj != __null" ") failed", "Precondition" ); ::breakpoint(); } } while (0); |
522 | assert(!_g1h->is_obj_dead_cond(_containing_obj, _vo),do { if (!(!_g1h->is_obj_dead_cond(_containing_obj, _vo))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/heapRegion.cpp" , 523, "assert(" "!_g1h->is_obj_dead_cond(_containing_obj, _vo)" ") failed", "Precondition"); ::breakpoint(); } } while (0) |
523 | "Precondition")do { if (!(!_g1h->is_obj_dead_cond(_containing_obj, _vo))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/heapRegion.cpp" , 523, "assert(" "!_g1h->is_obj_dead_cond(_containing_obj, _vo)" ") failed", "Precondition"); ::breakpoint(); } } while (0); |
524 | verify_liveness(p); |
525 | } |
526 | |
527 | template <class T> |
528 | void verify_liveness(T* p) { |
529 | T heap_oop = RawAccess<>::oop_load(p); |
530 | Log(gc, verify)LogImpl<(LogTag::_gc), (LogTag::_verify), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) > log; |
531 | if (!CompressedOops::is_null(heap_oop)) { |
532 | oop obj = CompressedOops::decode_not_null(heap_oop); |
533 | bool failed = false; |
534 | if (!_g1h->is_in(obj) || _g1h->is_obj_dead_cond(obj, _vo)) { |
535 | MutexLocker x(ParGCRareEvent_lock, |
536 | Mutex::_no_safepoint_check_flag); |
537 | |
538 | if (!_failures) { |
539 | log.error("----------"); |
540 | } |
541 | ResourceMark rm; |
542 | if (!_g1h->is_in(obj)) { |
543 | HeapRegion* from = _g1h->heap_region_containing((HeapWord*)p); |
544 | log.error("Field " PTR_FORMAT"0x%016" "l" "x" " of live obj " PTR_FORMAT"0x%016" "l" "x" " in region " HR_FORMAT"%u:(%s)[" "0x%016" "l" "x" "," "0x%016" "l" "x" "," "0x%016" "l" "x" "]", |
545 | p2i(p), p2i(_containing_obj), HR_FORMAT_PARAMS(from)(from)->hrm_index(), (from)->get_short_type_str(), p2i( (from)->bottom()), p2i((from)->top()), p2i((from)->end ())); |
546 | LogStream ls(log.error()); |
547 | print_object(&ls, _containing_obj); |
548 | HeapRegion* const to = _g1h->heap_region_containing(obj); |
549 | log.error("points to obj " PTR_FORMAT"0x%016" "l" "x" " in region " HR_FORMAT"%u:(%s)[" "0x%016" "l" "x" "," "0x%016" "l" "x" "," "0x%016" "l" "x" "]" " remset %s", |
550 | p2i(obj), HR_FORMAT_PARAMS(to)(to)->hrm_index(), (to)->get_short_type_str(), p2i((to) ->bottom()), p2i((to)->top()), p2i((to)->end()), to->rem_set()->get_state_str()); |
551 | } else { |
552 | HeapRegion* from = _g1h->heap_region_containing((HeapWord*)p); |
553 | HeapRegion* to = _g1h->heap_region_containing(obj); |
554 | log.error("Field " PTR_FORMAT"0x%016" "l" "x" " of live obj " PTR_FORMAT"0x%016" "l" "x" " in region " HR_FORMAT"%u:(%s)[" "0x%016" "l" "x" "," "0x%016" "l" "x" "," "0x%016" "l" "x" "]", |
555 | p2i(p), p2i(_containing_obj), HR_FORMAT_PARAMS(from)(from)->hrm_index(), (from)->get_short_type_str(), p2i( (from)->bottom()), p2i((from)->top()), p2i((from)->end ())); |
556 | LogStream ls(log.error()); |
557 | print_object(&ls, _containing_obj); |
558 | log.error("points to dead obj " PTR_FORMAT"0x%016" "l" "x" " in region " HR_FORMAT"%u:(%s)[" "0x%016" "l" "x" "," "0x%016" "l" "x" "," "0x%016" "l" "x" "]", |
559 | p2i(obj), HR_FORMAT_PARAMS(to)(to)->hrm_index(), (to)->get_short_type_str(), p2i((to) ->bottom()), p2i((to)->top()), p2i((to)->end())); |
560 | print_object(&ls, obj); |
561 | } |
562 | log.error("----------"); |
563 | _failures = true; |
564 | failed = true; |
565 | _n_failures++; |
566 | } |
567 | } |
568 | } |
569 | }; |
570 | |
571 | class VerifyRemSetClosure : public G1VerificationClosure { |
572 | public: |
573 | VerifyRemSetClosure(G1CollectedHeap* g1h, VerifyOption vo) : G1VerificationClosure(g1h, vo) {} |
574 | virtual void do_oop(narrowOop* p) { do_oop_work(p); } |
575 | virtual void do_oop(oop* p) { do_oop_work(p); } |
576 | |
577 | template <class T> |
578 | void do_oop_work(T* p) { |
579 | assert(_containing_obj != NULL, "Precondition")do { if (!(_containing_obj != __null)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/heapRegion.cpp" , 579, "assert(" "_containing_obj != __null" ") failed", "Precondition" ); ::breakpoint(); } } while (0); |
580 | assert(!_g1h->is_obj_dead_cond(_containing_obj, _vo),do { if (!(!_g1h->is_obj_dead_cond(_containing_obj, _vo))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/heapRegion.cpp" , 581, "assert(" "!_g1h->is_obj_dead_cond(_containing_obj, _vo)" ") failed", "Precondition"); ::breakpoint(); } } while (0) |
581 | "Precondition")do { if (!(!_g1h->is_obj_dead_cond(_containing_obj, _vo))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/heapRegion.cpp" , 581, "assert(" "!_g1h->is_obj_dead_cond(_containing_obj, _vo)" ") failed", "Precondition"); ::breakpoint(); } } while (0); |
582 | verify_remembered_set(p); |
583 | } |
584 | |
585 | template <class T> |
586 | void verify_remembered_set(T* p) { |
587 | T heap_oop = RawAccess<>::oop_load(p); |
588 | Log(gc, verify)LogImpl<(LogTag::_gc), (LogTag::_verify), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) > log; |
589 | if (!CompressedOops::is_null(heap_oop)) { |
590 | oop obj = CompressedOops::decode_not_null(heap_oop); |
591 | HeapRegion* from = _g1h->heap_region_containing((HeapWord*)p); |
592 | HeapRegion* to = _g1h->heap_region_containing(obj); |
593 | if (from != NULL__null && to != NULL__null && |
594 | from != to && |
595 | !to->is_pinned() && |
596 | to->rem_set()->is_complete()) { |
597 | jbyte cv_obj = *_ct->byte_for_const(_containing_obj); |
598 | jbyte cv_field = *_ct->byte_for_const(p); |
599 | const jbyte dirty = G1CardTable::dirty_card_val(); |
600 | |
601 | bool is_bad = !(from->is_young() |
602 | || to->rem_set()->contains_reference(p) |
603 | || (_containing_obj->is_objArray() ? |
604 | cv_field == dirty : |
605 | cv_obj == dirty || cv_field == dirty)); |
606 | if (is_bad) { |
607 | MutexLocker x(ParGCRareEvent_lock, |
608 | Mutex::_no_safepoint_check_flag); |
609 | |
610 | if (!_failures) { |
611 | log.error("----------"); |
612 | } |
613 | log.error("Missing rem set entry:"); |
614 | log.error("Field " PTR_FORMAT"0x%016" "l" "x" " of obj " PTR_FORMAT"0x%016" "l" "x" " in region " HR_FORMAT"%u:(%s)[" "0x%016" "l" "x" "," "0x%016" "l" "x" "," "0x%016" "l" "x" "]", |
615 | p2i(p), p2i(_containing_obj), HR_FORMAT_PARAMS(from)(from)->hrm_index(), (from)->get_short_type_str(), p2i( (from)->bottom()), p2i((from)->top()), p2i((from)->end ())); |
616 | ResourceMark rm; |
617 | LogStream ls(log.error()); |
618 | _containing_obj->print_on(&ls); |
619 | log.error("points to obj " PTR_FORMAT"0x%016" "l" "x" " in region " HR_FORMAT"%u:(%s)[" "0x%016" "l" "x" "," "0x%016" "l" "x" "," "0x%016" "l" "x" "]" " remset %s", |
620 | p2i(obj), HR_FORMAT_PARAMS(to)(to)->hrm_index(), (to)->get_short_type_str(), p2i((to) ->bottom()), p2i((to)->top()), p2i((to)->end()), to->rem_set()->get_state_str()); |
621 | if (oopDesc::is_oop(obj)) { |
622 | obj->print_on(&ls); |
623 | } |
624 | log.error("Obj head CTE = %d, field CTE = %d.", cv_obj, cv_field); |
625 | log.error("----------"); |
626 | _failures = true; |
627 | _n_failures++; |
628 | } |
629 | } |
630 | } |
631 | } |
632 | }; |
633 | |
634 | // Closure that applies the given two closures in sequence. |
635 | class G1Mux2Closure : public BasicOopIterateClosure { |
636 | OopClosure* _c1; |
637 | OopClosure* _c2; |
638 | public: |
639 | G1Mux2Closure(OopClosure *c1, OopClosure *c2) { _c1 = c1; _c2 = c2; } |
640 | template <class T> inline void do_oop_work(T* p) { |
641 | // Apply first closure; then apply the second. |
642 | _c1->do_oop(p); |
643 | _c2->do_oop(p); |
644 | } |
645 | virtual inline void do_oop(oop* p) { do_oop_work(p); } |
646 | virtual inline void do_oop(narrowOop* p) { do_oop_work(p); } |
647 | }; |
648 | |
649 | void HeapRegion::verify(VerifyOption vo, |
650 | bool* failures) const { |
651 | G1CollectedHeap* g1h = G1CollectedHeap::heap(); |
652 | *failures = false; |
653 | HeapWord* p = bottom(); |
654 | HeapWord* prev_p = NULL__null; |
655 | VerifyLiveClosure vl_cl(g1h, vo); |
656 | VerifyRemSetClosure vr_cl(g1h, vo); |
657 | bool is_region_humongous = is_humongous(); |
658 | // We cast p to an oop, so region-bottom must be an obj-start. |
659 | assert(!is_region_humongous || is_starts_humongous(), "invariant")do { if (!(!is_region_humongous || is_starts_humongous())) { ( *g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/heapRegion.cpp" , 659, "assert(" "!is_region_humongous || is_starts_humongous()" ") failed", "invariant"); ::breakpoint(); } } while (0); |
660 | size_t object_num = 0; |
661 | while (p < top()) { |
662 | oop obj = cast_to_oop(p); |
663 | size_t obj_size = block_size(p); |
664 | object_num += 1; |
665 | |
666 | if (!g1h->is_obj_dead_cond(obj, this, vo)) { |
667 | if (oopDesc::is_oop(obj)) { |
668 | Klass* klass = obj->klass(); |
669 | bool is_metaspace_object = Metaspace::contains(klass); |
670 | if (!is_metaspace_object) { |
671 | log_error(gc, verify)(!(LogImpl<(LogTag::_gc), (LogTag::_verify), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Error))) ? (void)0 : LogImpl<(LogTag ::_gc), (LogTag::_verify), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Error>("klass " PTR_FORMAT"0x%016" "l" "x" " of object " PTR_FORMAT"0x%016" "l" "x" " " |
672 | "not metadata", p2i(klass), p2i(obj)); |
673 | *failures = true; |
674 | return; |
675 | } else if (!klass->is_klass()) { |
676 | log_error(gc, verify)(!(LogImpl<(LogTag::_gc), (LogTag::_verify), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Error))) ? (void)0 : LogImpl<(LogTag ::_gc), (LogTag::_verify), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Error>("klass " PTR_FORMAT"0x%016" "l" "x" " of object " PTR_FORMAT"0x%016" "l" "x" " " |
677 | "not a klass", p2i(klass), p2i(obj)); |
678 | *failures = true; |
679 | return; |
680 | } else { |
681 | vl_cl.set_containing_obj(obj); |
682 | if (!g1h->collector_state()->in_full_gc() || G1VerifyRSetsDuringFullGC) { |
683 | // verify liveness and rem_set |
684 | vr_cl.set_containing_obj(obj); |
685 | G1Mux2Closure mux(&vl_cl, &vr_cl); |
686 | obj->oop_iterate(&mux); |
687 | |
688 | if (vr_cl.failures()) { |
689 | *failures = true; |
690 | } |
691 | if (G1MaxVerifyFailures >= 0 && |
692 | vr_cl.n_failures() >= G1MaxVerifyFailures) { |
693 | return; |
694 | } |
695 | } else { |
696 | // verify only liveness |
697 | obj->oop_iterate(&vl_cl); |
698 | } |
699 | if (vl_cl.failures()) { |
700 | *failures = true; |
701 | } |
702 | if (G1MaxVerifyFailures >= 0 && |
703 | vl_cl.n_failures() >= G1MaxVerifyFailures) { |
704 | return; |
705 | } |
706 | } |
707 | } else { |
708 | log_error(gc, verify)(!(LogImpl<(LogTag::_gc), (LogTag::_verify), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Error))) ? (void)0 : LogImpl<(LogTag ::_gc), (LogTag::_verify), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Error>(PTR_FORMAT"0x%016" "l" "x" " not an oop", p2i(obj)); |
709 | *failures = true; |
710 | return; |
711 | } |
712 | } |
713 | prev_p = p; |
Value stored to 'prev_p' is never read | |
714 | p += obj_size; |
715 | } |
716 | |
717 | // Only regions in old generation contain valid BOT. |
718 | if (!is_empty() && !is_young()) { |
719 | _bot_part.verify(); |
720 | } |
721 | |
722 | if (is_region_humongous) { |
723 | oop obj = cast_to_oop(this->humongous_start_region()->bottom()); |
724 | if (cast_from_oop<HeapWord*>(obj) > bottom() || cast_from_oop<HeapWord*>(obj) + obj->size() < bottom()) { |
725 | log_error(gc, verify)(!(LogImpl<(LogTag::_gc), (LogTag::_verify), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Error))) ? (void)0 : LogImpl<(LogTag ::_gc), (LogTag::_verify), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Error>("this humongous region is not part of its' humongous object " PTR_FORMAT"0x%016" "l" "x", p2i(obj)); |
726 | *failures = true; |
727 | return; |
728 | } |
729 | } |
730 | |
731 | if (!is_region_humongous && p != top()) { |
732 | log_error(gc, verify)(!(LogImpl<(LogTag::_gc), (LogTag::_verify), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Error))) ? (void)0 : LogImpl<(LogTag ::_gc), (LogTag::_verify), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Error>("end of last object " PTR_FORMAT"0x%016" "l" "x" " " |
733 | "does not match top " PTR_FORMAT"0x%016" "l" "x", p2i(p), p2i(top())); |
734 | *failures = true; |
735 | return; |
736 | } |
737 | |
738 | verify_strong_code_roots(vo, failures); |
739 | } |
740 | |
741 | void HeapRegion::verify_rem_set(VerifyOption vo, bool* failures) const { |
742 | G1CollectedHeap* g1h = G1CollectedHeap::heap(); |
743 | *failures = false; |
744 | HeapWord* p = bottom(); |
745 | HeapWord* prev_p = NULL__null; |
746 | VerifyRemSetClosure vr_cl(g1h, vo); |
747 | while (p < top()) { |
748 | oop obj = cast_to_oop(p); |
749 | size_t obj_size = block_size(p); |
750 | |
751 | if (!g1h->is_obj_dead_cond(obj, this, vo)) { |
752 | if (oopDesc::is_oop(obj)) { |
753 | vr_cl.set_containing_obj(obj); |
754 | obj->oop_iterate(&vr_cl); |
755 | |
756 | if (vr_cl.failures()) { |
757 | *failures = true; |
758 | } |
759 | if (G1MaxVerifyFailures >= 0 && |
760 | vr_cl.n_failures() >= G1MaxVerifyFailures) { |
761 | return; |
762 | } |
763 | } else { |
764 | log_error(gc, verify)(!(LogImpl<(LogTag::_gc), (LogTag::_verify), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Error))) ? (void)0 : LogImpl<(LogTag ::_gc), (LogTag::_verify), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Error>(PTR_FORMAT"0x%016" "l" "x" " not an oop", p2i(obj)); |
765 | *failures = true; |
766 | return; |
767 | } |
768 | } |
769 | |
770 | prev_p = p; |
771 | p += obj_size; |
772 | } |
773 | } |
774 | |
775 | void HeapRegion::verify_rem_set() const { |
776 | bool failures = false; |
777 | verify_rem_set(VerifyOption_G1UsePrevMarking, &failures); |
778 | guarantee(!failures, "HeapRegion RemSet verification failed")do { if (!(!failures)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/g1/heapRegion.cpp" , 778, "guarantee(" "!failures" ") failed", "HeapRegion RemSet verification failed" ); ::breakpoint(); } } while (0); |
779 | } |
780 | |
781 | void HeapRegion::clear(bool mangle_space) { |
782 | set_top(bottom()); |
783 | set_compaction_top(bottom()); |
784 | |
785 | if (ZapUnusedHeapArea && mangle_space) { |
786 | mangle_unused_area(); |
787 | } |
788 | reset_bot(); |
789 | } |
790 | |
791 | #ifndef PRODUCT |
792 | void HeapRegion::mangle_unused_area() { |
793 | SpaceMangler::mangle_region(MemRegion(top(), end())); |
794 | } |
795 | #endif |
796 | |
797 | void HeapRegion::initialize_bot_threshold() { |
798 | _bot_part.initialize_threshold(); |
799 | } |
800 | |
801 | void HeapRegion::alloc_block_in_bot(HeapWord* start, HeapWord* end) { |
802 | _bot_part.alloc_block(start, end); |
803 | } |
804 | |
805 | void HeapRegion::object_iterate(ObjectClosure* blk) { |
806 | HeapWord* p = bottom(); |
807 | while (p < top()) { |
808 | if (block_is_obj(p)) { |
809 | blk->do_object(cast_to_oop(p)); |
810 | } |
811 | p += block_size(p); |
812 | } |
813 | } |
814 | |
815 | void HeapRegion::fill_with_dummy_object(HeapWord* address, size_t word_size, bool zap) { |
816 | // Keep the BOT in sync for old generation regions. |
817 | if (is_old()) { |
818 | update_bot_at(address, word_size); |
819 | } |
820 | // Fill in the object. |
821 | CollectedHeap::fill_with_object(address, word_size, zap); |
822 | } |