Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4336421

No METHOD_ENTRY/METHOD_EXIT for inlined methods before jvmpi is enabled.

XMLWordPrintable

    • generic, x86, sparc
    • generic, solaris_8, windows_nt, windows_2000



      Name: dkR10031 Date: 05/08/2000



      The HotSpot Client VM 1.3.0fcs-C (win32) fails the test
      from testbase_nsk in compiled mode because no
      JVMPI_EVENT_METHOD_EXIT event is sent when the method's body is just:
      return 1 + d;
      When the sum is stored in a local:
      int res = 1 + d;
      return res;
      METHOD_EXIT event occurs as expected.

      -Xmixed, -Xint modes work OK as well as Server VM (win32) in all modes.

      To reproduce the bug run
      doit.bat <jdk root directory> -Xcomp
      in
      /net/sqesvr/vsn/GammaBase/Bugs/<this bug number>

      The test produces the output:

      >doit G:\ld24\java\hotspot\jdk1.3.0\win32 -Xcomp
      ...
      java version "1.3.0"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0-B)
      Java HotSpot(TM) Client VM (build 1.3.0-C, compiled mode)
      no METHOD_EXIT event for meth07

      ======================================================================

      karen.kinnear@East 2000-08-16

      Solaris/Sparc fails same test for -Xint, -Xcomp, -Xserver -Xcomp.
      It also fails all of these even if the test is explanded to
      the two lines of source code.

      ==================================================
      raghunath.verabelli@East on 06-15-01

      Refer to Incident #126318 reported by Licensee Sitraka (K L Group).
      It looks like METHOD_EXIT events are not correctly balanced with METHOD_ENTRY events. In particular, it looks like the JVM neglects to send a METHOD_EXIT event which messes up Profiler.

      Tested using 1.4.0-beta-b65 on Solaris :
      ========================================
      Program crashes for both Client and Server VM when using -Xcomp option.
      Works Fine without -Xcomp option.The default mode is -Xmixed and the program doesn't run long enough for the right stuff to get compiled. With the -Xcomp flag, things get compiled and boom.

      Refer to Incident # 126400

      Tested using build 1.3.1-rc2-b22 on Solaris :
      ==============================================
      Program fails with below error message when using Client VM only.
      Works fine with Server VM. Works fine even with -Xint option.

      Refer to Incident #126318.
       
      Output of Testing :
      -------------------
      prithvi 131 =>./bin/java -client -Xnoclassgc -Xrunstack Test
      2803c: METHOD_ENTRY/METHOD_EXIT mismatch
      Got method exit for method 10ab88, expected a4128
      We think stack (before exit) is:
      a4128
      10ab88
      10ab70
      10ab58
      10aaf8
      10aa80
      10a410
      10a3b0
      a44e8
      a44d0
      103210
      102ee0
      102ec8
      102ec8
      102eb0
      102e98
      e6dc8
      102e50
      102e20
      102c50
      102c08
      102aa0
      e6dc8
      102a58
      103758
      VM says stack now is:

      Unexpected Signal : 11 occurred at PC=0xfe58b5fc
      Function name=JVM_GetStackAccessControlContext
      Library=/home/raghuv/j2sdk1_3/jdk1.3.1/jre/lib/sparc/client/libjvm.so

      Current Java thread:
      [error occured during error reporting]
      Segmentation Fault


      JVMPI Client. Program (stack.c) compile it and to generate libstack.so file :
      ----------------------------------------------------------------------------

      #include <stdio.h>
      #include <stdlib.h>
      #include <jvmpi.h>

      #define JVMPI(m) (jvmpi->m)
      #define STACK_CHUNK 100

      static JVMPI_Interface *jvmpi;
      static void notify(JVMPI_Event *);

      struct callstack {
              size_t curr;
              size_t max;
              jmethodID * stack;
      };

      static struct callstack *
      get_callstack(JNIEnv * env)
      {
              struct callstack * cs;

              cs = (struct callstack *)JVMPI(GetThreadLocalStorage)(env);
              if (cs == NULL) {
                      cs = (struct callstack *)malloc(sizeof(struct callstack));
                      if (cs) {
                              cs->curr = 0;
                              cs->max = 0;
                              cs->stack = 0;
                              JVMPI(SetThreadLocalStorage)(env, (void *)cs);
                      } else {
                              fprintf(stderr, "Out of memory for per-thread stack\n"); exit(1);
                      }
              }
              return cs;
      }

      static void
      push(struct callstack * cs, jmethodID method)
      {
              if (cs->curr >= cs->max) {
                      cs->max += STACK_CHUNK;
                      cs->stack = (jmethodID *)realloc(cs->stack, sizeof(jmethodID) * cs->max);
                      if (!cs->stack) {
                              fprintf(stderr, "Out of memory for thread stack\n");
                              exit(1);
                      }
              }
              cs->stack[cs->curr++] = method;
      }

      static jmethodID
      pop(struct callstack * cs)
      {
              return cs->curr ? cs->stack[--cs->curr] : (jmethodID)0;
      }

      extern "C" JNIEXPORT jint JNICALL
      JVM_OnLoad(JavaVM *jvm, char *options, void *reserved)
      {
              int res = jvm->GetEnv((void **)&jvmpi, JVMPI_VERSION_1);

              if (res < 0) {
                      return JNI_ERR;
              }

              jvmpi->NotifyEvent = notify;

              JVMPI(EnableEvent)(JVMPI_EVENT_METHOD_ENTRY, NULL);
              JVMPI(EnableEvent)(JVMPI_EVENT_METHOD_EXIT, NULL);

              return JNI_OK;
      }


      void
      notify(JVMPI_Event * event)
      {
              JVMPI_CallTrace trace;
              JVMPI_CallFrame frame[100];
              struct callstack * cs;
              jmethodID method;

              switch (event->event_type) {
              case JVMPI_EVENT_METHOD_ENTRY:
                      push(get_callstack(event->env_id), event->u.method.method_id);
                      break;
              case JVMPI_EVENT_METHOD_EXIT:
                      cs = get_callstack(event->env_id);
                      method = pop(cs);
                      if (method <= 0) {
                              fprintf(stderr, "%p: Empty stack\n", (void *)event->env_id);
                      } else if (method != event->u.method.method_id) {
                              fprintf(stderr, "%p: METHOD_ENTRY/METHOD_EXIT mismatch\n",
                                              (void *)event->env_id);
                              fprintf(stderr, "Got method exit for method %p, expected %p\n",
                                              (void *)event->u.method.method_id, (void *)method);
                              fprintf(stderr, "We think stack (before exit) is:\n");
                              while (method) {
                                      fprintf(stderr, "%p\n", (void *)method);
                                      method = pop(cs);
                              }
                              fprintf(stderr, "VM says stack now is:\n");
                              trace.env_id = event->env_id;
                              trace.num_frames = 0;
                              trace.frames = &frame[0];
                              JVMPI(GetCallTrace)(&trace, sizeof(frame) / sizeof(JVMPI_CallFrame));
                              if (trace.num_frames < 1) {
                                      fprintf(stderr, "unknown location (num_frames <
      1)\n");
                              } else {
                                      for (int i = 0; i < trace.num_frames; ++i) {
                                              fprintf(stderr, "%p\n", (void *)frame[i].method_id);
                                      }
                              }
                      }
                      break;
              default:
                      break;
              }
      }


      ###@###.### 2001-12-05

      I changed the synopsis to reflect the problem with when jvmpi is enabled.
      C1 turns on inlining by default. So before jvmpi is enabled depending on
      when the agent library is loaded and the OnLoad function is called,
      methods may get inlined.

      The following NSK jvmpi tests failed due to this bug:

         nsk/jvmpi/events/mexit001
         nsk/jvmpi/events/mentry001

            Unassigned Unassigned
            dimasunw Dima Dima (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: