blob: d3b3af871f57ee887e7460b0d7c2cf4d485ed7f8 [file] [log] [blame]
Elliott Hughes2faa5f12012-01-30 14:42:07 -08001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
jeffhaoe343b762011-12-05 16:36:44 -080016
17#include "trace.h"
18
jeffhaoa9ef3fd2011-12-13 18:33:43 -080019#include <sys/uio.h>
John Reck0624a272015-03-26 15:47:54 -070020#include <unistd.h>
jeffhaoa9ef3fd2011-12-13 18:33:43 -080021
Ian Rogerscf7f1912014-10-22 22:06:39 -070022#define ATRACE_TAG ATRACE_TAG_DALVIK
23#include "cutils/trace.h"
24
Mathieu Chartiere401d142015-04-22 13:56:20 -070025#include "art_method-inl.h"
Andreas Gampee34a42c2015-04-25 14:44:29 -070026#include "base/casts.h"
Jeff Hao0abc72e2013-08-13 13:45:14 -070027#include "base/stl_util.h"
Vladimir Marko80afd022015-05-19 18:08:00 +010028#include "base/time_utils.h"
Elliott Hughes76160052012-12-12 16:31:20 -080029#include "base/unix_file/fd_file.h"
jeffhaoe343b762011-12-05 16:36:44 -080030#include "class_linker.h"
Ian Rogers62d6c772013-02-27 08:32:07 -080031#include "common_throws.h"
jeffhaoa9ef3fd2011-12-13 18:33:43 -080032#include "debugger.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070033#include "dex_file-inl.h"
jeffhao725a9572012-11-13 18:20:12 -080034#include "instrumentation.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070035#include "mirror/class-inl.h"
Andreas Gampe40da2862015-02-27 12:49:04 -080036#include "mirror/dex_cache-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080037#include "mirror/object_array-inl.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070038#include "mirror/object-inl.h"
jeffhaoa9ef3fd2011-12-13 18:33:43 -080039#include "os.h"
Ian Rogers00f7d0e2012-07-19 15:28:27 -070040#include "scoped_thread_state_change.h"
Jeff Hao0abc72e2013-08-13 13:45:14 -070041#include "ScopedLocalRef.h"
jeffhaoe343b762011-12-05 16:36:44 -080042#include "thread.h"
Ian Rogers57b86d42012-03-27 16:05:41 -070043#include "thread_list.h"
Vladimir Marko80afd022015-05-19 18:08:00 +010044#include "utils.h"
Ian Rogers166db042013-07-26 12:05:57 -070045#include "entrypoints/quick/quick_entrypoints.h"
jeffhao2692b572011-12-16 15:42:28 -080046
47namespace art {
48
Elliott Hughese119a362012-05-22 17:37:06 -070049// File format:
50// header
51// record 0
52// record 1
53// ...
54//
55// Header format:
56// u4 magic ('SLOW')
57// u2 version
58// u2 offset to data
59// u8 start date/time in usec
60// u2 record size in bytes (version >= 2 only)
61// ... padding to 32 bytes
62//
63// Record format v1:
64// u1 thread ID
65// u4 method ID | method action
66// u4 time delta since start, in usec
67//
68// Record format v2:
69// u2 thread ID
70// u4 method ID | method action
71// u4 time delta since start, in usec
72//
73// Record format v3:
74// u2 thread ID
75// u4 method ID | method action
76// u4 time delta since start, in usec
77// u4 wall time since start, in usec (when clock == "dual" only)
78//
79// 32 bits of microseconds is 70 minutes.
80//
81// All values are stored in little-endian order.
82
Ian Rogers62d6c772013-02-27 08:32:07 -080083enum TraceAction {
Brian Carlstrom7934ac22013-07-26 10:54:15 -070084 kTraceMethodEnter = 0x00, // method entry
85 kTraceMethodExit = 0x01, // method exit
86 kTraceUnroll = 0x02, // method exited by exception unrolling
Ian Rogers62d6c772013-02-27 08:32:07 -080087 // 0x03 currently unused
Brian Carlstrom7934ac22013-07-26 10:54:15 -070088 kTraceMethodActionMask = 0x03, // two bits
Ian Rogers62d6c772013-02-27 08:32:07 -080089};
90
Andreas Gampe40da2862015-02-27 12:49:04 -080091static constexpr uint8_t kOpNewMethod = 1U;
92static constexpr uint8_t kOpNewThread = 2U;
93
Jeff Hao0abc72e2013-08-13 13:45:14 -070094class BuildStackTraceVisitor : public StackVisitor {
95 public:
Nicolas Geoffray8e5bd182015-05-06 11:34:34 +010096 explicit BuildStackTraceVisitor(Thread* thread)
97 : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
98 method_trace_(Trace::AllocStackTrace()) {}
Jeff Hao0abc72e2013-08-13 13:45:14 -070099
Ian Rogersef7d42f2014-01-06 12:55:46 -0800100 bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700101 ArtMethod* m = GetMethod();
Jeff Hao0abc72e2013-08-13 13:45:14 -0700102 // Ignore runtime frames (in particular callee save).
103 if (!m->IsRuntimeMethod()) {
104 method_trace_->push_back(m);
105 }
106 return true;
107 }
108
109 // Returns a stack trace where the topmost frame corresponds with the first element of the vector.
Mathieu Chartiere401d142015-04-22 13:56:20 -0700110 std::vector<ArtMethod*>* GetStackTrace() const {
Jeff Hao0abc72e2013-08-13 13:45:14 -0700111 return method_trace_;
112 }
113
114 private:
Mathieu Chartiere401d142015-04-22 13:56:20 -0700115 std::vector<ArtMethod*>* const method_trace_;
Jeff Hao0abc72e2013-08-13 13:45:14 -0700116};
117
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800118static const char kTraceTokenChar = '*';
119static const uint16_t kTraceHeaderLength = 32;
120static const uint32_t kTraceMagicValue = 0x574f4c53;
121static const uint16_t kTraceVersionSingleClock = 2;
122static const uint16_t kTraceVersionDualClock = 3;
Mathieu Chartiere401d142015-04-22 13:56:20 -0700123static const uint16_t kTraceRecordSizeSingleClock = 14; // using v2
124static const uint16_t kTraceRecordSizeDualClock = 18; // using v3 with two timestamps
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800125
Ian Rogerse63db272014-07-15 15:36:11 -0700126TraceClockSource Trace::default_clock_source_ = kDefaultTraceClockSource;
Elliott Hughese119a362012-05-22 17:37:06 -0700127
Andreas Gampe40da2862015-02-27 12:49:04 -0800128Trace* volatile Trace::the_trace_ = nullptr;
Jeff Hao0abc72e2013-08-13 13:45:14 -0700129pthread_t Trace::sampling_pthread_ = 0U;
Mathieu Chartiere401d142015-04-22 13:56:20 -0700130std::unique_ptr<std::vector<ArtMethod*>> Trace::temp_stack_trace_;
Ian Rogers62d6c772013-02-27 08:32:07 -0800131
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200132// The key identifying the tracer to update instrumentation.
133static constexpr const char* kTracerInstrumentationKey = "Tracer";
134
Mathieu Chartiere401d142015-04-22 13:56:20 -0700135static ArtMethod* DecodeTraceMethodId(uint64_t tmid) {
136 return reinterpret_cast<ArtMethod*>(tmid & ~kTraceMethodActionMask);
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800137}
Elliott Hughese119a362012-05-22 17:37:06 -0700138
Ian Rogers62d6c772013-02-27 08:32:07 -0800139static TraceAction DecodeTraceAction(uint32_t tmid) {
140 return static_cast<TraceAction>(tmid & kTraceMethodActionMask);
141}
142
Mathieu Chartiere401d142015-04-22 13:56:20 -0700143static uint64_t EncodeTraceMethodAndAction(ArtMethod* method, TraceAction action) {
144 auto tmid = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(method)) | action;
Ian Rogers62d6c772013-02-27 08:32:07 -0800145 DCHECK_EQ(method, DecodeTraceMethodId(tmid));
146 return tmid;
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800147}
148
Mathieu Chartiere401d142015-04-22 13:56:20 -0700149std::vector<ArtMethod*>* Trace::AllocStackTrace() {
Andreas Gampe40da2862015-02-27 12:49:04 -0800150 if (temp_stack_trace_.get() != nullptr) {
Jeff Hao5ce4b172013-08-16 16:27:18 -0700151 return temp_stack_trace_.release();
152 } else {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700153 return new std::vector<ArtMethod*>();
Jeff Hao5ce4b172013-08-16 16:27:18 -0700154 }
155}
156
Mathieu Chartiere401d142015-04-22 13:56:20 -0700157void Trace::FreeStackTrace(std::vector<ArtMethod*>* stack_trace) {
Jeff Hao5ce4b172013-08-16 16:27:18 -0700158 stack_trace->clear();
159 temp_stack_trace_.reset(stack_trace);
160}
161
Ian Rogerse63db272014-07-15 15:36:11 -0700162void Trace::SetDefaultClockSource(TraceClockSource clock_source) {
Elliott Hughes0a18df82015-01-09 15:16:16 -0800163#if defined(__linux__)
Ian Rogers62d6c772013-02-27 08:32:07 -0800164 default_clock_source_ = clock_source;
165#else
Igor Murashkinaaebaa02015-01-26 10:55:53 -0800166 if (clock_source != TraceClockSource::kWall) {
Jeff Hao5ce4b172013-08-16 16:27:18 -0700167 LOG(WARNING) << "Ignoring tracing request to use CPU time.";
Ian Rogers62d6c772013-02-27 08:32:07 -0800168 }
169#endif
170}
171
Ian Rogerse63db272014-07-15 15:36:11 -0700172static uint16_t GetTraceVersion(TraceClockSource clock_source) {
Igor Murashkinaaebaa02015-01-26 10:55:53 -0800173 return (clock_source == TraceClockSource::kDual) ? kTraceVersionDualClock
Ian Rogers62d6c772013-02-27 08:32:07 -0800174 : kTraceVersionSingleClock;
175}
176
Ian Rogerse63db272014-07-15 15:36:11 -0700177static uint16_t GetRecordSize(TraceClockSource clock_source) {
Igor Murashkinaaebaa02015-01-26 10:55:53 -0800178 return (clock_source == TraceClockSource::kDual) ? kTraceRecordSizeDualClock
Ian Rogers62d6c772013-02-27 08:32:07 -0800179 : kTraceRecordSizeSingleClock;
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800180}
181
Elliott Hughese119a362012-05-22 17:37:06 -0700182bool Trace::UseThreadCpuClock() {
Igor Murashkinaaebaa02015-01-26 10:55:53 -0800183 return (clock_source_ == TraceClockSource::kThreadCpu) ||
184 (clock_source_ == TraceClockSource::kDual);
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800185}
186
Elliott Hughese119a362012-05-22 17:37:06 -0700187bool Trace::UseWallClock() {
Igor Murashkinaaebaa02015-01-26 10:55:53 -0800188 return (clock_source_ == TraceClockSource::kWall) ||
189 (clock_source_ == TraceClockSource::kDual);
Elliott Hughese119a362012-05-22 17:37:06 -0700190}
191
Jeff Haoc5d824a2014-07-28 18:35:38 -0700192void Trace::MeasureClockOverhead() {
193 if (UseThreadCpuClock()) {
Jeff Hao57dac6e2013-08-15 16:36:24 -0700194 Thread::Current()->GetCpuMicroTime();
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800195 }
Jeff Haoc5d824a2014-07-28 18:35:38 -0700196 if (UseWallClock()) {
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800197 MicroTime();
198 }
199}
200
Jeff Hao5ce4b172013-08-16 16:27:18 -0700201// Compute an average time taken to measure clocks.
Jeff Haoc5d824a2014-07-28 18:35:38 -0700202uint32_t Trace::GetClockOverheadNanoSeconds() {
Jeff Hao57dac6e2013-08-15 16:36:24 -0700203 Thread* self = Thread::Current();
204 uint64_t start = self->GetCpuMicroTime();
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800205
206 for (int i = 4000; i > 0; i--) {
Jeff Haoc5d824a2014-07-28 18:35:38 -0700207 MeasureClockOverhead();
208 MeasureClockOverhead();
209 MeasureClockOverhead();
210 MeasureClockOverhead();
211 MeasureClockOverhead();
212 MeasureClockOverhead();
213 MeasureClockOverhead();
214 MeasureClockOverhead();
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800215 }
216
Jeff Hao5ce4b172013-08-16 16:27:18 -0700217 uint64_t elapsed_us = self->GetCpuMicroTime() - start;
218 return static_cast<uint32_t>(elapsed_us / 32);
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800219}
220
Elliott Hughesffb465f2012-03-01 18:46:05 -0800221// TODO: put this somewhere with the big-endian equivalent used by JDWP.
222static void Append2LE(uint8_t* buf, uint16_t val) {
Jeff Hao5ce4b172013-08-16 16:27:18 -0700223 *buf++ = static_cast<uint8_t>(val);
224 *buf++ = static_cast<uint8_t>(val >> 8);
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800225}
226
Elliott Hughesffb465f2012-03-01 18:46:05 -0800227// TODO: put this somewhere with the big-endian equivalent used by JDWP.
228static void Append4LE(uint8_t* buf, uint32_t val) {
Jeff Hao5ce4b172013-08-16 16:27:18 -0700229 *buf++ = static_cast<uint8_t>(val);
230 *buf++ = static_cast<uint8_t>(val >> 8);
231 *buf++ = static_cast<uint8_t>(val >> 16);
232 *buf++ = static_cast<uint8_t>(val >> 24);
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800233}
234
Elliott Hughesffb465f2012-03-01 18:46:05 -0800235// TODO: put this somewhere with the big-endian equivalent used by JDWP.
236static void Append8LE(uint8_t* buf, uint64_t val) {
Jeff Hao5ce4b172013-08-16 16:27:18 -0700237 *buf++ = static_cast<uint8_t>(val);
238 *buf++ = static_cast<uint8_t>(val >> 8);
239 *buf++ = static_cast<uint8_t>(val >> 16);
240 *buf++ = static_cast<uint8_t>(val >> 24);
241 *buf++ = static_cast<uint8_t>(val >> 32);
242 *buf++ = static_cast<uint8_t>(val >> 40);
243 *buf++ = static_cast<uint8_t>(val >> 48);
244 *buf++ = static_cast<uint8_t>(val >> 56);
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800245}
246
Jeff Hao0abc72e2013-08-13 13:45:14 -0700247static void GetSample(Thread* thread, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
248 BuildStackTraceVisitor build_trace_visitor(thread);
249 build_trace_visitor.WalkStack();
Mathieu Chartiere401d142015-04-22 13:56:20 -0700250 std::vector<ArtMethod*>* stack_trace = build_trace_visitor.GetStackTrace();
Jeff Hao0abc72e2013-08-13 13:45:14 -0700251 Trace* the_trace = reinterpret_cast<Trace*>(arg);
252 the_trace->CompareAndUpdateStackTrace(thread, stack_trace);
253}
254
Andreas Gampeca714582015-04-03 19:41:34 -0700255static void ClearThreadStackTraceAndClockBase(Thread* thread, void* arg ATTRIBUTE_UNUSED) {
Jeff Hao5ce4b172013-08-16 16:27:18 -0700256 thread->SetTraceClockBase(0);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700257 std::vector<ArtMethod*>* stack_trace = thread->GetStackTraceSample();
Andreas Gampe40da2862015-02-27 12:49:04 -0800258 thread->SetStackTraceSample(nullptr);
Jeff Hao5ce4b172013-08-16 16:27:18 -0700259 delete stack_trace;
260}
261
Jeff Hao0abc72e2013-08-13 13:45:14 -0700262void Trace::CompareAndUpdateStackTrace(Thread* thread,
Mathieu Chartiere401d142015-04-22 13:56:20 -0700263 std::vector<ArtMethod*>* stack_trace) {
Jeff Hao0abc72e2013-08-13 13:45:14 -0700264 CHECK_EQ(pthread_self(), sampling_pthread_);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700265 std::vector<ArtMethod*>* old_stack_trace = thread->GetStackTraceSample();
Jeff Hao5ce4b172013-08-16 16:27:18 -0700266 // Update the thread's stack trace sample.
267 thread->SetStackTraceSample(stack_trace);
Jeff Haoc1ff4b72013-08-19 11:33:10 -0700268 // Read timer clocks to use for all events in this trace.
269 uint32_t thread_clock_diff = 0;
270 uint32_t wall_clock_diff = 0;
271 ReadClocks(thread, &thread_clock_diff, &wall_clock_diff);
Andreas Gampe40da2862015-02-27 12:49:04 -0800272 if (old_stack_trace == nullptr) {
Jeff Hao5ce4b172013-08-16 16:27:18 -0700273 // If there's no previous stack trace sample for this thread, log an entry event for all
Jeff Hao0abc72e2013-08-13 13:45:14 -0700274 // methods in the trace.
Mathieu Chartiere401d142015-04-22 13:56:20 -0700275 for (std::vector<ArtMethod*>::reverse_iterator rit = stack_trace->rbegin();
Jeff Hao0abc72e2013-08-13 13:45:14 -0700276 rit != stack_trace->rend(); ++rit) {
Jeff Haoc1ff4b72013-08-19 11:33:10 -0700277 LogMethodTraceEvent(thread, *rit, instrumentation::Instrumentation::kMethodEntered,
278 thread_clock_diff, wall_clock_diff);
Jeff Hao0abc72e2013-08-13 13:45:14 -0700279 }
280 } else {
281 // If there's a previous stack trace for this thread, diff the traces and emit entry and exit
282 // events accordingly.
Mathieu Chartiere401d142015-04-22 13:56:20 -0700283 std::vector<ArtMethod*>::reverse_iterator old_rit = old_stack_trace->rbegin();
284 std::vector<ArtMethod*>::reverse_iterator rit = stack_trace->rbegin();
Jeff Hao0abc72e2013-08-13 13:45:14 -0700285 // Iterate bottom-up over both traces until there's a difference between them.
286 while (old_rit != old_stack_trace->rend() && rit != stack_trace->rend() && *old_rit == *rit) {
287 old_rit++;
288 rit++;
289 }
290 // Iterate top-down over the old trace until the point where they differ, emitting exit events.
Mathieu Chartiere401d142015-04-22 13:56:20 -0700291 for (std::vector<ArtMethod*>::iterator old_it = old_stack_trace->begin();
Jeff Hao0abc72e2013-08-13 13:45:14 -0700292 old_it != old_rit.base(); ++old_it) {
Jeff Haoc1ff4b72013-08-19 11:33:10 -0700293 LogMethodTraceEvent(thread, *old_it, instrumentation::Instrumentation::kMethodExited,
294 thread_clock_diff, wall_clock_diff);
Jeff Hao0abc72e2013-08-13 13:45:14 -0700295 }
296 // Iterate bottom-up over the new trace from the point where they differ, emitting entry events.
297 for (; rit != stack_trace->rend(); ++rit) {
Jeff Haoc1ff4b72013-08-19 11:33:10 -0700298 LogMethodTraceEvent(thread, *rit, instrumentation::Instrumentation::kMethodEntered,
299 thread_clock_diff, wall_clock_diff);
Jeff Hao0abc72e2013-08-13 13:45:14 -0700300 }
Jeff Hao5ce4b172013-08-16 16:27:18 -0700301 FreeStackTrace(old_stack_trace);
Jeff Hao0abc72e2013-08-13 13:45:14 -0700302 }
303}
304
305void* Trace::RunSamplingThread(void* arg) {
306 Runtime* runtime = Runtime::Current();
Ian Rogersef7d42f2014-01-06 12:55:46 -0800307 intptr_t interval_us = reinterpret_cast<intptr_t>(arg);
Jeff Hao4044bda2014-01-06 15:50:45 -0800308 CHECK_GE(interval_us, 0);
Jeff Hao0abc72e2013-08-13 13:45:14 -0700309 CHECK(runtime->AttachCurrentThread("Sampling Profiler", true, runtime->GetSystemThreadGroup(),
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800310 !runtime->IsAotCompiler()));
Jeff Hao0abc72e2013-08-13 13:45:14 -0700311
312 while (true) {
Jeff Hao23009dc2013-08-22 15:36:42 -0700313 usleep(interval_us);
Jeff Hao5ce4b172013-08-16 16:27:18 -0700314 ATRACE_BEGIN("Profile sampling");
Jeff Hao0abc72e2013-08-13 13:45:14 -0700315 Thread* self = Thread::Current();
316 Trace* the_trace;
317 {
318 MutexLock mu(self, *Locks::trace_lock_);
319 the_trace = the_trace_;
Andreas Gampe40da2862015-02-27 12:49:04 -0800320 if (the_trace == nullptr) {
Jeff Hao0abc72e2013-08-13 13:45:14 -0700321 break;
322 }
323 }
324
Mathieu Chartierbf9fc582015-03-13 17:21:25 -0700325 runtime->GetThreadList()->SuspendAll(__FUNCTION__);
Jeff Hao0abc72e2013-08-13 13:45:14 -0700326 {
327 MutexLock mu(self, *Locks::thread_list_lock_);
328 runtime->GetThreadList()->ForEach(GetSample, the_trace);
329 }
330 runtime->GetThreadList()->ResumeAll();
Jeff Hao5ce4b172013-08-16 16:27:18 -0700331 ATRACE_END();
Jeff Hao0abc72e2013-08-13 13:45:14 -0700332 }
333
334 runtime->DetachCurrentThread();
Andreas Gampe40da2862015-02-27 12:49:04 -0800335 return nullptr;
Jeff Hao0abc72e2013-08-13 13:45:14 -0700336}
337
Andreas Gampee34a42c2015-04-25 14:44:29 -0700338void Trace::Start(const char* trace_filename, int trace_fd, size_t buffer_size, int flags,
Andreas Gampe7e7e0f42015-03-29 15:26:23 -0700339 TraceOutputMode output_mode, TraceMode trace_mode, int interval_us) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800340 Thread* self = Thread::Current();
341 {
342 MutexLock mu(self, *Locks::trace_lock_);
Andreas Gampe40da2862015-02-27 12:49:04 -0800343 if (the_trace_ != nullptr) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800344 LOG(ERROR) << "Trace already in progress, ignoring this request";
345 return;
346 }
jeffhaoe343b762011-12-05 16:36:44 -0800347 }
Jeff Haod063d912014-09-08 09:38:18 -0700348
349 // Check interval if sampling is enabled
Andreas Gampe7e7e0f42015-03-29 15:26:23 -0700350 if (trace_mode == TraceMode::kSampling && interval_us <= 0) {
Jeff Haod063d912014-09-08 09:38:18 -0700351 LOG(ERROR) << "Invalid sampling interval: " << interval_us;
352 ScopedObjectAccess soa(self);
353 ThrowRuntimeException("Invalid sampling interval: %d", interval_us);
354 return;
355 }
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800356
jeffhao2692b572011-12-16 15:42:28 -0800357 // Open trace file if not going directly to ddms.
Ian Rogers700a4022014-05-19 16:49:03 -0700358 std::unique_ptr<File> trace_file;
Andreas Gampe7e7e0f42015-03-29 15:26:23 -0700359 if (output_mode != TraceOutputMode::kDDMS) {
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800360 if (trace_fd < 0) {
Brian Carlstrom7571e8b2013-08-12 17:04:14 -0700361 trace_file.reset(OS::CreateEmptyFile(trace_filename));
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800362 } else {
Ian Rogers62d6c772013-02-27 08:32:07 -0800363 trace_file.reset(new File(trace_fd, "tracefile"));
Elliott Hughes76160052012-12-12 16:31:20 -0800364 trace_file->DisableAutoClose();
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800365 }
Andreas Gampe40da2862015-02-27 12:49:04 -0800366 if (trace_file.get() == nullptr) {
jeffhaob5e81852012-03-12 11:15:45 -0700367 PLOG(ERROR) << "Unable to open trace file '" << trace_filename << "'";
Ian Rogers62d6c772013-02-27 08:32:07 -0800368 ScopedObjectAccess soa(self);
369 ThrowRuntimeException("Unable to open trace file '%s'", trace_filename);
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800370 return;
371 }
372 }
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800373
Jeff Haod063d912014-09-08 09:38:18 -0700374 Runtime* runtime = Runtime::Current();
Mathieu Chartier9ef78b52014-09-25 17:03:12 -0700375
376 // Enable count of allocs if specified in the flags.
377 bool enable_stats = false;
378
Mathieu Chartierbf9fc582015-03-13 17:21:25 -0700379 runtime->GetThreadList()->SuspendAll(__FUNCTION__);
Jeff Haod063d912014-09-08 09:38:18 -0700380
jeffhao2692b572011-12-16 15:42:28 -0800381 // Create Trace object.
Ian Rogers62d6c772013-02-27 08:32:07 -0800382 {
383 MutexLock mu(self, *Locks::trace_lock_);
Andreas Gampe40da2862015-02-27 12:49:04 -0800384 if (the_trace_ != nullptr) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800385 LOG(ERROR) << "Trace already in progress, ignoring this request";
386 } else {
Mathieu Chartier9ef78b52014-09-25 17:03:12 -0700387 enable_stats = (flags && kTraceCountAllocs) != 0;
Andreas Gampe40da2862015-02-27 12:49:04 -0800388 the_trace_ = new Trace(trace_file.release(), trace_filename, buffer_size, flags, output_mode,
389 trace_mode);
Andreas Gampe7e7e0f42015-03-29 15:26:23 -0700390 if (trace_mode == TraceMode::kSampling) {
Andreas Gampe40da2862015-02-27 12:49:04 -0800391 CHECK_PTHREAD_CALL(pthread_create, (&sampling_pthread_, nullptr, &RunSamplingThread,
Jeff Hao23009dc2013-08-22 15:36:42 -0700392 reinterpret_cast<void*>(interval_us)),
393 "Sampling profiler thread");
Andreas Gampe40da2862015-02-27 12:49:04 -0800394 the_trace_->interval_us_ = interval_us;
Jeff Hao0abc72e2013-08-13 13:45:14 -0700395 } else {
396 runtime->GetInstrumentation()->AddListener(the_trace_,
397 instrumentation::Instrumentation::kMethodEntered |
398 instrumentation::Instrumentation::kMethodExited |
399 instrumentation::Instrumentation::kMethodUnwind);
Andreas Gampe40da2862015-02-27 12:49:04 -0800400 // TODO: In full-PIC mode, we don't need to fully deopt.
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200401 runtime->GetInstrumentation()->EnableMethodTracing(kTracerInstrumentationKey);
Jeff Hao0abc72e2013-08-13 13:45:14 -0700402 }
Ian Rogers62d6c772013-02-27 08:32:07 -0800403 }
jeffhao0791adc2012-04-04 11:14:32 -0700404 }
Jeff Haod063d912014-09-08 09:38:18 -0700405
Ian Rogers62d6c772013-02-27 08:32:07 -0800406 runtime->GetThreadList()->ResumeAll();
Mathieu Chartier9ef78b52014-09-25 17:03:12 -0700407
408 // Can't call this when holding the mutator lock.
409 if (enable_stats) {
410 runtime->SetStatsEnabled(true);
411 }
jeffhao2692b572011-12-16 15:42:28 -0800412}
413
Andreas Gampe40da2862015-02-27 12:49:04 -0800414void Trace::StopTracing(bool finish_tracing, bool flush_file) {
Mathieu Chartier9ef78b52014-09-25 17:03:12 -0700415 bool stop_alloc_counting = false;
Mathieu Chartier02e5f162015-03-11 09:54:22 -0700416 Runtime* const runtime = Runtime::Current();
417 Trace* the_trace = nullptr;
Jeff Hao0abc72e2013-08-13 13:45:14 -0700418 pthread_t sampling_pthread = 0U;
Ian Rogers62d6c772013-02-27 08:32:07 -0800419 {
420 MutexLock mu(Thread::Current(), *Locks::trace_lock_);
Andreas Gampe40da2862015-02-27 12:49:04 -0800421 if (the_trace_ == nullptr) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800422 LOG(ERROR) << "Trace stop requested, but no trace currently running";
423 } else {
424 the_trace = the_trace_;
Andreas Gampe40da2862015-02-27 12:49:04 -0800425 the_trace_ = nullptr;
Jeff Hao0abc72e2013-08-13 13:45:14 -0700426 sampling_pthread = sampling_pthread_;
Ian Rogers62d6c772013-02-27 08:32:07 -0800427 }
jeffhao2692b572011-12-16 15:42:28 -0800428 }
Mathieu Chartier02e5f162015-03-11 09:54:22 -0700429 // Make sure that we join before we delete the trace since we don't want to have
430 // the sampling thread access a stale pointer. This finishes since the sampling thread exits when
431 // the_trace_ is null.
432 if (sampling_pthread != 0U) {
Andreas Gampe40da2862015-02-27 12:49:04 -0800433 CHECK_PTHREAD_CALL(pthread_join, (sampling_pthread, nullptr), "sampling thread shutdown");
Mathieu Chartier02e5f162015-03-11 09:54:22 -0700434 sampling_pthread_ = 0U;
435 }
Mathieu Chartierbf9fc582015-03-13 17:21:25 -0700436 runtime->GetThreadList()->SuspendAll(__FUNCTION__);
Andreas Gampe40da2862015-02-27 12:49:04 -0800437
Mathieu Chartier02e5f162015-03-11 09:54:22 -0700438 if (the_trace != nullptr) {
Andreas Gampe40da2862015-02-27 12:49:04 -0800439 stop_alloc_counting = (the_trace->flags_ & Trace::kTraceCountAllocs) != 0;
440 if (finish_tracing) {
441 the_trace->FinishTracing();
442 }
Jeff Hao0abc72e2013-08-13 13:45:14 -0700443
Andreas Gampe7e7e0f42015-03-29 15:26:23 -0700444 if (the_trace->trace_mode_ == TraceMode::kSampling) {
Jeff Hao5ce4b172013-08-16 16:27:18 -0700445 MutexLock mu(Thread::Current(), *Locks::thread_list_lock_);
Mathieu Chartier02e5f162015-03-11 09:54:22 -0700446 runtime->GetThreadList()->ForEach(ClearThreadStackTraceAndClockBase, nullptr);
Jeff Hao5ce4b172013-08-16 16:27:18 -0700447 } else {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200448 runtime->GetInstrumentation()->DisableMethodTracing(kTracerInstrumentationKey);
Mathieu Chartier02e5f162015-03-11 09:54:22 -0700449 runtime->GetInstrumentation()->RemoveListener(
450 the_trace, instrumentation::Instrumentation::kMethodEntered |
451 instrumentation::Instrumentation::kMethodExited |
452 instrumentation::Instrumentation::kMethodUnwind);
Jeff Hao0abc72e2013-08-13 13:45:14 -0700453 }
Andreas Gampe4303ba92014-11-06 01:00:46 -0800454 if (the_trace->trace_file_.get() != nullptr) {
455 // Do not try to erase, so flush and close explicitly.
Andreas Gampe40da2862015-02-27 12:49:04 -0800456 if (flush_file) {
457 if (the_trace->trace_file_->Flush() != 0) {
458 PLOG(ERROR) << "Could not flush trace file.";
459 }
460 } else {
461 the_trace->trace_file_->MarkUnchecked(); // Do not trigger guard.
Andreas Gampe4303ba92014-11-06 01:00:46 -0800462 }
463 if (the_trace->trace_file_->Close() != 0) {
464 PLOG(ERROR) << "Could not close trace file.";
465 }
466 }
Ian Rogers62d6c772013-02-27 08:32:07 -0800467 delete the_trace;
468 }
469 runtime->GetThreadList()->ResumeAll();
Mathieu Chartier9ef78b52014-09-25 17:03:12 -0700470 if (stop_alloc_counting) {
471 // Can be racy since SetStatsEnabled is not guarded by any locks.
Mathieu Chartier02e5f162015-03-11 09:54:22 -0700472 runtime->SetStatsEnabled(false);
Jeff Hao0abc72e2013-08-13 13:45:14 -0700473 }
jeffhao2692b572011-12-16 15:42:28 -0800474}
475
Andreas Gampe40da2862015-02-27 12:49:04 -0800476void Trace::Abort() {
477 // Do not write anything anymore.
478 StopTracing(false, false);
479}
480
481void Trace::Stop() {
482 // Finish writing.
483 StopTracing(true, true);
484}
485
jeffhaob5e81852012-03-12 11:15:45 -0700486void Trace::Shutdown() {
Jeff Hao64caa7d2013-08-29 11:18:01 -0700487 if (GetMethodTracingMode() != kTracingInactive) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800488 Stop();
jeffhaob5e81852012-03-12 11:15:45 -0700489 }
jeffhaob5e81852012-03-12 11:15:45 -0700490}
491
Andreas Gampe40da2862015-02-27 12:49:04 -0800492void Trace::Pause() {
493 bool stop_alloc_counting = false;
494 Runtime* runtime = Runtime::Current();
495 Trace* the_trace = nullptr;
496
497 pthread_t sampling_pthread = 0U;
498 {
499 MutexLock mu(Thread::Current(), *Locks::trace_lock_);
500 if (the_trace_ == nullptr) {
501 LOG(ERROR) << "Trace pause requested, but no trace currently running";
502 return;
503 } else {
504 the_trace = the_trace_;
505 sampling_pthread = sampling_pthread_;
506 }
507 }
508
509 if (sampling_pthread != 0U) {
510 {
511 MutexLock mu(Thread::Current(), *Locks::trace_lock_);
512 the_trace_ = nullptr;
513 }
514 CHECK_PTHREAD_CALL(pthread_join, (sampling_pthread, nullptr), "sampling thread shutdown");
515 sampling_pthread_ = 0U;
516 {
517 MutexLock mu(Thread::Current(), *Locks::trace_lock_);
518 the_trace_ = the_trace;
519 }
520 }
521
522 if (the_trace != nullptr) {
523 runtime->GetThreadList()->SuspendAll(__FUNCTION__);
524 stop_alloc_counting = (the_trace->flags_ & Trace::kTraceCountAllocs) != 0;
525
526 if (the_trace->trace_mode_ == TraceMode::kSampling) {
527 MutexLock mu(Thread::Current(), *Locks::thread_list_lock_);
528 runtime->GetThreadList()->ForEach(ClearThreadStackTraceAndClockBase, nullptr);
529 } else {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200530 runtime->GetInstrumentation()->DisableMethodTracing(kTracerInstrumentationKey);
Andreas Gampe40da2862015-02-27 12:49:04 -0800531 runtime->GetInstrumentation()->RemoveListener(the_trace,
532 instrumentation::Instrumentation::kMethodEntered |
533 instrumentation::Instrumentation::kMethodExited |
534 instrumentation::Instrumentation::kMethodUnwind);
535 }
536 runtime->GetThreadList()->ResumeAll();
537 }
538
539 if (stop_alloc_counting) {
540 // Can be racy since SetStatsEnabled is not guarded by any locks.
541 Runtime::Current()->SetStatsEnabled(false);
542 }
543}
544
545void Trace::Resume() {
546 Thread* self = Thread::Current();
547 Trace* the_trace;
548 {
549 MutexLock mu(self, *Locks::trace_lock_);
550 if (the_trace_ == nullptr) {
551 LOG(ERROR) << "No trace to resume (or sampling mode), ignoring this request";
552 return;
553 }
554 the_trace = the_trace_;
555 }
556
557 Runtime* runtime = Runtime::Current();
558
559 // Enable count of allocs if specified in the flags.
560 bool enable_stats = (the_trace->flags_ && kTraceCountAllocs) != 0;
561
562 runtime->GetThreadList()->SuspendAll(__FUNCTION__);
563
564 // Reenable.
565 if (the_trace->trace_mode_ == TraceMode::kSampling) {
566 CHECK_PTHREAD_CALL(pthread_create, (&sampling_pthread_, nullptr, &RunSamplingThread,
567 reinterpret_cast<void*>(the_trace->interval_us_)), "Sampling profiler thread");
568 } else {
569 runtime->GetInstrumentation()->AddListener(the_trace,
570 instrumentation::Instrumentation::kMethodEntered |
571 instrumentation::Instrumentation::kMethodExited |
572 instrumentation::Instrumentation::kMethodUnwind);
573 // TODO: In full-PIC mode, we don't need to fully deopt.
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200574 runtime->GetInstrumentation()->EnableMethodTracing(kTracerInstrumentationKey);
Andreas Gampe40da2862015-02-27 12:49:04 -0800575 }
576
577 runtime->GetThreadList()->ResumeAll();
578
579 // Can't call this when holding the mutator lock.
580 if (enable_stats) {
581 runtime->SetStatsEnabled(true);
582 }
583}
584
Jeff Hao64caa7d2013-08-29 11:18:01 -0700585TracingMode Trace::GetMethodTracingMode() {
Ian Rogers62d6c772013-02-27 08:32:07 -0800586 MutexLock mu(Thread::Current(), *Locks::trace_lock_);
Andreas Gampe40da2862015-02-27 12:49:04 -0800587 if (the_trace_ == nullptr) {
Jeff Hao64caa7d2013-08-29 11:18:01 -0700588 return kTracingInactive;
Jeff Hao64caa7d2013-08-29 11:18:01 -0700589 } else {
Andreas Gampe7e7e0f42015-03-29 15:26:23 -0700590 switch (the_trace_->trace_mode_) {
591 case TraceMode::kSampling:
592 return kSampleProfilingActive;
593 case TraceMode::kMethodTracing:
594 return kMethodTracingActive;
595 }
596 LOG(FATAL) << "Unreachable";
597 UNREACHABLE();
Jeff Hao64caa7d2013-08-29 11:18:01 -0700598 }
Ian Rogers62d6c772013-02-27 08:32:07 -0800599}
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800600
Andreas Gampee34a42c2015-04-25 14:44:29 -0700601static constexpr size_t kMinBufSize = 18U; // Trace header is up to 18B.
Andreas Gampe40da2862015-02-27 12:49:04 -0800602
Andreas Gampee34a42c2015-04-25 14:44:29 -0700603Trace::Trace(File* trace_file, const char* trace_name, size_t buffer_size, int flags,
Andreas Gampe40da2862015-02-27 12:49:04 -0800604 TraceOutputMode output_mode, TraceMode trace_mode)
605 : trace_file_(trace_file),
Andreas Gampee34a42c2015-04-25 14:44:29 -0700606 buf_(new uint8_t[std::max(kMinBufSize, buffer_size)]()),
Andreas Gampe40da2862015-02-27 12:49:04 -0800607 flags_(flags), trace_output_mode_(output_mode), trace_mode_(trace_mode),
608 clock_source_(default_clock_source_),
Andreas Gampee34a42c2015-04-25 14:44:29 -0700609 buffer_size_(std::max(kMinBufSize, buffer_size)),
Andreas Gampe40da2862015-02-27 12:49:04 -0800610 start_time_(MicroTime()), clock_overhead_ns_(GetClockOverheadNanoSeconds()), cur_offset_(0),
611 overflow_(false), interval_us_(0), streaming_lock_(nullptr) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800612 uint16_t trace_version = GetTraceVersion(clock_source_);
Andreas Gampe40da2862015-02-27 12:49:04 -0800613 if (output_mode == TraceOutputMode::kStreaming) {
614 trace_version |= 0xF0U;
615 }
616 // Set up the beginning of the trace.
jeffhao2692b572011-12-16 15:42:28 -0800617 memset(buf_.get(), 0, kTraceHeaderLength);
618 Append4LE(buf_.get(), kTraceMagicValue);
Ian Rogers62d6c772013-02-27 08:32:07 -0800619 Append2LE(buf_.get() + 4, trace_version);
jeffhao2692b572011-12-16 15:42:28 -0800620 Append2LE(buf_.get() + 6, kTraceHeaderLength);
621 Append8LE(buf_.get() + 8, start_time_);
Ian Rogers62d6c772013-02-27 08:32:07 -0800622 if (trace_version >= kTraceVersionDualClock) {
623 uint16_t record_size = GetRecordSize(clock_source_);
624 Append2LE(buf_.get() + 16, record_size);
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800625 }
Andreas Gampee34a42c2015-04-25 14:44:29 -0700626 static_assert(18 <= kMinBufSize, "Minimum buffer size not large enough for trace header");
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800627
jeffhao2692b572011-12-16 15:42:28 -0800628 // Update current offset.
Ian Rogers8ab25ef2014-07-09 18:00:50 -0700629 cur_offset_.StoreRelaxed(kTraceHeaderLength);
Andreas Gampe40da2862015-02-27 12:49:04 -0800630
631 if (output_mode == TraceOutputMode::kStreaming) {
632 streaming_file_name_ = trace_name;
633 streaming_lock_ = new Mutex("tracing lock");
634 seen_threads_.reset(new ThreadIDBitSet());
635 }
636}
637
638Trace::~Trace() {
639 delete streaming_lock_;
Ian Rogers62d6c772013-02-27 08:32:07 -0800640}
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800641
Mathieu Chartiere401d142015-04-22 13:56:20 -0700642static uint64_t ReadBytes(uint8_t* buf, size_t bytes) {
643 uint64_t ret = 0;
644 for (size_t i = 0; i < bytes; ++i) {
645 ret |= static_cast<uint64_t>(buf[i]) << (i * 8);
646 }
647 return ret;
648}
649
Ian Rogerse63db272014-07-15 15:36:11 -0700650static void DumpBuf(uint8_t* buf, size_t buf_size, TraceClockSource clock_source)
Ian Rogers62d6c772013-02-27 08:32:07 -0800651 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
652 uint8_t* ptr = buf + kTraceHeaderLength;
653 uint8_t* end = buf + buf_size;
654
655 while (ptr < end) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700656 uint64_t tmid = ReadBytes(ptr + 2, sizeof(tmid));
657 ArtMethod* method = DecodeTraceMethodId(tmid);
Ian Rogers62d6c772013-02-27 08:32:07 -0800658 TraceAction action = DecodeTraceAction(tmid);
659 LOG(INFO) << PrettyMethod(method) << " " << static_cast<int>(action);
660 ptr += GetRecordSize(clock_source);
661 }
jeffhaoe343b762011-12-05 16:36:44 -0800662}
663
Andreas Gampe40da2862015-02-27 12:49:04 -0800664static void GetVisitedMethodsFromBitSets(
665 const std::map<mirror::DexCache*, DexIndexBitSet*>& seen_methods,
Mathieu Chartiere401d142015-04-22 13:56:20 -0700666 std::set<ArtMethod*>* visited_methods) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Andreas Gampe40da2862015-02-27 12:49:04 -0800667 for (auto& e : seen_methods) {
668 DexIndexBitSet* bit_set = e.second;
669 for (uint32_t i = 0; i < bit_set->size(); ++i) {
670 if ((*bit_set)[i]) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700671 visited_methods->insert(e.first->GetResolvedMethod(i, sizeof(void*)));
Andreas Gampe40da2862015-02-27 12:49:04 -0800672 }
673 }
674 }
675}
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800676
Andreas Gampe40da2862015-02-27 12:49:04 -0800677void Trace::FinishTracing() {
678 size_t final_offset = 0;
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800679
Mathieu Chartiere401d142015-04-22 13:56:20 -0700680 std::set<ArtMethod*> visited_methods;
Andreas Gampe40da2862015-02-27 12:49:04 -0800681 if (trace_output_mode_ == TraceOutputMode::kStreaming) {
682 // Write the secondary file with all the method names.
683 GetVisitedMethodsFromBitSets(seen_methods_, &visited_methods);
684
685 // Clean up.
686 for (auto& e : seen_methods_) {
687 delete e.second;
688 }
689 } else {
690 final_offset = cur_offset_.LoadRelaxed();
691 GetVisitedMethods(final_offset, &visited_methods);
692 }
693
694 // Compute elapsed time.
695 uint64_t elapsed = MicroTime() - start_time_;
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800696
697 std::ostringstream os;
698
699 os << StringPrintf("%cversion\n", kTraceTokenChar);
Ian Rogers62d6c772013-02-27 08:32:07 -0800700 os << StringPrintf("%d\n", GetTraceVersion(clock_source_));
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800701 os << StringPrintf("data-file-overflow=%s\n", overflow_ ? "true" : "false");
702 if (UseThreadCpuClock()) {
703 if (UseWallClock()) {
704 os << StringPrintf("clock=dual\n");
705 } else {
706 os << StringPrintf("clock=thread-cpu\n");
707 }
708 } else {
709 os << StringPrintf("clock=wall\n");
710 }
Ian Rogersef7d42f2014-01-06 12:55:46 -0800711 os << StringPrintf("elapsed-time-usec=%" PRIu64 "\n", elapsed);
Andreas Gampe40da2862015-02-27 12:49:04 -0800712 if (trace_output_mode_ != TraceOutputMode::kStreaming) {
713 size_t num_records = (final_offset - kTraceHeaderLength) / GetRecordSize(clock_source_);
714 os << StringPrintf("num-method-calls=%zd\n", num_records);
715 }
Jeff Haoc5d824a2014-07-28 18:35:38 -0700716 os << StringPrintf("clock-call-overhead-nsec=%d\n", clock_overhead_ns_);
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800717 os << StringPrintf("vm=art\n");
John Reck0624a272015-03-26 15:47:54 -0700718 os << StringPrintf("pid=%d\n", getpid());
jeffhao0791adc2012-04-04 11:14:32 -0700719 if ((flags_ & kTraceCountAllocs) != 0) {
720 os << StringPrintf("alloc-count=%d\n", Runtime::Current()->GetStat(KIND_ALLOCATED_OBJECTS));
721 os << StringPrintf("alloc-size=%d\n", Runtime::Current()->GetStat(KIND_ALLOCATED_BYTES));
722 os << StringPrintf("gc-count=%d\n", Runtime::Current()->GetStat(KIND_GC_INVOCATIONS));
723 }
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800724 os << StringPrintf("%cthreads\n", kTraceTokenChar);
725 DumpThreadList(os);
726 os << StringPrintf("%cmethods\n", kTraceTokenChar);
Ian Rogers62d6c772013-02-27 08:32:07 -0800727 DumpMethodList(os, visited_methods);
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800728 os << StringPrintf("%cend\n", kTraceTokenChar);
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800729 std::string header(os.str());
Andreas Gampe40da2862015-02-27 12:49:04 -0800730
731 if (trace_output_mode_ == TraceOutputMode::kStreaming) {
732 File file;
733 if (!file.Open(streaming_file_name_ + ".sec", O_CREAT | O_WRONLY)) {
734 LOG(WARNING) << "Could not open secondary trace file!";
735 return;
Ian Rogers62d6c772013-02-27 08:32:07 -0800736 }
Andreas Gampe40da2862015-02-27 12:49:04 -0800737 if (!file.WriteFully(header.c_str(), header.length())) {
738 file.Erase();
Elliott Hughes7b9d9962012-04-20 18:48:18 -0700739 std::string detail(StringPrintf("Trace data write failed: %s", strerror(errno)));
740 PLOG(ERROR) << detail;
Ian Rogers62d6c772013-02-27 08:32:07 -0800741 ThrowRuntimeException("%s", detail.c_str());
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800742 }
Andreas Gampe40da2862015-02-27 12:49:04 -0800743 if (file.FlushCloseOrErase() != 0) {
744 PLOG(ERROR) << "Could not write secondary file";
745 }
746 } else {
747 if (trace_file_.get() == nullptr) {
748 iovec iov[2];
749 iov[0].iov_base = reinterpret_cast<void*>(const_cast<char*>(header.c_str()));
750 iov[0].iov_len = header.length();
751 iov[1].iov_base = buf_.get();
752 iov[1].iov_len = final_offset;
753 Dbg::DdmSendChunkV(CHUNK_TYPE("MPSE"), iov, 2);
754 const bool kDumpTraceInfo = false;
755 if (kDumpTraceInfo) {
756 LOG(INFO) << "Trace sent:\n" << header;
757 DumpBuf(buf_.get(), final_offset, clock_source_);
758 }
759 } else {
760 if (!trace_file_->WriteFully(header.c_str(), header.length()) ||
761 !trace_file_->WriteFully(buf_.get(), final_offset)) {
762 std::string detail(StringPrintf("Trace data write failed: %s", strerror(errno)));
763 PLOG(ERROR) << detail;
764 ThrowRuntimeException("%s", detail.c_str());
765 }
766 }
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800767 }
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800768}
769
Ian Rogers62d6c772013-02-27 08:32:07 -0800770void Trace::DexPcMoved(Thread* thread, mirror::Object* this_object,
Mathieu Chartiere401d142015-04-22 13:56:20 -0700771 ArtMethod* method, uint32_t new_dex_pc) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700772 UNUSED(thread, this_object, method, new_dex_pc);
Ian Rogers62d6c772013-02-27 08:32:07 -0800773 // We're not recorded to listen to this kind of event, so complain.
774 LOG(ERROR) << "Unexpected dex PC event in tracing " << PrettyMethod(method) << " " << new_dex_pc;
Andreas Gampec8ccf682014-09-29 20:07:43 -0700775}
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800776
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700777void Trace::FieldRead(Thread* thread, mirror::Object* this_object,
Mathieu Chartiere401d142015-04-22 13:56:20 -0700778 ArtMethod* method, uint32_t dex_pc, ArtField* field)
Sebastien Hertz3f52eaf2014-04-04 17:50:18 +0200779 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700780 UNUSED(thread, this_object, method, dex_pc, field);
Sebastien Hertz3f52eaf2014-04-04 17:50:18 +0200781 // We're not recorded to listen to this kind of event, so complain.
782 LOG(ERROR) << "Unexpected field read event in tracing " << PrettyMethod(method) << " " << dex_pc;
783}
784
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700785void Trace::FieldWritten(Thread* thread, mirror::Object* this_object,
Mathieu Chartiere401d142015-04-22 13:56:20 -0700786 ArtMethod* method, uint32_t dex_pc, ArtField* field,
Sebastien Hertz3f52eaf2014-04-04 17:50:18 +0200787 const JValue& field_value)
788 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700789 UNUSED(thread, this_object, method, dex_pc, field, field_value);
Sebastien Hertz3f52eaf2014-04-04 17:50:18 +0200790 // We're not recorded to listen to this kind of event, so complain.
791 LOG(ERROR) << "Unexpected field write event in tracing " << PrettyMethod(method) << " " << dex_pc;
792}
793
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700794void Trace::MethodEntered(Thread* thread, mirror::Object* this_object ATTRIBUTE_UNUSED,
Mathieu Chartiere401d142015-04-22 13:56:20 -0700795 ArtMethod* method, uint32_t dex_pc ATTRIBUTE_UNUSED) {
Jeff Haoc1ff4b72013-08-19 11:33:10 -0700796 uint32_t thread_clock_diff = 0;
797 uint32_t wall_clock_diff = 0;
798 ReadClocks(thread, &thread_clock_diff, &wall_clock_diff);
799 LogMethodTraceEvent(thread, method, instrumentation::Instrumentation::kMethodEntered,
800 thread_clock_diff, wall_clock_diff);
Ian Rogers62d6c772013-02-27 08:32:07 -0800801}
802
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700803void Trace::MethodExited(Thread* thread, mirror::Object* this_object ATTRIBUTE_UNUSED,
Mathieu Chartiere401d142015-04-22 13:56:20 -0700804 ArtMethod* method, uint32_t dex_pc ATTRIBUTE_UNUSED,
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700805 const JValue& return_value ATTRIBUTE_UNUSED) {
Jeff Haoc1ff4b72013-08-19 11:33:10 -0700806 uint32_t thread_clock_diff = 0;
807 uint32_t wall_clock_diff = 0;
808 ReadClocks(thread, &thread_clock_diff, &wall_clock_diff);
809 LogMethodTraceEvent(thread, method, instrumentation::Instrumentation::kMethodExited,
810 thread_clock_diff, wall_clock_diff);
Ian Rogers62d6c772013-02-27 08:32:07 -0800811}
812
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700813void Trace::MethodUnwind(Thread* thread, mirror::Object* this_object ATTRIBUTE_UNUSED,
Mathieu Chartiere401d142015-04-22 13:56:20 -0700814 ArtMethod* method, uint32_t dex_pc ATTRIBUTE_UNUSED) {
Jeff Haoc1ff4b72013-08-19 11:33:10 -0700815 uint32_t thread_clock_diff = 0;
816 uint32_t wall_clock_diff = 0;
817 ReadClocks(thread, &thread_clock_diff, &wall_clock_diff);
818 LogMethodTraceEvent(thread, method, instrumentation::Instrumentation::kMethodUnwind,
819 thread_clock_diff, wall_clock_diff);
Ian Rogers62d6c772013-02-27 08:32:07 -0800820}
821
Nicolas Geoffray14691c52015-03-05 10:40:17 +0000822void Trace::ExceptionCaught(Thread* thread, mirror::Throwable* exception_object)
Ian Rogers62d6c772013-02-27 08:32:07 -0800823 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Nicolas Geoffray14691c52015-03-05 10:40:17 +0000824 UNUSED(thread, exception_object);
Ian Rogers62d6c772013-02-27 08:32:07 -0800825 LOG(ERROR) << "Unexpected exception caught event in tracing";
826}
827
Mathieu Chartiere401d142015-04-22 13:56:20 -0700828void Trace::BackwardBranch(Thread* /*thread*/, ArtMethod* method,
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800829 int32_t /*dex_pc_offset*/)
830 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
831 LOG(ERROR) << "Unexpected backward branch event in tracing" << PrettyMethod(method);
832}
833
Jeff Haoc1ff4b72013-08-19 11:33:10 -0700834void Trace::ReadClocks(Thread* thread, uint32_t* thread_clock_diff, uint32_t* wall_clock_diff) {
835 if (UseThreadCpuClock()) {
836 uint64_t clock_base = thread->GetTraceClockBase();
837 if (UNLIKELY(clock_base == 0)) {
838 // First event, record the base time in the map.
839 uint64_t time = thread->GetCpuMicroTime();
840 thread->SetTraceClockBase(time);
841 } else {
842 *thread_clock_diff = thread->GetCpuMicroTime() - clock_base;
843 }
844 }
845 if (UseWallClock()) {
846 *wall_clock_diff = MicroTime() - start_time_;
847 }
848}
849
Mathieu Chartiere401d142015-04-22 13:56:20 -0700850bool Trace::RegisterMethod(ArtMethod* method) {
Andreas Gampe40da2862015-02-27 12:49:04 -0800851 mirror::DexCache* dex_cache = method->GetDexCache();
Mathieu Chartiere401d142015-04-22 13:56:20 -0700852 auto* resolved_method = dex_cache->GetResolvedMethod(method->GetDexMethodIndex(), sizeof(void*));
853 if (resolved_method != method) {
854 DCHECK(resolved_method == nullptr);
855 dex_cache->SetResolvedMethod(method->GetDexMethodIndex(), method, sizeof(void*));
Andreas Gampe40da2862015-02-27 12:49:04 -0800856 }
857 if (seen_methods_.find(dex_cache) == seen_methods_.end()) {
858 seen_methods_.insert(std::make_pair(dex_cache, new DexIndexBitSet()));
859 }
860 DexIndexBitSet* bit_set = seen_methods_.find(dex_cache)->second;
861 if (!(*bit_set)[method->GetDexMethodIndex()]) {
862 bit_set->set(method->GetDexMethodIndex());
863 return true;
864 }
865 return false;
866}
867
868bool Trace::RegisterThread(Thread* thread) {
869 pid_t tid = thread->GetTid();
870 CHECK_LT(0U, static_cast<uint32_t>(tid));
871 CHECK_LT(static_cast<uint32_t>(tid), 65536U);
872
873 if (!(*seen_threads_)[tid]) {
874 seen_threads_->set(tid);
875 return true;
876 }
877 return false;
878}
879
Mathieu Chartiere401d142015-04-22 13:56:20 -0700880static std::string GetMethodLine(ArtMethod* method)
Andreas Gampe40da2862015-02-27 12:49:04 -0800881 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Mathieu Chartiere3b034a2015-05-31 14:29:23 -0700882 method = method->GetInterfaceMethodIfProxy(sizeof(void*));
Andreas Gampe40da2862015-02-27 12:49:04 -0800883 return StringPrintf("%p\t%s\t%s\t%s\t%s\n", method,
884 PrettyDescriptor(method->GetDeclaringClassDescriptor()).c_str(), method->GetName(),
885 method->GetSignature().ToString().c_str(), method->GetDeclaringClassSourceFile());
886}
887
888void Trace::WriteToBuf(const uint8_t* src, size_t src_size) {
889 int32_t old_offset = cur_offset_.LoadRelaxed();
890 int32_t new_offset = old_offset + static_cast<int32_t>(src_size);
Andreas Gampee34a42c2015-04-25 14:44:29 -0700891 if (dchecked_integral_cast<size_t>(new_offset) > buffer_size_) {
Andreas Gampe40da2862015-02-27 12:49:04 -0800892 // Flush buffer.
893 if (!trace_file_->WriteFully(buf_.get(), old_offset)) {
894 PLOG(WARNING) << "Failed streaming a tracing event.";
895 }
Andreas Gampee34a42c2015-04-25 14:44:29 -0700896
897 // Check whether the data is too large for the buffer, then write immediately.
898 if (src_size >= buffer_size_) {
899 if (!trace_file_->WriteFully(src, src_size)) {
900 PLOG(WARNING) << "Failed streaming a tracing event.";
901 }
902 cur_offset_.StoreRelease(0); // Buffer is empty now.
903 return;
904 }
905
Andreas Gampe40da2862015-02-27 12:49:04 -0800906 old_offset = 0;
907 new_offset = static_cast<int32_t>(src_size);
908 }
909 cur_offset_.StoreRelease(new_offset);
910 // Fill in data.
911 memcpy(buf_.get() + old_offset, src, src_size);
912}
913
Mathieu Chartiere401d142015-04-22 13:56:20 -0700914void Trace::LogMethodTraceEvent(Thread* thread, ArtMethod* method,
Jeff Haoc1ff4b72013-08-19 11:33:10 -0700915 instrumentation::Instrumentation::InstrumentationEvent event,
916 uint32_t thread_clock_diff, uint32_t wall_clock_diff) {
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800917 // Advance cur_offset_ atomically.
918 int32_t new_offset;
Andreas Gampe40da2862015-02-27 12:49:04 -0800919 int32_t old_offset = 0;
920
921 // We do a busy loop here trying to acquire the next offset.
922 if (trace_output_mode_ != TraceOutputMode::kStreaming) {
923 do {
924 old_offset = cur_offset_.LoadRelaxed();
925 new_offset = old_offset + GetRecordSize(clock_source_);
Andreas Gampee34a42c2015-04-25 14:44:29 -0700926 if (static_cast<size_t>(new_offset) > buffer_size_) {
Andreas Gampe40da2862015-02-27 12:49:04 -0800927 overflow_ = true;
928 return;
929 }
930 } while (!cur_offset_.CompareExchangeWeakSequentiallyConsistent(old_offset, new_offset));
931 }
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800932
Ian Rogers62d6c772013-02-27 08:32:07 -0800933 TraceAction action = kTraceMethodEnter;
934 switch (event) {
935 case instrumentation::Instrumentation::kMethodEntered:
936 action = kTraceMethodEnter;
937 break;
938 case instrumentation::Instrumentation::kMethodExited:
939 action = kTraceMethodExit;
940 break;
941 case instrumentation::Instrumentation::kMethodUnwind:
942 action = kTraceUnroll;
943 break;
944 default:
945 UNIMPLEMENTED(FATAL) << "Unexpected event: " << event;
946 }
947
Mathieu Chartiere401d142015-04-22 13:56:20 -0700948 uint64_t method_value = EncodeTraceMethodAndAction(method, action);
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800949
950 // Write data
Andreas Gampe40da2862015-02-27 12:49:04 -0800951 uint8_t* ptr;
Mathieu Chartiere401d142015-04-22 13:56:20 -0700952 static constexpr size_t kPacketSize = 18U; // The maximum size of data in a packet.
Andreas Gampe40da2862015-02-27 12:49:04 -0800953 uint8_t stack_buf[kPacketSize]; // Space to store a packet when in streaming mode.
954 if (trace_output_mode_ == TraceOutputMode::kStreaming) {
955 ptr = stack_buf;
956 } else {
957 ptr = buf_.get() + old_offset;
958 }
959
Ian Rogers62d6c772013-02-27 08:32:07 -0800960 Append2LE(ptr, thread->GetTid());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700961 Append8LE(ptr + 2, method_value);
962 ptr += 10;
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800963
964 if (UseThreadCpuClock()) {
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800965 Append4LE(ptr, thread_clock_diff);
966 ptr += 4;
967 }
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800968 if (UseWallClock()) {
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800969 Append4LE(ptr, wall_clock_diff);
970 }
Mathieu Chartiere401d142015-04-22 13:56:20 -0700971 static_assert(kPacketSize == 2 + 8 + 4 + 4, "Packet size incorrect.");
Andreas Gampe40da2862015-02-27 12:49:04 -0800972
973 if (trace_output_mode_ == TraceOutputMode::kStreaming) {
974 MutexLock mu(Thread::Current(), *streaming_lock_); // To serialize writing.
975 if (RegisterMethod(method)) {
976 // Write a special block with the name.
977 std::string method_line(GetMethodLine(method));
978 uint8_t buf2[5];
979 Append2LE(buf2, 0);
980 buf2[2] = kOpNewMethod;
981 Append2LE(buf2 + 3, static_cast<uint16_t>(method_line.length()));
982 WriteToBuf(buf2, sizeof(buf2));
983 WriteToBuf(reinterpret_cast<const uint8_t*>(method_line.c_str()), method_line.length());
984 }
985 if (RegisterThread(thread)) {
986 // It might be better to postpone this. Threads might not have received names...
987 std::string thread_name;
988 thread->GetThreadName(thread_name);
989 uint8_t buf2[7];
990 Append2LE(buf2, 0);
991 buf2[2] = kOpNewThread;
992 Append2LE(buf2 + 3, static_cast<uint16_t>(thread->GetTid()));
993 Append2LE(buf2 + 5, static_cast<uint16_t>(thread_name.length()));
994 WriteToBuf(buf2, sizeof(buf2));
995 WriteToBuf(reinterpret_cast<const uint8_t*>(thread_name.c_str()), thread_name.length());
996 }
997 WriteToBuf(stack_buf, sizeof(stack_buf));
998 }
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800999}
1000
Ian Rogers62d6c772013-02-27 08:32:07 -08001001void Trace::GetVisitedMethods(size_t buf_size,
Mathieu Chartiere401d142015-04-22 13:56:20 -07001002 std::set<ArtMethod*>* visited_methods) {
jeffhao2692b572011-12-16 15:42:28 -08001003 uint8_t* ptr = buf_.get() + kTraceHeaderLength;
Ian Rogers62d6c772013-02-27 08:32:07 -08001004 uint8_t* end = buf_.get() + buf_size;
jeffhaoa9ef3fd2011-12-13 18:33:43 -08001005
1006 while (ptr < end) {
Mathieu Chartiere401d142015-04-22 13:56:20 -07001007 uint64_t tmid = ReadBytes(ptr + 2, sizeof(tmid));
1008 ArtMethod* method = DecodeTraceMethodId(tmid);
Ian Rogers62d6c772013-02-27 08:32:07 -08001009 visited_methods->insert(method);
1010 ptr += GetRecordSize(clock_source_);
jeffhaoa9ef3fd2011-12-13 18:33:43 -08001011 }
1012}
1013
Mathieu Chartiere401d142015-04-22 13:56:20 -07001014void Trace::DumpMethodList(std::ostream& os, const std::set<ArtMethod*>& visited_methods) {
Mathieu Chartier02e25112013-08-14 16:14:24 -07001015 for (const auto& method : visited_methods) {
Andreas Gampe40da2862015-02-27 12:49:04 -08001016 os << GetMethodLine(method);
jeffhaoa9ef3fd2011-12-13 18:33:43 -08001017 }
jeffhaoa9ef3fd2011-12-13 18:33:43 -08001018}
1019
1020static void DumpThread(Thread* t, void* arg) {
Elliott Hughesffb465f2012-03-01 18:46:05 -08001021 std::ostream& os = *reinterpret_cast<std::ostream*>(arg);
1022 std::string name;
1023 t->GetThreadName(name);
1024 os << t->GetTid() << "\t" << name << "\n";
jeffhaoa9ef3fd2011-12-13 18:33:43 -08001025}
1026
1027void Trace::DumpThreadList(std::ostream& os) {
Ian Rogers81d425b2012-09-27 16:03:43 -07001028 Thread* self = Thread::Current();
Jeff Haoe094b872014-10-14 13:12:01 -07001029 for (auto it : exited_threads_) {
1030 os << it.first << "\t" << it.second << "\n";
1031 }
Ian Rogers81d425b2012-09-27 16:03:43 -07001032 Locks::thread_list_lock_->AssertNotHeld(self);
1033 MutexLock mu(self, *Locks::thread_list_lock_);
jeffhaoa9ef3fd2011-12-13 18:33:43 -08001034 Runtime::Current()->GetThreadList()->ForEach(DumpThread, &os);
jeffhaoe343b762011-12-05 16:36:44 -08001035}
1036
Jeff Haoe094b872014-10-14 13:12:01 -07001037void Trace::StoreExitingThreadInfo(Thread* thread) {
1038 MutexLock mu(thread, *Locks::trace_lock_);
1039 if (the_trace_ != nullptr) {
1040 std::string name;
1041 thread->GetThreadName(name);
Andreas Gampea1785c52014-11-25 20:40:08 -08001042 // The same thread/tid may be used multiple times. As SafeMap::Put does not allow to override
1043 // a previous mapping, use SafeMap::Overwrite.
1044 the_trace_->exited_threads_.Overwrite(thread->GetTid(), name);
Jeff Haoe094b872014-10-14 13:12:01 -07001045 }
1046}
1047
Andreas Gampe40da2862015-02-27 12:49:04 -08001048Trace::TraceOutputMode Trace::GetOutputMode() {
1049 MutexLock mu(Thread::Current(), *Locks::trace_lock_);
1050 CHECK(the_trace_ != nullptr) << "Trace output mode requested, but no trace currently running";
1051 return the_trace_->trace_output_mode_;
1052}
1053
1054Trace::TraceMode Trace::GetMode() {
1055 MutexLock mu(Thread::Current(), *Locks::trace_lock_);
1056 CHECK(the_trace_ != nullptr) << "Trace mode requested, but no trace currently running";
1057 return the_trace_->trace_mode_;
1058}
1059
Andreas Gampee34a42c2015-04-25 14:44:29 -07001060size_t Trace::GetBufferSize() {
1061 MutexLock mu(Thread::Current(), *Locks::trace_lock_);
1062 CHECK(the_trace_ != nullptr) << "Trace mode requested, but no trace currently running";
1063 return the_trace_->buffer_size_;
1064}
1065
jeffhaoe343b762011-12-05 16:36:44 -08001066} // namespace art