--- old/src/share/vm/classfile/symbolTable.cpp 2013-05-24 14:55:44.647055530 -0700 +++ new/src/share/vm/classfile/symbolTable.cpp 2013-05-24 14:55:44.437909787 -0700 @@ -598,6 +598,8 @@ bool StringTable::_needs_rehashing = false; +volatile uint StringTable::_par_claimed_idx = 0; + // Pick hashing algorithm unsigned int StringTable::hash_string(const jchar* s, int len) { return use_alternate_hashcode() ? AltHashing::murmur3_32(seed(), s, len) : @@ -784,6 +786,43 @@ } } +void StringTable::possibly_parallel_oops_do(OopClosure* f, uint worker_id) { + const uint ClaimChunkSize = 20; + const uint limit = the_table()->table_size(); + + for (;;) { + // Grab next set of buckets to scan + uint start_idx = (uint) Atomic::add((jint)ClaimChunkSize, + (volatile jint*)&_par_claimed_idx) - ClaimChunkSize; + if (start_idx >= limit) { + // End of table + break; + } + + uint end_idx = MIN2(limit, start_idx + ClaimChunkSize); + //gclog_or_tty->print_cr("[%u] Claimed [%d, %d)", worker_id, start_idx, end_idx); + + for (uint i = start_idx; i < end_idx; i += 1) { + HashtableEntry** p = the_table()->bucket_addr(i); + HashtableEntry* entry = the_table()->bucket(i); + + while (entry != NULL) { + f->do_oop((oop*)entry->literal_addr()); + + // Did the closure remove the literal from the table? + if (entry->literal() == NULL) { + assert(!entry->is_shared(), "immutable hashtable entry?"); + *p = entry->next(); + the_table()->free_entry(entry); + } else { + p = entry->next_addr(); + } + entry = (HashtableEntry*)HashtableEntry::make_ptr(*p); + } + } + } +} + void StringTable::verify() { for (int i = 0; i < the_table()->table_size(); ++i) { HashtableEntry* p = the_table()->bucket(i); --- old/src/share/vm/classfile/symbolTable.hpp 2013-05-24 14:55:45.728160380 -0700 +++ new/src/share/vm/classfile/symbolTable.hpp 2013-05-24 14:55:45.519931626 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -246,6 +246,9 @@ // Set if one bucket is out of balance due to hash algorithm deficiency static bool _needs_rehashing; + // Claimed high water mark for parallel chunked scanning + static volatile uint _par_claimed_idx; + static oop intern(Handle string_or_null, jchar* chars, int length, TRAPS); oop basic_add(int index, Handle string_or_null, jchar* name, int len, unsigned int hashValue, TRAPS); @@ -274,9 +277,12 @@ // Delete pointers to otherwise-unreachable objects. static void unlink(BoolObjectClosure* cl); - // Invoke "f->do_oop" on the locations of all oops in the table. + // Serially invoke "f->do_oop" on the locations of all oops in the table. static void oops_do(OopClosure* f); + // Possibly parallel version of the above + static void possibly_parallel_oops_do(OopClosure* f, uint worker_id); + // Hashing algorithm, used as the hash value used by the // StringTable for bucket selection and comparison (stored in the // HashtableEntry structures). This is used in the String.intern() method. @@ -312,5 +318,8 @@ // Rehash the symbol table if it gets out of balance static void rehash_table(); static bool needs_rehashing() { return _needs_rehashing; } + + // Parallel chunked scanning + static void clear_par_claimed_index() { _par_claimed_idx = 0; } }; #endif // SHARE_VM_CLASSFILE_SYMBOLTABLE_HPP --- old/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp 2013-05-24 14:55:46.801703441 -0700 +++ new/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp 2013-05-24 14:55:46.584839997 -0700 @@ -2935,7 +2935,7 @@ ¬Older, true, // walk code active on stacks NULL, - NULL); // SSS: Provide correct closure + NULL); // SSS: Provide correct closure // Now mark from the roots MarkFromRootsClosure markFromRootsClosure(this, _span, @@ -5186,7 +5186,9 @@ &par_mrias_cl, true, // walk all of code cache if (so & SO_CodeCache) NULL, - NULL); // The dirty klasses will be handled below + NULL, // The dirty klasses will be handled below + worker_id); + assert(_collector->should_unload_classes() || (_collector->CMSCollector::roots_scanning_options() & SharedHeap::SO_CodeCache), "if we didn't scan the code cache, we have to be ready to drop nmethods with expired weak oops"); --- old/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp 2013-05-24 14:55:48.041001622 -0700 +++ new/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp 2013-05-24 14:55:47.821886284 -0700 @@ -3307,14 +3307,13 @@ // Need cleared claim bits for the strong roots processing ClassLoaderDataGraph::clear_claimed_marks(); - process_strong_roots(true, // activate StrongRootsScope - false, // we set "is scavenging" to false, - // so we don't reset the dirty cards. - ScanningOption(so), // roots scanning options + process_strong_roots(true, // activate StrongRootsScope + false, // we set "is scavenging" to false, + // so we don't reset the dirty cards. + ScanningOption(so), // roots scanning options &rootsCl, &blobsCl, - &klassCl - ); + &klassCl); bool failures = rootsCl.failures(); @@ -5012,7 +5011,7 @@ OopClosure* scan_non_heap_roots, OopsInHeapRegionClosure* scan_rs, G1KlassScanClosure* scan_klasses, - int worker_i) { + uint worker_i) { // First scan the strong roots double ext_roots_start = os::elapsedTime(); @@ -5025,11 +5024,12 @@ G1FilteredCodeBlobToOopClosure eager_scan_code_roots(this, scan_non_heap_roots); process_strong_roots(false, // no scoping; this is parallel code - is_scavenging, so, + is_scavenging, + so, &buf_scan_non_heap_roots, &eager_scan_code_roots, - scan_klasses - ); + scan_klasses, + worker_i); // Now the CM ref_processor roots. if (!_process_strong_tasks->is_task_claimed(G1H_PS_refProcessor_oops_do)) { --- old/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp 2013-05-24 14:55:49.226530695 -0700 +++ new/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp 2013-05-24 14:55:49.010188131 -0700 @@ -818,7 +818,7 @@ OopClosure* scan_non_heap_roots, OopsInHeapRegionClosure* scan_rs, G1KlassScanClosure* scan_klasses, - int worker_i); + uint worker_i); // Apply "blk" to all the weak roots of the system. These include // JNI weak roots, the code cache, system dictionary, symbol table, --- old/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp 2013-05-24 14:55:50.327168314 -0700 +++ new/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp 2013-05-24 14:55:50.116271419 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -622,7 +622,8 @@ &par_scan_state.to_space_root_closure(), true, // walk *all* scavengable nmethods &par_scan_state.older_gen_closure(), - &klass_scan_closure); + &klass_scan_closure, + worker_id); par_scan_state.end_strong_roots(); // "evacuate followers". --- old/src/share/vm/memory/genCollectedHeap.cpp 2013-05-24 14:55:51.420175364 -0700 +++ new/src/share/vm/memory/genCollectedHeap.cpp 2013-05-24 14:55:51.210614343 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -598,17 +598,20 @@ OopsInGenClosure* not_older_gens, bool do_code_roots, OopsInGenClosure* older_gens, - KlassClosure* klass_closure) { + KlassClosure* klass_closure, + uint worker_id) { // General strong roots. if (!do_code_roots) { SharedHeap::process_strong_roots(activate_scope, is_scavenging, so, - not_older_gens, NULL, klass_closure); + not_older_gens, NULL, klass_closure, + worker_id); } else { bool do_code_marking = (activate_scope || nmethod::oops_do_marking_is_active()); CodeBlobToOopClosure code_roots(not_older_gens, /*do_marking=*/ do_code_marking); SharedHeap::process_strong_roots(activate_scope, is_scavenging, so, - not_older_gens, &code_roots, klass_closure); + not_older_gens, &code_roots, klass_closure, + worker_id); } if (younger_gens_as_roots) { --- old/src/share/vm/memory/genCollectedHeap.hpp 2013-05-24 14:55:52.502464796 -0700 +++ new/src/share/vm/memory/genCollectedHeap.hpp 2013-05-24 14:55:52.293800951 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -426,7 +426,8 @@ OopsInGenClosure* not_older_gens, bool do_code_roots, OopsInGenClosure* older_gens, - KlassClosure* klass_closure); + KlassClosure* klass_closure, + uint worker_id = 0); // Apply "blk" to all the weak roots of the system. These include // JNI weak roots, the code cache, system dictionary, symbol table, --- old/src/share/vm/memory/sharedHeap.cpp 2013-05-24 14:55:53.569782922 -0700 +++ new/src/share/vm/memory/sharedHeap.cpp 2013-05-24 14:55:53.361509029 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,7 +46,6 @@ SH_PS_Management_oops_do, SH_PS_SystemDictionary_oops_do, SH_PS_jvmti_oops_do, - SH_PS_StringTable_oops_do, SH_PS_CodeCache_oops_do, // Leave this one last. SH_PS_NumElements @@ -126,6 +125,8 @@ { if (_active) { outer->change_strong_roots_parity(); + // Zero the claimed high water mark in the StringTable + StringTable::clear_par_claimed_index(); } } @@ -138,7 +139,8 @@ ScanningOption so, OopClosure* roots, CodeBlobClosure* code_roots, - KlassClosure* klass_closure) { + KlassClosure* klass_closure, + uint worker_id) { StrongRootsScope srs(this, activate_scope); // General strong roots. @@ -153,14 +155,16 @@ // Global (strong) JNI handles if (!_process_strong_tasks->is_task_claimed(SH_PS_JNIHandles_oops_do)) JNIHandles::oops_do(roots); + // All threads execute this; the individual threads are task groups. CLDToOopClosure roots_from_clds(roots); CLDToOopClosure* roots_from_clds_p = (is_scavenging ? NULL : &roots_from_clds); - if (ParallelGCThreads > 0) { + if (CollectedHeap::use_parallel_gc_threads()) { Threads::possibly_parallel_oops_do(roots, roots_from_clds_p ,code_roots); } else { Threads::oops_do(roots, roots_from_clds_p, code_roots); } + if (!_process_strong_tasks-> is_task_claimed(SH_PS_ObjectSynchronizer_oops_do)) ObjectSynchronizer::oops_do(roots); if (!_process_strong_tasks->is_task_claimed(SH_PS_FlatProfiler_oops_do)) @@ -182,8 +186,13 @@ } } - if (!_process_strong_tasks->is_task_claimed(SH_PS_StringTable_oops_do)) { - if (so & SO_Strings) { + // All threads execute the following. A specific chunk of buckets + // from the StringTable are the individual tasks. + if (so & SO_Strings) { + if (CollectedHeap::use_parallel_gc_threads()) { + StringTable::possibly_parallel_oops_do(roots, worker_id); + } else { + assert(worker_id == 0, "only worker 0 for serial work"); StringTable::oops_do(roots); } } --- old/src/share/vm/memory/sharedHeap.hpp 2013-05-24 14:55:54.630912057 -0700 +++ new/src/share/vm/memory/sharedHeap.hpp 2013-05-24 14:55:54.423241116 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -243,7 +243,8 @@ ScanningOption so, OopClosure* roots, CodeBlobClosure* code_roots, - KlassClosure* klass_closure); + KlassClosure* klass_closure, + uint worker_id = 0); // Apply "blk" to all the weak roots of the system. These include // JNI weak roots, the code cache, system dictionary, symbol table,