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