summaryrefslogtreecommitdiff
path: root/runtime/indirect_reference_table.h
diff options
context:
space:
mode:
author Hans Boehm <hboehm@google.com> 2021-09-23 12:26:04 -0700
committer Hans Boehm <hboehm@google.com> 2021-10-27 20:05:43 +0000
commit4dcac3629ea5925e47b522073f3c49420e998911 (patch)
tree51219b64e869c15149a7397c8ab1eac2dc4e3cd4 /runtime/indirect_reference_table.h
parent48fb9f43a81fa0cab09ed4a4f3d478c1a0ecbe9e (diff)
Initially allocate smaller local IRT
Introduce a separate small object allocator to allocate tables for the initial local indirect reference tables, so they don't each occupy a full page. This seemed to be easier than using linear_alloc, since these allocations are done from multiple threads. This also has the advantage that GC roots are concentrated on separate pages, that could be protected as before, but there are many fewer of then than before. As discussed with Lokesh, it might eventually be better to allocate these in the Java heap. But doing that cleanly seems to require a major refactoring to split IrtEntrys into two separate components, which complicates iteration, etc. And that has locality disadvantages during lookup. Or we need to either drop the serial number of merge it into the GcRoot, neither of which is ideal either. Drive-by-fix: When trimming, don't call madvise on empty address ranges. Test: Build and boot AOSP. Test: art/test/testrunner/testrunner.py --host -b --64 Bug: 184847225 Change-Id: I297646acbdd9dbeab4af47461849fffa2fee23b1
Diffstat (limited to 'runtime/indirect_reference_table.h')
-rw-r--r--runtime/indirect_reference_table.h39
1 files changed, 38 insertions, 1 deletions
diff --git a/runtime/indirect_reference_table.h b/runtime/indirect_reference_table.h
index 97bd72dfe6..34340e55de 100644
--- a/runtime/indirect_reference_table.h
+++ b/runtime/indirect_reference_table.h
@@ -29,6 +29,7 @@
#include "base/locks.h"
#include "base/macros.h"
#include "base/mem_map.h"
+#include "base/mutex.h"
#include "gc_root.h"
#include "obj_ptr.h"
#include "offsets.h"
@@ -216,6 +217,39 @@ bool inline operator!=(const IrtIterator& lhs, const IrtIterator& rhs) {
return !lhs.equals(rhs);
}
+// We initially allocate local reference tables with a very small number of entries, packing
+// multiple tables into a single page. If we need to expand one, we allocate them in units of
+// pages.
+// TODO: We should allocate all IRT tables as nonmovable Java objects, That in turn works better
+// if we break up each table into 2 parallel arrays, one for the Java reference, and one for the
+// serial number. The current scheme page-aligns regions containing IRT tables, and so allows them
+// to be identified and page-protected in the future.
+constexpr size_t kInitialIrtBytes = 512; // Number of bytes in an initial local table.
+constexpr size_t kSmallIrtEntries = kInitialIrtBytes / sizeof(IrtEntry);
+static_assert(kPageSize % kInitialIrtBytes == 0);
+static_assert(kInitialIrtBytes % sizeof(IrtEntry) == 0);
+static_assert(kInitialIrtBytes % sizeof(void *) == 0);
+
+// A minimal stopgap allocator for initial small local IRT tables.
+class SmallIrtAllocator {
+ public:
+ SmallIrtAllocator();
+
+ // Allocate an IRT table for kSmallIrtEntries.
+ IrtEntry* Allocate(std::string* error_msg) REQUIRES(!lock_);
+
+ void Deallocate(IrtEntry* unneeded) REQUIRES(!lock_);
+
+ private:
+ // A free list of kInitialIrtBytes chunks linked through the first word.
+ IrtEntry* small_irt_freelist_;
+
+ // Repository of MemMaps used for small IRT tables.
+ std::vector<MemMap> shared_irt_maps_;
+
+ Mutex lock_;
+};
+
class IndirectReferenceTable {
public:
enum class ResizableCapacity {
@@ -228,6 +262,8 @@ class IndirectReferenceTable {
// construction has failed and the IndirectReferenceTable will be in an
// invalid state. Use IsValid to check whether the object is in an invalid
// state.
+ // Max_count is the minimum initial capacity (resizable), or minimum total capacity
+ // (not resizable). A value of 1 indicates an implementation-convenient small size.
IndirectReferenceTable(size_t max_count,
IndirectRefKind kind,
ResizableCapacity resizable,
@@ -407,7 +443,8 @@ class IndirectReferenceTable {
/// semi-public - read/write by jni down calls.
IRTSegmentState segment_state_;
- // Mem map where we store the indirect refs.
+ // Mem map where we store the indirect refs. If it's invalid, and table_ is non-null, then
+ // table_ is valid, but was allocated via allocSmallIRT();
MemMap table_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.