Thu, 18 Feb 2016 10:02:52 -0800
Merge
.hgtags | file | annotate | diff | comparison | revisions | |
src/share/vm/prims/jni.cpp | file | annotate | diff | comparison | revisions |
1.1 --- a/.hgtags Wed Feb 10 13:34:14 2016 +0000 1.2 +++ b/.hgtags Thu Feb 18 10:02:52 2016 -0800 1.3 @@ -818,6 +818,8 @@ 1.4 32b682649973231b54740c09b10889660f6ebde5 jdk8u75-b04 1.5 1f43bd4fab06d2ca5d1964611df14d8506d6b36e jdk8u75-b05 1.6 916712f178c39d0acbc590f38802133fc86a7346 jdk8u75-b06 1.7 +8c791dd1c24d85ebd18b03d49185c2a25263c129 jdk8u75-b07 1.8 +e4a935cb6f7178912fd653e2a9514eadec7935ab jdk8u75-b08 1.9 d7b01fb81aa8a5437cb03bc36afe15cf0e55fb89 jdk8u76-b00 1.10 c1679cc87ba045219169cabb6b9b378c2b5cc578 jdk8u76-b01 1.11 218483967e52b419d885d34af4488a81c5133804 jdk8u76-b02 1.12 @@ -825,4 +827,6 @@ 1.13 16f7b676725aadafb79ea105b22df112e2593a78 jdk8u76-b04 1.14 35bfaf7f9021b5c1e86effbeac075753a82e9a0c jdk8u76-b05 1.15 6449ee3bf707225372709ac830524c00984c601f jdk8u76-b06 1.16 +7d1074c74d6000ec8257917ebfcee3fed4249f7d jdk8u76-b07 1.17 +392f8722fc513e28f78c5c563d51af7dc8466b29 jdk8u76-b08 1.18 b374548dcb4834eb8731a06b52faddd0f10bd45d jdk8u81-b00
2.1 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Wed Feb 10 13:34:14 2016 +0000 2.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu Feb 18 10:02:52 2016 -0800 2.3 @@ -3839,6 +3839,16 @@ 2.4 _surviving_young_words = NULL; 2.5 } 2.6 2.7 +class VerifyRegionRemSetClosure : public HeapRegionClosure { 2.8 + public: 2.9 + bool doHeapRegion(HeapRegion* hr) { 2.10 + if (!hr->continuesHumongous()) { 2.11 + hr->verify_rem_set(); 2.12 + } 2.13 + return false; 2.14 + } 2.15 +}; 2.16 + 2.17 #ifdef ASSERT 2.18 class VerifyCSetClosure: public HeapRegionClosure { 2.19 public: 2.20 @@ -4015,6 +4025,14 @@ 2.21 increment_total_collections(false /* full gc */); 2.22 increment_gc_time_stamp(); 2.23 2.24 + if (VerifyRememberedSets) { 2.25 + if (!VerifySilently) { 2.26 + gclog_or_tty->print_cr("[Verifying RemSets before GC]"); 2.27 + } 2.28 + VerifyRegionRemSetClosure v_cl; 2.29 + heap_region_iterate(&v_cl); 2.30 + } 2.31 + 2.32 verify_before_gc(); 2.33 check_bitmaps("GC Start"); 2.34 2.35 @@ -4246,6 +4264,14 @@ 2.36 // scanning cards (see CR 7039627). 2.37 increment_gc_time_stamp(); 2.38 2.39 + if (VerifyRememberedSets) { 2.40 + if (!VerifySilently) { 2.41 + gclog_or_tty->print_cr("[Verifying RemSets after GC]"); 2.42 + } 2.43 + VerifyRegionRemSetClosure v_cl; 2.44 + heap_region_iterate(&v_cl); 2.45 + } 2.46 + 2.47 verify_after_gc(); 2.48 check_bitmaps("GC End"); 2.49
3.1 --- a/src/share/vm/gc_implementation/g1/heapRegion.cpp Wed Feb 10 13:34:14 2016 +0000 3.2 +++ b/src/share/vm/gc_implementation/g1/heapRegion.cpp Thu Feb 18 10:02:52 2016 -0800 3.3 @@ -639,8 +639,8 @@ 3.4 G1OffsetTableContigSpace::print_on(st); 3.5 } 3.6 3.7 -class VerifyLiveClosure: public OopClosure { 3.8 -private: 3.9 +class G1VerificationClosure : public OopClosure { 3.10 +protected: 3.11 G1CollectedHeap* _g1h; 3.12 CardTableModRefBS* _bs; 3.13 oop _containing_obj; 3.14 @@ -651,7 +651,7 @@ 3.15 // _vo == UsePrevMarking -> use "prev" marking information, 3.16 // _vo == UseNextMarking -> use "next" marking information, 3.17 // _vo == UseMarkWord -> use mark word from object header. 3.18 - VerifyLiveClosure(G1CollectedHeap* g1h, VerifyOption vo) : 3.19 + G1VerificationClosure(G1CollectedHeap* g1h, VerifyOption vo) : 3.20 _g1h(g1h), _bs(NULL), _containing_obj(NULL), 3.21 _failures(false), _n_failures(0), _vo(vo) 3.22 { 3.23 @@ -667,9 +667,6 @@ 3.24 bool failures() { return _failures; } 3.25 int n_failures() { return _n_failures; } 3.26 3.27 - virtual void do_oop(narrowOop* p) { do_oop_work(p); } 3.28 - virtual void do_oop( oop* p) { do_oop_work(p); } 3.29 - 3.30 void print_object(outputStream* out, oop obj) { 3.31 #ifdef PRODUCT 3.32 Klass* k = obj->klass(); 3.33 @@ -679,19 +676,31 @@ 3.34 obj->print_on(out); 3.35 #endif // PRODUCT 3.36 } 3.37 +}; 3.38 + 3.39 +class VerifyLiveClosure : public G1VerificationClosure { 3.40 +public: 3.41 + VerifyLiveClosure(G1CollectedHeap* g1h, VerifyOption vo) : G1VerificationClosure(g1h, vo) {} 3.42 + virtual void do_oop(narrowOop* p) { do_oop_work(p); } 3.43 + virtual void do_oop(oop* p) { do_oop_work(p); } 3.44 3.45 template <class T> 3.46 void do_oop_work(T* p) { 3.47 assert(_containing_obj != NULL, "Precondition"); 3.48 assert(!_g1h->is_obj_dead_cond(_containing_obj, _vo), 3.49 - "Precondition"); 3.50 + "Precondition"); 3.51 + verify_liveness(p); 3.52 + } 3.53 + 3.54 + template <class T> 3.55 + void verify_liveness(T* p) { 3.56 T heap_oop = oopDesc::load_heap_oop(p); 3.57 if (!oopDesc::is_null(heap_oop)) { 3.58 oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); 3.59 bool failed = false; 3.60 if (!_g1h->is_in_closed_subset(obj) || _g1h->is_obj_dead_cond(obj, _vo)) { 3.61 MutexLockerEx x(ParGCRareEvent_lock, 3.62 - Mutex::_no_safepoint_check_flag); 3.63 + Mutex::_no_safepoint_check_flag); 3.64 3.65 if (!_failures) { 3.66 gclog_or_tty->cr(); 3.67 @@ -727,50 +736,71 @@ 3.68 failed = true; 3.69 _n_failures++; 3.70 } 3.71 + } 3.72 + } 3.73 +}; 3.74 3.75 - if (!_g1h->full_collection() || G1VerifyRSetsDuringFullGC) { 3.76 - HeapRegion* from = _g1h->heap_region_containing((HeapWord*)p); 3.77 - HeapRegion* to = _g1h->heap_region_containing(obj); 3.78 - if (from != NULL && to != NULL && 3.79 - from != to && 3.80 - !to->isHumongous()) { 3.81 - jbyte cv_obj = *_bs->byte_for_const(_containing_obj); 3.82 - jbyte cv_field = *_bs->byte_for_const(p); 3.83 - const jbyte dirty = CardTableModRefBS::dirty_card_val(); 3.84 +class VerifyRemSetClosure : public G1VerificationClosure { 3.85 +public: 3.86 + VerifyRemSetClosure(G1CollectedHeap* g1h, VerifyOption vo) : G1VerificationClosure(g1h, vo) {} 3.87 + virtual void do_oop(narrowOop* p) { do_oop_work(p); } 3.88 + virtual void do_oop(oop* p) { do_oop_work(p); } 3.89 3.90 - bool is_bad = !(from->is_young() 3.91 - || to->rem_set()->contains_reference(p) 3.92 - || !G1HRRSFlushLogBuffersOnVerify && // buffers were not flushed 3.93 - (_containing_obj->is_objArray() ? 3.94 - cv_field == dirty 3.95 - : cv_obj == dirty || cv_field == dirty)); 3.96 - if (is_bad) { 3.97 - MutexLockerEx x(ParGCRareEvent_lock, 3.98 - Mutex::_no_safepoint_check_flag); 3.99 + template <class T> 3.100 + void do_oop_work(T* p) { 3.101 + assert(_containing_obj != NULL, "Precondition"); 3.102 + assert(!_g1h->is_obj_dead_cond(_containing_obj, _vo), 3.103 + "Precondition"); 3.104 + verify_remembered_set(p); 3.105 + } 3.106 3.107 - if (!_failures) { 3.108 - gclog_or_tty->cr(); 3.109 - gclog_or_tty->print_cr("----------"); 3.110 - } 3.111 - gclog_or_tty->print_cr("Missing rem set entry:"); 3.112 - gclog_or_tty->print_cr("Field "PTR_FORMAT" " 3.113 - "of obj "PTR_FORMAT", " 3.114 - "in region "HR_FORMAT, 3.115 - p, (void*) _containing_obj, 3.116 - HR_FORMAT_PARAMS(from)); 3.117 - _containing_obj->print_on(gclog_or_tty); 3.118 - gclog_or_tty->print_cr("points to obj "PTR_FORMAT" " 3.119 - "in region "HR_FORMAT, 3.120 - (void*) obj, 3.121 - HR_FORMAT_PARAMS(to)); 3.122 - obj->print_on(gclog_or_tty); 3.123 - gclog_or_tty->print_cr("Obj head CTE = %d, field CTE = %d.", 3.124 - cv_obj, cv_field); 3.125 + template <class T> 3.126 + void verify_remembered_set(T* p) { 3.127 + T heap_oop = oopDesc::load_heap_oop(p); 3.128 + if (!oopDesc::is_null(heap_oop)) { 3.129 + oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); 3.130 + bool failed = false; 3.131 + HeapRegion* from = _g1h->heap_region_containing((HeapWord*)p); 3.132 + HeapRegion* to = _g1h->heap_region_containing(obj); 3.133 + if (from != NULL && to != NULL && 3.134 + from != to && 3.135 + !to->isHumongous()) { 3.136 + jbyte cv_obj = *_bs->byte_for_const(_containing_obj); 3.137 + jbyte cv_field = *_bs->byte_for_const(p); 3.138 + const jbyte dirty = CardTableModRefBS::dirty_card_val(); 3.139 + 3.140 + bool is_bad = !(from->is_young() 3.141 + || to->rem_set()->contains_reference(p) 3.142 + || !G1HRRSFlushLogBuffersOnVerify && // buffers were not flushed 3.143 + (_containing_obj->is_objArray() ? 3.144 + cv_field == dirty 3.145 + : cv_obj == dirty || cv_field == dirty)); 3.146 + if (is_bad) { 3.147 + MutexLockerEx x(ParGCRareEvent_lock, 3.148 + Mutex::_no_safepoint_check_flag); 3.149 + 3.150 + if (!_failures) { 3.151 + gclog_or_tty->cr(); 3.152 gclog_or_tty->print_cr("----------"); 3.153 - gclog_or_tty->flush(); 3.154 - _failures = true; 3.155 - if (!failed) _n_failures++; 3.156 } 3.157 + gclog_or_tty->print_cr("Missing rem set entry:"); 3.158 + gclog_or_tty->print_cr("Field "PTR_FORMAT" " 3.159 + "of obj "PTR_FORMAT", " 3.160 + "in region "HR_FORMAT, 3.161 + p, (void*) _containing_obj, 3.162 + HR_FORMAT_PARAMS(from)); 3.163 + _containing_obj->print_on(gclog_or_tty); 3.164 + gclog_or_tty->print_cr("points to obj "PTR_FORMAT" " 3.165 + "in region "HR_FORMAT, 3.166 + (void*) obj, 3.167 + HR_FORMAT_PARAMS(to)); 3.168 + obj->print_on(gclog_or_tty); 3.169 + gclog_or_tty->print_cr("Obj head CTE = %d, field CTE = %d.", 3.170 + cv_obj, cv_field); 3.171 + gclog_or_tty->print_cr("----------"); 3.172 + gclog_or_tty->flush(); 3.173 + _failures = true; 3.174 + if (!failed) _n_failures++; 3.175 } 3.176 } 3.177 } 3.178 @@ -787,6 +817,7 @@ 3.179 HeapWord* p = bottom(); 3.180 HeapWord* prev_p = NULL; 3.181 VerifyLiveClosure vl_cl(g1, vo); 3.182 + VerifyRemSetClosure vr_cl(g1, vo); 3.183 bool is_humongous = isHumongous(); 3.184 bool do_bot_verify = !is_young(); 3.185 size_t object_num = 0; 3.186 @@ -832,7 +863,23 @@ 3.187 return; 3.188 } else { 3.189 vl_cl.set_containing_obj(obj); 3.190 - obj->oop_iterate_no_header(&vl_cl); 3.191 + if (!g1->full_collection() || G1VerifyRSetsDuringFullGC) { 3.192 + // verify liveness and rem_set 3.193 + vr_cl.set_containing_obj(obj); 3.194 + G1Mux2Closure mux(&vl_cl, &vr_cl); 3.195 + obj->oop_iterate_no_header(&mux); 3.196 + 3.197 + if (vr_cl.failures()) { 3.198 + *failures = true; 3.199 + } 3.200 + if (G1MaxVerifyFailures >= 0 && 3.201 + vr_cl.n_failures() >= G1MaxVerifyFailures) { 3.202 + return; 3.203 + } 3.204 + } else { 3.205 + // verify only liveness 3.206 + obj->oop_iterate_no_header(&vl_cl); 3.207 + } 3.208 if (vl_cl.failures()) { 3.209 *failures = true; 3.210 } 3.211 @@ -842,7 +889,7 @@ 3.212 } 3.213 } 3.214 } else { 3.215 - gclog_or_tty->print_cr(PTR_FORMAT" no an oop", (void *)obj); 3.216 + gclog_or_tty->print_cr(PTR_FORMAT" not an oop", (void *)obj); 3.217 *failures = true; 3.218 return; 3.219 } 3.220 @@ -930,6 +977,46 @@ 3.221 verify(VerifyOption_G1UsePrevMarking, /* failures */ &dummy); 3.222 } 3.223 3.224 +void HeapRegion::verify_rem_set(VerifyOption vo, bool* failures) const { 3.225 + G1CollectedHeap* g1 = G1CollectedHeap::heap(); 3.226 + *failures = false; 3.227 + HeapWord* p = bottom(); 3.228 + HeapWord* prev_p = NULL; 3.229 + VerifyRemSetClosure vr_cl(g1, vo); 3.230 + while (p < top()) { 3.231 + oop obj = oop(p); 3.232 + size_t obj_size = block_size(p); 3.233 + 3.234 + if (!g1->is_obj_dead_cond(obj, this, vo)) { 3.235 + if (obj->is_oop()) { 3.236 + vr_cl.set_containing_obj(obj); 3.237 + obj->oop_iterate_no_header(&vr_cl); 3.238 + 3.239 + if (vr_cl.failures()) { 3.240 + *failures = true; 3.241 + } 3.242 + if (G1MaxVerifyFailures >= 0 && 3.243 + vr_cl.n_failures() >= G1MaxVerifyFailures) { 3.244 + return; 3.245 + } 3.246 + } else { 3.247 + gclog_or_tty->print_cr(PTR_FORMAT " not an oop", p2i(obj)); 3.248 + *failures = true; 3.249 + return; 3.250 + } 3.251 + } 3.252 + 3.253 + prev_p = p; 3.254 + p += obj_size; 3.255 + } 3.256 +} 3.257 + 3.258 +void HeapRegion::verify_rem_set() const { 3.259 + bool failures = false; 3.260 + verify_rem_set(VerifyOption_G1UsePrevMarking, &failures); 3.261 + guarantee(!failures, "HeapRegion RemSet verification failed"); 3.262 +} 3.263 + 3.264 // G1OffsetTableContigSpace code; copied from space.cpp. Hope this can go 3.265 // away eventually. 3.266
4.1 --- a/src/share/vm/gc_implementation/g1/heapRegion.hpp Wed Feb 10 13:34:14 2016 +0000 4.2 +++ b/src/share/vm/gc_implementation/g1/heapRegion.hpp Thu Feb 18 10:02:52 2016 -0800 4.3 @@ -779,6 +779,9 @@ 4.4 4.5 // Override; it uses the "prev" marking information 4.6 virtual void verify() const; 4.7 + 4.8 + void verify_rem_set(VerifyOption vo, bool *failures) const; 4.9 + void verify_rem_set() const; 4.10 }; 4.11 4.12 // HeapRegionClosure is used for iterating over regions.
5.1 --- a/test/compiler/loopopts/CountedLoopProblem.java Wed Feb 10 13:34:14 2016 +0000 5.2 +++ b/test/compiler/loopopts/CountedLoopProblem.java Thu Feb 18 10:02:52 2016 -0800 5.3 @@ -36,18 +36,22 @@ 5.4 public static void main(String[] args) throws Exception { 5.5 Random r = new Random(42); 5.6 int x = 0; 5.7 - StringBuilder sb = new StringBuilder(); 5.8 - for(int i = 0; i < 1000000; ++i) { 5.9 - int v = Math.abs(r.nextInt()); 5.10 - sb.append('+').append(v).append('\n'); 5.11 - x += v; 5.12 - // To trigger the problem we must OSR in the following loop 5.13 - // To make the problem 100% reproducible run with -XX:-TieredCompilation -XX:OSROnlyBCI=62 5.14 - while(x < 0) x += 1000000000; 5.15 - sb.append('=').append(x).append('\n'); 5.16 - } 5.17 - if (sb.toString().hashCode() != 0xaba94591) { 5.18 - throw new Exception("Unexpected result"); 5.19 + try { 5.20 + StringBuilder sb = new StringBuilder(); 5.21 + for(int i = 0; i < 1000000; ++i) { 5.22 + int v = Math.abs(r.nextInt()); 5.23 + sb.append('+').append(v).append('\n'); 5.24 + x += v; 5.25 + // To trigger the problem we must OSR in the following loop 5.26 + // To make the problem 100% reproducible run with -XX:-TieredCompilation -XX:OSROnlyBCI=62 5.27 + while(x < 0) x += 1000000000; 5.28 + sb.append('=').append(x).append('\n'); 5.29 + } 5.30 + if (sb.toString().hashCode() != 0xaba94591) { 5.31 + throw new Exception("Unexpected result"); 5.32 + } 5.33 + } catch(OutOfMemoryError e) { 5.34 + // small heap, ignore 5.35 } 5.36 } 5.37 }
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/test/stress/gc/TestStressRSetCoarsening.java Thu Feb 18 10:02:52 2016 -0800 6.3 @@ -0,0 +1,334 @@ 6.4 +/* 6.5 + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. 6.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6.7 + * 6.8 + * This code is free software; you can redistribute it and/or modify it 6.9 + * under the terms of the GNU General Public License version 2 only, as 6.10 + * published by the Free Software Foundation. 6.11 + * 6.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 6.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 6.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 6.15 + * version 2 for more details (a copy is included in the LICENSE file that 6.16 + * accompanied this code). 6.17 + * 6.18 + * You should have received a copy of the GNU General Public License version 6.19 + * 2 along with this work; if not, write to the Free Software Foundation, 6.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 6.21 + * 6.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 6.23 + * or visit www.oracle.com if you need additional information or have any 6.24 + * questions. 6.25 + */ 6.26 + 6.27 +import java.util.concurrent.TimeoutException; 6.28 +import sun.hotspot.WhiteBox; 6.29 + 6.30 +/* 6.31 + * @test TestStressRSetCoarsening.java 6.32 + * @key stress 6.33 + * @bug 8146984 8147087 6.34 + * @requires vm.gc=="G1" | vm.gc=="null" 6.35 + * @requires os.maxMemory > 3G 6.36 + * 6.37 + * @summary Stress G1 Remembered Set by creating a lot of cross region links 6.38 + * @library /testlibrary /testlibrary/whitebox 6.39 + * @build sun.hotspot.WhiteBox 6.40 + * @run main ClassFileInstaller sun.hotspot.WhiteBox 6.41 + * sun.hotspot.WhiteBox$WhiteBoxPermission 6.42 + * @run main/othervm/timeout=300 6.43 + * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC 6.44 + * -XX:+IgnoreUnrecognizedVMOptions -XX:+PrintGC -XX:+PrintGCTimeStamps -Xlog:gc 6.45 + * -Xmx500m -XX:G1HeapRegionSize=1m -XX:MaxGCPauseMillis=1000 TestStressRSetCoarsening 1 0 300 6.46 + * @run main/othervm/timeout=300 6.47 + * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC 6.48 + * -XX:+IgnoreUnrecognizedVMOptions -XX:+PrintGC -XX:+PrintGCTimeStamps -Xlog:gc 6.49 + * -Xmx500m -XX:G1HeapRegionSize=8m -XX:MaxGCPauseMillis=1000 TestStressRSetCoarsening 1 10 300 6.50 + * @run main/othervm/timeout=300 6.51 + * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC 6.52 + * -XX:+IgnoreUnrecognizedVMOptions -XX:+PrintGC -XX:+PrintGCTimeStamps -Xlog:gc 6.53 + * -Xmx500m -XX:G1HeapRegionSize=32m -XX:MaxGCPauseMillis=1000 TestStressRSetCoarsening 42 10 300 6.54 + * @run main/othervm/timeout=300 6.55 + * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC 6.56 + * -XX:+IgnoreUnrecognizedVMOptions -XX:+PrintGC -XX:+PrintGCTimeStamps -Xlog:gc 6.57 + * -Xmx500m -XX:G1HeapRegionSize=1m -XX:MaxGCPauseMillis=1000 TestStressRSetCoarsening 2 0 300 6.58 + * @run main/othervm/timeout=1800 6.59 + * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC 6.60 + * -XX:+IgnoreUnrecognizedVMOptions -XX:+PrintGC -XX:+PrintGCTimeStamps -Xlog:gc 6.61 + * -Xmx1G -XX:G1HeapRegionSize=1m -XX:MaxGCPauseMillis=1000 TestStressRSetCoarsening 500 0 1800 6.62 + * @run main/othervm/timeout=1800 6.63 + * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC 6.64 + * -XX:+IgnoreUnrecognizedVMOptions -XX:+PrintGC -XX:+PrintGCTimeStamps -Xlog:gc 6.65 + * -Xmx1G -XX:G1HeapRegionSize=1m -XX:MaxGCPauseMillis=1000 TestStressRSetCoarsening 10 10 1800 6.66 + */ 6.67 + 6.68 +/** 6.69 + * What the test does. 6.70 + * Preparation stage: 6.71 + * Fill out ~90% of the heap with objects, each object is an object array. 6.72 + * If we want to allocate K objects per region, we calculate N to meet: 6.73 + * sizeOf(Object[N]) ~= regionSize / K 6.74 + * Stress stage: 6.75 + * No more allocation, so no more GC. 6.76 + * We will perform a number of iterations. On each iteration i, 6.77 + * for each pair of regions Rx and Ry we will set c[i] references 6.78 + * from Rx to Ry. If c[i] less than c[i-1] at the end of iteration 6.79 + * concurrent mark cycle will be initiated (to recalculate remembered sets). 6.80 + * As the result RSet will be growing up and down, up and down many times. 6.81 + * 6.82 + * The test expects: no crash and no timeouts. 6.83 + * 6.84 + * Test Parameters: 6.85 + * args[0] - number of objects per Heap Region (1 - means humongous) 6.86 + * args[1] - number of regions to refresh to provoke GC at the end of cycle. 6.87 + * (0 - means no GC, i.e. no reading from RSet) 6.88 + * args[2] - timeout in seconds (to stop execution to avoid jtreg timeout) 6.89 + */ 6.90 +public class TestStressRSetCoarsening { 6.91 + 6.92 + public static void main(String... args) throws InterruptedException { 6.93 + if (args.length != 3) { 6.94 + throw new IllegalArgumentException("Wrong number of arguments " + args.length); 6.95 + } 6.96 + int objectsPerRegion = Integer.parseInt(args[0]); // 1 means humongous 6.97 + int regsToRefresh = Integer.parseInt(args[1]); // 0 means no regions to refresh at the end of cycle 6.98 + int timeout = Integer.parseInt(args[2]); // in seconds, test should stop working eariler 6.99 + new TestStressRSetCoarsening(objectsPerRegion, regsToRefresh, timeout).go(); 6.100 + } 6.101 + 6.102 + private static final long KB = 1024; 6.103 + private static final long MB = 1024 * KB; 6.104 + 6.105 + private static final WhiteBox WB = WhiteBox.getWhiteBox(); 6.106 + 6.107 + public final Object[][] storage; 6.108 + 6.109 + /** 6.110 + * Number of objects per region. This is a test parameter. 6.111 + */ 6.112 + public final int K; 6.113 + 6.114 + /** 6.115 + * Length of object array: sizeOf(Object[N]) ~= regionSize / K 6.116 + * N will be calculated as function of K. 6.117 + */ 6.118 + public final int N; 6.119 + 6.120 + /** 6.121 + * How many regions involved into testing. 6.122 + * Will be calculated as heapFractionToAllocate * freeRegionCount. 6.123 + */ 6.124 + public final int regionCount; 6.125 + 6.126 + /** 6.127 + * How much heap to use. 6.128 + */ 6.129 + public final float heapFractionToAllocate = 0.9f; 6.130 + 6.131 + /** 6.132 + * How many regions to be refreshed at the end of cycle. 6.133 + * This is a test parameter. 6.134 + */ 6.135 + public final int regsToRefresh; 6.136 + 6.137 + /** 6.138 + * Initial time. 6.139 + */ 6.140 + public final long start; 6.141 + 6.142 + /** 6.143 + * Time when the test should stop working. 6.144 + */ 6.145 + public final long finishAt; 6.146 + 6.147 + /** 6.148 + * Does pre-calculation and allocate necessary objects. 6.149 + * 6.150 + * @param objPerRegions how many objects per G1 heap region 6.151 + */ 6.152 + TestStressRSetCoarsening(int objPerRegions, int regsToRefresh, int timeout) { 6.153 + this.K = objPerRegions; 6.154 + this.regsToRefresh = regsToRefresh; 6.155 + this.start = System.currentTimeMillis(); 6.156 + this.finishAt = start + timeout * 900; // 10% ahead of jtreg timeout 6.157 + 6.158 + long regionSize = WB.g1RegionSize(); 6.159 + 6.160 + // How many free regions 6.161 + Runtime rt = Runtime.getRuntime(); 6.162 + long used = rt.totalMemory() - rt.freeMemory(); 6.163 + long totalFree = rt.maxMemory() - used; 6.164 + regionCount = (int) ((totalFree / regionSize) * heapFractionToAllocate); 6.165 + long toAllocate = regionCount * regionSize; 6.166 + System.out.println("%% Test parameters"); 6.167 + System.out.println("%% Objects per region : " + K); 6.168 + System.out.println("%% Heap fraction to allocate : " + (int) (heapFractionToAllocate * 100) + "%"); 6.169 + System.out.println("%% Regions to refresh to provoke GC: " + regsToRefresh); 6.170 + 6.171 + System.out.println("%% Memory"); 6.172 + System.out.println("%% used : " + used / MB + "M"); 6.173 + System.out.println("%% available : " + totalFree / MB + "M"); 6.174 + System.out.println("%% to allocate : " + toAllocate / MB + "M"); 6.175 + System.out.println("%% (in regs) : " + regionCount); 6.176 + System.out.println("%% G1 Region Size: " + regionSize / MB + "M"); 6.177 + 6.178 + int refSize = WB.getHeapOopSize(); 6.179 + 6.180 + // Calculate N: K*sizeOf(Object[N]) ~= regionSize 6.181 + // sizeOf(Object[N]) ~= (N+4)*refSize 6.182 + // ==> 6.183 + // N = regionSize / K / refSize - 4; 6.184 + N = (int) ((regionSize / K) / refSize) - 5; 6.185 + 6.186 + /* 6.187 + * -------------- 6.188 + * region0 storage[0] = new Object[N] 6.189 + * ... 6.190 + * storage[K-1] = new Object[N] 6.191 + * --------------- 6.192 + * region1 storage[K] = new Object[N] 6.193 + * ... 6.194 + * storage[2*K - 1] = new Object[N] 6.195 + * -------------- 6.196 + * ... 6.197 + * -------------- 6.198 + * regionX storage[X*K] = new Object[N] 6.199 + * ... 6.200 + * storage[(X+1)*K -1] = new Object[N] 6.201 + * where X = HeapFraction * TotalRegions 6.202 + * ------------- 6.203 + */ 6.204 + System.out.println("%% Objects"); 6.205 + System.out.println("%% N (array length) : " + N); 6.206 + System.out.println("%% K (objects in regions): " + K); 6.207 + System.out.println("%% Reference size : " + refSize); 6.208 + System.out.println("%% Approximate obj size : " + (N + 2) * refSize / KB + "K)"); 6.209 + 6.210 + storage = new Object[regionCount * K][]; 6.211 + for (int i = 0; i < storage.length; i++) { 6.212 + storage[i] = new Object[N]; 6.213 + } 6.214 + } 6.215 + 6.216 + public void go() throws InterruptedException { 6.217 + // threshold for sparce -> fine 6.218 + final int FINE = WB.getIntxVMFlag("G1RSetSparseRegionEntries").intValue(); 6.219 + 6.220 + // threshold for fine -> coarse 6.221 + final int COARSE = WB.getIntxVMFlag("G1RSetRegionEntries").intValue(); 6.222 + 6.223 + // regToRegRefCounts - array of reference counts from region to region 6.224 + // at the the end of iteration. 6.225 + // The number of test iterations is array length - 1. 6.226 + // If c[i] > c[i-1] then during the iteration i more references will 6.227 + // be created. 6.228 + // If c[i] < c[i-1] then some referenes will be cleaned. 6.229 + int[] regToRegRefCounts = {0, FINE / 2, 0, FINE, (FINE + COARSE) / 2, 0, 6.230 + COARSE, COARSE + 10, FINE + 1, FINE / 2, 0}; 6.231 + 6.232 + // For progress tracking 6.233 + int[] progress = new int[regToRegRefCounts.length]; 6.234 + progress[0] = 0; 6.235 + for (int i = 1; i < regToRegRefCounts.length; i++) { 6.236 + progress[i] = progress[i - 1] + Math.abs(regToRegRefCounts[i] - regToRegRefCounts[i - 1]); 6.237 + } 6.238 + try { 6.239 + for (int i = 1; i < regToRegRefCounts.length; i++) { 6.240 + int pre = regToRegRefCounts[i - 1]; 6.241 + int cur = regToRegRefCounts[i]; 6.242 + float prog = ((float) progress[i - 1] / progress[progress.length - 1]); 6.243 + 6.244 + System.out.println("%% step " + i 6.245 + + " out of " + (regToRegRefCounts.length - 1) 6.246 + + " (~" + (int) (100 * prog) + "% done)"); 6.247 + System.out.println("%% " + pre + " --> " + cur); 6.248 + for (int to = 0; to < regionCount; to++) { 6.249 + // Select a celebrity object that we will install references to. 6.250 + // The celebrity will be referred from all other regions. 6.251 + // If the number of references after should be less than they 6.252 + // were before, select NULL. 6.253 + Object celebrity = cur > pre ? storage[to * K] : null; 6.254 + for (int from = 0; from < regionCount; from++) { 6.255 + if (to == from) { 6.256 + continue; // no need to refer to itself 6.257 + } 6.258 + 6.259 + int step = cur > pre ? +1 : -1; 6.260 + for (int rn = pre; rn != cur; rn += step) { 6.261 + storage[getY(to, from, rn)][getX(to, from, rn)] = celebrity; 6.262 + if (System.currentTimeMillis() > finishAt) { 6.263 + throw new TimeoutException(); 6.264 + } 6.265 + } 6.266 + } 6.267 + } 6.268 + if (pre > cur) { 6.269 + // Number of references went down. 6.270 + // Need to provoke recalculation of RSet. 6.271 + WB.g1StartConcMarkCycle(); 6.272 + while (WB.g1InConcurrentMark()) { 6.273 + Thread.sleep(1); 6.274 + } 6.275 + } 6.276 + 6.277 + // To force the use of rememebered set entries we need to provoke a GC. 6.278 + // To induce some fragmentation, and some mixed GCs, we need 6.279 + // to make a few objects unreachable. 6.280 + for (int toClean = i * regsToRefresh; toClean < (i + 1) * regsToRefresh; toClean++) { 6.281 + int to = toClean % regionCount; 6.282 + // Need to remove all references from all regions to the region 'to' 6.283 + for (int from = 0; from < regionCount; from++) { 6.284 + if (to == from) { 6.285 + continue; // no need to refer to itself 6.286 + } 6.287 + for (int rn = 0; rn <= cur; rn++) { 6.288 + storage[getY(to, from, rn)][getX(to, from, rn)] = null; 6.289 + } 6.290 + } 6.291 + // 'Refresh' storage elements for the region 'to' 6.292 + // After that loop all 'old' objects in the region 'to' 6.293 + // should become unreachable. 6.294 + for (int k = 0; k < K; k++) { 6.295 + storage[(to * K + k) % storage.length] = new Object[N]; 6.296 + } 6.297 + } 6.298 + } 6.299 + } catch (TimeoutException e) { 6.300 + System.out.println("%% TIMEOUT!!!"); 6.301 + } 6.302 + long now = System.currentTimeMillis(); 6.303 + System.out.println("%% Summary"); 6.304 + System.out.println("%% Time spent : " + ((now - start) / 1000) + " seconds"); 6.305 + System.out.println("%% Free memory left : " + Runtime.getRuntime().freeMemory() / KB + "K"); 6.306 + System.out.println("%% Test passed"); 6.307 + } 6.308 + 6.309 + /** 6.310 + * Returns X index in the Storage of the reference #rn from the region 6.311 + * 'from' to the region 'to'. 6.312 + * 6.313 + * @param to region # to refer to 6.314 + * @param from region # to refer from 6.315 + * @param rn number of reference 6.316 + * 6.317 + * @return X index in the range: [0 ... N-1] 6.318 + */ 6.319 + private int getX(int to, int from, int rn) { 6.320 + return (rn * regionCount + to) % N; 6.321 + } 6.322 + 6.323 + /** 6.324 + * Returns Y index in the Storage of the reference #rn from the region 6.325 + * 'from' to the region 'to'. 6.326 + * 6.327 + * @param to region # to refer to 6.328 + * @param from region # to refer from 6.329 + * @param rn number of reference 6.330 + * 6.331 + * @return Y index in the range: [0 ... K*regionCount -1] 6.332 + */ 6.333 + private int getY(int to, int from, int rn) { 6.334 + return ((rn * regionCount + to) / N + from * K) % (regionCount * K); 6.335 + } 6.336 +} 6.337 +