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, 66a1de6b93426cfc66a64eb1b57303348aab5e766dMathieu Chartier size_t maxCount, IndirectRefKind desiredKind) 67a1de6b93426cfc66a64eb1b57303348aab5e766dMathieu Chartier : kind_(desiredKind), 68a1de6b93426cfc66a64eb1b57303348aab5e766dMathieu Chartier max_entries_(maxCount) { 696c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes CHECK_GT(initialCount, 0U); 706c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes CHECK_LE(initialCount, maxCount); 71eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier CHECK_NE(desiredKind, kHandleScopeOrInvalid); 726c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 73c56057e40938c587a74984651a510e320a8cb4fdMathieu Chartier std::string error_str; 74a1de6b93426cfc66a64eb1b57303348aab5e766dMathieu Chartier const size_t table_bytes = maxCount * sizeof(IrtEntry); 75c56057e40938c587a74984651a510e320a8cb4fdMathieu Chartier table_mem_map_.reset(MemMap::MapAnonymous("indirect ref table", nullptr, table_bytes, 76c56057e40938c587a74984651a510e320a8cb4fdMathieu Chartier PROT_READ | PROT_WRITE, false, &error_str)); 77c56057e40938c587a74984651a510e320a8cb4fdMathieu Chartier CHECK(table_mem_map_.get() != nullptr) << error_str; 78a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light CHECK_EQ(table_mem_map_->Size(), table_bytes); 79a1de6b93426cfc66a64eb1b57303348aab5e766dMathieu Chartier table_ = reinterpret_cast<IrtEntry*>(table_mem_map_->Begin()); 80c56057e40938c587a74984651a510e320a8cb4fdMathieu Chartier CHECK(table_ != nullptr); 81dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers segment_state_.all = IRT_FIRST_SEGMENT; 826c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes} 836c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 846c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott HughesIndirectReferenceTable::~IndirectReferenceTable() { 856c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes} 866c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 87423d2a3dcbb260b020efb5da59f784c9f02accbfMathieu ChartierIndirectRef IndirectReferenceTable::Add(uint32_t cookie, mirror::Object* obj) { 886c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes IRTSegmentState prevState; 896c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes prevState.all = cookie; 90dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers size_t topIndex = segment_state_.parts.topIndex; 916c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 92cd2cfff09c916c9e72a7cfeb0686b441847dc62eMathieu Chartier CHECK(obj != NULL); 936dda898d47b3e8931e4404330e81b7110108e34fMathieu Chartier VerifyObject(obj); 946c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes DCHECK(table_ != NULL); 95dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers DCHECK_GE(segment_state_.parts.numHoles, prevState.parts.numHoles); 966c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 97a1de6b93426cfc66a64eb1b57303348aab5e766dMathieu Chartier if (topIndex == max_entries_) { 98a1de6b93426cfc66a64eb1b57303348aab5e766dMathieu Chartier LOG(FATAL) << "JNI ERROR (app bug): " << kind_ << " table overflow " 99a1de6b93426cfc66a64eb1b57303348aab5e766dMathieu Chartier << "(max=" << max_entries_ << ")\n" 100a1de6b93426cfc66a64eb1b57303348aab5e766dMathieu Chartier << MutatorLockedDumpable<IndirectReferenceTable>(*this); 1016c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 1026c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 10373e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes // We know there's enough room in the table. Now we just need to find 10473e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes // the right spot. If there's a hole, find it and fill it; otherwise, 10573e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes // add to the end of the list. 1066c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes IndirectRef result; 107dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers int numHoles = segment_state_.parts.numHoles - prevState.parts.numHoles; 108a1de6b93426cfc66a64eb1b57303348aab5e766dMathieu Chartier size_t index; 1096c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes if (numHoles > 0) { 1106c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes DCHECK_GT(topIndex, 1U); 11173e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes // Find the first hole; likely to be near the end of the list. 112a1de6b93426cfc66a64eb1b57303348aab5e766dMathieu Chartier IrtEntry* pScan = &table_[topIndex - 1]; 113a1de6b93426cfc66a64eb1b57303348aab5e766dMathieu Chartier DCHECK(!pScan->GetReference()->IsNull()); 11494f7b49578b6aaa80de8ffed230648d601393905Hiroshi Yamauchi --pScan; 115a1de6b93426cfc66a64eb1b57303348aab5e766dMathieu Chartier while (!pScan->GetReference()->IsNull()) { 1166c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes DCHECK_GE(pScan, table_ + prevState.parts.topIndex); 11794f7b49578b6aaa80de8ffed230648d601393905Hiroshi Yamauchi --pScan; 1186c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 119a1de6b93426cfc66a64eb1b57303348aab5e766dMathieu Chartier index = pScan - table_; 120dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers segment_state_.parts.numHoles--; 1216c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } else { 12273e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes // Add to the end. 123a1de6b93426cfc66a64eb1b57303348aab5e766dMathieu Chartier index = topIndex++; 124dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers segment_state_.parts.topIndex = topIndex; 1256c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 126a1de6b93426cfc66a64eb1b57303348aab5e766dMathieu Chartier table_[index].Add(obj); 127a1de6b93426cfc66a64eb1b57303348aab5e766dMathieu Chartier result = ToIndirectRef(index); 1285a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers if (false) { 1295a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers LOG(INFO) << "+++ added at " << ExtractIndex(result) << " top=" << segment_state_.parts.topIndex 1305a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers << " holes=" << segment_state_.parts.numHoles; 1315a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers } 1326c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 1336c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes DCHECK(result != NULL); 1346c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes return result; 1356c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes} 1366c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 137726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughesvoid IndirectReferenceTable::AssertEmpty() { 13800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers if (UNLIKELY(begin() != end())) { 13900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccess soa(Thread::Current()); 14073e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes LOG(FATAL) << "Internal Error: non-empty local reference table\n" 14100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers << MutatorLockedDumpable<IndirectReferenceTable>(*this); 142726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes } 143726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes} 144726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes 14573e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes// Removes an object. We extract the table offset bits from "iref" 14673e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes// and zap the corresponding entry, leaving a hole if it's not at the top. 14773e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes// If the entry is not between the current top index and the bottom index 14873e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes// specified by the cookie, we don't remove anything. This is the behavior 14973e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes// required by JNI's DeleteLocalRef function. 15073e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes// This method is not called when a local frame is popped; this is only used 15173e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes// for explicit single removals. 15273e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes// Returns "false" if nothing was removed. 1536c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughesbool IndirectReferenceTable::Remove(uint32_t cookie, IndirectRef iref) { 1546c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes IRTSegmentState prevState; 1556c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes prevState.all = cookie; 156dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers int topIndex = segment_state_.parts.topIndex; 1576c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes int bottomIndex = prevState.parts.topIndex; 1586c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 1596c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes DCHECK(table_ != NULL); 160dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers DCHECK_GE(segment_state_.parts.numHoles, prevState.parts.numHoles); 1616c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 162eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier if (GetIndirectRefKind(iref) == kHandleScopeOrInvalid && 163eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Thread::Current()->HandleScopeContains(reinterpret_cast<jobject>(iref))) { 164eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier LOG(WARNING) << "Attempt to remove local handle scope entry from IRT, ignoring"; 1655a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers return true; 1665a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers } 16784dc99d2fa67e5dff018685661cb2bff62132989Mathieu Chartier const int idx = ExtractIndex(iref); 1686c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes if (idx < bottomIndex) { 169726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes // Wrong segment. 170726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes LOG(WARNING) << "Attempt to remove index outside index area (" << idx 171726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes << " vs " << bottomIndex << "-" << topIndex << ")"; 1726c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes return false; 1736c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 1746c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes if (idx >= topIndex) { 175726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes // Bad --- stale reference? 176726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes LOG(WARNING) << "Attempt to remove invalid index " << idx 177726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes << " (bottom=" << bottomIndex << " top=" << topIndex << ")"; 1786c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes return false; 1796c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 1806c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 181a1de6b93426cfc66a64eb1b57303348aab5e766dMathieu Chartier if (idx == topIndex - 1) { 1826c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes // Top-most entry. Scan up and consume holes. 1836c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 184987560fee798e48fb725c44b796d8ca7a5872ad6Ian Rogers if (!CheckEntry("remove", iref, idx)) { 1856c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes return false; 1866c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 1876c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 188a1de6b93426cfc66a64eb1b57303348aab5e766dMathieu Chartier *table_[idx].GetReference() = GcRoot<mirror::Object>(nullptr); 189dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers int numHoles = segment_state_.parts.numHoles - prevState.parts.numHoles; 1906c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes if (numHoles != 0) { 1916c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes while (--topIndex > bottomIndex && numHoles != 0) { 1925a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers if (false) { 193a1de6b93426cfc66a64eb1b57303348aab5e766dMathieu Chartier LOG(INFO) << "+++ checking for hole at " << topIndex - 1 19494f7b49578b6aaa80de8ffed230648d601393905Hiroshi Yamauchi << " (cookie=" << cookie << ") val=" 195a1de6b93426cfc66a64eb1b57303348aab5e766dMathieu Chartier << table_[topIndex - 1].GetReference()->Read<kWithoutReadBarrier>(); 1965a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers } 197a1de6b93426cfc66a64eb1b57303348aab5e766dMathieu Chartier if (!table_[topIndex - 1].GetReference()->IsNull()) { 1986c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes break; 1996c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 2005a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers if (false) { 2015a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers LOG(INFO) << "+++ ate hole at " << (topIndex - 1); 2025a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers } 2036c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes numHoles--; 2046c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 205dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers segment_state_.parts.numHoles = numHoles + prevState.parts.numHoles; 206dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers segment_state_.parts.topIndex = topIndex; 2076c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } else { 208dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers segment_state_.parts.topIndex = topIndex-1; 2095a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers if (false) { 2105a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers LOG(INFO) << "+++ ate last entry " << topIndex - 1; 2115a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers } 2126c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 2136c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } else { 21473e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes // Not the top-most entry. This creates a hole. We NULL out the 21573e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes // entry to prevent somebody from deleting it twice and screwing up 21673e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes // the hole count. 217a1de6b93426cfc66a64eb1b57303348aab5e766dMathieu Chartier if (table_[idx].GetReference()->IsNull()) { 2186c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes LOG(INFO) << "--- WEIRD: removing null entry " << idx; 2196c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes return false; 2206c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 221987560fee798e48fb725c44b796d8ca7a5872ad6Ian Rogers if (!CheckEntry("remove", iref, idx)) { 2226c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes return false; 2236c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 2246c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 225a1de6b93426cfc66a64eb1b57303348aab5e766dMathieu Chartier *table_[idx].GetReference() = GcRoot<mirror::Object>(nullptr); 226dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers segment_state_.parts.numHoles++; 2275a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers if (false) { 2285a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers LOG(INFO) << "+++ left hole at " << idx << ", holes=" << segment_state_.parts.numHoles; 2295a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers } 2306c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 2316c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 2326c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes return true; 2336c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes} 2346c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 23584dc99d2fa67e5dff018685661cb2bff62132989Mathieu Chartiervoid IndirectReferenceTable::Trim() { 23684dc99d2fa67e5dff018685661cb2bff62132989Mathieu Chartier const size_t top_index = Capacity(); 23784dc99d2fa67e5dff018685661cb2bff62132989Mathieu Chartier auto* release_start = AlignUp(reinterpret_cast<uint8_t*>(&table_[top_index]), kPageSize); 23884dc99d2fa67e5dff018685661cb2bff62132989Mathieu Chartier uint8_t* release_end = table_mem_map_->End(); 23984dc99d2fa67e5dff018685661cb2bff62132989Mathieu Chartier madvise(release_start, release_end - release_start, MADV_DONTNEED); 24084dc99d2fa67e5dff018685661cb2bff62132989Mathieu Chartier} 24184dc99d2fa67e5dff018685661cb2bff62132989Mathieu Chartier 24212f7423a2bb4bfab76700d84eb6d4338d211983aMathieu Chartiervoid IndirectReferenceTable::VisitRoots(RootCallback* callback, void* arg, 24312f7423a2bb4bfab76700d84eb6d4338d211983aMathieu Chartier const RootInfo& root_info) { 24402e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier for (auto ref : *this) { 24512f7423a2bb4bfab76700d84eb6d4338d211983aMathieu Chartier callback(ref, arg, root_info); 246423d2a3dcbb260b020efb5da59f784c9f02accbfMathieu Chartier DCHECK(*ref != nullptr); 247410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes } 248410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes} 249410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes 25073e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughesvoid IndirectReferenceTable::Dump(std::ostream& os) const { 25173e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes os << kind_ << " table dump:\n"; 252196851b634a5bfdd8ab3fb59a320e550b21b0f4dHiroshi Yamauchi ReferenceTable::Table entries; 253196851b634a5bfdd8ab3fb59a320e550b21b0f4dHiroshi Yamauchi for (size_t i = 0; i < Capacity(); ++i) { 254a1de6b93426cfc66a64eb1b57303348aab5e766dMathieu Chartier mirror::Object* obj = table_[i].GetReference()->Read<kWithoutReadBarrier>(); 255196851b634a5bfdd8ab3fb59a320e550b21b0f4dHiroshi Yamauchi if (UNLIKELY(obj == nullptr)) { 256196851b634a5bfdd8ab3fb59a320e550b21b0f4dHiroshi Yamauchi // Remove NULLs. 257196851b634a5bfdd8ab3fb59a320e550b21b0f4dHiroshi Yamauchi } else if (UNLIKELY(obj == kClearedJniWeakGlobal)) { 258196851b634a5bfdd8ab3fb59a320e550b21b0f4dHiroshi Yamauchi // ReferenceTable::Dump() will handle kClearedJniWeakGlobal 259196851b634a5bfdd8ab3fb59a320e550b21b0f4dHiroshi Yamauchi // while the read barrier won't. 26094f7b49578b6aaa80de8ffed230648d601393905Hiroshi Yamauchi entries.push_back(GcRoot<mirror::Object>(obj)); 261196851b634a5bfdd8ab3fb59a320e550b21b0f4dHiroshi Yamauchi } else { 262a1de6b93426cfc66a64eb1b57303348aab5e766dMathieu Chartier obj = table_[i].GetReference()->Read(); 26394f7b49578b6aaa80de8ffed230648d601393905Hiroshi Yamauchi entries.push_back(GcRoot<mirror::Object>(obj)); 26463818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers } 26563818dc8b06af4a1e65c41b453f1a42166c22728Ian Rogers } 26673e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes ReferenceTable::Dump(os, entries); 2676c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes} 2686c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 2696c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes} // namespace art 270