summaryrefslogtreecommitdiffstats
path: root/runtime/indirect_reference_table.h
diff options
context:
space:
mode:
authorMathieu Chartier <mathieuc@google.com>2014-09-25 15:27:43 -0700
committerMathieu Chartier <mathieuc@google.com>2014-09-25 15:27:43 -0700
commit4838d6651eab0e8c0687ba44ce38e83b4553a4e2 (patch)
tree2bb025e19069f57c4a7a4d350daad6213dbc9ce5 /runtime/indirect_reference_table.h
parent1ed5b27ee329208fd8ae22b8a9a61d708e2c1ffb (diff)
downloadart-4838d6651eab0e8c0687ba44ce38e83b4553a4e2.tar.gz
art-4838d6651eab0e8c0687ba44ce38e83b4553a4e2.tar.bz2
art-4838d6651eab0e8c0687ba44ce38e83b4553a4e2.zip
Reduce IndirectReferenceTable memory usage
Changed the slot side table and the main table to be a single table, reduced number of slots per reference from 4 to 3 to make the IrtEntry a power of 2 size. Before: 20848 kB: Dalvik Other After: 16760 kB: Dalvik Other Bug: 17643507 (cherry picked from commit a1de6b93426cfc66a64eb1b57303348aab5e766d) Change-Id: I362475235a887c60eff6870bb10051a6be3d5814
Diffstat (limited to 'runtime/indirect_reference_table.h')
-rw-r--r--runtime/indirect_reference_table.h76
1 files changed, 35 insertions, 41 deletions
diff --git a/runtime/indirect_reference_table.h b/runtime/indirect_reference_table.h
index 5291e508a9..168f9f2764 100644
--- a/runtime/indirect_reference_table.h
+++ b/runtime/indirect_reference_table.h
@@ -125,16 +125,6 @@ static inline IndirectRefKind GetIndirectRefKind(IndirectRef iref) {
return static_cast<IndirectRefKind>(reinterpret_cast<uintptr_t>(iref) & 0x03);
}
-/*
- * Extended debugging structure. We keep a parallel array of these, one
- * per slot in the table.
- */
-static const size_t kIRTPrevCount = 4;
-struct IndirectRefSlot {
- uint32_t serial;
- const mirror::Object* previous[kIRTPrevCount];
-};
-
/* use as initial value for "cookie", and when table has only one segment */
static const uint32_t IRT_FIRST_SEGMENT = 0;
@@ -201,9 +191,35 @@ union IRTSegmentState {
} parts;
};
+// Try to choose kIRTPrevCount so that sizeof(IrtEntry) is a power of 2.
+// Contains multiple entries but only one active one, this helps us detect use after free errors
+// since the serial stored in the indirect ref wont match.
+static const size_t kIRTPrevCount = kIsDebugBuild ? 7 : 3;
+class PACKED(4) IrtEntry {
+ public:
+ void Add(mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ ++serial_;
+ if (serial_ == kIRTPrevCount) {
+ serial_ = 0;
+ }
+ references_[serial_] = GcRoot<mirror::Object>(obj);
+ }
+ GcRoot<mirror::Object>* GetReference() {
+ DCHECK_LT(serial_, kIRTPrevCount);
+ return &references_[serial_];
+ }
+ uint32_t GetSerial() const {
+ return serial_;
+ }
+
+ private:
+ uint32_t serial_;
+ GcRoot<mirror::Object> references_[kIRTPrevCount];
+};
+
class IrtIterator {
public:
- explicit IrtIterator(GcRoot<mirror::Object>* table, size_t i, size_t capacity)
+ explicit IrtIterator(IrtEntry* table, size_t i, size_t capacity)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
: table_(table), i_(i), capacity_(capacity) {
}
@@ -215,7 +231,7 @@ class IrtIterator {
mirror::Object** operator*() {
// This does not have a read barrier as this is used to visit roots.
- return table_[i_].AddressWithoutBarrier();
+ return table_[i_].GetReference()->AddressWithoutBarrier();
}
bool equals(const IrtIterator& rhs) const {
@@ -223,7 +239,7 @@ class IrtIterator {
}
private:
- GcRoot<mirror::Object>* const table_;
+ IrtEntry* const table_;
size_t i_;
const size_t capacity_;
};
@@ -316,9 +332,7 @@ class IndirectReferenceTable {
}
private:
- /*
- * Extract the table index from an indirect reference.
- */
+ // Extract the table index from an indirect reference.
static uint32_t ExtractIndex(IndirectRef iref) {
uintptr_t uref = reinterpret_cast<uintptr_t>(iref);
return (uref >> 2) & 0xffff;
@@ -330,25 +344,11 @@ class IndirectReferenceTable {
*/
IndirectRef ToIndirectRef(uint32_t tableIndex) const {
DCHECK_LT(tableIndex, 65536U);
- uint32_t serialChunk = slot_data_[tableIndex].serial;
- uintptr_t uref = serialChunk << 20 | (tableIndex << 2) | kind_;
+ uint32_t serialChunk = table_[tableIndex].GetSerial();
+ uintptr_t uref = (serialChunk << 20) | (tableIndex << 2) | kind_;
return reinterpret_cast<IndirectRef>(uref);
}
- /*
- * Update extended debug info when an entry is added.
- *
- * We advance the serial number, invalidating any outstanding references to
- * this slot.
- */
- void UpdateSlotAdd(const mirror::Object* obj, int slot) {
- if (slot_data_ != NULL) {
- IndirectRefSlot* pSlot = &slot_data_[slot];
- pSlot->serial++;
- pSlot->previous[pSlot->serial % kIRTPrevCount] = obj;
- }
- }
-
// Abort if check_jni is not enabled.
static void AbortIfNoCheckJNI();
@@ -361,19 +361,13 @@ class IndirectReferenceTable {
// Mem map where we store the indirect refs.
std::unique_ptr<MemMap> table_mem_map_;
- // Mem map where we store the extended debugging info.
- std::unique_ptr<MemMap> slot_mem_map_;
// bottom of the stack. Do not directly access the object references
// in this as they are roots. Use Get() that has a read barrier.
- GcRoot<mirror::Object>* table_;
+ IrtEntry* table_;
/* bit mask, ORed into all irefs */
- IndirectRefKind kind_;
- /* extended debugging info */
- IndirectRefSlot* slot_data_;
- /* #of entries we have space for */
- size_t alloc_entries_;
+ const IndirectRefKind kind_;
/* max #of entries allowed */
- size_t max_entries_;
+ const size_t max_entries_;
};
} // namespace art