1 /* 2 * Copyright (c) 2001, 2012, 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_PARALLELSCAVENGE_OBJECTSTARTARRAY_HPP 26 #define SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_OBJECTSTARTARRAY_HPP 27 28 #include "gc_implementation/parallelScavenge/psVirtualspace.hpp" 29 #include "memory/allocation.hpp" 30 #include "memory/memRegion.hpp" 31 #include "oops/oop.hpp" 32 33 // 34 // This class can be used to locate the beginning of an object in the 35 // covered region. 36 // 37 38 class ObjectStartArray : public CHeapObj<mtGC> { 39 friend class VerifyObjectStartArrayClosure; 40 41 private: 42 PSVirtualSpace _virtual_space; 43 MemRegion _reserved_region; 44 MemRegion _covered_region; 45 MemRegion _blocks_region; 46 jbyte* _raw_base; 47 jbyte* _offset_base; 48 49 public: 50 51 enum BlockValueConstants { 52 clean_block = -1 53 }; 54 55 enum BlockSizeConstants { 56 block_shift = 9, 57 block_size = 1 << block_shift, 58 block_size_in_words = block_size / sizeof(HeapWord) 59 }; 60 61 protected: 62 63 // Mapping from address to object start array entry 64 jbyte* block_for_addr(void* p) const { 65 assert(_covered_region.contains(p), 66 "out of bounds access to object start array"); 67 jbyte* result = &_offset_base[uintptr_t(p) >> block_shift]; 68 assert(_blocks_region.contains(result), 69 "out of bounds result in byte_for"); 70 return result; 71 } 72 73 // Mapping from object start array entry to address of first word 74 HeapWord* addr_for_block(jbyte* p) { 75 assert(_blocks_region.contains(p), 76 "out of bounds access to object start array"); 77 size_t delta = pointer_delta(p, _offset_base, sizeof(jbyte)); 78 HeapWord* result = (HeapWord*) (delta << block_shift); 79 assert(_covered_region.contains(result), 80 "out of bounds accessor from card marking array"); 81 return result; 82 } 83 84 // Mapping that includes the derived offset. 85 // If the block is clean, returns the last address in the covered region. 86 // If the block is < index 0, returns the start of the covered region. 87 HeapWord* offset_addr_for_block (jbyte* p) const { 88 // We have to do this before the assert 89 if (p < _raw_base) { 90 return _covered_region.start(); 91 } 92 93 assert(_blocks_region.contains(p), 94 "out of bounds access to object start array"); 95 96 if (*p == clean_block) { 97 return _covered_region.end(); 98 } 99 100 size_t delta = pointer_delta(p, _offset_base, sizeof(jbyte)); 101 HeapWord* result = (HeapWord*) (delta << block_shift); 102 result += *p; 103 104 assert(_covered_region.contains(result), 105 "out of bounds accessor from card marking array"); 106 107 return result; 108 } 109 110 public: 111 112 // This method is in lieu of a constructor, so that this class can be 113 // embedded inline in other classes. 114 void initialize(MemRegion reserved_region); 115 116 void set_covered_region(MemRegion mr); 117 118 void reset(); 119 120 MemRegion covered_region() { return _covered_region; } 121 122 #define assert_covered_region_contains(addr) \ 123 assert(_covered_region.contains(addr), \ 124 err_msg(#addr " (" PTR_FORMAT ") is not in covered region [" PTR_FORMAT ", " PTR_FORMAT "]", \ 125 p2i(addr), p2i(_covered_region.start()), p2i(_covered_region.end()))) \ 126 127 void allocate_block(HeapWord* p) { 128 assert_covered_region_contains(p); 129 jbyte* block = block_for_addr(p); 130 HeapWord* block_base = addr_for_block(block); 131 size_t offset = pointer_delta(p, block_base, sizeof(HeapWord*)); 132 assert(offset < 128, "Sanity"); 133 // When doing MT offsets, we can't assert this. 134 //assert(offset > *block, "Found backwards allocation"); 135 *block = (jbyte)offset; 136 } 137 138 // Optimized for finding the first object that crosses into 139 // a given block. The blocks contain the offset of the last 140 // object in that block. Scroll backwards by one, and the first 141 // object hit should be at the beginning of the block 142 HeapWord* object_start(HeapWord* addr) const { 143 assert_covered_region_contains(addr); 144 jbyte* block = block_for_addr(addr); 145 HeapWord* scroll_forward = offset_addr_for_block(block--); 146 while (scroll_forward > addr) { 147 scroll_forward = offset_addr_for_block(block--); 148 } 149 150 HeapWord* next = scroll_forward; 151 while (next <= addr) { 152 scroll_forward = next; 153 next += oop(next)->size(); 154 } 155 assert(scroll_forward <= addr, "wrong order for current and arg"); 156 assert(addr <= next, "wrong order for arg and next"); 157 return scroll_forward; 158 } 159 160 bool is_block_allocated(HeapWord* addr) { 161 assert_covered_region_contains(addr); 162 jbyte* block = block_for_addr(addr); 163 if (*block == clean_block) 164 return false; 165 166 return true; 167 } 168 #undef assert_covered_region_contains 169 170 // Return true if an object starts in the range of heap addresses. 171 // If an object starts at an address corresponding to 172 // "start", the method will return true. 173 bool object_starts_in_range(HeapWord* start_addr, HeapWord* end_addr) const; 174 }; 175 176 #endif // SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_OBJECTSTARTARRAY_HPP