1 /* 2 * Copyright (c) 2021, Amazon.com, Inc. or its affiliates. All rights reserved. 3 * 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 * 24 */ 25 26 27 #include "precompiled.hpp" 28 29 #include "gc/shenandoah/shenandoahHeap.inline.hpp" 30 #include "gc/shenandoah/shenandoahOopClosures.inline.hpp" 31 #include "gc/shenandoah/shenandoahReferenceProcessor.hpp" 32 #include "gc/shenandoah/shenandoahScanRemembered.inline.hpp" 33 34 ShenandoahDirectCardMarkRememberedSet::ShenandoahDirectCardMarkRememberedSet(ShenandoahCardTable* card_table, size_t total_card_count) { 35 _heap = ShenandoahHeap::heap(); 36 _card_table = card_table; 37 _total_card_count = total_card_count; 38 _cluster_count = total_card_count / ShenandoahCardCluster<ShenandoahDirectCardMarkRememberedSet>::CardsPerCluster; 39 _card_shift = CardTable::card_shift(); 40 41 _byte_map = _card_table->byte_for_index(0); 42 43 _whole_heap_base = _card_table->addr_for(_byte_map); 44 _whole_heap_end = _whole_heap_base + total_card_count * CardTable::card_size(); 45 46 _byte_map_base = _byte_map - (uintptr_t(_whole_heap_base) >> _card_shift); 47 48 _overreach_map = (uint8_t *) malloc(total_card_count); 49 _overreach_map_base = (_overreach_map - 50 (uintptr_t(_whole_heap_base) >> _card_shift)); 51 52 assert(total_card_count % ShenandoahCardCluster<ShenandoahDirectCardMarkRememberedSet>::CardsPerCluster == 0, "Invalid card count."); 53 assert(total_card_count > 0, "Card count cannot be zero."); 54 // assert(_overreach_cards != NULL); 55 } 56 57 ShenandoahDirectCardMarkRememberedSet::~ShenandoahDirectCardMarkRememberedSet() { 58 free(_overreach_map); 59 } 60 61 void ShenandoahDirectCardMarkRememberedSet::initialize_overreach(size_t first_cluster, size_t count) { 62 63 // We can make this run faster in the future by explicitly 64 // unrolling the loop and doing wide writes if the compiler 65 // doesn't do this for us. 66 size_t first_card_index = first_cluster * ShenandoahCardCluster<ShenandoahDirectCardMarkRememberedSet>::CardsPerCluster; 67 uint8_t* omp = &_overreach_map[first_card_index]; 68 uint8_t* endp = omp + count * ShenandoahCardCluster<ShenandoahDirectCardMarkRememberedSet>::CardsPerCluster; 69 while (omp < endp) 70 *omp++ = CardTable::clean_card_val(); 71 } 72 73 void ShenandoahDirectCardMarkRememberedSet::merge_overreach(size_t first_cluster, size_t count) { 74 75 // We can make this run faster in the future by explicitly unrolling the loop and doing wide writes if the compiler 76 // doesn't do this for us. 77 size_t first_card_index = first_cluster * ShenandoahCardCluster<ShenandoahDirectCardMarkRememberedSet>::CardsPerCluster; 78 uint8_t* bmp = &_byte_map[first_card_index]; 79 uint8_t* endp = bmp + count * ShenandoahCardCluster<ShenandoahDirectCardMarkRememberedSet>::CardsPerCluster; 80 uint8_t* omp = &_overreach_map[first_card_index]; 81 82 // dirty_card is 0, clean card is 0xff; if either *bmp or *omp is dirty, we need to mark it as dirty 83 while (bmp < endp) 84 *bmp++ &= *omp++; 85 } 86 87 ShenandoahScanRememberedTask::ShenandoahScanRememberedTask(ShenandoahObjToScanQueueSet* queue_set, 88 ShenandoahObjToScanQueueSet* old_queue_set, 89 ShenandoahReferenceProcessor* rp, 90 ShenandoahRegionIterator* regions) : 91 WorkerTask("Scan Remembered Set"), 92 _queue_set(queue_set), _old_queue_set(old_queue_set), _rp(rp), _regions(regions) {} 93 94 void ShenandoahScanRememberedTask::work(uint worker_id) { 95 // This sets up a thread local reference to the worker_id which is necessary 96 // the weak reference processor. 97 ShenandoahParallelWorkerSession worker_session(worker_id); 98 ShenandoahWorkerTimingsTracker x(ShenandoahPhaseTimings::init_scan_rset, ShenandoahPhaseTimings::ScanClusters, worker_id); 99 100 ShenandoahObjToScanQueue* q = _queue_set->queue(worker_id); 101 ShenandoahObjToScanQueue* old = _old_queue_set == NULL ? NULL : _old_queue_set->queue(worker_id); 102 ShenandoahMarkRefsClosure<YOUNG> cl(q, _rp, old); 103 RememberedScanner* scanner = ShenandoahHeap::heap()->card_scan(); 104 105 // set up thread local closure for shen ref processor 106 _rp->set_mark_closure(worker_id, &cl); 107 ShenandoahHeapRegion* region = _regions->next(); 108 while (region != NULL) { 109 log_debug(gc)("ShenandoahScanRememberedTask::work(%u), looking at region " SIZE_FORMAT, worker_id, region->index()); 110 if (region->affiliation() == OLD_GENERATION) { 111 scanner->process_region(region, &cl); 112 } 113 region = _regions->next(); 114 } 115 }