annotate src/share/vm/gc_implementation/parNew/parCardTableModRefBS.cpp @ 3762:5c0a3c1858b1

7048782: CMS: assert(last_chunk_index_to_check<= last_chunk_index) failed: parCardTableModRefBS.cpp:359 Summary: The LNC array is sized before the start of a scavenge, while the heap may expand during a scavenge. With CMS, the last block of an arbitrary suffice of the LNC array may expand due to coalition with the expansion delta. We now take care not to attempt access past the end of the LNC array. LNC array code will be cleaned up and suitably encapsulated as part of the forthcoming performance RFE 7043675. Reviewed-by: brutisso
author ysr
date Thu, 02 Jun 2011 10:23:36 -0700
parents 7d64aa23eb96
children 3be7439273c5
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
3256
c69b1043dfb1 7036482: clear argument is redundant and unused in cardtable methods
ysr
parents: 1972
diff changeset
2 * Copyright (c) 2007, 2011 Oracle and/or its affiliates. All rights reserved.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
a61af66fc99e Initial load
duke
parents:
diff changeset
4 *
a61af66fc99e Initial load
duke
parents:
diff changeset
5 * This code is free software; you can redistribute it and/or modify it
a61af66fc99e Initial load
duke
parents:
diff changeset
6 * under the terms of the GNU General Public License version 2 only, as
a61af66fc99e Initial load
duke
parents:
diff changeset
7 * published by the Free Software Foundation.
a61af66fc99e Initial load
duke
parents:
diff changeset
8 *
a61af66fc99e Initial load
duke
parents:
diff changeset
9 * This code is distributed in the hope that it will be useful, but WITHOUT
a61af66fc99e Initial load
duke
parents:
diff changeset
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
a61af66fc99e Initial load
duke
parents:
diff changeset
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a61af66fc99e Initial load
duke
parents:
diff changeset
12 * version 2 for more details (a copy is included in the LICENSE file that
a61af66fc99e Initial load
duke
parents:
diff changeset
13 * accompanied this code).
a61af66fc99e Initial load
duke
parents:
diff changeset
14 *
a61af66fc99e Initial load
duke
parents:
diff changeset
15 * You should have received a copy of the GNU General Public License version
a61af66fc99e Initial load
duke
parents:
diff changeset
16 * 2 along with this work; if not, write to the Free Software Foundation,
a61af66fc99e Initial load
duke
parents:
diff changeset
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
a61af66fc99e Initial load
duke
parents:
diff changeset
18 *
1552
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 845
diff changeset
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 845
diff changeset
20 * or visit www.oracle.com if you need additional information or have any
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 845
diff changeset
21 * questions.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
22 *
a61af66fc99e Initial load
duke
parents:
diff changeset
23 */
a61af66fc99e Initial load
duke
parents:
diff changeset
24
1972
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1833
diff changeset
25 #include "precompiled.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1833
diff changeset
26 #include "memory/allocation.inline.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1833
diff changeset
27 #include "memory/cardTableModRefBS.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1833
diff changeset
28 #include "memory/cardTableRS.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1833
diff changeset
29 #include "memory/sharedHeap.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1833
diff changeset
30 #include "memory/space.inline.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1833
diff changeset
31 #include "memory/universe.hpp"
3357
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
32 #include "oops/oop.inline.hpp"
1972
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1833
diff changeset
33 #include "runtime/java.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1833
diff changeset
34 #include "runtime/mutexLocker.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1833
diff changeset
35 #include "runtime/virtualspace.hpp"
0
a61af66fc99e Initial load
duke
parents:
diff changeset
36
3287
c48ad6ab8bdf 7037276: Unnecessary double traversal of dirty card windows
ysr
parents: 3256
diff changeset
37 void CardTableModRefBS::non_clean_card_iterate_parallel_work(Space* sp, MemRegion mr,
3357
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
38 OopsInGenClosure* cl,
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
39 CardTableRS* ct,
3287
c48ad6ab8bdf 7037276: Unnecessary double traversal of dirty card windows
ysr
parents: 3256
diff changeset
40 int n_threads) {
c48ad6ab8bdf 7037276: Unnecessary double traversal of dirty card windows
ysr
parents: 3256
diff changeset
41 assert(n_threads > 0, "Error: expected n_threads > 0");
c48ad6ab8bdf 7037276: Unnecessary double traversal of dirty card windows
ysr
parents: 3256
diff changeset
42 assert((n_threads == 1 && ParallelGCThreads == 0) ||
c48ad6ab8bdf 7037276: Unnecessary double traversal of dirty card windows
ysr
parents: 3256
diff changeset
43 n_threads <= (int)ParallelGCThreads,
c48ad6ab8bdf 7037276: Unnecessary double traversal of dirty card windows
ysr
parents: 3256
diff changeset
44 "# worker threads != # requested!");
c48ad6ab8bdf 7037276: Unnecessary double traversal of dirty card windows
ysr
parents: 3256
diff changeset
45 // Make sure the LNC array is valid for the space.
c48ad6ab8bdf 7037276: Unnecessary double traversal of dirty card windows
ysr
parents: 3256
diff changeset
46 jbyte** lowest_non_clean;
c48ad6ab8bdf 7037276: Unnecessary double traversal of dirty card windows
ysr
parents: 3256
diff changeset
47 uintptr_t lowest_non_clean_base_chunk_index;
c48ad6ab8bdf 7037276: Unnecessary double traversal of dirty card windows
ysr
parents: 3256
diff changeset
48 size_t lowest_non_clean_chunk_size;
c48ad6ab8bdf 7037276: Unnecessary double traversal of dirty card windows
ysr
parents: 3256
diff changeset
49 get_LNC_array_for_space(sp, lowest_non_clean,
c48ad6ab8bdf 7037276: Unnecessary double traversal of dirty card windows
ysr
parents: 3256
diff changeset
50 lowest_non_clean_base_chunk_index,
c48ad6ab8bdf 7037276: Unnecessary double traversal of dirty card windows
ysr
parents: 3256
diff changeset
51 lowest_non_clean_chunk_size);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
52
3357
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
53 int n_strides = n_threads * ParGCStridesPerThread;
3287
c48ad6ab8bdf 7037276: Unnecessary double traversal of dirty card windows
ysr
parents: 3256
diff changeset
54 SequentialSubTasksDone* pst = sp->par_seq_tasks();
c48ad6ab8bdf 7037276: Unnecessary double traversal of dirty card windows
ysr
parents: 3256
diff changeset
55 pst->set_n_threads(n_threads);
c48ad6ab8bdf 7037276: Unnecessary double traversal of dirty card windows
ysr
parents: 3256
diff changeset
56 pst->set_n_tasks(n_strides);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
57
3287
c48ad6ab8bdf 7037276: Unnecessary double traversal of dirty card windows
ysr
parents: 3256
diff changeset
58 int stride = 0;
c48ad6ab8bdf 7037276: Unnecessary double traversal of dirty card windows
ysr
parents: 3256
diff changeset
59 while (!pst->is_task_claimed(/* reference */ stride)) {
3357
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
60 process_stride(sp, mr, stride, n_strides, cl, ct,
3287
c48ad6ab8bdf 7037276: Unnecessary double traversal of dirty card windows
ysr
parents: 3256
diff changeset
61 lowest_non_clean,
c48ad6ab8bdf 7037276: Unnecessary double traversal of dirty card windows
ysr
parents: 3256
diff changeset
62 lowest_non_clean_base_chunk_index,
c48ad6ab8bdf 7037276: Unnecessary double traversal of dirty card windows
ysr
parents: 3256
diff changeset
63 lowest_non_clean_chunk_size);
c48ad6ab8bdf 7037276: Unnecessary double traversal of dirty card windows
ysr
parents: 3256
diff changeset
64 }
c48ad6ab8bdf 7037276: Unnecessary double traversal of dirty card windows
ysr
parents: 3256
diff changeset
65 if (pst->all_tasks_completed()) {
c48ad6ab8bdf 7037276: Unnecessary double traversal of dirty card windows
ysr
parents: 3256
diff changeset
66 // Clear lowest_non_clean array for next time.
c48ad6ab8bdf 7037276: Unnecessary double traversal of dirty card windows
ysr
parents: 3256
diff changeset
67 intptr_t first_chunk_index = addr_to_chunk_index(mr.start());
c48ad6ab8bdf 7037276: Unnecessary double traversal of dirty card windows
ysr
parents: 3256
diff changeset
68 uintptr_t last_chunk_index = addr_to_chunk_index(mr.last());
c48ad6ab8bdf 7037276: Unnecessary double traversal of dirty card windows
ysr
parents: 3256
diff changeset
69 for (uintptr_t ch = first_chunk_index; ch <= last_chunk_index; ch++) {
c48ad6ab8bdf 7037276: Unnecessary double traversal of dirty card windows
ysr
parents: 3256
diff changeset
70 intptr_t ind = ch - lowest_non_clean_base_chunk_index;
c48ad6ab8bdf 7037276: Unnecessary double traversal of dirty card windows
ysr
parents: 3256
diff changeset
71 assert(0 <= ind && ind < (intptr_t)lowest_non_clean_chunk_size,
c48ad6ab8bdf 7037276: Unnecessary double traversal of dirty card windows
ysr
parents: 3256
diff changeset
72 "Bounds error");
c48ad6ab8bdf 7037276: Unnecessary double traversal of dirty card windows
ysr
parents: 3256
diff changeset
73 lowest_non_clean[ind] = NULL;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
74 }
a61af66fc99e Initial load
duke
parents:
diff changeset
75 }
a61af66fc99e Initial load
duke
parents:
diff changeset
76 }
a61af66fc99e Initial load
duke
parents:
diff changeset
77
a61af66fc99e Initial load
duke
parents:
diff changeset
78 void
a61af66fc99e Initial load
duke
parents:
diff changeset
79 CardTableModRefBS::
a61af66fc99e Initial load
duke
parents:
diff changeset
80 process_stride(Space* sp,
a61af66fc99e Initial load
duke
parents:
diff changeset
81 MemRegion used,
a61af66fc99e Initial load
duke
parents:
diff changeset
82 jint stride, int n_strides,
3357
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
83 OopsInGenClosure* cl,
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
84 CardTableRS* ct,
0
a61af66fc99e Initial load
duke
parents:
diff changeset
85 jbyte** lowest_non_clean,
a61af66fc99e Initial load
duke
parents:
diff changeset
86 uintptr_t lowest_non_clean_base_chunk_index,
a61af66fc99e Initial load
duke
parents:
diff changeset
87 size_t lowest_non_clean_chunk_size) {
3357
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
88 // We go from higher to lower addresses here; it wouldn't help that much
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
89 // because of the strided parallelism pattern used here.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
90
a61af66fc99e Initial load
duke
parents:
diff changeset
91 // Find the first card address of the first chunk in the stride that is
a61af66fc99e Initial load
duke
parents:
diff changeset
92 // at least "bottom" of the used region.
a61af66fc99e Initial load
duke
parents:
diff changeset
93 jbyte* start_card = byte_for(used.start());
a61af66fc99e Initial load
duke
parents:
diff changeset
94 jbyte* end_card = byte_after(used.last());
a61af66fc99e Initial load
duke
parents:
diff changeset
95 uintptr_t start_chunk = addr_to_chunk_index(used.start());
a61af66fc99e Initial load
duke
parents:
diff changeset
96 uintptr_t start_chunk_stride_num = start_chunk % n_strides;
a61af66fc99e Initial load
duke
parents:
diff changeset
97 jbyte* chunk_card_start;
a61af66fc99e Initial load
duke
parents:
diff changeset
98
a61af66fc99e Initial load
duke
parents:
diff changeset
99 if ((uintptr_t)stride >= start_chunk_stride_num) {
a61af66fc99e Initial load
duke
parents:
diff changeset
100 chunk_card_start = (jbyte*)(start_card +
a61af66fc99e Initial load
duke
parents:
diff changeset
101 (stride - start_chunk_stride_num) *
3357
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
102 ParGCCardsPerStrideChunk);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
103 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
104 // Go ahead to the next chunk group boundary, then to the requested stride.
a61af66fc99e Initial load
duke
parents:
diff changeset
105 chunk_card_start = (jbyte*)(start_card +
a61af66fc99e Initial load
duke
parents:
diff changeset
106 (n_strides - start_chunk_stride_num + stride) *
3357
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
107 ParGCCardsPerStrideChunk);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
108 }
a61af66fc99e Initial load
duke
parents:
diff changeset
109
a61af66fc99e Initial load
duke
parents:
diff changeset
110 while (chunk_card_start < end_card) {
3357
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
111 // Even though we go from lower to higher addresses below, the
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
112 // strided parallelism can interleave the actual processing of the
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
113 // dirty pages in various ways. For a specific chunk within this
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
114 // stride, we take care to avoid double scanning or missing a card
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
115 // by suitably initializing the "min_done" field in process_chunk_boundaries()
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
116 // below, together with the dirty region extension accomplished in
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
117 // DirtyCardToOopClosure::do_MemRegion().
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
118 jbyte* chunk_card_end = chunk_card_start + ParGCCardsPerStrideChunk;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
119 // Invariant: chunk_mr should be fully contained within the "used" region.
a61af66fc99e Initial load
duke
parents:
diff changeset
120 MemRegion chunk_mr = MemRegion(addr_for(chunk_card_start),
a61af66fc99e Initial load
duke
parents:
diff changeset
121 chunk_card_end >= end_card ?
a61af66fc99e Initial load
duke
parents:
diff changeset
122 used.end() : addr_for(chunk_card_end));
a61af66fc99e Initial load
duke
parents:
diff changeset
123 assert(chunk_mr.word_size() > 0, "[chunk_card_start > used_end)");
a61af66fc99e Initial load
duke
parents:
diff changeset
124 assert(used.contains(chunk_mr), "chunk_mr should be subset of used");
a61af66fc99e Initial load
duke
parents:
diff changeset
125
3357
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
126 DirtyCardToOopClosure* dcto_cl = sp->new_dcto_cl(cl, precision(),
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
127 cl->gen_boundary());
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
128 ClearNoncleanCardWrapper clear_cl(dcto_cl, ct);
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
129
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
130
0
a61af66fc99e Initial load
duke
parents:
diff changeset
131 // Process the chunk.
a61af66fc99e Initial load
duke
parents:
diff changeset
132 process_chunk_boundaries(sp,
a61af66fc99e Initial load
duke
parents:
diff changeset
133 dcto_cl,
a61af66fc99e Initial load
duke
parents:
diff changeset
134 chunk_mr,
a61af66fc99e Initial load
duke
parents:
diff changeset
135 used,
a61af66fc99e Initial load
duke
parents:
diff changeset
136 lowest_non_clean,
a61af66fc99e Initial load
duke
parents:
diff changeset
137 lowest_non_clean_base_chunk_index,
a61af66fc99e Initial load
duke
parents:
diff changeset
138 lowest_non_clean_chunk_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
139
3357
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
140 // We want the LNC array updates above in process_chunk_boundaries
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
141 // to be visible before any of the card table value changes as a
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
142 // result of the dirty card iteration below.
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
143 OrderAccess::storestore();
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
144
3287
c48ad6ab8bdf 7037276: Unnecessary double traversal of dirty card windows
ysr
parents: 3256
diff changeset
145 // We do not call the non_clean_card_iterate_serial() version because
3357
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
146 // we want to clear the cards: clear_cl here does the work of finding
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
147 // contiguous dirty ranges of cards to process and clear.
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
148 clear_cl.do_MemRegion(chunk_mr);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
149
a61af66fc99e Initial load
duke
parents:
diff changeset
150 // Find the next chunk of the stride.
3357
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
151 chunk_card_start += ParGCCardsPerStrideChunk * n_strides;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
152 }
a61af66fc99e Initial load
duke
parents:
diff changeset
153 }
a61af66fc99e Initial load
duke
parents:
diff changeset
154
3357
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
155
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
156 // If you want a talkative process_chunk_boundaries,
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
157 // then #define NOISY(x) x
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
158 #ifdef NOISY
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
159 #error "Encountered a global preprocessor flag, NOISY, which might clash with local definition to follow"
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
160 #else
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
161 #define NOISY(x)
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
162 #endif
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
163
0
a61af66fc99e Initial load
duke
parents:
diff changeset
164 void
a61af66fc99e Initial load
duke
parents:
diff changeset
165 CardTableModRefBS::
a61af66fc99e Initial load
duke
parents:
diff changeset
166 process_chunk_boundaries(Space* sp,
a61af66fc99e Initial load
duke
parents:
diff changeset
167 DirtyCardToOopClosure* dcto_cl,
a61af66fc99e Initial load
duke
parents:
diff changeset
168 MemRegion chunk_mr,
a61af66fc99e Initial load
duke
parents:
diff changeset
169 MemRegion used,
a61af66fc99e Initial load
duke
parents:
diff changeset
170 jbyte** lowest_non_clean,
a61af66fc99e Initial load
duke
parents:
diff changeset
171 uintptr_t lowest_non_clean_base_chunk_index,
a61af66fc99e Initial load
duke
parents:
diff changeset
172 size_t lowest_non_clean_chunk_size)
a61af66fc99e Initial load
duke
parents:
diff changeset
173 {
3357
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
174 // We must worry about non-array objects that cross chunk boundaries,
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
175 // because such objects are both precisely and imprecisely marked:
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
176 // .. if the head of such an object is dirty, the entire object
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
177 // needs to be scanned, under the interpretation that this
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
178 // was an imprecise mark
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
179 // .. if the head of such an object is not dirty, we can assume
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
180 // precise marking and it's efficient to scan just the dirty
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
181 // cards.
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
182 // In either case, each scanned reference must be scanned precisely
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
183 // once so as to avoid cloning of a young referent. For efficiency,
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
184 // our closures depend on this property and do not protect against
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
185 // double scans.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
186
a61af66fc99e Initial load
duke
parents:
diff changeset
187 uintptr_t cur_chunk_index = addr_to_chunk_index(chunk_mr.start());
a61af66fc99e Initial load
duke
parents:
diff changeset
188 cur_chunk_index = cur_chunk_index - lowest_non_clean_base_chunk_index;
a61af66fc99e Initial load
duke
parents:
diff changeset
189
3357
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
190 NOISY(tty->print_cr("===========================================================================");)
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
191 NOISY(tty->print_cr(" process_chunk_boundary: Called with [" PTR_FORMAT "," PTR_FORMAT ")",
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
192 chunk_mr.start(), chunk_mr.end());)
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
193
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
194 // First, set "our" lowest_non_clean entry, which would be
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
195 // used by the thread scanning an adjoining left chunk with
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
196 // a non-array object straddling the mutual boundary.
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
197 // Find the object that spans our boundary, if one exists.
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
198 // first_block is the block possibly straddling our left boundary.
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
199 HeapWord* first_block = sp->block_start(chunk_mr.start());
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
200 assert((chunk_mr.start() != used.start()) || (first_block == chunk_mr.start()),
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
201 "First chunk should always have a co-initial block");
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
202 // Does the block straddle the chunk's left boundary, and is it
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
203 // a non-array object?
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
204 if (first_block < chunk_mr.start() // first block straddles left bdry
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
205 && sp->block_is_obj(first_block) // first block is an object
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
206 && !(oop(first_block)->is_objArray() // first block is not an array (arrays are precisely dirtied)
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
207 || oop(first_block)->is_typeArray())) {
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
208 // Find our least non-clean card, so that a left neighbour
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
209 // does not scan an object straddling the mutual boundary
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
210 // too far to the right, and attempt to scan a portion of
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
211 // that object twice.
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
212 jbyte* first_dirty_card = NULL;
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
213 jbyte* last_card_of_first_obj =
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
214 byte_for(first_block + sp->block_size(first_block) - 1);
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
215 jbyte* first_card_of_cur_chunk = byte_for(chunk_mr.start());
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
216 jbyte* last_card_of_cur_chunk = byte_for(chunk_mr.last());
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
217 jbyte* last_card_to_check =
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
218 (jbyte*) MIN2((intptr_t) last_card_of_cur_chunk,
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
219 (intptr_t) last_card_of_first_obj);
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
220 // Note that this does not need to go beyond our last card
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
221 // if our first object completely straddles this chunk.
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
222 for (jbyte* cur = first_card_of_cur_chunk;
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
223 cur <= last_card_to_check; cur++) {
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
224 jbyte val = *cur;
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
225 if (card_will_be_scanned(val)) {
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
226 first_dirty_card = cur; break;
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
227 } else {
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
228 assert(!card_may_have_been_dirty(val), "Error");
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
229 }
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
230 }
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
231 if (first_dirty_card != NULL) {
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
232 NOISY(tty->print_cr(" LNC: Found a dirty card at " PTR_FORMAT " in current chunk",
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
233 first_dirty_card);)
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
234 assert(0 <= cur_chunk_index && cur_chunk_index < lowest_non_clean_chunk_size,
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
235 "Bounds error.");
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
236 assert(lowest_non_clean[cur_chunk_index] == NULL,
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
237 "Write exactly once : value should be stable hereafter for this round");
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
238 lowest_non_clean[cur_chunk_index] = first_dirty_card;
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
239 } NOISY(else {
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
240 tty->print_cr(" LNC: Found no dirty card in current chunk; leaving LNC entry NULL");
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
241 // In the future, we could have this thread look for a non-NULL value to copy from its
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
242 // right neighbour (up to the end of the first object).
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
243 if (last_card_of_cur_chunk < last_card_of_first_obj) {
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
244 tty->print_cr(" LNC: BEWARE!!! first obj straddles past right end of chunk:\n"
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
245 " might be efficient to get value from right neighbour?");
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
246 }
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
247 })
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
248 } else {
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
249 // In this case we can help our neighbour by just asking them
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
250 // to stop at our first card (even though it may not be dirty).
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
251 NOISY(tty->print_cr(" LNC: first block is not a non-array object; setting LNC to first card of current chunk");)
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
252 assert(lowest_non_clean[cur_chunk_index] == NULL, "Write once : value should be stable hereafter");
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
253 jbyte* first_card_of_cur_chunk = byte_for(chunk_mr.start());
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
254 lowest_non_clean[cur_chunk_index] = first_card_of_cur_chunk;
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
255 }
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
256 NOISY(tty->print_cr(" process_chunk_boundary: lowest_non_clean[" INTPTR_FORMAT "] = " PTR_FORMAT
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
257 " which corresponds to the heap address " PTR_FORMAT,
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
258 cur_chunk_index, lowest_non_clean[cur_chunk_index],
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
259 (lowest_non_clean[cur_chunk_index] != NULL)
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
260 ? addr_for(lowest_non_clean[cur_chunk_index])
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
261 : NULL);)
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
262 NOISY(tty->print_cr("---------------------------------------------------------------------------");)
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
263
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
264 // Next, set our own max_to_do, which will strictly/exclusively bound
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
265 // the highest address that we will scan past the right end of our chunk.
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
266 HeapWord* max_to_do = NULL;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
267 if (chunk_mr.end() < used.end()) {
3357
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
268 // This is not the last chunk in the used region.
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
269 // What is our last block? We check the first block of
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
270 // the next (right) chunk rather than strictly check our last block
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
271 // because it's potentially more efficient to do so.
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
272 HeapWord* const last_block = sp->block_start(chunk_mr.end());
0
a61af66fc99e Initial load
duke
parents:
diff changeset
273 assert(last_block <= chunk_mr.end(), "In case this property changes.");
3357
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
274 if ((last_block == chunk_mr.end()) // our last block does not straddle boundary
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
275 || !sp->block_is_obj(last_block) // last_block isn't an object
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
276 || oop(last_block)->is_objArray() // last_block is an array (precisely marked)
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
277 || oop(last_block)->is_typeArray()) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
278 max_to_do = chunk_mr.end();
3357
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
279 NOISY(tty->print_cr(" process_chunk_boundary: Last block on this card is not a non-array object;\n"
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
280 " max_to_do left at " PTR_FORMAT, max_to_do);)
0
a61af66fc99e Initial load
duke
parents:
diff changeset
281 } else {
3357
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
282 assert(last_block < chunk_mr.end(), "Tautology");
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
283 // It is a non-array object that straddles the right boundary of this chunk.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
284 // last_obj_card is the card corresponding to the start of the last object
a61af66fc99e Initial load
duke
parents:
diff changeset
285 // in the chunk. Note that the last object may not start in
a61af66fc99e Initial load
duke
parents:
diff changeset
286 // the chunk.
3357
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
287 jbyte* const last_obj_card = byte_for(last_block);
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
288 const jbyte val = *last_obj_card;
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
289 if (!card_will_be_scanned(val)) {
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
290 assert(!card_may_have_been_dirty(val), "Error");
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
291 // The card containing the head is not dirty. Any marks on
0
a61af66fc99e Initial load
duke
parents:
diff changeset
292 // subsequent cards still in this chunk must have been made
3357
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
293 // precisely; we can cap processing at the end of our chunk.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
294 max_to_do = chunk_mr.end();
3357
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
295 NOISY(tty->print_cr(" process_chunk_boundary: Head of last object on this card is not dirty;\n"
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
296 " max_to_do left at " PTR_FORMAT,
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
297 max_to_do);)
0
a61af66fc99e Initial load
duke
parents:
diff changeset
298 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
299 // The last object must be considered dirty, and extends onto the
a61af66fc99e Initial load
duke
parents:
diff changeset
300 // following chunk. Look for a dirty card in that chunk that will
a61af66fc99e Initial load
duke
parents:
diff changeset
301 // bound our processing.
a61af66fc99e Initial load
duke
parents:
diff changeset
302 jbyte* limit_card = NULL;
3357
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
303 const size_t last_block_size = sp->block_size(last_block);
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
304 jbyte* const last_card_of_last_obj =
0
a61af66fc99e Initial load
duke
parents:
diff changeset
305 byte_for(last_block + last_block_size - 1);
3357
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
306 jbyte* const first_card_of_next_chunk = byte_for(chunk_mr.end());
0
a61af66fc99e Initial load
duke
parents:
diff changeset
307 // This search potentially goes a long distance looking
3357
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
308 // for the next card that will be scanned, terminating
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
309 // at the end of the last_block, if no earlier dirty card
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
310 // is found.
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
311 assert(byte_for(chunk_mr.end()) - byte_for(chunk_mr.start()) == ParGCCardsPerStrideChunk,
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
312 "last card of next chunk may be wrong");
0
a61af66fc99e Initial load
duke
parents:
diff changeset
313 for (jbyte* cur = first_card_of_next_chunk;
3357
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
314 cur <= last_card_of_last_obj; cur++) {
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
315 const jbyte val = *cur;
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
316 if (card_will_be_scanned(val)) {
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
317 NOISY(tty->print_cr(" Found a non-clean card " PTR_FORMAT " with value 0x%x",
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
318 cur, (int)val);)
0
a61af66fc99e Initial load
duke
parents:
diff changeset
319 limit_card = cur; break;
3357
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
320 } else {
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
321 assert(!card_may_have_been_dirty(val), "Error: card can't be skipped");
0
a61af66fc99e Initial load
duke
parents:
diff changeset
322 }
a61af66fc99e Initial load
duke
parents:
diff changeset
323 }
3357
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
324 if (limit_card != NULL) {
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
325 max_to_do = addr_for(limit_card);
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
326 assert(limit_card != NULL && max_to_do != NULL, "Error");
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
327 NOISY(tty->print_cr(" process_chunk_boundary: Found a dirty card at " PTR_FORMAT
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
328 " max_to_do set at " PTR_FORMAT " which is before end of last block in chunk: "
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
329 PTR_FORMAT " + " PTR_FORMAT " = " PTR_FORMAT,
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
330 limit_card, max_to_do, last_block, last_block_size, (last_block+last_block_size));)
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
331 } else {
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
332 // The following is a pessimistic value, because it's possible
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
333 // that a dirty card on a subsequent chunk has been cleared by
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
334 // the time we get to look at it; we'll correct for that further below,
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
335 // using the LNC array which records the least non-clean card
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
336 // before cards were cleared in a particular chunk.
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
337 limit_card = last_card_of_last_obj;
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
338 max_to_do = last_block + last_block_size;
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
339 assert(limit_card != NULL && max_to_do != NULL, "Error");
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
340 NOISY(tty->print_cr(" process_chunk_boundary: Found no dirty card before end of last block in chunk\n"
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
341 " Setting limit_card to " PTR_FORMAT
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
342 " and max_to_do " PTR_FORMAT " + " PTR_FORMAT " = " PTR_FORMAT,
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
343 limit_card, last_block, last_block_size, max_to_do);)
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
344 }
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
345 assert(0 < cur_chunk_index+1 && cur_chunk_index+1 < lowest_non_clean_chunk_size,
0
a61af66fc99e Initial load
duke
parents:
diff changeset
346 "Bounds error.");
3357
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
347 // It is possible that a dirty card for the last object may have been
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
348 // cleared before we had a chance to examine it. In that case, the value
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
349 // will have been logged in the LNC for that chunk.
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
350 // We need to examine as many chunks to the right as this object
3762
5c0a3c1858b1 7048782: CMS: assert(last_chunk_index_to_check<= last_chunk_index) failed: parCardTableModRefBS.cpp:359
ysr
parents: 3359
diff changeset
351 // covers. However, we need to bound this checking to the largest
5c0a3c1858b1 7048782: CMS: assert(last_chunk_index_to_check<= last_chunk_index) failed: parCardTableModRefBS.cpp:359
ysr
parents: 3359
diff changeset
352 // entry in the LNC array: this is because the heap may expand
5c0a3c1858b1 7048782: CMS: assert(last_chunk_index_to_check<= last_chunk_index) failed: parCardTableModRefBS.cpp:359
ysr
parents: 3359
diff changeset
353 // after the LNC array has been created but before we reach this point,
5c0a3c1858b1 7048782: CMS: assert(last_chunk_index_to_check<= last_chunk_index) failed: parCardTableModRefBS.cpp:359
ysr
parents: 3359
diff changeset
354 // and the last block in our chunk may have been expanded to include
5c0a3c1858b1 7048782: CMS: assert(last_chunk_index_to_check<= last_chunk_index) failed: parCardTableModRefBS.cpp:359
ysr
parents: 3359
diff changeset
355 // the expansion delta (and possibly subsequently allocated from, so
5c0a3c1858b1 7048782: CMS: assert(last_chunk_index_to_check<= last_chunk_index) failed: parCardTableModRefBS.cpp:359
ysr
parents: 3359
diff changeset
356 // it wouldn't be sufficient to check whether that last block was
5c0a3c1858b1 7048782: CMS: assert(last_chunk_index_to_check<= last_chunk_index) failed: parCardTableModRefBS.cpp:359
ysr
parents: 3359
diff changeset
357 // or was not an object at this point).
5c0a3c1858b1 7048782: CMS: assert(last_chunk_index_to_check<= last_chunk_index) failed: parCardTableModRefBS.cpp:359
ysr
parents: 3359
diff changeset
358 uintptr_t last_chunk_index_to_check = addr_to_chunk_index(last_block + last_block_size - 1)
5c0a3c1858b1 7048782: CMS: assert(last_chunk_index_to_check<= last_chunk_index) failed: parCardTableModRefBS.cpp:359
ysr
parents: 3359
diff changeset
359 - lowest_non_clean_base_chunk_index;
5c0a3c1858b1 7048782: CMS: assert(last_chunk_index_to_check<= last_chunk_index) failed: parCardTableModRefBS.cpp:359
ysr
parents: 3359
diff changeset
360 const uintptr_t last_chunk_index = addr_to_chunk_index(used.last())
5c0a3c1858b1 7048782: CMS: assert(last_chunk_index_to_check<= last_chunk_index) failed: parCardTableModRefBS.cpp:359
ysr
parents: 3359
diff changeset
361 - lowest_non_clean_base_chunk_index;
5c0a3c1858b1 7048782: CMS: assert(last_chunk_index_to_check<= last_chunk_index) failed: parCardTableModRefBS.cpp:359
ysr
parents: 3359
diff changeset
362 if (last_chunk_index_to_check > last_chunk_index) {
5c0a3c1858b1 7048782: CMS: assert(last_chunk_index_to_check<= last_chunk_index) failed: parCardTableModRefBS.cpp:359
ysr
parents: 3359
diff changeset
363 assert(last_block + last_block_size > used.end(),
5c0a3c1858b1 7048782: CMS: assert(last_chunk_index_to_check<= last_chunk_index) failed: parCardTableModRefBS.cpp:359
ysr
parents: 3359
diff changeset
364 err_msg("Inconsistency detected: last_block [" PTR_FORMAT "," PTR_FORMAT "]"
5c0a3c1858b1 7048782: CMS: assert(last_chunk_index_to_check<= last_chunk_index) failed: parCardTableModRefBS.cpp:359
ysr
parents: 3359
diff changeset
365 " does not exceed used.end() = " PTR_FORMAT ","
5c0a3c1858b1 7048782: CMS: assert(last_chunk_index_to_check<= last_chunk_index) failed: parCardTableModRefBS.cpp:359
ysr
parents: 3359
diff changeset
366 " yet last_chunk_index_to_check " INTPTR_FORMAT
5c0a3c1858b1 7048782: CMS: assert(last_chunk_index_to_check<= last_chunk_index) failed: parCardTableModRefBS.cpp:359
ysr
parents: 3359
diff changeset
367 " exceeds last_chunk_index " INTPTR_FORMAT,
5c0a3c1858b1 7048782: CMS: assert(last_chunk_index_to_check<= last_chunk_index) failed: parCardTableModRefBS.cpp:359
ysr
parents: 3359
diff changeset
368 last_chunk_index_to_check, last_chunk_index));
5c0a3c1858b1 7048782: CMS: assert(last_chunk_index_to_check<= last_chunk_index) failed: parCardTableModRefBS.cpp:359
ysr
parents: 3359
diff changeset
369 assert(sp->used_region().end() > used.end(),
5c0a3c1858b1 7048782: CMS: assert(last_chunk_index_to_check<= last_chunk_index) failed: parCardTableModRefBS.cpp:359
ysr
parents: 3359
diff changeset
370 err_msg("Expansion did not happen: "
5c0a3c1858b1 7048782: CMS: assert(last_chunk_index_to_check<= last_chunk_index) failed: parCardTableModRefBS.cpp:359
ysr
parents: 3359
diff changeset
371 "[" PTR_FORMAT "," PTR_FORMAT ") -> [" PTR_FORMAT "," PTR_FORMAT ")",
5c0a3c1858b1 7048782: CMS: assert(last_chunk_index_to_check<= last_chunk_index) failed: parCardTableModRefBS.cpp:359
ysr
parents: 3359
diff changeset
372 sp->used_region().start(), sp->used_region().end(), used.start(), used.end()));
5c0a3c1858b1 7048782: CMS: assert(last_chunk_index_to_check<= last_chunk_index) failed: parCardTableModRefBS.cpp:359
ysr
parents: 3359
diff changeset
373 NOISY(tty->print_cr(" process_chunk_boundary: heap expanded; explicitly bounding last_chunk");)
5c0a3c1858b1 7048782: CMS: assert(last_chunk_index_to_check<= last_chunk_index) failed: parCardTableModRefBS.cpp:359
ysr
parents: 3359
diff changeset
374 last_chunk_index_to_check = last_chunk_index;
5c0a3c1858b1 7048782: CMS: assert(last_chunk_index_to_check<= last_chunk_index) failed: parCardTableModRefBS.cpp:359
ysr
parents: 3359
diff changeset
375 }
3357
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
376 for (uintptr_t lnc_index = cur_chunk_index + 1;
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
377 lnc_index <= last_chunk_index_to_check;
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
378 lnc_index++) {
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
379 jbyte* lnc_card = lowest_non_clean[lnc_index];
0
a61af66fc99e Initial load
duke
parents:
diff changeset
380 if (lnc_card != NULL) {
3357
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
381 // we can stop at the first non-NULL entry we find
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
382 if (lnc_card <= limit_card) {
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
383 NOISY(tty->print_cr(" process_chunk_boundary: LNC card " PTR_FORMAT " is lower than limit_card " PTR_FORMAT,
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
384 " max_to_do will be lowered to " PTR_FORMAT " from " PTR_FORMAT,
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
385 lnc_card, limit_card, addr_for(lnc_card), max_to_do);)
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
386 limit_card = lnc_card;
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
387 max_to_do = addr_for(limit_card);
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
388 assert(limit_card != NULL && max_to_do != NULL, "Error");
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
389 }
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
390 // In any case, we break now
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
391 break;
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
392 } // else continue to look for a non-NULL entry if any
0
a61af66fc99e Initial load
duke
parents:
diff changeset
393 }
3357
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
394 assert(limit_card != NULL && max_to_do != NULL, "Error");
0
a61af66fc99e Initial load
duke
parents:
diff changeset
395 }
3357
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
396 assert(max_to_do != NULL, "OOPS 1 !");
0
a61af66fc99e Initial load
duke
parents:
diff changeset
397 }
3357
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
398 assert(max_to_do != NULL, "OOPS 2!");
0
a61af66fc99e Initial load
duke
parents:
diff changeset
399 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
400 max_to_do = used.end();
3357
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
401 NOISY(tty->print_cr(" process_chunk_boundary: Last chunk of this space;\n"
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
402 " max_to_do left at " PTR_FORMAT,
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
403 max_to_do);)
0
a61af66fc99e Initial load
duke
parents:
diff changeset
404 }
3357
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
405 assert(max_to_do != NULL, "OOPS 3!");
0
a61af66fc99e Initial load
duke
parents:
diff changeset
406 // Now we can set the closure we're using so it doesn't to beyond
a61af66fc99e Initial load
duke
parents:
diff changeset
407 // max_to_do.
a61af66fc99e Initial load
duke
parents:
diff changeset
408 dcto_cl->set_min_done(max_to_do);
a61af66fc99e Initial load
duke
parents:
diff changeset
409 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
410 dcto_cl->set_last_bottom(max_to_do);
a61af66fc99e Initial load
duke
parents:
diff changeset
411 #endif
3357
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
412 NOISY(tty->print_cr("===========================================================================\n");)
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
413 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
414
3357
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
415 #undef NOISY
0
a61af66fc99e Initial load
duke
parents:
diff changeset
416
a61af66fc99e Initial load
duke
parents:
diff changeset
417 void
a61af66fc99e Initial load
duke
parents:
diff changeset
418 CardTableModRefBS::
a61af66fc99e Initial load
duke
parents:
diff changeset
419 get_LNC_array_for_space(Space* sp,
a61af66fc99e Initial load
duke
parents:
diff changeset
420 jbyte**& lowest_non_clean,
a61af66fc99e Initial load
duke
parents:
diff changeset
421 uintptr_t& lowest_non_clean_base_chunk_index,
a61af66fc99e Initial load
duke
parents:
diff changeset
422 size_t& lowest_non_clean_chunk_size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
423
a61af66fc99e Initial load
duke
parents:
diff changeset
424 int i = find_covering_region_containing(sp->bottom());
a61af66fc99e Initial load
duke
parents:
diff changeset
425 MemRegion covered = _covered[i];
a61af66fc99e Initial load
duke
parents:
diff changeset
426 size_t n_chunks = chunks_to_cover(covered);
a61af66fc99e Initial load
duke
parents:
diff changeset
427
a61af66fc99e Initial load
duke
parents:
diff changeset
428 // Only the first thread to obtain the lock will resize the
a61af66fc99e Initial load
duke
parents:
diff changeset
429 // LNC array for the covered region. Any later expansion can't affect
a61af66fc99e Initial load
duke
parents:
diff changeset
430 // the used_at_save_marks region.
a61af66fc99e Initial load
duke
parents:
diff changeset
431 // (I observed a bug in which the first thread to execute this would
3357
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
432 // resize, and then it would cause "expand_and_allocate" that would
fc2b798ab316 6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents: 3287
diff changeset
433 // increase the number of chunks in the covered region. Then a second
0
a61af66fc99e Initial load
duke
parents:
diff changeset
434 // thread would come and execute this, see that the size didn't match,
a61af66fc99e Initial load
duke
parents:
diff changeset
435 // and free and allocate again. So the first thread would be using a
a61af66fc99e Initial load
duke
parents:
diff changeset
436 // freed "_lowest_non_clean" array.)
a61af66fc99e Initial load
duke
parents:
diff changeset
437
a61af66fc99e Initial load
duke
parents:
diff changeset
438 // Do a dirty read here. If we pass the conditional then take the rare
a61af66fc99e Initial load
duke
parents:
diff changeset
439 // event lock and do the read again in case some other thread had already
a61af66fc99e Initial load
duke
parents:
diff changeset
440 // succeeded and done the resize.
a61af66fc99e Initial load
duke
parents:
diff changeset
441 int cur_collection = Universe::heap()->total_collections();
a61af66fc99e Initial load
duke
parents:
diff changeset
442 if (_last_LNC_resizing_collection[i] != cur_collection) {
a61af66fc99e Initial load
duke
parents:
diff changeset
443 MutexLocker x(ParGCRareEvent_lock);
a61af66fc99e Initial load
duke
parents:
diff changeset
444 if (_last_LNC_resizing_collection[i] != cur_collection) {
a61af66fc99e Initial load
duke
parents:
diff changeset
445 if (_lowest_non_clean[i] == NULL ||
a61af66fc99e Initial load
duke
parents:
diff changeset
446 n_chunks != _lowest_non_clean_chunk_size[i]) {
a61af66fc99e Initial load
duke
parents:
diff changeset
447
a61af66fc99e Initial load
duke
parents:
diff changeset
448 // Should we delete the old?
a61af66fc99e Initial load
duke
parents:
diff changeset
449 if (_lowest_non_clean[i] != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
450 assert(n_chunks != _lowest_non_clean_chunk_size[i],
a61af66fc99e Initial load
duke
parents:
diff changeset
451 "logical consequence");
a61af66fc99e Initial load
duke
parents:
diff changeset
452 FREE_C_HEAP_ARRAY(CardPtr, _lowest_non_clean[i]);
a61af66fc99e Initial load
duke
parents:
diff changeset
453 _lowest_non_clean[i] = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
454 }
a61af66fc99e Initial load
duke
parents:
diff changeset
455 // Now allocate a new one if necessary.
a61af66fc99e Initial load
duke
parents:
diff changeset
456 if (_lowest_non_clean[i] == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
457 _lowest_non_clean[i] = NEW_C_HEAP_ARRAY(CardPtr, n_chunks);
a61af66fc99e Initial load
duke
parents:
diff changeset
458 _lowest_non_clean_chunk_size[i] = n_chunks;
a61af66fc99e Initial load
duke
parents:
diff changeset
459 _lowest_non_clean_base_chunk_index[i] = addr_to_chunk_index(covered.start());
a61af66fc99e Initial load
duke
parents:
diff changeset
460 for (int j = 0; j < (int)n_chunks; j++)
a61af66fc99e Initial load
duke
parents:
diff changeset
461 _lowest_non_clean[i][j] = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
462 }
a61af66fc99e Initial load
duke
parents:
diff changeset
463 }
a61af66fc99e Initial load
duke
parents:
diff changeset
464 _last_LNC_resizing_collection[i] = cur_collection;
a61af66fc99e Initial load
duke
parents:
diff changeset
465 }
a61af66fc99e Initial load
duke
parents:
diff changeset
466 }
a61af66fc99e Initial load
duke
parents:
diff changeset
467 // In any case, now do the initialization.
a61af66fc99e Initial load
duke
parents:
diff changeset
468 lowest_non_clean = _lowest_non_clean[i];
a61af66fc99e Initial load
duke
parents:
diff changeset
469 lowest_non_clean_base_chunk_index = _lowest_non_clean_base_chunk_index[i];
a61af66fc99e Initial load
duke
parents:
diff changeset
470 lowest_non_clean_chunk_size = _lowest_non_clean_chunk_size[i];
a61af66fc99e Initial load
duke
parents:
diff changeset
471 }