src/share/vm/opto/indexSet.hpp

Thu, 12 Mar 2009 18:16:36 -0700

author
trims
date
Thu, 12 Mar 2009 18:16:36 -0700
changeset 1063
7bb995fbd3c0
parent 435
a61af66fc99e
child 1907
c18cbe5936b8
permissions
-rw-r--r--

Merge

duke@435 1 /*
duke@435 2 * Copyright 1998-2005 Sun Microsystems, Inc. All Rights Reserved.
duke@435 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@435 4 *
duke@435 5 * This code is free software; you can redistribute it and/or modify it
duke@435 6 * under the terms of the GNU General Public License version 2 only, as
duke@435 7 * published by the Free Software Foundation.
duke@435 8 *
duke@435 9 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@435 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@435 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@435 12 * version 2 for more details (a copy is included in the LICENSE file that
duke@435 13 * accompanied this code).
duke@435 14 *
duke@435 15 * You should have received a copy of the GNU General Public License version
duke@435 16 * 2 along with this work; if not, write to the Free Software Foundation,
duke@435 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@435 18 *
duke@435 19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
duke@435 20 * CA 95054 USA or visit www.sun.com if you need additional information or
duke@435 21 * have any questions.
duke@435 22 *
duke@435 23 */
duke@435 24
duke@435 25 // This file defines the IndexSet class, a set of sparse integer indices.
duke@435 26 // This data structure is used by the compiler in its liveness analysis and
duke@435 27 // during register allocation.
duke@435 28
duke@435 29 //-------------------------------- class IndexSet ----------------------------
duke@435 30 // An IndexSet is a piece-wise bitvector. At the top level, we have an array
duke@435 31 // of pointers to bitvector chunks called BitBlocks. Each BitBlock has a fixed
duke@435 32 // size and is allocated from a shared free list. The bits which are set in
duke@435 33 // each BitBlock correspond to the elements of the set.
duke@435 34
duke@435 35 class IndexSet : public ResourceObj {
duke@435 36 friend class IndexSetIterator;
duke@435 37
duke@435 38 public:
duke@435 39 // When we allocate an IndexSet, it starts off with an array of top level block
duke@435 40 // pointers of a set length. This size is intended to be large enough for the
duke@435 41 // majority of IndexSets. In the cases when this size is not large enough,
duke@435 42 // a separately allocated array is used.
duke@435 43
duke@435 44 // The length of the preallocated top level block array
duke@435 45 enum { preallocated_block_list_size = 16 };
duke@435 46
duke@435 47 // Elements of a IndexSet get decomposed into three fields. The highest order
duke@435 48 // bits are the block index, which tell which high level block holds the element.
duke@435 49 // Within that block, the word index indicates which word holds the element.
duke@435 50 // Finally, the bit index determines which single bit within that word indicates
duke@435 51 // membership of the element in the set.
duke@435 52
duke@435 53 // The lengths of the index bitfields
duke@435 54 enum { bit_index_length = 5,
duke@435 55 word_index_length = 3,
duke@435 56 block_index_length = 8 // not used
duke@435 57 };
duke@435 58
duke@435 59 // Derived constants used for manipulating the index bitfields
duke@435 60 enum {
duke@435 61 bit_index_offset = 0, // not used
duke@435 62 word_index_offset = bit_index_length,
duke@435 63 block_index_offset = bit_index_length + word_index_length,
duke@435 64
duke@435 65 bits_per_word = 1 << bit_index_length,
duke@435 66 words_per_block = 1 << word_index_length,
duke@435 67 bits_per_block = bits_per_word * words_per_block,
duke@435 68
duke@435 69 bit_index_mask = right_n_bits(bit_index_length),
duke@435 70 word_index_mask = right_n_bits(word_index_length)
duke@435 71 };
duke@435 72
duke@435 73 // These routines are used for extracting the block, word, and bit index
duke@435 74 // from an element.
duke@435 75 static uint get_block_index(uint element) {
duke@435 76 return element >> block_index_offset;
duke@435 77 }
duke@435 78 static uint get_word_index(uint element) {
duke@435 79 return mask_bits(element >> word_index_offset,word_index_mask);
duke@435 80 }
duke@435 81 static uint get_bit_index(uint element) {
duke@435 82 return mask_bits(element,bit_index_mask);
duke@435 83 }
duke@435 84
duke@435 85 //------------------------------ class BitBlock ----------------------------
duke@435 86 // The BitBlock class is a segment of a bitvector set.
duke@435 87
duke@435 88 class BitBlock : public ResourceObj {
duke@435 89 friend class IndexSetIterator;
duke@435 90 friend class IndexSet;
duke@435 91
duke@435 92 private:
duke@435 93 // All of BitBlocks fields and methods are declared private. We limit
duke@435 94 // access to IndexSet and IndexSetIterator.
duke@435 95
duke@435 96 // A BitBlock is composed of some number of 32 bit words. When a BitBlock
duke@435 97 // is not in use by any IndexSet, it is stored on a free list. The next field
duke@435 98 // is used by IndexSet to mainting this free list.
duke@435 99
duke@435 100 union {
duke@435 101 uint32 _words[words_per_block];
duke@435 102 BitBlock *_next;
duke@435 103 } _data;
duke@435 104
duke@435 105 // accessors
duke@435 106 uint32 *words() { return _data._words; }
duke@435 107 void set_next(BitBlock *next) { _data._next = next; }
duke@435 108 BitBlock *next() { return _data._next; }
duke@435 109
duke@435 110 // Operations. A BitBlock supports four simple operations,
duke@435 111 // clear(), member(), insert(), and remove(). These methods do
duke@435 112 // not assume that the block index has been masked out.
duke@435 113
duke@435 114 void clear() {
duke@435 115 memset(words(), 0, sizeof(uint32) * words_per_block);
duke@435 116 }
duke@435 117
duke@435 118 bool member(uint element) {
duke@435 119 uint word_index = IndexSet::get_word_index(element);
duke@435 120 uint bit_index = IndexSet::get_bit_index(element);
duke@435 121
duke@435 122 return ((words()[word_index] & (uint32)(0x1 << bit_index)) != 0);
duke@435 123 }
duke@435 124
duke@435 125 bool insert(uint element) {
duke@435 126 uint word_index = IndexSet::get_word_index(element);
duke@435 127 uint bit_index = IndexSet::get_bit_index(element);
duke@435 128
duke@435 129 uint32 bit = (0x1 << bit_index);
duke@435 130 uint32 before = words()[word_index];
duke@435 131 words()[word_index] = before | bit;
duke@435 132 return ((before & bit) != 0);
duke@435 133 }
duke@435 134
duke@435 135 bool remove(uint element) {
duke@435 136 uint word_index = IndexSet::get_word_index(element);
duke@435 137 uint bit_index = IndexSet::get_bit_index(element);
duke@435 138
duke@435 139 uint32 bit = (0x1 << bit_index);
duke@435 140 uint32 before = words()[word_index];
duke@435 141 words()[word_index] = before & ~bit;
duke@435 142 return ((before & bit) != 0);
duke@435 143 }
duke@435 144 };
duke@435 145
duke@435 146 //-------------------------- BitBlock allocation ---------------------------
duke@435 147 private:
duke@435 148
duke@435 149 // All IndexSets share an arena from which they allocate BitBlocks. Unused
duke@435 150 // BitBlocks are placed on a free list.
duke@435 151
duke@435 152 // The number of BitBlocks to allocate at a time
duke@435 153 enum { bitblock_alloc_chunk_size = 50 };
duke@435 154
duke@435 155 static Arena *arena() { return Compile::current()->indexSet_arena(); }
duke@435 156
duke@435 157 static void populate_free_list();
duke@435 158
duke@435 159 public:
duke@435 160
duke@435 161 // Invalidate the current free BitBlock list and begin allocation
duke@435 162 // from a new arena. It is essential that this method is called whenever
duke@435 163 // the Arena being used for BitBlock allocation is reset.
duke@435 164 static void reset_memory(Compile* compile, Arena *arena) {
duke@435 165 compile->set_indexSet_free_block_list(NULL);
duke@435 166 compile->set_indexSet_arena(arena);
duke@435 167
duke@435 168 // This should probably be done in a static initializer
duke@435 169 _empty_block.clear();
duke@435 170 }
duke@435 171
duke@435 172 private:
duke@435 173 friend class BitBlock;
duke@435 174 // A distinguished BitBlock which always remains empty. When a new IndexSet is
duke@435 175 // created, all of its top level BitBlock pointers are initialized to point to
duke@435 176 // this.
duke@435 177 static BitBlock _empty_block;
duke@435 178
duke@435 179 //-------------------------- Members ------------------------------------------
duke@435 180
duke@435 181 // The number of elements in the set
duke@435 182 uint _count;
duke@435 183
duke@435 184 // Our top level array of bitvector segments
duke@435 185 BitBlock **_blocks;
duke@435 186
duke@435 187 BitBlock *_preallocated_block_list[preallocated_block_list_size];
duke@435 188
duke@435 189 // The number of top level array entries in use
duke@435 190 uint _max_blocks;
duke@435 191
duke@435 192 // Our assertions need to know the maximum number allowed in the set
duke@435 193 #ifdef ASSERT
duke@435 194 uint _max_elements;
duke@435 195 #endif
duke@435 196
duke@435 197 // The next IndexSet on the free list (not used at same time as count)
duke@435 198 IndexSet *_next;
duke@435 199
duke@435 200 public:
duke@435 201 //-------------------------- Free list operations ------------------------------
duke@435 202 // Individual IndexSets can be placed on a free list. This is done in PhaseLive.
duke@435 203
duke@435 204 IndexSet *next() {
duke@435 205 #ifdef ASSERT
duke@435 206 if( VerifyOpto ) {
duke@435 207 check_watch("removed from free list?", ((_next == NULL) ? 0 : _next->_serial_number));
duke@435 208 }
duke@435 209 #endif
duke@435 210 return _next;
duke@435 211 }
duke@435 212
duke@435 213 void set_next(IndexSet *next) {
duke@435 214 #ifdef ASSERT
duke@435 215 if( VerifyOpto ) {
duke@435 216 check_watch("put on free list?", ((next == NULL) ? 0 : next->_serial_number));
duke@435 217 }
duke@435 218 #endif
duke@435 219 _next = next;
duke@435 220 }
duke@435 221
duke@435 222 private:
duke@435 223 //-------------------------- Utility methods -----------------------------------
duke@435 224
duke@435 225 // Get the block which holds element
duke@435 226 BitBlock *get_block_containing(uint element) const {
duke@435 227 assert(element < _max_elements, "element out of bounds");
duke@435 228 return _blocks[get_block_index(element)];
duke@435 229 }
duke@435 230
duke@435 231 // Set a block in the top level array
duke@435 232 void set_block(uint index, BitBlock *block) {
duke@435 233 #ifdef ASSERT
duke@435 234 if( VerifyOpto )
duke@435 235 check_watch("set block", index);
duke@435 236 #endif
duke@435 237 _blocks[index] = block;
duke@435 238 }
duke@435 239
duke@435 240 // Get a BitBlock from the free list
duke@435 241 BitBlock *alloc_block();
duke@435 242
duke@435 243 // Get a BitBlock from the free list and place it in the top level array
duke@435 244 BitBlock *alloc_block_containing(uint element);
duke@435 245
duke@435 246 // Free a block from the top level array, placing it on the free BitBlock list
duke@435 247 void free_block(uint i);
duke@435 248
duke@435 249 public:
duke@435 250 //-------------------------- Primitive set operations --------------------------
duke@435 251
duke@435 252 void clear() {
duke@435 253 #ifdef ASSERT
duke@435 254 if( VerifyOpto )
duke@435 255 check_watch("clear");
duke@435 256 #endif
duke@435 257 _count = 0;
duke@435 258 for (uint i = 0; i < _max_blocks; i++) {
duke@435 259 BitBlock *block = _blocks[i];
duke@435 260 if (block != &_empty_block) {
duke@435 261 free_block(i);
duke@435 262 }
duke@435 263 }
duke@435 264 }
duke@435 265
duke@435 266 uint count() const { return _count; }
duke@435 267
duke@435 268 bool is_empty() const { return _count == 0; }
duke@435 269
duke@435 270 bool member(uint element) const {
duke@435 271 return get_block_containing(element)->member(element);
duke@435 272 }
duke@435 273
duke@435 274 bool insert(uint element) {
duke@435 275 #ifdef ASSERT
duke@435 276 if( VerifyOpto )
duke@435 277 check_watch("insert", element);
duke@435 278 #endif
duke@435 279 if (element == 0) {
duke@435 280 return 0;
duke@435 281 }
duke@435 282 BitBlock *block = get_block_containing(element);
duke@435 283 if (block == &_empty_block) {
duke@435 284 block = alloc_block_containing(element);
duke@435 285 }
duke@435 286 bool present = block->insert(element);
duke@435 287 if (!present) {
duke@435 288 _count++;
duke@435 289 }
duke@435 290 return !present;
duke@435 291 }
duke@435 292
duke@435 293 bool remove(uint element) {
duke@435 294 #ifdef ASSERT
duke@435 295 if( VerifyOpto )
duke@435 296 check_watch("remove", element);
duke@435 297 #endif
duke@435 298
duke@435 299 BitBlock *block = get_block_containing(element);
duke@435 300 bool present = block->remove(element);
duke@435 301 if (present) {
duke@435 302 _count--;
duke@435 303 }
duke@435 304 return present;
duke@435 305 }
duke@435 306
duke@435 307 //-------------------------- Compound set operations ------------------------
duke@435 308 // Compute the union of all elements of one and two which interfere
duke@435 309 // with the RegMask mask. If the degree of the union becomes
duke@435 310 // exceeds fail_degree, the union bails out. The underlying set is
duke@435 311 // cleared before the union is performed.
duke@435 312 uint lrg_union(uint lr1, uint lr2,
duke@435 313 const uint fail_degree,
duke@435 314 const class PhaseIFG *ifg,
duke@435 315 const RegMask &mask);
duke@435 316
duke@435 317
duke@435 318 //------------------------- Construction, initialization -----------------------
duke@435 319
duke@435 320 IndexSet() {}
duke@435 321
duke@435 322 // This constructor is used for making a deep copy of a IndexSet.
duke@435 323 IndexSet(IndexSet *set);
duke@435 324
duke@435 325 // Perform initialization on a IndexSet
duke@435 326 void initialize(uint max_element);
duke@435 327
duke@435 328 // Initialize a IndexSet. If the top level BitBlock array needs to be
duke@435 329 // allocated, do it from the proffered arena. BitBlocks are still allocated
duke@435 330 // from the static Arena member.
duke@435 331 void initialize(uint max_element, Arena *arena);
duke@435 332
duke@435 333 // Exchange two sets
duke@435 334 void swap(IndexSet *set);
duke@435 335
duke@435 336 //-------------------------- Debugging and statistics --------------------------
duke@435 337
duke@435 338 #ifndef PRODUCT
duke@435 339 // Output a IndexSet for debugging
duke@435 340 void dump() const;
duke@435 341 #endif
duke@435 342
duke@435 343 #ifdef ASSERT
duke@435 344 void tally_iteration_statistics() const;
duke@435 345
duke@435 346 // BitBlock allocation statistics
duke@435 347 static uint _alloc_new;
duke@435 348 static uint _alloc_total;
duke@435 349
duke@435 350 // Block density statistics
duke@435 351 static long _total_bits;
duke@435 352 static long _total_used_blocks;
duke@435 353 static long _total_unused_blocks;
duke@435 354
duke@435 355 // Sanity tests
duke@435 356 void verify() const;
duke@435 357
duke@435 358 static int _serial_count;
duke@435 359 int _serial_number;
duke@435 360
duke@435 361 // Check to see if the serial number of the current set is the one we're tracing.
duke@435 362 // If it is, print a message.
duke@435 363 void check_watch(const char *operation, uint operand) const {
duke@435 364 if (IndexSetWatch != 0) {
duke@435 365 if (IndexSetWatch == -1 || _serial_number == IndexSetWatch) {
duke@435 366 tty->print_cr("IndexSet %d : %s ( %d )", _serial_number, operation, operand);
duke@435 367 }
duke@435 368 }
duke@435 369 }
duke@435 370 void check_watch(const char *operation) const {
duke@435 371 if (IndexSetWatch != 0) {
duke@435 372 if (IndexSetWatch == -1 || _serial_number == IndexSetWatch) {
duke@435 373 tty->print_cr("IndexSet %d : %s", _serial_number, operation);
duke@435 374 }
duke@435 375 }
duke@435 376 }
duke@435 377
duke@435 378 public:
duke@435 379 static void print_statistics();
duke@435 380
duke@435 381 #endif
duke@435 382 };
duke@435 383
duke@435 384
duke@435 385 //-------------------------------- class IndexSetIterator --------------------
duke@435 386 // An iterator for IndexSets.
duke@435 387
duke@435 388 class IndexSetIterator VALUE_OBJ_CLASS_SPEC {
duke@435 389 friend class IndexSet;
duke@435 390
duke@435 391 public:
duke@435 392
duke@435 393 // We walk over the bits in a word in chunks of size window_size.
duke@435 394 enum { window_size = 5,
duke@435 395 window_mask = right_n_bits(window_size),
duke@435 396 table_size = (1 << window_size) };
duke@435 397
duke@435 398 // For an integer of length window_size, what is the first set bit?
duke@435 399 static const byte _first_bit[table_size];
duke@435 400
duke@435 401 // For an integer of length window_size, what is the second set bit?
duke@435 402 static const byte _second_bit[table_size];
duke@435 403
duke@435 404 private:
duke@435 405 // The current word we are inspecting
duke@435 406 uint32 _current;
duke@435 407
duke@435 408 // What element number are we currently on?
duke@435 409 uint _value;
duke@435 410
duke@435 411 // The index of the next word we will inspect
duke@435 412 uint _next_word;
duke@435 413
duke@435 414 // A pointer to the contents of the current block
duke@435 415 uint32 *_words;
duke@435 416
duke@435 417 // The index of the next block we will inspect
duke@435 418 uint _next_block;
duke@435 419
duke@435 420 // A pointer to the blocks in our set
duke@435 421 IndexSet::BitBlock **_blocks;
duke@435 422
duke@435 423 // The number of blocks in the set
duke@435 424 uint _max_blocks;
duke@435 425
duke@435 426 // If the iterator was created from a non-const set, we replace
duke@435 427 // non-canonical empty blocks with the _empty_block pointer. If
duke@435 428 // _set is NULL, we do no replacement.
duke@435 429 IndexSet *_set;
duke@435 430
duke@435 431 // Advance to the next non-empty word and return the next
duke@435 432 // element in the set.
duke@435 433 uint advance_and_next();
duke@435 434
duke@435 435
duke@435 436 public:
duke@435 437
duke@435 438 // If an iterator is built from a constant set then empty blocks
duke@435 439 // are not canonicalized.
duke@435 440 IndexSetIterator(IndexSet *set);
duke@435 441 IndexSetIterator(const IndexSet *set);
duke@435 442
duke@435 443 // Return the next element of the set. Return 0 when done.
duke@435 444 uint next() {
duke@435 445 uint current = _current;
duke@435 446 if (current != 0) {
duke@435 447 uint value = _value;
duke@435 448 while (mask_bits(current,window_mask) == 0) {
duke@435 449 current >>= window_size;
duke@435 450 value += window_size;
duke@435 451 }
duke@435 452
duke@435 453 uint advance = _second_bit[mask_bits(current,window_mask)];
duke@435 454 _current = current >> advance;
duke@435 455 _value = value + advance;
duke@435 456 return value + _first_bit[mask_bits(current,window_mask)];
duke@435 457 } else {
duke@435 458 return advance_and_next();
duke@435 459 }
duke@435 460 }
duke@435 461 };

mercurial