src/hotspot/share/memory/archiveUtils.hpp
changeset 59070 22ee476cc664
equal deleted inserted replaced
59069:e0d59f0c2b7d 59070:22ee476cc664
       
     1 /*
       
     2  * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  *
       
    23  */
       
    24 
       
    25 #ifndef SHARE_MEMORY_ARCHIVEUTILS_HPP
       
    26 #define SHARE_MEMORY_ARCHIVEUTILS_HPP
       
    27 
       
    28 #include "logging/log.hpp"
       
    29 #include "runtime/arguments.hpp"
       
    30 #include "utilities/bitMap.hpp"
       
    31 
       
    32 // ArchivePtrMarker is used to mark the location of pointers embedded in a CDS archive. E.g., when an
       
    33 // InstanceKlass k is dumped, we mark the location of the k->_name pointer by effectively calling
       
    34 // mark_pointer(/*ptr_loc=*/&k->_name). It's required that (_prt_base <= ptr_loc < _ptr_end). _ptr_base is
       
    35 // fixed, but _ptr_end can be expanded as more objects are dumped.
       
    36 class ArchivePtrMarker : AllStatic {
       
    37   static CHeapBitMap* _ptrmap;
       
    38   static address*     _ptr_base;
       
    39   static address*     _ptr_end;
       
    40 
       
    41   // Once _ptrmap is compacted, we don't allow bit marking anymore. This is to
       
    42   // avoid unintentional copy operations after the bitmap has been finalized and written.
       
    43   static bool         _compacted;
       
    44 public:
       
    45   static void initialize(CHeapBitMap* ptrmap, address* ptr_base, address* ptr_end);
       
    46   static void mark_pointer(address* ptr_loc);
       
    47   static void compact(address relocatable_base, address relocatable_end);
       
    48   static void compact(size_t max_non_null_offset);
       
    49 
       
    50   template <typename T>
       
    51   static void mark_pointer(T* ptr_loc) {
       
    52     mark_pointer((address*)ptr_loc);
       
    53   }
       
    54 
       
    55   static void expand_ptr_end(address *new_ptr_end) {
       
    56     assert(_ptr_end <= new_ptr_end, "must be");
       
    57     _ptr_end = new_ptr_end;
       
    58   }
       
    59 
       
    60   static CHeapBitMap* ptrmap() {
       
    61     return _ptrmap;
       
    62   }
       
    63 };
       
    64 
       
    65 // SharedDataRelocator is used to shift pointers in the CDS archive.
       
    66 //
       
    67 // The CDS archive is basically a contiguous block of memory (divided into several regions)
       
    68 // that contains multiple objects. The objects may contain direct pointers that point to other objects
       
    69 // within the archive (e.g., InstanceKlass::_name points to a Symbol in the archive). During dumping, we
       
    70 // built a bitmap that marks the locations of all these pointers (using ArchivePtrMarker, see comments above).
       
    71 //
       
    72 // The contents of the archive assumes that it’s mapped at the default SharedBaseAddress (e.g. 0x800000000).
       
    73 // If the archive ends up being mapped at a different address (e.g. 0x810000000), SharedDataRelocator
       
    74 // is used to shift each marked pointer by a delta (0x10000000 in this example), so that it points to
       
    75 // the actually mapped location of the target object.
       
    76 template <bool COMPACTING>
       
    77 class SharedDataRelocator: public BitMapClosure {
       
    78   // for all (address** p), where (is_marked(p) && _patch_base <= p && p < _patch_end) { *p += delta; }
       
    79 
       
    80   // Patch all pointers within this region that are marked.
       
    81   address* _patch_base;
       
    82   address* _patch_end;
       
    83 
       
    84   // Before patching, all pointers must point to this region.
       
    85   address _valid_old_base;
       
    86   address _valid_old_end;
       
    87 
       
    88   // After patching, all pointers must point to this region.
       
    89   address _valid_new_base;
       
    90   address _valid_new_end;
       
    91 
       
    92   // How much to relocate for each pointer.
       
    93   intx _delta;
       
    94 
       
    95   // The following fields are used only when COMPACTING == true;
       
    96   // The highest offset (inclusive) in the bitmap that contains a non-null pointer.
       
    97   // This is used at dump time to reduce the size of the bitmap (which may have been over-allocated).
       
    98   size_t _max_non_null_offset;
       
    99   CHeapBitMap* _ptrmap;
       
   100 
       
   101  public:
       
   102   SharedDataRelocator(address* patch_base, address* patch_end,
       
   103                       address valid_old_base, address valid_old_end,
       
   104                       address valid_new_base, address valid_new_end, intx delta,
       
   105                       CHeapBitMap* ptrmap = NULL) :
       
   106     _patch_base(patch_base), _patch_end(patch_end),
       
   107     _valid_old_base(valid_old_base), _valid_old_end(valid_old_end),
       
   108     _valid_new_base(valid_new_base), _valid_new_end(valid_new_end),
       
   109     _delta(delta) {
       
   110     log_debug(cds, reloc)("SharedDataRelocator::_patch_base     = " PTR_FORMAT, p2i(_patch_base));
       
   111     log_debug(cds, reloc)("SharedDataRelocator::_patch_end      = " PTR_FORMAT, p2i(_patch_end));
       
   112     log_debug(cds, reloc)("SharedDataRelocator::_valid_old_base = " PTR_FORMAT, p2i(_valid_old_base));
       
   113     log_debug(cds, reloc)("SharedDataRelocator::_valid_old_end  = " PTR_FORMAT, p2i(_valid_old_end));
       
   114     log_debug(cds, reloc)("SharedDataRelocator::_valid_new_base = " PTR_FORMAT, p2i(_valid_new_base));
       
   115     log_debug(cds, reloc)("SharedDataRelocator::_valid_new_end  = " PTR_FORMAT, p2i(_valid_new_end));
       
   116     if (COMPACTING) {
       
   117       assert(ptrmap != NULL, "must be");
       
   118       _max_non_null_offset = 0;
       
   119       _ptrmap = ptrmap;
       
   120     } else {
       
   121       // Don't touch the _max_non_null_offset and _ptrmap fields. Hopefully a good C++ compiler can
       
   122       // elide them.
       
   123       assert(ptrmap == NULL, "must be");
       
   124     }
       
   125   }
       
   126 
       
   127   size_t max_non_null_offset() {
       
   128     assert(COMPACTING, "must be");
       
   129     return _max_non_null_offset;
       
   130   }
       
   131 
       
   132   inline bool do_bit(size_t offset);
       
   133 };
       
   134 
       
   135 
       
   136 #endif // SHARE_MEMORY_ARCHIVEUTILS_HPP