12faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes/* 22faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Copyright (C) 2011 The Android Open Source Project 32faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 42faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License"); 52faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * you may not use this file except in compliance with the License. 62faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * You may obtain a copy of the License at 72faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 82faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 92faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 102faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Unless required by applicable law or agreed to in writing, software 112faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 122faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * See the License for the specific language governing permissions and 142faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * limitations under the License. 152faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes */ 16e343b76af81a005ef64f5e75a555389fd9147dabjeffhao 17e343b76af81a005ef64f5e75a555389fd9147dabjeffhao#include "trace.h" 18e343b76af81a005ef64f5e75a555389fd9147dabjeffhao 19a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao#include <sys/uio.h> 200624a27b9a2951bfcf23321a714543e137836904John Reck#include <unistd.h> 21a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 22e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier#include "art_method-inl.h" 23e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampe#include "base/casts.h" 240abc72ebe356c32354b575c48189965a0edc7890Jeff Hao#include "base/stl_util.h" 2532ce2adefb8a3d0eda59a29f5e87c1eb43eef796Mathieu Chartier#include "base/systrace.h" 2680afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko#include "base/time_utils.h" 27761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes#include "base/unix_file/fd_file.h" 28e343b76af81a005ef64f5e75a555389fd9147dabjeffhao#include "class_linker.h" 2962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers#include "common_throws.h" 30a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao#include "debugger.h" 314f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "dex_file-inl.h" 32aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier#include "gc/scoped_gc_critical_section.h" 33725a957985171d712d5c048cc3d00ff14968784bjeffhao#include "instrumentation.h" 344f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "mirror/class-inl.h" 3540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe#include "mirror/dex_cache-inl.h" 362dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object_array-inl.h" 374f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "mirror/object-inl.h" 38a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao#include "os.h" 3900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#include "scoped_thread_state_change.h" 400abc72ebe356c32354b575c48189965a0edc7890Jeff Hao#include "ScopedLocalRef.h" 41e343b76af81a005ef64f5e75a555389fd9147dabjeffhao#include "thread.h" 4257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers#include "thread_list.h" 4380afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko#include "utils.h" 44166db04e259ca51838c311891598664deeed85adIan Rogers#include "entrypoints/quick/quick_entrypoints.h" 452692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao 462692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhaonamespace art { 472692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao 484d64cd45acc6a26742e8237eb65136998612820dMathieu Chartierstatic constexpr size_t TraceActionBits = MinimumBitsToStore( 494d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier static_cast<size_t>(kTraceMethodActionMask)); 5040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampestatic constexpr uint8_t kOpNewMethod = 1U; 5140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampestatic constexpr uint8_t kOpNewThread = 2U; 5240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe 530abc72ebe356c32354b575c48189965a0edc7890Jeff Haoclass BuildStackTraceVisitor : public StackVisitor { 540abc72ebe356c32354b575c48189965a0edc7890Jeff Hao public: 558e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray explicit BuildStackTraceVisitor(Thread* thread) 568e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames), 578e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray method_trace_(Trace::AllocStackTrace()) {} 580abc72ebe356c32354b575c48189965a0edc7890Jeff Hao 5990443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier bool VisitFrame() SHARED_REQUIRES(Locks::mutator_lock_) { 60e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod* m = GetMethod(); 610abc72ebe356c32354b575c48189965a0edc7890Jeff Hao // Ignore runtime frames (in particular callee save). 620abc72ebe356c32354b575c48189965a0edc7890Jeff Hao if (!m->IsRuntimeMethod()) { 630abc72ebe356c32354b575c48189965a0edc7890Jeff Hao method_trace_->push_back(m); 640abc72ebe356c32354b575c48189965a0edc7890Jeff Hao } 650abc72ebe356c32354b575c48189965a0edc7890Jeff Hao return true; 660abc72ebe356c32354b575c48189965a0edc7890Jeff Hao } 670abc72ebe356c32354b575c48189965a0edc7890Jeff Hao 680abc72ebe356c32354b575c48189965a0edc7890Jeff Hao // Returns a stack trace where the topmost frame corresponds with the first element of the vector. 69e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier std::vector<ArtMethod*>* GetStackTrace() const { 700abc72ebe356c32354b575c48189965a0edc7890Jeff Hao return method_trace_; 710abc72ebe356c32354b575c48189965a0edc7890Jeff Hao } 720abc72ebe356c32354b575c48189965a0edc7890Jeff Hao 730abc72ebe356c32354b575c48189965a0edc7890Jeff Hao private: 74e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier std::vector<ArtMethod*>* const method_trace_; 7526f728661a08062a373a3203b72dc2555c2aed2dSebastien Hertz 7626f728661a08062a373a3203b72dc2555c2aed2dSebastien Hertz DISALLOW_COPY_AND_ASSIGN(BuildStackTraceVisitor); 770abc72ebe356c32354b575c48189965a0edc7890Jeff Hao}; 780abc72ebe356c32354b575c48189965a0edc7890Jeff Hao 79a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhaostatic const char kTraceTokenChar = '*'; 80a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhaostatic const uint16_t kTraceHeaderLength = 32; 81a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhaostatic const uint32_t kTraceMagicValue = 0x574f4c53; 82a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhaostatic const uint16_t kTraceVersionSingleClock = 2; 83a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhaostatic const uint16_t kTraceVersionDualClock = 3; 844d64cd45acc6a26742e8237eb65136998612820dMathieu Chartierstatic const uint16_t kTraceRecordSizeSingleClock = 10; // using v2 854d64cd45acc6a26742e8237eb65136998612820dMathieu Chartierstatic const uint16_t kTraceRecordSizeDualClock = 14; // using v3 with two timestamps 86a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 87e63db27db913f1a88e2095a1ee8239b2bb9124e8Ian RogersTraceClockSource Trace::default_clock_source_ = kDefaultTraceClockSource; 8862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 8940da286d3207d88ed8ff3f5caac4873874603428Andreas GampeTrace* volatile Trace::the_trace_ = nullptr; 900abc72ebe356c32354b575c48189965a0edc7890Jeff Haopthread_t Trace::sampling_pthread_ = 0U; 91e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartierstd::unique_ptr<std::vector<ArtMethod*>> Trace::temp_stack_trace_; 92e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes 930462c4c87c39db6cfcd338f323844738109ac3c9Sebastien Hertz// The key identifying the tracer to update instrumentation. 940462c4c87c39db6cfcd338f323844738109ac3c9Sebastien Hertzstatic constexpr const char* kTracerInstrumentationKey = "Tracer"; 950462c4c87c39db6cfcd338f323844738109ac3c9Sebastien Hertz 9662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersstatic TraceAction DecodeTraceAction(uint32_t tmid) { 9762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers return static_cast<TraceAction>(tmid & kTraceMethodActionMask); 98a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao} 99a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 1004d64cd45acc6a26742e8237eb65136998612820dMathieu ChartierArtMethod* Trace::DecodeTraceMethod(uint32_t tmid) { 1014d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier MutexLock mu(Thread::Current(), *unique_methods_lock_); 1024d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier return unique_methods_[tmid >> TraceActionBits]; 103e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes} 104e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes 1054d64cd45acc6a26742e8237eb65136998612820dMathieu Chartieruint32_t Trace::EncodeTraceMethod(ArtMethod* method) { 1064d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier MutexLock mu(Thread::Current(), *unique_methods_lock_); 1074d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier uint32_t idx; 1084d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier auto it = art_method_id_map_.find(method); 1094d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier if (it != art_method_id_map_.end()) { 1104d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier idx = it->second; 1115ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao } else { 1124d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier unique_methods_.push_back(method); 1134d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier idx = unique_methods_.size() - 1; 1144d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier art_method_id_map_.emplace(method, idx); 1155ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao } 1164d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier DCHECK_LT(idx, unique_methods_.size()); 1174d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier DCHECK_EQ(unique_methods_[idx], method); 1184d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier return idx; 1194d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier} 1204d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier 1214d64cd45acc6a26742e8237eb65136998612820dMathieu Chartieruint32_t Trace::EncodeTraceMethodAndAction(ArtMethod* method, TraceAction action) { 1224d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier uint32_t tmid = (EncodeTraceMethod(method) << TraceActionBits) | action; 1234d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier DCHECK_EQ(method, DecodeTraceMethod(tmid)); 1244d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier return tmid; 1254d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier} 1264d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier 1274d64cd45acc6a26742e8237eb65136998612820dMathieu Chartierstd::vector<ArtMethod*>* Trace::AllocStackTrace() { 1284d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier return (temp_stack_trace_.get() != nullptr) ? temp_stack_trace_.release() : 1294d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier new std::vector<ArtMethod*>(); 1305ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao} 1315ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao 132e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartiervoid Trace::FreeStackTrace(std::vector<ArtMethod*>* stack_trace) { 1335ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao stack_trace->clear(); 1345ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao temp_stack_trace_.reset(stack_trace); 1355ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao} 1365ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao 137e63db27db913f1a88e2095a1ee8239b2bb9124e8Ian Rogersvoid Trace::SetDefaultClockSource(TraceClockSource clock_source) { 1380a18df82f4dea95b7398f8c934341fccbf04eeeeElliott Hughes#if defined(__linux__) 13962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers default_clock_source_ = clock_source; 140e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes#else 141aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin if (clock_source != TraceClockSource::kWall) { 1425ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao LOG(WARNING) << "Ignoring tracing request to use CPU time."; 14362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 144e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes#endif 145a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao} 146a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 147e63db27db913f1a88e2095a1ee8239b2bb9124e8Ian Rogersstatic uint16_t GetTraceVersion(TraceClockSource clock_source) { 148aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return (clock_source == TraceClockSource::kDual) ? kTraceVersionDualClock 14962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers : kTraceVersionSingleClock; 15062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers} 15162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 152e63db27db913f1a88e2095a1ee8239b2bb9124e8Ian Rogersstatic uint16_t GetRecordSize(TraceClockSource clock_source) { 153aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return (clock_source == TraceClockSource::kDual) ? kTraceRecordSizeDualClock 15462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers : kTraceRecordSizeSingleClock; 15562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers} 15662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 15762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersbool Trace::UseThreadCpuClock() { 158aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return (clock_source_ == TraceClockSource::kThreadCpu) || 159aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin (clock_source_ == TraceClockSource::kDual); 16062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers} 16162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 162e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughesbool Trace::UseWallClock() { 163aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return (clock_source_ == TraceClockSource::kWall) || 164aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin (clock_source_ == TraceClockSource::kDual); 165a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao} 166a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 167c5d824a20c225763761a6dff43294b229ff35469Jeff Haovoid Trace::MeasureClockOverhead() { 168c5d824a20c225763761a6dff43294b229ff35469Jeff Hao if (UseThreadCpuClock()) { 16957dac6ed61a0a25c14d4e2fabc84435578d42360Jeff Hao Thread::Current()->GetCpuMicroTime(); 170a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao } 171c5d824a20c225763761a6dff43294b229ff35469Jeff Hao if (UseWallClock()) { 172a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao MicroTime(); 173a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao } 174a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao} 175a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 1765ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao// Compute an average time taken to measure clocks. 177c5d824a20c225763761a6dff43294b229ff35469Jeff Haouint32_t Trace::GetClockOverheadNanoSeconds() { 17857dac6ed61a0a25c14d4e2fabc84435578d42360Jeff Hao Thread* self = Thread::Current(); 17957dac6ed61a0a25c14d4e2fabc84435578d42360Jeff Hao uint64_t start = self->GetCpuMicroTime(); 180a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 181a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao for (int i = 4000; i > 0; i--) { 182c5d824a20c225763761a6dff43294b229ff35469Jeff Hao MeasureClockOverhead(); 183c5d824a20c225763761a6dff43294b229ff35469Jeff Hao MeasureClockOverhead(); 184c5d824a20c225763761a6dff43294b229ff35469Jeff Hao MeasureClockOverhead(); 185c5d824a20c225763761a6dff43294b229ff35469Jeff Hao MeasureClockOverhead(); 186c5d824a20c225763761a6dff43294b229ff35469Jeff Hao MeasureClockOverhead(); 187c5d824a20c225763761a6dff43294b229ff35469Jeff Hao MeasureClockOverhead(); 188c5d824a20c225763761a6dff43294b229ff35469Jeff Hao MeasureClockOverhead(); 189c5d824a20c225763761a6dff43294b229ff35469Jeff Hao MeasureClockOverhead(); 190a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao } 191a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 1925ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao uint64_t elapsed_us = self->GetCpuMicroTime() - start; 1935ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao return static_cast<uint32_t>(elapsed_us / 32); 194a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao} 195a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 196ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes// TODO: put this somewhere with the big-endian equivalent used by JDWP. 197ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughesstatic void Append2LE(uint8_t* buf, uint16_t val) { 1985ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao *buf++ = static_cast<uint8_t>(val); 1995ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao *buf++ = static_cast<uint8_t>(val >> 8); 200a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao} 201a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 202ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes// TODO: put this somewhere with the big-endian equivalent used by JDWP. 203ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughesstatic void Append4LE(uint8_t* buf, uint32_t val) { 2045ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao *buf++ = static_cast<uint8_t>(val); 2055ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao *buf++ = static_cast<uint8_t>(val >> 8); 2065ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao *buf++ = static_cast<uint8_t>(val >> 16); 2075ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao *buf++ = static_cast<uint8_t>(val >> 24); 208a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao} 209a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 210ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes// TODO: put this somewhere with the big-endian equivalent used by JDWP. 211ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughesstatic void Append8LE(uint8_t* buf, uint64_t val) { 2125ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao *buf++ = static_cast<uint8_t>(val); 2135ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao *buf++ = static_cast<uint8_t>(val >> 8); 2145ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao *buf++ = static_cast<uint8_t>(val >> 16); 2155ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao *buf++ = static_cast<uint8_t>(val >> 24); 2165ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao *buf++ = static_cast<uint8_t>(val >> 32); 2175ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao *buf++ = static_cast<uint8_t>(val >> 40); 2185ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao *buf++ = static_cast<uint8_t>(val >> 48); 2195ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao *buf++ = static_cast<uint8_t>(val >> 56); 220a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao} 221a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 22290443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartierstatic void GetSample(Thread* thread, void* arg) SHARED_REQUIRES(Locks::mutator_lock_) { 2230abc72ebe356c32354b575c48189965a0edc7890Jeff Hao BuildStackTraceVisitor build_trace_visitor(thread); 2240abc72ebe356c32354b575c48189965a0edc7890Jeff Hao build_trace_visitor.WalkStack(); 225e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier std::vector<ArtMethod*>* stack_trace = build_trace_visitor.GetStackTrace(); 2260abc72ebe356c32354b575c48189965a0edc7890Jeff Hao Trace* the_trace = reinterpret_cast<Trace*>(arg); 2270abc72ebe356c32354b575c48189965a0edc7890Jeff Hao the_trace->CompareAndUpdateStackTrace(thread, stack_trace); 2280abc72ebe356c32354b575c48189965a0edc7890Jeff Hao} 2290abc72ebe356c32354b575c48189965a0edc7890Jeff Hao 230ca71458862be8505330b7fd5649a062f31d143dcAndreas Gampestatic void ClearThreadStackTraceAndClockBase(Thread* thread, void* arg ATTRIBUTE_UNUSED) { 2315ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao thread->SetTraceClockBase(0); 232e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier std::vector<ArtMethod*>* stack_trace = thread->GetStackTraceSample(); 23340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe thread->SetStackTraceSample(nullptr); 2345ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao delete stack_trace; 2355ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao} 2365ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao 2370abc72ebe356c32354b575c48189965a0edc7890Jeff Haovoid Trace::CompareAndUpdateStackTrace(Thread* thread, 238e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier std::vector<ArtMethod*>* stack_trace) { 2390abc72ebe356c32354b575c48189965a0edc7890Jeff Hao CHECK_EQ(pthread_self(), sampling_pthread_); 240e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier std::vector<ArtMethod*>* old_stack_trace = thread->GetStackTraceSample(); 2415ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao // Update the thread's stack trace sample. 2425ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao thread->SetStackTraceSample(stack_trace); 243c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao // Read timer clocks to use for all events in this trace. 244c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao uint32_t thread_clock_diff = 0; 245c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao uint32_t wall_clock_diff = 0; 246c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao ReadClocks(thread, &thread_clock_diff, &wall_clock_diff); 24740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe if (old_stack_trace == nullptr) { 2485ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao // If there's no previous stack trace sample for this thread, log an entry event for all 2490abc72ebe356c32354b575c48189965a0edc7890Jeff Hao // methods in the trace. 2504d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier for (auto rit = stack_trace->rbegin(); rit != stack_trace->rend(); ++rit) { 251c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao LogMethodTraceEvent(thread, *rit, instrumentation::Instrumentation::kMethodEntered, 252c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao thread_clock_diff, wall_clock_diff); 2530abc72ebe356c32354b575c48189965a0edc7890Jeff Hao } 2540abc72ebe356c32354b575c48189965a0edc7890Jeff Hao } else { 2550abc72ebe356c32354b575c48189965a0edc7890Jeff Hao // If there's a previous stack trace for this thread, diff the traces and emit entry and exit 2560abc72ebe356c32354b575c48189965a0edc7890Jeff Hao // events accordingly. 2574d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier auto old_rit = old_stack_trace->rbegin(); 2584d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier auto rit = stack_trace->rbegin(); 2590abc72ebe356c32354b575c48189965a0edc7890Jeff Hao // Iterate bottom-up over both traces until there's a difference between them. 2600abc72ebe356c32354b575c48189965a0edc7890Jeff Hao while (old_rit != old_stack_trace->rend() && rit != stack_trace->rend() && *old_rit == *rit) { 2610abc72ebe356c32354b575c48189965a0edc7890Jeff Hao old_rit++; 2620abc72ebe356c32354b575c48189965a0edc7890Jeff Hao rit++; 2630abc72ebe356c32354b575c48189965a0edc7890Jeff Hao } 2640abc72ebe356c32354b575c48189965a0edc7890Jeff Hao // Iterate top-down over the old trace until the point where they differ, emitting exit events. 2654d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier for (auto old_it = old_stack_trace->begin(); old_it != old_rit.base(); ++old_it) { 266c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao LogMethodTraceEvent(thread, *old_it, instrumentation::Instrumentation::kMethodExited, 267c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao thread_clock_diff, wall_clock_diff); 2680abc72ebe356c32354b575c48189965a0edc7890Jeff Hao } 2690abc72ebe356c32354b575c48189965a0edc7890Jeff Hao // Iterate bottom-up over the new trace from the point where they differ, emitting entry events. 2700abc72ebe356c32354b575c48189965a0edc7890Jeff Hao for (; rit != stack_trace->rend(); ++rit) { 271c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao LogMethodTraceEvent(thread, *rit, instrumentation::Instrumentation::kMethodEntered, 272c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao thread_clock_diff, wall_clock_diff); 2730abc72ebe356c32354b575c48189965a0edc7890Jeff Hao } 2745ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao FreeStackTrace(old_stack_trace); 2750abc72ebe356c32354b575c48189965a0edc7890Jeff Hao } 2760abc72ebe356c32354b575c48189965a0edc7890Jeff Hao} 2770abc72ebe356c32354b575c48189965a0edc7890Jeff Hao 2780abc72ebe356c32354b575c48189965a0edc7890Jeff Haovoid* Trace::RunSamplingThread(void* arg) { 2790abc72ebe356c32354b575c48189965a0edc7890Jeff Hao Runtime* runtime = Runtime::Current(); 280ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers intptr_t interval_us = reinterpret_cast<intptr_t>(arg); 2814044bdac490777cbc8a12d467bec675ef8aa6eb1Jeff Hao CHECK_GE(interval_us, 0); 2820abc72ebe356c32354b575c48189965a0edc7890Jeff Hao CHECK(runtime->AttachCurrentThread("Sampling Profiler", true, runtime->GetSystemThreadGroup(), 283e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier !runtime->IsAotCompiler())); 2840abc72ebe356c32354b575c48189965a0edc7890Jeff Hao 2850abc72ebe356c32354b575c48189965a0edc7890Jeff Hao while (true) { 28623009dca63c1699e28bfeaa8b45ca48fa0e86aceJeff Hao usleep(interval_us); 28732ce2adefb8a3d0eda59a29f5e87c1eb43eef796Mathieu Chartier ScopedTrace trace("Profile sampling"); 2880abc72ebe356c32354b575c48189965a0edc7890Jeff Hao Thread* self = Thread::Current(); 2890abc72ebe356c32354b575c48189965a0edc7890Jeff Hao Trace* the_trace; 2900abc72ebe356c32354b575c48189965a0edc7890Jeff Hao { 2910abc72ebe356c32354b575c48189965a0edc7890Jeff Hao MutexLock mu(self, *Locks::trace_lock_); 2920abc72ebe356c32354b575c48189965a0edc7890Jeff Hao the_trace = the_trace_; 29340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe if (the_trace == nullptr) { 2940abc72ebe356c32354b575c48189965a0edc7890Jeff Hao break; 2950abc72ebe356c32354b575c48189965a0edc7890Jeff Hao } 2960abc72ebe356c32354b575c48189965a0edc7890Jeff Hao } 2970abc72ebe356c32354b575c48189965a0edc7890Jeff Hao { 2984f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier ScopedSuspendAll ssa(__FUNCTION__); 2990abc72ebe356c32354b575c48189965a0edc7890Jeff Hao MutexLock mu(self, *Locks::thread_list_lock_); 3000abc72ebe356c32354b575c48189965a0edc7890Jeff Hao runtime->GetThreadList()->ForEach(GetSample, the_trace); 3010abc72ebe356c32354b575c48189965a0edc7890Jeff Hao } 3020abc72ebe356c32354b575c48189965a0edc7890Jeff Hao } 3030abc72ebe356c32354b575c48189965a0edc7890Jeff Hao 3040abc72ebe356c32354b575c48189965a0edc7890Jeff Hao runtime->DetachCurrentThread(); 30540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe return nullptr; 3060abc72ebe356c32354b575c48189965a0edc7890Jeff Hao} 3070abc72ebe356c32354b575c48189965a0edc7890Jeff Hao 308e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampevoid Trace::Start(const char* trace_filename, int trace_fd, size_t buffer_size, int flags, 3097e7e0f47628fb358da70c5e2766545c4f0596235Andreas Gampe TraceOutputMode output_mode, TraceMode trace_mode, int interval_us) { 31062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers Thread* self = Thread::Current(); 31162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers { 31262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers MutexLock mu(self, *Locks::trace_lock_); 31340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe if (the_trace_ != nullptr) { 31462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers LOG(ERROR) << "Trace already in progress, ignoring this request"; 31562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers return; 31662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 317e343b76af81a005ef64f5e75a555389fd9147dabjeffhao } 318d063d912e5580222b1822b152de315420cef49eeJeff Hao 319d063d912e5580222b1822b152de315420cef49eeJeff Hao // Check interval if sampling is enabled 3207e7e0f47628fb358da70c5e2766545c4f0596235Andreas Gampe if (trace_mode == TraceMode::kSampling && interval_us <= 0) { 321d063d912e5580222b1822b152de315420cef49eeJeff Hao LOG(ERROR) << "Invalid sampling interval: " << interval_us; 322d063d912e5580222b1822b152de315420cef49eeJeff Hao ScopedObjectAccess soa(self); 323d063d912e5580222b1822b152de315420cef49eeJeff Hao ThrowRuntimeException("Invalid sampling interval: %d", interval_us); 324d063d912e5580222b1822b152de315420cef49eeJeff Hao return; 325d063d912e5580222b1822b152de315420cef49eeJeff Hao } 326a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 3272692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao // Open trace file if not going directly to ddms. 328700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers std::unique_ptr<File> trace_file; 3297e7e0f47628fb358da70c5e2766545c4f0596235Andreas Gampe if (output_mode != TraceOutputMode::kDDMS) { 330a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao if (trace_fd < 0) { 331f83e733618066e3c672c9a7ee872a3bba8202e7fCalin Juravle trace_file.reset(OS::CreateEmptyFileWriteOnly(trace_filename)); 332a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao } else { 33362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers trace_file.reset(new File(trace_fd, "tracefile")); 334761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes trace_file->DisableAutoClose(); 335a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao } 33640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe if (trace_file.get() == nullptr) { 337b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao PLOG(ERROR) << "Unable to open trace file '" << trace_filename << "'"; 33862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ScopedObjectAccess soa(self); 33962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ThrowRuntimeException("Unable to open trace file '%s'", trace_filename); 340a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao return; 341a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao } 342a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao } 343a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 344d063d912e5580222b1822b152de315420cef49eeJeff Hao Runtime* runtime = Runtime::Current(); 3459ef78b59da51080882e47505896b420977fd79aeMathieu Chartier 3469ef78b59da51080882e47505896b420977fd79aeMathieu Chartier // Enable count of allocs if specified in the flags. 3479ef78b59da51080882e47505896b420977fd79aeMathieu Chartier bool enable_stats = false; 3489ef78b59da51080882e47505896b420977fd79aeMathieu Chartier 3492692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao // Create Trace object. 35062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers { 351aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier // Required since EnableMethodTracing calls ConfigureStubs which visits class linker classes. 352aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier gc::ScopedGCCriticalSection gcs(self, 353aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier gc::kGcCauseInstrumentation, 354aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier gc::kCollectorTypeInstrumentation); 3554f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier ScopedSuspendAll ssa(__FUNCTION__); 35662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers MutexLock mu(self, *Locks::trace_lock_); 35740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe if (the_trace_ != nullptr) { 35862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers LOG(ERROR) << "Trace already in progress, ignoring this request"; 35962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } else { 3609ef78b59da51080882e47505896b420977fd79aeMathieu Chartier enable_stats = (flags && kTraceCountAllocs) != 0; 36140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe the_trace_ = new Trace(trace_file.release(), trace_filename, buffer_size, flags, output_mode, 36240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe trace_mode); 3637e7e0f47628fb358da70c5e2766545c4f0596235Andreas Gampe if (trace_mode == TraceMode::kSampling) { 36440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe CHECK_PTHREAD_CALL(pthread_create, (&sampling_pthread_, nullptr, &RunSamplingThread, 36523009dca63c1699e28bfeaa8b45ca48fa0e86aceJeff Hao reinterpret_cast<void*>(interval_us)), 36623009dca63c1699e28bfeaa8b45ca48fa0e86aceJeff Hao "Sampling profiler thread"); 36740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe the_trace_->interval_us_ = interval_us; 3680abc72ebe356c32354b575c48189965a0edc7890Jeff Hao } else { 3690abc72ebe356c32354b575c48189965a0edc7890Jeff Hao runtime->GetInstrumentation()->AddListener(the_trace_, 3700abc72ebe356c32354b575c48189965a0edc7890Jeff Hao instrumentation::Instrumentation::kMethodEntered | 3710abc72ebe356c32354b575c48189965a0edc7890Jeff Hao instrumentation::Instrumentation::kMethodExited | 3720abc72ebe356c32354b575c48189965a0edc7890Jeff Hao instrumentation::Instrumentation::kMethodUnwind); 37340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe // TODO: In full-PIC mode, we don't need to fully deopt. 3740462c4c87c39db6cfcd338f323844738109ac3c9Sebastien Hertz runtime->GetInstrumentation()->EnableMethodTracing(kTracerInstrumentationKey); 3750abc72ebe356c32354b575c48189965a0edc7890Jeff Hao } 37662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 37762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 378d063d912e5580222b1822b152de315420cef49eeJeff Hao 3799ef78b59da51080882e47505896b420977fd79aeMathieu Chartier // Can't call this when holding the mutator lock. 3809ef78b59da51080882e47505896b420977fd79aeMathieu Chartier if (enable_stats) { 3819ef78b59da51080882e47505896b420977fd79aeMathieu Chartier runtime->SetStatsEnabled(true); 3829ef78b59da51080882e47505896b420977fd79aeMathieu Chartier } 3832692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao} 3842692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao 38540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampevoid Trace::StopTracing(bool finish_tracing, bool flush_file) { 3869ef78b59da51080882e47505896b420977fd79aeMathieu Chartier bool stop_alloc_counting = false; 38702e5f160d9cc02da20d9e47af30f948c462f7043Mathieu Chartier Runtime* const runtime = Runtime::Current(); 38802e5f160d9cc02da20d9e47af30f948c462f7043Mathieu Chartier Trace* the_trace = nullptr; 3899ea02c4f01b079bf6a5f49c62cb59fa5791cbc60Hiroshi Yamauchi Thread* const self = Thread::Current(); 3900abc72ebe356c32354b575c48189965a0edc7890Jeff Hao pthread_t sampling_pthread = 0U; 39162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers { 3929ea02c4f01b079bf6a5f49c62cb59fa5791cbc60Hiroshi Yamauchi MutexLock mu(self, *Locks::trace_lock_); 39340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe if (the_trace_ == nullptr) { 39462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers LOG(ERROR) << "Trace stop requested, but no trace currently running"; 39562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } else { 39662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers the_trace = the_trace_; 39740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe the_trace_ = nullptr; 3980abc72ebe356c32354b575c48189965a0edc7890Jeff Hao sampling_pthread = sampling_pthread_; 39962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 4002692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao } 40102e5f160d9cc02da20d9e47af30f948c462f7043Mathieu Chartier // Make sure that we join before we delete the trace since we don't want to have 40202e5f160d9cc02da20d9e47af30f948c462f7043Mathieu Chartier // the sampling thread access a stale pointer. This finishes since the sampling thread exits when 40302e5f160d9cc02da20d9e47af30f948c462f7043Mathieu Chartier // the_trace_ is null. 40402e5f160d9cc02da20d9e47af30f948c462f7043Mathieu Chartier if (sampling_pthread != 0U) { 40540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe CHECK_PTHREAD_CALL(pthread_join, (sampling_pthread, nullptr), "sampling thread shutdown"); 40602e5f160d9cc02da20d9e47af30f948c462f7043Mathieu Chartier sampling_pthread_ = 0U; 40702e5f160d9cc02da20d9e47af30f948c462f7043Mathieu Chartier } 40840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe 4094f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier { 4109ea02c4f01b079bf6a5f49c62cb59fa5791cbc60Hiroshi Yamauchi gc::ScopedGCCriticalSection gcs(self, 4119ea02c4f01b079bf6a5f49c62cb59fa5791cbc60Hiroshi Yamauchi gc::kGcCauseInstrumentation, 4129ea02c4f01b079bf6a5f49c62cb59fa5791cbc60Hiroshi Yamauchi gc::kCollectorTypeInstrumentation); 4134f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier ScopedSuspendAll ssa(__FUNCTION__); 4144f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier if (the_trace != nullptr) { 4154f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier stop_alloc_counting = (the_trace->flags_ & Trace::kTraceCountAllocs) != 0; 4164f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier if (finish_tracing) { 4174f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier the_trace->FinishTracing(); 4184f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier } 4190abc72ebe356c32354b575c48189965a0edc7890Jeff Hao 4204f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier if (the_trace->trace_mode_ == TraceMode::kSampling) { 4219ea02c4f01b079bf6a5f49c62cb59fa5791cbc60Hiroshi Yamauchi MutexLock mu(self, *Locks::thread_list_lock_); 4224f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier runtime->GetThreadList()->ForEach(ClearThreadStackTraceAndClockBase, nullptr); 42340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe } else { 4244f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier runtime->GetInstrumentation()->DisableMethodTracing(kTracerInstrumentationKey); 4254f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier runtime->GetInstrumentation()->RemoveListener( 4264f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier the_trace, instrumentation::Instrumentation::kMethodEntered | 4274f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier instrumentation::Instrumentation::kMethodExited | 4284f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier instrumentation::Instrumentation::kMethodUnwind); 4294303ba97313458491e038d78efa041d41cf7bb43Andreas Gampe } 4304f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier if (the_trace->trace_file_.get() != nullptr) { 4314f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier // Do not try to erase, so flush and close explicitly. 4324f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier if (flush_file) { 4334f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier if (the_trace->trace_file_->Flush() != 0) { 4344f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier PLOG(WARNING) << "Could not flush trace file."; 4354f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier } 4364f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier } else { 4374f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier the_trace->trace_file_->MarkUnchecked(); // Do not trigger guard. 4384f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier } 4394f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier if (the_trace->trace_file_->Close() != 0) { 4404f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier PLOG(ERROR) << "Could not close trace file."; 4414f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier } 4424303ba97313458491e038d78efa041d41cf7bb43Andreas Gampe } 4434f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier delete the_trace; 4444303ba97313458491e038d78efa041d41cf7bb43Andreas Gampe } 44562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 4469ef78b59da51080882e47505896b420977fd79aeMathieu Chartier if (stop_alloc_counting) { 4479ef78b59da51080882e47505896b420977fd79aeMathieu Chartier // Can be racy since SetStatsEnabled is not guarded by any locks. 44802e5f160d9cc02da20d9e47af30f948c462f7043Mathieu Chartier runtime->SetStatsEnabled(false); 4490abc72ebe356c32354b575c48189965a0edc7890Jeff Hao } 4502692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao} 4512692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao 45240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampevoid Trace::Abort() { 45340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe // Do not write anything anymore. 45440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe StopTracing(false, false); 45540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe} 45640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe 45740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampevoid Trace::Stop() { 45840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe // Finish writing. 45940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe StopTracing(true, true); 46040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe} 46140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe 462b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhaovoid Trace::Shutdown() { 46364caa7dcf46ed6139b766dbe77fbd7353899417fJeff Hao if (GetMethodTracingMode() != kTracingInactive) { 46462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers Stop(); 465b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao } 466b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao} 467b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao 46840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampevoid Trace::Pause() { 46940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe bool stop_alloc_counting = false; 47040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe Runtime* runtime = Runtime::Current(); 47140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe Trace* the_trace = nullptr; 47240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe 473aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier Thread* const self = Thread::Current(); 47440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe pthread_t sampling_pthread = 0U; 47540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe { 476aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier MutexLock mu(self, *Locks::trace_lock_); 47740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe if (the_trace_ == nullptr) { 47840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe LOG(ERROR) << "Trace pause requested, but no trace currently running"; 47940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe return; 48040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe } else { 48140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe the_trace = the_trace_; 48240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe sampling_pthread = sampling_pthread_; 48340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe } 48440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe } 48540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe 48640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe if (sampling_pthread != 0U) { 48740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe { 488aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier MutexLock mu(self, *Locks::trace_lock_); 48940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe the_trace_ = nullptr; 49040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe } 49140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe CHECK_PTHREAD_CALL(pthread_join, (sampling_pthread, nullptr), "sampling thread shutdown"); 49240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe sampling_pthread_ = 0U; 49340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe { 494aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier MutexLock mu(self, *Locks::trace_lock_); 49540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe the_trace_ = the_trace; 49640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe } 49740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe } 49840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe 49940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe if (the_trace != nullptr) { 500aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier gc::ScopedGCCriticalSection gcs(self, 501aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier gc::kGcCauseInstrumentation, 502aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier gc::kCollectorTypeInstrumentation); 5034f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier ScopedSuspendAll ssa(__FUNCTION__); 50440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe stop_alloc_counting = (the_trace->flags_ & Trace::kTraceCountAllocs) != 0; 50540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe 50640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe if (the_trace->trace_mode_ == TraceMode::kSampling) { 507aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier MutexLock mu(self, *Locks::thread_list_lock_); 50840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe runtime->GetThreadList()->ForEach(ClearThreadStackTraceAndClockBase, nullptr); 50940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe } else { 5100462c4c87c39db6cfcd338f323844738109ac3c9Sebastien Hertz runtime->GetInstrumentation()->DisableMethodTracing(kTracerInstrumentationKey); 5114f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier runtime->GetInstrumentation()->RemoveListener( 5124f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier the_trace, 5134f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier instrumentation::Instrumentation::kMethodEntered | 5144f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier instrumentation::Instrumentation::kMethodExited | 5154f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier instrumentation::Instrumentation::kMethodUnwind); 51640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe } 51740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe } 51840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe 51940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe if (stop_alloc_counting) { 52040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe // Can be racy since SetStatsEnabled is not guarded by any locks. 52140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe Runtime::Current()->SetStatsEnabled(false); 52240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe } 52340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe} 52440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe 52540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampevoid Trace::Resume() { 52640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe Thread* self = Thread::Current(); 52740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe Trace* the_trace; 52840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe { 52940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe MutexLock mu(self, *Locks::trace_lock_); 53040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe if (the_trace_ == nullptr) { 53140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe LOG(ERROR) << "No trace to resume (or sampling mode), ignoring this request"; 53240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe return; 53340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe } 53440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe the_trace = the_trace_; 53540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe } 53640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe 53740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe Runtime* runtime = Runtime::Current(); 53840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe 53940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe // Enable count of allocs if specified in the flags. 54040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe bool enable_stats = (the_trace->flags_ && kTraceCountAllocs) != 0; 54140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe 5424f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier { 543aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier gc::ScopedGCCriticalSection gcs(self, 544aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier gc::kGcCauseInstrumentation, 545aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier gc::kCollectorTypeInstrumentation); 5464f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier ScopedSuspendAll ssa(__FUNCTION__); 54740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe 5484f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier // Reenable. 5494f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier if (the_trace->trace_mode_ == TraceMode::kSampling) { 5504f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier CHECK_PTHREAD_CALL(pthread_create, (&sampling_pthread_, nullptr, &RunSamplingThread, 5514f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier reinterpret_cast<void*>(the_trace->interval_us_)), "Sampling profiler thread"); 5524f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier } else { 5534f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier runtime->GetInstrumentation()->AddListener(the_trace, 5544f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier instrumentation::Instrumentation::kMethodEntered | 5554f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier instrumentation::Instrumentation::kMethodExited | 5564f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier instrumentation::Instrumentation::kMethodUnwind); 5574f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier // TODO: In full-PIC mode, we don't need to fully deopt. 5584f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier runtime->GetInstrumentation()->EnableMethodTracing(kTracerInstrumentationKey); 5594f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier } 56040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe } 56140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe 56240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe // Can't call this when holding the mutator lock. 56340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe if (enable_stats) { 56440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe runtime->SetStatsEnabled(true); 56540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe } 56640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe} 56740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe 56864caa7dcf46ed6139b766dbe77fbd7353899417fJeff HaoTracingMode Trace::GetMethodTracingMode() { 56962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers MutexLock mu(Thread::Current(), *Locks::trace_lock_); 57040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe if (the_trace_ == nullptr) { 57164caa7dcf46ed6139b766dbe77fbd7353899417fJeff Hao return kTracingInactive; 57264caa7dcf46ed6139b766dbe77fbd7353899417fJeff Hao } else { 5737e7e0f47628fb358da70c5e2766545c4f0596235Andreas Gampe switch (the_trace_->trace_mode_) { 5747e7e0f47628fb358da70c5e2766545c4f0596235Andreas Gampe case TraceMode::kSampling: 5757e7e0f47628fb358da70c5e2766545c4f0596235Andreas Gampe return kSampleProfilingActive; 5767e7e0f47628fb358da70c5e2766545c4f0596235Andreas Gampe case TraceMode::kMethodTracing: 5777e7e0f47628fb358da70c5e2766545c4f0596235Andreas Gampe return kMethodTracingActive; 5787e7e0f47628fb358da70c5e2766545c4f0596235Andreas Gampe } 5797e7e0f47628fb358da70c5e2766545c4f0596235Andreas Gampe LOG(FATAL) << "Unreachable"; 5807e7e0f47628fb358da70c5e2766545c4f0596235Andreas Gampe UNREACHABLE(); 58164caa7dcf46ed6139b766dbe77fbd7353899417fJeff Hao } 58262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers} 583a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 584e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampestatic constexpr size_t kMinBufSize = 18U; // Trace header is up to 18B. 58540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe 586e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas GampeTrace::Trace(File* trace_file, const char* trace_name, size_t buffer_size, int flags, 58740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe TraceOutputMode output_mode, TraceMode trace_mode) 58840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe : trace_file_(trace_file), 589e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampe buf_(new uint8_t[std::max(kMinBufSize, buffer_size)]()), 59040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe flags_(flags), trace_output_mode_(output_mode), trace_mode_(trace_mode), 59140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe clock_source_(default_clock_source_), 592e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampe buffer_size_(std::max(kMinBufSize, buffer_size)), 59340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe start_time_(MicroTime()), clock_overhead_ns_(GetClockOverheadNanoSeconds()), cur_offset_(0), 5944d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier overflow_(false), interval_us_(0), streaming_lock_(nullptr), 5957526d783ab68ed1dd53c763c75895cb432532b0fAndreas Gampe unique_methods_lock_(new Mutex("unique methods lock", kTracingUniqueMethodsLock)) { 59662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers uint16_t trace_version = GetTraceVersion(clock_source_); 59740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe if (output_mode == TraceOutputMode::kStreaming) { 59840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe trace_version |= 0xF0U; 59940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe } 60040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe // Set up the beginning of the trace. 6012692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao memset(buf_.get(), 0, kTraceHeaderLength); 6022692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao Append4LE(buf_.get(), kTraceMagicValue); 60362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers Append2LE(buf_.get() + 4, trace_version); 6042692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao Append2LE(buf_.get() + 6, kTraceHeaderLength); 6052692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao Append8LE(buf_.get() + 8, start_time_); 60662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (trace_version >= kTraceVersionDualClock) { 60762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers uint16_t record_size = GetRecordSize(clock_source_); 60862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers Append2LE(buf_.get() + 16, record_size); 609a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao } 610e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampe static_assert(18 <= kMinBufSize, "Minimum buffer size not large enough for trace header"); 611a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 6122692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao // Update current offset. 6138ab25ef11aed383bf7d3aa96e95f777972d1b58fIan Rogers cur_offset_.StoreRelaxed(kTraceHeaderLength); 61440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe 61540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe if (output_mode == TraceOutputMode::kStreaming) { 61640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe streaming_file_name_ = trace_name; 6177526d783ab68ed1dd53c763c75895cb432532b0fAndreas Gampe streaming_lock_ = new Mutex("tracing lock", LockLevel::kTracingStreamingLock); 61840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe seen_threads_.reset(new ThreadIDBitSet()); 61940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe } 62040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe} 62140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe 62240da286d3207d88ed8ff3f5caac4873874603428Andreas GampeTrace::~Trace() { 62340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe delete streaming_lock_; 6247526d783ab68ed1dd53c763c75895cb432532b0fAndreas Gampe delete unique_methods_lock_; 62562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers} 62662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 627e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartierstatic uint64_t ReadBytes(uint8_t* buf, size_t bytes) { 628e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier uint64_t ret = 0; 629e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier for (size_t i = 0; i < bytes; ++i) { 630e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ret |= static_cast<uint64_t>(buf[i]) << (i * 8); 631e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier } 632e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier return ret; 633e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier} 634e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier 6354d64cd45acc6a26742e8237eb65136998612820dMathieu Chartiervoid Trace::DumpBuf(uint8_t* buf, size_t buf_size, TraceClockSource clock_source) { 63662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers uint8_t* ptr = buf + kTraceHeaderLength; 63762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers uint8_t* end = buf + buf_size; 638a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 63962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers while (ptr < end) { 6404d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier uint32_t tmid = ReadBytes(ptr + 2, sizeof(tmid)); 6414d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier ArtMethod* method = DecodeTraceMethod(tmid); 64262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers TraceAction action = DecodeTraceAction(tmid); 64362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers LOG(INFO) << PrettyMethod(method) << " " << static_cast<int>(action); 64462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ptr += GetRecordSize(clock_source); 64562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 646e343b76af81a005ef64f5e75a555389fd9147dabjeffhao} 647e343b76af81a005ef64f5e75a555389fd9147dabjeffhao 64840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampestatic void GetVisitedMethodsFromBitSets( 6497526d783ab68ed1dd53c763c75895cb432532b0fAndreas Gampe const std::map<const DexFile*, DexIndexBitSet*>& seen_methods, 65090443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier std::set<ArtMethod*>* visited_methods) SHARED_REQUIRES(Locks::mutator_lock_) { 6517526d783ab68ed1dd53c763c75895cb432532b0fAndreas Gampe ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 652673ed3d8aedc5462a47ded827c99f35d46525457Mathieu Chartier Thread* const self = Thread::Current(); 65340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe for (auto& e : seen_methods) { 65440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe DexIndexBitSet* bit_set = e.second; 655673ed3d8aedc5462a47ded827c99f35d46525457Mathieu Chartier // TODO: Visit trace methods as roots. 656673ed3d8aedc5462a47ded827c99f35d46525457Mathieu Chartier mirror::DexCache* dex_cache = class_linker->FindDexCache(self, *e.first, false); 65740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe for (uint32_t i = 0; i < bit_set->size(); ++i) { 65840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe if ((*bit_set)[i]) { 6597526d783ab68ed1dd53c763c75895cb432532b0fAndreas Gampe visited_methods->insert(dex_cache->GetResolvedMethod(i, sizeof(void*))); 66040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe } 66140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe } 66240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe } 66340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe} 664a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 66540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampevoid Trace::FinishTracing() { 66640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe size_t final_offset = 0; 667a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 668e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier std::set<ArtMethod*> visited_methods; 66940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe if (trace_output_mode_ == TraceOutputMode::kStreaming) { 67040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe // Write the secondary file with all the method names. 67140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe GetVisitedMethodsFromBitSets(seen_methods_, &visited_methods); 67240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe 67340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe // Clean up. 6744d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier STLDeleteValues(&seen_methods_); 67540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe } else { 67640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe final_offset = cur_offset_.LoadRelaxed(); 67740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe GetVisitedMethods(final_offset, &visited_methods); 67840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe } 67940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe 68040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe // Compute elapsed time. 68140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe uint64_t elapsed = MicroTime() - start_time_; 682a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 683a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao std::ostringstream os; 684a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 685a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao os << StringPrintf("%cversion\n", kTraceTokenChar); 68662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers os << StringPrintf("%d\n", GetTraceVersion(clock_source_)); 687a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao os << StringPrintf("data-file-overflow=%s\n", overflow_ ? "true" : "false"); 688a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao if (UseThreadCpuClock()) { 689a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao if (UseWallClock()) { 690a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao os << StringPrintf("clock=dual\n"); 691a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao } else { 692a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao os << StringPrintf("clock=thread-cpu\n"); 693a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao } 694a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao } else { 695a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao os << StringPrintf("clock=wall\n"); 696a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao } 697ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers os << StringPrintf("elapsed-time-usec=%" PRIu64 "\n", elapsed); 69840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe if (trace_output_mode_ != TraceOutputMode::kStreaming) { 69940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe size_t num_records = (final_offset - kTraceHeaderLength) / GetRecordSize(clock_source_); 70040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe os << StringPrintf("num-method-calls=%zd\n", num_records); 70140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe } 702c5d824a20c225763761a6dff43294b229ff35469Jeff Hao os << StringPrintf("clock-call-overhead-nsec=%d\n", clock_overhead_ns_); 703a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao os << StringPrintf("vm=art\n"); 7040624a27b9a2951bfcf23321a714543e137836904John Reck os << StringPrintf("pid=%d\n", getpid()); 7050791adc2249366c50684935a4c42ba5e58bc3746jeffhao if ((flags_ & kTraceCountAllocs) != 0) { 7060791adc2249366c50684935a4c42ba5e58bc3746jeffhao os << StringPrintf("alloc-count=%d\n", Runtime::Current()->GetStat(KIND_ALLOCATED_OBJECTS)); 7070791adc2249366c50684935a4c42ba5e58bc3746jeffhao os << StringPrintf("alloc-size=%d\n", Runtime::Current()->GetStat(KIND_ALLOCATED_BYTES)); 7080791adc2249366c50684935a4c42ba5e58bc3746jeffhao os << StringPrintf("gc-count=%d\n", Runtime::Current()->GetStat(KIND_GC_INVOCATIONS)); 7090791adc2249366c50684935a4c42ba5e58bc3746jeffhao } 710a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao os << StringPrintf("%cthreads\n", kTraceTokenChar); 711a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao DumpThreadList(os); 712a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao os << StringPrintf("%cmethods\n", kTraceTokenChar); 71362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers DumpMethodList(os, visited_methods); 714a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao os << StringPrintf("%cend\n", kTraceTokenChar); 715a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao std::string header(os.str()); 71640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe 71740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe if (trace_output_mode_ == TraceOutputMode::kStreaming) { 71840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe File file; 71940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe if (!file.Open(streaming_file_name_ + ".sec", O_CREAT | O_WRONLY)) { 72040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe LOG(WARNING) << "Could not open secondary trace file!"; 72140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe return; 72262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 72340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe if (!file.WriteFully(header.c_str(), header.length())) { 72440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe file.Erase(); 7257b9d996e4cd7d154bb1a244d67139aff0c363cf2Elliott Hughes std::string detail(StringPrintf("Trace data write failed: %s", strerror(errno))); 7267b9d996e4cd7d154bb1a244d67139aff0c363cf2Elliott Hughes PLOG(ERROR) << detail; 72762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ThrowRuntimeException("%s", detail.c_str()); 728a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao } 72940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe if (file.FlushCloseOrErase() != 0) { 73040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe PLOG(ERROR) << "Could not write secondary file"; 73140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe } 73240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe } else { 73340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe if (trace_file_.get() == nullptr) { 73440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe iovec iov[2]; 73540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe iov[0].iov_base = reinterpret_cast<void*>(const_cast<char*>(header.c_str())); 73640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe iov[0].iov_len = header.length(); 73740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe iov[1].iov_base = buf_.get(); 73840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe iov[1].iov_len = final_offset; 73940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe Dbg::DdmSendChunkV(CHUNK_TYPE("MPSE"), iov, 2); 74040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe const bool kDumpTraceInfo = false; 74140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe if (kDumpTraceInfo) { 74240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe LOG(INFO) << "Trace sent:\n" << header; 74340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe DumpBuf(buf_.get(), final_offset, clock_source_); 74440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe } 74540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe } else { 74640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe if (!trace_file_->WriteFully(header.c_str(), header.length()) || 74740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe !trace_file_->WriteFully(buf_.get(), final_offset)) { 74840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe std::string detail(StringPrintf("Trace data write failed: %s", strerror(errno))); 74940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe PLOG(ERROR) << detail; 75040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe ThrowRuntimeException("%s", detail.c_str()); 75140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe } 75240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe } 753a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao } 754e343b76af81a005ef64f5e75a555389fd9147dabjeffhao} 755e343b76af81a005ef64f5e75a555389fd9147dabjeffhao 7564b8f1ecd3aa5a29ec1463ff88fee9db365f257dcRoland Levillainvoid Trace::DexPcMoved(Thread* thread ATTRIBUTE_UNUSED, 7574b8f1ecd3aa5a29ec1463ff88fee9db365f257dcRoland Levillain mirror::Object* this_object ATTRIBUTE_UNUSED, 7584b8f1ecd3aa5a29ec1463ff88fee9db365f257dcRoland Levillain ArtMethod* method, 7594b8f1ecd3aa5a29ec1463ff88fee9db365f257dcRoland Levillain uint32_t new_dex_pc) { 76062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers // We're not recorded to listen to this kind of event, so complain. 76162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers LOG(ERROR) << "Unexpected dex PC event in tracing " << PrettyMethod(method) << " " << new_dex_pc; 762c8ccf68b805c92674545f63e0341ba47e8d9701cAndreas Gampe} 76362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 7644b8f1ecd3aa5a29ec1463ff88fee9db365f257dcRoland Levillainvoid Trace::FieldRead(Thread* thread ATTRIBUTE_UNUSED, 7654b8f1ecd3aa5a29ec1463ff88fee9db365f257dcRoland Levillain mirror::Object* this_object ATTRIBUTE_UNUSED, 7664b8f1ecd3aa5a29ec1463ff88fee9db365f257dcRoland Levillain ArtMethod* method, 7674b8f1ecd3aa5a29ec1463ff88fee9db365f257dcRoland Levillain uint32_t dex_pc, 7684b8f1ecd3aa5a29ec1463ff88fee9db365f257dcRoland Levillain ArtField* field ATTRIBUTE_UNUSED) 76990443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier SHARED_REQUIRES(Locks::mutator_lock_) { 7703f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz // We're not recorded to listen to this kind of event, so complain. 7713f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz LOG(ERROR) << "Unexpected field read event in tracing " << PrettyMethod(method) << " " << dex_pc; 7723f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz} 7733f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz 7744b8f1ecd3aa5a29ec1463ff88fee9db365f257dcRoland Levillainvoid Trace::FieldWritten(Thread* thread ATTRIBUTE_UNUSED, 7754b8f1ecd3aa5a29ec1463ff88fee9db365f257dcRoland Levillain mirror::Object* this_object ATTRIBUTE_UNUSED, 7764b8f1ecd3aa5a29ec1463ff88fee9db365f257dcRoland Levillain ArtMethod* method, 7774b8f1ecd3aa5a29ec1463ff88fee9db365f257dcRoland Levillain uint32_t dex_pc, 7784b8f1ecd3aa5a29ec1463ff88fee9db365f257dcRoland Levillain ArtField* field ATTRIBUTE_UNUSED, 7794b8f1ecd3aa5a29ec1463ff88fee9db365f257dcRoland Levillain const JValue& field_value ATTRIBUTE_UNUSED) 78090443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier SHARED_REQUIRES(Locks::mutator_lock_) { 7813f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz // We're not recorded to listen to this kind of event, so complain. 7823f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz LOG(ERROR) << "Unexpected field write event in tracing " << PrettyMethod(method) << " " << dex_pc; 7833f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz} 7843f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz 7856a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersvoid Trace::MethodEntered(Thread* thread, mirror::Object* this_object ATTRIBUTE_UNUSED, 786e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod* method, uint32_t dex_pc ATTRIBUTE_UNUSED) { 787c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao uint32_t thread_clock_diff = 0; 788c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao uint32_t wall_clock_diff = 0; 789c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao ReadClocks(thread, &thread_clock_diff, &wall_clock_diff); 790c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao LogMethodTraceEvent(thread, method, instrumentation::Instrumentation::kMethodEntered, 791c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao thread_clock_diff, wall_clock_diff); 79262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers} 79362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 7946a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersvoid Trace::MethodExited(Thread* thread, mirror::Object* this_object ATTRIBUTE_UNUSED, 795e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod* method, uint32_t dex_pc ATTRIBUTE_UNUSED, 7966a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers const JValue& return_value ATTRIBUTE_UNUSED) { 797c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao uint32_t thread_clock_diff = 0; 798c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao uint32_t wall_clock_diff = 0; 799c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao ReadClocks(thread, &thread_clock_diff, &wall_clock_diff); 800c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao LogMethodTraceEvent(thread, method, instrumentation::Instrumentation::kMethodExited, 801c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao thread_clock_diff, wall_clock_diff); 80262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers} 80362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 8046a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersvoid Trace::MethodUnwind(Thread* thread, mirror::Object* this_object ATTRIBUTE_UNUSED, 805e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod* method, uint32_t dex_pc ATTRIBUTE_UNUSED) { 806c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao uint32_t thread_clock_diff = 0; 807c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao uint32_t wall_clock_diff = 0; 808c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao ReadClocks(thread, &thread_clock_diff, &wall_clock_diff); 809c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao LogMethodTraceEvent(thread, method, instrumentation::Instrumentation::kMethodUnwind, 810c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao thread_clock_diff, wall_clock_diff); 81162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers} 81262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 8134b8f1ecd3aa5a29ec1463ff88fee9db365f257dcRoland Levillainvoid Trace::ExceptionCaught(Thread* thread ATTRIBUTE_UNUSED, 8144b8f1ecd3aa5a29ec1463ff88fee9db365f257dcRoland Levillain mirror::Throwable* exception_object ATTRIBUTE_UNUSED) 81590443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier SHARED_REQUIRES(Locks::mutator_lock_) { 81662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers LOG(ERROR) << "Unexpected exception caught event in tracing"; 81762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers} 818a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 81981f0f953c4bb159997046c962d44cb1898b1778dNicolas Geoffrayvoid Trace::Branch(Thread* /*thread*/, ArtMethod* method, 82081f0f953c4bb159997046c962d44cb1898b1778dNicolas Geoffray uint32_t /*dex_pc*/, int32_t /*dex_pc_offset*/) 82190443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier SHARED_REQUIRES(Locks::mutator_lock_) { 82281f0f953c4bb159997046c962d44cb1898b1778dNicolas Geoffray LOG(ERROR) << "Unexpected branch event in tracing" << PrettyMethod(method); 823e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier} 824e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 8255550ca8bcc742b109d77e62f3a0877c667d894d3Nicolas Geoffrayvoid Trace::InvokeVirtualOrInterface(Thread*, 8265550ca8bcc742b109d77e62f3a0877c667d894d3Nicolas Geoffray mirror::Object*, 8275550ca8bcc742b109d77e62f3a0877c667d894d3Nicolas Geoffray ArtMethod* method, 8285550ca8bcc742b109d77e62f3a0877c667d894d3Nicolas Geoffray uint32_t dex_pc, 8295550ca8bcc742b109d77e62f3a0877c667d894d3Nicolas Geoffray ArtMethod*) { 8305550ca8bcc742b109d77e62f3a0877c667d894d3Nicolas Geoffray LOG(ERROR) << "Unexpected invoke event in tracing" << PrettyMethod(method) 8315550ca8bcc742b109d77e62f3a0877c667d894d3Nicolas Geoffray << " " << dex_pc; 8325550ca8bcc742b109d77e62f3a0877c667d894d3Nicolas Geoffray} 8335550ca8bcc742b109d77e62f3a0877c667d894d3Nicolas Geoffray 834c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Haovoid Trace::ReadClocks(Thread* thread, uint32_t* thread_clock_diff, uint32_t* wall_clock_diff) { 835c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao if (UseThreadCpuClock()) { 836c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao uint64_t clock_base = thread->GetTraceClockBase(); 837c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao if (UNLIKELY(clock_base == 0)) { 838c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao // First event, record the base time in the map. 839c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao uint64_t time = thread->GetCpuMicroTime(); 840c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao thread->SetTraceClockBase(time); 841c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao } else { 842c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao *thread_clock_diff = thread->GetCpuMicroTime() - clock_base; 843c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao } 844c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao } 845c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao if (UseWallClock()) { 846c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao *wall_clock_diff = MicroTime() - start_time_; 847c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao } 848c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao} 849c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao 850e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartierbool Trace::RegisterMethod(ArtMethod* method) { 85140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe mirror::DexCache* dex_cache = method->GetDexCache(); 8527526d783ab68ed1dd53c763c75895cb432532b0fAndreas Gampe const DexFile* dex_file = dex_cache->GetDexFile(); 853e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier auto* resolved_method = dex_cache->GetResolvedMethod(method->GetDexMethodIndex(), sizeof(void*)); 854e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier if (resolved_method != method) { 855e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier DCHECK(resolved_method == nullptr); 856e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier dex_cache->SetResolvedMethod(method->GetDexMethodIndex(), method, sizeof(void*)); 85740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe } 8587526d783ab68ed1dd53c763c75895cb432532b0fAndreas Gampe if (seen_methods_.find(dex_file) == seen_methods_.end()) { 8597526d783ab68ed1dd53c763c75895cb432532b0fAndreas Gampe seen_methods_.insert(std::make_pair(dex_file, new DexIndexBitSet())); 86040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe } 8617526d783ab68ed1dd53c763c75895cb432532b0fAndreas Gampe DexIndexBitSet* bit_set = seen_methods_.find(dex_file)->second; 86240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe if (!(*bit_set)[method->GetDexMethodIndex()]) { 86340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe bit_set->set(method->GetDexMethodIndex()); 86440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe return true; 86540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe } 86640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe return false; 86740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe} 86840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe 86940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampebool Trace::RegisterThread(Thread* thread) { 87040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe pid_t tid = thread->GetTid(); 87140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe CHECK_LT(0U, static_cast<uint32_t>(tid)); 87240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe CHECK_LT(static_cast<uint32_t>(tid), 65536U); 87340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe 87440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe if (!(*seen_threads_)[tid]) { 87540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe seen_threads_->set(tid); 87640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe return true; 87740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe } 87840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe return false; 87940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe} 88040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe 8814d64cd45acc6a26742e8237eb65136998612820dMathieu Chartierstd::string Trace::GetMethodLine(ArtMethod* method) { 882e3b034a6f6f0d80d519ab08bdd18be4de2a4a2dbMathieu Chartier method = method->GetInterfaceMethodIfProxy(sizeof(void*)); 8834d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier return StringPrintf("%p\t%s\t%s\t%s\t%s\n", 8844d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier reinterpret_cast<void*>((EncodeTraceMethod(method) << TraceActionBits)), 88540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe PrettyDescriptor(method->GetDeclaringClassDescriptor()).c_str(), method->GetName(), 88640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe method->GetSignature().ToString().c_str(), method->GetDeclaringClassSourceFile()); 88740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe} 88840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe 88940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampevoid Trace::WriteToBuf(const uint8_t* src, size_t src_size) { 89040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe int32_t old_offset = cur_offset_.LoadRelaxed(); 89140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe int32_t new_offset = old_offset + static_cast<int32_t>(src_size); 892e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampe if (dchecked_integral_cast<size_t>(new_offset) > buffer_size_) { 89340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe // Flush buffer. 89440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe if (!trace_file_->WriteFully(buf_.get(), old_offset)) { 89540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe PLOG(WARNING) << "Failed streaming a tracing event."; 89640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe } 897e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampe 898e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampe // Check whether the data is too large for the buffer, then write immediately. 899e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampe if (src_size >= buffer_size_) { 900e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampe if (!trace_file_->WriteFully(src, src_size)) { 901e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampe PLOG(WARNING) << "Failed streaming a tracing event."; 902e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampe } 903e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampe cur_offset_.StoreRelease(0); // Buffer is empty now. 904e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampe return; 905e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampe } 906e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampe 90740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe old_offset = 0; 90840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe new_offset = static_cast<int32_t>(src_size); 90940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe } 91040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe cur_offset_.StoreRelease(new_offset); 91140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe // Fill in data. 91240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe memcpy(buf_.get() + old_offset, src, src_size); 91340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe} 91440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe 915e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartiervoid Trace::LogMethodTraceEvent(Thread* thread, ArtMethod* method, 916c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao instrumentation::Instrumentation::InstrumentationEvent event, 917c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao uint32_t thread_clock_diff, uint32_t wall_clock_diff) { 918a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao // Advance cur_offset_ atomically. 919a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao int32_t new_offset; 92040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe int32_t old_offset = 0; 92140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe 92240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe // We do a busy loop here trying to acquire the next offset. 92340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe if (trace_output_mode_ != TraceOutputMode::kStreaming) { 92440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe do { 92540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe old_offset = cur_offset_.LoadRelaxed(); 92640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe new_offset = old_offset + GetRecordSize(clock_source_); 927e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampe if (static_cast<size_t>(new_offset) > buffer_size_) { 92840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe overflow_ = true; 92940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe return; 93040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe } 93140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe } while (!cur_offset_.CompareExchangeWeakSequentiallyConsistent(old_offset, new_offset)); 93240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe } 933a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 93462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers TraceAction action = kTraceMethodEnter; 93562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers switch (event) { 93662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers case instrumentation::Instrumentation::kMethodEntered: 93762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers action = kTraceMethodEnter; 93862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers break; 93962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers case instrumentation::Instrumentation::kMethodExited: 94062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers action = kTraceMethodExit; 94162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers break; 94262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers case instrumentation::Instrumentation::kMethodUnwind: 94362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers action = kTraceUnroll; 94462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers break; 94562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers default: 94662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers UNIMPLEMENTED(FATAL) << "Unexpected event: " << event; 94762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 94862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 9494d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier uint32_t method_value = EncodeTraceMethodAndAction(method, action); 950a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 951a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao // Write data 95240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe uint8_t* ptr; 9534d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier static constexpr size_t kPacketSize = 14U; // The maximum size of data in a packet. 95440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe uint8_t stack_buf[kPacketSize]; // Space to store a packet when in streaming mode. 95540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe if (trace_output_mode_ == TraceOutputMode::kStreaming) { 95640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe ptr = stack_buf; 95740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe } else { 95840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe ptr = buf_.get() + old_offset; 95940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe } 96040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe 96162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers Append2LE(ptr, thread->GetTid()); 9624d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier Append4LE(ptr + 2, method_value); 9634d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier ptr += 6; 964a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 965a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao if (UseThreadCpuClock()) { 966a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao Append4LE(ptr, thread_clock_diff); 967a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao ptr += 4; 968e343b76af81a005ef64f5e75a555389fd9147dabjeffhao } 969a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao if (UseWallClock()) { 970a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao Append4LE(ptr, wall_clock_diff); 971a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao } 9724d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier static_assert(kPacketSize == 2 + 4 + 4 + 4, "Packet size incorrect."); 97340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe 97440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe if (trace_output_mode_ == TraceOutputMode::kStreaming) { 97540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe MutexLock mu(Thread::Current(), *streaming_lock_); // To serialize writing. 97640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe if (RegisterMethod(method)) { 97740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe // Write a special block with the name. 97840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe std::string method_line(GetMethodLine(method)); 97940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe uint8_t buf2[5]; 98040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe Append2LE(buf2, 0); 98140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe buf2[2] = kOpNewMethod; 98240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe Append2LE(buf2 + 3, static_cast<uint16_t>(method_line.length())); 98340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe WriteToBuf(buf2, sizeof(buf2)); 98440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe WriteToBuf(reinterpret_cast<const uint8_t*>(method_line.c_str()), method_line.length()); 98540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe } 98640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe if (RegisterThread(thread)) { 98740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe // It might be better to postpone this. Threads might not have received names... 98840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe std::string thread_name; 98940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe thread->GetThreadName(thread_name); 99040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe uint8_t buf2[7]; 99140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe Append2LE(buf2, 0); 99240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe buf2[2] = kOpNewThread; 99340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe Append2LE(buf2 + 3, static_cast<uint16_t>(thread->GetTid())); 99440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe Append2LE(buf2 + 5, static_cast<uint16_t>(thread_name.length())); 99540da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe WriteToBuf(buf2, sizeof(buf2)); 99640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe WriteToBuf(reinterpret_cast<const uint8_t*>(thread_name.c_str()), thread_name.length()); 99740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe } 99840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe WriteToBuf(stack_buf, sizeof(stack_buf)); 99940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe } 1000a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao} 1001a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 100262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid Trace::GetVisitedMethods(size_t buf_size, 1003e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier std::set<ArtMethod*>* visited_methods) { 10042692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao uint8_t* ptr = buf_.get() + kTraceHeaderLength; 100562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers uint8_t* end = buf_.get() + buf_size; 1006a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 1007a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao while (ptr < end) { 10084d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier uint32_t tmid = ReadBytes(ptr + 2, sizeof(tmid)); 10094d64cd45acc6a26742e8237eb65136998612820dMathieu Chartier ArtMethod* method = DecodeTraceMethod(tmid); 101062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers visited_methods->insert(method); 101162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ptr += GetRecordSize(clock_source_); 1012a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao } 1013a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao} 1014a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 1015e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartiervoid Trace::DumpMethodList(std::ostream& os, const std::set<ArtMethod*>& visited_methods) { 101602e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier for (const auto& method : visited_methods) { 101740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe os << GetMethodLine(method); 1018a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao } 1019a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao} 1020a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 1021a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhaostatic void DumpThread(Thread* t, void* arg) { 1022ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes std::ostream& os = *reinterpret_cast<std::ostream*>(arg); 1023ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes std::string name; 1024ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes t->GetThreadName(name); 1025ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes os << t->GetTid() << "\t" << name << "\n"; 1026a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao} 1027a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 1028a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhaovoid Trace::DumpThreadList(std::ostream& os) { 102981d425b0b232962441616f8b14f73620bffef5e5Ian Rogers Thread* self = Thread::Current(); 1030e094b87c6f6ea9ebf83aa56a3114ac59556aaf9fJeff Hao for (auto it : exited_threads_) { 1031e094b87c6f6ea9ebf83aa56a3114ac59556aaf9fJeff Hao os << it.first << "\t" << it.second << "\n"; 1032e094b87c6f6ea9ebf83aa56a3114ac59556aaf9fJeff Hao } 103381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers Locks::thread_list_lock_->AssertNotHeld(self); 103481d425b0b232962441616f8b14f73620bffef5e5Ian Rogers MutexLock mu(self, *Locks::thread_list_lock_); 1035a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao Runtime::Current()->GetThreadList()->ForEach(DumpThread, &os); 1036a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao} 1037a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 1038e094b87c6f6ea9ebf83aa56a3114ac59556aaf9fJeff Haovoid Trace::StoreExitingThreadInfo(Thread* thread) { 1039e094b87c6f6ea9ebf83aa56a3114ac59556aaf9fJeff Hao MutexLock mu(thread, *Locks::trace_lock_); 1040e094b87c6f6ea9ebf83aa56a3114ac59556aaf9fJeff Hao if (the_trace_ != nullptr) { 1041e094b87c6f6ea9ebf83aa56a3114ac59556aaf9fJeff Hao std::string name; 1042e094b87c6f6ea9ebf83aa56a3114ac59556aaf9fJeff Hao thread->GetThreadName(name); 1043a1785c5cd88f6256a838a95c93ac0a1bee6c5145Andreas Gampe // The same thread/tid may be used multiple times. As SafeMap::Put does not allow to override 1044a1785c5cd88f6256a838a95c93ac0a1bee6c5145Andreas Gampe // a previous mapping, use SafeMap::Overwrite. 1045a1785c5cd88f6256a838a95c93ac0a1bee6c5145Andreas Gampe the_trace_->exited_threads_.Overwrite(thread->GetTid(), name); 1046e094b87c6f6ea9ebf83aa56a3114ac59556aaf9fJeff Hao } 1047e094b87c6f6ea9ebf83aa56a3114ac59556aaf9fJeff Hao} 1048e094b87c6f6ea9ebf83aa56a3114ac59556aaf9fJeff Hao 104940da286d3207d88ed8ff3f5caac4873874603428Andreas GampeTrace::TraceOutputMode Trace::GetOutputMode() { 105040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe MutexLock mu(Thread::Current(), *Locks::trace_lock_); 105140da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe CHECK(the_trace_ != nullptr) << "Trace output mode requested, but no trace currently running"; 105240da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe return the_trace_->trace_output_mode_; 105340da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe} 105440da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe 105540da286d3207d88ed8ff3f5caac4873874603428Andreas GampeTrace::TraceMode Trace::GetMode() { 105640da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe MutexLock mu(Thread::Current(), *Locks::trace_lock_); 105740da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe CHECK(the_trace_ != nullptr) << "Trace mode requested, but no trace currently running"; 105840da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe return the_trace_->trace_mode_; 105940da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe} 106040da286d3207d88ed8ff3f5caac4873874603428Andreas Gampe 1061e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampesize_t Trace::GetBufferSize() { 1062e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampe MutexLock mu(Thread::Current(), *Locks::trace_lock_); 1063e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampe CHECK(the_trace_ != nullptr) << "Trace mode requested, but no trace currently running"; 1064e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampe return the_trace_->buffer_size_; 1065e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampe} 1066e34a42cd37b2b3b6b21280df14fa6f40917b5d6eAndreas Gampe 10677778b880b9cf46fe7a303b11477bd92b5cf65316Mathieu Chartierbool Trace::IsTracingEnabled() { 10687778b880b9cf46fe7a303b11477bd92b5cf65316Mathieu Chartier MutexLock mu(Thread::Current(), *Locks::trace_lock_); 10697778b880b9cf46fe7a303b11477bd92b5cf65316Mathieu Chartier return the_trace_ != nullptr; 10707778b880b9cf46fe7a303b11477bd92b5cf65316Mathieu Chartier} 10717778b880b9cf46fe7a303b11477bd92b5cf65316Mathieu Chartier 1072e343b76af81a005ef64f5e75a555389fd9147dabjeffhao} // namespace art 1073