1 /*
   2  * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
   3  * Copyright (c) 2018, 2020 SAP SE. All rights reserved.
   4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   5  *
   6  * This code is free software; you can redistribute it and/or modify it
   7  * under the terms of the GNU General Public License version 2 only, as
   8  * published by the Free Software Foundation.
   9  *
  10  * This code is distributed in the hope that it will be useful, but WITHOUT
  11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  *
  24  */
  25 
  26 #ifndef GTEST_METASPACE_METASPACETESTCOMMON_HPP
  27 #define GTEST_METASPACE_METASPACETESTCOMMON_HPP
  28 
  29 #include "memory/allocation.hpp"
  30 
  31 
  32 #include "memory/metaspace/arenaGrowthPolicy.hpp"
  33 #include "memory/metaspace/binlist.hpp"
  34 #include "memory/metaspace/blocktree.hpp"
  35 #include "memory/metaspace/chunkHeaderPool.hpp"
  36 #include "memory/metaspace/chunkLevel.hpp"
  37 #include "memory/metaspace/chunkManager.hpp"
  38 #include "memory/metaspace/counter.hpp"
  39 #include "memory/metaspace/commitLimiter.hpp"
  40 #include "memory/metaspace/commitMask.hpp"
  41 #include "memory/metaspace/freeBlocks.hpp"
  42 #include "memory/metaspace/freeChunkList.hpp"
  43 #include "memory/metaspace/internStat.hpp"
  44 #include "memory/metaspace/metachunk.hpp"
  45 #include "memory/metaspace/metaspaceArena.hpp"
  46 #include "memory/metaspace/metaspaceCommon.hpp"
  47 #include "memory/metaspace/metaspaceEnums.hpp"
  48 #include "memory/metaspace/metaspaceStatistics.hpp"
  49 #include "memory/metaspace/metaspace_test.hpp"
  50 #include "memory/metaspace/virtualSpaceList.hpp"
  51 #include "memory/metaspace/settings.hpp"
  52 #include "runtime/mutexLocker.hpp"
  53 #include "runtime/os.hpp"
  54 
  55 #include "utilities/align.hpp"
  56 #include "utilities/debug.hpp"
  57 #include "utilities/globalDefinitions.hpp"
  58 
  59 #include "unittest.hpp"
  60 
  61 
  62 #include <stdio.h>
  63 
  64 
  65 //////////////////////////////////////////////////////////
  66 // handy aliases
  67 
  68 using metaspace::BinListImpl;
  69 using metaspace::BlockTree;
  70 using metaspace::ArenaGrowthPolicy;
  71 using metaspace::ChunkHeaderPool;
  72 using metaspace::ChunkManager;
  73 using metaspace::CommitLimiter;
  74 using metaspace::CommitMask;
  75 using metaspace::SizeCounter;
  76 using metaspace::SizeAtomicCounter;
  77 using metaspace::IntCounter;
  78 using metaspace::FreeBlocks;
  79 using metaspace::FreeChunkList;
  80 using metaspace::FreeChunkListVector;
  81 using metaspace::MemRangeCounter;
  82 using metaspace::Metachunk;
  83 using metaspace::MetachunkList;
  84 using metaspace::Settings;
  85 using metaspace::arena_stats_t;
  86 using metaspace::in_use_chunk_stats_t;
  87 using metaspace::cm_stats_t;
  88 using metaspace::SizeCounter;
  89 using metaspace::MetaspaceArena;
  90 using metaspace::VirtualSpaceList;
  91 using metaspace::VirtualSpaceNode;
  92 
  93 using metaspace::chunklevel_t;
  94 using namespace metaspace::chunklevel;
  95 
  96 
  97 /////////////////////////////////////////////////////////////////////
  98 // A little mockup to mimick and test the CommitMask in various tests
  99 
 100 class TestMap {
 101   const size_t _len;
 102   char* _arr;
 103 public:
 104   TestMap(size_t len) : _len(len), _arr(NULL) {
 105     _arr = NEW_C_HEAP_ARRAY(char, len, mtInternal);
 106     memset(_arr, 0, _len);
 107   }
 108   ~TestMap() { FREE_C_HEAP_ARRAY(char, _arr); }
 109 
 110   int get_num_set(size_t from, size_t to) const {
 111     int result = 0;
 112     for(size_t i = from; i < to; i ++) {
 113       if (_arr[i] > 0) {
 114         result ++;
 115       }
 116     }
 117     return result;
 118   }
 119 
 120   size_t get_num_set() const { return get_num_set(0, _len); }
 121 
 122   void set_range(size_t from, size_t to) {
 123     memset(_arr + from, 1, to - from);
 124   }
 125 
 126   void clear_range(size_t from, size_t to) {
 127     memset(_arr + from, 0, to - from);
 128   }
 129 
 130   bool at(size_t pos) const {
 131     return _arr[pos] == 1;
 132   }
 133 
 134 };
 135 
 136 
 137 ///////////////////////////////////////////////////////////
 138 // Helper class for generating random allocation sizes
 139 class RandSizeGenerator {
 140   const size_t _min; // [
 141   const size_t _max; // )
 142   const float _outlier_chance; // 0.0 -- 1.0
 143   const size_t _outlier_min; // [
 144   const size_t _outlier_max; // )
 145 public:
 146   RandSizeGenerator(size_t min, size_t max)
 147     : _min(min), _max(max), _outlier_chance(0.0), _outlier_min(min), _outlier_max(max)
 148   {}
 149 
 150   RandSizeGenerator(size_t min, size_t max, float outlier_chance, size_t outlier_min, size_t outlier_max)
 151     : _min(min), _max(max), _outlier_chance(outlier_chance), _outlier_min(outlier_min), _outlier_max(outlier_max)
 152   {}
 153 
 154   size_t min() const { return _min; }
 155   size_t max() const { return _max; }
 156 
 157   size_t get() const {
 158     size_t l1 = _min;
 159     size_t l2 = _max;
 160     int r = os::random() % 1000;
 161     if ((float)r < _outlier_chance * 1000.0) {
 162       l1 = _outlier_min;
 163       l2 = _outlier_max;
 164     }
 165     const size_t d = l2 - l1;
 166     return l1 + (os::random() % d);
 167   }
 168 
 169 }; // end RandSizeGenerator
 170 
 171 size_t get_random_size(size_t min, size_t max);
 172 
 173 ///////////////////////////////////////////////////////////
 174 // Function to test-access a memory range
 175 
 176 void zap_range(MetaWord* p, size_t word_size);
 177 
 178 // "fill_range_with_pattern" fills a range of heap words with pointers to itself.
 179 //
 180 // The idea is to fill a memory range with a pattern which is both marked clearly to the caller
 181 // and cannot be moved without becoming invalid.
 182 //
 183 // The filled range can be checked with check_range_for_pattern. One also can only check
 184 // a sub range of the original range.
 185 void fill_range_with_pattern(MetaWord* p, uintx pattern, size_t word_size);
 186 void check_range_for_pattern(const MetaWord* p, uintx pattern, size_t word_size);
 187 
 188 // Writes a uniqe pattern to p
 189 void mark_address(MetaWord* p, uintx pattern);
 190 // checks pattern at address
 191 void check_marked_address(const MetaWord* p, uintx pattern);
 192 
 193 // Similar to fill_range_with_pattern, but only marks start and end. This is optimized for cases
 194 // where fill_range_with_pattern just is too slow.
 195 // Use check_marked_range to check the range. In contrast to check_range_for_pattern, only the original
 196 // range can be checked.
 197 void mark_range(MetaWord* p, uintx pattern, size_t word_size);
 198 void check_marked_range(const MetaWord* p, uintx pattern, size_t word_size);
 199 
 200 void mark_range(MetaWord* p, size_t word_size);
 201 void check_marked_range(const MetaWord* p, size_t word_size);
 202 
 203 //////////////////////////////////////////////////////////
 204 // Some helpers to avoid typing out those annoying casts for NULL
 205 
 206 #define ASSERT_NOT_NULL(ptr)      ASSERT_NE((void*)NULL, (void*)ptr)
 207 #define ASSERT_NULL(ptr)          ASSERT_EQ((void*)NULL, (void*)ptr)
 208 #define EXPECT_NOT_NULL(ptr)      EXPECT_NE((void*)NULL, (void*)ptr)
 209 #define EXPECT_NULL(ptr)          EXPECT_EQ((void*)NULL, (void*)ptr)
 210 
 211 #define ASSERT_0(v)               ASSERT_EQ((intptr_t)0, (intptr_t)v)
 212 #define ASSERT_NOT_0(v)           ASSERT_NE((intptr_t)0, (intptr_t)v)
 213 #define EXPECT_0(v)               EXPECT_EQ((intptr_t)0, (intptr_t)v)
 214 #define EXPECT_NOT_0(v)           EXPECT_NE((intptr_t)0, (intptr_t)v)
 215 
 216 //////////////////////////////////////////////////////////
 217 // logging
 218 
 219 // Define "LOG_PLEASE" to switch on logging for a particular test before inclusion of this header.
 220 #ifdef LOG_PLEASE
 221   #define LOG(...) { printf(__VA_ARGS__); printf("\n"); fflush(stdout); }
 222 #else
 223   #define LOG(...)
 224 #endif
 225 
 226 //////////////////////////////////////////////////////////
 227 // Helper
 228 
 229 size_t get_workingset_size();
 230 
 231 // A simple preallocated buffer used to "feed" someone.
 232 // Mimicks chunk retirement leftover blocks.
 233 class FeederBuffer {
 234 
 235   MetaWord* _buf;
 236 
 237   // Buffer capacity in size of words.
 238   const size_t _cap;
 239 
 240   // Used words.
 241   size_t _used;
 242 
 243 public:
 244 
 245   FeederBuffer(size_t size) : _buf(NULL), _cap(size), _used(0) {
 246     _buf = NEW_C_HEAP_ARRAY(MetaWord, _cap, mtInternal);
 247   }
 248 
 249   ~FeederBuffer() {
 250     FREE_C_HEAP_ARRAY(MetaWord, _buf);
 251   }
 252 
 253   MetaWord* get(size_t word_size) {
 254     if (_used + word_size > _cap) {
 255       return NULL;
 256     }
 257     MetaWord* p = _buf + _used;
 258     _used += word_size;
 259     return p;
 260   }
 261 
 262   bool is_valid_pointer(MetaWord* p) const {
 263     return p >= _buf && p < _buf + _used;
 264   }
 265 
 266   bool is_valid_range(MetaWord* p, size_t word_size) const {
 267     return is_valid_pointer(p) &&
 268            word_size > 0 ? is_valid_pointer(p + word_size - 1) : true;
 269   }
 270 
 271 };
 272 
 273 #endif // GTEST_METASPACE_METASPACETESTCOMMON_HPP