Skip to content

Commit 501b606

Browse files
author
Kim Barrett
committed
8298725: Add BitMap support for reverse iteration
Reviewed-by: stefank, aboldtch, tschatzl
1 parent 9764948 commit 501b606

File tree

3 files changed

+127
-24
lines changed

3 files changed

+127
-24
lines changed

src/hotspot/share/utilities/bitMap.hpp

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ class BitMap {
264264
void verify_range(idx_t beg, idx_t end) const NOT_DEBUG_RETURN;
265265

266266
// Applies an operation to the index of each set bit in [beg, end), in
267-
// increasing order.
267+
// increasing (decreasing for reverse iteration) order.
268268
//
269269
// If i is an index of the bitmap, the operation is either
270270
// - function(i)
@@ -276,8 +276,8 @@ class BitMap {
276276
// an operation returning false.
277277
//
278278
// If an operation modifies the bitmap, modifications to bits at indices
279-
// greater than the current index will affect which further indices the
280-
// operation will be applied to.
279+
// greater than (less than for reverse iteration) the current index will
280+
// affect which further indices the operation will be applied to.
281281
//
282282
// precondition: beg and end form a valid range for the bitmap.
283283
template<typename Function>
@@ -296,6 +296,22 @@ class BitMap {
296296
return iterate(cl, 0, size());
297297
}
298298

299+
template<typename Function>
300+
bool reverse_iterate(Function function, idx_t beg, idx_t end) const;
301+
302+
template<typename BitMapClosureType>
303+
bool reverse_iterate(BitMapClosureType* cl, idx_t beg, idx_t end) const;
304+
305+
template<typename Function>
306+
bool reverse_iterate(Function function) const {
307+
return reverse_iterate(function, 0, size());
308+
}
309+
310+
template<typename BitMapClosureType>
311+
bool reverse_iterate(BitMapClosureType* cl) const {
312+
return reverse_iterate(cl, 0, size());
313+
}
314+
299315
// Return the index of the first set (or clear) bit in the range [beg, end),
300316
// or end if none found.
301317
// precondition: beg and end form a valid range for the bitmap.

src/hotspot/share/utilities/bitMap.inline.hpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,25 @@ inline bool BitMap::iterate(BitMapClosureType* cl, idx_t beg, idx_t end) const {
351351
return iterate(function, beg, end);
352352
}
353353

354+
template <typename Function>
355+
inline bool BitMap::reverse_iterate(Function function, idx_t beg, idx_t end) const {
356+
auto invoke = IterateInvoker<decltype(function(beg))>();
357+
for (idx_t index; true; end = index) {
358+
index = find_last_set_bit(beg, end);
359+
if (index >= end) {
360+
return true;
361+
} else if (!invoke(function, index)) {
362+
return false;
363+
}
364+
}
365+
}
366+
367+
template <typename BitMapClosureType>
368+
inline bool BitMap::reverse_iterate(BitMapClosureType* cl, idx_t beg, idx_t end) const {
369+
auto function = [&](idx_t index) { return cl->do_bit(index); };
370+
return reverse_iterate(function, beg, end);
371+
}
372+
354373
// Returns a bit mask for a range of bits [beg, end) within a single word. Each
355374
// bit in the mask is 0 if the bit is in the range, 1 if not in the range. The
356375
// returned mask can be used directly to clear the range, or inverted to set the

test/hotspot/gtest/utilities/test_bitMap_iterate.cpp

Lines changed: 89 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -59,31 +59,81 @@ static void test_iterate_lambda(const BitMap& map,
5959
ASSERT_EQ(positions_index, positions_size);
6060
}
6161

62+
static void test_reverse_iterate_lambda(const BitMap& map,
63+
const idx_t* positions,
64+
size_t positions_size) {
65+
SCOPED_TRACE("reverse iterate with lambda");
66+
size_t positions_index = positions_size;
67+
auto f = [&](idx_t i) {
68+
test_iterate_step(map, i, positions, --positions_index, positions_size);
69+
};
70+
ASSERT_TRUE(map.reverse_iterate(f));
71+
ASSERT_EQ(positions_index, 0u);
72+
}
73+
74+
75+
struct TestBitMapIterationData {
76+
const BitMap& _map;
77+
const idx_t* _positions;
78+
size_t _positions_index;
79+
size_t _positions_size;
80+
81+
TestBitMapIterationData(const BitMap& map,
82+
const idx_t* positions,
83+
size_t positions_index,
84+
size_t positions_size)
85+
: _map(map),
86+
_positions(positions),
87+
_positions_index(positions_index),
88+
_positions_size(positions_size)
89+
{}
90+
91+
void test(idx_t index) const {
92+
test_iterate_step(_map, index, _positions, _positions_index, _positions_size);
93+
}
94+
};
95+
6296
// Test closure returning bool. Also tests lambda returning bool.
6397
static void test_iterate_closure(const BitMap& map,
6498
const idx_t* positions,
6599
size_t positions_size) {
66100
SCOPED_TRACE("iterate with BitMapClosure");
67101
struct Closure : public BitMapClosure {
68-
const BitMap& _map;
69-
const idx_t* _positions;
70-
size_t _positions_index;
71-
size_t _positions_size;
102+
TestBitMapIterationData _data;
72103

73104
Closure(const BitMap& map, const idx_t* positions, size_t positions_size)
74-
: _map(map),
75-
_positions(positions),
76-
_positions_index(0),
77-
_positions_size(positions_size)
105+
: _data(map, positions, 0, positions_size)
78106
{}
79107

80108
bool do_bit(idx_t i) override {
81-
test_iterate_step(_map, i, _positions, _positions_index++, _positions_size);
109+
_data.test(i);
110+
_data._positions_index += 1;
82111
return true;
83112
}
84113
} closure{map, positions, positions_size};
85114
ASSERT_TRUE(map.iterate(&closure));
86-
ASSERT_EQ(closure._positions_index, positions_size);
115+
ASSERT_EQ(closure._data._positions_index, positions_size);
116+
}
117+
118+
static void test_reverse_iterate_closure(const BitMap& map,
119+
const idx_t* positions,
120+
size_t positions_size) {
121+
SCOPED_TRACE("reverse iterate with BitMapClosure");
122+
struct Closure : public BitMapClosure {
123+
TestBitMapIterationData _data;
124+
125+
Closure(const BitMap& map, const idx_t* positions, size_t positions_size)
126+
: _data(map, positions, positions_size, positions_size)
127+
{}
128+
129+
bool do_bit(idx_t i) override {
130+
_data._positions_index -= 1;
131+
_data.test(i);
132+
return true;
133+
}
134+
} closure{map, positions, positions_size};
135+
ASSERT_TRUE(map.reverse_iterate(&closure));
136+
ASSERT_EQ(closure._data._positions_index, 0u);
87137
}
88138

89139
// Test closure returning void. Also tests lambda returning bool.
@@ -92,24 +142,37 @@ static void test_iterate_non_closure(const BitMap& map,
92142
size_t positions_size) {
93143
SCOPED_TRACE("iterate with non-BitMapClosure");
94144
struct Closure {
95-
const BitMap& _map;
96-
const idx_t* _positions;
97-
size_t _positions_index;
98-
size_t _positions_size;
99-
145+
TestBitMapIterationData _data;
100146
Closure(const BitMap& map, const idx_t* positions, size_t positions_size)
101-
: _map(map),
102-
_positions(positions),
103-
_positions_index(0),
104-
_positions_size(positions_size)
147+
: _data(map, positions, 0, positions_size)
105148
{}
106149

107150
void do_bit(idx_t i) {
108-
test_iterate_step(_map, i, _positions, _positions_index++, _positions_size);
151+
_data.test(i);
152+
_data._positions_index += 1;
109153
}
110154
} closure{map, positions, positions_size};
111155
ASSERT_TRUE(map.iterate(&closure));
112-
ASSERT_EQ(closure._positions_index, positions_size);
156+
ASSERT_EQ(closure._data._positions_index, positions_size);
157+
}
158+
159+
static void test_reverse_iterate_non_closure(const BitMap& map,
160+
const idx_t* positions,
161+
size_t positions_size) {
162+
SCOPED_TRACE("reverse iterate with non-BitMapClosure");
163+
struct Closure {
164+
TestBitMapIterationData _data;
165+
Closure(const BitMap& map, const idx_t* positions, size_t positions_size)
166+
: _data(map, positions, positions_size, positions_size)
167+
{}
168+
169+
void do_bit(idx_t i) {
170+
_data._positions_index -= 1;
171+
_data.test(i);
172+
}
173+
} closure{map, positions, positions_size};
174+
ASSERT_TRUE(map.reverse_iterate(&closure));
175+
ASSERT_EQ(closure._data._positions_index, 0u);
113176
}
114177

115178
static void fill_iterate_map(BitMap& map,
@@ -125,9 +188,14 @@ static void test_iterate(BitMap& map,
125188
const idx_t* positions,
126189
size_t positions_size) {
127190
fill_iterate_map(map, positions, positions_size);
191+
128192
test_iterate_lambda(map, positions, positions_size);
129193
test_iterate_closure(map, positions, positions_size);
130194
test_iterate_non_closure(map, positions, positions_size);
195+
196+
test_reverse_iterate_lambda(map, positions, positions_size);
197+
test_reverse_iterate_closure(map, positions, positions_size);
198+
test_reverse_iterate_non_closure(map, positions, positions_size);
131199
}
132200

133201
TEST(BitMap, iterate_empty) {

0 commit comments

Comments
 (0)