summaryrefslogtreecommitdiff
path: root/runtime/debugger.cc
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/debugger.cc')
-rw-r--r--runtime/debugger.cc79
1 files changed, 42 insertions, 37 deletions
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index 12bdb32fec..b59511214d 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -18,7 +18,9 @@
#include <sys/uio.h>
+#include <memory>
#include <set>
+#include <vector>
#include "android-base/stringprintf.h"
@@ -26,6 +28,7 @@
#include "art_field-inl.h"
#include "art_method-inl.h"
#include "base/enums.h"
+#include "base/strlcpy.h"
#include "base/time_utils.h"
#include "class_linker.h"
#include "class_linker-inl.h"
@@ -77,25 +80,10 @@ static uint16_t CappedAllocRecordCount(size_t alloc_record_count) {
return alloc_record_count;
}
-// Takes a method and returns a 'canonical' one if the method is default (and therefore potentially
-// copied from some other class). This ensures that the debugger does not get confused as to which
-// method we are in.
-static ArtMethod* GetCanonicalMethod(ArtMethod* m)
- REQUIRES_SHARED(Locks::mutator_lock_) {
- if (LIKELY(!m->IsDefault())) {
- return m;
- } else {
- mirror::Class* declaring_class = m->GetDeclaringClass();
- return declaring_class->FindDeclaredVirtualMethod(declaring_class->GetDexCache(),
- m->GetDexMethodIndex(),
- kRuntimePointerSize);
- }
-}
-
class Breakpoint : public ValueObject {
public:
Breakpoint(ArtMethod* method, uint32_t dex_pc, DeoptimizationRequest::Kind deoptimization_kind)
- : method_(GetCanonicalMethod(method)),
+ : method_(method->GetCanonicalMethod(kRuntimePointerSize)),
dex_pc_(dex_pc),
deoptimization_kind_(deoptimization_kind) {
CHECK(deoptimization_kind_ == DeoptimizationRequest::kNothing ||
@@ -125,7 +113,7 @@ class Breakpoint : public ValueObject {
// Returns true if the method of this breakpoint and the passed in method should be considered the
// same. That is, they are either the same method or they are copied from the same method.
bool IsInMethod(ArtMethod* m) const REQUIRES_SHARED(Locks::mutator_lock_) {
- return method_ == GetCanonicalMethod(m);
+ return method_ == m->GetCanonicalMethod(kRuntimePointerSize);
}
private:
@@ -1367,7 +1355,8 @@ JDWP::FieldId Dbg::ToFieldId(const ArtField* f) {
static JDWP::MethodId ToMethodId(ArtMethod* m)
REQUIRES_SHARED(Locks::mutator_lock_) {
- return static_cast<JDWP::MethodId>(reinterpret_cast<uintptr_t>(GetCanonicalMethod(m)));
+ return static_cast<JDWP::MethodId>(
+ reinterpret_cast<uintptr_t>(m->GetCanonicalMethod(kRuntimePointerSize)));
}
static ArtField* FromFieldId(JDWP::FieldId fid)
@@ -2460,7 +2449,7 @@ JDWP::JdwpError Dbg::SuspendThread(JDWP::ObjectId thread_id, bool request_suspen
ThreadList* thread_list = Runtime::Current()->GetThreadList();
Thread* thread = thread_list->SuspendThreadByPeer(peer.get(),
request_suspension,
- /* debug_suspension */ true,
+ SuspendReason::kForDebugger,
&timed_out);
if (thread != nullptr) {
return JDWP::ERR_NONE;
@@ -2491,7 +2480,7 @@ void Dbg::ResumeThread(JDWP::ObjectId thread_id) {
needs_resume = thread->GetDebugSuspendCount() > 0;
}
if (needs_resume) {
- Runtime::Current()->GetThreadList()->Resume(thread, true);
+ Runtime::Current()->GetThreadList()->Resume(thread, SuspendReason::kForDebugger);
}
}
@@ -2887,7 +2876,7 @@ static void SetEventLocation(JDWP::EventLocation* location, ArtMethod* m, uint32
if (m == nullptr) {
memset(location, 0, sizeof(*location));
} else {
- location->method = GetCanonicalMethod(m);
+ location->method = m->GetCanonicalMethod(kRuntimePointerSize);
location->dex_pc = (m->IsNative() || m->IsProxyMethod()) ? static_cast<uint32_t>(-1) : dex_pc;
}
}
@@ -3708,7 +3697,7 @@ class ScopedDebuggerThreadSuspension {
ThreadList* const thread_list = Runtime::Current()->GetThreadList();
suspended_thread = thread_list->SuspendThreadByPeer(thread_peer,
/* request_suspension */ true,
- /* debug_suspension */ true,
+ SuspendReason::kForDebugger,
&timed_out);
}
if (suspended_thread == nullptr) {
@@ -3732,7 +3721,7 @@ class ScopedDebuggerThreadSuspension {
~ScopedDebuggerThreadSuspension() {
if (other_suspend_) {
- Runtime::Current()->GetThreadList()->Resume(thread_, true);
+ Runtime::Current()->GetThreadList()->Resume(thread_, SuspendReason::kForDebugger);
}
}
@@ -4054,7 +4043,7 @@ JDWP::JdwpError Dbg::PrepareInvokeMethod(uint32_t request_id, JDWP::ObjectId thr
thread_list->UndoDebuggerSuspensions();
} else {
VLOG(jdwp) << " Resuming event thread only";
- thread_list->Resume(targetThread, true);
+ thread_list->Resume(targetThread, SuspendReason::kForDebugger);
}
return JDWP::ERR_NONE;
@@ -4940,11 +4929,20 @@ class StringTable {
StringTable() {
}
- void Add(const std::string& str) {
- table_.insert(str);
- }
+ void Add(const char* str, bool copy_string) {
+ if (UNLIKELY(copy_string)) {
+ // Check whether it's already there.
+ if (table_.find(str) != table_.end()) {
+ return;
+ }
- void Add(const char* str) {
+ // Make a copy.
+ size_t str_len = strlen(str);
+ char* copy = new char[str_len + 1];
+ strlcpy(copy, str, str_len + 1);
+ string_backup_.emplace_back(copy);
+ str = copy;
+ }
table_.insert(str);
}
@@ -4961,17 +4959,23 @@ class StringTable {
}
void WriteTo(std::vector<uint8_t>& bytes) const {
- for (const std::string& str : table_) {
- const char* s = str.c_str();
- size_t s_len = CountModifiedUtf8Chars(s);
+ for (const char* str : table_) {
+ size_t s_len = CountModifiedUtf8Chars(str);
std::unique_ptr<uint16_t[]> s_utf16(new uint16_t[s_len]);
- ConvertModifiedUtf8ToUtf16(s_utf16.get(), s);
+ ConvertModifiedUtf8ToUtf16(s_utf16.get(), str);
JDWP::AppendUtf16BE(bytes, s_utf16.get(), s_len);
}
}
private:
- std::set<std::string> table_;
+ struct ConstCharStarComparator {
+ bool operator()(const char *s1, const char *s2) const {
+ return strcmp(s1, s2) < 0;
+ }
+ };
+
+ std::set<const char*, ConstCharStarComparator> table_;
+ std::vector<std::unique_ptr<char[]>> string_backup_;
DISALLOW_COPY_AND_ASSIGN(StringTable);
};
@@ -5058,12 +5062,13 @@ jbyteArray Dbg::GetRecentAllocations() {
count > 0 && it != end; count--, it++) {
const gc::AllocRecord* record = &it->second;
std::string temp;
- class_names.Add(record->GetClassDescriptor(&temp));
+ const char* class_descr = record->GetClassDescriptor(&temp);
+ class_names.Add(class_descr, !temp.empty());
for (size_t i = 0, depth = record->GetDepth(); i < depth; i++) {
ArtMethod* m = record->StackElement(i).GetMethod();
- class_names.Add(m->GetDeclaringClassDescriptor());
- method_names.Add(m->GetName());
- filenames.Add(GetMethodSourceFile(m));
+ class_names.Add(m->GetDeclaringClassDescriptor(), false);
+ method_names.Add(m->GetName(), false);
+ filenames.Add(GetMethodSourceFile(m), false);
}
}