hotspot/src/share/vm/memory/blockOffsetTable.hpp
author ysr
Mon, 16 Aug 2010 15:58:42 -0700
changeset 6258 68f252c6e825
parent 5547 f4b087cbb361
child 6274 a4a2e26fe2d0
permissions -rw-r--r--
6948538: CMS: BOT walkers can fall into object allocation and initialization cracks Summary: GC workers now recognize an intermediate transient state of blocks which are allocated but have not yet completed initialization. blk_start() calls do not attempt to determine the size of a block in the transient state, rather waiting for the block to become initialized so that it is safe to query its size. Audited and ensured the order of initialization of object fields (klass, free bit and size) to respect block state transition protocol. Also included some new assertion checking code enabled in debug mode. Reviewed-by: chrisphi, johnc, poonam
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
     1
/*
6258
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
     2
 * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
489c9b5090e2 Initial load
duke
parents:
diff changeset
     4
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
489c9b5090e2 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
489c9b5090e2 Initial load
duke
parents:
diff changeset
     7
 * published by the Free Software Foundation.
489c9b5090e2 Initial load
duke
parents:
diff changeset
     8
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
     9
 * This code is distributed in the hope that it will be useful, but WITHOUT
489c9b5090e2 Initial load
duke
parents:
diff changeset
    10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
489c9b5090e2 Initial load
duke
parents:
diff changeset
    11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
489c9b5090e2 Initial load
duke
parents:
diff changeset
    12
 * version 2 for more details (a copy is included in the LICENSE file that
489c9b5090e2 Initial load
duke
parents:
diff changeset
    13
 * accompanied this code).
489c9b5090e2 Initial load
duke
parents:
diff changeset
    14
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    15
 * You should have received a copy of the GNU General Public License version
489c9b5090e2 Initial load
duke
parents:
diff changeset
    16
 * 2 along with this work; if not, write to the Free Software Foundation,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    18
 *
5547
f4b087cbb361 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 5431
diff changeset
    19
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
f4b087cbb361 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 5431
diff changeset
    20
 * or visit www.oracle.com if you need additional information or have any
f4b087cbb361 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 5431
diff changeset
    21
 * questions.
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
    22
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    23
 */
489c9b5090e2 Initial load
duke
parents:
diff changeset
    24
489c9b5090e2 Initial load
duke
parents:
diff changeset
    25
// The CollectedHeap type requires subtypes to implement a method
489c9b5090e2 Initial load
duke
parents:
diff changeset
    26
// "block_start".  For some subtypes, notably generational
489c9b5090e2 Initial load
duke
parents:
diff changeset
    27
// systems using card-table-based write barriers, the efficiency of this
489c9b5090e2 Initial load
duke
parents:
diff changeset
    28
// operation may be important.  Implementations of the "BlockOffsetArray"
489c9b5090e2 Initial load
duke
parents:
diff changeset
    29
// class may be useful in providing such efficient implementations.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    30
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
    31
// BlockOffsetTable (abstract)
489c9b5090e2 Initial load
duke
parents:
diff changeset
    32
//   - BlockOffsetArray (abstract)
489c9b5090e2 Initial load
duke
parents:
diff changeset
    33
//     - BlockOffsetArrayNonContigSpace
489c9b5090e2 Initial load
duke
parents:
diff changeset
    34
//     - BlockOffsetArrayContigSpace
489c9b5090e2 Initial load
duke
parents:
diff changeset
    35
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
    36
489c9b5090e2 Initial load
duke
parents:
diff changeset
    37
class ContiguousSpace;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    38
class SerializeOopClosure;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    39
489c9b5090e2 Initial load
duke
parents:
diff changeset
    40
//////////////////////////////////////////////////////////////////////////
489c9b5090e2 Initial load
duke
parents:
diff changeset
    41
// The BlockOffsetTable "interface"
489c9b5090e2 Initial load
duke
parents:
diff changeset
    42
//////////////////////////////////////////////////////////////////////////
489c9b5090e2 Initial load
duke
parents:
diff changeset
    43
