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);