src/hotspot/share/gc/z/zPhysicalMemory.cpp
changeset 50525 767cdb97f103
child 50979 270b11dadbaf
equal deleted inserted replaced
50524:04f4e983c2f7 50525:767cdb97f103
       
     1 /*
       
     2  * Copyright (c) 2015, 2017, 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 #include "precompiled.hpp"
       
    25 #include "gc/z/zPhysicalMemory.inline.hpp"
       
    26 #include "logging/log.hpp"
       
    27 #include "memory/allocation.inline.hpp"
       
    28 #include "services/memTracker.hpp"
       
    29 #include "utilities/debug.hpp"
       
    30 
       
    31 ZPhysicalMemory::ZPhysicalMemory() :
       
    32     _nsegments(0),
       
    33     _segments(NULL) {}
       
    34 
       
    35 ZPhysicalMemory::ZPhysicalMemory(size_t size) :
       
    36     _nsegments(0),
       
    37     _segments(NULL) {
       
    38   add_segment(ZPhysicalMemorySegment(0, size));
       
    39 }
       
    40 
       
    41 ZPhysicalMemory::ZPhysicalMemory(const ZPhysicalMemorySegment& segment) :
       
    42     _nsegments(0),
       
    43     _segments(NULL) {
       
    44   add_segment(segment);
       
    45 }
       
    46 
       
    47 size_t ZPhysicalMemory::size() const {
       
    48   size_t size = 0;
       
    49 
       
    50   for (size_t i = 0; i < _nsegments; i++) {
       
    51     size += _segments[i].size();
       
    52   }
       
    53 
       
    54   return size;
       
    55 }
       
    56 
       
    57 void ZPhysicalMemory::add_segment(ZPhysicalMemorySegment segment) {
       
    58   // Try merge with last segment
       
    59   if (_nsegments > 0) {
       
    60     ZPhysicalMemorySegment& last = _segments[_nsegments - 1];
       
    61     assert(last.end() <= segment.start(), "Segments added out of order");
       
    62     if (last.end() == segment.start()) {
       
    63       // Merge
       
    64       last.expand(segment.size());
       
    65       return;
       
    66     }
       
    67   }
       
    68 
       
    69   // Make room for a new segment
       
    70   const size_t size = sizeof(ZPhysicalMemorySegment) * (_nsegments + 1);
       
    71   _segments = (ZPhysicalMemorySegment*)ReallocateHeap((char*)_segments, size, mtGC);
       
    72 
       
    73   // Add new segment
       
    74   _segments[_nsegments] = segment;
       
    75   _nsegments++;
       
    76 }
       
    77 
       
    78 ZPhysicalMemory ZPhysicalMemory::split(size_t split_size) {
       
    79   // Only splitting of single-segment instances have been implemented.
       
    80   assert(nsegments() == 1, "Can only have one segment");
       
    81   assert(split_size <= size(), "Invalid size");
       
    82   return ZPhysicalMemory(_segments[0].split(split_size));
       
    83 }
       
    84 
       
    85 void ZPhysicalMemory::clear() {
       
    86   if (_segments != NULL) {
       
    87     FreeHeap(_segments);
       
    88     _segments = NULL;
       
    89     _nsegments = 0;
       
    90   }
       
    91 }
       
    92 
       
    93 ZPhysicalMemoryManager::ZPhysicalMemoryManager(size_t max_capacity, size_t granule_size) :
       
    94     _backing(max_capacity, granule_size),
       
    95     _max_capacity(max_capacity),
       
    96     _capacity(0),
       
    97     _used(0) {}
       
    98 
       
    99 bool ZPhysicalMemoryManager::is_initialized() const {
       
   100   return _backing.is_initialized();
       
   101 }
       
   102 
       
   103 bool ZPhysicalMemoryManager::ensure_available(size_t size) {
       
   104   const size_t unused_capacity = _capacity - _used;
       
   105   if (unused_capacity >= size) {
       
   106     // Enough unused capacity available
       
   107     return true;
       
   108   }
       
   109 
       
   110   const size_t expand_with = size - unused_capacity;
       
   111   const size_t new_capacity = _capacity + expand_with;
       
   112   if (new_capacity > _max_capacity) {
       
   113     // Can not expand beyond max capacity
       
   114     return false;
       
   115   }
       
   116 
       
   117   // Expand
       
   118   if (!_backing.expand(_capacity, new_capacity)) {
       
   119     log_error(gc)("Failed to expand Java heap with " SIZE_FORMAT "%s",
       
   120                   byte_size_in_proper_unit(expand_with),
       
   121                   proper_unit_for_byte_size(expand_with));
       
   122     return false;
       
   123   }
       
   124 
       
   125   _capacity = new_capacity;
       
   126 
       
   127   return true;
       
   128 }
       
   129 
       
   130 void ZPhysicalMemoryManager::nmt_commit(ZPhysicalMemory pmem, uintptr_t offset) {
       
   131   const uintptr_t addr = _backing.nmt_address(offset);
       
   132   const size_t size = pmem.size();
       
   133   MemTracker::record_virtual_memory_commit((void*)addr, size, CALLER_PC);
       
   134 }
       
   135 
       
   136 void ZPhysicalMemoryManager::nmt_uncommit(ZPhysicalMemory pmem, uintptr_t offset) {
       
   137   if (MemTracker::tracking_level() > NMT_minimal) {
       
   138     const uintptr_t addr = _backing.nmt_address(offset);
       
   139     const size_t size = pmem.size();
       
   140 
       
   141     Tracker tracker(Tracker::uncommit);
       
   142     tracker.record((address)addr, size);
       
   143   }
       
   144 }
       
   145 
       
   146 ZPhysicalMemory ZPhysicalMemoryManager::alloc(size_t size) {
       
   147   if (!ensure_available(size)) {
       
   148     // Not enough memory available
       
   149     return ZPhysicalMemory();
       
   150   }
       
   151 
       
   152   _used += size;
       
   153   return _backing.alloc(size);
       
   154 }
       
   155 
       
   156 void ZPhysicalMemoryManager::free(ZPhysicalMemory pmem) {
       
   157   _backing.free(pmem);
       
   158   _used -= pmem.size();
       
   159 }
       
   160 
       
   161 void ZPhysicalMemoryManager::map(ZPhysicalMemory pmem, uintptr_t offset) {
       
   162   // Map page
       
   163   _backing.map(pmem, offset);
       
   164 
       
   165   // Update native memory tracker
       
   166   nmt_commit(pmem, offset);
       
   167 }
       
   168 
       
   169 void ZPhysicalMemoryManager::unmap(ZPhysicalMemory pmem, uintptr_t offset) {
       
   170   // Update native memory tracker
       
   171   nmt_uncommit(pmem, offset);
       
   172 
       
   173   // Unmap page
       
   174   _backing.unmap(pmem, offset);
       
   175 }
       
   176 
       
   177 void ZPhysicalMemoryManager::flip(ZPhysicalMemory pmem, uintptr_t offset) {
       
   178   _backing.flip(pmem, offset);
       
   179 }