class BlockOffsetTable VALUE_OBJ_CLASS_SPEC {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    44
  friend class VMStructs;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    45
protected:
489c9b5090e2 Initial load
duke
parents:
diff changeset
    46
  // These members describe the region covered by the table.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    47
489c9b5090e2 Initial load
duke
parents:
diff changeset
    48
  // The space this table is covering.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    49
  HeapWord* _bottom;    // == reserved.start
489c9b5090e2 Initial load
duke
parents:
diff changeset
    50
  HeapWord* _end;       // End of currently allocated region.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    51
489c9b5090e2 Initial load
duke
parents:
diff changeset
    52
public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
    53
  // Initialize the table to cover the given space.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    54
  // The contents of the initial table are undefined.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    55
  BlockOffsetTable(HeapWord* bottom, HeapWord* end):
489c9b5090e2 Initial load
duke
parents:
diff changeset
    56
    _bottom(bottom), _end(end) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    57
    assert(_bottom <= _end, "arguments out of order");
489c9b5090e2 Initial load
duke
parents:
diff changeset
    58
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    59
489c9b5090e2 Initial load
duke
parents:
diff changeset
    60
  // Note that the committed size of the covered space may have changed,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    61
  // so the table size might also wish to change.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    62
  virtual void resize(size_t new_word_size) = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    63
489c9b5090e2 Initial load
duke
parents:
diff changeset
    64
  virtual void set_bottom(HeapWord* new_bottom) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    65
    assert(new_bottom <= _end, "new_bottom > _end");
489c9b5090e2 Initial load
duke
parents:
diff changeset
    66
    _bottom = new_bottom;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    67
    resize(pointer_delta(_end, _bottom));
489c9b5090e2 Initial load
duke
parents:
diff changeset
    68
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    69
489c9b5090e2 Initial load
duke
parents:
diff changeset
    70
  // Requires "addr" to be contained by a block, and returns the address of
489c9b5090e2 Initial load
duke
parents:
diff changeset
    71
  // the start of that block.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    72
  virtual HeapWord* block_start_unsafe(const void* addr) const = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    73
489c9b5090e2 Initial load
duke
parents:
diff changeset
    74
  // Returns the address of the start of the block containing "addr", or
489c9b5090e2 Initial load
duke
parents:
diff changeset
    75
  // else "null" if it is covered by no block.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    76
  HeapWord* block_start(const void* addr) const;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    77
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
    78
489c9b5090e2 Initial load
duke
parents:
diff changeset
    79
//////////////////////////////////////////////////////////////////////////
489c9b5090e2 Initial load
duke
parents:
diff changeset
    80
// One implementation of "BlockOffsetTable," the BlockOffsetArray,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    81
// divides the covered region into "N"-word subregions (where
489c9b5090e2 Initial load
duke
parents:
diff changeset
    82
// "N" = 2^"LogN".  An array with an entry for each such subregion
489c9b5090e2 Initial load
duke
parents:
diff changeset
    83
// indicates how far back one must go to find the start of the
489c9b5090e2 Initial load
duke
parents:
diff changeset
    84
// chunk that includes the first word of the subregion.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    85
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
    86
// Each BlockOffsetArray is owned by a Space.  However, the actual array
489c9b5090e2 Initial load
duke
parents:
diff changeset
    87
// may be shared by several BlockOffsetArrays; this is useful
489c9b5090e2 Initial load
duke
parents:
diff changeset
    88
// when a single resizable area (such as a generation) is divided up into
489c9b5090e2 Initial load
duke
parents:
diff changeset
    89
// several spaces in which contiguous allocation takes place.  (Consider,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    90
// for example, the garbage-first generation.)
489c9b5090e2 Initial load
duke
parents:
diff changeset
    91
489c9b5090e2 Initial load
duke
parents:
diff changeset
    92
// Here is the shared array type.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    93
//////////////////////////////////////////////////////////////////////////
489c9b5090e2 Initial load
duke
parents:
diff changeset
    94
// BlockOffsetSharedArray
489c9b5090e2 Initial load
duke
parents:
diff changeset
    95
//////////////////////////////////////////////////////////////////////////
489c9b5090e2 Initial load
duke
parents:
diff changeset
    96
class BlockOffsetSharedArray: public CHeapObj {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    97
  friend class BlockOffsetArray;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    98
  friend class BlockOffsetArrayNonContigSpace;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    99
  friend class BlockOffsetArrayContigSpace;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   100
  friend class VMStructs;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   101
489c9b5090e2 Initial load
duke
parents:
diff changeset
   102
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   103
  enum SomePrivateConstants {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   104
    LogN = 9,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   105
    LogN_words = LogN - LogHeapWordSize,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   106
    N_bytes = 1 << LogN,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   107
    N_words = 1 << LogN_words
489c9b5090e2 Initial load
duke
parents:
diff changeset
   108
  };
489c9b5090e2 Initial load
duke
parents:
diff changeset
   109
6258
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   110
  bool _init_to_zero;
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   111
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   112
  // The reserved region covered by the shared array.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   113
  MemRegion _reserved;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   114
489c9b5090e2 Initial load
duke
parents:
diff changeset
   115
  // End of the current committed region.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   116
  HeapWord* _end;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   117
489c9b5090e2 Initial load
duke
parents:
diff changeset
   118
  // Array for keeping offsets for retrieving object start fast given an
489c9b5090e2 Initial load
duke
parents:
diff changeset
   119
  // address.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   120
  VirtualSpace _vs;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   121
  u_char* _offset_array;          // byte array keeping backwards offsets
489c9b5090e2 Initial load
duke
parents:
diff changeset
   122
489c9b5090e2 Initial load
duke
parents:
diff changeset
   123
 protected:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   124
  // Bounds checking accessors:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   125
  // For performance these have to devolve to array accesses in product builds.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   126
  u_char offset_array(size_t index) const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   127
    assert(index < _vs.committed_size(), "index out of range");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   128
    return _offset_array[index];
489c9b5090e2 Initial load
duke
parents:
diff changeset
   129
  }
6258
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   130
  // An assertion-checking helper method for the set_offset_array() methods below.
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   131
  void check_reducing_assertion(bool reducing);
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   132
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   133
  void set_offset_array(size_t index, u_char offset, bool reducing = false) {
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   134
    check_reducing_assertion(reducing);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   135
    assert(index < _vs.committed_size(), "index out of range");
6258
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   136
    assert(!reducing || _offset_array[index] >= offset, "Not reducing");
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   137
    _offset_array[index] = offset;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   138
  }
6258
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   139
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   140
  void set_offset_array(size_t index, HeapWord* high, HeapWord* low, bool reducing = false) {
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   141
    check_reducing_assertion(reducing);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   142
    assert(index < _vs.committed_size(), "index out of range");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   143
    assert(high >= low, "addresses out of order");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   144
    assert(pointer_delta(high, low) <= N_words, "offset too large");
6258
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   145
    assert(!reducing || _offset_array[index] >=  (u_char)pointer_delta(high, low),
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   146
           "Not reducing");
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   147
    _offset_array[index] = (u_char)pointer_delta(high, low);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   148
  }
6258
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   149
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   150
  void set_offset_array(HeapWord* left, HeapWord* right, u_char offset, bool reducing = false) {
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   151
    check_reducing_assertion(reducing);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   152
    assert(index_for(right - 1) < _vs.committed_size(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   153
           "right address out of range");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   154
    assert(left  < right, "Heap addresses out of order");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   155
    size_t num_cards = pointer_delta(right, left) >> LogN_words;
5431
5c4054a50dbb 6948537: CMS: BOT walkers observe out-of-thin-air zeros on sun4v sparc/CMT
ysr
parents: 3261
diff changeset
   156
5c4054a50dbb 6948537: CMS: BOT walkers observe out-of-thin-air zeros on sun4v sparc/CMT
ysr
parents: 3261
diff changeset
   157
    // Below, we may use an explicit loop instead of memset()
5c4054a50dbb 6948537: CMS: BOT walkers observe out-of-thin-air zeros on sun4v sparc/CMT
ysr
parents: 3261
diff changeset
   158
    // because on certain platforms memset() can give concurrent
5c4054a50dbb 6948537: CMS: BOT walkers observe out-of-thin-air zeros on sun4v sparc/CMT
ysr
parents: 3261
diff changeset
   159
    // readers "out-of-thin-air," phantom zeros; see 6948537.
5c4054a50dbb 6948537: CMS: BOT walkers observe out-of-thin-air zeros on sun4v sparc/CMT
ysr
parents: 3261
diff changeset
   160
    if (UseMemSetInBOT) {
5c4054a50dbb 6948537: CMS: BOT walkers observe out-of-thin-air zeros on sun4v sparc/CMT
ysr
parents: 3261
diff changeset
   161
      memset(&_offset_array[index_for(left)], offset, num_cards);
5c4054a50dbb 6948537: CMS: BOT walkers observe out-of-thin-air zeros on sun4v sparc/CMT
ysr
parents: 3261
diff changeset
   162
    } else {
5c4054a50dbb 6948537: CMS: BOT walkers observe out-of-thin-air zeros on sun4v sparc/CMT
ysr
parents: 3261
diff changeset
   163
      size_t i = index_for(left);
5c4054a50dbb 6948537: CMS: BOT walkers observe out-of-thin-air zeros on sun4v sparc/CMT
ysr
parents: 3261
diff changeset
   164
      const size_t end = i + num_cards;
5c4054a50dbb 6948537: CMS: BOT walkers observe out-of-thin-air zeros on sun4v sparc/CMT
ysr
parents: 3261
diff changeset
   165
      for (; i < end; i++) {
6258
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   166
        assert(!reducing || _offset_array[i] >= offset, "Not reducing");
5431
5c4054a50dbb 6948537: CMS: BOT walkers observe out-of-thin-air zeros on sun4v sparc/CMT
ysr
parents: 3261
diff changeset
   167
        _offset_array[i] = offset;
5c4054a50dbb 6948537: CMS: BOT walkers observe out-of-thin-air zeros on sun4v sparc/CMT
ysr
parents: 3261
diff changeset
   168
      }
5c4054a50dbb 6948537: CMS: BOT walkers observe out-of-thin-air zeros on sun4v sparc/CMT
ysr
parents: 3261
diff changeset
   169
    }
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   170
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   171
6258
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   172
  void set_offset_array(size_t left, size_t right, u_char offset, bool reducing = false) {
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   173
    check_reducing_assertion(reducing);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   174
    assert(right < _vs.committed_size(), "right address out of range");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   175
    assert(left  <= right, "indexes out of order");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   176
    size_t num_cards = right - left + 1;
5431
5c4054a50dbb 6948537: CMS: BOT walkers observe out-of-thin-air zeros on sun4v sparc/CMT
ysr
parents: 3261
diff changeset
   177
5c4054a50dbb 6948537: CMS: BOT walkers observe out-of-thin-air zeros on sun4v sparc/CMT
ysr
parents: 3261
diff changeset
   178
    // Below, we may use an explicit loop instead of memset
5c4054a50dbb 6948537: CMS: BOT walkers observe out-of-thin-air zeros on sun4v sparc/CMT
ysr
parents: 3261
diff changeset
   179
    // because on certain platforms memset() can give concurrent
5c4054a50dbb 6948537: CMS: BOT walkers observe out-of-thin-air zeros on sun4v sparc/CMT
ysr
parents: 3261
diff changeset
   180
    // readers "out-of-thin-air," phantom zeros; see 6948537.
5c4054a50dbb 6948537: CMS: BOT walkers observe out-of-thin-air zeros on sun4v sparc/CMT
ysr
parents: 3261
diff changeset
   181
    if (UseMemSetInBOT) {
5c4054a50dbb 6948537: CMS: BOT walkers observe out-of-thin-air zeros on sun4v sparc/CMT
ysr
parents: 3261
diff changeset
   182
      memset(&_offset_array[left], offset, num_cards);
5c4054a50dbb 6948537: CMS: BOT walkers observe out-of-thin-air zeros on sun4v sparc/CMT
ysr
parents: 3261
diff changeset
   183
    } else {
5c4054a50dbb 6948537: CMS: BOT walkers observe out-of-thin-air zeros on sun4v sparc/CMT
ysr
parents: 3261
diff changeset
   184
      size_t i = left;
5c4054a50dbb 6948537: CMS: BOT walkers observe out-of-thin-air zeros on sun4v sparc/CMT
ysr
parents: 3261
diff changeset
   185
      const size_t end = i + num_cards;
5c4054a50dbb 6948537: CMS: BOT walkers observe out-of-thin-air zeros on sun4v sparc/CMT
ysr
parents: 3261
diff changeset
   186
      for (; i < end; i++) {
6258
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   187
        assert(!reducing || _offset_array[i] >= offset, "Not reducing");
5431
5c4054a50dbb 6948537: CMS: BOT walkers observe out-of-thin-air zeros on sun4v sparc/CMT
ysr
parents: 3261
diff changeset
   188
        _offset_array[i] = offset;
5c4054a50dbb 6948537: CMS: BOT walkers observe out-of-thin-air zeros on sun4v sparc/CMT
ysr
parents: 3261
diff changeset
   189
      }
5c4054a50dbb 6948537: CMS: BOT walkers observe out-of-thin-air zeros on sun4v sparc/CMT
ysr
parents: 3261
diff changeset
   190
    }
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   191
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   192
489c9b5090e2 Initial load
duke
parents:
diff changeset
   193
  void check_offset_array(size_t index, HeapWord* high, HeapWord* low) const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   194
    assert(index < _vs.committed_size(), "index out of range");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   195
    assert(high >= low, "addresses out of order");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   196
    assert(pointer_delta(high, low) <= N_words, "offset too large");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   197
    assert(_offset_array[index] == pointer_delta(high, low),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   198
           "Wrong offset");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   199
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   200
489c9b5090e2 Initial load
duke
parents:
diff changeset
   201
  bool is_card_boundary(HeapWord* p) const;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   202
489c9b5090e2 Initial load
duke
parents:
diff changeset
   203
  // Return the number of slots needed for an offset array
489c9b5090e2 Initial load
duke
parents:
diff changeset
   204
  // that covers mem_region_words words.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   205
  // We always add an extra slot because if an object
489c9b5090e2 Initial load
duke
parents:
diff changeset
   206
  // ends on a card boundary we put a 0 in the next
489c9b5090e2 Initial load
duke
parents:
diff changeset
   207
  // offset array slot, so we want that slot always
489c9b5090e2 Initial load
duke
parents:
diff changeset
   208
  // to be reserved.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   209
489c9b5090e2 Initial load
duke
parents:
diff changeset
   210
  size_t compute_size(size_t mem_region_words) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   211
    size_t number_of_slots = (mem_region_words / N_words) + 1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   212
    return ReservedSpace::allocation_align_size_up(number_of_slots);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   213
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   214
489c9b5090e2 Initial load
duke
parents:
diff changeset
   215
public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   216
  // Initialize the table to cover from "base" to (at least)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   217
  // "base + init_word_size".  In the future, the table may be expanded
489c9b5090e2 Initial load
duke
parents:
diff changeset
   218
  // (see "resize" below) up to the size of "_reserved" (which must be at
489c9b5090e2 Initial load
duke
parents:
diff changeset
   219
  // least "init_word_size".)  The contents of the initial table are
489c9b5090e2 Initial load
duke
parents:
diff changeset
   220
  // undefined; it is the responsibility of the constituent
489c9b5090e2 Initial load
duke
parents:
diff changeset
   221
  // BlockOffsetTable(s) to initialize cards.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   222
  BlockOffsetSharedArray(MemRegion reserved, size_t init_word_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   223
489c9b5090e2 Initial load
duke
parents:
diff changeset
   224
  // Notes a change in the committed size of the region covered by the
489c9b5090e2 Initial load
duke
parents:
diff changeset
   225
  // table.  The "new_word_size" may not be larger than the size of the
489c9b5090e2 Initial load
duke
parents:
diff changeset
   226
  // reserved region this table covers.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   227
  void resize(size_t new_word_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   228
489c9b5090e2 Initial load
duke
parents:
diff changeset
   229
  void set_bottom(HeapWord* new_bottom);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   230
6258
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   231
  // Whether entries should be initialized to zero. Used currently only for
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   232
  // error checking.
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   233
  void set_init_to_zero(bool val) { _init_to_zero = val; }
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   234
  bool init_to_zero() { return _init_to_zero; }
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   235
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   236
  // Updates all the BlockOffsetArray's sharing this shared array to
489c9b5090e2 Initial load
duke
parents:
diff changeset
   237
  // reflect the current "top"'s of their spaces.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   238
  void update_offset_arrays();   // Not yet implemented!
489c9b5090e2 Initial load
duke
parents:
diff changeset
   239
489c9b5090e2 Initial load
duke
parents:
diff changeset
   240
  // Return the appropriate index into "_offset_array" for "p".
489c9b5090e2 Initial load
duke
parents:
diff changeset
   241
  size_t index_for(const void* p) const;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   242
489c9b5090e2 Initial load
duke
parents:
diff changeset
   243
  // Return the address indicating the start of the region corresponding to
489c9b5090e2 Initial load
duke
parents:
diff changeset
   244
  // "index" in "_offset_array".
489c9b5090e2 Initial load
duke
parents:
diff changeset
   245
  HeapWord* address_for_index(size_t index) const;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   246
1063
f666dc7f514d 6728478: Assertion at parallel promotion from young to old generation
jmasa
parents: 1
diff changeset
   247
  // Return the address "p" incremented by the size of
f666dc7f514d 6728478: Assertion at parallel promotion from young to old generation
jmasa
parents: 1
diff changeset
   248
  // a region.  This method does not align the address
f666dc7f514d 6728478: Assertion at parallel promotion from young to old generation
jmasa
parents: 1
diff changeset
   249
  // returned to the start of a region.  It is a simple
f666dc7f514d 6728478: Assertion at parallel promotion from young to old generation
jmasa
parents: 1
diff changeset
   250
  // primitive.
f666dc7f514d 6728478: Assertion at parallel promotion from young to old generation
jmasa
parents: 1
diff changeset
   251
  HeapWord* inc_by_region_size(HeapWord* p) const { return p + N_words; }
f666dc7f514d 6728478: Assertion at parallel promotion from young to old generation
jmasa
parents: 1
diff changeset
   252
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   253
  // Shared space support
489c9b5090e2 Initial load
duke
parents:
diff changeset
   254
  void serialize(SerializeOopClosure* soc, HeapWord* start, HeapWord* end);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   255
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   256
489c9b5090e2 Initial load
duke
parents:
diff changeset
   257
//////////////////////////////////////////////////////////////////////////
489c9b5090e2 Initial load
duke
parents:
diff changeset
   258
// The BlockOffsetArray whose subtypes use the BlockOffsetSharedArray.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   259
//////////////////////////////////////////////////////////////////////////
489c9b5090e2 Initial load
duke
parents:
diff changeset
   260
class BlockOffsetArray: public BlockOffsetTable {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   261
  friend class VMStructs;
1374
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 1
diff changeset
   262
  friend class G1BlockOffsetArray; // temp. until we restructure and cleanup
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   263
 protected:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   264
  // The following enums are used by do_block_internal() below
489c9b5090e2 Initial load
duke
parents:
diff changeset
   265
  enum Action {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   266
    Action_single,      // BOT records a single block (see single_block())
489c9b5090e2 Initial load
duke
parents:
diff changeset
   267
    Action_mark,        // BOT marks the start of a block (see mark_block())
489c9b5090e2 Initial load
duke
parents:
diff changeset
   268
    Action_check        // Check that BOT records block correctly
489c9b5090e2 Initial load
duke
parents:
diff changeset
   269
                        // (see verify_single_block()).
489c9b5090e2 Initial load
duke
parents:
diff changeset
   270
  };
489c9b5090e2 Initial load
duke
parents:
diff changeset
   271
489c9b5090e2 Initial load
duke
parents:
diff changeset
   272
  enum SomePrivateConstants {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   273
    N_words = BlockOffsetSharedArray::N_words,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   274
    LogN    = BlockOffsetSharedArray::LogN,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   275
    // entries "e" of at least N_words mean "go back by Base^(e-N_words)."
489c9b5090e2 Initial load
duke
parents:
diff changeset
   276
    // All entries are less than "N_words + N_powers".
489c9b5090e2 Initial load
duke
parents:
diff changeset
   277
    LogBase = 4,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   278
    Base = (1 << LogBase),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   279
    N_powers = 14
489c9b5090e2 Initial load
duke
parents:
diff changeset
   280
  };
489c9b5090e2 Initial load
duke
parents:
diff changeset
   281
489c9b5090e2 Initial load
duke
parents:
diff changeset
   282
  static size_t power_to_cards_back(uint i) {
2257
d8e6e11e7f32 6816308: Changes to allow builds with latest Windows SDK 6.1 on 64bit Windows 2003
kvn
parents: 1412
diff changeset
   283
    return (size_t)(1 << (LogBase * i));
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   284
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   285
  static size_t power_to_words_back(uint i) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   286
    return power_to_cards_back(i) * N_words;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   287
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   288
  static size_t entry_to_cards_back(u_char entry) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   289
    assert(entry >= N_words, "Precondition");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   290
    return power_to_cards_back(entry - N_words);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   291
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   292
  static size_t entry_to_words_back(u_char entry) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   293
    assert(entry >= N_words, "Precondition");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   294
    return power_to_words_back(entry - N_words);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   295
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   296
489c9b5090e2 Initial load
duke
parents:
diff changeset
   297
  // The shared array, which is shared with other BlockOffsetArray's
489c9b5090e2 Initial load
duke
parents:
diff changeset
   298
  // corresponding to different spaces within a generation or span of
489c9b5090e2 Initial load
duke
parents:
diff changeset
   299
  // memory.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   300
  BlockOffsetSharedArray* _array;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   301
489c9b5090e2 Initial load
duke
parents:
diff changeset
   302
  // The space that owns this subregion.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   303
  Space* _sp;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   304
489c9b5090e2 Initial load
duke
parents:
diff changeset
   305
  // If true, array entries are initialized to 0; otherwise, they are
489c9b5090e2 Initial load
duke
parents:
diff changeset
   306
  // initialized to point backwards to the beginning of the covered region.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   307
  bool _init_to_zero;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   308
6258
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   309
  // An assertion-checking helper method for the set_remainder*() methods below.
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   310
  void check_reducing_assertion(bool reducing) { _array->check_reducing_assertion(reducing); }
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   311
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   312
  // Sets the entries
489c9b5090e2 Initial load
duke
parents:
diff changeset
   313
  // corresponding to the cards starting at "start" and ending at "end"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   314
  // to point back to the card before "start": the interval [start, end)
6258
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   315
  // is right-open. The last parameter, reducing, indicates whether the
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   316
  // updates to individual entries always reduce the entry from a higher
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   317
  // to a lower value. (For example this would hold true during a temporal
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   318
  // regime during which only block splits were updating the BOT.
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   319
  void set_remainder_to_point_to_start(HeapWord* start, HeapWord* end, bool reducing = false);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   320
  // Same as above, except that the args here are a card _index_ interval
489c9b5090e2 Initial load
duke
parents:
diff changeset
   321
  // that is closed: [start_index, end_index]
6258
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   322
  void set_remainder_to_point_to_start_incl(size_t start, size_t end, bool reducing = false);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   323
489c9b5090e2 Initial load
duke
parents:
diff changeset
   324
  // A helper function for BOT adjustment/verification work
6258
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   325
  void do_block_internal(HeapWord* blk_start, HeapWord* blk_end, Action action, bool reducing = false);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   326
489c9b5090e2 Initial load
duke
parents:
diff changeset
   327
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   328
  // The space may not have its bottom and top set yet, which is why the
489c9b5090e2 Initial load
duke
parents:
diff changeset
   329
  // region is passed as a parameter.  If "init_to_zero" is true, the
489c9b5090e2 Initial load
duke
parents:
diff changeset
   330
  // elements of the array are initialized to zero.  Otherwise, they are
489c9b5090e2 Initial load
duke
parents:
diff changeset
   331
  // initialized to point backwards to the beginning.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   332
  BlockOffsetArray(BlockOffsetSharedArray* array, MemRegion mr,
6258
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   333
                   bool init_to_zero_);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   334
489c9b5090e2 Initial load
duke
parents:
diff changeset
   335
  // Note: this ought to be part of the constructor, but that would require
489c9b5090e2 Initial load
duke
parents:
diff changeset
   336
  // "this" to be passed as a parameter to a member constructor for
489c9b5090e2 Initial load
duke
parents:
diff changeset
   337
  // the containing concrete subtype of Space.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   338
  // This would be legal C++, but MS VC++ doesn't allow it.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   339
  void set_space(Space* sp) { _sp = sp; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   340
489c9b5090e2 Initial load
duke
parents:
diff changeset
   341
  // Resets the covered region to the given "mr".
489c9b5090e2 Initial load
duke
parents:
diff changeset
   342
  void set_region(MemRegion mr) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   343
    _bottom = mr.start();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   344
    _end = mr.end();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   345
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   346
489c9b5090e2 Initial load
duke
parents:
diff changeset
   347
  // Note that the committed size of the covered space may have changed,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   348
  // so the table size might also wish to change.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   349
  virtual void resize(size_t new_word_size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   350
    HeapWord* new_end = _bottom + new_word_size;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   351
    if (_end < new_end && !init_to_zero()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   352
      // verify that the old and new boundaries are also card boundaries
489c9b5090e2 Initial load
duke
parents:
diff changeset
   353
      assert(_array->is_card_boundary(_end),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   354
             "_end not a card boundary");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   355
      assert(_array->is_card_boundary(new_end),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   356
             "new _end would not be a card boundary");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   357
      // set all the newly added cards
489c9b5090e2 Initial load
duke
parents:
diff changeset
   358
      _array->set_offset_array(_end, new_end, N_words);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   359
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   360
    _end = new_end;  // update _end
489c9b5090e2 Initial load
duke
parents:
diff changeset
   361
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   362
489c9b5090e2 Initial load
duke
parents:
diff changeset
   363
  // Adjust the BOT to show that it has a single block in the
489c9b5090e2 Initial load
duke
parents:
diff changeset
   364
  // range [blk_start, blk_start + size). All necessary BOT
489c9b5090e2 Initial load
duke
parents:
diff changeset
   365
  // cards are adjusted, but _unallocated_block isn't.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   366
  void single_block(HeapWord* blk_start, HeapWord* blk_end);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   367
  void single_block(HeapWord* blk, size_t size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   368
    single_block(blk, blk + size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   369
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   370
489c9b5090e2 Initial load
duke
parents:
diff changeset
   371
  // When the alloc_block() call returns, the block offset table should
489c9b5090e2 Initial load
duke
parents:
diff changeset
   372
  // have enough information such that any subsequent block_start() call
489c9b5090e2 Initial load
duke
parents:
diff changeset
   373
  // with an argument equal to an address that is within the range
489c9b5090e2 Initial load
duke
parents:
diff changeset
   374
  // [blk_start, blk_end) would return the value blk_start, provided
489c9b5090e2 Initial load
duke
parents:
diff changeset
   375
  // there have been no calls in between that reset this information
489c9b5090e2 Initial load
duke
parents:
diff changeset
   376
  // (e.g. see BlockOffsetArrayNonContigSpace::single_block() call
489c9b5090e2 Initial load
duke
parents:
diff changeset
   377
  // for an appropriate range covering the said interval).
489c9b5090e2 Initial load
duke
parents:
diff changeset
   378
  // These methods expect to be called with [blk_start, blk_end)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   379
  // representing a block of memory in the heap.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   380
  virtual void alloc_block(HeapWord* blk_start, HeapWord* blk_end);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   381
  void alloc_block(HeapWord* blk, size_t size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   382
    alloc_block(blk, blk + size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   383
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   384
489c9b5090e2 Initial load
duke
parents:
diff changeset
   385
  // If true, initialize array slots with no allocated blocks to zero.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   386
  // Otherwise, make them point back to the front.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   387
  bool init_to_zero() { return _init_to_zero; }
6258
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   388
  // Corresponding setter
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   389
  void set_init_to_zero(bool val) {
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   390
    _init_to_zero = val;
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   391
    assert(_array != NULL, "_array should be non-NULL");
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   392
    _array->set_init_to_zero(val);
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   393
  }
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   394
489c9b5090e2 Initial load
duke
parents:
diff changeset
   395
  // Debugging
489c9b5090e2 Initial load
duke
parents:
diff changeset
   396
  // Return the index of the last entry in the "active" region.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   397
  virtual size_t last_active_index() const = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   398
  // Verify the block offset table
489c9b5090e2 Initial load
duke
parents:
diff changeset
   399
  void verify() const;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   400
  void check_all_cards(size_t left_card, size_t right_card) const;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   401
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   402
489c9b5090e2 Initial load
duke
parents:
diff changeset
   403
////////////////////////////////////////////////////////////////////////////
489c9b5090e2 Initial load
duke
parents:
diff changeset
   404
// A subtype of BlockOffsetArray that takes advantage of the fact
489c9b5090e2 Initial load
duke
parents:
diff changeset
   405
// that its underlying space is a NonContiguousSpace, so that some
489c9b5090e2 Initial load
duke
parents:
diff changeset
   406
// specialized interfaces can be made available for spaces that
489c9b5090e2 Initial load
duke
parents:
diff changeset
   407
// manipulate the table.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   408
////////////////////////////////////////////////////////////////////////////
489c9b5090e2 Initial load
duke
parents:
diff changeset
   409
class BlockOffsetArrayNonContigSpace: public BlockOffsetArray {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   410
  friend class VMStructs;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   411
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   412
  // The portion [_unallocated_block, _sp.end()) of the space that
489c9b5090e2 Initial load
duke
parents:
diff changeset
   413
  // is a single block known not to contain any objects.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   414
  // NOTE: See BlockOffsetArrayUseUnallocatedBlock flag.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   415
  HeapWord* _unallocated_block;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   416
489c9b5090e2 Initial load
duke
parents:
diff changeset
   417
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   418
  BlockOffsetArrayNonContigSpace(BlockOffsetSharedArray* array, MemRegion mr):
489c9b5090e2 Initial load
duke
parents:
diff changeset
   419
    BlockOffsetArray(array, mr, false),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   420
    _unallocated_block(_bottom) { }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   421
489c9b5090e2 Initial load
duke
parents:
diff changeset
   422
  // accessor
489c9b5090e2 Initial load
duke
parents:
diff changeset
   423
  HeapWord* unallocated_block() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   424
    assert(BlockOffsetArrayUseUnallocatedBlock,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   425
           "_unallocated_block is not being maintained");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   426
    return _unallocated_block;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   427
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   428
489c9b5090e2 Initial load
duke
parents:
diff changeset
   429
  void set_unallocated_block(HeapWord* block) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   430
    assert(BlockOffsetArrayUseUnallocatedBlock,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   431
           "_unallocated_block is not being maintained");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   432
    assert(block >= _bottom && block <= _end, "out of range");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   433
    _unallocated_block = block;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   434
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   435
489c9b5090e2 Initial load
duke
parents:
diff changeset
   436
  // These methods expect to be called with [blk_start, blk_end)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   437
  // representing a block of memory in the heap.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   438
  void alloc_block(HeapWord* blk_start, HeapWord* blk_end);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   439
  void alloc_block(HeapWord* blk, size_t size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   440
    alloc_block(blk, blk + size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   441
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   442
489c9b5090e2 Initial load
duke
parents:
diff changeset
   443
  // The following methods are useful and optimized for a
489c9b5090e2 Initial load
duke
parents:
diff changeset
   444
  // non-contiguous space.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   445
489c9b5090e2 Initial load
duke
parents:
diff changeset
   446
  // Given a block [blk_start, blk_start + full_blk_size), and
489c9b5090e2 Initial load
duke
parents:
diff changeset
   447
  // a left_blk_size < full_blk_size, adjust the BOT to show two
489c9b5090e2 Initial load
duke
parents:
diff changeset
   448
  // blocks [blk_start, blk_start + left_blk_size) and
489c9b5090e2 Initial load
duke
parents:
diff changeset
   449
  // [blk_start + left_blk_size, blk_start + full_blk_size).
489c9b5090e2 Initial load
duke
parents:
diff changeset
   450
  // It is assumed (and verified in the non-product VM) that the
489c9b5090e2 Initial load
duke
parents:
diff changeset
   451
  // BOT was correct for the original block.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   452
  void split_block(HeapWord* blk_start, size_t full_blk_size,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   453
                           size_t left_blk_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   454
489c9b5090e2 Initial load
duke
parents:
diff changeset
   455
  // Adjust BOT to show that it has a block in the range
489c9b5090e2 Initial load
duke
parents:
diff changeset
   456
  // [blk_start, blk_start + size). Only the first card
489c9b5090e2 Initial load
duke
parents:
diff changeset
   457
  // of BOT is touched. It is assumed (and verified in the
489c9b5090e2 Initial load
duke
parents:
diff changeset
   458
  // non-product VM) that the remaining cards of the block
489c9b5090e2 Initial load
duke
parents:
diff changeset
   459
  // are correct.
6258
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   460
  void mark_block(HeapWord* blk_start, HeapWord* blk_end, bool reducing = false);
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   461
  void mark_block(HeapWord* blk, size_t size, bool reducing = false) {
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   462
    mark_block(blk, blk + size, reducing);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   463
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   464
489c9b5090e2 Initial load
duke
parents:
diff changeset
   465
  // Adjust _unallocated_block to indicate that a particular
489c9b5090e2 Initial load
duke
parents:
diff changeset
   466
  // block has been newly allocated or freed. It is assumed (and
489c9b5090e2 Initial load
duke
parents:
diff changeset
   467
  // verified in the non-product VM) that the BOT is correct for
489c9b5090e2 Initial load
duke
parents:
diff changeset
   468
  // the given block.
6258
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   469
  void allocated(HeapWord* blk_start, HeapWord* blk_end, bool reducing = false) {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   470
    // Verify that the BOT shows [blk, blk + blk_size) to be one block.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   471
    verify_single_block(blk_start, blk_end);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   472
    if (BlockOffsetArrayUseUnallocatedBlock) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   473
      _unallocated_block = MAX2(_unallocated_block, blk_end);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   474
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   475
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   476
6258
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   477
  void allocated(HeapWord* blk, size_t size, bool reducing = false) {
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   478
    allocated(blk, blk + size, reducing);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   479
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   480
489c9b5090e2 Initial load
duke
parents:
diff changeset
   481
  void freed(HeapWord* blk_start, HeapWord* blk_end);
6258
68f252c6e825 6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents: 5547
diff changeset
   482
  void freed(HeapWord* blk, size_t size);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   483
489c9b5090e2 Initial load
duke
parents:
diff changeset
   484
  HeapWord* block_start_unsafe(const void* addr) const;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   485
489c9b5090e2 Initial load
duke
parents:
diff changeset
   486
  // Requires "addr" to be the start of a card and returns the
489c9b5090e2 Initial load
duke
parents:
diff changeset
   487
  // start of the block that contains the given address.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   488
  HeapWord* block_start_careful(const void* addr) const;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   489
489c9b5090e2 Initial load
duke
parents:
diff changeset
   490
  // Verification & debugging: ensure that the offset table reflects
489c9b5090e2 Initial load
duke
parents:
diff changeset
   491
  // the fact that the block [blk_start, blk_end) or [blk, blk + size)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   492
  // is a single block of storage. NOTE: can't const this because of
489c9b5090e2 Initial load
duke
parents:
diff changeset
   493
  // call to non-const do_block_internal() below.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   494
  void verify_single_block(HeapWord* blk_start, HeapWord* blk_end)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   495
    PRODUCT_RETURN;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   496
  void verify_single_block(HeapWord* blk, size_t size) PRODUCT_RETURN;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   497
489c9b5090e2 Initial load
duke
parents:
diff changeset
   498
  // Verify that the given block is before _unallocated_block
489c9b5090e2 Initial load
duke
parents:
diff changeset
   499
  void verify_not_unallocated(HeapWord* blk_start, HeapWord* blk_end)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   500
    const PRODUCT_RETURN;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   501
  void verify_not_unallocated(HeapWord* blk, size_t size)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   502
    const PRODUCT_RETURN;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   503
489c9b5090e2 Initial load
duke
parents:
diff changeset
   504
  // Debugging support
489c9b5090e2 Initial load
duke
parents:
diff changeset
   505
  virtual size_t last_active_index() const;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   506
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   507
489c9b5090e2 Initial load
duke
parents:
diff changeset
   508
////////////////////////////////////////////////////////////////////////////
489c9b5090e2 Initial load
duke
parents:
diff changeset
   509
// A subtype of BlockOffsetArray that takes advantage of the fact
489c9b5090e2 Initial load
duke
parents:
diff changeset
   510
// that its underlying space is a ContiguousSpace, so that its "active"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   511
// region can be more efficiently tracked (than for a non-contiguous space).
489c9b5090e2 Initial load
duke
parents:
diff changeset
   512
////////////////////////////////////////////////////////////////////////////
489c9b5090e2 Initial load
duke
parents:
diff changeset
   513
class BlockOffsetArrayContigSpace: public BlockOffsetArray {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   514
  friend class VMStructs;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   515
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   516
  // allocation boundary at which offset array must be updated
489c9b5090e2 Initial load
duke
parents:
diff changeset
   517
  HeapWord* _next_offset_threshold;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   518
  size_t    _next_offset_index;      // index corresponding to that boundary
489c9b5090e2 Initial load
duke
parents:
diff changeset
   519
489c9b5090e2 Initial load
duke
parents:
diff changeset
   520
  // Work function when allocation start crosses threshold.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   521
  void alloc_block_work(HeapWord* blk_start, HeapWord* blk_end);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   522
489c9b5090e2 Initial load
duke
parents:
diff changeset
   523
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   524
  BlockOffsetArrayContigSpace(BlockOffsetSharedArray* array, MemRegion mr):
489c9b5090e2 Initial load
duke
parents:
diff changeset
   525
    BlockOffsetArray(array, mr, true) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   526
    _next_offset_threshold = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   527
    _next_offset_index = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   528
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   529
489c9b5090e2 Initial load
duke
parents:
diff changeset
   530
  void set_contig_space(ContiguousSpace* sp) { set_space((Space*)sp); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   531
489c9b5090e2 Initial load
duke
parents:
diff changeset
   532
  // Initialize the threshold for an empty heap.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   533
  HeapWord* initialize_threshold();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   534
  // Zero out the entry for _bottom (offset will be zero)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   535
  void      zero_bottom_entry();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   536
489c9b5090e2 Initial load
duke
parents:
diff changeset
   537
  // Return the next threshold, the point at which the table should be
489c9b5090e2 Initial load
duke
parents:
diff changeset
   538
  // updated.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   539
  HeapWord* threshold() const { return _next_offset_threshold; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   540
489c9b5090e2 Initial load
duke
parents:
diff changeset
   541
  // In general, these methods expect to be called with
489c9b5090e2 Initial load
duke
parents:
diff changeset
   542
  // [blk_start, blk_end) representing a block of memory in the heap.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   543
  // In this implementation, however, we are OK even if blk_start and/or
489c9b5090e2 Initial load
duke
parents:
diff changeset
   544
  // blk_end are NULL because NULL is represented as 0, and thus
489c9b5090e2 Initial load
duke
parents:
diff changeset
   545
  // never exceeds the "_next_offset_threshold".
489c9b5090e2 Initial load
duke
parents:
diff changeset
   546
  void alloc_block(HeapWord* blk_start, HeapWord* blk_end) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   547
    if (blk_end > _next_offset_threshold) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   548
      alloc_block_work(blk_start, blk_end);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   549
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   550
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   551
  void alloc_block(HeapWord* blk, size_t size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   552
    alloc_block(blk, blk + size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   553
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   554
489c9b5090e2 Initial load
duke
parents:
diff changeset
   555
  HeapWord* block_start_unsafe(const void* addr) const;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   556
489c9b5090e2 Initial load
duke
parents:
diff changeset
   557
  void serialize(SerializeOopClosure* soc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   558
489c9b5090e2 Initial load
duke
parents:
diff changeset
   559
  // Debugging support
489c9b5090e2 Initial load
duke
parents:
diff changeset
   560
  virtual size_t last_active_index() const;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   561
};