src/hotspot/share/memory/metaspace/commitMask.hpp
branchstuefe-new-metaspace-branch
changeset 58063 bdf136b8ae0e
child 58646 bcdba1c9f1fe
equal deleted inserted replaced
58062:65cad575ace3 58063:bdf136b8ae0e
       
     1 /*
       
     2  * Copyright (c) 2019, SAP SE. All rights reserved.
       
     3  * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
       
     4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     5  *
       
     6  * This code is free software; you can redistribute it and/or modify it
       
     7  * under the terms of the GNU General Public License version 2 only, as
       
     8  * published by the Free Software Foundation.
       
     9  *
       
    10  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    13  * version 2 for more details (a copy is included in the LICENSE file that
       
    14  * accompanied this code).
       
    15  *
       
    16  * You should have received a copy of the GNU General Public License version
       
    17  * 2 along with this work; if not, write to the Free Software Foundation,
       
    18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    19  *
       
    20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    21  * or visit www.oracle.com if you need additional information or have any
       
    22  * questions.
       
    23  *
       
    24  */
       
    25 
       
    26 #ifndef SHARE_MEMORY_METASPACE_COMMITMASK_HPP
       
    27 #define SHARE_MEMORY_METASPACE_COMMITMASK_HPP
       
    28 
       
    29 #include "utilities/debug.hpp"
       
    30 #include "utilities/bitMap.hpp"
       
    31 #include "utilities/globalDefinitions.hpp"
       
    32 
       
    33 class outputStream;
       
    34 
       
    35 namespace metaspace {
       
    36 
       
    37 // A bitmap covering a range of metaspace; each bit in this mask corresponds to
       
    38 //
       
    39 class CommitMask : public CHeapBitMap {
       
    40 
       
    41   const MetaWord* const _base;
       
    42   const size_t _word_size;
       
    43   const size_t _words_per_bit;
       
    44 
       
    45   // Given an offset, in words, into the area, return the number of the bit
       
    46   // covering it.
       
    47   static idx_t bitno_for_word_offset(size_t offset, size_t words_per_bit) {
       
    48     return offset / words_per_bit;
       
    49   }
       
    50 
       
    51   idx_t bitno_for_address(const MetaWord* p) const {
       
    52     // Note: we allow one-beyond since this is a typical need.
       
    53     assert(p >= _base && p <= _base + _word_size, "Invalid address");
       
    54     const size_t off = p - _base;
       
    55     return bitno_for_word_offset(off, _words_per_bit);
       
    56   }
       
    57 
       
    58   static idx_t mask_size(size_t word_size, size_t words_per_bit) {
       
    59     return bitno_for_word_offset(word_size, words_per_bit);
       
    60   }
       
    61 
       
    62   struct BitCounterClosure : public BitMapClosure {
       
    63     idx_t cnt;
       
    64     bool do_bit(BitMap::idx_t offset) { cnt ++; return true; }
       
    65   };
       
    66 
       
    67   // Missing from BitMap.
       
    68   // Count 1 bits in range [start, end).
       
    69   idx_t count_one_bits_in_range(idx_t start, idx_t end) const {
       
    70     assert(start < end, "Zero range");
       
    71     // TODO: This can be done more efficiently.
       
    72     BitCounterClosure bcc;
       
    73     bcc.cnt = 0;
       
    74     iterate(&bcc, start, end);
       
    75     return bcc.cnt;
       
    76   }
       
    77 
       
    78 #ifdef ASSERT
       
    79   // Given a pointer, check if it points into the range this bitmap covers.
       
    80   bool is_pointer_valid(const MetaWord* p) const {
       
    81     return p >= _base && p < _base + _word_size;
       
    82   }
       
    83 
       
    84   // Given a pointer, check if it points into the range this bitmap covers.
       
    85   void check_pointer(const MetaWord* p) const {
       
    86     assert(is_pointer_valid(p),
       
    87            "Pointer " PTR_FORMAT " not in range of this bitmap [" PTR_FORMAT ", " PTR_FORMAT ").",
       
    88            p2i(p), p2i(_base), p2i(_base + _word_size));
       
    89   }
       
    90   // Given a pointer, check if it points into the range this bitmap covers,
       
    91   // and if it is aligned to commit granule border.
       
    92   void check_pointer_aligned(const MetaWord* p) const {
       
    93     check_pointer(p);
       
    94     assert(is_aligned(p, _words_per_bit * BytesPerWord),
       
    95            "Pointer " PTR_FORMAT " should be aligned to commit granule size " SIZE_FORMAT ".",
       
    96            p2i(p), _words_per_bit * BytesPerWord);
       
    97   }
       
    98   // Given a range, check if it points into the range this bitmap covers,
       
    99   // and if its borders are aligned to commit granule border.
       
   100   void check_range(const MetaWord* start, size_t word_size) const {
       
   101     check_pointer_aligned(start);
       
   102     assert(is_aligned(word_size, _words_per_bit),
       
   103            "Range " SIZE_FORMAT " should be aligned to commit granule size " SIZE_FORMAT ".",
       
   104            word_size, _words_per_bit);
       
   105     check_pointer(start + word_size - 1);
       
   106   }
       
   107 #endif
       
   108 
       
   109   // Marks a single commit granule as committed (value == true)
       
   110   // or uncomitted (value == false) and returns
       
   111   // its prior state.
       
   112   bool mark_granule(idx_t bitno, bool value) {
       
   113     bool b = at(bitno);
       
   114     at_put(bitno, value);
       
   115     return b;
       
   116   }
       
   117 
       
   118 public:
       
   119 
       
   120   CommitMask(const MetaWord* start, size_t word_size);
       
   121 
       
   122   const MetaWord* base() const  { return _base; }
       
   123   size_t word_size() const      { return _word_size; }
       
   124   const MetaWord* end() const   { return _base + word_size(); }
       
   125 
       
   126   // Given an address, returns true if the address is committed, false if not.
       
   127   bool is_committed_address(const MetaWord* p) const {
       
   128     DEBUG_ONLY(check_pointer(p));
       
   129     const idx_t bitno = bitno_for_address(p);
       
   130     return at(bitno);
       
   131   }
       
   132 
       
   133   // Given an address range [start..end), returns true if area is fully committed through.
       
   134   bool is_fully_committed_range(const MetaWord* start, size_t word_size) const {
       
   135     DEBUG_ONLY(check_range(start, word_size));
       
   136     assert(word_size > 0, "zero range");
       
   137     const idx_t b1 = bitno_for_address(start);
       
   138     const idx_t b2 = bitno_for_address(start + word_size);
       
   139     return get_next_zero_offset(b1, b2) == b2;
       
   140   }
       
   141 
       
   142   // Given an address range, return size, in number of words, of committed area within that range.
       
   143   size_t get_committed_size_in_range(const MetaWord* start, size_t word_size) const {
       
   144     DEBUG_ONLY(check_range(start, word_size));
       
   145     assert(word_size > 0, "zero range");
       
   146     const idx_t b1 = bitno_for_address(start);
       
   147     const idx_t b2 = bitno_for_address(start + word_size);
       
   148     const idx_t num_bits = count_one_bits_in_range(b1, b2);
       
   149     return num_bits * _words_per_bit;
       
   150   }
       
   151 
       
   152   // Return total committed size, in number of words.
       
   153   size_t get_committed_size() const {
       
   154     return count_one_bits() * _words_per_bit;
       
   155   }
       
   156 
       
   157   // Mark a whole address range [start, end) as committed.
       
   158   // Return the number of words which had already been committed before this operation.
       
   159   size_t mark_range_as_committed(const MetaWord* start, size_t word_size) {
       
   160     DEBUG_ONLY(check_range(start, word_size));
       
   161     assert(word_size > 0, "zero range");
       
   162     const idx_t b1 = bitno_for_address(start);
       
   163     const idx_t b2 = bitno_for_address(start + word_size);
       
   164     if (b1 == b2) { // Simple case, 1 granule
       
   165       bool was_committed = mark_granule(b1, true);
       
   166       return was_committed ? _words_per_bit : 0;
       
   167     }
       
   168     const idx_t one_bits_in_range_before = count_one_bits_in_range(b1, b2);
       
   169     set_range(b1, b2);
       
   170     return one_bits_in_range_before * _words_per_bit;
       
   171   }
       
   172 
       
   173   // Mark a whole address range [start, end) as uncommitted.
       
   174   // Return the number of words which had already been uncommitted before this operation.
       
   175   size_t mark_range_as_uncommitted(const MetaWord* start, size_t word_size) {
       
   176     DEBUG_ONLY(check_range(start, word_size));
       
   177     assert(word_size > 0, "zero range");
       
   178     const idx_t b1 = bitno_for_address(start);
       
   179     const idx_t b2 = bitno_for_address(start + word_size);
       
   180     if (b1 == b2) { // Simple case, 1 granule
       
   181       bool was_committed = mark_granule(b1, false);
       
   182       return was_committed ? 0 : _words_per_bit;
       
   183     }
       
   184     const idx_t zero_bits_in_range_before =
       
   185         (b2 - b1) - count_one_bits_in_range(b1, b2);
       
   186     clear_range(b1, b2);
       
   187     return zero_bits_in_range_before * _words_per_bit;
       
   188   }
       
   189 
       
   190 
       
   191   //// Debug stuff ////
       
   192   DEBUG_ONLY(void verify(bool slow, bool do_touch_test = true) const;)
       
   193 
       
   194   void print_on(outputStream* st) const;
       
   195 
       
   196 };
       
   197 
       
   198 } // namespace metaspace
       
   199 
       
   200 #endif // SHARE_MEMORY_METASPACE_COMMITMASK_HPP