indirect_reference_table.cc revision 94f7b49578b6aaa80de8ffed230648d601393905
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" 18c56057e40938c587a74984651a510e320a8cb4fdMathieu Chartier 19a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#include "jni_internal.h" 206c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes#include "reference_table.h" 21a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#include "runtime.h" 2200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#include "scoped_thread_state_change.h" 235a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers#include "thread.h" 24cdd1d2d3fee0711b8b11db99f2dfb80113520100Ian Rogers#include "utils.h" 256dda898d47b3e8931e4404330e81b7110108e34fMathieu Chartier#include "verify_object-inl.h" 266c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 276c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes#include <cstdlib> 286c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 296c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughesnamespace art { 306c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 31719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogerstemplate<typename T> 32719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogersclass MutatorLockedDumpable { 33719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers public: 34719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers explicit MutatorLockedDumpable(T& value) 35719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : value_(value) { 36719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers } 37719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers 38719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers void Dump(std::ostream& os) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 39719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers value_.Dump(os); 40719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers } 41719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers 42719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers private: 43719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers T& value_; 44719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers 45719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers DISALLOW_COPY_AND_ASSIGN(MutatorLockedDumpable); 46719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers}; 47719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers 48719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogerstemplate<typename T> 49719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogersstd::ostream& operator<<(std::ostream& os, const MutatorLockedDumpable<T>& rhs) 50719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers// TODO: should be SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) however annotalysis 51719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers// currently fails for this. 52719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers NO_THREAD_SAFETY_ANALYSIS { 53719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers rhs.Dump(os); 54719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers return os; 55719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers} 56719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers 57c56057e40938c587a74984651a510e320a8cb4fdMathieu Chartiervoid IndirectReferenceTable::AbortIfNoCheckJNI() { 58a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes // If -Xcheck:jni is on, it'll give a more detailed error before aborting. 59a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes if (!Runtime::Current()->GetJavaVM()->check_jni) { 60a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes // Otherwise, we want to abort rather than hand back a bad reference. 61a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes LOG(FATAL) << "JNI ERROR (app bug): see above."; 62a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 636c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes} 646c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 656c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott HughesIndirectReferenceTable::IndirectReferenceTable(size_t initialCount, 66ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes size_t maxCount, IndirectRefKind desiredKind) { 676c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes CHECK_GT(initialCount, 0U); 686c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes CHECK_LE(initialCount, maxCount); 69eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier CHECK_NE(desiredKind, kHandleScopeOrInvalid); 706c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 71c56057e40938c587a74984651a510e320a8cb4fdMathieu Chartier std::string error_str; 72c56057e40938c587a74984651a510e320a8cb4fdMathieu Chartier const size_t initial_bytes = initialCount * sizeof(const mirror::Object*); 73c56057e40938c587a74984651a510e320a8cb4fdMathieu Chartier const size_t table_bytes = maxCount * sizeof(const mirror::Object*); 74c56057e40938c587a74984651a510e320a8cb4fdMathieu Chartier table_mem_map_.reset(MemMap::MapAnonymous("indirect ref table", nullptr, table_bytes, 75c56057e40938c587a74984651a510e320a8cb4fdMathieu Chartier PROT_READ | PROT_WRITE, false, &error_str)); 76c56057e40938c587a74984651a510e320a8cb4fdMathieu Chartier CHECK(table_mem_map_.get() != nullptr) << error_str; 77a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light CHECK_EQ(table_mem_map_->Size(), table_bytes); 78c56057e40938c587a74984651a510e320a8cb4fdMathieu Chartier 7994f7b49578b6aaa80de8ffed230648d601393905Hiroshi Yamauchi table_ = reinterpret_cast<GcRoot<mirror::Object>*>(table_mem_map_->Begin()); 80c56057e40938c587a74984651a510e320a8cb4fdMathieu Chartier CHECK(table_ != nullptr); 81c56057e40938c587a74984651a510e320a8cb4fdMathieu Chartier memset(table_, 0xd1, initial_bytes); 826c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 83c56057e40938c587a74984651a510e320a8cb4fdMathieu Chartier const size_t slot_bytes = maxCount * sizeof(IndirectRefSlot); 84c56057e40938c587a74984651a510e320a8cb4fdMathieu Chartier slot_mem_map_.reset(MemMap::MapAnonymous("indirect ref table slots", nullptr, slot_bytes, 85c56057e40938c587a74984651a510e320a8cb4fdMathieu Chartier PROT_READ | PROT_WRITE, false, &error_str)); 86c56057e40938c587a74984651a510e320a8cb4fdMathieu Chartier CHECK(slot_mem_map_.get() != nullptr) << error_str; 87c56057e40938c587a74984651a510e320a8cb4fdMathieu Chartier slot_data_ = reinterpret_cast<IndirectRefSlot*>(slot_mem_map_->Begin()); 88c56057e40938c587a74984651a510e320a8cb4fdMathieu Chartier CHECK(slot_data_ != nullptr); 896c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 90dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers segment_state_.all = IRT_FIRST_SEGMENT; 916c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes alloc_entries_ = initialCount; 926c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes max_entries_ = maxCount; 936c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes kind_ = desiredKind; 946c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes} 956c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 966c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott HughesIndirectReferenceTable::~IndirectReferenceTable() { 976c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes} 986c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 99423d2a3dcbb260b020efb5da59f784c9f02accbfMathieu ChartierIndirectRef IndirectReferenceTable::Add(uint32_t cookie, mirror::Object* obj) { 1006c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes IRTSegmentState prevState; 1016c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes prevState.all = cookie; 102dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers size_t topIndex = segment_state_.parts.topIndex; 1036c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 104cd2cfff09c916c9e72a7cfeb0686b441847dc62eMathieu Chartier CHECK(obj != NULL); 1056dda898d47b3e8931e4404330e81b7110108e34fMathieu Chartier VerifyObject(obj); 1066c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes DCHECK(table_ != NULL); 1076c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes DCHECK_LE(alloc_entries_, max_entries_); 108dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers DCHECK_GE(segment_state_.parts.numHoles, prevState.parts.numHoles); 1096c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 1106c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes if (topIndex == alloc_entries_) { 11173e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes // reached end of allocated space; did we hit buffer max? 1126c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes if (topIndex == max_entries_) { 11373e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes LOG(FATAL) << "JNI ERROR (app bug): " << kind_ << " table overflow " 11473e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes << "(max=" << max_entries_ << ")\n" 11500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers << MutatorLockedDumpable<IndirectReferenceTable>(*this); 1166c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 1176c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 1186c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes size_t newSize = alloc_entries_ * 2; 1196c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes if (newSize > max_entries_) { 1206c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes newSize = max_entries_; 1216c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 1226c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes DCHECK_GT(newSize, alloc_entries_); 1236c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 1246c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes alloc_entries_ = newSize; 1256c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 1266c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 12773e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes // We know there's enough room in the table. Now we just need to find 12873e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes // the right spot. If there's a hole, find it and fill it; otherwise, 12973e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes // add to the end of the list. 1306c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes IndirectRef result; 131dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers int numHoles = segment_state_.parts.numHoles - prevState.parts.numHoles; 1326c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes if (numHoles > 0) { 1336c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes DCHECK_GT(topIndex, 1U); 13473e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes // Find the first hole; likely to be near the end of the list. 13594f7b49578b6aaa80de8ffed230648d601393905Hiroshi Yamauchi GcRoot<mirror::Object>* pScan = &table_[topIndex - 1]; 13694f7b49578b6aaa80de8ffed230648d601393905Hiroshi Yamauchi DCHECK(!pScan->IsNull()); 13794f7b49578b6aaa80de8ffed230648d601393905Hiroshi Yamauchi --pScan; 13894f7b49578b6aaa80de8ffed230648d601393905Hiroshi Yamauchi while (!pScan->IsNull()) { 1396c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes DCHECK_GE(pScan, table_ + prevState.parts.topIndex); 14094f7b49578b6aaa80de8ffed230648d601393905Hiroshi Yamauchi --pScan; 1416c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 1426c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes UpdateSlotAdd(obj, pScan - table_); 143ea2e1bd713ca8295ba4fcd01e77a3ce532ea61e4Hiroshi Yamauchi result = ToIndirectRef(pScan - table_); 14494f7b49578b6aaa80de8ffed230648d601393905Hiroshi Yamauchi *pScan = GcRoot<mirror::Object>(obj); 145dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers segment_state_.parts.numHoles--; 1466c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } else { 14773e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes // Add to the end. 1486c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes UpdateSlotAdd(obj, topIndex); 149ea2e1bd713ca8295ba4fcd01e77a3ce532ea61e4Hiroshi Yamauchi result = ToIndirectRef(topIndex); 15094f7b49578b6aaa80de8ffed230648d601393905Hiroshi Yamauchi table_[topIndex++] = GcRoot<mirror::Object>(obj); 151dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers segment_state_.parts.topIndex = topIndex; 1526c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 1535a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers if (false) { 1545a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers LOG(INFO) << "+++ added at " << ExtractIndex(result) << " top=" << segment_state_.parts.topIndex 1555a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers << " holes=" << segment_state_.parts.numHoles; 1565a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers } 1576c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 1586c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes DCHECK(result != NULL); 1596c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes return result; 1606c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes} 1616c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 162726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughesvoid IndirectReferenceTable::AssertEmpty() { 16300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers if (UNLIKELY(begin() != end())) { 16400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccess soa(Thread::Current()); 16573e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes LOG(FATAL) << "Internal Error: non-empty local reference table\n" 16600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers << MutatorLockedDumpable<IndirectReferenceTable>(*this); 167726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes } 168726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes} 169726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes 17073e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes// Removes an object. We extract the table offset bits from "iref" 17173e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes// and zap the corresponding entry, leaving a hole if it's not at the top. 17273e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes// If the entry is not between the current top index and the bottom index 17373e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes// specified by the cookie, we don't remove anything. This is the behavior 17473e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes// required by JNI's DeleteLocalRef function. 17573e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes// This method is not called when a local frame is popped; this is only used 17673e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes// for explicit single removals. 17773e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes// Returns "false" if nothing was removed. 1786c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughesbool IndirectReferenceTable::Remove(uint32_t cookie, IndirectRef iref) { 1796c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes IRTSegmentState prevState; 1806c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes prevState.all = cookie; 181dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers int topIndex = segment_state_.parts.topIndex; 1826c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes int bottomIndex = prevState.parts.topIndex; 1836c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 1846c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes DCHECK(table_ != NULL); 1856c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes DCHECK_LE(alloc_entries_, max_entries_); 186dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers DCHECK_GE(segment_state_.parts.numHoles, prevState.parts.numHoles); 1876c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 1886c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes int idx = ExtractIndex(iref); 1896c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 190eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier if (GetIndirectRefKind(iref) == kHandleScopeOrInvalid && 191eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Thread::Current()->HandleScopeContains(reinterpret_cast<jobject>(iref))) { 192eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier LOG(WARNING) << "Attempt to remove local handle scope entry from IRT, ignoring"; 1935a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers return true; 1945a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers } 1956c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 1966c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes if (idx < bottomIndex) { 197726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes // Wrong segment. 198726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes LOG(WARNING) << "Attempt to remove index outside index area (" << idx 199726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes << " vs " << bottomIndex << "-" << topIndex << ")"; 2006c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes return false; 2016c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 2026c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes if (idx >= topIndex) { 203726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes // Bad --- stale reference? 204726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes LOG(WARNING) << "Attempt to remove invalid index " << idx 205726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes << " (bottom=" << bottomIndex << " top=" << topIndex << ")"; 2066c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes return false; 2076c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 2086c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 2096c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes if (idx == topIndex-1) { 2106c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes // Top-most entry. Scan up and consume holes. 2116c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 212987560fee798e48fb725c44b796d8ca7a5872ad6Ian Rogers if (!CheckEntry("remove", iref, idx)) { 2136c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes return false; 2146c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 2156c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 21694f7b49578b6aaa80de8ffed230648d601393905Hiroshi Yamauchi table_[idx] = GcRoot<mirror::Object>(nullptr); 217dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers int numHoles = segment_state_.parts.numHoles - prevState.parts.numHoles; 2186c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes if (numHoles != 0) { 2196c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes while (--topIndex > bottomIndex && numHoles != 0) { 2205a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers if (false) { 2215a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers LOG(INFO) << "+++ checking for hole at " << topIndex-1 22294f7b49578b6aaa80de8ffed230648d601393905Hiroshi Yamauchi << " (cookie=" << cookie << ") val=" 22394f7b49578b6aaa80de8ffed230648d601393905Hiroshi Yamauchi << table_[topIndex - 1].Read<kWithoutReadBarrier>(); 2245a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers } 22594f7b49578b6aaa80de8ffed230648d601393905Hiroshi Yamauchi if (!table_[topIndex-1].IsNull()) { 2266c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes break; 2276c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 2285a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers if (false) { 2295a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers LOG(INFO) << "+++ ate hole at " << (topIndex - 1); 2305a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers } 2316c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes numHoles--; 2326c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 233dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers segment_state_.parts.numHoles = numHoles + prevState.parts.numHoles; 234dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers segment_state_.parts.topIndex = topIndex; 2356c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } else { 236dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers segment_state_.parts.topIndex = topIndex-1; 2375a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers if (false) { 2385a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers LOG(INFO) << "+++ ate last entry " << topIndex - 1; 2395a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers } 2406c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 2416c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } else { 24273e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes // Not the top-most entry. This creates a hole. We NULL out the 24373e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes // entry to prevent somebody from deleting it twice and screwing up 24473e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes // the hole count. 24594f7b49578b6aaa80de8ffed230648d601393905Hiroshi Yamauchi if (table_[idx].IsNull()) { 2466c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes LOG(INFO) << "--- WEIRD: removing null entry " << idx; 2476c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes return false; 2486c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 249987560fee798e48fb725c44b796d8ca7a5872ad6Ian Rogers if (!CheckEntry("remove", iref, idx)) { 2506c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes return false; 2516c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 2526c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 25394f7b49578b6aaa80de8ffed230648d601393905Hiroshi Yamauchi table_[idx] = GcRoot<mirror::Object>(nullptr); 254dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers segment_state_.parts.numHoles++; 2555a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers if (false) { 2565a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers LOG(INFO) << "+++ left hole at " << idx << ", holes=" << segment_state_.parts.numHoles; 2575a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers } 2586c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 2596c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 2606c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes return true; 2616c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes} 2626c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 26383c8ee000d525017ead8753fce6bc1020249b96aMathieu Chartiervoid IndirectReferenceTable::VisitRoots(RootCallback* callback, void* arg, uint32_t tid, 26483c8ee000d525017ead8753fce6bc1020249b96aMathieu Chartier RootType root_type) { 26502e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier for (auto ref : *this) { 266815873ecc312b1d231acce71e1a16f42cdaf09f2Mathieu Chartier callback(ref, arg, tid, root_type); 267423d2a3dcbb260b020efb5da59f784c9f02accbfMathieu Chartier DCHECK(*ref != nullptr); 268410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes } 269410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes} 270410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes 27173e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughesvoid IndirectReferenceTable::Dump(std::ostream& os) const { 27273e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes os << kind_ << " table dump:\n"; 273196851b634a5bfdd8ab3fb59a320e550b21b0f4dHiroshi Yamauchi ReferenceTable::Table entries; 274196851b634a5bfdd8ab3fb59a320e550b21b0f4dHiroshi Yamauchi for (size_t i = 0; i < Capacity(); ++i) { 27594f7b49578b6aaa80de8ffed230648d601393905Hiroshi Yamauchi mirror::Object* obj = table_[i].Read<kWithoutReadBarrier>(); 276196851b634a5bfdd8ab3fb59a320e550b21b0f4dHiroshi Yamauchi if (UNLIKELY(obj == nullptr)) { 277196851b634a5bfdd8ab3fb59a320e550b21b0f4dHiroshi Yamauchi // Remove NULLs. 278196851b634a5bfdd8ab3fb59a320e550b21b0f4dHiroshi Yamauchi } else if (UNLIKELY(obj == kClearedJniWeakGlobal)) { 279196851b634a5bfdd8ab3fb59a320e550b21b0f4dHiroshi Yamauchi // ReferenceTable::Dump() will handle kClearedJniWeakGlobal 280196851b634a5bfdd8ab3fb59a320e550b21b0f4dHiroshi Yamauchi // while the read barrier won't. 28194f7b49578b6aaa80de8ffed230648d601393905Hiroshi Yamauchi entries.push_back(GcRoot<mirror::Object>(obj)); 282196851b634a5bfdd8ab3fb59a320e550b21b0f4dHiroshi Yamauchi } else { 28394f7b49578b6aaa80de8ffed230648d601393905Hiroshi Yamauchi obj = table_[i].Read(); 28494f7b49578b6aaa80de8ffed230648d601393905Hiroshi Yamauchi entries.push_back(GcRoot<mirror::Object>(obj)); 28563818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers } 28663818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers } 28773e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes ReferenceTable::Dump(os, entries); 2886c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes} 2896c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 2906c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes} // namespace art 291