src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp

Print this page
rev 4535 : 6725714: par compact - add a table to speed up bitmap searches
Reviewed-by: jmasa, tschatzl

*** 221,230 **** --- 221,241 ---- // Mask for the bits in a pointer to get an offset within a region. static const size_t RegionAddrOffsetMask; // Mask for the bits in a pointer to get the address of the start of a region. static const size_t RegionAddrMask; + static const size_t Log2BlockSize; + static const size_t BlockSize; + static const size_t BlockSizeBytes; + + static const size_t BlockSizeOffsetMask; + static const size_t BlockAddrOffsetMask; + static const size_t BlockAddrMask; + + static const size_t BlocksPerRegion; + static const size_t Log2BlocksPerRegion; + class RegionData { public: // Destination address of the region. HeapWord* destination() const { return _destination; }
*** 273,282 **** --- 284,299 ---- // been filled, the destination_count should be set to the completed value // (dc_completed). inline uint destination_count() const; inline uint destination_count_raw() const; + // Whether the block table for this region has been filled. + inline bool blocks_filled() const; + + // Number of times the block table was filled. + DEBUG_ONLY(inline size_t blocks_filled_count() const;) + // The location of the java heap data that corresponds to this region. inline HeapWord* data_location() const; // The highest address referenced by objects in this region. inline HeapWord* highest_ref() const;
*** 297,306 **** --- 314,324 ---- void set_deferred_obj_addr(HeapWord* addr) { _partial_obj_addr = addr; } void set_partial_obj_addr(HeapWord* addr) { _partial_obj_addr = addr; } void set_partial_obj_size(size_t words) { _partial_obj_size = (region_sz_t) words; } + inline void set_blocks_filled(); inline void set_destination_count(uint count); inline void set_live_obj_size(size_t words); inline void set_data_location(HeapWord* addr); inline void set_completed();
*** 329,352 **** HeapWord* _destination; size_t _source_region; HeapWord* _partial_obj_addr; region_sz_t _partial_obj_size; region_sz_t volatile _dc_and_los; #ifdef ASSERT // These enable optimizations that are only partially implemented. Use // debug builds to prevent the code fragments from breaking. HeapWord* _data_location; HeapWord* _highest_ref; #endif // #ifdef ASSERT #ifdef ASSERT public: ! uint _pushed; // 0 until region is pushed onto a worker's stack private: #endif }; public: ParallelCompactData(); bool initialize(MemRegion covered_region); size_t region_count() const { return _region_count; } --- 347,389 ---- HeapWord* _destination; size_t _source_region; HeapWord* _partial_obj_addr; region_sz_t _partial_obj_size; region_sz_t volatile _dc_and_los; + bool _blocks_filled; + #ifdef ASSERT + size_t _blocks_filled_count; // Number of block table fills. + // These enable optimizations that are only partially implemented. Use // debug builds to prevent the code fragments from breaking. HeapWord* _data_location; HeapWord* _highest_ref; #endif // #ifdef ASSERT #ifdef ASSERT public: ! uint _pushed; // 0 until region is pushed onto a stack private: #endif }; + // "Blocks" allow shorter sections of the bitmap to be searched. Each Block + // holds an offset, which is the amount of live data in the Region to the left + // of the first live object that starts in the Block. + class BlockData + { + public: + typedef unsigned short int blk_ofs_t; + + blk_ofs_t offset() const { return _offset; } + void set_offset(size_t val) { _offset = (blk_ofs_t)val; } + + private: + blk_ofs_t _offset; + }; + public: ParallelCompactData(); bool initialize(MemRegion covered_region); size_t region_count() const { return _region_count; }
*** 353,364 **** // Convert region indices to/from RegionData pointers. inline RegionData* region(size_t region_idx) const; inline size_t region(const RegionData* const region_ptr) const; ! // Returns true if the given address is contained within the region ! bool region_contains(size_t region_index, HeapWord* addr); void add_obj(HeapWord* addr, size_t len); void add_obj(oop p, size_t len) { add_obj((HeapWord*)p, len); } // Fill in the regions covering [beg, end) so that no data moves; i.e., the --- 390,402 ---- // Convert region indices to/from RegionData pointers. inline RegionData* region(size_t region_idx) const; inline size_t region(const RegionData* const region_ptr) const; ! size_t block_count() const { return _block_count; } ! inline BlockData* block(size_t block_idx) const; ! inline size_t block(const BlockData* block_ptr) const; void add_obj(HeapWord* addr, size_t len); void add_obj(oop p, size_t len) { add_obj((HeapWord*)p, len); } // Fill in the regions covering [beg, end) so that no data moves; i.e., the
*** 394,408 **** inline HeapWord* region_align_down(HeapWord* addr) const; inline HeapWord* region_align_up(HeapWord* addr) const; inline bool is_region_aligned(HeapWord* addr) const; // Return the address one past the end of the partial object. HeapWord* partial_obj_end(size_t region_idx) const; ! // Return the new location of the object p after the ! // the compaction. HeapWord* calc_new_pointer(HeapWord* addr); HeapWord* calc_new_pointer(oop p) { return calc_new_pointer((HeapWord*) p); } --- 432,459 ---- inline HeapWord* region_align_down(HeapWord* addr) const; inline HeapWord* region_align_up(HeapWord* addr) const; inline bool is_region_aligned(HeapWord* addr) const; + // Analogous to region_offset() for blocks. + size_t block_offset(const HeapWord* addr) const; + size_t addr_to_block_idx(const HeapWord* addr) const; + size_t addr_to_block_idx(const oop obj) const { + return addr_to_block_idx((HeapWord*) obj); + } + inline BlockData* addr_to_block_ptr(const HeapWord* addr) const; + inline HeapWord* block_to_addr(size_t block) const; + inline size_t region_to_block_idx(size_t region) const; + + inline HeapWord* block_align_down(HeapWord* addr) const; + inline HeapWord* block_align_up(HeapWord* addr) const; + inline bool is_block_aligned(HeapWord* addr) const; + // Return the address one past the end of the partial object. HeapWord* partial_obj_end(size_t region_idx) const; ! // Return the location of the object after compaction. HeapWord* calc_new_pointer(HeapWord* addr); HeapWord* calc_new_pointer(oop p) { return calc_new_pointer((HeapWord*) p); }
*** 414,423 **** --- 465,475 ---- void verify_clear(const PSVirtualSpace* vspace); void verify_clear(); #endif // #ifdef ASSERT private: + bool initialize_block_data(); bool initialize_region_data(size_t region_size); PSVirtualSpace* create_vspace(size_t count, size_t element_size); private: HeapWord* _region_start;
*** 426,435 **** --- 478,491 ---- #endif // #ifdef ASSERT PSVirtualSpace* _region_vspace; RegionData* _region_data; size_t _region_count; + + PSVirtualSpace* _block_vspace; + BlockData* _block_data; + size_t _block_count; }; inline uint ParallelCompactData::RegionData::destination_count_raw() const {
*** 440,450 **** --- 496,528 ---- ParallelCompactData::RegionData::destination_count() const { return destination_count_raw() >> dc_shift; } + inline bool + ParallelCompactData::RegionData::blocks_filled() const + { + return _blocks_filled; + } + + #ifdef ASSERT + inline size_t + ParallelCompactData::RegionData::blocks_filled_count() const + { + return _blocks_filled_count; + } + #endif // #ifdef ASSERT + inline void + ParallelCompactData::RegionData::set_blocks_filled() + { + _blocks_filled = true; + // Debug builds count the number of times the table was filled. + DEBUG_ONLY(Atomic::inc_ptr(&_blocks_filled_count)); + } + + inline void ParallelCompactData::RegionData::set_destination_count(uint count) { assert(count <= (dc_completed >> dc_shift), "count too large"); const region_sz_t live_sz = (region_sz_t) live_obj_size(); _dc_and_los = (count << dc_shift) | live_sz;
*** 534,543 **** --- 612,627 ---- assert(region_ptr >= _region_data, "bad arg"); assert(region_ptr <= _region_data + region_count(), "bad arg"); return pointer_delta(region_ptr, _region_data, sizeof(RegionData)); } + inline ParallelCompactData::BlockData* + ParallelCompactData::block(size_t n) const { + assert(n < block_count(), "bad arg"); + return _block_data + n; + } + inline size_t ParallelCompactData::region_offset(const HeapWord* addr) const { assert(addr >= _region_start, "bad addr"); assert(addr <= _region_end, "bad addr");
*** 600,609 **** --- 684,750 ---- ParallelCompactData::is_region_aligned(HeapWord* addr) const { return region_offset(addr) == 0; } + inline size_t + ParallelCompactData::block_offset(const HeapWord* addr) const + { + assert(addr >= _region_start, "bad addr"); + assert(addr <= _region_end, "bad addr"); + return (size_t(addr) & BlockAddrOffsetMask) >> LogHeapWordSize; + } + + inline size_t + ParallelCompactData::addr_to_block_idx(const HeapWord* addr) const + { + assert(addr >= _region_start, "bad addr"); + assert(addr <= _region_end, "bad addr"); + return pointer_delta(addr, _region_start) >> Log2BlockSize; + } + + inline ParallelCompactData::BlockData* + ParallelCompactData::addr_to_block_ptr(const HeapWord* addr) const + { + return block(addr_to_block_idx(addr)); + } + + inline HeapWord* + ParallelCompactData::block_to_addr(size_t block) const + { + assert(block < _block_count, "block out of range"); + return _region_start + (block << Log2BlockSize); + } + + inline size_t + ParallelCompactData::region_to_block_idx(size_t region) const + { + return region << Log2BlocksPerRegion; + } + + inline HeapWord* + ParallelCompactData::block_align_down(HeapWord* addr) const + { + assert(addr >= _region_start, "bad addr"); + assert(addr < _region_end + RegionSize, "bad addr"); + return (HeapWord*)(size_t(addr) & BlockAddrMask); + } + + inline HeapWord* + ParallelCompactData::block_align_up(HeapWord* addr) const + { + assert(addr >= _region_start, "bad addr"); + assert(addr <= _region_end, "bad addr"); + return block_align_down(addr + BlockSizeOffsetMask); + } + + inline bool + ParallelCompactData::is_block_aligned(HeapWord* addr) const + { + return block_offset(addr) == 0; + } + // Abstract closure for use with ParMarkBitMap::iterate(), which will invoke the // do_addr() method. // // The closure is initialized with the number of heap words to process // (words_remaining()), and becomes 'full' when it reaches 0. The do_addr()
*** 777,786 **** --- 918,928 ---- class PSParallelCompact : AllStatic { public: // Convenient access to type names. typedef ParMarkBitMap::idx_t idx_t; typedef ParallelCompactData::RegionData RegionData; + typedef ParallelCompactData::BlockData BlockData; typedef enum { perm_space_id, old_space_id, eden_space_id, from_space_id, to_space_id, last_space_id } SpaceId;
*** 985,994 **** --- 1127,1138 ---- static void adjust_roots(); // Serial code executed in preparation for the compaction phase. static void compact_prologue(); + DEBUG_ONLY(static void write_block_fill_histogram(outputStream* const out);) + // Move objects to new locations. static void compact_perm(ParCompactionManager* cm); static void compact(); // Add available regions to the stack and draining tasks to the task queue.
*** 1156,1165 **** --- 1300,1312 ---- static void fill_region(ParCompactionManager* cm, size_t region_idx); static void fill_and_update_region(ParCompactionManager* cm, size_t region) { fill_region(cm, region); } + // Fill in the block table for the specified region. + static void fill_blocks(size_t region_idx); + // Update the deferred objects in the space. static void update_deferred_objects(ParCompactionManager* cm, SpaceId id); static ParMarkBitMap* mark_bitmap() { return &_mark_bitmap; } static ParallelCompactData& summary_data() { return _summary_data; }