src/share/vm/utilities/resourceHash.cpp

Thu, 27 Feb 2020 06:41:35 +0000

author
andrew
date
Thu, 27 Feb 2020 06:41:35 +0000
changeset 9845
68172de2a0d7
permissions
-rw-r--r--

8055283: Expand ResourceHashtable with C_HEAP allocation, removal and some unit tests
Reviewed-by: phh

andrew@9845 1 /*
andrew@9845 2 * Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
andrew@9845 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
andrew@9845 4 *
andrew@9845 5 * This code is free software; you can redistribute it and/or modify it
andrew@9845 6 * under the terms of the GNU General Public License version 2 only, as
andrew@9845 7 * published by the Free Software Foundation.
andrew@9845 8 *
andrew@9845 9 * This code is distributed in the hope that it will be useful, but WITHOUT
andrew@9845 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
andrew@9845 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
andrew@9845 12 * version 2 for more details (a copy is included in the LICENSE file that
andrew@9845 13 * accompanied this code).
andrew@9845 14 *
andrew@9845 15 * You should have received a copy of the GNU General Public License version
andrew@9845 16 * 2 along with this work; if not, write to the Free Software Foundation,
andrew@9845 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
andrew@9845 18 *
andrew@9845 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
andrew@9845 20 * or visit www.oracle.com if you need additional information or have any
andrew@9845 21 * questions.
andrew@9845 22 *
andrew@9845 23 */
andrew@9845 24
andrew@9845 25 #include "precompiled.hpp"
andrew@9845 26 #include "memory/allocation.hpp"
andrew@9845 27 #include "memory/resourceArea.hpp"
andrew@9845 28 #include "utilities/debug.hpp"
andrew@9845 29 #include "utilities/resourceHash.hpp"
andrew@9845 30
andrew@9845 31 #ifndef PRODUCT
andrew@9845 32
andrew@9845 33 /////////////// Unit tests ///////////////
andrew@9845 34
andrew@9845 35 class TestResourceHashtable : public AllStatic {
andrew@9845 36 typedef void* K;
andrew@9845 37 typedef int V;
andrew@9845 38
andrew@9845 39 static unsigned identity_hash(const K& k) {
andrew@9845 40 return (unsigned)(uintptr_t)k;
andrew@9845 41 }
andrew@9845 42
andrew@9845 43 static unsigned bad_hash(const K& k) {
andrew@9845 44 return 1;
andrew@9845 45 }
andrew@9845 46
andrew@9845 47 class EqualityTestIter {
andrew@9845 48 public:
andrew@9845 49 bool do_entry(K const& k, V const& v) {
andrew@9845 50 assert((uintptr_t)k == (uintptr_t)v, "");
andrew@9845 51 return true; // continue iteration
andrew@9845 52 }
andrew@9845 53 };
andrew@9845 54
andrew@9845 55 template<
andrew@9845 56 unsigned (*HASH) (K const&) = primitive_hash<K>,
andrew@9845 57 bool (*EQUALS)(K const&, K const&) = primitive_equals<K>,
andrew@9845 58 unsigned SIZE = 256,
andrew@9845 59 ResourceObj::allocation_type ALLOC_TYPE = ResourceObj::RESOURCE_AREA,
andrew@9845 60 MEMFLAGS MEM_TYPE = mtInternal
andrew@9845 61 >
andrew@9845 62 class Runner : public AllStatic {
andrew@9845 63 static void* as_K(uintptr_t val) { return (void*)val; }
andrew@9845 64
andrew@9845 65 public:
andrew@9845 66 static void test_small() {
andrew@9845 67 EqualityTestIter et;
andrew@9845 68 ResourceHashtable<K, V, HASH, EQUALS, SIZE, ALLOC_TYPE, MEM_TYPE> rh;
andrew@9845 69
andrew@9845 70 assert(!rh.contains(as_K(0x1)), "");
andrew@9845 71
andrew@9845 72 assert(rh.put(as_K(0x1), 0x1), "");
andrew@9845 73 assert(rh.contains(as_K(0x1)), "");
andrew@9845 74
andrew@9845 75 assert(!rh.put(as_K(0x1), 0x1), "");
andrew@9845 76
andrew@9845 77 assert(rh.put(as_K(0x2), 0x2), "");
andrew@9845 78 assert(rh.put(as_K(0x3), 0x3), "");
andrew@9845 79 assert(rh.put(as_K(0x4), 0x4), "");
andrew@9845 80 assert(rh.put(as_K(0x5), 0x5), "");
andrew@9845 81
andrew@9845 82 assert(!rh.remove(as_K(0x0)), "");
andrew@9845 83 rh.iterate(&et);
andrew@9845 84
andrew@9845 85 assert(rh.remove(as_K(0x1)), "");
andrew@9845 86 rh.iterate(&et);
andrew@9845 87
andrew@9845 88 }
andrew@9845 89
andrew@9845 90 // We use keys with the low bits cleared since the default hash will do some shifting
andrew@9845 91 static void test_small_shifted() {
andrew@9845 92 EqualityTestIter et;
andrew@9845 93 ResourceHashtable<K, V, HASH, EQUALS, SIZE, ALLOC_TYPE, MEM_TYPE> rh;
andrew@9845 94
andrew@9845 95 assert(!rh.contains(as_K(0x10)), "");
andrew@9845 96
andrew@9845 97 assert(rh.put(as_K(0x10), 0x10), "");
andrew@9845 98 assert(rh.contains(as_K(0x10)), "");
andrew@9845 99
andrew@9845 100 assert(!rh.put(as_K(0x10), 0x10), "");
andrew@9845 101
andrew@9845 102 assert(rh.put(as_K(0x20), 0x20), "");
andrew@9845 103 assert(rh.put(as_K(0x30), 0x30), "");
andrew@9845 104 assert(rh.put(as_K(0x40), 0x40), "");
andrew@9845 105 assert(rh.put(as_K(0x50), 0x50), "");
andrew@9845 106
andrew@9845 107 assert(!rh.remove(as_K(0x00)), "");
andrew@9845 108
andrew@9845 109 assert(rh.remove(as_K(0x10)), "");
andrew@9845 110
andrew@9845 111 rh.iterate(&et);
andrew@9845 112 }
andrew@9845 113
andrew@9845 114 static void test(unsigned num_elements = SIZE) {
andrew@9845 115 EqualityTestIter et;
andrew@9845 116 ResourceHashtable<K, V, HASH, EQUALS, SIZE, ALLOC_TYPE, MEM_TYPE> rh;
andrew@9845 117
andrew@9845 118 for (uintptr_t i = 0; i < num_elements; ++i) {
andrew@9845 119 assert(rh.put(as_K(i), i), "");
andrew@9845 120 }
andrew@9845 121
andrew@9845 122 rh.iterate(&et);
andrew@9845 123
andrew@9845 124 for (uintptr_t i = num_elements; i > 0; --i) {
andrew@9845 125 uintptr_t index = i - 1;
andrew@9845 126 assert(rh.remove(as_K(index)), "");
andrew@9845 127 }
andrew@9845 128 rh.iterate(&et);
andrew@9845 129 for (uintptr_t i = num_elements; i > 0; --i) {
andrew@9845 130 uintptr_t index = i - 1;
andrew@9845 131 assert(!rh.remove(as_K(index)), "");
andrew@9845 132 }
andrew@9845 133 rh.iterate(&et);
andrew@9845 134 }
andrew@9845 135 };
andrew@9845 136
andrew@9845 137 public:
andrew@9845 138 static void run_tests() {
andrew@9845 139 {
andrew@9845 140 ResourceMark rm;
andrew@9845 141 Runner<>::test_small();
andrew@9845 142 Runner<>::test_small_shifted();
andrew@9845 143 Runner<>::test();
andrew@9845 144 }
andrew@9845 145
andrew@9845 146 {
andrew@9845 147 ResourceMark rm;
andrew@9845 148 Runner<identity_hash>::test_small();
andrew@9845 149 Runner<identity_hash>::test_small_shifted();
andrew@9845 150 Runner<identity_hash>::test();
andrew@9845 151 }
andrew@9845 152
andrew@9845 153 {
andrew@9845 154 ResourceMark rm;
andrew@9845 155 Runner<bad_hash>::test_small();
andrew@9845 156 Runner<bad_hash>::test_small_shifted();
andrew@9845 157 Runner<bad_hash>::test();
andrew@9845 158 }
andrew@9845 159
andrew@9845 160
andrew@9845 161 assert(Thread::current()->resource_area()->nesting() == 0, "this code depends on not having an active ResourceMark");
andrew@9845 162 // The following test calls will cause an assert if resource allocations occur since we don't have an active mark
andrew@9845 163 Runner<primitive_hash<K>, primitive_equals<K>, 512, ResourceObj::C_HEAP>::test_small();
andrew@9845 164 Runner<primitive_hash<K>, primitive_equals<K>, 512, ResourceObj::C_HEAP>::test_small_shifted();
andrew@9845 165 Runner<primitive_hash<K>, primitive_equals<K>, 512, ResourceObj::C_HEAP>::test();
andrew@9845 166
andrew@9845 167 Runner<bad_hash, primitive_equals<K>, 512, ResourceObj::C_HEAP>::test_small();
andrew@9845 168 Runner<bad_hash, primitive_equals<K>, 512, ResourceObj::C_HEAP>::test_small_shifted();
andrew@9845 169 Runner<bad_hash, primitive_equals<K>, 512, ResourceObj::C_HEAP>::test();
andrew@9845 170
andrew@9845 171 Runner<identity_hash, primitive_equals<K>, 1, ResourceObj::C_HEAP>::test_small();
andrew@9845 172 Runner<identity_hash, primitive_equals<K>, 1, ResourceObj::C_HEAP>::test_small_shifted();
andrew@9845 173 Runner<identity_hash, primitive_equals<K>, 1, ResourceObj::C_HEAP>::test(512);
andrew@9845 174 }
andrew@9845 175 };
andrew@9845 176
andrew@9845 177 void TestResourcehash_test() {
andrew@9845 178 TestResourceHashtable::run_tests();
andrew@9845 179 }
andrew@9845 180
andrew@9845 181 #endif // not PRODUCT
andrew@9845 182

mercurial