summaryrefslogtreecommitdiffstats
path: root/runtime/trace.cc
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/trace.cc')
-rw-r--r--runtime/trace.cc109
1 files changed, 59 insertions, 50 deletions
diff --git a/runtime/trace.cc b/runtime/trace.cc
index f8747168b3..d3b3af871f 100644
--- a/runtime/trace.cc
+++ b/runtime/trace.cc
@@ -22,6 +22,7 @@
#define ATRACE_TAG ATRACE_TAG_DALVIK
#include "cutils/trace.h"
+#include "art_method-inl.h"
#include "base/casts.h"
#include "base/stl_util.h"
#include "base/time_utils.h"
@@ -31,7 +32,6 @@
#include "debugger.h"
#include "dex_file-inl.h"
#include "instrumentation.h"
-#include "mirror/art_method-inl.h"
#include "mirror/class-inl.h"
#include "mirror/dex_cache-inl.h"
#include "mirror/object_array-inl.h"
@@ -98,7 +98,7 @@ class BuildStackTraceVisitor : public StackVisitor {
method_trace_(Trace::AllocStackTrace()) {}
bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- mirror::ArtMethod* m = GetMethod();
+ ArtMethod* m = GetMethod();
// Ignore runtime frames (in particular callee save).
if (!m->IsRuntimeMethod()) {
method_trace_->push_back(m);
@@ -107,12 +107,12 @@ class BuildStackTraceVisitor : public StackVisitor {
}
// Returns a stack trace where the topmost frame corresponds with the first element of the vector.
- std::vector<mirror::ArtMethod*>* GetStackTrace() const {
+ std::vector<ArtMethod*>* GetStackTrace() const {
return method_trace_;
}
private:
- std::vector<mirror::ArtMethod*>* const method_trace_;
+ std::vector<ArtMethod*>* const method_trace_;
};
static const char kTraceTokenChar = '*';
@@ -120,42 +120,41 @@ 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 = 10; // using v2
-static const uint16_t kTraceRecordSizeDualClock = 14; // using v3 with two timestamps
+static const uint16_t kTraceRecordSizeSingleClock = 14; // using v2
+static const uint16_t kTraceRecordSizeDualClock = 18; // using v3 with two timestamps
TraceClockSource Trace::default_clock_source_ = kDefaultTraceClockSource;
Trace* volatile Trace::the_trace_ = nullptr;
pthread_t Trace::sampling_pthread_ = 0U;
-std::unique_ptr<std::vector<mirror::ArtMethod*>> Trace::temp_stack_trace_;
+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 mirror::ArtMethod* DecodeTraceMethodId(uint32_t tmid) {
- return reinterpret_cast<mirror::ArtMethod*>(tmid & ~kTraceMethodActionMask);
+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 uint32_t EncodeTraceMethodAndAction(mirror::ArtMethod* method,
- TraceAction action) {
- uint32_t tmid = PointerToLowMemUInt32(method) | action;
+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;
}
-std::vector<mirror::ArtMethod*>* Trace::AllocStackTrace() {
+std::vector<ArtMethod*>* Trace::AllocStackTrace() {
if (temp_stack_trace_.get() != nullptr) {
return temp_stack_trace_.release();
} else {
- return new std::vector<mirror::ArtMethod*>();
+ return new std::vector<ArtMethod*>();
}
}
-void Trace::FreeStackTrace(std::vector<mirror::ArtMethod*>* stack_trace) {
+void Trace::FreeStackTrace(std::vector<ArtMethod*>* stack_trace) {
stack_trace->clear();
temp_stack_trace_.reset(stack_trace);
}
@@ -248,22 +247,22 @@ static void Append8LE(uint8_t* buf, uint64_t val) {
static void GetSample(Thread* thread, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
BuildStackTraceVisitor build_trace_visitor(thread);
build_trace_visitor.WalkStack();
- std::vector<mirror::ArtMethod*>* stack_trace = build_trace_visitor.GetStackTrace();
+ std::vector<ArtMethod*>* stack_trace = build_trace_visitor.GetStackTrace();
Trace* the_trace = reinterpret_cast<Trace*>(arg);
the_trace->CompareAndUpdateStackTrace(thread, stack_trace);
}
static void ClearThreadStackTraceAndClockBase(Thread* thread, void* arg ATTRIBUTE_UNUSED) {
thread->SetTraceClockBase(0);
- std::vector<mirror::ArtMethod*>* stack_trace = thread->GetStackTraceSample();
+ std::vector<ArtMethod*>* stack_trace = thread->GetStackTraceSample();
thread->SetStackTraceSample(nullptr);
delete stack_trace;
}
void Trace::CompareAndUpdateStackTrace(Thread* thread,
- std::vector<mirror::ArtMethod*>* stack_trace) {
+ std::vector<ArtMethod*>* stack_trace) {
CHECK_EQ(pthread_self(), sampling_pthread_);
- std::vector<mirror::ArtMethod*>* old_stack_trace = thread->GetStackTraceSample();
+ std::vector<ArtMethod*>* old_stack_trace = thread->GetStackTraceSample();
// Update the thread's stack trace sample.
thread->SetStackTraceSample(stack_trace);
// Read timer clocks to use for all events in this trace.
@@ -273,7 +272,7 @@ 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<mirror::ArtMethod*>::reverse_iterator rit = stack_trace->rbegin();
+ for (std::vector<ArtMethod*>::reverse_iterator rit = stack_trace->rbegin();
rit != stack_trace->rend(); ++rit) {
LogMethodTraceEvent(thread, *rit, instrumentation::Instrumentation::kMethodEntered,
thread_clock_diff, wall_clock_diff);
@@ -281,15 +280,15 @@ void Trace::CompareAndUpdateStackTrace(Thread* thread,
} else {
// If there's a previous stack trace for this thread, diff the traces and emit entry and exit
// events accordingly.
- std::vector<mirror::ArtMethod*>::reverse_iterator old_rit = old_stack_trace->rbegin();
- std::vector<mirror::ArtMethod*>::reverse_iterator rit = stack_trace->rbegin();
+ std::vector<ArtMethod*>::reverse_iterator old_rit = old_stack_trace->rbegin();
+ std::vector<ArtMethod*>::reverse_iterator 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<mirror::ArtMethod*>::iterator old_it = old_stack_trace->begin();
+ for (std::vector<ArtMethod*>::iterator 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);
@@ -640,14 +639,22 @@ Trace::~Trace() {
delete streaming_lock_;
}
+static uint64_t ReadBytes(uint8_t* buf, size_t bytes) {
+ uint64_t ret = 0;
+ for (size_t i = 0; i < bytes; ++i) {
+ ret |= static_cast<uint64_t>(buf[i]) << (i * 8);
+ }
+ return ret;
+}
+
static void DumpBuf(uint8_t* buf, size_t buf_size, TraceClockSource clock_source)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
uint8_t* ptr = buf + kTraceHeaderLength;
uint8_t* end = buf + buf_size;
while (ptr < end) {
- uint32_t tmid = ptr[2] | (ptr[3] << 8) | (ptr[4] << 16) | (ptr[5] << 24);
- mirror::ArtMethod* method = DecodeTraceMethodId(tmid);
+ uint64_t tmid = ReadBytes(ptr + 2, sizeof(tmid));
+ ArtMethod* method = DecodeTraceMethodId(tmid);
TraceAction action = DecodeTraceAction(tmid);
LOG(INFO) << PrettyMethod(method) << " " << static_cast<int>(action);
ptr += GetRecordSize(clock_source);
@@ -656,12 +663,12 @@ static void DumpBuf(uint8_t* buf, size_t buf_size, TraceClockSource clock_source
static void GetVisitedMethodsFromBitSets(
const std::map<mirror::DexCache*, DexIndexBitSet*>& seen_methods,
- std::set<mirror::ArtMethod*>* visited_methods) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ std::set<ArtMethod*>* visited_methods) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
for (auto& e : seen_methods) {
DexIndexBitSet* bit_set = e.second;
for (uint32_t i = 0; i < bit_set->size(); ++i) {
if ((*bit_set)[i]) {
- visited_methods->insert(e.first->GetResolvedMethod(i));
+ visited_methods->insert(e.first->GetResolvedMethod(i, sizeof(void*)));
}
}
}
@@ -670,7 +677,7 @@ static void GetVisitedMethodsFromBitSets(
void Trace::FinishTracing() {
size_t final_offset = 0;
- std::set<mirror::ArtMethod*> visited_methods;
+ std::set<ArtMethod*> visited_methods;
if (trace_output_mode_ == TraceOutputMode::kStreaming) {
// Write the secondary file with all the method names.
GetVisitedMethodsFromBitSets(seen_methods_, &visited_methods);
@@ -761,14 +768,14 @@ void Trace::FinishTracing() {
}
void Trace::DexPcMoved(Thread* thread, mirror::Object* this_object,
- mirror::ArtMethod* method, uint32_t new_dex_pc) {
+ ArtMethod* method, uint32_t new_dex_pc) {
UNUSED(thread, this_object, method, new_dex_pc);
// We're not recorded to listen to this kind of event, so complain.
LOG(ERROR) << "Unexpected dex PC event in tracing " << PrettyMethod(method) << " " << new_dex_pc;
}
void Trace::FieldRead(Thread* thread, mirror::Object* this_object,
- mirror::ArtMethod* method, uint32_t dex_pc, ArtField* field)
+ ArtMethod* method, uint32_t dex_pc, ArtField* field)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
UNUSED(thread, this_object, method, dex_pc, field);
// We're not recorded to listen to this kind of event, so complain.
@@ -776,7 +783,7 @@ void Trace::FieldRead(Thread* thread, mirror::Object* this_object,
}
void Trace::FieldWritten(Thread* thread, mirror::Object* this_object,
- mirror::ArtMethod* method, uint32_t dex_pc, ArtField* field,
+ ArtMethod* method, uint32_t dex_pc, ArtField* field,
const JValue& field_value)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
UNUSED(thread, this_object, method, dex_pc, field, field_value);
@@ -785,7 +792,7 @@ void Trace::FieldWritten(Thread* thread, mirror::Object* this_object,
}
void Trace::MethodEntered(Thread* thread, mirror::Object* this_object ATTRIBUTE_UNUSED,
- mirror::ArtMethod* method, uint32_t dex_pc ATTRIBUTE_UNUSED) {
+ ArtMethod* method, uint32_t dex_pc ATTRIBUTE_UNUSED) {
uint32_t thread_clock_diff = 0;
uint32_t wall_clock_diff = 0;
ReadClocks(thread, &thread_clock_diff, &wall_clock_diff);
@@ -794,7 +801,7 @@ void Trace::MethodEntered(Thread* thread, mirror::Object* this_object ATTRIBUTE_
}
void Trace::MethodExited(Thread* thread, mirror::Object* this_object ATTRIBUTE_UNUSED,
- mirror::ArtMethod* method, uint32_t dex_pc ATTRIBUTE_UNUSED,
+ ArtMethod* method, uint32_t dex_pc ATTRIBUTE_UNUSED,
const JValue& return_value ATTRIBUTE_UNUSED) {
uint32_t thread_clock_diff = 0;
uint32_t wall_clock_diff = 0;
@@ -804,7 +811,7 @@ void Trace::MethodExited(Thread* thread, mirror::Object* this_object ATTRIBUTE_U
}
void Trace::MethodUnwind(Thread* thread, mirror::Object* this_object ATTRIBUTE_UNUSED,
- mirror::ArtMethod* method, uint32_t dex_pc ATTRIBUTE_UNUSED) {
+ ArtMethod* method, uint32_t dex_pc ATTRIBUTE_UNUSED) {
uint32_t thread_clock_diff = 0;
uint32_t wall_clock_diff = 0;
ReadClocks(thread, &thread_clock_diff, &wall_clock_diff);
@@ -818,7 +825,7 @@ void Trace::ExceptionCaught(Thread* thread, mirror::Throwable* exception_object)
LOG(ERROR) << "Unexpected exception caught event in tracing";
}
-void Trace::BackwardBranch(Thread* /*thread*/, mirror::ArtMethod* method,
+void Trace::BackwardBranch(Thread* /*thread*/, ArtMethod* method,
int32_t /*dex_pc_offset*/)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
LOG(ERROR) << "Unexpected backward branch event in tracing" << PrettyMethod(method);
@@ -840,11 +847,12 @@ void Trace::ReadClocks(Thread* thread, uint32_t* thread_clock_diff, uint32_t* wa
}
}
-bool Trace::RegisterMethod(mirror::ArtMethod* method) {
+bool Trace::RegisterMethod(ArtMethod* method) {
mirror::DexCache* dex_cache = method->GetDexCache();
- if (dex_cache->GetResolvedMethod(method->GetDexMethodIndex()) != method) {
- DCHECK(dex_cache->GetResolvedMethod(method->GetDexMethodIndex()) == nullptr);
- dex_cache->SetResolvedMethod(method->GetDexMethodIndex(), method);
+ auto* resolved_method = dex_cache->GetResolvedMethod(method->GetDexMethodIndex(), sizeof(void*));
+ if (resolved_method != method) {
+ DCHECK(resolved_method == nullptr);
+ dex_cache->SetResolvedMethod(method->GetDexMethodIndex(), method, sizeof(void*));
}
if (seen_methods_.find(dex_cache) == seen_methods_.end()) {
seen_methods_.insert(std::make_pair(dex_cache, new DexIndexBitSet()));
@@ -869,8 +877,9 @@ bool Trace::RegisterThread(Thread* thread) {
return false;
}
-static std::string GetMethodLine(mirror::ArtMethod* method)
+static std::string GetMethodLine(ArtMethod* method)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ method = method->GetInterfaceMethodIfProxy(sizeof(void*));
return StringPrintf("%p\t%s\t%s\t%s\t%s\n", method,
PrettyDescriptor(method->GetDeclaringClassDescriptor()).c_str(), method->GetName(),
method->GetSignature().ToString().c_str(), method->GetDeclaringClassSourceFile());
@@ -902,7 +911,7 @@ void Trace::WriteToBuf(const uint8_t* src, size_t src_size) {
memcpy(buf_.get() + old_offset, src, src_size);
}
-void Trace::LogMethodTraceEvent(Thread* thread, mirror::ArtMethod* method,
+void Trace::LogMethodTraceEvent(Thread* thread, ArtMethod* method,
instrumentation::Instrumentation::InstrumentationEvent event,
uint32_t thread_clock_diff, uint32_t wall_clock_diff) {
// Advance cur_offset_ atomically.
@@ -936,11 +945,11 @@ void Trace::LogMethodTraceEvent(Thread* thread, mirror::ArtMethod* method,
UNIMPLEMENTED(FATAL) << "Unexpected event: " << event;
}
- uint32_t method_value = EncodeTraceMethodAndAction(method, action);
+ uint64_t method_value = EncodeTraceMethodAndAction(method, action);
// Write data
uint8_t* ptr;
- static constexpr size_t kPacketSize = 14U; // The maximum size of data in a packet.
+ static constexpr size_t kPacketSize = 18U; // 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;
@@ -949,8 +958,8 @@ void Trace::LogMethodTraceEvent(Thread* thread, mirror::ArtMethod* method,
}
Append2LE(ptr, thread->GetTid());
- Append4LE(ptr + 2, method_value);
- ptr += 6;
+ Append8LE(ptr + 2, method_value);
+ ptr += 10;
if (UseThreadCpuClock()) {
Append4LE(ptr, thread_clock_diff);
@@ -959,7 +968,7 @@ void Trace::LogMethodTraceEvent(Thread* thread, mirror::ArtMethod* method,
if (UseWallClock()) {
Append4LE(ptr, wall_clock_diff);
}
- static_assert(kPacketSize == 2 + 4 + 4 + 4, "Packet size incorrect.");
+ static_assert(kPacketSize == 2 + 8 + 4 + 4, "Packet size incorrect.");
if (trace_output_mode_ == TraceOutputMode::kStreaming) {
MutexLock mu(Thread::Current(), *streaming_lock_); // To serialize writing.
@@ -990,19 +999,19 @@ void Trace::LogMethodTraceEvent(Thread* thread, mirror::ArtMethod* method,
}
void Trace::GetVisitedMethods(size_t buf_size,
- std::set<mirror::ArtMethod*>* visited_methods) {
+ std::set<ArtMethod*>* visited_methods) {
uint8_t* ptr = buf_.get() + kTraceHeaderLength;
uint8_t* end = buf_.get() + buf_size;
while (ptr < end) {
- uint32_t tmid = ptr[2] | (ptr[3] << 8) | (ptr[4] << 16) | (ptr[5] << 24);
- mirror::ArtMethod* method = DecodeTraceMethodId(tmid);
+ uint64_t tmid = ReadBytes(ptr + 2, sizeof(tmid));
+ ArtMethod* method = DecodeTraceMethodId(tmid);
visited_methods->insert(method);
ptr += GetRecordSize(clock_source_);
}
}
-void Trace::DumpMethodList(std::ostream& os, const std::set<mirror::ArtMethod*>& visited_methods) {
+void Trace::DumpMethodList(std::ostream& os, const std::set<ArtMethod*>& visited_methods) {
for (const auto& method : visited_methods) {
os << GetMethodLine(method);
}