12faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes/*
22faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Copyright (C) 2011 The Android Open Source Project
32faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
42faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
52faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * you may not use this file except in compliance with the License.
62faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * You may obtain a copy of the License at
72faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
82faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
92faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
102faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Unless required by applicable law or agreed to in writing, software
112faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
122faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * See the License for the specific language governing permissions and
142faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * limitations under the License.
152faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes */
16e343b76af81a005ef64f5e75a555389fd9147dabjeffhao
17e343b76af81a005ef64f5e75a555389fd9147dabjeffhao#include "trace.h"
18e343b76af81a005ef64f5e75a555389fd9147dabjeffhao
19a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao#include <sys/uio.h>
200624a27b9a2951bfcf23321a714543e137836904John Reck#include <unistd.h>
21a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
2246ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampe#include "android-base/stringprintf.h"
2346ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampe
24e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier#include "art_method-inl.h"
25e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampe#include "base/casts.h"
26542451cc546779f5c67840e105c51205a1b0a8fdAndreas Gampe#include "base/enums.h"
270abc72ebe356c32354b575c48189965a0edc7890Jeff Hao#include "base/stl_util.h"
2832ce2adefb8a3d0eda59a29f5e87c1eb43eef796Mathieu Chartier#include "base/systrace.h"
2980afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko#include "base/time_utils.h"
30761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes#include "base/unix_file/fd_file.h"
31e343b76af81a005ef64f5e75a555389fd9147dabjeffhao#include "class_linker.h"
3262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers#include "common_throws.h"
33a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao#include "debugger.h"
344f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "dex_file-inl.h"
35aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier#include "gc/scoped_gc_critical_section.h"
36725a957985171d712d5c048cc3d00ff14968784bjeffhao#include "instrumentation.h"
374f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "mirror/class-inl.h"
3840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe#include "mirror/dex_cache-inl.h"
392dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object_array-inl.h"
404f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "mirror/object-inl.h"
41a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao#include "os.h"
420795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier#include "scoped_thread_state_change-inl.h"
430abc72ebe356c32354b575c48189965a0edc7890Jeff Hao#include "ScopedLocalRef.h"
44e343b76af81a005ef64f5e75a555389fd9147dabjeffhao#include "thread.h"
4557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers#include "thread_list.h"
4680afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko#include "utils.h"
47166db04e259ca51838c311891598664deeed85adIan Rogers#include "entrypoints/quick/quick_entrypoints.h"
482692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao
492692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhaonamespace art {
502692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao
5146ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampeusing android::base::StringPrintf;
5246ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampe
534d64cd45acc6a26742e8237eb65136998612820dMathieu Chartierstatic constexpr size_t TraceActionBits = MinimumBitsToStore(
544d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier    static_cast<size_t>(kTraceMethodActionMask));
5540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampestatic constexpr uint8_t kOpNewMethod = 1U;
5640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampestatic constexpr uint8_t kOpNewThread = 2U;
578a5ab9102fe705b63eda6e6bcfe98ee1c03e5a6cShukang Zhoustatic constexpr uint8_t kOpTraceSummary = 3U;
5840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe
590abc72ebe356c32354b575c48189965a0edc7890Jeff Haoclass BuildStackTraceVisitor : public StackVisitor {
600abc72ebe356c32354b575c48189965a0edc7890Jeff Hao public:
618e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray  explicit BuildStackTraceVisitor(Thread* thread)
628e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray      : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
638e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray        method_trace_(Trace::AllocStackTrace()) {}
640abc72ebe356c32354b575c48189965a0edc7890Jeff Hao
65bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe  bool VisitFrame() REQUIRES_SHARED(Locks::mutator_lock_) {
66e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier    ArtMethod* m = GetMethod();
670abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    // Ignore runtime frames (in particular callee save).
680abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    if (!m->IsRuntimeMethod()) {
690abc72ebe356c32354b575c48189965a0edc7890Jeff Hao      method_trace_->push_back(m);
700abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    }
710abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    return true;
720abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  }
730abc72ebe356c32354b575c48189965a0edc7890Jeff Hao
740abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  // Returns a stack trace where the topmost frame corresponds with the first element of the vector.
75e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  std::vector<ArtMethod*>* GetStackTrace() const {
760abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    return method_trace_;
770abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  }
780abc72ebe356c32354b575c48189965a0edc7890Jeff Hao
790abc72ebe356c32354b575c48189965a0edc7890Jeff Hao private:
80e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  std::vector<ArtMethod*>* const method_trace_;
8126f728661a08062a373a3203b72dc2555c2aed2dSebastien Hertz
8226f728661a08062a373a3203b72dc2555c2aed2dSebastien Hertz  DISALLOW_COPY_AND_ASSIGN(BuildStackTraceVisitor);
830abc72ebe356c32354b575c48189965a0edc7890Jeff Hao};
840abc72ebe356c32354b575c48189965a0edc7890Jeff Hao
85a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhaostatic const char     kTraceTokenChar             = '*';
86a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhaostatic const uint16_t kTraceHeaderLength          = 32;
87a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhaostatic const uint32_t kTraceMagicValue            = 0x574f4c53;
88a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhaostatic const uint16_t kTraceVersionSingleClock    = 2;
89a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhaostatic const uint16_t kTraceVersionDualClock      = 3;
904d64cd45acc6a26742e8237eb65136998612820dMathieu Chartierstatic const uint16_t kTraceRecordSizeSingleClock = 10;  // using v2
914d64cd45acc6a26742e8237eb65136998612820dMathieu Chartierstatic const uint16_t kTraceRecordSizeDualClock   = 14;  // using v3 with two timestamps
92a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
93e63db27db913f1a88e2095a1ee8239b2bb9124e8Ian RogersTraceClockSource Trace::default_clock_source_ = kDefaultTraceClockSource;
9462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
9540da286d3207d88ed8ff3f5caac4873874603428Andreas GampeTrace* volatile Trace::the_trace_ = nullptr;
960abc72ebe356c32354b575c48189965a0edc7890Jeff Haopthread_t Trace::sampling_pthread_ = 0U;
97e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartierstd::unique_ptr<std::vector<ArtMethod*>> Trace::temp_stack_trace_;
98e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes
990462c4c87c39db6cfcd338f323844738109ac3c9Sebastien Hertz// The key identifying the tracer to update instrumentation.
1000462c4c87c39db6cfcd338f323844738109ac3c9Sebastien Hertzstatic constexpr const char* kTracerInstrumentationKey = "Tracer";
1010462c4c87c39db6cfcd338f323844738109ac3c9Sebastien Hertz
10262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersstatic TraceAction DecodeTraceAction(uint32_t tmid) {
10362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  return static_cast<TraceAction>(tmid & kTraceMethodActionMask);
104a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao}
105a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
1064d64cd45acc6a26742e8237eb65136998612820dMathieu ChartierArtMethod* Trace::DecodeTraceMethod(uint32_t tmid) {
1074d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier  MutexLock mu(Thread::Current(), *unique_methods_lock_);
1084d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier  return unique_methods_[tmid >> TraceActionBits];
109e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes}
110e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes
1114d64cd45acc6a26742e8237eb65136998612820dMathieu Chartieruint32_t Trace::EncodeTraceMethod(ArtMethod* method) {
1124d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier  MutexLock mu(Thread::Current(), *unique_methods_lock_);
1134d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier  uint32_t idx;
1144d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier  auto it = art_method_id_map_.find(method);
1154d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier  if (it != art_method_id_map_.end()) {
1164d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier    idx = it->second;
1175ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  } else {
1184d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier    unique_methods_.push_back(method);
1194d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier    idx = unique_methods_.size() - 1;
1204d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier    art_method_id_map_.emplace(method, idx);
1215ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  }
1224d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier  DCHECK_LT(idx, unique_methods_.size());
1234d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier  DCHECK_EQ(unique_methods_[idx], method);
1244d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier  return idx;
1254d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier}
1264d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier
1274d64cd45acc6a26742e8237eb65136998612820dMathieu Chartieruint32_t Trace::EncodeTraceMethodAndAction(ArtMethod* method, TraceAction action) {
1284d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier  uint32_t tmid = (EncodeTraceMethod(method) << TraceActionBits) | action;
1294d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier  DCHECK_EQ(method, DecodeTraceMethod(tmid));
1304d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier  return tmid;
1314d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier}
1324d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier
1334d64cd45acc6a26742e8237eb65136998612820dMathieu Chartierstd::vector<ArtMethod*>* Trace::AllocStackTrace() {
1344d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier  return (temp_stack_trace_.get() != nullptr)  ? temp_stack_trace_.release() :
1354d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier      new std::vector<ArtMethod*>();
1365ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao}
1375ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao
138e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartiervoid Trace::FreeStackTrace(std::vector<ArtMethod*>* stack_trace) {
1395ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  stack_trace->clear();
1405ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  temp_stack_trace_.reset(stack_trace);
1415ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao}
1425ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao
143e63db27db913f1a88e2095a1ee8239b2bb9124e8Ian Rogersvoid Trace::SetDefaultClockSource(TraceClockSource clock_source) {
1440a18df82f4dea95b7398f8c934341fccbf04eeeeElliott Hughes#if defined(__linux__)
14562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  default_clock_source_ = clock_source;
146e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes#else
147aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin  if (clock_source != TraceClockSource::kWall) {
1485ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao    LOG(WARNING) << "Ignoring tracing request to use CPU time.";
14962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
150e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes#endif
151a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao}
152a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
153e63db27db913f1a88e2095a1ee8239b2bb9124e8Ian Rogersstatic uint16_t GetTraceVersion(TraceClockSource clock_source) {
154aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin  return (clock_source == TraceClockSource::kDual) ? kTraceVersionDualClock
15562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                                                    : kTraceVersionSingleClock;
15662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
15762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
158e63db27db913f1a88e2095a1ee8239b2bb9124e8Ian Rogersstatic uint16_t GetRecordSize(TraceClockSource clock_source) {
159aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin  return (clock_source == TraceClockSource::kDual) ? kTraceRecordSizeDualClock
16062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                                                    : kTraceRecordSizeSingleClock;
16162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
16262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
16362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersbool Trace::UseThreadCpuClock() {
164aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin  return (clock_source_ == TraceClockSource::kThreadCpu) ||
165aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin      (clock_source_ == TraceClockSource::kDual);
16662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
16762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
168e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughesbool Trace::UseWallClock() {
169aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin  return (clock_source_ == TraceClockSource::kWall) ||
170aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin      (clock_source_ == TraceClockSource::kDual);
171a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao}
172a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
173c5d824a20c225763761a6dff43294b229ff35469Jeff Haovoid Trace::MeasureClockOverhead() {
174c5d824a20c225763761a6dff43294b229ff35469Jeff Hao  if (UseThreadCpuClock()) {
17557dac6ed61a0a25c14d4e2fabc84435578d42360Jeff Hao    Thread::Current()->GetCpuMicroTime();
176a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  }
177c5d824a20c225763761a6dff43294b229ff35469Jeff Hao  if (UseWallClock()) {
178a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    MicroTime();
179a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  }
180a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao}
181a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
1825ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao// Compute an average time taken to measure clocks.
183c5d824a20c225763761a6dff43294b229ff35469Jeff Haouint32_t Trace::GetClockOverheadNanoSeconds() {
18457dac6ed61a0a25c14d4e2fabc84435578d42360Jeff Hao  Thread* self = Thread::Current();
18557dac6ed61a0a25c14d4e2fabc84435578d42360Jeff Hao  uint64_t start = self->GetCpuMicroTime();
186a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
187a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  for (int i = 4000; i > 0; i--) {
188c5d824a20c225763761a6dff43294b229ff35469Jeff Hao    MeasureClockOverhead();
189c5d824a20c225763761a6dff43294b229ff35469Jeff Hao    MeasureClockOverhead();
190c5d824a20c225763761a6dff43294b229ff35469Jeff Hao    MeasureClockOverhead();
191c5d824a20c225763761a6dff43294b229ff35469Jeff Hao    MeasureClockOverhead();
192c5d824a20c225763761a6dff43294b229ff35469Jeff Hao    MeasureClockOverhead();
193c5d824a20c225763761a6dff43294b229ff35469Jeff Hao    MeasureClockOverhead();
194c5d824a20c225763761a6dff43294b229ff35469Jeff Hao    MeasureClockOverhead();
195c5d824a20c225763761a6dff43294b229ff35469Jeff Hao    MeasureClockOverhead();
196a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  }
197a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
1985ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  uint64_t elapsed_us = self->GetCpuMicroTime() - start;
1995ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  return static_cast<uint32_t>(elapsed_us / 32);
200a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao}
201a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
202ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes// TODO: put this somewhere with the big-endian equivalent used by JDWP.
203ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughesstatic void Append2LE(uint8_t* buf, uint16_t val) {
2045ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  *buf++ = static_cast<uint8_t>(val);
2055ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  *buf++ = static_cast<uint8_t>(val >> 8);
206a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao}
207a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
208ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes// TODO: put this somewhere with the big-endian equivalent used by JDWP.
209ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughesstatic void Append4LE(uint8_t* buf, uint32_t val) {
2105ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  *buf++ = static_cast<uint8_t>(val);
2115ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  *buf++ = static_cast<uint8_t>(val >> 8);
2125ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  *buf++ = static_cast<uint8_t>(val >> 16);
2135ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  *buf++ = static_cast<uint8_t>(val >> 24);
214a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao}
215a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
216ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes// TODO: put this somewhere with the big-endian equivalent used by JDWP.
217ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughesstatic void Append8LE(uint8_t* buf, uint64_t val) {
2185ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  *buf++ = static_cast<uint8_t>(val);
2195ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  *buf++ = static_cast<uint8_t>(val >> 8);
2205ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  *buf++ = static_cast<uint8_t>(val >> 16);
2215ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  *buf++ = static_cast<uint8_t>(val >> 24);
2225ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  *buf++ = static_cast<uint8_t>(val >> 32);
2235ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  *buf++ = static_cast<uint8_t>(val >> 40);
2245ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  *buf++ = static_cast<uint8_t>(val >> 48);
2255ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  *buf++ = static_cast<uint8_t>(val >> 56);
226a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao}
227a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
228bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampestatic void GetSample(Thread* thread, void* arg) REQUIRES_SHARED(Locks::mutator_lock_) {
2290abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  BuildStackTraceVisitor build_trace_visitor(thread);
2300abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  build_trace_visitor.WalkStack();
231e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  std::vector<ArtMethod*>* stack_trace = build_trace_visitor.GetStackTrace();
2320abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  Trace* the_trace = reinterpret_cast<Trace*>(arg);
2330abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  the_trace->CompareAndUpdateStackTrace(thread, stack_trace);
2340abc72ebe356c32354b575c48189965a0edc7890Jeff Hao}
2350abc72ebe356c32354b575c48189965a0edc7890Jeff Hao
236ca71458862be8505330b7fd5649a062f31d143dcAndreas Gampestatic void ClearThreadStackTraceAndClockBase(Thread* thread, void* arg ATTRIBUTE_UNUSED) {
2375ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  thread->SetTraceClockBase(0);
238e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  std::vector<ArtMethod*>* stack_trace = thread->GetStackTraceSample();
23940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  thread->SetStackTraceSample(nullptr);
2405ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  delete stack_trace;
2415ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao}
2425ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao
2430abc72ebe356c32354b575c48189965a0edc7890Jeff Haovoid Trace::CompareAndUpdateStackTrace(Thread* thread,
244e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier                                       std::vector<ArtMethod*>* stack_trace) {
2450abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  CHECK_EQ(pthread_self(), sampling_pthread_);
246e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  std::vector<ArtMethod*>* old_stack_trace = thread->GetStackTraceSample();
2475ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  // Update the thread's stack trace sample.
2485ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  thread->SetStackTraceSample(stack_trace);
249c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao  // Read timer clocks to use for all events in this trace.
250c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao  uint32_t thread_clock_diff = 0;
251c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao  uint32_t wall_clock_diff = 0;
252c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao  ReadClocks(thread, &thread_clock_diff, &wall_clock_diff);
25340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  if (old_stack_trace == nullptr) {
2545ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao    // If there's no previous stack trace sample for this thread, log an entry event for all
2550abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    // methods in the trace.
2564d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier    for (auto rit = stack_trace->rbegin(); rit != stack_trace->rend(); ++rit) {
257c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao      LogMethodTraceEvent(thread, *rit, instrumentation::Instrumentation::kMethodEntered,
258c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao                          thread_clock_diff, wall_clock_diff);
2590abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    }
2600abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  } else {
2610abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    // If there's a previous stack trace for this thread, diff the traces and emit entry and exit
2620abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    // events accordingly.
2634d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier    auto old_rit = old_stack_trace->rbegin();
2644d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier    auto rit = stack_trace->rbegin();
2650abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    // Iterate bottom-up over both traces until there's a difference between them.
2660abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    while (old_rit != old_stack_trace->rend() && rit != stack_trace->rend() && *old_rit == *rit) {
2670abc72ebe356c32354b575c48189965a0edc7890Jeff Hao      old_rit++;
2680abc72ebe356c32354b575c48189965a0edc7890Jeff Hao      rit++;
2690abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    }
2700abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    // Iterate top-down over the old trace until the point where they differ, emitting exit events.
2714d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier    for (auto old_it = old_stack_trace->begin(); old_it != old_rit.base(); ++old_it) {
272c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao      LogMethodTraceEvent(thread, *old_it, instrumentation::Instrumentation::kMethodExited,
273c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao                          thread_clock_diff, wall_clock_diff);
2740abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    }
2750abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    // Iterate bottom-up over the new trace from the point where they differ, emitting entry events.
2760abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    for (; rit != stack_trace->rend(); ++rit) {
277c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao      LogMethodTraceEvent(thread, *rit, instrumentation::Instrumentation::kMethodEntered,
278c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao                          thread_clock_diff, wall_clock_diff);
2790abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    }
2805ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao    FreeStackTrace(old_stack_trace);
2810abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  }
2820abc72ebe356c32354b575c48189965a0edc7890Jeff Hao}
2830abc72ebe356c32354b575c48189965a0edc7890Jeff Hao
2840abc72ebe356c32354b575c48189965a0edc7890Jeff Haovoid* Trace::RunSamplingThread(void* arg) {
2850abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  Runtime* runtime = Runtime::Current();
286ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  intptr_t interval_us = reinterpret_cast<intptr_t>(arg);
2874044bdac490777cbc8a12d467bec675ef8aa6eb1Jeff Hao  CHECK_GE(interval_us, 0);
2880abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  CHECK(runtime->AttachCurrentThread("Sampling Profiler", true, runtime->GetSystemThreadGroup(),
289e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier                                     !runtime->IsAotCompiler()));
2900abc72ebe356c32354b575c48189965a0edc7890Jeff Hao
2910abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  while (true) {
29223009dca63c1699e28bfeaa8b45ca48fa0e86aceJeff Hao    usleep(interval_us);
29332ce2adefb8a3d0eda59a29f5e87c1eb43eef796Mathieu Chartier    ScopedTrace trace("Profile sampling");
2940abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    Thread* self = Thread::Current();
2950abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    Trace* the_trace;
2960abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    {
2970abc72ebe356c32354b575c48189965a0edc7890Jeff Hao      MutexLock mu(self, *Locks::trace_lock_);
2980abc72ebe356c32354b575c48189965a0edc7890Jeff Hao      the_trace = the_trace_;
29940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      if (the_trace == nullptr) {
3000abc72ebe356c32354b575c48189965a0edc7890Jeff Hao        break;
3010abc72ebe356c32354b575c48189965a0edc7890Jeff Hao      }
3020abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    }
3030abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    {
3044f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier      ScopedSuspendAll ssa(__FUNCTION__);
3050abc72ebe356c32354b575c48189965a0edc7890Jeff Hao      MutexLock mu(self, *Locks::thread_list_lock_);
3060abc72ebe356c32354b575c48189965a0edc7890Jeff Hao      runtime->GetThreadList()->ForEach(GetSample, the_trace);
3070abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    }
3080abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  }
3090abc72ebe356c32354b575c48189965a0edc7890Jeff Hao
3100abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  runtime->DetachCurrentThread();
31140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  return nullptr;
3120abc72ebe356c32354b575c48189965a0edc7890Jeff Hao}
3130abc72ebe356c32354b575c48189965a0edc7890Jeff Hao
314e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampevoid Trace::Start(const char* trace_filename, int trace_fd, size_t buffer_size, int flags,
3157e7e0f47628fb358da70c5e2766545c4f0596235Andreas Gampe                  TraceOutputMode output_mode, TraceMode trace_mode, int interval_us) {
31662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  Thread* self = Thread::Current();
31762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  {
31862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    MutexLock mu(self, *Locks::trace_lock_);
31940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    if (the_trace_ != nullptr) {
32062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      LOG(ERROR) << "Trace already in progress, ignoring this request";
32162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      return;
32262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    }
323e343b76af81a005ef64f5e75a555389fd9147dabjeffhao  }
324d063d912e5580222b1822b152de315420cef49eeJeff Hao
325d063d912e5580222b1822b152de315420cef49eeJeff Hao  // Check interval if sampling is enabled
3267e7e0f47628fb358da70c5e2766545c4f0596235Andreas Gampe  if (trace_mode == TraceMode::kSampling && interval_us <= 0) {
327d063d912e5580222b1822b152de315420cef49eeJeff Hao    LOG(ERROR) << "Invalid sampling interval: " << interval_us;
328d063d912e5580222b1822b152de315420cef49eeJeff Hao    ScopedObjectAccess soa(self);
329d063d912e5580222b1822b152de315420cef49eeJeff Hao    ThrowRuntimeException("Invalid sampling interval: %d", interval_us);
330d063d912e5580222b1822b152de315420cef49eeJeff Hao    return;
331d063d912e5580222b1822b152de315420cef49eeJeff Hao  }
332a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
3332692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  // Open trace file if not going directly to ddms.
334700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers  std::unique_ptr<File> trace_file;
3357e7e0f47628fb358da70c5e2766545c4f0596235Andreas Gampe  if (output_mode != TraceOutputMode::kDDMS) {
336a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    if (trace_fd < 0) {
337f83e733618066e3c672c9a7ee872a3bba8202e7fCalin Juravle      trace_file.reset(OS::CreateEmptyFileWriteOnly(trace_filename));
338a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    } else {
33962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      trace_file.reset(new File(trace_fd, "tracefile"));
340761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes      trace_file->DisableAutoClose();
341a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    }
34240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    if (trace_file.get() == nullptr) {
343b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao      PLOG(ERROR) << "Unable to open trace file '" << trace_filename << "'";
34462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      ScopedObjectAccess soa(self);
34562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      ThrowRuntimeException("Unable to open trace file '%s'", trace_filename);
346a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao      return;
347a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    }
348a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  }
349a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
350d063d912e5580222b1822b152de315420cef49eeJeff Hao  Runtime* runtime = Runtime::Current();
3519ef78b59da51080882e47505896b420977fd79aeMathieu Chartier
3529ef78b59da51080882e47505896b420977fd79aeMathieu Chartier  // Enable count of allocs if specified in the flags.
3539ef78b59da51080882e47505896b420977fd79aeMathieu Chartier  bool enable_stats = false;
3549ef78b59da51080882e47505896b420977fd79aeMathieu Chartier
3552692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  // Create Trace object.
35662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  {
357aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier    // Required since EnableMethodTracing calls ConfigureStubs which visits class linker classes.
358aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier    gc::ScopedGCCriticalSection gcs(self,
359aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier                                    gc::kGcCauseInstrumentation,
360aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier                                    gc::kCollectorTypeInstrumentation);
3614f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier    ScopedSuspendAll ssa(__FUNCTION__);
36262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    MutexLock mu(self, *Locks::trace_lock_);
36340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    if (the_trace_ != nullptr) {
36462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      LOG(ERROR) << "Trace already in progress, ignoring this request";
36562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    } else {
3669ef78b59da51080882e47505896b420977fd79aeMathieu Chartier      enable_stats = (flags && kTraceCountAllocs) != 0;
36740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      the_trace_ = new Trace(trace_file.release(), trace_filename, buffer_size, flags, output_mode,
36840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe                             trace_mode);
3697e7e0f47628fb358da70c5e2766545c4f0596235Andreas Gampe      if (trace_mode == TraceMode::kSampling) {
37040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe        CHECK_PTHREAD_CALL(pthread_create, (&sampling_pthread_, nullptr, &RunSamplingThread,
37123009dca63c1699e28bfeaa8b45ca48fa0e86aceJeff Hao                                            reinterpret_cast<void*>(interval_us)),
37223009dca63c1699e28bfeaa8b45ca48fa0e86aceJeff Hao                                            "Sampling profiler thread");
37340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe        the_trace_->interval_us_ = interval_us;
3740abc72ebe356c32354b575c48189965a0edc7890Jeff Hao      } else {
3750abc72ebe356c32354b575c48189965a0edc7890Jeff Hao        runtime->GetInstrumentation()->AddListener(the_trace_,
3760abc72ebe356c32354b575c48189965a0edc7890Jeff Hao                                                   instrumentation::Instrumentation::kMethodEntered |
3770abc72ebe356c32354b575c48189965a0edc7890Jeff Hao                                                   instrumentation::Instrumentation::kMethodExited |
3780abc72ebe356c32354b575c48189965a0edc7890Jeff Hao                                                   instrumentation::Instrumentation::kMethodUnwind);
37940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe        // TODO: In full-PIC mode, we don't need to fully deopt.
3800462c4c87c39db6cfcd338f323844738109ac3c9Sebastien Hertz        runtime->GetInstrumentation()->EnableMethodTracing(kTracerInstrumentationKey);
3810abc72ebe356c32354b575c48189965a0edc7890Jeff Hao      }
38262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    }
38362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
384d063d912e5580222b1822b152de315420cef49eeJeff Hao
3859ef78b59da51080882e47505896b420977fd79aeMathieu Chartier  // Can't call this when holding the mutator lock.
3869ef78b59da51080882e47505896b420977fd79aeMathieu Chartier  if (enable_stats) {
3879ef78b59da51080882e47505896b420977fd79aeMathieu Chartier    runtime->SetStatsEnabled(true);
3889ef78b59da51080882e47505896b420977fd79aeMathieu Chartier  }
3892692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao}
3902692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao
39140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampevoid Trace::StopTracing(bool finish_tracing, bool flush_file) {
3929ef78b59da51080882e47505896b420977fd79aeMathieu Chartier  bool stop_alloc_counting = false;
39302e5f160d9cc02da20d9e47af30f948c462f7043Mathieu Chartier  Runtime* const runtime = Runtime::Current();
39402e5f160d9cc02da20d9e47af30f948c462f7043Mathieu Chartier  Trace* the_trace = nullptr;
3959ea02c4f01b079bf6a5f49c62cb59fa5791cbc60Hiroshi Yamauchi  Thread* const self = Thread::Current();
3960abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  pthread_t sampling_pthread = 0U;
39762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  {
3989ea02c4f01b079bf6a5f49c62cb59fa5791cbc60Hiroshi Yamauchi    MutexLock mu(self, *Locks::trace_lock_);
39940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    if (the_trace_ == nullptr) {
40062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      LOG(ERROR) << "Trace stop requested, but no trace currently running";
40162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    } else {
40262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      the_trace = the_trace_;
40340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      the_trace_ = nullptr;
4040abc72ebe356c32354b575c48189965a0edc7890Jeff Hao      sampling_pthread = sampling_pthread_;
40562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    }
4062692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  }
40702e5f160d9cc02da20d9e47af30f948c462f7043Mathieu Chartier  // Make sure that we join before we delete the trace since we don't want to have
40802e5f160d9cc02da20d9e47af30f948c462f7043Mathieu Chartier  // the sampling thread access a stale pointer. This finishes since the sampling thread exits when
40902e5f160d9cc02da20d9e47af30f948c462f7043Mathieu Chartier  // the_trace_ is null.
41002e5f160d9cc02da20d9e47af30f948c462f7043Mathieu Chartier  if (sampling_pthread != 0U) {
41140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    CHECK_PTHREAD_CALL(pthread_join, (sampling_pthread, nullptr), "sampling thread shutdown");
41202e5f160d9cc02da20d9e47af30f948c462f7043Mathieu Chartier    sampling_pthread_ = 0U;
41302e5f160d9cc02da20d9e47af30f948c462f7043Mathieu Chartier  }
41440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe
4154f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier  {
4169ea02c4f01b079bf6a5f49c62cb59fa5791cbc60Hiroshi Yamauchi    gc::ScopedGCCriticalSection gcs(self,
4179ea02c4f01b079bf6a5f49c62cb59fa5791cbc60Hiroshi Yamauchi                                    gc::kGcCauseInstrumentation,
4189ea02c4f01b079bf6a5f49c62cb59fa5791cbc60Hiroshi Yamauchi                                    gc::kCollectorTypeInstrumentation);
4194f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier    ScopedSuspendAll ssa(__FUNCTION__);
4204f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier    if (the_trace != nullptr) {
4214f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier      stop_alloc_counting = (the_trace->flags_ & Trace::kTraceCountAllocs) != 0;
4224f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier      if (finish_tracing) {
4234f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier        the_trace->FinishTracing();
4244f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier      }
4250abc72ebe356c32354b575c48189965a0edc7890Jeff Hao
4264f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier      if (the_trace->trace_mode_ == TraceMode::kSampling) {
4279ea02c4f01b079bf6a5f49c62cb59fa5791cbc60Hiroshi Yamauchi        MutexLock mu(self, *Locks::thread_list_lock_);
4284f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier        runtime->GetThreadList()->ForEach(ClearThreadStackTraceAndClockBase, nullptr);
42940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      } else {
4304f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier        runtime->GetInstrumentation()->DisableMethodTracing(kTracerInstrumentationKey);
4314f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier        runtime->GetInstrumentation()->RemoveListener(
4324f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier            the_trace, instrumentation::Instrumentation::kMethodEntered |
4334f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier            instrumentation::Instrumentation::kMethodExited |
4344f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier            instrumentation::Instrumentation::kMethodUnwind);
4354303ba97313458491e038d78efa041d41cf7bb43Andreas Gampe      }
4364f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier      if (the_trace->trace_file_.get() != nullptr) {
4374f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier        // Do not try to erase, so flush and close explicitly.
4384f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier        if (flush_file) {
4394f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier          if (the_trace->trace_file_->Flush() != 0) {
4404f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier            PLOG(WARNING) << "Could not flush trace file.";
4414f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier          }
4424f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier        } else {
4434f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier          the_trace->trace_file_->MarkUnchecked();  // Do not trigger guard.
4444f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier        }
4454f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier        if (the_trace->trace_file_->Close() != 0) {
4464f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier          PLOG(ERROR) << "Could not close trace file.";
4474f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier        }
4484303ba97313458491e038d78efa041d41cf7bb43Andreas Gampe      }
4494f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier      delete the_trace;
4504303ba97313458491e038d78efa041d41cf7bb43Andreas Gampe    }
45162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
4529ef78b59da51080882e47505896b420977fd79aeMathieu Chartier  if (stop_alloc_counting) {
4539ef78b59da51080882e47505896b420977fd79aeMathieu Chartier    // Can be racy since SetStatsEnabled is not guarded by any locks.
45402e5f160d9cc02da20d9e47af30f948c462f7043Mathieu Chartier    runtime->SetStatsEnabled(false);
4550abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  }
4562692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao}
4572692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao
45840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampevoid Trace::Abort() {
45940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  // Do not write anything anymore.
46040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  StopTracing(false, false);
46140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe}
46240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe
46340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampevoid Trace::Stop() {
46440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  // Finish writing.
46540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  StopTracing(true, true);
46640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe}
46740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe
468b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhaovoid Trace::Shutdown() {
46964caa7dcf46ed6139b766dbe77fbd7353899417fJeff Hao  if (GetMethodTracingMode() != kTracingInactive) {
47062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    Stop();
471b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao  }
472b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao}
473b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao
47440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampevoid Trace::Pause() {
47540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  bool stop_alloc_counting = false;
47640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  Runtime* runtime = Runtime::Current();
47740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  Trace* the_trace = nullptr;
47840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe
479aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier  Thread* const self = Thread::Current();
48040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  pthread_t sampling_pthread = 0U;
48140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  {
482aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier    MutexLock mu(self, *Locks::trace_lock_);
48340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    if (the_trace_ == nullptr) {
48440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      LOG(ERROR) << "Trace pause requested, but no trace currently running";
48540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      return;
48640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    } else {
48740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      the_trace = the_trace_;
48840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      sampling_pthread = sampling_pthread_;
48940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    }
49040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  }
49140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe
49240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  if (sampling_pthread != 0U) {
49340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    {
494aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier      MutexLock mu(self, *Locks::trace_lock_);
49540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      the_trace_ = nullptr;
49640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    }
49740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    CHECK_PTHREAD_CALL(pthread_join, (sampling_pthread, nullptr), "sampling thread shutdown");
49840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    sampling_pthread_ = 0U;
49940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    {
500aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier      MutexLock mu(self, *Locks::trace_lock_);
50140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      the_trace_ = the_trace;
50240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    }
50340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  }
50440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe
50540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  if (the_trace != nullptr) {
506aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier    gc::ScopedGCCriticalSection gcs(self,
507aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier                                    gc::kGcCauseInstrumentation,
508aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier                                    gc::kCollectorTypeInstrumentation);
5094f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier    ScopedSuspendAll ssa(__FUNCTION__);
51040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    stop_alloc_counting = (the_trace->flags_ & Trace::kTraceCountAllocs) != 0;
51140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe
51240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    if (the_trace->trace_mode_ == TraceMode::kSampling) {
513aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier      MutexLock mu(self, *Locks::thread_list_lock_);
51440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      runtime->GetThreadList()->ForEach(ClearThreadStackTraceAndClockBase, nullptr);
51540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    } else {
5160462c4c87c39db6cfcd338f323844738109ac3c9Sebastien Hertz      runtime->GetInstrumentation()->DisableMethodTracing(kTracerInstrumentationKey);
5174f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier      runtime->GetInstrumentation()->RemoveListener(
5184f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier          the_trace,
5194f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier          instrumentation::Instrumentation::kMethodEntered |
5204f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier          instrumentation::Instrumentation::kMethodExited |
5214f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier          instrumentation::Instrumentation::kMethodUnwind);
52240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    }
52340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  }
52440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe
52540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  if (stop_alloc_counting) {
52640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    // Can be racy since SetStatsEnabled is not guarded by any locks.
52740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    Runtime::Current()->SetStatsEnabled(false);
52840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  }
52940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe}
53040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe
53140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampevoid Trace::Resume() {
53240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  Thread* self = Thread::Current();
53340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  Trace* the_trace;
53440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  {
53540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    MutexLock mu(self, *Locks::trace_lock_);
53640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    if (the_trace_ == nullptr) {
53740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      LOG(ERROR) << "No trace to resume (or sampling mode), ignoring this request";
53840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      return;
53940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    }
54040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    the_trace = the_trace_;
54140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  }
54240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe
54340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  Runtime* runtime = Runtime::Current();
54440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe
54540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  // Enable count of allocs if specified in the flags.
54640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  bool enable_stats = (the_trace->flags_ && kTraceCountAllocs) != 0;
54740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe
5484f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier  {
549aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier    gc::ScopedGCCriticalSection gcs(self,
550aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier                                    gc::kGcCauseInstrumentation,
551aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier                                    gc::kCollectorTypeInstrumentation);
5524f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier    ScopedSuspendAll ssa(__FUNCTION__);
55340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe
5544f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier    // Reenable.
5554f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier    if (the_trace->trace_mode_ == TraceMode::kSampling) {
5564f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier      CHECK_PTHREAD_CALL(pthread_create, (&sampling_pthread_, nullptr, &RunSamplingThread,
5574f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier          reinterpret_cast<void*>(the_trace->interval_us_)), "Sampling profiler thread");
5584f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier    } else {
5594f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier      runtime->GetInstrumentation()->AddListener(the_trace,
5604f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier                                                 instrumentation::Instrumentation::kMethodEntered |
5614f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier                                                 instrumentation::Instrumentation::kMethodExited |
5624f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier                                                 instrumentation::Instrumentation::kMethodUnwind);
5634f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier      // TODO: In full-PIC mode, we don't need to fully deopt.
5644f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier      runtime->GetInstrumentation()->EnableMethodTracing(kTracerInstrumentationKey);
5654f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier    }
56640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  }
56740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe
56840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  // Can't call this when holding the mutator lock.
56940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  if (enable_stats) {
57040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    runtime->SetStatsEnabled(true);
57140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  }
57240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe}
57340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe
57464caa7dcf46ed6139b766dbe77fbd7353899417fJeff HaoTracingMode Trace::GetMethodTracingMode() {
57562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  MutexLock mu(Thread::Current(), *Locks::trace_lock_);
57640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  if (the_trace_ == nullptr) {
57764caa7dcf46ed6139b766dbe77fbd7353899417fJeff Hao    return kTracingInactive;
57864caa7dcf46ed6139b766dbe77fbd7353899417fJeff Hao  } else {
5797e7e0f47628fb358da70c5e2766545c4f0596235Andreas Gampe    switch (the_trace_->trace_mode_) {
5807e7e0f47628fb358da70c5e2766545c4f0596235Andreas Gampe      case TraceMode::kSampling:
5817e7e0f47628fb358da70c5e2766545c4f0596235Andreas Gampe        return kSampleProfilingActive;
5827e7e0f47628fb358da70c5e2766545c4f0596235Andreas Gampe      case TraceMode::kMethodTracing:
5837e7e0f47628fb358da70c5e2766545c4f0596235Andreas Gampe        return kMethodTracingActive;
5847e7e0f47628fb358da70c5e2766545c4f0596235Andreas Gampe    }
5857e7e0f47628fb358da70c5e2766545c4f0596235Andreas Gampe    LOG(FATAL) << "Unreachable";
5867e7e0f47628fb358da70c5e2766545c4f0596235Andreas Gampe    UNREACHABLE();
58764caa7dcf46ed6139b766dbe77fbd7353899417fJeff Hao  }
58862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
589a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
590e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampestatic constexpr size_t kMinBufSize = 18U;  // Trace header is up to 18B.
59140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe
592e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas GampeTrace::Trace(File* trace_file, const char* trace_name, size_t buffer_size, int flags,
59340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe             TraceOutputMode output_mode, TraceMode trace_mode)
59440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    : trace_file_(trace_file),
595e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampe      buf_(new uint8_t[std::max(kMinBufSize, buffer_size)]()),
59640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      flags_(flags), trace_output_mode_(output_mode), trace_mode_(trace_mode),
59740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      clock_source_(default_clock_source_),
598e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampe      buffer_size_(std::max(kMinBufSize, buffer_size)),
59940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      start_time_(MicroTime()), clock_overhead_ns_(GetClockOverheadNanoSeconds()), cur_offset_(0),
6004d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier      overflow_(false), interval_us_(0), streaming_lock_(nullptr),
6017526d783ab68ed1dd53c763c75895cb432532b0fAndreas Gampe      unique_methods_lock_(new Mutex("unique methods lock", kTracingUniqueMethodsLock)) {
60262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  uint16_t trace_version = GetTraceVersion(clock_source_);
60340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  if (output_mode == TraceOutputMode::kStreaming) {
60440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    trace_version |= 0xF0U;
60540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  }
60640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  // Set up the beginning of the trace.
6072692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  memset(buf_.get(), 0, kTraceHeaderLength);
6082692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  Append4LE(buf_.get(), kTraceMagicValue);
60962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  Append2LE(buf_.get() + 4, trace_version);
6102692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  Append2LE(buf_.get() + 6, kTraceHeaderLength);
6112692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  Append8LE(buf_.get() + 8, start_time_);
61262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  if (trace_version >= kTraceVersionDualClock) {
61362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    uint16_t record_size = GetRecordSize(clock_source_);
61462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    Append2LE(buf_.get() + 16, record_size);
615a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  }
616e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampe  static_assert(18 <= kMinBufSize, "Minimum buffer size not large enough for trace header");
617a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
6182692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  // Update current offset.
6198ab25ef11aed383bf7d3aa96e95f777972d1b58fIan Rogers  cur_offset_.StoreRelaxed(kTraceHeaderLength);
62040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe
62140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  if (output_mode == TraceOutputMode::kStreaming) {
62240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    streaming_file_name_ = trace_name;
6237526d783ab68ed1dd53c763c75895cb432532b0fAndreas Gampe    streaming_lock_ = new Mutex("tracing lock", LockLevel::kTracingStreamingLock);
62440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    seen_threads_.reset(new ThreadIDBitSet());
62540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  }
62640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe}
62740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe
62840da286d3207d88ed8ff3f5caac4873874603428Andreas GampeTrace::~Trace() {
62940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  delete streaming_lock_;
6307526d783ab68ed1dd53c763c75895cb432532b0fAndreas Gampe  delete unique_methods_lock_;
63162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
63262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
633e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartierstatic uint64_t ReadBytes(uint8_t* buf, size_t bytes) {
634e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  uint64_t ret = 0;
635e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  for (size_t i = 0; i < bytes; ++i) {
636e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier    ret |= static_cast<uint64_t>(buf[i]) << (i * 8);
637e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  }
638e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  return ret;
639e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier}
640e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier
6414d64cd45acc6a26742e8237eb65136998612820dMathieu Chartiervoid Trace::DumpBuf(uint8_t* buf, size_t buf_size, TraceClockSource clock_source) {
64262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  uint8_t* ptr = buf + kTraceHeaderLength;
64362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  uint8_t* end = buf + buf_size;
644a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
64562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  while (ptr < end) {
6464d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier    uint32_t tmid = ReadBytes(ptr + 2, sizeof(tmid));
6474d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier    ArtMethod* method = DecodeTraceMethod(tmid);
64862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    TraceAction action = DecodeTraceAction(tmid);
649709b070044354d9f47641f273edacaeeb0240ab7David Sehr    LOG(INFO) << ArtMethod::PrettyMethod(method) << " " << static_cast<int>(action);
65062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    ptr += GetRecordSize(clock_source);
65162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
652e343b76af81a005ef64f5e75a555389fd9147dabjeffhao}
653e343b76af81a005ef64f5e75a555389fd9147dabjeffhao
65440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampevoid Trace::FinishTracing() {
65540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  size_t final_offset = 0;
656a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
657e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  std::set<ArtMethod*> visited_methods;
65840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  if (trace_output_mode_ == TraceOutputMode::kStreaming) {
65940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    // Clean up.
6604d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier    STLDeleteValues(&seen_methods_);
66140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  } else {
66240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    final_offset = cur_offset_.LoadRelaxed();
66340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    GetVisitedMethods(final_offset, &visited_methods);
66440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  }
66540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe
66640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  // Compute elapsed time.
66740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  uint64_t elapsed = MicroTime() - start_time_;
668a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
669a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  std::ostringstream os;
670a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
671a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  os << StringPrintf("%cversion\n", kTraceTokenChar);
67262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  os << StringPrintf("%d\n", GetTraceVersion(clock_source_));
673a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  os << StringPrintf("data-file-overflow=%s\n", overflow_ ? "true" : "false");
674a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  if (UseThreadCpuClock()) {
675a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    if (UseWallClock()) {
676a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao      os << StringPrintf("clock=dual\n");
677a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    } else {
678a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao      os << StringPrintf("clock=thread-cpu\n");
679a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    }
680a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  } else {
681a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    os << StringPrintf("clock=wall\n");
682a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  }
683ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  os << StringPrintf("elapsed-time-usec=%" PRIu64 "\n", elapsed);
68440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  if (trace_output_mode_ != TraceOutputMode::kStreaming) {
68540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    size_t num_records = (final_offset - kTraceHeaderLength) / GetRecordSize(clock_source_);
68640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    os << StringPrintf("num-method-calls=%zd\n", num_records);
68740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  }
688c5d824a20c225763761a6dff43294b229ff35469Jeff Hao  os << StringPrintf("clock-call-overhead-nsec=%d\n", clock_overhead_ns_);
689a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  os << StringPrintf("vm=art\n");
6900624a27b9a2951bfcf23321a714543e137836904John Reck  os << StringPrintf("pid=%d\n", getpid());
6910791adc2249366c50684935a4c42ba5e58bc3746jeffhao  if ((flags_ & kTraceCountAllocs) != 0) {
6920791adc2249366c50684935a4c42ba5e58bc3746jeffhao    os << StringPrintf("alloc-count=%d\n", Runtime::Current()->GetStat(KIND_ALLOCATED_OBJECTS));
6930791adc2249366c50684935a4c42ba5e58bc3746jeffhao    os << StringPrintf("alloc-size=%d\n", Runtime::Current()->GetStat(KIND_ALLOCATED_BYTES));
6940791adc2249366c50684935a4c42ba5e58bc3746jeffhao    os << StringPrintf("gc-count=%d\n", Runtime::Current()->GetStat(KIND_GC_INVOCATIONS));
6950791adc2249366c50684935a4c42ba5e58bc3746jeffhao  }
696a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  os << StringPrintf("%cthreads\n", kTraceTokenChar);
697a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  DumpThreadList(os);
698a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  os << StringPrintf("%cmethods\n", kTraceTokenChar);
69962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  DumpMethodList(os, visited_methods);
700a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  os << StringPrintf("%cend\n", kTraceTokenChar);
701a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  std::string header(os.str());
70240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe
70340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  if (trace_output_mode_ == TraceOutputMode::kStreaming) {
7048a5ab9102fe705b63eda6e6bcfe98ee1c03e5a6cShukang Zhou    MutexLock mu(Thread::Current(), *streaming_lock_);  // To serialize writing.
7058a5ab9102fe705b63eda6e6bcfe98ee1c03e5a6cShukang Zhou    // Write a special token to mark the end of trace records and the start of
7068a5ab9102fe705b63eda6e6bcfe98ee1c03e5a6cShukang Zhou    // trace summary.
7078a5ab9102fe705b63eda6e6bcfe98ee1c03e5a6cShukang Zhou    uint8_t buf[7];
7088a5ab9102fe705b63eda6e6bcfe98ee1c03e5a6cShukang Zhou    Append2LE(buf, 0);
7098a5ab9102fe705b63eda6e6bcfe98ee1c03e5a6cShukang Zhou    buf[2] = kOpTraceSummary;
7108a5ab9102fe705b63eda6e6bcfe98ee1c03e5a6cShukang Zhou    Append4LE(buf + 3, static_cast<uint32_t>(header.length()));
7118a5ab9102fe705b63eda6e6bcfe98ee1c03e5a6cShukang Zhou    WriteToBuf(buf, sizeof(buf));
7128a5ab9102fe705b63eda6e6bcfe98ee1c03e5a6cShukang Zhou    // Write the trace summary. The summary is identical to the file header when
7138a5ab9102fe705b63eda6e6bcfe98ee1c03e5a6cShukang Zhou    // the output mode is not streaming (except for methods).
7148a5ab9102fe705b63eda6e6bcfe98ee1c03e5a6cShukang Zhou    WriteToBuf(reinterpret_cast<const uint8_t*>(header.c_str()), header.length());
7158a5ab9102fe705b63eda6e6bcfe98ee1c03e5a6cShukang Zhou    // Flush the buffer, which may include some trace records before the summary.
7168a5ab9102fe705b63eda6e6bcfe98ee1c03e5a6cShukang Zhou    FlushBuf();
71740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  } else {
71840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    if (trace_file_.get() == nullptr) {
71940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      iovec iov[2];
72040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      iov[0].iov_base = reinterpret_cast<void*>(const_cast<char*>(header.c_str()));
72140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      iov[0].iov_len = header.length();
72240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      iov[1].iov_base = buf_.get();
72340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      iov[1].iov_len = final_offset;
72440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      Dbg::DdmSendChunkV(CHUNK_TYPE("MPSE"), iov, 2);
72540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      const bool kDumpTraceInfo = false;
72640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      if (kDumpTraceInfo) {
72740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe        LOG(INFO) << "Trace sent:\n" << header;
72840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe        DumpBuf(buf_.get(), final_offset, clock_source_);
72940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      }
73040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    } else {
73140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      if (!trace_file_->WriteFully(header.c_str(), header.length()) ||
73240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe          !trace_file_->WriteFully(buf_.get(), final_offset)) {
73340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe        std::string detail(StringPrintf("Trace data write failed: %s", strerror(errno)));
73440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe        PLOG(ERROR) << detail;
73540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe        ThrowRuntimeException("%s", detail.c_str());
73640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      }
73740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    }
738a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  }
739e343b76af81a005ef64f5e75a555389fd9147dabjeffhao}
740e343b76af81a005ef64f5e75a555389fd9147dabjeffhao
7414b8f1ecd3aa5a29ec1463ff88fee9db365f257dcRoland Levillainvoid Trace::DexPcMoved(Thread* thread ATTRIBUTE_UNUSED,
7424b8f1ecd3aa5a29ec1463ff88fee9db365f257dcRoland Levillain                       mirror::Object* this_object ATTRIBUTE_UNUSED,
7434b8f1ecd3aa5a29ec1463ff88fee9db365f257dcRoland Levillain                       ArtMethod* method,
7444b8f1ecd3aa5a29ec1463ff88fee9db365f257dcRoland Levillain                       uint32_t new_dex_pc) {
74562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // We're not recorded to listen to this kind of event, so complain.
746709b070044354d9f47641f273edacaeeb0240ab7David Sehr  LOG(ERROR) << "Unexpected dex PC event in tracing " << ArtMethod::PrettyMethod(method)
747709b070044354d9f47641f273edacaeeb0240ab7David Sehr             << " " << new_dex_pc;
748c8ccf68b805c92674545f63e0341ba47e8d9701cAndreas Gampe}
74962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
7504b8f1ecd3aa5a29ec1463ff88fee9db365f257dcRoland Levillainvoid Trace::FieldRead(Thread* thread ATTRIBUTE_UNUSED,
7514b8f1ecd3aa5a29ec1463ff88fee9db365f257dcRoland Levillain                      mirror::Object* this_object ATTRIBUTE_UNUSED,
7524b8f1ecd3aa5a29ec1463ff88fee9db365f257dcRoland Levillain                      ArtMethod* method,
7534b8f1ecd3aa5a29ec1463ff88fee9db365f257dcRoland Levillain                      uint32_t dex_pc,
7544b8f1ecd3aa5a29ec1463ff88fee9db365f257dcRoland Levillain                      ArtField* field ATTRIBUTE_UNUSED)
755bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe    REQUIRES_SHARED(Locks::mutator_lock_) {
7563f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz  // We're not recorded to listen to this kind of event, so complain.
757709b070044354d9f47641f273edacaeeb0240ab7David Sehr  LOG(ERROR) << "Unexpected field read event in tracing " << ArtMethod::PrettyMethod(method)
758709b070044354d9f47641f273edacaeeb0240ab7David Sehr             << " " << dex_pc;
7593f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz}
7603f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz
7614b8f1ecd3aa5a29ec1463ff88fee9db365f257dcRoland Levillainvoid Trace::FieldWritten(Thread* thread ATTRIBUTE_UNUSED,
7624b8f1ecd3aa5a29ec1463ff88fee9db365f257dcRoland Levillain                         mirror::Object* this_object ATTRIBUTE_UNUSED,
7634b8f1ecd3aa5a29ec1463ff88fee9db365f257dcRoland Levillain                         ArtMethod* method,
7644b8f1ecd3aa5a29ec1463ff88fee9db365f257dcRoland Levillain                         uint32_t dex_pc,
7654b8f1ecd3aa5a29ec1463ff88fee9db365f257dcRoland Levillain                         ArtField* field ATTRIBUTE_UNUSED,
7664b8f1ecd3aa5a29ec1463ff88fee9db365f257dcRoland Levillain                         const JValue& field_value ATTRIBUTE_UNUSED)
767bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe    REQUIRES_SHARED(Locks::mutator_lock_) {
7683f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz  // We're not recorded to listen to this kind of event, so complain.
769709b070044354d9f47641f273edacaeeb0240ab7David Sehr  LOG(ERROR) << "Unexpected field write event in tracing " << ArtMethod::PrettyMethod(method)
770709b070044354d9f47641f273edacaeeb0240ab7David Sehr             << " " << dex_pc;
7713f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz}
7723f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz
7736a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersvoid Trace::MethodEntered(Thread* thread, mirror::Object* this_object ATTRIBUTE_UNUSED,
774e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier                          ArtMethod* method, uint32_t dex_pc ATTRIBUTE_UNUSED) {
775c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao  uint32_t thread_clock_diff = 0;
776c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao  uint32_t wall_clock_diff = 0;
777c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao  ReadClocks(thread, &thread_clock_diff, &wall_clock_diff);
778c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao  LogMethodTraceEvent(thread, method, instrumentation::Instrumentation::kMethodEntered,
779c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao                      thread_clock_diff, wall_clock_diff);
78062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
78162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
7826a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersvoid Trace::MethodExited(Thread* thread, mirror::Object* this_object ATTRIBUTE_UNUSED,
783e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier                         ArtMethod* method, uint32_t dex_pc ATTRIBUTE_UNUSED,
7846a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers                         const JValue& return_value ATTRIBUTE_UNUSED) {
785c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao  uint32_t thread_clock_diff = 0;
786c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao  uint32_t wall_clock_diff = 0;
787c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao  ReadClocks(thread, &thread_clock_diff, &wall_clock_diff);
788c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao  LogMethodTraceEvent(thread, method, instrumentation::Instrumentation::kMethodExited,
789c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao                      thread_clock_diff, wall_clock_diff);
79062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
79162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
7926a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersvoid Trace::MethodUnwind(Thread* thread, mirror::Object* this_object ATTRIBUTE_UNUSED,
793e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier                         ArtMethod* method, uint32_t dex_pc ATTRIBUTE_UNUSED) {
794c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao  uint32_t thread_clock_diff = 0;
795c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao  uint32_t wall_clock_diff = 0;
796c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao  ReadClocks(thread, &thread_clock_diff, &wall_clock_diff);
797c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao  LogMethodTraceEvent(thread, method, instrumentation::Instrumentation::kMethodUnwind,
798c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao                      thread_clock_diff, wall_clock_diff);
79962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
80062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
8014b8f1ecd3aa5a29ec1463ff88fee9db365f257dcRoland Levillainvoid Trace::ExceptionCaught(Thread* thread ATTRIBUTE_UNUSED,
8024b8f1ecd3aa5a29ec1463ff88fee9db365f257dcRoland Levillain                            mirror::Throwable* exception_object ATTRIBUTE_UNUSED)
803bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe    REQUIRES_SHARED(Locks::mutator_lock_) {
80462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  LOG(ERROR) << "Unexpected exception caught event in tracing";
80562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
806a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
80781f0f953c4bb159997046c962d44cb1898b1778dNicolas Geoffrayvoid Trace::Branch(Thread* /*thread*/, ArtMethod* method,
80881f0f953c4bb159997046c962d44cb1898b1778dNicolas Geoffray                   uint32_t /*dex_pc*/, int32_t /*dex_pc_offset*/)
809bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe      REQUIRES_SHARED(Locks::mutator_lock_) {
810709b070044354d9f47641f273edacaeeb0240ab7David Sehr  LOG(ERROR) << "Unexpected branch event in tracing" << ArtMethod::PrettyMethod(method);
811e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier}
812e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier
8135550ca8bcc742b109d77e62f3a0877c667d894d3Nicolas Geoffrayvoid Trace::InvokeVirtualOrInterface(Thread*,
8145550ca8bcc742b109d77e62f3a0877c667d894d3Nicolas Geoffray                                     mirror::Object*,
8155550ca8bcc742b109d77e62f3a0877c667d894d3Nicolas Geoffray                                     ArtMethod* method,
8165550ca8bcc742b109d77e62f3a0877c667d894d3Nicolas Geoffray                                     uint32_t dex_pc,
8175550ca8bcc742b109d77e62f3a0877c667d894d3Nicolas Geoffray                                     ArtMethod*) {
818709b070044354d9f47641f273edacaeeb0240ab7David Sehr  LOG(ERROR) << "Unexpected invoke event in tracing" << ArtMethod::PrettyMethod(method)
8195550ca8bcc742b109d77e62f3a0877c667d894d3Nicolas Geoffray             << " " << dex_pc;
8205550ca8bcc742b109d77e62f3a0877c667d894d3Nicolas Geoffray}
8215550ca8bcc742b109d77e62f3a0877c667d894d3Nicolas Geoffray
822c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Haovoid Trace::ReadClocks(Thread* thread, uint32_t* thread_clock_diff, uint32_t* wall_clock_diff) {
823c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao  if (UseThreadCpuClock()) {
824c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao    uint64_t clock_base = thread->GetTraceClockBase();
825c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao    if (UNLIKELY(clock_base == 0)) {
826c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao      // First event, record the base time in the map.
827c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao      uint64_t time = thread->GetCpuMicroTime();
828c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao      thread->SetTraceClockBase(time);
829c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao    } else {
830c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao      *thread_clock_diff = thread->GetCpuMicroTime() - clock_base;
831c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao    }
832c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao  }
833c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao  if (UseWallClock()) {
834c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao    *wall_clock_diff = MicroTime() - start_time_;
835c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao  }
836c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao}
837c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao
838e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartierbool Trace::RegisterMethod(ArtMethod* method) {
83940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  mirror::DexCache* dex_cache = method->GetDexCache();
8407526d783ab68ed1dd53c763c75895cb432532b0fAndreas Gampe  const DexFile* dex_file = dex_cache->GetDexFile();
8417526d783ab68ed1dd53c763c75895cb432532b0fAndreas Gampe  if (seen_methods_.find(dex_file) == seen_methods_.end()) {
8427526d783ab68ed1dd53c763c75895cb432532b0fAndreas Gampe    seen_methods_.insert(std::make_pair(dex_file, new DexIndexBitSet()));
84340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  }
8447526d783ab68ed1dd53c763c75895cb432532b0fAndreas Gampe  DexIndexBitSet* bit_set = seen_methods_.find(dex_file)->second;
84540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  if (!(*bit_set)[method->GetDexMethodIndex()]) {
84640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    bit_set->set(method->GetDexMethodIndex());
84740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    return true;
84840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  }
84940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  return false;
85040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe}
85140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe
85240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampebool Trace::RegisterThread(Thread* thread) {
85340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  pid_t tid = thread->GetTid();
85440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  CHECK_LT(0U, static_cast<uint32_t>(tid));
855a344f6a153d84d9adc4f4d3c608538d7741168a9Alex Light  CHECK_LT(static_cast<uint32_t>(tid), kMaxThreadIdNumber);
85640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe
85740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  if (!(*seen_threads_)[tid]) {
85840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    seen_threads_->set(tid);
85940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    return true;
86040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  }
86140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  return false;
86240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe}
86340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe
8644d64cd45acc6a26742e8237eb65136998612820dMathieu Chartierstd::string Trace::GetMethodLine(ArtMethod* method) {
865542451cc546779f5c67840e105c51205a1b0a8fdAndreas Gampe  method = method->GetInterfaceMethodIfProxy(kRuntimePointerSize);
8660f7e8f59698265d416d40844233bb09d02e7fc33Alex Light  return StringPrintf("%#x\t%s\t%s\t%s\t%s\n", (EncodeTraceMethod(method) << TraceActionBits),
86740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      PrettyDescriptor(method->GetDeclaringClassDescriptor()).c_str(), method->GetName(),
86840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      method->GetSignature().ToString().c_str(), method->GetDeclaringClassSourceFile());
86940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe}
87040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe
87140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampevoid Trace::WriteToBuf(const uint8_t* src, size_t src_size) {
87240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  int32_t old_offset = cur_offset_.LoadRelaxed();
87340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  int32_t new_offset = old_offset + static_cast<int32_t>(src_size);
874e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampe  if (dchecked_integral_cast<size_t>(new_offset) > buffer_size_) {
87540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    // Flush buffer.
87640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    if (!trace_file_->WriteFully(buf_.get(), old_offset)) {
87740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      PLOG(WARNING) << "Failed streaming a tracing event.";
87840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    }
879e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampe
880e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampe    // Check whether the data is too large for the buffer, then write immediately.
881e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampe    if (src_size >= buffer_size_) {
882e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampe      if (!trace_file_->WriteFully(src, src_size)) {
883e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampe        PLOG(WARNING) << "Failed streaming a tracing event.";
884e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampe      }
885e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampe      cur_offset_.StoreRelease(0);  // Buffer is empty now.
886e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampe      return;
887e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampe    }
888e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampe
88940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    old_offset = 0;
89040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    new_offset = static_cast<int32_t>(src_size);
89140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  }
89240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  cur_offset_.StoreRelease(new_offset);
89340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  // Fill in data.
89440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  memcpy(buf_.get() + old_offset, src, src_size);
89540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe}
89640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe
8978a5ab9102fe705b63eda6e6bcfe98ee1c03e5a6cShukang Zhouvoid Trace::FlushBuf() {
8988a5ab9102fe705b63eda6e6bcfe98ee1c03e5a6cShukang Zhou  int32_t offset = cur_offset_.LoadRelaxed();
8998a5ab9102fe705b63eda6e6bcfe98ee1c03e5a6cShukang Zhou  if (!trace_file_->WriteFully(buf_.get(), offset)) {
9008a5ab9102fe705b63eda6e6bcfe98ee1c03e5a6cShukang Zhou    PLOG(WARNING) << "Failed flush the remaining data in streaming.";
9018a5ab9102fe705b63eda6e6bcfe98ee1c03e5a6cShukang Zhou  }
9028a5ab9102fe705b63eda6e6bcfe98ee1c03e5a6cShukang Zhou  cur_offset_.StoreRelease(0);
9038a5ab9102fe705b63eda6e6bcfe98ee1c03e5a6cShukang Zhou}
9048a5ab9102fe705b63eda6e6bcfe98ee1c03e5a6cShukang Zhou
905e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartiervoid Trace::LogMethodTraceEvent(Thread* thread, ArtMethod* method,
906c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao                                instrumentation::Instrumentation::InstrumentationEvent event,
907c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao                                uint32_t thread_clock_diff, uint32_t wall_clock_diff) {
9084ba388a39333b13f0f3bcde826444c77fd7166edAlex Light  // Ensure we always use the non-obsolete version of the method so that entry/exit events have the
9094ba388a39333b13f0f3bcde826444c77fd7166edAlex Light  // same pointer value.
9104ba388a39333b13f0f3bcde826444c77fd7166edAlex Light  method = method->GetNonObsoleteMethod();
911a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  // Advance cur_offset_ atomically.
912a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  int32_t new_offset;
91340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  int32_t old_offset = 0;
91440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe
91540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  // We do a busy loop here trying to acquire the next offset.
91640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  if (trace_output_mode_ != TraceOutputMode::kStreaming) {
91740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    do {
91840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      old_offset = cur_offset_.LoadRelaxed();
91940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      new_offset = old_offset + GetRecordSize(clock_source_);
920e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampe      if (static_cast<size_t>(new_offset) > buffer_size_) {
92140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe        overflow_ = true;
92240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe        return;
92340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      }
92440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    } while (!cur_offset_.CompareExchangeWeakSequentiallyConsistent(old_offset, new_offset));
92540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  }
926a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
92762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  TraceAction action = kTraceMethodEnter;
92862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  switch (event) {
92962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    case instrumentation::Instrumentation::kMethodEntered:
93062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      action = kTraceMethodEnter;
93162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      break;
93262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    case instrumentation::Instrumentation::kMethodExited:
93362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      action = kTraceMethodExit;
93462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      break;
93562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    case instrumentation::Instrumentation::kMethodUnwind:
93662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      action = kTraceUnroll;
93762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      break;
93862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    default:
93962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      UNIMPLEMENTED(FATAL) << "Unexpected event: " << event;
94062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
94162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
9424d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier  uint32_t method_value = EncodeTraceMethodAndAction(method, action);
943a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
944a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  // Write data
94540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  uint8_t* ptr;
9464d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier  static constexpr size_t kPacketSize = 14U;  // The maximum size of data in a packet.
94740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  uint8_t stack_buf[kPacketSize];             // Space to store a packet when in streaming mode.
94840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  if (trace_output_mode_ == TraceOutputMode::kStreaming) {
94940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    ptr = stack_buf;
95040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  } else {
95140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    ptr = buf_.get() + old_offset;
95240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  }
95340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe
95462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  Append2LE(ptr, thread->GetTid());
9554d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier  Append4LE(ptr + 2, method_value);
9564d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier  ptr += 6;
957a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
958a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  if (UseThreadCpuClock()) {
959a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    Append4LE(ptr, thread_clock_diff);
960a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    ptr += 4;
961e343b76af81a005ef64f5e75a555389fd9147dabjeffhao  }
962a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  if (UseWallClock()) {
963a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    Append4LE(ptr, wall_clock_diff);
964a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  }
9654d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier  static_assert(kPacketSize == 2 + 4 + 4 + 4, "Packet size incorrect.");
96640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe
96740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  if (trace_output_mode_ == TraceOutputMode::kStreaming) {
96840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    MutexLock mu(Thread::Current(), *streaming_lock_);  // To serialize writing.
96940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    if (RegisterMethod(method)) {
97040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      // Write a special block with the name.
97140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      std::string method_line(GetMethodLine(method));
97240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      uint8_t buf2[5];
97340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      Append2LE(buf2, 0);
97440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      buf2[2] = kOpNewMethod;
97540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      Append2LE(buf2 + 3, static_cast<uint16_t>(method_line.length()));
97640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      WriteToBuf(buf2, sizeof(buf2));
97740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      WriteToBuf(reinterpret_cast<const uint8_t*>(method_line.c_str()), method_line.length());
97840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    }
97940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    if (RegisterThread(thread)) {
98040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      // It might be better to postpone this. Threads might not have received names...
98140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      std::string thread_name;
98240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      thread->GetThreadName(thread_name);
98340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      uint8_t buf2[7];
98440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      Append2LE(buf2, 0);
98540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      buf2[2] = kOpNewThread;
98640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      Append2LE(buf2 + 3, static_cast<uint16_t>(thread->GetTid()));
98740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      Append2LE(buf2 + 5, static_cast<uint16_t>(thread_name.length()));
98840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      WriteToBuf(buf2, sizeof(buf2));
98940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe      WriteToBuf(reinterpret_cast<const uint8_t*>(thread_name.c_str()), thread_name.length());
99040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    }
99140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    WriteToBuf(stack_buf, sizeof(stack_buf));
99240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  }
993a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao}
994a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
99562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid Trace::GetVisitedMethods(size_t buf_size,
996e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier                              std::set<ArtMethod*>* visited_methods) {
9972692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  uint8_t* ptr = buf_.get() + kTraceHeaderLength;
99862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  uint8_t* end = buf_.get() + buf_size;
999a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
1000a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  while (ptr < end) {
10014d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier    uint32_t tmid = ReadBytes(ptr + 2, sizeof(tmid));
10024d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier    ArtMethod* method = DecodeTraceMethod(tmid);
100362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    visited_methods->insert(method);
100462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    ptr += GetRecordSize(clock_source_);
1005a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  }
1006a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao}
1007a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
1008e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartiervoid Trace::DumpMethodList(std::ostream& os, const std::set<ArtMethod*>& visited_methods) {
100902e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier  for (const auto& method : visited_methods) {
101040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe    os << GetMethodLine(method);
1011a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  }
1012a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao}
1013a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
1014a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhaostatic void DumpThread(Thread* t, void* arg) {
1015ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes  std::ostream& os = *reinterpret_cast<std::ostream*>(arg);
1016ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes  std::string name;
1017ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes  t->GetThreadName(name);
1018ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes  os << t->GetTid() << "\t" << name << "\n";
1019a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao}
1020a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
1021a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhaovoid Trace::DumpThreadList(std::ostream& os) {
102281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  Thread* self = Thread::Current();
1023e094b87c6f6ea9ebf83aa56a3114ac59556aaf9fJeff Hao  for (auto it : exited_threads_) {
1024e094b87c6f6ea9ebf83aa56a3114ac59556aaf9fJeff Hao    os << it.first << "\t" << it.second << "\n";
1025e094b87c6f6ea9ebf83aa56a3114ac59556aaf9fJeff Hao  }
102681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  Locks::thread_list_lock_->AssertNotHeld(self);
102781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  MutexLock mu(self, *Locks::thread_list_lock_);
1028a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  Runtime::Current()->GetThreadList()->ForEach(DumpThread, &os);
1029a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao}
1030a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
1031e094b87c6f6ea9ebf83aa56a3114ac59556aaf9fJeff Haovoid Trace::StoreExitingThreadInfo(Thread* thread) {
1032e094b87c6f6ea9ebf83aa56a3114ac59556aaf9fJeff Hao  MutexLock mu(thread, *Locks::trace_lock_);
1033e094b87c6f6ea9ebf83aa56a3114ac59556aaf9fJeff Hao  if (the_trace_ != nullptr) {
1034e094b87c6f6ea9ebf83aa56a3114ac59556aaf9fJeff Hao    std::string name;
1035e094b87c6f6ea9ebf83aa56a3114ac59556aaf9fJeff Hao    thread->GetThreadName(name);
1036a1785c5cd88f6256a838a95c93ac0a1bee6c5145Andreas Gampe    // The same thread/tid may be used multiple times. As SafeMap::Put does not allow to override
1037a1785c5cd88f6256a838a95c93ac0a1bee6c5145Andreas Gampe    // a previous mapping, use SafeMap::Overwrite.
1038a1785c5cd88f6256a838a95c93ac0a1bee6c5145Andreas Gampe    the_trace_->exited_threads_.Overwrite(thread->GetTid(), name);
1039e094b87c6f6ea9ebf83aa56a3114ac59556aaf9fJeff Hao  }
1040e094b87c6f6ea9ebf83aa56a3114ac59556aaf9fJeff Hao}
1041e094b87c6f6ea9ebf83aa56a3114ac59556aaf9fJeff Hao
104240da286d3207d88ed8ff3f5caac4873874603428Andreas GampeTrace::TraceOutputMode Trace::GetOutputMode() {
104340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  MutexLock mu(Thread::Current(), *Locks::trace_lock_);
104440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  CHECK(the_trace_ != nullptr) << "Trace output mode requested, but no trace currently running";
104540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  return the_trace_->trace_output_mode_;
104640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe}
104740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe
104840da286d3207d88ed8ff3f5caac4873874603428Andreas GampeTrace::TraceMode Trace::GetMode() {
104940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  MutexLock mu(Thread::Current(), *Locks::trace_lock_);
105040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  CHECK(the_trace_ != nullptr) << "Trace mode requested, but no trace currently running";
105140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe  return the_trace_->trace_mode_;
105240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe}
105340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe
1054e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampesize_t Trace::GetBufferSize() {
1055e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampe  MutexLock mu(Thread::Current(), *Locks::trace_lock_);
1056e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampe  CHECK(the_trace_ != nullptr) << "Trace mode requested, but no trace currently running";
1057e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampe  return the_trace_->buffer_size_;
1058e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampe}
1059e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampe
10607778b880b9cf46fe7a303b11477bd92b5cf65316Mathieu Chartierbool Trace::IsTracingEnabled() {
10617778b880b9cf46fe7a303b11477bd92b5cf65316Mathieu Chartier  MutexLock mu(Thread::Current(), *Locks::trace_lock_);
10627778b880b9cf46fe7a303b11477bd92b5cf65316Mathieu Chartier  return the_trace_ != nullptr;
10637778b880b9cf46fe7a303b11477bd92b5cf65316Mathieu Chartier}
10647778b880b9cf46fe7a303b11477bd92b5cf65316Mathieu Chartier
1065e343b76af81a005ef64f5e75a555389fd9147dabjeffhao}  // namespace art
1066