diff --git a/src/hotspot/share/utilities/growableArray.hpp b/src/hotspot/share/utilities/growableArray.hpp index 1823a2ba861..e300bea6993 100644 --- a/src/hotspot/share/utilities/growableArray.hpp +++ b/src/hotspot/share/utilities/growableArray.hpp @@ -493,16 +493,16 @@ public: return false; } - // Remove all elements up to the index (exclusive). The order is preserved. - void remove_till(int idx) { - remove_range(0, idx); + // Remove all elements in the range [0; end). The order is preserved. + void remove_till(int end) { + remove_range(0, end); } - // Remove all elements in the range [start - end). The order is preserved. + // Remove all elements in the range [start; end). The order is preserved. void remove_range(int start, int end) { assert(0 <= start, "illegal start index %d", start); - assert(start < end && end <= this->_len, - "erase called with invalid range (%d, %d) for length %d", + assert(start <= end && end <= this->_len, + "erase called with invalid range [%d, %d) for length %d", start, end, this->_len); for (int i = start, j = end; j < this->length(); i++, j++) { diff --git a/test/hotspot/gtest/utilities/test_growableArray.cpp b/test/hotspot/gtest/utilities/test_growableArray.cpp index 45fc9498d27..6958da18ac3 100644 --- a/test/hotspot/gtest/utilities/test_growableArray.cpp +++ b/test/hotspot/gtest/utilities/test_growableArray.cpp @@ -232,12 +232,111 @@ protected: } } + template + static void test_remove_range(ArrayClass* a) { + // Seed initial + for (int i = 0; i < 10; i++) { + a->append(i); + } + ASSERT_EQ(a->length(), 10); + + // Remove empty range from the non-empty list, should not modify the list. + a->remove_range(0, 0); + ASSERT_EQ(a->length(), 10); + + // Remove one element from head, should result in [1 ... 9] + a->remove_range(0, 1); + ASSERT_EQ(a->length(), 9); + for (int i = 0; i < a->length(); i++) { + ASSERT_EQ(a->at(i), i + 1); + } + + // Remove one element from tail, should result in [1 ... 8] + a->remove_range(8, 9); + ASSERT_EQ(a->length(), 8); + for (int i = 0; i < a->length(); i++) { + ASSERT_EQ(a->at(i), i + 1); + } + + // Remove another empty range from the non-empty list, should not modify + a->remove_range(1, 1); + ASSERT_EQ(a->length(), 8); + + // Remove some elements from the middle, should result in [1 2 7 8] + a->remove_range(2, 6); + ASSERT_EQ(a->length(), 4); + ASSERT_EQ(a->at(0), 1); + ASSERT_EQ(a->at(1), 2); + ASSERT_EQ(a->at(2), 7); + ASSERT_EQ(a->at(3), 8); + + // Remove the rest of the elements one by one + a->remove_range(0, 1); + ASSERT_EQ(a->length(), 3); + ASSERT_EQ(a->at(0), 2); + ASSERT_EQ(a->at(1), 7); + ASSERT_EQ(a->at(2), 8); + + a->remove_range(0, 1); + ASSERT_EQ(a->length(), 2); + ASSERT_EQ(a->at(0), 7); + ASSERT_EQ(a->at(1), 8); + + a->remove_range(0, 1); + ASSERT_EQ(a->length(), 1); + ASSERT_EQ(a->at(0), 8); + + a->remove_range(0, 1); + ASSERT_EQ(a->length(), 0); + + // Remove elements from empty list with empty range, should be accepted + a->remove_range(0, 0); + ASSERT_EQ(a->length(), 0); + } + + template + static void test_remove_till(ArrayClass* a) { + // Seed initial + for (int i = 0; i < 10; i++) { + a->append(i); + } + ASSERT_EQ(a->length(), 10); + + // Remove empty range from non-empty list, should work + a->remove_till(0); + ASSERT_EQ(a->length(), 10); + + // Remove one element from head, should result in [1 ... 9] + a->remove_till(1); + ASSERT_EQ(a->length(), 9); + for (int i = 0; i < a->length(); i++) { + ASSERT_EQ(a->at(i), i + 1); + } + + // Remove two elements from head, should result in [3 ... 9] + a->remove_till(2); + ASSERT_EQ(a->length(), 7); + for (int i = 0; i < a->length(); i++) { + ASSERT_EQ(a->at(i), i + 3); + } + + // Remove remaining elements, should result in [] + a->remove_till(a->length()); + ASSERT_EQ(a->length(), 0); + + // Remove empty range from empty list, should work + a->remove_till(0); + ASSERT_EQ(a->length(), 0); + } + // Supported by all GrowableArrays enum TestEnum { Append, Clear, Capacity, - Iterator + Iterator, + RemoveRange, + RemoveTill }; template @@ -259,6 +358,14 @@ protected: test_iterator(a); break; + case RemoveRange: + test_remove_range(a); + break; + + case RemoveTill: + test_remove_till(a); + break; + default: fatal("Missing dispatch"); break; @@ -451,6 +558,14 @@ TEST_VM_F(GrowableArrayTest, iterator) { with_all_types_all_0(Iterator); } +TEST_VM_F(GrowableArrayTest, remove_range) { + with_all_types_all_0(RemoveRange); +} + +TEST_VM_F(GrowableArrayTest, remove_till) { + with_all_types_all_0(RemoveTill); +} + TEST_VM_F(GrowableArrayTest, copy) { with_no_cheap_array_append1(Copy1); }