Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/hotspot/gtest/gc/shared/test_oopStorage.cpp
41152 views
1
/*
2
* Copyright (c) 2018, 2021, 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
24
#include "precompiled.hpp"
25
#include "gc/shared/oopStorage.inline.hpp"
26
#include "gc/shared/oopStorageParState.inline.hpp"
27
#include "gc/shared/workgroup.hpp"
28
#include "memory/allocation.inline.hpp"
29
#include "memory/resourceArea.hpp"
30
#include "metaprogramming/conditional.hpp"
31
#include "metaprogramming/enableIf.hpp"
32
#include "runtime/handles.inline.hpp"
33
#include "runtime/interfaceSupport.inline.hpp"
34
#include "runtime/mutex.hpp"
35
#include "runtime/mutexLocker.hpp"
36
#include "runtime/thread.hpp"
37
#include "runtime/vmOperations.hpp"
38
#include "runtime/vmThread.hpp"
39
#include "utilities/align.hpp"
40
#include "utilities/ostream.hpp"
41
#include "utilities/quickSort.hpp"
42
#include "unittest.hpp"
43
44
// Access storage internals.
45
class OopStorage::TestAccess : public AllStatic {
46
public:
47
typedef OopStorage::Block Block;
48
typedef OopStorage::AllocationList AllocationList;
49
typedef OopStorage::ActiveArray ActiveArray;
50
51
static ActiveArray& active_array(const OopStorage& storage) {
52
return *storage._active_array;
53
}
54
55
static AllocationList& allocation_list(OopStorage& storage) {
56
return storage._allocation_list;
57
}
58
59
static const AllocationList& allocation_list(const OopStorage& storage) {
60
return storage._allocation_list;
61
}
62
63
static Mutex* allocation_mutex(const OopStorage& storage) {
64
return storage._allocation_mutex;
65
}
66
67
static bool reduce_deferred_updates(OopStorage& storage) {
68
return storage.reduce_deferred_updates();
69
}
70
71
static bool block_is_empty(const Block& block) {
72
return block.is_empty();
73
}
74
75
static bool block_is_full(const Block& block) {
76
return block.is_full();
77
}
78
79
static unsigned block_allocation_count(const Block& block) {
80
uintx bitmask = block.allocated_bitmask();
81
unsigned count = 0;
82
for ( ; bitmask != 0; bitmask >>= 1) {
83
if ((bitmask & 1) != 0) {
84
++count;
85
}
86
}
87
return count;
88
}
89
90
static size_t memory_per_block() {
91
return Block::allocation_size();
92
}
93
94
static void block_array_set_block_count(ActiveArray* blocks, size_t count) {
95
blocks->_block_count = count;
96
}
97
};
98
99
typedef OopStorage::TestAccess TestAccess;
100
101
// The "Oop" prefix is to avoid collision with similar opto names when
102
// building with precompiled headers, or for consistency with that
103
// workaround. There really should be an opto namespace.
104
typedef TestAccess::Block OopBlock;
105
typedef TestAccess::AllocationList AllocationList;
106
typedef TestAccess::ActiveArray ActiveArray;
107
108
// Using EXPECT_EQ can't use NULL directly. Otherwise AIX build breaks.
109
const OopBlock* const NULL_BLOCK = NULL;
110
111
static size_t list_length(const AllocationList& list) {
112
size_t result = 0;
113
for (const OopBlock* block = list.chead();
114
block != NULL;
115
block = list.next(*block)) {
116
++result;
117
}
118
return result;
119
}
120
121
static void clear_list(AllocationList& list) {
122
OopBlock* next;
123
for (OopBlock* block = list.head(); block != NULL; block = next) {
124
next = list.next(*block);
125
list.unlink(*block);
126
}
127
}
128
129
static bool is_list_empty(const AllocationList& list) {
130
return list.chead() == NULL;
131
}
132
133
static bool process_deferred_updates(OopStorage& storage) {
134
MutexLocker ml(TestAccess::allocation_mutex(storage), Mutex::_no_safepoint_check_flag);
135
bool result = false;
136
while (TestAccess::reduce_deferred_updates(storage)) {
137
result = true;
138
}
139
return result;
140
}
141
142
static void release_entry(OopStorage& storage, oop* entry, bool process_deferred = true) {
143
*entry = NULL;
144
storage.release(entry);
145
if (process_deferred) {
146
process_deferred_updates(storage);
147
}
148
}
149
150
static size_t empty_block_count(const OopStorage& storage) {
151
const AllocationList& list = TestAccess::allocation_list(storage);
152
size_t count = 0;
153
for (const OopBlock* block = list.ctail();
154
(block != NULL) && block->is_empty();
155
++count, block = list.prev(*block))
156
{}
157
return count;
158
}
159
160
static size_t active_count(const OopStorage& storage) {
161
return TestAccess::active_array(storage).block_count();
162
}
163
164
static OopBlock* active_head(const OopStorage& storage) {
165
ActiveArray& ba = TestAccess::active_array(storage);
166
size_t count = ba.block_count();
167
if (count == 0) {
168
return NULL;
169
} else {
170
return ba.at(count - 1);
171
}
172
}
173
174
class OopStorageTest : public ::testing::Test {
175
public:
176
OopStorageTest();
177
~OopStorageTest();
178
179
OopStorage _storage;
180
181
class CountingIterateClosure;
182
template<bool is_const> class VM_CountAtSafepoint;
183
};
184
185
OopStorageTest::OopStorageTest() :
186
_storage("Test Storage", mtGC)
187
{ }
188
189
OopStorageTest::~OopStorageTest() {
190
clear_list(TestAccess::allocation_list(_storage));
191
}
192
193
class OopStorageTestWithAllocation : public OopStorageTest {
194
public:
195
OopStorageTestWithAllocation();
196
197
static const size_t _max_entries = 1000;
198
oop* _entries[_max_entries];
199
};
200
201
OopStorageTestWithAllocation::OopStorageTestWithAllocation() {
202
for (size_t i = 0; i < _max_entries; ++i) {
203
_entries[i] = _storage.allocate();
204
EXPECT_TRUE(_entries[i] != NULL);
205
EXPECT_EQ(i + 1, _storage.allocation_count());
206
}
207
};
208
209
const size_t OopStorageTestWithAllocation::_max_entries;
210
211
static bool is_allocation_list_sorted(const OopStorage& storage) {
212
// The allocation_list isn't strictly sorted. Rather, all empty
213
// blocks are segregated to the end of the list.
214
const AllocationList& list = TestAccess::allocation_list(storage);
215
const OopBlock* block = list.ctail();
216
for ( ; (block != NULL) && block->is_empty(); block = list.prev(*block)) {}
217
for ( ; block != NULL; block = list.prev(*block)) {
218
if (block->is_empty()) {
219
return false;
220
}
221
}
222
return true;
223
}
224
225
static size_t total_allocation_count(const OopStorage& storage) {
226
size_t total_count = 0;
227
const ActiveArray& ba = TestAccess::active_array(storage);
228
size_t limit = active_count(storage);
229
for (size_t i = 0; i < limit; ++i) {
230
total_count += TestAccess::block_allocation_count(*ba.at(i));
231
}
232
return total_count;
233
}
234
235
TEST_VM_F(OopStorageTest, allocate_one) {
236
EXPECT_EQ(0u, active_count(_storage));
237
EXPECT_TRUE(is_list_empty(TestAccess::allocation_list(_storage)));
238
239
oop* ptr = _storage.allocate();
240
EXPECT_TRUE(ptr != NULL);
241
EXPECT_EQ(1u, _storage.allocation_count());
242
243
EXPECT_EQ(1u, active_count(_storage));
244
EXPECT_EQ(1u, _storage.block_count());
245
EXPECT_EQ(1u, list_length(TestAccess::allocation_list(_storage)));
246
247
EXPECT_EQ(0u, empty_block_count(_storage));
248
249
const OopBlock* block = TestAccess::allocation_list(_storage).chead();
250
EXPECT_NE(block, (OopBlock*)NULL);
251
EXPECT_EQ(block, active_head(_storage));
252
EXPECT_FALSE(TestAccess::block_is_empty(*block));
253
EXPECT_FALSE(TestAccess::block_is_full(*block));
254
EXPECT_EQ(1u, TestAccess::block_allocation_count(*block));
255
256
release_entry(_storage, ptr);
257
EXPECT_EQ(0u, _storage.allocation_count());
258
259
EXPECT_EQ(1u, active_count(_storage));
260
EXPECT_EQ(1u, _storage.block_count());
261
EXPECT_EQ(1u, list_length(TestAccess::allocation_list(_storage)));
262
263
EXPECT_EQ(1u, empty_block_count(_storage));
264
265
const OopBlock* new_block = TestAccess::allocation_list(_storage).chead();
266
EXPECT_EQ(block, new_block);
267
EXPECT_EQ(block, active_head(_storage));
268
EXPECT_TRUE(TestAccess::block_is_empty(*block));
269
EXPECT_FALSE(TestAccess::block_is_full(*block));
270
EXPECT_EQ(0u, TestAccess::block_allocation_count(*block));
271
}
272
273
TEST_VM_F(OopStorageTest, allocation_count) {
274
static const size_t max_entries = 1000;
275
oop* entries[max_entries];
276
277
AllocationList& allocation_list = TestAccess::allocation_list(_storage);
278
279
EXPECT_EQ(0u, active_count(_storage));
280
EXPECT_EQ(0u, _storage.block_count());
281
EXPECT_TRUE(is_list_empty(allocation_list));
282
283
size_t allocated = 0;
284
for ( ; allocated < max_entries; ++allocated) {
285
EXPECT_EQ(allocated, _storage.allocation_count());
286
if (active_count(_storage) != 0) {
287
EXPECT_EQ(1u, active_count(_storage));
288
EXPECT_EQ(1u, _storage.block_count());
289
const OopBlock& block = *TestAccess::active_array(_storage).at(0);
290
EXPECT_EQ(allocated, TestAccess::block_allocation_count(block));
291
if (TestAccess::block_is_full(block)) {
292
break;
293
} else {
294
EXPECT_FALSE(is_list_empty(allocation_list));
295
EXPECT_EQ(&block, allocation_list.chead());
296
}
297
}
298
entries[allocated] = _storage.allocate();
299
}
300
301
EXPECT_EQ(allocated, _storage.allocation_count());
302
EXPECT_EQ(1u, active_count(_storage));
303
EXPECT_EQ(1u, _storage.block_count());
304
EXPECT_TRUE(is_list_empty(allocation_list));
305
const OopBlock& block = *TestAccess::active_array(_storage).at(0);
306
EXPECT_TRUE(TestAccess::block_is_full(block));
307
EXPECT_EQ(allocated, TestAccess::block_allocation_count(block));
308
309
for (size_t i = 0; i < allocated; ++i) {
310
release_entry(_storage, entries[i]);
311
size_t remaining = allocated - (i + 1);
312
EXPECT_EQ(remaining, TestAccess::block_allocation_count(block));
313
EXPECT_EQ(remaining, _storage.allocation_count());
314
EXPECT_FALSE(is_list_empty(allocation_list));
315
}
316
}
317
318
TEST_VM_F(OopStorageTest, allocate_many) {
319
static const size_t max_entries = 1000;
320
oop* entries[max_entries];
321
322
AllocationList& allocation_list = TestAccess::allocation_list(_storage);
323
324
EXPECT_EQ(0u, empty_block_count(_storage));
325
326
entries[0] = _storage.allocate();
327
ASSERT_TRUE(entries[0] != NULL);
328
EXPECT_EQ(1u, active_count(_storage));
329
EXPECT_EQ(1u, _storage.block_count());
330
EXPECT_EQ(1u, list_length(allocation_list));
331
EXPECT_EQ(0u, empty_block_count(_storage));
332
333
const OopBlock* block = TestAccess::active_array(_storage).at(0);
334
EXPECT_EQ(1u, TestAccess::block_allocation_count(*block));
335
EXPECT_EQ(block, allocation_list.chead());
336
337
for (size_t i = 1; i < max_entries; ++i) {
338
entries[i] = _storage.allocate();
339
EXPECT_EQ(i + 1, _storage.allocation_count());
340
ASSERT_TRUE(entries[i] != NULL);
341
EXPECT_EQ(0u, empty_block_count(_storage));
342
343
if (block == NULL) {
344
ASSERT_FALSE(is_list_empty(allocation_list));
345
EXPECT_EQ(1u, list_length(allocation_list));
346
block = allocation_list.chead();
347
EXPECT_EQ(1u, TestAccess::block_allocation_count(*block));
348
EXPECT_EQ(block, active_head(_storage));
349
} else if (TestAccess::block_is_full(*block)) {
350
EXPECT_TRUE(is_list_empty(allocation_list));
351
block = NULL;
352
} else {
353
EXPECT_FALSE(is_list_empty(allocation_list));
354
EXPECT_EQ(block, allocation_list.chead());
355
EXPECT_EQ(block, active_head(_storage));
356
}
357
}
358
359
if (block != NULL) {
360
EXPECT_NE(0u, TestAccess::block_allocation_count(*block));
361
EXPECT_FALSE(is_list_empty(allocation_list));
362
EXPECT_EQ(block, allocation_list.chead());
363
EXPECT_EQ(block, active_head(_storage));
364
}
365
366
for (size_t i = 0; i < max_entries; ++i) {
367
release_entry(_storage, entries[i]);
368
EXPECT_TRUE(is_allocation_list_sorted(_storage));
369
EXPECT_EQ(max_entries - (i + 1), total_allocation_count(_storage));
370
}
371
372
EXPECT_EQ(active_count(_storage), list_length(allocation_list));
373
EXPECT_EQ(active_count(_storage), _storage.block_count());
374
EXPECT_EQ(active_count(_storage), empty_block_count(_storage));
375
for (const OopBlock* block = allocation_list.chead();
376
block != NULL;
377
block = allocation_list.next(*block)) {
378
EXPECT_TRUE(TestAccess::block_is_empty(*block));
379
}
380
}
381
382
TEST_VM_F(OopStorageTestWithAllocation, random_release) {
383
static const size_t step = 11;
384
ASSERT_NE(0u, _max_entries % step); // max_entries and step are mutually prime
385
386
EXPECT_EQ(0u, empty_block_count(_storage));
387
388
AllocationList& allocation_list = TestAccess::allocation_list(_storage);
389
390
EXPECT_EQ(_max_entries, total_allocation_count(_storage));
391
EXPECT_GE(1u, list_length(allocation_list));
392
393
// Release all entries in "random" order.
394
size_t released = 0;
395
for (size_t i = 0; released < _max_entries; i = (i + step) % _max_entries) {
396
if (_entries[i] != NULL) {
397
release_entry(_storage, _entries[i]);
398
_entries[i] = NULL;
399
++released;
400
EXPECT_EQ(_max_entries - released, total_allocation_count(_storage));
401
EXPECT_TRUE(is_allocation_list_sorted(_storage));
402
}
403
}
404
405
EXPECT_EQ(active_count(_storage), list_length(allocation_list));
406
EXPECT_EQ(active_count(_storage), _storage.block_count());
407
EXPECT_EQ(0u, total_allocation_count(_storage));
408
EXPECT_EQ(list_length(allocation_list), empty_block_count(_storage));
409
}
410
411
TEST_VM_F(OopStorageTestWithAllocation, random_allocate_release) {
412
static const size_t release_step = 11;
413
static const size_t allocate_step = 5;
414
ASSERT_NE(0u, _max_entries % release_step); // max_entries and step are mutually prime
415
416
EXPECT_EQ(0u, empty_block_count(_storage));
417
418
AllocationList& allocation_list = TestAccess::allocation_list(_storage);
419
420
EXPECT_EQ(_max_entries, total_allocation_count(_storage));
421
EXPECT_GE(1u, list_length(allocation_list));
422
423
// Release all entries in "random" order, "randomly" interspersed
424
// with additional allocations.
425
size_t released = 0;
426
size_t total_released = 0;
427
for (size_t i = 0; released < _max_entries; i = (i + release_step) % _max_entries) {
428
if (_entries[i] != NULL) {
429
release_entry(_storage, _entries[i]);
430
_entries[i] = NULL;
431
++released;
432
++total_released;
433
EXPECT_EQ(_max_entries - released, total_allocation_count(_storage));
434
EXPECT_TRUE(is_allocation_list_sorted(_storage));
435
if (total_released % allocate_step == 0) {
436
_entries[i] = _storage.allocate();
437
--released;
438
EXPECT_EQ(_max_entries - released, total_allocation_count(_storage));
439
EXPECT_TRUE(is_allocation_list_sorted(_storage));
440
}
441
}
442
}
443
444
EXPECT_EQ(active_count(_storage), list_length(allocation_list));
445
EXPECT_EQ(active_count(_storage), _storage.block_count());
446
EXPECT_EQ(0u, total_allocation_count(_storage));
447
EXPECT_EQ(list_length(allocation_list), empty_block_count(_storage));
448
}
449
450
template<bool sorted>
451
class OopStorageTestBlockRelease : public OopStorageTestWithAllocation {
452
public:
453
void SetUp() {
454
size_t nrelease = _max_entries / 2;
455
oop** to_release = NEW_C_HEAP_ARRAY(oop*, nrelease, mtInternal);
456
457
for (size_t i = 0; i < nrelease; ++i) {
458
to_release[i] = _entries[2 * i];
459
*to_release[i] = NULL;
460
}
461
if (sorted) {
462
QuickSort::sort(to_release, nrelease, PointerCompare(), false);
463
}
464
465
_storage.release(to_release, nrelease);
466
EXPECT_EQ(_max_entries - nrelease, _storage.allocation_count());
467
468
for (size_t i = 0; i < nrelease; ++i) {
469
release_entry(_storage, _entries[2 * i + 1], false);
470
EXPECT_EQ(_max_entries - nrelease - (i + 1), _storage.allocation_count());
471
}
472
EXPECT_TRUE(process_deferred_updates(_storage));
473
474
EXPECT_EQ(_storage.block_count(), empty_block_count(_storage));
475
476
FREE_C_HEAP_ARRAY(oop*, to_release);
477
}
478
479
struct PointerCompare {
480
int operator()(const void* p, const void* q) const {
481
return (p < q) ? -1 : int(p != q);
482
}
483
};
484
};
485
486
typedef OopStorageTestBlockRelease<true> OopStorageTestBlockReleaseSorted;
487
typedef OopStorageTestBlockRelease<false> OopStorageTestBlockReleaseUnsorted;
488
489
TEST_VM_F(OopStorageTestBlockReleaseSorted, block_release) {}
490
TEST_VM_F(OopStorageTestBlockReleaseUnsorted, block_release) {}
491
492
TEST_VM_F(OopStorageTest, bulk_allocation) {
493
static const size_t max_entries = 1000;
494
static const size_t zero = 0;
495
oop* entries[max_entries] = {};
496
497
AllocationList& allocation_list = TestAccess::allocation_list(_storage);
498
499
EXPECT_EQ(0u, empty_block_count(_storage));
500
size_t allocated = _storage.allocate(entries, max_entries);
501
ASSERT_NE(allocated, zero);
502
// ASSERT_LE would ODR-use the OopStorage constant.
503
size_t bulk_allocate_limit = OopStorage::bulk_allocate_limit;
504
ASSERT_LE(allocated, bulk_allocate_limit);
505
ASSERT_LE(allocated, max_entries);
506
for (size_t i = 0; i < allocated; ++i) {
507
EXPECT_EQ(OopStorage::ALLOCATED_ENTRY, _storage.allocation_status(entries[i]));
508
}
509
for (size_t i = allocated; i < max_entries; ++i) {
510
EXPECT_EQ(NULL, entries[i]);
511
}
512
_storage.release(entries, allocated);
513
EXPECT_EQ(0u, _storage.allocation_count());
514
for (size_t i = 0; i < allocated; ++i) {
515
EXPECT_EQ(OopStorage::UNALLOCATED_ENTRY, _storage.allocation_status(entries[i]));
516
}
517
}
518
519
#ifndef DISABLE_GARBAGE_ALLOCATION_STATUS_TESTS
520
TEST_VM_F(OopStorageTest, invalid_pointer) {
521
{
522
char* mem = NEW_C_HEAP_ARRAY(char, 1000, mtInternal);
523
oop* ptr = reinterpret_cast<oop*>(align_down(mem + 250, sizeof(oop)));
524
// Predicate returns false for some malloc'ed block.
525
EXPECT_EQ(OopStorage::INVALID_ENTRY, _storage.allocation_status(ptr));
526
FREE_C_HEAP_ARRAY(char, mem);
527
}
528
529
{
530
oop obj;
531
oop* ptr = &obj;
532
// Predicate returns false for some "random" location.
533
EXPECT_EQ(OopStorage::INVALID_ENTRY, _storage.allocation_status(ptr));
534
}
535
}
536
#endif // DISABLE_GARBAGE_ALLOCATION_STATUS_TESTS
537
538
class OopStorageTest::CountingIterateClosure {
539
public:
540
size_t _const_count;
541
size_t _const_non_null;
542
size_t _non_const_count;
543
size_t _non_const_non_null;
544
545
void do_oop(const oop* ptr) {
546
++_const_count;
547
if (*ptr != NULL) {
548
++_const_non_null;
549
}
550
}
551
552
void do_oop(oop* ptr) {
553
++_non_const_count;
554
if (*ptr != NULL) {
555
++_non_const_non_null;
556
}
557
}
558
559
CountingIterateClosure() :
560
_const_count(0),
561
_const_non_null(0),
562
_non_const_count(0),
563
_non_const_non_null(0)
564
{}
565
};
566
567
template<bool is_const>
568
class OopStorageTest::VM_CountAtSafepoint : public VM_GTestExecuteAtSafepoint {
569
public:
570
typedef typename Conditional<is_const,
571
const OopStorage,
572
OopStorage>::type Storage;
573
574
VM_CountAtSafepoint(Storage* storage, CountingIterateClosure* cl) :
575
_storage(storage), _cl(cl)
576
{}
577
578
void doit() { _storage->oops_do(_cl); }
579
580
private:
581
Storage* _storage;
582
CountingIterateClosure* _cl;
583
};
584
585
TEST_VM_F(OopStorageTest, simple_iterate) {
586
// Dummy oop value.
587
intptr_t dummy_oop_value = 0xbadbeaf;
588
oop dummy_oop = reinterpret_cast<oopDesc*>(&dummy_oop_value);
589
590
const size_t max_entries = 1000;
591
oop* entries[max_entries];
592
593
size_t allocated = 0;
594
size_t entries_with_values = 0;
595
for (size_t i = 0; i < max_entries; i += 10) {
596
for ( ; allocated < i; ++allocated) {
597
entries[allocated] = _storage.allocate();
598
ASSERT_TRUE(entries[allocated] != NULL);
599
if ((allocated % 3) != 0) {
600
*entries[allocated] = dummy_oop;
601
++entries_with_values;
602
}
603
}
604
605
{
606
CountingIterateClosure cl;
607
VM_CountAtSafepoint<false> op(&_storage, &cl);
608
{
609
ThreadInVMfromNative invm(JavaThread::current());
610
VMThread::execute(&op);
611
}
612
EXPECT_EQ(allocated, cl._non_const_count);
613
EXPECT_EQ(entries_with_values, cl._non_const_non_null);
614
EXPECT_EQ(0u, cl._const_count);
615
EXPECT_EQ(0u, cl._const_non_null);
616
}
617
618
{
619
CountingIterateClosure cl;
620
VM_CountAtSafepoint<true> op(&_storage, &cl);
621
{
622
ThreadInVMfromNative invm(JavaThread::current());
623
VMThread::execute(&op);
624
}
625
EXPECT_EQ(allocated, cl._const_count);
626
EXPECT_EQ(entries_with_values, cl._const_non_null);
627
EXPECT_EQ(0u, cl._non_const_count);
628
EXPECT_EQ(0u, cl._non_const_non_null);
629
}
630
}
631
632
while (allocated > 0) {
633
release_entry(_storage, entries[--allocated], false);
634
}
635
process_deferred_updates(_storage);
636
}
637
638
class OopStorageTestIteration : public OopStorageTestWithAllocation {
639
public:
640
static const size_t _max_workers = 2;
641
unsigned char _states[_max_workers][_max_entries];
642
643
static const unsigned char mark_released = 1u << 0;
644
static const unsigned char mark_invalid = 1u << 1;
645
static const unsigned char mark_const = 1u << 2;
646
static const unsigned char mark_non_const = 1u << 3;
647
648
virtual void SetUp() {
649
OopStorageTestWithAllocation::SetUp();
650
651
memset(_states, 0, sizeof(_states));
652
653
size_t initial_release = 0;
654
for ( ; empty_block_count(_storage) < 2; ++initial_release) {
655
ASSERT_GT(_max_entries, initial_release);
656
release_entry(_storage, _entries[initial_release]);
657
_states[0][initial_release] = mark_released;
658
}
659
660
for (size_t i = initial_release; i < _max_entries; i += 3) {
661
release_entry(_storage, _entries[i], false);
662
_states[0][i] = mark_released;
663
}
664
process_deferred_updates(_storage);
665
}
666
667
class VerifyState;
668
class VerifyFn;
669
template<bool is_const> class VM_Verify;
670
671
class VerifyClosure;
672
class VM_VerifyUsingOopsDo;
673
};
674
675
const unsigned char OopStorageTestIteration::mark_released;
676
const unsigned char OopStorageTestIteration::mark_invalid;
677
const unsigned char OopStorageTestIteration::mark_const;
678
const unsigned char OopStorageTestIteration::mark_non_const;
679
680
class OopStorageTestIteration::VerifyState {
681
public:
682
unsigned char _expected_mark;
683
const oop* const* _entries;
684
unsigned char (&_states)[_max_workers][_max_entries];
685
686
VerifyState(unsigned char expected_mark,
687
const oop* const* entries,
688
unsigned char (&states)[_max_workers][_max_entries]) :
689
_expected_mark(expected_mark),
690
_entries(entries),
691
_states(states)
692
{ }
693
694
bool update(const oop* ptr, uint worker_id, unsigned char mark) const {
695
size_t index = 0;
696
bool found = find_entry(ptr, &index);
697
EXPECT_TRUE(found);
698
EXPECT_GT(_max_entries, index);
699
EXPECT_GT(_max_workers, worker_id);
700
if (!found) {
701
return false;
702
} else if (index >= _max_entries) {
703
return false;
704
} else if (worker_id >= _max_workers) {
705
return false;
706
} else {
707
EXPECT_EQ(0, _states[worker_id][index]);
708
if (_states[worker_id][index] != 0) {
709
_states[worker_id][index] |= mark_invalid;
710
return false;
711
} else {
712
_states[worker_id][index] |= mark;
713
return true;
714
}
715
}
716
}
717
718
void check() const {
719
for (size_t i = 0; i < _max_entries; ++i) {
720
unsigned char mark = 0;
721
for (size_t w = 0; w < _max_workers; ++w) {
722
if (mark == 0) {
723
mark = _states[w][i];
724
} else {
725
EXPECT_EQ(0u, _states[w][i]);
726
}
727
}
728
if (mark == 0) {
729
EXPECT_NE(0u, mark);
730
} else if ((mark & mark_released) != 0) {
731
EXPECT_EQ(mark_released, mark);
732
} else {
733
EXPECT_EQ(_expected_mark, mark);
734
}
735
}
736
}
737
738
private:
739
bool find_entry(const oop* ptr, size_t* index) const {
740
for (size_t i = 0; i < _max_entries; ++i) {
741
if (ptr == _entries[i]) {
742
*index = i;
743
return true;
744
}
745
}
746
return false;
747
}
748
};
749
750
class OopStorageTestIteration::VerifyFn {
751
public:
752
VerifyFn(VerifyState* state, uint worker_id = 0) :
753
_state(state),
754
_worker_id(worker_id)
755
{}
756
757
bool operator()( oop* ptr) const {
758
return _state->update(ptr, _worker_id, mark_non_const);
759
}
760
761
bool operator()(const oop* ptr) const {
762
return _state->update(ptr, _worker_id, mark_const);
763
}
764
765
private:
766
VerifyState* _state;
767
uint _worker_id;
768
};
769
770
class OopStorageTestIteration::VerifyClosure {
771
public:
772
VerifyClosure(VerifyState* state, uint worker_id = 0) :
773
_state(state),
774
_worker_id(worker_id)
775
{}
776
777
void do_oop(oop* ptr) {
778
_state->update(ptr, _worker_id, mark_non_const);
779
}
780
781
void do_oop(const oop* ptr) {
782
_state->update(ptr, _worker_id, mark_const);
783
}
784
785
private:
786
VerifyState* _state;
787
uint _worker_id;
788
};
789
790
const size_t OopStorageTestIteration::_max_workers;
791
792
template<bool is_const>
793
class OopStorageTestIteration::VM_Verify : public VM_GTestExecuteAtSafepoint {
794
public:
795
typedef typename Conditional<is_const,
796
const OopStorage,
797
OopStorage>::type Storage;
798
799
VM_Verify(Storage* storage, VerifyState* vstate) :
800
_storage(storage), _vstate(vstate), _result(false)
801
{}
802
803
void doit() {
804
VerifyFn verifier(_vstate);
805
_result = _storage->iterate_safepoint(verifier);
806
}
807
808
bool result() const { return _result; }
809
810
private:
811
Storage* _storage;
812
VerifyState* _vstate;
813
bool _result;
814
};
815
816
class OopStorageTestIteration::VM_VerifyUsingOopsDo : public VM_GTestExecuteAtSafepoint {
817
public:
818
VM_VerifyUsingOopsDo(OopStorage* storage, VerifyState* vstate) :
819
_storage(storage), _vstate(vstate)
820
{}
821
822
void doit() {
823
VerifyClosure verifier(_vstate);
824
_storage->oops_do(&verifier);
825
}
826
827
private:
828
OopStorage* _storage;
829
VerifyState* _vstate;
830
};
831
832
TEST_VM_F(OopStorageTestIteration, iterate_safepoint) {
833
VerifyState vstate(mark_non_const, _entries, _states);
834
VM_Verify<false> op(&_storage, &vstate);
835
{
836
ThreadInVMfromNative invm(JavaThread::current());
837
VMThread::execute(&op);
838
}
839
EXPECT_TRUE(op.result());
840
vstate.check();
841
}
842
843
TEST_VM_F(OopStorageTestIteration, const_iterate_safepoint) {
844
VerifyState vstate(mark_const, _entries, _states);
845
VM_Verify<true> op(&_storage, &vstate);
846
{
847
ThreadInVMfromNative invm(JavaThread::current());
848
VMThread::execute(&op);
849
}
850
EXPECT_TRUE(op.result());
851
vstate.check();
852
}
853
854
TEST_VM_F(OopStorageTestIteration, oops_do) {
855
VerifyState vstate(mark_non_const, _entries, _states);
856
VM_VerifyUsingOopsDo op(&_storage, &vstate);
857
{
858
ThreadInVMfromNative invm(JavaThread::current());
859
VMThread::execute(&op);
860
}
861
vstate.check();
862
}
863
864
class OopStorageTestParIteration : public OopStorageTestIteration {
865
public:
866
WorkGang* workers();
867
868
class VM_ParStateVerify;
869
870
template<bool concurrent, bool is_const> class Task;
871
template<bool concurrent, bool is_const> class TaskUsingOopsDo;
872
873
private:
874
static WorkGang* _workers;
875
};
876
877
WorkGang* OopStorageTestParIteration::_workers = NULL;
878
879
WorkGang* OopStorageTestParIteration::workers() {
880
if (_workers == NULL) {
881
_workers = new WorkGang("OopStorageTestParIteration workers",
882
_max_workers,
883
false,
884
false);
885
_workers->initialize_workers();
886
_workers->update_active_workers(_max_workers);
887
}
888
return _workers;
889
}
890
891
template<bool concurrent, bool is_const>
892
class OopStorageTestParIteration::Task : public AbstractGangTask {
893
typedef OopStorage::ParState<concurrent, is_const> StateType;
894
895
typedef typename Conditional<is_const,
896
const OopStorage,
897
OopStorage>::type Storage;
898
899
public:
900
Task(const char* name, Storage* storage, VerifyState* vstate) :
901
AbstractGangTask(name),
902
_state(storage),
903
_vstate(vstate)
904
{}
905
906
virtual void work(uint worker_id) {
907
VerifyFn verifier(_vstate, worker_id);
908
_state.iterate(verifier);
909
}
910
911
private:
912
StateType _state;
913
VerifyState* _vstate;
914
};
915
916
template<bool concurrent, bool is_const>
917
class OopStorageTestParIteration::TaskUsingOopsDo : public AbstractGangTask {
918
public:
919
TaskUsingOopsDo(const char* name, OopStorage* storage, VerifyState* vstate) :
920
AbstractGangTask(name),
921
_state(storage),
922
_vstate(vstate)
923
{}
924
925
virtual void work(uint worker_id) {
926
VerifyClosure verifier(_vstate, worker_id);
927
_state.oops_do(&verifier);
928
}
929
930
private:
931
OopStorage::ParState<concurrent, is_const> _state;
932
VerifyState* _vstate;
933
};
934
935
class OopStorageTestParIteration::VM_ParStateVerify : public VM_GTestExecuteAtSafepoint {
936
public:
937
VM_ParStateVerify(WorkGang* workers, AbstractGangTask* task) :
938
_workers(workers), _task(task)
939
{}
940
941
void doit() {
942
_workers->run_task(_task);
943
}
944
945
private:
946
WorkGang* _workers;
947
AbstractGangTask* _task;
948
};
949
950
TEST_VM_F(OopStorageTestParIteration, par_state_safepoint_iterate) {
951
VerifyState vstate(mark_non_const, _entries, _states);
952
Task<false, false> task("test", &_storage, &vstate);
953
VM_ParStateVerify op(workers(), &task);
954
{
955
ThreadInVMfromNative invm(JavaThread::current());
956
VMThread::execute(&op);
957
}
958
vstate.check();
959
}
960
961
TEST_VM_F(OopStorageTestParIteration, par_state_safepoint_const_iterate) {
962
VerifyState vstate(mark_const, _entries, _states);
963
Task<false, true> task("test", &_storage, &vstate);
964
VM_ParStateVerify op(workers(), &task);
965
{
966
ThreadInVMfromNative invm(JavaThread::current());
967
VMThread::execute(&op);
968
}
969
vstate.check();
970
}
971
972
TEST_VM_F(OopStorageTestParIteration, par_state_safepoint_oops_do) {
973
VerifyState vstate(mark_non_const, _entries, _states);
974
TaskUsingOopsDo<false, false> task("test", &_storage, &vstate);
975
VM_ParStateVerify op(workers(), &task);
976
{
977
ThreadInVMfromNative invm(JavaThread::current());
978
VMThread::execute(&op);
979
}
980
vstate.check();
981
}
982
983
TEST_VM_F(OopStorageTestParIteration, par_state_safepoint_const_oops_do) {
984
VerifyState vstate(mark_const, _entries, _states);
985
TaskUsingOopsDo<false, true> task("test", &_storage, &vstate);
986
VM_ParStateVerify op(workers(), &task);
987
{
988
ThreadInVMfromNative invm(JavaThread::current());
989
VMThread::execute(&op);
990
}
991
vstate.check();
992
}
993
994
TEST_VM_F(OopStorageTestParIteration, par_state_concurrent_iterate) {
995
VerifyState vstate(mark_non_const, _entries, _states);
996
Task<true, false> task("test", &_storage, &vstate);
997
workers()->run_task(&task);
998
vstate.check();
999
}
1000
1001
TEST_VM_F(OopStorageTestParIteration, par_state_concurrent_const_iterate) {
1002
VerifyState vstate(mark_const, _entries, _states);
1003
Task<true, true> task("test", &_storage, &vstate);
1004
workers()->run_task(&task);
1005
vstate.check();
1006
}
1007
1008
TEST_VM_F(OopStorageTestParIteration, par_state_concurrent_oops_do) {
1009
VerifyState vstate(mark_non_const, _entries, _states);
1010
TaskUsingOopsDo<true, false> task("test", &_storage, &vstate);
1011
workers()->run_task(&task);
1012
vstate.check();
1013
}
1014
1015
TEST_VM_F(OopStorageTestParIteration, par_state_concurrent_const_oops_do) {
1016
VerifyState vstate(mark_const, _entries, _states);
1017
TaskUsingOopsDo<true, true> task("test", &_storage, &vstate);
1018
workers()->run_task(&task);
1019
vstate.check();
1020
}
1021
1022
TEST_VM_F(OopStorageTestWithAllocation, delete_empty_blocks) {
1023
size_t initial_active_size = active_count(_storage);
1024
EXPECT_EQ(initial_active_size, _storage.block_count());
1025
ASSERT_LE(3u, initial_active_size); // Need at least 3 blocks for test
1026
1027
for (size_t i = 0; empty_block_count(_storage) < 3; ++i) {
1028
ASSERT_GT(_max_entries, i);
1029
release_entry(_storage, _entries[i]);
1030
}
1031
1032
EXPECT_EQ(initial_active_size, active_count(_storage));
1033
EXPECT_EQ(initial_active_size, _storage.block_count());
1034
EXPECT_EQ(3u, empty_block_count(_storage));
1035
{
1036
ThreadInVMfromNative invm(JavaThread::current());
1037
while (_storage.delete_empty_blocks()) {}
1038
}
1039
EXPECT_EQ(0u, empty_block_count(_storage));
1040
EXPECT_EQ(initial_active_size - 3, active_count(_storage));
1041
EXPECT_EQ(initial_active_size - 3, _storage.block_count());
1042
}
1043
1044
TEST_VM_F(OopStorageTestWithAllocation, allocation_status) {
1045
oop* retained = _entries[200];
1046
oop* released = _entries[300];
1047
oop* garbage = reinterpret_cast<oop*>(1024 * 1024);
1048
release_entry(_storage, released);
1049
1050
EXPECT_EQ(OopStorage::ALLOCATED_ENTRY, _storage.allocation_status(retained));
1051
EXPECT_EQ(OopStorage::UNALLOCATED_ENTRY, _storage.allocation_status(released));
1052
EXPECT_EQ(OopStorage::INVALID_ENTRY, _storage.allocation_status(garbage));
1053
1054
for (size_t i = 0; i < _max_entries; ++i) {
1055
if ((_entries[i] != retained) && (_entries[i] != released)) {
1056
// Leave deferred release updates to block deletion.
1057
release_entry(_storage, _entries[i], false);
1058
}
1059
}
1060
1061
{
1062
ThreadInVMfromNative invm(JavaThread::current());
1063
while (_storage.delete_empty_blocks()) {}
1064
}
1065
EXPECT_EQ(OopStorage::ALLOCATED_ENTRY, _storage.allocation_status(retained));
1066
EXPECT_EQ(OopStorage::INVALID_ENTRY, _storage.allocation_status(released));
1067
EXPECT_EQ(OopStorage::INVALID_ENTRY, _storage.allocation_status(garbage));
1068
}
1069
1070
TEST_VM_F(OopStorageTest, usage_info) {
1071
size_t goal_blocks = 5;
1072
oop* entries[1000];
1073
size_t allocated = 0;
1074
1075
EXPECT_EQ(0u, _storage.block_count());
1076
// There is non-block overhead, so always some usage.
1077
EXPECT_LT(0u, _storage.total_memory_usage());
1078
1079
while (_storage.block_count() < goal_blocks) {
1080
size_t this_count = _storage.block_count();
1081
while (_storage.block_count() == this_count) {
1082
ASSERT_GT(ARRAY_SIZE(entries), allocated);
1083
entries[allocated] = _storage.allocate();
1084
ASSERT_TRUE(entries[allocated] != NULL);
1085
++allocated;
1086
}
1087
EXPECT_NE(0u, _storage.block_count());
1088
EXPECT_NE(0u, _storage.total_memory_usage());
1089
}
1090
1091
EXPECT_LT(TestAccess::memory_per_block() * _storage.block_count(),
1092
_storage.total_memory_usage());
1093
}
1094
1095
#ifndef PRODUCT
1096
1097
TEST_VM_F(OopStorageTestWithAllocation, print_storage) {
1098
// Release the first 1/2
1099
for (size_t i = 0; i < (_max_entries / 2); ++i) {
1100
// Deferred updates don't affect print output.
1101
release_entry(_storage, _entries[i], false);
1102
_entries[i] = NULL;
1103
}
1104
// Release every other remaining
1105
for (size_t i = _max_entries / 2; i < _max_entries; i += 2) {
1106
// Deferred updates don't affect print output.
1107
release_entry(_storage, _entries[i], false);
1108
_entries[i] = NULL;
1109
}
1110
1111
size_t expected_entries = _max_entries / 4;
1112
EXPECT_EQ(expected_entries, _storage.allocation_count());
1113
1114
size_t entries_per_block = BitsPerWord;
1115
size_t expected_blocks = (_max_entries + entries_per_block - 1) / entries_per_block;
1116
EXPECT_EQ(expected_blocks, _storage.block_count());
1117
1118
double expected_usage = (100.0 * expected_entries) / (expected_blocks * entries_per_block);
1119
1120
{
1121
ResourceMark rm;
1122
stringStream expected_st;
1123
expected_st.print("Test Storage: " SIZE_FORMAT
1124
" entries in " SIZE_FORMAT
1125
" blocks (%.F%%), " SIZE_FORMAT " bytes",
1126
expected_entries,
1127
expected_blocks,
1128
expected_usage,
1129
_storage.total_memory_usage());
1130
stringStream st;
1131
_storage.print_on(&st);
1132
EXPECT_STREQ(expected_st.as_string(), st.as_string());
1133
}
1134
}
1135
1136
#endif // !PRODUCT
1137
1138
class OopStorageBlockCollectionTest : public ::testing::Test {
1139
protected:
1140
OopStorageBlockCollectionTest() {
1141
for (size_t i = 0; i < nvalues; ++i) {
1142
values[i] = OopBlock::new_block(pseudo_owner());
1143
}
1144
}
1145
1146
~OopStorageBlockCollectionTest() {
1147
for (size_t i = 0; i < nvalues; ++i) {
1148
OopBlock::delete_block(*values[i]);
1149
}
1150
}
1151
1152
public:
1153
static const size_t nvalues = 10;
1154
OopBlock* values[nvalues];
1155
1156
private:
1157
// The only thing we actually care about is the address of the owner.
1158
static const size_t pseudo_owner_size = sizeof(OopStorage) / sizeof(void*);
1159
static const void* const _pseudo_owner[pseudo_owner_size];
1160
static const OopStorage* pseudo_owner() {
1161
return reinterpret_cast<const OopStorage*>(&_pseudo_owner);
1162
}
1163
};
1164
1165
const size_t OopStorageBlockCollectionTest::nvalues;
1166
const void* const OopStorageBlockCollectionTest::_pseudo_owner[] = {};
1167
1168
class OopStorageAllocationListTest : public OopStorageBlockCollectionTest {};
1169
1170
TEST_F(OopStorageAllocationListTest, empty_list) {
1171
AllocationList list;
1172
1173
EXPECT_TRUE(is_list_empty(list));
1174
EXPECT_EQ(NULL_BLOCK, list.head());
1175
EXPECT_EQ(NULL_BLOCK, list.chead());
1176
EXPECT_EQ(NULL_BLOCK, list.ctail());
1177
}
1178
1179
TEST_F(OopStorageAllocationListTest, push_back) {
1180
AllocationList list;
1181
1182
for (size_t i = 0; i < nvalues; ++i) {
1183
list.push_back(*values[i]);
1184
EXPECT_FALSE(is_list_empty(list));
1185
EXPECT_EQ(list.ctail(), values[i]);
1186
}
1187
1188
EXPECT_EQ(list.chead(), list.head());
1189
EXPECT_EQ(list.chead(), values[0]);
1190
EXPECT_EQ(list.ctail(), values[nvalues - 1]);
1191
1192
const OopBlock* block = list.chead();
1193
for (size_t i = 0; i < nvalues; ++i) {
1194
EXPECT_EQ(block, values[i]);
1195
block = list.next(*block);
1196
}
1197
EXPECT_EQ(NULL_BLOCK, block);
1198
1199
block = list.ctail();
1200
for (size_t i = 0; i < nvalues; ++i) {
1201
EXPECT_EQ(block, values[nvalues - i - 1]);
1202
block = list.prev(*block);
1203
}
1204
EXPECT_EQ(NULL_BLOCK, block);
1205
1206
clear_list(list);
1207
}
1208
1209
TEST_F(OopStorageAllocationListTest, push_front) {
1210
AllocationList list;
1211
1212
for (size_t i = 0; i < nvalues; ++i) {
1213
list.push_front(*values[i]);
1214
EXPECT_FALSE(is_list_empty(list));
1215
EXPECT_EQ(list.head(), values[i]);
1216
}
1217
1218
EXPECT_EQ(list.chead(), list.head());
1219
EXPECT_EQ(list.chead(), values[nvalues - 1]);
1220
EXPECT_EQ(list.ctail(), values[0]);
1221
1222
const OopBlock* block = list.chead();
1223
for (size_t i = 0; i < nvalues; ++i) {
1224
EXPECT_EQ(block, values[nvalues - i - 1]);
1225
block = list.next(*block);
1226
}
1227
EXPECT_EQ(NULL_BLOCK, block);
1228
1229
block = list.ctail();
1230
for (size_t i = 0; i < nvalues; ++i) {
1231
EXPECT_EQ(block, values[i]);
1232
block = list.prev(*block);
1233
}
1234
EXPECT_EQ(NULL_BLOCK, block);
1235
1236
clear_list(list);
1237
}
1238
1239
class OopStorageAllocationListTestWithList : public OopStorageAllocationListTest {
1240
public:
1241
OopStorageAllocationListTestWithList() : list() {
1242
for (size_t i = 0; i < nvalues; ++i) {
1243
list.push_back(*values[i]);
1244
}
1245
}
1246
1247
~OopStorageAllocationListTestWithList() {
1248
clear_list(list);
1249
}
1250
1251
AllocationList list;
1252
};
1253
1254
TEST_F(OopStorageAllocationListTestWithList, unlink_front) {
1255
EXPECT_EQ(list.chead(), values[0]);
1256
EXPECT_EQ(list.ctail(), values[nvalues - 1]);
1257
1258
list.unlink(*values[0]);
1259
EXPECT_EQ(NULL_BLOCK, list.next(*values[0]));
1260
EXPECT_EQ(NULL_BLOCK, list.prev(*values[0]));
1261
EXPECT_EQ(list.chead(), values[1]);
1262
EXPECT_EQ(list.ctail(), values[nvalues - 1]);
1263
1264
const OopBlock* block = list.chead();
1265
for (size_t i = 1; i < nvalues; ++i) {
1266
EXPECT_EQ(block, values[i]);
1267
block = list.next(*block);
1268
}
1269
EXPECT_EQ(NULL_BLOCK, block);
1270
}
1271
1272
TEST_F(OopStorageAllocationListTestWithList, unlink_back) {
1273
EXPECT_EQ(list.chead(), values[0]);
1274
1275
list.unlink(*values[nvalues - 1]);
1276
EXPECT_EQ(NULL_BLOCK, list.next(*values[nvalues - 1]));
1277
EXPECT_EQ(NULL_BLOCK, list.prev(*values[nvalues - 1]));
1278
EXPECT_EQ(list.chead(), values[0]);
1279
EXPECT_EQ(list.ctail(), values[nvalues - 2]);
1280
1281
const OopBlock* block = list.chead();
1282
for (size_t i = 0; i < nvalues - 1; ++i) {
1283
EXPECT_EQ(block, values[i]);
1284
block = list.next(*block);
1285
}
1286
EXPECT_EQ(NULL_BLOCK, block);
1287
}
1288
1289
TEST_F(OopStorageAllocationListTestWithList, unlink_middle) {
1290
EXPECT_EQ(list.chead(), values[0]);
1291
1292
size_t index = nvalues / 2;
1293
1294
list.unlink(*values[index]);
1295
EXPECT_EQ(NULL_BLOCK, list.next(*values[index]));
1296
EXPECT_EQ(NULL_BLOCK, list.prev(*values[index]));
1297
EXPECT_EQ(list.chead(), values[0]);
1298
EXPECT_EQ(list.ctail(), values[nvalues - 1]);
1299
1300
const OopBlock* block = list.chead();
1301
for (size_t i = 0; i < index; ++i) {
1302
EXPECT_EQ(block, values[i]);
1303
block = list.next(*block);
1304
}
1305
for (size_t i = index + 1; i < nvalues; ++i) {
1306
EXPECT_EQ(block, values[i]);
1307
block = list.next(*block);
1308
}
1309
EXPECT_EQ(NULL_BLOCK, block);
1310
}
1311
1312
TEST_F(OopStorageAllocationListTest, single) {
1313
AllocationList list;
1314
1315
list.push_back(*values[0]);
1316
EXPECT_EQ(NULL_BLOCK, list.next(*values[0]));
1317
EXPECT_EQ(NULL_BLOCK, list.prev(*values[0]));
1318
EXPECT_EQ(list.chead(), values[0]);
1319
EXPECT_EQ(list.ctail(), values[0]);
1320
1321
list.unlink(*values[0]);
1322
EXPECT_EQ(NULL_BLOCK, list.next(*values[0]));
1323
EXPECT_EQ(NULL_BLOCK, list.prev(*values[0]));
1324
EXPECT_EQ(NULL_BLOCK, list.chead());
1325
EXPECT_EQ(NULL_BLOCK, list.ctail());
1326
}
1327
1328
class OopStorageActiveArrayTest : public OopStorageBlockCollectionTest {};
1329
1330
TEST_F(OopStorageActiveArrayTest, empty_array) {
1331
ActiveArray* a = ActiveArray::create(nvalues);
1332
1333
EXPECT_EQ(nvalues, a->size());
1334
EXPECT_EQ(0u, a->block_count_acquire());
1335
TestAccess::block_array_set_block_count(a, 2);
1336
EXPECT_EQ(2u, a->block_count_acquire());
1337
TestAccess::block_array_set_block_count(a, 0);
1338
a->increment_refcount();
1339
a->increment_refcount();
1340
EXPECT_FALSE(a->decrement_refcount());
1341
EXPECT_TRUE(a->decrement_refcount());
1342
1343
ActiveArray::destroy(a);
1344
}
1345
1346
TEST_F(OopStorageActiveArrayTest, push) {
1347
ActiveArray* a = ActiveArray::create(nvalues - 1);
1348
1349
for (size_t i = 0; i < nvalues - 1; ++i) {
1350
EXPECT_TRUE(a->push(values[i]));
1351
EXPECT_EQ(i + 1, a->block_count_acquire());
1352
EXPECT_EQ(values[i], a->at(i));
1353
}
1354
EXPECT_FALSE(a->push(values[nvalues - 1]));
1355
1356
TestAccess::block_array_set_block_count(a, 0);
1357
ActiveArray::destroy(a);
1358
}
1359
1360
class OopStorageActiveArrayTestWithArray : public OopStorageActiveArrayTest {
1361
public:
1362
OopStorageActiveArrayTestWithArray() : a(ActiveArray::create(nvalues)) {
1363
for (size_t i = 0; i < nvalues; ++i) {
1364
a->push(values[i]);
1365
}
1366
}
1367
1368
~OopStorageActiveArrayTestWithArray() {
1369
TestAccess::block_array_set_block_count(a, 0);
1370
ActiveArray::destroy(a);
1371
}
1372
1373
ActiveArray* a;
1374
};
1375
1376
TEST_F(OopStorageActiveArrayTestWithArray, remove0) {
1377
a->remove(values[0]);
1378
EXPECT_EQ(nvalues - 1, a->block_count_acquire());
1379
EXPECT_EQ(values[nvalues - 1], a->at(0));
1380
for (size_t i = 1; i < nvalues - 1; ++i) {
1381
EXPECT_EQ(values[i], a->at(i));
1382
}
1383
}
1384
1385
TEST_F(OopStorageActiveArrayTestWithArray, remove3) {
1386
a->remove(values[3]);
1387
EXPECT_EQ(nvalues - 1, a->block_count_acquire());
1388
for (size_t i = 0; i < 3; ++i) {
1389
EXPECT_EQ(values[i], a->at(i));
1390
}
1391
EXPECT_EQ(values[nvalues - 1], a->at(3));
1392
for (size_t i = 4; i < nvalues - 1; ++i) {
1393
EXPECT_EQ(values[i], a->at(i));
1394
}
1395
}
1396
1397
TEST_F(OopStorageActiveArrayTestWithArray, remove_last) {
1398
a->remove(values[nvalues - 1]);
1399
EXPECT_EQ(nvalues - 1, a->block_count_acquire());
1400
for (size_t i = 0; i < nvalues - 1; ++i) {
1401
EXPECT_EQ(values[i], a->at(i));
1402
}
1403
}
1404
1405