Home | History | Annotate | Download | only in runtime
      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:
     61   explicit BuildStackTraceVisitor(Thread* thread)
     62       : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
     63         method_trace_(Trace::AllocStackTrace()) {}
     64 
     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.
     75   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 
    102 static TraceAction DecodeTraceAction(uint32_t tmid) {
    103   return static_cast<TraceAction>(tmid & kTraceMethodActionMask);
    104 }
    105 
    106 ArtMethod* Trace::DecodeTraceMethod(uint32_t tmid) {
    107   MutexLock mu(Thread::Current(), *unique_methods_lock_);
    108   return unique_methods_[tmid >> TraceActionBits];
    109 }
    110 
    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 
    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 
    133 std::vector<ArtMethod*>* Trace::AllocStackTrace() {
    134   return (temp_stack_trace_.get() != nullptr)  ? temp_stack_trace_.release() :
    135       new std::vector<ArtMethod*>();
    136 }
    137 
    138 void Trace::FreeStackTrace(std::vector<ArtMethod*>* stack_trace) {
    139   stack_trace->clear();
    140   temp_stack_trace_.reset(stack_trace);
    141 }
    142 
    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 
    153 static uint16_t GetTraceVersion(TraceClockSource clock_source) {
    154   return (clock_source == TraceClockSource::kDual) ? kTraceVersionDualClock
    155                                                     : kTraceVersionSingleClock;
    156 }
    157 
    158 static uint16_t GetRecordSize(TraceClockSource clock_source) {
    159   return (clock_source == TraceClockSource::kDual) ? kTraceRecordSizeDualClock
    160                                                     : kTraceRecordSizeSingleClock;
    161 }
    162 
    163 bool Trace::UseThreadCpuClock() {
    164   return (clock_source_ == TraceClockSource::kThreadCpu) ||
    165       (clock_source_ == TraceClockSource::kDual);
    166 }
    167 
    168 bool Trace::UseWallClock() {
    169   return (clock_source_ == TraceClockSource::kWall) ||
    170       (clock_source_ == TraceClockSource::kDual);
    171 }
    172 
    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.
    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.
    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.
    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.
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    458 void Trace::Abort() {
    459   // Do not write anything anymore.
    460   StopTracing(false, false);
    461 }
    462 
    463 void Trace::Stop() {
    464   // Finish writing.
    465   StopTracing(true, true);
    466 }
    467 
    468 void Trace::Shutdown() {
    469   if (GetMethodTracingMode() != kTracingInactive) {
    470     Stop();
    471   }
    472 }
    473 
    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 
    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 
    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 
    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 
    628 Trace::~Trace() {
    629   delete streaming_lock_;
    630   delete unique_methods_lock_;
    631 }
    632 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   1060 bool Trace::IsTracingEnabled() {
   1061   MutexLock mu(Thread::Current(), *Locks::trace_lock_);
   1062   return the_trace_ != nullptr;
   1063 }
   1064 
   1065 }  // namespace art
   1066