trace.cc revision e2f77e7592842cad5a59e73535b8982c35e156ca
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>
20a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
210abc72ebe356c32354b575c48189965a0edc7890Jeff Hao#include "base/stl_util.h"
22761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes#include "base/unix_file/fd_file.h"
23e343b76af81a005ef64f5e75a555389fd9147dabjeffhao#include "class_linker.h"
2462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers#include "common_throws.h"
25a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao#include "debugger.h"
264f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "dex_file-inl.h"
27725a957985171d712d5c048cc3d00ff14968784bjeffhao#include "instrumentation.h"
28ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom#include "mirror/art_method-inl.h"
294f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "mirror/class-inl.h"
302dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/dex_cache.h"
312dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object_array-inl.h"
324f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "mirror/object-inl.h"
33a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao#include "object_utils.h"
34a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao#include "os.h"
3500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#include "scoped_thread_state_change.h"
360abc72ebe356c32354b575c48189965a0edc7890Jeff Hao#include "ScopedLocalRef.h"
37e343b76af81a005ef64f5e75a555389fd9147dabjeffhao#include "thread.h"
3857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers#include "thread_list.h"
39166db04e259ca51838c311891598664deeed85adIan Rogers#if !defined(ART_USE_PORTABLE_COMPILER)
40166db04e259ca51838c311891598664deeed85adIan Rogers#include "entrypoints/quick/quick_entrypoints.h"
41166db04e259ca51838c311891598664deeed85adIan Rogers#endif
422692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao
432692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhaonamespace art {
442692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao
45e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes// File format:
46e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes//     header
47e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes//     record 0
48e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes//     record 1
49e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes//     ...
50e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes//
51e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes// Header format:
52e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes//     u4  magic ('SLOW')
53e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes//     u2  version
54e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes//     u2  offset to data
55e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes//     u8  start date/time in usec
56e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes//     u2  record size in bytes (version >= 2 only)
57e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes//     ... padding to 32 bytes
58e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes//
59e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes// Record format v1:
60e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes//     u1  thread ID
61e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes//     u4  method ID | method action
62e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes//     u4  time delta since start, in usec
63e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes//
64e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes// Record format v2:
65e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes//     u2  thread ID
66e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes//     u4  method ID | method action
67e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes//     u4  time delta since start, in usec
68e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes//
69e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes// Record format v3:
70e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes//     u2  thread ID
71e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes//     u4  method ID | method action
72e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes//     u4  time delta since start, in usec
73e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes//     u4  wall time since start, in usec (when clock == "dual" only)
74e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes//
75e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes// 32 bits of microseconds is 70 minutes.
76e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes//
77e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes// All values are stored in little-endian order.
78e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes
7962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersenum TraceAction {
807934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom    kTraceMethodEnter = 0x00,       // method entry
817934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom    kTraceMethodExit = 0x01,        // method exit
827934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom    kTraceUnroll = 0x02,            // method exited by exception unrolling
8362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    // 0x03 currently unused
847934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom    kTraceMethodActionMask = 0x03,  // two bits
8562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers};
8662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
870abc72ebe356c32354b575c48189965a0edc7890Jeff Haoclass BuildStackTraceVisitor : public StackVisitor {
880abc72ebe356c32354b575c48189965a0edc7890Jeff Hao public:
890abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  explicit BuildStackTraceVisitor(Thread* thread) : StackVisitor(thread, NULL),
90e2f77e7592842cad5a59e73535b8982c35e156caIan Rogers      method_trace_(new std::vector<mirror::ArtMethod*>) {}
910abc72ebe356c32354b575c48189965a0edc7890Jeff Hao
920abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  bool VisitFrame() {
93e2f77e7592842cad5a59e73535b8982c35e156caIan Rogers    mirror::ArtMethod* m = GetMethod();
940abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    // Ignore runtime frames (in particular callee save).
950abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    if (!m->IsRuntimeMethod()) {
960abc72ebe356c32354b575c48189965a0edc7890Jeff Hao      method_trace_->push_back(m);
970abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    }
980abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    return true;
990abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  }
1000abc72ebe356c32354b575c48189965a0edc7890Jeff Hao
1010abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  // Returns a stack trace where the topmost frame corresponds with the first element of the vector.
102e2f77e7592842cad5a59e73535b8982c35e156caIan Rogers  std::vector<mirror::ArtMethod*>* GetStackTrace() const {
1030abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    return method_trace_;
1040abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  }
1050abc72ebe356c32354b575c48189965a0edc7890Jeff Hao
1060abc72ebe356c32354b575c48189965a0edc7890Jeff Hao private:
107e2f77e7592842cad5a59e73535b8982c35e156caIan Rogers  std::vector<mirror::ArtMethod*>* const method_trace_;
1080abc72ebe356c32354b575c48189965a0edc7890Jeff Hao};
1090abc72ebe356c32354b575c48189965a0edc7890Jeff Hao
110a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhaostatic const char     kTraceTokenChar             = '*';
111a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhaostatic const uint16_t kTraceHeaderLength          = 32;
112a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhaostatic const uint32_t kTraceMagicValue            = 0x574f4c53;
113a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhaostatic const uint16_t kTraceVersionSingleClock    = 2;
114a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhaostatic const uint16_t kTraceVersionDualClock      = 3;
1157934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstromstatic const uint16_t kTraceRecordSizeSingleClock = 10;  // using v2
1167934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstromstatic const uint16_t kTraceRecordSizeDualClock   = 14;  // using v3 with two timestamps
117a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
11862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers#if defined(HAVE_POSIX_CLOCKS)
11962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian RogersProfilerClockSource Trace::default_clock_source_ = kProfilerClockSourceDual;
12062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers#else
12162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian RogersProfilerClockSource Trace::default_clock_source_ = kProfilerClockSourceWall;
12262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers#endif
12362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
1240abc72ebe356c32354b575c48189965a0edc7890Jeff HaoTrace* volatile Trace::the_trace_ = NULL;
1250abc72ebe356c32354b575c48189965a0edc7890Jeff Hao// TODO: Add way to enable sampling and set interval through gui.
1260abc72ebe356c32354b575c48189965a0edc7890Jeff Haobool Trace::sampling_enabled_ = true;
1270abc72ebe356c32354b575c48189965a0edc7890Jeff Haouint32_t Trace::sampling_interval_us_ = 10000;
1280abc72ebe356c32354b575c48189965a0edc7890Jeff Haopthread_t Trace::sampling_pthread_ = 0U;
129e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes
130ea46f950e7a51585db293cd7f047de190a482414Brian Carlstromstatic mirror::ArtMethod* DecodeTraceMethodId(uint32_t tmid) {
131ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  return reinterpret_cast<mirror::ArtMethod*>(tmid & ~kTraceMethodActionMask);
132a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao}
133e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes
13462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersstatic TraceAction DecodeTraceAction(uint32_t tmid) {
13562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  return static_cast<TraceAction>(tmid & kTraceMethodActionMask);
136a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao}
137a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
138ea46f950e7a51585db293cd7f047de190a482414Brian Carlstromstatic uint32_t EncodeTraceMethodAndAction(const mirror::ArtMethod* method,
13962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                                           TraceAction action) {
14062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  uint32_t tmid = reinterpret_cast<uint32_t>(method) | action;
14162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  DCHECK_EQ(method, DecodeTraceMethodId(tmid));
14262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  return tmid;
143e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes}
144e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes
14562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid Trace::SetDefaultClockSource(ProfilerClockSource clock_source) {
146e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes#if defined(HAVE_POSIX_CLOCKS)
14762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  default_clock_source_ = clock_source;
148e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes#else
14962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  if (clock_source != kProfilerClockSourceWall) {
15062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    LOG(WARNING) << "Ignoring tracing request to use ";
15162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
152e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes#endif
153a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao}
154a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
15562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersstatic uint16_t GetTraceVersion(ProfilerClockSource clock_source) {
15662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  return (clock_source == kProfilerClockSourceDual) ? kTraceVersionDualClock
15762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                                                    : kTraceVersionSingleClock;
15862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
15962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
16062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersstatic uint16_t GetRecordSize(ProfilerClockSource clock_source) {
16162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  return (clock_source == kProfilerClockSourceDual) ? kTraceRecordSizeDualClock
16262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                                                    : kTraceRecordSizeSingleClock;
16362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
16462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
16562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersbool Trace::UseThreadCpuClock() {
16662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  return (clock_source_ == kProfilerClockSourceThreadCpu) ||
16762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      (clock_source_ == kProfilerClockSourceDual);
16862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
16962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
170e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughesbool Trace::UseWallClock() {
17162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  return (clock_source_ == kProfilerClockSourceWall) ||
17262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      (clock_source_ == kProfilerClockSourceDual);
173a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao}
174a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
175e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughesstatic void MeasureClockOverhead(Trace* trace) {
176e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes  if (trace->UseThreadCpuClock()) {
177a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    ThreadCpuMicroTime();
178a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  }
179e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes  if (trace->UseWallClock()) {
180a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    MicroTime();
181a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  }
182a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao}
183a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
184e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughesstatic uint32_t GetClockOverhead(Trace* trace) {
185a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  uint64_t start = ThreadCpuMicroTime();
186a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
187a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  for (int i = 4000; i > 0; i--) {
188e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes    MeasureClockOverhead(trace);
189e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes    MeasureClockOverhead(trace);
190e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes    MeasureClockOverhead(trace);
191e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes    MeasureClockOverhead(trace);
192e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes    MeasureClockOverhead(trace);
193e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes    MeasureClockOverhead(trace);
194e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes    MeasureClockOverhead(trace);
195e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes    MeasureClockOverhead(trace);
196a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  }
197a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
198a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  uint64_t elapsed = ThreadCpuMicroTime() - start;
199a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  return uint32_t (elapsed / 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) {
204a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  *buf++ = (uint8_t) val;
205a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  *buf++ = (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) {
210a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  *buf++ = (uint8_t) val;
211a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  *buf++ = (uint8_t) (val >> 8);
212a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  *buf++ = (uint8_t) (val >> 16);
213a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  *buf++ = (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) {
218a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  *buf++ = (uint8_t) val;
219a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  *buf++ = (uint8_t) (val >> 8);
220a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  *buf++ = (uint8_t) (val >> 16);
221a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  *buf++ = (uint8_t) (val >> 24);
222a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  *buf++ = (uint8_t) (val >> 32);
223a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  *buf++ = (uint8_t) (val >> 40);
224a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  *buf++ = (uint8_t) (val >> 48);
225a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  *buf++ = (uint8_t) (val >> 56);
226a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao}
227a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
2280abc72ebe356c32354b575c48189965a0edc7890Jeff Haostatic void GetSample(Thread* thread, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
2290abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  BuildStackTraceVisitor build_trace_visitor(thread);
2300abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  build_trace_visitor.WalkStack();
231e2f77e7592842cad5a59e73535b8982c35e156caIan Rogers  std::vector<mirror::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
2360abc72ebe356c32354b575c48189965a0edc7890Jeff Haovoid Trace::CompareAndUpdateStackTrace(Thread* thread,
237e2f77e7592842cad5a59e73535b8982c35e156caIan Rogers                                       std::vector<mirror::ArtMethod*>* stack_trace) {
2380abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  CHECK_EQ(pthread_self(), sampling_pthread_);
239e2f77e7592842cad5a59e73535b8982c35e156caIan Rogers  SafeMap<Thread*, std::vector<mirror::ArtMethod*>*>::iterator map_it = thread_stack_trace_map_.find(thread);
2400abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  if (map_it == thread_stack_trace_map_.end()) {
2410abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    // If there's no existing stack trace in the map for this thread, log an entry event for all
2420abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    // methods in the trace.
2430abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    thread_stack_trace_map_.Put(thread, stack_trace);
244e2f77e7592842cad5a59e73535b8982c35e156caIan Rogers    for (std::vector<mirror::ArtMethod*>::reverse_iterator rit = stack_trace->rbegin();
2450abc72ebe356c32354b575c48189965a0edc7890Jeff Hao         rit != stack_trace->rend(); ++rit) {
2460abc72ebe356c32354b575c48189965a0edc7890Jeff Hao      LogMethodTraceEvent(thread, *rit, instrumentation::Instrumentation::kMethodEntered);
2470abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    }
2480abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  } else {
2490abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    // If there's a previous stack trace for this thread, diff the traces and emit entry and exit
2500abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    // events accordingly.
251e2f77e7592842cad5a59e73535b8982c35e156caIan Rogers    std::vector<mirror::ArtMethod*>* old_stack_trace = map_it->second;
2520abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    thread_stack_trace_map_.Overwrite(thread, stack_trace);
253e2f77e7592842cad5a59e73535b8982c35e156caIan Rogers    std::vector<mirror::ArtMethod*>::reverse_iterator old_rit = old_stack_trace->rbegin();
254e2f77e7592842cad5a59e73535b8982c35e156caIan Rogers    std::vector<mirror::ArtMethod*>::reverse_iterator rit = stack_trace->rbegin();
2550abc72ebe356c32354b575c48189965a0edc7890Jeff Hao
2560abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    // Iterate bottom-up over both traces until there's a difference between them.
2570abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    while (old_rit != old_stack_trace->rend() && rit != stack_trace->rend() && *old_rit == *rit) {
2580abc72ebe356c32354b575c48189965a0edc7890Jeff Hao      old_rit++;
2590abc72ebe356c32354b575c48189965a0edc7890Jeff Hao      rit++;
2600abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    }
2610abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    // Iterate top-down over the old trace until the point where they differ, emitting exit events.
262e2f77e7592842cad5a59e73535b8982c35e156caIan Rogers    for (std::vector<mirror::ArtMethod*>::iterator old_it = old_stack_trace->begin();
2630abc72ebe356c32354b575c48189965a0edc7890Jeff Hao         old_it != old_rit.base(); ++old_it) {
2640abc72ebe356c32354b575c48189965a0edc7890Jeff Hao      LogMethodTraceEvent(thread, *old_it, instrumentation::Instrumentation::kMethodExited);
2650abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    }
2660abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    // Iterate bottom-up over the new trace from the point where they differ, emitting entry events.
2670abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    for (; rit != stack_trace->rend(); ++rit) {
2680abc72ebe356c32354b575c48189965a0edc7890Jeff Hao      LogMethodTraceEvent(thread, *rit, instrumentation::Instrumentation::kMethodEntered);
2690abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    }
2700abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    delete old_stack_trace;
2710abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  }
2720abc72ebe356c32354b575c48189965a0edc7890Jeff Hao}
2730abc72ebe356c32354b575c48189965a0edc7890Jeff Hao
2740abc72ebe356c32354b575c48189965a0edc7890Jeff Haovoid* Trace::RunSamplingThread(void* arg) {
2750abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  Runtime* runtime = Runtime::Current();
2760abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  CHECK(runtime->AttachCurrentThread("Sampling Profiler", true, runtime->GetSystemThreadGroup(),
2770abc72ebe356c32354b575c48189965a0edc7890Jeff Hao                                     !runtime->IsCompiler()));
2780abc72ebe356c32354b575c48189965a0edc7890Jeff Hao
2790abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  while (true) {
2800abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    usleep(sampling_interval_us_);
2810abc72ebe356c32354b575c48189965a0edc7890Jeff Hao
2820abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    Thread* self = Thread::Current();
2830abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    Trace* the_trace;
2840abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    {
2850abc72ebe356c32354b575c48189965a0edc7890Jeff Hao      MutexLock mu(self, *Locks::trace_lock_);
2860abc72ebe356c32354b575c48189965a0edc7890Jeff Hao      the_trace = the_trace_;
2870abc72ebe356c32354b575c48189965a0edc7890Jeff Hao      if (the_trace == NULL) {
2880abc72ebe356c32354b575c48189965a0edc7890Jeff Hao        break;
2890abc72ebe356c32354b575c48189965a0edc7890Jeff Hao      }
2900abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    }
2910abc72ebe356c32354b575c48189965a0edc7890Jeff Hao
2920abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    runtime->GetThreadList()->SuspendAll();
2930abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    {
2940abc72ebe356c32354b575c48189965a0edc7890Jeff Hao      MutexLock mu(self, *Locks::thread_list_lock_);
2950abc72ebe356c32354b575c48189965a0edc7890Jeff Hao      runtime->GetThreadList()->ForEach(GetSample, the_trace);
2960abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    }
2970abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    runtime->GetThreadList()->ResumeAll();
2980abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  }
2990abc72ebe356c32354b575c48189965a0edc7890Jeff Hao
3000abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  runtime->DetachCurrentThread();
3010abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  return NULL;
3020abc72ebe356c32354b575c48189965a0edc7890Jeff Hao}
3030abc72ebe356c32354b575c48189965a0edc7890Jeff Hao
30462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid Trace::Start(const char* trace_filename, int trace_fd, int buffer_size, int flags,
30562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                  bool direct_to_ddms) {
30662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  Thread* self = Thread::Current();
30762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  {
30862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    MutexLock mu(self, *Locks::trace_lock_);
30962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    if (the_trace_ != NULL) {
31062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      LOG(ERROR) << "Trace already in progress, ignoring this request";
31162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      return;
31262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    }
313e343b76af81a005ef64f5e75a555389fd9147dabjeffhao  }
31462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  Runtime* runtime = Runtime::Current();
31562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  runtime->GetThreadList()->SuspendAll();
316a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
3172692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  // Open trace file if not going directly to ddms.
31862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  UniquePtr<File> trace_file;
319a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  if (!direct_to_ddms) {
320a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    if (trace_fd < 0) {
32162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      trace_file.reset(OS::OpenFile(trace_filename, true));
322a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    } else {
32362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      trace_file.reset(new File(trace_fd, "tracefile"));
324761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes      trace_file->DisableAutoClose();
325a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    }
32662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    if (trace_file.get() == NULL) {
327b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao      PLOG(ERROR) << "Unable to open trace file '" << trace_filename << "'";
32862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      runtime->GetThreadList()->ResumeAll();
32962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      ScopedObjectAccess soa(self);
33062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      ThrowRuntimeException("Unable to open trace file '%s'", trace_filename);
331a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao      return;
332a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    }
333a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  }
334a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
3352692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  // Create Trace object.
33662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  {
33762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    MutexLock mu(self, *Locks::trace_lock_);
338df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom    if (the_trace_ != NULL) {
33962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      LOG(ERROR) << "Trace already in progress, ignoring this request";
34062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    } else {
34162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      the_trace_ = new Trace(trace_file.release(), buffer_size, flags);
3420791adc2249366c50684935a4c42ba5e58bc3746jeffhao
34362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      // Enable count of allocs if specified in the flags.
34462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      if ((flags && kTraceCountAllocs) != 0) {
34562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers        runtime->SetStatsEnabled(true);
34662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      }
3472692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao
3480abc72ebe356c32354b575c48189965a0edc7890Jeff Hao      if (sampling_enabled_) {
3490abc72ebe356c32354b575c48189965a0edc7890Jeff Hao        CHECK_PTHREAD_CALL(pthread_create, (&sampling_pthread_, NULL, &RunSamplingThread, NULL),
3500abc72ebe356c32354b575c48189965a0edc7890Jeff Hao                           "Sampling profiler thread");
3510abc72ebe356c32354b575c48189965a0edc7890Jeff Hao      } else {
3520abc72ebe356c32354b575c48189965a0edc7890Jeff Hao        runtime->GetInstrumentation()->AddListener(the_trace_,
3530abc72ebe356c32354b575c48189965a0edc7890Jeff Hao                                                   instrumentation::Instrumentation::kMethodEntered |
3540abc72ebe356c32354b575c48189965a0edc7890Jeff Hao                                                   instrumentation::Instrumentation::kMethodExited |
3550abc72ebe356c32354b575c48189965a0edc7890Jeff Hao                                                   instrumentation::Instrumentation::kMethodUnwind);
3560abc72ebe356c32354b575c48189965a0edc7890Jeff Hao      }
35762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    }
35862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
35962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  runtime->GetThreadList()->ResumeAll();
3602692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao}
3612692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao
3622692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhaovoid Trace::Stop() {
36362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  Runtime* runtime = Runtime::Current();
36462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  runtime->GetThreadList()->SuspendAll();
36562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  Trace* the_trace = NULL;
3660abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  pthread_t sampling_pthread = 0U;
36762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  {
36862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    MutexLock mu(Thread::Current(), *Locks::trace_lock_);
36962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    if (the_trace_ == NULL) {
37062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      LOG(ERROR) << "Trace stop requested, but no trace currently running";
37162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    } else {
37262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      the_trace = the_trace_;
37362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      the_trace_ = NULL;
3740abc72ebe356c32354b575c48189965a0edc7890Jeff Hao      sampling_pthread = sampling_pthread_;
3750abc72ebe356c32354b575c48189965a0edc7890Jeff Hao      sampling_pthread_ = 0U;
37662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    }
3772692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  }
37862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  if (the_trace != NULL) {
37962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    the_trace->FinishTracing();
3800abc72ebe356c32354b575c48189965a0edc7890Jeff Hao
3810abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    if (!sampling_enabled_) {
3820abc72ebe356c32354b575c48189965a0edc7890Jeff Hao      runtime->GetInstrumentation()->RemoveListener(the_trace,
3830abc72ebe356c32354b575c48189965a0edc7890Jeff Hao                                                    instrumentation::Instrumentation::kMethodEntered |
3840abc72ebe356c32354b575c48189965a0edc7890Jeff Hao                                                    instrumentation::Instrumentation::kMethodExited |
3850abc72ebe356c32354b575c48189965a0edc7890Jeff Hao                                                    instrumentation::Instrumentation::kMethodUnwind);
3860abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    }
38762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    delete the_trace;
38862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
38962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  runtime->GetThreadList()->ResumeAll();
3900abc72ebe356c32354b575c48189965a0edc7890Jeff Hao
3910abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  if (sampling_enabled_ && sampling_pthread != 0U) {
3920abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    CHECK_PTHREAD_CALL(pthread_join, (sampling_pthread, NULL), "sampling thread shutdown");
3930abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  }
3942692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao}
3952692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao
396b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhaovoid Trace::Shutdown() {
39762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  if (IsMethodTracingActive()) {
39862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    Stop();
399b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao  }
400b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao}
401b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao
40262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersbool Trace::IsMethodTracingActive() {
40362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  MutexLock mu(Thread::Current(), *Locks::trace_lock_);
40462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  return the_trace_ != NULL;
40562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
406a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
40762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian RogersTrace::Trace(File* trace_file, int buffer_size, int flags)
40862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    : trace_file_(trace_file), buf_(new uint8_t[buffer_size]()), flags_(flags),
40962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      clock_source_(default_clock_source_), buffer_size_(buffer_size), start_time_(MicroTime()),
41062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      cur_offset_(0),  overflow_(false) {
411a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  // Set up the beginning of the trace.
41262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  uint16_t trace_version = GetTraceVersion(clock_source_);
4132692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  memset(buf_.get(), 0, kTraceHeaderLength);
4142692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  Append4LE(buf_.get(), kTraceMagicValue);
41562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  Append2LE(buf_.get() + 4, trace_version);
4162692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  Append2LE(buf_.get() + 6, kTraceHeaderLength);
4172692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  Append8LE(buf_.get() + 8, start_time_);
41862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  if (trace_version >= kTraceVersionDualClock) {
41962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    uint16_t record_size = GetRecordSize(clock_source_);
42062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    Append2LE(buf_.get() + 16, record_size);
421a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  }
422a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
4232692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  // Update current offset.
4242692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  cur_offset_ = kTraceHeaderLength;
42562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
42662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
4270abc72ebe356c32354b575c48189965a0edc7890Jeff HaoTrace::~Trace() {
4280abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  CHECK_EQ(sampling_pthread_, static_cast<pthread_t>(0U));
4290abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  STLDeleteValues(&thread_stack_trace_map_);
4300abc72ebe356c32354b575c48189965a0edc7890Jeff Hao}
4310abc72ebe356c32354b575c48189965a0edc7890Jeff Hao
43262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersstatic void DumpBuf(uint8_t* buf, size_t buf_size, ProfilerClockSource clock_source)
43362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
43462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  uint8_t* ptr = buf + kTraceHeaderLength;
43562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  uint8_t* end = buf + buf_size;
436a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
43762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  while (ptr < end) {
43862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    uint32_t tmid = ptr[2] | (ptr[3] << 8) | (ptr[4] << 16) | (ptr[5] << 24);
439ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom    mirror::ArtMethod* method = DecodeTraceMethodId(tmid);
44062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    TraceAction action = DecodeTraceAction(tmid);
44162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    LOG(INFO) << PrettyMethod(method) << " " << static_cast<int>(action);
44262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    ptr += GetRecordSize(clock_source);
44362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
444e343b76af81a005ef64f5e75a555389fd9147dabjeffhao}
445e343b76af81a005ef64f5e75a555389fd9147dabjeffhao
4462692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhaovoid Trace::FinishTracing() {
447a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  // Compute elapsed time.
448a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  uint64_t elapsed = MicroTime() - start_time_;
449a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
450a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  size_t final_offset = cur_offset_;
451e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes  uint32_t clock_overhead = GetClockOverhead(this);
452a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
4530791adc2249366c50684935a4c42ba5e58bc3746jeffhao  if ((flags_ & kTraceCountAllocs) != 0) {
4540791adc2249366c50684935a4c42ba5e58bc3746jeffhao    Runtime::Current()->SetStatsEnabled(false);
4550791adc2249366c50684935a4c42ba5e58bc3746jeffhao  }
4560791adc2249366c50684935a4c42ba5e58bc3746jeffhao
457ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  std::set<mirror::ArtMethod*> visited_methods;
45862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  GetVisitedMethods(final_offset, &visited_methods);
459a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
460a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  std::ostringstream os;
461a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
462a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  os << StringPrintf("%cversion\n", kTraceTokenChar);
46362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  os << StringPrintf("%d\n", GetTraceVersion(clock_source_));
464a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  os << StringPrintf("data-file-overflow=%s\n", overflow_ ? "true" : "false");
465a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  if (UseThreadCpuClock()) {
466a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    if (UseWallClock()) {
467a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao      os << StringPrintf("clock=dual\n");
468a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    } else {
469a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao      os << StringPrintf("clock=thread-cpu\n");
470a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    }
471a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  } else {
472a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    os << StringPrintf("clock=wall\n");
473a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  }
474a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  os << StringPrintf("elapsed-time-usec=%llu\n", elapsed);
47562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  size_t num_records = (final_offset - kTraceHeaderLength) / GetRecordSize(clock_source_);
47662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  os << StringPrintf("num-method-calls=%zd\n", num_records);
477a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  os << StringPrintf("clock-call-overhead-nsec=%d\n", clock_overhead);
478a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  os << StringPrintf("vm=art\n");
4790791adc2249366c50684935a4c42ba5e58bc3746jeffhao  if ((flags_ & kTraceCountAllocs) != 0) {
4800791adc2249366c50684935a4c42ba5e58bc3746jeffhao    os << StringPrintf("alloc-count=%d\n", Runtime::Current()->GetStat(KIND_ALLOCATED_OBJECTS));
4810791adc2249366c50684935a4c42ba5e58bc3746jeffhao    os << StringPrintf("alloc-size=%d\n", Runtime::Current()->GetStat(KIND_ALLOCATED_BYTES));
4820791adc2249366c50684935a4c42ba5e58bc3746jeffhao    os << StringPrintf("gc-count=%d\n", Runtime::Current()->GetStat(KIND_GC_INVOCATIONS));
4830791adc2249366c50684935a4c42ba5e58bc3746jeffhao  }
484a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  os << StringPrintf("%cthreads\n", kTraceTokenChar);
485a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  DumpThreadList(os);
486a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  os << StringPrintf("%cmethods\n", kTraceTokenChar);
48762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  DumpMethodList(os, visited_methods);
488a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  os << StringPrintf("%cend\n", kTraceTokenChar);
489a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
490a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  std::string header(os.str());
4912692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  if (trace_file_.get() == NULL) {
4927b9d996e4cd7d154bb1a244d67139aff0c363cf2Elliott Hughes    iovec iov[2];
493a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    iov[0].iov_base = reinterpret_cast<void*>(const_cast<char*>(header.c_str()));
494a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    iov[0].iov_len = header.length();
4952692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao    iov[1].iov_base = buf_.get();
496a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    iov[1].iov_len = final_offset;
497a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    Dbg::DdmSendChunkV(CHUNK_TYPE("MPSE"), iov, 2);
49862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    const bool kDumpTraceInfo = false;
49962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    if (kDumpTraceInfo) {
50062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      LOG(INFO) << "Trace sent:\n" << header;
50162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      DumpBuf(buf_.get(), final_offset, clock_source_);
50262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    }
503a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  } else {
504a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    if (!trace_file_->WriteFully(header.c_str(), header.length()) ||
5052692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao        !trace_file_->WriteFully(buf_.get(), final_offset)) {
5067b9d996e4cd7d154bb1a244d67139aff0c363cf2Elliott Hughes      std::string detail(StringPrintf("Trace data write failed: %s", strerror(errno)));
5077b9d996e4cd7d154bb1a244d67139aff0c363cf2Elliott Hughes      PLOG(ERROR) << detail;
50862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      ThrowRuntimeException("%s", detail.c_str());
509a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    }
510a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  }
511e343b76af81a005ef64f5e75a555389fd9147dabjeffhao}
512e343b76af81a005ef64f5e75a555389fd9147dabjeffhao
51362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid Trace::DexPcMoved(Thread* thread, mirror::Object* this_object,
514ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                       const mirror::ArtMethod* method, uint32_t new_dex_pc) {
51562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // We're not recorded to listen to this kind of event, so complain.
51662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  LOG(ERROR) << "Unexpected dex PC event in tracing " << PrettyMethod(method) << " " << new_dex_pc;
51762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers};
51862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
51962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid Trace::MethodEntered(Thread* thread, mirror::Object* this_object,
520ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                          const mirror::ArtMethod* method, uint32_t dex_pc) {
52162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  LogMethodTraceEvent(thread, method, instrumentation::Instrumentation::kMethodEntered);
52262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
52362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
52462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid Trace::MethodExited(Thread* thread, mirror::Object* this_object,
525ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                         const mirror::ArtMethod* method, uint32_t dex_pc,
52662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                         const JValue& return_value) {
52762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  UNUSED(return_value);
52862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  LogMethodTraceEvent(thread, method, instrumentation::Instrumentation::kMethodExited);
52962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
53062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
531ea46f950e7a51585db293cd7f047de190a482414Brian Carlstromvoid Trace::MethodUnwind(Thread* thread, const mirror::ArtMethod* method, uint32_t dex_pc) {
53262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  LogMethodTraceEvent(thread, method, instrumentation::Instrumentation::kMethodUnwind);
53362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
53462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
53562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid Trace::ExceptionCaught(Thread* thread, const ThrowLocation& throw_location,
536ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                            mirror::ArtMethod* catch_method, uint32_t catch_dex_pc,
53762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                            mirror::Throwable* exception_object)
53862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
53962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  LOG(ERROR) << "Unexpected exception caught event in tracing";
54062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
541a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
542ea46f950e7a51585db293cd7f047de190a482414Brian Carlstromvoid Trace::LogMethodTraceEvent(Thread* thread, const mirror::ArtMethod* method,
54362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                                instrumentation::Instrumentation::InstrumentationEvent event) {
544a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  // Advance cur_offset_ atomically.
545a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  int32_t new_offset;
546a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  int32_t old_offset;
547a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  do {
548a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    old_offset = cur_offset_;
54962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    new_offset = old_offset + GetRecordSize(clock_source_);
550a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    if (new_offset > buffer_size_) {
551a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao      overflow_ = true;
552a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao      return;
553a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    }
554a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  } while (android_atomic_release_cas(old_offset, new_offset, &cur_offset_) != 0);
555a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
55662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  TraceAction action = kTraceMethodEnter;
55762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  switch (event) {
55862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    case instrumentation::Instrumentation::kMethodEntered:
55962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      action = kTraceMethodEnter;
56062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      break;
56162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    case instrumentation::Instrumentation::kMethodExited:
56262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      action = kTraceMethodExit;
56362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      break;
56462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    case instrumentation::Instrumentation::kMethodUnwind:
56562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      action = kTraceUnroll;
56662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      break;
56762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    default:
56862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      UNIMPLEMENTED(FATAL) << "Unexpected event: " << event;
56962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
57062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
57162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  uint32_t method_value = EncodeTraceMethodAndAction(method, action);
572a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
573a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  // Write data
5742692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  uint8_t* ptr = buf_.get() + old_offset;
57562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  Append2LE(ptr, thread->GetTid());
576a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  Append4LE(ptr + 2, method_value);
577a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  ptr += 6;
578a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
579a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  if (UseThreadCpuClock()) {
58062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    // TODO: this isn't vaguely thread safe.
58162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    SafeMap<Thread*, uint64_t>::iterator it = thread_clock_base_map_.find(thread);
58262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    uint32_t thread_clock_diff = 0;
58362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    if (UNLIKELY(it == thread_clock_base_map_.end())) {
58462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      // First event, the diff is 0, record the base time in the map.
58562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      uint64_t time = ThreadCpuMicroTime();
58662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      thread_clock_base_map_.Put(thread, time);
58762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    } else {
58862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      uint64_t thread_clock_base = it->second;
58962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      thread_clock_diff = ThreadCpuMicroTime() - thread_clock_base;
59062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    }
591a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    Append4LE(ptr, thread_clock_diff);
592a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    ptr += 4;
593e343b76af81a005ef64f5e75a555389fd9147dabjeffhao  }
594a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  if (UseWallClock()) {
595a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    uint32_t wall_clock_diff = MicroTime() - start_time_;
596a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    Append4LE(ptr, wall_clock_diff);
597a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  }
598a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao}
599a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
60062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid Trace::GetVisitedMethods(size_t buf_size,
601ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                              std::set<mirror::ArtMethod*>* visited_methods) {
6022692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  uint8_t* ptr = buf_.get() + kTraceHeaderLength;
60362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  uint8_t* end = buf_.get() + buf_size;
604a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
605a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  while (ptr < end) {
60662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    uint32_t tmid = ptr[2] | (ptr[3] << 8) | (ptr[4] << 16) | (ptr[5] << 24);
607ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom    mirror::ArtMethod* method = DecodeTraceMethodId(tmid);
60862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    visited_methods->insert(method);
60962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    ptr += GetRecordSize(clock_source_);
610a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  }
611a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao}
612a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
61362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid Trace::DumpMethodList(std::ostream& os,
614ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                           const std::set<mirror::ArtMethod*>& visited_methods) {
615ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  typedef std::set<mirror::ArtMethod*>::const_iterator It;  // TODO: C++0x auto
61662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  MethodHelper mh;
61762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  for (It it = visited_methods.begin(); it != visited_methods.end(); ++it) {
618ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom    mirror::ArtMethod* method = *it;
61962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    mh.ChangeMethod(method);
6200399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    os << StringPrintf("%p\t%s\t%s\t%s\t%s\n", method,
621a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao        PrettyDescriptor(mh.GetDeclaringClassDescriptor()).c_str(), mh.GetName(),
6220399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers        mh.GetSignature().c_str(), mh.GetDeclaringClassSourceFile());
623a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  }
624a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao}
625a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
626a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhaostatic void DumpThread(Thread* t, void* arg) {
627ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes  std::ostream& os = *reinterpret_cast<std::ostream*>(arg);
628ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes  std::string name;
629ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes  t->GetThreadName(name);
630ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes  os << t->GetTid() << "\t" << name << "\n";
631a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao}
632a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
633a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhaovoid Trace::DumpThreadList(std::ostream& os) {
63481d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  Thread* self = Thread::Current();
63581d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  Locks::thread_list_lock_->AssertNotHeld(self);
63681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  MutexLock mu(self, *Locks::thread_list_lock_);
637a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  Runtime::Current()->GetThreadList()->ForEach(DumpThread, &os);
638a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao}
639a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
640e343b76af81a005ef64f5e75a555389fd9147dabjeffhao}  // namespace art
641