Fix DDMS allocation tracker.

The allocation tracker previously did a NewByteArray while holding the
gAllocTrackerLock. This was problematic due to the fact that this new
allocation would also try to acquire said lock. Fixed the issue by
moving the newByteArray call outside of the lock.

Bug: 9767557

Change-Id: I7e94e631d9c96aa642637de52f100b371f813294
diff --git a/src/debugger.cc b/src/debugger.cc
index f2a10f0..d50b55b 100644
--- a/src/debugger.cc
+++ b/src/debugger.cc
@@ -3650,111 +3650,111 @@
   }
 
   Thread* self = Thread::Current();
-  MutexLock mu(self, gAllocTrackerLock);
-
-  //
-  // Part 1: generate string tables.
-  //
-  StringTable class_names;
-  StringTable method_names;
-  StringTable filenames;
-
-  int count = gAllocRecordCount;
-  int idx = HeadIndex();
-  while (count--) {
-    AllocRecord* record = &recent_allocation_records_[idx];
-
-    class_names.Add(ClassHelper(record->type).GetDescriptor());
-
-    MethodHelper mh;
-    for (size_t i = 0; i < kMaxAllocRecordStackDepth; i++) {
-      mirror::AbstractMethod* m = record->stack[i].method;
-      if (m != NULL) {
-        mh.ChangeMethod(m);
-        class_names.Add(mh.GetDeclaringClassDescriptor());
-        method_names.Add(mh.GetName());
-        filenames.Add(mh.GetDeclaringClassSourceFile());
-      }
-    }
-
-    idx = (idx + 1) & (kNumAllocRecords-1);
-  }
-
-  LOG(INFO) << "allocation records: " << gAllocRecordCount;
-
-  //
-  // Part 2: allocate a buffer and generate the output.
-  //
   std::vector<uint8_t> bytes;
