Skip to content

Commit 9130ca4

Browse files
committed
8256401: ZGC: Improve ZList verification
Reviewed-by: ayang, stefank
1 parent f2a9d02 commit 9130ca4

File tree

4 files changed

+72
-139
lines changed

4 files changed

+72
-139
lines changed

src/hotspot/share/gc/z/zList.hpp

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,18 +35,18 @@ class ZListNode {
3535
friend class ZList<T>;
3636

3737
private:
38-
ZListNode* _next;
39-
ZListNode* _prev;
38+
ZListNode<T>* _next;
39+
ZListNode<T>* _prev;
4040

41-
ZListNode(ZListNode* next, ZListNode* prev);
41+
NONCOPYABLE(ZListNode);
4242

43-
void set_unused();
43+
void verify_links() const;
44+
void verify_links_linked() const;
45+
void verify_links_unlinked() const;
4446

4547
public:
4648
ZListNode();
4749
~ZListNode();
48-
49-
bool is_unused() const;
5050
};
5151

5252
// Doubly linked list
@@ -58,7 +58,7 @@ class ZList {
5858

5959
NONCOPYABLE(ZList);
6060

61-
void verify() const;
61+
void verify_head() const;
6262

6363
void insert(ZListNode<T>* before, ZListNode<T>* node);
6464

@@ -84,8 +84,6 @@ class ZList {
8484
void remove(T* elem);
8585
T* remove_first();
8686
T* remove_last();
87-
88-
void transfer(ZList<T>* list);
8987
};
9088

9189
template <typename T, bool Forward>

src/hotspot/share/gc/z/zList.inline.hpp

Lines changed: 55 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -28,47 +28,54 @@
2828
#include "utilities/debug.hpp"
2929

3030
template <typename T>
31-
inline ZListNode<T>::ZListNode(ZListNode* next, ZListNode* prev) :
32-
_next(next),
33-
_prev(prev) {}
31+
inline ZListNode<T>::ZListNode() :
32+
_next(this),
33+
_prev(this) {}
3434

3535
template <typename T>
36-
inline void ZListNode<T>::set_unused() {
37-
_next = NULL;
38-
_prev = NULL;
36+
inline ZListNode<T>::~ZListNode() {
37+
verify_links_unlinked();
3938
}
4039

4140
template <typename T>
42-
inline ZListNode<T>::ZListNode() {
43-
set_unused();
41+
inline void ZListNode<T>::verify_links() const {
42+
assert(_next->_prev == this, "Corrupt list node");
43+
assert(_prev->_next == this, "Corrupt list node");
4444
}
4545

4646
template <typename T>
47-
inline ZListNode<T>::~ZListNode() {
48-
set_unused();
47+
inline void ZListNode<T>::verify_links_linked() const {
48+
assert(_next != this, "Should be in a list");
49+
assert(_prev != this, "Should be in a list");
50+
verify_links();
4951
}
5052

5153
template <typename T>
52-
inline bool ZListNode<T>::is_unused() const {
53-
return _next == NULL && _prev == NULL;
54+
inline void ZListNode<T>::verify_links_unlinked() const {
55+
assert(_next == this, "Should not be in a list");
56+
assert(_prev == this, "Should not be in a list");
5457
}
5558

5659
template <typename T>
57-
inline void ZList<T>::verify() const {
58-
assert(_head._next->_prev == &_head, "List corrupt");
59-
assert(_head._prev->_next == &_head, "List corrupt");
60+
inline void ZList<T>::verify_head() const {
61+
_head.verify_links();
6062
}
6163

6264
template <typename T>
6365
inline void ZList<T>::insert(ZListNode<T>* before, ZListNode<T>* node) {
64-
verify();
66+
verify_head();
67+
68+
before->verify_links();
69+
node->verify_links_unlinked();
6570

66-
assert(node->is_unused(), "Already in a list");
6771
node->_prev = before;
6872
node->_next = before->_next;
6973
before->_next = node;
7074
node->_next->_prev = node;
7175

76+
before->verify_links_linked();
77+
node->verify_links_linked();
78+
7279
_size++;
7380
}
7481

@@ -84,20 +91,20 @@ inline T* ZList<T>::cast_to_outer(ZListNode<T>* node) const {
8491

8592
template <typename T>
8693
inline ZList<T>::ZList() :
87-
_head(&_head, &_head),
94+
_head(),
8895
_size(0) {
89-
verify();
96+
verify_head();
9097
}
9198

9299
template <typename T>
93100
inline size_t ZList<T>::size() const {
94-
verify();
101+
verify_head();
95102
return _size;
96103
}
97104

98105
template <typename T>
99106
inline bool ZList<T>::is_empty() const {
100-
return _size == 0;
107+
return size() == 0;
101108
}
102109

103110
template <typename T>
@@ -112,15 +119,27 @@ inline T* ZList<T>::last() const {
112119

113120
template <typename T>
114121
inline T* ZList<T>::next(T* elem) const {
115-
verify();
116-
ZListNode<T>* next = cast_to_inner(elem)->_next;
122+
verify_head();
123+
124+
ZListNode<T>* const node = cast_to_inner(elem);
125+
node->verify_links_linked();
126+
127+
ZListNode<T>* const next = node->_next;
128+
next->verify_links_linked();
129+
117130
return (next == &_head) ? NULL : cast_to_outer(next);
118131
}
119132

120133
template <typename T>
121134
inline T* ZList<T>::prev(T* elem) const {
122-
verify();
123-
ZListNode<T>* prev = cast_to_inner(elem)->_prev;
135+
verify_head();
136+
137+
ZListNode<T>* const node = cast_to_inner(elem);
138+
node->verify_links_linked();
139+
140+
ZListNode<T>* const prev = node->_prev;
141+
prev->verify_links_linked();
142+
124143
return (prev == &_head) ? NULL : cast_to_outer(prev);
125144
}
126145

@@ -146,19 +165,24 @@ inline void ZList<T>::insert_after(T* after, T* elem) {
146165

147166
template <typename T>
148167
inline void ZList<T>::remove(T* elem) {
149-
verify();
168+
verify_head();
150169

151170
ZListNode<T>* const node = cast_to_inner(elem);
152-
assert(!node->is_unused(), "Not in a list");
171+
node->verify_links_linked();
153172

154173
ZListNode<T>* const next = node->_next;
155174
ZListNode<T>* const prev = node->_prev;
156-
assert(next->_prev == node, "List corrupt");
157-
assert(prev->_next == node, "List corrupt");
175+
next->verify_links_linked();
176+
prev->verify_links_linked();
177+
178+
node->_next = prev->_next;
179+
node->_prev = next->_prev;
180+
node->verify_links_unlinked();
158181

159-
prev->_next = next;
160182
next->_prev = prev;
161-
node->set_unused();
183+
prev->_next = next;
184+
next->verify_links();
185+
prev->verify_links();
162186

163187
_size--;
164188
}
@@ -183,28 +207,6 @@ inline T* ZList<T>::remove_last() {
183207
return elem;
184208
}
185209

186-
template <typename T>
187-
inline void ZList<T>::transfer(ZList<T>* list) {
188-
verify();
189-
190-
if (!list->is_empty()) {
191-
list->_head._next->_prev = _head._prev;
192-
list->_head._prev->_next = _head._prev->_next;
193-
194-
_head._prev->_next = list->_head._next;
195-
_head._prev = list->_head._prev;
196-
197-
list->_head._next = &list->_head;
198-
list->_head._prev = &list->_head;
199-
200-
_size += list->_size;
201-
list->_size = 0;
202-
203-
list->verify();
204-
verify();
205-
}
206-
}
207-
208210
template <typename T, bool Forward>
209211
inline ZListIteratorImpl<T, Forward>::ZListIteratorImpl(const ZList<T>* list) :
210212
_list(list),

src/hotspot/share/gc/z/zPage.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ ZPage::ZPage(uint8_t type, const ZVirtualMemory& vmem, const ZPhysicalMemory& pm
4040
_top(start()),
4141
_livemap(object_max_count()),
4242
_last_used(0),
43-
_physical(pmem) {
43+
_physical(pmem),
44+
_node() {
4445
assert_initialized();
4546
}
4647

test/hotspot/gtest/gc/z/test_zList.cpp

Lines changed: 8 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -87,6 +87,13 @@ TEST_F(ZListTest, test_insert) {
8787

8888
EXPECT_EQ(list.size(), 6u);
8989
assert_sorted(&list);
90+
91+
for (int i = 0; i < 6; i++) {
92+
ZTestEntry* e = list.remove_first();
93+
EXPECT_EQ(e->id(), i);
94+
}
95+
96+
EXPECT_EQ(list.size(), 0u);
9097
}
9198

9299
TEST_F(ZListTest, test_remove) {
@@ -145,79 +152,4 @@ TEST_F(ZListTest, test_remove) {
145152
}
146153
}
147154

148-
TEST_F(ZListTest, test_transfer) {
149-
// Transfer empty to empty
150-
{
151-
ZList<ZTestEntry> list0;
152-
ZList<ZTestEntry> list1;
153-
154-
EXPECT_TRUE(list0.is_empty());
155-
EXPECT_TRUE(list1.is_empty());
156-
157-
list0.transfer(&list1);
158-
159-
EXPECT_TRUE(list0.is_empty());
160-
EXPECT_TRUE(list1.is_empty());
161-
}
162-
163-
// Transfer non-empty to empty
164-
{
165-
ZList<ZTestEntry> list0;
166-
ZList<ZTestEntry> list1;
167-
ZTestEntry e0(0);
168-
ZTestEntry e1(1);
169-
ZTestEntry e2(2);
170-
ZTestEntry e3(3);
171-
ZTestEntry e4(4);
172-
ZTestEntry e5(5);
173-
174-
list1.insert_last(&e0);
175-
list1.insert_last(&e1);
176-
list1.insert_last(&e2);
177-
list1.insert_last(&e3);
178-
list1.insert_last(&e4);
179-
list1.insert_last(&e5);
180-
181-
EXPECT_EQ(list0.size(), 0u);
182-
EXPECT_EQ(list1.size(), 6u);
183-
184-
list0.transfer(&list1);
185-
186-
EXPECT_EQ(list0.size(), 6u);
187-
EXPECT_EQ(list1.size(), 0u);
188-
189-
assert_sorted(&list0);
190-
}
191-
192-
// Transfer non-empty to non-empty
193-
{
194-
ZList<ZTestEntry> list0;
195-
ZList<ZTestEntry> list1;
196-
ZTestEntry e0(0);
197-
ZTestEntry e1(1);
198-
ZTestEntry e2(2);
199-
ZTestEntry e3(3);
200-
ZTestEntry e4(4);
201-
ZTestEntry e5(5);
202-
203-
list0.insert_last(&e0);
204-
list0.insert_last(&e1);
205-
list0.insert_last(&e2);
206-
207-
list1.insert_last(&e3);
208-
list1.insert_last(&e4);
209-
list1.insert_last(&e5);
210-
211-
EXPECT_EQ(list0.size(), 3u);
212-
EXPECT_EQ(list1.size(), 3u);
213-
214-
list0.transfer(&list1);
215-
216-
EXPECT_EQ(list0.size(), 6u);
217-
EXPECT_EQ(list1.size(), 0u);
218-
219-
assert_sorted(&list0);
220-
}
221-
}
222-
223155
#endif // PRODUCT

0 commit comments

Comments
 (0)