Remove ART dependence on property debug.allocTracker.stackDepth
Added VMDebug API to set this property. It will be called from framework
code.
Test: test-art-host
Bug: 37291459
Change-Id: I832a013fc8685bf063809e9394e0524bd9cd422e
diff --git a/runtime/gc/allocation_record.cc b/runtime/gc/allocation_record.cc
index 40792c4..4900a9a 100644
--- a/runtime/gc/allocation_record.cc
+++ b/runtime/gc/allocation_record.cc
@@ -39,26 +39,11 @@
return klass_.IsNull() ? "null" : klass_.Read()->GetDescriptor(storage);
}
-void AllocRecordObjectMap::SetProperties() {
-#ifdef ART_TARGET_ANDROID
- // Check whether there's a system property overriding the max depth of stack trace.
- const char* propertyName = "debug.allocTracker.stackDepth";
- std::string stackDepthString = android::base::GetProperty(propertyName, "");
- if (!stackDepthString.empty()) {
- char* end;
- size_t value = strtoul(stackDepthString.c_str(), &end, 10);
- if (*end != '\0') {
- LOG(ERROR) << "Ignoring " << propertyName << " '" << stackDepthString
- << "' --- invalid";
- } else if (value > kMaxSupportedStackDepth) {
- LOG(WARNING) << propertyName << " '" << stackDepthString << "' too large, using "
- << kMaxSupportedStackDepth;
- max_stack_depth_ = kMaxSupportedStackDepth;
- } else {
- max_stack_depth_ = value;
- }
- }
-#endif // ART_TARGET_ANDROID
+void AllocRecordObjectMap::SetMaxStackDepth(size_t max_stack_depth) {
+ // Log fatal since this should already be checked when calling VMDebug.setAllocTrackerStackDepth.
+ CHECK_LE(max_stack_depth, kMaxSupportedStackDepth)
+ << "Allocation record max stack depth is too large";
+ max_stack_depth_ = max_stack_depth;
}
AllocRecordObjectMap::~AllocRecordObjectMap() {
@@ -167,7 +152,7 @@
heap->SetAllocationRecords(records);
}
CHECK(records != nullptr);
- records->SetProperties();
+ records->SetMaxStackDepth(heap->GetAllocTrackerStackDepth());
std::string self_name;
self->GetThreadName(self_name);
if (self_name == "JDWP") {
diff --git a/runtime/gc/allocation_record.h b/runtime/gc/allocation_record.h
index d1311df..7c4181c 100644
--- a/runtime/gc/allocation_record.h
+++ b/runtime/gc/allocation_record.h
@@ -200,6 +200,11 @@
class AllocRecordObjectMap {
public:
+ static constexpr size_t kDefaultNumAllocRecords = 512 * 1024;
+ static constexpr size_t kDefaultNumRecentRecords = 64 * 1024 - 1;
+ static constexpr size_t kDefaultAllocStackDepth = 16;
+ static constexpr size_t kMaxSupportedStackDepth = 128;
+
// GcRoot<mirror::Object> pointers in the list are weak roots, and the last recent_record_max_
// number of AllocRecord::klass_ pointers are strong roots (and the rest of klass_ pointers are
// weak roots). The last recent_record_max_ number of pairs in the list are always kept for DDMS's
@@ -291,10 +296,6 @@
void Clear() REQUIRES(Locks::alloc_tracker_lock_);
private:
- static constexpr size_t kDefaultNumAllocRecords = 512 * 1024;
- static constexpr size_t kDefaultNumRecentRecords = 64 * 1024 - 1;
- static constexpr size_t kDefaultAllocStackDepth = 16;
- static constexpr size_t kMaxSupportedStackDepth = 128;
size_t alloc_record_max_ GUARDED_BY(Locks::alloc_tracker_lock_) = kDefaultNumAllocRecords;
size_t recent_record_max_ GUARDED_BY(Locks::alloc_tracker_lock_) = kDefaultNumRecentRecords;
size_t max_stack_depth_ = kDefaultAllocStackDepth;
@@ -304,7 +305,7 @@
// see the comment in typedef of EntryList
EntryList entries_ GUARDED_BY(Locks::alloc_tracker_lock_);
- void SetProperties() REQUIRES(Locks::alloc_tracker_lock_);
+ void SetMaxStackDepth(size_t max_stack_depth) REQUIRES(Locks::alloc_tracker_lock_);
};
} // namespace gc
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 7a565bd..987b239 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -303,6 +303,7 @@
blocking_gc_count_rate_histogram_("blocking gc count rate histogram", 1U,
kGcCountRateMaxBucketCount),
alloc_tracking_enabled_(false),
+ alloc_record_depth_(AllocRecordObjectMap::kDefaultAllocStackDepth),
backtrace_lock_(nullptr),
seen_backtrace_count_(0u),
unique_backtrace_count_(0u),
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index 898a51c..5cf1978 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -835,8 +835,17 @@
alloc_tracking_enabled_.store(enabled, std::memory_order_relaxed);
}
- AllocRecordObjectMap* GetAllocationRecords() const
- REQUIRES(Locks::alloc_tracker_lock_) {
+ // Return the current stack depth of allocation records.
+ size_t GetAllocTrackerStackDepth() const {
+ return alloc_record_depth_;
+ }
+
+ // Return the current stack depth of allocation records.
+ void SetAllocTrackerStackDepth(size_t alloc_record_depth) {
+ alloc_record_depth_ = alloc_record_depth;
+ }
+
+ AllocRecordObjectMap* GetAllocationRecords() const REQUIRES(Locks::alloc_tracker_lock_) {
return allocation_records_.get();
}
@@ -1520,6 +1529,7 @@
// Allocation tracking support
Atomic<bool> alloc_tracking_enabled_;
std::unique_ptr<AllocRecordObjectMap> allocation_records_;
+ size_t alloc_record_depth_;
// GC stress related data structures.
Mutex* backtrace_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
diff --git a/runtime/native/dalvik_system_VMDebug.cc b/runtime/native/dalvik_system_VMDebug.cc
index 1531bac..83398ec 100644
--- a/runtime/native/dalvik_system_VMDebug.cc
+++ b/runtime/native/dalvik_system_VMDebug.cc
@@ -610,6 +610,19 @@
h_caller->SetSkipHiddenApiChecks();
}
+static void VMDebug_setAllocTrackerStackDepth(JNIEnv* env, jclass, jint stack_depth) {
+ Runtime* runtime = Runtime::Current();
+ if (stack_depth < 0 ||
+ static_cast<size_t>(stack_depth) > gc::AllocRecordObjectMap::kMaxSupportedStackDepth) {
+ ScopedObjectAccess soa(env);
+ soa.Self()->ThrowNewExceptionF("Ljava/lang/RuntimeException;",
+ "Stack depth is invalid: %d",
+ stack_depth);
+ } else {
+ runtime->GetHeap()->SetAllocTrackerStackDepth(static_cast<size_t>(stack_depth));
+ }
+}
+
static JNINativeMethod gMethods[] = {
NATIVE_METHOD(VMDebug, countInstancesOfClass, "(Ljava/lang/Class;Z)J"),
NATIVE_METHOD(VMDebug, countInstancesOfClasses, "([Ljava/lang/Class;Z)[J"),
@@ -646,6 +659,7 @@
NATIVE_METHOD(VMDebug, getRuntimeStatsInternal, "()[Ljava/lang/String;"),
NATIVE_METHOD(VMDebug, nativeAttachAgent, "(Ljava/lang/String;Ljava/lang/ClassLoader;)V"),
NATIVE_METHOD(VMDebug, allowHiddenApiReflectionFrom, "(Ljava/lang/Class;)V"),
+ NATIVE_METHOD(VMDebug, setAllocTrackerStackDepth, "(I)V"),
};
void register_dalvik_system_VMDebug(JNIEnv* env) {
diff --git a/test/145-alloc-tracking-stress/src/Main.java b/test/145-alloc-tracking-stress/src-art/Main.java
similarity index 93%
rename from test/145-alloc-tracking-stress/src/Main.java
rename to test/145-alloc-tracking-stress/src-art/Main.java
index 4a67a80..cf82d78 100644
--- a/test/145-alloc-tracking-stress/src/Main.java
+++ b/test/145-alloc-tracking-stress/src-art/Main.java
@@ -18,9 +18,12 @@
import java.lang.reflect.Method;
import java.util.Map;
+import dalvik.system.VMDebug;
+
public class Main implements Runnable {
static final int numberOfThreads = 4;
static final int totalOperations = 1000;
+ static final int maxStackDepth = 128;
static Method enableAllocTrackingMethod;
static Object holder;
static volatile boolean trackingThreadDone = false;
@@ -56,6 +59,7 @@
if (threadIndex == 0) {
for (int i = 0; i < totalOperations; ++i) {
try {
+ VMDebug.setAllocTrackerStackDepth(i % (maxStackDepth + 1));
enableAllocTrackingMethod.invoke(null, true);
holder = new Object();
enableAllocTrackingMethod.invoke(null, false);