1 /* 2 * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1BLOCKOFFSETTABLE_INLINE_HPP 26 #define SHARE_VM_GC_IMPLEMENTATION_G1_G1BLOCKOFFSETTABLE_INLINE_HPP 27 28 #include "gc_implementation/g1/g1BlockOffsetTable.hpp" 29 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" 30 #include "gc_implementation/g1/heapRegion.inline.hpp" 31 #include "memory/space.hpp" 32 33 inline HeapWord* G1BlockOffsetTable::block_start(const void* addr) { 34 if (addr >= _bottom && addr < _end) { 35 return block_start_unsafe(addr); 36 } else { 37 return NULL; 38 } 39 } 40 41 inline HeapWord* 42 G1BlockOffsetTable::block_start_const(const void* addr) const { 43 if (addr >= _bottom && addr < _end) { 44 return block_start_unsafe_const(addr); 45 } else { 46 return NULL; 47 } 48 } 49 50 inline size_t G1BlockOffsetSharedArray::index_for(const void* p) const { 51 char* pc = (char*)p; 52 assert(pc >= (char*)_reserved.start() && 53 pc < (char*)_reserved.end(), 54 err_msg("p (" PTR_FORMAT ") not in reserved [" PTR_FORMAT ", " PTR_FORMAT ")", 55 p2i(p), p2i(_reserved.start()), p2i(_reserved.end()))); 56 size_t delta = pointer_delta(pc, _reserved.start(), sizeof(char)); 57 size_t result = delta >> LogN; 58 check_index(result, "bad index from address"); 59 return result; 60 } 61 62 inline HeapWord* 63 G1BlockOffsetSharedArray::address_for_index(size_t index) const { 64 check_index(index, "index out of range"); 65 HeapWord* result = _reserved.start() + (index << LogN_words); 66 assert(result >= _reserved.start() && result < _reserved.end(), 67 err_msg("bad address from index result " PTR_FORMAT 68 " _reserved.start() " PTR_FORMAT " _reserved.end() " 69 PTR_FORMAT, 70 p2i(result), p2i(_reserved.start()), p2i(_reserved.end()))); 71 return result; 72 } 73 74 inline size_t 75 G1BlockOffsetArray::block_size(const HeapWord* p) const { 76 return gsp()->block_size(p); 77 } 78 79 inline HeapWord* 80 G1BlockOffsetArray::block_at_or_preceding(const void* addr, 81 bool has_max_index, 82 size_t max_index) const { 83 assert(_array->offset_array(0) == 0, "objects can't cross covered areas"); 84 size_t index = _array->index_for(addr); 85 // We must make sure that the offset table entry we use is valid. If 86 // "addr" is past the end, start at the last known one and go forward. 87 if (has_max_index) { 88 index = MIN2(index, max_index); 89 } 90 HeapWord* q = _array->address_for_index(index); 91 92 uint offset = _array->offset_array(index); // Extend u_char to uint. 93 while (offset >= N_words) { 94 // The excess of the offset from N_words indicates a power of Base 95 // to go back by. 96 size_t n_cards_back = BlockOffsetArray::entry_to_cards_back(offset); 97 q -= (N_words * n_cards_back); 98 assert(q >= gsp()->bottom(), "Went below bottom!"); 99 index -= n_cards_back; 100 offset = _array->offset_array(index); 101 } 102 assert(offset < N_words, "offset too large"); 103 q -= offset; 104 return q; 105 } 106 107 inline HeapWord* 108 G1BlockOffsetArray:: 109 forward_to_block_containing_addr_const(HeapWord* q, HeapWord* n, 110 const void* addr) const { 111 if (addr >= gsp()->top()) return gsp()->top(); 112 while (n <= addr) { 113 q = n; 114 oop obj = oop(q); 115 if (obj->klass_or_null() == NULL) return q; 116 n += block_size(q); 117 } 118 assert(q <= n, "wrong order for q and addr"); 119 assert(addr < n, "wrong order for addr and n"); 120 return q; 121 } 122 123 inline HeapWord* 124 G1BlockOffsetArray::forward_to_block_containing_addr(HeapWord* q, 125 const void* addr) { 126 if (oop(q)->klass_or_null() == NULL) return q; 127 HeapWord* n = q + block_size(q); 128 // In the normal case, where the query "addr" is a card boundary, and the 129 // offset table chunks are the same size as cards, the block starting at 130 // "q" will contain addr, so the test below will fail, and we'll fall 131 // through quickly. 132 if (n <= addr) { 133 q = forward_to_block_containing_addr_slow(q, n, addr); 134 } 135 assert(q <= addr, "wrong order for current and arg"); 136 return q; 137 } 138 139 ////////////////////////////////////////////////////////////////////////// 140 // BlockOffsetArrayNonContigSpace inlines 141 ////////////////////////////////////////////////////////////////////////// 142 inline void G1BlockOffsetArray::freed(HeapWord* blk_start, HeapWord* blk_end) { 143 // Verify that the BOT shows [blk_start, blk_end) to be one block. 144 verify_single_block(blk_start, blk_end); 145 // adjust _unallocated_block upward or downward 146 // as appropriate 147 if (BlockOffsetArrayUseUnallocatedBlock) { 148 assert(_unallocated_block <= _end, 149 "Inconsistent value for _unallocated_block"); 150 if (blk_end >= _unallocated_block && blk_start <= _unallocated_block) { 151 // CMS-specific note: a block abutting _unallocated_block to 152 // its left is being freed, a new block is being added or 153 // we are resetting following a compaction 154 _unallocated_block = blk_start; 155 } 156 } 157 } 158 159 inline void G1BlockOffsetArray::freed(HeapWord* blk, size_t size) { 160 freed(blk, blk + size); 161 } 162 163 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1BLOCKOFFSETTABLE_INLINE_HPP