Mercurial > hg > truffle
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 |
rev | line source |
---|---|
0 | 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 | 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 * | |
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 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "memory/allocation.inline.hpp" | |
27 #include "memory/cardTableModRefBS.hpp" | |
28 #include "memory/cardTableRS.hpp" | |
29 #include "memory/sharedHeap.hpp" | |
30 #include "memory/space.inline.hpp" | |
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 | 33 #include "runtime/java.hpp" |
34 #include "runtime/mutexLocker.hpp" | |
35 #include "runtime/virtualspace.hpp" | |
0 | 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 | 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 | 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 | 74 } |
75 } | |
76 } | |
77 | |
78 void | |
79 CardTableModRefBS:: | |
80 process_stride(Space* sp, | |
81 MemRegion used, | |
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 | 85 jbyte** lowest_non_clean, |
86 uintptr_t lowest_non_clean_base_chunk_index, | |
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 | 90 |
91 // Find the first card address of the first chunk in the stride that is | |
92 // at least "bottom" of the used region. | |
93 jbyte* start_card = byte_for(used.start()); | |
94 jbyte* end_card = byte_after(used.last()); | |
95 uintptr_t start_chunk = addr_to_chunk_index(used.start()); | |
96 uintptr_t start_chunk_stride_num = start_chunk % n_strides; | |
97 jbyte* chunk_card_start; | |
98 | |
99 if ((uintptr_t)stride >= start_chunk_stride_num) { | |
100 chunk_card_start = (jbyte*)(start_card + | |
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 | 103 } else { |
104 // Go ahead to the next chunk group boundary, then to the requested stride. | |
105 chunk_card_start = (jbyte*)(start_card + | |
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 | 108 } |
109 | |
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 | 119 // Invariant: chunk_mr should be fully contained within the "used" region. |
120 MemRegion chunk_mr = MemRegion(addr_for(chunk_card_start), | |
121 chunk_card_end >= end_card ? | |
122 used.end() : addr_for(chunk_card_end)); | |
123 assert(chunk_mr.word_size() > 0, "[chunk_card_start > used_end)"); | |
124 assert(used.contains(chunk_mr), "chunk_mr should be subset of used"); | |
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 | 131 // Process the chunk. |
132 process_chunk_boundaries(sp, | |
133 dcto_cl, | |
134 chunk_mr, | |
135 used, | |
136 lowest_non_clean, | |
137 lowest_non_clean_base_chunk_index, | |
138 lowest_non_clean_chunk_size); | |
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 | 149 |
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 | 152 } |
153 } | |
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 | 164 void |
165 CardTableModRefBS:: | |
166 process_chunk_boundaries(Space* sp, | |
167 DirtyCardToOopClosure* dcto_cl, | |
168 MemRegion chunk_mr, | |
169 MemRegion used, | |
170 jbyte** lowest_non_clean, | |
171 uintptr_t lowest_non_clean_base_chunk_index, | |
172 size_t lowest_non_clean_chunk_size) | |
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 | 186 |
187 uintptr_t cur_chunk_index = addr_to_chunk_index(chunk_mr.start()); | |
188 cur_chunk_index = cur_chunk_index - lowest_non_clean_base_chunk_index; | |
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 | 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 | 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 | 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 | 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 | 284 // last_obj_card is the card corresponding to the start of the last object |
285 // in the chunk. Note that the last object may not start in | |
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 | 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 | 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 | 298 } else { |
299 // The last object must be considered dirty, and extends onto the | |
300 // following chunk. Look for a dirty card in that chunk that will | |
301 // bound our processing. | |
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 | 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 | 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 | 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 | 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 | 322 } |
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 | 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 | 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 | 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 | 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 | 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 | 399 } else { |
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 | 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 | 406 // Now we can set the closure we're using so it doesn't to beyond |
407 // max_to_do. | |
408 dcto_cl->set_min_done(max_to_do); | |
409 #ifndef PRODUCT | |
410 dcto_cl->set_last_bottom(max_to_do); | |
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 | 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 | 416 |
417 void | |
418 CardTableModRefBS:: | |
419 get_LNC_array_for_space(Space* sp, | |
420 jbyte**& lowest_non_clean, | |
421 uintptr_t& lowest_non_clean_base_chunk_index, | |
422 size_t& lowest_non_clean_chunk_size) { | |
423 | |
424 int i = find_covering_region_containing(sp->bottom()); | |
425 MemRegion covered = _covered[i]; | |
426 size_t n_chunks = chunks_to_cover(covered); | |
427 | |
428 // Only the first thread to obtain the lock will resize the | |
429 // LNC array for the covered region. Any later expansion can't affect | |
430 // the used_at_save_marks region. | |
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 | 434 // thread would come and execute this, see that the size didn't match, |
435 // and free and allocate again. So the first thread would be using a | |
436 // freed "_lowest_non_clean" array.) | |
437 | |
438 // Do a dirty read here. If we pass the conditional then take the rare | |
439 // event lock and do the read again in case some other thread had already | |
440 // succeeded and done the resize. | |
441 int cur_collection = Universe::heap()->total_collections(); | |
442 if (_last_LNC_resizing_collection[i] != cur_collection) { | |
443 MutexLocker x(ParGCRareEvent_lock); | |
444 if (_last_LNC_resizing_collection[i] != cur_collection) { | |
445 if (_lowest_non_clean[i] == NULL || | |
446 n_chunks != _lowest_non_clean_chunk_size[i]) { | |
447 | |
448 // Should we delete the old? | |
449 if (_lowest_non_clean[i] != NULL) { | |
450 assert(n_chunks != _lowest_non_clean_chunk_size[i], | |
451 "logical consequence"); | |
452 FREE_C_HEAP_ARRAY(CardPtr, _lowest_non_clean[i]); | |
453 _lowest_non_clean[i] = NULL; | |
454 } | |
455 // Now allocate a new one if necessary. | |
456 if (_lowest_non_clean[i] == NULL) { | |
457 _lowest_non_clean[i] = NEW_C_HEAP_ARRAY(CardPtr, n_chunks); | |
458 _lowest_non_clean_chunk_size[i] = n_chunks; | |
459 _lowest_non_clean_base_chunk_index[i] = addr_to_chunk_index(covered.start()); | |
460 for (int j = 0; j < (int)n_chunks; j++) | |
461 _lowest_non_clean[i][j] = NULL; | |
462 } | |
463 } | |
464 _last_LNC_resizing_collection[i] = cur_collection; | |
465 } | |
466 } | |
467 // In any case, now do the initialization. | |
468 lowest_non_clean = _lowest_non_clean[i]; | |
469 lowest_non_clean_base_chunk_index = _lowest_non_clean_base_chunk_index[i]; | |
470 lowest_non_clean_chunk_size = _lowest_non_clean_chunk_size[i]; | |
471 } |