summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Hao <jeffhao@google.com>2013-11-18 13:16:49 -0800
committerJeff Hao <jeffhao@google.com>2013-11-19 11:16:44 -0800
commit579b02416e05e32e535126e1ed61613a2cdb030e (patch)
tree4431587a30c1d5a3e7c0435decbd7ac21104bf7a
parente4a50ee34695a9d90cf03fbb1e8afd1e434f6ee1 (diff)
downloadart-579b02416e05e32e535126e1ed61613a2cdb030e.zip
art-579b02416e05e32e535126e1ed61613a2cdb030e.tar.gz
art-579b02416e05e32e535126e1ed61613a2cdb030e.tar.bz2
Add support for JDWP METHOD_EXIT_WITH_RETURN_VALUE events.
Bug: 11569539 Change-Id: Ibc7a80df83470ffd726d73695a05f4938248f292
-rw-r--r--runtime/debugger.cc68
-rw-r--r--runtime/debugger.h8
-rw-r--r--runtime/jdwp/jdwp.h6
-rw-r--r--runtime/jdwp/jdwp_event.cc10
4 files changed, 62 insertions, 30 deletions
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index 3ef0a7f..af92b4b 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -121,19 +121,18 @@ class DebugInstrumentationListener : public instrumentation::InstrumentationList
// TODO: post location events is a suspension point and native method entry stubs aren't.
return;
}
- Dbg::PostLocationEvent(method, 0, this_object, Dbg::kMethodEntry);
+ Dbg::PostLocationEvent(method, 0, this_object, Dbg::kMethodEntry, nullptr);
}
virtual void MethodExited(Thread* thread, mirror::Object* this_object,
const mirror::ArtMethod* method,
uint32_t dex_pc, const JValue& return_value)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- UNUSED(return_value);
if (method->IsNative()) {
// TODO: post location events is a suspension point and native method entry stubs aren't.
return;
}
- Dbg::PostLocationEvent(method, dex_pc, this_object, Dbg::kMethodExit);
+ Dbg::PostLocationEvent(method, dex_pc, this_object, Dbg::kMethodExit, &return_value);
}
virtual void MethodUnwind(Thread* thread, const mirror::ArtMethod* method,
@@ -1393,6 +1392,13 @@ void Dbg::OutputVariableTable(JDWP::RefTypeId, JDWP::MethodId method_id, bool wi
JDWP::Set4BE(expandBufGetBuffer(pReply) + variable_count_offset, context.variable_count);
}
+void Dbg::OutputMethodReturnValue(JDWP::MethodId method_id, const JValue* return_value,
+ JDWP::ExpandBuf* pReply) {
+ mirror::ArtMethod* m = FromMethodId(method_id);
+ JDWP::JdwpTag tag = BasicTagFromDescriptor(MethodHelper(m).GetShorty());
+ OutputJValue(tag, return_value, pReply);
+}
+
JDWP::JdwpError Dbg::GetBytecodes(JDWP::RefTypeId, JDWP::MethodId method_id,
std::vector<uint8_t>& bytecodes)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -1461,25 +1467,18 @@ static JDWP::JdwpError GetFieldValueImpl(JDWP::RefTypeId ref_type_id, JDWP::Obje
}
JDWP::JdwpTag tag = BasicTagFromDescriptor(FieldHelper(f).GetTypeDescriptor());
-
- if (IsPrimitiveTag(tag)) {
- expandBufAdd1(pReply, tag);
- if (tag == JDWP::JT_BOOLEAN || tag == JDWP::JT_BYTE) {
- expandBufAdd1(pReply, f->Get32(o));
- } else if (tag == JDWP::JT_CHAR || tag == JDWP::JT_SHORT) {
- expandBufAdd2BE(pReply, f->Get32(o));
- } else if (tag == JDWP::JT_FLOAT || tag == JDWP::JT_INT) {
- expandBufAdd4BE(pReply, f->Get32(o));
- } else if (tag == JDWP::JT_DOUBLE || tag == JDWP::JT_LONG) {
- expandBufAdd8BE(pReply, f->Get64(o));
- } else {
- LOG(FATAL) << "Unknown tag: " << tag;
- }
+ JValue field_value;
+ if (tag == JDWP::JT_VOID) {
+ LOG(FATAL) << "Unknown tag: " << tag;
+ } else if (!IsPrimitiveTag(tag)) {
+ field_value.SetL(f->GetObject(o));
+ } else if (tag == JDWP::JT_DOUBLE || tag == JDWP::JT_LONG) {
+ field_value.SetJ(f->Get64(o));
} else {
- mirror::Object* value = f->GetObject(o);
- expandBufAdd1(pReply, TagFromObject(value));
- expandBufAddObjectId(pReply, gRegistry->Add(value));
+ field_value.SetI(f->Get32(o));
}
+ Dbg::OutputJValue(tag, &field_value, pReply);
+
return JDWP::ERR_NONE;
}
@@ -1557,6 +1556,27 @@ std::string Dbg::StringToUtf8(JDWP::ObjectId string_id) {
return s->ToModifiedUtf8();
}
+void Dbg::OutputJValue(JDWP::JdwpTag tag, const JValue* return_value, JDWP::ExpandBuf* pReply) {
+ if (IsPrimitiveTag(tag)) {
+ expandBufAdd1(pReply, tag);
+ if (tag == JDWP::JT_BOOLEAN || tag == JDWP::JT_BYTE) {
+ expandBufAdd1(pReply, return_value->GetI());
+ } else if (tag == JDWP::JT_CHAR || tag == JDWP::JT_SHORT) {
+ expandBufAdd2BE(pReply, return_value->GetI());
+ } else if (tag == JDWP::JT_FLOAT || tag == JDWP::JT_INT) {
+ expandBufAdd4BE(pReply, return_value->GetI());
+ } else if (tag == JDWP::JT_DOUBLE || tag == JDWP::JT_LONG) {
+ expandBufAdd8BE(pReply, return_value->GetJ());
+ } else {
+ CHECK_EQ(tag, JDWP::JT_VOID);
+ }
+ } else {
+ mirror::Object* value = return_value->GetL();
+ expandBufAdd1(pReply, TagFromObject(value));
+ expandBufAddObjectId(pReply, gRegistry->Add(value));
+ }
+}
+
JDWP::JdwpError Dbg::GetThreadName(JDWP::ObjectId thread_id, std::string& name) {
ScopedObjectAccessUnchecked soa(Thread::Current());
MutexLock mu(soa.Self(), *Locks::thread_list_lock_);
@@ -2226,8 +2246,8 @@ void Dbg::SetLocalValue(JDWP::ObjectId thread_id, JDWP::FrameId frame_id, int sl
visitor.WalkStack();
}
-void Dbg::PostLocationEvent(const mirror::ArtMethod* m, int dex_pc,
- mirror::Object* this_object, int event_flags) {
+void Dbg::PostLocationEvent(const mirror::ArtMethod* m, int dex_pc, mirror::Object* this_object,
+ int event_flags, const JValue* return_value) {
mirror::Class* c = m->GetDeclaringClass();
JDWP::JdwpLocation location;
@@ -2242,7 +2262,7 @@ void Dbg::PostLocationEvent(const mirror::ArtMethod* m, int dex_pc,
if (gRegistry->Contains(this_object)) {
this_id = gRegistry->Add(this_object);
}
- gJdwpState->PostLocationEvent(&location, this_id, event_flags);
+ gJdwpState->PostLocationEvent(&location, this_id, event_flags, return_value);
}
void Dbg::PostException(Thread* thread, const ThrowLocation& throw_location,
@@ -2356,7 +2376,7 @@ void Dbg::UpdateDebugger(Thread* thread, mirror::Object* this_object,
// If there's something interesting going on, see if it matches one
// of the debugger filters.
if (event_flags != 0) {
- Dbg::PostLocationEvent(m, dex_pc, this_object, event_flags);
+ Dbg::PostLocationEvent(m, dex_pc, this_object, event_flags, nullptr);
}
}
diff --git a/runtime/debugger.h b/runtime/debugger.h
index 8574a33..d193628 100644
--- a/runtime/debugger.h
+++ b/runtime/debugger.h
@@ -230,6 +230,9 @@ class Dbg {
static void OutputVariableTable(JDWP::RefTypeId ref_type_id, JDWP::MethodId id, bool with_generic,
JDWP::ExpandBuf* pReply)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ static void OutputMethodReturnValue(JDWP::MethodId method_id, const JValue* return_value,
+ JDWP::ExpandBuf* pReply)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static JDWP::JdwpError GetBytecodes(JDWP::RefTypeId class_id, JDWP::MethodId method_id,
std::vector<uint8_t>& bytecodes)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -254,6 +257,8 @@ class Dbg {
static std::string StringToUtf8(JDWP::ObjectId string_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ static void OutputJValue(JDWP::JdwpTag tag, const JValue* return_value, JDWP::ExpandBuf* pReply)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
/*
* Thread, ThreadGroup, Frame
@@ -327,7 +332,8 @@ class Dbg {
kMethodExit = 0x08,
};
static void PostLocationEvent(const mirror::ArtMethod* method, int pcOffset,
- mirror::Object* thisPtr, int eventFlags)
+ mirror::Object* thisPtr, int eventFlags,
+ const JValue* return_value)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static void PostException(Thread* thread, const ThrowLocation& throw_location,
mirror::ArtMethod* catch_method,
diff --git a/runtime/jdwp/jdwp.h b/runtime/jdwp/jdwp.h
index a1657d0..fd78bf2 100644
--- a/runtime/jdwp/jdwp.h
+++ b/runtime/jdwp/jdwp.h
@@ -31,6 +31,7 @@
struct iovec;
namespace art {
+ union JValue;
namespace mirror {
class ArtMethod;
} // namespace mirror
@@ -185,8 +186,11 @@ struct JdwpState {
* issuing a MethodEntry on a native method.
*
* "eventFlags" indicates the types of events that have occurred.
+ *
+ * "returnValue" is non-null for MethodExit events only.
*/
- bool PostLocationEvent(const JdwpLocation* pLoc, ObjectId thisPtr, int eventFlags)
+ bool PostLocationEvent(const JdwpLocation* pLoc, ObjectId thisPtr, int eventFlags,
+ const JValue* returnValue)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
/*
diff --git a/runtime/jdwp/jdwp_event.cc b/runtime/jdwp/jdwp_event.cc
index 345549d..61bd1ed 100644
--- a/runtime/jdwp/jdwp_event.cc
+++ b/runtime/jdwp/jdwp_event.cc
@@ -719,7 +719,8 @@ bool JdwpState::PostVMStart() {
* - Single-step to a line with a breakpoint. Should get a single
* event message with both events in it.
*/
-bool JdwpState::PostLocationEvent(const JdwpLocation* pLoc, ObjectId thisPtr, int eventFlags) {
+bool JdwpState::PostLocationEvent(const JdwpLocation* pLoc, ObjectId thisPtr, int eventFlags,
+ const JValue* returnValue) {
ModBasket basket;
basket.pLoc = pLoc;
basket.classId = pLoc->class_id;
@@ -771,9 +772,7 @@ bool JdwpState::PostLocationEvent(const JdwpLocation* pLoc, ObjectId thisPtr, in
}
if ((eventFlags & Dbg::kMethodExit) != 0) {
FindMatchingEvents(EK_METHOD_EXIT, &basket, match_list, &match_count);
-
- // TODO: match EK_METHOD_EXIT_WITH_RETURN_VALUE too; we need to include the 'value', though.
- // FindMatchingEvents(EK_METHOD_EXIT_WITH_RETURN_VALUE, &basket, match_list, &match_count);
+ FindMatchingEvents(EK_METHOD_EXIT_WITH_RETURN_VALUE, &basket, match_list, &match_count);
}
if (match_count != 0) {
VLOG(jdwp) << "EVENT: " << match_list[0]->eventKind << "(" << match_count << " total) "
@@ -792,6 +791,9 @@ bool JdwpState::PostLocationEvent(const JdwpLocation* pLoc, ObjectId thisPtr, in
expandBufAdd4BE(pReq, match_list[i]->requestId);
expandBufAdd8BE(pReq, basket.threadId);
expandBufAddLocation(pReq, *pLoc);
+ if (match_list[i]->eventKind == EK_METHOD_EXIT_WITH_RETURN_VALUE) {
+ Dbg::OutputMethodReturnValue(pLoc->method_id, returnValue, pReq);
+ }
}
}