Move GCStress BacktraceHelper to libbacktrace

On host x86_64-linux the libgcc based BacktraceHelper could get
confused by our trampoline instrumentation. This replaces it with the
libbacktrace based stack walker that we use elsewhere in the runtime.
This has the advantage of being generally supported better.

For test 001-HelloWorld, this has an ~300% measured time cost as
compared to libgcc (from 9.063s to 28.587s). 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).

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

Change-Id: I745acb0ae92f312f86c3d31d81cfd179dbf9ae7e
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..c2c0cee
--- /dev/null
+++ b/runtime/backtrace_helper.cc
@@ -0,0 +1,76 @@
+/*
+ * 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>
+
+#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__)
+
+void BacktraceCollector::Collect() {
+  std::unique_ptr<BacktraceMap> map(BacktraceMap::Create(getpid()));
+  // We don't care about the function names. Turning this off makes everything significantly faster.
+  map->SetResolveNames(false);
+  std::unique_ptr<Backtrace> backtrace(Backtrace::Create(BACKTRACE_CURRENT_PROCESS,
+                                                         BACKTRACE_CURRENT_THREAD,
+                                                         map.get()));
+  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;