src/hotspot/share/gc/z/zPageAllocator.cpp
changeset 50979 270b11dadbaf
parent 50875 2217b2fc29ea
child 52653 ec92cbf2152b
--- a/src/hotspot/share/gc/z/zPageAllocator.cpp	Wed Jul 04 16:49:34 2018 +0800
+++ b/src/hotspot/share/gc/z/zPageAllocator.cpp	Wed Jul 04 12:04:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -84,11 +84,12 @@
 ZPage* const ZPageAllocator::gc_marker = (ZPage*)-1;
 
 ZPageAllocator::ZPageAllocator(size_t min_capacity, size_t max_capacity, size_t max_reserve) :
+    _lock(),
     _virtual(),
     _physical(max_capacity, ZPageSizeMin),
     _cache(),
-    _pre_mapped(_virtual, _physical, min_capacity),
     _max_reserve(max_reserve),
+    _pre_mapped(_virtual, _physical, try_ensure_unused_for_pre_mapped(min_capacity)),
     _used_high(0),
     _used_low(0),
     _used(0),
@@ -107,6 +108,10 @@
   return _physical.max_capacity();
 }
 
+size_t ZPageAllocator::current_max_capacity() const {
+  return _physical.current_max_capacity();
+}
+
 size_t ZPageAllocator::capacity() const {
   return _physical.capacity();
 }
@@ -169,18 +174,43 @@
   }
 }
 
-size_t ZPageAllocator::available(ZAllocationFlags flags) const {
-  size_t available = max_capacity() - used();
-  assert(_physical.available() + _pre_mapped.available() + _cache.available()  == available, "Should be equal");
+size_t ZPageAllocator::max_available(bool no_reserve) const {
+  size_t available = current_max_capacity() - used();
 
-  if (flags.no_reserve()) {
-    // The memory reserve should not be considered free
+  if (no_reserve) {
+    // The reserve should not be considered available
     available -= MIN2(available, max_reserve());
   }
 
   return available;
 }
 
+size_t ZPageAllocator::try_ensure_unused(size_t size, bool no_reserve) {
+  // Ensure that we always have space available for the reserve. This
+  // is needed to avoid losing the reserve because of failure to map
+  // more memory before reaching max capacity.
+  _physical.try_ensure_unused_capacity(size + max_reserve());
+
+  size_t unused = _physical.unused_capacity();
+
+  if (no_reserve) {
+    // The reserve should not be considered unused
+    unused -= MIN2(unused, max_reserve());
+  }
+
+  return MIN2(size, unused);
+}
+
+size_t ZPageAllocator::try_ensure_unused_for_pre_mapped(size_t size) {
+  // This function is called during construction, where the
+  // physical memory manager might have failed to initialied.
+  if (!_physical.is_initialized()) {
+    return 0;
+  }
+
+  return try_ensure_unused(size, true /* no_reserve */);
+}
+
 ZPage* ZPageAllocator::create_page(uint8_t type, size_t size) {
   // Allocate physical memory
   const ZPhysicalMemory pmem = _physical.alloc(size);
@@ -259,8 +289,8 @@
 }
 
 ZPage* ZPageAllocator::alloc_page_common_inner(uint8_t type, size_t size, ZAllocationFlags flags) {
-  const size_t available_total = available(flags);
-  if (available_total < size) {
+  const size_t max = max_available(flags.no_reserve());
+  if (max < size) {
     // Not enough free memory
     return NULL;
   }
@@ -281,11 +311,11 @@
   // subsequent allocations can use the physical memory.
   flush_pre_mapped();
 
-  // Check if physical memory is available
-  const size_t available_physical = _physical.available();
-  if (available_physical < size) {
+  // Try ensure that physical memory is available
+  const size_t unused = try_ensure_unused(size, flags.no_reserve());
+  if (unused < size) {
     // Flush cache to free up more physical memory
-    flush_cache(size - available_physical);
+    flush_cache(size - unused);
   }
 
   // Create new page and allocate physical memory
@@ -303,7 +333,7 @@
   increase_used(size, flags.relocation());
 
   // Send trace event
-  ZTracer::tracer()->report_page_alloc(size, used(), available(flags), _cache.available(), flags);
+  ZTracer::tracer()->report_page_alloc(size, used(), max_available(flags.no_reserve()), _cache.available(), flags);
 
   return page;
 }