1 /*
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  */
16 
17 #include "trace.h"
18 
19 #include <sys/uio.h>
20 #include <unistd.h>
21 
22 #include "android-base/stringprintf.h"
23 
24 #include "art_method-inl.h"
25 #include "base/casts.h"
26 #include "base/enums.h"
27 #include "base/stl_util.h"
28 #include "base/systrace.h"
29 #include "base/time_utils.h"
30 #include "base/unix_file/fd_file.h"
31 #include "class_linker.h"
32 #include "common_throws.h"
33 #include "debugger.h"
34 #include "dex_file-inl.h"
35 #include "gc/scoped_gc_critical_section.h"
36 #include "instrumentation.h"
37 #include "mirror/class-inl.h"
38 #include "mirror/dex_cache-inl.h"
39 #include "mirror/object_array-inl.h"
40 #include "mirror/object-inl.h"
41 #include "os.h"
42 #include "scoped_thread_state_change-inl.h"
43 #include "ScopedLocalRef.h"
44 #include "thread.h"
45 #include "thread_list.h"
46 #include "utils.h"
47 #include "entrypoints/quick/quick_entrypoints.h"
48 
49 namespace art {
50 
51 using android::base::StringPrintf;
52 
53 static constexpr size_t TraceActionBits = MinimumBitsToStore(
54     static_cast<size_t>(kTraceMethodActionMask));
55 static constexpr uint8_t kOpNewMethod = 1U;
56 static constexpr uint8_t kOpNewThread = 2U;
57 static constexpr uint8_t kOpTraceSummary = 3U;
58 
59 class BuildStackTraceVisitor : public StackVisitor {
60  public:
BuildStackTraceVisitor(Thread * thread)61   explicit BuildStackTraceVisitor(Thread* thread)
62       : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
63         method_trace_(Trace::AllocStackTrace()) {}
64 
VisitFrame()65   bool VisitFrame() REQUIRES_SHARED(Locks::mutator_lock_) {
66     ArtMethod* m = GetMethod();
67     // Ignore runtime frames (in particular callee save).
68     if (!m->IsRuntimeMethod()) {
69       method_trace_->push_back(m);
70     }
71     return true;
72   }
73 
74   // Returns a stack trace where the topmost frame corresponds with the first element of the vector.
GetStackTrace() const75   std::vector<ArtMethod*>* GetStackTrace() const {
76     return method_trace_;
77   }
78 
79  private:
80   std::vector<ArtMethod*>* const method_trace_;
81 
82   DISALLOW_COPY_AND_ASSIGN(BuildStackTraceVisitor);
83 };
84 
85 static const char     kTraceTokenChar             = '*';
86 static const uint16_t kTraceHeaderLength          = 32;
87 static const uint32_t kTraceMagicValue            = 0x574f4c53;
88 static const uint16_t kTraceVersionSingleClock    = 2;
89 static const uint16_t kTraceVersionDualClock      = 3;
90 static const uint16_t kTraceRecordSizeSingleClock = 10;  // using v2
91 static const uint16_t kTraceRecordSizeDualClock   = 14;  // using v3 with two timestamps
92 
93 TraceClockSource Trace::default_clock_source_ = kDefaultTraceClockSource;
94 
95 Trace* volatile Trace::the_trace_ = nullptr;
96 pthread_t Trace::sampling_pthread_ = 0U;
97 std::unique_ptr<std::vector<ArtMethod*>> Trace::temp_stack_trace_;
98 
99 // The key identifying the tracer to update instrumentation.
100 static constexpr const char* kTracerInstrumentationKey = "Tracer";
101 
DecodeTraceAction(uint32_t tmid)102 static TraceAction DecodeTraceAction(uint32_t tmid) {
103   return static_cast<TraceAction>(tmid & kTraceMethodActionMask);
104 }
105 
DecodeTraceMethod(uint32_t tmid)106 ArtMethod* Trace::DecodeTraceMethod(uint32_t tmid) {
107   MutexLock mu(Thread::Current(), *unique_methods_lock_);
108   return unique_methods_[tmid >> TraceActionBits];
109 }
110 
EncodeTraceMethod(ArtMethod * method)111 uint32_t Trace::EncodeTraceMethod(ArtMethod* method) {
112   MutexLock mu(Thread::Current(), *unique_methods_lock_);
113   uint32_t idx;
114   auto it = art_method_id_map_.find(method);
115   if (it != art_method_id_map_.end()) {
116     idx = it->second;
117   } else {
118     unique_methods_.push_back(method);
119     idx = unique_methods_.size() - 1;
120     art_method_id_map_.emplace(method, idx);
121   }
122   DCHECK_LT(idx, unique_methods_.size());
123   DCHECK_EQ(unique_methods_[idx], method);
124   return idx;
125 }
126 
EncodeTraceMethodAndAction(ArtMethod * method,TraceAction action)127 uint32_t Trace::EncodeTraceMethodAndAction(ArtMethod* method, TraceAction action) {
128   uint32_t tmid = (EncodeTraceMethod(method) << TraceActionBits) | action;
129   DCHECK_EQ(method, DecodeTraceMethod(tmid));
130   return tmid;
131 }
132 
AllocStackTrace()133 std::vector<ArtMethod*>* Trace::AllocStackTrace() {
134   return (temp_stack_trace_.get() != nullptr)  ? temp_stack_trace_.release() :
135       new std::vector<ArtMethod*>();
136 }
137 
FreeStackTrace(std::vector<ArtMethod * > * stack_trace)138 void Trace::FreeStackTrace(std::vector<ArtMethod*>* stack_trace) {
139   stack_trace->clear();
140   temp_stack_trace_.reset(stack_trace);
141 }
142 
SetDefaultClockSource(TraceClockSource clock_source)143 void Trace::SetDefaultClockSource(TraceClockSource clock_source) {
144 #if defined(__linux__)
145   default_clock_source_ = clock_source;
146 #else
147   if (clock_source != TraceClockSource::kWall) {
148     LOG(WARNING) << "Ignoring tracing request to use CPU time.";
149   }
150 #endif
151 }
152 
GetTraceVersion(TraceClockSource clock_source)153 static uint16_t GetTraceVersion(TraceClockSource clock_source) {
154   return (clock_source == TraceClockSource::kDual) ? kTraceVersionDualClock
155                                                     : kTraceVersionSingleClock;
156 }
157 
GetRecordSize(TraceClockSource clock_source)158 static uint16_t GetRecordSize(TraceClockSource clock_source) {
159   return (clock_source == TraceClockSource::kDual) ? kTraceRecordSizeDualClock
160                                                     : kTraceRecordSizeSingleClock;
161 }
162 
UseThreadCpuClock()163 bool Trace::UseThreadCpuClock() {
164   return (clock_source_ == TraceClockSource::kThreadCpu) ||
165       (clock_source_ == TraceClockSource::kDual);
166 }
167 
UseWallClock()168 bool Trace::UseWallClock() {
169   return (clock_source_ == TraceClockSource::kWall) ||
170       (clock_source_ == TraceClockSource::kDual);
171 }
172 
MeasureClockOverhead()173 void Trace::MeasureClockOverhead() {
174   if (UseThreadCpuClock()) {
175     Thread::Current()->GetCpuMicroTime();
176   }
177   if (UseWallClock()) {
178     MicroTime();
179   }
180 }
181 
182 // Compute an average time taken to measure clocks.
GetClockOverheadNanoSeconds()183 uint32_t Trace::GetClockOverheadNanoSeconds() {
184   Thread* self = Thread::Current();
185   uint64_t start = self->GetCpuMicroTime();
186 
187   for (int i = 4000; i > 0; i--) {
188     MeasureClockOverhead();
189     MeasureClockOverhead();
190     MeasureClockOverhead();
191     MeasureClockOverhead();
192     MeasureClockOverhead();
193     MeasureClockOverhead();
194     MeasureClockOverhead();
195     MeasureClockOverhead();
196   }
197 
198   uint64_t elapsed_us = self->GetCpuMicroTime() - start;
199   return static_cast<uint32_t>(elapsed_us / 32);
200 }
201 
202 // TODO: put this somewhere with the big-endian equivalent used by JDWP.
Append2LE(uint8_t * buf,uint16_t val)203 static void Append2LE(uint8_t* buf, uint16_t val) {
204   *buf++ = static_cast<uint8_t>(val);
205   *buf++ = static_cast<uint8_t>(val >> 8);
206 }
207 
208 // TODO: put this somewhere with the big-endian equivalent used by JDWP.
Append4LE(uint8_t * buf,uint32_t val)209 static void Append4LE(uint8_t* buf, uint32_t val) {
210   *buf++ = static_cast<uint8_t>(val);
211   *buf++ = static_cast<uint8_t>(val >> 8);
212   *buf++ = static_cast<uint8_t>(val >> 16);
213   *buf++ = static_cast<uint8_t>(val >> 24);
214 }
215 
216 // TODO: put this somewhere with the big-endian equivalent used by JDWP.
Append8LE(uint8_t * buf,uint64_t val)217 static void Append8LE(uint8_t* buf, uint64_t val) {
218   *buf++ = static_cast<uint8_t>(val);
219   *buf++ = static_cast<uint8_t>(val >> 8);
220   *buf++ = static_cast<uint8_t>(val >> 16);
221   *buf++ = static_cast<uint8_t>(val >> 24);
222   *buf++ = static_cast<uint8_t>(val >> 32);
223   *buf++ = static_cast<uint8_t>(val >> 40);
224   *buf++ = static_cast<uint8_t>(val >> 48);
225   *buf++ = static_cast<uint8_t>(val >> 56);
226 }
227 
GetSample(Thread * thread,void * arg)228 static void GetSample(Thread* thread, void* arg) REQUIRES_SHARED(Locks::mutator_lock_) {
229   BuildStackTraceVisitor build_trace_visitor(thread);
230   build_trace_visitor.WalkStack();
231   std::vector<ArtMethod*>* stack_trace = build_trace_visitor.GetStackTrace();
232   Trace* the_trace = reinterpret_cast<Trace*>(arg);
233   the_trace->CompareAndUpdateStackTrace(thread, stack_trace);
234 }
235 
ClearThreadStackTraceAndClockBase(Thread * thread,void * arg ATTRIBUTE_UNUSED)236 static void ClearThreadStackTraceAndClockBase(Thread* thread, void* arg ATTRIBUTE_UNUSED) {
237   thread->SetTraceClockBase(0);
238   std::vector<ArtMethod*>* stack_trace = thread->GetStackTraceSample();
239   thread->SetStackTraceSample(nullptr);
240   delete stack_trace;
241 }
242 
CompareAndUpdateStackTrace(Thread * thread,std::vector<ArtMethod * > * stack_trace)243 void Trace::CompareAndUpdateStackTrace(Thread* thread,
244                                        std::vector<ArtMethod*>* stack_trace) {
245   CHECK_EQ(pthread_self(), sampling_pthread_);
246   std::vector<ArtMethod*>* old_stack_trace = thread->GetStackTraceSample();
247   // Update the thread's stack trace sample.
248   thread->SetStackTraceSample(stack_trace);
249   // Read timer clocks to use for all events in this trace.
250   uint32_t thread_clock_diff = 0;
251   uint32_t wall_clock_diff = 0;
252   ReadClocks(thread, &thread_clock_diff, &wall_clock_diff);
253   if (old_stack_trace == nullptr) {
254     // If there's no previous stack trace sample for this thread, log an entry event for all
255     // methods in the trace.
256     for (auto rit = stack_trace->rbegin(); rit != stack_trace->rend(); ++rit) {
257       LogMethodTraceEvent(thread, *rit, instrumentation::Instrumentation::kMethodEntered,
258                           thread_clock_diff, wall_clock_diff);
259     }
260   } else {
261     // If there's a previous stack trace for this thread, diff the traces and emit entry and exit
262     // events accordingly.
263     auto old_rit = old_stack_trace->rbegin();
264     auto rit = stack_trace->rbegin();
265     // Iterate bottom-up over both traces until there's a difference between them.
266     while (old_rit != old_stack_trace->rend() && rit != stack_trace->rend() && *old_rit == *rit) {
267       old_rit++;
268       rit++;
269     }
270     // Iterate top-down over the old trace until the point where they differ, emitting exit events.
271     for (auto old_it = old_stack_trace->begin(); old_it != old_rit.base(); ++old_it) {
272       LogMethodTraceEvent(thread, *old_it, instrumentation::Instrumentation::kMethodExited,
273                           thread_clock_diff, wall_clock_diff);
274     }
275     // Iterate bottom-up over the new trace from the point where they differ, emitting entry events.
276     for (; rit != stack_trace->rend(); ++rit) {
277       LogMethodTraceEvent(thread, *rit, instrumentation::Instrumentation::kMethodEntered,
278                           thread_clock_diff, wall_clock_diff);
279     }
280     FreeStackTrace(old_stack_trace);
281   }
282 }
283 
RunSamplingThread(void * arg)284 void* Trace::RunSamplingThread(void* arg) {
285   Runtime* runtime = Runtime::Current();
286   intptr_t interval_us = reinterpret_cast<intptr_t>(arg);
287   CHECK_GE(interval_us, 0);
288   CHECK(runtime->AttachCurrentThread("Sampling Profiler", true, runtime->GetSystemThreadGroup(),
289                                      !runtime->IsAotCompiler()));
290 
291   while (true) {
292     usleep(interval_us);
293     ScopedTrace trace("Profile sampling");
294     Thread* self = Thread::Current();
295     Trace* the_trace;
296     {
297       MutexLock mu(self, *Locks::trace_lock_);
298       the_trace = the_trace_;
299       if (the_trace == nullptr) {
300         break;
301       }
302     }
303     {
304       ScopedSuspendAll ssa(__FUNCTION__);
305       MutexLock mu(self, *Locks::thread_list_lock_);
306       runtime->GetThreadList()->ForEach(GetSample, the_trace);
307     }
308   }
309 
310   runtime->DetachCurrentThread();
311   return nullptr;
312 }
313 
Start(const char * trace_filename,int trace_fd,size_t buffer_size,int flags,TraceOutputMode output_mode,TraceMode trace_mode,int interval_us)314 void Trace::Start(const char* trace_filename, int trace_fd, size_t buffer_size, int flags,
315                   TraceOutputMode output_mode, TraceMode trace_mode, int interval_us) {
316   Thread* self = Thread::Current();
317   {
318     MutexLock mu(self, *Locks::trace_lock_);
319     if (the_trace_ != nullptr) {
320       LOG(ERROR) << "Trace already in progress, ignoring this request";
321       return;
322     }
323   }
324 
325   // Check interval if sampling is enabled
326   if (trace_mode == TraceMode::kSampling && interval_us <= 0) {
327     LOG(ERROR) << "Invalid sampling interval: " << interval_us;
328     ScopedObjectAccess soa(self);
329     ThrowRuntimeException("Invalid sampling interval: %d", interval_us);
330     return;
331   }
332 
333   // Open trace file if not going directly to ddms.
334   std::unique_ptr<File> trace_file;
335   if (output_mode != TraceOutputMode::kDDMS) {
336     if (trace_fd < 0) {
337       trace_file.reset(OS::CreateEmptyFileWriteOnly(trace_filename));
338     } else {
339       trace_file.reset(new File(trace_fd, "tracefile"));
340       trace_file->DisableAutoClose();
341     }
342     if (trace_file.get() == nullptr) {
343       PLOG(ERROR) << "Unable to open trace file '" << trace_filename << "'";
344       ScopedObjectAccess soa(self);
345       ThrowRuntimeException("Unable to open trace file '%s'", trace_filename);
346       return;
347     }
348   }
349 
350   Runtime* runtime = Runtime::Current();
351 
352   // Enable count of allocs if specified in the flags.
353   bool enable_stats = false;
354 
355   // Create Trace object.
356   {
357     // Required since EnableMethodTracing calls ConfigureStubs which visits class linker classes.
358     gc::ScopedGCCriticalSection gcs(self,
359                                     gc::kGcCauseInstrumentation,
360                                     gc::kCollectorTypeInstrumentation);
361     ScopedSuspendAll ssa(__FUNCTION__);
362     MutexLock mu(self, *Locks::trace_lock_);
363     if (the_trace_ != nullptr) {
364       LOG(ERROR) << "Trace already in progress, ignoring this request";
365     } else {
366       enable_stats = (flags && kTraceCountAllocs) != 0;
367       the_trace_ = new Trace(trace_file.release(), trace_filename, buffer_size, flags, output_mode,
368                              trace_mode);
369       if (trace_mode == TraceMode::kSampling) {
370         CHECK_PTHREAD_CALL(pthread_create, (&sampling_pthread_, nullptr, &RunSamplingThread,
371                                             reinterpret_cast<void*>(interval_us)),
372                                             "Sampling profiler thread");
373         the_trace_->interval_us_ = interval_us;
374       } else {
375         runtime->GetInstrumentation()->AddListener(the_trace_,
376                                                    instrumentation::Instrumentation::kMethodEntered |
377                                                    instrumentation::Instrumentation::kMethodExited |
378                                                    instrumentation::Instrumentation::kMethodUnwind);
379         // TODO: In full-PIC mode, we don't need to fully deopt.
380         runtime->GetInstrumentation()->EnableMethodTracing(kTracerInstrumentationKey);
381       }
382     }
383   }
384 
385   // Can't call this when holding the mutator lock.
386   if (enable_stats) {
387     runtime->SetStatsEnabled(true);
388   }
389 }
390 
StopTracing(bool finish_tracing,bool flush_file)391 void Trace::StopTracing(bool finish_tracing, bool flush_file) {
392   bool stop_alloc_counting = false;
393   Runtime* const runtime = Runtime::Current();
394   Trace* the_trace = nullptr;
395   Thread* const self = Thread::Current();
396   pthread_t sampling_pthread = 0U;
397   {
398     MutexLock mu(self, *Locks::trace_lock_);
399     if (the_trace_ == nullptr) {
400       LOG(ERROR) << "Trace stop requested, but no trace currently running";
401     } else {
402       the_trace = the_trace_;
403       the_trace_ = nullptr;
404       sampling_pthread = sampling_pthread_;
405     }
406   }
407   // Make sure that we join before we delete the trace since we don't want to have
408   // the sampling thread access a stale pointer. This finishes since the sampling thread exits when
409   // the_trace_ is null.
410   if (sampling_pthread != 0U) {
411     CHECK_PTHREAD_CALL(pthread_join, (sampling_pthread, nullptr), "sampling thread shutdown");
412     sampling_pthread_ = 0U;
413   }
414 
415   {
416     gc::ScopedGCCriticalSection gcs(self,
417                                     gc::kGcCauseInstrumentation,
418                                     gc::kCollectorTypeInstrumentation);
419     ScopedSuspendAll ssa(__FUNCTION__);
420     if (the_trace != nullptr) {
421       stop_alloc_counting = (the_trace->flags_ & Trace::kTraceCountAllocs) != 0;
422       if (finish_tracing) {
423         the_trace->FinishTracing();
424       }
425 
426       if (the_trace->trace_mode_ == TraceMode::kSampling) {
427         MutexLock mu(self, *Locks::thread_list_lock_);
428         runtime->GetThreadList()->ForEach(ClearThreadStackTraceAndClockBase, nullptr);
429       } else {
430         runtime->GetInstrumentation()->DisableMethodTracing(kTracerInstrumentationKey);
431         runtime->GetInstrumentation()->RemoveListener(
432             the_trace, instrumentation::Instrumentation::kMethodEntered |
433             instrumentation::Instrumentation::kMethodExited |
434             instrumentation::Instrumentation::kMethodUnwind);
435       }
436       if (the_trace->trace_file_.get() != nullptr) {
437         // Do not try to erase, so flush and close explicitly.
438         if (flush_file) {
439           if (the_trace->trace_file_->Flush() != 0) {
440             PLOG(WARNING) << "Could not flush trace file.";
441           }
442         } else {
443           the_trace->trace_file_->MarkUnchecked();  // Do not trigger guard.
444         }
445         if (the_trace->trace_file_->Close() != 0) {
446           PLOG(ERROR) << "Could not close trace file.";
447         }
448       }
449       delete the_trace;
450     }
451   }
452   if (stop_alloc_counting) {
453     // Can be racy since SetStatsEnabled is not guarded by any locks.
454     runtime->SetStatsEnabled(false);
455   }
456 }
457 
Abort()458 void Trace::Abort() {
459   // Do not write anything anymore.
460   StopTracing(false, false);
461 }
462 
Stop()463 void Trace::Stop() {
464   // Finish writing.
465   StopTracing(true, true);
466 }
467 
Shutdown()468 void Trace::Shutdown() {
469   if (GetMethodTracingMode() != kTracingInactive) {
470     Stop();
471   }
472 }
473 
Pause()474 void Trace::Pause() {
475   bool stop_alloc_counting = false;
476   Runtime* runtime = Runtime::Current();
477   Trace* the_trace = nullptr;
478 
479   Thread* const self = Thread::Current();
480   pthread_t sampling_pthread = 0U;
481   {
482     MutexLock mu(self, *Locks::trace_lock_);
483     if (the_trace_ == nullptr) {
484       LOG(ERROR) << "Trace pause requested, but no trace currently running";
485       return;
486     } else {
487       the_trace = the_trace_;
488       sampling_pthread = sampling_pthread_;
489     }
490   }
491 
492   if (sampling_pthread != 0U) {
493     {
494       MutexLock mu(self, *Locks::trace_lock_);
495       the_trace_ = nullptr;
496     }
497     CHECK_PTHREAD_CALL(pthread_join, (sampling_pthread, nullptr), "sampling thread shutdown");
498     sampling_pthread_ = 0U;
499     {
500       MutexLock mu(self, *Locks::trace_lock_);
501       the_trace_ = the_trace;
502     }
503   }
504 
505   if (the_trace != nullptr) {
506     gc::ScopedGCCriticalSection gcs(self,
507                                     gc::kGcCauseInstrumentation,
508                                     gc::kCollectorTypeInstrumentation);
509     ScopedSuspendAll ssa(__FUNCTION__);
510     stop_alloc_counting = (the_trace->flags_ & Trace::kTraceCountAllocs) != 0;
511 
512     if (the_trace->trace_mode_ == TraceMode::kSampling) {
513       MutexLock mu(self, *Locks::thread_list_lock_);
514       runtime->GetThreadList()->ForEach(ClearThreadStackTraceAndClockBase, nullptr);
515     } else {
516       runtime->GetInstrumentation()->DisableMethodTracing(kTracerInstrumentationKey);
517       runtime->GetInstrumentation()->RemoveListener(
518           the_trace,
519           instrumentation::Instrumentation::kMethodEntered |
520           instrumentation::Instrumentation::kMethodExited |
521           instrumentation::Instrumentation::kMethodUnwind);
522     }
523   }
524 
525   if (stop_alloc_counting) {
526     // Can be racy since SetStatsEnabled is not guarded by any locks.
527     Runtime::Current()->SetStatsEnabled(false);
528   }
529 }
530 
Resume()531 void Trace::Resume() {
532   Thread* self = Thread::Current();
533   Trace* the_trace;
534   {
535     MutexLock mu(self, *Locks::trace_lock_);
536     if (the_trace_ == nullptr) {
537       LOG(ERROR) << "No trace to resume (or sampling mode), ignoring this request";
538       return;
539     }
540     the_trace = the_trace_;
541   }
542 
543   Runtime* runtime = Runtime::Current();
544 
545   // Enable count of allocs if specified in the flags.
546   bool enable_stats = (the_trace->flags_ && kTraceCountAllocs) != 0;
547 
548   {
549     gc::ScopedGCCriticalSection gcs(self,
550                                     gc::kGcCauseInstrumentation,
551                                     gc::kCollectorTypeInstrumentation);
552     ScopedSuspendAll ssa(__FUNCTION__);
553 
554     // Reenable.
555     if (the_trace->trace_mode_ == TraceMode::kSampling) {
556       CHECK_PTHREAD_CALL(pthread_create, (&sampling_pthread_, nullptr, &RunSamplingThread,
557           reinterpret_cast<void*>(the_trace->interval_us_)), "Sampling profiler thread");
558     } else {
559       runtime->GetInstrumentation()->AddListener(the_trace,
560                                                  instrumentation::Instrumentation::kMethodEntered |
561                                                  instrumentation::Instrumentation::kMethodExited |
562                                                  instrumentation::Instrumentation::kMethodUnwind);
563       // TODO: In full-PIC mode, we don't need to fully deopt.
564       runtime->GetInstrumentation()->EnableMethodTracing(kTracerInstrumentationKey);
565     }
566   }
567 
568   // Can't call this when holding the mutator lock.
569   if (enable_stats) {
570     runtime->SetStatsEnabled(true);
571   }
572 }
573 
GetMethodTracingMode()574 TracingMode Trace::GetMethodTracingMode() {
575   MutexLock mu(Thread::Current(), *Locks::trace_lock_);
576   if (the_trace_ == nullptr) {
577     return kTracingInactive;
578   } else {
579     switch (the_trace_->trace_mode_) {
580       case TraceMode::kSampling:
581         return kSampleProfilingActive;
582       case TraceMode::kMethodTracing:
583         return kMethodTracingActive;
584     }
585     LOG(FATAL) << "Unreachable";
586     UNREACHABLE();
587   }
588 }
589 
590 static constexpr size_t kMinBufSize = 18U;  // Trace header is up to 18B.
591 
Trace(File * trace_file,const char * trace_name,size_t buffer_size,int flags,TraceOutputMode output_mode,TraceMode trace_mode)592 Trace::Trace(File* trace_file, const char* trace_name, size_t buffer_size, int flags,
593              TraceOutputMode output_mode, TraceMode trace_mode)
594     : trace_file_(trace_file),
595       buf_(new uint8_t[std::max(kMinBufSize, buffer_size)]()),
596       flags_(flags), trace_output_mode_(output_mode), trace_mode_(trace_mode),
597       clock_source_(default_clock_source_),
598       buffer_size_(std::max(kMinBufSize, buffer_size)),
599       start_time_(MicroTime()), clock_overhead_ns_(GetClockOverheadNanoSeconds()), cur_offset_(0),
600       overflow_(false), interval_us_(0), streaming_lock_(nullptr),
601       unique_methods_lock_(new Mutex("unique methods lock", kTracingUniqueMethodsLock)) {
602   uint16_t trace_version = GetTraceVersion(clock_source_);
603   if (output_mode == TraceOutputMode::kStreaming) {
604     trace_version |= 0xF0U;
605   }
606   // Set up the beginning of the trace.
607   memset(buf_.get(), 0, kTraceHeaderLength);
608   Append4LE(buf_.get(), kTraceMagicValue);
609   Append2LE(buf_.get() + 4, trace_version);
610   Append2LE(buf_.get() + 6, kTraceHeaderLength);
611   Append8LE(buf_.get() + 8, start_time_);
612   if (trace_version >= kTraceVersionDualClock) {
613     uint16_t record_size = GetRecordSize(clock_source_);
614     Append2LE(buf_.get() + 16, record_size);
615   }
616   static_assert(18 <= kMinBufSize, "Minimum buffer size not large enough for trace header");
617 
618   // Update current offset.
619   cur_offset_.StoreRelaxed(kTraceHeaderLength);
620 
621   if (output_mode == TraceOutputMode::kStreaming) {
622     streaming_file_name_ = trace_name;
623     streaming_lock_ = new Mutex("tracing lock", LockLevel::kTracingStreamingLock);
624     seen_threads_.reset(new ThreadIDBitSet());
625   }
626 }
627 
~Trace()628 Trace::~Trace() {
629   delete streaming_lock_;
630   delete unique_methods_lock_;
631 }
632 
ReadBytes(uint8_t * buf,size_t bytes)633 static uint64_t ReadBytes(uint8_t* buf, size_t bytes) {
634   uint64_t ret = 0;
635   for (size_t i = 0; i < bytes; ++i) {
636     ret |= static_cast<uint64_t>(buf[i]) << (i * 8);
637   }
638   return ret;
639 }
640 
DumpBuf(uint8_t * buf,size_t buf_size,TraceClockSource clock_source)641 void Trace::DumpBuf(uint8_t* buf, size_t buf_size, TraceClockSource clock_source) {
642   uint8_t* ptr = buf + kTraceHeaderLength;
643   uint8_t* end = buf + buf_size;
644 
645   while (ptr < end) {
646     uint32_t tmid = ReadBytes(ptr + 2, sizeof(tmid));
647     ArtMethod* method = DecodeTraceMethod(tmid);
648     TraceAction action = DecodeTraceAction(tmid);
649     LOG(INFO) << ArtMethod::PrettyMethod(method) << " " << static_cast<int>(action);
650     ptr += GetRecordSize(clock_source);
651   }
652 }
653 
FinishTracing()654 void Trace::FinishTracing() {
655   size_t final_offset = 0;
656 
657   std::set<ArtMethod*> visited_methods;
658   if (trace_output_mode_ == TraceOutputMode::kStreaming) {
659     // Clean up.
660     STLDeleteValues(&seen_methods_);
661   } else {
662     final_offset = cur_offset_.LoadRelaxed();
663     GetVisitedMethods(final_offset, &visited_methods);
664   }
665 
666   // Compute elapsed time.
667   uint64_t elapsed = MicroTime() - start_time_;
668 
669   std::ostringstream os;
670 
671   os << StringPrintf("%cversion\n", kTraceTokenChar);
672   os << StringPrintf("%d\n", GetTraceVersion(clock_source_));
673   os << StringPrintf("data-file-overflow=%s\n", overflow_ ? "true" : "false");
674   if (UseThreadCpuClock()) {
675     if (UseWallClock()) {
676       os << StringPrintf("clock=dual\n");
677     } else {
678       os << StringPrintf("clock=thread-cpu\n");
679     }
680   } else {
681     os << StringPrintf("clock=wall\n");
682   }
683   os << StringPrintf("elapsed-time-usec=%" PRIu64 "\n", elapsed);
684   if (trace_output_mode_ != TraceOutputMode::kStreaming) {
685     size_t num_records = (final_offset - kTraceHeaderLength) / GetRecordSize(clock_source_);
686     os << StringPrintf("num-method-calls=%zd\n", num_records);
687   }
688   os << StringPrintf("clock-call-overhead-nsec=%d\n", clock_overhead_ns_);
689   os << StringPrintf("vm=art\n");
690   os << StringPrintf("pid=%d\n", getpid());
691   if ((flags_ & kTraceCountAllocs) != 0) {
692     os << StringPrintf("alloc-count=%d\n", Runtime::Current()->GetStat(KIND_ALLOCATED_OBJECTS));
693     os << StringPrintf("alloc-size=%d\n", Runtime::Current()->GetStat(KIND_ALLOCATED_BYTES));
694     os << StringPrintf("gc-count=%d\n", Runtime::Current()->GetStat(KIND_GC_INVOCATIONS));
695   }
696   os << StringPrintf("%cthreads\n", kTraceTokenChar);
697   DumpThreadList(os);
698   os << StringPrintf("%cmethods\n", kTraceTokenChar);
699   DumpMethodList(os, visited_methods);
700   os << StringPrintf("%cend\n", kTraceTokenChar);
701   std::string header(os.str());
702 
703   if (trace_output_mode_ == TraceOutputMode::kStreaming) {
704     MutexLock mu(Thread::Current(), *streaming_lock_);  // To serialize writing.
705     // Write a special token to mark the end of trace records and the start of
706     // trace summary.
707     uint8_t buf[7];
708     Append2LE(buf, 0);
709     buf[2] = kOpTraceSummary;
710     Append4LE(buf + 3, static_cast<uint32_t>(header.length()));
711     WriteToBuf(buf, sizeof(buf));
712     // Write the trace summary. The summary is identical to the file header when
713     // the output mode is not streaming (except for methods).
714     WriteToBuf(reinterpret_cast<const uint8_t*>(header.c_str()), header.length());
715     // Flush the buffer, which may include some trace records before the summary.
716     FlushBuf();
717   } else {
718     if (trace_file_.get() == nullptr) {
719       iovec iov[2];
720       iov[0].iov_base = reinterpret_cast<void*>(const_cast<char*>(header.c_str()));
721       iov[0].iov_len = header.length();
722       iov[1].iov_base = buf_.get();
723       iov[1].iov_len = final_offset;
724       Dbg::DdmSendChunkV(CHUNK_TYPE("MPSE"), iov, 2);
725       const bool kDumpTraceInfo = false;
726       if (kDumpTraceInfo) {
727         LOG(INFO) << "Trace sent:\n" << header;
728         DumpBuf(buf_.get(), final_offset, clock_source_);
729       }
730     } else {
731       if (!trace_file_->WriteFully(header.c_str(), header.length()) ||
732           !trace_file_->WriteFully(buf_.get(), final_offset)) {
733         std::string detail(StringPrintf("Trace data write failed: %s", strerror(errno)));
734         PLOG(ERROR) << detail;
735         ThrowRuntimeException("%s", detail.c_str());
736       }
737     }
738   }
739 }
740 
DexPcMoved(Thread * thread ATTRIBUTE_UNUSED,mirror::Object * this_object ATTRIBUTE_UNUSED,ArtMethod * method,uint32_t new_dex_pc)741 void Trace::DexPcMoved(Thread* thread ATTRIBUTE_UNUSED,
742                        mirror::Object* this_object ATTRIBUTE_UNUSED,
743                        ArtMethod* method,
744                        uint32_t new_dex_pc) {
745   // We're not recorded to listen to this kind of event, so complain.
746   LOG(ERROR) << "Unexpected dex PC event in tracing " << ArtMethod::PrettyMethod(method)
747              << " " << new_dex_pc;
748 }
749 
FieldRead(Thread * thread ATTRIBUTE_UNUSED,mirror::Object * this_object ATTRIBUTE_UNUSED,ArtMethod * method,uint32_t dex_pc,ArtField * field ATTRIBUTE_UNUSED)750 void Trace::FieldRead(Thread* thread ATTRIBUTE_UNUSED,
751                       mirror::Object* this_object ATTRIBUTE_UNUSED,
752                       ArtMethod* method,
753                       uint32_t dex_pc,
754                       ArtField* field ATTRIBUTE_UNUSED)
755     REQUIRES_SHARED(Locks::mutator_lock_) {
756   // We're not recorded to listen to this kind of event, so complain.
757   LOG(ERROR) << "Unexpected field read event in tracing " << ArtMethod::PrettyMethod(method)
758              << " " << dex_pc;
759 }
760 
FieldWritten(Thread * thread ATTRIBUTE_UNUSED,mirror::Object * this_object ATTRIBUTE_UNUSED,ArtMethod * method,uint32_t dex_pc,ArtField * field ATTRIBUTE_UNUSED,const JValue & field_value ATTRIBUTE_UNUSED)761 void Trace::FieldWritten(Thread* thread ATTRIBUTE_UNUSED,
762                          mirror::Object* this_object ATTRIBUTE_UNUSED,
763                          ArtMethod* method,
764                          uint32_t dex_pc,
765                          ArtField* field ATTRIBUTE_UNUSED,
766                          const JValue& field_value ATTRIBUTE_UNUSED)
767     REQUIRES_SHARED(Locks::mutator_lock_) {
768   // We're not recorded to listen to this kind of event, so complain.
769   LOG(ERROR) << "Unexpected field write event in tracing " << ArtMethod::PrettyMethod(method)
770              << " " << dex_pc;
771 }
772 
MethodEntered(Thread * thread,mirror::Object * this_object ATTRIBUTE_UNUSED,ArtMethod * method,uint32_t dex_pc ATTRIBUTE_UNUSED)773 void Trace::MethodEntered(Thread* thread, mirror::Object* this_object ATTRIBUTE_UNUSED,
774                           ArtMethod* method, uint32_t dex_pc ATTRIBUTE_UNUSED) {
775   uint32_t thread_clock_diff = 0;
776   uint32_t wall_clock_diff = 0;
777   ReadClocks(thread, &thread_clock_diff, &wall_clock_diff);
778   LogMethodTraceEvent(thread, method, instrumentation::Instrumentation::kMethodEntered,
779                       thread_clock_diff, wall_clock_diff);
780 }
781 
MethodExited(Thread * thread,mirror::Object * this_object ATTRIBUTE_UNUSED,ArtMethod * method,uint32_t dex_pc ATTRIBUTE_UNUSED,const JValue & return_value ATTRIBUTE_UNUSED)782 void Trace::MethodExited(Thread* thread, mirror::Object* this_object ATTRIBUTE_UNUSED,
783                          ArtMethod* method, uint32_t dex_pc ATTRIBUTE_UNUSED,
784                          const JValue& return_value ATTRIBUTE_UNUSED) {
785   uint32_t thread_clock_diff = 0;
786   uint32_t wall_clock_diff = 0;
787   ReadClocks(thread, &thread_clock_diff, &wall_clock_diff);
788   LogMethodTraceEvent(thread, method, instrumentation::Instrumentation::kMethodExited,
789                       thread_clock_diff, wall_clock_diff);
790 }
791 
MethodUnwind(Thread * thread,mirror::Object * this_object ATTRIBUTE_UNUSED,ArtMethod * method,uint32_t dex_pc ATTRIBUTE_UNUSED)792 void Trace::MethodUnwind(Thread* thread, mirror::Object* this_object ATTRIBUTE_UNUSED,
793                          ArtMethod* method, uint32_t dex_pc ATTRIBUTE_UNUSED) {
794   uint32_t thread_clock_diff = 0;
795   uint32_t wall_clock_diff = 0;
796   ReadClocks(thread, &thread_clock_diff, &wall_clock_diff);
797   LogMethodTraceEvent(thread, method, instrumentation::Instrumentation::kMethodUnwind,
798                       thread_clock_diff, wall_clock_diff);
799 }
800 
ExceptionCaught(Thread * thread ATTRIBUTE_UNUSED,mirror::Throwable * exception_object ATTRIBUTE_UNUSED)801 void Trace::ExceptionCaught(Thread* thread ATTRIBUTE_UNUSED,
802                             mirror::Throwable* exception_object ATTRIBUTE_UNUSED)
803     REQUIRES_SHARED(Locks::mutator_lock_) {
804   LOG(ERROR) << "Unexpected exception caught event in tracing";
805 }
806 
Branch(Thread *,ArtMethod * method,uint32_t,int32_t)807 void Trace::Branch(Thread* /*thread*/, ArtMethod* method,
808                    uint32_t /*dex_pc*/, int32_t /*dex_pc_offset*/)
809       REQUIRES_SHARED(Locks::mutator_lock_) {
810   LOG(ERROR) << "Unexpected branch event in tracing" << ArtMethod::PrettyMethod(method);
811 }
812 
InvokeVirtualOrInterface(Thread *,mirror::Object *,ArtMethod * method,uint32_t dex_pc,ArtMethod *)813 void Trace::InvokeVirtualOrInterface(Thread*,
814                                      mirror::Object*,
815                                      ArtMethod* method,
816                                      uint32_t dex_pc,
817                                      ArtMethod*) {
818   LOG(ERROR) << "Unexpected invoke event in tracing" << ArtMethod::PrettyMethod(method)
819              << " " << dex_pc;
820 }
821 
ReadClocks(Thread * thread,uint32_t * thread_clock_diff,uint32_t * wall_clock_diff)822 void Trace::ReadClocks(Thread* thread, uint32_t* thread_clock_diff, uint32_t* wall_clock_diff) {
823   if (UseThreadCpuClock()) {
824     uint64_t clock_base = thread->GetTraceClockBase();
825     if (UNLIKELY(clock_base == 0)) {
826       // First event, record the base time in the map.
827       uint64_t time = thread->GetCpuMicroTime();
828       thread->SetTraceClockBase(time);
829     } else {
830       *thread_clock_diff = thread->GetCpuMicroTime() - clock_base;
831     }
832   }
833   if (UseWallClock()) {
834     *wall_clock_diff = MicroTime() - start_time_;
835   }
836 }
837 
RegisterMethod(ArtMethod * method)838 bool Trace::RegisterMethod(ArtMethod* method) {
839   mirror::DexCache* dex_cache = method->GetDexCache();
840   const DexFile* dex_file = dex_cache->GetDexFile();
841   if (seen_methods_.find(dex_file) == seen_methods_.end()) {
842     seen_methods_.insert(std::make_pair(dex_file, new DexIndexBitSet()));
843   }
844   DexIndexBitSet* bit_set = seen_methods_.find(dex_file)->second;
845   if (!(*bit_set)[method->GetDexMethodIndex()]) {
846     bit_set->set(method->GetDexMethodIndex());
847     return true;
848   }
849   return false;
850 }
851 
RegisterThread(Thread * thread)852 bool Trace::RegisterThread(Thread* thread) {
853   pid_t tid = thread->GetTid();
854   CHECK_LT(0U, static_cast<uint32_t>(tid));
855   CHECK_LT(static_cast<uint32_t>(tid), kMaxThreadIdNumber);
856 
857   if (!(*seen_threads_)[tid]) {
858     seen_threads_->set(tid);
859     return true;
860   }
861   return false;
862 }
863 
GetMethodLine(ArtMethod * method)864 std::string Trace::GetMethodLine(ArtMethod* method) {
865   method = method->GetInterfaceMethodIfProxy(kRuntimePointerSize);
866   return StringPrintf("%#x\t%s\t%s\t%s\t%s\n", (EncodeTraceMethod(method) << TraceActionBits),
867       PrettyDescriptor(method->GetDeclaringClassDescriptor()).c_str(), method->GetName(),
868       method->GetSignature().ToString().c_str(), method->GetDeclaringClassSourceFile());
869 }
870 
WriteToBuf(const uint8_t * src,size_t src_size)871 void Trace::WriteToBuf(const uint8_t* src, size_t src_size) {
872   int32_t old_offset = cur_offset_.LoadRelaxed();
873   int32_t new_offset = old_offset + static_cast<int32_t>(src_size);
874   if (dchecked_integral_cast<size_t>(new_offset) > buffer_size_) {
875     // Flush buffer.
876     if (!trace_file_->WriteFully(buf_.get(), old_offset)) {
877       PLOG(WARNING) << "Failed streaming a tracing event.";
878     }
879 
880     // Check whether the data is too large for the buffer, then write immediately.
881     if (src_size >= buffer_size_) {
882       if (!trace_file_->WriteFully(src, src_size)) {
883         PLOG(WARNING) << "Failed streaming a tracing event.";
884       }
885       cur_offset_.StoreRelease(0);  // Buffer is empty now.
886       return;
887     }
888 
889     old_offset = 0;
890     new_offset = static_cast<int32_t>(src_size);
891   }
892   cur_offset_.StoreRelease(new_offset);
893   // Fill in data.
894   memcpy(buf_.get() + old_offset, src, src_size);
895 }
896 
FlushBuf()897 void Trace::FlushBuf() {
898   int32_t offset = cur_offset_.LoadRelaxed();
899   if (!trace_file_->WriteFully(buf_.get(), offset)) {
900     PLOG(WARNING) << "Failed flush the remaining data in streaming.";
901   }
902   cur_offset_.StoreRelease(0);
903 }
904 
LogMethodTraceEvent(Thread * thread,ArtMethod * method,instrumentation::Instrumentation::InstrumentationEvent event,uint32_t thread_clock_diff,uint32_t wall_clock_diff)905 void Trace::LogMethodTraceEvent(Thread* thread, ArtMethod* method,
906                                 instrumentation::Instrumentation::InstrumentationEvent event,
907                                 uint32_t thread_clock_diff, uint32_t wall_clock_diff) {
908   // Ensure we always use the non-obsolete version of the method so that entry/exit events have the
909   // same pointer value.
910   method = method->GetNonObsoleteMethod();
911   // Advance cur_offset_ atomically.
912   int32_t new_offset;
913   int32_t old_offset = 0;
914 
915   // We do a busy loop here trying to acquire the next offset.
916   if (trace_output_mode_ != TraceOutputMode::kStreaming) {
917     do {
918       old_offset = cur_offset_.LoadRelaxed();
919       new_offset = old_offset + GetRecordSize(clock_source_);
920       if (static_cast<size_t>(new_offset) > buffer_size_) {
921         overflow_ = true;
922         return;
923       }
924     } while (!cur_offset_.CompareExchangeWeakSequentiallyConsistent(old_offset, new_offset));
925   }
926 
927   TraceAction action = kTraceMethodEnter;
928   switch (event) {
929     case instrumentation::Instrumentation::kMethodEntered:
930       action = kTraceMethodEnter;
931       break;
932     case instrumentation::Instrumentation::kMethodExited:
933       action = kTraceMethodExit;
934       break;
935     case instrumentation::Instrumentation::kMethodUnwind:
936       action = kTraceUnroll;
937       break;
938     default:
939       UNIMPLEMENTED(FATAL) << "Unexpected event: " << event;
940   }
941 
942   uint32_t method_value = EncodeTraceMethodAndAction(method, action);
943 
944   // Write data
945   uint8_t* ptr;
946   static constexpr size_t kPacketSize = 14U;  // The maximum size of data in a packet.
947   uint8_t stack_buf[kPacketSize];             // Space to store a packet when in streaming mode.
948   if (trace_output_mode_ == TraceOutputMode::kStreaming) {
949     ptr = stack_buf;
950   } else {
951     ptr = buf_.get() + old_offset;
952   }
953 
954   Append2LE(ptr, thread->GetTid());
955   Append4LE(ptr + 2, method_value);
956   ptr += 6;
957 
958   if (UseThreadCpuClock()) {
959     Append4LE(ptr, thread_clock_diff);
960     ptr += 4;
961   }
962   if (UseWallClock()) {
963     Append4LE(ptr, wall_clock_diff);
964   }
965   static_assert(kPacketSize == 2 + 4 + 4 + 4, "Packet size incorrect.");
966 
967   if (trace_output_mode_ == TraceOutputMode::kStreaming) {
968     MutexLock mu(Thread::Current(), *streaming_lock_);  // To serialize writing.
969     if (RegisterMethod(method)) {
970       // Write a special block with the name.
971       std::string method_line(GetMethodLine(method));
972       uint8_t buf2[5];
973       Append2LE(buf2, 0);
974       buf2[2] = kOpNewMethod;
975       Append2LE(buf2 + 3, static_cast<uint16_t>(method_line.length()));
976       WriteToBuf(buf2, sizeof(buf2));
977       WriteToBuf(reinterpret_cast<const uint8_t*>(method_line.c_str()), method_line.length());
978     }
979     if (RegisterThread(thread)) {
980       // It might be better to postpone this. Threads might not have received names...
981       std::string thread_name;
982       thread->GetThreadName(thread_name);
983       uint8_t buf2[7];
984       Append2LE(buf2, 0);
985       buf2[2] = kOpNewThread;
986       Append2LE(buf2 + 3, static_cast<uint16_t>(thread->GetTid()));
987       Append2LE(buf2 + 5, static_cast<uint16_t>(thread_name.length()));
988       WriteToBuf(buf2, sizeof(buf2));
989       WriteToBuf(reinterpret_cast<const uint8_t*>(thread_name.c_str()), thread_name.length());
990     }
991     WriteToBuf(stack_buf, sizeof(stack_buf));
992   }
993 }
994 
GetVisitedMethods(size_t buf_size,std::set<ArtMethod * > * visited_methods)995 void Trace::GetVisitedMethods(size_t buf_size,
996                               std::set<ArtMethod*>* visited_methods) {
997   uint8_t* ptr = buf_.get() + kTraceHeaderLength;
998   uint8_t* end = buf_.get() + buf_size;
999 
1000   while (ptr < end) {
1001     uint32_t tmid = ReadBytes(ptr + 2, sizeof(tmid));
1002     ArtMethod* method = DecodeTraceMethod(tmid);
1003     visited_methods->insert(method);
1004     ptr += GetRecordSize(clock_source_);
1005   }
1006 }
1007 
DumpMethodList(std::ostream & os,const std::set<ArtMethod * > & visited_methods)1008 void Trace::DumpMethodList(std::ostream& os, const std::set<ArtMethod*>& visited_methods) {
1009   for (const auto& method : visited_methods) {
1010     os << GetMethodLine(method);
1011   }
1012 }
1013 
DumpThread(Thread * t,void * arg)1014 static void DumpThread(Thread* t, void* arg) {
1015   std::ostream& os = *reinterpret_cast<std::ostream*>(arg);
1016   std::string name;
1017   t->GetThreadName(name);
1018   os << t->GetTid() << "\t" << name << "\n";
1019 }
1020 
DumpThreadList(std::ostream & os)1021 void Trace::DumpThreadList(std::ostream& os) {
1022   Thread* self = Thread::Current();
1023   for (auto it : exited_threads_) {
1024     os << it.first << "\t" << it.second << "\n";
1025   }
1026   Locks::thread_list_lock_->AssertNotHeld(self);
1027   MutexLock mu(self, *Locks::thread_list_lock_);
1028   Runtime::Current()->GetThreadList()->ForEach(DumpThread, &os);
1029 }
1030 
StoreExitingThreadInfo(Thread * thread)1031 void Trace::StoreExitingThreadInfo(Thread* thread) {
1032   MutexLock mu(thread, *Locks::trace_lock_);
1033   if (the_trace_ != nullptr) {
1034     std::string name;
1035     thread->GetThreadName(name);
1036     // The same thread/tid may be used multiple times. As SafeMap::Put does not allow to override
1037     // a previous mapping, use SafeMap::Overwrite.
1038     the_trace_->exited_threads_.Overwrite(thread->GetTid(), name);
1039   }
1040 }
1041 
GetOutputMode()1042 Trace::TraceOutputMode Trace::GetOutputMode() {
1043   MutexLock mu(Thread::Current(), *Locks::trace_lock_);
1044   CHECK(the_trace_ != nullptr) << "Trace output mode requested, but no trace currently running";
1045   return the_trace_->trace_output_mode_;
1046 }
1047 
GetMode()1048 Trace::TraceMode Trace::GetMode() {
1049   MutexLock mu(Thread::Current(), *Locks::trace_lock_);
1050   CHECK(the_trace_ != nullptr) << "Trace mode requested, but no trace currently running";
1051   return the_trace_->trace_mode_;
1052 }
1053 
GetBufferSize()1054 size_t Trace::GetBufferSize() {
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_->buffer_size_;
1058 }
1059 
IsTracingEnabled()1060 bool Trace::IsTracingEnabled() {
1061   MutexLock mu(Thread::Current(), *Locks::trace_lock_);
1062   return the_trace_ != nullptr;
1063 }
1064 
1065 }  // namespace art
1066