diff options
Diffstat (limited to 'runtime/jdwp')
-rw-r--r-- | runtime/jdwp/jdwp.h | 11 | ||||
-rw-r--r-- | runtime/jdwp/jdwp_event.cc | 99 | ||||
-rw-r--r-- | runtime/jdwp/jdwp_handler.cc | 4 |
3 files changed, 95 insertions, 19 deletions
diff --git a/runtime/jdwp/jdwp.h b/runtime/jdwp/jdwp.h index 66ebb96..1477324 100644 --- a/runtime/jdwp/jdwp.h +++ b/runtime/jdwp/jdwp.h @@ -197,6 +197,17 @@ struct JdwpState { SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); /* + * A field of interest has been accessed or modified. This is used for field access and field + * modification events. + * + * "fieldValue" is non-null for field modification events only. + * "is_modification" is true for field modification, false for field access. + */ + bool PostFieldEvent(const JdwpLocation* pLoc, RefTypeId typeId, FieldId fieldId, + ObjectId thisPtr, const JValue* fieldValue, bool is_modification) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + /* * An exception has been thrown. * * Pass in a zeroed-out "*pCatchLoc" if the exception wasn't caught. diff --git a/runtime/jdwp/jdwp_event.cc b/runtime/jdwp/jdwp_event.cc index 9b3ea2e..9627802 100644 --- a/runtime/jdwp/jdwp_event.cc +++ b/runtime/jdwp/jdwp_event.cc @@ -121,26 +121,14 @@ struct ModBasket { /* nothing for StepOnly -- handled differently */ }; -/* - * Dump an event to the log file. - */ -static void dumpEvent(const JdwpEvent* pEvent) { - LOG(INFO) << StringPrintf("Event id=0x%4x %p (prev=%p next=%p):", pEvent->requestId, pEvent, pEvent->prev, pEvent->next); - LOG(INFO) << " kind=" << pEvent->eventKind << " susp=" << pEvent->suspend_policy << " modCount=" << pEvent->modCount; - - for (int i = 0; i < pEvent->modCount; i++) { - const JdwpEventMod* pMod = &pEvent->mods[i]; - LOG(INFO) << " " << pMod->modKind; - /* TODO - show details */ - } -} - static bool NeedsFullDeoptimization(JdwpEventKind eventKind) { switch (eventKind) { case EK_METHOD_ENTRY: case EK_METHOD_EXIT: case EK_METHOD_EXIT_WITH_RETURN_VALUE: case EK_SINGLE_STEP: + case EK_FIELD_ACCESS: + case EK_FIELD_MODIFICATION: return true; default: return false; @@ -177,9 +165,6 @@ JdwpError JdwpState::RegisterEvent(JdwpEvent* pEvent) { if (status != ERR_NONE) { return status; } - } else if (pMod->modKind == MK_FIELD_ONLY) { - /* should be for EK_FIELD_ACCESS or EK_FIELD_MODIFICATION */ - dumpEvent(pEvent); /* TODO - need for field watches */ } } if (NeedsFullDeoptimization(pEvent->eventKind)) { @@ -843,6 +828,86 @@ bool JdwpState::PostLocationEvent(const JdwpLocation* pLoc, ObjectId thisPtr, in return match_count != 0; } +bool JdwpState::PostFieldEvent(const JdwpLocation* pLoc, RefTypeId typeId, FieldId fieldId, + ObjectId thisPtr, const JValue* fieldValue, bool is_modification) { + ModBasket basket; + basket.pLoc = pLoc; + basket.classId = pLoc->class_id; + basket.thisPtr = thisPtr; + basket.threadId = Dbg::GetThreadSelfId(); + basket.className = Dbg::GetClassName(pLoc->class_id); + basket.field = fieldId; + + if (InvokeInProgress()) { + VLOG(jdwp) << "Not posting field event during invoke"; + return false; + } + + // Get field's reference type tag. + JDWP::JdwpTypeTag type_tag; + uint32_t class_status; // unused here. + JdwpError error = Dbg::GetClassInfo(typeId, &type_tag, &class_status, NULL); + if (error != ERR_NONE) { + return false; + } + + // Get instance type tag. + uint8_t tag; + error = Dbg::GetObjectTag(thisPtr, tag); + if (error != ERR_NONE) { + return false; + } + + int match_count = 0; + ExpandBuf* pReq = NULL; + JdwpSuspendPolicy suspend_policy = SP_NONE; + { + MutexLock mu(Thread::Current(), event_list_lock_); + JdwpEvent** match_list = AllocMatchList(event_list_size_); + + if (is_modification) { + FindMatchingEvents(EK_FIELD_MODIFICATION, &basket, match_list, &match_count); + } else { + FindMatchingEvents(EK_FIELD_ACCESS, &basket, match_list, &match_count); + } + if (match_count != 0) { + VLOG(jdwp) << "EVENT: " << match_list[0]->eventKind << "(" << match_count << " total) " + << basket.className << "." << Dbg::GetMethodName(pLoc->method_id) + << StringPrintf(" thread=%#" PRIx64 " dex_pc=%#" PRIx64 ")", + basket.threadId, pLoc->dex_pc); + + suspend_policy = scanSuspendPolicy(match_list, match_count); + VLOG(jdwp) << " suspend_policy=" << suspend_policy; + + pReq = eventPrep(); + expandBufAdd1(pReq, suspend_policy); + expandBufAdd4BE(pReq, match_count); + + for (int i = 0; i < match_count; i++) { + expandBufAdd1(pReq, match_list[i]->eventKind); + expandBufAdd4BE(pReq, match_list[i]->requestId); + expandBufAdd8BE(pReq, basket.threadId); + expandBufAddLocation(pReq, *pLoc); + expandBufAdd1(pReq, type_tag); + expandBufAddRefTypeId(pReq, typeId); + expandBufAddFieldId(pReq, fieldId); + expandBufAdd1(pReq, tag); + expandBufAddObjectId(pReq, thisPtr); + if (is_modification) { + Dbg::OutputFieldValue(fieldId, fieldValue, pReq); + } + } + } + + CleanupMatchList(match_list, match_count); + } + + Dbg::ManageDeoptimization(); + + SendRequestAndPossiblySuspend(pReq, suspend_policy, basket.threadId); + return match_count != 0; +} + /* * A thread is starting or stopping. * diff --git a/runtime/jdwp/jdwp_handler.cc b/runtime/jdwp/jdwp_handler.cc index c2a2b54..8f224d2 100644 --- a/runtime/jdwp/jdwp_handler.cc +++ b/runtime/jdwp/jdwp_handler.cc @@ -353,8 +353,8 @@ static JdwpError VM_DisposeObjects(JdwpState*, Request& request, ExpandBuf*) static JdwpError VM_Capabilities(JdwpState*, Request&, ExpandBuf* reply) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - expandBufAdd1(reply, false); // canWatchFieldModification - expandBufAdd1(reply, false); // canWatchFieldAccess + expandBufAdd1(reply, true); // canWatchFieldModification + expandBufAdd1(reply, true); // canWatchFieldAccess expandBufAdd1(reply, true); // canGetBytecodes expandBufAdd1(reply, true); // canGetSyntheticAttribute expandBufAdd1(reply, true); // canGetOwnedMonitorInfo |