1 /*
   2  * Copyright (c) 2018, 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 #include "precompiled.hpp"
  25 
  26 #include "logging/log.hpp"
  27 #include "memory/metaspace.hpp"
  28 #include "memory/metaspaceTracer.hpp"
  29 #include "memory/metaspace/chunkAllocSequence.hpp"
  30 #include "memory/metaspace/chunkManager.hpp"
  31 #include "memory/metaspace/classLoaderMetaspace.hpp"
  32 #include "memory/metaspace/metaspaceEnums.hpp"
  33 #include "memory/metaspace/metaspaceStatistics.hpp"
  34 #include "memory/metaspace/spaceManager.hpp"
  35 #include "runtime/atomic.hpp"
  36 #include "utilities/debug.hpp"
  37 
  38 namespace metaspace {
  39 
  40 ClassLoaderMetaspace::ClassLoaderMetaspace(Mutex* lock, MetaspaceType space_type)
  41   : _lock(lock)
  42   , _space_type(space_type)
  43   , _non_class_space_manager(NULL)
  44   , _class_space_manager(NULL)
  45 {
  46   DEBUG_ONLY(Atomic::inc(&g_internal_statistics.num_metaspace_births));
  47 
  48   // Initialize non-class spacemanager
  49   _non_class_space_manager = new SpaceManager(
  50       ChunkManager::chunkmanager_nonclass(),
  51       ChunkAllocSequence::alloc_sequence_by_space_type(space_type, false),
  52       lock);
  53 
  54   // If needed, initialize class spacemanager
  55   if (Metaspace::using_class_space()) {
  56     _class_space_manager = new SpaceManager(
  57         ChunkManager::chunkmanager_class(),
  58         ChunkAllocSequence::alloc_sequence_by_space_type(space_type, true),
  59         lock);
  60   }
  61 
  62 }
  63 
  64 ClassLoaderMetaspace::~ClassLoaderMetaspace() {
  65   Metaspace::assert_not_frozen();
  66   DEBUG_ONLY(Atomic::inc(&g_internal_statistics.num_metaspace_deaths));
  67   delete _non_class_space_manager;
  68   delete _class_space_manager;
  69 }
  70 
  71 // Allocate word_size words from Metaspace.
  72 MetaWord* ClassLoaderMetaspace::allocate(size_t word_size, MetadataType mdType) {
  73   Metaspace::assert_not_frozen();
  74   DEBUG_ONLY(Atomic::inc(&g_internal_statistics.num_allocs));
  75   if (is_class(mdType) && Metaspace::using_class_space()) {
  76     return class_space_manager()->allocate(word_size);
  77   } else {
  78     return non_class_space_manager()->allocate(word_size);
  79   }
  80 }
  81 
  82 // Attempt to expand the GC threshold to be good for at least another word_size words
  83 // and allocate. Returns NULL if failure. Used during Metaspace GC.
  84 MetaWord* ClassLoaderMetaspace::expand_and_allocate(size_t word_size, MetadataType mdType) {
  85   Metaspace::assert_not_frozen();
  86   size_t delta_bytes = MetaspaceGC::delta_capacity_until_GC(word_size * BytesPerWord);
  87   assert(delta_bytes > 0, "Must be");
  88 
  89   size_t before = 0;
  90   size_t after = 0;
  91   bool can_retry = true;
  92   MetaWord* res;
  93   bool incremented;
  94 
  95   // Each thread increments the HWM at most once. Even if the thread fails to increment
  96   // the HWM, an allocation is still attempted. This is because another thread must then
  97   // have incremented the HWM and therefore the allocation might still succeed.
  98   do {
  99     incremented = MetaspaceGC::inc_capacity_until_GC(delta_bytes, &after, &before, &can_retry);
 100     res = allocate(word_size, mdType);
 101   } while (!incremented && res == NULL && can_retry);
 102 
 103   if (incremented) {
 104     Metaspace::tracer()->report_gc_threshold(before, after,
 105                                   MetaspaceGCThresholdUpdater::ExpandAndAllocate);
 106     log_trace(gc, metaspace)("Increase capacity to GC from " SIZE_FORMAT " to " SIZE_FORMAT, before, after);
 107   }
 108 
 109   return res;
 110 }
 111 
 112 // Prematurely returns a metaspace allocation to the _block_freelists
 113 // because it is not needed anymore.
 114 void ClassLoaderMetaspace::deallocate(MetaWord* ptr, size_t word_size, bool is_class) {
 115 
 116   Metaspace::assert_not_frozen();
 117   DEBUG_ONLY(Atomic::inc(&g_internal_statistics.num_external_deallocs));
 118 
 119   if (is_class && Metaspace::using_class_space()) {
 120     class_space_manager()->deallocate(ptr, word_size);
 121   } else {
 122     non_class_space_manager()->deallocate(ptr, word_size);
 123   }
 124 
 125 }
 126 
 127 // Update statistics. This walks all in-use chunks.
 128 void ClassLoaderMetaspace::add_to_statistics(ClassLoaderMetaspaceStatistics* out) const {
 129   non_class_space_manager()->add_to_statistics(&out->sm_stats[NonClassType]);
 130   if (class_space_manager() != NULL) {
 131     class_space_manager()->add_to_statistics(&out->sm_stats[ClassType]);
 132   }
 133 }
 134 
 135 #ifdef ASSERT
 136 void ClassLoaderMetaspace::verify(bool slow) const {
 137   check_valid_spacetype(_space_type);
 138   non_class_space_manager()->verify(slow);
 139   if (Metaspace::using_class_space()) {
 140     class_space_manager()->verify(slow);
 141   }
 142 }
 143 #endif // ASSERT
 144 
 145 } // end namespace metaspace
 146 
 147 
 148 
 149