+  {
+    MutexLock mu(self, gAllocTrackerLock);
+    //
+    // Part 1: generate string tables.
+    //
+    StringTable class_names;
+    StringTable method_names;
+    StringTable filenames;
 
-  // (1b) message header len (to allow future expansion); includes itself
-  // (1b) entry header len
-  // (1b) stack frame len
-  const int kMessageHeaderLen = 15;
-  const int kEntryHeaderLen = 9;
-  const int kStackFrameLen = 8;
-  JDWP::Append1BE(bytes, kMessageHeaderLen);
-  JDWP::Append1BE(bytes, kEntryHeaderLen);
-  JDWP::Append1BE(bytes, kStackFrameLen);
+    int count = gAllocRecordCount;
+    int idx = HeadIndex();
+    while (count--) {
+      AllocRecord* record = &recent_allocation_records_[idx];
 
-  // (2b) number of entries
-  // (4b) offset to string table from start of message
-  // (2b) number of class name strings
-  // (2b) number of method name strings
-  // (2b) number of source file name strings
-  JDWP::Append2BE(bytes, gAllocRecordCount);
-  size_t string_table_offset = bytes.size();
-  JDWP::Append4BE(bytes, 0); // We'll patch this later...
-  JDWP::Append2BE(bytes, class_names.Size());
-  JDWP::Append2BE(bytes, method_names.Size());
-  JDWP::Append2BE(bytes, filenames.Size());
+      class_names.Add(ClassHelper(record->type).GetDescriptor());
 
-  count = gAllocRecordCount;
-  idx = HeadIndex();
-  ClassHelper kh;
-  while (count--) {
-    // For each entry:
-    // (4b) total allocation size
-    // (2b) thread id
-    // (2b) allocated object's class name index
-    // (1b) stack depth
-    AllocRecord* record = &recent_allocation_records_[idx];
-    size_t stack_depth = record->GetDepth();
-    kh.ChangeClass(record->type);
-    size_t allocated_object_class_name_index = class_names.IndexOf(kh.GetDescriptor());
-    JDWP::Append4BE(bytes, record->byte_count);
-    JDWP::Append2BE(bytes, record->thin_lock_id);
-    JDWP::Append2BE(bytes, allocated_object_class_name_index);
-    JDWP::Append1BE(bytes, stack_depth);
+      MethodHelper mh;
+      for (size_t i = 0; i < kMaxAllocRecordStackDepth; i++) {
+        mirror::AbstractMethod* m = record->stack[i].method;
+        if (m != NULL) {
+          mh.ChangeMethod(m);
+          class_names.Add(mh.GetDeclaringClassDescriptor());
+          method_names.Add(mh.GetName());
+          filenames.Add(mh.GetDeclaringClassSourceFile());
+        }
+      }
 
-    MethodHelper mh;
-    for (size_t stack_frame = 0; stack_frame < stack_depth; ++stack_frame) {
-      // For each stack frame:
-      // (2b) method's class name
-      // (2b) method name
-      // (2b) method source file
-      // (2b) line number, clipped to 32767; -2 if native; -1 if no source
-      mh.ChangeMethod(record->stack[stack_frame].method);
-      size_t class_name_index = class_names.IndexOf(mh.GetDeclaringClassDescriptor());
-      size_t method_name_index = method_names.IndexOf(mh.GetName());
-      size_t file_name_index = filenames.IndexOf(mh.GetDeclaringClassSourceFile());
-      JDWP::Append2BE(bytes, class_name_index);
-      JDWP::Append2BE(bytes, method_name_index);
-      JDWP::Append2BE(bytes, file_name_index);
-      JDWP::Append2BE(bytes, record->stack[stack_frame].LineNumber());
+      idx = (idx + 1) & (kNumAllocRecords-1);
     }
 
-    idx = (idx + 1) & (kNumAllocRecords-1);
+    LOG(INFO) << "allocation records: " << gAllocRecordCount;
+
+    //
+    // Part 2: Generate the output and store it in the buffer.
+    //
+
+    // (1b) message header len (to allow future expansion); includes itself
+    // (1b) entry header len
+    // (1b) stack frame len
+    const int kMessageHeaderLen = 15;
+    const int kEntryHeaderLen = 9;
+    const int kStackFrameLen = 8;
+    JDWP::Append1BE(bytes, kMessageHeaderLen);
+    JDWP::Append1BE(bytes, kEntryHeaderLen);
+    JDWP::Append1BE(bytes, kStackFrameLen);
+
+    // (2b) number of entries
+    // (4b) offset to string table from start of message
+    // (2b) number of class name strings
+    // (2b) number of method name strings
+    // (2b) number of source file name strings
+    JDWP::Append2BE(bytes, gAllocRecordCount);
+    size_t string_table_offset = bytes.size();
+    JDWP::Append4BE(bytes, 0); // We'll patch this later...
+    JDWP::Append2BE(bytes, class_names.Size());
+    JDWP::Append2BE(bytes, method_names.Size());
+    JDWP::Append2BE(bytes, filenames.Size());
+
+    count = gAllocRecordCount;
+    idx = HeadIndex();
+    ClassHelper kh;
+    while (count--) {
+      // For each entry:
+      // (4b) total allocation size
+      // (2b) thread id
+      // (2b) allocated object's class name index
+      // (1b) stack depth
+      AllocRecord* record = &recent_allocation_records_[idx];
+      size_t stack_depth = record->GetDepth();
+      kh.ChangeClass(record->type);
+      size_t allocated_object_class_name_index = class_names.IndexOf(kh.GetDescriptor());
+      JDWP::Append4BE(bytes, record->byte_count);
+      JDWP::Append2BE(bytes, record->thin_lock_id);
+      JDWP::Append2BE(bytes, allocated_object_class_name_index);
+      JDWP::Append1BE(bytes, stack_depth);
+
+      MethodHelper mh;
+      for (size_t stack_frame = 0; stack_frame < stack_depth; ++stack_frame) {
+        // For each stack frame:
+        // (2b) method's class name
+        // (2b) method name
+        // (2b) method source file
+        // (2b) line number, clipped to 32767; -2 if native; -1 if no source
+        mh.ChangeMethod(record->stack[stack_frame].method);
+        size_t class_name_index = class_names.IndexOf(mh.GetDeclaringClassDescriptor());
+        size_t method_name_index = method_names.IndexOf(mh.GetName());
+        size_t file_name_index = filenames.IndexOf(mh.GetDeclaringClassSourceFile());
+        JDWP::Append2BE(bytes, class_name_index);
+        JDWP::Append2BE(bytes, method_name_index);
+        JDWP::Append2BE(bytes, file_name_index);
+        JDWP::Append2BE(bytes, record->stack[stack_frame].LineNumber());
+      }
+
+      idx = (idx + 1) & (kNumAllocRecords-1);
+    }
+
+    // (xb) class name strings
+    // (xb) method name strings
+    // (xb) source file strings
+    JDWP::Set4BE(&bytes[string_table_offset], bytes.size());
+    class_names.WriteTo(bytes);
+    method_names.WriteTo(bytes);
+    filenames.WriteTo(bytes);
   }
-
-  // (xb) class name strings
-  // (xb) method name strings
-  // (xb) source file strings
-  JDWP::Set4BE(&bytes[string_table_offset], bytes.size());
-  class_names.WriteTo(bytes);
-  method_names.WriteTo(bytes);
-  filenames.WriteTo(bytes);
-
   JNIEnv* env = self->GetJniEnv();
   jbyteArray result = env->NewByteArray(bytes.size());
   if (result != NULL) {