1 /*
2 * Copyright (c) 2015, 2022, 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 */
135 ASSERT_TRUE(rh.remove(as_K(step)));
136 ASSERT_FALSE(rh.contains(as_K(step)));
137 rh.iterate(&et);
138
139 // Test put_if_absent(key, value)
140 v = rh.put_if_absent(as_K(step), step, &created);
141 ASSERT_EQ(*v, step);
142 ASSERT_TRUE(rh.contains(as_K(step)));
143 ASSERT_TRUE(created);
144
145 v2 = rh.put_if_absent(as_K(step), step, &created);
146 // Calling this function a second time should yield the same value pointer
147 ASSERT_EQ(v, v2);
148 ASSERT_EQ(*v2, (V)step);
149 ASSERT_FALSE(created);
150
151 ASSERT_TRUE(rh.remove(as_K(step)));
152 ASSERT_FALSE(rh.contains(as_K(step)));
153 rh.iterate(&et);
154
155
156 }
157 };
158 };
159
160 TEST_VM_F(SmallResourceHashtableTest, default) {
161 ResourceMark rm;
162 Runner<>::test(0x1);
163 }
164
165 TEST_VM_F(SmallResourceHashtableTest, default_shifted) {
166 ResourceMark rm;
167 Runner<>::test(0x10);
168 }
169
170 TEST_VM_F(SmallResourceHashtableTest, bad_hash) {
171 ResourceMark rm;
172 Runner<bad_hash>::test(0x1);
173 }
174
175 TEST_VM_F(SmallResourceHashtableTest, bad_hash_shifted) {
242 }
243
244 rh.iterate(&et);
245 if (::testing::Test::HasFailure()) {
246 return;
247 }
248 for (uintptr_t i = num_elements; i > 0; --i) {
249 uintptr_t index = i - 1;
250 ASSERT_FALSE(rh.remove(as_K(index)));
251 }
252 rh.iterate(&et);
253
254 // Add more entries in and then delete one.
255 for (uintptr_t i = 10; i > 0; --i) {
256 uintptr_t index = i - 1;
257 ASSERT_TRUE(rh.put(as_K(index), index));
258 }
259 DeleterTestIter dt(5);
260 rh.unlink(&dt);
261 ASSERT_FALSE(rh.get(as_K(5)));
262 }
263 };
264 };
265
266 TEST_VM_F(GenericResourceHashtableTest, default) {
267 ResourceMark rm;
268 Runner<>::test();
269 }
270
271 TEST_VM_F(GenericResourceHashtableTest, bad_hash) {
272 ResourceMark rm;
273 Runner<bad_hash>::test();
274 }
275
276 TEST_VM_F(GenericResourceHashtableTest, identity_hash) {
277 ResourceMark rm;
278 Runner<identity_hash>::test();
279 }
280
281 TEST_VM_F(GenericResourceHashtableTest, primitive_hash_no_rm) {
313 ASSERT_EQ(s->refcount(), s_orig_count + 1) << "refcount should be incremented in table";
314
315 // Deleting this value from a hashtable
316 _simple_test_table.remove(s);
317 ASSERT_EQ(s->refcount(), s_orig_count) << "refcount should be same as start";
318 }
319
320 TEST_VM_F(SimpleResourceHashtableDeleteTest, simple_delete) {
321 TempNewSymbol t = SymbolTable::new_symbol("abcdefg_simple");
322 Symbol* s = t;
323 int s_orig_count = s->refcount();
324 _simple_test_table.put(s, 66);
325 ASSERT_EQ(s->refcount(), s_orig_count + 1) << "refcount should be incremented in table";
326
327 // Use unlink to remove the matching (or all) values from the table.
328 SimpleDeleter deleter;
329 _simple_test_table.unlink(&deleter);
330 ASSERT_EQ(s->refcount(), s_orig_count) << "refcount should be same as start";
331 }
332
333 // More complicated ResourceHashtable with SymbolHandle in the key. Since the *same* Symbol is part
334 // of the value, it's not necessary to manipulate the refcount of the key, but you must in the value.
335 // Luckily SymbolHandle does this.
336 class ResourceHashtableDeleteTest : public ::testing::Test {
337 public:
338 class TestValue : public CHeapObj<mtTest> {
339 SymbolHandle _s;
340 public:
341 // Never have ctors and dtors fix refcounts without copy ctors and assignment operators!
342 // Unless it's declared and used as a CHeapObj with
343 // NONCOPYABLE(TestValue)
344
345 // Using SymbolHandle deals with refcount manipulation so this class doesn't have to
346 // have dtors, copy ctors and assignment operators to do so.
347 TestValue(Symbol* name) : _s(name) { }
348 // Symbol* s() const { return _s; } // needed for conversion from TempNewSymbol to SymbolHandle member
349 };
350
351 // ResourceHashtable whose value is a *copy* of TestValue.
352 ResourceHashtable<Symbol*, TestValue, 107, AnyObj::C_HEAP, mtTest> _test_table;
394 _test_table.remove(s);
395 // Removal should make the refcount be the original refcount.
396 ASSERT_EQ(s->refcount(), s_orig_count) << "refcount should be as we started";
397 }
398
399 TEST_VM_F(ResourceHashtableDeleteTest, value_delete) {
400 TempNewSymbol d = SymbolTable::new_symbol("defghijklmnop");
401 int d_orig_count = d->refcount();
402 {
403 TestValue tv(d);
404 // Same as above, but the do_entry does nothing because the value is deleted when the
405 // hashtable node is deleted.
406 _test_table.put(d, tv);
407 ASSERT_EQ(d->refcount(), d_orig_count + 2) << "refcount incremented by copy";
408 }
409 ASSERT_EQ(d->refcount(), d_orig_count + 1) << "refcount incremented in table";
410 Deleter deleter;
411 _test_table.unlink(&deleter);
412 ASSERT_EQ(d->refcount(), d_orig_count) << "refcount should be as we started";
413 }
414
415 TEST_VM_F(ResourceHashtableDeleteTest, check_delete_ptr) {
416 TempNewSymbol s = SymbolTable::new_symbol("abcdefg_ptr");
417 int s_orig_count = s->refcount();
418 {
419 TestValue* tv = new TestValue(s);
420 // Again since TestValue contains the pointer to the key Symbol, it will
421 // handle the refcounting.
422 _ptr_test_table.put(s, tv);
423 ASSERT_EQ(s->refcount(), s_orig_count + 1) << "refcount incremented by allocation";
424 }
425 ASSERT_EQ(s->refcount(), s_orig_count + 1) << "refcount incremented in table";
426
427 // Deleting this pointer value from a hashtable must call the destructor in the
428 // do_entry function.
429 PtrDeleter deleter;
430 _ptr_test_table.unlink(&deleter);
431 // Removal should make the refcount be the original refcount.
432 ASSERT_EQ(s->refcount(), s_orig_count) << "refcount should be as we started";
433 }
|
1 /*
2 * Copyright (c) 2015, 2023, 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 */
135 ASSERT_TRUE(rh.remove(as_K(step)));
136 ASSERT_FALSE(rh.contains(as_K(step)));
137 rh.iterate(&et);
138
139 // Test put_if_absent(key, value)
140 v = rh.put_if_absent(as_K(step), step, &created);
141 ASSERT_EQ(*v, step);
142 ASSERT_TRUE(rh.contains(as_K(step)));
143 ASSERT_TRUE(created);
144
145 v2 = rh.put_if_absent(as_K(step), step, &created);
146 // Calling this function a second time should yield the same value pointer
147 ASSERT_EQ(v, v2);
148 ASSERT_EQ(*v2, (V)step);
149 ASSERT_FALSE(created);
150
151 ASSERT_TRUE(rh.remove(as_K(step)));
152 ASSERT_FALSE(rh.contains(as_K(step)));
153 rh.iterate(&et);
154
155 rh.unlink_all();
156 }
157 };
158 };
159
160 TEST_VM_F(SmallResourceHashtableTest, default) {
161 ResourceMark rm;
162 Runner<>::test(0x1);
163 }
164
165 TEST_VM_F(SmallResourceHashtableTest, default_shifted) {
166 ResourceMark rm;
167 Runner<>::test(0x10);
168 }
169
170 TEST_VM_F(SmallResourceHashtableTest, bad_hash) {
171 ResourceMark rm;
172 Runner<bad_hash>::test(0x1);
173 }
174
175 TEST_VM_F(SmallResourceHashtableTest, bad_hash_shifted) {
242 }
243
244 rh.iterate(&et);
245 if (::testing::Test::HasFailure()) {
246 return;
247 }
248 for (uintptr_t i = num_elements; i > 0; --i) {
249 uintptr_t index = i - 1;
250 ASSERT_FALSE(rh.remove(as_K(index)));
251 }
252 rh.iterate(&et);
253
254 // Add more entries in and then delete one.
255 for (uintptr_t i = 10; i > 0; --i) {
256 uintptr_t index = i - 1;
257 ASSERT_TRUE(rh.put(as_K(index), index));
258 }
259 DeleterTestIter dt(5);
260 rh.unlink(&dt);
261 ASSERT_FALSE(rh.get(as_K(5)));
262
263 rh.unlink_all();
264 for (uintptr_t i = 10; i > 0; --i) {
265 uintptr_t index = i - 1;
266 ASSERT_FALSE(rh.get(as_K(index)));
267 }
268 }
269 };
270 };
271
272 TEST_VM_F(GenericResourceHashtableTest, default) {
273 ResourceMark rm;
274 Runner<>::test();
275 }
276
277 TEST_VM_F(GenericResourceHashtableTest, bad_hash) {
278 ResourceMark rm;
279 Runner<bad_hash>::test();
280 }
281
282 TEST_VM_F(GenericResourceHashtableTest, identity_hash) {
283 ResourceMark rm;
284 Runner<identity_hash>::test();
285 }
286
287 TEST_VM_F(GenericResourceHashtableTest, primitive_hash_no_rm) {
319 ASSERT_EQ(s->refcount(), s_orig_count + 1) << "refcount should be incremented in table";
320
321 // Deleting this value from a hashtable
322 _simple_test_table.remove(s);
323 ASSERT_EQ(s->refcount(), s_orig_count) << "refcount should be same as start";
324 }
325
326 TEST_VM_F(SimpleResourceHashtableDeleteTest, simple_delete) {
327 TempNewSymbol t = SymbolTable::new_symbol("abcdefg_simple");
328 Symbol* s = t;
329 int s_orig_count = s->refcount();
330 _simple_test_table.put(s, 66);
331 ASSERT_EQ(s->refcount(), s_orig_count + 1) << "refcount should be incremented in table";
332
333 // Use unlink to remove the matching (or all) values from the table.
334 SimpleDeleter deleter;
335 _simple_test_table.unlink(&deleter);
336 ASSERT_EQ(s->refcount(), s_orig_count) << "refcount should be same as start";
337 }
338
339 TEST_VM_F(SimpleResourceHashtableDeleteTest, simle_unlink_all) {
340 TempNewSymbol t = SymbolTable::new_symbol("abcdefg_simple");
341 Symbol* s = t;
342 int s_orig_count = s->refcount();
343 _simple_test_table.put(s, 66);
344 ASSERT_EQ(s->refcount(), s_orig_count + 1) << "refcount should be incremented in table";
345
346 // Use unlink_all to remove the matching (or all) values from the table.
347 _simple_test_table.unlink_all();
348 ASSERT_EQ(s->refcount(), s_orig_count) << "refcount should be same as start";
349 }
350
351 // More complicated ResourceHashtable with SymbolHandle in the key. Since the *same* Symbol is part
352 // of the value, it's not necessary to manipulate the refcount of the key, but you must in the value.
353 // Luckily SymbolHandle does this.
354 class ResourceHashtableDeleteTest : public ::testing::Test {
355 public:
356 class TestValue : public CHeapObj<mtTest> {
357 SymbolHandle _s;
358 public:
359 // Never have ctors and dtors fix refcounts without copy ctors and assignment operators!
360 // Unless it's declared and used as a CHeapObj with
361 // NONCOPYABLE(TestValue)
362
363 // Using SymbolHandle deals with refcount manipulation so this class doesn't have to
364 // have dtors, copy ctors and assignment operators to do so.
365 TestValue(Symbol* name) : _s(name) { }
366 // Symbol* s() const { return _s; } // needed for conversion from TempNewSymbol to SymbolHandle member
367 };
368
369 // ResourceHashtable whose value is a *copy* of TestValue.
370 ResourceHashtable<Symbol*, TestValue, 107, AnyObj::C_HEAP, mtTest> _test_table;
412 _test_table.remove(s);
413 // Removal should make the refcount be the original refcount.
414 ASSERT_EQ(s->refcount(), s_orig_count) << "refcount should be as we started";
415 }
416
417 TEST_VM_F(ResourceHashtableDeleteTest, value_delete) {
418 TempNewSymbol d = SymbolTable::new_symbol("defghijklmnop");
419 int d_orig_count = d->refcount();
420 {
421 TestValue tv(d);
422 // Same as above, but the do_entry does nothing because the value is deleted when the
423 // hashtable node is deleted.
424 _test_table.put(d, tv);
425 ASSERT_EQ(d->refcount(), d_orig_count + 2) << "refcount incremented by copy";
426 }
427 ASSERT_EQ(d->refcount(), d_orig_count + 1) << "refcount incremented in table";
428 Deleter deleter;
429 _test_table.unlink(&deleter);
430 ASSERT_EQ(d->refcount(), d_orig_count) << "refcount should be as we started";
431 }
432
433 TEST_VM_F(ResourceHashtableDeleteTest, value_unlink_all) {
434 TempNewSymbol d = SymbolTable::new_symbol("defghijklmnop");
435 int d_orig_count = d->refcount();
436 {
437 TestValue tv(d);
438 // Same as above, but the do_entry does nothing because the value is deleted when the
439 // hashtable node is deleted.
440 _test_table.put(d, tv);
441 ASSERT_EQ(d->refcount(), d_orig_count + 2) << "refcount incremented by copy";
442 }
443 ASSERT_EQ(d->refcount(), d_orig_count + 1) << "refcount incremented in table";
444 _test_table.unlink_all();
445 ASSERT_EQ(d->refcount(), d_orig_count) << "refcount should be as we started";
446 }
447
448 TEST_VM_F(ResourceHashtableDeleteTest, check_delete_ptr) {
449 TempNewSymbol s = SymbolTable::new_symbol("abcdefg_ptr");
450 int s_orig_count = s->refcount();
451 {
452 TestValue* tv = new TestValue(s);
453 // Again since TestValue contains the pointer to the key Symbol, it will
454 // handle the refcounting.
455 _ptr_test_table.put(s, tv);
456 ASSERT_EQ(s->refcount(), s_orig_count + 1) << "refcount incremented by allocation";
457 }
458 ASSERT_EQ(s->refcount(), s_orig_count + 1) << "refcount incremented in table";
459
460 // Deleting this pointer value from a hashtable must call the destructor in the
461 // do_entry function.
462 PtrDeleter deleter;
463 _ptr_test_table.unlink(&deleter);
464 // Removal should make the refcount be the original refcount.
465 ASSERT_EQ(s->refcount(), s_orig_count) << "refcount should be as we started";
466 }
|