indirect_reference_table.cc revision cdd1d2d3fee0711b8b11db99f2dfb80113520100
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 176c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes#include "indirect_reference_table.h" 186c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes#include "reference_table.h" 19cdd1d2d3fee0711b8b11db99f2dfb80113520100Ian Rogers#include "utils.h" 206c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 216c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes#include <cstdlib> 226c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 236c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughesnamespace art { 246c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 256c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes// TODO: implement this for art. (only needed for non-CheckJNI operation.) 266c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughesstatic void AbortMaybe() { 276c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes // If CheckJNI is on, it'll give a more detailed error before aborting. 286c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes // Otherwise, we want to abort rather than hand back a bad reference. 296c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes// if (!gDvmJni.useCheckJni) { 306c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes// LOG(FATAL) << "bye!"; 316c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes// } 326c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes} 336c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 346c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott HughesIndirectReferenceTable::IndirectReferenceTable(size_t initialCount, 356c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes size_t maxCount, IndirectRefKind desiredKind) 366c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes{ 376c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes CHECK_GT(initialCount, 0U); 386c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes CHECK_LE(initialCount, maxCount); 396c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes CHECK_NE(desiredKind, kInvalid); 406c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 416c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes table_ = reinterpret_cast<Object**>(malloc(initialCount * sizeof(Object*))); 426c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes CHECK(table_ != NULL); 436c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes#ifndef NDEBUG 446c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes memset(table_, 0xd1, initialCount * sizeof(Object*)); 456c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes#endif 466c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 476c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes slot_data_ = reinterpret_cast<IndirectRefSlot*>(calloc(initialCount, sizeof(IndirectRefSlot))); 486c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes CHECK(slot_data_ != NULL); 496c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 506c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes segmentState.all = IRT_FIRST_SEGMENT; 516c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes alloc_entries_ = initialCount; 526c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes max_entries_ = maxCount; 536c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes kind_ = desiredKind; 546c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes} 556c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 566c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott HughesIndirectReferenceTable::~IndirectReferenceTable() { 576c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes free(table_); 586c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes free(slot_data_); 596c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes table_ = NULL; 606c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes slot_data_ = NULL; 616c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes alloc_entries_ = max_entries_ = -1; 626c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes} 636c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 646c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes/* 656c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes * Make sure that the entry at "idx" is correctly paired with "iref". 666c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes */ 676c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughesbool IndirectReferenceTable::CheckEntry(const char* what, IndirectRef iref, int idx) const { 686c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes Object* obj = table_[idx]; 696c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes IndirectRef checkRef = ToIndirectRef(obj, idx); 706c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes if (checkRef != iref) { 716c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes LOG(ERROR) << "JNI ERROR (app bug): attempt to " << what 726c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes << " stale " << kind_ << " " << iref 736c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes << " (should be " << checkRef << ")"; 746c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes AbortMaybe(); 756c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes return false; 766c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 776c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes return true; 786c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes} 796c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 806c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott HughesIndirectRef IndirectReferenceTable::Add(uint32_t cookie, Object* obj) { 816c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes IRTSegmentState prevState; 826c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes prevState.all = cookie; 836c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes size_t topIndex = segmentState.parts.topIndex; 846c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 856c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes DCHECK(obj != NULL); 86cdd1d2d3fee0711b8b11db99f2dfb80113520100Ian Rogers // TODO: stronger sanity check on the object (such as in heap) 87cdd1d2d3fee0711b8b11db99f2dfb80113520100Ian Rogers DCHECK(IsAligned(reinterpret_cast<intptr_t>(obj), 8)); 886c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes DCHECK(table_ != NULL); 896c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes DCHECK_LE(alloc_entries_, max_entries_); 906c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes DCHECK_GE(segmentState.parts.numHoles, prevState.parts.numHoles); 916c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 926c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes if (topIndex == alloc_entries_) { 936c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes /* reached end of allocated space; did we hit buffer max? */ 946c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes if (topIndex == max_entries_) { 956c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes LOG(ERROR) << "JNI ERROR (app bug): " << kind_ << " table overflow " 966c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes << "(max=" << max_entries_ << ")"; 976c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes Dump(); 986c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes LOG(FATAL); // TODO: operator<< for IndirectReferenceTable 996c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 1006c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 1016c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes size_t newSize = alloc_entries_ * 2; 1026c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes if (newSize > max_entries_) { 1036c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes newSize = max_entries_; 1046c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 1056c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes DCHECK_GT(newSize, alloc_entries_); 1066c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 1076c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes table_ = (Object**) realloc(table_, newSize * sizeof(Object*)); 1086c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes slot_data_ = (IndirectRefSlot*) realloc(slot_data_, newSize * sizeof(IndirectRefSlot)); 1096c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes if (table_ == NULL || slot_data_ == NULL) { 1106c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes LOG(ERROR) << "JNI ERROR (app bug): unable to expand " 1116c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes << kind_ << " table (from " 1126c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes << alloc_entries_ << " to " << newSize 1136c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes << ", max=" << max_entries_ << ")"; 1146c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes Dump(); 1156c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes LOG(FATAL); // TODO: operator<< for IndirectReferenceTable 1166c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 1176c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 1186c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes // Clear the newly-allocated slot_data_ elements. 1196c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes memset(slot_data_ + alloc_entries_, 0, (newSize - alloc_entries_) * sizeof(IndirectRefSlot)); 1206c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 1216c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes alloc_entries_ = newSize; 1226c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 1236c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 1246c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes /* 1256c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes * We know there's enough room in the table. Now we just need to find 1266c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes * the right spot. If there's a hole, find it and fill it; otherwise, 1276c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes * add to the end of the list. 1286c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes */ 1296c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes IndirectRef result; 1306c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes int numHoles = segmentState.parts.numHoles - prevState.parts.numHoles; 1316c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes if (numHoles > 0) { 1326c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes DCHECK_GT(topIndex, 1U); 1336c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes /* find the first hole; likely to be near the end of the list */ 1346c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes Object** pScan = &table_[topIndex - 1]; 1356c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes DCHECK(*pScan != NULL); 1366c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes while (*--pScan != NULL) { 1376c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes DCHECK_GE(pScan, table_ + prevState.parts.topIndex); 1386c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 1396c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes UpdateSlotAdd(obj, pScan - table_); 1406c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes result = ToIndirectRef(obj, pScan - table_); 1416c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes *pScan = obj; 1426c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes segmentState.parts.numHoles--; 1436c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } else { 1446c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes /* add to the end */ 1456c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes UpdateSlotAdd(obj, topIndex); 1466c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes result = ToIndirectRef(obj, topIndex); 1476c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes table_[topIndex++] = obj; 1486c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes segmentState.parts.topIndex = topIndex; 1496c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 1506c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 1516c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes DCHECK(result != NULL); 1526c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes return result; 1536c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes} 1546c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 1556c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes/* 1566c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes * Verify that the indirect table lookup is valid. 1576c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes * 1586c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes * Returns "false" if something looks bad. 1596c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes */ 1606c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughesbool IndirectReferenceTable::GetChecked(IndirectRef iref) const { 1616c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes if (iref == NULL) { 1626c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes LOG(WARNING) << "Attempt to look up NULL " << kind_; 1636c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes return false; 1646c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 1656c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes if (GetIndirectRefKind(iref) == kInvalid) { 1666c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes LOG(ERROR) << "JNI ERROR (app bug): invalid " << kind_ << " " << iref; 1676c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes AbortMaybe(); 1686c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes return false; 1696c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 1706c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 1716c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes int topIndex = segmentState.parts.topIndex; 1726c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes int idx = ExtractIndex(iref); 1736c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes if (idx >= topIndex) { 1746c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes /* bad -- stale reference? */ 1756c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes LOG(ERROR) << "JNI ERROR (app bug): accessed stale " << kind_ << " " << iref << " (index " << idx << " in a table of size " << topIndex << ")"; 1766c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes AbortMaybe(); 1776c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes return false; 1786c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 1796c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 1806c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes if (table_[idx] == NULL) { 1816c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes LOG(ERROR) << "JNI ERROR (app bug): accessed deleted " << kind_ << " " << iref; 1826c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes AbortMaybe(); 1836c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes return false; 1846c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 1856c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 1866c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes if (!CheckEntry("use", iref, idx)) { 1876c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes return false; 1886c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 1896c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 1906c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes return true; 1916c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes} 1926c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 1936c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughesstatic int LinearScan(IndirectRef iref, int bottomIndex, int topIndex, Object** table) { 1946c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes for (int i = bottomIndex; i < topIndex; ++i) { 1956c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes if (table[i] == reinterpret_cast<Object*>(iref)) { 1966c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes return i; 1976c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 1986c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 1996c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes return -1; 2006c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes} 2016c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 2026c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughesbool IndirectReferenceTable::Contains(IndirectRef iref) const { 2036c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes return LinearScan(iref, 0, segmentState.parts.topIndex, table_) != -1; 2046c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes} 2056c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 2066c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes/* 2076c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes * Remove "obj" from "pRef". We extract the table offset bits from "iref" 2086c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes * and zap the corresponding entry, leaving a hole if it's not at the top. 2096c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes * 2106c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes * If the entry is not between the current top index and the bottom index 2116c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes * specified by the cookie, we don't remove anything. This is the behavior 2126c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes * required by JNI's DeleteLocalRef function. 2136c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes * 2146c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes * Note this is NOT called when a local frame is popped. This is only used 2156c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes * for explicit single removals. 2166c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes * 2176c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes * Returns "false" if nothing was removed. 2186c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes */ 2196c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughesbool IndirectReferenceTable::Remove(uint32_t cookie, IndirectRef iref) { 2206c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes IRTSegmentState prevState; 2216c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes prevState.all = cookie; 2226c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes int topIndex = segmentState.parts.topIndex; 2236c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes int bottomIndex = prevState.parts.topIndex; 2246c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 2256c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes DCHECK(table_ != NULL); 2266c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes DCHECK_LE(alloc_entries_, max_entries_); 2276c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes DCHECK_GE(segmentState.parts.numHoles, prevState.parts.numHoles); 2286c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 2296c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes int idx = ExtractIndex(iref); 2306c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes bool workAroundAppJniBugs = false; 2316c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 2326c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes if (GetIndirectRefKind(iref) == kInvalid /*&& gDvmJni.workAroundAppJniBugs*/) { // TODO 2336c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes idx = LinearScan(iref, bottomIndex, topIndex, table_); 2346c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes workAroundAppJniBugs = true; 2356c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes if (idx == -1) { 2366c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes LOG(WARNING) << "trying to work around app JNI bugs, but didn't find " << iref << " in table!"; 2376c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes return false; 2386c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 2396c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 2406c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 2416c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes if (idx < bottomIndex) { 2426c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes /* wrong segment */ 2436c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes LOG(INFO) << "Attempt to remove index outside index area (" << idx << " vs " << bottomIndex << "-" << topIndex << ")"; 2446c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes return false; 2456c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 2466c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes if (idx >= topIndex) { 2476c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes /* bad -- stale reference? */ 2486c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes LOG(INFO) << "Attempt to remove invalid index " << idx << " (bottom=" << bottomIndex << " top=" << topIndex << ")"; 2496c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes return false; 2506c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 2516c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 2526c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes if (idx == topIndex-1) { 2536c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes // Top-most entry. Scan up and consume holes. 2546c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 2556c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes if (workAroundAppJniBugs == false && !CheckEntry("remove", iref, idx)) { 2566c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes return false; 2576c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 2586c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 2596c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes table_[idx] = NULL; 2606c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes int numHoles = segmentState.parts.numHoles - prevState.parts.numHoles; 2616c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes if (numHoles != 0) { 2626c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes while (--topIndex > bottomIndex && numHoles != 0) { 2636c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes //LOG(INFO) << "+++ checking for hole at " << topIndex-1 << " (cookie=" << cookie << ") val=" << table_[topIndex-1]; 2646c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes if (table_[topIndex-1] != NULL) { 2656c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes break; 2666c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 2676c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes //LOG(INFO) << "+++ ate hole at " << (topIndex-1); 2686c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes numHoles--; 2696c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 2706c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes segmentState.parts.numHoles = numHoles + prevState.parts.numHoles; 2716c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes segmentState.parts.topIndex = topIndex; 2726c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } else { 2736c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes segmentState.parts.topIndex = topIndex-1; 274c5f7c91ab89055cffb573fff7e06dbdd860bccedElliott Hughes //LOG(INFO) << "+++ ate last entry " << topIndex-1; 2756c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 2766c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } else { 2776c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes /* 2786c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes * Not the top-most entry. This creates a hole. We NULL out the 2796c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes * entry to prevent somebody from deleting it twice and screwing up 2806c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes * the hole count. 2816c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes */ 2826c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes if (table_[idx] == NULL) { 2836c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes LOG(INFO) << "--- WEIRD: removing null entry " << idx; 2846c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes return false; 2856c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 2866c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes if (workAroundAppJniBugs == false && !CheckEntry("remove", iref, idx)) { 2876c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes return false; 2886c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 2896c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 2906c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes table_[idx] = NULL; 2916c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes segmentState.parts.numHoles++; 2926c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes //LOG(INFO) << "+++ left hole at " << idx << ", holes=" << segmentState.parts.numHoles; 2936c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 2946c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 2956c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes return true; 2966c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes} 2976c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 2986c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughesstd::ostream& operator<<(std::ostream& os, IndirectRefKind rhs) { 2996c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes switch (rhs) { 3006c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes case kInvalid: 3016c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes os << "invalid reference"; 3026c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes break; 3036c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes case kLocal: 3046c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes os << "local reference"; 3056c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes break; 3066c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes case kGlobal: 3076c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes os << "global reference"; 3086c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes break; 3096c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes case kWeakGlobal: 3106c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes os << "weak global reference"; 3116c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes break; 3126c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes default: 3136c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes os << "IndirectRefKind[" << static_cast<int>(rhs) << "]"; 3146c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes break; 3156c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes } 3166c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes return os; 3176c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes} 3186c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 3196c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughesvoid IndirectReferenceTable::Dump() const { 3206c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes LOG(WARNING) << kind_ << " table dump:"; 3216c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes std::vector<Object*> entries(table_, table_ + Capacity()); 3226c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes ReferenceTable::Dump(entries); 3236c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes} 3246c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes 3256c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes} // namespace art 326