Thu, 20 Aug 2020 04:10:59 +0100
Merge
1.1 --- a/src/share/vm/gc_implementation/g1/concurrentMark.cpp Tue Aug 18 03:41:25 2020 +0100 1.2 +++ b/src/share/vm/gc_implementation/g1/concurrentMark.cpp Thu Aug 20 04:10:59 2020 +0100 1.3 @@ -3096,7 +3096,10 @@ 1.4 } 1.5 1.6 void do_object_work(oop obj) { 1.7 - guarantee(!_g1h->obj_in_cs(obj), 1.8 + guarantee(G1CMObjArrayProcessor::is_array_slice(obj) || obj->is_oop(), 1.9 + err_msg("Non-oop " PTR_FORMAT ", phase: %s, info: %d", 1.10 + p2i((void*) obj), phase_str(), _info)); 1.11 + guarantee(G1CMObjArrayProcessor::is_array_slice(obj) || !_g1h->obj_in_cs(obj), 1.12 err_msg("obj: " PTR_FORMAT " in CSet, phase: %s, info: %d", 1.13 p2i((void*) obj), phase_str(), _info)); 1.14 } 1.15 @@ -3506,18 +3509,25 @@ 1.16 template<bool scan> 1.17 inline void CMTask::process_grey_object(oop obj) { 1.18 assert(scan || obj->is_typeArray(), "Skipping scan of grey non-typeArray"); 1.19 - assert(_nextMarkBitMap->isMarked((HeapWord*) obj), "invariant"); 1.20 1.21 if (_cm->verbose_high()) { 1.22 gclog_or_tty->print_cr("[%u] processing grey object " PTR_FORMAT, 1.23 _worker_id, p2i((void*) obj)); 1.24 } 1.25 1.26 - size_t obj_size = obj->size(); 1.27 - _words_scanned += obj_size; 1.28 + assert(G1CMObjArrayProcessor::is_array_slice(obj) || _nextMarkBitMap->isMarked((HeapWord*) obj), 1.29 + "Any stolen object should be a slice or marked"); 1.30 1.31 if (scan) { 1.32 - obj->oop_iterate(_cm_oop_closure); 1.33 + if (G1CMObjArrayProcessor::is_array_slice(obj)) { 1.34 + _words_scanned += _objArray_processor.process_slice(obj); 1.35 + } else if (G1CMObjArrayProcessor::should_be_sliced(obj)) { 1.36 + _words_scanned += _objArray_processor.process_obj(obj); 1.37 + } else { 1.38 + size_t obj_size = obj->size(); 1.39 + _words_scanned += obj_size; 1.40 + obj->oop_iterate(_cm_oop_closure);; 1.41 + } 1.42 } 1.43 statsOnly( ++_objs_scanned ); 1.44 check_limits(); 1.45 @@ -3877,6 +3887,8 @@ 1.46 _worker_id, n); 1.47 } 1.48 for (int i = 0; i < n; ++i) { 1.49 + assert(G1CMObjArrayProcessor::is_array_slice(buffer[i]) || buffer[i]->is_oop(), 1.50 + err_msg("Element " PTR_FORMAT " must be an array slice or oop", p2i(buffer[i]))); 1.51 bool success = _task_queue->push(buffer[i]); 1.52 // We only call this when the local queue is empty or under a 1.53 // given target limit. So, we do not expect this push to fail. 1.54 @@ -3895,7 +3907,9 @@ 1.55 } 1.56 1.57 void CMTask::drain_local_queue(bool partially) { 1.58 - if (has_aborted()) return; 1.59 + if (has_aborted()) { 1.60 + return; 1.61 + } 1.62 1.63 // Decide what the target size is, depending whether we're going to 1.64 // drain it partially (so that other tasks can steal if they run out 1.65 @@ -3923,10 +3937,6 @@ 1.66 p2i((void*) obj)); 1.67 } 1.68 1.69 - assert(_g1h->is_in_g1_reserved((HeapWord*) obj), "invariant" ); 1.70 - assert(!_g1h->is_on_master_free_list( 1.71 - _g1h->heap_region_containing((HeapWord*) obj)), "invariant"); 1.72 - 1.73 scan_object(obj); 1.74 1.75 if (_task_queue->size() <= target_size || has_aborted()) { 1.76 @@ -4427,8 +4437,6 @@ 1.77 1.78 statsOnly( ++_steals ); 1.79 1.80 - assert(_nextMarkBitMap->isMarked((HeapWord*) obj), 1.81 - "any stolen object should be marked"); 1.82 scan_object(obj); 1.83 1.84 // And since we're towards the end, let's totally drain the 1.85 @@ -4602,6 +4610,7 @@ 1.86 CMTaskQueueSet* task_queues) 1.87 : _g1h(G1CollectedHeap::heap()), 1.88 _worker_id(worker_id), _cm(cm), 1.89 + _objArray_processor(this), 1.90 _claimed(false), 1.91 _nextMarkBitMap(NULL), _hash_seed(17), 1.92 _task_queue(task_queue),
2.1 --- a/src/share/vm/gc_implementation/g1/concurrentMark.hpp Tue Aug 18 03:41:25 2020 +0100 2.2 +++ b/src/share/vm/gc_implementation/g1/concurrentMark.hpp Thu Aug 20 04:10:59 2020 +0100 2.3 @@ -26,6 +26,7 @@ 2.4 #define SHARE_VM_GC_IMPLEMENTATION_G1_CONCURRENTMARK_HPP 2.5 2.6 #include "classfile/javaClasses.hpp" 2.7 +#include "gc_implementation/g1/g1ConcurrentMarkObjArrayProcessor.hpp" 2.8 #include "gc_implementation/g1/heapRegionSet.hpp" 2.9 #include "gc_implementation/g1/g1RegionToSpaceMapper.hpp" 2.10 #include "gc_implementation/shared/gcId.hpp" 2.11 @@ -942,7 +943,7 @@ 2.12 words_scanned_period = 12*1024, 2.13 // the regular clock call is called once the number of visited 2.14 // references reaches this limit 2.15 - refs_reached_period = 384, 2.16 + refs_reached_period = 1024, 2.17 // initial value for the hash seed, used in the work stealing code 2.18 init_hash_seed = 17, 2.19 // how many entries will be transferred between global stack and 2.20 @@ -950,6 +951,8 @@ 2.21 global_stack_transfer_size = 16 2.22 }; 2.23 2.24 + G1CMObjArrayProcessor _objArray_processor; 2.25 + 2.26 uint _worker_id; 2.27 G1CollectedHeap* _g1h; 2.28 ConcurrentMark* _cm; 2.29 @@ -1110,6 +1113,9 @@ 2.30 template<bool scan> void process_grey_object(oop obj); 2.31 2.32 public: 2.33 + // Apply the closure on the given area of the objArray. Return the number of words 2.34 + // scanned. 2.35 + inline size_t scan_objArray(objArrayOop obj, MemRegion mr); 2.36 // It resets the task; it should be called right at the beginning of 2.37 // a marking phase. 2.38 void reset(CMBitMap* _nextMarkBitMap);
3.1 --- a/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp Tue Aug 18 03:41:25 2020 +0100 3.2 +++ b/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp Thu Aug 20 04:10:59 2020 +0100 3.3 @@ -27,6 +27,7 @@ 3.4 3.5 #include "gc_implementation/g1/concurrentMark.hpp" 3.6 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" 3.7 +#include "gc_implementation/g1/g1ConcurrentMarkObjArrayProcessor.inline.hpp" 3.8 3.9 // Utility routine to set an exclusive range of cards on the given 3.10 // card liveness bitmap 3.11 @@ -224,11 +225,11 @@ 3.12 3.13 inline void CMTask::push(oop obj) { 3.14 HeapWord* objAddr = (HeapWord*) obj; 3.15 - assert(_g1h->is_in_g1_reserved(objAddr), "invariant"); 3.16 - assert(!_g1h->is_on_master_free_list( 3.17 + assert(G1CMObjArrayProcessor::is_array_slice(obj) || _g1h->is_in_g1_reserved(objAddr), "invariant"); 3.18 + assert(G1CMObjArrayProcessor::is_array_slice(obj) || !_g1h->is_on_master_free_list( 3.19 _g1h->heap_region_containing((HeapWord*) objAddr)), "invariant"); 3.20 - assert(!_g1h->is_obj_ill(obj), "invariant"); 3.21 - assert(_nextMarkBitMap->isMarked(objAddr), "invariant"); 3.22 + assert(G1CMObjArrayProcessor::is_array_slice(obj) || !_g1h->is_obj_ill(obj), "invariant"); 3.23 + assert(G1CMObjArrayProcessor::is_array_slice(obj) || _nextMarkBitMap->isMarked(objAddr), "invariant"); 3.24 3.25 if (_cm->verbose_high()) { 3.26 gclog_or_tty->print_cr("[%u] pushing " PTR_FORMAT, _worker_id, p2i((void*) obj)); 3.27 @@ -365,6 +366,11 @@ 3.28 } 3.29 } 3.30 3.31 +inline size_t CMTask::scan_objArray(objArrayOop obj, MemRegion mr) { 3.32 + obj->oop_iterate(_cm_oop_closure, mr); 3.33 + return mr.word_size(); 3.34 +} 3.35 + 3.36 inline void ConcurrentMark::markPrev(oop p) { 3.37 assert(!_prevMarkBitMap->isMarked((HeapWord*) p), "sanity"); 3.38 // Note we are overriding the read-only view of the prev map here, via
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/src/share/vm/gc_implementation/g1/g1ConcurrentMarkObjArrayProcessor.cpp Thu Aug 20 04:10:59 2020 +0100 4.3 @@ -0,0 +1,87 @@ 4.4 +/* 4.5 + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. 4.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4.7 + * 4.8 + * This code is free software; you can redistribute it and/or modify it 4.9 + * under the terms of the GNU General Public License version 2 only, as 4.10 + * published by the Free Software Foundation. 4.11 + * 4.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 4.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 4.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 4.15 + * version 2 for more details (a copy is included in the LICENSE file that 4.16 + * accompanied this code). 4.17 + * 4.18 + * You should have received a copy of the GNU General Public License version 4.19 + * 2 along with this work; if not, write to the Free Software Foundation, 4.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 4.21 + * 4.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 4.23 + * or visit www.oracle.com if you need additional information or have any 4.24 + * questions. 4.25 + * 4.26 + */ 4.27 + 4.28 +#include "precompiled.hpp" 4.29 +#include "gc_implementation/g1/concurrentMark.inline.hpp" 4.30 +#include "gc_implementation/g1/g1ConcurrentMarkObjArrayProcessor.inline.hpp" 4.31 + 4.32 +oop G1CMObjArrayProcessor::encode_array_slice(HeapWord* addr) { 4.33 + return oop((void*)((uintptr_t)addr | ArraySliceBit)); 4.34 +} 4.35 + 4.36 +HeapWord* G1CMObjArrayProcessor::decode_array_slice(oop value) { 4.37 + assert(is_array_slice(value), err_msg("Given value " PTR_FORMAT " is not an array slice", p2i(value))); 4.38 + return (HeapWord*)((uintptr_t)(void*)value & ~ArraySliceBit); 4.39 +} 4.40 + 4.41 +void G1CMObjArrayProcessor::push_array_slice(HeapWord* what) { 4.42 + oop obj = encode_array_slice(what); 4.43 + _task->push(obj); 4.44 +} 4.45 + 4.46 +size_t G1CMObjArrayProcessor::process_array_slice(objArrayOop obj, HeapWord* start_from, size_t remaining) { 4.47 + size_t words_to_scan = MIN2(remaining, ObjArrayMarkingStride); 4.48 + 4.49 + if (remaining > ObjArrayMarkingStride) { 4.50 + push_array_slice(start_from + ObjArrayMarkingStride); 4.51 + } 4.52 + 4.53 + // Then process current area. 4.54 + MemRegion mr(start_from, words_to_scan); 4.55 + return _task->scan_objArray(obj, mr); 4.56 +} 4.57 + 4.58 +size_t G1CMObjArrayProcessor::process_obj(oop obj) { 4.59 + assert(should_be_sliced(obj), err_msg("Must be an array object %d and large " SIZE_FORMAT, obj->is_objArray(), (size_t)obj->size())); 4.60 + 4.61 + return process_array_slice(objArrayOop(obj), (HeapWord*)obj, (size_t)objArrayOop(obj)->size()); 4.62 +} 4.63 + 4.64 +size_t G1CMObjArrayProcessor::process_slice(oop obj) { 4.65 + HeapWord* const decoded_address = decode_array_slice(obj); 4.66 + 4.67 + // Find the start address of the objArrayOop. 4.68 + // Shortcut the BOT access if the given address is from a humongous object. The BOT 4.69 + // slide is fast enough for "smaller" objects in non-humongous regions, but is slower 4.70 + // than directly using heap region table. 4.71 + G1CollectedHeap* g1h = G1CollectedHeap::heap(); 4.72 + HeapRegion* r = g1h->heap_region_containing(decoded_address); 4.73 + 4.74 + HeapWord* const start_address = r->isHumongous() ? 4.75 + r->humongous_start_region()->bottom() : 4.76 + g1h->block_start(decoded_address); 4.77 + 4.78 + assert(oop(start_address)->is_objArray(), err_msg("Address " PTR_FORMAT " does not refer to an object array ", p2i(start_address))); 4.79 + assert(start_address < decoded_address, 4.80 + err_msg("Object start address " PTR_FORMAT " must be smaller than decoded address " PTR_FORMAT, 4.81 + p2i(start_address), 4.82 + p2i(decoded_address))); 4.83 + 4.84 + objArrayOop objArray = objArrayOop(start_address); 4.85 + 4.86 + size_t already_scanned = decoded_address - start_address; 4.87 + size_t remaining = objArray->size() - already_scanned; 4.88 + 4.89 + return process_array_slice(objArray, decoded_address, remaining); 4.90 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/src/share/vm/gc_implementation/g1/g1ConcurrentMarkObjArrayProcessor.hpp Thu Aug 20 04:10:59 2020 +0100 5.3 @@ -0,0 +1,70 @@ 5.4 +/* 5.5 + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. 5.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5.7 + * 5.8 + * This code is free software; you can redistribute it and/or modify it 5.9 + * under the terms of the GNU General Public License version 2 only, as 5.10 + * published by the Free Software Foundation. 5.11 + * 5.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 5.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 5.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 5.15 + * version 2 for more details (a copy is included in the LICENSE file that 5.16 + * accompanied this code). 5.17 + * 5.18 + * You should have received a copy of the GNU General Public License version 5.19 + * 2 along with this work; if not, write to the Free Software Foundation, 5.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 5.21 + * 5.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 5.23 + * or visit www.oracle.com if you need additional information or have any 5.24 + * questions. 5.25 + * 5.26 + */ 5.27 + 5.28 +#ifndef SHARE_VM_GC_G1_G1CONCURRENTMARKOBJARRAYPROCESSOR_HPP 5.29 +#define SHARE_VM_GC_G1_G1CONCURRENTMARKOBJARRAYPROCESSOR_HPP 5.30 + 5.31 +#include "oops/oopsHierarchy.hpp" 5.32 +#include "memory/allocation.hpp" 5.33 + 5.34 +class CMTask; 5.35 + 5.36 +// Helper class to mark through large objArrays during marking in an efficient way. 5.37 +// Instead of pushing large object arrays, we push continuations onto the 5.38 +// mark stack. These continuations are identified by having their LSB set. 5.39 +// This allows incremental processing of large objects. 5.40 +class G1CMObjArrayProcessor VALUE_OBJ_CLASS_SPEC { 5.41 +private: 5.42 + // The bit mask for the continuation indicator of elements on the mark stack. 5.43 + static const size_t ArraySliceBit = 1; 5.44 + 5.45 + // Reference to the task for doing the actual work. 5.46 + CMTask* _task; 5.47 + 5.48 + // Encodes the given address as a continuation "oop". 5.49 + oop encode_array_slice(HeapWord* addr); 5.50 + // Remove the continuation marker from the given oop from the mark stack. 5.51 + HeapWord* decode_array_slice(oop value); 5.52 + 5.53 + // Push the continuation at the given address onto the mark stack. 5.54 + void push_array_slice(HeapWord* addr); 5.55 + 5.56 + // Process (apply the closure) on the given continuation of the given objArray. 5.57 + size_t process_array_slice(objArrayOop const obj, HeapWord* start_from, size_t remaining); 5.58 +public: 5.59 + static bool is_array_slice(void* obj) { return ((uintptr_t)obj & ArraySliceBit) != 0; } 5.60 + 5.61 + static bool should_be_sliced(oop obj); 5.62 + 5.63 + G1CMObjArrayProcessor(CMTask* task) : _task(task) { 5.64 + } 5.65 + 5.66 + // Process the given continuation "oop". Returns the number of words scanned. 5.67 + size_t process_slice(oop obj); 5.68 + // Start processing the given objArrayOop by scanning the header and pushing its 5.69 + // continuation. 5.70 + size_t process_obj(oop obj); 5.71 +}; 5.72 + 5.73 +#endif /* SHARE_VM_GC_G1_G1CONCURRENTMARKOBJARRAYPROCESSOR_HPP */
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/src/share/vm/gc_implementation/g1/g1ConcurrentMarkObjArrayProcessor.inline.hpp Thu Aug 20 04:10:59 2020 +0100 6.3 @@ -0,0 +1,36 @@ 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 + 6.28 +#ifndef SHARE_VM_GC_G1_G1CONCURRENTMARKOBJARRAYPROCESSOR_INLINE_HPP 6.29 +#define SHARE_VM_GC_G1_G1CONCURRENTMARKOBJARRAYPROCESSOR_INLINE_HPP 6.30 + 6.31 +#include "oops/oop.inline.hpp" 6.32 +#include "oops/oopsHierarchy.hpp" 6.33 +#include "runtime/globals.hpp" 6.34 + 6.35 +inline bool G1CMObjArrayProcessor::should_be_sliced(oop obj) { 6.36 + return obj->is_objArray() && ((size_t)((objArrayOop)obj)->size()) >= 2 * ObjArrayMarkingStride; 6.37 +} 6.38 + 6.39 +#endif /* SHARE_VM_GC_G1_G1CONCURRENTMARKOBJARRAYPROCESSOR_INLINE_HPP */
7.1 --- a/src/share/vm/runtime/globals.hpp Tue Aug 18 03:41:25 2020 +0100 7.2 +++ b/src/share/vm/runtime/globals.hpp Thu Aug 20 04:10:59 2020 +0100 7.3 @@ -2019,7 +2019,7 @@ 7.4 experimental(uintx, WorkStealingSpinToYieldRatio, 10, \ 7.5 "Ratio of hard spins to calls to yield") \ 7.6 \ 7.7 - develop(uintx, ObjArrayMarkingStride, 512, \ 7.8 + develop(uintx, ObjArrayMarkingStride, 2048, \ 7.9 "Number of object array elements to push onto the marking stack " \ 7.10 "before pushing a continuation entry") \ 7.11 \
8.1 --- a/src/share/vm/utilities/taskqueue.hpp Tue Aug 18 03:41:25 2020 +0100 8.2 +++ b/src/share/vm/utilities/taskqueue.hpp Thu Aug 20 04:10:59 2020 +0100 8.3 @@ -332,7 +332,8 @@ 8.4 // index, &_elems[index], _elems[index]); 8.5 E* t = (E*)&_elems[index]; // cast away volatility 8.6 oop* p = (oop*)t; 8.7 - assert((*t)->is_oop_or_null(), "Not an oop or null"); 8.8 + // G1 does its own checking 8.9 + assert(UseG1GC || (*t)->is_oop_or_null(), "Not an oop or null"); 8.10 f->do_oop(p); 8.11 } 8.12 // tty->print_cr("END OopTaskQueue::oops_do");