Add max stack depth to agent

As a stack depth limit to the ti-alloc-sample agent.  This will allow
the invocation to control how deep the stacks are, permitting better
flamegraphs.

Bug: none
Test: attach the agent; run the startop test; look at the log.
Change-Id: I3cee52c20c7e5034f5823a73ad8e2ce7efe42faa
diff --git a/tools/jvmti-agents/ti-alloc-sample/README.md b/tools/jvmti-agents/ti-alloc-sample/README.md
index bfd78a0..e4f3793 100644
--- a/tools/jvmti-agents/ti-alloc-sample/README.md
+++ b/tools/jvmti-agents/ti-alloc-sample/README.md
@@ -16,11 +16,13 @@
 
 The agent is loaded using -agentpath like normal. It takes arguments in the
 following format:
->     `sample_rate,log_path`
+>     `sample_rate,stack_depth_limit,log_path`
 
 * sample_rate is an integer specifying how frequently an event is reported.
   E.g., 10 means every tenth call to new will be logged.
-* log_path is an absolued file path specifying where the log is to be written.
+* stack_depth_limit is an integer that determines the number of frames the deepest stack trace
+  can contain.  It returns just the top portion if the limit is exceeded.
+* log_path is an absolute file path specifying where the log is to be written.
 
 #### Output Format
 
diff --git a/tools/jvmti-agents/ti-alloc-sample/ti_alloc_sample.cc b/tools/jvmti-agents/ti-alloc-sample/ti_alloc_sample.cc
index 08ec434..f156421 100644
--- a/tools/jvmti-agents/ti-alloc-sample/ti_alloc_sample.cc
+++ b/tools/jvmti-agents/ti-alloc-sample/ti_alloc_sample.cc
@@ -324,6 +324,7 @@
 }
 
 static int sampling_rate = 10;
+static int stack_depth_limit = 50;
 
 static void JNICALL logVMObjectAlloc(jvmtiEnv* jvmti,
                                      JNIEnv* jni,
@@ -358,10 +359,13 @@
                                           klass,
                                           jlongContainer{.val = size}) + ")";
 
-  static constexpr size_t kFrameDepthLimit = 20;
-  jvmtiFrameInfo stack_frames[kFrameDepthLimit];
+  std::unique_ptr<jvmtiFrameInfo[]> stack_frames(new jvmtiFrameInfo[stack_depth_limit]);
   jint stack_depth;
-  jvmtiError err = jvmti->GetStackTrace(thread, 0, kFrameDepthLimit, stack_frames, &stack_depth);
+  jvmtiError err = jvmti->GetStackTrace(thread,
+                                        0,
+                                        stack_depth_limit,
+                                        stack_frames.get(),
+                                        &stack_depth);
   if (err == JVMTI_ERROR_NONE) {
     for (int i = 0; i < stack_depth; ++i) {
       record += "\n    " + formatMethod(jvmti, stack_frames[i].method);
@@ -397,15 +401,24 @@
 static jint AgentStart(JavaVM* vm,
                        char* options,
                        void* reserved ATTRIBUTE_UNUSED) {
-  // options string should contain "sampling_rate,output_file_path".
+  // options string should contain "sampling_rate,stack_depth_limit,output_file_path".
   std::string args(options);
   size_t comma_pos = args.find(',');
   if (comma_pos == std::string::npos) {
     return JNI_ERR;
   }
   sampling_rate = std::stoi(args.substr(0, comma_pos));
+  args = args.substr(comma_pos + 1);
+  comma_pos = args.find(',');
+  if (comma_pos == std::string::npos) {
+    return JNI_ERR;
+  }
+  stack_depth_limit = std::stoi(args.substr(0, comma_pos));
   std::string output_file_path = args.substr(comma_pos + 1);
 
+  LOG(INFO) << "Starting allocation tracing: sampling_rate=" << sampling_rate
+            << ", stack_depth_limit=" << stack_depth_limit;
+
   // Create the environment.
   jvmtiEnv* jvmti = nullptr;
   if (SetupJvmtiEnv(vm, &jvmti) != JNI_OK) {