Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/opto/indexSet.hpp
32285 views
/*1* Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#ifndef SHARE_VM_OPTO_INDEXSET_HPP25#define SHARE_VM_OPTO_INDEXSET_HPP2627#include "memory/allocation.hpp"28#include "memory/resourceArea.hpp"29#include "opto/compile.hpp"30#include "opto/regmask.hpp"3132// This file defines the IndexSet class, a set of sparse integer indices.33// This data structure is used by the compiler in its liveness analysis and34// during register allocation.3536//-------------------------------- class IndexSet ----------------------------37// An IndexSet is a piece-wise bitvector. At the top level, we have an array38// of pointers to bitvector chunks called BitBlocks. Each BitBlock has a fixed39// size and is allocated from a shared free list. The bits which are set in40// each BitBlock correspond to the elements of the set.4142class IndexSet : public ResourceObj {43friend class IndexSetIterator;4445public:46// When we allocate an IndexSet, it starts off with an array of top level block47// pointers of a set length. This size is intended to be large enough for the48// majority of IndexSets. In the cases when this size is not large enough,49// a separately allocated array is used.5051// The length of the preallocated top level block array52enum { preallocated_block_list_size = 16 };5354// Elements of a IndexSet get decomposed into three fields. The highest order55// bits are the block index, which tell which high level block holds the element.56// Within that block, the word index indicates which word holds the element.57// Finally, the bit index determines which single bit within that word indicates58// membership of the element in the set.5960// The lengths of the index bitfields61enum { bit_index_length = 5,62word_index_length = 3,63block_index_length = 8 // not used64};6566// Derived constants used for manipulating the index bitfields67enum {68bit_index_offset = 0, // not used69word_index_offset = bit_index_length,70block_index_offset = bit_index_length + word_index_length,7172bits_per_word = 1 << bit_index_length,73words_per_block = 1 << word_index_length,74bits_per_block = bits_per_word * words_per_block,7576bit_index_mask = right_n_bits(bit_index_length),77word_index_mask = right_n_bits(word_index_length)78};7980// These routines are used for extracting the block, word, and bit index81// from an element.82static uint get_block_index(uint element) {83return element >> block_index_offset;84}85static uint get_word_index(uint element) {86return mask_bits(element >> word_index_offset,word_index_mask);87}88static uint get_bit_index(uint element) {89return mask_bits(element,bit_index_mask);90}9192//------------------------------ class BitBlock ----------------------------93// The BitBlock class is a segment of a bitvector set.9495class BitBlock : public ResourceObj {96friend class IndexSetIterator;97friend class IndexSet;9899private:100// All of BitBlocks fields and methods are declared private. We limit101// access to IndexSet and IndexSetIterator.102103// A BitBlock is composed of some number of 32 bit words. When a BitBlock104// is not in use by any IndexSet, it is stored on a free list. The next field105// is used by IndexSet to mainting this free list.106107union {108uint32 _words[words_per_block];109BitBlock *_next;110} _data;111112// accessors113uint32 *words() { return _data._words; }114void set_next(BitBlock *next) { _data._next = next; }115BitBlock *next() { return _data._next; }116117// Operations. A BitBlock supports four simple operations,118// clear(), member(), insert(), and remove(). These methods do119// not assume that the block index has been masked out.120121void clear() {122memset(words(), 0, sizeof(uint32) * words_per_block);123}124125bool member(uint element) {126uint word_index = IndexSet::get_word_index(element);127uint bit_index = IndexSet::get_bit_index(element);128129return ((words()[word_index] & (uint32)(0x1 << bit_index)) != 0);130}131132bool insert(uint element) {133uint word_index = IndexSet::get_word_index(element);134uint bit_index = IndexSet::get_bit_index(element);135136uint32 bit = (0x1 << bit_index);137uint32 before = words()[word_index];138words()[word_index] = before | bit;139return ((before & bit) != 0);140}141142bool remove(uint element) {143uint word_index = IndexSet::get_word_index(element);144uint bit_index = IndexSet::get_bit_index(element);145146uint32 bit = (0x1 << bit_index);147uint32 before = words()[word_index];148words()[word_index] = before & ~bit;149return ((before & bit) != 0);150}151};152153//-------------------------- BitBlock allocation ---------------------------154private:155156// All IndexSets share an arena from which they allocate BitBlocks. Unused157// BitBlocks are placed on a free list.158159// The number of BitBlocks to allocate at a time160enum { bitblock_alloc_chunk_size = 50 };161162static Arena *arena() { return Compile::current()->indexSet_arena(); }163164static void populate_free_list();165166public:167168// Invalidate the current free BitBlock list and begin allocation169// from a new arena. It is essential that this method is called whenever170// the Arena being used for BitBlock allocation is reset.171static void reset_memory(Compile* compile, Arena *arena) {172compile->set_indexSet_free_block_list(NULL);173compile->set_indexSet_arena(arena);174175// This should probably be done in a static initializer176_empty_block.clear();177}178179private:180friend class BitBlock;181// A distinguished BitBlock which always remains empty. When a new IndexSet is182// created, all of its top level BitBlock pointers are initialized to point to183// this.184static BitBlock _empty_block;185186//-------------------------- Members ------------------------------------------187188// The number of elements in the set189uint _count;190191// Our top level array of bitvector segments192BitBlock **_blocks;193194BitBlock *_preallocated_block_list[preallocated_block_list_size];195196// The number of top level array entries in use197uint _max_blocks;198199// Our assertions need to know the maximum number allowed in the set200#ifdef ASSERT201uint _max_elements;202#endif203204// The next IndexSet on the free list (not used at same time as count)205IndexSet *_next;206207public:208//-------------------------- Free list operations ------------------------------209// Individual IndexSets can be placed on a free list. This is done in PhaseLive.210211IndexSet *next() {212#ifdef ASSERT213if( VerifyOpto ) {214check_watch("removed from free list?", ((_next == NULL) ? 0 : _next->_serial_number));215}216#endif217return _next;218}219220void set_next(IndexSet *next) {221#ifdef ASSERT222if( VerifyOpto ) {223check_watch("put on free list?", ((next == NULL) ? 0 : next->_serial_number));224}225#endif226_next = next;227}228229private:230//-------------------------- Utility methods -----------------------------------231232// Get the block which holds element233BitBlock *get_block_containing(uint element) const {234assert(element < _max_elements, "element out of bounds");235return _blocks[get_block_index(element)];236}237238// Set a block in the top level array239void set_block(uint index, BitBlock *block) {240#ifdef ASSERT241if( VerifyOpto )242check_watch("set block", index);243#endif244_blocks[index] = block;245}246247// Get a BitBlock from the free list248BitBlock *alloc_block();249250// Get a BitBlock from the free list and place it in the top level array251BitBlock *alloc_block_containing(uint element);252253// Free a block from the top level array, placing it on the free BitBlock list254void free_block(uint i);255256public:257//-------------------------- Primitive set operations --------------------------258259void clear() {260#ifdef ASSERT261if( VerifyOpto )262check_watch("clear");263#endif264_count = 0;265for (uint i = 0; i < _max_blocks; i++) {266BitBlock *block = _blocks[i];267if (block != &_empty_block) {268free_block(i);269}270}271}272273uint count() const { return _count; }274275bool is_empty() const { return _count == 0; }276277bool member(uint element) const {278return get_block_containing(element)->member(element);279}280281bool insert(uint element) {282#ifdef ASSERT283if( VerifyOpto )284check_watch("insert", element);285#endif286if (element == 0) {287return 0;288}289BitBlock *block = get_block_containing(element);290if (block == &_empty_block) {291block = alloc_block_containing(element);292}293bool present = block->insert(element);294if (!present) {295_count++;296}297return !present;298}299300bool remove(uint element) {301#ifdef ASSERT302if( VerifyOpto )303check_watch("remove", element);304#endif305306BitBlock *block = get_block_containing(element);307bool present = block->remove(element);308if (present) {309_count--;310}311return present;312}313314//-------------------------- Compound set operations ------------------------315// Compute the union of all elements of one and two which interfere316// with the RegMask mask. If the degree of the union becomes317// exceeds fail_degree, the union bails out. The underlying set is318// cleared before the union is performed.319uint lrg_union(uint lr1, uint lr2,320const uint fail_degree,321const class PhaseIFG *ifg,322const RegMask &mask);323324325//------------------------- Construction, initialization -----------------------326327IndexSet() {}328329// This constructor is used for making a deep copy of a IndexSet.330IndexSet(IndexSet *set);331332// Perform initialization on a IndexSet333void initialize(uint max_element);334335// Initialize a IndexSet. If the top level BitBlock array needs to be336// allocated, do it from the proffered arena. BitBlocks are still allocated337// from the static Arena member.338void initialize(uint max_element, Arena *arena);339340// Exchange two sets341void swap(IndexSet *set);342343//-------------------------- Debugging and statistics --------------------------344345#ifndef PRODUCT346// Output a IndexSet for debugging347void dump() const;348#endif349350#ifdef ASSERT351void tally_iteration_statistics() const;352353// BitBlock allocation statistics354static julong _alloc_new;355static julong _alloc_total;356357// Block density statistics358static julong _total_bits;359static julong _total_used_blocks;360static julong _total_unused_blocks;361362// Sanity tests363void verify() const;364365static int _serial_count;366int _serial_number;367368// Check to see if the serial number of the current set is the one we're tracing.369// If it is, print a message.370void check_watch(const char *operation, uint operand) const {371if (IndexSetWatch != 0) {372if (IndexSetWatch == -1 || _serial_number == IndexSetWatch) {373tty->print_cr("IndexSet %d : %s ( %d )", _serial_number, operation, operand);374}375}376}377void check_watch(const char *operation) const {378if (IndexSetWatch != 0) {379if (IndexSetWatch == -1 || _serial_number == IndexSetWatch) {380tty->print_cr("IndexSet %d : %s", _serial_number, operation);381}382}383}384385public:386static void print_statistics();387388#endif389};390391392//-------------------------------- class IndexSetIterator --------------------393// An iterator for IndexSets.394395class IndexSetIterator VALUE_OBJ_CLASS_SPEC {396friend class IndexSet;397398public:399400// We walk over the bits in a word in chunks of size window_size.401enum { window_size = 5,402window_mask = right_n_bits(window_size),403table_size = (1 << window_size) };404405// For an integer of length window_size, what is the first set bit?406static const byte _first_bit[table_size];407408// For an integer of length window_size, what is the second set bit?409static const byte _second_bit[table_size];410411private:412// The current word we are inspecting413uint32 _current;414415// What element number are we currently on?416uint _value;417418// The index of the next word we will inspect419uint _next_word;420421// A pointer to the contents of the current block422uint32 *_words;423424// The index of the next block we will inspect425uint _next_block;426427// A pointer to the blocks in our set428IndexSet::BitBlock **_blocks;429430// The number of blocks in the set431uint _max_blocks;432433// If the iterator was created from a non-const set, we replace434// non-canonical empty blocks with the _empty_block pointer. If435// _set is NULL, we do no replacement.436IndexSet *_set;437438// Advance to the next non-empty word and return the next439// element in the set.440uint advance_and_next();441442443public:444445// If an iterator is built from a constant set then empty blocks446// are not canonicalized.447IndexSetIterator(IndexSet *set);448IndexSetIterator(const IndexSet *set);449450// Return the next element of the set. Return 0 when done.451uint next() {452uint current = _current;453if (current != 0) {454uint value = _value;455while (mask_bits(current,window_mask) == 0) {456current >>= window_size;457value += window_size;458}459460uint advance = _second_bit[mask_bits(current,window_mask)];461_current = current >> advance;462_value = value + advance;463return value + _first_bit[mask_bits(current,window_mask)];464} else {465return advance_and_next();466}467}468};469470#endif // SHARE_VM_OPTO_INDEXSET_HPP471472473