diff options
author | Jeff Hao <jeffhao@google.com> | 2013-11-18 13:16:49 -0800 |
---|---|---|
committer | Jeff Hao <jeffhao@google.com> | 2013-11-19 11:16:44 -0800 |
commit | 579b02416e05e32e535126e1ed61613a2cdb030e (patch) | |
tree | 4431587a30c1d5a3e7c0435decbd7ac21104bf7a | |
parent | e4a50ee34695a9d90cf03fbb1e8afd1e434f6ee1 (diff) | |
download | art-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.cc | 68 | ||||
-rw-r--r-- | runtime/debugger.h | 8 | ||||
-rw-r--r-- | runtime/jdwp/jdwp.h | 6 | ||||
-rw-r--r-- | runtime/jdwp/jdwp_event.cc | 10 |
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); + } } } |