diff options
Diffstat (limited to 'runtime/indirect_reference_table.cc')
-rw-r--r-- | runtime/indirect_reference_table.cc | 119 |
1 files changed, 19 insertions, 100 deletions
diff --git a/runtime/indirect_reference_table.cc b/runtime/indirect_reference_table.cc index 987df91..b81e43a 100644 --- a/runtime/indirect_reference_table.cc +++ b/runtime/indirect_reference_table.cc @@ -14,7 +14,8 @@ * limitations under the License. */ -#include "indirect_reference_table.h" +#include "indirect_reference_table-inl.h" + #include "jni_internal.h" #include "reference_table.h" #include "runtime.h" @@ -53,7 +54,7 @@ std::ostream& operator<<(std::ostream& os, const MutatorLockedDumpable<T>& rhs) return os; } -static void AbortMaybe() { +void IndirectReferenceTable::AbortIfNoCheckJNI() { // If -Xcheck:jni is on, it'll give a more detailed error before aborting. if (!Runtime::Current()->GetJavaVM()->check_jni) { // Otherwise, we want to abort rather than hand back a bad reference. @@ -67,12 +68,23 @@ IndirectReferenceTable::IndirectReferenceTable(size_t initialCount, CHECK_LE(initialCount, maxCount); CHECK_NE(desiredKind, kSirtOrInvalid); - table_ = reinterpret_cast<mirror::Object**>(malloc(initialCount * sizeof(const mirror::Object*))); - CHECK(table_ != NULL); - memset(table_, 0xd1, initialCount * sizeof(const mirror::Object*)); + std::string error_str; + const size_t initial_bytes = initialCount * sizeof(const mirror::Object*); + const size_t table_bytes = maxCount * sizeof(const mirror::Object*); + table_mem_map_.reset(MemMap::MapAnonymous("indirect ref table", nullptr, table_bytes, + PROT_READ | PROT_WRITE, false, &error_str)); + CHECK(table_mem_map_.get() != nullptr) << error_str; + + table_ = reinterpret_cast<mirror::Object**>(table_mem_map_->Begin()); + CHECK(table_ != nullptr); + memset(table_, 0xd1, initial_bytes); - slot_data_ = reinterpret_cast<IndirectRefSlot*>(calloc(initialCount, sizeof(IndirectRefSlot))); - CHECK(slot_data_ != NULL); + const size_t slot_bytes = maxCount * sizeof(IndirectRefSlot); + slot_mem_map_.reset(MemMap::MapAnonymous("indirect ref table slots", nullptr, slot_bytes, + PROT_READ | PROT_WRITE, false, &error_str)); + CHECK(slot_mem_map_.get() != nullptr) << error_str; + slot_data_ = reinterpret_cast<IndirectRefSlot*>(slot_mem_map_->Begin()); + CHECK(slot_data_ != nullptr); segment_state_.all = IRT_FIRST_SEGMENT; alloc_entries_ = initialCount; @@ -81,25 +93,6 @@ IndirectReferenceTable::IndirectReferenceTable(size_t initialCount, } IndirectReferenceTable::~IndirectReferenceTable() { - free(table_); - free(slot_data_); - table_ = NULL; - slot_data_ = NULL; - alloc_entries_ = max_entries_ = -1; -} - -// Make sure that the entry at "idx" is correctly paired with "iref". -bool IndirectReferenceTable::CheckEntry(const char* what, IndirectRef iref, int idx) const { - const mirror::Object* obj = table_[idx]; - IndirectRef checkRef = ToIndirectRef(obj, idx); - if (UNLIKELY(checkRef != iref)) { - LOG(ERROR) << "JNI ERROR (app bug): attempt to " << what - << " stale " << kind_ << " " << iref - << " (should be " << checkRef << ")"; - AbortMaybe(); - return false; - } - return true; } IndirectRef IndirectReferenceTable::Add(uint32_t cookie, mirror::Object* obj) { @@ -127,20 +120,6 @@ IndirectRef IndirectReferenceTable::Add(uint32_t cookie, mirror::Object* obj) { } DCHECK_GT(newSize, alloc_entries_); - table_ = reinterpret_cast<mirror::Object**>(realloc(table_, newSize * sizeof(mirror::Object*))); - slot_data_ = reinterpret_cast<IndirectRefSlot*>(realloc(slot_data_, - newSize * sizeof(IndirectRefSlot))); - if (table_ == NULL || slot_data_ == NULL) { - LOG(FATAL) << "JNI ERROR (app bug): unable to expand " - << kind_ << " table (from " - << alloc_entries_ << " to " << newSize - << ", max=" << max_entries_ << ")\n" - << MutatorLockedDumpable<IndirectReferenceTable>(*this); - } - - // Clear the newly-allocated slot_data_ elements. - memset(slot_data_ + alloc_entries_, 0, (newSize - alloc_entries_) * sizeof(IndirectRefSlot)); - alloc_entries_ = newSize; } @@ -185,55 +164,6 @@ void IndirectReferenceTable::AssertEmpty() { } } -// Verifies that the indirect table lookup is valid. -// Returns "false" if something looks bad. -bool IndirectReferenceTable::GetChecked(IndirectRef iref) const { - if (UNLIKELY(iref == NULL)) { - LOG(WARNING) << "Attempt to look up NULL " << kind_; - return false; - } - if (UNLIKELY(GetIndirectRefKind(iref) == kSirtOrInvalid)) { - LOG(ERROR) << "JNI ERROR (app bug): invalid " << kind_ << " " << iref; - AbortMaybe(); - return false; - } - - int topIndex = segment_state_.parts.topIndex; - int idx = ExtractIndex(iref); - if (UNLIKELY(idx >= topIndex)) { - LOG(ERROR) << "JNI ERROR (app bug): accessed stale " << kind_ << " " - << iref << " (index " << idx << " in a table of size " << topIndex << ")"; - AbortMaybe(); - return false; - } - - if (UNLIKELY(table_[idx] == NULL)) { - LOG(ERROR) << "JNI ERROR (app bug): accessed deleted " << kind_ << " " << iref; - AbortMaybe(); - return false; - } - - if (UNLIKELY(!CheckEntry("use", iref, idx))) { - return false; - } - - return true; -} - -static int Find(mirror::Object* direct_pointer, int bottomIndex, int topIndex, - mirror::Object** table) { - for (int i = bottomIndex; i < topIndex; ++i) { - if (table[i] == direct_pointer) { - return i; - } - } - return -1; -} - -bool IndirectReferenceTable::ContainsDirectPointer(mirror::Object* direct_pointer) const { - return Find(direct_pointer, 0, segment_state_.parts.topIndex, table_) != -1; -} - // Removes an object. We extract the table offset bits from "iref" // and zap the corresponding entry, leaving a hole if it's not at the top. // If the entry is not between the current top index and the bottom index @@ -346,15 +276,4 @@ void IndirectReferenceTable::Dump(std::ostream& os) const { ReferenceTable::Dump(os, entries); } -mirror::Object* IndirectReferenceTable::Get(IndirectRef iref) const { - if (!GetChecked(iref)) { - return kInvalidIndirectRefObject; - } - mirror::Object* obj = table_[ExtractIndex(iref)];; - if (obj != kClearedJniWeakGlobal) { - VerifyObject(obj); - } - return obj; -} - } // namespace art |