diff options
author | Mathieu Chartier <mathieuc@google.com> | 2015-06-02 16:38:29 -0700 |
---|---|---|
committer | Mathieu Chartier <mathieuc@google.com> | 2015-06-02 17:11:38 -0700 |
commit | d40bcc4fab1589e3aac0f4b59217c6ab4e72102a (patch) | |
tree | 93a44603e6804ec09439fe158b51d272c7e89cc8 /runtime/trace.cc | |
parent | ff6d8cffb7c14eee56df16d1422b1fcc180decde (diff) | |
download | art-d40bcc4fab1589e3aac0f4b59217c6ab4e72102a.tar.gz art-d40bcc4fab1589e3aac0f4b59217c6ab4e72102a.tar.bz2 art-d40bcc4fab1589e3aac0f4b59217c6ab4e72102a.zip |
Fix tracing
Move back to 32 bit method IDs, add a bijective map for method IDs.
Also some cleanup.
Bug: 19264997
Change-Id: Icdd36591df53ff975d30b9000cfe67d3ae8c51d5
Diffstat (limited to 'runtime/trace.cc')
-rw-r--r-- | runtime/trace.cc | 130 |
1 files changed, 50 insertions, 80 deletions
diff --git a/runtime/trace.cc b/runtime/trace.cc index d3b3af871f..5a43b567aa 100644 --- a/runtime/trace.cc +++ b/runtime/trace.cc @@ -46,48 +46,8 @@ namespace art { -// File format: -// header -// record 0 -// record 1 -// ... -// -// Header format: -// u4 magic ('SLOW') -// u2 version -// u2 offset to data -// u8 start date/time in usec -// u2 record size in bytes (version >= 2 only) -// ... padding to 32 bytes -// -// Record format v1: -// u1 thread ID -// u4 method ID | method action -// u4 time delta since start, in usec -// -// Record format v2: -// u2 thread ID -// u4 method ID | method action -// u4 time delta since start, in usec -// -// Record format v3: -// u2 thread ID -// u4 method ID | method action -// u4 time delta since start, in usec -// u4 wall time since start, in usec (when clock == "dual" only) -// -// 32 bits of microseconds is 70 minutes. -// -// All values are stored in little-endian order. - -enum TraceAction { - kTraceMethodEnter = 0x00, // method entry - kTraceMethodExit = 0x01, // method exit - kTraceUnroll = 0x02, // method exited by exception unrolling - // 0x03 currently unused - kTraceMethodActionMask = 0x03, // two bits -}; - +static constexpr size_t TraceActionBits = MinimumBitsToStore( + static_cast<size_t>(kTraceMethodActionMask)); static constexpr uint8_t kOpNewMethod = 1U; static constexpr uint8_t kOpNewThread = 2U; @@ -120,8 +80,8 @@ static const uint16_t kTraceHeaderLength = 32; static const uint32_t kTraceMagicValue = 0x574f4c53; static const uint16_t kTraceVersionSingleClock = 2; static const uint16_t kTraceVersionDualClock = 3; -static const uint16_t kTraceRecordSizeSingleClock = 14; // using v2 -static const uint16_t kTraceRecordSizeDualClock = 18; // using v3 with two timestamps +static const uint16_t kTraceRecordSizeSingleClock = 10; // using v2 +static const uint16_t kTraceRecordSizeDualClock = 14; // using v3 with two timestamps TraceClockSource Trace::default_clock_source_ = kDefaultTraceClockSource; @@ -132,26 +92,40 @@ std::unique_ptr<std::vector<ArtMethod*>> Trace::temp_stack_trace_; // The key identifying the tracer to update instrumentation. static constexpr const char* kTracerInstrumentationKey = "Tracer"; -static ArtMethod* DecodeTraceMethodId(uint64_t tmid) { - return reinterpret_cast<ArtMethod*>(tmid & ~kTraceMethodActionMask); -} - static TraceAction DecodeTraceAction(uint32_t tmid) { return static_cast<TraceAction>(tmid & kTraceMethodActionMask); } -static uint64_t EncodeTraceMethodAndAction(ArtMethod* method, TraceAction action) { - auto tmid = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(method)) | action; - DCHECK_EQ(method, DecodeTraceMethodId(tmid)); - return tmid; +ArtMethod* Trace::DecodeTraceMethod(uint32_t tmid) { + MutexLock mu(Thread::Current(), *unique_methods_lock_); + return unique_methods_[tmid >> TraceActionBits]; } -std::vector<ArtMethod*>* Trace::AllocStackTrace() { - if (temp_stack_trace_.get() != nullptr) { - return temp_stack_trace_.release(); +uint32_t Trace::EncodeTraceMethod(ArtMethod* method) { + MutexLock mu(Thread::Current(), *unique_methods_lock_); + uint32_t idx; + auto it = art_method_id_map_.find(method); + if (it != art_method_id_map_.end()) { + idx = it->second; } else { - return new std::vector<ArtMethod*>(); + unique_methods_.push_back(method); + idx = unique_methods_.size() - 1; + art_method_id_map_.emplace(method, idx); } + DCHECK_LT(idx, unique_methods_.size()); + DCHECK_EQ(unique_methods_[idx], method); + return idx; +} + +uint32_t Trace::EncodeTraceMethodAndAction(ArtMethod* method, TraceAction action) { + uint32_t tmid = (EncodeTraceMethod(method) << TraceActionBits) | action; + DCHECK_EQ(method, DecodeTraceMethod(tmid)); + return tmid; +} + +std::vector<ArtMethod*>* Trace::AllocStackTrace() { + return (temp_stack_trace_.get() != nullptr) ? temp_stack_trace_.release() : + new std::vector<ArtMethod*>(); } void Trace::FreeStackTrace(std::vector<ArtMethod*>* stack_trace) { @@ -272,24 +246,22 @@ void Trace::CompareAndUpdateStackTrace(Thread* thread, if (old_stack_trace == nullptr) { // If there's no previous stack trace sample for this thread, log an entry event for all // methods in the trace. - for (std::vector<ArtMethod*>::reverse_iterator rit = stack_trace->rbegin(); - rit != stack_trace->rend(); ++rit) { + for (auto rit = stack_trace->rbegin(); rit != stack_trace->rend(); ++rit) { LogMethodTraceEvent(thread, *rit, instrumentation::Instrumentation::kMethodEntered, thread_clock_diff, wall_clock_diff); } } else { // If there's a previous stack trace for this thread, diff the traces and emit entry and exit // events accordingly. - std::vector<ArtMethod*>::reverse_iterator old_rit = old_stack_trace->rbegin(); - std::vector<ArtMethod*>::reverse_iterator rit = stack_trace->rbegin(); + auto old_rit = old_stack_trace->rbegin(); + auto rit = stack_trace->rbegin(); // Iterate bottom-up over both traces until there's a difference between them. while (old_rit != old_stack_trace->rend() && rit != stack_trace->rend() && *old_rit == *rit) { old_rit++; rit++; } // Iterate top-down over the old trace until the point where they differ, emitting exit events. - for (std::vector<ArtMethod*>::iterator old_it = old_stack_trace->begin(); - old_it != old_rit.base(); ++old_it) { + for (auto old_it = old_stack_trace->begin(); old_it != old_rit.base(); ++old_it) { LogMethodTraceEvent(thread, *old_it, instrumentation::Instrumentation::kMethodExited, thread_clock_diff, wall_clock_diff); } @@ -608,7 +580,8 @@ Trace::Trace(File* trace_file, const char* trace_name, size_t buffer_size, int f clock_source_(default_clock_source_), buffer_size_(std::max(kMinBufSize, buffer_size)), start_time_(MicroTime()), clock_overhead_ns_(GetClockOverheadNanoSeconds()), cur_offset_(0), - overflow_(false), interval_us_(0), streaming_lock_(nullptr) { + overflow_(false), interval_us_(0), streaming_lock_(nullptr), + unique_methods_lock_(new Mutex("unique methods lock")) { uint16_t trace_version = GetTraceVersion(clock_source_); if (output_mode == TraceOutputMode::kStreaming) { trace_version |= 0xF0U; @@ -647,14 +620,13 @@ static uint64_t ReadBytes(uint8_t* buf, size_t bytes) { return ret; } -static void DumpBuf(uint8_t* buf, size_t buf_size, TraceClockSource clock_source) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { +void Trace::DumpBuf(uint8_t* buf, size_t buf_size, TraceClockSource clock_source) { uint8_t* ptr = buf + kTraceHeaderLength; uint8_t* end = buf + buf_size; while (ptr < end) { - uint64_t tmid = ReadBytes(ptr + 2, sizeof(tmid)); - ArtMethod* method = DecodeTraceMethodId(tmid); + uint32_t tmid = ReadBytes(ptr + 2, sizeof(tmid)); + ArtMethod* method = DecodeTraceMethod(tmid); TraceAction action = DecodeTraceAction(tmid); LOG(INFO) << PrettyMethod(method) << " " << static_cast<int>(action); ptr += GetRecordSize(clock_source); @@ -683,9 +655,7 @@ void Trace::FinishTracing() { GetVisitedMethodsFromBitSets(seen_methods_, &visited_methods); // Clean up. - for (auto& e : seen_methods_) { - delete e.second; - } + STLDeleteValues(&seen_methods_); } else { final_offset = cur_offset_.LoadRelaxed(); GetVisitedMethods(final_offset, &visited_methods); @@ -877,10 +847,10 @@ bool Trace::RegisterThread(Thread* thread) { return false; } -static std::string GetMethodLine(ArtMethod* method) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { +std::string Trace::GetMethodLine(ArtMethod* method) { method = method->GetInterfaceMethodIfProxy(sizeof(void*)); - return StringPrintf("%p\t%s\t%s\t%s\t%s\n", method, + return StringPrintf("%p\t%s\t%s\t%s\t%s\n", + reinterpret_cast<void*>((EncodeTraceMethod(method) << TraceActionBits)), PrettyDescriptor(method->GetDeclaringClassDescriptor()).c_str(), method->GetName(), method->GetSignature().ToString().c_str(), method->GetDeclaringClassSourceFile()); } @@ -945,11 +915,11 @@ void Trace::LogMethodTraceEvent(Thread* thread, ArtMethod* method, UNIMPLEMENTED(FATAL) << "Unexpected event: " << event; } - uint64_t method_value = EncodeTraceMethodAndAction(method, action); + uint32_t method_value = EncodeTraceMethodAndAction(method, action); // Write data uint8_t* ptr; - static constexpr size_t kPacketSize = 18U; // The maximum size of data in a packet. + static constexpr size_t kPacketSize = 14U; // The maximum size of data in a packet. uint8_t stack_buf[kPacketSize]; // Space to store a packet when in streaming mode. if (trace_output_mode_ == TraceOutputMode::kStreaming) { ptr = stack_buf; @@ -958,8 +928,8 @@ void Trace::LogMethodTraceEvent(Thread* thread, ArtMethod* method, } Append2LE(ptr, thread->GetTid()); - Append8LE(ptr + 2, method_value); - ptr += 10; + Append4LE(ptr + 2, method_value); + ptr += 6; if (UseThreadCpuClock()) { Append4LE(ptr, thread_clock_diff); @@ -968,7 +938,7 @@ void Trace::LogMethodTraceEvent(Thread* thread, ArtMethod* method, if (UseWallClock()) { Append4LE(ptr, wall_clock_diff); } - static_assert(kPacketSize == 2 + 8 + 4 + 4, "Packet size incorrect."); + static_assert(kPacketSize == 2 + 4 + 4 + 4, "Packet size incorrect."); if (trace_output_mode_ == TraceOutputMode::kStreaming) { MutexLock mu(Thread::Current(), *streaming_lock_); // To serialize writing. @@ -1004,8 +974,8 @@ void Trace::GetVisitedMethods(size_t buf_size, uint8_t* end = buf_.get() + buf_size; while (ptr < end) { - uint64_t tmid = ReadBytes(ptr + 2, sizeof(tmid)); - ArtMethod* method = DecodeTraceMethodId(tmid); + uint32_t tmid = ReadBytes(ptr + 2, sizeof(tmid)); + ArtMethod* method = DecodeTraceMethod(tmid); visited_methods->insert(method); ptr += GetRecordSize(clock_source_); } |