Hi Serguei,

We could combine both listeners in one but in this case this listener should be 
DefaultClassPrepareEventListener  that is registered only once  at the very 
beginning of the whole test. We will also need to add a method to reset 
eventReceived counter between invocations of testSourceFilter() since every 
call of testSourceFilter() is a separate subtest.

Just wanted to make sure that I correctly understood your proposal.

addListener() is invoked after startListening() just due to specifics of 
EventHandler implementation. EventHandler.addListener() adds a listener to the 
head of the list, so the last added listener is the first one to be called. And 
default listeners (including "unhandled events" one) are created when 
EventHandler.startListening() method is called. So to ensure that our listener 
is called before the "unhandled events" we have to call addListener() after 
startListening() method.

cat -n test/hotspot/jtreg/vmTestbase/nsk/share/jdi/EventHandler.java

   222      /**
   223       * This is normally called in the main thread of the test debugger.
   224       * It starts up an <code>EventHandler</code> thread that gets 
events coming in
   225       * from the debuggee and distributes them to listeners.
   226       */
   227      public void startListening() {
   228          createDefaultEventRequests();
   229          createDefaultListeners();
   230          listenThread.start();
   231      }
   232

250         /**
   251       * This method sets up default listeners.
   252       */
   253      private void createDefaultListeners() {
   254          /**
   255           * This listener catches up all unexpected events.
   256           *
   257           */
   258          addListener(
   259                  new EventListener() {
   260                      public boolean eventReceived(Event event) {
   261                          log.complain("EventHandler>  Unexpected event: 
" + event.getClass().getName());
   262                          unexpectedEventCaught = true;
   263                          return true;
   264                      }
   265                  }
   266          );
   267

               /**
   350       * Add at beginning of the list because we want
   351       * the LAST added listener to be FIRST to process
   352       * current event.
   353       */
   354      public void addListener(EventListener listener) {
   355          display("Adding listener " + listener);
   356          synchronized(listeners) {
   357              listeners.add(0, listener);
   358          }
   359      }

 
Thanks!

Best regards,
Daniil

From: "serguei.spit...@oracle.com" <serguei.spit...@oracle.com>
Date: Tuesday, July 17, 2018 at 4:53 PM
To: Daniil Titov <daniil.x.ti...@oracle.com>, 
"serviceability-dev@openjdk.java.net serviceability-dev@openjdk.java.net" 
<serviceability-dev@openjdk.java.net>
Subject: Re: RFR 8204695: [Graal] 
vmTestbase/nsk/jdi/ClassPrepareRequest/addSourceNameFilter/addSourceNameFilter002/addSourceNameFilter002.java
 fails

Hi Daniil,

Thank you for clarification and the webrev update!
I still have a couple of questions though.

I'd suggest more simple approach like below:
 154         public boolean eventReceived(Event event) {
 155             if (event instanceof ClassPrepareEvent) {
 156                 ClassPrepareEvent classPrepareEvent = (ClassPrepareEvent) 
event;
 157                 ThreadReference thread = classPrepareEvent.thread();
 158                 if (thread != null && 
DEBUGGEE_MAIN_THREAD.equals(thread.name())) {
 159                     eventReceived++;
 160 
 161                     log.display("ClassPrepareEventListener: Event 
received: " + event +
 162                             " Class: " + 
classPrepareEvent.referenceType().name());
 163 
 164                     vm.resume();
 165 
 166                     return true;
 167                 }
 168             }
 169 
 170             return false;
 171         }

to something like:
          public boolean eventReceived(Event event) {
              if (event instanceof ClassPrepareEvent) {
                  ClassPrepareEvent classPrepareEvent = (ClassPrepareEvent) 
event;
                  ThreadReference thread = classPrepareEvent.thread();
                  if (thread != null && 
DEBUGGEE_MAIN_THREAD.equals(thread.name())) {
                      eventReceived++;
                      log.display("ClassPrepareEventListener: Event received: " 
+ event +
                              " Class: " + 
classPrepareEvent.referenceType().name());
                  } else {
                      log.display("ClassPrepareEventListener: Event filtered 
out: " + event +
                              " Class: " + 
classPrepareEvent.referenceType().name() +
                              " Thread:" + classPrepareEvent.thread().name());
                  }
                  vm.resume();
                  return true;
              }
              return false;
          }

 245         eventHandler.startListening();
 246         // Add a listener to handle ClassPrepare events fired by other 
(e.g. compiler) threads.
 247         // The listener should be added after the event listener is 
started to ensure that it
 248         // called before the default event listener that handles 
unexpected events.
 249         eventHandler.addListener(new DefaultClassPrepareEventListener());
  Still unclear why addListener() is invoked after startListening() but not 
before.
  It can be that a place add this listener is not right and have to be moved 
into testSourceFilter(). 
  But I hope this fragment is not needed with the simplified approach.
  Otherwise, it looks good.

Thanks,
Serguei


On 7/17/18 14:55, Daniil Titov wrote:
Hi Serguei,

The test starts the event handler (nsk.share.jdi.EventHandler) and then 
iterates several times calling testSourceFilter() method passing there 
different parameters.  The testSourceFilter() method does the following:
      1.  creates a ClassPrepareRequest object
      2. registers new ClassPrepareEventListener
      3. sends a command to debuggee to a load test class 
      4. waits till the debuggee performed the command
      5. removes ClassPrepareEventListener
      6. checks if a ClassPrepareEvent was received
 

Upon its start the EventHandler creates a default list of events listeners. The 
last listener in this list handles unexpected events (that are events not 
processed by the previous listeners)

cat -n  test/hotspot/jtreg/vmTestbase/nsk/share/jdi/EventHandler.java
  /**
   251       * This method sets up default listeners.
   252       */
   253      private void createDefaultListeners() {
   254          /**
   255           * This listener catches up all unexpected events.
   256           *
   257           */
   258          addListener(
   259                  new EventListener() {
   260                      public boolean eventReceived(Event event) {
   261                          log.complain("EventHandler>  Unexpected event: 
" + event.getClass().getName());
   262                          unexpectedEventCaught = true;
   263                          return true;
   264                      }
   265                  }
   266          );
   267

On step 2 above the ClassPrepareEventListener is added at the head of the list 
of the listeners. It handles ClassPrepareEvents and prevents the next listeners 
from being invoked by returning "true" from its eventReceived(Event) method. 

With Graal turned on after step 1 the JVMTI compiler thread starts sending 
class prepare events for classes it compiles. If any of such event is 
dispatched after step 5 (when ClassPrepareEventListener  is removed) there is 
no any registered listeners to handle it and this event is handled by the 
"unexpected events listener" (see above) that marks the test as failed. 

That is why DefaultClassPrepareEventListener is needed: to process ClassPrepare 
events dispatched after ClassPrepareEventListener  is unregistered inside 
testSourceFilter() method.

Please see below the new webrev with the changes you suggested.

Webrev: http://cr.openjdk.java.net/~dtitov/8204695/webrev.02/


Thanks!

Best regards,
Daniil


From: mailto:serguei.spit...@oracle.com mailto:serguei.spit...@oracle.com
Date: Tuesday, July 17, 2018 at 1:34 PM
To: Daniil Titov mailto:daniil.x.ti...@oracle.com, 
mailto:serviceability-...@openjdk.java.netserviceability-...@openjdk.java.net 
mailto:serviceability-dev@openjdk.java.net
Subject: Re: RFR 8204695: [Graal] 
vmTestbase/nsk/jdi/ClassPrepareRequest/addSourceNameFilter/addSourceNameFilter002/addSourceNameFilter002.java
 fails

Hi Daniil,

Not sure, I fully understand the fix.
So, let's start from some questions.

Why the DefaultClassPrepareEventListener is needed?
Is it not enough to filter out the other threads in the
ClassPrepareEventListener.eventReceived() method ?
 243         eventHandler.startListening();
 244         // Add a listener to handle class prepared events fired by other ( 
e.g. compiler) threads.
 245         // The listener should be added after the event listener is 
started to ensure that it called before
 246         // the default event listener that handles unexpected events.
 247         eventHandler.addListener(new DefaultClassPrepareEventListener());

  It is still not clear why the default listener is added
  after the listening is started but not before.
  If the default listener is really needed then could you, please,
  split the lines above and L129, L160 to make a little bit shorter?
  
  I'd also suggest to replace "class prepared events" at L244
  with "ClassPrepare event" or "class prepare event".
  There is also an unneeded space in the "( e.g. compiler)".

Thanks,
Serguei


On 7/17/18 01:20, Daniil Titov wrote:
Please review the change that fix the JDI test when running with Graal.

The problem here is that the test verifies that a class prepare event is 
generated when the target VM loads a specific test class, but with Graal turned 
on additional class prepare events are generated by the compiler threads. The 
test doesn't expect them and fails. The fix ensures that additional class 
prepare events are ignored by the test and properly handled.

Bug: https://bugs.openjdk.java.net/browse/JDK-8204695 
Webrev: http://cr.openjdk.java.net/~dtitov/8204695/webrev.01/

Thanks!
--Daniil











Reply via email to