Thu, 27 Feb 2020 06:41:35 +0000
8055283: Expand ResourceHashtable with C_HEAP allocation, removal and some unit tests
Reviewed-by: phh
1 /*
2 * Copyright (c) 2015 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 */
25 #include "precompiled.hpp"
26 #include "memory/allocation.hpp"
27 #include "memory/resourceArea.hpp"
28 #include "utilities/debug.hpp"
29 #include "utilities/resourceHash.hpp"
31 #ifndef PRODUCT
33 /////////////// Unit tests ///////////////
35 class TestResourceHashtable : public AllStatic {
36 typedef void* K;
37 typedef int V;
39 static unsigned identity_hash(const K& k) {
40 return (unsigned)(uintptr_t)k;
41 }
43 static unsigned bad_hash(const K& k) {
44 return 1;
45 }
47 class EqualityTestIter {
48 public:
49 bool do_entry(K const& k, V const& v) {
50 assert((uintptr_t)k == (uintptr_t)v, "");
51 return true; // continue iteration
52 }
53 };
55 template<
56 unsigned (*HASH) (K const&) = primitive_hash<K>,
57 bool (*EQUALS)(K const&, K const&) = primitive_equals<K>,
58 unsigned SIZE = 256,
59 ResourceObj::allocation_type ALLOC_TYPE = ResourceObj::RESOURCE_AREA,
60 MEMFLAGS MEM_TYPE = mtInternal
61 >
62 class Runner : public AllStatic {
63 static void* as_K(uintptr_t val) { return (void*)val; }
65 public:
66 static void test_small() {
67 EqualityTestIter et;
68 ResourceHashtable<K, V, HASH, EQUALS, SIZE, ALLOC_TYPE, MEM_TYPE> rh;
70 assert(!rh.contains(as_K(0x1)), "");
72 assert(rh.put(as_K(0x1), 0x1), "");
73 assert(rh.contains(as_K(0x1)), "");
75 assert(!rh.put(as_K(0x1), 0x1), "");
77 assert(rh.put(as_K(0x2), 0x2), "");
78 assert(rh.put(as_K(0x3), 0x3), "");
79 assert(rh.put(as_K(0x4), 0x4), "");
80 assert(rh.put(as_K(0x5), 0x5), "");
82 assert(!rh.remove(as_K(0x0)), "");
83 rh.iterate(&et);
85 assert(rh.remove(as_K(0x1)), "");
86 rh.iterate(&et);
88 }
90 // We use keys with the low bits cleared since the default hash will do some shifting
91 static void test_small_shifted() {
92 EqualityTestIter et;
93 ResourceHashtable<K, V, HASH, EQUALS, SIZE, ALLOC_TYPE, MEM_TYPE> rh;
95 assert(!rh.contains(as_K(0x10)), "");
97 assert(rh.put(as_K(0x10), 0x10), "");
98 assert(rh.contains(as_K(0x10)), "");
100 assert(!rh.put(as_K(0x10), 0x10), "");
102 assert(rh.put(as_K(0x20), 0x20), "");
103 assert(rh.put(as_K(0x30), 0x30), "");
104 assert(rh.put(as_K(0x40), 0x40), "");
105 assert(rh.put(as_K(0x50), 0x50), "");
107 assert(!rh.remove(as_K(0x00)), "");
109 assert(rh.remove(as_K(0x10)), "");
111 rh.iterate(&et);
112 }
114 static void test(unsigned num_elements = SIZE) {
115 EqualityTestIter et;
116 ResourceHashtable<K, V, HASH, EQUALS, SIZE, ALLOC_TYPE, MEM_TYPE> rh;
118 for (uintptr_t i = 0; i < num_elements; ++i) {
119 assert(rh.put(as_K(i), i), "");
120 }
122 rh.iterate(&et);
124 for (uintptr_t i = num_elements; i > 0; --i) {
125 uintptr_t index = i - 1;
126 assert(rh.remove(as_K(index)), "");
127 }
128 rh.iterate(&et);
129 for (uintptr_t i = num_elements; i > 0; --i) {
130 uintptr_t index = i - 1;
131 assert(!rh.remove(as_K(index)), "");
132 }
133 rh.iterate(&et);
134 }
135 };
137 public:
138 static void run_tests() {
139 {
140 ResourceMark rm;
141 Runner<>::test_small();
142 Runner<>::test_small_shifted();
143 Runner<>::test();
144 }
146 {
147 ResourceMark rm;
148 Runner<identity_hash>::test_small();
149 Runner<identity_hash>::test_small_shifted();
150 Runner<identity_hash>::test();
151 }
153 {
154 ResourceMark rm;
155 Runner<bad_hash>::test_small();
156 Runner<bad_hash>::test_small_shifted();
157 Runner<bad_hash>::test();
158 }
161 assert(Thread::current()->resource_area()->nesting() == 0, "this code depends on not having an active ResourceMark");
162 // The following test calls will cause an assert if resource allocations occur since we don't have an active mark
163 Runner<primitive_hash<K>, primitive_equals<K>, 512, ResourceObj::C_HEAP>::test_small();
164 Runner<primitive_hash<K>, primitive_equals<K>, 512, ResourceObj::C_HEAP>::test_small_shifted();
165 Runner<primitive_hash<K>, primitive_equals<K>, 512, ResourceObj::C_HEAP>::test();
167 Runner<bad_hash, primitive_equals<K>, 512, ResourceObj::C_HEAP>::test_small();
168 Runner<bad_hash, primitive_equals<K>, 512, ResourceObj::C_HEAP>::test_small_shifted();
169 Runner<bad_hash, primitive_equals<K>, 512, ResourceObj::C_HEAP>::test();
171 Runner<identity_hash, primitive_equals<K>, 1, ResourceObj::C_HEAP>::test_small();
172 Runner<identity_hash, primitive_equals<K>, 1, ResourceObj::C_HEAP>::test_small_shifted();
173 Runner<identity_hash, primitive_equals<K>, 1, ResourceObj::C_HEAP>::test(512);
174 }
175 };
177 void TestResourcehash_test() {
178 TestResourceHashtable::run_tests();
179 }
181 #endif // not PRODUCT