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