Revert^2 "Move GCStress BacktraceHelper to libbacktrace"

By changing to keeping the BacktraceMap in each threads TLS we avoid
having to recreate it each time we do an allocation in GCStress. This
makes running in gcstress significantly faster than it was in the
initial version of this CL.

For test 001-HelloWorld, this has an ~30% measured time cost as
compared to libgcc (from 9.063s to 12.262s). On the other hand it
seems better at actually differentiating distinct stack traces. Total
time spent doing gcs is about doubled (from 4107.91ms to 7036.97ms).
Total number of gcs is about doubled (from 175 to 320).

This reverts commit 7d3256a376709145d6c402a13b1977350816aec2.

Reason for revert: Fixed issue causing gcstress to take too long.

Test: ./test/testrunner/testrunner.py --host --gcstress --jit --64 -t 989
Test: ./test/testrunner/testrunner.py --host --gcstress

Change-Id: I668f53513d8495d4a4c7aa540137676118903f8a
diff --git a/runtime/Android.bp b/runtime/Android.bp
index 8411982..6ec6265 100644
--- a/runtime/Android.bp
+++ b/runtime/Android.bp
@@ -31,6 +31,7 @@
         "aot_class_linker.cc",
         "art_field.cc",
         "art_method.cc",
+        "backtrace_helper.cc",
         "barrier.cc",
         "base/mem_map_arena_pool.cc",
         "base/mutex.cc",
diff --git a/runtime/backtrace_helper.cc b/runtime/backtrace_helper.cc
new file mode 100644
index 0000000..21a0568
--- /dev/null
+++ b/runtime/backtrace_helper.cc
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "backtrace_helper.h"
+
+#if defined(__linux__)
+
+#include <backtrace/Backtrace.h>
+#include <backtrace/BacktraceMap.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+
+#include "thread-inl.h"
+
+#else
+
+// For UNUSED
+#include "base/macros.h"
+
+#endif
+
+namespace art {
+
+// We only really support libbacktrace on linux which is unfortunate but since this is only for
+// gcstress this isn't a huge deal.
+#if defined(__linux__)
+
+static const char* kBacktraceCollectorTlsKey = "BacktraceCollectorTlsKey";
+
+struct BacktraceMapHolder : public TLSData {
+  BacktraceMapHolder() : map_(BacktraceMap::Create(getpid())) {}
+
+  std::unique_ptr<BacktraceMap> map_;
+};
+
+static BacktraceMap* GetMap(Thread* self) {
+  BacktraceMapHolder* map_holder =
+      reinterpret_cast<BacktraceMapHolder*>(self->GetCustomTLS(kBacktraceCollectorTlsKey));
+  if (map_holder == nullptr) {
+    map_holder = new BacktraceMapHolder;
+    // We don't care about the function names. Turning this off makes everything significantly
+    // faster.
+    map_holder->map_->SetResolveNames(false);
+    // Only created and queried on Thread::Current so no sync needed.
+    self->SetCustomTLS(kBacktraceCollectorTlsKey, map_holder);
+  }
+
+  return map_holder->map_.get();
+}
+
+void BacktraceCollector::Collect() {
+  std::unique_ptr<Backtrace> backtrace(Backtrace::Create(BACKTRACE_CURRENT_PROCESS,
+                                                         BACKTRACE_CURRENT_THREAD,
+                                                         GetMap(Thread::Current())));
+  backtrace->SetSkipFrames(true);
+  if (!backtrace->Unwind(skip_count_, nullptr)) {
+    return;
+  }
+  for (Backtrace::const_iterator it = backtrace->begin();
+       max_depth_ > num_frames_ && it != backtrace->end();
+       ++it) {
+    out_frames_[num_frames_++] = static_cast<uintptr_t>(it->pc);
+  }
+}
+
+#else
+
+#pragma clang diagnostic push
+#pragma clang diagnostic warning "-W#warnings"
+#warning "Backtrace collector is not implemented. GCStress cannot be used."
+#pragma clang diagnostic pop
+
+// We only have an implementation for linux. On other plaforms just return nothing. This is not
+// really correct but we only use this for hashing and gcstress so it's not too big a deal.
+void BacktraceCollector::Collect() {
+  UNUSED(skip_count_);
+  UNUSED(out_frames_);
+  UNUSED(max_depth_);
+  num_frames_ = 0;
+}
+
+#endif
+
+}  // namespace art
diff --git a/runtime/backtrace_helper.h b/runtime/backtrace_helper.h
index ace118c..8eda3fa 100644
--- a/runtime/backtrace_helper.h
+++ b/runtime/backtrace_helper.h
@@ -17,11 +17,12 @@
 #ifndef ART_RUNTIME_BACKTRACE_HELPER_H_
 #define ART_RUNTIME_BACKTRACE_HELPER_H_
 
-#include <unwind.h>
+#include <stddef.h>
+#include <stdint.h>
 
 namespace art {
 
-// Based on debug malloc logic from libc/bionic/debug_stacktrace.cpp.
+// Using libbacktrace
 class BacktraceCollector {
  public:
   BacktraceCollector(uintptr_t* out_frames, size_t max_depth, size_t skip_count)
@@ -32,25 +33,9 @@
   }
 
   // Collect the backtrace, do not call more than once.
-  void Collect() {
-    _Unwind_Backtrace(&Callback, this);
-  }
+  void Collect();
 
  private:
-  static _Unwind_Reason_Code Callback(_Unwind_Context* context, void* arg) {
-    auto* const state = reinterpret_cast<BacktraceCollector*>(arg);
-    const uintptr_t ip = _Unwind_GetIP(context);
-    // The first stack frame is get_backtrace itself. Skip it.
-    if (ip != 0 && state->skip_count_ > 0) {
-      --state->skip_count_;
-      return _URC_NO_REASON;
-    }
-    // ip may be off for ARM but it shouldn't matter since we only use it for hashing.
-    state->out_frames_[state->num_frames_] = ip;
-    state->num_frames_++;
-    return state->num_frames_ >= state->max_depth_ ? _URC_END_OF_STACK : _URC_NO_REASON;
-  }
-
   uintptr_t* const out_frames_ = nullptr;
   size_t num_frames_ = 0u;
   const size_t max_depth_ = 0u;