Path: blob/master/test/hotspot/gtest/metaspace/test_commitmask.cpp
41145 views
/*1* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.2* Copyright (c) 2020 SAP SE. 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 it6* under the terms of the GNU General Public License version 2 only, as7* published by the Free Software Foundation.8*9* This code is distributed in the hope that it will be useful, but WITHOUT10* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or11* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License12* version 2 for more details (a copy is included in the LICENSE file that13* accompanied this code).14*15* You should have received a copy of the GNU General Public License version16* 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 USA20* or visit www.oracle.com if you need additional information or have any21* questions.22*23*/2425#include "precompiled.hpp"26#include "memory/metaspace/commitMask.hpp"27#include "memory/metaspace/metaspaceSettings.hpp"28#include "metaspaceGtestCommon.hpp"29#include "metaspaceGtestRangeHelpers.hpp"30#include "runtime/os.hpp"31#include "utilities/align.hpp"32#include "utilities/debug.hpp"3334using metaspace::CommitMask;35using metaspace::Settings;3637static int get_random(int limit) { return os::random() % limit; }3839class CommitMaskTest {40const MetaWord* const _base;41const size_t _word_size;4243CommitMask _mask;4445void verify_mask() {46// Note: we omit the touch test since we operate on fictional47// memory48DEBUG_ONLY(_mask.verify();)49}5051// Return a random sub range within [_base.._base + word_size),52// aligned to granule size53const MetaWord* calc_random_subrange(size_t* p_word_size) {54size_t l1 = get_random((int)_word_size);55size_t l2 = get_random((int)_word_size);56if (l1 > l2) {57size_t l = l1;58l1 = l2;59l2 = l;60}61l1 = align_down(l1, Settings::commit_granule_words());62l2 = align_up(l2, Settings::commit_granule_words());6364const MetaWord* p = _base + l1;65const size_t len = l2 - l1;6667assert(p >= _base && p + len <= _base + _word_size,68"Sanity");69*p_word_size = len;7071return p;72}7374void test1() {7576LOG("test1");7778// Commit everything79size_t prior_committed = _mask.mark_range_as_committed(_base, _word_size);80verify_mask();81ASSERT_LE(prior_committed, _word_size); // We do not really know8283// Commit everything again, should be a noop84prior_committed = _mask.mark_range_as_committed(_base, _word_size);85verify_mask();86ASSERT_EQ(prior_committed, _word_size);8788ASSERT_EQ(_mask.get_committed_size(),89_word_size);90ASSERT_EQ(_mask.get_committed_size_in_range(_base, _word_size),91_word_size);9293for (const MetaWord* p = _base; p < _base + _word_size; p++) {94ASSERT_TRUE(_mask.is_committed_address(p));95}9697// Now make an uncommitted hole98size_t sr_word_size;99const MetaWord* sr_base = calc_random_subrange(&sr_word_size);100LOG("subrange " PTR_FORMAT "-" PTR_FORMAT ".",101p2i(sr_base), p2i(sr_base + sr_word_size));102103size_t prior_uncommitted =104_mask.mark_range_as_uncommitted(sr_base, sr_word_size);105verify_mask();106ASSERT_EQ(prior_uncommitted, (size_t)0);107108// Again, for fun, should be a noop now.109prior_uncommitted = _mask.mark_range_as_uncommitted(sr_base, sr_word_size);110verify_mask();111ASSERT_EQ(prior_uncommitted, sr_word_size);112113ASSERT_EQ(_mask.get_committed_size_in_range(sr_base, sr_word_size),114(size_t)0);115ASSERT_EQ(_mask.get_committed_size(),116_word_size - sr_word_size);117ASSERT_EQ(_mask.get_committed_size_in_range(_base, _word_size),118_word_size - sr_word_size);119for (const MetaWord* p = _base; p < _base + _word_size; p++) {120if (p >= sr_base && p < sr_base + sr_word_size) {121ASSERT_FALSE(_mask.is_committed_address(p));122} else {123ASSERT_TRUE(_mask.is_committed_address(p));124}125}126127// Recommit whole range128prior_committed = _mask.mark_range_as_committed(_base, _word_size);129verify_mask();130ASSERT_EQ(prior_committed, _word_size - sr_word_size);131132ASSERT_EQ(_mask.get_committed_size_in_range(sr_base, sr_word_size),133sr_word_size);134ASSERT_EQ(_mask.get_committed_size(),135_word_size);136ASSERT_EQ(_mask.get_committed_size_in_range(_base, _word_size),137_word_size);138for (const MetaWord* p = _base; p < _base + _word_size; p++) {139ASSERT_TRUE(_mask.is_committed_address(p));140}141142}143144void test2() {145146LOG("test2");147148// Uncommit everything149size_t prior_uncommitted = _mask.mark_range_as_uncommitted(_base, _word_size);150verify_mask();151ASSERT_LE(prior_uncommitted, _word_size);152153// Uncommit everything again, should be a noop154prior_uncommitted = _mask.mark_range_as_uncommitted(_base, _word_size);155verify_mask();156ASSERT_EQ(prior_uncommitted, _word_size);157158ASSERT_EQ(_mask.get_committed_size(),159(size_t)0);160ASSERT_EQ(_mask.get_committed_size_in_range(_base, _word_size),161(size_t)0);162163// Now make an committed region164size_t sr_word_size;165const MetaWord* sr_base = calc_random_subrange(&sr_word_size);166LOG("subrange " PTR_FORMAT "-" PTR_FORMAT ".",167p2i(sr_base), p2i(sr_base + sr_word_size));168169ASSERT_EQ(_mask.get_committed_size_in_range(sr_base, sr_word_size),170(size_t)0);171for (const MetaWord* p = _base; p < _base + _word_size; p++) {172ASSERT_FALSE(_mask.is_committed_address(p));173}174175size_t prior_committed = _mask.mark_range_as_committed(sr_base, sr_word_size);176verify_mask();177ASSERT_EQ(prior_committed, (size_t)0);178179// Again, for fun, should be a noop now.180prior_committed = _mask.mark_range_as_committed(sr_base, sr_word_size);181verify_mask();182ASSERT_EQ(prior_committed, sr_word_size);183184ASSERT_EQ(_mask.get_committed_size_in_range(sr_base, sr_word_size),185sr_word_size);186ASSERT_EQ(_mask.get_committed_size(),187sr_word_size);188ASSERT_EQ(_mask.get_committed_size_in_range(_base, _word_size),189sr_word_size);190for (const MetaWord* p = _base; p < _base + _word_size; p++) {191if (p >= sr_base && p < sr_base + sr_word_size) {192ASSERT_TRUE(_mask.is_committed_address(p));193} else {194ASSERT_FALSE(_mask.is_committed_address(p));195}196}197198// Re-uncommit whole range199prior_uncommitted = _mask.mark_range_as_uncommitted(_base, _word_size);200verify_mask();201ASSERT_EQ(prior_uncommitted, _word_size - sr_word_size);202203EXPECT_EQ(_mask.get_committed_size_in_range(sr_base, sr_word_size),204(size_t)0);205EXPECT_EQ(_mask.get_committed_size(),206(size_t)0);207EXPECT_EQ(_mask.get_committed_size_in_range(_base, _word_size),208(size_t)0);209for (const MetaWord* p = _base; p < _base + _word_size; p++) {210ASSERT_FALSE(_mask.is_committed_address(p));211}212213}214215void test3() {216217// arbitrary ranges are set and cleared and compared with the test map218TestMap map(_word_size);219220_mask.clear_large();221222for (int run = 0; run < 100; run++) {223224// A random range225SizeRange r = SizeRange(_word_size).random_aligned_subrange(Settings::commit_granule_words());226227if (os::random() % 100 < 50) {228_mask.mark_range_as_committed(_base + r.lowest(), r.size());229map.set_range(r.lowest(), r.end());230} else {231_mask.mark_range_as_uncommitted(_base + r.lowest(), r.size());232map.clear_range(r.lowest(), r.end());233}234235ASSERT_EQ(_mask.get_committed_size(), (size_t)map.get_num_set());236237ASSERT_EQ(_mask.get_committed_size_in_range(_base + r.lowest(), r.size()),238(size_t)map.get_num_set(r.lowest(), r.end()));239240}241242}243244public:245246CommitMaskTest(const MetaWord* base, size_t size) :247_base(base),248_word_size(size),249_mask(base, size)250{}251252void test() {253LOG("mask range: " PTR_FORMAT "-" PTR_FORMAT254" (" SIZE_FORMAT " words).",255p2i(_base), p2i(_base + _word_size), _word_size);256for (int i = 0; i < 5; i++) {257test1(); test2(); test3();258}259}260261};262263TEST_VM(metaspace, commit_mask_basics) {264265const MetaWord* const base = (const MetaWord*) 0x100000;266267CommitMask mask1(base, Settings::commit_granule_words());268ASSERT_EQ(mask1.size(), (BitMap::idx_t)1);269270CommitMask mask2(base, Settings::commit_granule_words() * 4);271ASSERT_EQ(mask2.size(), (BitMap::idx_t)4);272273CommitMask mask3(base, Settings::commit_granule_words() * 43);274ASSERT_EQ(mask3.size(), (BitMap::idx_t)43);275276mask3.mark_range_as_committed(base, Settings::commit_granule_words());277mask3.mark_range_as_committed(base + (Settings::commit_granule_words() * 42), Settings::commit_granule_words());278279ASSERT_EQ(mask3.at(0), 1);280for (int i = 1; i < 42; i++) {281ASSERT_EQ(mask3.at(i), 0);282}283ASSERT_EQ(mask3.at(42), 1);284285}286287TEST_VM(metaspace, commit_mask_small) {288289const MetaWord* const base = (const MetaWord*) 0x100000;290291CommitMaskTest test(base, Settings::commit_granule_words());292test.test();293294}295296TEST_VM(metaspace, commit_mask_range) {297298const MetaWord* const base = (const MetaWord*) 0x100000;299const size_t len = Settings::commit_granule_words() * 4;300const MetaWord* const end = base + len;301CommitMask mask(base, len);302303LOG("total range: " PTR_FORMAT "-" PTR_FORMAT "\n", p2i(base), p2i(end));304305size_t l = mask.mark_range_as_committed(base, len);306ASSERT_LE(l, len);307308for (const MetaWord* p = base; p <= end - Settings::commit_granule_words();309p += Settings::commit_granule_words()) {310for (const MetaWord* p2 = p + Settings::commit_granule_words();311p2 <= end; p2 += Settings::commit_granule_words()) {312LOG(PTR_FORMAT "-" PTR_FORMAT "\n", p2i(p), p2i(p2));313EXPECT_EQ(mask.get_committed_size_in_range(p, p2 - p),314(size_t)(p2 - p));315}316}317318l = mask.mark_range_as_uncommitted(base, len);319ASSERT_EQ(l, (size_t)0);320321for (const MetaWord* p = base; p <= end - Settings::commit_granule_words();322p += Settings::commit_granule_words()) {323for (const MetaWord* p2 = p + Settings::commit_granule_words();324p2 <= end; p2 += Settings::commit_granule_words()) {325LOG(PTR_FORMAT "-" PTR_FORMAT "\n", p2i(p), p2i(p2));326EXPECT_EQ(mask.get_committed_size_in_range(p, p2 - p),327(size_t)(0));328}329}330331}332333TEST_VM(metaspace, commit_mask_random) {334335for (int i = 0; i < 5; i++) {336337// make up a range out of thin air338const MetaWord* const base =339align_down( (const MetaWord*) ((uintptr_t) os::random() * os::random()),340Settings::commit_granule_bytes());341const size_t len = align_up( 1 + (os::random() % M),342Settings::commit_granule_words());343344CommitMaskTest test(base, len);345test.test();346347}348349}350351352