src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.cpp

Thu, 07 Apr 2011 09:53:20 -0700

author
johnc
date
Thu, 07 Apr 2011 09:53:20 -0700
changeset 2781
e1162778c1c8
parent 2314
f95d63e2154a
child 3156
f08d439fab8c
permissions
-rw-r--r--

7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
Summary: A referent object that is only weakly reachable at the start of concurrent marking but is re-attached to the strongly reachable object graph during marking may not be marked as live. This can cause the reference object to be processed prematurely and leave dangling pointers to the referent object. Implement a read barrier for the java.lang.ref.Reference::referent field by intrinsifying the Reference.get() method, and intercepting accesses though JNI, reflection, and Unsafe, so that when a non-null referent object is read it is also logged in an SATB buffer.
Reviewed-by: kvn, iveresov, never, tonyp, dholmes

ysr@777 1 /*
johnc@2781 2 * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
ysr@777 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
ysr@777 4 *
ysr@777 5 * This code is free software; you can redistribute it and/or modify it
ysr@777 6 * under the terms of the GNU General Public License version 2 only, as
ysr@777 7 * published by the Free Software Foundation.
ysr@777 8 *
ysr@777 9 * This code is distributed in the hope that it will be useful, but WITHOUT
ysr@777 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
ysr@777 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
ysr@777 12 * version 2 for more details (a copy is included in the LICENSE file that
ysr@777 13 * accompanied this code).
ysr@777 14 *
ysr@777 15 * You should have received a copy of the GNU General Public License version
ysr@777 16 * 2 along with this work; if not, write to the Free Software Foundation,
ysr@777 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
ysr@777 18 *
trims@1907 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
trims@1907 20 * or visit www.oracle.com if you need additional information or have any
trims@1907 21 * questions.
ysr@777 22 *
ysr@777 23 */
ysr@777 24
stefank@2314 25 #include "precompiled.hpp"
stefank@2314 26 #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
stefank@2314 27 #include "gc_implementation/g1/heapRegion.hpp"
stefank@2314 28 #include "gc_implementation/g1/satbQueue.hpp"
stefank@2314 29 #include "runtime/mutexLocker.hpp"
stefank@2314 30 #include "runtime/thread.hpp"
stefank@2314 31 #ifdef TARGET_OS_FAMILY_linux
stefank@2314 32 # include "thread_linux.inline.hpp"
stefank@2314 33 #endif
stefank@2314 34 #ifdef TARGET_OS_FAMILY_solaris
stefank@2314 35 # include "thread_solaris.inline.hpp"
stefank@2314 36 #endif
stefank@2314 37 #ifdef TARGET_OS_FAMILY_windows
stefank@2314 38 # include "thread_windows.inline.hpp"
stefank@2314 39 #endif
ysr@777 40
ysr@777 41 G1SATBCardTableModRefBS::G1SATBCardTableModRefBS(MemRegion whole_heap,
ysr@777 42 int max_covered_regions) :
ysr@777 43 CardTableModRefBSForCTRS(whole_heap, max_covered_regions)
ysr@777 44 {
ysr@777 45 _kind = G1SATBCT;
ysr@777 46 }
ysr@777 47
ysr@777 48
ysr@777 49 void G1SATBCardTableModRefBS::enqueue(oop pre_val) {
johnc@2781 50 // Nulls should have been already filtered.
johnc@2781 51 assert(pre_val->is_oop(true), "Error");
johnc@2781 52
tonyp@1752 53 if (!JavaThread::satb_mark_queue_set().is_active()) return;
ysr@777 54 Thread* thr = Thread::current();
ysr@777 55 if (thr->is_Java_thread()) {
ysr@777 56 JavaThread* jt = (JavaThread*)thr;
ysr@777 57 jt->satb_mark_queue().enqueue(pre_val);
ysr@777 58 } else {
ysr@777 59 MutexLocker x(Shared_SATB_Q_lock);
ysr@777 60 JavaThread::satb_mark_queue_set().shared_satb_queue()->enqueue(pre_val);
ysr@777 61 }
ysr@777 62 }
ysr@777 63
ysr@1280 64 template <class T> void
ysr@1280 65 G1SATBCardTableModRefBS::write_ref_array_pre_work(T* dst, int count) {
tonyp@1752 66 if (!JavaThread::satb_mark_queue_set().is_active()) return;
ysr@1280 67 T* elem_ptr = dst;
ysr@1280 68 for (int i = 0; i < count; i++, elem_ptr++) {
ysr@1280 69 T heap_oop = oopDesc::load_heap_oop(elem_ptr);
ysr@1280 70 if (!oopDesc::is_null(heap_oop)) {
ysr@1280 71 enqueue(oopDesc::decode_heap_oop_not_null(heap_oop));
ysr@1280 72 }
ysr@777 73 }
ysr@777 74 }
ysr@777 75
ysr@777 76 G1SATBCardTableLoggingModRefBS::
ysr@777 77 G1SATBCardTableLoggingModRefBS(MemRegion whole_heap,
ysr@777 78 int max_covered_regions) :
ysr@777 79 G1SATBCardTableModRefBS(whole_heap, max_covered_regions),
ysr@777 80 _dcqs(JavaThread::dirty_card_queue_set())
ysr@777 81 {
ysr@777 82 _kind = G1SATBCTLogging;
ysr@777 83 }
ysr@777 84
ysr@777 85 void
ysr@777 86 G1SATBCardTableLoggingModRefBS::write_ref_field_work(void* field,
ysr@777 87 oop new_val) {
ysr@777 88 jbyte* byte = byte_for(field);
ysr@777 89 if (*byte != dirty_card) {
ysr@777 90 *byte = dirty_card;
ysr@777 91 Thread* thr = Thread::current();
ysr@777 92 if (thr->is_Java_thread()) {
ysr@777 93 JavaThread* jt = (JavaThread*)thr;
ysr@777 94 jt->dirty_card_queue().enqueue(byte);
ysr@777 95 } else {
ysr@777 96 MutexLockerEx x(Shared_DirtyCardQ_lock,
ysr@777 97 Mutex::_no_safepoint_check_flag);
ysr@777 98 _dcqs.shared_dirty_card_queue()->enqueue(byte);
ysr@777 99 }
ysr@777 100 }
ysr@777 101 }
ysr@777 102
ysr@777 103 void
ysr@777 104 G1SATBCardTableLoggingModRefBS::write_ref_field_static(void* field,
ysr@777 105 oop new_val) {
ysr@777 106 uintptr_t field_uint = (uintptr_t)field;
ysr@777 107 uintptr_t new_val_uint = (uintptr_t)new_val;
ysr@777 108 uintptr_t comb = field_uint ^ new_val_uint;
ysr@777 109 comb = comb >> HeapRegion::LogOfHRGrainBytes;
ysr@777 110 if (comb == 0) return;
ysr@777 111 if (new_val == NULL) return;
ysr@777 112 // Otherwise, log it.
ysr@777 113 G1SATBCardTableLoggingModRefBS* g1_bs =
ysr@777 114 (G1SATBCardTableLoggingModRefBS*)Universe::heap()->barrier_set();
ysr@777 115 g1_bs->write_ref_field_work(field, new_val);
ysr@777 116 }
ysr@777 117
ysr@777 118 void
ysr@777 119 G1SATBCardTableLoggingModRefBS::invalidate(MemRegion mr, bool whole_heap) {
ysr@777 120 jbyte* byte = byte_for(mr.start());
ysr@777 121 jbyte* last_byte = byte_for(mr.last());
ysr@777 122 Thread* thr = Thread::current();
ysr@777 123 if (whole_heap) {
ysr@777 124 while (byte <= last_byte) {
ysr@777 125 *byte = dirty_card;
ysr@777 126 byte++;
ysr@777 127 }
ysr@777 128 } else {
ysr@777 129 // Enqueue if necessary.
ysr@777 130 if (thr->is_Java_thread()) {
ysr@777 131 JavaThread* jt = (JavaThread*)thr;
ysr@777 132 while (byte <= last_byte) {
ysr@777 133 if (*byte != dirty_card) {
ysr@777 134 *byte = dirty_card;
ysr@777 135 jt->dirty_card_queue().enqueue(byte);
ysr@777 136 }
ysr@777 137 byte++;
ysr@777 138 }
ysr@777 139 } else {
ysr@777 140 MutexLockerEx x(Shared_DirtyCardQ_lock,
ysr@777 141 Mutex::_no_safepoint_check_flag);
ysr@777 142 while (byte <= last_byte) {
ysr@777 143 if (*byte != dirty_card) {
ysr@777 144 *byte = dirty_card;
ysr@777 145 _dcqs.shared_dirty_card_queue()->enqueue(byte);
ysr@777 146 }
ysr@777 147 byte++;
ysr@777 148 }
ysr@777 149 }
ysr@777 150 }
ysr@777 151 }

mercurial