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 #include "precompiled.hpp"
  27 
  28 #include "metaspace/metaspace_testhelper.hpp"
  29 
  30 using namespace metaspace::chunklevel;
  31 
  32   // No reserve limit, and a commit limit.
  33 MetaspaceTestHelper::MetaspaceTestHelper(size_t commit_limit, size_t reserve_limit)
  34 : metaspace::MetaspaceTestContext("metaspace-gtest-context", commit_limit, reserve_limit),
  35   _num_chunks_allocated(0)
  36 {
  37 }
  38 
  39 void MetaspaceTestHelper::checked_alloc_chunk_0(Metachunk** p_return_value, chunklevel_t preferred_level, chunklevel_t max_level,
  40                                                       size_t min_committed_size) {
  41 
  42   *p_return_value = NULL;
  43 
  44   Metachunk* c = cm().get_chunk(preferred_level, max_level, min_committed_size);
  45 
  46   if (c != NULL) {
  47 
  48     ASSERT_LE(c->level(), max_level);
  49     ASSERT_GE(c->level(), preferred_level);
  50     ASSERT_GE(c->committed_words(), min_committed_size);
  51     ASSERT_EQ(c->committed_words(), c->free_below_committed_words());
  52     ASSERT_EQ(c->used_words(), (size_t)0);
  53     ASSERT_TRUE(c->is_in_use());
  54     ASSERT_FALSE(c->is_free());
  55     ASSERT_FALSE(c->is_dead());
  56     ASSERT_NULL(c->next());
  57     ASSERT_NULL(c->prev());
  58     if (c->level() == HIGHEST_CHUNK_LEVEL) {
  59       ASSERT_TRUE(c->is_leaf_chunk());
  60     } else {
  61       ASSERT_FALSE(c->is_leaf_chunk());
  62     }
  63     if (c->level() == LOWEST_CHUNK_LEVEL) {
  64       ASSERT_TRUE(c->is_root_chunk());
  65     } else {
  66       ASSERT_FALSE(c->is_root_chunk());
  67     }
  68     if (_num_chunks_allocated == 0) { // First chunk? We can make more assumptions
  69       ASSERT_EQ(c->level(), preferred_level);
  70       // Needs lock EXPECT_NULL(c->next_in_vs());
  71       // Needs lock EXPECT_NULL(c->prev_in_vs());
  72       ASSERT_TRUE(c->is_root_chunk() || c->is_leader());
  73     }
  74     _num_chunks_allocated ++;
  75 
  76   }
  77 
  78   *p_return_value = c;
  79 
  80 }
  81 
  82 // Test pattern established when allocating from the chunk with allocate_from_chunk_with_tests().
  83 void MetaspaceTestHelper::test_pattern(Metachunk* c, size_t word_size) {
  84   check_range_for_pattern(c->base(), word_size, (uintx)c);
  85 }
  86 
  87 void MetaspaceTestHelper::return_chunk(Metachunk* c) {
  88   test_pattern(c);
  89   c->set_in_use(); // Forestall assert in cm
  90   cm().return_chunk(c);
  91 }
  92 
  93  void MetaspaceTestHelper::allocate_from_chunk(MetaWord** p_return_value, Metachunk* c, size_t word_size) {
  94 
  95   size_t used_before = c->used_words();
  96   size_t free_before = c->free_words();
  97   size_t free_below_committed_before = c->free_below_committed_words();
  98   const MetaWord* top_before = c->top();
  99 
 100   MetaWord* p = c->allocate(word_size);
 101   EXPECT_NOT_NULL(p);
 102   EXPECT_EQ(c->used_words(), used_before + word_size);
 103   EXPECT_EQ(c->free_words(), free_before - word_size);
 104   EXPECT_EQ(c->free_below_committed_words(), free_below_committed_before - word_size);
 105   EXPECT_EQ(c->top(), top_before + word_size);
 106 
 107   // Old content should be preserved
 108   test_pattern(c, used_before);
 109 
 110   // Fill newly allocated range too
 111   fill_range_with_pattern(p, word_size, (uintx)c);
 112 
 113   *p_return_value = p;
 114 }
 115 
 116 void MetaspaceTestHelper::commit_chunk_with_test(Metachunk* c, size_t additional_size) {
 117 
 118   size_t used_before = c->used_words();
 119   size_t free_before = c->free_words();
 120   const MetaWord* top_before = c->top();
 121 
 122   c->set_in_use();
 123   bool b = c->ensure_committed_additional(additional_size);
 124   EXPECT_TRUE(b);
 125 
 126   // We should have enough committed size now
 127   EXPECT_GE(c->free_below_committed_words(), additional_size);
 128 
 129   // used, free, top should be unchanged.
 130   EXPECT_EQ(c->used_words(), used_before);
 131   EXPECT_EQ(c->free_words(), free_before);
 132   EXPECT_EQ(c->top(), top_before);
 133 
 134   test_pattern(c, used_before);
 135 
 136 }
 137 
 138 void MetaspaceTestHelper::commit_chunk_expect_failure(Metachunk* c, size_t additional_size) {
 139 
 140   size_t used_before = c->used_words();
 141   size_t free_before = c->free_words();
 142   size_t free_below_committed_before = c->free_below_committed_words();
 143   const MetaWord* top_before = c->top();
 144 
 145   c->set_in_use();
 146   bool b = c->ensure_committed_additional(additional_size);
 147   EXPECT_FALSE(b);
 148 
 149   // Nothing should have changed
 150   EXPECT_EQ(c->used_words(), used_before);
 151   EXPECT_EQ(c->free_words(), free_before);
 152   EXPECT_EQ(c->free_below_committed_words(), free_below_committed_before);
 153   EXPECT_EQ(c->top(), top_before);
 154 
 155   test_pattern(c, used_before);
 156 
 157 }
 158 
 159 void MetaspaceTestHelper::uncommit_chunk_with_test(Metachunk* c) {
 160   if (c->word_size() >= Settings::commit_granule_words()) {
 161     c->set_free();  // Forestall assert in uncommit
 162     c->reset_used_words();
 163     c->uncommit();
 164 
 165     EXPECT_EQ(c->free_below_committed_words(), (size_t)0);
 166     EXPECT_EQ(c->used_words(), (size_t)0);
 167     EXPECT_EQ(c->free_words(), c->word_size());
 168     EXPECT_EQ(c->top(), c->base());
 169     EXPECT_TRUE(c->is_fully_uncommitted());
 170   }
 171 }
 172 
 173 
 174 
 175 /////// SparseArray<T> ////////////////
 176 
 177 
 178