trace.cc revision 700a402244a1a423da4f3ba8032459f4b65fa18f
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),
905ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao      method_trace_(Trace::AllocStackTrace()) {}
910abc72ebe356c32354b575c48189965a0edc7890Jeff Hao
92ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
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
118491ca9e75fad381468dd7f5fdbff56d1a9738dd7Brian CarlstromProfilerClockSource Trace::default_clock_source_ = kDefaultProfilerClockSource;
11962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
1200abc72ebe356c32354b575c48189965a0edc7890Jeff HaoTrace* volatile Trace::the_trace_ = NULL;
1210abc72ebe356c32354b575c48189965a0edc7890Jeff Haopthread_t Trace::sampling_pthread_ = 0U;
122700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogersstd::unique_ptr<std::vector<mirror::ArtMethod*>> Trace::temp_stack_trace_;
123e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes
124ea46f950e7a51585db293cd7f047de190a482414Brian Carlstromstatic mirror::ArtMethod* DecodeTraceMethodId(uint32_t tmid) {
125ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  return reinterpret_cast<mirror::ArtMethod*>(tmid & ~kTraceMethodActionMask);
126a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao}
127e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes
12862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersstatic TraceAction DecodeTraceAction(uint32_t tmid) {
12962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  return static_cast<TraceAction>(tmid & kTraceMethodActionMask);
130a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao}
131a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
132ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogersstatic uint32_t EncodeTraceMethodAndAction(mirror::ArtMethod* method,
13362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                                           TraceAction action) {
134ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  uint32_t tmid = PointerToLowMemUInt32(method) | action;
13562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  DCHECK_EQ(method, DecodeTraceMethodId(tmid));
13662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  return tmid;
137e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes}
138e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes
1395ce4b178d2483df679e7f718e379305e5d42a300Jeff Haostd::vector<mirror::ArtMethod*>* Trace::AllocStackTrace() {
1405ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  if (temp_stack_trace_.get() != NULL) {
1415ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao    return temp_stack_trace_.release();
1425ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  } else {
1435ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao    return new std::vector<mirror::ArtMethod*>();
1445ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  }
1455ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao}
1465ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao
1475ce4b178d2483df679e7f718e379305e5d42a300Jeff Haovoid Trace::FreeStackTrace(std::vector<mirror::ArtMethod*>* stack_trace) {
1485ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  stack_trace->clear();
1495ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  temp_stack_trace_.reset(stack_trace);
1505ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao}
1515ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao
15262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid Trace::SetDefaultClockSource(ProfilerClockSource clock_source) {
153e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes#if defined(HAVE_POSIX_CLOCKS)
15462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  default_clock_source_ = clock_source;
155e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes#else
15662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  if (clock_source != kProfilerClockSourceWall) {
1575ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao    LOG(WARNING) << "Ignoring tracing request to use CPU time.";
15862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
159e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes#endif
160a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao}
161a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
16262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersstatic uint16_t GetTraceVersion(ProfilerClockSource clock_source) {
16362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  return (clock_source == kProfilerClockSourceDual) ? kTraceVersionDualClock
16462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                                                    : kTraceVersionSingleClock;
16562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
16662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
16762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersstatic uint16_t GetRecordSize(ProfilerClockSource clock_source) {
16862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  return (clock_source == kProfilerClockSourceDual) ? kTraceRecordSizeDualClock
16962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                                                    : kTraceRecordSizeSingleClock;
17062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
17162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
17262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersbool Trace::UseThreadCpuClock() {
17362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  return (clock_source_ == kProfilerClockSourceThreadCpu) ||
17462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      (clock_source_ == kProfilerClockSourceDual);
17562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
17662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
177e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughesbool Trace::UseWallClock() {
17862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  return (clock_source_ == kProfilerClockSourceWall) ||
17962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      (clock_source_ == kProfilerClockSourceDual);
180a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao}
181a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
182e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughesstatic void MeasureClockOverhead(Trace* trace) {
183e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes  if (trace->UseThreadCpuClock()) {
18457dac6ed61a0a25c14d4e2fabc84435578d42360Jeff Hao    Thread::Current()->GetCpuMicroTime();
185a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  }
186e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes  if (trace->UseWallClock()) {
187a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    MicroTime();
188a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  }
189a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao}
190a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
1915ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao// Compute an average time taken to measure clocks.
1925ce4b178d2483df679e7f718e379305e5d42a300Jeff Haostatic uint32_t GetClockOverheadNanoSeconds(Trace* trace) {
19357dac6ed61a0a25c14d4e2fabc84435578d42360Jeff Hao  Thread* self = Thread::Current();
19457dac6ed61a0a25c14d4e2fabc84435578d42360Jeff Hao  uint64_t start = self->GetCpuMicroTime();
195a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
196a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  for (int i = 4000; i > 0; i--) {
197e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes    MeasureClockOverhead(trace);
198e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes    MeasureClockOverhead(trace);
199e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes    MeasureClockOverhead(trace);
200e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes    MeasureClockOverhead(trace);
201e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes    MeasureClockOverhead(trace);
202e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes    MeasureClockOverhead(trace);
203e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes    MeasureClockOverhead(trace);
204e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes    MeasureClockOverhead(trace);
205a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  }
206a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
2075ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  uint64_t elapsed_us = self->GetCpuMicroTime() - start;
2085ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  return static_cast<uint32_t>(elapsed_us / 32);
209a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao}
210a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
211ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes// TODO: put this somewhere with the big-endian equivalent used by JDWP.
212ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughesstatic void Append2LE(uint8_t* buf, uint16_t val) {
2135ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  *buf++ = static_cast<uint8_t>(val);
2145ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  *buf++ = static_cast<uint8_t>(val >> 8);
215a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao}
216a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
217ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes// TODO: put this somewhere with the big-endian equivalent used by JDWP.
218ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughesstatic void Append4LE(uint8_t* buf, uint32_t val) {
2195ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  *buf++ = static_cast<uint8_t>(val);
2205ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  *buf++ = static_cast<uint8_t>(val >> 8);
2215ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  *buf++ = static_cast<uint8_t>(val >> 16);
2225ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  *buf++ = static_cast<uint8_t>(val >> 24);
223a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao}
224a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
225ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes// TODO: put this somewhere with the big-endian equivalent used by JDWP.
226ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughesstatic void Append8LE(uint8_t* buf, uint64_t val) {
2275ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  *buf++ = static_cast<uint8_t>(val);
2285ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  *buf++ = static_cast<uint8_t>(val >> 8);
2295ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  *buf++ = static_cast<uint8_t>(val >> 16);
2305ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  *buf++ = static_cast<uint8_t>(val >> 24);
2315ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  *buf++ = static_cast<uint8_t>(val >> 32);
2325ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  *buf++ = static_cast<uint8_t>(val >> 40);
2335ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  *buf++ = static_cast<uint8_t>(val >> 48);
2345ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  *buf++ = static_cast<uint8_t>(val >> 56);
235a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao}
236a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
2370abc72ebe356c32354b575c48189965a0edc7890Jeff Haostatic void GetSample(Thread* thread, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
2380abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  BuildStackTraceVisitor build_trace_visitor(thread);
2390abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  build_trace_visitor.WalkStack();
240e2f77e7592842cad5a59e73535b8982c35e156caIan Rogers  std::vector<mirror::ArtMethod*>* stack_trace = build_trace_visitor.GetStackTrace();
2410abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  Trace* the_trace = reinterpret_cast<Trace*>(arg);
2420abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  the_trace->CompareAndUpdateStackTrace(thread, stack_trace);
2430abc72ebe356c32354b575c48189965a0edc7890Jeff Hao}
2440abc72ebe356c32354b575c48189965a0edc7890Jeff Hao
2455ce4b178d2483df679e7f718e379305e5d42a300Jeff Haostatic void ClearThreadStackTraceAndClockBase(Thread* thread, void* arg) {
2465ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  thread->SetTraceClockBase(0);
2475ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  std::vector<mirror::ArtMethod*>* stack_trace = thread->GetStackTraceSample();
2485ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  thread->SetStackTraceSample(NULL);
2495ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  delete stack_trace;
2505ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao}
2515ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao
2520abc72ebe356c32354b575c48189965a0edc7890Jeff Haovoid Trace::CompareAndUpdateStackTrace(Thread* thread,
253e2f77e7592842cad5a59e73535b8982c35e156caIan Rogers                                       std::vector<mirror::ArtMethod*>* stack_trace) {
2540abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  CHECK_EQ(pthread_self(), sampling_pthread_);
2555ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  std::vector<mirror::ArtMethod*>* old_stack_trace = thread->GetStackTraceSample();
2565ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  // Update the thread's stack trace sample.
2575ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  thread->SetStackTraceSample(stack_trace);
258c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao  // Read timer clocks to use for all events in this trace.
259c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao  uint32_t thread_clock_diff = 0;
260c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao  uint32_t wall_clock_diff = 0;
261c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao  ReadClocks(thread, &thread_clock_diff, &wall_clock_diff);
2625ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  if (old_stack_trace == NULL) {
2635ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao    // If there's no previous stack trace sample for this thread, log an entry event for all
2640abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    // methods in the trace.
265e2f77e7592842cad5a59e73535b8982c35e156caIan Rogers    for (std::vector<mirror::ArtMethod*>::reverse_iterator rit = stack_trace->rbegin();
2660abc72ebe356c32354b575c48189965a0edc7890Jeff Hao         rit != stack_trace->rend(); ++rit) {
267c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao      LogMethodTraceEvent(thread, *rit, instrumentation::Instrumentation::kMethodEntered,
268c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao                          thread_clock_diff, wall_clock_diff);
2690abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    }
2700abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  } else {
2710abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    // If there's a previous stack trace for this thread, diff the traces and emit entry and exit
2720abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    // events accordingly.
273e2f77e7592842cad5a59e73535b8982c35e156caIan Rogers    std::vector<mirror::ArtMethod*>::reverse_iterator old_rit = old_stack_trace->rbegin();
274e2f77e7592842cad5a59e73535b8982c35e156caIan Rogers    std::vector<mirror::ArtMethod*>::reverse_iterator rit = stack_trace->rbegin();
2750abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    // Iterate bottom-up over both traces until there's a difference between them.
2760abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    while (old_rit != old_stack_trace->rend() && rit != stack_trace->rend() && *old_rit == *rit) {
2770abc72ebe356c32354b575c48189965a0edc7890Jeff Hao      old_rit++;
2780abc72ebe356c32354b575c48189965a0edc7890Jeff Hao      rit++;
2790abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    }
2800abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    // Iterate top-down over the old trace until the point where they differ, emitting exit events.
281e2f77e7592842cad5a59e73535b8982c35e156caIan Rogers    for (std::vector<mirror::ArtMethod*>::iterator old_it = old_stack_trace->begin();
2820abc72ebe356c32354b575c48189965a0edc7890Jeff Hao         old_it != old_rit.base(); ++old_it) {
283c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao      LogMethodTraceEvent(thread, *old_it, instrumentation::Instrumentation::kMethodExited,
284c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao                          thread_clock_diff, wall_clock_diff);
2850abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    }
2860abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    // Iterate bottom-up over the new trace from the point where they differ, emitting entry events.
2870abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    for (; rit != stack_trace->rend(); ++rit) {
288c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao      LogMethodTraceEvent(thread, *rit, instrumentation::Instrumentation::kMethodEntered,
289c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao                          thread_clock_diff, wall_clock_diff);
2900abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    }
2915ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao    FreeStackTrace(old_stack_trace);
2920abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  }
2930abc72ebe356c32354b575c48189965a0edc7890Jeff Hao}
2940abc72ebe356c32354b575c48189965a0edc7890Jeff Hao
2950abc72ebe356c32354b575c48189965a0edc7890Jeff Haovoid* Trace::RunSamplingThread(void* arg) {
2960abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  Runtime* runtime = Runtime::Current();
297ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  intptr_t interval_us = reinterpret_cast<intptr_t>(arg);
2984044bdac490777cbc8a12d467bec675ef8aa6eb1Jeff Hao  CHECK_GE(interval_us, 0);
2990abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  CHECK(runtime->AttachCurrentThread("Sampling Profiler", true, runtime->GetSystemThreadGroup(),
3000abc72ebe356c32354b575c48189965a0edc7890Jeff Hao                                     !runtime->IsCompiler()));
3010abc72ebe356c32354b575c48189965a0edc7890Jeff Hao
3020abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  while (true) {
30323009dca63c1699e28bfeaa8b45ca48fa0e86aceJeff Hao    usleep(interval_us);
3045ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao    ATRACE_BEGIN("Profile sampling");
3050abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    Thread* self = Thread::Current();
3060abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    Trace* the_trace;
3070abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    {
3080abc72ebe356c32354b575c48189965a0edc7890Jeff Hao      MutexLock mu(self, *Locks::trace_lock_);
3090abc72ebe356c32354b575c48189965a0edc7890Jeff Hao      the_trace = the_trace_;
3100abc72ebe356c32354b575c48189965a0edc7890Jeff Hao      if (the_trace == NULL) {
3110abc72ebe356c32354b575c48189965a0edc7890Jeff Hao        break;
3120abc72ebe356c32354b575c48189965a0edc7890Jeff Hao      }
3130abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    }
3140abc72ebe356c32354b575c48189965a0edc7890Jeff Hao
3150abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    runtime->GetThreadList()->SuspendAll();
3160abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    {
3170abc72ebe356c32354b575c48189965a0edc7890Jeff Hao      MutexLock mu(self, *Locks::thread_list_lock_);
3180abc72ebe356c32354b575c48189965a0edc7890Jeff Hao      runtime->GetThreadList()->ForEach(GetSample, the_trace);
3190abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    }
3200abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    runtime->GetThreadList()->ResumeAll();
3215ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao    ATRACE_END();
3220abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  }
3230abc72ebe356c32354b575c48189965a0edc7890Jeff Hao
3240abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  runtime->DetachCurrentThread();
3250abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  return NULL;
3260abc72ebe356c32354b575c48189965a0edc7890Jeff Hao}
3270abc72ebe356c32354b575c48189965a0edc7890Jeff Hao
32862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid Trace::Start(const char* trace_filename, int trace_fd, int buffer_size, int flags,
32923009dca63c1699e28bfeaa8b45ca48fa0e86aceJeff Hao                  bool direct_to_ddms, bool sampling_enabled, int interval_us) {
33062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  Thread* self = Thread::Current();
33162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  {
33262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    MutexLock mu(self, *Locks::trace_lock_);
33362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    if (the_trace_ != NULL) {
33462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      LOG(ERROR) << "Trace already in progress, ignoring this request";
33562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      return;
33662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    }
337e343b76af81a005ef64f5e75a555389fd9147dabjeffhao  }
33862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  Runtime* runtime = Runtime::Current();
33962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  runtime->GetThreadList()->SuspendAll();
340a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
3412692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  // Open trace file if not going directly to ddms.
342700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers  std::unique_ptr<File> trace_file;
343a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  if (!direct_to_ddms) {
344a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    if (trace_fd < 0) {
3457571e8b761ebc2c923525e12ea9fcf07e62cb33eBrian Carlstrom      trace_file.reset(OS::CreateEmptyFile(trace_filename));
346a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    } else {
34762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      trace_file.reset(new File(trace_fd, "tracefile"));
348761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes      trace_file->DisableAutoClose();
349a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    }
35062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    if (trace_file.get() == NULL) {
351b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao      PLOG(ERROR) << "Unable to open trace file '" << trace_filename << "'";
35262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      runtime->GetThreadList()->ResumeAll();
35362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      ScopedObjectAccess soa(self);
35462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      ThrowRuntimeException("Unable to open trace file '%s'", trace_filename);
355a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao      return;
356a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    }
357a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  }
358a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
3592692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  // Create Trace object.
36062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  {
36162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    MutexLock mu(self, *Locks::trace_lock_);
362df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom    if (the_trace_ != NULL) {
36362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      LOG(ERROR) << "Trace already in progress, ignoring this request";
36462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    } else {
36523009dca63c1699e28bfeaa8b45ca48fa0e86aceJeff Hao      the_trace_ = new Trace(trace_file.release(), buffer_size, flags, sampling_enabled);
3660791adc2249366c50684935a4c42ba5e58bc3746jeffhao
36762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      // Enable count of allocs if specified in the flags.
36862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      if ((flags && kTraceCountAllocs) != 0) {
36962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers        runtime->SetStatsEnabled(true);
37062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      }
3712692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao
37223009dca63c1699e28bfeaa8b45ca48fa0e86aceJeff Hao
37323009dca63c1699e28bfeaa8b45ca48fa0e86aceJeff Hao
37423009dca63c1699e28bfeaa8b45ca48fa0e86aceJeff Hao      if (sampling_enabled) {
37523009dca63c1699e28bfeaa8b45ca48fa0e86aceJeff Hao        CHECK_PTHREAD_CALL(pthread_create, (&sampling_pthread_, NULL, &RunSamplingThread,
37623009dca63c1699e28bfeaa8b45ca48fa0e86aceJeff Hao                                            reinterpret_cast<void*>(interval_us)),
37723009dca63c1699e28bfeaa8b45ca48fa0e86aceJeff Hao                                            "Sampling profiler thread");
3780abc72ebe356c32354b575c48189965a0edc7890Jeff Hao      } else {
3790abc72ebe356c32354b575c48189965a0edc7890Jeff Hao        runtime->GetInstrumentation()->AddListener(the_trace_,
3800abc72ebe356c32354b575c48189965a0edc7890Jeff Hao                                                   instrumentation::Instrumentation::kMethodEntered |
3810abc72ebe356c32354b575c48189965a0edc7890Jeff Hao                                                   instrumentation::Instrumentation::kMethodExited |
3820abc72ebe356c32354b575c48189965a0edc7890Jeff Hao                                                   instrumentation::Instrumentation::kMethodUnwind);
383138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz        runtime->GetInstrumentation()->EnableMethodTracing();
3840abc72ebe356c32354b575c48189965a0edc7890Jeff Hao      }
38562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    }
38662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
38762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  runtime->GetThreadList()->ResumeAll();
3882692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao}
3892692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao
3902692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhaovoid Trace::Stop() {
39162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  Runtime* runtime = Runtime::Current();
39262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  runtime->GetThreadList()->SuspendAll();
39362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  Trace* the_trace = NULL;
3940abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  pthread_t sampling_pthread = 0U;
39562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  {
39662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    MutexLock mu(Thread::Current(), *Locks::trace_lock_);
39762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    if (the_trace_ == NULL) {
39862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      LOG(ERROR) << "Trace stop requested, but no trace currently running";
39962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    } else {
40062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      the_trace = the_trace_;
40162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      the_trace_ = NULL;
4020abc72ebe356c32354b575c48189965a0edc7890Jeff Hao      sampling_pthread = sampling_pthread_;
4030abc72ebe356c32354b575c48189965a0edc7890Jeff Hao      sampling_pthread_ = 0U;
40462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    }
4052692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  }
40662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  if (the_trace != NULL) {
40762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    the_trace->FinishTracing();
4080abc72ebe356c32354b575c48189965a0edc7890Jeff Hao
40923009dca63c1699e28bfeaa8b45ca48fa0e86aceJeff Hao    if (the_trace->sampling_enabled_) {
4105ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao      MutexLock mu(Thread::Current(), *Locks::thread_list_lock_);
4115ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao      runtime->GetThreadList()->ForEach(ClearThreadStackTraceAndClockBase, NULL);
4125ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao    } else {
413138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz      runtime->GetInstrumentation()->DisableMethodTracing();
4140abc72ebe356c32354b575c48189965a0edc7890Jeff Hao      runtime->GetInstrumentation()->RemoveListener(the_trace,
4150abc72ebe356c32354b575c48189965a0edc7890Jeff Hao                                                    instrumentation::Instrumentation::kMethodEntered |
4160abc72ebe356c32354b575c48189965a0edc7890Jeff Hao                                                    instrumentation::Instrumentation::kMethodExited |
4170abc72ebe356c32354b575c48189965a0edc7890Jeff Hao                                                    instrumentation::Instrumentation::kMethodUnwind);
4180abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    }
41962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    delete the_trace;
42062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
42162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  runtime->GetThreadList()->ResumeAll();
4220abc72ebe356c32354b575c48189965a0edc7890Jeff Hao
42323009dca63c1699e28bfeaa8b45ca48fa0e86aceJeff Hao  if (sampling_pthread != 0U) {
4240abc72ebe356c32354b575c48189965a0edc7890Jeff Hao    CHECK_PTHREAD_CALL(pthread_join, (sampling_pthread, NULL), "sampling thread shutdown");
4250abc72ebe356c32354b575c48189965a0edc7890Jeff Hao  }
4262692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao}
4272692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao
428b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhaovoid Trace::Shutdown() {
42964caa7dcf46ed6139b766dbe77fbd7353899417fJeff Hao  if (GetMethodTracingMode() != kTracingInactive) {
43062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    Stop();
431b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao  }
432b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao}
433b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao
43464caa7dcf46ed6139b766dbe77fbd7353899417fJeff HaoTracingMode Trace::GetMethodTracingMode() {
43562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  MutexLock mu(Thread::Current(), *Locks::trace_lock_);
43664caa7dcf46ed6139b766dbe77fbd7353899417fJeff Hao  if (the_trace_ == NULL) {
43764caa7dcf46ed6139b766dbe77fbd7353899417fJeff Hao    return kTracingInactive;
43864caa7dcf46ed6139b766dbe77fbd7353899417fJeff Hao  } else if (the_trace_->sampling_enabled_) {
43964caa7dcf46ed6139b766dbe77fbd7353899417fJeff Hao    return kSampleProfilingActive;
44064caa7dcf46ed6139b766dbe77fbd7353899417fJeff Hao  } else {
44164caa7dcf46ed6139b766dbe77fbd7353899417fJeff Hao    return kMethodTracingActive;
44264caa7dcf46ed6139b766dbe77fbd7353899417fJeff Hao  }
44362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
444a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
44523009dca63c1699e28bfeaa8b45ca48fa0e86aceJeff HaoTrace::Trace(File* trace_file, int buffer_size, int flags, bool sampling_enabled)
44662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    : trace_file_(trace_file), buf_(new uint8_t[buffer_size]()), flags_(flags),
44723009dca63c1699e28bfeaa8b45ca48fa0e86aceJeff Hao      sampling_enabled_(sampling_enabled), clock_source_(default_clock_source_),
44823009dca63c1699e28bfeaa8b45ca48fa0e86aceJeff Hao      buffer_size_(buffer_size), start_time_(MicroTime()), cur_offset_(0),  overflow_(false) {
449a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  // Set up the beginning of the trace.
45062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  uint16_t trace_version = GetTraceVersion(clock_source_);
4512692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  memset(buf_.get(), 0, kTraceHeaderLength);
4522692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  Append4LE(buf_.get(), kTraceMagicValue);
45362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  Append2LE(buf_.get() + 4, trace_version);
4542692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  Append2LE(buf_.get() + 6, kTraceHeaderLength);
4552692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  Append8LE(buf_.get() + 8, start_time_);
45662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  if (trace_version >= kTraceVersionDualClock) {
45762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    uint16_t record_size = GetRecordSize(clock_source_);
45862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    Append2LE(buf_.get() + 16, record_size);
459a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  }
460a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
4612692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  // Update current offset.
4622692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  cur_offset_ = kTraceHeaderLength;
46362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
46462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
46562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersstatic void DumpBuf(uint8_t* buf, size_t buf_size, ProfilerClockSource clock_source)
46662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
46762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  uint8_t* ptr = buf + kTraceHeaderLength;
46862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  uint8_t* end = buf + buf_size;
469a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
47062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  while (ptr < end) {
47162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    uint32_t tmid = ptr[2] | (ptr[3] << 8) | (ptr[4] << 16) | (ptr[5] << 24);
472ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom    mirror::ArtMethod* method = DecodeTraceMethodId(tmid);
47362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    TraceAction action = DecodeTraceAction(tmid);
47462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    LOG(INFO) << PrettyMethod(method) << " " << static_cast<int>(action);
47562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    ptr += GetRecordSize(clock_source);
47662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
477e343b76af81a005ef64f5e75a555389fd9147dabjeffhao}
478e343b76af81a005ef64f5e75a555389fd9147dabjeffhao
4792692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhaovoid Trace::FinishTracing() {
480a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  // Compute elapsed time.
481a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  uint64_t elapsed = MicroTime() - start_time_;
482a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
483a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  size_t final_offset = cur_offset_;
4845ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  uint32_t clock_overhead_ns = GetClockOverheadNanoSeconds(this);
485a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
4860791adc2249366c50684935a4c42ba5e58bc3746jeffhao  if ((flags_ & kTraceCountAllocs) != 0) {
4870791adc2249366c50684935a4c42ba5e58bc3746jeffhao    Runtime::Current()->SetStatsEnabled(false);
4880791adc2249366c50684935a4c42ba5e58bc3746jeffhao  }
4890791adc2249366c50684935a4c42ba5e58bc3746jeffhao
490ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  std::set<mirror::ArtMethod*> visited_methods;
49162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  GetVisitedMethods(final_offset, &visited_methods);
492a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
493a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  std::ostringstream os;
494a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
495a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  os << StringPrintf("%cversion\n", kTraceTokenChar);
49662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  os << StringPrintf("%d\n", GetTraceVersion(clock_source_));
497a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  os << StringPrintf("data-file-overflow=%s\n", overflow_ ? "true" : "false");
498a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  if (UseThreadCpuClock()) {
499a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    if (UseWallClock()) {
500a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao      os << StringPrintf("clock=dual\n");
501a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    } else {
502a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao      os << StringPrintf("clock=thread-cpu\n");
503a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    }
504a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  } else {
505a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    os << StringPrintf("clock=wall\n");
506a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  }
507ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  os << StringPrintf("elapsed-time-usec=%" PRIu64 "\n", elapsed);
50862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  size_t num_records = (final_offset - kTraceHeaderLength) / GetRecordSize(clock_source_);
50962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  os << StringPrintf("num-method-calls=%zd\n", num_records);
5105ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao  os << StringPrintf("clock-call-overhead-nsec=%d\n", clock_overhead_ns);
511a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  os << StringPrintf("vm=art\n");
5120791adc2249366c50684935a4c42ba5e58bc3746jeffhao  if ((flags_ & kTraceCountAllocs) != 0) {
5130791adc2249366c50684935a4c42ba5e58bc3746jeffhao    os << StringPrintf("alloc-count=%d\n", Runtime::Current()->GetStat(KIND_ALLOCATED_OBJECTS));
5140791adc2249366c50684935a4c42ba5e58bc3746jeffhao    os << StringPrintf("alloc-size=%d\n", Runtime::Current()->GetStat(KIND_ALLOCATED_BYTES));
5150791adc2249366c50684935a4c42ba5e58bc3746jeffhao    os << StringPrintf("gc-count=%d\n", Runtime::Current()->GetStat(KIND_GC_INVOCATIONS));
5160791adc2249366c50684935a4c42ba5e58bc3746jeffhao  }
517a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  os << StringPrintf("%cthreads\n", kTraceTokenChar);
518a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  DumpThreadList(os);
519a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  os << StringPrintf("%cmethods\n", kTraceTokenChar);
52062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  DumpMethodList(os, visited_methods);
521a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  os << StringPrintf("%cend\n", kTraceTokenChar);
522a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
523a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  std::string header(os.str());
5242692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  if (trace_file_.get() == NULL) {
5257b9d996e4cd7d154bb1a244d67139aff0c363cf2Elliott Hughes    iovec iov[2];
526a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    iov[0].iov_base = reinterpret_cast<void*>(const_cast<char*>(header.c_str()));
527a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    iov[0].iov_len = header.length();
5282692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao    iov[1].iov_base = buf_.get();
529a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    iov[1].iov_len = final_offset;
530a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    Dbg::DdmSendChunkV(CHUNK_TYPE("MPSE"), iov, 2);
53162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    const bool kDumpTraceInfo = false;
53262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    if (kDumpTraceInfo) {
53362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      LOG(INFO) << "Trace sent:\n" << header;
53462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      DumpBuf(buf_.get(), final_offset, clock_source_);
53562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    }
536a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  } else {
537a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    if (!trace_file_->WriteFully(header.c_str(), header.length()) ||
5382692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao        !trace_file_->WriteFully(buf_.get(), final_offset)) {
5397b9d996e4cd7d154bb1a244d67139aff0c363cf2Elliott Hughes      std::string detail(StringPrintf("Trace data write failed: %s", strerror(errno)));
5407b9d996e4cd7d154bb1a244d67139aff0c363cf2Elliott Hughes      PLOG(ERROR) << detail;
54162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      ThrowRuntimeException("%s", detail.c_str());
542a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    }
543a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  }
544e343b76af81a005ef64f5e75a555389fd9147dabjeffhao}
545e343b76af81a005ef64f5e75a555389fd9147dabjeffhao
54662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid Trace::DexPcMoved(Thread* thread, mirror::Object* this_object,
547ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers                       mirror::ArtMethod* method, uint32_t new_dex_pc) {
54862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // We're not recorded to listen to this kind of event, so complain.
54962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  LOG(ERROR) << "Unexpected dex PC event in tracing " << PrettyMethod(method) << " " << new_dex_pc;
55062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers};
55162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
5523f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertzvoid Trace::FieldRead(Thread* /*thread*/, mirror::Object* this_object,
5533f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz                       mirror::ArtMethod* method, uint32_t dex_pc, mirror::ArtField* field)
5543f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
5553f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz  // We're not recorded to listen to this kind of event, so complain.
5563f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz  LOG(ERROR) << "Unexpected field read event in tracing " << PrettyMethod(method) << " " << dex_pc;
5573f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz}
5583f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz
5593f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertzvoid Trace::FieldWritten(Thread* /*thread*/, mirror::Object* this_object,
5603f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz                          mirror::ArtMethod* method, uint32_t dex_pc, mirror::ArtField* field,
5613f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz                          const JValue& field_value)
5623f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
5633f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz  // We're not recorded to listen to this kind of event, so complain.
5643f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz  LOG(ERROR) << "Unexpected field write event in tracing " << PrettyMethod(method) << " " << dex_pc;
5653f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz}
5663f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz
56762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid Trace::MethodEntered(Thread* thread, mirror::Object* this_object,
568ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers                          mirror::ArtMethod* method, uint32_t dex_pc) {
569c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao  uint32_t thread_clock_diff = 0;
570c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao  uint32_t wall_clock_diff = 0;
571c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao  ReadClocks(thread, &thread_clock_diff, &wall_clock_diff);
572c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao  LogMethodTraceEvent(thread, method, instrumentation::Instrumentation::kMethodEntered,
573c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao                      thread_clock_diff, wall_clock_diff);
57462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
57562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
57662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid Trace::MethodExited(Thread* thread, mirror::Object* this_object,
577ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers                         mirror::ArtMethod* method, uint32_t dex_pc,
57862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                         const JValue& return_value) {
57962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  UNUSED(return_value);
580c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao  uint32_t thread_clock_diff = 0;
581c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao  uint32_t wall_clock_diff = 0;
582c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao  ReadClocks(thread, &thread_clock_diff, &wall_clock_diff);
583c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao  LogMethodTraceEvent(thread, method, instrumentation::Instrumentation::kMethodExited,
584c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao                      thread_clock_diff, wall_clock_diff);
58562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
58662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
58751db44a194bafc3810a41164a8b39614f10e79dfSebastien Hertzvoid Trace::MethodUnwind(Thread* thread, mirror::Object* this_object,
588ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers                         mirror::ArtMethod* method, uint32_t dex_pc) {
589c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao  uint32_t thread_clock_diff = 0;
590c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao  uint32_t wall_clock_diff = 0;
591c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao  ReadClocks(thread, &thread_clock_diff, &wall_clock_diff);
592c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao  LogMethodTraceEvent(thread, method, instrumentation::Instrumentation::kMethodUnwind,
593c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao                      thread_clock_diff, wall_clock_diff);
59462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
59562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
59662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid Trace::ExceptionCaught(Thread* thread, const ThrowLocation& throw_location,
597ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                            mirror::ArtMethod* catch_method, uint32_t catch_dex_pc,
59862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                            mirror::Throwable* exception_object)
59962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
60062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  LOG(ERROR) << "Unexpected exception caught event in tracing";
60162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}
602a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
603c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Haovoid Trace::ReadClocks(Thread* thread, uint32_t* thread_clock_diff, uint32_t* wall_clock_diff) {
604c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao  if (UseThreadCpuClock()) {
605c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao    uint64_t clock_base = thread->GetTraceClockBase();
606c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao    if (UNLIKELY(clock_base == 0)) {
607c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao      // First event, record the base time in the map.
608c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao      uint64_t time = thread->GetCpuMicroTime();
609c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao      thread->SetTraceClockBase(time);
610c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao    } else {
611c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao      *thread_clock_diff = thread->GetCpuMicroTime() - clock_base;
612c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao    }
613c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao  }
614c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao  if (UseWallClock()) {
615c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao    *wall_clock_diff = MicroTime() - start_time_;
616c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao  }
617c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao}
618c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao
619ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogersvoid Trace::LogMethodTraceEvent(Thread* thread, mirror::ArtMethod* method,
620c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao                                instrumentation::Instrumentation::InstrumentationEvent event,
621c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao                                uint32_t thread_clock_diff, uint32_t wall_clock_diff) {
622a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  // Advance cur_offset_ atomically.
623a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  int32_t new_offset;
624a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  int32_t old_offset;
625a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  do {
626a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    old_offset = cur_offset_;
62762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    new_offset = old_offset + GetRecordSize(clock_source_);
628a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    if (new_offset > buffer_size_) {
629a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao      overflow_ = true;
630a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao      return;
631a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    }
632a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  } while (android_atomic_release_cas(old_offset, new_offset, &cur_offset_) != 0);
633a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
63462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  TraceAction action = kTraceMethodEnter;
63562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  switch (event) {
63662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    case instrumentation::Instrumentation::kMethodEntered:
63762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      action = kTraceMethodEnter;
63862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      break;
63962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    case instrumentation::Instrumentation::kMethodExited:
64062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      action = kTraceMethodExit;
64162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      break;
64262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    case instrumentation::Instrumentation::kMethodUnwind:
64362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      action = kTraceUnroll;
64462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      break;
64562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    default:
64662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      UNIMPLEMENTED(FATAL) << "Unexpected event: " << event;
64762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
64862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
64962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  uint32_t method_value = EncodeTraceMethodAndAction(method, action);
650a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
651a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  // Write data
6522692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  uint8_t* ptr = buf_.get() + old_offset;
65362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  Append2LE(ptr, thread->GetTid());
654a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  Append4LE(ptr + 2, method_value);
655a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  ptr += 6;
656a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
657a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  if (UseThreadCpuClock()) {
658a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    Append4LE(ptr, thread_clock_diff);
659a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    ptr += 4;
660e343b76af81a005ef64f5e75a555389fd9147dabjeffhao  }
661a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  if (UseWallClock()) {
662a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao    Append4LE(ptr, wall_clock_diff);
663a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  }
664a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao}
665a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
66662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid Trace::GetVisitedMethods(size_t buf_size,
667ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                              std::set<mirror::ArtMethod*>* visited_methods) {
6682692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao  uint8_t* ptr = buf_.get() + kTraceHeaderLength;
66962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  uint8_t* end = buf_.get() + buf_size;
670a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
671a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  while (ptr < end) {
67262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    uint32_t tmid = ptr[2] | (ptr[3] << 8) | (ptr[4] << 16) | (ptr[5] << 24);
673ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom    mirror::ArtMethod* method = DecodeTraceMethodId(tmid);
67462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    visited_methods->insert(method);
67562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    ptr += GetRecordSize(clock_source_);
676a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  }
677a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao}
678a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
67902e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartiervoid Trace::DumpMethodList(std::ostream& os, const std::set<mirror::ArtMethod*>& visited_methods) {
68062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  MethodHelper mh;
68102e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier  for (const auto& method : visited_methods) {
68262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    mh.ChangeMethod(method);
6830399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    os << StringPrintf("%p\t%s\t%s\t%s\t%s\n", method,
684a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao        PrettyDescriptor(mh.GetDeclaringClassDescriptor()).c_str(), mh.GetName(),
685d91d6d6a80748f277fd938a412211e5af28913b1Ian Rogers        mh.GetSignature().ToString().c_str(), mh.GetDeclaringClassSourceFile());
686a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  }
687a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao}
688a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
689a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhaostatic void DumpThread(Thread* t, void* arg) {
690ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes  std::ostream& os = *reinterpret_cast<std::ostream*>(arg);
691ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes  std::string name;
692ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes  t->GetThreadName(name);
693ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes  os << t->GetTid() << "\t" << name << "\n";
694a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao}
695a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
696a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhaovoid Trace::DumpThreadList(std::ostream& os) {
69781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  Thread* self = Thread::Current();
69881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  Locks::thread_list_lock_->AssertNotHeld(self);
69981d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  MutexLock mu(self, *Locks::thread_list_lock_);
700a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao  Runtime::Current()->GetThreadList()->ForEach(DumpThread, &os);
701a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao}
702a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao
703e343b76af81a005ef64f5e75a555389fd9147dabjeffhao}  // namespace art
704