void JNICALL RequestManager::HandleSingleStep()

in modules/jpda/src/main/native/jdwp/common/agent/core/RequestManager.cpp [2010:2152]


void JNICALL RequestManager::HandleSingleStep(jvmtiEnv* jvmti, JNIEnv* jni,
        jthread thread, jmethodID method, jlocation location)
{
    JDWP_TRACE_ENTRY("HandleSingleStep(" << jvmti << ',' << jni << ',' << thread
        << ',' << method << ',' << location << ')');

    // if is popFrames process, invoke internal handler of step event
    if (GetThreadManager().IsPopFramesProcess(jni, thread)) {
        GetThreadManager().HandleInternalSingleStep(jni, thread, method, location);
        return;
    }

    // if in agent thread, ignore event
    if (GetThreadManager().IsAgentThread(jni, thread)) {
        return;
    }

    try {
        jvmtiError err;
        EventInfo eInfo;
        memset(&eInfo, 0, sizeof(eInfo));
        eInfo.kind = JDWP_EVENT_SINGLE_STEP;
        eInfo.thread = thread;
        eInfo.method = method;
        eInfo.location = location;
        CombinedEventsInfo::CombinedEventsKind combinedKind = CombinedEventsInfo::COMBINED_EVENT_SINGLE_STEP;

        // if this combined event was already prediced, ignore event
        if (GetRequestManager().IsPredictedCombinedEvent(jni, eInfo, combinedKind)) {
            return;
        }

        JVMTI_TRACE(err, GetJvmtiEnv()->GetMethodDeclaringClass(method,
            &eInfo.cls));
        if (err != JVMTI_ERROR_NONE) {
            throw AgentException(err);
        }

        JVMTI_TRACE(err, GetJvmtiEnv()->GetClassSignature(eInfo.cls,
            &eInfo.signature, 0));
        JvmtiAutoFree jafSignature(eInfo.signature);
        if (err != JVMTI_ERROR_NONE) {
            throw AgentException(err);
        }

#ifndef NDEBUG
        if (JDWP_TRACE_ENABLED(LOG_KIND_EVENT)) {
            char* name = 0;
            JVMTI_TRACE(err, GetJvmtiEnv()->GetMethodName(eInfo.method, &name, 0, 0));

            jvmtiThreadInfo info;
            JVMTI_TRACE(err, GetJvmtiEnv()->GetThreadInfo(thread, &info));

            JDWP_TRACE_EVENT("SINGLE_STEP event:" 
                << " class=" << JDWP_CHECK_NULL(eInfo.signature) 
                << " method=" << JDWP_CHECK_NULL(name) 
                << " loc=" << eInfo.location
                << " thread=" << JDWP_CHECK_NULL(info.name));
        }
#endif // NDEBUG

        // create new info about combined events for this location
        CombinedEventsInfo* combinedEvents = new CombinedEventsInfo();
        combinedEvents->Init(jni, eInfo);
        
        // generate SINGLE_STEP events according to existing requests
        jdwpSuspendPolicy sp = JDWP_SUSPEND_NONE;
        CombinedEventsInfo::CombinedEventsList* events = 
            &combinedEvents->m_combinedEventsLists[combinedKind];
        GetRequestManager().GenerateEvents(jni, eInfo, events->count, events->list, sp);
        JDWP_TRACE_EVENT("HandleSingleStep: SINGLE_STEP events:"
                << " count=" << events->count
                << ", suspendPolicy=" << sp 
                << ", location=" << combinedEvents->m_eInfo.location);

        // if no SINGLE_STEP events then return from callback
        if (events->count <= 0) {
            combinedEvents->Clean(jni);
            delete combinedEvents;
            combinedEvents = 0;
            return;
        }

        // check if extra combined events should be generated: BREAKPOINT, METHOD_EXIT
        {
            // check for BREAKPOINT events
            {
                combinedKind = CombinedEventsInfo::COMBINED_EVENT_BREAKPOINT;
                events = &combinedEvents->m_combinedEventsLists[combinedKind];
                eInfo.kind = JDWP_EVENT_BREAKPOINT;
                // generate extra events
                GetRequestManager().GenerateEvents(jni, eInfo, events->count, events->list, sp);
                JDWP_TRACE_EVENT("HandleSingleStep: BREAKPOINT events:" 
                    << " count=" << events->count
                    << ", suspendPolicy=" << sp 
                    << ", location=" << combinedEvents->m_eInfo.location);
                // check if corresponding callback should be ignored
                if (events->count > 0) {
                    events->ignored = 1;
                }
            }

            // check for METHOD_EXIT events
            if (ENABLE_COMBINED_METHOD_EXIT_EVENT) {
                if (GetRequestManager().IsMethodExitLocation(jni, eInfo)) {
                    combinedKind = CombinedEventsInfo::COMBINED_EVENT_METHOD_EXIT;
                    events = &combinedEvents->m_combinedEventsLists[combinedKind];
                    eInfo.kind = JDWP_EVENT_METHOD_EXIT;
                    // generate extra events
                    GetRequestManager().GenerateEvents(jni, eInfo, events->count, events->list, sp);
                    JDWP_TRACE_EVENT("HandleSingleStep: METHOD_EXIT events:" 
                        << " count=" << events->count
                        << ", suspendPolicy=" << sp 
                        << ", location=" << combinedEvents->m_eInfo.location);
                    // check if corresponding callback should be ignored
                    if (events->count > 0) {
                        events->ignored = 1;
                    }
                }
            }
        }

        // post all generated events
        EventComposer *ec = GetRequestManager().CombineEvents(jni, combinedEvents, sp);
        JDWP_TRACE_EVENT("HandleSingleStep: post set of " << combinedEvents->GetEventsCount() << " events");
        GetEventDispatcher().PostEventSet(jni, ec, JDWP_EVENT_SINGLE_STEP);

        // store info about combined events if other callbacks should be ignored
        if (combinedEvents->GetIgnoredCallbacksCount() > 0) {
            JDWP_TRACE_EVENT("HandleSingleStep: store combined events for new location:"
                        << " method=" << eInfo.method
                        << " loc=" << eInfo.location);
            GetRequestManager().AddCombinedEventsInfo(jni, combinedEvents);
        } else {
            combinedEvents->Clean(jni);
            delete combinedEvents;
            combinedEvents = 0;
        }

    } catch (AgentException& e) {
        JDWP_INFO("JDWP error in SINGLE_STEP: " << e.what() << " [" << e.ErrCode() << "]");
    }
}