src/share/vm/opto/indexSet.hpp

Mon, 27 May 2013 12:56:34 +0200

author
stefank
date
Mon, 27 May 2013 12:56:34 +0200
changeset 5195
95c00927be11
parent 2557
f7de3327c683
child 6876
710a3c8b516e
permissions
-rw-r--r--

8015428: Remove unused CDS support from StringTable
Summary: The string in StringTable is not used by CDS anymore. Remove the unnecessary code in preparation for 8015422: Large performance hit when the StringTable is walked twice in Parallel Scavenge
Reviewed-by: pliden, tschatzl, coleenp

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

mercurial