duke@435: /* mikael@4153: * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. duke@435: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@435: * duke@435: * This code is free software; you can redistribute it and/or modify it duke@435: * under the terms of the GNU General Public License version 2 only, as duke@435: * published by the Free Software Foundation. duke@435: * duke@435: * This code is distributed in the hope that it will be useful, but WITHOUT duke@435: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@435: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@435: * version 2 for more details (a copy is included in the LICENSE file that duke@435: * accompanied this code). duke@435: * duke@435: * You should have received a copy of the GNU General Public License version duke@435: * 2 along with this work; if not, write to the Free Software Foundation, duke@435: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@435: * trims@1907: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA trims@1907: * or visit www.oracle.com if you need additional information or have any trims@1907: * questions. duke@435: * duke@435: */ duke@435: stefank@2314: #ifndef SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_OBJECTSTARTARRAY_HPP stefank@2314: #define SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_OBJECTSTARTARRAY_HPP stefank@2314: stefank@2314: #include "gc_implementation/parallelScavenge/psVirtualspace.hpp" stefank@2314: #include "memory/allocation.hpp" stefank@2314: #include "memory/memRegion.hpp" stefank@2314: #include "oops/oop.hpp" stefank@2314: duke@435: // duke@435: // This class can be used to locate the beginning of an object in the duke@435: // covered region. duke@435: // duke@435: zgu@3900: class ObjectStartArray : public CHeapObj { duke@435: friend class VerifyObjectStartArrayClosure; duke@435: duke@435: private: duke@435: PSVirtualSpace _virtual_space; duke@435: MemRegion _reserved_region; duke@435: MemRegion _covered_region; duke@435: MemRegion _blocks_region; duke@435: jbyte* _raw_base; duke@435: jbyte* _offset_base; duke@435: duke@435: public: duke@435: duke@435: enum BlockValueConstants { duke@435: clean_block = -1 duke@435: }; duke@435: duke@435: enum BlockSizeConstants { duke@435: block_shift = 9, duke@435: block_size = 1 << block_shift, duke@435: block_size_in_words = block_size / sizeof(HeapWord) duke@435: }; duke@435: duke@435: protected: duke@435: duke@435: // Mapping from address to object start array entry duke@435: jbyte* block_for_addr(void* p) const { duke@435: assert(_covered_region.contains(p), duke@435: "out of bounds access to object start array"); duke@435: jbyte* result = &_offset_base[uintptr_t(p) >> block_shift]; duke@435: assert(_blocks_region.contains(result), duke@435: "out of bounds result in byte_for"); duke@435: return result; duke@435: } duke@435: duke@435: // Mapping from object start array entry to address of first word duke@435: HeapWord* addr_for_block(jbyte* p) { duke@435: assert(_blocks_region.contains(p), duke@435: "out of bounds access to object start array"); duke@435: size_t delta = pointer_delta(p, _offset_base, sizeof(jbyte)); duke@435: HeapWord* result = (HeapWord*) (delta << block_shift); duke@435: assert(_covered_region.contains(result), duke@435: "out of bounds accessor from card marking array"); duke@435: return result; duke@435: } duke@435: duke@435: // Mapping that includes the derived offset. duke@435: // If the block is clean, returns the last address in the covered region. duke@435: // If the block is < index 0, returns the start of the covered region. duke@435: HeapWord* offset_addr_for_block (jbyte* p) const { duke@435: // We have to do this before the assert duke@435: if (p < _raw_base) { duke@435: return _covered_region.start(); duke@435: } duke@435: duke@435: assert(_blocks_region.contains(p), duke@435: "out of bounds access to object start array"); duke@435: duke@435: if (*p == clean_block) { duke@435: return _covered_region.end(); duke@435: } duke@435: duke@435: size_t delta = pointer_delta(p, _offset_base, sizeof(jbyte)); duke@435: HeapWord* result = (HeapWord*) (delta << block_shift); duke@435: result += *p; duke@435: duke@435: assert(_covered_region.contains(result), duke@435: "out of bounds accessor from card marking array"); duke@435: duke@435: return result; duke@435: } duke@435: duke@435: public: duke@435: duke@435: // This method is in lieu of a constructor, so that this class can be duke@435: // embedded inline in other classes. duke@435: void initialize(MemRegion reserved_region); duke@435: duke@435: void set_covered_region(MemRegion mr); duke@435: duke@435: void reset(); duke@435: duke@435: MemRegion covered_region() { return _covered_region; } duke@435: duke@435: void allocate_block(HeapWord* p) { duke@435: assert(_covered_region.contains(p), "Must be in covered region"); duke@435: jbyte* block = block_for_addr(p); duke@435: HeapWord* block_base = addr_for_block(block); duke@435: size_t offset = pointer_delta(p, block_base, sizeof(HeapWord*)); duke@435: assert(offset < 128, "Sanity"); duke@435: // When doing MT offsets, we can't assert this. duke@435: //assert(offset > *block, "Found backwards allocation"); duke@435: *block = (jbyte)offset; duke@435: duke@435: // tty->print_cr("[%p]", p); duke@435: } duke@435: duke@435: // Optimized for finding the first object that crosses into duke@435: // a given block. The blocks contain the offset of the last duke@435: // object in that block. Scroll backwards by one, and the first twisti@1040: // object hit should be at the beginning of the block duke@435: HeapWord* object_start(HeapWord* addr) const { duke@435: assert(_covered_region.contains(addr), "Must be in covered region"); duke@435: jbyte* block = block_for_addr(addr); duke@435: HeapWord* scroll_forward = offset_addr_for_block(block--); duke@435: while (scroll_forward > addr) { duke@435: scroll_forward = offset_addr_for_block(block--); duke@435: } duke@435: duke@435: HeapWord* next = scroll_forward; duke@435: while (next <= addr) { duke@435: scroll_forward = next; duke@435: next += oop(next)->size(); duke@435: } duke@435: assert(scroll_forward <= addr, "wrong order for current and arg"); duke@435: assert(addr <= next, "wrong order for arg and next"); duke@435: return scroll_forward; duke@435: } duke@435: duke@435: bool is_block_allocated(HeapWord* addr) { duke@435: assert(_covered_region.contains(addr), "Must be in covered region"); duke@435: jbyte* block = block_for_addr(addr); duke@435: if (*block == clean_block) duke@435: return false; duke@435: duke@435: return true; duke@435: } duke@435: duke@435: // Return true if an object starts in the range of heap addresses. duke@435: // If an object starts at an address corresponding to duke@435: // "start", the method will return true. duke@435: bool object_starts_in_range(HeapWord* start_addr, HeapWord* end_addr) const; duke@435: }; stefank@2314: stefank@2314: #endif // SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_OBJECTSTARTARRAY_HPP