1*e82f7db8SAndroid Build Coastguard Worker /*
2*e82f7db8SAndroid Build Coastguard Worker * Copyright (c) 1998, 2005, Oracle and/or its affiliates. All rights reserved.
3*e82f7db8SAndroid Build Coastguard Worker * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*e82f7db8SAndroid Build Coastguard Worker *
5*e82f7db8SAndroid Build Coastguard Worker * This code is free software; you can redistribute it and/or modify it
6*e82f7db8SAndroid Build Coastguard Worker * under the terms of the GNU General Public License version 2 only, as
7*e82f7db8SAndroid Build Coastguard Worker * published by the Free Software Foundation. Oracle designates this
8*e82f7db8SAndroid Build Coastguard Worker * particular file as subject to the "Classpath" exception as provided
9*e82f7db8SAndroid Build Coastguard Worker * by Oracle in the LICENSE file that accompanied this code.
10*e82f7db8SAndroid Build Coastguard Worker *
11*e82f7db8SAndroid Build Coastguard Worker * This code is distributed in the hope that it will be useful, but WITHOUT
12*e82f7db8SAndroid Build Coastguard Worker * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13*e82f7db8SAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14*e82f7db8SAndroid Build Coastguard Worker * version 2 for more details (a copy is included in the LICENSE file that
15*e82f7db8SAndroid Build Coastguard Worker * accompanied this code).
16*e82f7db8SAndroid Build Coastguard Worker *
17*e82f7db8SAndroid Build Coastguard Worker * You should have received a copy of the GNU General Public License version
18*e82f7db8SAndroid Build Coastguard Worker * 2 along with this work; if not, write to the Free Software Foundation,
19*e82f7db8SAndroid Build Coastguard Worker * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20*e82f7db8SAndroid Build Coastguard Worker *
21*e82f7db8SAndroid Build Coastguard Worker * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22*e82f7db8SAndroid Build Coastguard Worker * or visit www.oracle.com if you need additional information or have any
23*e82f7db8SAndroid Build Coastguard Worker * questions.
24*e82f7db8SAndroid Build Coastguard Worker */
25*e82f7db8SAndroid Build Coastguard Worker
26*e82f7db8SAndroid Build Coastguard Worker #include "util.h"
27*e82f7db8SAndroid Build Coastguard Worker #include "stepControl.h"
28*e82f7db8SAndroid Build Coastguard Worker #include "eventHandler.h"
29*e82f7db8SAndroid Build Coastguard Worker #include "eventHelper.h"
30*e82f7db8SAndroid Build Coastguard Worker #include "threadControl.h"
31*e82f7db8SAndroid Build Coastguard Worker #include "SDE.h"
32*e82f7db8SAndroid Build Coastguard Worker
33*e82f7db8SAndroid Build Coastguard Worker static jrawMonitorID stepLock;
34*e82f7db8SAndroid Build Coastguard Worker
35*e82f7db8SAndroid Build Coastguard Worker static jint
getFrameCount(jthread thread)36*e82f7db8SAndroid Build Coastguard Worker getFrameCount(jthread thread)
37*e82f7db8SAndroid Build Coastguard Worker {
38*e82f7db8SAndroid Build Coastguard Worker jint count = 0;
39*e82f7db8SAndroid Build Coastguard Worker jvmtiError error;
40*e82f7db8SAndroid Build Coastguard Worker
41*e82f7db8SAndroid Build Coastguard Worker error = JVMTI_FUNC_PTR(gdata->jvmti,GetFrameCount)
42*e82f7db8SAndroid Build Coastguard Worker (gdata->jvmti, thread, &count);
43*e82f7db8SAndroid Build Coastguard Worker if (error != JVMTI_ERROR_NONE) {
44*e82f7db8SAndroid Build Coastguard Worker EXIT_ERROR(error, "getting frame count");
45*e82f7db8SAndroid Build Coastguard Worker }
46*e82f7db8SAndroid Build Coastguard Worker return count;
47*e82f7db8SAndroid Build Coastguard Worker }
48*e82f7db8SAndroid Build Coastguard Worker
49*e82f7db8SAndroid Build Coastguard Worker /*
50*e82f7db8SAndroid Build Coastguard Worker * Most enabling/disabling of JVMTI events happens implicitly through
51*e82f7db8SAndroid Build Coastguard Worker * the inserting and freeing of handlers for those events. Stepping is
52*e82f7db8SAndroid Build Coastguard Worker * different because requested steps are usually not identical to JVMTI steps.
53*e82f7db8SAndroid Build Coastguard Worker * They usually require multiple events step, and otherwise, before they
54*e82f7db8SAndroid Build Coastguard Worker * complete. While a step request is pending, we may need to temporarily
55*e82f7db8SAndroid Build Coastguard Worker * disable and re-enable stepping, but we can't just remove the handlers
56*e82f7db8SAndroid Build Coastguard Worker * because that would break the application's ability to remove the
57*e82f7db8SAndroid Build Coastguard Worker * events. So, for step events only, we directly enable and disable stepping.
58*e82f7db8SAndroid Build Coastguard Worker * This is safe because there can only ever be one pending step request
59*e82f7db8SAndroid Build Coastguard Worker * per thread.
60*e82f7db8SAndroid Build Coastguard Worker */
61*e82f7db8SAndroid Build Coastguard Worker static void
enableStepping(jthread thread)62*e82f7db8SAndroid Build Coastguard Worker enableStepping(jthread thread)
63*e82f7db8SAndroid Build Coastguard Worker {
64*e82f7db8SAndroid Build Coastguard Worker jvmtiError error;
65*e82f7db8SAndroid Build Coastguard Worker
66*e82f7db8SAndroid Build Coastguard Worker LOG_STEP(("enableStepping: thread=%p", thread));
67*e82f7db8SAndroid Build Coastguard Worker
68*e82f7db8SAndroid Build Coastguard Worker error = threadControl_setEventMode(JVMTI_ENABLE, EI_SINGLE_STEP,
69*e82f7db8SAndroid Build Coastguard Worker thread);
70*e82f7db8SAndroid Build Coastguard Worker if (error != JVMTI_ERROR_NONE) {
71*e82f7db8SAndroid Build Coastguard Worker EXIT_ERROR(error, "enabling single step");
72*e82f7db8SAndroid Build Coastguard Worker }
73*e82f7db8SAndroid Build Coastguard Worker }
74*e82f7db8SAndroid Build Coastguard Worker
75*e82f7db8SAndroid Build Coastguard Worker static void
disableStepping(jthread thread)76*e82f7db8SAndroid Build Coastguard Worker disableStepping(jthread thread)
77*e82f7db8SAndroid Build Coastguard Worker {
78*e82f7db8SAndroid Build Coastguard Worker jvmtiError error;
79*e82f7db8SAndroid Build Coastguard Worker
80*e82f7db8SAndroid Build Coastguard Worker LOG_STEP(("disableStepping: thread=%p", thread));
81*e82f7db8SAndroid Build Coastguard Worker
82*e82f7db8SAndroid Build Coastguard Worker error = threadControl_setEventMode(JVMTI_DISABLE, EI_SINGLE_STEP,
83*e82f7db8SAndroid Build Coastguard Worker thread);
84*e82f7db8SAndroid Build Coastguard Worker if (error != JVMTI_ERROR_NONE) {
85*e82f7db8SAndroid Build Coastguard Worker EXIT_ERROR(error, "disabling single step");
86*e82f7db8SAndroid Build Coastguard Worker }
87*e82f7db8SAndroid Build Coastguard Worker }
88*e82f7db8SAndroid Build Coastguard Worker
89*e82f7db8SAndroid Build Coastguard Worker static jvmtiError
getFrameLocation(jthread thread,jclass * pclazz,jmethodID * pmethod,jlocation * plocation)90*e82f7db8SAndroid Build Coastguard Worker getFrameLocation(jthread thread,
91*e82f7db8SAndroid Build Coastguard Worker jclass *pclazz, jmethodID *pmethod, jlocation *plocation)
92*e82f7db8SAndroid Build Coastguard Worker {
93*e82f7db8SAndroid Build Coastguard Worker jvmtiError error;
94*e82f7db8SAndroid Build Coastguard Worker
95*e82f7db8SAndroid Build Coastguard Worker *pclazz = NULL;
96*e82f7db8SAndroid Build Coastguard Worker *pmethod = NULL;
97*e82f7db8SAndroid Build Coastguard Worker *plocation = -1;
98*e82f7db8SAndroid Build Coastguard Worker
99*e82f7db8SAndroid Build Coastguard Worker error = JVMTI_FUNC_PTR(gdata->jvmti,GetFrameLocation)
100*e82f7db8SAndroid Build Coastguard Worker (gdata->jvmti, thread, 0, pmethod, plocation);
101*e82f7db8SAndroid Build Coastguard Worker if (error == JVMTI_ERROR_NONE && *pmethod!=NULL ) {
102*e82f7db8SAndroid Build Coastguard Worker /* This also serves to verify that the methodID is valid */
103*e82f7db8SAndroid Build Coastguard Worker error = methodClass(*pmethod, pclazz);
104*e82f7db8SAndroid Build Coastguard Worker }
105*e82f7db8SAndroid Build Coastguard Worker return error;
106*e82f7db8SAndroid Build Coastguard Worker }
107*e82f7db8SAndroid Build Coastguard Worker
108*e82f7db8SAndroid Build Coastguard Worker static void
getLineNumberTable(jmethodID method,jint * pcount,jvmtiLineNumberEntry ** ptable)109*e82f7db8SAndroid Build Coastguard Worker getLineNumberTable(jmethodID method, jint *pcount,
110*e82f7db8SAndroid Build Coastguard Worker jvmtiLineNumberEntry **ptable)
111*e82f7db8SAndroid Build Coastguard Worker {
112*e82f7db8SAndroid Build Coastguard Worker jvmtiError error;
113*e82f7db8SAndroid Build Coastguard Worker
114*e82f7db8SAndroid Build Coastguard Worker *pcount = 0;
115*e82f7db8SAndroid Build Coastguard Worker *ptable = NULL;
116*e82f7db8SAndroid Build Coastguard Worker
117*e82f7db8SAndroid Build Coastguard Worker /* If the method is native or obsolete, don't even ask for the line table */
118*e82f7db8SAndroid Build Coastguard Worker if ( isMethodObsolete(method) || isMethodNative(method)) {
119*e82f7db8SAndroid Build Coastguard Worker return;
120*e82f7db8SAndroid Build Coastguard Worker }
121*e82f7db8SAndroid Build Coastguard Worker
122*e82f7db8SAndroid Build Coastguard Worker error = JVMTI_FUNC_PTR(gdata->jvmti,GetLineNumberTable)
123*e82f7db8SAndroid Build Coastguard Worker (gdata->jvmti, method, pcount, ptable);
124*e82f7db8SAndroid Build Coastguard Worker if (error != JVMTI_ERROR_NONE) {
125*e82f7db8SAndroid Build Coastguard Worker *pcount = 0;
126*e82f7db8SAndroid Build Coastguard Worker }
127*e82f7db8SAndroid Build Coastguard Worker }
128*e82f7db8SAndroid Build Coastguard Worker
129*e82f7db8SAndroid Build Coastguard Worker static jint
findLineNumber(jthread thread,jlocation location,jvmtiLineNumberEntry * lines,jint count)130*e82f7db8SAndroid Build Coastguard Worker findLineNumber(jthread thread, jlocation location,
131*e82f7db8SAndroid Build Coastguard Worker jvmtiLineNumberEntry *lines, jint count)
132*e82f7db8SAndroid Build Coastguard Worker {
133*e82f7db8SAndroid Build Coastguard Worker jint line = -1;
134*e82f7db8SAndroid Build Coastguard Worker
135*e82f7db8SAndroid Build Coastguard Worker if (location != -1) {
136*e82f7db8SAndroid Build Coastguard Worker if (count > 0) {
137*e82f7db8SAndroid Build Coastguard Worker jint i;
138*e82f7db8SAndroid Build Coastguard Worker /* any preface before first line is assigned to first line */
139*e82f7db8SAndroid Build Coastguard Worker for (i=1; i<count; i++) {
140*e82f7db8SAndroid Build Coastguard Worker if (location < lines[i].start_location) {
141*e82f7db8SAndroid Build Coastguard Worker break;
142*e82f7db8SAndroid Build Coastguard Worker }
143*e82f7db8SAndroid Build Coastguard Worker }
144*e82f7db8SAndroid Build Coastguard Worker line = lines[i-1].line_number;
145*e82f7db8SAndroid Build Coastguard Worker }
146*e82f7db8SAndroid Build Coastguard Worker }
147*e82f7db8SAndroid Build Coastguard Worker return line;
148*e82f7db8SAndroid Build Coastguard Worker }
149*e82f7db8SAndroid Build Coastguard Worker
150*e82f7db8SAndroid Build Coastguard Worker static jboolean
hasLineNumbers(jmethodID method)151*e82f7db8SAndroid Build Coastguard Worker hasLineNumbers(jmethodID method)
152*e82f7db8SAndroid Build Coastguard Worker {
153*e82f7db8SAndroid Build Coastguard Worker jint count;
154*e82f7db8SAndroid Build Coastguard Worker jvmtiLineNumberEntry *table;
155*e82f7db8SAndroid Build Coastguard Worker
156*e82f7db8SAndroid Build Coastguard Worker getLineNumberTable(method, &count, &table);
157*e82f7db8SAndroid Build Coastguard Worker if ( count == 0 ) {
158*e82f7db8SAndroid Build Coastguard Worker return JNI_FALSE;
159*e82f7db8SAndroid Build Coastguard Worker } else {
160*e82f7db8SAndroid Build Coastguard Worker jvmtiDeallocate(table);
161*e82f7db8SAndroid Build Coastguard Worker }
162*e82f7db8SAndroid Build Coastguard Worker return JNI_TRUE;
163*e82f7db8SAndroid Build Coastguard Worker }
164*e82f7db8SAndroid Build Coastguard Worker
165*e82f7db8SAndroid Build Coastguard Worker static jvmtiError
initState(JNIEnv * env,jthread thread,StepRequest * step)166*e82f7db8SAndroid Build Coastguard Worker initState(JNIEnv *env, jthread thread, StepRequest *step)
167*e82f7db8SAndroid Build Coastguard Worker {
168*e82f7db8SAndroid Build Coastguard Worker jvmtiError error;
169*e82f7db8SAndroid Build Coastguard Worker
170*e82f7db8SAndroid Build Coastguard Worker /*
171*e82f7db8SAndroid Build Coastguard Worker * Initial values that may be changed below
172*e82f7db8SAndroid Build Coastguard Worker */
173*e82f7db8SAndroid Build Coastguard Worker step->fromLine = -1;
174*e82f7db8SAndroid Build Coastguard Worker step->fromNative = JNI_FALSE;
175*e82f7db8SAndroid Build Coastguard Worker step->frameExited = JNI_FALSE;
176*e82f7db8SAndroid Build Coastguard Worker step->fromStackDepth = getFrameCount(thread);
177*e82f7db8SAndroid Build Coastguard Worker
178*e82f7db8SAndroid Build Coastguard Worker if (step->fromStackDepth <= 0) {
179*e82f7db8SAndroid Build Coastguard Worker /*
180*e82f7db8SAndroid Build Coastguard Worker * If there are no stack frames, treat the step as though
181*e82f7db8SAndroid Build Coastguard Worker * from a native frame. This is most likely to occur at the
182*e82f7db8SAndroid Build Coastguard Worker * beginning of a debug session, right after the VM_INIT event,
183*e82f7db8SAndroid Build Coastguard Worker * so we need to do something intelligent.
184*e82f7db8SAndroid Build Coastguard Worker */
185*e82f7db8SAndroid Build Coastguard Worker step->fromNative = JNI_TRUE;
186*e82f7db8SAndroid Build Coastguard Worker return JVMTI_ERROR_NONE;
187*e82f7db8SAndroid Build Coastguard Worker }
188*e82f7db8SAndroid Build Coastguard Worker
189*e82f7db8SAndroid Build Coastguard Worker /*
190*e82f7db8SAndroid Build Coastguard Worker * Try to get a notification on frame pop. If we're in an opaque frame
191*e82f7db8SAndroid Build Coastguard Worker * we won't be able to, but we can use other methods to detect that
192*e82f7db8SAndroid Build Coastguard Worker * a native frame has exited.
193*e82f7db8SAndroid Build Coastguard Worker *
194*e82f7db8SAndroid Build Coastguard Worker * TO DO: explain the need for this notification.
195*e82f7db8SAndroid Build Coastguard Worker */
196*e82f7db8SAndroid Build Coastguard Worker error = JVMTI_FUNC_PTR(gdata->jvmti,NotifyFramePop)
197*e82f7db8SAndroid Build Coastguard Worker (gdata->jvmti, thread, 0);
198*e82f7db8SAndroid Build Coastguard Worker if (error == JVMTI_ERROR_OPAQUE_FRAME) {
199*e82f7db8SAndroid Build Coastguard Worker step->fromNative = JNI_TRUE;
200*e82f7db8SAndroid Build Coastguard Worker error = JVMTI_ERROR_NONE;
201*e82f7db8SAndroid Build Coastguard Worker /* continue without error */
202*e82f7db8SAndroid Build Coastguard Worker } else if (error == JVMTI_ERROR_DUPLICATE) {
203*e82f7db8SAndroid Build Coastguard Worker error = JVMTI_ERROR_NONE;
204*e82f7db8SAndroid Build Coastguard Worker /* Already being notified, continue without error */
205*e82f7db8SAndroid Build Coastguard Worker } else if (error != JVMTI_ERROR_NONE) {
206*e82f7db8SAndroid Build Coastguard Worker return error;
207*e82f7db8SAndroid Build Coastguard Worker }
208*e82f7db8SAndroid Build Coastguard Worker
209*e82f7db8SAndroid Build Coastguard Worker LOG_STEP(("initState(): frame=%d", step->fromStackDepth));
210*e82f7db8SAndroid Build Coastguard Worker
211*e82f7db8SAndroid Build Coastguard Worker /*
212*e82f7db8SAndroid Build Coastguard Worker * Note: we can't undo the frame pop notify, so
213*e82f7db8SAndroid Build Coastguard Worker * we'll just have to let the handler ignore it if
214*e82f7db8SAndroid Build Coastguard Worker * there are any errors below.
215*e82f7db8SAndroid Build Coastguard Worker */
216*e82f7db8SAndroid Build Coastguard Worker
217*e82f7db8SAndroid Build Coastguard Worker if (step->granularity == JDWP_STEP_SIZE(LINE) ) {
218*e82f7db8SAndroid Build Coastguard Worker
219*e82f7db8SAndroid Build Coastguard Worker LOG_STEP(("initState(): Begin line step"));
220*e82f7db8SAndroid Build Coastguard Worker
221*e82f7db8SAndroid Build Coastguard Worker WITH_LOCAL_REFS(env, 1) {
222*e82f7db8SAndroid Build Coastguard Worker
223*e82f7db8SAndroid Build Coastguard Worker jclass clazz;
224*e82f7db8SAndroid Build Coastguard Worker jmethodID method;
225*e82f7db8SAndroid Build Coastguard Worker jlocation location;
226*e82f7db8SAndroid Build Coastguard Worker
227*e82f7db8SAndroid Build Coastguard Worker error = getFrameLocation(thread, &clazz, &method, &location);
228*e82f7db8SAndroid Build Coastguard Worker if (error == JVMTI_ERROR_NONE) {
229*e82f7db8SAndroid Build Coastguard Worker /* Clear out previous line table only if we changed methods */
230*e82f7db8SAndroid Build Coastguard Worker if ( method != step->method ) {
231*e82f7db8SAndroid Build Coastguard Worker step->lineEntryCount = 0;
232*e82f7db8SAndroid Build Coastguard Worker if (step->lineEntries != NULL) {
233*e82f7db8SAndroid Build Coastguard Worker jvmtiDeallocate(step->lineEntries);
234*e82f7db8SAndroid Build Coastguard Worker step->lineEntries = NULL;
235*e82f7db8SAndroid Build Coastguard Worker }
236*e82f7db8SAndroid Build Coastguard Worker step->method = method;
237*e82f7db8SAndroid Build Coastguard Worker getLineNumberTable(step->method,
238*e82f7db8SAndroid Build Coastguard Worker &step->lineEntryCount, &step->lineEntries);
239*e82f7db8SAndroid Build Coastguard Worker if (step->lineEntryCount > 0) {
240*e82f7db8SAndroid Build Coastguard Worker convertLineNumberTable(env, clazz,
241*e82f7db8SAndroid Build Coastguard Worker &step->lineEntryCount, &step->lineEntries);
242*e82f7db8SAndroid Build Coastguard Worker }
243*e82f7db8SAndroid Build Coastguard Worker }
244*e82f7db8SAndroid Build Coastguard Worker step->fromLine = findLineNumber(thread, location,
245*e82f7db8SAndroid Build Coastguard Worker step->lineEntries, step->lineEntryCount);
246*e82f7db8SAndroid Build Coastguard Worker }
247*e82f7db8SAndroid Build Coastguard Worker
248*e82f7db8SAndroid Build Coastguard Worker } END_WITH_LOCAL_REFS(env);
249*e82f7db8SAndroid Build Coastguard Worker
250*e82f7db8SAndroid Build Coastguard Worker }
251*e82f7db8SAndroid Build Coastguard Worker
252*e82f7db8SAndroid Build Coastguard Worker return error;
253*e82f7db8SAndroid Build Coastguard Worker }
254*e82f7db8SAndroid Build Coastguard Worker
255*e82f7db8SAndroid Build Coastguard Worker /*
256*e82f7db8SAndroid Build Coastguard Worker * TO DO: The step handlers (handleFrameChange and handleStep can
257*e82f7db8SAndroid Build Coastguard Worker * be broken down and made simpler now that we can install and de-install event
258*e82f7db8SAndroid Build Coastguard Worker * handlers.
259*e82f7db8SAndroid Build Coastguard Worker */
260*e82f7db8SAndroid Build Coastguard Worker static void
handleFramePopEvent(JNIEnv * env,EventInfo * evinfo,HandlerNode * node,struct bag * eventBag)261*e82f7db8SAndroid Build Coastguard Worker handleFramePopEvent(JNIEnv *env, EventInfo *evinfo,
262*e82f7db8SAndroid Build Coastguard Worker HandlerNode *node,
263*e82f7db8SAndroid Build Coastguard Worker struct bag *eventBag)
264*e82f7db8SAndroid Build Coastguard Worker {
265*e82f7db8SAndroid Build Coastguard Worker StepRequest *step;
266*e82f7db8SAndroid Build Coastguard Worker jthread thread = evinfo->thread;
267*e82f7db8SAndroid Build Coastguard Worker
268*e82f7db8SAndroid Build Coastguard Worker stepControl_lock();
269*e82f7db8SAndroid Build Coastguard Worker
270*e82f7db8SAndroid Build Coastguard Worker step = threadControl_getStepRequest(thread);
271*e82f7db8SAndroid Build Coastguard Worker if (step == NULL) {
272*e82f7db8SAndroid Build Coastguard Worker EXIT_ERROR(AGENT_ERROR_INVALID_THREAD, "getting step request");
273*e82f7db8SAndroid Build Coastguard Worker }
274*e82f7db8SAndroid Build Coastguard Worker
275*e82f7db8SAndroid Build Coastguard Worker if (step->pending) {
276*e82f7db8SAndroid Build Coastguard Worker /*
277*e82f7db8SAndroid Build Coastguard Worker * Note: current depth is reported as *before* the pending frame
278*e82f7db8SAndroid Build Coastguard Worker * pop.
279*e82f7db8SAndroid Build Coastguard Worker */
280*e82f7db8SAndroid Build Coastguard Worker jint currentDepth;
281*e82f7db8SAndroid Build Coastguard Worker jint fromDepth;
282*e82f7db8SAndroid Build Coastguard Worker jint afterPopDepth;
283*e82f7db8SAndroid Build Coastguard Worker
284*e82f7db8SAndroid Build Coastguard Worker currentDepth = getFrameCount(thread);
285*e82f7db8SAndroid Build Coastguard Worker fromDepth = step->fromStackDepth;
286*e82f7db8SAndroid Build Coastguard Worker afterPopDepth = currentDepth-1;
287*e82f7db8SAndroid Build Coastguard Worker
288*e82f7db8SAndroid Build Coastguard Worker LOG_STEP(("handleFramePopEvent: BEGIN fromDepth=%d, currentDepth=%d",
289*e82f7db8SAndroid Build Coastguard Worker fromDepth, currentDepth));
290*e82f7db8SAndroid Build Coastguard Worker
291*e82f7db8SAndroid Build Coastguard Worker /*
292*e82f7db8SAndroid Build Coastguard Worker * If we are exiting the original stepping frame, record that
293*e82f7db8SAndroid Build Coastguard Worker * fact here. Once the next step event comes in, we can safely
294*e82f7db8SAndroid Build Coastguard Worker * stop stepping there.
295*e82f7db8SAndroid Build Coastguard Worker */
296*e82f7db8SAndroid Build Coastguard Worker if (fromDepth > afterPopDepth ) {
297*e82f7db8SAndroid Build Coastguard Worker step->frameExited = JNI_TRUE;
298*e82f7db8SAndroid Build Coastguard Worker }
299*e82f7db8SAndroid Build Coastguard Worker
300*e82f7db8SAndroid Build Coastguard Worker if (step->depth == JDWP_STEP_DEPTH(OVER)) {
301*e82f7db8SAndroid Build Coastguard Worker /*
302*e82f7db8SAndroid Build Coastguard Worker * Either
303*e82f7db8SAndroid Build Coastguard Worker * 1) the original stepping frame is about to be popped
304*e82f7db8SAndroid Build Coastguard Worker * [fromDepth == currentDepth]. Re-enable stepping to
305*e82f7db8SAndroid Build Coastguard Worker * reach a point where we can stop.
306*e82f7db8SAndroid Build Coastguard Worker * 2) a method called from the stepping frame has returned
307*e82f7db8SAndroid Build Coastguard Worker * (during which we had stepping disabled)
308*e82f7db8SAndroid Build Coastguard Worker * [fromDepth == currentDepth - 1]. Re-enable stepping
309*e82f7db8SAndroid Build Coastguard Worker * so that we can continue instructions steps in the
310*e82f7db8SAndroid Build Coastguard Worker * original stepping frame.
311*e82f7db8SAndroid Build Coastguard Worker * 3) a method further down the call chain has notified
312*e82f7db8SAndroid Build Coastguard Worker * of a frame pop [fromDepth < currentDepth - 1]. This
313*e82f7db8SAndroid Build Coastguard Worker * *might* represent case (2) above if the stepping frame
314*e82f7db8SAndroid Build Coastguard Worker * was calling a native method which in turn called a
315*e82f7db8SAndroid Build Coastguard Worker * java method. If so, we must enable stepping to
316*e82f7db8SAndroid Build Coastguard Worker * ensure that we get control back after the intervening
317*e82f7db8SAndroid Build Coastguard Worker * native frame is popped (you can't get frame pop
318*e82f7db8SAndroid Build Coastguard Worker * notifications on native frames). If the native caller
319*e82f7db8SAndroid Build Coastguard Worker * calls another Java method before returning,
320*e82f7db8SAndroid Build Coastguard Worker * stepping will be diabled again and another frame pop
321*e82f7db8SAndroid Build Coastguard Worker * will be awaited.
322*e82f7db8SAndroid Build Coastguard Worker *
323*e82f7db8SAndroid Build Coastguard Worker * If it turns out that this is not case (2) with native
324*e82f7db8SAndroid Build Coastguard Worker * methods, then the enabled stepping is benign and
325*e82f7db8SAndroid Build Coastguard Worker * will be disabled again on the next step event.
326*e82f7db8SAndroid Build Coastguard Worker *
327*e82f7db8SAndroid Build Coastguard Worker * Note that the condition not covered above,
328*e82f7db8SAndroid Build Coastguard Worker * [fromDepth > currentDepth] shouldn't happen since it means
329*e82f7db8SAndroid Build Coastguard Worker * that too many frames have been popped. For robustness,
330*e82f7db8SAndroid Build Coastguard Worker * we enable stepping in that case too, so that the errant
331*e82f7db8SAndroid Build Coastguard Worker * step-over can be stopped.
332*e82f7db8SAndroid Build Coastguard Worker *
333*e82f7db8SAndroid Build Coastguard Worker */
334*e82f7db8SAndroid Build Coastguard Worker LOG_STEP(("handleFramePopEvent: starting singlestep, depth==OVER"));
335*e82f7db8SAndroid Build Coastguard Worker enableStepping(thread);
336*e82f7db8SAndroid Build Coastguard Worker } else if (step->depth == JDWP_STEP_DEPTH(OUT) &&
337*e82f7db8SAndroid Build Coastguard Worker fromDepth > afterPopDepth) {
338*e82f7db8SAndroid Build Coastguard Worker /*
339*e82f7db8SAndroid Build Coastguard Worker * The original stepping frame is about to be popped. Step
340*e82f7db8SAndroid Build Coastguard Worker * until we reach the next safe place to stop.
341*e82f7db8SAndroid Build Coastguard Worker */
342*e82f7db8SAndroid Build Coastguard Worker LOG_STEP(("handleFramePopEvent: starting singlestep, depth==OUT && fromDepth > afterPopDepth (%d>%d)",fromDepth, afterPopDepth));
343*e82f7db8SAndroid Build Coastguard Worker enableStepping(thread);
344*e82f7db8SAndroid Build Coastguard Worker } else if (step->methodEnterHandlerNode != NULL &&
345*e82f7db8SAndroid Build Coastguard Worker fromDepth >= afterPopDepth) {
346*e82f7db8SAndroid Build Coastguard Worker /*
347*e82f7db8SAndroid Build Coastguard Worker * We installed a method entry event handler as part of a
348*e82f7db8SAndroid Build Coastguard Worker * step into operation. We've popped back to the original
349*e82f7db8SAndroid Build Coastguard Worker * stepping frame without finding a place to stop.
350*e82f7db8SAndroid Build Coastguard Worker * Resume stepping in the original frame.
351*e82f7db8SAndroid Build Coastguard Worker */
352*e82f7db8SAndroid Build Coastguard Worker LOG_STEP(("handleFramePopEvent: starting singlestep, have methodEnter handler && depth==OUT && fromDepth >= afterPopDepth (%d>%d)",fromDepth, afterPopDepth));
353*e82f7db8SAndroid Build Coastguard Worker enableStepping(thread);
354*e82f7db8SAndroid Build Coastguard Worker (void)eventHandler_free(step->methodEnterHandlerNode);
355*e82f7db8SAndroid Build Coastguard Worker step->methodEnterHandlerNode = NULL;
356*e82f7db8SAndroid Build Coastguard Worker }
357*e82f7db8SAndroid Build Coastguard Worker LOG_STEP(("handleFramePopEvent: finished"));
358*e82f7db8SAndroid Build Coastguard Worker }
359*e82f7db8SAndroid Build Coastguard Worker
360*e82f7db8SAndroid Build Coastguard Worker stepControl_unlock();
361*e82f7db8SAndroid Build Coastguard Worker }
362*e82f7db8SAndroid Build Coastguard Worker
363*e82f7db8SAndroid Build Coastguard Worker static void
handleExceptionCatchEvent(JNIEnv * env,EventInfo * evinfo,HandlerNode * node,struct bag * eventBag)364*e82f7db8SAndroid Build Coastguard Worker handleExceptionCatchEvent(JNIEnv *env, EventInfo *evinfo,
365*e82f7db8SAndroid Build Coastguard Worker HandlerNode *node,
366*e82f7db8SAndroid Build Coastguard Worker struct bag *eventBag)
367*e82f7db8SAndroid Build Coastguard Worker {
368*e82f7db8SAndroid Build Coastguard Worker StepRequest *step;
369*e82f7db8SAndroid Build Coastguard Worker jthread thread = evinfo->thread;
370*e82f7db8SAndroid Build Coastguard Worker
371*e82f7db8SAndroid Build Coastguard Worker stepControl_lock();
372*e82f7db8SAndroid Build Coastguard Worker
373*e82f7db8SAndroid Build Coastguard Worker step = threadControl_getStepRequest(thread);
374*e82f7db8SAndroid Build Coastguard Worker if (step == NULL) {
375*e82f7db8SAndroid Build Coastguard Worker EXIT_ERROR(AGENT_ERROR_INVALID_THREAD, "getting step request");
376*e82f7db8SAndroid Build Coastguard Worker }
377*e82f7db8SAndroid Build Coastguard Worker
378*e82f7db8SAndroid Build Coastguard Worker if (step->pending) {
379*e82f7db8SAndroid Build Coastguard Worker /*
380*e82f7db8SAndroid Build Coastguard Worker * Determine where we are on the call stack relative to where
381*e82f7db8SAndroid Build Coastguard Worker * we started.
382*e82f7db8SAndroid Build Coastguard Worker */
383*e82f7db8SAndroid Build Coastguard Worker jint currentDepth = getFrameCount(thread);
384*e82f7db8SAndroid Build Coastguard Worker jint fromDepth = step->fromStackDepth;
385*e82f7db8SAndroid Build Coastguard Worker
386*e82f7db8SAndroid Build Coastguard Worker LOG_STEP(("handleExceptionCatchEvent: fromDepth=%d, currentDepth=%d",
387*e82f7db8SAndroid Build Coastguard Worker fromDepth, currentDepth));
388*e82f7db8SAndroid Build Coastguard Worker
389*e82f7db8SAndroid Build Coastguard Worker /*
390*e82f7db8SAndroid Build Coastguard Worker * If we are exiting the original stepping frame, record that
391*e82f7db8SAndroid Build Coastguard Worker * fact here. Once the next step event comes in, we can safely
392*e82f7db8SAndroid Build Coastguard Worker * stop stepping there.
393*e82f7db8SAndroid Build Coastguard Worker */
394*e82f7db8SAndroid Build Coastguard Worker if (fromDepth > currentDepth) {
395*e82f7db8SAndroid Build Coastguard Worker step->frameExited = JNI_TRUE;
396*e82f7db8SAndroid Build Coastguard Worker }
397*e82f7db8SAndroid Build Coastguard Worker
398*e82f7db8SAndroid Build Coastguard Worker if (step->depth == JDWP_STEP_DEPTH(OVER) &&
399*e82f7db8SAndroid Build Coastguard Worker fromDepth >= currentDepth) {
400*e82f7db8SAndroid Build Coastguard Worker /*
401*e82f7db8SAndroid Build Coastguard Worker * Either the original stepping frame is done,
402*e82f7db8SAndroid Build Coastguard Worker * or a called method has returned (during which we had stepping
403*e82f7db8SAndroid Build Coastguard Worker * disabled). In either case we must resume stepping.
404*e82f7db8SAndroid Build Coastguard Worker */
405*e82f7db8SAndroid Build Coastguard Worker enableStepping(thread);
406*e82f7db8SAndroid Build Coastguard Worker } else if (step->depth == JDWP_STEP_DEPTH(OUT) &&
407*e82f7db8SAndroid Build Coastguard Worker fromDepth > currentDepth) {
408*e82f7db8SAndroid Build Coastguard Worker /*
409*e82f7db8SAndroid Build Coastguard Worker * The original stepping frame is done. Step
410*e82f7db8SAndroid Build Coastguard Worker * until we reach the next safe place to stop.
411*e82f7db8SAndroid Build Coastguard Worker */
412*e82f7db8SAndroid Build Coastguard Worker enableStepping(thread);
413*e82f7db8SAndroid Build Coastguard Worker } else if (step->methodEnterHandlerNode != NULL &&
414*e82f7db8SAndroid Build Coastguard Worker fromDepth >= currentDepth) {
415*e82f7db8SAndroid Build Coastguard Worker /*
416*e82f7db8SAndroid Build Coastguard Worker * We installed a method entry event handler as part of a
417*e82f7db8SAndroid Build Coastguard Worker * step into operation. We've popped back to the original
418*e82f7db8SAndroid Build Coastguard Worker * stepping frame or higher without finding a place to stop.
419*e82f7db8SAndroid Build Coastguard Worker * Resume stepping in the original frame.
420*e82f7db8SAndroid Build Coastguard Worker */
421*e82f7db8SAndroid Build Coastguard Worker enableStepping(thread);
422*e82f7db8SAndroid Build Coastguard Worker (void)eventHandler_free(step->methodEnterHandlerNode);
423*e82f7db8SAndroid Build Coastguard Worker step->methodEnterHandlerNode = NULL;
424*e82f7db8SAndroid Build Coastguard Worker }
425*e82f7db8SAndroid Build Coastguard Worker }
426*e82f7db8SAndroid Build Coastguard Worker
427*e82f7db8SAndroid Build Coastguard Worker stepControl_unlock();
428*e82f7db8SAndroid Build Coastguard Worker }
429*e82f7db8SAndroid Build Coastguard Worker
430*e82f7db8SAndroid Build Coastguard Worker static void
handleMethodEnterEvent(JNIEnv * env,EventInfo * evinfo,HandlerNode * node,struct bag * eventBag)431*e82f7db8SAndroid Build Coastguard Worker handleMethodEnterEvent(JNIEnv *env, EventInfo *evinfo,
432*e82f7db8SAndroid Build Coastguard Worker HandlerNode *node,
433*e82f7db8SAndroid Build Coastguard Worker struct bag *eventBag)
434*e82f7db8SAndroid Build Coastguard Worker {
435*e82f7db8SAndroid Build Coastguard Worker StepRequest *step;
436*e82f7db8SAndroid Build Coastguard Worker jthread thread;
437*e82f7db8SAndroid Build Coastguard Worker
438*e82f7db8SAndroid Build Coastguard Worker thread = evinfo->thread;
439*e82f7db8SAndroid Build Coastguard Worker
440*e82f7db8SAndroid Build Coastguard Worker stepControl_lock();
441*e82f7db8SAndroid Build Coastguard Worker
442*e82f7db8SAndroid Build Coastguard Worker step = threadControl_getStepRequest(thread);
443*e82f7db8SAndroid Build Coastguard Worker if (step == NULL) {
444*e82f7db8SAndroid Build Coastguard Worker EXIT_ERROR(AGENT_ERROR_INVALID_THREAD, "getting step request");
445*e82f7db8SAndroid Build Coastguard Worker }
446*e82f7db8SAndroid Build Coastguard Worker
447*e82f7db8SAndroid Build Coastguard Worker if (step->pending) {
448*e82f7db8SAndroid Build Coastguard Worker jclass clazz;
449*e82f7db8SAndroid Build Coastguard Worker jmethodID method;
450*e82f7db8SAndroid Build Coastguard Worker char *classname;
451*e82f7db8SAndroid Build Coastguard Worker
452*e82f7db8SAndroid Build Coastguard Worker LOG_STEP(("handleMethodEnterEvent: thread=%p", thread));
453*e82f7db8SAndroid Build Coastguard Worker
454*e82f7db8SAndroid Build Coastguard Worker clazz = evinfo->clazz;
455*e82f7db8SAndroid Build Coastguard Worker method = evinfo->method;
456*e82f7db8SAndroid Build Coastguard Worker classname = getClassname(clazz);
457*e82f7db8SAndroid Build Coastguard Worker
458*e82f7db8SAndroid Build Coastguard Worker /*
459*e82f7db8SAndroid Build Coastguard Worker * This handler is relevant only to step into
460*e82f7db8SAndroid Build Coastguard Worker */
461*e82f7db8SAndroid Build Coastguard Worker JDI_ASSERT(step->depth == JDWP_STEP_DEPTH(INTO));
462*e82f7db8SAndroid Build Coastguard Worker
463*e82f7db8SAndroid Build Coastguard Worker if ( (!eventFilter_predictFiltering(step->stepHandlerNode,
464*e82f7db8SAndroid Build Coastguard Worker clazz, classname))
465*e82f7db8SAndroid Build Coastguard Worker && ( step->granularity != JDWP_STEP_SIZE(LINE)
466*e82f7db8SAndroid Build Coastguard Worker || hasLineNumbers(method) ) ) {
467*e82f7db8SAndroid Build Coastguard Worker /*
468*e82f7db8SAndroid Build Coastguard Worker * We've found a suitable method in which to stop. Step
469*e82f7db8SAndroid Build Coastguard Worker * until we reach the next safe location to complete the step->,
470*e82f7db8SAndroid Build Coastguard Worker * and we can get rid of the method entry handler.
471*e82f7db8SAndroid Build Coastguard Worker */
472*e82f7db8SAndroid Build Coastguard Worker enableStepping(thread);
473*e82f7db8SAndroid Build Coastguard Worker if ( step->methodEnterHandlerNode != NULL ) {
474*e82f7db8SAndroid Build Coastguard Worker (void)eventHandler_free(step->methodEnterHandlerNode);
475*e82f7db8SAndroid Build Coastguard Worker step->methodEnterHandlerNode = NULL;
476*e82f7db8SAndroid Build Coastguard Worker }
477*e82f7db8SAndroid Build Coastguard Worker }
478*e82f7db8SAndroid Build Coastguard Worker jvmtiDeallocate(classname);
479*e82f7db8SAndroid Build Coastguard Worker classname = NULL;
480*e82f7db8SAndroid Build Coastguard Worker }
481*e82f7db8SAndroid Build Coastguard Worker
482*e82f7db8SAndroid Build Coastguard Worker stepControl_unlock();
483*e82f7db8SAndroid Build Coastguard Worker }
484*e82f7db8SAndroid Build Coastguard Worker
485*e82f7db8SAndroid Build Coastguard Worker static void
completeStep(JNIEnv * env,jthread thread,StepRequest * step)486*e82f7db8SAndroid Build Coastguard Worker completeStep(JNIEnv *env, jthread thread, StepRequest *step)
487*e82f7db8SAndroid Build Coastguard Worker {
488*e82f7db8SAndroid Build Coastguard Worker jvmtiError error;
489*e82f7db8SAndroid Build Coastguard Worker
490*e82f7db8SAndroid Build Coastguard Worker /*
491*e82f7db8SAndroid Build Coastguard Worker * We've completed a step; reset state for the next one, if any
492*e82f7db8SAndroid Build Coastguard Worker */
493*e82f7db8SAndroid Build Coastguard Worker
494*e82f7db8SAndroid Build Coastguard Worker LOG_STEP(("completeStep: thread=%p", thread));
495*e82f7db8SAndroid Build Coastguard Worker
496*e82f7db8SAndroid Build Coastguard Worker if (step->methodEnterHandlerNode != NULL) {
497*e82f7db8SAndroid Build Coastguard Worker (void)eventHandler_free(step->methodEnterHandlerNode);
498*e82f7db8SAndroid Build Coastguard Worker step->methodEnterHandlerNode = NULL;
499*e82f7db8SAndroid Build Coastguard Worker }
500*e82f7db8SAndroid Build Coastguard Worker
501*e82f7db8SAndroid Build Coastguard Worker error = initState(env, thread, step);
502*e82f7db8SAndroid Build Coastguard Worker if (error != JVMTI_ERROR_NONE) {
503*e82f7db8SAndroid Build Coastguard Worker /*
504*e82f7db8SAndroid Build Coastguard Worker * None of the initState errors should happen after one step
505*e82f7db8SAndroid Build Coastguard Worker * has successfully completed.
506*e82f7db8SAndroid Build Coastguard Worker */
507*e82f7db8SAndroid Build Coastguard Worker EXIT_ERROR(error, "initializing step state");
508*e82f7db8SAndroid Build Coastguard Worker }
509*e82f7db8SAndroid Build Coastguard Worker }
510*e82f7db8SAndroid Build Coastguard Worker
511*e82f7db8SAndroid Build Coastguard Worker jboolean
stepControl_handleStep(JNIEnv * env,jthread thread,jclass clazz,jmethodID method)512*e82f7db8SAndroid Build Coastguard Worker stepControl_handleStep(JNIEnv *env, jthread thread,
513*e82f7db8SAndroid Build Coastguard Worker jclass clazz, jmethodID method)
514*e82f7db8SAndroid Build Coastguard Worker {
515*e82f7db8SAndroid Build Coastguard Worker jboolean completed = JNI_FALSE;
516*e82f7db8SAndroid Build Coastguard Worker StepRequest *step;
517*e82f7db8SAndroid Build Coastguard Worker jint currentDepth;
518*e82f7db8SAndroid Build Coastguard Worker jint fromDepth;
519*e82f7db8SAndroid Build Coastguard Worker jvmtiError error;
520*e82f7db8SAndroid Build Coastguard Worker char *classname;
521*e82f7db8SAndroid Build Coastguard Worker
522*e82f7db8SAndroid Build Coastguard Worker classname = NULL;
523*e82f7db8SAndroid Build Coastguard Worker stepControl_lock();
524*e82f7db8SAndroid Build Coastguard Worker
525*e82f7db8SAndroid Build Coastguard Worker step = threadControl_getStepRequest(thread);
526*e82f7db8SAndroid Build Coastguard Worker if (step == NULL) {
527*e82f7db8SAndroid Build Coastguard Worker EXIT_ERROR(AGENT_ERROR_INVALID_THREAD, "getting step request");
528*e82f7db8SAndroid Build Coastguard Worker }
529*e82f7db8SAndroid Build Coastguard Worker
530*e82f7db8SAndroid Build Coastguard Worker /*
531*e82f7db8SAndroid Build Coastguard Worker * If no step is currently pending, ignore the event
532*e82f7db8SAndroid Build Coastguard Worker */
533*e82f7db8SAndroid Build Coastguard Worker if (!step->pending) {
534*e82f7db8SAndroid Build Coastguard Worker goto done;
535*e82f7db8SAndroid Build Coastguard Worker }
536*e82f7db8SAndroid Build Coastguard Worker
537*e82f7db8SAndroid Build Coastguard Worker LOG_STEP(("stepControl_handleStep: thread=%p", thread));
538*e82f7db8SAndroid Build Coastguard Worker
539*e82f7db8SAndroid Build Coastguard Worker /*
540*e82f7db8SAndroid Build Coastguard Worker * We never filter step into instruction. It's always over on the
541*e82f7db8SAndroid Build Coastguard Worker * first step event.
542*e82f7db8SAndroid Build Coastguard Worker */
543*e82f7db8SAndroid Build Coastguard Worker if (step->depth == JDWP_STEP_DEPTH(INTO) &&
544*e82f7db8SAndroid Build Coastguard Worker step->granularity == JDWP_STEP_SIZE(MIN)) {
545*e82f7db8SAndroid Build Coastguard Worker completed = JNI_TRUE;
546*e82f7db8SAndroid Build Coastguard Worker LOG_STEP(("stepControl_handleStep: completed, into min"));
547*e82f7db8SAndroid Build Coastguard Worker goto done;
548*e82f7db8SAndroid Build Coastguard Worker }
549*e82f7db8SAndroid Build Coastguard Worker
550*e82f7db8SAndroid Build Coastguard Worker /*
551*e82f7db8SAndroid Build Coastguard Worker * If we have left the method in which
552*e82f7db8SAndroid Build Coastguard Worker * stepping started, the step is always complete.
553*e82f7db8SAndroid Build Coastguard Worker */
554*e82f7db8SAndroid Build Coastguard Worker if (step->frameExited) {
555*e82f7db8SAndroid Build Coastguard Worker completed = JNI_TRUE;
556*e82f7db8SAndroid Build Coastguard Worker LOG_STEP(("stepControl_handleStep: completed, frame exited"));
557*e82f7db8SAndroid Build Coastguard Worker goto done;
558*e82f7db8SAndroid Build Coastguard Worker }
559*e82f7db8SAndroid Build Coastguard Worker
560*e82f7db8SAndroid Build Coastguard Worker /*
561*e82f7db8SAndroid Build Coastguard Worker * Determine where we are on the call stack relative to where
562*e82f7db8SAndroid Build Coastguard Worker * we started.
563*e82f7db8SAndroid Build Coastguard Worker */
564*e82f7db8SAndroid Build Coastguard Worker currentDepth = getFrameCount(thread);
565*e82f7db8SAndroid Build Coastguard Worker fromDepth = step->fromStackDepth;
566*e82f7db8SAndroid Build Coastguard Worker
567*e82f7db8SAndroid Build Coastguard Worker if (fromDepth > currentDepth) {
568*e82f7db8SAndroid Build Coastguard Worker /*
569*e82f7db8SAndroid Build Coastguard Worker * We have returned from the caller. There are cases where
570*e82f7db8SAndroid Build Coastguard Worker * we don't get frame pop notifications
571*e82f7db8SAndroid Build Coastguard Worker * (e.g. stepping from opaque frames), and that's when
572*e82f7db8SAndroid Build Coastguard Worker * this code will be reached. Complete the step->
573*e82f7db8SAndroid Build Coastguard Worker */
574*e82f7db8SAndroid Build Coastguard Worker completed = JNI_TRUE;
575*e82f7db8SAndroid Build Coastguard Worker LOG_STEP(("stepControl_handleStep: completed, fromDepth>currentDepth(%d>%d)", fromDepth, currentDepth));
576*e82f7db8SAndroid Build Coastguard Worker } else if (fromDepth < currentDepth) {
577*e82f7db8SAndroid Build Coastguard Worker /* We have dropped into a called method. */
578*e82f7db8SAndroid Build Coastguard Worker if ( step->depth == JDWP_STEP_DEPTH(INTO)
579*e82f7db8SAndroid Build Coastguard Worker && (!eventFilter_predictFiltering(step->stepHandlerNode, clazz,
580*e82f7db8SAndroid Build Coastguard Worker (classname = getClassname(clazz))))
581*e82f7db8SAndroid Build Coastguard Worker && hasLineNumbers(method) ) {
582*e82f7db8SAndroid Build Coastguard Worker
583*e82f7db8SAndroid Build Coastguard Worker /* Stepped into a method with lines, so we're done */
584*e82f7db8SAndroid Build Coastguard Worker completed = JNI_TRUE;
585*e82f7db8SAndroid Build Coastguard Worker LOG_STEP(("stepControl_handleStep: completed, fromDepth<currentDepth(%d<%d) and into method with lines", fromDepth, currentDepth));
586*e82f7db8SAndroid Build Coastguard Worker } else {
587*e82f7db8SAndroid Build Coastguard Worker /*
588*e82f7db8SAndroid Build Coastguard Worker * We need to continue, but don't want the overhead of step
589*e82f7db8SAndroid Build Coastguard Worker * events from this method. So, we disable stepping and
590*e82f7db8SAndroid Build Coastguard Worker * enable a frame pop. If we're stepping into, we also
591*e82f7db8SAndroid Build Coastguard Worker * enable method enter events because a called frame may be
592*e82f7db8SAndroid Build Coastguard Worker * where we want to stop.
593*e82f7db8SAndroid Build Coastguard Worker */
594*e82f7db8SAndroid Build Coastguard Worker disableStepping(thread);
595*e82f7db8SAndroid Build Coastguard Worker
596*e82f7db8SAndroid Build Coastguard Worker if (step->depth == JDWP_STEP_DEPTH(INTO)) {
597*e82f7db8SAndroid Build Coastguard Worker step->methodEnterHandlerNode =
598*e82f7db8SAndroid Build Coastguard Worker eventHandler_createInternalThreadOnly(
599*e82f7db8SAndroid Build Coastguard Worker EI_METHOD_ENTRY,
600*e82f7db8SAndroid Build Coastguard Worker handleMethodEnterEvent, thread);
601*e82f7db8SAndroid Build Coastguard Worker if (step->methodEnterHandlerNode == NULL) {
602*e82f7db8SAndroid Build Coastguard Worker EXIT_ERROR(AGENT_ERROR_INVALID_EVENT_TYPE,
603*e82f7db8SAndroid Build Coastguard Worker "installing event method enter handler");
604*e82f7db8SAndroid Build Coastguard Worker }
605*e82f7db8SAndroid Build Coastguard Worker }
606*e82f7db8SAndroid Build Coastguard Worker
607*e82f7db8SAndroid Build Coastguard Worker error = JVMTI_FUNC_PTR(gdata->jvmti,NotifyFramePop)
608*e82f7db8SAndroid Build Coastguard Worker (gdata->jvmti, thread, 0);
609*e82f7db8SAndroid Build Coastguard Worker if (error == JVMTI_ERROR_DUPLICATE) {
610*e82f7db8SAndroid Build Coastguard Worker error = JVMTI_ERROR_NONE;
611*e82f7db8SAndroid Build Coastguard Worker } else if (error != JVMTI_ERROR_NONE) {
612*e82f7db8SAndroid Build Coastguard Worker EXIT_ERROR(error, "setting up notify frame pop");
613*e82f7db8SAndroid Build Coastguard Worker }
614*e82f7db8SAndroid Build Coastguard Worker }
615*e82f7db8SAndroid Build Coastguard Worker jvmtiDeallocate(classname);
616*e82f7db8SAndroid Build Coastguard Worker classname = NULL;
617*e82f7db8SAndroid Build Coastguard Worker } else {
618*e82f7db8SAndroid Build Coastguard Worker /*
619*e82f7db8SAndroid Build Coastguard Worker * We are at the same stack depth where stepping started.
620*e82f7db8SAndroid Build Coastguard Worker * Instruction steps are complete at this point. For line
621*e82f7db8SAndroid Build Coastguard Worker * steps we must check to see whether we've moved to a
622*e82f7db8SAndroid Build Coastguard Worker * different line.
623*e82f7db8SAndroid Build Coastguard Worker */
624*e82f7db8SAndroid Build Coastguard Worker if (step->granularity == JDWP_STEP_SIZE(MIN)) {
625*e82f7db8SAndroid Build Coastguard Worker completed = JNI_TRUE;
626*e82f7db8SAndroid Build Coastguard Worker LOG_STEP(("stepControl_handleStep: completed, fromDepth==currentDepth(%d) and min", fromDepth));
627*e82f7db8SAndroid Build Coastguard Worker } else {
628*e82f7db8SAndroid Build Coastguard Worker if (step->fromLine != -1) {
629*e82f7db8SAndroid Build Coastguard Worker jint line = -1;
630*e82f7db8SAndroid Build Coastguard Worker jlocation location;
631*e82f7db8SAndroid Build Coastguard Worker jmethodID method;
632*e82f7db8SAndroid Build Coastguard Worker WITH_LOCAL_REFS(env, 1) {
633*e82f7db8SAndroid Build Coastguard Worker jclass clazz;
634*e82f7db8SAndroid Build Coastguard Worker error = getFrameLocation(thread,
635*e82f7db8SAndroid Build Coastguard Worker &clazz, &method, &location);
636*e82f7db8SAndroid Build Coastguard Worker if ( isMethodObsolete(method)) {
637*e82f7db8SAndroid Build Coastguard Worker method = NULL;
638*e82f7db8SAndroid Build Coastguard Worker location = -1;
639*e82f7db8SAndroid Build Coastguard Worker }
640*e82f7db8SAndroid Build Coastguard Worker if (error != JVMTI_ERROR_NONE || location == -1) {
641*e82f7db8SAndroid Build Coastguard Worker EXIT_ERROR(error, "getting frame location");
642*e82f7db8SAndroid Build Coastguard Worker }
643*e82f7db8SAndroid Build Coastguard Worker if ( method == step->method ) {
644*e82f7db8SAndroid Build Coastguard Worker LOG_STEP(("stepControl_handleStep: checking line location"));
645*e82f7db8SAndroid Build Coastguard Worker log_debugee_location("stepControl_handleStep: checking line loc",
646*e82f7db8SAndroid Build Coastguard Worker thread, method, location);
647*e82f7db8SAndroid Build Coastguard Worker line = findLineNumber(thread, location,
648*e82f7db8SAndroid Build Coastguard Worker step->lineEntries, step->lineEntryCount);
649*e82f7db8SAndroid Build Coastguard Worker }
650*e82f7db8SAndroid Build Coastguard Worker if (line != step->fromLine) {
651*e82f7db8SAndroid Build Coastguard Worker completed = JNI_TRUE;
652*e82f7db8SAndroid Build Coastguard Worker LOG_STEP(("stepControl_handleStep: completed, fromDepth==currentDepth(%d) and different line", fromDepth));
653*e82f7db8SAndroid Build Coastguard Worker }
654*e82f7db8SAndroid Build Coastguard Worker } END_WITH_LOCAL_REFS(env);
655*e82f7db8SAndroid Build Coastguard Worker } else {
656*e82f7db8SAndroid Build Coastguard Worker /*
657*e82f7db8SAndroid Build Coastguard Worker * This is a rare case. We have stepped from a location
658*e82f7db8SAndroid Build Coastguard Worker * inside a native method to a location within a Java
659*e82f7db8SAndroid Build Coastguard Worker * method at the same stack depth. This means that
660*e82f7db8SAndroid Build Coastguard Worker * the original native method returned to another
661*e82f7db8SAndroid Build Coastguard Worker * native method which, in turn, invoked a Java method.
662*e82f7db8SAndroid Build Coastguard Worker *
663*e82f7db8SAndroid Build Coastguard Worker * Since the original frame was native, we were unable
664*e82f7db8SAndroid Build Coastguard Worker * to ask for a frame pop event, and, thus, could not
665*e82f7db8SAndroid Build Coastguard Worker * set the step->frameExited flag when the original
666*e82f7db8SAndroid Build Coastguard Worker * method was done. Instead we end up here
667*e82f7db8SAndroid Build Coastguard Worker * and act just as though the frameExited flag was set
668*e82f7db8SAndroid Build Coastguard Worker * and complete the step immediately.
669*e82f7db8SAndroid Build Coastguard Worker */
670*e82f7db8SAndroid Build Coastguard Worker completed = JNI_TRUE;
671*e82f7db8SAndroid Build Coastguard Worker LOG_STEP(("stepControl_handleStep: completed, fromDepth==currentDepth(%d) and no line", fromDepth));
672*e82f7db8SAndroid Build Coastguard Worker }
673*e82f7db8SAndroid Build Coastguard Worker }
674*e82f7db8SAndroid Build Coastguard Worker LOG_STEP(("stepControl_handleStep: finished"));
675*e82f7db8SAndroid Build Coastguard Worker }
676*e82f7db8SAndroid Build Coastguard Worker done:
677*e82f7db8SAndroid Build Coastguard Worker if (completed) {
678*e82f7db8SAndroid Build Coastguard Worker completeStep(env, thread, step);
679*e82f7db8SAndroid Build Coastguard Worker }
680*e82f7db8SAndroid Build Coastguard Worker stepControl_unlock();
681*e82f7db8SAndroid Build Coastguard Worker return completed;
682*e82f7db8SAndroid Build Coastguard Worker }
683*e82f7db8SAndroid Build Coastguard Worker
684*e82f7db8SAndroid Build Coastguard Worker
685*e82f7db8SAndroid Build Coastguard Worker void
stepControl_initialize(void)686*e82f7db8SAndroid Build Coastguard Worker stepControl_initialize(void)
687*e82f7db8SAndroid Build Coastguard Worker {
688*e82f7db8SAndroid Build Coastguard Worker stepLock = debugMonitorCreate("JDWP Step Handler Lock");
689*e82f7db8SAndroid Build Coastguard Worker }
690*e82f7db8SAndroid Build Coastguard Worker
691*e82f7db8SAndroid Build Coastguard Worker void
stepControl_reset(void)692*e82f7db8SAndroid Build Coastguard Worker stepControl_reset(void)
693*e82f7db8SAndroid Build Coastguard Worker {
694*e82f7db8SAndroid Build Coastguard Worker }
695*e82f7db8SAndroid Build Coastguard Worker
696*e82f7db8SAndroid Build Coastguard Worker /*
697*e82f7db8SAndroid Build Coastguard Worker * Reset step control request stack depth and line number.
698*e82f7db8SAndroid Build Coastguard Worker */
699*e82f7db8SAndroid Build Coastguard Worker void
stepControl_resetRequest(jthread thread)700*e82f7db8SAndroid Build Coastguard Worker stepControl_resetRequest(jthread thread)
701*e82f7db8SAndroid Build Coastguard Worker {
702*e82f7db8SAndroid Build Coastguard Worker
703*e82f7db8SAndroid Build Coastguard Worker StepRequest *step;
704*e82f7db8SAndroid Build Coastguard Worker jvmtiError error;
705*e82f7db8SAndroid Build Coastguard Worker
706*e82f7db8SAndroid Build Coastguard Worker LOG_STEP(("stepControl_resetRequest: thread=%p", thread));
707*e82f7db8SAndroid Build Coastguard Worker
708*e82f7db8SAndroid Build Coastguard Worker stepControl_lock();
709*e82f7db8SAndroid Build Coastguard Worker
710*e82f7db8SAndroid Build Coastguard Worker step = threadControl_getStepRequest(thread);
711*e82f7db8SAndroid Build Coastguard Worker
712*e82f7db8SAndroid Build Coastguard Worker if (step != NULL) {
713*e82f7db8SAndroid Build Coastguard Worker JNIEnv *env;
714*e82f7db8SAndroid Build Coastguard Worker env = getEnv();
715*e82f7db8SAndroid Build Coastguard Worker error = initState(env, thread, step);
716*e82f7db8SAndroid Build Coastguard Worker if (error != JVMTI_ERROR_NONE) {
717*e82f7db8SAndroid Build Coastguard Worker EXIT_ERROR(error, "initializing step state");
718*e82f7db8SAndroid Build Coastguard Worker }
719*e82f7db8SAndroid Build Coastguard Worker } else {
720*e82f7db8SAndroid Build Coastguard Worker EXIT_ERROR(AGENT_ERROR_INVALID_THREAD, "getting step request");
721*e82f7db8SAndroid Build Coastguard Worker }
722*e82f7db8SAndroid Build Coastguard Worker
723*e82f7db8SAndroid Build Coastguard Worker stepControl_unlock();
724*e82f7db8SAndroid Build Coastguard Worker }
725*e82f7db8SAndroid Build Coastguard Worker
726*e82f7db8SAndroid Build Coastguard Worker static void
initEvents(jthread thread,StepRequest * step)727*e82f7db8SAndroid Build Coastguard Worker initEvents(jthread thread, StepRequest *step)
728*e82f7db8SAndroid Build Coastguard Worker {
729*e82f7db8SAndroid Build Coastguard Worker /* Need to install frame pop handler and exception catch handler when
730*e82f7db8SAndroid Build Coastguard Worker * single-stepping is enabled (i.e. step-into or step-over/step-out
731*e82f7db8SAndroid Build Coastguard Worker * when fromStackDepth > 0).
732*e82f7db8SAndroid Build Coastguard Worker */
733*e82f7db8SAndroid Build Coastguard Worker if (step->depth == JDWP_STEP_DEPTH(INTO) || step->fromStackDepth > 0) {
734*e82f7db8SAndroid Build Coastguard Worker /*
735*e82f7db8SAndroid Build Coastguard Worker * TO DO: These might be able to applied more selectively to
736*e82f7db8SAndroid Build Coastguard Worker * boost performance.
737*e82f7db8SAndroid Build Coastguard Worker */
738*e82f7db8SAndroid Build Coastguard Worker step->catchHandlerNode = eventHandler_createInternalThreadOnly(
739*e82f7db8SAndroid Build Coastguard Worker EI_EXCEPTION_CATCH,
740*e82f7db8SAndroid Build Coastguard Worker handleExceptionCatchEvent,
741*e82f7db8SAndroid Build Coastguard Worker thread);
742*e82f7db8SAndroid Build Coastguard Worker step->framePopHandlerNode = eventHandler_createInternalThreadOnly(
743*e82f7db8SAndroid Build Coastguard Worker EI_FRAME_POP,
744*e82f7db8SAndroid Build Coastguard Worker handleFramePopEvent,
745*e82f7db8SAndroid Build Coastguard Worker thread);
746*e82f7db8SAndroid Build Coastguard Worker
747*e82f7db8SAndroid Build Coastguard Worker if (step->catchHandlerNode == NULL ||
748*e82f7db8SAndroid Build Coastguard Worker step->framePopHandlerNode == NULL) {
749*e82f7db8SAndroid Build Coastguard Worker EXIT_ERROR(AGENT_ERROR_INVALID_EVENT_TYPE,
750*e82f7db8SAndroid Build Coastguard Worker "installing step event handlers");
751*e82f7db8SAndroid Build Coastguard Worker }
752*e82f7db8SAndroid Build Coastguard Worker
753*e82f7db8SAndroid Build Coastguard Worker }
754*e82f7db8SAndroid Build Coastguard Worker /*
755*e82f7db8SAndroid Build Coastguard Worker * Initially enable stepping:
756*e82f7db8SAndroid Build Coastguard Worker * 1) For step into, always
757*e82f7db8SAndroid Build Coastguard Worker * 2) For step over, unless right after the VM_INIT.
758*e82f7db8SAndroid Build Coastguard Worker * Enable stepping for STEP_MIN or STEP_LINE with or without line numbers.
759*e82f7db8SAndroid Build Coastguard Worker * If the class is redefined then non EMCP methods may not have line
760*e82f7db8SAndroid Build Coastguard Worker * number info. So enable line stepping for non line number so that it
761*e82f7db8SAndroid Build Coastguard Worker * behaves like STEP_MIN/STEP_OVER.
762*e82f7db8SAndroid Build Coastguard Worker * 3) For step out, only if stepping from native, except right after VM_INIT
763*e82f7db8SAndroid Build Coastguard Worker *
764*e82f7db8SAndroid Build Coastguard Worker * (right after VM_INIT, a step->over or out is identical to running
765*e82f7db8SAndroid Build Coastguard Worker * forever)
766*e82f7db8SAndroid Build Coastguard Worker */
767*e82f7db8SAndroid Build Coastguard Worker switch (step->depth) {
768*e82f7db8SAndroid Build Coastguard Worker case JDWP_STEP_DEPTH(INTO):
769*e82f7db8SAndroid Build Coastguard Worker enableStepping(thread);
770*e82f7db8SAndroid Build Coastguard Worker break;
771*e82f7db8SAndroid Build Coastguard Worker case JDWP_STEP_DEPTH(OVER):
772*e82f7db8SAndroid Build Coastguard Worker if (step->fromStackDepth > 0 && !step->fromNative ) {
773*e82f7db8SAndroid Build Coastguard Worker enableStepping(thread);
774*e82f7db8SAndroid Build Coastguard Worker }
775*e82f7db8SAndroid Build Coastguard Worker break;
776*e82f7db8SAndroid Build Coastguard Worker case JDWP_STEP_DEPTH(OUT):
777*e82f7db8SAndroid Build Coastguard Worker if (step->fromNative &&
778*e82f7db8SAndroid Build Coastguard Worker (step->fromStackDepth > 0)) {
779*e82f7db8SAndroid Build Coastguard Worker enableStepping(thread);
780*e82f7db8SAndroid Build Coastguard Worker }
781*e82f7db8SAndroid Build Coastguard Worker break;
782*e82f7db8SAndroid Build Coastguard Worker default:
783*e82f7db8SAndroid Build Coastguard Worker JDI_ASSERT(JNI_FALSE);
784*e82f7db8SAndroid Build Coastguard Worker }
785*e82f7db8SAndroid Build Coastguard Worker }
786*e82f7db8SAndroid Build Coastguard Worker
787*e82f7db8SAndroid Build Coastguard Worker jvmtiError
stepControl_beginStep(JNIEnv * env,jthread thread,jint size,jint depth,HandlerNode * node)788*e82f7db8SAndroid Build Coastguard Worker stepControl_beginStep(JNIEnv *env, jthread thread, jint size, jint depth,
789*e82f7db8SAndroid Build Coastguard Worker HandlerNode *node)
790*e82f7db8SAndroid Build Coastguard Worker {
791*e82f7db8SAndroid Build Coastguard Worker StepRequest *step;
792*e82f7db8SAndroid Build Coastguard Worker jvmtiError error;
793*e82f7db8SAndroid Build Coastguard Worker jvmtiError error2;
794*e82f7db8SAndroid Build Coastguard Worker
795*e82f7db8SAndroid Build Coastguard Worker LOG_STEP(("stepControl_beginStep: thread=%p,size=%d,depth=%d",
796*e82f7db8SAndroid Build Coastguard Worker thread, size, depth));
797*e82f7db8SAndroid Build Coastguard Worker
798*e82f7db8SAndroid Build Coastguard Worker eventHandler_lock(); /* for proper lock order */
799*e82f7db8SAndroid Build Coastguard Worker stepControl_lock();
800*e82f7db8SAndroid Build Coastguard Worker
801*e82f7db8SAndroid Build Coastguard Worker step = threadControl_getStepRequest(thread);
802*e82f7db8SAndroid Build Coastguard Worker if (step == NULL) {
803*e82f7db8SAndroid Build Coastguard Worker error = AGENT_ERROR_INVALID_THREAD;
804*e82f7db8SAndroid Build Coastguard Worker /* Normally not getting a StepRequest struct pointer is a fatal error
805*e82f7db8SAndroid Build Coastguard Worker * but on a beginStep, we just return an error code.
806*e82f7db8SAndroid Build Coastguard Worker */
807*e82f7db8SAndroid Build Coastguard Worker } else {
808*e82f7db8SAndroid Build Coastguard Worker /*
809*e82f7db8SAndroid Build Coastguard Worker * In case the thread isn't already suspended, do it again.
810*e82f7db8SAndroid Build Coastguard Worker */
811*e82f7db8SAndroid Build Coastguard Worker error = threadControl_suspendThread(thread, JNI_FALSE);
812*e82f7db8SAndroid Build Coastguard Worker if (error == JVMTI_ERROR_NONE) {
813*e82f7db8SAndroid Build Coastguard Worker /*
814*e82f7db8SAndroid Build Coastguard Worker * Overwrite any currently executing step.
815*e82f7db8SAndroid Build Coastguard Worker */
816*e82f7db8SAndroid Build Coastguard Worker step->granularity = size;
817*e82f7db8SAndroid Build Coastguard Worker step->depth = depth;
818*e82f7db8SAndroid Build Coastguard Worker step->catchHandlerNode = NULL;
819*e82f7db8SAndroid Build Coastguard Worker step->framePopHandlerNode = NULL;
820*e82f7db8SAndroid Build Coastguard Worker step->methodEnterHandlerNode = NULL;
821*e82f7db8SAndroid Build Coastguard Worker step->stepHandlerNode = node;
822*e82f7db8SAndroid Build Coastguard Worker error = initState(env, thread, step);
823*e82f7db8SAndroid Build Coastguard Worker if (error == JVMTI_ERROR_NONE) {
824*e82f7db8SAndroid Build Coastguard Worker initEvents(thread, step);
825*e82f7db8SAndroid Build Coastguard Worker }
826*e82f7db8SAndroid Build Coastguard Worker /* false means it is not okay to unblock the commandLoop thread */
827*e82f7db8SAndroid Build Coastguard Worker error2 = threadControl_resumeThread(thread, JNI_FALSE);
828*e82f7db8SAndroid Build Coastguard Worker if (error2 != JVMTI_ERROR_NONE && error == JVMTI_ERROR_NONE) {
829*e82f7db8SAndroid Build Coastguard Worker error = error2;
830*e82f7db8SAndroid Build Coastguard Worker }
831*e82f7db8SAndroid Build Coastguard Worker
832*e82f7db8SAndroid Build Coastguard Worker /*
833*e82f7db8SAndroid Build Coastguard Worker * If everything went ok, indicate a step is pending.
834*e82f7db8SAndroid Build Coastguard Worker */
835*e82f7db8SAndroid Build Coastguard Worker if (error == JVMTI_ERROR_NONE) {
836*e82f7db8SAndroid Build Coastguard Worker step->pending = JNI_TRUE;
837*e82f7db8SAndroid Build Coastguard Worker }
838*e82f7db8SAndroid Build Coastguard Worker } else {
839*e82f7db8SAndroid Build Coastguard Worker EXIT_ERROR(error, "stepControl_beginStep: cannot suspend thread");
840*e82f7db8SAndroid Build Coastguard Worker }
841*e82f7db8SAndroid Build Coastguard Worker }
842*e82f7db8SAndroid Build Coastguard Worker
843*e82f7db8SAndroid Build Coastguard Worker stepControl_unlock();
844*e82f7db8SAndroid Build Coastguard Worker eventHandler_unlock();
845*e82f7db8SAndroid Build Coastguard Worker
846*e82f7db8SAndroid Build Coastguard Worker return error;
847*e82f7db8SAndroid Build Coastguard Worker }
848*e82f7db8SAndroid Build Coastguard Worker
849*e82f7db8SAndroid Build Coastguard Worker
850*e82f7db8SAndroid Build Coastguard Worker static void
clearStep(jthread thread,StepRequest * step)851*e82f7db8SAndroid Build Coastguard Worker clearStep(jthread thread, StepRequest *step)
852*e82f7db8SAndroid Build Coastguard Worker {
853*e82f7db8SAndroid Build Coastguard Worker if (step->pending) {
854*e82f7db8SAndroid Build Coastguard Worker
855*e82f7db8SAndroid Build Coastguard Worker disableStepping(thread);
856*e82f7db8SAndroid Build Coastguard Worker if ( step->catchHandlerNode != NULL ) {
857*e82f7db8SAndroid Build Coastguard Worker (void)eventHandler_free(step->catchHandlerNode);
858*e82f7db8SAndroid Build Coastguard Worker step->catchHandlerNode = NULL;
859*e82f7db8SAndroid Build Coastguard Worker }
860*e82f7db8SAndroid Build Coastguard Worker if ( step->framePopHandlerNode!= NULL ) {
861*e82f7db8SAndroid Build Coastguard Worker (void)eventHandler_free(step->framePopHandlerNode);
862*e82f7db8SAndroid Build Coastguard Worker step->framePopHandlerNode = NULL;
863*e82f7db8SAndroid Build Coastguard Worker }
864*e82f7db8SAndroid Build Coastguard Worker if ( step->methodEnterHandlerNode != NULL ) {
865*e82f7db8SAndroid Build Coastguard Worker (void)eventHandler_free(step->methodEnterHandlerNode);
866*e82f7db8SAndroid Build Coastguard Worker step->methodEnterHandlerNode = NULL;
867*e82f7db8SAndroid Build Coastguard Worker }
868*e82f7db8SAndroid Build Coastguard Worker step->pending = JNI_FALSE;
869*e82f7db8SAndroid Build Coastguard Worker
870*e82f7db8SAndroid Build Coastguard Worker /*
871*e82f7db8SAndroid Build Coastguard Worker * Warning: Do not clear step->method, step->lineEntryCount,
872*e82f7db8SAndroid Build Coastguard Worker * or step->lineEntries here, they will likely
873*e82f7db8SAndroid Build Coastguard Worker * be needed on the next step.
874*e82f7db8SAndroid Build Coastguard Worker */
875*e82f7db8SAndroid Build Coastguard Worker
876*e82f7db8SAndroid Build Coastguard Worker }
877*e82f7db8SAndroid Build Coastguard Worker }
878*e82f7db8SAndroid Build Coastguard Worker
879*e82f7db8SAndroid Build Coastguard Worker jvmtiError
stepControl_endStep(jthread thread)880*e82f7db8SAndroid Build Coastguard Worker stepControl_endStep(jthread thread)
881*e82f7db8SAndroid Build Coastguard Worker {
882*e82f7db8SAndroid Build Coastguard Worker StepRequest *step;
883*e82f7db8SAndroid Build Coastguard Worker jvmtiError error;
884*e82f7db8SAndroid Build Coastguard Worker
885*e82f7db8SAndroid Build Coastguard Worker LOG_STEP(("stepControl_endStep: thread=%p", thread));
886*e82f7db8SAndroid Build Coastguard Worker
887*e82f7db8SAndroid Build Coastguard Worker eventHandler_lock(); /* for proper lock order */
888*e82f7db8SAndroid Build Coastguard Worker stepControl_lock();
889*e82f7db8SAndroid Build Coastguard Worker
890*e82f7db8SAndroid Build Coastguard Worker step = threadControl_getStepRequest(thread);
891*e82f7db8SAndroid Build Coastguard Worker if (step != NULL) {
892*e82f7db8SAndroid Build Coastguard Worker clearStep(thread, step);
893*e82f7db8SAndroid Build Coastguard Worker error = JVMTI_ERROR_NONE;
894*e82f7db8SAndroid Build Coastguard Worker } else {
895*e82f7db8SAndroid Build Coastguard Worker /* If the stepRequest can't be gotten, then this thread no longer
896*e82f7db8SAndroid Build Coastguard Worker * exists, just return, don't die here, this is normal at
897*e82f7db8SAndroid Build Coastguard Worker * termination time. Return JVMTI_ERROR_NONE so the thread Ref
898*e82f7db8SAndroid Build Coastguard Worker * can be tossed.
899*e82f7db8SAndroid Build Coastguard Worker */
900*e82f7db8SAndroid Build Coastguard Worker error = JVMTI_ERROR_NONE;
901*e82f7db8SAndroid Build Coastguard Worker }
902*e82f7db8SAndroid Build Coastguard Worker
903*e82f7db8SAndroid Build Coastguard Worker stepControl_unlock();
904*e82f7db8SAndroid Build Coastguard Worker eventHandler_unlock();
905*e82f7db8SAndroid Build Coastguard Worker
906*e82f7db8SAndroid Build Coastguard Worker return error;
907*e82f7db8SAndroid Build Coastguard Worker }
908*e82f7db8SAndroid Build Coastguard Worker
909*e82f7db8SAndroid Build Coastguard Worker void
stepControl_clearRequest(jthread thread,StepRequest * step)910*e82f7db8SAndroid Build Coastguard Worker stepControl_clearRequest(jthread thread, StepRequest *step)
911*e82f7db8SAndroid Build Coastguard Worker {
912*e82f7db8SAndroid Build Coastguard Worker LOG_STEP(("stepControl_clearRequest: thread=%p", thread));
913*e82f7db8SAndroid Build Coastguard Worker clearStep(thread, step);
914*e82f7db8SAndroid Build Coastguard Worker }
915*e82f7db8SAndroid Build Coastguard Worker
916*e82f7db8SAndroid Build Coastguard Worker void
stepControl_lock(void)917*e82f7db8SAndroid Build Coastguard Worker stepControl_lock(void)
918*e82f7db8SAndroid Build Coastguard Worker {
919*e82f7db8SAndroid Build Coastguard Worker debugMonitorEnter(stepLock);
920*e82f7db8SAndroid Build Coastguard Worker }
921*e82f7db8SAndroid Build Coastguard Worker
922*e82f7db8SAndroid Build Coastguard Worker void
stepControl_unlock(void)923*e82f7db8SAndroid Build Coastguard Worker stepControl_unlock(void)
924*e82f7db8SAndroid Build Coastguard Worker {
925*e82f7db8SAndroid Build Coastguard Worker debugMonitorExit(stepLock);
926*e82f7db8SAndroid Build Coastguard Worker }
927