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