From 0f4154a9e9805534595feccc53a4a1abf20f99ae Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Johan=20Sj=C3=B6len?= <jsjolen@openjdk.org>
Date: Tue, 4 Jun 2024 10:53:26 +0000
Subject: [PATCH] 8331193: Return references when possible in GrowableArray

Reviewed-by: stefank, kbarrett, epeter
---
 src/hotspot/share/utilities/growableArray.hpp | 24 +++++++++++++----
 .../gtest/utilities/test_growableArray.cpp    | 27 +++++++++++++++++++
 2 files changed, 46 insertions(+), 5 deletions(-)

diff --git a/src/hotspot/share/utilities/growableArray.hpp b/src/hotspot/share/utilities/growableArray.hpp
index c3c64762942..79d03f58a9e 100644
--- a/src/hotspot/share/utilities/growableArray.hpp
+++ b/src/hotspot/share/utilities/growableArray.hpp
@@ -153,17 +153,31 @@ public:
     return &_data[i];
   }
 
-  E first() const {
+  E& first() {
     assert(_len > 0, "empty");
     return _data[0];
   }
 
-  E top() const {
+  E const& first() const {
     assert(_len > 0, "empty");
-    return _data[_len-1];
+    return _data[0];
   }
 
-  E last() const {
+  E& top() {
+    assert(_len > 0, "empty");
+    return _data[_len - 1];
+  }
+
+  E const& top() const {
+    assert(_len > 0, "empty");
+    return _data[_len - 1];
+  }
+
+  E& last() {
+    return top();
+  }
+
+  E const& last() const {
     return top();
   }
 
@@ -410,7 +424,7 @@ public:
 
   void push(const E& elem) { append(elem); }
 
-  E at_grow(int i, const E& fill = E()) {
+  E& at_grow(int i, const E& fill = E()) {
     assert(0 <= i, "negative index %d", i);
     if (i >= this->_len) {
       if (i >= this->_capacity) grow(i);
diff --git a/test/hotspot/gtest/utilities/test_growableArray.cpp b/test/hotspot/gtest/utilities/test_growableArray.cpp
index cd269e09212..74eb354cb2e 100644
--- a/test/hotspot/gtest/utilities/test_growableArray.cpp
+++ b/test/hotspot/gtest/utilities/test_growableArray.cpp
@@ -663,3 +663,30 @@ TEST(GrowableArrayCHeap, find_from_end_if) {
     ASSERT_EQ(index, -1);
   }
 }
+
+TEST(GrowableArrayCHeap, returning_references_works_as_expected) {
+  GrowableArrayCHeap<int, mtTest> arr(8, 8, -1); // Pre-fill with 8 -1s
+  int& x = arr.at_grow(9, -1);
+  EXPECT_EQ(-1, arr.at(9));
+  EXPECT_EQ(-1, x);
+  x = 2;
+  EXPECT_EQ(2, arr.at(9));
+  int& x2 = arr.top();
+  EXPECT_EQ(2, arr.at(9));
+  x2 = 5;
+  EXPECT_EQ(5, arr.at(9));
+
+  int y = arr.at_grow(10, -1);
+  EXPECT_EQ(-1, arr.at(10));
+  y = arr.top();
+  EXPECT_EQ(-1, arr.at(10));
+
+  GrowableArrayCHeap<int, mtTest> arr2(1, 1, -1);
+  int& first = arr2.first();
+  int& last = arr2.last();
+  EXPECT_EQ(-1, first);
+  EXPECT_EQ(-1, last);
+  first = 5;
+  EXPECT_EQ(5, first);
+  EXPECT_EQ(5, last);
+}