< prev index next >

src/jdk.jdwp.agent/share/native/libjdwp/stepControl.c

Print this page


   1 /*
   2  * Copyright (c) 1998, 2005, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #include "util.h"
  27 #include "stepControl.h"
  28 #include "eventHandler.h"
  29 #include "eventHelper.h"
  30 #include "threadControl.h"
  31 #include "SDE.h"
  32 
  33 static jrawMonitorID stepLock;
  34 
  35 static jint
  36 getFrameCount(jthread thread)
  37 {
  38     jint count = 0;
  39     jvmtiError error;
  40 
  41     error = JVMTI_FUNC_PTR(gdata->jvmti,GetFrameCount)
  42                     (gdata->jvmti, thread, &count);
  43     if (error != JVMTI_ERROR_NONE) {
  44         EXIT_ERROR(error, "getting frame count");
  45     }
  46     return count;
  47 }
  48 
  49 /*
  50  * Most enabling/disabling of JVMTI events happens implicitly through
  51  * the inserting and freeing of handlers for those events. Stepping is
  52  * different because requested steps are usually not identical to JVMTI steps.
  53  * They usually require multiple events step, and otherwise, before they
  54  * complete. While a step request is pending, we may need to temporarily
  55  * disable and re-enable stepping, but we can't just remove the handlers
  56  * because that would break the application's ability to remove the
  57  * events. So, for step events only, we directly enable and disable stepping.
  58  * This is safe because there can only ever be one pending step request
  59  * per thread.
  60  */
  61 static void
  62 enableStepping(jthread thread)
  63 {
  64     jvmtiError error;
  65 
  66     LOG_STEP(("enableStepping: thread=%p", thread));
  67 
  68     error = threadControl_setEventMode(JVMTI_ENABLE, EI_SINGLE_STEP,
  69                                             thread);
  70     if (error != JVMTI_ERROR_NONE) {
  71         EXIT_ERROR(error, "enabling single step");
  72     }
  73 }
  74 
  75 static void
  76 disableStepping(jthread thread)
  77 {
  78     jvmtiError error;
  79 
  80     LOG_STEP(("disableStepping: thread=%p", thread));
  81 
  82     error = threadControl_setEventMode(JVMTI_DISABLE, EI_SINGLE_STEP,
  83                                             thread);
  84     if (error != JVMTI_ERROR_NONE) {
  85         EXIT_ERROR(error, "disabling single step");
  86     }
  87 }
  88 








  89 static jvmtiError
  90 getFrameLocation(jthread thread,
  91         jclass *pclazz, jmethodID *pmethod, jlocation *plocation)
  92 {
  93     jvmtiError error;
  94 
  95     *pclazz = NULL;
  96     *pmethod = NULL;
  97     *plocation = -1;
  98 
  99     error = JVMTI_FUNC_PTR(gdata->jvmti,GetFrameLocation)
 100             (gdata->jvmti, thread, 0, pmethod, plocation);
 101     if (error == JVMTI_ERROR_NONE && *pmethod!=NULL ) {
 102         /* This also serves to verify that the methodID is valid */
 103         error = methodClass(*pmethod, pclazz);
 104     }
 105     return error;
 106 }
 107 
 108 static void


 156     getLineNumberTable(method, &count, &table);
 157     if ( count == 0 ) {
 158         return JNI_FALSE;
 159     } else {
 160         jvmtiDeallocate(table);
 161     }
 162     return JNI_TRUE;
 163 }
 164 
 165 static jvmtiError
 166 initState(JNIEnv *env, jthread thread, StepRequest *step)
 167 {
 168     jvmtiError error;
 169 
 170     /*
 171      * Initial values that may be changed below
 172      */
 173     step->fromLine = -1;
 174     step->fromNative = JNI_FALSE;
 175     step->frameExited = JNI_FALSE;
 176     step->fromStackDepth = getFrameCount(thread);
 177 
 178     if (step->fromStackDepth <= 0) {
 179         /*
 180          * If there are no stack frames, treat the step as though
 181          * from a native frame. This is most likely to occur at the
 182          * beginning of a debug session, right after the VM_INIT event,
 183          * so we need to do something intelligent.
 184          */
 185         step->fromNative = JNI_TRUE;
 186         return JVMTI_ERROR_NONE;
 187     }
 188 
 189     /*
 190      * Try to get a notification on frame pop. If we're in an opaque frame
 191      * we won't be able to, but we can use other methods to detect that
 192      * a native frame has exited.
 193      *
 194      * TO DO: explain the need for this notification.
 195      */
 196     error = JVMTI_FUNC_PTR(gdata->jvmti,NotifyFramePop)


 264 {
 265     StepRequest *step;
 266     jthread thread = evinfo->thread;
 267 
 268     stepControl_lock();
 269 
 270     step = threadControl_getStepRequest(thread);
 271     if (step == NULL) {
 272         EXIT_ERROR(AGENT_ERROR_INVALID_THREAD, "getting step request");
 273     }
 274 
 275     if (step->pending) {
 276         /*
 277          * Note: current depth is reported as *before* the pending frame
 278          * pop.
 279          */
 280         jint currentDepth;
 281         jint fromDepth;
 282         jint afterPopDepth;
 283 
 284         currentDepth = getFrameCount(thread);
 285         fromDepth = step->fromStackDepth;
 286         afterPopDepth = currentDepth-1;
 287 
 288         LOG_STEP(("handleFramePopEvent: BEGIN fromDepth=%d, currentDepth=%d",
 289                         fromDepth, currentDepth));
 290 
 291         /*
 292          * If we are exiting the original stepping frame, record that
 293          * fact here. Once the next step event comes in, we can safely
 294          * stop stepping there.
 295          */
 296         if (fromDepth > afterPopDepth ) {
 297             step->frameExited = JNI_TRUE;
 298         }
 299 
 300         if (step->depth == JDWP_STEP_DEPTH(OVER)) {
 301             /*
 302              * Either
 303              * 1) the original stepping frame is about to be popped
 304              *    [fromDepth == currentDepth]. Re-enable stepping to


 324              *    methods, then the enabled stepping is benign and
 325              *    will be disabled again on the next step event.
 326              *
 327              * Note that the condition not covered above,
 328              * [fromDepth > currentDepth] shouldn't happen since it means
 329              * that too many frames have been popped. For robustness,
 330              * we enable stepping in that case too, so that the errant
 331              * step-over can be stopped.
 332              *
 333              */
 334             LOG_STEP(("handleFramePopEvent: starting singlestep, depth==OVER"));
 335             enableStepping(thread);
 336         } else if (step->depth == JDWP_STEP_DEPTH(OUT) &&
 337                    fromDepth > afterPopDepth) {
 338             /*
 339              * The original stepping frame is about to be popped. Step
 340              * until we reach the next safe place to stop.
 341              */
 342             LOG_STEP(("handleFramePopEvent: starting singlestep, depth==OUT && fromDepth > afterPopDepth (%d>%d)",fromDepth, afterPopDepth));
 343             enableStepping(thread);
 344         } else if (step->methodEnterHandlerNode != NULL &&
 345                    fromDepth >= afterPopDepth) {
 346             /*
 347              * We installed a method entry event handler as part of a
 348              * step into operation. We've popped back to the original
 349              * stepping frame without finding a place to stop.
 350              * Resume stepping in the original frame.
 351              */
 352             LOG_STEP(("handleFramePopEvent: starting singlestep, have methodEnter handler && depth==OUT && fromDepth >= afterPopDepth (%d>%d)",fromDepth, afterPopDepth));









 353             enableStepping(thread);
 354             (void)eventHandler_free(step->methodEnterHandlerNode);
 355             step->methodEnterHandlerNode = NULL;
 356         }
 357         LOG_STEP(("handleFramePopEvent: finished"));
 358     }
 359 
 360     stepControl_unlock();
 361 }
 362 
 363 static void
 364 handleExceptionCatchEvent(JNIEnv *env, EventInfo *evinfo,
 365                           HandlerNode *node,
 366                           struct bag *eventBag)
 367 {
 368     StepRequest *step;
 369     jthread thread = evinfo->thread;
 370 
 371     stepControl_lock();
 372 
 373     step = threadControl_getStepRequest(thread);
 374     if (step == NULL) {
 375         EXIT_ERROR(AGENT_ERROR_INVALID_THREAD, "getting step request");
 376     }
 377 
 378     if (step->pending) {
 379         /*
 380          *  Determine where we are on the call stack relative to where
 381          *  we started.
 382          */
 383         jint currentDepth = getFrameCount(thread);
 384         jint fromDepth = step->fromStackDepth;
 385 
 386         LOG_STEP(("handleExceptionCatchEvent: fromDepth=%d, currentDepth=%d",
 387                         fromDepth, currentDepth));
 388 
 389         /*
 390          * If we are exiting the original stepping frame, record that
 391          * fact here. Once the next step event comes in, we can safely
 392          * stop stepping there.
 393          */
 394         if (fromDepth > currentDepth) {
 395             step->frameExited = JNI_TRUE;
 396         }
 397 
 398         if (step->depth == JDWP_STEP_DEPTH(OVER) &&
 399             fromDepth >= currentDepth) {
 400             /*
 401              * Either the original stepping frame is done,
 402              * or a called method has returned (during which we had stepping
 403              * disabled). In either case we must resume stepping.


 410              * until we reach the next safe place to stop.
 411              */
 412             enableStepping(thread);
 413         } else if (step->methodEnterHandlerNode != NULL &&
 414                    fromDepth >= currentDepth) {
 415             /*
 416              * We installed a method entry event handler as part of a
 417              * step into operation. We've popped back to the original
 418              * stepping frame or higher without finding a place to stop.
 419              * Resume stepping in the original frame.
 420              */
 421             enableStepping(thread);
 422             (void)eventHandler_free(step->methodEnterHandlerNode);
 423             step->methodEnterHandlerNode = NULL;
 424         }
 425     }
 426 
 427     stepControl_unlock();
 428 }
 429 

































 430 static void
 431 handleMethodEnterEvent(JNIEnv *env, EventInfo *evinfo,
 432                        HandlerNode *node,
 433                        struct bag *eventBag)
 434 {
 435     StepRequest *step;
 436     jthread thread;
 437 
 438     thread = evinfo->thread;
 439 
 440     stepControl_lock();
 441 
 442     step = threadControl_getStepRequest(thread);
 443     if (step == NULL) {
 444         EXIT_ERROR(AGENT_ERROR_INVALID_THREAD, "getting step request");
 445     }



 446 
 447     if (step->pending) {
 448         jclass    clazz;












 449         jmethodID method;
 450         char     *classname;
 451 
 452         LOG_STEP(("handleMethodEnterEvent: thread=%p", thread));
 453 
 454         clazz     = evinfo->clazz;
 455         method    = evinfo->method;
 456         classname = getClassname(clazz);
 457 
 458         /*
 459          * This handler is relevant only to step into

 460          */
 461         JDI_ASSERT(step->depth == JDWP_STEP_DEPTH(INTO));




 462 
 463         if (    (!eventFilter_predictFiltering(step->stepHandlerNode,
 464                                                clazz, classname))
 465              && (   step->granularity != JDWP_STEP_SIZE(LINE)
 466                  || hasLineNumbers(method) ) ) {
 467             /*
 468              * We've found a suitable method in which to stop. Step
 469              * until we reach the next safe location to complete the step->,
 470              * and we can get rid of the method entry handler.
 471              */
 472             enableStepping(thread);
 473             if ( step->methodEnterHandlerNode != NULL ) {
 474                 (void)eventHandler_free(step->methodEnterHandlerNode);
 475                 step->methodEnterHandlerNode = NULL;


 476             }
 477         }
 478         jvmtiDeallocate(classname);
 479         classname = NULL;
 480     }
 481 
 482     stepControl_unlock();
 483 }
 484 
 485 static void
 486 completeStep(JNIEnv *env, jthread thread, StepRequest *step)
 487 {
 488     jvmtiError error;
 489 
 490     /*
 491      * We've completed a step; reset state for the next one, if any
 492      */
 493 
 494     LOG_STEP(("completeStep: thread=%p", thread));
 495 
 496     if (step->methodEnterHandlerNode != NULL) {
 497         (void)eventHandler_free(step->methodEnterHandlerNode);
 498         step->methodEnterHandlerNode = NULL;
 499     }
 500 
 501     error = initState(env, thread, step);
 502     if (error != JVMTI_ERROR_NONE) {
 503         /*
 504          * None of the initState errors should happen after one step
 505          * has successfully completed.
 506          */
 507         EXIT_ERROR(error, "initializing step state");
 508     }
 509 }
 510 
 511 jboolean
 512 stepControl_handleStep(JNIEnv *env, jthread thread,
 513                        jclass clazz, jmethodID method)
 514 {
 515     jboolean completed = JNI_FALSE;
 516     StepRequest *step;
 517     jint currentDepth;
 518     jint fromDepth;
 519     jvmtiError error;
 520     char *classname;
 521 
 522     classname = NULL;
 523     stepControl_lock();
 524 
 525     step = threadControl_getStepRequest(thread);
 526     if (step == NULL) {
 527         EXIT_ERROR(AGENT_ERROR_INVALID_THREAD, "getting step request");
 528     }
 529 
 530     /*
 531      * If no step is currently pending, ignore the event
 532      */
 533     if (!step->pending) {
 534         goto done;
 535     }
 536 
 537     LOG_STEP(("stepControl_handleStep: thread=%p", thread));
 538 



 539     /*
 540      * We never filter step into instruction. It's always over on the
 541      * first step event.
 542      */
 543     if (step->depth == JDWP_STEP_DEPTH(INTO) &&
 544         step->granularity == JDWP_STEP_SIZE(MIN)) {
 545         completed = JNI_TRUE;
 546         LOG_STEP(("stepControl_handleStep: completed, into min"));
 547         goto done;
 548     }
 549 
 550     /*
 551      * If we have left the method in which
 552      * stepping started, the step is always complete.
 553      */
 554     if (step->frameExited) {
 555         completed = JNI_TRUE;
 556         LOG_STEP(("stepControl_handleStep: completed, frame exited"));
 557         goto done;
 558     }
 559 
 560     /*
 561      *  Determine where we are on the call stack relative to where
 562      *  we started.
 563      */
 564     currentDepth = getFrameCount(thread);
 565     fromDepth = step->fromStackDepth;
 566 
 567     if (fromDepth > currentDepth) {
 568         /*
 569          * We have returned from the caller. There are cases where
 570          * we don't get frame pop notifications
 571          * (e.g. stepping from opaque frames), and that's when
 572          * this code will be reached. Complete the step->
 573          */
 574         completed = JNI_TRUE;
 575         LOG_STEP(("stepControl_handleStep: completed, fromDepth>currentDepth(%d>%d)", fromDepth, currentDepth));
 576     } else if (fromDepth < currentDepth) {
 577         /* We have dropped into a called method. */
 578         if (   step->depth == JDWP_STEP_DEPTH(INTO)
 579             && (!eventFilter_predictFiltering(step->stepHandlerNode, clazz,
 580                                           (classname = getClassname(clazz))))
 581             && hasLineNumbers(method) ) {
 582 
 583             /* Stepped into a method with lines, so we're done */
 584             completed = JNI_TRUE;
 585             LOG_STEP(("stepControl_handleStep: completed, fromDepth<currentDepth(%d<%d) and into method with lines", fromDepth, currentDepth));
 586         } else {
 587             /*
 588              * We need to continue, but don't want the overhead of step
 589              * events from this method. So, we disable stepping and
 590              * enable a frame pop. If we're stepping into, we also
 591              * enable method enter events because a called frame may be
 592              * where we want to stop.
 593              */
 594             disableStepping(thread);
 595 
 596             if (step->depth == JDWP_STEP_DEPTH(INTO)) {
 597                 step->methodEnterHandlerNode =
 598                     eventHandler_createInternalThreadOnly(
 599                                        EI_METHOD_ENTRY,
 600                                        handleMethodEnterEvent, thread);
 601                 if (step->methodEnterHandlerNode == NULL) {
 602                     EXIT_ERROR(AGENT_ERROR_INVALID_EVENT_TYPE,
 603                                 "installing event method enter handler");
 604                 }
 605             }

 606 
 607             error = JVMTI_FUNC_PTR(gdata->jvmti,NotifyFramePop)
 608                         (gdata->jvmti, thread, 0);
 609             if (error == JVMTI_ERROR_DUPLICATE) {
 610                 error = JVMTI_ERROR_NONE;
 611             } else if (error != JVMTI_ERROR_NONE) {
 612                 EXIT_ERROR(error, "setting up notify frame pop");
 613             }
 614         }
 615         jvmtiDeallocate(classname);
 616         classname = NULL;
 617     } else {
 618         /*
 619          * We are at the same stack depth where stepping started.
 620          * Instruction steps are complete at this point. For line
 621          * steps we must check to see whether we've moved to a
 622          * different line.
 623          */
 624         if (step->granularity == JDWP_STEP_SIZE(MIN)) {
 625             completed = JNI_TRUE;


 707 
 708     stepControl_lock();
 709 
 710     step = threadControl_getStepRequest(thread);
 711 
 712     if (step != NULL) {
 713         JNIEnv *env;
 714         env = getEnv();
 715         error = initState(env, thread, step);
 716         if (error != JVMTI_ERROR_NONE) {
 717             EXIT_ERROR(error, "initializing step state");
 718         }
 719     } else {
 720         EXIT_ERROR(AGENT_ERROR_INVALID_THREAD, "getting step request");
 721     }
 722 
 723     stepControl_unlock();
 724 }
 725 
 726 static void
 727 initEvents(jthread thread, StepRequest *step)
 728 {
 729     /* Need to install frame pop handler and exception catch handler when
 730      * single-stepping is enabled (i.e. step-into or step-over/step-out
 731      * when fromStackDepth > 0).
 732      */
 733     if (step->depth == JDWP_STEP_DEPTH(INTO) || step->fromStackDepth > 0) {
 734         /*
 735          * TO DO: These might be able to applied more selectively to
 736          * boost performance.
 737          */
 738         step->catchHandlerNode = eventHandler_createInternalThreadOnly(
 739                                      EI_EXCEPTION_CATCH,
 740                                      handleExceptionCatchEvent,
 741                                      thread);

 742         step->framePopHandlerNode = eventHandler_createInternalThreadOnly(
 743                                         EI_FRAME_POP,
 744                                         handleFramePopEvent,
 745                                         thread);
 746 
 747         if (step->catchHandlerNode == NULL ||
 748             step->framePopHandlerNode == NULL) {
 749             EXIT_ERROR(AGENT_ERROR_INVALID_EVENT_TYPE,
 750                         "installing step event handlers");
 751         }
 752 
 753     }
 754     /*
 755      * Initially enable stepping:
 756      * 1) For step into, always
 757      * 2) For step over, unless right after the VM_INIT.
 758      *    Enable stepping for STEP_MIN or STEP_LINE with or without line numbers.
 759      *    If the class is redefined then non EMCP methods may not have line
 760      *    number info. So enable line stepping for non line number so that it
 761      *    behaves like STEP_MIN/STEP_OVER.
 762      * 3) For step out, only if stepping from native, except right after VM_INIT
 763      *
 764      * (right after VM_INIT, a step->over or out is identical to running
 765      * forever)


 768         case JDWP_STEP_DEPTH(INTO):
 769             enableStepping(thread);
 770             break;
 771         case JDWP_STEP_DEPTH(OVER):
 772             if (step->fromStackDepth > 0 && !step->fromNative ) {
 773               enableStepping(thread);
 774             }
 775             break;
 776         case JDWP_STEP_DEPTH(OUT):
 777             if (step->fromNative &&
 778                 (step->fromStackDepth > 0)) {
 779                 enableStepping(thread);
 780             }
 781             break;
 782         default:
 783             JDI_ASSERT(JNI_FALSE);
 784     }
 785 }
 786 
 787 jvmtiError
 788 stepControl_beginStep(JNIEnv *env, jthread thread, jint size, jint depth,
 789                       HandlerNode *node)
 790 {
 791     StepRequest *step;
 792     jvmtiError error;
 793     jvmtiError error2;

















 794 
 795     LOG_STEP(("stepControl_beginStep: thread=%p,size=%d,depth=%d",
 796                         thread, size, depth));
 797 
 798     eventHandler_lock(); /* for proper lock order */
 799     stepControl_lock();
 800 
















 801     step = threadControl_getStepRequest(thread);
 802     if (step == NULL) {
 803         error = AGENT_ERROR_INVALID_THREAD;
 804         /* Normally not getting a StepRequest struct pointer is a fatal error
 805          *   but on a beginStep, we just return an error code.
 806          */
 807     } else {
 808         /*
 809          * In case the thread isn't already suspended, do it again.
 810          */
 811         error = threadControl_suspendThread(thread, JNI_FALSE);
 812         if (error == JVMTI_ERROR_NONE) {
 813             /*
 814              * Overwrite any currently executing step.
 815              */
 816             step->granularity = size;
 817             step->depth = depth;

 818             step->catchHandlerNode = NULL;
 819             step->framePopHandlerNode = NULL;
 820             step->methodEnterHandlerNode = NULL;
 821             step->stepHandlerNode = node;
 822             error = initState(env, thread, step);
 823             if (error == JVMTI_ERROR_NONE) {
 824                 initEvents(thread, step);
 825             }
 826             /* false means it is not okay to unblock the commandLoop thread */
 827             error2 = threadControl_resumeThread(thread, JNI_FALSE);
 828             if (error2 != JVMTI_ERROR_NONE && error == JVMTI_ERROR_NONE) {
 829                 error = error2;
 830             }
 831 
 832             /*
 833              * If everything went ok, indicate a step is pending.
 834              */
 835             if (error == JVMTI_ERROR_NONE) {
 836                 step->pending = JNI_TRUE;
 837             }
 838         } else {
 839             EXIT_ERROR(error, "stepControl_beginStep: cannot suspend thread");
 840         }
 841     }
 842 
 843     stepControl_unlock();
 844     eventHandler_unlock();


 870         /*
 871          * Warning: Do not clear step->method, step->lineEntryCount,
 872          *          or step->lineEntries here, they will likely
 873          *          be needed on the next step.
 874          */
 875 
 876     }
 877 }
 878 
 879 jvmtiError
 880 stepControl_endStep(jthread thread)
 881 {
 882     StepRequest *step;
 883     jvmtiError error;
 884 
 885     LOG_STEP(("stepControl_endStep: thread=%p", thread));
 886 
 887     eventHandler_lock(); /* for proper lock order */
 888     stepControl_lock();
 889 







 890     step = threadControl_getStepRequest(thread);
 891     if (step != NULL) {
 892         clearStep(thread, step);
 893         error = JVMTI_ERROR_NONE;
 894     } else {
 895         /* If the stepRequest can't be gotten, then this thread no longer
 896          *   exists, just return, don't die here, this is normal at
 897          *   termination time. Return JVMTI_ERROR_NONE so the thread Ref
 898          *   can be tossed.
 899          */
 900          error = JVMTI_ERROR_NONE;
 901     }
 902 
 903     stepControl_unlock();
 904     eventHandler_unlock();
 905 
 906     return error;
 907 }
 908 
 909 void
   1 /*
   2  * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #include "util.h"
  27 #include "stepControl.h"
  28 #include "eventHandler.h"
  29 #include "eventHelper.h"
  30 #include "threadControl.h"
  31 #include "SDE.h"
  32 
  33 static jrawMonitorID stepLock;
  34 














  35 /*
  36  * Most enabling/disabling of JVMTI events happens implicitly through
  37  * the inserting and freeing of handlers for those events. Stepping is
  38  * different because requested steps are usually not identical to JVMTI steps.
  39  * They usually require multiple events step, and otherwise, before they
  40  * complete. While a step request is pending, we may need to temporarily
  41  * disable and re-enable stepping, but we can't just remove the handlers
  42  * because that would break the application's ability to remove the
  43  * events. So, for step events only, we directly enable and disable stepping.
  44  * This is safe because there can only ever be one pending step request
  45  * per thread.
  46  */
  47 static void
  48 enableStepping(jthread thread)
  49 {
  50     jvmtiError error;
  51 
  52     LOG_STEP(("enableStepping: thread=%p", thread));
  53 
  54     error = threadControl_setEventMode(JVMTI_ENABLE, EI_SINGLE_STEP,
  55                                             thread);
  56     if (error != JVMTI_ERROR_NONE) {
  57         EXIT_ERROR(error, "enabling single step");
  58     }
  59 }
  60 
  61 static void
  62 disableStepping(jthread thread)
  63 {
  64     jvmtiError error;
  65 
  66     LOG_STEP(("disableStepping: thread=%p", thread));
  67 
  68     error = threadControl_setEventMode(JVMTI_DISABLE, EI_SINGLE_STEP,
  69                                             thread);
  70     if (error != JVMTI_ERROR_NONE) {
  71         EXIT_ERROR(error, "disabling single step");
  72     }
  73 }
  74 
  75 void stepControl_enableStepping(jthread thread) {
  76   enableStepping(thread);
  77 }
  78 
  79 void stepControl_disableStepping(jthread thread) {
  80   disableStepping(thread);
  81 }
  82 
  83 static jvmtiError
  84 getFrameLocation(jthread thread,
  85         jclass *pclazz, jmethodID *pmethod, jlocation *plocation)
  86 {
  87     jvmtiError error;
  88 
  89     *pclazz = NULL;
  90     *pmethod = NULL;
  91     *plocation = -1;
  92 
  93     error = JVMTI_FUNC_PTR(gdata->jvmti,GetFrameLocation)
  94             (gdata->jvmti, thread, 0, pmethod, plocation);
  95     if (error == JVMTI_ERROR_NONE && *pmethod!=NULL ) {
  96         /* This also serves to verify that the methodID is valid */
  97         error = methodClass(*pmethod, pclazz);
  98     }
  99     return error;
 100 }
 101 
 102 static void


 150     getLineNumberTable(method, &count, &table);
 151     if ( count == 0 ) {
 152         return JNI_FALSE;
 153     } else {
 154         jvmtiDeallocate(table);
 155     }
 156     return JNI_TRUE;
 157 }
 158 
 159 static jvmtiError
 160 initState(JNIEnv *env, jthread thread, StepRequest *step)
 161 {
 162     jvmtiError error;
 163 
 164     /*
 165      * Initial values that may be changed below
 166      */
 167     step->fromLine = -1;
 168     step->fromNative = JNI_FALSE;
 169     step->frameExited = JNI_FALSE;
 170     step->fromStackDepth = getThreadFrameCount(thread);
 171 
 172     if (step->fromStackDepth <= 0) {
 173         /*
 174          * If there are no stack frames, treat the step as though
 175          * from a native frame. This is most likely to occur at the
 176          * beginning of a debug session, right after the VM_INIT event,
 177          * so we need to do something intelligent.
 178          */
 179         step->fromNative = JNI_TRUE;
 180         return JVMTI_ERROR_NONE;
 181     }
 182 
 183     /*
 184      * Try to get a notification on frame pop. If we're in an opaque frame
 185      * we won't be able to, but we can use other methods to detect that
 186      * a native frame has exited.
 187      *
 188      * TO DO: explain the need for this notification.
 189      */
 190     error = JVMTI_FUNC_PTR(gdata->jvmti,NotifyFramePop)


 258 {
 259     StepRequest *step;
 260     jthread thread = evinfo->thread;
 261 
 262     stepControl_lock();
 263 
 264     step = threadControl_getStepRequest(thread);
 265     if (step == NULL) {
 266         EXIT_ERROR(AGENT_ERROR_INVALID_THREAD, "getting step request");
 267     }
 268 
 269     if (step->pending) {
 270         /*
 271          * Note: current depth is reported as *before* the pending frame
 272          * pop.
 273          */
 274         jint currentDepth;
 275         jint fromDepth;
 276         jint afterPopDepth;
 277 
 278         currentDepth = getThreadFrameCount(thread);
 279         fromDepth = step->fromStackDepth;
 280         afterPopDepth = currentDepth-1;
 281 
 282         LOG_STEP(("handleFramePopEvent: BEGIN fromDepth=%d, currentDepth=%d",
 283                         fromDepth, currentDepth));
 284 
 285         /*
 286          * If we are exiting the original stepping frame, record that
 287          * fact here. Once the next step event comes in, we can safely
 288          * stop stepping there.
 289          */
 290         if (fromDepth > afterPopDepth ) {
 291             step->frameExited = JNI_TRUE;
 292         }
 293 
 294         if (step->depth == JDWP_STEP_DEPTH(OVER)) {
 295             /*
 296              * Either
 297              * 1) the original stepping frame is about to be popped
 298              *    [fromDepth == currentDepth]. Re-enable stepping to


 318              *    methods, then the enabled stepping is benign and
 319              *    will be disabled again on the next step event.
 320              *
 321              * Note that the condition not covered above,
 322              * [fromDepth > currentDepth] shouldn't happen since it means
 323              * that too many frames have been popped. For robustness,
 324              * we enable stepping in that case too, so that the errant
 325              * step-over can be stopped.
 326              *
 327              */
 328             LOG_STEP(("handleFramePopEvent: starting singlestep, depth==OVER"));
 329             enableStepping(thread);
 330         } else if (step->depth == JDWP_STEP_DEPTH(OUT) &&
 331                    fromDepth > afterPopDepth) {
 332             /*
 333              * The original stepping frame is about to be popped. Step
 334              * until we reach the next safe place to stop.
 335              */
 336             LOG_STEP(("handleFramePopEvent: starting singlestep, depth==OUT && fromDepth > afterPopDepth (%d>%d)",fromDepth, afterPopDepth));
 337             enableStepping(thread);
 338         } else if (step->methodEnterHandlerNode != NULL) {
 339             /* We installed a method entry event handler as part of a step into operation. */
 340             JDI_ASSERT(step->depth == JDWP_STEP_DEPTH(INTO));
 341             if (fromDepth >= afterPopDepth) {
 342                 /*
 343                  * We've popped back to the original stepping frame without finding a place to stop.
 344                  * Resume stepping in the original frame.
 345                  */
 346                 LOG_STEP(("handleFramePopEvent: starting singlestep, have methodEnter handler && depth==INTO && fromDepth >= afterPopDepth (%d>=%d)", fromDepth, afterPopDepth));
 347             } else {
 348                 /*
 349                  * The only way this should happen is if FramePop events were enabled to support a
 350                  * CONTINUATION_RUN event while doing a STEP_INTO. See stepControl_handleContinuationRun().
 351                  * Resume stepping in the current frame. If it is not the correct frame to resume stepping
 352                  * in, then handleStep() will disable single stepping and setup another FramePop request.
 353                  */
 354                 LOG_STEP(("handleFramePopEvent: starting singlestep, have methodEnter handler && depth==INTO && fromDepth < afterPopDepth (%d<%d)", fromDepth, afterPopDepth));
 355             }
 356             enableStepping(thread);
 357             (void)eventHandler_free(step->methodEnterHandlerNode);
 358             step->methodEnterHandlerNode = NULL;
 359         }
 360         LOG_STEP(("handleFramePopEvent: finished"));
 361     }
 362 
 363     stepControl_unlock();
 364 }
 365 
 366 static void
 367 handleExceptionCatchEvent(JNIEnv *env, EventInfo *evinfo,
 368                           HandlerNode *node,
 369                           struct bag *eventBag)
 370 {
 371     StepRequest *step;
 372     jthread thread = evinfo->thread;
 373 
 374     stepControl_lock();
 375 
 376     step = threadControl_getStepRequest(thread);
 377     if (step == NULL) {
 378         EXIT_ERROR(AGENT_ERROR_INVALID_THREAD, "getting step request");
 379     }
 380 
 381     if (step->pending) {
 382         /*
 383          *  Determine where we are on the call stack relative to where
 384          *  we started.
 385          */
 386         jint currentDepth = getThreadFrameCount(thread);
 387         jint fromDepth = step->fromStackDepth;
 388 
 389         LOG_STEP(("handleExceptionCatchEvent: fromDepth=%d, currentDepth=%d",
 390                         fromDepth, currentDepth));
 391 
 392         /*
 393          * If we are exiting the original stepping frame, record that
 394          * fact here. Once the next step event comes in, we can safely
 395          * stop stepping there.
 396          */
 397         if (fromDepth > currentDepth) {
 398             step->frameExited = JNI_TRUE;
 399         }
 400 
 401         if (step->depth == JDWP_STEP_DEPTH(OVER) &&
 402             fromDepth >= currentDepth) {
 403             /*
 404              * Either the original stepping frame is done,
 405              * or a called method has returned (during which we had stepping
 406              * disabled). In either case we must resume stepping.


 413              * until we reach the next safe place to stop.
 414              */
 415             enableStepping(thread);
 416         } else if (step->methodEnterHandlerNode != NULL &&
 417                    fromDepth >= currentDepth) {
 418             /*
 419              * We installed a method entry event handler as part of a
 420              * step into operation. We've popped back to the original
 421              * stepping frame or higher without finding a place to stop.
 422              * Resume stepping in the original frame.
 423              */
 424             enableStepping(thread);
 425             (void)eventHandler_free(step->methodEnterHandlerNode);
 426             step->methodEnterHandlerNode = NULL;
 427         }
 428     }
 429 
 430     stepControl_unlock();
 431 }
 432 
 433 /*
 434  * Help deal with a METHOD_ENTRY event (or a simulated one). Returns JNI_TRUE if
 435  * single stepping gets enabled.
 436  */
 437 static jboolean
 438 methodEnterHelper(JNIEnv *env, jthread thread, StepRequest *step, jclass clazz, jmethodID method)
 439 {
 440     jboolean steppingEnabled = JNI_FALSE;
 441     if (step->pending) {
 442         char *classname = getClassname(clazz);
 443 
 444         /* This handler is relevant only to step into. */
 445         JDI_ASSERT(step->depth == JDWP_STEP_DEPTH(INTO));
 446 
 447         if ((!eventFilter_predictFiltering(step->stepHandlerNode, clazz, classname))
 448             && (step->granularity != JDWP_STEP_SIZE(LINE) || hasLineNumbers(method))) {
 449             /*
 450              * We've found a suitable method in which to resume stepping.
 451              * We can also get rid of the method entry handler now.
 452              */
 453             enableStepping(thread);
 454             steppingEnabled = JNI_TRUE;
 455             if ( step->methodEnterHandlerNode != NULL ) {
 456                 (void)eventHandler_free(step->methodEnterHandlerNode);
 457                 step->methodEnterHandlerNode = NULL;
 458             }
 459         }
 460         jvmtiDeallocate(classname);
 461         classname = NULL;
 462     }
 463     return steppingEnabled;
 464 }
 465 
 466 static void
 467 handleMethodEnterEvent(JNIEnv *env, EventInfo *evinfo,
 468                        HandlerNode *node,
 469                        struct bag *eventBag)
 470 {
 471     StepRequest *step;
 472     jthread thread = evinfo->thread;


 473 
 474     stepControl_lock();
 475     LOG_STEP(("handleMethodEnterEvent: thread=%p", thread));
 476     step = threadControl_getStepRequest(thread);
 477     if (step == NULL) {
 478         EXIT_ERROR(AGENT_ERROR_INVALID_THREAD, "getting step request");
 479     }
 480     methodEnterHelper(env, thread, step, evinfo->clazz, evinfo->method);
 481     stepControl_unlock();
 482 }
 483 
 484 void
 485 stepControl_handleContinuationRun(JNIEnv *env, jthread thread, StepRequest *step)
 486 {
 487     stepControl_lock();
 488     if (step->methodEnterHandlerNode != NULL) {
 489         /* 
 490          * Looks like we were doing a single step INTO with filtering enabled, so a MethodEntry
 491          * handler was installed to detect when we enter an unfiltered method. It's possible
 492          * that the continuation method we are resuming execution in is unfiltered, but there
 493          * will be no MethodEntry event for it. So we fake one here so the single stepping
 494          * state is udpated appropriately.
 495          */
 496         jboolean steppingEnabled;
 497         jclass clazz;
 498         jmethodID method;
 499         jlocation location;
 500         jvmtiError error;
 501         
 502         JDI_ASSERT(step->depth == JDWP_STEP_DEPTH(INTO));



 503 
 504         /*
 505          * We leverage the existing MethodEntry handler support for this, but it needs to know
 506          * the location of the MethodEntry, so we get this from the current frame.
 507          */
 508         error = getFrameLocation(thread, &clazz, &method, &location);
 509         if (error != JVMTI_ERROR_NONE) {
 510             EXIT_ERROR(error, "getting frame location");
 511         }
 512         steppingEnabled = methodEnterHelper(env, thread, step, clazz, method);
 513 
 514         if (!steppingEnabled) {



 515             /*
 516              * It looks like the continuation is resuming in a filtered method. We need to setup
 517              * a FramePop request on the current frame, so when it exits we can check if the 
 518              * method we return to is filtered, and enable single stepping if not.
 519              */
 520             error = JVMTI_FUNC_PTR(gdata->jvmti,NotifyFramePop)
 521                 (gdata->jvmti, thread, 0);
 522             if (error == JVMTI_ERROR_DUPLICATE) {
 523                 error = JVMTI_ERROR_NONE;
 524             } else if (error != JVMTI_ERROR_NONE) {
 525                 EXIT_ERROR(error, "setting up notify frame pop");
 526             }
 527         }


 528     }

 529     stepControl_unlock();
 530 }
 531 
 532 static void
 533 completeStep(JNIEnv *env, jthread thread, StepRequest *step)
 534 {
 535     jvmtiError error;
 536 
 537     /*
 538      * We've completed a step; reset state for the next one, if any
 539      */
 540 
 541     LOG_STEP(("completeStep: thread=%p", thread));
 542 
 543     if (step->methodEnterHandlerNode != NULL) {
 544         (void)eventHandler_free(step->methodEnterHandlerNode);
 545         step->methodEnterHandlerNode = NULL;
 546     }
 547 
 548     error = initState(env, thread, step);
 549     if (error != JVMTI_ERROR_NONE) {
 550         /*
 551          * None of the initState errors should happen after one step
 552          * has successfully completed.
 553          */
 554         EXIT_ERROR(error, "initializing step state");
 555     }
 556 }
 557 
 558 jboolean
 559 stepControl_handleStep(JNIEnv *env, jthread thread, jthread fiber, jboolean matchesFiber,
 560                        jclass clazz, jmethodID method)
 561 {
 562     jboolean completed = JNI_FALSE;
 563     StepRequest *step;
 564     jint currentDepth;
 565     jint fromDepth;
 566     jvmtiError error;
 567     char *classname;
 568 
 569     classname = NULL;
 570     stepControl_lock();
 571 
 572     step = threadControl_getStepRequest(thread);
 573     if (step == NULL) {
 574         EXIT_ERROR(AGENT_ERROR_INVALID_THREAD, "getting step request");
 575     }
 576 
 577     /*
 578      * If no step is currently pending, ignore the event
 579      */
 580     if (!step->pending) {
 581         goto done;
 582     }
 583 
 584     LOG_STEP(("stepControl_handleStep: thread=%p", thread));
 585 
 586     /* Make sure the StepRequest is in agreement as to whether or not we are stepping in a fiber. */
 587     JDI_ASSERT(step->is_fiber == matchesFiber);
 588 
 589     /*
 590      * We never filter step into instruction. It's always over on the
 591      * first step event.
 592      */
 593     if (step->depth == JDWP_STEP_DEPTH(INTO) &&
 594         step->granularity == JDWP_STEP_SIZE(MIN)) {
 595         completed = JNI_TRUE;
 596         LOG_STEP(("stepControl_handleStep: completed, into min"));
 597         goto done;
 598     }
 599 
 600     /*
 601      * If we have left the method in which
 602      * stepping started, the step is always complete.
 603      */
 604     if (step->frameExited) {
 605         completed = JNI_TRUE;
 606         LOG_STEP(("stepControl_handleStep: completed, frame exited"));
 607         goto done;
 608     }
 609 
 610     /*
 611      *  Determine where we are on the call stack relative to where
 612      *  we started.
 613      */
 614     currentDepth = getThreadFrameCount(thread);
 615     fromDepth = step->fromStackDepth;
 616 
 617     if (fromDepth > currentDepth) {
 618         /*
 619          * We have returned from the caller. There are cases where
 620          * we don't get frame pop notifications
 621          * (e.g. stepping from opaque frames), and that's when
 622          * this code will be reached. Complete the step->
 623          */
 624         completed = JNI_TRUE;
 625         LOG_STEP(("stepControl_handleStep: completed, fromDepth>currentDepth(%d>%d)", fromDepth, currentDepth));
 626     } else if (fromDepth < currentDepth) {
 627         /* We have dropped into a called method. */
 628         if (   step->depth == JDWP_STEP_DEPTH(INTO)
 629             && (!eventFilter_predictFiltering(step->stepHandlerNode, clazz,
 630                                           (classname = getClassname(clazz))))
 631             && hasLineNumbers(method) ) {
 632 
 633             /* Stepped into a method with lines, so we're done */
 634             completed = JNI_TRUE;
 635             LOG_STEP(("stepControl_handleStep: completed, fromDepth<currentDepth(%d<%d) and into method with lines", fromDepth, currentDepth));
 636         } else {
 637             /*
 638              * We need to continue, but don't want the overhead of step
 639              * events from this method. So, we disable stepping and
 640              * enable a frame pop. If we're stepping into, we also
 641              * enable method enter events because a called frame may be
 642              * where we want to stop.
 643              */
 644             disableStepping(thread);
 645 
 646             if (step->depth == JDWP_STEP_DEPTH(INTO)) {
 647                 step->methodEnterHandlerNode =
 648                     eventHandler_createInternalThreadOnly(
 649                                        EI_METHOD_ENTRY,
 650                                        handleMethodEnterEvent, matchesFiber ? fiber : thread);
 651                 if (step->methodEnterHandlerNode == NULL) {
 652                     EXIT_ERROR(AGENT_ERROR_INVALID_EVENT_TYPE,
 653                                 "installing event method enter handler");
 654                 }
 655             }
 656             LOG_STEP(("stepControl_handleStep: NotifyFramePop, (fromDepth currentDepth)(%d %d) ", fromDepth, currentDepth));
 657 
 658             error = JVMTI_FUNC_PTR(gdata->jvmti,NotifyFramePop)
 659                         (gdata->jvmti, thread, 0);
 660             if (error == JVMTI_ERROR_DUPLICATE) {
 661                 error = JVMTI_ERROR_NONE;
 662             } else if (error != JVMTI_ERROR_NONE) {
 663                 EXIT_ERROR(error, "setting up notify frame pop");
 664             }
 665         }
 666         jvmtiDeallocate(classname);
 667         classname = NULL;
 668     } else {
 669         /*
 670          * We are at the same stack depth where stepping started.
 671          * Instruction steps are complete at this point. For line
 672          * steps we must check to see whether we've moved to a
 673          * different line.
 674          */
 675         if (step->granularity == JDWP_STEP_SIZE(MIN)) {
 676             completed = JNI_TRUE;


 758 
 759     stepControl_lock();
 760 
 761     step = threadControl_getStepRequest(thread);
 762 
 763     if (step != NULL) {
 764         JNIEnv *env;
 765         env = getEnv();
 766         error = initState(env, thread, step);
 767         if (error != JVMTI_ERROR_NONE) {
 768             EXIT_ERROR(error, "initializing step state");
 769         }
 770     } else {
 771         EXIT_ERROR(AGENT_ERROR_INVALID_THREAD, "getting step request");
 772     }
 773 
 774     stepControl_unlock();
 775 }
 776 
 777 static void
 778 initEvents(jthread thread, jthread filter_thread, StepRequest *step)
 779 {
 780     /* Need to install frame pop handler and exception catch handler when
 781      * single-stepping is enabled (i.e. step-into or step-over/step-out
 782      * when fromStackDepth > 0).
 783      */
 784     if (step->depth == JDWP_STEP_DEPTH(INTO) || step->fromStackDepth > 0) {
 785         /*
 786          * TO DO: These might be able to applied more selectively to
 787          * boost performance.
 788          */
 789         step->catchHandlerNode = eventHandler_createInternalThreadOnly(
 790                                      EI_EXCEPTION_CATCH,
 791                                      handleExceptionCatchEvent,
 792                                      filter_thread);
 793         JDI_ASSERT(step->framePopHandlerNode == NULL);
 794         step->framePopHandlerNode = eventHandler_createInternalThreadOnly(
 795                                         EI_FRAME_POP,
 796                                         handleFramePopEvent,
 797                                         filter_thread);
 798 
 799         if (step->catchHandlerNode == NULL ||
 800             step->framePopHandlerNode == NULL) {
 801             EXIT_ERROR(AGENT_ERROR_INVALID_EVENT_TYPE,
 802                         "installing step event handlers");
 803         }
 804 
 805     }
 806     /*
 807      * Initially enable stepping:
 808      * 1) For step into, always
 809      * 2) For step over, unless right after the VM_INIT.
 810      *    Enable stepping for STEP_MIN or STEP_LINE with or without line numbers.
 811      *    If the class is redefined then non EMCP methods may not have line
 812      *    number info. So enable line stepping for non line number so that it
 813      *    behaves like STEP_MIN/STEP_OVER.
 814      * 3) For step out, only if stepping from native, except right after VM_INIT
 815      *
 816      * (right after VM_INIT, a step->over or out is identical to running
 817      * forever)


 820         case JDWP_STEP_DEPTH(INTO):
 821             enableStepping(thread);
 822             break;
 823         case JDWP_STEP_DEPTH(OVER):
 824             if (step->fromStackDepth > 0 && !step->fromNative ) {
 825               enableStepping(thread);
 826             }
 827             break;
 828         case JDWP_STEP_DEPTH(OUT):
 829             if (step->fromNative &&
 830                 (step->fromStackDepth > 0)) {
 831                 enableStepping(thread);
 832             }
 833             break;
 834         default:
 835             JDI_ASSERT(JNI_FALSE);
 836     }
 837 }
 838 
 839 jvmtiError
 840 stepControl_beginStep(JNIEnv *env, jthread filter_thread,  jint size, jint depth,
 841                       HandlerNode *node)
 842 {
 843     StepRequest *step;
 844     jvmtiError error;
 845     jvmtiError error2;
 846     jthread thread;
 847     jboolean is_fiber;
 848 
 849     /* filter_thread could be a fiber. Get the carrier thread it is mounted on. */
 850     is_fiber = isFiber(filter_thread);
 851     if (is_fiber) {
 852         thread = getFiberThread(filter_thread);
 853         if (thread == NULL) {
 854             /* fiber fixme: It is possible for the StepRequest to have been made on an unmounted
 855              * fiber, and currently we don't support this. 
 856              */
 857             LOG_STEP(("stepControl_beginStep: thread is an unmounted fiber(%p)", filter_thread));
 858             return JVMTI_ERROR_INVALID_THREAD;
 859         }
 860     }  else {
 861         thread = filter_thread;
 862     }
 863 
 864     LOG_STEP(("stepControl_beginStep: filter_thread=%p,thread=%p,size=%d,depth=%d",
 865               filter_thread, thread, size, depth));
 866 
 867     eventHandler_lock(); /* for proper lock order */
 868     stepControl_lock();
 869 
 870     /* fiber fixme: we should consider getting the StepRequest from the fiber instead of the thread.
 871      * That way we don't need to copy back and forth in threadControl_mountFiber and
 872      * threadControl_unmountFiber. It would require some additional changes in the step event 
 873      * support to always pass the fiber to threadControl_getStepRequest(). We also need to 
 874      * deal with node->instructionStepMode, referenceing the fiber copy when appropriate. Note
 875      * this will get tricky if you try to single step in both the fiber and thread. With the
 876      * current impl, if you single step in the fiber first, hit a breakpoint while stepping over
 877      * a method call, and then switch to the carrier thread and start to single step there,
 878      * that will clear out the fiber single stepping. If we get the StepRequest
 879      * from the fiber instead, it won't automatically clear out the fiber single stepping
 880      * when you start single stepping in the carrier thread, but it won't work as expected either
 881      * because JVMTI single stepping on the carrier thread will be disabled once the single
 882      * step is complete. We'd need to detect that we were single stepping on the fiber and
 883      * keep JVMTI single stepping enabled, or we need to clear the single stepping state of
 884      * the fiber.
 885      */
 886     step = threadControl_getStepRequest(thread);
 887     if (step == NULL) {
 888         error = AGENT_ERROR_INVALID_THREAD;
 889         /* Normally not getting a StepRequest struct pointer is a fatal error
 890          *   but on a beginStep, we just return an error code.
 891          */
 892     } else {
 893         /*
 894          * In case the thread isn't already suspended, do it again.
 895          */
 896         error = threadControl_suspendThread(thread, JNI_FALSE);
 897         if (error == JVMTI_ERROR_NONE) {
 898             /*
 899              * Overwrite any currently executing step.
 900              */
 901             step->granularity = size;
 902             step->depth = depth;
 903             step->is_fiber = is_fiber;
 904             step->catchHandlerNode = NULL;
 905             step->framePopHandlerNode = NULL;
 906             step->methodEnterHandlerNode = NULL;
 907             step->stepHandlerNode = node;
 908             error = initState(env, thread, step);
 909             if (error == JVMTI_ERROR_NONE) {
 910                 initEvents(thread, filter_thread, step);
 911             }
 912             /* false means it is not okay to unblock the commandLoop thread */
 913             error2 = threadControl_resumeThread(thread, JNI_FALSE);
 914             if (error2 != JVMTI_ERROR_NONE && error == JVMTI_ERROR_NONE) {
 915                 error = error2;
 916             }
 917 
 918             /*
 919              * If everything went ok, indicate a step is pending.
 920              */
 921             if (error == JVMTI_ERROR_NONE) {
 922                 step->pending = JNI_TRUE;
 923             }
 924         } else {
 925             EXIT_ERROR(error, "stepControl_beginStep: cannot suspend thread");
 926         }
 927     }
 928 
 929     stepControl_unlock();
 930     eventHandler_unlock();


 956         /*
 957          * Warning: Do not clear step->method, step->lineEntryCount,
 958          *          or step->lineEntries here, they will likely
 959          *          be needed on the next step.
 960          */
 961 
 962     }
 963 }
 964 
 965 jvmtiError
 966 stepControl_endStep(jthread thread)
 967 {
 968     StepRequest *step;
 969     jvmtiError error;
 970 
 971     LOG_STEP(("stepControl_endStep: thread=%p", thread));
 972 
 973     eventHandler_lock(); /* for proper lock order */
 974     stepControl_lock();
 975 
 976     if (isFiber(thread)) {
 977         jthread carrier_thread = getFiberThread(thread);
 978         /* During termination the fiber might not be mounted, so a NULL carrier thead is ok in that case. */
 979         if (carrier_thread != NULL) {
 980             thread = carrier_thread;
 981         }
 982     }
 983     step = threadControl_getStepRequest(thread);
 984     if (step != NULL) {
 985         clearStep(thread, step);
 986         error = JVMTI_ERROR_NONE;
 987     } else {
 988         /* If the stepRequest can't be gotten, then this thread no longer
 989          *   exists, just return, don't die here, this is normal at
 990          *   termination time. Return JVMTI_ERROR_NONE so the thread Ref
 991          *   can be tossed.
 992          */
 993          error = JVMTI_ERROR_NONE;
 994     }
 995 
 996     stepControl_unlock();
 997     eventHandler_unlock();
 998 
 999     return error;
1000 }
1001 
1002 void
< prev index next >