src/share/vm/gc_implementation/g1/g1BlockOffsetTable.inline.hpp

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 4037
da91efe96a93
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 /*
stefank@2314 2 * Copyright (c) 2001, 2010, 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 #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1BLOCKOFFSETTABLE_INLINE_HPP
stefank@2314 26 #define SHARE_VM_GC_IMPLEMENTATION_G1_G1BLOCKOFFSETTABLE_INLINE_HPP
stefank@2314 27
stefank@2314 28 #include "gc_implementation/g1/g1BlockOffsetTable.hpp"
stefank@2314 29 #include "memory/space.hpp"
stefank@2314 30
ysr@777 31 inline HeapWord* G1BlockOffsetTable::block_start(const void* addr) {
ysr@777 32 if (addr >= _bottom && addr < _end) {
ysr@777 33 return block_start_unsafe(addr);
ysr@777 34 } else {
ysr@777 35 return NULL;
ysr@777 36 }
ysr@777 37 }
ysr@777 38
ysr@777 39 inline HeapWord*
ysr@777 40 G1BlockOffsetTable::block_start_const(const void* addr) const {
ysr@777 41 if (addr >= _bottom && addr < _end) {
ysr@777 42 return block_start_unsafe_const(addr);
ysr@777 43 } else {
ysr@777 44 return NULL;
ysr@777 45 }
ysr@777 46 }
ysr@777 47
ysr@777 48 inline size_t G1BlockOffsetSharedArray::index_for(const void* p) const {
ysr@777 49 char* pc = (char*)p;
ysr@777 50 assert(pc >= (char*)_reserved.start() &&
ysr@777 51 pc < (char*)_reserved.end(),
ysr@777 52 "p not in range.");
ysr@777 53 size_t delta = pointer_delta(pc, _reserved.start(), sizeof(char));
ysr@777 54 size_t result = delta >> LogN;
ysr@777 55 assert(result < _vs.committed_size(), "bad index from address");
ysr@777 56 return result;
ysr@777 57 }
ysr@777 58
ysr@777 59 inline HeapWord*
ysr@777 60 G1BlockOffsetSharedArray::address_for_index(size_t index) const {
ysr@777 61 assert(index < _vs.committed_size(), "bad index");
ysr@777 62 HeapWord* result = _reserved.start() + (index << LogN_words);
ysr@777 63 assert(result >= _reserved.start() && result < _reserved.end(),
ysr@777 64 "bad address from index");
ysr@777 65 return result;
ysr@777 66 }
ysr@777 67
ysr@777 68 inline HeapWord*
ysr@777 69 G1BlockOffsetArray::block_at_or_preceding(const void* addr,
ysr@777 70 bool has_max_index,
ysr@777 71 size_t max_index) const {
ysr@777 72 assert(_array->offset_array(0) == 0, "objects can't cross covered areas");
ysr@777 73 size_t index = _array->index_for(addr);
ysr@777 74 // We must make sure that the offset table entry we use is valid. If
ysr@777 75 // "addr" is past the end, start at the last known one and go forward.
ysr@777 76 if (has_max_index) {
ysr@777 77 index = MIN2(index, max_index);
ysr@777 78 }
ysr@777 79 HeapWord* q = _array->address_for_index(index);
ysr@777 80
ysr@777 81 uint offset = _array->offset_array(index); // Extend u_char to uint.
ysr@777 82 while (offset >= N_words) {
ysr@777 83 // The excess of the offset from N_words indicates a power of Base
ysr@777 84 // to go back by.
ysr@777 85 size_t n_cards_back = BlockOffsetArray::entry_to_cards_back(offset);
ysr@777 86 q -= (N_words * n_cards_back);
ysr@777 87 assert(q >= _sp->bottom(), "Went below bottom!");
ysr@777 88 index -= n_cards_back;
ysr@777 89 offset = _array->offset_array(index);
ysr@777 90 }
ysr@777 91 assert(offset < N_words, "offset too large");
ysr@777 92 q -= offset;
ysr@777 93 return q;
ysr@777 94 }
ysr@777 95
ysr@777 96 inline HeapWord*
ysr@777 97 G1BlockOffsetArray::
ysr@777 98 forward_to_block_containing_addr_const(HeapWord* q, HeapWord* n,
ysr@777 99 const void* addr) const {
ysr@777 100 if (csp() != NULL) {
ysr@777 101 if (addr >= csp()->top()) return csp()->top();
ysr@777 102 while (n <= addr) {
ysr@777 103 q = n;
ysr@777 104 oop obj = oop(q);
ysr@1280 105 if (obj->klass_or_null() == NULL) return q;
ysr@777 106 n += obj->size();
ysr@777 107 }
ysr@777 108 } else {
ysr@777 109 while (n <= addr) {
ysr@777 110 q = n;
ysr@777 111 oop obj = oop(q);
ysr@1280 112 if (obj->klass_or_null() == NULL) return q;
ysr@777 113 n += _sp->block_size(q);
ysr@777 114 }
ysr@777 115 }
ysr@777 116 assert(q <= n, "wrong order for q and addr");
ysr@777 117 assert(addr < n, "wrong order for addr and n");
ysr@777 118 return q;
ysr@777 119 }
ysr@777 120
ysr@777 121 inline HeapWord*
ysr@777 122 G1BlockOffsetArray::forward_to_block_containing_addr(HeapWord* q,
ysr@777 123 const void* addr) {
ysr@1280 124 if (oop(q)->klass_or_null() == NULL) return q;
ysr@777 125 HeapWord* n = q + _sp->block_size(q);
ysr@777 126 // In the normal case, where the query "addr" is a card boundary, and the
ysr@777 127 // offset table chunks are the same size as cards, the block starting at
ysr@777 128 // "q" will contain addr, so the test below will fail, and we'll fall
ysr@777 129 // through quickly.
ysr@777 130 if (n <= addr) {
ysr@777 131 q = forward_to_block_containing_addr_slow(q, n, addr);
ysr@777 132 }
ysr@777 133 assert(q <= addr, "wrong order for current and arg");
ysr@777 134 return q;
ysr@777 135 }
ysr@777 136
ysr@777 137 //////////////////////////////////////////////////////////////////////////
ysr@777 138 // BlockOffsetArrayNonContigSpace inlines
ysr@777 139 //////////////////////////////////////////////////////////////////////////
ysr@777 140 inline void G1BlockOffsetArray::freed(HeapWord* blk_start, HeapWord* blk_end) {
ysr@777 141 // Verify that the BOT shows [blk_start, blk_end) to be one block.
ysr@777 142 verify_single_block(blk_start, blk_end);
ysr@777 143 // adjust _unallocated_block upward or downward
ysr@777 144 // as appropriate
ysr@777 145 if (BlockOffsetArrayUseUnallocatedBlock) {
ysr@777 146 assert(_unallocated_block <= _end,
ysr@777 147 "Inconsistent value for _unallocated_block");
ysr@777 148 if (blk_end >= _unallocated_block && blk_start <= _unallocated_block) {
ysr@777 149 // CMS-specific note: a block abutting _unallocated_block to
ysr@777 150 // its left is being freed, a new block is being added or
ysr@777 151 // we are resetting following a compaction
ysr@777 152 _unallocated_block = blk_start;
ysr@777 153 }
ysr@777 154 }
ysr@777 155 }
ysr@777 156
ysr@777 157 inline void G1BlockOffsetArray::freed(HeapWord* blk, size_t size) {
ysr@777 158 freed(blk, blk + size);
ysr@777 159 }
stefank@2314 160
stefank@2314 161 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1BLOCKOFFSETTABLE_INLINE_HPP

mercurial