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/metaspace/chunkAllocSequence.hpp"
  29 #include "memory/metaspace/classLoaderMetaspace.hpp"
  30 #include "memory/metaspace/spaceManager.hpp"
  31 #include "runtime/atomic.hpp"
  32 #include "utilities/debug.hpp"
  33 
  34 namespace metaspace {
  35 
  36 ClassLoaderMetaspace::ClassLoaderMetaspace(Mutex* lock, Metaspace::MetaspaceType space_type)
  37   : _lock(lock)
  38   , _space_type(space_type)
  39   , _non_class_space_manager(NULL)
  40   , _class_space_manager(NULL)
  41 {
  42   DEBUG_ONLY(Atomic::inc(&g_internal_statistics.num_metaspace_births));
  43 
  44   // Initialize non-class spacemanager
  45   _non_class_space_manager = new SpaceManager(
  46       Metaspace::chunk_manager_metadata(),
  47       ChunkAllocSequence::alloc_sequence_by_space_type(space_type, false),
  48       lock);
  49 
  50   // If needed, initialize class spacemanager
  51   if (Metaspace::using_class_space()) {
  52     _class_space_manager = new SpaceManager(
  53         Metaspace::chunk_manager_class(),
  54         ChunkAllocSequence::alloc_sequence_by_space_type(space_type, true),
  55         lock);
  56   }
  57 
  58 }
  59 
  60 ClassLoaderMetaspace::~ClassLoaderMetaspace() {
  61   Metaspace::assert_not_frozen();
  62   DEBUG_ONLY(Atomic::inc(&g_internal_statistics.num_metaspace_deaths));
  63   delete _non_class_space_manager;
  64   delete _class_space_manager;
  65 }
  66 
  67 // Allocate word_size words from Metaspace.
  68 MetaWord* ClassLoaderMetaspace::allocate(size_t word_size, bool is_class) {
  69   Metaspace::assert_not_frozen();
  70   DEBUG_ONLY(Atomic::inc(&g_internal_statistics.num_allocs));
  71   if (is_class && Metaspace::using_class_space()) {
  72     return class_space_manager()->allocate(word_size);
  73   } else {
  74     return non_class_space_manager()->allocate(word_size);
  75   }
  76 }
  77 
  78 // Attempt to expand the GC threshold to be good for at least another word_size words
  79 // and allocate. Returns NULL if failure. Used during Metaspace GC.
  80 MetaWord* ClassLoaderMetaspace::expand_GC_threshold_and_allocate(size_t word_size, bool is_class) {
  81   Metaspace::assert_not_frozen();
  82   size_t delta_bytes = MetaspaceGC::delta_capacity_until_GC(word_size * BytesPerWord);
  83   assert(delta_bytes > 0, "Must be");
  84 
  85   size_t before = 0;
  86   size_t after = 0;
  87   bool can_retry = true;
  88   MetaWord* res;
  89   bool incremented;
  90 
  91   // Each thread increments the HWM at most once. Even if the thread fails to increment
  92   // the HWM, an allocation is still attempted. This is because another thread must then
  93   // have incremented the HWM and therefore the allocation might still succeed.
  94   do {
  95     incremented = MetaspaceGC::inc_capacity_until_GC(delta_bytes, &after, &before, &can_retry);
  96     res = allocate(word_size, is_class);
  97   } while (!incremented && res == NULL && can_retry);
  98 
  99   if (incremented) {
 100     Metaspace::tracer()->report_gc_threshold(before, after,
 101                                   MetaspaceGCThresholdUpdater::ExpandAndAllocate);
 102     log_trace(gc, metaspace)("Increase capacity to GC from " SIZE_FORMAT " to " SIZE_FORMAT, before, after);
 103   }
 104 
 105   return res;
 106 }
 107 
 108 // Prematurely returns a metaspace allocation to the _block_freelists
 109 // because it is not needed anymore.
 110 void ClassLoaderMetaspace::deallocate(MetaWord* ptr, size_t word_size, bool is_class) {
 111 
 112   Metaspace::assert_not_frozen();
 113   DEBUG_ONLY(Atomic::inc(&g_internal_statistics.num_external_deallocs));
 114 
 115   if (is_class && Metaspace::using_class_space()) {
 116     class_space_manager()->deallocate(ptr, word_size);
 117   } else {
 118     non_class_space_manager()->deallocate(ptr, word_size);
 119   }
 120 
 121 }
 122 
 123 
 124 } // end namespace metaspace
 125 
 126 
 127 
 128