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