Mercurial > hg > graal-compiler
annotate src/share/vm/gc_implementation/parNew/parCardTableModRefBS.cpp @ 10185:d50cc62e94ff
8012715: G1: GraphKit accesses PtrQueue::_index as int but is size_t
Summary: In graphKit INT operations were generated to access PtrQueue::_index which has type size_t. This is 64 bit on 64-bit machines. No problems occur on little endian machines as long as the index fits into 32 bit, but on big endian machines the upper part is read, which is zero. This leads to unnecessary branches to the slow path in the runtime.
Reviewed-by: twisti, johnc
Contributed-by: Martin Doerr <martin.doerr@sap.com>
author | johnc |
---|---|
date | Wed, 24 Apr 2013 14:48:43 -0700 |
parents | 3c9db54c2660 |
children | b9a918201d47 de6a9e811145 |
rev | line source |
---|---|
0 | 1 /* |
6842
b9a9ed0f8eeb
7197424: update copyright year to match last edit in jdk8 hotspot repository
mikael
parents:
6197
diff
changeset
|
2 * Copyright (c) 2007, 2012, 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" | |
4095
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
3860
diff
changeset
|
36 #include "runtime/vmThread.hpp" |
0 | 37 |
3287
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
38 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
|
39 OopsInGenClosure* cl, |
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
40 CardTableRS* ct, |
3287
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
41 int n_threads) { |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
42 assert(n_threads > 0, "Error: expected n_threads > 0"); |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
43 assert((n_threads == 1 && ParallelGCThreads == 0) || |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
44 n_threads <= (int)ParallelGCThreads, |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
45 "# worker threads != # requested!"); |
4095
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
3860
diff
changeset
|
46 assert(!Thread::current()->is_VM_thread() || (n_threads == 1), "There is only 1 VM thread"); |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
3860
diff
changeset
|
47 assert(UseDynamicNumberOfGCThreads || |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
3860
diff
changeset
|
48 !FLAG_IS_DEFAULT(ParallelGCThreads) || |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
3860
diff
changeset
|
49 n_threads == (int)ParallelGCThreads, |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
3860
diff
changeset
|
50 "# worker threads != # requested!"); |
3287
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
51 // Make sure the LNC array is valid for the space. |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
52 jbyte** lowest_non_clean; |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
53 uintptr_t lowest_non_clean_base_chunk_index; |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
54 size_t lowest_non_clean_chunk_size; |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
55 get_LNC_array_for_space(sp, lowest_non_clean, |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
56 lowest_non_clean_base_chunk_index, |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
57 lowest_non_clean_chunk_size); |
0 | 58 |
4728
441e946dc1af
7121618: Change type of number of GC workers to unsigned int.
jmasa
parents:
4095
diff
changeset
|
59 uint n_strides = n_threads * ParGCStridesPerThread; |
3287
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
60 SequentialSubTasksDone* pst = sp->par_seq_tasks(); |
4095
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
3860
diff
changeset
|
61 // Sets the condition for completion of the subtask (how many threads |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
3860
diff
changeset
|
62 // need to finish in order to be done). |
3287
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
63 pst->set_n_threads(n_threads); |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
64 pst->set_n_tasks(n_strides); |
0 | 65 |
4728
441e946dc1af
7121618: Change type of number of GC workers to unsigned int.
jmasa
parents:
4095
diff
changeset
|
66 uint stride = 0; |
3287
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
67 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
|
68 process_stride(sp, mr, stride, n_strides, cl, ct, |
3287
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
69 lowest_non_clean, |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
70 lowest_non_clean_base_chunk_index, |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
71 lowest_non_clean_chunk_size); |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
72 } |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
73 if (pst->all_tasks_completed()) { |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
74 // Clear lowest_non_clean array for next time. |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
75 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
|
76 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
|
77 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
|
78 intptr_t ind = ch - lowest_non_clean_base_chunk_index; |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
79 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
|
80 "Bounds error"); |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
81 lowest_non_clean[ind] = NULL; |
0 | 82 } |
83 } | |
84 } | |
85 | |
86 void | |
87 CardTableModRefBS:: | |
88 process_stride(Space* sp, | |
89 MemRegion used, | |
90 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
|
91 OopsInGenClosure* cl, |
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
92 CardTableRS* ct, |
0 | 93 jbyte** lowest_non_clean, |
94 uintptr_t lowest_non_clean_base_chunk_index, | |
95 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
|
96 // 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
|
97 // because of the strided parallelism pattern used here. |
0 | 98 |
99 // Find the first card address of the first chunk in the stride that is | |
100 // at least "bottom" of the used region. | |
101 jbyte* start_card = byte_for(used.start()); | |
102 jbyte* end_card = byte_after(used.last()); | |
103 uintptr_t start_chunk = addr_to_chunk_index(used.start()); | |
104 uintptr_t start_chunk_stride_num = start_chunk % n_strides; | |
105 jbyte* chunk_card_start; | |
106 | |
107 if ((uintptr_t)stride >= start_chunk_stride_num) { | |
108 chunk_card_start = (jbyte*)(start_card + | |
109 (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
|
110 ParGCCardsPerStrideChunk); |
0 | 111 } else { |
112 // Go ahead to the next chunk group boundary, then to the requested stride. | |
113 chunk_card_start = (jbyte*)(start_card + | |
114 (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
|
115 ParGCCardsPerStrideChunk); |
0 | 116 } |
117 | |
118 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
|
119 // 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
|
120 // 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
|
121 // 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
|
122 // 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
|
123 // 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
|
124 // 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
|
125 // DirtyCardToOopClosure::do_MemRegion(). |
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
126 jbyte* chunk_card_end = chunk_card_start + ParGCCardsPerStrideChunk; |
0 | 127 // Invariant: chunk_mr should be fully contained within the "used" region. |
128 MemRegion chunk_mr = MemRegion(addr_for(chunk_card_start), | |
129 chunk_card_end >= end_card ? | |
130 used.end() : addr_for(chunk_card_end)); | |
131 assert(chunk_mr.word_size() > 0, "[chunk_card_start > used_end)"); | |
132 assert(used.contains(chunk_mr), "chunk_mr should be subset of used"); | |
133 | |
3357
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
134 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
|
135 cl->gen_boundary()); |
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
136 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
|
137 |
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
138 |
0 | 139 // Process the chunk. |
140 process_chunk_boundaries(sp, | |
141 dcto_cl, | |
142 chunk_mr, | |
143 used, | |
144 lowest_non_clean, | |
145 lowest_non_clean_base_chunk_index, | |
146 lowest_non_clean_chunk_size); | |
147 | |
3357
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
148 // 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
|
149 // 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
|
150 // 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
|
151 OrderAccess::storestore(); |
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
152 |
3287
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
153 // 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
|
154 // 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
|
155 // 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
|
156 clear_cl.do_MemRegion(chunk_mr); |
0 | 157 |
158 // 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
|
159 chunk_card_start += ParGCCardsPerStrideChunk * n_strides; |
0 | 160 } |
161 } | |
162 | |
3357
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
163 |
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
164 // 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
|
165 // 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
|
166 #ifdef NOISY |
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
167 #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
|
168 #else |
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
169 #define NOISY(x) |
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
170 #endif |
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
171 |
0 | 172 void |
173 CardTableModRefBS:: | |
174 process_chunk_boundaries(Space* sp, | |
175 DirtyCardToOopClosure* dcto_cl, | |
176 MemRegion chunk_mr, | |
177 MemRegion used, | |
178 jbyte** lowest_non_clean, | |
179 uintptr_t lowest_non_clean_base_chunk_index, | |
180 size_t lowest_non_clean_chunk_size) | |
181 { | |
3357
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
182 // 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
|
183 // 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
|
184 // .. 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
|
185 // 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
|
186 // 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
|
187 // .. 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
|
188 // 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
|
189 // cards. |
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
190 // 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
|
191 // 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
|
192 // 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
|
193 // double scans. |
0 | 194 |
195 uintptr_t cur_chunk_index = addr_to_chunk_index(chunk_mr.start()); | |
196 cur_chunk_index = cur_chunk_index - lowest_non_clean_base_chunk_index; | |
197 | |
3357
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
198 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
|
199 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
|
200 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
|
201 |
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
202 // 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
|
203 // 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
|
204 // 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
|
205 // 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
|
206 // 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
|
207 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
|
208 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
|
209 "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
|
210 // 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
|
211 // 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
|
212 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
|
213 && 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
|
214 && !(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
|
215 || 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
|
216 // 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
|
217 // 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
|
218 // 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
|
219 // that object twice. |
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
220 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
|
221 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
|
222 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
|
223 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
|
224 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
|
225 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
|
226 (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
|
227 (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
|
228 // 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
|
229 // 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
|
230 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
|
231 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
|
232 jbyte val = *cur; |
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
233 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
|
234 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
|
235 } else { |
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
236 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
|
237 } |
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
238 } |
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
239 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
|
240 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
|
241 first_dirty_card);) |
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
242 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
|
243 "Bounds error."); |
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
244 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
|
245 "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
|
246 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
|
247 } NOISY(else { |
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
248 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
|
249 // 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
|
250 // 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
|
251 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
|
252 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
|
253 " 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
|
254 } |
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 } else { |
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
257 // 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
|
258 // 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
|
259 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
|
260 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
|
261 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
|
262 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
|
263 } |
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
264 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
|
265 " 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
|
266 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
|
267 (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
|
268 ? 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
|
269 : NULL);) |
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
270 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
|
271 |
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
272 // 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
|
273 // 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
|
274 HeapWord* max_to_do = NULL; |
0 | 275 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
|
276 // 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
|
277 // 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
|
278 // 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
|
279 // 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
|
280 HeapWord* const last_block = sp->block_start(chunk_mr.end()); |
0 | 281 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
|
282 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
|
283 || !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
|
284 || 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
|
285 || oop(last_block)->is_typeArray()) { |
0 | 286 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
|
287 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
|
288 " max_to_do left at " PTR_FORMAT, max_to_do);) |
0 | 289 } else { |
3357
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
290 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
|
291 // It is a non-array object that straddles the right boundary of this chunk. |
0 | 292 // last_obj_card is the card corresponding to the start of the last object |
293 // in the chunk. Note that the last object may not start in | |
294 // the chunk. | |
3357
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
295 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
|
296 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
|
297 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
|
298 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
|
299 // The card containing the head is not dirty. Any marks on |
0 | 300 // 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
|
301 // precisely; we can cap processing at the end of our chunk. |
0 | 302 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
|
303 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
|
304 " 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
|
305 max_to_do);) |
0 | 306 } else { |
307 // The last object must be considered dirty, and extends onto the | |
308 // following chunk. Look for a dirty card in that chunk that will | |
309 // bound our processing. | |
310 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
|
311 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
|
312 jbyte* const last_card_of_last_obj = |
0 | 313 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
|
314 jbyte* const first_card_of_next_chunk = byte_for(chunk_mr.end()); |
0 | 315 // 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
|
316 // 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
|
317 // 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
|
318 // is found. |
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
319 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
|
320 "last card of next chunk may be wrong"); |
0 | 321 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
|
322 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
|
323 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
|
324 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
|
325 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
|
326 cur, (int)val);) |
0 | 327 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
|
328 } else { |
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
329 assert(!card_may_have_been_dirty(val), "Error: card can't be skipped"); |
0 | 330 } |
331 } | |
3357
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
332 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
|
333 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
|
334 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
|
335 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
|
336 " 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
|
337 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
|
338 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
|
339 } else { |
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
340 // 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
|
341 // 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
|
342 // 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
|
343 // 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
|
344 // 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
|
345 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
|
346 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
|
347 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
|
348 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
|
349 " 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
|
350 " 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
|
351 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
|
352 } |
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
353 assert(0 < cur_chunk_index+1 && cur_chunk_index+1 < lowest_non_clean_chunk_size, |
0 | 354 "Bounds error."); |
3357
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
355 // 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
|
356 // 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
|
357 // 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
|
358 // 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
|
359 // 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
|
360 // 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
|
361 // 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
|
362 // 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
|
363 // 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
|
364 // 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
|
365 // 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
|
366 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
|
367 - 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
|
368 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
|
369 - 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
|
370 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
|
371 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
|
372 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
|
373 " 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
|
374 " 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
|
375 " exceeds last_chunk_index " INTPTR_FORMAT, |
8668 | 376 last_block, last_block + last_block_size, |
377 used.end(), | |
3762
5c0a3c1858b1
7048782: CMS: assert(last_chunk_index_to_check<= last_chunk_index) failed: parCardTableModRefBS.cpp:359
ysr
parents:
3359
diff
changeset
|
378 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
|
379 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
|
380 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
|
381 "[" 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
|
382 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
|
383 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
|
384 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
|
385 } |
3357
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
386 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
|
387 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
|
388 lnc_index++) { |
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
389 jbyte* lnc_card = lowest_non_clean[lnc_index]; |
0 | 390 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
|
391 // 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
|
392 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
|
393 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
|
394 " 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
|
395 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
|
396 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
|
397 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
|
398 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
|
399 } |
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
400 // 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
|
401 break; |
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
402 } // else continue to look for a non-NULL entry if any |
0 | 403 } |
3357
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
404 assert(limit_card != NULL && max_to_do != NULL, "Error"); |
0 | 405 } |
3357
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
406 assert(max_to_do != NULL, "OOPS 1 !"); |
0 | 407 } |
3357
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
408 assert(max_to_do != NULL, "OOPS 2!"); |
0 | 409 } else { |
410 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
|
411 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
|
412 " 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
|
413 max_to_do);) |
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 assert(max_to_do != NULL, "OOPS 3!"); |
0 | 416 // Now we can set the closure we're using so it doesn't to beyond |
417 // max_to_do. | |
418 dcto_cl->set_min_done(max_to_do); | |
419 #ifndef PRODUCT | |
420 dcto_cl->set_last_bottom(max_to_do); | |
421 #endif | |
3357
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
422 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
|
423 } |
0 | 424 |
3357
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3287
diff
changeset
|
425 #undef NOISY |
0 | 426 |
427 void | |
428 CardTableModRefBS:: | |
429 get_LNC_array_for_space(Space* sp, | |
430 jbyte**& lowest_non_clean, | |
431 uintptr_t& lowest_non_clean_base_chunk_index, | |
432 size_t& lowest_non_clean_chunk_size) { | |
433 | |
434 int i = find_covering_region_containing(sp->bottom()); | |
435 MemRegion covered = _covered[i]; | |
436 size_t n_chunks = chunks_to_cover(covered); | |
437 | |
438 // Only the first thread to obtain the lock will resize the | |
439 // LNC array for the covered region. Any later expansion can't affect | |
440 // the used_at_save_marks region. | |
441 // (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
|
442 // 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
|
443 // increase the number of chunks in the covered region. Then a second |
0 | 444 // thread would come and execute this, see that the size didn't match, |
445 // and free and allocate again. So the first thread would be using a | |
446 // freed "_lowest_non_clean" array.) | |
447 | |
448 // Do a dirty read here. If we pass the conditional then take the rare | |
449 // event lock and do the read again in case some other thread had already | |
450 // succeeded and done the resize. | |
451 int cur_collection = Universe::heap()->total_collections(); | |
452 if (_last_LNC_resizing_collection[i] != cur_collection) { | |
453 MutexLocker x(ParGCRareEvent_lock); | |
454 if (_last_LNC_resizing_collection[i] != cur_collection) { | |
455 if (_lowest_non_clean[i] == NULL || | |
456 n_chunks != _lowest_non_clean_chunk_size[i]) { | |
457 | |
458 // Should we delete the old? | |
459 if (_lowest_non_clean[i] != NULL) { | |
460 assert(n_chunks != _lowest_non_clean_chunk_size[i], | |
461 "logical consequence"); | |
6197 | 462 FREE_C_HEAP_ARRAY(CardPtr, _lowest_non_clean[i], mtGC); |
0 | 463 _lowest_non_clean[i] = NULL; |
464 } | |
465 // Now allocate a new one if necessary. | |
466 if (_lowest_non_clean[i] == NULL) { | |
6197 | 467 _lowest_non_clean[i] = NEW_C_HEAP_ARRAY(CardPtr, n_chunks, mtGC); |
0 | 468 _lowest_non_clean_chunk_size[i] = n_chunks; |
469 _lowest_non_clean_base_chunk_index[i] = addr_to_chunk_index(covered.start()); | |
470 for (int j = 0; j < (int)n_chunks; j++) | |
471 _lowest_non_clean[i][j] = NULL; | |
472 } | |
473 } | |
474 _last_LNC_resizing_collection[i] = cur_collection; | |
475 } | |
476 } | |
477 // In any case, now do the initialization. | |
478 lowest_non_clean = _lowest_non_clean[i]; | |
479 lowest_non_clean_base_chunk_index = _lowest_non_clean_base_chunk_index[i]; | |
480 lowest_non_clean_chunk_size = _lowest_non_clean_chunk_size[i]; | |
481 } |