< prev index next >

src/hotspot/share/memory/metaspace/metaspaceCommon.cpp

Print this page
rev 60538 : imported patch jep387-core.patch

@@ -1,7 +1,8 @@
 /*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2020 SAP SE. 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
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.

@@ -22,19 +23,22 @@
  *
  */
 
 #include "precompiled.hpp"
 
+#include "memory/metaspace/allocationGuard.hpp"
+#include "memory/metaspace/freeBlocks.hpp"
 #include "memory/metaspace/metaspaceCommon.hpp"
 #include "memory/metaspace/virtualSpaceNode.hpp"
+
+#include "utilities/align.hpp"
 #include "utilities/debug.hpp"
 #include "utilities/globalDefinitions.hpp"
 #include "utilities/ostream.hpp"
 
 namespace metaspace {
 
-DEBUG_ONLY(internal_statistics_t g_internal_statistics;)
 
 // Print a size, in words, scaled.
 void print_scaled_words(outputStream* st, size_t word_size, size_t scale, int width) {
   print_human_readable_size(st, word_size * sizeof(MetaWord), scale, width);
 }

@@ -45,10 +49,23 @@
   st->print(" (");
   print_percentage(st, compare_word_size, word_size);
   st->print(")");
 }
 
+static const char* display_unit_for_scale(size_t scale) {
+  const char* s = NULL;
+  switch(scale) {
+    case 1: s = "bytes"; break;
+    case BytesPerWord: s = "words"; break;
+    case K: s = "KB"; break;
+    case M: s = "MB"; break;
+    case G: s = "GB"; break;
+    default:
+      ShouldNotReachHere();
+  }
+  return s;
+}
 
 // Print a human readable size.
 // byte_size: size, in bytes, to be printed.
 // scale: one of 1 (byte-wise printing), sizeof(word) (word-size printing), K, M, G (scaled by KB, MB, GB respectively,
 //         or 0, which means the best scale is choosen dynamically.

@@ -72,42 +89,51 @@
     }
     return print_human_readable_size(st, byte_size, scale, width);
   }
 
 #ifdef ASSERT
-  assert(scale == 1 || scale == BytesPerWord || scale == K || scale == M || scale == G, "Invalid scale");
+  assert(scale == 1 || scale == BytesPerWord ||
+         scale == K || scale == M || scale == G, "Invalid scale");
   // Special case: printing wordsize should only be done with word-sized values
   if (scale == BytesPerWord) {
     assert(byte_size % BytesPerWord == 0, "not word sized");
   }
 #endif
 
+  if (width == -1) {
+    if (scale == 1) {
+      st->print(SIZE_FORMAT " bytes", byte_size);
+    } else if (scale == BytesPerWord) {
+      st->print(SIZE_FORMAT " words", byte_size / BytesPerWord);
+    } else {
+      const char* display_unit = display_unit_for_scale(scale);
+      float display_value = (float) byte_size / scale;
+      // Prevent very small but non-null values showing up as 0.00.
+      if (byte_size > 0 && display_value < 0.01f) {
+        st->print("<0.01 %s", display_unit);
+      } else {
+        st->print("%.2f %s", display_value, display_unit);
+      }
+    }
+  } else {
   if (scale == 1) {
     st->print("%*" PRIuPTR " bytes", width, byte_size);
   } else if (scale == BytesPerWord) {
     st->print("%*" PRIuPTR " words", width, byte_size / BytesPerWord);
   } else {
-    const char* display_unit = "";
-    switch(scale) {
-      case 1: display_unit = "bytes"; break;
-      case BytesPerWord: display_unit = "words"; break;
-      case K: display_unit = "KB"; break;
-      case M: display_unit = "MB"; break;
-      case G: display_unit = "GB"; break;
-      default:
-        ShouldNotReachHere();
-    }
+      const char* display_unit = display_unit_for_scale(scale);
     float display_value = (float) byte_size / scale;
     // Since we use width to display a number with two trailing digits, increase it a bit.
     width += 3;
     // Prevent very small but non-null values showing up as 0.00.
     if (byte_size > 0 && display_value < 0.01f) {
       st->print("%*s %s", width, "<0.01", display_unit);
     } else {
       st->print("%*.2f %s", width, display_value, display_unit);
     }
   }
+  }
 }
 
 // Prints a percentage value. Values smaller than 1% but not 0 are displayed as "<1%", values
 // larger than 99% but not 100% are displayed as ">100%".
 void print_percentage(outputStream* st, size_t total, size_t part) {

@@ -128,74 +154,10 @@
       st->print("%3.0f%%", p);
     }
   }
 }
 
