16c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes/*
26c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes * Copyright (C) 2009 The Android Open Source Project
36c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes *
46c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
56c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes * you may not use this file except in compliance with the License.
66c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes * You may obtain a copy of the License at
76c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes *
86c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
96c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes *
106c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes * Unless required by applicable law or agreed to in writing, software
116c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
126c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes * See the License for the specific language governing permissions and
146c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes * limitations under the License.
156c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes */
166c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes
17c56057e40938c587a74984651a510e320a8cb4fdMathieu Chartier#include "indirect_reference_table-inl.h"
18a1ce1fef2d49d1d537776a5308ace7102a815fe5Brian Carlstrom
1946ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampe#include "android-base/stringprintf.h"
2046ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampe
213481ba2c4e4f3aa80d8c6d50a9f85dacb56b508bVladimir Marko#include "class_linker-inl.h"
22a1ce1fef2d49d1d537776a5308ace7102a815fe5Brian Carlstrom#include "common_runtime_test.h"
23967a0adf8b93a23d2a8fef82e06bd913db94ac19Hiroshi Yamauchi#include "mirror/object-inl.h"
240795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier#include "scoped_thread_state_change-inl.h"
256c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes
266c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughesnamespace art {
276c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes
2846ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampeusing android::base::StringPrintf;
2946ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampe
30a1ce1fef2d49d1d537776a5308ace7102a815fe5Brian Carlstromclass IndirectReferenceTableTest : public CommonRuntimeTest {};
316c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes
3263818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogersstatic void CheckDump(IndirectReferenceTable* irt, size_t num_objects, size_t num_unique)
33bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe    REQUIRES_SHARED(Locks::mutator_lock_) {
3463818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  std::ostringstream oss;
3563818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  irt->Dump(oss);
3663818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  if (num_objects == 0) {
3763818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers    EXPECT_EQ(oss.str().find("java.lang.Object"), std::string::npos) << oss.str();
3863818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  } else if (num_objects == 1) {
3963818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers    EXPECT_NE(oss.str().find("1 of java.lang.Object"), std::string::npos) << oss.str();
4063818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  } else {
4163818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers    EXPECT_NE(oss.str().find(StringPrintf("%zd of java.lang.Object (%zd unique instances)",
4263818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers                                          num_objects, num_unique)),
4363818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers              std::string::npos)
4463818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers                  << "\n Expected number of objects: " << num_objects
4563818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers                  << "\n Expected unique objects: " << num_unique << "\n"
4663818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers                  << oss.str();
4763818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  }
4863818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers}
4963818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers
506c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott HughesTEST_F(IndirectReferenceTableTest, BasicTest) {
51369810a98e6394b6dd162f5349e38a1f597b3bc7Andreas Gampe  // This will lead to error messages in the log.
52369810a98e6394b6dd162f5349e38a1f597b3bc7Andreas Gampe  ScopedLogSeverity sls(LogSeverity::FATAL);
53369810a98e6394b6dd162f5349e38a1f597b3bc7Andreas Gampe
5400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ScopedObjectAccess soa(Thread::Current());
556c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  static const size_t kTableMax = 20;
56da0a69edb24122d3d35ce1483c5ab94de919d714Richard Uhler  std::string error_msg;
579d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe  IndirectReferenceTable irt(kTableMax,
589d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe                             kGlobal,
599d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe                             IndirectReferenceTable::ResizableCapacity::kNo,
609d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe                             &error_msg);
61da0a69edb24122d3d35ce1483c5ab94de919d714Richard Uhler  ASSERT_TRUE(irt.IsValid()) << error_msg;
626c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes
639837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers  mirror::Class* c = class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;");
6428bd2e4f151267b34b8e1eb19c489d8d547bbf5cMathieu Chartier  StackHandleScope<4> hs(soa.Self());
65c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  ASSERT_TRUE(c != nullptr);
6628bd2e4f151267b34b8e1eb19c489d8d547bbf5cMathieu Chartier  Handle<mirror::Object> obj0 = hs.NewHandle(c->AllocObject(soa.Self()));
67fa4333dcb481e564f54726b4e6f8153612df835eAndreas Gampe  ASSERT_TRUE(obj0 != nullptr);
6828bd2e4f151267b34b8e1eb19c489d8d547bbf5cMathieu Chartier  Handle<mirror::Object> obj1 = hs.NewHandle(c->AllocObject(soa.Self()));
69fa4333dcb481e564f54726b4e6f8153612df835eAndreas Gampe  ASSERT_TRUE(obj1 != nullptr);
7028bd2e4f151267b34b8e1eb19c489d8d547bbf5cMathieu Chartier  Handle<mirror::Object> obj2 = hs.NewHandle(c->AllocObject(soa.Self()));
71fa4333dcb481e564f54726b4e6f8153612df835eAndreas Gampe  ASSERT_TRUE(obj2 != nullptr);
7228bd2e4f151267b34b8e1eb19c489d8d547bbf5cMathieu Chartier  Handle<mirror::Object> obj3 = hs.NewHandle(c->AllocObject(soa.Self()));
73fa4333dcb481e564f54726b4e6f8153612df835eAndreas Gampe  ASSERT_TRUE(obj3 != nullptr);
746c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes
75e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe  const IRTSegmentState cookie = kIRTFirstSegment;
766c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes
7763818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  CheckDump(&irt, 0, 0);
7863818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers
796c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  IndirectRef iref0 = (IndirectRef) 0x11110;
806c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  EXPECT_FALSE(irt.Remove(cookie, iref0)) << "unexpectedly successful removal";
816c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes
826c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  // Add three, check, remove in the order in which they were added.
8325651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe  iref0 = irt.Add(cookie, obj0.Get(), &error_msg);
84c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  EXPECT_TRUE(iref0 != nullptr);
8563818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  CheckDump(&irt, 1, 1);
8625651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe  IndirectRef iref1 = irt.Add(cookie, obj1.Get(), &error_msg);
87c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  EXPECT_TRUE(iref1 != nullptr);
8863818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  CheckDump(&irt, 2, 2);
8925651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe  IndirectRef iref2 = irt.Add(cookie, obj2.Get(), &error_msg);
90c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  EXPECT_TRUE(iref2 != nullptr);
9163818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  CheckDump(&irt, 3, 3);
926c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes
9328bd2e4f151267b34b8e1eb19c489d8d547bbf5cMathieu Chartier  EXPECT_OBJ_PTR_EQ(obj0.Get(), irt.Get(iref0));
9428bd2e4f151267b34b8e1eb19c489d8d547bbf5cMathieu Chartier  EXPECT_OBJ_PTR_EQ(obj1.Get(), irt.Get(iref1));
9528bd2e4f151267b34b8e1eb19c489d8d547bbf5cMathieu Chartier  EXPECT_OBJ_PTR_EQ(obj2.Get(), irt.Get(iref2));
966c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes
976c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  EXPECT_TRUE(irt.Remove(cookie, iref0));
9863818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  CheckDump(&irt, 2, 2);
996c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  EXPECT_TRUE(irt.Remove(cookie, iref1));
10063818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  CheckDump(&irt, 1, 1);
1016c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  EXPECT_TRUE(irt.Remove(cookie, iref2));
10263818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  CheckDump(&irt, 0, 0);
1036c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes
1046c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  // Table should be empty now.
1056c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  EXPECT_EQ(0U, irt.Capacity());
1066c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes
1076c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  // Get invalid entry (off the end of the list).
108c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  EXPECT_TRUE(irt.Get(iref0) == nullptr);
1096c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes
1106c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  // Add three, remove in the opposite order.
11125651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe  iref0 = irt.Add(cookie, obj0.Get(), &error_msg);
112c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  EXPECT_TRUE(iref0 != nullptr);
11325651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe  iref1 = irt.Add(cookie, obj1.Get(), &error_msg);
114c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  EXPECT_TRUE(iref1 != nullptr);
11525651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe  iref2 = irt.Add(cookie, obj2.Get(), &error_msg);
116c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  EXPECT_TRUE(iref2 != nullptr);
11763818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  CheckDump(&irt, 3, 3);
1186c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes
1196c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  ASSERT_TRUE(irt.Remove(cookie, iref2));
12063818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  CheckDump(&irt, 2, 2);
1216c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  ASSERT_TRUE(irt.Remove(cookie, iref1));
12263818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  CheckDump(&irt, 1, 1);
1236c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  ASSERT_TRUE(irt.Remove(cookie, iref0));
12463818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  CheckDump(&irt, 0, 0);
1256c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes
1266c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  // Table should be empty now.
1276c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  ASSERT_EQ(0U, irt.Capacity());
1286c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes
1296c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  // Add three, remove middle / middle / bottom / top.  (Second attempt
1306c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  // to remove middle should fail.)
13125651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe  iref0 = irt.Add(cookie, obj0.Get(), &error_msg);
132c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  EXPECT_TRUE(iref0 != nullptr);
13325651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe  iref1 = irt.Add(cookie, obj1.Get(), &error_msg);
134c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  EXPECT_TRUE(iref1 != nullptr);
13525651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe  iref2 = irt.Add(cookie, obj2.Get(), &error_msg);
136c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  EXPECT_TRUE(iref2 != nullptr);
13763818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  CheckDump(&irt, 3, 3);
1386c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes
1396c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  ASSERT_EQ(3U, irt.Capacity());
1406c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes
1416c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  ASSERT_TRUE(irt.Remove(cookie, iref1));
14263818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  CheckDump(&irt, 2, 2);
1436c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  ASSERT_FALSE(irt.Remove(cookie, iref1));
14463818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  CheckDump(&irt, 2, 2);
1456c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes
1466c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  // Get invalid entry (from hole).
147c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  EXPECT_TRUE(irt.Get(iref1) == nullptr);
1486c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes
1496c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  ASSERT_TRUE(irt.Remove(cookie, iref2));
15063818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  CheckDump(&irt, 1, 1);
1516c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  ASSERT_TRUE(irt.Remove(cookie, iref0));
15263818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  CheckDump(&irt, 0, 0);
1536c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes
1546c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  // Table should be empty now.
1556c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  ASSERT_EQ(0U, irt.Capacity());
1566c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes
1576c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  // Add four entries.  Remove #1, add new entry, verify that table size
1586c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  // is still 4 (i.e. holes are getting filled).  Remove #1 and #3, verify
1596c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  // that we delete one and don't hole-compact the other.
16025651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe  iref0 = irt.Add(cookie, obj0.Get(), &error_msg);
161c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  EXPECT_TRUE(iref0 != nullptr);
16225651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe  iref1 = irt.Add(cookie, obj1.Get(), &error_msg);
163c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  EXPECT_TRUE(iref1 != nullptr);
16425651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe  iref2 = irt.Add(cookie, obj2.Get(), &error_msg);
165c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  EXPECT_TRUE(iref2 != nullptr);
16625651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe  IndirectRef iref3 = irt.Add(cookie, obj3.Get(), &error_msg);
167c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  EXPECT_TRUE(iref3 != nullptr);
16863818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  CheckDump(&irt, 4, 4);
1696c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes
1706c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  ASSERT_TRUE(irt.Remove(cookie, iref1));
17163818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  CheckDump(&irt, 3, 3);
1726c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes
17325651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe  iref1 = irt.Add(cookie, obj1.Get(), &error_msg);
174c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  EXPECT_TRUE(iref1 != nullptr);
1756c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes
1766c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  ASSERT_EQ(4U, irt.Capacity()) << "hole not filled";
17763818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  CheckDump(&irt, 4, 4);
1786c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes
1796c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  ASSERT_TRUE(irt.Remove(cookie, iref1));
18063818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  CheckDump(&irt, 3, 3);
1816c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  ASSERT_TRUE(irt.Remove(cookie, iref3));
18263818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  CheckDump(&irt, 2, 2);
1836c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes
1846c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  ASSERT_EQ(3U, irt.Capacity()) << "should be 3 after two deletions";
1856c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes
1866c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  ASSERT_TRUE(irt.Remove(cookie, iref2));
18763818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  CheckDump(&irt, 1, 1);
1886c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  ASSERT_TRUE(irt.Remove(cookie, iref0));
18963818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  CheckDump(&irt, 0, 0);
1906c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes
1916c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  ASSERT_EQ(0U, irt.Capacity()) << "not empty after split remove";
1926c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes
1936c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  // Add an entry, remove it, add a new entry, and try to use the original
1946c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  // iref.  They have the same slot number but are for different objects.
1956c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  // With the extended checks in place, this should fail.
19625651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe  iref0 = irt.Add(cookie, obj0.Get(), &error_msg);
197c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  EXPECT_TRUE(iref0 != nullptr);
19863818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  CheckDump(&irt, 1, 1);
1996c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  ASSERT_TRUE(irt.Remove(cookie, iref0));
20063818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  CheckDump(&irt, 0, 0);
20125651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe  iref1 = irt.Add(cookie, obj1.Get(), &error_msg);
202c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  EXPECT_TRUE(iref1 != nullptr);
20363818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  CheckDump(&irt, 1, 1);
2046c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  ASSERT_FALSE(irt.Remove(cookie, iref0)) << "mismatched del succeeded";
20563818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  CheckDump(&irt, 1, 1);
2066c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  ASSERT_TRUE(irt.Remove(cookie, iref1)) << "switched del failed";
2076c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  ASSERT_EQ(0U, irt.Capacity()) << "switching del not empty";
20863818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  CheckDump(&irt, 0, 0);
2096c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes
2106c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  // Same as above, but with the same object.  A more rigorous checker
2116c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  // (e.g. with slot serialization) will catch this.
21225651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe  iref0 = irt.Add(cookie, obj0.Get(), &error_msg);
213c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  EXPECT_TRUE(iref0 != nullptr);
21463818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  CheckDump(&irt, 1, 1);
2156c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  ASSERT_TRUE(irt.Remove(cookie, iref0));
21663818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  CheckDump(&irt, 0, 0);
21725651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe  iref1 = irt.Add(cookie, obj0.Get(), &error_msg);
218c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  EXPECT_TRUE(iref1 != nullptr);
21963818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  CheckDump(&irt, 1, 1);
2206c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  if (iref0 != iref1) {
2216c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes    // Try 0, should not work.
2226c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes    ASSERT_FALSE(irt.Remove(cookie, iref0)) << "temporal del succeeded";
2236c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  }
2246c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  ASSERT_TRUE(irt.Remove(cookie, iref1)) << "temporal cleanup failed";
2256c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  ASSERT_EQ(0U, irt.Capacity()) << "temporal del not empty";
22663818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  CheckDump(&irt, 0, 0);
2276c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes
2282cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  // null isn't a valid iref.
229c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  ASSERT_TRUE(irt.Get(nullptr) == nullptr);
2306c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes
2316c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  // Stale lookup.
23225651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe  iref0 = irt.Add(cookie, obj0.Get(), &error_msg);
233c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  EXPECT_TRUE(iref0 != nullptr);
23463818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  CheckDump(&irt, 1, 1);
2356c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  ASSERT_TRUE(irt.Remove(cookie, iref0));
236c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  EXPECT_TRUE(irt.Get(iref0) == nullptr) << "stale lookup succeeded";
23763818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  CheckDump(&irt, 0, 0);
2386c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes
2396c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  // Test table resizing.
2406c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  // These ones fit...
241a8e3b8622565089ff7eb86363a18214b9b2b7da8Andreas Gampe  static const size_t kTableInitial = kTableMax / 2;
2426c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  IndirectRef manyRefs[kTableInitial];
2436c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  for (size_t i = 0; i < kTableInitial; i++) {
24425651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe    manyRefs[i] = irt.Add(cookie, obj0.Get(), &error_msg);
245c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    ASSERT_TRUE(manyRefs[i] != nullptr) << "Failed adding " << i;
24663818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers    CheckDump(&irt, i + 1, 1);
2476c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  }
2486c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  // ...this one causes overflow.
24925651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe  iref0 = irt.Add(cookie, obj0.Get(), &error_msg);
250c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  ASSERT_TRUE(iref0 != nullptr);
2516c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  ASSERT_EQ(kTableInitial + 1, irt.Capacity());
25263818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  CheckDump(&irt, kTableInitial + 1, 1);
2536c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes
2546c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  for (size_t i = 0; i < kTableInitial; i++) {
2556c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes    ASSERT_TRUE(irt.Remove(cookie, manyRefs[i])) << "failed removing " << i;
25663818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers    CheckDump(&irt, kTableInitial - i, 1);
2576c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  }
2586c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  // Because of removal order, should have 11 entries, 10 of them holes.
2596c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  ASSERT_EQ(kTableInitial + 1, irt.Capacity());
2606c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes
2616c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  ASSERT_TRUE(irt.Remove(cookie, iref0)) << "multi-remove final failed";
2626c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes
2636c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  ASSERT_EQ(0U, irt.Capacity()) << "multi-del not empty";
26463818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers  CheckDump(&irt, 0, 0);
2656c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes}
2666c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes
267e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas GampeTEST_F(IndirectReferenceTableTest, Holes) {
268e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe  // Test the explicitly named cases from the IRT implementation:
269e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe  //
270e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe  // 1) Segment with holes (current_num_holes_ > 0), push new segment, add/remove reference
271e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe  // 2) Segment with holes (current_num_holes_ > 0), pop segment, add/remove reference
272e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe  // 3) Segment with holes (current_num_holes_ > 0), push new segment, pop segment, add/remove
273e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe  //    reference
274e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe  // 4) Empty segment, push new segment, create a hole, pop a segment, add/remove a reference
275e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe  // 5) Base segment, push new segment, create a hole, pop a segment, push new segment, add/remove
276e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe  //    reference
277e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
278e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe  ScopedObjectAccess soa(Thread::Current());
279e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe  static const size_t kTableMax = 10;
280e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
281e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe  mirror::Class* c = class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;");
282e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe  StackHandleScope<5> hs(soa.Self());
283e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe  ASSERT_TRUE(c != nullptr);
284e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe  Handle<mirror::Object> obj0 = hs.NewHandle(c->AllocObject(soa.Self()));
285fa4333dcb481e564f54726b4e6f8153612df835eAndreas Gampe  ASSERT_TRUE(obj0 != nullptr);
286e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe  Handle<mirror::Object> obj1 = hs.NewHandle(c->AllocObject(soa.Self()));
287fa4333dcb481e564f54726b4e6f8153612df835eAndreas Gampe  ASSERT_TRUE(obj1 != nullptr);
288e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe  Handle<mirror::Object> obj2 = hs.NewHandle(c->AllocObject(soa.Self()));
289fa4333dcb481e564f54726b4e6f8153612df835eAndreas Gampe  ASSERT_TRUE(obj2 != nullptr);
290e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe  Handle<mirror::Object> obj3 = hs.NewHandle(c->AllocObject(soa.Self()));
291fa4333dcb481e564f54726b4e6f8153612df835eAndreas Gampe  ASSERT_TRUE(obj3 != nullptr);
292e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe  Handle<mirror::Object> obj4 = hs.NewHandle(c->AllocObject(soa.Self()));
293fa4333dcb481e564f54726b4e6f8153612df835eAndreas Gampe  ASSERT_TRUE(obj4 != nullptr);
294e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
295e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe  std::string error_msg;
296e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
297e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe  // 1) Segment with holes (current_num_holes_ > 0), push new segment, add/remove reference.
298e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe  {
2999d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe    IndirectReferenceTable irt(kTableMax,
3009d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe                               kGlobal,
3019d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe                               IndirectReferenceTable::ResizableCapacity::kNo,
3029d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe                               &error_msg);
303e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    ASSERT_TRUE(irt.IsValid()) << error_msg;
304e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
305e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    const IRTSegmentState cookie0 = kIRTFirstSegment;
306e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
307e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    CheckDump(&irt, 0, 0);
308e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
30925651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe    IndirectRef iref0 = irt.Add(cookie0, obj0.Get(), &error_msg);
31025651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe    IndirectRef iref1 = irt.Add(cookie0, obj1.Get(), &error_msg);
31125651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe    IndirectRef iref2 = irt.Add(cookie0, obj2.Get(), &error_msg);
312e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
313e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    EXPECT_TRUE(irt.Remove(cookie0, iref1));
314e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
315e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    // New segment.
316e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    const IRTSegmentState cookie1 = irt.GetSegmentState();
317e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
31825651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe    IndirectRef iref3 = irt.Add(cookie1, obj3.Get(), &error_msg);
319e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
320e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    // Must not have filled the previous hole.
321e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    EXPECT_EQ(irt.Capacity(), 4u);
322e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    EXPECT_TRUE(irt.Get(iref1) == nullptr);
323e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    CheckDump(&irt, 3, 3);
324e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
325e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    UNUSED(iref0, iref1, iref2, iref3);
326e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe  }
327e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
328e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe  // 2) Segment with holes (current_num_holes_ > 0), pop segment, add/remove reference
329e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe  {
3309d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe    IndirectReferenceTable irt(kTableMax,
3319d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe                               kGlobal,
3329d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe                               IndirectReferenceTable::ResizableCapacity::kNo,
3339d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe                               &error_msg);
334e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    ASSERT_TRUE(irt.IsValid()) << error_msg;
335e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
336e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    const IRTSegmentState cookie0 = kIRTFirstSegment;
337e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
338e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    CheckDump(&irt, 0, 0);
339e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
34025651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe    IndirectRef iref0 = irt.Add(cookie0, obj0.Get(), &error_msg);
341e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
342e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    // New segment.
343e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    const IRTSegmentState cookie1 = irt.GetSegmentState();
344e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
34525651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe    IndirectRef iref1 = irt.Add(cookie1, obj1.Get(), &error_msg);
34625651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe    IndirectRef iref2 = irt.Add(cookie1, obj2.Get(), &error_msg);
34725651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe    IndirectRef iref3 = irt.Add(cookie1, obj3.Get(), &error_msg);
348e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
349e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    EXPECT_TRUE(irt.Remove(cookie1, iref2));
350e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
351e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    // Pop segment.
352e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    irt.SetSegmentState(cookie1);
353e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
35425651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe    IndirectRef iref4 = irt.Add(cookie1, obj4.Get(), &error_msg);
355e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
356e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    EXPECT_EQ(irt.Capacity(), 2u);
357e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    EXPECT_TRUE(irt.Get(iref2) == nullptr);
358e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    CheckDump(&irt, 2, 2);
359e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
360e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    UNUSED(iref0, iref1, iref2, iref3, iref4);
361e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe  }
362e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
363e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe  // 3) Segment with holes (current_num_holes_ > 0), push new segment, pop segment, add/remove
364e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe  //    reference.
365e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe  {
3669d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe    IndirectReferenceTable irt(kTableMax,
3679d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe                               kGlobal,
3689d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe                               IndirectReferenceTable::ResizableCapacity::kNo,
3699d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe                               &error_msg);
370e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    ASSERT_TRUE(irt.IsValid()) << error_msg;
371e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
372e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    const IRTSegmentState cookie0 = kIRTFirstSegment;
373e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
374e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    CheckDump(&irt, 0, 0);
375e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
37625651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe    IndirectRef iref0 = irt.Add(cookie0, obj0.Get(), &error_msg);
377e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
378e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    // New segment.
379e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    const IRTSegmentState cookie1 = irt.GetSegmentState();
380e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
38125651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe    IndirectRef iref1 = irt.Add(cookie1, obj1.Get(), &error_msg);
38225651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe    IndirectRef iref2 = irt.Add(cookie1, obj2.Get(), &error_msg);
383e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
384e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    EXPECT_TRUE(irt.Remove(cookie1, iref1));
385e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
386e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    // New segment.
387e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    const IRTSegmentState cookie2 = irt.GetSegmentState();
388e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
38925651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe    IndirectRef iref3 = irt.Add(cookie2, obj3.Get(), &error_msg);
390e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
391e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    // Pop segment.
392e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    irt.SetSegmentState(cookie2);
393e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
39425651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe    IndirectRef iref4 = irt.Add(cookie1, obj4.Get(), &error_msg);
395e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
396e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    EXPECT_EQ(irt.Capacity(), 3u);
397e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    EXPECT_TRUE(irt.Get(iref1) == nullptr);
398e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    CheckDump(&irt, 3, 3);
399e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
400e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    UNUSED(iref0, iref1, iref2, iref3, iref4);
401e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe  }
402e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
403e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe  // 4) Empty segment, push new segment, create a hole, pop a segment, add/remove a reference.
404e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe  {
4059d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe    IndirectReferenceTable irt(kTableMax,
4069d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe                               kGlobal,
4079d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe                               IndirectReferenceTable::ResizableCapacity::kNo,
4089d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe                               &error_msg);
409e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    ASSERT_TRUE(irt.IsValid()) << error_msg;
410e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
411e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    const IRTSegmentState cookie0 = kIRTFirstSegment;
412e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
413e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    CheckDump(&irt, 0, 0);
414e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
41525651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe    IndirectRef iref0 = irt.Add(cookie0, obj0.Get(), &error_msg);
416e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
417e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    // New segment.
418e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    const IRTSegmentState cookie1 = irt.GetSegmentState();
419e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
42025651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe    IndirectRef iref1 = irt.Add(cookie1, obj1.Get(), &error_msg);
421e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    EXPECT_TRUE(irt.Remove(cookie1, iref1));
422e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
423e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    // Emptied segment, push new one.
424e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    const IRTSegmentState cookie2 = irt.GetSegmentState();
425e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
42625651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe    IndirectRef iref2 = irt.Add(cookie1, obj1.Get(), &error_msg);
42725651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe    IndirectRef iref3 = irt.Add(cookie1, obj2.Get(), &error_msg);
42825651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe    IndirectRef iref4 = irt.Add(cookie1, obj3.Get(), &error_msg);
429e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
430e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    EXPECT_TRUE(irt.Remove(cookie1, iref3));
431e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
432e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    // Pop segment.
433e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    UNUSED(cookie2);
434e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    irt.SetSegmentState(cookie1);
435e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
43625651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe    IndirectRef iref5 = irt.Add(cookie1, obj4.Get(), &error_msg);
437e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
438e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    EXPECT_EQ(irt.Capacity(), 2u);
439e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    EXPECT_TRUE(irt.Get(iref3) == nullptr);
440e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    CheckDump(&irt, 2, 2);
441e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
442e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    UNUSED(iref0, iref1, iref2, iref3, iref4, iref5);
443e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe  }
444e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
445e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe  // 5) Base segment, push new segment, create a hole, pop a segment, push new segment, add/remove
446e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe  //    reference
447e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe  {
4489d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe    IndirectReferenceTable irt(kTableMax,
4499d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe                               kGlobal,
4509d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe                               IndirectReferenceTable::ResizableCapacity::kNo,
4519d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe                               &error_msg);
452e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    ASSERT_TRUE(irt.IsValid()) << error_msg;
453e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
454e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    const IRTSegmentState cookie0 = kIRTFirstSegment;
455e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
456e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    CheckDump(&irt, 0, 0);
457e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
45825651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe    IndirectRef iref0 = irt.Add(cookie0, obj0.Get(), &error_msg);
459e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
460e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    // New segment.
461e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    const IRTSegmentState cookie1 = irt.GetSegmentState();
462e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
46325651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe    IndirectRef iref1 = irt.Add(cookie1, obj1.Get(), &error_msg);
46425651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe    IndirectRef iref2 = irt.Add(cookie1, obj1.Get(), &error_msg);
46525651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe    IndirectRef iref3 = irt.Add(cookie1, obj2.Get(), &error_msg);
466e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
467e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    EXPECT_TRUE(irt.Remove(cookie1, iref2));
468e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
469e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    // Pop segment.
470e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    irt.SetSegmentState(cookie1);
471e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
472e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    // Push segment.
473e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    const IRTSegmentState cookie1_second = irt.GetSegmentState();
474e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    UNUSED(cookie1_second);
475e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
47625651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe    IndirectRef iref4 = irt.Add(cookie1, obj3.Get(), &error_msg);
477e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
478e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    EXPECT_EQ(irt.Capacity(), 2u);
479e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    EXPECT_TRUE(irt.Get(iref3) == nullptr);
480e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    CheckDump(&irt, 2, 2);
481e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
482e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe    UNUSED(iref0, iref1, iref2, iref3, iref4);
483e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe  }
484e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe}
485e03662b71bbb4d262af0840bf90ce4fc84750b43Andreas Gampe
4869d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas GampeTEST_F(IndirectReferenceTableTest, Resize) {
4879d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe  ScopedObjectAccess soa(Thread::Current());
4889d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe  static const size_t kTableMax = 512;
4899d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe
4909d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe  mirror::Class* c = class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;");
4919d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe  StackHandleScope<1> hs(soa.Self());
4929d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe  ASSERT_TRUE(c != nullptr);
4939d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe  Handle<mirror::Object> obj0 = hs.NewHandle(c->AllocObject(soa.Self()));
494fa4333dcb481e564f54726b4e6f8153612df835eAndreas Gampe  ASSERT_TRUE(obj0 != nullptr);
4959d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe
4969d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe  std::string error_msg;
4979d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe  IndirectReferenceTable irt(kTableMax,
4989d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe                             kLocal,
4999d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe                             IndirectReferenceTable::ResizableCapacity::kYes,
5009d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe                             &error_msg);
5019d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe  ASSERT_TRUE(irt.IsValid()) << error_msg;
5029d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe
5039d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe  CheckDump(&irt, 0, 0);
5049d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe  const IRTSegmentState cookie = kIRTFirstSegment;
5059d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe
5069d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe  for (size_t i = 0; i != kTableMax + 1; ++i) {
50725651129552c3e9a8c87c68852da43c6069d7a53Andreas Gampe    irt.Add(cookie, obj0.Get(), &error_msg);
5089d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe  }
5099d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe
5109d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe  EXPECT_EQ(irt.Capacity(), kTableMax + 1);
5119d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe}
5129d7ef62b854289632791a83223c1a5a5b3c8fc64Andreas Gampe
5136c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes}  // namespace art
514