-// Returns size of this chunk type.
-size_t get_size_for_nonhumongous_chunktype(ChunkIndex chunktype, bool is_class) {
-  assert(is_valid_nonhumongous_chunktype(chunktype), "invalid chunk type.");
-  size_t size = 0;
-  if (is_class) {
-    switch(chunktype) {
-      case SpecializedIndex: size = ClassSpecializedChunk; break;
-      case SmallIndex: size = ClassSmallChunk; break;
-      case MediumIndex: size = ClassMediumChunk; break;
-      default:
-        ShouldNotReachHere();
-    }
-  } else {
-    switch(chunktype) {
-      case SpecializedIndex: size = SpecializedChunk; break;
-      case SmallIndex: size = SmallChunk; break;
-      case MediumIndex: size = MediumChunk; break;
-      default:
-        ShouldNotReachHere();
-    }
-  }
-  return size;
-}
-
-ChunkIndex get_chunk_type_by_size(size_t size, bool is_class) {
-  if (is_class) {
-    if (size == ClassSpecializedChunk) {
-      return SpecializedIndex;
-    } else if (size == ClassSmallChunk) {
-      return SmallIndex;
-    } else if (size == ClassMediumChunk) {
-      return MediumIndex;
-    } else if (size > ClassMediumChunk) {
-      // A valid humongous chunk size is a multiple of the smallest chunk size.
-      assert(is_aligned(size, ClassSpecializedChunk), "Invalid chunk size");
-      return HumongousIndex;
-    }
-  } else {
-    if (size == SpecializedChunk) {
-      return SpecializedIndex;
-    } else if (size == SmallChunk) {
-      return SmallIndex;
-    } else if (size == MediumChunk) {
-      return MediumIndex;
-    } else if (size > MediumChunk) {
-      // A valid humongous chunk size is a multiple of the smallest chunk size.
-      assert(is_aligned(size, SpecializedChunk), "Invalid chunk size");
-      return HumongousIndex;
-    }
-  }
-  ShouldNotReachHere();
-  return (ChunkIndex)-1;
-}
-
-ChunkIndex next_chunk_index(ChunkIndex i) {
-  assert(i < NumberOfInUseLists, "Out of bound");
-  return (ChunkIndex) (i+1);
-}
-
-ChunkIndex prev_chunk_index(ChunkIndex i) {
-  assert(i > ZeroIndex, "Out of bound");
-  return (ChunkIndex) (i-1);
-}
-
 const char* loaders_plural(uintx num) {
   return num == 1 ? "loader" : "loaders";
 }
 
 const char* classes_plural(uintx num) {

@@ -207,7 +169,36 @@
   if (classes_shared > 0) {
     out->print(" (" UINTX_FORMAT " shared)", classes_shared);
   }
 }
 
+// Given a net allocation word size, return the raw word size we actually allocate.
+// Note: externally visible for gtests.
+//static
+size_t get_raw_word_size_for_requested_word_size(size_t word_size) {
+
+  size_t byte_size = word_size * BytesPerWord;
+
+  // Deallocated metablocks are kept in a binlist which limits their minimal
+  //  size to at least the size of a binlist item (2 words).
+  byte_size = MAX2(byte_size, FreeBlocks::minimal_word_size * BytesPerWord);
+
+  // Metaspace allocations are aligned to word size.
+  byte_size = align_up(byte_size, allocation_alignment_bytes);
+
+  // If we guard allocations, we need additional space for a prefix.
+#ifdef ASSERT
+  if (Settings::use_allocation_guard()) {
+    byte_size += align_up(prefix_size(), allocation_alignment_bytes);
+  }
+#endif
+
+  size_t raw_word_size = byte_size / BytesPerWord;
+
+  assert(raw_word_size * BytesPerWord == byte_size, "Sanity");
+
+  return raw_word_size;
+
+}
+
 } // namespace metaspace
 
< prev index next >