From suenaga at oss.nttdata.com Wed Jul 1 01:53:55 2020 From: suenaga at oss.nttdata.com (Yasumasa Suenaga) Date: Wed, 1 Jul 2020 10:53:55 +0900 Subject: RFR: 8242428: JVMTI thread operations should use Thread-Local Handshake In-Reply-To: References: <6c263e4c-0a83-be7a-0288-ecb2de0b7cea@oss.nttdata.com> <2ea2f5d8-5c43-a7d3-d525-cd44c4009d25@oss.nttdata.com> <65889ab4-6b7e-86fb-59cc-012520b83138@oracle.com> <4b7df6f8-c8f7-fedf-6366-b885d2235b58@oss.nttdata.com> Message-ID: <74c05dfd-ffb2-b73d-66e5-dc98752729f5@oss.nttdata.com> Hi, I uploaded new webrev. Could review again? http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.02/ >>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>> >>>>> 820 assert(SafepointSynchronize::is_at_safepoint() || >>>>> 821 java_thread->is_thread_fully_suspended(false, &debug_bits) || >>>>> 822 current_thread == java_thread->active_handshaker(), >>>>> 823 "at safepoint / handshake or target thread is suspended"); >>>>> >>>>> I don't think the suspension check is necessary, as even if the target is suspended we must still be at a safepoint or in a handshake with it. Makes me wonder if we used to allow a racy stacktrace operation on a suspended thread, assuming it would remain suspended? This function (JvmtiEnvBase::get_stack_trace()) can be called to get own stack trace. For example, we can call GetStackTrace() for current thread at JVMTI event. So I changed assert as below: ``` 820 assert(current_thread == java_thread || 821 SafepointSynchronize::is_at_safepoint() || 822 current_thread == java_thread->active_handshaker(), 823 "call by myself / at safepoint / at handshake"); ``` Thanks, Yasumasa On 2020/07/01 8:48, David Holmes wrote: > Hi Yasumasa, > > On 1/07/2020 9:05 am, Yasumasa Suenaga wrote: >> Hi David, >> >>>>> 1271???? ResourceMark rm; >>>>> >>>>> IIUC at this point the _calling_thread is the current thread, so we can use: >>>>> >>>>> ???? ResourceMark rm(_calling_thread); >> >> If so, we can call make_local() in L1272 without JavaThread (or we can pass current thread to make_local()). Is it right? >> >> ``` >> 1271???? ResourceMark rm; >> 1272 _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, thread_oop), >> 1273??????????????????????????? jt, thread_oop); >> ``` > > Sorry I got confused, _calling_thread may not be the current thread as we could be executing the handshake in the target thread itself. So the ResourceMark is correct as-is (implicitly for current thread). > > The argument to fill_frames will be used in the jvmtiStackInfo and passed back to the _calling_thread, so it must be created via make_local(_calling_thread, ...) as you presently have. > > Thanks, > David > >> Thanks, >> >> Yasumasa >> >> >> On 2020/07/01 7:05, David Holmes wrote: >>> On 1/07/2020 12:17 am, Yasumasa Suenaga wrote: >>>> Hi David, >>>> >>>> Thank you for reviewing! I will update new webrev tomorrow. >>>> >>>>> 466 class MultipleStackTracesCollector : public StackObj { >>>>> >>>>> ? 498 class VM_GetAllStackTraces : public VM_Operation { >>>>> ? 499 private: >>>>> ? 500?? JavaThread *_calling_thread; >>>>> ? 501?? jint _final_thread_count; >>>>> ? 502?? MultipleStackTracesCollector _collector; >>>>> >>>>> You can't have a StackObj as a member of another class like that as it may not be on the stack. I think MultipleStackTracesCollector should not extend any allocation class, and should always be embedded directly in another class. >>>> >>>> I'm not sure what does mean "embedded". >>>> Is it ok as below? >>>> >>>> ``` >>>> class MultipleStackTracesCollector { >>>> ??? : >>>> } >>>> >>>> class GetAllStackTraces : public VM_Operation { >>>> ?? private: >>>> ???? MultipleStackTracesCollector _collector; >>>> } >>>> ``` >>> >>> Yes that I what I meant. >>> >>> Thanks, >>> David >>> ----- >>> >>>> >>>> Thanks, >>>> >>>> Yasumasa >>>> >>>> >>>> On 2020/06/30 22:22, David Holmes wrote: >>>>> Hi Yasumasa, >>>>> >>>>> On 30/06/2020 10:05 am, Yasumasa Suenaga wrote: >>>>>> Hi David, Serguei, >>>>>> >>>>>> I updated webrev for 8242428. Could you review again? >>>>>> This change migrate to use direct handshake for GetStackTrace() and GetThreadListStackTraces() (when thread_count == 1). >>>>>> >>>>>> ?? http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.01/ >>>>> >>>>> This looks really good now! I only have a few nits below. There is one thing I don't like about it but it requires a change to the main Handshake logic to address - in JvmtiEnv::GetThreadListStackTraces you have to create a ThreadsListHandle to convert the jthread to a JavaThread, but then the Handshake::execute_direct creates another ThreadsListHandle internally. That's a waste. I will discuss with Robbin and file a RFE to have an overload of execute_direct that takes an existing TLH. Actually it's worse than that because we have another TLH in use at the entry point for the JVMTI functions, so I think there may be some scope for simplifying the use of TLH instances - future RFE. >>>>> >>>>> --- >>>>> >>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>> >>>>> ??451?? GetStackTraceClosure(JvmtiEnv *env, jint start_depth, jint max_count, >>>>> ??452??????????????????????? jvmtiFrameInfo* frame_buffer, jint* count_ptr) >>>>> ??453???? : HandshakeClosure("GetStackTrace"), >>>>> ??454?????? _env(env), _start_depth(start_depth), _max_count(max_count), >>>>> ??455?????? _frame_buffer(frame_buffer), _count_ptr(count_ptr), >>>>> ??456?????? _result(JVMTI_ERROR_THREAD_NOT_ALIVE) { >>>>> >>>>> Nit: can you do one initializer per line please. >>>>> >>>>> This looks wrong: >>>>> >>>>> 466 class MultipleStackTracesCollector : public StackObj { >>>>> >>>>> ??498 class VM_GetAllStackTraces : public VM_Operation { >>>>> ??499 private: >>>>> ??500?? JavaThread *_calling_thread; >>>>> ??501?? jint _final_thread_count; >>>>> ??502?? MultipleStackTracesCollector _collector; >>>>> >>>>> You can't have a StackObj as a member of another class like that as it may not be on the stack. I think MultipleStackTracesCollector should not extend any allocation class, and should always be embedded directly in another class. >>>>> >>>>> 481?? MultipleStackTracesCollector(JvmtiEnv *env, jint max_frame_count) { >>>>> ??482???? _env = env; >>>>> ??483???? _max_frame_count = max_frame_count; >>>>> ??484???? _frame_count_total = 0; >>>>> ??485???? _head = NULL; >>>>> ??486???? _stack_info = NULL; >>>>> ??487???? _result = JVMTI_ERROR_NONE; >>>>> ??488?? } >>>>> >>>>> As you are touching this can you change it to use an initializer list as you did for the HandshakeClosure, and please keep one item per line. >>>>> >>>>> --- >>>>> >>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>> >>>>> ??820?? assert(SafepointSynchronize::is_at_safepoint() || >>>>> ??821????????? java_thread->is_thread_fully_suspended(false, &debug_bits) || >>>>> ??822????????? current_thread == java_thread->active_handshaker(), >>>>> ??823????????? "at safepoint / handshake or target thread is suspended"); >>>>> >>>>> I don't think the suspension check is necessary, as even if the target is suspended we must still be at a safepoint or in a handshake with it. Makes me wonder if we used to allow a racy stacktrace operation on a suspended thread, assuming it would remain suspended? >>>>> >>>>> 1268?? oop thread_oop = jt->threadObj(); >>>>> 1269 >>>>> 1270?? if (!jt->is_exiting() && (jt->threadObj() != NULL)) { >>>>> >>>>> You can use thread_oop in line 1270. >>>>> >>>>> 1272 _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, thread_oop), >>>>> 1273??????????????????????????? jt, thread_oop); >>>>> >>>>> It is frustrating that this entire call chain started with a jthread reference, which we converted to a JavaThread, only to eventually need to convert it back to a jthread! I think there is some scope for simplification here but not as part of this change. >>>>> >>>>> 1271???? ResourceMark rm; >>>>> >>>>> IIUC at this point the _calling_thread is the current thread, so we can use: >>>>> >>>>> ???? ResourceMark rm(_calling_thread); >>>>> >>>>> --- >>>>> >>>>> Please add @bug lines to the tests. >>>>> >>>>> I'm still pondering the test logic but wanted to send this now. >>>>> >>>>> Thanks, >>>>> David >>>>> ----- >>>>>> VM_GetThreadListStackTrace (for GetThreadListStackTraces) and VM_GetAllStackTraces (for GetAllStackTraces) have inherited VM_GetMultipleStackTraces VM operation which provides the feature to generate jvmtiStackInfo. I modified? VM_GetMultipleStackTraces to a normal C++ class to share with HandshakeClosure for GetThreadListStackTraces (GetSingleStackTraceClosure). >>>>>> >>>>>> Also I added new testcases which test GetThreadListStackTraces() with thread_count == 1 and with all threads. >>>>>> >>>>>> This change has been tested in serviceability/jvmti serviceability/jdwp vmTestbase/nsk/jvmti vmTestbase/nsk/jdi vmTestbase/nsk/jdwp. >>>>>> >>>>>> >>>>>> Thanks, >>>>>> >>>>>> Yasumasa >>>>>> >>>>>> >>>>>> On 2020/06/24 15:50, Yasumasa Suenaga wrote: >>>>>>> Hi all, >>>>>>> >>>>>>> Please review this change: >>>>>>> >>>>>>> ?? JBS: https://bugs.openjdk.java.net/browse/JDK-8242428 >>>>>>> ?? webrev: http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.00/ >>>>>>> >>>>>>> This change replace following VM operations to direct handshake. >>>>>>> >>>>>>> ??- VM_GetFrameCount (GetFrameCount()) >>>>>>> ??- VM_GetFrameLocation (GetFrameLocation()) >>>>>>> ??- VM_GetThreadListStackTraces (GetThreadListStackTrace()) >>>>>>> ??- VM_GetCurrentLocation >>>>>>> >>>>>>> GetThreadListStackTrace() uses direct handshake if thread count == 1. In other case (thread count > 1), it would be performed as VM operation (VM_GetThreadListStackTraces). >>>>>>> Caller of VM_GetCurrentLocation (JvmtiEnvThreadState::reset_current_location()) might be called at safepoint. So I added safepoint check in its caller. >>>>>>> >>>>>>> This change has been tested in serviceability/jvmti serviceability/jdwp vmTestbase/nsk/jvmti vmTestbase/nsk/jdi vmTestbase/ns >>>>>>> k/jdwp. >>>>>>> >>>>>>> Also I tested it on submit repo, then it has execution error (mach5-one-ysuenaga-JDK-8242428-20200624-0054-12034717) due to dependency error. So I think it does not occur by this change. >>>>>>> >>>>>>> >>>>>>> Thanks, >>>>>>> >>>>>>> Yasumasa From daniil.x.titov at oracle.com Wed Jul 1 03:00:22 2020 From: daniil.x.titov at oracle.com (Daniil Titov) Date: Tue, 30 Jun 2020 20:00:22 -0700 Subject: RFR(S): 8247533: SA stack walking sometimes fails with sun.jvm.hotspot.debugger.DebuggerException: get_thread_regs failed for a lwp In-Reply-To: <4B569840-8BA6-481C-B76A-533C59C93FE5@oracle.com> References: <5e3727cd-dee9-abdf-fe7a-657fe6a4c845@oracle.com> <4B569840-8BA6-481C-B76A-533C59C93FE5@oracle.com> Message-ID: <9942F460-797D-4C5C-98D3-53057EBA2FCA@oracle.com> Hi Chris, The fix looks good to me. Best regards, Daniil On 6/25/20 13:29, Chris Plummer wrote: > Ping. I still need one more review for this. There was one updated > webev. I list it below so you don't need to dig it up in the long > email thread: >> I've updated with webrev based on the new finding that a JavaThread >> cannot be on the ThreadList after its OS thread has been destroyed >> since the JavaThread removes itself from the ThreadList, and >> therefore must be running on its OS thread. The logic of the fix is >> unchanged from the first webrev, but I updated the comments to better >> reflect what is going on. I also updated the CR: >> >> https://bugs.openjdk.java.net/browse/JDK-8247533 >> http://cr.openjdk.java.net/~cjplummer/8247533/webrev.01/index.html > > thanks, > > Chris > > On 6/17/20 1:34 PM, Chris Plummer wrote: >> Hello, >> >> Please help review the following: >> >> https://bugs.openjdk.java.net/browse/JDK-8247533 >> http://cr.openjdk.java.net/~cjplummer/8247533/webrev.00/index.html >> >> The CR contains all the needed details. Here's a summary of changes >> in each file: >> >> src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.cpp >> src/jdk.hotspot.agent/macosx/native/libsaproc/MacosxDebuggerLocal.m >> src/jdk.hotspot.agent/windows/native/libsaproc/sawindbg.cpp >> -Instead of throwing an exception when the OS ThreadID is invalid, >> print a warning. >> >> src/jdk.hotspot.agent/linux/native/libsaproc/ps_proc.c >> -Improve a print_debug message >> >> src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdThread.java >> >> src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxThread.java >> >> src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/windbg/amd64/WindbgAMD64Thread.java >> >> -Deal with the array of registers read in being null due to the OS >> ThreadID not being valid. >> >> src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java >> >> src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxDebuggerLocal.java >> >> -Fix issue with "sun.jvm.hotspot.debugger.DebuggerException" >> appearing twice when printing the exception. >> >> thanks, >> >> Chris > > From daniil.x.titov at oracle.com Wed Jul 1 05:24:46 2020 From: daniil.x.titov at oracle.com (Daniil Titov) Date: Tue, 30 Jun 2020 22:24:46 -0700 Subject: RFR(M): 8244383: jhsdb/HeapDumpTestWithActiveProcess.java fails with "AssertionFailure: illegal bci" In-Reply-To: References: <28e1b453-e1ea-0a1c-0ae0-0494b52f4b71@oracle.com> <6efbc900-732f-ee8b-5561-f9a813ebfeca@oracle.com> Message-ID: Hi Chris, The fix, in general, looks good to me. Some small comments for src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64CurrentFrameGuess.java: 1) Imports at lines 30 and 35 are not used and could be removed. 30 import sun.jvm.hotspot.interpreter.*; 35 import sun.jvm.hotspot.utilities.*; 2) Local variable "end" defined at line 189 is not used. 189 Address end = sp.addOffsetTo(regionInBytesToSearch); No new webrev is required. Thanks, Daniil ?On 6/25/20, 1:55 PM, "serviceability-dev on behalf of Chris Plummer" wrote: Ping #2. I still need one more reviewer (Thanks for the review, Dan). I updated the webrev based on Dan's comments: http://cr.openjdk.java.net/~cjplummer/8244383/webrev.01/ I can still make the simplification mentioned below if necessary. thanks, Chris On 6/23/20 11:29 AM, Chris Plummer wrote: > Ping! > > If this fix is too complicated, there is a simplification I can make, > but at the cost of abandoning some attempts to determine the current > frame when this error condition pops up. At the start of > validateInterpreterFrame() it attempts to verify that the frame is > valid by verifying that frame->method and frame->bcp are valid. This > part is pretty simple. The complicated part is everything that follows > if the verification fails. It attempts to error correct the situation > by looking at various register contents and stack contents. I could > just abandon this complicated code and return false if frame->method > and frame->bcp don't check out. Upon return, the caller's code would > be simplified to: > > if (validateInterpreterFrame(sp, fp, pc)) { > return true; // We're done. setValues() has been called > for valid interpreter frame. > } else { > return checkLastJavaSP(); > } > > So there's still a chance we can determine a valid current frame if > "last java frame" has been setup. However, if not setup we would not > be able to. This is where the complicated code in > validateInterpreterFrame() is useful because it can usually determine > the current frame, even if "last java frame" is not setup, but it's > rare enough that we run into this situation that I think failing to > get the current frame is ok. > > So if I can get a couple promises for reviews if I make this change, > I'll go ahead and do it and send out a new RFR. > > thanks, > > Chris > > On 6/18/20 5:54 PM, Chris Plummer wrote: >> [I've added runtime-dev to this SA review since understanding >> interpreter invokes (code generated by >> TemplateInterpreterGenerator::generate_normal_entry()) and stack >> walking is probably more important than understanding SA.] >> >> Hello, >> >> Please help review the following: >> >> https://bugs.openjdk.java.net/browse/JDK-8244383 >> http://cr.openjdk.java.net/~cjplummer/8244383/webrev.00/index.html >> >> The crux of the bug is when doing stack walking the topmost frame is >> in an inconsistent state because we are in the middle of pushing a >> new interpreter frame. Basically we are executing code generated by >> TemplateInterpreterGenerator::generate_normal_entry(). Since the PC >> register is in this code, SA assumes the topmost frame is an >> interpreter frame. >> >> The first issue with this interpreter frame assumption is if we >> haven't actually pushed the frame yet, then the current frame is the >> caller's frame, and could be compiled. But since SA thinks it's >> interpreted, later on it tries to convert the frame->bcp to a BCI, >> but frame->bcp is only valid for interpreter frames. Thus the >> "illegal BCI" failures. If the previous frame happened to be >> interpreted, then the existing SA code works fine. >> >> The other state of frame pushing that was problematic was when the >> new frame had been pushed, but frame->method and frame->bcp were not >> setup yet. This also would lead to "illegal BCI" later on because >> garbage would be stored in these locations. >> >> Fixing the above problems requires trying to determine the state of >> the frame push through a series of checks, and then adapting what is >> considered to be the current frame based on the outcome of the >> checks. The first things checked is that frame->method is valid (we >> can successfully instantiate a wrapper for the Method* without >> failure) and that frame->bcp is within the method. If both these pass >> then we can use the frame as-is. >> >> If the above checks fail, then we try to determine whether the issue >> is that the frame is not yet pushed and the current frame is actually >> compiled, or the frame has been pushed but not yet initialized. This >> is done by first getting the return address from the stack or RAX >> (it's location depends on how far along we are in the entry code) and >> comparing this to what is stored in frame->return_addr. If they are >> the same, then we have pushed the frame but not yet initialized it. >> In this case we use the previous frame (senderSP() and senderFP()) as >> the current frame since the current frame is not yet initialized. If >> the return address check fails, then we assume the new frame is not >> yet pushed, and and treat the current frame as compiled, even though >> PC points into the interpreter (we replace PC with RAX in this case). >> >> Comments in the code pretty well explain all the above, so it is >> probably easier to follow the logic in the code along with the >> comments rather than apply my above description to the code. >> >> I should add that it's very rare that we ever get into this special >> error handling code. This bug was very hard to reproduce initially. I >> was only able to make progress with reproducing and debugging by >> inserting delay loops in various spots in the code generated by >> TemplateInterpreterGenerator::generate_normal_entry(). By doing this >> I was able to reproduce the issue quite easily and hit all the logic >> in the new code I've added. >> >> The fix is basically entirely contained within >> AMD64CurrentFrameGuess.java. The rest of the changes are minor: >> >> src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64CurrentFrameGuess.java >> >> -Main fix for CR >> >> src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java >> >> -Added getInterpreterFrameBCP(), which is now needed by >> AMD64CurrentFrameGuess.java >> -I also simplified some code by using the existing >> getInterpreterFrameMethod() >> rather than replicating inline what it does. >> >> src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/amd64/BsdAMD64CFrame.java >> >> -I noticed the windows version of this code had some extra checks >> that were missing >> from the bsd version. I then looked at the linux version, but it had >> been heavily modified >> a short while back to leverage DWARF info to determine frames. So I >> looked at the previous >> rev and it too had these extra checks. I decided to add them to the >> BSD port. I'm not sure >> if it helps at all, but it certainly doesn't seem to do any harm. >> >> thanks, >> >> Chris >> > > From daniil.x.titov at oracle.com Wed Jul 1 17:05:45 2020 From: daniil.x.titov at oracle.com (Daniil Titov) Date: Wed, 01 Jul 2020 10:05:45 -0700 Subject: RFR: 8227337: javax/management/remote/mandatory/connection/ReconnectTest.java NoSuchObjectException no such object in table Message-ID: <119571EF-7387-4DD1-9284-24821E98135C@oracle.com> Hi Paul, Thank you for reviewing this change. You are right, in most test configurations test.timeout.factor is greater than 1.0. Best regards, Daniil ?On 6/30/20, 8:50 AM, "Hohensee, Paul" wrote: The JBS issue is non-public, but this looks fine. I assume you set test.timeout.factor to something larger than 1.0 when you run MultiThreadDeadLockTest. Thanks, Paul ?On 6/29/20, 12:43 PM, "serviceability-dev on behalf of Daniil Titov" wrote: Please review the change that fixes an intermittent tests failure. The tests javax/management/remote/mandatory/connection/ReconnectTest.java and javax/management/remote/mandatory/connection/MultiThreadDeadLockTest.java use specific settings for server timeout that in some cases (e.g. when the test is run with -Xcomp) result in JMX server connection timeout thread unexports the remote object while the client connection is still in the progress. Below is an example of a such stacktrace: java.rmi.NoSuchObjectException: no such object in table at java.rmi/sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:303) at java.rmi/sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:279) at java.rmi/sun.rmi.server.UnicastRef.invoke(UnicastRef.java:164) at jdk.remoteref/jdk.jmx.remote.internal.rmi.PRef.invoke(Unknown Source) at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl_Stub.getConnectionId(RMIConnectionImpl_Stub.java:318) at java.management.rmi/javax.management.remote.rmi.RMIConnector.getConnectionId(RMIConnector.java:385) at java.management.rmi/javax.management.remote.rmi.RMIConnector.connect(RMIConnector.java:347) at java.management/javax.management.remote.JMXConnectorFactory.connect(JMXConnectorFactory.java:270) at MultiThreadDeadLockTest.main(MultiThreadDeadLockTest.java:87) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:564) at com.sun.javatest.regtest.agent.MainWrapper$MainThread.run(MainWrapper.java:127) at java.base/java.lang.Thread.run(Thread.java:832) The fix adjusts the server timeout the tests use for "test.timeout.factor" system property. Testing: Mach5 tests are in the progress. [1] https://cr.openjdk.java.net/~dtitov/8227337/webrev.01/ [2] https://bugs.openjdk.java.net/browse/JDK-8227337 Thanks, Daniil From leonid.mesnik at oracle.com Wed Jul 1 17:48:32 2020 From: leonid.mesnik at oracle.com (Leonid Mesnik) Date: Wed, 1 Jul 2020 10:48:32 -0700 Subject: RFR (Preliminary): 8248194: Need better support for running SA tests on core files In-Reply-To: <84c27b68-d90b-c0c6-4e65-1a97aa9f2126@oracle.com> References: <04c841a1-1e38-155a-5d94-5d0e5a32c708@oracle.com> <8BD2E0F8-EE7B-4308-A058-2EC235D5212F@oracle.com> <2ac19e8a-0f0d-a215-6f92-748fd8c0c5ab@oracle.com> <6980c0f3-5ae7-a813-3adb-16cac40fe7f6@oracle.com> <84c27b68-d90b-c0c6-4e65-1a97aa9f2126@oracle.com> Message-ID: Good idea, I think. So we will have core utils which allow to ensure that core is dumped and help to find them. Leonid > On Jun 29, 2020, at 5:10 PM, Chris Plummer wrote: > > Hi Leonid, > > I'm starting to think that this should all go in a new CoreUtils.java file. I experimented with moving getCoreFileLocation() to OutputAnalyzer. It worked, but one adjustment I had to make is also moving SATestUtils.unzipCores() there also and make it private (no one else calls it). But that just got me thinking that maybe CoreUtils.java would be a better solution. I think I would put the addCoreUlimitCommand() API discussed below there also. What do you think? > > thanks, > > Chris > > On 6/28/20 5:29 PM, Chris Plummer wrote: >> Hi Leonid, >> >> I think getCoreFileLocation() can simply move to OutputAnalyzer. No need for it to be in SAUtils and be passed the String argument that comes from OutputAnalyzer.getOutput(). >> >> For the ulimit support, how about if in ProcessTools I add: >> >> public static ProcessBuilder addCoreUlimitCommand(ProcessBuilder pb); >> >> All the ulimit logic would move there from SATestUtils. It's straight forward to use this API in LingeredApp and TestJmapCore. For ClhsdbCDSCore I'll need to rework the getTestJvmCommandlineWithPrefix() code a bit, since it creates a pb, but doesn't save it. It only uses it to get the cmd String. >> >> Also, there's one new finding since I sent out the review. I found the following in CiReplayBase.java: >> >> // lets search few possible locations using process output and return existing location >> private String getCoreFileLocation(String crashOutputString) { >> >> This is identical to the code I pulled from ClhsdbCDSCore and is now in SATestUtils.parseCoreFileLocationFromOutput(). Although this is in the compiler directory, it is in fact an SA test that uses clhsdb, although directly via the CLHSDB class rather than through "jhsdb clhsdb". >> >> This also explains why ClhsdbCDSCore had some logic to move and rename the core file to "cds_core_file". I removed this logic because it seemed unnecessary, but for CiReplayBase.java it needs to be in a known location so SABase.java can find it. It's still fine for ClhsdbCDSCore to not do the rename, and renaming is independent of any code that locates the core file. >> >> I'm not going to update CiReplayBase.java as part of these changes because the two tests that use it both have issues. TestSAServer is problem listed, and when I removed it from the problem list it failed with every run on every platform. There's also TestSAClient, but it relies on client VM, which we don't support anymore. So with neither of these tests running, I'd rather not introduce changes I can't really test. >> >> However, there was something good that came out of the CiReplayBase.java discovery. I had previously noted that ClhsdbCDSCore is excluded from running on windows. When I removed the @requires for this, it failed for a reason I didn't quite understand. The complaint was about the path to java.exe when running the process that was suppose to crash, although the path looked fine. However, I found that TestSAServer ran fine on Windows, even though it was basically the process launching code for causing the crash. I looked closer and found one difference. In getTestJvmCommandlineWithPrefix(), which both tests have, the CiReplayBase version had some extra code for Windows: >> >> return new String[]{"sh", "-c", prefix >> + (Platform.isWindows() ? cmd.replace('\\', '/').replace(";", "\\;").replace("|", "\\|") : cmd)}; >> >> So on Windows it's doing a path conversion. Once I started doing the same with ClhsdbCDSCore, it started to run fine on Windwos also. >> >> thanks, >> >> Chris >> >> On 6/26/20 8:42 PM, Chris Plummer wrote: >>> Hi Leonid, >>> >>> On 6/26/20 7:51 PM, Leonid Mesnik wrote: >>>> Hi >>>> >>>> The idea basically looks good. I think it just make a sense to polish it a little bit to hide "sh" usage from test and get core from OutputAnalyzer. >>> Ok, I'll look into both of those. >>>> Also, there is a 'CrashApp' in ClhsdbCDSCore.java. Makes it sense to unify it with LingeredApp crasher? Currently, it uses Unsafe to crash application. >>> Yes, I purposely didn't not make that change. My main goal with the LingeredApp changes is to make it easier to make existing LingeredApp SA tests run on both a live process and on a core, and my main goal with ClhsdbCDSCore and TestJmapCore was to move the core finding code and ulimit code to a common location that could be reused by other tests. >>> >>> Keep in mind that ClhsdbLauncher and LingeredApp are independent of each other. You can have a LingeredApp tests that use or don't use ClhsdbLauncher, and you can have a non-LingeredApp tests that use or don't use ClhsdbLauncher. So I didn't want to go down the path of changing ClhsdbCDSCore (a non LingeredApp test) to use LingeredApp. Likewise I did not change TestJmapCore to use LingeredApp or ClhsdbLauncher. Possibly there is good reason to convert some of the tests to start using LingeredApp and/or ClhsdbLauncher, but that should be done under a separate RFE. >>> >>>> >>>> Also, crashes are used in other tests, I see some implementations in >>>> open/test/hotspot/jtreg/vmTestbase/vm/share/vmcrasher >>> I don't see vmcrasher being used by any tests. In any case, my first attempt went down the Unsafe path to produce a crash. The issue is that it forces every user of LingeredApp to include the @module for Unsafe. I also tried using a WhiteBox API. That was worse, also requiring every user of LingeredApp to include an @module, plus the tests that actually want to cause a crash need to @build WhiteBox.java and then do the classfile install. It also required additional module related hacks in LingeredApp. The issue with my current solution is how to get libLingeredApp.c to compile has not been settled on. I'm still waiting for an answer from the build team. >>>> >>>> So it would be nice to have some common way to crash hotspot. >>> I can see possibly moving the crashing code out of LingeredApp and into a native lib that non-LingeredApp tests can use, although that really is just a very small part of the changes to LingeredApp. For the most part the changes would look the same except you would call a different API to cause the crash. >>>> >>>> Leonid >>>> >>> Thanks for having a look. >>> >>> Chris >>>>> On Jun 25, 2020, at 2:41 PM, Chris Plummer wrote: >>>>> >>>>> Hello, >>>>> >>>>> Please help with a preliminary review of changes to add better support for writing SA tests that work on core files: >>>>> >>>>> https://bugs.openjdk.java.net/browse/JDK-8248194 >>>>> http://cr.openjdk.java.net/~cjplummer/8248194/webrev.00/index.html >>>>> >>>>> As pointed out, this is a preliminary review. I suspect there will be some feedback for changes/improvements. Also, I still need to work out a final solution for how to get LingeredApp to produce a crash. What I currently have works but is somewhat of a hack w.r.t. the makefile change, so you can ignore the makefiile change for now. I'm working on a more proper solution with the build team. >>>>> >>>>> As outlined in the CR, these are the 3 main goals of this CR: >>>>> >>>>> 1. SATestUtils should include support for finding the core file. This includes parsing the output of the crashed process to locate where the core file was saved, and returning this location to the user. >>>>> >>>>> 2. SATestUtils should include support for adding the "ulimit -c unlimited" prefix to the command that will produce the core file, allowing the overriding of any lower limit so we can be sure the core file will be produced. >>>>> >>>>> 3. LingeredApp should include support for producing a core file. >>>>> >>>>> As proof of concept for these 3 changes in test library support, I'm updating the following 3 tests: >>>>> >>>>> ClhsdbCDSCore.java: Use the SATestUtils support listed above. This test does not use LingeredApp, so those improvements don't apply. >>>>> >>>>> TestJmapCore.java: Use the SATestUtils support listed above. This test does not use LingeredApp, so those improvements don't apply. >>>>> >>>>> ClhsdbFindPC.java: Use all the above features, including having LingeredApp produce a core file. This is the only test modified to start testing on core files that didn't previously do so. It still also tests on a live process. >>>>> >>>>> In the future more Clhsdb tests will be converted to work on core files in a manner similar to ClhsdbFindPC. >>>>> >>>>> The new SATestUtils code is borrowed from (more like ripped out of) ClhsdbCDSCore.java and TestJmapCore.java. They both had a lot of code dedicated to finding the core file and also applying "ulimit -c unlimitted" if necessary, but didn't do so in quite the same way. Now both these tests share code in SATestUtils.java. One thing I did drop is TestJmapCore.java use of ":KILLED_PID" in the output to help find the core file. It's no longer necessary based on the smarter core locating code I pulled from ClhsdbCDSCore.java. >>>>> >>>>> thanks, >>>>> >>>>> Chris >>> >> >> > > From leonid.mesnik at oracle.com Wed Jul 1 18:05:50 2020 From: leonid.mesnik at oracle.com (Leonid Mesnik) Date: Wed, 1 Jul 2020 11:05:50 -0700 Subject: RFR: 8248658: Remove vmTestbase/vm/share/vmcrasher Message-ID: <94402391-8422-474F-980C-56E7D6DC2A42@oracle.com> Hi Could you please review fix which removes unused code. webrev: http://cr.openjdk.java.net/~lmesnik/8248658/webrev.00/ bug: https://bugs.openjdk.java.net/browse/JDK-8248658 -------------- next part -------------- An HTML attachment was scrubbed... URL: From chris.plummer at oracle.com Wed Jul 1 18:32:23 2020 From: chris.plummer at oracle.com (Chris Plummer) Date: Wed, 1 Jul 2020 11:32:23 -0700 Subject: RFR: 8248658: Remove vmTestbase/vm/share/vmcrasher In-Reply-To: <94402391-8422-474F-980C-56E7D6DC2A42@oracle.com> References: <94402391-8422-474F-980C-56E7D6DC2A42@oracle.com> Message-ID: <03971bd5-0f4f-492c-2a10-222807e61247@oracle.com> Looks good. Chris On 7/1/20 11:05 AM, Leonid Mesnik wrote: > Hi > > Could you please review fix which removes unused code. > > webrev: http://cr.openjdk.java.net/~lmesnik/8248658/webrev.00/ > bug: https://bugs.openjdk.java.net/browse/JDK-8248658 From serguei.spitsyn at oracle.com Wed Jul 1 19:56:08 2020 From: serguei.spitsyn at oracle.com (serguei.spitsyn at oracle.com) Date: Wed, 1 Jul 2020 12:56:08 -0700 Subject: RFR: 8248658: Remove vmTestbase/vm/share/vmcrasher In-Reply-To: <03971bd5-0f4f-492c-2a10-222807e61247@oracle.com> References: <94402391-8422-474F-980C-56E7D6DC2A42@oracle.com> <03971bd5-0f4f-492c-2a10-222807e61247@oracle.com> Message-ID: Hi Leonid, LGTM++ Thanks, Serguei On 7/1/20 11:32, Chris Plummer wrote: > Looks good. > > Chris > > On 7/1/20 11:05 AM, Leonid Mesnik wrote: >> Hi >> >> Could you please review fix which removes unused code. >> >> webrev: http://cr.openjdk.java.net/~lmesnik/8248658/webrev.00/ >> bug: https://bugs.openjdk.java.net/browse/JDK-8248658 > From david.holmes at oracle.com Thu Jul 2 06:05:25 2020 From: david.holmes at oracle.com (David Holmes) Date: Thu, 2 Jul 2020 16:05:25 +1000 Subject: RFR: 8242428: JVMTI thread operations should use Thread-Local Handshake In-Reply-To: <74c05dfd-ffb2-b73d-66e5-dc98752729f5@oss.nttdata.com> References: <6c263e4c-0a83-be7a-0288-ecb2de0b7cea@oss.nttdata.com> <2ea2f5d8-5c43-a7d3-d525-cd44c4009d25@oss.nttdata.com> <65889ab4-6b7e-86fb-59cc-012520b83138@oracle.com> <4b7df6f8-c8f7-fedf-6366-b885d2235b58@oss.nttdata.com> <74c05dfd-ffb2-b73d-66e5-dc98752729f5@oss.nttdata.com> Message-ID: Hi Yasumasa, On 1/07/2020 11:53 am, Yasumasa Suenaga wrote: > Hi, > > I uploaded new webrev. Could review again? > > ? http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.02/ Updates look fine - thanks. One minor nit: 1274 _collector.allocate_and_fill_stacks(1); 1275 _collector.set_result(JVMTI_ERROR_NONE); In the other places where you use _collector you rely on result being initialized to JVMTI_ERROR_NONE, rather than setting it directly after allocate_and_fill_stacks(). > >>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>> >>>>>> ? 820?? assert(SafepointSynchronize::is_at_safepoint() || >>>>>> ? 821????????? java_thread->is_thread_fully_suspended(false, >>>>>> &debug_bits) || >>>>>> ? 822????????? current_thread == java_thread->active_handshaker(), >>>>>> ? 823????????? "at safepoint / handshake or target thread is >>>>>> suspended"); >>>>>> >>>>>> I don't think the suspension check is necessary, as even if the >>>>>> target is suspended we must still be at a safepoint or in a >>>>>> handshake with it. Makes me wonder if we used to allow a racy >>>>>> stacktrace operation on a suspended thread, assuming it would >>>>>> remain suspended? > > This function (JvmtiEnvBase::get_stack_trace()) can be called to get own > stack trace. For example, we can call GetStackTrace() for current thread > at JVMTI event. > So I changed assert as below: > > ``` > ?820?? assert(current_thread == java_thread || > ?821????????? SafepointSynchronize::is_at_safepoint() || > ?822????????? current_thread == java_thread->active_handshaker(), > ?823????????? "call by myself / at safepoint / at handshake"); > ``` Yep good catch. I hope current tests caught that. Speaking of tests ... In the native code I think you need to check the success of all JNI methods that can throw exceptions - otherwise I believe the tests may trigger warnings if -Xcheck:jni is used with them. See for example: test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/libHeapMonitorTest.cpp In the Java code the target thread: 45 public void run() { 46 try { 47 synchronized (lock) { 48 lock.wait(); 49 System.out.println("OK"); 50 } is potentially susceptible to spurious wakeups. Using a CountDownLatch would be robust. Thanks, David ----- > > Thanks, > > Yasumasa > > > On 2020/07/01 8:48, David Holmes wrote: >> Hi Yasumasa, >> >> On 1/07/2020 9:05 am, Yasumasa Suenaga wrote: >>> Hi David, >>> >>>>>> 1271???? ResourceMark rm; >>>>>> >>>>>> IIUC at this point the _calling_thread is the current thread, so >>>>>> we can use: >>>>>> >>>>>> ???? ResourceMark rm(_calling_thread); >>> >>> If so, we can call make_local() in L1272 without JavaThread (or we >>> can pass current thread to make_local()). Is it right? >>> >>> ``` >>> 1271???? ResourceMark rm; >>> 1272 >>> _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, >>> thread_oop), >>> 1273??????????????????????????? jt, thread_oop); >>> ``` >> >> Sorry I got confused, _calling_thread may not be the current thread as >> we could be executing the handshake in the target thread itself. So >> the ResourceMark is correct as-is (implicitly for current thread). >> >> The argument to fill_frames will be used in the jvmtiStackInfo and >> passed back to the _calling_thread, so it must be created via >> make_local(_calling_thread, ...) as you presently have. >> >> Thanks, >> David >> >>> Thanks, >>> >>> Yasumasa >>> >>> >>> On 2020/07/01 7:05, David Holmes wrote: >>>> On 1/07/2020 12:17 am, Yasumasa Suenaga wrote: >>>>> Hi David, >>>>> >>>>> Thank you for reviewing! I will update new webrev tomorrow. >>>>> >>>>>> 466 class MultipleStackTracesCollector : public StackObj { >>>>>> >>>>>> ? 498 class VM_GetAllStackTraces : public VM_Operation { >>>>>> ? 499 private: >>>>>> ? 500?? JavaThread *_calling_thread; >>>>>> ? 501?? jint _final_thread_count; >>>>>> ? 502?? MultipleStackTracesCollector _collector; >>>>>> >>>>>> You can't have a StackObj as a member of another class like that >>>>>> as it may not be on the stack. I think >>>>>> MultipleStackTracesCollector should not extend any allocation >>>>>> class, and should always be embedded directly in another class. >>>>> >>>>> I'm not sure what does mean "embedded". >>>>> Is it ok as below? >>>>> >>>>> ``` >>>>> class MultipleStackTracesCollector { >>>>> ??? : >>>>> } >>>>> >>>>> class GetAllStackTraces : public VM_Operation { >>>>> ?? private: >>>>> ???? MultipleStackTracesCollector _collector; >>>>> } >>>>> ``` >>>> >>>> Yes that I what I meant. >>>> >>>> Thanks, >>>> David >>>> ----- >>>> >>>>> >>>>> Thanks, >>>>> >>>>> Yasumasa >>>>> >>>>> >>>>> On 2020/06/30 22:22, David Holmes wrote: >>>>>> Hi Yasumasa, >>>>>> >>>>>> On 30/06/2020 10:05 am, Yasumasa Suenaga wrote: >>>>>>> Hi David, Serguei, >>>>>>> >>>>>>> I updated webrev for 8242428. Could you review again? >>>>>>> This change migrate to use direct handshake for GetStackTrace() >>>>>>> and GetThreadListStackTraces() (when thread_count == 1). >>>>>>> >>>>>>> ?? http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.01/ >>>>>> >>>>>> This looks really good now! I only have a few nits below. There is >>>>>> one thing I don't like about it but it requires a change to the >>>>>> main Handshake logic to address - in >>>>>> JvmtiEnv::GetThreadListStackTraces you have to create a >>>>>> ThreadsListHandle to convert the jthread to a JavaThread, but then >>>>>> the Handshake::execute_direct creates another ThreadsListHandle >>>>>> internally. That's a waste. I will discuss with Robbin and file a >>>>>> RFE to have an overload of execute_direct that takes an existing >>>>>> TLH. Actually it's worse than that because we have another TLH in >>>>>> use at the entry point for the JVMTI functions, so I think there >>>>>> may be some scope for simplifying the use of TLH instances - >>>>>> future RFE. >>>>>> >>>>>> --- >>>>>> >>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>> >>>>>> ??451?? GetStackTraceClosure(JvmtiEnv *env, jint start_depth, jint >>>>>> max_count, >>>>>> ??452??????????????????????? jvmtiFrameInfo* frame_buffer, jint* >>>>>> count_ptr) >>>>>> ??453???? : HandshakeClosure("GetStackTrace"), >>>>>> ??454?????? _env(env), _start_depth(start_depth), >>>>>> _max_count(max_count), >>>>>> ??455?????? _frame_buffer(frame_buffer), _count_ptr(count_ptr), >>>>>> ??456?????? _result(JVMTI_ERROR_THREAD_NOT_ALIVE) { >>>>>> >>>>>> Nit: can you do one initializer per line please. >>>>>> >>>>>> This looks wrong: >>>>>> >>>>>> 466 class MultipleStackTracesCollector : public StackObj { >>>>>> >>>>>> ??498 class VM_GetAllStackTraces : public VM_Operation { >>>>>> ??499 private: >>>>>> ??500?? JavaThread *_calling_thread; >>>>>> ??501?? jint _final_thread_count; >>>>>> ??502?? MultipleStackTracesCollector _collector; >>>>>> >>>>>> You can't have a StackObj as a member of another class like that >>>>>> as it may not be on the stack. I think >>>>>> MultipleStackTracesCollector should not extend any allocation >>>>>> class, and should always be embedded directly in another class. >>>>>> >>>>>> 481?? MultipleStackTracesCollector(JvmtiEnv *env, jint >>>>>> max_frame_count) { >>>>>> ??482???? _env = env; >>>>>> ??483???? _max_frame_count = max_frame_count; >>>>>> ??484???? _frame_count_total = 0; >>>>>> ??485???? _head = NULL; >>>>>> ??486???? _stack_info = NULL; >>>>>> ??487???? _result = JVMTI_ERROR_NONE; >>>>>> ??488?? } >>>>>> >>>>>> As you are touching this can you change it to use an initializer >>>>>> list as you did for the HandshakeClosure, and please keep one item >>>>>> per line. >>>>>> >>>>>> --- >>>>>> >>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>> >>>>>> ??820?? assert(SafepointSynchronize::is_at_safepoint() || >>>>>> ??821????????? java_thread->is_thread_fully_suspended(false, >>>>>> &debug_bits) || >>>>>> ??822????????? current_thread == java_thread->active_handshaker(), >>>>>> ??823????????? "at safepoint / handshake or target thread is >>>>>> suspended"); >>>>>> >>>>>> I don't think the suspension check is necessary, as even if the >>>>>> target is suspended we must still be at a safepoint or in a >>>>>> handshake with it. Makes me wonder if we used to allow a racy >>>>>> stacktrace operation on a suspended thread, assuming it would >>>>>> remain suspended? >>>>>> >>>>>> 1268?? oop thread_oop = jt->threadObj(); >>>>>> 1269 >>>>>> 1270?? if (!jt->is_exiting() && (jt->threadObj() != NULL)) { >>>>>> >>>>>> You can use thread_oop in line 1270. >>>>>> >>>>>> 1272 >>>>>> _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, >>>>>> thread_oop), >>>>>> 1273??????????????????????????? jt, thread_oop); >>>>>> >>>>>> It is frustrating that this entire call chain started with a >>>>>> jthread reference, which we converted to a JavaThread, only to >>>>>> eventually need to convert it back to a jthread! I think there is >>>>>> some scope for simplification here but not as part of this change. >>>>>> >>>>>> 1271???? ResourceMark rm; >>>>>> >>>>>> IIUC at this point the _calling_thread is the current thread, so >>>>>> we can use: >>>>>> >>>>>> ???? ResourceMark rm(_calling_thread); >>>>>> >>>>>> --- >>>>>> >>>>>> Please add @bug lines to the tests. >>>>>> >>>>>> I'm still pondering the test logic but wanted to send this now. >>>>>> >>>>>> Thanks, >>>>>> David >>>>>> ----- >>>>>>> VM_GetThreadListStackTrace (for GetThreadListStackTraces) and >>>>>>> VM_GetAllStackTraces (for GetAllStackTraces) have inherited >>>>>>> VM_GetMultipleStackTraces VM operation which provides the feature >>>>>>> to generate jvmtiStackInfo. I modified? VM_GetMultipleStackTraces >>>>>>> to a normal C++ class to share with HandshakeClosure for >>>>>>> GetThreadListStackTraces (GetSingleStackTraceClosure). >>>>>>> >>>>>>> Also I added new testcases which test GetThreadListStackTraces() >>>>>>> with thread_count == 1 and with all threads. >>>>>>> >>>>>>> This change has been tested in serviceability/jvmti >>>>>>> serviceability/jdwp vmTestbase/nsk/jvmti vmTestbase/nsk/jdi >>>>>>> vmTestbase/nsk/jdwp. >>>>>>> >>>>>>> >>>>>>> Thanks, >>>>>>> >>>>>>> Yasumasa >>>>>>> >>>>>>> >>>>>>> On 2020/06/24 15:50, Yasumasa Suenaga wrote: >>>>>>>> Hi all, >>>>>>>> >>>>>>>> Please review this change: >>>>>>>> >>>>>>>> ?? JBS: https://bugs.openjdk.java.net/browse/JDK-8242428 >>>>>>>> ?? webrev: >>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.00/ >>>>>>>> >>>>>>>> This change replace following VM operations to direct handshake. >>>>>>>> >>>>>>>> ??- VM_GetFrameCount (GetFrameCount()) >>>>>>>> ??- VM_GetFrameLocation (GetFrameLocation()) >>>>>>>> ??- VM_GetThreadListStackTraces (GetThreadListStackTrace()) >>>>>>>> ??- VM_GetCurrentLocation >>>>>>>> >>>>>>>> GetThreadListStackTrace() uses direct handshake if thread count >>>>>>>> == 1. In other case (thread count > 1), it would be performed as >>>>>>>> VM operation (VM_GetThreadListStackTraces). >>>>>>>> Caller of VM_GetCurrentLocation >>>>>>>> (JvmtiEnvThreadState::reset_current_location()) might be called >>>>>>>> at safepoint. So I added safepoint check in its caller. >>>>>>>> >>>>>>>> This change has been tested in serviceability/jvmti >>>>>>>> serviceability/jdwp vmTestbase/nsk/jvmti vmTestbase/nsk/jdi >>>>>>>> vmTestbase/ns >>>>>>>> k/jdwp. >>>>>>>> >>>>>>>> Also I tested it on submit repo, then it has execution error >>>>>>>> (mach5-one-ysuenaga-JDK-8242428-20200624-0054-12034717) due to >>>>>>>> dependency error. So I think it does not occur by this change. >>>>>>>> >>>>>>>> >>>>>>>> Thanks, >>>>>>>> >>>>>>>> Yasumasa From suenaga at oss.nttdata.com Thu Jul 2 09:19:55 2020 From: suenaga at oss.nttdata.com (Yasumasa Suenaga) Date: Thu, 2 Jul 2020 18:19:55 +0900 Subject: RFR: 8242428: JVMTI thread operations should use Thread-Local Handshake In-Reply-To: References: <6c263e4c-0a83-be7a-0288-ecb2de0b7cea@oss.nttdata.com> <2ea2f5d8-5c43-a7d3-d525-cd44c4009d25@oss.nttdata.com> <65889ab4-6b7e-86fb-59cc-012520b83138@oracle.com> <4b7df6f8-c8f7-fedf-6366-b885d2235b58@oss.nttdata.com> <74c05dfd-ffb2-b73d-66e5-dc98752729f5@oss.nttdata.com> Message-ID: <763793b1-9506-44c6-0681-1c71c44a44fd@oss.nttdata.com> Hi David, I upload new webrev. Could you review again? http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.03/ On 2020/07/02 15:05, David Holmes wrote: > Hi Yasumasa, > > On 1/07/2020 11:53 am, Yasumasa Suenaga wrote: >> Hi, >> >> I uploaded new webrev. Could review again? >> >> ?? http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.02/ > > Updates look fine - thanks. > > One minor nit: > > 1274???? _collector.allocate_and_fill_stacks(1); > 1275???? _collector.set_result(JVMTI_ERROR_NONE); > > In the other places where you use _collector you rely on result being initialized to JVMTI_ERROR_NONE, rather than setting it directly after allocate_and_fill_stacks(). Fixed. >>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>> >>>>>>> ? 820?? assert(SafepointSynchronize::is_at_safepoint() || >>>>>>> ? 821????????? java_thread->is_thread_fully_suspended(false, &debug_bits) || >>>>>>> ? 822????????? current_thread == java_thread->active_handshaker(), >>>>>>> ? 823????????? "at safepoint / handshake or target thread is suspended"); >>>>>>> >>>>>>> I don't think the suspension check is necessary, as even if the target is suspended we must still be at a safepoint or in a handshake with it. Makes me wonder if we used to allow a racy stacktrace operation on a suspended thread, assuming it would remain suspended? >> >> This function (JvmtiEnvBase::get_stack_trace()) can be called to get own stack trace. For example, we can call GetStackTrace() for current thread at JVMTI event. >> So I changed assert as below: >> >> ``` >> ??820?? assert(current_thread == java_thread || >> ??821????????? SafepointSynchronize::is_at_safepoint() || >> ??822????????? current_thread == java_thread->active_handshaker(), >> ??823????????? "call by myself / at safepoint / at handshake"); >> ``` > > Yep good catch. I hope current tests caught that. They would be tested in vmTestbase/nsk/jvmti/GetStackTrace/getstacktr001/ (own call stacks), and getstacktr003 (call stacks in other thread). > Speaking of tests ... > > In the native code I think you need to check the success of all JNI methods that can throw exceptions - otherwise I believe the tests may trigger warnings if -Xcheck:jni is used with them. See for example: > > test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/libHeapMonitorTest.cpp I updated testcases to check JNI and JVMTI function calls. > In the Java code the target thread: > > ? 45???? public void run() { > ? 46?????? try { > ? 47?????????? synchronized (lock) { > ? 48?????????????? lock.wait(); > ? 49?????????????? System.out.println("OK"); > ? 50?????????? } > > is potentially susceptible to spurious wakeups. Using a CountDownLatch would be robust. Fixed. Thanks, Yasumasa > Thanks, > David > ----- > >> >> Thanks, >> >> Yasumasa >> >> >> On 2020/07/01 8:48, David Holmes wrote: >>> Hi Yasumasa, >>> >>> On 1/07/2020 9:05 am, Yasumasa Suenaga wrote: >>>> Hi David, >>>> >>>>>>> 1271???? ResourceMark rm; >>>>>>> >>>>>>> IIUC at this point the _calling_thread is the current thread, so we can use: >>>>>>> >>>>>>> ???? ResourceMark rm(_calling_thread); >>>> >>>> If so, we can call make_local() in L1272 without JavaThread (or we can pass current thread to make_local()). Is it right? >>>> >>>> ``` >>>> 1271???? ResourceMark rm; >>>> 1272 _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, thread_oop), >>>> 1273??????????????????????????? jt, thread_oop); >>>> ``` >>> >>> Sorry I got confused, _calling_thread may not be the current thread as we could be executing the handshake in the target thread itself. So the ResourceMark is correct as-is (implicitly for current thread). >>> >>> The argument to fill_frames will be used in the jvmtiStackInfo and passed back to the _calling_thread, so it must be created via make_local(_calling_thread, ...) as you presently have. >>> >>> Thanks, >>> David >>> >>>> Thanks, >>>> >>>> Yasumasa >>>> >>>> >>>> On 2020/07/01 7:05, David Holmes wrote: >>>>> On 1/07/2020 12:17 am, Yasumasa Suenaga wrote: >>>>>> Hi David, >>>>>> >>>>>> Thank you for reviewing! I will update new webrev tomorrow. >>>>>> >>>>>>> 466 class MultipleStackTracesCollector : public StackObj { >>>>>>> >>>>>>> ? 498 class VM_GetAllStackTraces : public VM_Operation { >>>>>>> ? 499 private: >>>>>>> ? 500?? JavaThread *_calling_thread; >>>>>>> ? 501?? jint _final_thread_count; >>>>>>> ? 502?? MultipleStackTracesCollector _collector; >>>>>>> >>>>>>> You can't have a StackObj as a member of another class like that as it may not be on the stack. I think MultipleStackTracesCollector should not extend any allocation class, and should always be embedded directly in another class. >>>>>> >>>>>> I'm not sure what does mean "embedded". >>>>>> Is it ok as below? >>>>>> >>>>>> ``` >>>>>> class MultipleStackTracesCollector { >>>>>> ??? : >>>>>> } >>>>>> >>>>>> class GetAllStackTraces : public VM_Operation { >>>>>> ?? private: >>>>>> ???? MultipleStackTracesCollector _collector; >>>>>> } >>>>>> ``` >>>>> >>>>> Yes that I what I meant. >>>>> >>>>> Thanks, >>>>> David >>>>> ----- >>>>> >>>>>> >>>>>> Thanks, >>>>>> >>>>>> Yasumasa >>>>>> >>>>>> >>>>>> On 2020/06/30 22:22, David Holmes wrote: >>>>>>> Hi Yasumasa, >>>>>>> >>>>>>> On 30/06/2020 10:05 am, Yasumasa Suenaga wrote: >>>>>>>> Hi David, Serguei, >>>>>>>> >>>>>>>> I updated webrev for 8242428. Could you review again? >>>>>>>> This change migrate to use direct handshake for GetStackTrace() and GetThreadListStackTraces() (when thread_count == 1). >>>>>>>> >>>>>>>> ?? http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.01/ >>>>>>> >>>>>>> This looks really good now! I only have a few nits below. There is one thing I don't like about it but it requires a change to the main Handshake logic to address - in JvmtiEnv::GetThreadListStackTraces you have to create a ThreadsListHandle to convert the jthread to a JavaThread, but then the Handshake::execute_direct creates another ThreadsListHandle internally. That's a waste. I will discuss with Robbin and file a RFE to have an overload of execute_direct that takes an existing TLH. Actually it's worse than that because we have another TLH in use at the entry point for the JVMTI functions, so I think there may be some scope for simplifying the use of TLH instances - future RFE. >>>>>>> >>>>>>> --- >>>>>>> >>>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>>> >>>>>>> ??451?? GetStackTraceClosure(JvmtiEnv *env, jint start_depth, jint max_count, >>>>>>> ??452??????????????????????? jvmtiFrameInfo* frame_buffer, jint* count_ptr) >>>>>>> ??453???? : HandshakeClosure("GetStackTrace"), >>>>>>> ??454?????? _env(env), _start_depth(start_depth), _max_count(max_count), >>>>>>> ??455?????? _frame_buffer(frame_buffer), _count_ptr(count_ptr), >>>>>>> ??456?????? _result(JVMTI_ERROR_THREAD_NOT_ALIVE) { >>>>>>> >>>>>>> Nit: can you do one initializer per line please. >>>>>>> >>>>>>> This looks wrong: >>>>>>> >>>>>>> 466 class MultipleStackTracesCollector : public StackObj { >>>>>>> >>>>>>> ??498 class VM_GetAllStackTraces : public VM_Operation { >>>>>>> ??499 private: >>>>>>> ??500?? JavaThread *_calling_thread; >>>>>>> ??501?? jint _final_thread_count; >>>>>>> ??502?? MultipleStackTracesCollector _collector; >>>>>>> >>>>>>> You can't have a StackObj as a member of another class like that as it may not be on the stack. I think MultipleStackTracesCollector should not extend any allocation class, and should always be embedded directly in another class. >>>>>>> >>>>>>> 481?? MultipleStackTracesCollector(JvmtiEnv *env, jint max_frame_count) { >>>>>>> ??482???? _env = env; >>>>>>> ??483???? _max_frame_count = max_frame_count; >>>>>>> ??484???? _frame_count_total = 0; >>>>>>> ??485???? _head = NULL; >>>>>>> ??486???? _stack_info = NULL; >>>>>>> ??487???? _result = JVMTI_ERROR_NONE; >>>>>>> ??488?? } >>>>>>> >>>>>>> As you are touching this can you change it to use an initializer list as you did for the HandshakeClosure, and please keep one item per line. >>>>>>> >>>>>>> --- >>>>>>> >>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>> >>>>>>> ??820?? assert(SafepointSynchronize::is_at_safepoint() || >>>>>>> ??821????????? java_thread->is_thread_fully_suspended(false, &debug_bits) || >>>>>>> ??822????????? current_thread == java_thread->active_handshaker(), >>>>>>> ??823????????? "at safepoint / handshake or target thread is suspended"); >>>>>>> >>>>>>> I don't think the suspension check is necessary, as even if the target is suspended we must still be at a safepoint or in a handshake with it. Makes me wonder if we used to allow a racy stacktrace operation on a suspended thread, assuming it would remain suspended? >>>>>>> >>>>>>> 1268?? oop thread_oop = jt->threadObj(); >>>>>>> 1269 >>>>>>> 1270?? if (!jt->is_exiting() && (jt->threadObj() != NULL)) { >>>>>>> >>>>>>> You can use thread_oop in line 1270. >>>>>>> >>>>>>> 1272 _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, thread_oop), >>>>>>> 1273??????????????????????????? jt, thread_oop); >>>>>>> >>>>>>> It is frustrating that this entire call chain started with a jthread reference, which we converted to a JavaThread, only to eventually need to convert it back to a jthread! I think there is some scope for simplification here but not as part of this change. >>>>>>> >>>>>>> 1271???? ResourceMark rm; >>>>>>> >>>>>>> IIUC at this point the _calling_thread is the current thread, so we can use: >>>>>>> >>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>> >>>>>>> --- >>>>>>> >>>>>>> Please add @bug lines to the tests. >>>>>>> >>>>>>> I'm still pondering the test logic but wanted to send this now. >>>>>>> >>>>>>> Thanks, >>>>>>> David >>>>>>> ----- >>>>>>>> VM_GetThreadListStackTrace (for GetThreadListStackTraces) and VM_GetAllStackTraces (for GetAllStackTraces) have inherited VM_GetMultipleStackTraces VM operation which provides the feature to generate jvmtiStackInfo. I modified? VM_GetMultipleStackTraces to a normal C++ class to share with HandshakeClosure for GetThreadListStackTraces (GetSingleStackTraceClosure). >>>>>>>> >>>>>>>> Also I added new testcases which test GetThreadListStackTraces() with thread_count == 1 and with all threads. >>>>>>>> >>>>>>>> This change has been tested in serviceability/jvmti serviceability/jdwp vmTestbase/nsk/jvmti vmTestbase/nsk/jdi vmTestbase/nsk/jdwp. >>>>>>>> >>>>>>>> >>>>>>>> Thanks, >>>>>>>> >>>>>>>> Yasumasa >>>>>>>> >>>>>>>> >>>>>>>> On 2020/06/24 15:50, Yasumasa Suenaga wrote: >>>>>>>>> Hi all, >>>>>>>>> >>>>>>>>> Please review this change: >>>>>>>>> >>>>>>>>> ?? JBS: https://bugs.openjdk.java.net/browse/JDK-8242428 >>>>>>>>> ?? webrev: http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.00/ >>>>>>>>> >>>>>>>>> This change replace following VM operations to direct handshake. >>>>>>>>> >>>>>>>>> ??- VM_GetFrameCount (GetFrameCount()) >>>>>>>>> ??- VM_GetFrameLocation (GetFrameLocation()) >>>>>>>>> ??- VM_GetThreadListStackTraces (GetThreadListStackTrace()) >>>>>>>>> ??- VM_GetCurrentLocation >>>>>>>>> >>>>>>>>> GetThreadListStackTrace() uses direct handshake if thread count == 1. In other case (thread count > 1), it would be performed as VM operation (VM_GetThreadListStackTraces). >>>>>>>>> Caller of VM_GetCurrentLocation (JvmtiEnvThreadState::reset_current_location()) might be called at safepoint. So I added safepoint check in its caller. >>>>>>>>> >>>>>>>>> This change has been tested in serviceability/jvmti serviceability/jdwp vmTestbase/nsk/jvmti vmTestbase/nsk/jdi vmTestbase/ns >>>>>>>>> k/jdwp. >>>>>>>>> >>>>>>>>> Also I tested it on submit repo, then it has execution error (mach5-one-ysuenaga-JDK-8242428-20200624-0054-12034717) due to dependency error. So I think it does not occur by this change. >>>>>>>>> >>>>>>>>> >>>>>>>>> Thanks, >>>>>>>>> >>>>>>>>> Yasumasa From chris.plummer at oracle.com Thu Jul 2 14:21:14 2020 From: chris.plummer at oracle.com (Chris Plummer) Date: Thu, 2 Jul 2020 07:21:14 -0700 Subject: RFR (L): 8248194: Need better support for running SA tests on core files Message-ID: <5760b18e-7ba2-2fdd-94af-1e555cef74cc@oracle.com> [Note, the following changes only impact serviceability tests, but I am adding some test library code to assist with creating and finding core files, and I thought others on hotspot-dev might have an interest in that.] Hello, Please help review the following changes to add better support for writing SA tests that work on core files: https://bugs.openjdk.java.net/browse/JDK-8248194 http://cr.openjdk.java.net/~cjplummer/8248194/webrev.01/index.html As outlined in the CR, these are the 3 main goals of this CR: 1. Add a shared API for locating the path to the core file. This includes parsing the output of the crashed process to locate where the core file was saved, and returning this location to the user. This API will be placed in the new CoreUtils class. 2. Add a shared API to support adding the "ulimit -c unlimited" prefix to the command that will produce the core file, allowing the overriding of any lower limit so we can be sure the core file will be produced. This API will also be placed in the new CoreUtils class. 3. LingeredApp should include support for producing a core file. As proof of concept for these improvements, I'm updating the following 3 tests to make use of them: ClhsdbCDSCore.java and TestJmapCore.java: Use the CoreUtils support listed above. These tests do not use LingeredApp, so those improvements don't apply. ClhsdbFindPC.java: Use all the above new features, including having LingeredApp produce a core file. This is the only test modified to start testing on core files that didn't previously do so. It still also tests on a live process. In the future more Clhsdb tests will be converted to work on core files in a manner similar to ClhsdbFindPC. The new CoreUtils code is borrowed from (more like ripped out of) ClhsdbCDSCore.java and TestJmapCore.java. They both had a lot of code dedicated to finding the core file and also applying "ulimit -c unlimited", but didn't do so in quite the same way. Now both these tests share code in CoreUtils.java. One thing I did drop is TestJmapCore.java use of ":KILLED_PID" in the output to help find the core file. It's no longer necessary based on the smarter core locating code I pulled from ClhsdbCDSCore.java. One other improvement was to enable windows support for ClhsdbCDSCore. The only reason it was not enabled previously is because the author couldn't figure out how to properly generate the command for the process that produces the core. Since it is launched using "sh -c", the path has to be converted to use forward slashes. This is now done in CoreUtils. One other change in ClhsdbCDSCore is that it no longer renames the core file to a well known name in the cwd. This was unnecessary. It originated in code from ciReplayBase.java, which does have a reason to do the rename, but ClhsdbCDSCore does not. The new libLingeredApp.c relies on JDK-8248667 [1] being in place in order to have the build system properly compile it. JDK-8248667 will be reviewed separately on build-dev and pushed just before the changes for this CR. thanks, Chris [1] https://bugs.openjdk.java.net/browse/JDK-8248667 From daniel.daugherty at oracle.com Thu Jul 2 22:16:54 2020 From: daniel.daugherty at oracle.com (Daniel D. Daugherty) Date: Thu, 2 Jul 2020 18:16:54 -0400 Subject: RFR: 8242428: JVMTI thread operations should use Thread-Local Handshake In-Reply-To: <763793b1-9506-44c6-0681-1c71c44a44fd@oss.nttdata.com> References: <6c263e4c-0a83-be7a-0288-ecb2de0b7cea@oss.nttdata.com> <2ea2f5d8-5c43-a7d3-d525-cd44c4009d25@oss.nttdata.com> <65889ab4-6b7e-86fb-59cc-012520b83138@oracle.com> <4b7df6f8-c8f7-fedf-6366-b885d2235b58@oss.nttdata.com> <74c05dfd-ffb2-b73d-66e5-dc98752729f5@oss.nttdata.com> <763793b1-9506-44c6-0681-1c71c44a44fd@oss.nttdata.com> Message-ID: <5107c478-1de2-7a49-ee71-dfad6a99a667@oracle.com> On 7/2/20 5:19 AM, Yasumasa Suenaga wrote: > Hi David, > > I upload new webrev. Could you review again? > > http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.03/ src/hotspot/share/prims/jvmtiEnv.cpp ??? L1542: ??? // Get stack trace with handshake ??????? nit - please add a period at the end. ??? L1591: ??? *stack_info_ptr = op.stack_info(); ??????? The return parameter should not be touched unless the return ??????? code in 'err' == JVMTI_ERROR_NONE. ??? old L1582: ? if (err == JVMTI_ERROR_NONE) { ??????? Please restore this check. The return parameter should not ??????? be touched unless the return code in 'err' == JVMTI_ERROR_NONE. ??? L1272: ? if (!jt->is_exiting() && (thread_oop != NULL)) { ??????? nit - extra parens around the second expression. src/hotspot/share/prims/jvmtiEnvBase.cpp ??? old L1532: ? _result = JVMTI_ERROR_THREAD_NOT_ALIVE; ??????? This deletion of the _result field threw me for a minute and then ??? ? ? I figured out that the field is init to JVMTI_ERROR_THREAD_NOT_ALIVE ??????? in the constructor. ??? L1553: ? if (!jt->is_exiting() && (jt->threadObj() != NULL)) { ??????? nit - extra parens around the second expression. src/hotspot/share/prims/jvmtiEnvBase.hpp ??? No comments. src/hotspot/share/runtime/vmOperations.hpp ??? No comments. test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/GetThreadListStackTraces.java ??? No comments. test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/OneGetThreadListStackTraces.java ??? L64: ??????? startSignal.countDown(); ??????? I was expecting this to be a call to await() instead of ??????? countDown(). What am I missing here? ??????? I think this test might be passing by accident right now, but... test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libGetThreadListStackTraces.c ??? L92: ? jthreads = (jthread *)malloc(sizeof(jthread) * num_threads); ??????? You don't check for malloc() failure. ??????? 'jthreads' is allocated but never freed. test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.c ??? L91: ? result = (*jvmti)->SuspendThread(jvmti, thread); ??????? Why are you suspending the thread? GetAllStackTraces() and ??????? GetThreadListStackTraces() do not require the target thread(s) ??????? to be suspend. ??????? If you decide not to SuspendThread, then you don't need the ??????? AddCapabilities or the ResumeThread calls. Dan > > On 2020/07/02 15:05, David Holmes wrote: >> Hi Yasumasa, >> >> On 1/07/2020 11:53 am, Yasumasa Suenaga wrote: >>> Hi, >>> >>> I uploaded new webrev. Could review again? >>> >>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.02/ >> >> Updates look fine - thanks. >> >> One minor nit: >> >> 1274???? _collector.allocate_and_fill_stacks(1); >> 1275???? _collector.set_result(JVMTI_ERROR_NONE); >> >> In the other places where you use _collector you rely on result being >> initialized to JVMTI_ERROR_NONE, rather than setting it directly >> after allocate_and_fill_stacks(). > > Fixed. > > >>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>> >>>>>>>> ? 820 assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>> ? 821 java_thread->is_thread_fully_suspended(false, >>>>>>>> &debug_bits) || >>>>>>>> ? 822????????? current_thread == java_thread->active_handshaker(), >>>>>>>> ? 823????????? "at safepoint / handshake or target thread is >>>>>>>> suspended"); >>>>>>>> >>>>>>>> I don't think the suspension check is necessary, as even if the >>>>>>>> target is suspended we must still be at a safepoint or in a >>>>>>>> handshake with it. Makes me wonder if we used to allow a racy >>>>>>>> stacktrace operation on a suspended thread, assuming it would >>>>>>>> remain suspended? >>> >>> This function (JvmtiEnvBase::get_stack_trace()) can be called to get >>> own stack trace. For example, we can call GetStackTrace() for >>> current thread at JVMTI event. >>> So I changed assert as below: >>> >>> ``` >>> ??820?? assert(current_thread == java_thread || >>> ??821????????? SafepointSynchronize::is_at_safepoint() || >>> ??822????????? current_thread == java_thread->active_handshaker(), >>> ??823????????? "call by myself / at safepoint / at handshake"); >>> ``` >> >> Yep good catch. I hope current tests caught that. > > They would be tested in > vmTestbase/nsk/jvmti/GetStackTrace/getstacktr001/ (own call stacks), > and getstacktr003 (call stacks in other thread). > > >> Speaking of tests ... >> >> In the native code I think you need to check the success of all JNI >> methods that can throw exceptions - otherwise I believe the tests may >> trigger warnings if -Xcheck:jni is used with them. See for example: >> >> test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/libHeapMonitorTest.cpp >> > > I updated testcases to check JNI and JVMTI function calls. > > >> In the Java code the target thread: >> >> ?? 45???? public void run() { >> ?? 46?????? try { >> ?? 47?????????? synchronized (lock) { >> ?? 48?????????????? lock.wait(); >> ?? 49?????????????? System.out.println("OK"); >> ?? 50?????????? } >> >> is potentially susceptible to spurious wakeups. Using a >> CountDownLatch would be robust. > > Fixed. > > > Thanks, > > Yasumasa > > >> Thanks, >> David >> ----- >> >>> >>> Thanks, >>> >>> Yasumasa >>> >>> >>> On 2020/07/01 8:48, David Holmes wrote: >>>> Hi Yasumasa, >>>> >>>> On 1/07/2020 9:05 am, Yasumasa Suenaga wrote: >>>>> Hi David, >>>>> >>>>>>>> 1271???? ResourceMark rm; >>>>>>>> >>>>>>>> IIUC at this point the _calling_thread is the current thread, >>>>>>>> so we can use: >>>>>>>> >>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>> >>>>> If so, we can call make_local() in L1272 without JavaThread (or we >>>>> can pass current thread to make_local()). Is it right? >>>>> >>>>> ``` >>>>> 1271???? ResourceMark rm; >>>>> 1272 >>>>> _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, >>>>> thread_oop), >>>>> 1273??????????????????????????? jt, thread_oop); >>>>> ``` >>>> >>>> Sorry I got confused, _calling_thread may not be the current thread >>>> as we could be executing the handshake in the target thread itself. >>>> So the ResourceMark is correct as-is (implicitly for current thread). >>>> >>>> The argument to fill_frames will be used in the jvmtiStackInfo and >>>> passed back to the _calling_thread, so it must be created via >>>> make_local(_calling_thread, ...) as you presently have. >>>> >>>> Thanks, >>>> David >>>> >>>>> Thanks, >>>>> >>>>> Yasumasa >>>>> >>>>> >>>>> On 2020/07/01 7:05, David Holmes wrote: >>>>>> On 1/07/2020 12:17 am, Yasumasa Suenaga wrote: >>>>>>> Hi David, >>>>>>> >>>>>>> Thank you for reviewing! I will update new webrev tomorrow. >>>>>>> >>>>>>>> 466 class MultipleStackTracesCollector : public StackObj { >>>>>>>> >>>>>>>> ? 498 class VM_GetAllStackTraces : public VM_Operation { >>>>>>>> ? 499 private: >>>>>>>> ? 500?? JavaThread *_calling_thread; >>>>>>>> ? 501?? jint _final_thread_count; >>>>>>>> ? 502?? MultipleStackTracesCollector _collector; >>>>>>>> >>>>>>>> You can't have a StackObj as a member of another class like >>>>>>>> that as it may not be on the stack. I think >>>>>>>> MultipleStackTracesCollector should not extend any allocation >>>>>>>> class, and should always be embedded directly in another class. >>>>>>> >>>>>>> I'm not sure what does mean "embedded". >>>>>>> Is it ok as below? >>>>>>> >>>>>>> ``` >>>>>>> class MultipleStackTracesCollector { >>>>>>> ??? : >>>>>>> } >>>>>>> >>>>>>> class GetAllStackTraces : public VM_Operation { >>>>>>> ?? private: >>>>>>> ???? MultipleStackTracesCollector _collector; >>>>>>> } >>>>>>> ``` >>>>>> >>>>>> Yes that I what I meant. >>>>>> >>>>>> Thanks, >>>>>> David >>>>>> ----- >>>>>> >>>>>>> >>>>>>> Thanks, >>>>>>> >>>>>>> Yasumasa >>>>>>> >>>>>>> >>>>>>> On 2020/06/30 22:22, David Holmes wrote: >>>>>>>> Hi Yasumasa, >>>>>>>> >>>>>>>> On 30/06/2020 10:05 am, Yasumasa Suenaga wrote: >>>>>>>>> Hi David, Serguei, >>>>>>>>> >>>>>>>>> I updated webrev for 8242428. Could you review again? >>>>>>>>> This change migrate to use direct handshake for >>>>>>>>> GetStackTrace() and GetThreadListStackTraces() (when >>>>>>>>> thread_count == 1). >>>>>>>>> >>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.01/ >>>>>>>> >>>>>>>> This looks really good now! I only have a few nits below. There >>>>>>>> is one thing I don't like about it but it requires a change to >>>>>>>> the main Handshake logic to address - in >>>>>>>> JvmtiEnv::GetThreadListStackTraces you have to create a >>>>>>>> ThreadsListHandle to convert the jthread to a JavaThread, but >>>>>>>> then the Handshake::execute_direct creates another >>>>>>>> ThreadsListHandle internally. That's a waste. I will discuss >>>>>>>> with Robbin and file a RFE to have an overload of >>>>>>>> execute_direct that takes an existing TLH. Actually it's worse >>>>>>>> than that because we have another TLH in use at the entry point >>>>>>>> for the JVMTI functions, so I think there may be some scope for >>>>>>>> simplifying the use of TLH instances - future RFE. >>>>>>>> >>>>>>>> --- >>>>>>>> >>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>>>> >>>>>>>> ??451?? GetStackTraceClosure(JvmtiEnv *env, jint start_depth, >>>>>>>> jint max_count, >>>>>>>> ??452??????????????????????? jvmtiFrameInfo* frame_buffer, >>>>>>>> jint* count_ptr) >>>>>>>> ??453???? : HandshakeClosure("GetStackTrace"), >>>>>>>> ??454?????? _env(env), _start_depth(start_depth), >>>>>>>> _max_count(max_count), >>>>>>>> ??455?????? _frame_buffer(frame_buffer), _count_ptr(count_ptr), >>>>>>>> ??456?????? _result(JVMTI_ERROR_THREAD_NOT_ALIVE) { >>>>>>>> >>>>>>>> Nit: can you do one initializer per line please. >>>>>>>> >>>>>>>> This looks wrong: >>>>>>>> >>>>>>>> 466 class MultipleStackTracesCollector : public StackObj { >>>>>>>> >>>>>>>> ??498 class VM_GetAllStackTraces : public VM_Operation { >>>>>>>> ??499 private: >>>>>>>> ??500?? JavaThread *_calling_thread; >>>>>>>> ??501?? jint _final_thread_count; >>>>>>>> ??502?? MultipleStackTracesCollector _collector; >>>>>>>> >>>>>>>> You can't have a StackObj as a member of another class like >>>>>>>> that as it may not be on the stack. I think >>>>>>>> MultipleStackTracesCollector should not extend any allocation >>>>>>>> class, and should always be embedded directly in another class. >>>>>>>> >>>>>>>> 481?? MultipleStackTracesCollector(JvmtiEnv *env, jint >>>>>>>> max_frame_count) { >>>>>>>> ??482???? _env = env; >>>>>>>> ??483???? _max_frame_count = max_frame_count; >>>>>>>> ??484???? _frame_count_total = 0; >>>>>>>> ??485???? _head = NULL; >>>>>>>> ??486???? _stack_info = NULL; >>>>>>>> ??487???? _result = JVMTI_ERROR_NONE; >>>>>>>> ??488?? } >>>>>>>> >>>>>>>> As you are touching this can you change it to use an >>>>>>>> initializer list as you did for the HandshakeClosure, and >>>>>>>> please keep one item per line. >>>>>>>> >>>>>>>> --- >>>>>>>> >>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>> >>>>>>>> ??820 assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>> ??821 java_thread->is_thread_fully_suspended(false, >>>>>>>> &debug_bits) || >>>>>>>> ??822????????? current_thread == java_thread->active_handshaker(), >>>>>>>> ??823????????? "at safepoint / handshake or target thread is >>>>>>>> suspended"); >>>>>>>> >>>>>>>> I don't think the suspension check is necessary, as even if the >>>>>>>> target is suspended we must still be at a safepoint or in a >>>>>>>> handshake with it. Makes me wonder if we used to allow a racy >>>>>>>> stacktrace operation on a suspended thread, assuming it would >>>>>>>> remain suspended? >>>>>>>> >>>>>>>> 1268?? oop thread_oop = jt->threadObj(); >>>>>>>> 1269 >>>>>>>> 1270?? if (!jt->is_exiting() && (jt->threadObj() != NULL)) { >>>>>>>> >>>>>>>> You can use thread_oop in line 1270. >>>>>>>> >>>>>>>> 1272 >>>>>>>> _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, >>>>>>>> thread_oop), >>>>>>>> 1273??????????????????????????? jt, thread_oop); >>>>>>>> >>>>>>>> It is frustrating that this entire call chain started with a >>>>>>>> jthread reference, which we converted to a JavaThread, only to >>>>>>>> eventually need to convert it back to a jthread! I think there >>>>>>>> is some scope for simplification here but not as part of this >>>>>>>> change. >>>>>>>> >>>>>>>> 1271???? ResourceMark rm; >>>>>>>> >>>>>>>> IIUC at this point the _calling_thread is the current thread, >>>>>>>> so we can use: >>>>>>>> >>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>>> >>>>>>>> --- >>>>>>>> >>>>>>>> Please add @bug lines to the tests. >>>>>>>> >>>>>>>> I'm still pondering the test logic but wanted to send this now. >>>>>>>> >>>>>>>> Thanks, >>>>>>>> David >>>>>>>> ----- >>>>>>>>> VM_GetThreadListStackTrace (for GetThreadListStackTraces) and >>>>>>>>> VM_GetAllStackTraces (for GetAllStackTraces) have inherited >>>>>>>>> VM_GetMultipleStackTraces VM operation which provides the >>>>>>>>> feature to generate jvmtiStackInfo. I modified >>>>>>>>> VM_GetMultipleStackTraces to a normal C++ class to share with >>>>>>>>> HandshakeClosure for GetThreadListStackTraces >>>>>>>>> (GetSingleStackTraceClosure). >>>>>>>>> >>>>>>>>> Also I added new testcases which test >>>>>>>>> GetThreadListStackTraces() with thread_count == 1 and with all >>>>>>>>> threads. >>>>>>>>> >>>>>>>>> This change has been tested in serviceability/jvmti >>>>>>>>> serviceability/jdwp vmTestbase/nsk/jvmti vmTestbase/nsk/jdi >>>>>>>>> vmTestbase/nsk/jdwp. >>>>>>>>> >>>>>>>>> >>>>>>>>> Thanks, >>>>>>>>> >>>>>>>>> Yasumasa >>>>>>>>> >>>>>>>>> >>>>>>>>> On 2020/06/24 15:50, Yasumasa Suenaga wrote: >>>>>>>>>> Hi all, >>>>>>>>>> >>>>>>>>>> Please review this change: >>>>>>>>>> >>>>>>>>>> ?? JBS: https://bugs.openjdk.java.net/browse/JDK-8242428 >>>>>>>>>> ?? webrev: >>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.00/ >>>>>>>>>> >>>>>>>>>> This change replace following VM operations to direct handshake. >>>>>>>>>> >>>>>>>>>> ??- VM_GetFrameCount (GetFrameCount()) >>>>>>>>>> ??- VM_GetFrameLocation (GetFrameLocation()) >>>>>>>>>> ??- VM_GetThreadListStackTraces (GetThreadListStackTrace()) >>>>>>>>>> ??- VM_GetCurrentLocation >>>>>>>>>> >>>>>>>>>> GetThreadListStackTrace() uses direct handshake if thread >>>>>>>>>> count == 1. In other case (thread count > 1), it would be >>>>>>>>>> performed as VM operation (VM_GetThreadListStackTraces). >>>>>>>>>> Caller of VM_GetCurrentLocation >>>>>>>>>> (JvmtiEnvThreadState::reset_current_location()) might be >>>>>>>>>> called at safepoint. So I added safepoint check in its caller. >>>>>>>>>> >>>>>>>>>> This change has been tested in serviceability/jvmti >>>>>>>>>> serviceability/jdwp vmTestbase/nsk/jvmti vmTestbase/nsk/jdi >>>>>>>>>> vmTestbase/ns >>>>>>>>>> k/jdwp. >>>>>>>>>> >>>>>>>>>> Also I tested it on submit repo, then it has execution error >>>>>>>>>> (mach5-one-ysuenaga-JDK-8242428-20200624-0054-12034717) due >>>>>>>>>> to dependency error. So I think it does not occur by this >>>>>>>>>> change. >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> Thanks, >>>>>>>>>> >>>>>>>>>> Yasumasa From suenaga at oss.nttdata.com Thu Jul 2 23:14:17 2020 From: suenaga at oss.nttdata.com (Yasumasa Suenaga) Date: Fri, 3 Jul 2020 08:14:17 +0900 Subject: RFR: 8242428: JVMTI thread operations should use Thread-Local Handshake In-Reply-To: <5107c478-1de2-7a49-ee71-dfad6a99a667@oracle.com> References: <6c263e4c-0a83-be7a-0288-ecb2de0b7cea@oss.nttdata.com> <2ea2f5d8-5c43-a7d3-d525-cd44c4009d25@oss.nttdata.com> <65889ab4-6b7e-86fb-59cc-012520b83138@oracle.com> <4b7df6f8-c8f7-fedf-6366-b885d2235b58@oss.nttdata.com> <74c05dfd-ffb2-b73d-66e5-dc98752729f5@oss.nttdata.com> <763793b1-9506-44c6-0681-1c71c44a44fd@oss.nttdata.com> <5107c478-1de2-7a49-ee71-dfad6a99a667@oracle.com> Message-ID: <90cdfef9-e558-0d25-33f5-25b7d65bb83b@oss.nttdata.com> Hi Dan, Thanks for your comment! On 2020/07/03 7:16, Daniel D. Daugherty wrote: > On 7/2/20 5:19 AM, Yasumasa Suenaga wrote: >> Hi David, >> >> I upload new webrev. Could you review again? >> >> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.03/ > > src/hotspot/share/prims/jvmtiEnv.cpp > ??? L1542: ??? // Get stack trace with handshake > ??????? nit - please add a period at the end. I will fix it. > ??? L1591: ??? *stack_info_ptr = op.stack_info(); > ??????? The return parameter should not be touched unless the return > ??????? code in 'err' == JVMTI_ERROR_NONE. > > ??? old L1582: ? if (err == JVMTI_ERROR_NONE) { > ??????? Please restore this check. The return parameter should not > ??????? be touched unless the return code in 'err' == JVMTI_ERROR_NONE. I will fix it. > ??? L1272: ? if (!jt->is_exiting() && (thread_oop != NULL)) { > ??????? nit - extra parens around the second expression. I will fix it. > src/hotspot/share/prims/jvmtiEnvBase.cpp > ??? old L1532: ? _result = JVMTI_ERROR_THREAD_NOT_ALIVE; > ??????? This deletion of the _result field threw me for a minute and then > ??? ? ? I figured out that the field is init to JVMTI_ERROR_THREAD_NOT_ALIVE > ??????? in the constructor. > > ??? L1553: ? if (!jt->is_exiting() && (jt->threadObj() != NULL)) { > ??????? nit - extra parens around the second expression. I will fix it. > src/hotspot/share/prims/jvmtiEnvBase.hpp > ??? No comments. > > src/hotspot/share/runtime/vmOperations.hpp > ??? No comments. > > test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/GetThreadListStackTraces.java > ??? No comments. > > test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/OneGetThreadListStackTraces.java > ??? L64: ??????? startSignal.countDown(); > ??????? I was expecting this to be a call to await() instead of > ??????? countDown(). What am I missing here? > > ??????? I think this test might be passing by accident right now, but... Main thread (which call JVMTI functions to test) should wait until test thread is ready. So main thread would wait startSignal, and test thread would count down. > test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libGetThreadListStackTraces.c > ??? L92: ? jthreads = (jthread *)malloc(sizeof(jthread) * num_threads); > ??????? You don't check for malloc() failure. > ??????? 'jthreads' is allocated but never freed. I will fix it. > test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.c > ??? L91: ? result = (*jvmti)->SuspendThread(jvmti, thread); > ??????? Why are you suspending the thread? GetAllStackTraces() and > ??????? GetThreadListStackTraces() do not require the target thread(s) > ??????? to be suspend. > > ??????? If you decide not to SuspendThread, then you don't need the > ??????? AddCapabilities or the ResumeThread calls. Test thread might not be entered following code (stopSignal.await()). We might see deferent call stack between GetAllStackTraces() and GetThreadListStackTraces(). We cannot control to freeze call stack of test thread in Java code. (I didn't use SuspendThread() at first, but I saw some errors which causes in above.) So we need to call SuspendThread() to ensure we can see same call stack. Thanks, Yasumasa > Dan > >> >> On 2020/07/02 15:05, David Holmes wrote: >>> Hi Yasumasa, >>> >>> On 1/07/2020 11:53 am, Yasumasa Suenaga wrote: >>>> Hi, >>>> >>>> I uploaded new webrev. Could review again? >>>> >>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.02/ >>> >>> Updates look fine - thanks. >>> >>> One minor nit: >>> >>> 1274???? _collector.allocate_and_fill_stacks(1); >>> 1275???? _collector.set_result(JVMTI_ERROR_NONE); >>> >>> In the other places where you use _collector you rely on result being initialized to JVMTI_ERROR_NONE, rather than setting it directly after allocate_and_fill_stacks(). >> >> Fixed. >> >> >>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>> >>>>>>>>> ? 820 assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>> ? 821 java_thread->is_thread_fully_suspended(false, &debug_bits) || >>>>>>>>> ? 822????????? current_thread == java_thread->active_handshaker(), >>>>>>>>> ? 823????????? "at safepoint / handshake or target thread is suspended"); >>>>>>>>> >>>>>>>>> I don't think the suspension check is necessary, as even if the target is suspended we must still be at a safepoint or in a handshake with it. Makes me wonder if we used to allow a racy stacktrace operation on a suspended thread, assuming it would remain suspended? >>>> >>>> This function (JvmtiEnvBase::get_stack_trace()) can be called to get own stack trace. For example, we can call GetStackTrace() for current thread at JVMTI event. >>>> So I changed assert as below: >>>> >>>> ``` >>>> ??820?? assert(current_thread == java_thread || >>>> ??821????????? SafepointSynchronize::is_at_safepoint() || >>>> ??822????????? current_thread == java_thread->active_handshaker(), >>>> ??823????????? "call by myself / at safepoint / at handshake"); >>>> ``` >>> >>> Yep good catch. I hope current tests caught that. >> >> They would be tested in vmTestbase/nsk/jvmti/GetStackTrace/getstacktr001/ (own call stacks), and getstacktr003 (call stacks in other thread). >> >> >>> Speaking of tests ... >>> >>> In the native code I think you need to check the success of all JNI methods that can throw exceptions - otherwise I believe the tests may trigger warnings if -Xcheck:jni is used with them. See for example: >>> >>> test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/libHeapMonitorTest.cpp >> >> I updated testcases to check JNI and JVMTI function calls. >> >> >>> In the Java code the target thread: >>> >>> ?? 45???? public void run() { >>> ?? 46?????? try { >>> ?? 47?????????? synchronized (lock) { >>> ?? 48?????????????? lock.wait(); >>> ?? 49?????????????? System.out.println("OK"); >>> ?? 50?????????? } >>> >>> is potentially susceptible to spurious wakeups. Using a CountDownLatch would be robust. >> >> Fixed. >> >> >> Thanks, >> >> Yasumasa >> >> >>> Thanks, >>> David >>> ----- >>> >>>> >>>> Thanks, >>>> >>>> Yasumasa >>>> >>>> >>>> On 2020/07/01 8:48, David Holmes wrote: >>>>> Hi Yasumasa, >>>>> >>>>> On 1/07/2020 9:05 am, Yasumasa Suenaga wrote: >>>>>> Hi David, >>>>>> >>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>> >>>>>>>>> IIUC at this point the _calling_thread is the current thread, so we can use: >>>>>>>>> >>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>> >>>>>> If so, we can call make_local() in L1272 without JavaThread (or we can pass current thread to make_local()). Is it right? >>>>>> >>>>>> ``` >>>>>> 1271???? ResourceMark rm; >>>>>> 1272 _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, thread_oop), >>>>>> 1273??????????????????????????? jt, thread_oop); >>>>>> ``` >>>>> >>>>> Sorry I got confused, _calling_thread may not be the current thread as we could be executing the handshake in the target thread itself. So the ResourceMark is correct as-is (implicitly for current thread). >>>>> >>>>> The argument to fill_frames will be used in the jvmtiStackInfo and passed back to the _calling_thread, so it must be created via make_local(_calling_thread, ...) as you presently have. >>>>> >>>>> Thanks, >>>>> David >>>>> >>>>>> Thanks, >>>>>> >>>>>> Yasumasa >>>>>> >>>>>> >>>>>> On 2020/07/01 7:05, David Holmes wrote: >>>>>>> On 1/07/2020 12:17 am, Yasumasa Suenaga wrote: >>>>>>>> Hi David, >>>>>>>> >>>>>>>> Thank you for reviewing! I will update new webrev tomorrow. >>>>>>>> >>>>>>>>> 466 class MultipleStackTracesCollector : public StackObj { >>>>>>>>> >>>>>>>>> ? 498 class VM_GetAllStackTraces : public VM_Operation { >>>>>>>>> ? 499 private: >>>>>>>>> ? 500?? JavaThread *_calling_thread; >>>>>>>>> ? 501?? jint _final_thread_count; >>>>>>>>> ? 502?? MultipleStackTracesCollector _collector; >>>>>>>>> >>>>>>>>> You can't have a StackObj as a member of another class like that as it may not be on the stack. I think MultipleStackTracesCollector should not extend any allocation class, and should always be embedded directly in another class. >>>>>>>> >>>>>>>> I'm not sure what does mean "embedded". >>>>>>>> Is it ok as below? >>>>>>>> >>>>>>>> ``` >>>>>>>> class MultipleStackTracesCollector { >>>>>>>> ??? : >>>>>>>> } >>>>>>>> >>>>>>>> class GetAllStackTraces : public VM_Operation { >>>>>>>> ?? private: >>>>>>>> ???? MultipleStackTracesCollector _collector; >>>>>>>> } >>>>>>>> ``` >>>>>>> >>>>>>> Yes that I what I meant. >>>>>>> >>>>>>> Thanks, >>>>>>> David >>>>>>> ----- >>>>>>> >>>>>>>> >>>>>>>> Thanks, >>>>>>>> >>>>>>>> Yasumasa >>>>>>>> >>>>>>>> >>>>>>>> On 2020/06/30 22:22, David Holmes wrote: >>>>>>>>> Hi Yasumasa, >>>>>>>>> >>>>>>>>> On 30/06/2020 10:05 am, Yasumasa Suenaga wrote: >>>>>>>>>> Hi David, Serguei, >>>>>>>>>> >>>>>>>>>> I updated webrev for 8242428. Could you review again? >>>>>>>>>> This change migrate to use direct handshake for GetStackTrace() and GetThreadListStackTraces() (when thread_count == 1). >>>>>>>>>> >>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.01/ >>>>>>>>> >>>>>>>>> This looks really good now! I only have a few nits below. There is one thing I don't like about it but it requires a change to the main Handshake logic to address - in JvmtiEnv::GetThreadListStackTraces you have to create a ThreadsListHandle to convert the jthread to a JavaThread, but then the Handshake::execute_direct creates another ThreadsListHandle internally. That's a waste. I will discuss with Robbin and file a RFE to have an overload of execute_direct that takes an existing TLH. Actually it's worse than that because we have another TLH in use at the entry point for the JVMTI functions, so I think there may be some scope for simplifying the use of TLH instances - future RFE. >>>>>>>>> >>>>>>>>> --- >>>>>>>>> >>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>>>>> >>>>>>>>> ??451?? GetStackTraceClosure(JvmtiEnv *env, jint start_depth, jint max_count, >>>>>>>>> ??452??????????????????????? jvmtiFrameInfo* frame_buffer, jint* count_ptr) >>>>>>>>> ??453???? : HandshakeClosure("GetStackTrace"), >>>>>>>>> ??454?????? _env(env), _start_depth(start_depth), _max_count(max_count), >>>>>>>>> ??455?????? _frame_buffer(frame_buffer), _count_ptr(count_ptr), >>>>>>>>> ??456?????? _result(JVMTI_ERROR_THREAD_NOT_ALIVE) { >>>>>>>>> >>>>>>>>> Nit: can you do one initializer per line please. >>>>>>>>> >>>>>>>>> This looks wrong: >>>>>>>>> >>>>>>>>> 466 class MultipleStackTracesCollector : public StackObj { >>>>>>>>> >>>>>>>>> ??498 class VM_GetAllStackTraces : public VM_Operation { >>>>>>>>> ??499 private: >>>>>>>>> ??500?? JavaThread *_calling_thread; >>>>>>>>> ??501?? jint _final_thread_count; >>>>>>>>> ??502?? MultipleStackTracesCollector _collector; >>>>>>>>> >>>>>>>>> You can't have a StackObj as a member of another class like that as it may not be on the stack. I think MultipleStackTracesCollector should not extend any allocation class, and should always be embedded directly in another class. >>>>>>>>> >>>>>>>>> 481?? MultipleStackTracesCollector(JvmtiEnv *env, jint max_frame_count) { >>>>>>>>> ??482???? _env = env; >>>>>>>>> ??483???? _max_frame_count = max_frame_count; >>>>>>>>> ??484???? _frame_count_total = 0; >>>>>>>>> ??485???? _head = NULL; >>>>>>>>> ??486???? _stack_info = NULL; >>>>>>>>> ??487???? _result = JVMTI_ERROR_NONE; >>>>>>>>> ??488?? } >>>>>>>>> >>>>>>>>> As you are touching this can you change it to use an initializer list as you did for the HandshakeClosure, and please keep one item per line. >>>>>>>>> >>>>>>>>> --- >>>>>>>>> >>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>> >>>>>>>>> ??820 assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>> ??821 java_thread->is_thread_fully_suspended(false, &debug_bits) || >>>>>>>>> ??822????????? current_thread == java_thread->active_handshaker(), >>>>>>>>> ??823????????? "at safepoint / handshake or target thread is suspended"); >>>>>>>>> >>>>>>>>> I don't think the suspension check is necessary, as even if the target is suspended we must still be at a safepoint or in a handshake with it. Makes me wonder if we used to allow a racy stacktrace operation on a suspended thread, assuming it would remain suspended? >>>>>>>>> >>>>>>>>> 1268?? oop thread_oop = jt->threadObj(); >>>>>>>>> 1269 >>>>>>>>> 1270?? if (!jt->is_exiting() && (jt->threadObj() != NULL)) { >>>>>>>>> >>>>>>>>> You can use thread_oop in line 1270. >>>>>>>>> >>>>>>>>> 1272 _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, thread_oop), >>>>>>>>> 1273??????????????????????????? jt, thread_oop); >>>>>>>>> >>>>>>>>> It is frustrating that this entire call chain started with a jthread reference, which we converted to a JavaThread, only to eventually need to convert it back to a jthread! I think there is some scope for simplification here but not as part of this change. >>>>>>>>> >>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>> >>>>>>>>> IIUC at this point the _calling_thread is the current thread, so we can use: >>>>>>>>> >>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>>>> >>>>>>>>> --- >>>>>>>>> >>>>>>>>> Please add @bug lines to the tests. >>>>>>>>> >>>>>>>>> I'm still pondering the test logic but wanted to send this now. >>>>>>>>> >>>>>>>>> Thanks, >>>>>>>>> David >>>>>>>>> ----- >>>>>>>>>> VM_GetThreadListStackTrace (for GetThreadListStackTraces) and VM_GetAllStackTraces (for GetAllStackTraces) have inherited VM_GetMultipleStackTraces VM operation which provides the feature to generate jvmtiStackInfo. I modified VM_GetMultipleStackTraces to a normal C++ class to share with HandshakeClosure for GetThreadListStackTraces (GetSingleStackTraceClosure). >>>>>>>>>> >>>>>>>>>> Also I added new testcases which test GetThreadListStackTraces() with thread_count == 1 and with all threads. >>>>>>>>>> >>>>>>>>>> This change has been tested in serviceability/jvmti serviceability/jdwp vmTestbase/nsk/jvmti vmTestbase/nsk/jdi vmTestbase/nsk/jdwp. >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> Thanks, >>>>>>>>>> >>>>>>>>>> Yasumasa >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> On 2020/06/24 15:50, Yasumasa Suenaga wrote: >>>>>>>>>>> Hi all, >>>>>>>>>>> >>>>>>>>>>> Please review this change: >>>>>>>>>>> >>>>>>>>>>> ?? JBS: https://bugs.openjdk.java.net/browse/JDK-8242428 >>>>>>>>>>> ?? webrev: http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.00/ >>>>>>>>>>> >>>>>>>>>>> This change replace following VM operations to direct handshake. >>>>>>>>>>> >>>>>>>>>>> ??- VM_GetFrameCount (GetFrameCount()) >>>>>>>>>>> ??- VM_GetFrameLocation (GetFrameLocation()) >>>>>>>>>>> ??- VM_GetThreadListStackTraces (GetThreadListStackTrace()) >>>>>>>>>>> ??- VM_GetCurrentLocation >>>>>>>>>>> >>>>>>>>>>> GetThreadListStackTrace() uses direct handshake if thread count == 1. In other case (thread count > 1), it would be performed as VM operation (VM_GetThreadListStackTraces). >>>>>>>>>>> Caller of VM_GetCurrentLocation (JvmtiEnvThreadState::reset_current_location()) might be called at safepoint. So I added safepoint check in its caller. >>>>>>>>>>> >>>>>>>>>>> This change has been tested in serviceability/jvmti serviceability/jdwp vmTestbase/nsk/jvmti vmTestbase/nsk/jdi vmTestbase/ns >>>>>>>>>>> k/jdwp. >>>>>>>>>>> >>>>>>>>>>> Also I tested it on submit repo, then it has execution error (mach5-one-ysuenaga-JDK-8242428-20200624-0054-12034717) due to dependency error. So I think it does not occur by this change. >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> Thanks, >>>>>>>>>>> >>>>>>>>>>> Yasumasa > From daniel.daugherty at oracle.com Fri Jul 3 00:56:39 2020 From: daniel.daugherty at oracle.com (Daniel D. Daugherty) Date: Thu, 2 Jul 2020 20:56:39 -0400 Subject: RFR: 8242428: JVMTI thread operations should use Thread-Local Handshake In-Reply-To: <90cdfef9-e558-0d25-33f5-25b7d65bb83b@oss.nttdata.com> References: <6c263e4c-0a83-be7a-0288-ecb2de0b7cea@oss.nttdata.com> <2ea2f5d8-5c43-a7d3-d525-cd44c4009d25@oss.nttdata.com> <65889ab4-6b7e-86fb-59cc-012520b83138@oracle.com> <4b7df6f8-c8f7-fedf-6366-b885d2235b58@oss.nttdata.com> <74c05dfd-ffb2-b73d-66e5-dc98752729f5@oss.nttdata.com> <763793b1-9506-44c6-0681-1c71c44a44fd@oss.nttdata.com> <5107c478-1de2-7a49-ee71-dfad6a99a667@oracle.com> <90cdfef9-e558-0d25-33f5-25b7d65bb83b@oss.nttdata.com> Message-ID: On 7/2/20 7:14 PM, Yasumasa Suenaga wrote: > Hi Dan, > > Thanks for your comment! > > On 2020/07/03 7:16, Daniel D. Daugherty wrote: >> On 7/2/20 5:19 AM, Yasumasa Suenaga wrote: >>> Hi David, >>> >>> I upload new webrev. Could you review again? >>> >>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.03/ >> >> src/hotspot/share/prims/jvmtiEnv.cpp >> ???? L1542: ??? // Get stack trace with handshake >> ???????? nit - please add a period at the end. > > I will fix it. > > >> ???? L1591: ??? *stack_info_ptr = op.stack_info(); >> ???????? The return parameter should not be touched unless the return >> ???????? code in 'err' == JVMTI_ERROR_NONE. >> >> ???? old L1582: ? if (err == JVMTI_ERROR_NONE) { >> ???????? Please restore this check. The return parameter should not >> ???????? be touched unless the return code in 'err' == JVMTI_ERROR_NONE. > > I will fix it. > > >> ???? L1272: ? if (!jt->is_exiting() && (thread_oop != NULL)) { >> ???????? nit - extra parens around the second expression. > > I will fix it. > > >> src/hotspot/share/prims/jvmtiEnvBase.cpp >> ???? old L1532: ? _result = JVMTI_ERROR_THREAD_NOT_ALIVE; >> ???????? This deletion of the _result field threw me for a minute and >> then >> ???? ? ? I figured out that the field is init to >> JVMTI_ERROR_THREAD_NOT_ALIVE >> ???????? in the constructor. >> >> ???? L1553: ? if (!jt->is_exiting() && (jt->threadObj() != NULL)) { >> ???????? nit - extra parens around the second expression. > > I will fix it. > > >> src/hotspot/share/prims/jvmtiEnvBase.hpp >> ???? No comments. >> >> src/hotspot/share/runtime/vmOperations.hpp >> ???? No comments. >> >> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/GetThreadListStackTraces.java >> >> ???? No comments. >> >> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/OneGetThreadListStackTraces.java >> >> ???? L64: ??????? startSignal.countDown(); >> ???????? I was expecting this to be a call to await() instead of >> ???????? countDown(). What am I missing here? >> >> ???????? I think this test might be passing by accident right now, >> but... > > Main thread (which call JVMTI functions to test) should wait until > test thread is ready. > So main thread would wait startSignal, and test thread would count down. That's my point. L64 is the main thread so it should be a call to startSignal.await(). > > >> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libGetThreadListStackTraces.c >> >> ???? L92: ? jthreads = (jthread *)malloc(sizeof(jthread) * num_threads); >> ???????? You don't check for malloc() failure. >> ???????? 'jthreads' is allocated but never freed. > > I will fix it. > > >> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.c >> >> ???? L91: ? result = (*jvmti)->SuspendThread(jvmti, thread); >> ???????? Why are you suspending the thread? GetAllStackTraces() and >> ???????? GetThreadListStackTraces() do not require the target thread(s) >> ???????? to be suspend. >> >> ???????? If you decide not to SuspendThread, then you don't need the >> ???????? AddCapabilities or the ResumeThread calls. > > Test thread might not be entered following code (stopSignal.await()). > We might see deferent call stack between GetAllStackTraces() and > GetThreadListStackTraces(). We cannot control to freeze call stack of > test thread in Java code. > (I didn't use SuspendThread() at first, but I saw some errors which > causes in above.) > > So we need to call SuspendThread() to ensure we can see same call stack. That sounds like a good reason. Please add a comment near the SuspendThread() call so that other readers won't wonder... Dan > > > Thanks, > > Yasumasa > > >> Dan >> >>> >>> On 2020/07/02 15:05, David Holmes wrote: >>>> Hi Yasumasa, >>>> >>>> On 1/07/2020 11:53 am, Yasumasa Suenaga wrote: >>>>> Hi, >>>>> >>>>> I uploaded new webrev. Could review again? >>>>> >>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.02/ >>>> >>>> Updates look fine - thanks. >>>> >>>> One minor nit: >>>> >>>> 1274???? _collector.allocate_and_fill_stacks(1); >>>> 1275???? _collector.set_result(JVMTI_ERROR_NONE); >>>> >>>> In the other places where you use _collector you rely on result >>>> being initialized to JVMTI_ERROR_NONE, rather than setting it >>>> directly after allocate_and_fill_stacks(). >>> >>> Fixed. >>> >>> >>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>> >>>>>>>>>> ? 820 assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>>> ? 821 java_thread->is_thread_fully_suspended(false, >>>>>>>>>> &debug_bits) || >>>>>>>>>> ? 822????????? current_thread == >>>>>>>>>> java_thread->active_handshaker(), >>>>>>>>>> ? 823????????? "at safepoint / handshake or target thread is >>>>>>>>>> suspended"); >>>>>>>>>> >>>>>>>>>> I don't think the suspension check is necessary, as even if >>>>>>>>>> the target is suspended we must still be at a safepoint or in >>>>>>>>>> a handshake with it. Makes me wonder if we used to allow a >>>>>>>>>> racy stacktrace operation on a suspended thread, assuming it >>>>>>>>>> would remain suspended? >>>>> >>>>> This function (JvmtiEnvBase::get_stack_trace()) can be called to >>>>> get own stack trace. For example, we can call GetStackTrace() for >>>>> current thread at JVMTI event. >>>>> So I changed assert as below: >>>>> >>>>> ``` >>>>> ??820?? assert(current_thread == java_thread || >>>>> ??821????????? SafepointSynchronize::is_at_safepoint() || >>>>> ??822????????? current_thread == java_thread->active_handshaker(), >>>>> ??823????????? "call by myself / at safepoint / at handshake"); >>>>> ``` >>>> >>>> Yep good catch. I hope current tests caught that. >>> >>> They would be tested in >>> vmTestbase/nsk/jvmti/GetStackTrace/getstacktr001/ (own call stacks), >>> and getstacktr003 (call stacks in other thread). >>> >>> >>>> Speaking of tests ... >>>> >>>> In the native code I think you need to check the success of all JNI >>>> methods that can throw exceptions - otherwise I believe the tests >>>> may trigger warnings if -Xcheck:jni is used with them. See for >>>> example: >>>> >>>> test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/libHeapMonitorTest.cpp >>>> >>> >>> I updated testcases to check JNI and JVMTI function calls. >>> >>> >>>> In the Java code the target thread: >>>> >>>> ?? 45???? public void run() { >>>> ?? 46?????? try { >>>> ?? 47?????????? synchronized (lock) { >>>> ?? 48?????????????? lock.wait(); >>>> ?? 49?????????????? System.out.println("OK"); >>>> ?? 50?????????? } >>>> >>>> is potentially susceptible to spurious wakeups. Using a >>>> CountDownLatch would be robust. >>> >>> Fixed. >>> >>> >>> Thanks, >>> >>> Yasumasa >>> >>> >>>> Thanks, >>>> David >>>> ----- >>>> >>>>> >>>>> Thanks, >>>>> >>>>> Yasumasa >>>>> >>>>> >>>>> On 2020/07/01 8:48, David Holmes wrote: >>>>>> Hi Yasumasa, >>>>>> >>>>>> On 1/07/2020 9:05 am, Yasumasa Suenaga wrote: >>>>>>> Hi David, >>>>>>> >>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>> >>>>>>>>>> IIUC at this point the _calling_thread is the current thread, >>>>>>>>>> so we can use: >>>>>>>>>> >>>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>> >>>>>>> If so, we can call make_local() in L1272 without JavaThread (or >>>>>>> we can pass current thread to make_local()). Is it right? >>>>>>> >>>>>>> ``` >>>>>>> 1271???? ResourceMark rm; >>>>>>> 1272 >>>>>>> _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, >>>>>>> thread_oop), >>>>>>> 1273??????????????????????????? jt, thread_oop); >>>>>>> ``` >>>>>> >>>>>> Sorry I got confused, _calling_thread may not be the current >>>>>> thread as we could be executing the handshake in the target >>>>>> thread itself. So the ResourceMark is correct as-is (implicitly >>>>>> for current thread). >>>>>> >>>>>> The argument to fill_frames will be used in the jvmtiStackInfo >>>>>> and passed back to the _calling_thread, so it must be created via >>>>>> make_local(_calling_thread, ...) as you presently have. >>>>>> >>>>>> Thanks, >>>>>> David >>>>>> >>>>>>> Thanks, >>>>>>> >>>>>>> Yasumasa >>>>>>> >>>>>>> >>>>>>> On 2020/07/01 7:05, David Holmes wrote: >>>>>>>> On 1/07/2020 12:17 am, Yasumasa Suenaga wrote: >>>>>>>>> Hi David, >>>>>>>>> >>>>>>>>> Thank you for reviewing! I will update new webrev tomorrow. >>>>>>>>> >>>>>>>>>> 466 class MultipleStackTracesCollector : public StackObj { >>>>>>>>>> >>>>>>>>>> ? 498 class VM_GetAllStackTraces : public VM_Operation { >>>>>>>>>> ? 499 private: >>>>>>>>>> ? 500?? JavaThread *_calling_thread; >>>>>>>>>> ? 501?? jint _final_thread_count; >>>>>>>>>> ? 502?? MultipleStackTracesCollector _collector; >>>>>>>>>> >>>>>>>>>> You can't have a StackObj as a member of another class like >>>>>>>>>> that as it may not be on the stack. I think >>>>>>>>>> MultipleStackTracesCollector should not extend any allocation >>>>>>>>>> class, and should always be embedded directly in another class. >>>>>>>>> >>>>>>>>> I'm not sure what does mean "embedded". >>>>>>>>> Is it ok as below? >>>>>>>>> >>>>>>>>> ``` >>>>>>>>> class MultipleStackTracesCollector { >>>>>>>>> ??? : >>>>>>>>> } >>>>>>>>> >>>>>>>>> class GetAllStackTraces : public VM_Operation { >>>>>>>>> ?? private: >>>>>>>>> ???? MultipleStackTracesCollector _collector; >>>>>>>>> } >>>>>>>>> ``` >>>>>>>> >>>>>>>> Yes that I what I meant. >>>>>>>> >>>>>>>> Thanks, >>>>>>>> David >>>>>>>> ----- >>>>>>>> >>>>>>>>> >>>>>>>>> Thanks, >>>>>>>>> >>>>>>>>> Yasumasa >>>>>>>>> >>>>>>>>> >>>>>>>>> On 2020/06/30 22:22, David Holmes wrote: >>>>>>>>>> Hi Yasumasa, >>>>>>>>>> >>>>>>>>>> On 30/06/2020 10:05 am, Yasumasa Suenaga wrote: >>>>>>>>>>> Hi David, Serguei, >>>>>>>>>>> >>>>>>>>>>> I updated webrev for 8242428. Could you review again? >>>>>>>>>>> This change migrate to use direct handshake for >>>>>>>>>>> GetStackTrace() and GetThreadListStackTraces() (when >>>>>>>>>>> thread_count == 1). >>>>>>>>>>> >>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.01/ >>>>>>>>>> >>>>>>>>>> This looks really good now! I only have a few nits below. >>>>>>>>>> There is one thing I don't like about it but it requires a >>>>>>>>>> change to the main Handshake logic to address - in >>>>>>>>>> JvmtiEnv::GetThreadListStackTraces you have to create a >>>>>>>>>> ThreadsListHandle to convert the jthread to a JavaThread, but >>>>>>>>>> then the Handshake::execute_direct creates another >>>>>>>>>> ThreadsListHandle internally. That's a waste. I will discuss >>>>>>>>>> with Robbin and file a RFE to have an overload of >>>>>>>>>> execute_direct that takes an existing TLH. Actually it's >>>>>>>>>> worse than that because we have another TLH in use at the >>>>>>>>>> entry point for the JVMTI functions, so I think there may be >>>>>>>>>> some scope for simplifying the use of TLH instances - future >>>>>>>>>> RFE. >>>>>>>>>> >>>>>>>>>> --- >>>>>>>>>> >>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>>>>>> >>>>>>>>>> ??451?? GetStackTraceClosure(JvmtiEnv *env, jint start_depth, >>>>>>>>>> jint max_count, >>>>>>>>>> ??452??????????????????????? jvmtiFrameInfo* frame_buffer, >>>>>>>>>> jint* count_ptr) >>>>>>>>>> ??453???? : HandshakeClosure("GetStackTrace"), >>>>>>>>>> ??454?????? _env(env), _start_depth(start_depth), >>>>>>>>>> _max_count(max_count), >>>>>>>>>> ??455?????? _frame_buffer(frame_buffer), _count_ptr(count_ptr), >>>>>>>>>> ??456 _result(JVMTI_ERROR_THREAD_NOT_ALIVE) { >>>>>>>>>> >>>>>>>>>> Nit: can you do one initializer per line please. >>>>>>>>>> >>>>>>>>>> This looks wrong: >>>>>>>>>> >>>>>>>>>> 466 class MultipleStackTracesCollector : public StackObj { >>>>>>>>>> >>>>>>>>>> ??498 class VM_GetAllStackTraces : public VM_Operation { >>>>>>>>>> ??499 private: >>>>>>>>>> ??500?? JavaThread *_calling_thread; >>>>>>>>>> ??501?? jint _final_thread_count; >>>>>>>>>> ??502?? MultipleStackTracesCollector _collector; >>>>>>>>>> >>>>>>>>>> You can't have a StackObj as a member of another class like >>>>>>>>>> that as it may not be on the stack. I think >>>>>>>>>> MultipleStackTracesCollector should not extend any allocation >>>>>>>>>> class, and should always be embedded directly in another class. >>>>>>>>>> >>>>>>>>>> 481?? MultipleStackTracesCollector(JvmtiEnv *env, jint >>>>>>>>>> max_frame_count) { >>>>>>>>>> ??482???? _env = env; >>>>>>>>>> ??483???? _max_frame_count = max_frame_count; >>>>>>>>>> ??484???? _frame_count_total = 0; >>>>>>>>>> ??485???? _head = NULL; >>>>>>>>>> ??486???? _stack_info = NULL; >>>>>>>>>> ??487???? _result = JVMTI_ERROR_NONE; >>>>>>>>>> ??488?? } >>>>>>>>>> >>>>>>>>>> As you are touching this can you change it to use an >>>>>>>>>> initializer list as you did for the HandshakeClosure, and >>>>>>>>>> please keep one item per line. >>>>>>>>>> >>>>>>>>>> --- >>>>>>>>>> >>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>> >>>>>>>>>> ??820 assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>>> ??821 java_thread->is_thread_fully_suspended(false, >>>>>>>>>> &debug_bits) || >>>>>>>>>> ??822????????? current_thread == >>>>>>>>>> java_thread->active_handshaker(), >>>>>>>>>> ??823????????? "at safepoint / handshake or target thread is >>>>>>>>>> suspended"); >>>>>>>>>> >>>>>>>>>> I don't think the suspension check is necessary, as even if >>>>>>>>>> the target is suspended we must still be at a safepoint or in >>>>>>>>>> a handshake with it. Makes me wonder if we used to allow a >>>>>>>>>> racy stacktrace operation on a suspended thread, assuming it >>>>>>>>>> would remain suspended? >>>>>>>>>> >>>>>>>>>> 1268?? oop thread_oop = jt->threadObj(); >>>>>>>>>> 1269 >>>>>>>>>> 1270?? if (!jt->is_exiting() && (jt->threadObj() != NULL)) { >>>>>>>>>> >>>>>>>>>> You can use thread_oop in line 1270. >>>>>>>>>> >>>>>>>>>> 1272 >>>>>>>>>> _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, >>>>>>>>>> thread_oop), >>>>>>>>>> 1273??????????????????????????? jt, thread_oop); >>>>>>>>>> >>>>>>>>>> It is frustrating that this entire call chain started with a >>>>>>>>>> jthread reference, which we converted to a JavaThread, only >>>>>>>>>> to eventually need to convert it back to a jthread! I think >>>>>>>>>> there is some scope for simplification here but not as part >>>>>>>>>> of this change. >>>>>>>>>> >>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>> >>>>>>>>>> IIUC at this point the _calling_thread is the current thread, >>>>>>>>>> so we can use: >>>>>>>>>> >>>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>>>>> >>>>>>>>>> --- >>>>>>>>>> >>>>>>>>>> Please add @bug lines to the tests. >>>>>>>>>> >>>>>>>>>> I'm still pondering the test logic but wanted to send this now. >>>>>>>>>> >>>>>>>>>> Thanks, >>>>>>>>>> David >>>>>>>>>> ----- >>>>>>>>>>> VM_GetThreadListStackTrace (for GetThreadListStackTraces) >>>>>>>>>>> and VM_GetAllStackTraces (for GetAllStackTraces) have >>>>>>>>>>> inherited VM_GetMultipleStackTraces VM operation which >>>>>>>>>>> provides the feature to generate jvmtiStackInfo. I modified >>>>>>>>>>> VM_GetMultipleStackTraces to a normal C++ class to share >>>>>>>>>>> with HandshakeClosure for GetThreadListStackTraces >>>>>>>>>>> (GetSingleStackTraceClosure). >>>>>>>>>>> >>>>>>>>>>> Also I added new testcases which test >>>>>>>>>>> GetThreadListStackTraces() with thread_count == 1 and with >>>>>>>>>>> all threads. >>>>>>>>>>> >>>>>>>>>>> This change has been tested in serviceability/jvmti >>>>>>>>>>> serviceability/jdwp vmTestbase/nsk/jvmti vmTestbase/nsk/jdi >>>>>>>>>>> vmTestbase/nsk/jdwp. >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> Thanks, >>>>>>>>>>> >>>>>>>>>>> Yasumasa >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> On 2020/06/24 15:50, Yasumasa Suenaga wrote: >>>>>>>>>>>> Hi all, >>>>>>>>>>>> >>>>>>>>>>>> Please review this change: >>>>>>>>>>>> >>>>>>>>>>>> ?? JBS: https://bugs.openjdk.java.net/browse/JDK-8242428 >>>>>>>>>>>> ?? webrev: >>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.00/ >>>>>>>>>>>> >>>>>>>>>>>> This change replace following VM operations to direct >>>>>>>>>>>> handshake. >>>>>>>>>>>> >>>>>>>>>>>> ??- VM_GetFrameCount (GetFrameCount()) >>>>>>>>>>>> ??- VM_GetFrameLocation (GetFrameLocation()) >>>>>>>>>>>> ??- VM_GetThreadListStackTraces (GetThreadListStackTrace()) >>>>>>>>>>>> ??- VM_GetCurrentLocation >>>>>>>>>>>> >>>>>>>>>>>> GetThreadListStackTrace() uses direct handshake if thread >>>>>>>>>>>> count == 1. In other case (thread count > 1), it would be >>>>>>>>>>>> performed as VM operation (VM_GetThreadListStackTraces). >>>>>>>>>>>> Caller of VM_GetCurrentLocation >>>>>>>>>>>> (JvmtiEnvThreadState::reset_current_location()) might be >>>>>>>>>>>> called at safepoint. So I added safepoint check in its caller. >>>>>>>>>>>> >>>>>>>>>>>> This change has been tested in serviceability/jvmti >>>>>>>>>>>> serviceability/jdwp vmTestbase/nsk/jvmti vmTestbase/nsk/jdi >>>>>>>>>>>> vmTestbase/ns >>>>>>>>>>>> k/jdwp. >>>>>>>>>>>> >>>>>>>>>>>> Also I tested it on submit repo, then it has execution >>>>>>>>>>>> error >>>>>>>>>>>> (mach5-one-ysuenaga-JDK-8242428-20200624-0054-12034717) due >>>>>>>>>>>> to dependency error. So I think it does not occur by this >>>>>>>>>>>> change. >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> Thanks, >>>>>>>>>>>> >>>>>>>>>>>> Yasumasa >> From vladimir.kozlov at oracle.com Fri Jul 3 02:02:06 2020 From: vladimir.kozlov at oracle.com (Vladimir Kozlov) Date: Thu, 2 Jul 2020 19:02:06 -0700 Subject: [15] RFR(T) 8247527: serviceability/dcmd/gc/HeapDumpCompressedTest.java fails with Graal + ZGC Message-ID: https://cr.openjdk.java.net/~kvn/8247527/webrev.00/ https://bugs.openjdk.java.net/browse/JDK-8247527 Test should have @requires which excludes running Graal with GC which it does not support. Testing: hs-tier1,hs-tier4-graal Thanks, Vladimir From igor.ignatyev at oracle.com Fri Jul 3 02:24:15 2020 From: igor.ignatyev at oracle.com (igor.ignatyev at oracle.com) Date: Thu, 2 Jul 2020 19:24:15 -0700 Subject: [15] RFR(T) 8247527: serviceability/dcmd/gc/HeapDumpCompressedTest.java fails with Graal + ZGC In-Reply-To: References: Message-ID: <5E33E613-882E-400A-886A-EA4FAD85F2EA@oracle.com> LGTM ? Igor > On Jul 2, 2020, at 7:03 PM, Vladimir Kozlov wrote: > > ?https://cr.openjdk.java.net/~kvn/8247527/webrev.00/ > https://bugs.openjdk.java.net/browse/JDK-8247527 > > Test should have @requires which excludes running Graal with GC which it does not support. > > Testing: hs-tier1,hs-tier4-graal > > Thanks, > Vladimir From david.holmes at oracle.com Fri Jul 3 02:25:45 2020 From: david.holmes at oracle.com (David Holmes) Date: Fri, 3 Jul 2020 12:25:45 +1000 Subject: [15] RFR(T) 8247527: serviceability/dcmd/gc/HeapDumpCompressedTest.java fails with Graal + ZGC In-Reply-To: References: Message-ID: Hi Vladimir, On 3/07/2020 12:02 pm, Vladimir Kozlov wrote: > https://cr.openjdk.java.net/~kvn/8247527/webrev.00/ > https://bugs.openjdk.java.net/browse/JDK-8247527 > > Test should have @requires which excludes running Graal with GC which it > does not support. I find it somewhat disturbing that a generic test has to know about the limitations between GCs and Graal! I would have been more inclined to just exclude this test when running with Graal, even if that theoretically reduced the test coverage in a ting way. If/When Graal supports these other GCs who will remember to re-enable these test cases? Thanks, David > Testing: hs-tier1,hs-tier4-graal > > Thanks, > Vladimir From david.holmes at oracle.com Fri Jul 3 02:50:03 2020 From: david.holmes at oracle.com (David Holmes) Date: Fri, 3 Jul 2020 12:50:03 +1000 Subject: RFR: 8242428: JVMTI thread operations should use Thread-Local Handshake In-Reply-To: <90cdfef9-e558-0d25-33f5-25b7d65bb83b@oss.nttdata.com> References: <6c263e4c-0a83-be7a-0288-ecb2de0b7cea@oss.nttdata.com> <2ea2f5d8-5c43-a7d3-d525-cd44c4009d25@oss.nttdata.com> <65889ab4-6b7e-86fb-59cc-012520b83138@oracle.com> <4b7df6f8-c8f7-fedf-6366-b885d2235b58@oss.nttdata.com> <74c05dfd-ffb2-b73d-66e5-dc98752729f5@oss.nttdata.com> <763793b1-9506-44c6-0681-1c71c44a44fd@oss.nttdata.com> <5107c478-1de2-7a49-ee71-dfad6a99a667@oracle.com> <90cdfef9-e558-0d25-33f5-25b7d65bb83b@oss.nttdata.com> Message-ID: <0e359819-618f-c17b-a427-bb7e4daa2c58@oracle.com> Sorry I'm responding here without seeing latest webrev but there is enough context I think ... On 3/07/2020 9:14 am, Yasumasa Suenaga wrote: > Hi Dan, > > Thanks for your comment! > > On 2020/07/03 7:16, Daniel D. Daugherty wrote: >> On 7/2/20 5:19 AM, Yasumasa Suenaga wrote: >>> Hi David, >>> >>> I upload new webrev. Could you review again? >>> >>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.03/ >> >> src/hotspot/share/prims/jvmtiEnv.cpp >> ???? L1542: ??? // Get stack trace with handshake >> ???????? nit - please add a period at the end. > > I will fix it. > > >> ???? L1591: ??? *stack_info_ptr = op.stack_info(); >> ???????? The return parameter should not be touched unless the return >> ???????? code in 'err' == JVMTI_ERROR_NONE. >> >> ???? old L1582: ? if (err == JVMTI_ERROR_NONE) { >> ???????? Please restore this check. The return parameter should not >> ???????? be touched unless the return code in 'err' == JVMTI_ERROR_NONE. > > I will fix it. But op.stack_info() will return NULL if the error is not JVMTI_ERROR_NONE. Are you (Dan) concerned about someone passing in a non-null/initialized out-pointer that will be reset to NULL if there was an error? > >> ???? L1272: ? if (!jt->is_exiting() && (thread_oop != NULL)) { >> ???????? nit - extra parens around the second expression. > > I will fix it. > > >> src/hotspot/share/prims/jvmtiEnvBase.cpp >> ???? old L1532: ? _result = JVMTI_ERROR_THREAD_NOT_ALIVE; >> ???????? This deletion of the _result field threw me for a minute and >> then >> ???? ? ? I figured out that the field is init to >> JVMTI_ERROR_THREAD_NOT_ALIVE >> ???????? in the constructor. >> >> ???? L1553: ? if (!jt->is_exiting() && (jt->threadObj() != NULL)) { >> ???????? nit - extra parens around the second expression. > > I will fix it. > > >> src/hotspot/share/prims/jvmtiEnvBase.hpp >> ???? No comments. >> >> src/hotspot/share/runtime/vmOperations.hpp >> ???? No comments. >> >> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/GetThreadListStackTraces.java >> >> ???? No comments. >> >> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/OneGetThreadListStackTraces.java >> >> ???? L64: ??????? startSignal.countDown(); >> ???????? I was expecting this to be a call to await() instead of >> ???????? countDown(). What am I missing here? >> >> ???????? I think this test might be passing by accident right now, but... > > Main thread (which call JVMTI functions to test) should wait until test > thread is ready. > So main thread would wait startSignal, and test thread would count down. No! The test thread that previously called obj.wait() now calls latch.await(). The main thread that previously called obj.notify() now calls latch.countDown(). The main thread continues to spin until it sees the target is WAITING before proceeding with the test. > >> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libGetThreadListStackTraces.c >> >> ???? L92: ? jthreads = (jthread *)malloc(sizeof(jthread) * num_threads); >> ???????? You don't check for malloc() failure. >> ???????? 'jthreads' is allocated but never freed. > > I will fix it. > > >> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.c >> >> ???? L91: ? result = (*jvmti)->SuspendThread(jvmti, thread); >> ???????? Why are you suspending the thread? GetAllStackTraces() and >> ???????? GetThreadListStackTraces() do not require the target thread(s) >> ???????? to be suspend. >> >> ???????? If you decide not to SuspendThread, then you don't need the >> ???????? AddCapabilities or the ResumeThread calls. > > Test thread might not be entered following code (stopSignal.await()). We > might see deferent call stack between GetAllStackTraces() and > GetThreadListStackTraces(). We cannot control to freeze call stack of > test thread in Java code. > (I didn't use SuspendThread() at first, but I saw some errors which > causes in above.) > > So we need to call SuspendThread() to ensure we can see same call stack. If you are checking that the thread is in state WAITING then it cannot escape from that state and you can sample the stack multiple times from any API and get the same result. I suspect the errors you saw were from the apparent incorrect use of the CountDownLatch. Cheers, David ----- > > Thanks, > > Yasumasa > > >> Dan >> >>> >>> On 2020/07/02 15:05, David Holmes wrote: >>>> Hi Yasumasa, >>>> >>>> On 1/07/2020 11:53 am, Yasumasa Suenaga wrote: >>>>> Hi, >>>>> >>>>> I uploaded new webrev. Could review again? >>>>> >>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.02/ >>>> >>>> Updates look fine - thanks. >>>> >>>> One minor nit: >>>> >>>> 1274???? _collector.allocate_and_fill_stacks(1); >>>> 1275???? _collector.set_result(JVMTI_ERROR_NONE); >>>> >>>> In the other places where you use _collector you rely on result >>>> being initialized to JVMTI_ERROR_NONE, rather than setting it >>>> directly after allocate_and_fill_stacks(). >>> >>> Fixed. >>> >>> >>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>> >>>>>>>>>> ? 820 assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>>> ? 821 java_thread->is_thread_fully_suspended(false, >>>>>>>>>> &debug_bits) || >>>>>>>>>> ? 822????????? current_thread == >>>>>>>>>> java_thread->active_handshaker(), >>>>>>>>>> ? 823????????? "at safepoint / handshake or target thread is >>>>>>>>>> suspended"); >>>>>>>>>> >>>>>>>>>> I don't think the suspension check is necessary, as even if >>>>>>>>>> the target is suspended we must still be at a safepoint or in >>>>>>>>>> a handshake with it. Makes me wonder if we used to allow a >>>>>>>>>> racy stacktrace operation on a suspended thread, assuming it >>>>>>>>>> would remain suspended? >>>>> >>>>> This function (JvmtiEnvBase::get_stack_trace()) can be called to >>>>> get own stack trace. For example, we can call GetStackTrace() for >>>>> current thread at JVMTI event. >>>>> So I changed assert as below: >>>>> >>>>> ``` >>>>> ??820?? assert(current_thread == java_thread || >>>>> ??821????????? SafepointSynchronize::is_at_safepoint() || >>>>> ??822????????? current_thread == java_thread->active_handshaker(), >>>>> ??823????????? "call by myself / at safepoint / at handshake"); >>>>> ``` >>>> >>>> Yep good catch. I hope current tests caught that. >>> >>> They would be tested in >>> vmTestbase/nsk/jvmti/GetStackTrace/getstacktr001/ (own call stacks), >>> and getstacktr003 (call stacks in other thread). >>> >>> >>>> Speaking of tests ... >>>> >>>> In the native code I think you need to check the success of all JNI >>>> methods that can throw exceptions - otherwise I believe the tests >>>> may trigger warnings if -Xcheck:jni is used with them. See for example: >>>> >>>> test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/libHeapMonitorTest.cpp >>>> >>> >>> I updated testcases to check JNI and JVMTI function calls. >>> >>> >>>> In the Java code the target thread: >>>> >>>> ?? 45???? public void run() { >>>> ?? 46?????? try { >>>> ?? 47?????????? synchronized (lock) { >>>> ?? 48?????????????? lock.wait(); >>>> ?? 49?????????????? System.out.println("OK"); >>>> ?? 50?????????? } >>>> >>>> is potentially susceptible to spurious wakeups. Using a >>>> CountDownLatch would be robust. >>> >>> Fixed. >>> >>> >>> Thanks, >>> >>> Yasumasa >>> >>> >>>> Thanks, >>>> David >>>> ----- >>>> >>>>> >>>>> Thanks, >>>>> >>>>> Yasumasa >>>>> >>>>> >>>>> On 2020/07/01 8:48, David Holmes wrote: >>>>>> Hi Yasumasa, >>>>>> >>>>>> On 1/07/2020 9:05 am, Yasumasa Suenaga wrote: >>>>>>> Hi David, >>>>>>> >>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>> >>>>>>>>>> IIUC at this point the _calling_thread is the current thread, >>>>>>>>>> so we can use: >>>>>>>>>> >>>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>> >>>>>>> If so, we can call make_local() in L1272 without JavaThread (or >>>>>>> we can pass current thread to make_local()). Is it right? >>>>>>> >>>>>>> ``` >>>>>>> 1271???? ResourceMark rm; >>>>>>> 1272 >>>>>>> _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, >>>>>>> thread_oop), >>>>>>> 1273??????????????????????????? jt, thread_oop); >>>>>>> ``` >>>>>> >>>>>> Sorry I got confused, _calling_thread may not be the current >>>>>> thread as we could be executing the handshake in the target thread >>>>>> itself. So the ResourceMark is correct as-is (implicitly for >>>>>> current thread). >>>>>> >>>>>> The argument to fill_frames will be used in the jvmtiStackInfo and >>>>>> passed back to the _calling_thread, so it must be created via >>>>>> make_local(_calling_thread, ...) as you presently have. >>>>>> >>>>>> Thanks, >>>>>> David >>>>>> >>>>>>> Thanks, >>>>>>> >>>>>>> Yasumasa >>>>>>> >>>>>>> >>>>>>> On 2020/07/01 7:05, David Holmes wrote: >>>>>>>> On 1/07/2020 12:17 am, Yasumasa Suenaga wrote: >>>>>>>>> Hi David, >>>>>>>>> >>>>>>>>> Thank you for reviewing! I will update new webrev tomorrow. >>>>>>>>> >>>>>>>>>> 466 class MultipleStackTracesCollector : public StackObj { >>>>>>>>>> >>>>>>>>>> ? 498 class VM_GetAllStackTraces : public VM_Operation { >>>>>>>>>> ? 499 private: >>>>>>>>>> ? 500?? JavaThread *_calling_thread; >>>>>>>>>> ? 501?? jint _final_thread_count; >>>>>>>>>> ? 502?? MultipleStackTracesCollector _collector; >>>>>>>>>> >>>>>>>>>> You can't have a StackObj as a member of another class like >>>>>>>>>> that as it may not be on the stack. I think >>>>>>>>>> MultipleStackTracesCollector should not extend any allocation >>>>>>>>>> class, and should always be embedded directly in another class. >>>>>>>>> >>>>>>>>> I'm not sure what does mean "embedded". >>>>>>>>> Is it ok as below? >>>>>>>>> >>>>>>>>> ``` >>>>>>>>> class MultipleStackTracesCollector { >>>>>>>>> ??? : >>>>>>>>> } >>>>>>>>> >>>>>>>>> class GetAllStackTraces : public VM_Operation { >>>>>>>>> ?? private: >>>>>>>>> ???? MultipleStackTracesCollector _collector; >>>>>>>>> } >>>>>>>>> ``` >>>>>>>> >>>>>>>> Yes that I what I meant. >>>>>>>> >>>>>>>> Thanks, >>>>>>>> David >>>>>>>> ----- >>>>>>>> >>>>>>>>> >>>>>>>>> Thanks, >>>>>>>>> >>>>>>>>> Yasumasa >>>>>>>>> >>>>>>>>> >>>>>>>>> On 2020/06/30 22:22, David Holmes wrote: >>>>>>>>>> Hi Yasumasa, >>>>>>>>>> >>>>>>>>>> On 30/06/2020 10:05 am, Yasumasa Suenaga wrote: >>>>>>>>>>> Hi David, Serguei, >>>>>>>>>>> >>>>>>>>>>> I updated webrev for 8242428. Could you review again? >>>>>>>>>>> This change migrate to use direct handshake for >>>>>>>>>>> GetStackTrace() and GetThreadListStackTraces() (when >>>>>>>>>>> thread_count == 1). >>>>>>>>>>> >>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.01/ >>>>>>>>>> >>>>>>>>>> This looks really good now! I only have a few nits below. >>>>>>>>>> There is one thing I don't like about it but it requires a >>>>>>>>>> change to the main Handshake logic to address - in >>>>>>>>>> JvmtiEnv::GetThreadListStackTraces you have to create a >>>>>>>>>> ThreadsListHandle to convert the jthread to a JavaThread, but >>>>>>>>>> then the Handshake::execute_direct creates another >>>>>>>>>> ThreadsListHandle internally. That's a waste. I will discuss >>>>>>>>>> with Robbin and file a RFE to have an overload of >>>>>>>>>> execute_direct that takes an existing TLH. Actually it's worse >>>>>>>>>> than that because we have another TLH in use at the entry >>>>>>>>>> point for the JVMTI functions, so I think there may be some >>>>>>>>>> scope for simplifying the use of TLH instances - future RFE. >>>>>>>>>> >>>>>>>>>> --- >>>>>>>>>> >>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>>>>>> >>>>>>>>>> ??451?? GetStackTraceClosure(JvmtiEnv *env, jint start_depth, >>>>>>>>>> jint max_count, >>>>>>>>>> ??452??????????????????????? jvmtiFrameInfo* frame_buffer, >>>>>>>>>> jint* count_ptr) >>>>>>>>>> ??453???? : HandshakeClosure("GetStackTrace"), >>>>>>>>>> ??454?????? _env(env), _start_depth(start_depth), >>>>>>>>>> _max_count(max_count), >>>>>>>>>> ??455?????? _frame_buffer(frame_buffer), _count_ptr(count_ptr), >>>>>>>>>> ??456?????? _result(JVMTI_ERROR_THREAD_NOT_ALIVE) { >>>>>>>>>> >>>>>>>>>> Nit: can you do one initializer per line please. >>>>>>>>>> >>>>>>>>>> This looks wrong: >>>>>>>>>> >>>>>>>>>> 466 class MultipleStackTracesCollector : public StackObj { >>>>>>>>>> >>>>>>>>>> ??498 class VM_GetAllStackTraces : public VM_Operation { >>>>>>>>>> ??499 private: >>>>>>>>>> ??500?? JavaThread *_calling_thread; >>>>>>>>>> ??501?? jint _final_thread_count; >>>>>>>>>> ??502?? MultipleStackTracesCollector _collector; >>>>>>>>>> >>>>>>>>>> You can't have a StackObj as a member of another class like >>>>>>>>>> that as it may not be on the stack. I think >>>>>>>>>> MultipleStackTracesCollector should not extend any allocation >>>>>>>>>> class, and should always be embedded directly in another class. >>>>>>>>>> >>>>>>>>>> 481?? MultipleStackTracesCollector(JvmtiEnv *env, jint >>>>>>>>>> max_frame_count) { >>>>>>>>>> ??482???? _env = env; >>>>>>>>>> ??483???? _max_frame_count = max_frame_count; >>>>>>>>>> ??484???? _frame_count_total = 0; >>>>>>>>>> ??485???? _head = NULL; >>>>>>>>>> ??486???? _stack_info = NULL; >>>>>>>>>> ??487???? _result = JVMTI_ERROR_NONE; >>>>>>>>>> ??488?? } >>>>>>>>>> >>>>>>>>>> As you are touching this can you change it to use an >>>>>>>>>> initializer list as you did for the HandshakeClosure, and >>>>>>>>>> please keep one item per line. >>>>>>>>>> >>>>>>>>>> --- >>>>>>>>>> >>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>> >>>>>>>>>> ??820 assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>>> ??821 java_thread->is_thread_fully_suspended(false, >>>>>>>>>> &debug_bits) || >>>>>>>>>> ??822????????? current_thread == >>>>>>>>>> java_thread->active_handshaker(), >>>>>>>>>> ??823????????? "at safepoint / handshake or target thread is >>>>>>>>>> suspended"); >>>>>>>>>> >>>>>>>>>> I don't think the suspension check is necessary, as even if >>>>>>>>>> the target is suspended we must still be at a safepoint or in >>>>>>>>>> a handshake with it. Makes me wonder if we used to allow a >>>>>>>>>> racy stacktrace operation on a suspended thread, assuming it >>>>>>>>>> would remain suspended? >>>>>>>>>> >>>>>>>>>> 1268?? oop thread_oop = jt->threadObj(); >>>>>>>>>> 1269 >>>>>>>>>> 1270?? if (!jt->is_exiting() && (jt->threadObj() != NULL)) { >>>>>>>>>> >>>>>>>>>> You can use thread_oop in line 1270. >>>>>>>>>> >>>>>>>>>> 1272 >>>>>>>>>> _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, >>>>>>>>>> thread_oop), >>>>>>>>>> 1273??????????????????????????? jt, thread_oop); >>>>>>>>>> >>>>>>>>>> It is frustrating that this entire call chain started with a >>>>>>>>>> jthread reference, which we converted to a JavaThread, only to >>>>>>>>>> eventually need to convert it back to a jthread! I think there >>>>>>>>>> is some scope for simplification here but not as part of this >>>>>>>>>> change. >>>>>>>>>> >>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>> >>>>>>>>>> IIUC at this point the _calling_thread is the current thread, >>>>>>>>>> so we can use: >>>>>>>>>> >>>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>>>>> >>>>>>>>>> --- >>>>>>>>>> >>>>>>>>>> Please add @bug lines to the tests. >>>>>>>>>> >>>>>>>>>> I'm still pondering the test logic but wanted to send this now. >>>>>>>>>> >>>>>>>>>> Thanks, >>>>>>>>>> David >>>>>>>>>> ----- >>>>>>>>>>> VM_GetThreadListStackTrace (for GetThreadListStackTraces) and >>>>>>>>>>> VM_GetAllStackTraces (for GetAllStackTraces) have inherited >>>>>>>>>>> VM_GetMultipleStackTraces VM operation which provides the >>>>>>>>>>> feature to generate jvmtiStackInfo. I modified >>>>>>>>>>> VM_GetMultipleStackTraces to a normal C++ class to share with >>>>>>>>>>> HandshakeClosure for GetThreadListStackTraces >>>>>>>>>>> (GetSingleStackTraceClosure). >>>>>>>>>>> >>>>>>>>>>> Also I added new testcases which test >>>>>>>>>>> GetThreadListStackTraces() with thread_count == 1 and with >>>>>>>>>>> all threads. >>>>>>>>>>> >>>>>>>>>>> This change has been tested in serviceability/jvmti >>>>>>>>>>> serviceability/jdwp vmTestbase/nsk/jvmti vmTestbase/nsk/jdi >>>>>>>>>>> vmTestbase/nsk/jdwp. >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> Thanks, >>>>>>>>>>> >>>>>>>>>>> Yasumasa >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> On 2020/06/24 15:50, Yasumasa Suenaga wrote: >>>>>>>>>>>> Hi all, >>>>>>>>>>>> >>>>>>>>>>>> Please review this change: >>>>>>>>>>>> >>>>>>>>>>>> ?? JBS: https://bugs.openjdk.java.net/browse/JDK-8242428 >>>>>>>>>>>> ?? webrev: >>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.00/ >>>>>>>>>>>> >>>>>>>>>>>> This change replace following VM operations to direct >>>>>>>>>>>> handshake. >>>>>>>>>>>> >>>>>>>>>>>> ??- VM_GetFrameCount (GetFrameCount()) >>>>>>>>>>>> ??- VM_GetFrameLocation (GetFrameLocation()) >>>>>>>>>>>> ??- VM_GetThreadListStackTraces (GetThreadListStackTrace()) >>>>>>>>>>>> ??- VM_GetCurrentLocation >>>>>>>>>>>> >>>>>>>>>>>> GetThreadListStackTrace() uses direct handshake if thread >>>>>>>>>>>> count == 1. In other case (thread count > 1), it would be >>>>>>>>>>>> performed as VM operation (VM_GetThreadListStackTraces). >>>>>>>>>>>> Caller of VM_GetCurrentLocation >>>>>>>>>>>> (JvmtiEnvThreadState::reset_current_location()) might be >>>>>>>>>>>> called at safepoint. So I added safepoint check in its caller. >>>>>>>>>>>> >>>>>>>>>>>> This change has been tested in serviceability/jvmti >>>>>>>>>>>> serviceability/jdwp vmTestbase/nsk/jvmti vmTestbase/nsk/jdi >>>>>>>>>>>> vmTestbase/ns >>>>>>>>>>>> k/jdwp. >>>>>>>>>>>> >>>>>>>>>>>> Also I tested it on submit repo, then it has execution error >>>>>>>>>>>> (mach5-one-ysuenaga-JDK-8242428-20200624-0054-12034717) due >>>>>>>>>>>> to dependency error. So I think it does not occur by this >>>>>>>>>>>> change. >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> Thanks, >>>>>>>>>>>> >>>>>>>>>>>> Yasumasa >> From igor.ignatyev at oracle.com Fri Jul 3 02:59:35 2020 From: igor.ignatyev at oracle.com (Igor Ignatyev) Date: Thu, 2 Jul 2020 19:59:35 -0700 Subject: [15] RFR(T) 8247527: serviceability/dcmd/gc/HeapDumpCompressedTest.java fails with Graal + ZGC In-Reply-To: References: Message-ID: Hi David, it's in my todo list to improve this situation and have vm.gc.X to take selected JIT into account; and update existing (>200) occurrences of 'vm.gc.X & !vm.graal.enabled' -- Igor > On Jul 2, 2020, at 7:25 PM, David Holmes wrote: > > Hi Vladimir, > > On 3/07/2020 12:02 pm, Vladimir Kozlov wrote: >> https://cr.openjdk.java.net/~kvn/8247527/webrev.00/ >> https://bugs.openjdk.java.net/browse/JDK-8247527 >> Test should have @requires which excludes running Graal with GC which it does not support. > > I find it somewhat disturbing that a generic test has to know about the limitations between GCs and Graal! > > I would have been more inclined to just exclude this test when running with Graal, even if that theoretically reduced the test coverage in a ting way. > > If/When Graal supports these other GCs who will remember to re-enable these test cases? > > Thanks, > David > >> Testing: hs-tier1,hs-tier4-graal >> Thanks, >> Vladimir From daniel.daugherty at oracle.com Fri Jul 3 03:24:06 2020 From: daniel.daugherty at oracle.com (Daniel D. Daugherty) Date: Thu, 2 Jul 2020 23:24:06 -0400 Subject: RFR: 8242428: JVMTI thread operations should use Thread-Local Handshake In-Reply-To: <0e359819-618f-c17b-a427-bb7e4daa2c58@oracle.com> References: <6c263e4c-0a83-be7a-0288-ecb2de0b7cea@oss.nttdata.com> <2ea2f5d8-5c43-a7d3-d525-cd44c4009d25@oss.nttdata.com> <65889ab4-6b7e-86fb-59cc-012520b83138@oracle.com> <4b7df6f8-c8f7-fedf-6366-b885d2235b58@oss.nttdata.com> <74c05dfd-ffb2-b73d-66e5-dc98752729f5@oss.nttdata.com> <763793b1-9506-44c6-0681-1c71c44a44fd@oss.nttdata.com> <5107c478-1de2-7a49-ee71-dfad6a99a667@oracle.com> <90cdfef9-e558-0d25-33f5-25b7d65bb83b@oss.nttdata.com> <0e359819-618f-c17b-a427-bb7e4daa2c58@oracle.com> Message-ID: <3f890bed-6892-e64d-b21b-ca0cbe11784e@oracle.com> On 7/2/20 10:50 PM, David Holmes wrote: > Sorry I'm responding here without seeing latest webrev but there is > enough context I think ... > > On 3/07/2020 9:14 am, Yasumasa Suenaga wrote: >> Hi Dan, >> >> Thanks for your comment! >> >> On 2020/07/03 7:16, Daniel D. Daugherty wrote: >>> On 7/2/20 5:19 AM, Yasumasa Suenaga wrote: >>>> Hi David, >>>> >>>> I upload new webrev. Could you review again? >>>> >>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.03/ >>> >>> src/hotspot/share/prims/jvmtiEnv.cpp >>> ???? L1542: ??? // Get stack trace with handshake >>> ???????? nit - please add a period at the end. >> >> I will fix it. >> >> >>> ???? L1591: ??? *stack_info_ptr = op.stack_info(); >>> ???????? The return parameter should not be touched unless the return >>> ???????? code in 'err' == JVMTI_ERROR_NONE. >>> >>> ???? old L1582: ? if (err == JVMTI_ERROR_NONE) { >>> ???????? Please restore this check. The return parameter should not >>> ???????? be touched unless the return code in 'err' == >>> JVMTI_ERROR_NONE. >> >> I will fix it. > > But op.stack_info() will return NULL if the error is not > JVMTI_ERROR_NONE. Are you (Dan) concerned about someone passing in a > non-null/initialized out-pointer that will be reset to NULL if there > was an error? Actually the way we used to test this in POSIX tests is to call an API with known bad parameters and the return parameter ptr set to NULL. If the return parameter ptr was touched when an error should have been detected on an earlier parameter, then the test failed. > >> >>> ???? L1272: ? if (!jt->is_exiting() && (thread_oop != NULL)) { >>> ???????? nit - extra parens around the second expression. >> >> I will fix it. >> >> >>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>> ???? old L1532: ? _result = JVMTI_ERROR_THREAD_NOT_ALIVE; >>> ???????? This deletion of the _result field threw me for a minute >>> and then >>> ???? ? ? I figured out that the field is init to >>> JVMTI_ERROR_THREAD_NOT_ALIVE >>> ???????? in the constructor. >>> >>> ???? L1553: ? if (!jt->is_exiting() && (jt->threadObj() != NULL)) { >>> ???????? nit - extra parens around the second expression. >> >> I will fix it. >> >> >>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>> ???? No comments. >>> >>> src/hotspot/share/runtime/vmOperations.hpp >>> ???? No comments. >>> >>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/GetThreadListStackTraces.java >>> >>> ???? No comments. >>> >>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/OneGetThreadListStackTraces.java >>> >>> ???? L64: ??????? startSignal.countDown(); >>> ???????? I was expecting this to be a call to await() instead of >>> ???????? countDown(). What am I missing here? >>> >>> ???????? I think this test might be passing by accident right now, >>> but... >> >> Main thread (which call JVMTI functions to test) should wait until >> test thread is ready. >> So main thread would wait startSignal, and test thread would count down. > > No! > > The test thread that previously called obj.wait() now calls > latch.await(). > > The main thread that previously called obj.notify() now calls > latch.countDown(). > > The main thread continues to spin until it sees the target is WAITING > before proceeding with the test. Here's the flow as I see it: main thread ? - start worker thread ? - startSignal.await() ??? - main is now blocked worker thread ? - startSignal.countDown() ??? - main is now unblocked ? - stopSignal.await() ??? - worker is now blocked main thread ? - checkCallStacks(th) ? - stopSignal.countDown() ??? - worker is now unblocked ? - th.join ??? - main is now blocked worker thread ? - runs off the end of run() ??? - main is now unblocked main thread ? - run off the end of main() > >> >>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libGetThreadListStackTraces.c >>> >>> ???? L92: ? jthreads = (jthread *)malloc(sizeof(jthread) * >>> num_threads); >>> ???????? You don't check for malloc() failure. >>> ???????? 'jthreads' is allocated but never freed. >> >> I will fix it. >> >> >>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.c >>> >>> ???? L91: ? result = (*jvmti)->SuspendThread(jvmti, thread); >>> ???????? Why are you suspending the thread? GetAllStackTraces() and >>> ???????? GetThreadListStackTraces() do not require the target thread(s) >>> ???????? to be suspend. >>> >>> ???????? If you decide not to SuspendThread, then you don't need the >>> ???????? AddCapabilities or the ResumeThread calls. >> >> Test thread might not be entered following code (stopSignal.await()). >> We might see deferent call stack between GetAllStackTraces() and >> GetThreadListStackTraces(). We cannot control to freeze call stack of >> test thread in Java code. >> (I didn't use SuspendThread() at first, but I saw some errors which >> causes in above.) >> >> So we need to call SuspendThread() to ensure we can see same call stack. > > If you are checking that the thread is in state WAITING then it cannot > escape from that state and you can sample the stack multiple times > from any API and get the same result. > > I suspect the errors you saw were from the apparent incorrect use of > the CountDownLatch. With the flow outlined above, the worker thread should be nicely blocked in stopSignal.await() when stuff is sampled. Dan > > Cheers, > David > ----- > >> >> Thanks, >> >> Yasumasa >> >> >>> Dan >>> >>>> >>>> On 2020/07/02 15:05, David Holmes wrote: >>>>> Hi Yasumasa, >>>>> >>>>> On 1/07/2020 11:53 am, Yasumasa Suenaga wrote: >>>>>> Hi, >>>>>> >>>>>> I uploaded new webrev. Could review again? >>>>>> >>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.02/ >>>>> >>>>> Updates look fine - thanks. >>>>> >>>>> One minor nit: >>>>> >>>>> 1274???? _collector.allocate_and_fill_stacks(1); >>>>> 1275???? _collector.set_result(JVMTI_ERROR_NONE); >>>>> >>>>> In the other places where you use _collector you rely on result >>>>> being initialized to JVMTI_ERROR_NONE, rather than setting it >>>>> directly after allocate_and_fill_stacks(). >>>> >>>> Fixed. >>>> >>>> >>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>> >>>>>>>>>>> ? 820 assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>> ? 821 java_thread->is_thread_fully_suspended(false, >>>>>>>>>>> &debug_bits) || >>>>>>>>>>> ? 822????????? current_thread == >>>>>>>>>>> java_thread->active_handshaker(), >>>>>>>>>>> ? 823????????? "at safepoint / handshake or target thread is >>>>>>>>>>> suspended"); >>>>>>>>>>> >>>>>>>>>>> I don't think the suspension check is necessary, as even if >>>>>>>>>>> the target is suspended we must still be at a safepoint or >>>>>>>>>>> in a handshake with it. Makes me wonder if we used to allow >>>>>>>>>>> a racy stacktrace operation on a suspended thread, assuming >>>>>>>>>>> it would remain suspended? >>>>>> >>>>>> This function (JvmtiEnvBase::get_stack_trace()) can be called to >>>>>> get own stack trace. For example, we can call GetStackTrace() for >>>>>> current thread at JVMTI event. >>>>>> So I changed assert as below: >>>>>> >>>>>> ``` >>>>>> ??820?? assert(current_thread == java_thread || >>>>>> ??821????????? SafepointSynchronize::is_at_safepoint() || >>>>>> ??822????????? current_thread == java_thread->active_handshaker(), >>>>>> ??823????????? "call by myself / at safepoint / at handshake"); >>>>>> ``` >>>>> >>>>> Yep good catch. I hope current tests caught that. >>>> >>>> They would be tested in >>>> vmTestbase/nsk/jvmti/GetStackTrace/getstacktr001/ (own call >>>> stacks), and getstacktr003 (call stacks in other thread). >>>> >>>> >>>>> Speaking of tests ... >>>>> >>>>> In the native code I think you need to check the success of all >>>>> JNI methods that can throw exceptions - otherwise I believe the >>>>> tests may trigger warnings if -Xcheck:jni is used with them. See >>>>> for example: >>>>> >>>>> test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/libHeapMonitorTest.cpp >>>>> >>>> >>>> I updated testcases to check JNI and JVMTI function calls. >>>> >>>> >>>>> In the Java code the target thread: >>>>> >>>>> ?? 45???? public void run() { >>>>> ?? 46?????? try { >>>>> ?? 47?????????? synchronized (lock) { >>>>> ?? 48?????????????? lock.wait(); >>>>> ?? 49?????????????? System.out.println("OK"); >>>>> ?? 50?????????? } >>>>> >>>>> is potentially susceptible to spurious wakeups. Using a >>>>> CountDownLatch would be robust. >>>> >>>> Fixed. >>>> >>>> >>>> Thanks, >>>> >>>> Yasumasa >>>> >>>> >>>>> Thanks, >>>>> David >>>>> ----- >>>>> >>>>>> >>>>>> Thanks, >>>>>> >>>>>> Yasumasa >>>>>> >>>>>> >>>>>> On 2020/07/01 8:48, David Holmes wrote: >>>>>>> Hi Yasumasa, >>>>>>> >>>>>>> On 1/07/2020 9:05 am, Yasumasa Suenaga wrote: >>>>>>>> Hi David, >>>>>>>> >>>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>>> >>>>>>>>>>> IIUC at this point the _calling_thread is the current >>>>>>>>>>> thread, so we can use: >>>>>>>>>>> >>>>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>>> >>>>>>>> If so, we can call make_local() in L1272 without JavaThread (or >>>>>>>> we can pass current thread to make_local()). Is it right? >>>>>>>> >>>>>>>> ``` >>>>>>>> 1271???? ResourceMark rm; >>>>>>>> 1272 >>>>>>>> _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, >>>>>>>> thread_oop), >>>>>>>> 1273??????????????????????????? jt, thread_oop); >>>>>>>> ``` >>>>>>> >>>>>>> Sorry I got confused, _calling_thread may not be the current >>>>>>> thread as we could be executing the handshake in the target >>>>>>> thread itself. So the ResourceMark is correct as-is (implicitly >>>>>>> for current thread). >>>>>>> >>>>>>> The argument to fill_frames will be used in the jvmtiStackInfo >>>>>>> and passed back to the _calling_thread, so it must be created >>>>>>> via make_local(_calling_thread, ...) as you presently have. >>>>>>> >>>>>>> Thanks, >>>>>>> David >>>>>>> >>>>>>>> Thanks, >>>>>>>> >>>>>>>> Yasumasa >>>>>>>> >>>>>>>> >>>>>>>> On 2020/07/01 7:05, David Holmes wrote: >>>>>>>>> On 1/07/2020 12:17 am, Yasumasa Suenaga wrote: >>>>>>>>>> Hi David, >>>>>>>>>> >>>>>>>>>> Thank you for reviewing! I will update new webrev tomorrow. >>>>>>>>>> >>>>>>>>>>> 466 class MultipleStackTracesCollector : public StackObj { >>>>>>>>>>> >>>>>>>>>>> ? 498 class VM_GetAllStackTraces : public VM_Operation { >>>>>>>>>>> ? 499 private: >>>>>>>>>>> ? 500?? JavaThread *_calling_thread; >>>>>>>>>>> ? 501?? jint _final_thread_count; >>>>>>>>>>> ? 502?? MultipleStackTracesCollector _collector; >>>>>>>>>>> >>>>>>>>>>> You can't have a StackObj as a member of another class like >>>>>>>>>>> that as it may not be on the stack. I think >>>>>>>>>>> MultipleStackTracesCollector should not extend any >>>>>>>>>>> allocation class, and should always be embedded directly in >>>>>>>>>>> another class. >>>>>>>>>> >>>>>>>>>> I'm not sure what does mean "embedded". >>>>>>>>>> Is it ok as below? >>>>>>>>>> >>>>>>>>>> ``` >>>>>>>>>> class MultipleStackTracesCollector { >>>>>>>>>> ??? : >>>>>>>>>> } >>>>>>>>>> >>>>>>>>>> class GetAllStackTraces : public VM_Operation { >>>>>>>>>> ?? private: >>>>>>>>>> ???? MultipleStackTracesCollector _collector; >>>>>>>>>> } >>>>>>>>>> ``` >>>>>>>>> >>>>>>>>> Yes that I what I meant. >>>>>>>>> >>>>>>>>> Thanks, >>>>>>>>> David >>>>>>>>> ----- >>>>>>>>> >>>>>>>>>> >>>>>>>>>> Thanks, >>>>>>>>>> >>>>>>>>>> Yasumasa >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> On 2020/06/30 22:22, David Holmes wrote: >>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>> >>>>>>>>>>> On 30/06/2020 10:05 am, Yasumasa Suenaga wrote: >>>>>>>>>>>> Hi David, Serguei, >>>>>>>>>>>> >>>>>>>>>>>> I updated webrev for 8242428. Could you review again? >>>>>>>>>>>> This change migrate to use direct handshake for >>>>>>>>>>>> GetStackTrace() and GetThreadListStackTraces() (when >>>>>>>>>>>> thread_count == 1). >>>>>>>>>>>> >>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.01/ >>>>>>>>>>> >>>>>>>>>>> This looks really good now! I only have a few nits below. >>>>>>>>>>> There is one thing I don't like about it but it requires a >>>>>>>>>>> change to the main Handshake logic to address - in >>>>>>>>>>> JvmtiEnv::GetThreadListStackTraces you have to create a >>>>>>>>>>> ThreadsListHandle to convert the jthread to a JavaThread, >>>>>>>>>>> but then the Handshake::execute_direct creates another >>>>>>>>>>> ThreadsListHandle internally. That's a waste. I will discuss >>>>>>>>>>> with Robbin and file a RFE to have an overload of >>>>>>>>>>> execute_direct that takes an existing TLH. Actually it's >>>>>>>>>>> worse than that because we have another TLH in use at the >>>>>>>>>>> entry point for the JVMTI functions, so I think there may be >>>>>>>>>>> some scope for simplifying the use of TLH instances - future >>>>>>>>>>> RFE. >>>>>>>>>>> >>>>>>>>>>> --- >>>>>>>>>>> >>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>>>>>>> >>>>>>>>>>> ??451?? GetStackTraceClosure(JvmtiEnv *env, jint >>>>>>>>>>> start_depth, jint max_count, >>>>>>>>>>> ??452??????????????????????? jvmtiFrameInfo* frame_buffer, >>>>>>>>>>> jint* count_ptr) >>>>>>>>>>> ??453???? : HandshakeClosure("GetStackTrace"), >>>>>>>>>>> ??454?????? _env(env), _start_depth(start_depth), >>>>>>>>>>> _max_count(max_count), >>>>>>>>>>> ??455?????? _frame_buffer(frame_buffer), _count_ptr(count_ptr), >>>>>>>>>>> ??456 _result(JVMTI_ERROR_THREAD_NOT_ALIVE) { >>>>>>>>>>> >>>>>>>>>>> Nit: can you do one initializer per line please. >>>>>>>>>>> >>>>>>>>>>> This looks wrong: >>>>>>>>>>> >>>>>>>>>>> 466 class MultipleStackTracesCollector : public StackObj { >>>>>>>>>>> >>>>>>>>>>> ??498 class VM_GetAllStackTraces : public VM_Operation { >>>>>>>>>>> ??499 private: >>>>>>>>>>> ??500?? JavaThread *_calling_thread; >>>>>>>>>>> ??501?? jint _final_thread_count; >>>>>>>>>>> ??502?? MultipleStackTracesCollector _collector; >>>>>>>>>>> >>>>>>>>>>> You can't have a StackObj as a member of another class like >>>>>>>>>>> that as it may not be on the stack. I think >>>>>>>>>>> MultipleStackTracesCollector should not extend any >>>>>>>>>>> allocation class, and should always be embedded directly in >>>>>>>>>>> another class. >>>>>>>>>>> >>>>>>>>>>> 481?? MultipleStackTracesCollector(JvmtiEnv *env, jint >>>>>>>>>>> max_frame_count) { >>>>>>>>>>> ??482???? _env = env; >>>>>>>>>>> ??483???? _max_frame_count = max_frame_count; >>>>>>>>>>> ??484???? _frame_count_total = 0; >>>>>>>>>>> ??485???? _head = NULL; >>>>>>>>>>> ??486???? _stack_info = NULL; >>>>>>>>>>> ??487???? _result = JVMTI_ERROR_NONE; >>>>>>>>>>> ??488?? } >>>>>>>>>>> >>>>>>>>>>> As you are touching this can you change it to use an >>>>>>>>>>> initializer list as you did for the HandshakeClosure, and >>>>>>>>>>> please keep one item per line. >>>>>>>>>>> >>>>>>>>>>> --- >>>>>>>>>>> >>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>> >>>>>>>>>>> ??820 assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>> ??821 java_thread->is_thread_fully_suspended(false, >>>>>>>>>>> &debug_bits) || >>>>>>>>>>> ??822????????? current_thread == >>>>>>>>>>> java_thread->active_handshaker(), >>>>>>>>>>> ??823????????? "at safepoint / handshake or target thread is >>>>>>>>>>> suspended"); >>>>>>>>>>> >>>>>>>>>>> I don't think the suspension check is necessary, as even if >>>>>>>>>>> the target is suspended we must still be at a safepoint or >>>>>>>>>>> in a handshake with it. Makes me wonder if we used to allow >>>>>>>>>>> a racy stacktrace operation on a suspended thread, assuming >>>>>>>>>>> it would remain suspended? >>>>>>>>>>> >>>>>>>>>>> 1268?? oop thread_oop = jt->threadObj(); >>>>>>>>>>> 1269 >>>>>>>>>>> 1270?? if (!jt->is_exiting() && (jt->threadObj() != NULL)) { >>>>>>>>>>> >>>>>>>>>>> You can use thread_oop in line 1270. >>>>>>>>>>> >>>>>>>>>>> 1272 >>>>>>>>>>> _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, >>>>>>>>>>> thread_oop), >>>>>>>>>>> 1273??????????????????????????? jt, thread_oop); >>>>>>>>>>> >>>>>>>>>>> It is frustrating that this entire call chain started with a >>>>>>>>>>> jthread reference, which we converted to a JavaThread, only >>>>>>>>>>> to eventually need to convert it back to a jthread! I think >>>>>>>>>>> there is some scope for simplification here but not as part >>>>>>>>>>> of this change. >>>>>>>>>>> >>>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>>> >>>>>>>>>>> IIUC at this point the _calling_thread is the current >>>>>>>>>>> thread, so we can use: >>>>>>>>>>> >>>>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>>>>>> >>>>>>>>>>> --- >>>>>>>>>>> >>>>>>>>>>> Please add @bug lines to the tests. >>>>>>>>>>> >>>>>>>>>>> I'm still pondering the test logic but wanted to send this now. >>>>>>>>>>> >>>>>>>>>>> Thanks, >>>>>>>>>>> David >>>>>>>>>>> ----- >>>>>>>>>>>> VM_GetThreadListStackTrace (for GetThreadListStackTraces) >>>>>>>>>>>> and VM_GetAllStackTraces (for GetAllStackTraces) have >>>>>>>>>>>> inherited VM_GetMultipleStackTraces VM operation which >>>>>>>>>>>> provides the feature to generate jvmtiStackInfo. I modified >>>>>>>>>>>> VM_GetMultipleStackTraces to a normal C++ class to share >>>>>>>>>>>> with HandshakeClosure for GetThreadListStackTraces >>>>>>>>>>>> (GetSingleStackTraceClosure). >>>>>>>>>>>> >>>>>>>>>>>> Also I added new testcases which test >>>>>>>>>>>> GetThreadListStackTraces() with thread_count == 1 and with >>>>>>>>>>>> all threads. >>>>>>>>>>>> >>>>>>>>>>>> This change has been tested in serviceability/jvmti >>>>>>>>>>>> serviceability/jdwp vmTestbase/nsk/jvmti vmTestbase/nsk/jdi >>>>>>>>>>>> vmTestbase/nsk/jdwp. >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> Thanks, >>>>>>>>>>>> >>>>>>>>>>>> Yasumasa >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> On 2020/06/24 15:50, Yasumasa Suenaga wrote: >>>>>>>>>>>>> Hi all, >>>>>>>>>>>>> >>>>>>>>>>>>> Please review this change: >>>>>>>>>>>>> >>>>>>>>>>>>> ?? JBS: https://bugs.openjdk.java.net/browse/JDK-8242428 >>>>>>>>>>>>> ?? webrev: >>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.00/ >>>>>>>>>>>>> >>>>>>>>>>>>> This change replace following VM operations to direct >>>>>>>>>>>>> handshake. >>>>>>>>>>>>> >>>>>>>>>>>>> ??- VM_GetFrameCount (GetFrameCount()) >>>>>>>>>>>>> ??- VM_GetFrameLocation (GetFrameLocation()) >>>>>>>>>>>>> ??- VM_GetThreadListStackTraces (GetThreadListStackTrace()) >>>>>>>>>>>>> ??- VM_GetCurrentLocation >>>>>>>>>>>>> >>>>>>>>>>>>> GetThreadListStackTrace() uses direct handshake if thread >>>>>>>>>>>>> count == 1. In other case (thread count > 1), it would be >>>>>>>>>>>>> performed as VM operation (VM_GetThreadListStackTraces). >>>>>>>>>>>>> Caller of VM_GetCurrentLocation >>>>>>>>>>>>> (JvmtiEnvThreadState::reset_current_location()) might be >>>>>>>>>>>>> called at safepoint. So I added safepoint check in its >>>>>>>>>>>>> caller. >>>>>>>>>>>>> >>>>>>>>>>>>> This change has been tested in serviceability/jvmti >>>>>>>>>>>>> serviceability/jdwp vmTestbase/nsk/jvmti >>>>>>>>>>>>> vmTestbase/nsk/jdi vmTestbase/ns >>>>>>>>>>>>> k/jdwp. >>>>>>>>>>>>> >>>>>>>>>>>>> Also I tested it on submit repo, then it has execution >>>>>>>>>>>>> error >>>>>>>>>>>>> (mach5-one-ysuenaga-JDK-8242428-20200624-0054-12034717) >>>>>>>>>>>>> due to dependency error. So I think it does not occur by >>>>>>>>>>>>> this change. >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> Thanks, >>>>>>>>>>>>> >>>>>>>>>>>>> Yasumasa >>> From suenaga at oss.nttdata.com Fri Jul 3 04:27:15 2020 From: suenaga at oss.nttdata.com (Yasumasa Suenaga) Date: Fri, 3 Jul 2020 13:27:15 +0900 Subject: RFR: 8242428: JVMTI thread operations should use Thread-Local Handshake In-Reply-To: <3f890bed-6892-e64d-b21b-ca0cbe11784e@oracle.com> References: <6c263e4c-0a83-be7a-0288-ecb2de0b7cea@oss.nttdata.com> <2ea2f5d8-5c43-a7d3-d525-cd44c4009d25@oss.nttdata.com> <65889ab4-6b7e-86fb-59cc-012520b83138@oracle.com> <4b7df6f8-c8f7-fedf-6366-b885d2235b58@oss.nttdata.com> <74c05dfd-ffb2-b73d-66e5-dc98752729f5@oss.nttdata.com> <763793b1-9506-44c6-0681-1c71c44a44fd@oss.nttdata.com> <5107c478-1de2-7a49-ee71-dfad6a99a667@oracle.com> <90cdfef9-e558-0d25-33f5-25b7d65bb83b@oss.nttdata.com> <0e359819-618f-c17b-a427-bb7e4daa2c58@oracle.com> <3f890bed-6892-e64d-b21b-ca0cbe11784e@oracle.com> Message-ID: <7dc1903b-6295-3864-6301-4c02aacdb971@oss.nttdata.com> On 2020/07/03 12:24, Daniel D. Daugherty wrote: > On 7/2/20 10:50 PM, David Holmes wrote: >> Sorry I'm responding here without seeing latest webrev but there is enough context I think ... >> >> On 3/07/2020 9:14 am, Yasumasa Suenaga wrote: >>> Hi Dan, >>> >>> Thanks for your comment! >>> >>> On 2020/07/03 7:16, Daniel D. Daugherty wrote: >>>> On 7/2/20 5:19 AM, Yasumasa Suenaga wrote: >>>>> Hi David, >>>>> >>>>> I upload new webrev. Could you review again? >>>>> >>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.03/ >>>> >>>> src/hotspot/share/prims/jvmtiEnv.cpp >>>> ???? L1542: ??? // Get stack trace with handshake >>>> ???????? nit - please add a period at the end. >>> >>> I will fix it. >>> >>> >>>> ???? L1591: ??? *stack_info_ptr = op.stack_info(); >>>> ???????? The return parameter should not be touched unless the return >>>> ???????? code in 'err' == JVMTI_ERROR_NONE. >>>> >>>> ???? old L1582: ? if (err == JVMTI_ERROR_NONE) { >>>> ???????? Please restore this check. The return parameter should not >>>> ???????? be touched unless the return code in 'err' == JVMTI_ERROR_NONE. >>> >>> I will fix it. >> >> But op.stack_info() will return NULL if the error is not JVMTI_ERROR_NONE. Are you (Dan) concerned about someone passing in a non-null/initialized out-pointer that will be reset to NULL if there was an error? > > Actually the way we used to test this in POSIX tests is to call > an API with known bad parameters and the return parameter ptr > set to NULL. If the return parameter ptr was touched when an > error should have been detected on an earlier parameter, then > the test failed. > > >> >>> >>>> ???? L1272: ? if (!jt->is_exiting() && (thread_oop != NULL)) { >>>> ???????? nit - extra parens around the second expression. >>> >>> I will fix it. >>> >>> >>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>> ???? old L1532: ? _result = JVMTI_ERROR_THREAD_NOT_ALIVE; >>>> ???????? This deletion of the _result field threw me for a minute and then >>>> ???? ? ? I figured out that the field is init to JVMTI_ERROR_THREAD_NOT_ALIVE >>>> ???????? in the constructor. >>>> >>>> ???? L1553: ? if (!jt->is_exiting() && (jt->threadObj() != NULL)) { >>>> ???????? nit - extra parens around the second expression. >>> >>> I will fix it. >>> >>> >>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>> ???? No comments. >>>> >>>> src/hotspot/share/runtime/vmOperations.hpp >>>> ???? No comments. >>>> >>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/GetThreadListStackTraces.java >>>> ???? No comments. >>>> >>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/OneGetThreadListStackTraces.java >>>> ???? L64: ??????? startSignal.countDown(); >>>> ???????? I was expecting this to be a call to await() instead of >>>> ???????? countDown(). What am I missing here? >>>> >>>> ???????? I think this test might be passing by accident right now, but... >>> >>> Main thread (which call JVMTI functions to test) should wait until test thread is ready. >>> So main thread would wait startSignal, and test thread would count down. >> >> No! >> >> The test thread that previously called obj.wait() now calls latch.await(). >> >> The main thread that previously called obj.notify() now calls latch.countDown(). >> >> The main thread continues to spin until it sees the target is WAITING before proceeding with the test. If I add spin wait to wait until transit target thread state is WAITING (as following), we don't need to call SuspendThread(). Which is better? ``` /* Wait until the thread state transits to "waiting" */ while (th.getState() != Thread.State.WAITING) { Thread.onSpinWait(); } ``` For simplify, spin wait is prefer to OneGetThreadListStackTraces.java in webrev.03. Thanks, Yasumasa > Here's the flow as I see it: > > main thread > ? - start worker thread > ? - startSignal.await() > ??? - main is now blocked > > worker thread > ? - startSignal.countDown() > ??? - main is now unblocked > ? - stopSignal.await() > ??? - worker is now blocked > > main thread > ? - checkCallStacks(th) > ? - stopSignal.countDown() > ??? - worker is now unblocked > ? - th.join > ??? - main is now blocked > > worker thread > ? - runs off the end of run() > ??? - main is now unblocked > > main thread > ? - run off the end of main() > > >> >>> >>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libGetThreadListStackTraces.c >>>> ???? L92: ? jthreads = (jthread *)malloc(sizeof(jthread) * num_threads); >>>> ???????? You don't check for malloc() failure. >>>> ???????? 'jthreads' is allocated but never freed. >>> >>> I will fix it. >>> >>> >>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.c >>>> ???? L91: ? result = (*jvmti)->SuspendThread(jvmti, thread); >>>> ???????? Why are you suspending the thread? GetAllStackTraces() and >>>> ???????? GetThreadListStackTraces() do not require the target thread(s) >>>> ???????? to be suspend. >>>> >>>> ???????? If you decide not to SuspendThread, then you don't need the >>>> ???????? AddCapabilities or the ResumeThread calls. >>> >>> Test thread might not be entered following code (stopSignal.await()). We might see deferent call stack between GetAllStackTraces() and GetThreadListStackTraces(). We cannot control to freeze call stack of test thread in Java code. >>> (I didn't use SuspendThread() at first, but I saw some errors which causes in above.) >>> >>> So we need to call SuspendThread() to ensure we can see same call stack. >> >> If you are checking that the thread is in state WAITING then it cannot escape from that state and you can sample the stack multiple times from any API and get the same result. >> >> I suspect the errors you saw were from the apparent incorrect use of the CountDownLatch. > > With the flow outlined above, the worker thread should be > nicely blocked in stopSignal.await() when stuff is sampled. > > Dan > > >> >> Cheers, >> David >> ----- >> >>> >>> Thanks, >>> >>> Yasumasa >>> >>> >>>> Dan >>>> >>>>> >>>>> On 2020/07/02 15:05, David Holmes wrote: >>>>>> Hi Yasumasa, >>>>>> >>>>>> On 1/07/2020 11:53 am, Yasumasa Suenaga wrote: >>>>>>> Hi, >>>>>>> >>>>>>> I uploaded new webrev. Could review again? >>>>>>> >>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.02/ >>>>>> >>>>>> Updates look fine - thanks. >>>>>> >>>>>> One minor nit: >>>>>> >>>>>> 1274???? _collector.allocate_and_fill_stacks(1); >>>>>> 1275???? _collector.set_result(JVMTI_ERROR_NONE); >>>>>> >>>>>> In the other places where you use _collector you rely on result being initialized to JVMTI_ERROR_NONE, rather than setting it directly after allocate_and_fill_stacks(). >>>>> >>>>> Fixed. >>>>> >>>>> >>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>> >>>>>>>>>>>> ? 820 assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>> ? 821 java_thread->is_thread_fully_suspended(false, &debug_bits) || >>>>>>>>>>>> ? 822????????? current_thread == java_thread->active_handshaker(), >>>>>>>>>>>> ? 823????????? "at safepoint / handshake or target thread is suspended"); >>>>>>>>>>>> >>>>>>>>>>>> I don't think the suspension check is necessary, as even if the target is suspended we must still be at a safepoint or in a handshake with it. Makes me wonder if we used to allow a racy stacktrace operation on a suspended thread, assuming it would remain suspended? >>>>>>> >>>>>>> This function (JvmtiEnvBase::get_stack_trace()) can be called to get own stack trace. For example, we can call GetStackTrace() for current thread at JVMTI event. >>>>>>> So I changed assert as below: >>>>>>> >>>>>>> ``` >>>>>>> ??820?? assert(current_thread == java_thread || >>>>>>> ??821????????? SafepointSynchronize::is_at_safepoint() || >>>>>>> ??822????????? current_thread == java_thread->active_handshaker(), >>>>>>> ??823????????? "call by myself / at safepoint / at handshake"); >>>>>>> ``` >>>>>> >>>>>> Yep good catch. I hope current tests caught that. >>>>> >>>>> They would be tested in vmTestbase/nsk/jvmti/GetStackTrace/getstacktr001/ (own call stacks), and getstacktr003 (call stacks in other thread). >>>>> >>>>> >>>>>> Speaking of tests ... >>>>>> >>>>>> In the native code I think you need to check the success of all JNI methods that can throw exceptions - otherwise I believe the tests may trigger warnings if -Xcheck:jni is used with them. See for example: >>>>>> >>>>>> test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/libHeapMonitorTest.cpp >>>>> >>>>> I updated testcases to check JNI and JVMTI function calls. >>>>> >>>>> >>>>>> In the Java code the target thread: >>>>>> >>>>>> ?? 45???? public void run() { >>>>>> ?? 46?????? try { >>>>>> ?? 47?????????? synchronized (lock) { >>>>>> ?? 48?????????????? lock.wait(); >>>>>> ?? 49?????????????? System.out.println("OK"); >>>>>> ?? 50?????????? } >>>>>> >>>>>> is potentially susceptible to spurious wakeups. Using a CountDownLatch would be robust. >>>>> >>>>> Fixed. >>>>> >>>>> >>>>> Thanks, >>>>> >>>>> Yasumasa >>>>> >>>>> >>>>>> Thanks, >>>>>> David >>>>>> ----- >>>>>> >>>>>>> >>>>>>> Thanks, >>>>>>> >>>>>>> Yasumasa >>>>>>> >>>>>>> >>>>>>> On 2020/07/01 8:48, David Holmes wrote: >>>>>>>> Hi Yasumasa, >>>>>>>> >>>>>>>> On 1/07/2020 9:05 am, Yasumasa Suenaga wrote: >>>>>>>>> Hi David, >>>>>>>>> >>>>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>>>> >>>>>>>>>>>> IIUC at this point the _calling_thread is the current thread, so we can use: >>>>>>>>>>>> >>>>>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>>>> >>>>>>>>> If so, we can call make_local() in L1272 without JavaThread (or we can pass current thread to make_local()). Is it right? >>>>>>>>> >>>>>>>>> ``` >>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>> 1272 _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, thread_oop), >>>>>>>>> 1273??????????????????????????? jt, thread_oop); >>>>>>>>> ``` >>>>>>>> >>>>>>>> Sorry I got confused, _calling_thread may not be the current thread as we could be executing the handshake in the target thread itself. So the ResourceMark is correct as-is (implicitly for current thread). >>>>>>>> >>>>>>>> The argument to fill_frames will be used in the jvmtiStackInfo and passed back to the _calling_thread, so it must be created via make_local(_calling_thread, ...) as you presently have. >>>>>>>> >>>>>>>> Thanks, >>>>>>>> David >>>>>>>> >>>>>>>>> Thanks, >>>>>>>>> >>>>>>>>> Yasumasa >>>>>>>>> >>>>>>>>> >>>>>>>>> On 2020/07/01 7:05, David Holmes wrote: >>>>>>>>>> On 1/07/2020 12:17 am, Yasumasa Suenaga wrote: >>>>>>>>>>> Hi David, >>>>>>>>>>> >>>>>>>>>>> Thank you for reviewing! I will update new webrev tomorrow. >>>>>>>>>>> >>>>>>>>>>>> 466 class MultipleStackTracesCollector : public StackObj { >>>>>>>>>>>> >>>>>>>>>>>> ? 498 class VM_GetAllStackTraces : public VM_Operation { >>>>>>>>>>>> ? 499 private: >>>>>>>>>>>> ? 500?? JavaThread *_calling_thread; >>>>>>>>>>>> ? 501?? jint _final_thread_count; >>>>>>>>>>>> ? 502?? MultipleStackTracesCollector _collector; >>>>>>>>>>>> >>>>>>>>>>>> You can't have a StackObj as a member of another class like that as it may not be on the stack. I think MultipleStackTracesCollector should not extend any allocation class, and should always be embedded directly in another class. >>>>>>>>>>> >>>>>>>>>>> I'm not sure what does mean "embedded". >>>>>>>>>>> Is it ok as below? >>>>>>>>>>> >>>>>>>>>>> ``` >>>>>>>>>>> class MultipleStackTracesCollector { >>>>>>>>>>> ??? : >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> class GetAllStackTraces : public VM_Operation { >>>>>>>>>>> ?? private: >>>>>>>>>>> ???? MultipleStackTracesCollector _collector; >>>>>>>>>>> } >>>>>>>>>>> ``` >>>>>>>>>> >>>>>>>>>> Yes that I what I meant. >>>>>>>>>> >>>>>>>>>> Thanks, >>>>>>>>>> David >>>>>>>>>> ----- >>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> Thanks, >>>>>>>>>>> >>>>>>>>>>> Yasumasa >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> On 2020/06/30 22:22, David Holmes wrote: >>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>> >>>>>>>>>>>> On 30/06/2020 10:05 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>> Hi David, Serguei, >>>>>>>>>>>>> >>>>>>>>>>>>> I updated webrev for 8242428. Could you review again? >>>>>>>>>>>>> This change migrate to use direct handshake for GetStackTrace() and GetThreadListStackTraces() (when thread_count == 1). >>>>>>>>>>>>> >>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.01/ >>>>>>>>>>>> >>>>>>>>>>>> This looks really good now! I only have a few nits below. There is one thing I don't like about it but it requires a change to the main Handshake logic to address - in JvmtiEnv::GetThreadListStackTraces you have to create a ThreadsListHandle to convert the jthread to a JavaThread, but then the Handshake::execute_direct creates another ThreadsListHandle internally. That's a waste. I will discuss with Robbin and file a RFE to have an overload of execute_direct that takes an existing TLH. Actually it's worse than that because we have another TLH in use at the entry point for the JVMTI functions, so I think there may be some scope for simplifying the use of TLH instances - future RFE. >>>>>>>>>>>> >>>>>>>>>>>> --- >>>>>>>>>>>> >>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>>>>>>>> >>>>>>>>>>>> ??451?? GetStackTraceClosure(JvmtiEnv *env, jint start_depth, jint max_count, >>>>>>>>>>>> ??452??????????????????????? jvmtiFrameInfo* frame_buffer, jint* count_ptr) >>>>>>>>>>>> ??453???? : HandshakeClosure("GetStackTrace"), >>>>>>>>>>>> ??454?????? _env(env), _start_depth(start_depth), _max_count(max_count), >>>>>>>>>>>> ??455?????? _frame_buffer(frame_buffer), _count_ptr(count_ptr), >>>>>>>>>>>> ??456 _result(JVMTI_ERROR_THREAD_NOT_ALIVE) { >>>>>>>>>>>> >>>>>>>>>>>> Nit: can you do one initializer per line please. >>>>>>>>>>>> >>>>>>>>>>>> This looks wrong: >>>>>>>>>>>> >>>>>>>>>>>> 466 class MultipleStackTracesCollector : public StackObj { >>>>>>>>>>>> >>>>>>>>>>>> ??498 class VM_GetAllStackTraces : public VM_Operation { >>>>>>>>>>>> ??499 private: >>>>>>>>>>>> ??500?? JavaThread *_calling_thread; >>>>>>>>>>>> ??501?? jint _final_thread_count; >>>>>>>>>>>> ??502?? MultipleStackTracesCollector _collector; >>>>>>>>>>>> >>>>>>>>>>>> You can't have a StackObj as a member of another class like that as it may not be on the stack. I think MultipleStackTracesCollector should not extend any allocation class, and should always be embedded directly in another class. >>>>>>>>>>>> >>>>>>>>>>>> 481?? MultipleStackTracesCollector(JvmtiEnv *env, jint max_frame_count) { >>>>>>>>>>>> ??482???? _env = env; >>>>>>>>>>>> ??483???? _max_frame_count = max_frame_count; >>>>>>>>>>>> ??484???? _frame_count_total = 0; >>>>>>>>>>>> ??485???? _head = NULL; >>>>>>>>>>>> ??486???? _stack_info = NULL; >>>>>>>>>>>> ??487???? _result = JVMTI_ERROR_NONE; >>>>>>>>>>>> ??488?? } >>>>>>>>>>>> >>>>>>>>>>>> As you are touching this can you change it to use an initializer list as you did for the HandshakeClosure, and please keep one item per line. >>>>>>>>>>>> >>>>>>>>>>>> --- >>>>>>>>>>>> >>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>> >>>>>>>>>>>> ??820 assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>> ??821 java_thread->is_thread_fully_suspended(false, &debug_bits) || >>>>>>>>>>>> ??822????????? current_thread == java_thread->active_handshaker(), >>>>>>>>>>>> ??823????????? "at safepoint / handshake or target thread is suspended"); >>>>>>>>>>>> >>>>>>>>>>>> I don't think the suspension check is necessary, as even if the target is suspended we must still be at a safepoint or in a handshake with it. Makes me wonder if we used to allow a racy stacktrace operation on a suspended thread, assuming it would remain suspended? >>>>>>>>>>>> >>>>>>>>>>>> 1268?? oop thread_oop = jt->threadObj(); >>>>>>>>>>>> 1269 >>>>>>>>>>>> 1270?? if (!jt->is_exiting() && (jt->threadObj() != NULL)) { >>>>>>>>>>>> >>>>>>>>>>>> You can use thread_oop in line 1270. >>>>>>>>>>>> >>>>>>>>>>>> 1272 _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, thread_oop), >>>>>>>>>>>> 1273??????????????????????????? jt, thread_oop); >>>>>>>>>>>> >>>>>>>>>>>> It is frustrating that this entire call chain started with a jthread reference, which we converted to a JavaThread, only to eventually need to convert it back to a jthread! I think there is some scope for simplification here but not as part of this change. >>>>>>>>>>>> >>>>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>>>> >>>>>>>>>>>> IIUC at this point the _calling_thread is the current thread, so we can use: >>>>>>>>>>>> >>>>>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>>>>>>> >>>>>>>>>>>> --- >>>>>>>>>>>> >>>>>>>>>>>> Please add @bug lines to the tests. >>>>>>>>>>>> >>>>>>>>>>>> I'm still pondering the test logic but wanted to send this now. >>>>>>>>>>>> >>>>>>>>>>>> Thanks, >>>>>>>>>>>> David >>>>>>>>>>>> ----- >>>>>>>>>>>>> VM_GetThreadListStackTrace (for GetThreadListStackTraces) and VM_GetAllStackTraces (for GetAllStackTraces) have inherited VM_GetMultipleStackTraces VM operation which provides the feature to generate jvmtiStackInfo. I modified VM_GetMultipleStackTraces to a normal C++ class to share with HandshakeClosure for GetThreadListStackTraces (GetSingleStackTraceClosure). >>>>>>>>>>>>> >>>>>>>>>>>>> Also I added new testcases which test GetThreadListStackTraces() with thread_count == 1 and with all threads. >>>>>>>>>>>>> >>>>>>>>>>>>> This change has been tested in serviceability/jvmti serviceability/jdwp vmTestbase/nsk/jvmti vmTestbase/nsk/jdi vmTestbase/nsk/jdwp. >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> Thanks, >>>>>>>>>>>>> >>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> On 2020/06/24 15:50, Yasumasa Suenaga wrote: >>>>>>>>>>>>>> Hi all, >>>>>>>>>>>>>> >>>>>>>>>>>>>> Please review this change: >>>>>>>>>>>>>> >>>>>>>>>>>>>> ?? JBS: https://bugs.openjdk.java.net/browse/JDK-8242428 >>>>>>>>>>>>>> ?? webrev: http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.00/ >>>>>>>>>>>>>> >>>>>>>>>>>>>> This change replace following VM operations to direct handshake. >>>>>>>>>>>>>> >>>>>>>>>>>>>> ??- VM_GetFrameCount (GetFrameCount()) >>>>>>>>>>>>>> ??- VM_GetFrameLocation (GetFrameLocation()) >>>>>>>>>>>>>> ??- VM_GetThreadListStackTraces (GetThreadListStackTrace()) >>>>>>>>>>>>>> ??- VM_GetCurrentLocation >>>>>>>>>>>>>> >>>>>>>>>>>>>> GetThreadListStackTrace() uses direct handshake if thread count == 1. In other case (thread count > 1), it would be performed as VM operation (VM_GetThreadListStackTraces). >>>>>>>>>>>>>> Caller of VM_GetCurrentLocation (JvmtiEnvThreadState::reset_current_location()) might be called at safepoint. So I added safepoint check in its caller. >>>>>>>>>>>>>> >>>>>>>>>>>>>> This change has been tested in serviceability/jvmti serviceability/jdwp vmTestbase/nsk/jvmti vmTestbase/nsk/jdi vmTestbase/ns >>>>>>>>>>>>>> k/jdwp. >>>>>>>>>>>>>> >>>>>>>>>>>>>> Also I tested it on submit repo, then it has execution error (mach5-one-ysuenaga-JDK-8242428-20200624-0054-12034717) due to dependency error. So I think it does not occur by this change. >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>> >>>>>>>>>>>>>> Yasumasa >>>> > From david.holmes at oracle.com Fri Jul 3 05:09:28 2020 From: david.holmes at oracle.com (David Holmes) Date: Fri, 3 Jul 2020 15:09:28 +1000 Subject: [15] RFR(T) 8247527: serviceability/dcmd/gc/HeapDumpCompressedTest.java fails with Graal + ZGC In-Reply-To: References: Message-ID: Hi Igor, On 3/07/2020 12:59 pm, Igor Ignatyev wrote: > Hi David, > > it's in my todo list to improve this situation and have vm.gc.X to take selected JIT into account; and update existing (>200) occurrences of 'vm.gc.X & !vm.graal.enabled' 200+ ouch! :( I guess this fix doesn't make the situation any worse in a practical sense. Thanks, David ----- > -- Igor > >> On Jul 2, 2020, at 7:25 PM, David Holmes wrote: >> >> Hi Vladimir, >> >> On 3/07/2020 12:02 pm, Vladimir Kozlov wrote: >>> https://cr.openjdk.java.net/~kvn/8247527/webrev.00/ >>> https://bugs.openjdk.java.net/browse/JDK-8247527 >>> Test should have @requires which excludes running Graal with GC which it does not support. >> >> I find it somewhat disturbing that a generic test has to know about the limitations between GCs and Graal! >> >> I would have been more inclined to just exclude this test when running with Graal, even if that theoretically reduced the test coverage in a ting way. >> >> If/When Graal supports these other GCs who will remember to re-enable these test cases? >> >> Thanks, >> David >> >>> Testing: hs-tier1,hs-tier4-graal >>> Thanks, >>> Vladimir > From david.holmes at oracle.com Fri Jul 3 05:12:47 2020 From: david.holmes at oracle.com (David Holmes) Date: Fri, 3 Jul 2020 15:12:47 +1000 Subject: RFR: 8242428: JVMTI thread operations should use Thread-Local Handshake In-Reply-To: <3f890bed-6892-e64d-b21b-ca0cbe11784e@oracle.com> References: <6c263e4c-0a83-be7a-0288-ecb2de0b7cea@oss.nttdata.com> <2ea2f5d8-5c43-a7d3-d525-cd44c4009d25@oss.nttdata.com> <65889ab4-6b7e-86fb-59cc-012520b83138@oracle.com> <4b7df6f8-c8f7-fedf-6366-b885d2235b58@oss.nttdata.com> <74c05dfd-ffb2-b73d-66e5-dc98752729f5@oss.nttdata.com> <763793b1-9506-44c6-0681-1c71c44a44fd@oss.nttdata.com> <5107c478-1de2-7a49-ee71-dfad6a99a667@oracle.com> <90cdfef9-e558-0d25-33f5-25b7d65bb83b@oss.nttdata.com> <0e359819-618f-c17b-a427-bb7e4daa2c58@oracle.com> <3f890bed-6892-e64d-b21b-ca0cbe11784e@oracle.com> Message-ID: On 3/07/2020 1:24 pm, Daniel D. Daugherty wrote: > On 7/2/20 10:50 PM, David Holmes wrote: >> Sorry I'm responding here without seeing latest webrev but there is >> enough context I think ... >> >> On 3/07/2020 9:14 am, Yasumasa Suenaga wrote: >>> Hi Dan, >>> >>> Thanks for your comment! >>> >>> On 2020/07/03 7:16, Daniel D. Daugherty wrote: >>>> On 7/2/20 5:19 AM, Yasumasa Suenaga wrote: >>>>> Hi David, >>>>> >>>>> I upload new webrev. Could you review again? >>>>> >>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.03/ >>>> >>>> src/hotspot/share/prims/jvmtiEnv.cpp >>>> ???? L1542: ??? // Get stack trace with handshake >>>> ???????? nit - please add a period at the end. >>> >>> I will fix it. >>> >>> >>>> ???? L1591: ??? *stack_info_ptr = op.stack_info(); >>>> ???????? The return parameter should not be touched unless the return >>>> ???????? code in 'err' == JVMTI_ERROR_NONE. >>>> >>>> ???? old L1582: ? if (err == JVMTI_ERROR_NONE) { >>>> ???????? Please restore this check. The return parameter should not >>>> ???????? be touched unless the return code in 'err' == >>>> JVMTI_ERROR_NONE. >>> >>> I will fix it. >> >> But op.stack_info() will return NULL if the error is not >> JVMTI_ERROR_NONE. Are you (Dan) concerned about someone passing in a >> non-null/initialized out-pointer that will be reset to NULL if there >> was an error? > > Actually the way we used to test this in POSIX tests is to call > an API with known bad parameters and the return parameter ptr > set to NULL. If the return parameter ptr was touched when an > error should have been detected on an earlier parameter, then > the test failed. Okay. > >> >>> >>>> ???? L1272: ? if (!jt->is_exiting() && (thread_oop != NULL)) { >>>> ???????? nit - extra parens around the second expression. >>> >>> I will fix it. >>> >>> >>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>> ???? old L1532: ? _result = JVMTI_ERROR_THREAD_NOT_ALIVE; >>>> ???????? This deletion of the _result field threw me for a minute >>>> and then >>>> ???? ? ? I figured out that the field is init to >>>> JVMTI_ERROR_THREAD_NOT_ALIVE >>>> ???????? in the constructor. >>>> >>>> ???? L1553: ? if (!jt->is_exiting() && (jt->threadObj() != NULL)) { >>>> ???????? nit - extra parens around the second expression. >>> >>> I will fix it. >>> >>> >>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>> ???? No comments. >>>> >>>> src/hotspot/share/runtime/vmOperations.hpp >>>> ???? No comments. >>>> >>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/GetThreadListStackTraces.java >>>> >>>> ???? No comments. >>>> >>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/OneGetThreadListStackTraces.java >>>> >>>> ???? L64: ??????? startSignal.countDown(); >>>> ???????? I was expecting this to be a call to await() instead of >>>> ???????? countDown(). What am I missing here? >>>> >>>> ???????? I think this test might be passing by accident right now, >>>> but... >>> >>> Main thread (which call JVMTI functions to test) should wait until >>> test thread is ready. >>> So main thread would wait startSignal, and test thread would count down. >> >> No! >> >> The test thread that previously called obj.wait() now calls >> latch.await(). >> >> The main thread that previously called obj.notify() now calls >> latch.countDown(). >> >> The main thread continues to spin until it sees the target is WAITING >> before proceeding with the test. > > Here's the flow as I see it: > > main thread > ? - start worker thread > ? - startSignal.await() > ??? - main is now blocked > > worker thread > ? - startSignal.countDown() > ??? - main is now unblocked > ? - stopSignal.await() > ??? - worker is now blocked > > main thread > ? - checkCallStacks(th) > ? - stopSignal.countDown() > ??? - worker is now unblocked > ? - th.join > ??? - main is now blocked > > worker thread > ? - runs off the end of run() > ??? - main is now unblocked > > main thread > ? - run off the end of main() That is not all what I wanted when I said to use the CountDownLatch and its broken because it is now racy. :( Cheers, David ----- > >> >>> >>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libGetThreadListStackTraces.c >>>> >>>> ???? L92: ? jthreads = (jthread *)malloc(sizeof(jthread) * >>>> num_threads); >>>> ???????? You don't check for malloc() failure. >>>> ???????? 'jthreads' is allocated but never freed. >>> >>> I will fix it. >>> >>> >>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.c >>>> >>>> ???? L91: ? result = (*jvmti)->SuspendThread(jvmti, thread); >>>> ???????? Why are you suspending the thread? GetAllStackTraces() and >>>> ???????? GetThreadListStackTraces() do not require the target thread(s) >>>> ???????? to be suspend. >>>> >>>> ???????? If you decide not to SuspendThread, then you don't need the >>>> ???????? AddCapabilities or the ResumeThread calls. >>> >>> Test thread might not be entered following code (stopSignal.await()). >>> We might see deferent call stack between GetAllStackTraces() and >>> GetThreadListStackTraces(). We cannot control to freeze call stack of >>> test thread in Java code. >>> (I didn't use SuspendThread() at first, but I saw some errors which >>> causes in above.) >>> >>> So we need to call SuspendThread() to ensure we can see same call stack. >> >> If you are checking that the thread is in state WAITING then it cannot >> escape from that state and you can sample the stack multiple times >> from any API and get the same result. >> >> I suspect the errors you saw were from the apparent incorrect use of >> the CountDownLatch. > > With the flow outlined above, the worker thread should be > nicely blocked in stopSignal.await() when stuff is sampled. > > Dan > > >> >> Cheers, >> David >> ----- >> >>> >>> Thanks, >>> >>> Yasumasa >>> >>> >>>> Dan >>>> >>>>> >>>>> On 2020/07/02 15:05, David Holmes wrote: >>>>>> Hi Yasumasa, >>>>>> >>>>>> On 1/07/2020 11:53 am, Yasumasa Suenaga wrote: >>>>>>> Hi, >>>>>>> >>>>>>> I uploaded new webrev. Could review again? >>>>>>> >>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.02/ >>>>>> >>>>>> Updates look fine - thanks. >>>>>> >>>>>> One minor nit: >>>>>> >>>>>> 1274???? _collector.allocate_and_fill_stacks(1); >>>>>> 1275???? _collector.set_result(JVMTI_ERROR_NONE); >>>>>> >>>>>> In the other places where you use _collector you rely on result >>>>>> being initialized to JVMTI_ERROR_NONE, rather than setting it >>>>>> directly after allocate_and_fill_stacks(). >>>>> >>>>> Fixed. >>>>> >>>>> >>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>> >>>>>>>>>>>> ? 820 assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>> ? 821 java_thread->is_thread_fully_suspended(false, >>>>>>>>>>>> &debug_bits) || >>>>>>>>>>>> ? 822????????? current_thread == >>>>>>>>>>>> java_thread->active_handshaker(), >>>>>>>>>>>> ? 823????????? "at safepoint / handshake or target thread is >>>>>>>>>>>> suspended"); >>>>>>>>>>>> >>>>>>>>>>>> I don't think the suspension check is necessary, as even if >>>>>>>>>>>> the target is suspended we must still be at a safepoint or >>>>>>>>>>>> in a handshake with it. Makes me wonder if we used to allow >>>>>>>>>>>> a racy stacktrace operation on a suspended thread, assuming >>>>>>>>>>>> it would remain suspended? >>>>>>> >>>>>>> This function (JvmtiEnvBase::get_stack_trace()) can be called to >>>>>>> get own stack trace. For example, we can call GetStackTrace() for >>>>>>> current thread at JVMTI event. >>>>>>> So I changed assert as below: >>>>>>> >>>>>>> ``` >>>>>>> ??820?? assert(current_thread == java_thread || >>>>>>> ??821????????? SafepointSynchronize::is_at_safepoint() || >>>>>>> ??822????????? current_thread == java_thread->active_handshaker(), >>>>>>> ??823????????? "call by myself / at safepoint / at handshake"); >>>>>>> ``` >>>>>> >>>>>> Yep good catch. I hope current tests caught that. >>>>> >>>>> They would be tested in >>>>> vmTestbase/nsk/jvmti/GetStackTrace/getstacktr001/ (own call >>>>> stacks), and getstacktr003 (call stacks in other thread). >>>>> >>>>> >>>>>> Speaking of tests ... >>>>>> >>>>>> In the native code I think you need to check the success of all >>>>>> JNI methods that can throw exceptions - otherwise I believe the >>>>>> tests may trigger warnings if -Xcheck:jni is used with them. See >>>>>> for example: >>>>>> >>>>>> test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/libHeapMonitorTest.cpp >>>>>> >>>>> >>>>> I updated testcases to check JNI and JVMTI function calls. >>>>> >>>>> >>>>>> In the Java code the target thread: >>>>>> >>>>>> ?? 45???? public void run() { >>>>>> ?? 46?????? try { >>>>>> ?? 47?????????? synchronized (lock) { >>>>>> ?? 48?????????????? lock.wait(); >>>>>> ?? 49?????????????? System.out.println("OK"); >>>>>> ?? 50?????????? } >>>>>> >>>>>> is potentially susceptible to spurious wakeups. Using a >>>>>> CountDownLatch would be robust. >>>>> >>>>> Fixed. >>>>> >>>>> >>>>> Thanks, >>>>> >>>>> Yasumasa >>>>> >>>>> >>>>>> Thanks, >>>>>> David >>>>>> ----- >>>>>> >>>>>>> >>>>>>> Thanks, >>>>>>> >>>>>>> Yasumasa >>>>>>> >>>>>>> >>>>>>> On 2020/07/01 8:48, David Holmes wrote: >>>>>>>> Hi Yasumasa, >>>>>>>> >>>>>>>> On 1/07/2020 9:05 am, Yasumasa Suenaga wrote: >>>>>>>>> Hi David, >>>>>>>>> >>>>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>>>> >>>>>>>>>>>> IIUC at this point the _calling_thread is the current >>>>>>>>>>>> thread, so we can use: >>>>>>>>>>>> >>>>>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>>>> >>>>>>>>> If so, we can call make_local() in L1272 without JavaThread (or >>>>>>>>> we can pass current thread to make_local()). Is it right? >>>>>>>>> >>>>>>>>> ``` >>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>> 1272 >>>>>>>>> _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, >>>>>>>>> thread_oop), >>>>>>>>> 1273??????????????????????????? jt, thread_oop); >>>>>>>>> ``` >>>>>>>> >>>>>>>> Sorry I got confused, _calling_thread may not be the current >>>>>>>> thread as we could be executing the handshake in the target >>>>>>>> thread itself. So the ResourceMark is correct as-is (implicitly >>>>>>>> for current thread). >>>>>>>> >>>>>>>> The argument to fill_frames will be used in the jvmtiStackInfo >>>>>>>> and passed back to the _calling_thread, so it must be created >>>>>>>> via make_local(_calling_thread, ...) as you presently have. >>>>>>>> >>>>>>>> Thanks, >>>>>>>> David >>>>>>>> >>>>>>>>> Thanks, >>>>>>>>> >>>>>>>>> Yasumasa >>>>>>>>> >>>>>>>>> >>>>>>>>> On 2020/07/01 7:05, David Holmes wrote: >>>>>>>>>> On 1/07/2020 12:17 am, Yasumasa Suenaga wrote: >>>>>>>>>>> Hi David, >>>>>>>>>>> >>>>>>>>>>> Thank you for reviewing! I will update new webrev tomorrow. >>>>>>>>>>> >>>>>>>>>>>> 466 class MultipleStackTracesCollector : public StackObj { >>>>>>>>>>>> >>>>>>>>>>>> ? 498 class VM_GetAllStackTraces : public VM_Operation { >>>>>>>>>>>> ? 499 private: >>>>>>>>>>>> ? 500?? JavaThread *_calling_thread; >>>>>>>>>>>> ? 501?? jint _final_thread_count; >>>>>>>>>>>> ? 502?? MultipleStackTracesCollector _collector; >>>>>>>>>>>> >>>>>>>>>>>> You can't have a StackObj as a member of another class like >>>>>>>>>>>> that as it may not be on the stack. I think >>>>>>>>>>>> MultipleStackTracesCollector should not extend any >>>>>>>>>>>> allocation class, and should always be embedded directly in >>>>>>>>>>>> another class. >>>>>>>>>>> >>>>>>>>>>> I'm not sure what does mean "embedded". >>>>>>>>>>> Is it ok as below? >>>>>>>>>>> >>>>>>>>>>> ``` >>>>>>>>>>> class MultipleStackTracesCollector { >>>>>>>>>>> ??? : >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> class GetAllStackTraces : public VM_Operation { >>>>>>>>>>> ?? private: >>>>>>>>>>> ???? MultipleStackTracesCollector _collector; >>>>>>>>>>> } >>>>>>>>>>> ``` >>>>>>>>>> >>>>>>>>>> Yes that I what I meant. >>>>>>>>>> >>>>>>>>>> Thanks, >>>>>>>>>> David >>>>>>>>>> ----- >>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> Thanks, >>>>>>>>>>> >>>>>>>>>>> Yasumasa >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> On 2020/06/30 22:22, David Holmes wrote: >>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>> >>>>>>>>>>>> On 30/06/2020 10:05 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>> Hi David, Serguei, >>>>>>>>>>>>> >>>>>>>>>>>>> I updated webrev for 8242428. Could you review again? >>>>>>>>>>>>> This change migrate to use direct handshake for >>>>>>>>>>>>> GetStackTrace() and GetThreadListStackTraces() (when >>>>>>>>>>>>> thread_count == 1). >>>>>>>>>>>>> >>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.01/ >>>>>>>>>>>> >>>>>>>>>>>> This looks really good now! I only have a few nits below. >>>>>>>>>>>> There is one thing I don't like about it but it requires a >>>>>>>>>>>> change to the main Handshake logic to address - in >>>>>>>>>>>> JvmtiEnv::GetThreadListStackTraces you have to create a >>>>>>>>>>>> ThreadsListHandle to convert the jthread to a JavaThread, >>>>>>>>>>>> but then the Handshake::execute_direct creates another >>>>>>>>>>>> ThreadsListHandle internally. That's a waste. I will discuss >>>>>>>>>>>> with Robbin and file a RFE to have an overload of >>>>>>>>>>>> execute_direct that takes an existing TLH. Actually it's >>>>>>>>>>>> worse than that because we have another TLH in use at the >>>>>>>>>>>> entry point for the JVMTI functions, so I think there may be >>>>>>>>>>>> some scope for simplifying the use of TLH instances - future >>>>>>>>>>>> RFE. >>>>>>>>>>>> >>>>>>>>>>>> --- >>>>>>>>>>>> >>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>>>>>>>> >>>>>>>>>>>> ??451?? GetStackTraceClosure(JvmtiEnv *env, jint >>>>>>>>>>>> start_depth, jint max_count, >>>>>>>>>>>> ??452??????????????????????? jvmtiFrameInfo* frame_buffer, >>>>>>>>>>>> jint* count_ptr) >>>>>>>>>>>> ??453???? : HandshakeClosure("GetStackTrace"), >>>>>>>>>>>> ??454?????? _env(env), _start_depth(start_depth), >>>>>>>>>>>> _max_count(max_count), >>>>>>>>>>>> ??455?????? _frame_buffer(frame_buffer), _count_ptr(count_ptr), >>>>>>>>>>>> ??456 _result(JVMTI_ERROR_THREAD_NOT_ALIVE) { >>>>>>>>>>>> >>>>>>>>>>>> Nit: can you do one initializer per line please. >>>>>>>>>>>> >>>>>>>>>>>> This looks wrong: >>>>>>>>>>>> >>>>>>>>>>>> 466 class MultipleStackTracesCollector : public StackObj { >>>>>>>>>>>> >>>>>>>>>>>> ??498 class VM_GetAllStackTraces : public VM_Operation { >>>>>>>>>>>> ??499 private: >>>>>>>>>>>> ??500?? JavaThread *_calling_thread; >>>>>>>>>>>> ??501?? jint _final_thread_count; >>>>>>>>>>>> ??502?? MultipleStackTracesCollector _collector; >>>>>>>>>>>> >>>>>>>>>>>> You can't have a StackObj as a member of another class like >>>>>>>>>>>> that as it may not be on the stack. I think >>>>>>>>>>>> MultipleStackTracesCollector should not extend any >>>>>>>>>>>> allocation class, and should always be embedded directly in >>>>>>>>>>>> another class. >>>>>>>>>>>> >>>>>>>>>>>> 481?? MultipleStackTracesCollector(JvmtiEnv *env, jint >>>>>>>>>>>> max_frame_count) { >>>>>>>>>>>> ??482???? _env = env; >>>>>>>>>>>> ??483???? _max_frame_count = max_frame_count; >>>>>>>>>>>> ??484???? _frame_count_total = 0; >>>>>>>>>>>> ??485???? _head = NULL; >>>>>>>>>>>> ??486???? _stack_info = NULL; >>>>>>>>>>>> ??487???? _result = JVMTI_ERROR_NONE; >>>>>>>>>>>> ??488?? } >>>>>>>>>>>> >>>>>>>>>>>> As you are touching this can you change it to use an >>>>>>>>>>>> initializer list as you did for the HandshakeClosure, and >>>>>>>>>>>> please keep one item per line. >>>>>>>>>>>> >>>>>>>>>>>> --- >>>>>>>>>>>> >>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>> >>>>>>>>>>>> ??820 assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>> ??821 java_thread->is_thread_fully_suspended(false, >>>>>>>>>>>> &debug_bits) || >>>>>>>>>>>> ??822????????? current_thread == >>>>>>>>>>>> java_thread->active_handshaker(), >>>>>>>>>>>> ??823????????? "at safepoint / handshake or target thread is >>>>>>>>>>>> suspended"); >>>>>>>>>>>> >>>>>>>>>>>> I don't think the suspension check is necessary, as even if >>>>>>>>>>>> the target is suspended we must still be at a safepoint or >>>>>>>>>>>> in a handshake with it. Makes me wonder if we used to allow >>>>>>>>>>>> a racy stacktrace operation on a suspended thread, assuming >>>>>>>>>>>> it would remain suspended? >>>>>>>>>>>> >>>>>>>>>>>> 1268?? oop thread_oop = jt->threadObj(); >>>>>>>>>>>> 1269 >>>>>>>>>>>> 1270?? if (!jt->is_exiting() && (jt->threadObj() != NULL)) { >>>>>>>>>>>> >>>>>>>>>>>> You can use thread_oop in line 1270. >>>>>>>>>>>> >>>>>>>>>>>> 1272 >>>>>>>>>>>> _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, >>>>>>>>>>>> thread_oop), >>>>>>>>>>>> 1273??????????????????????????? jt, thread_oop); >>>>>>>>>>>> >>>>>>>>>>>> It is frustrating that this entire call chain started with a >>>>>>>>>>>> jthread reference, which we converted to a JavaThread, only >>>>>>>>>>>> to eventually need to convert it back to a jthread! I think >>>>>>>>>>>> there is some scope for simplification here but not as part >>>>>>>>>>>> of this change. >>>>>>>>>>>> >>>>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>>>> >>>>>>>>>>>> IIUC at this point the _calling_thread is the current >>>>>>>>>>>> thread, so we can use: >>>>>>>>>>>> >>>>>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>>>>>>> >>>>>>>>>>>> --- >>>>>>>>>>>> >>>>>>>>>>>> Please add @bug lines to the tests. >>>>>>>>>>>> >>>>>>>>>>>> I'm still pondering the test logic but wanted to send this now. >>>>>>>>>>>> >>>>>>>>>>>> Thanks, >>>>>>>>>>>> David >>>>>>>>>>>> ----- >>>>>>>>>>>>> VM_GetThreadListStackTrace (for GetThreadListStackTraces) >>>>>>>>>>>>> and VM_GetAllStackTraces (for GetAllStackTraces) have >>>>>>>>>>>>> inherited VM_GetMultipleStackTraces VM operation which >>>>>>>>>>>>> provides the feature to generate jvmtiStackInfo. I modified >>>>>>>>>>>>> VM_GetMultipleStackTraces to a normal C++ class to share >>>>>>>>>>>>> with HandshakeClosure for GetThreadListStackTraces >>>>>>>>>>>>> (GetSingleStackTraceClosure). >>>>>>>>>>>>> >>>>>>>>>>>>> Also I added new testcases which test >>>>>>>>>>>>> GetThreadListStackTraces() with thread_count == 1 and with >>>>>>>>>>>>> all threads. >>>>>>>>>>>>> >>>>>>>>>>>>> This change has been tested in serviceability/jvmti >>>>>>>>>>>>> serviceability/jdwp vmTestbase/nsk/jvmti vmTestbase/nsk/jdi >>>>>>>>>>>>> vmTestbase/nsk/jdwp. >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> Thanks, >>>>>>>>>>>>> >>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> On 2020/06/24 15:50, Yasumasa Suenaga wrote: >>>>>>>>>>>>>> Hi all, >>>>>>>>>>>>>> >>>>>>>>>>>>>> Please review this change: >>>>>>>>>>>>>> >>>>>>>>>>>>>> ?? JBS: https://bugs.openjdk.java.net/browse/JDK-8242428 >>>>>>>>>>>>>> ?? webrev: >>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.00/ >>>>>>>>>>>>>> >>>>>>>>>>>>>> This change replace following VM operations to direct >>>>>>>>>>>>>> handshake. >>>>>>>>>>>>>> >>>>>>>>>>>>>> ??- VM_GetFrameCount (GetFrameCount()) >>>>>>>>>>>>>> ??- VM_GetFrameLocation (GetFrameLocation()) >>>>>>>>>>>>>> ??- VM_GetThreadListStackTraces (GetThreadListStackTrace()) >>>>>>>>>>>>>> ??- VM_GetCurrentLocation >>>>>>>>>>>>>> >>>>>>>>>>>>>> GetThreadListStackTrace() uses direct handshake if thread >>>>>>>>>>>>>> count == 1. In other case (thread count > 1), it would be >>>>>>>>>>>>>> performed as VM operation (VM_GetThreadListStackTraces). >>>>>>>>>>>>>> Caller of VM_GetCurrentLocation >>>>>>>>>>>>>> (JvmtiEnvThreadState::reset_current_location()) might be >>>>>>>>>>>>>> called at safepoint. So I added safepoint check in its >>>>>>>>>>>>>> caller. >>>>>>>>>>>>>> >>>>>>>>>>>>>> This change has been tested in serviceability/jvmti >>>>>>>>>>>>>> serviceability/jdwp vmTestbase/nsk/jvmti >>>>>>>>>>>>>> vmTestbase/nsk/jdi vmTestbase/ns >>>>>>>>>>>>>> k/jdwp. >>>>>>>>>>>>>> >>>>>>>>>>>>>> Also I tested it on submit repo, then it has execution >>>>>>>>>>>>>> error >>>>>>>>>>>>>> (mach5-one-ysuenaga-JDK-8242428-20200624-0054-12034717) >>>>>>>>>>>>>> due to dependency error. So I think it does not occur by >>>>>>>>>>>>>> this change. >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>> >>>>>>>>>>>>>> Yasumasa >>>> > From david.holmes at oracle.com Fri Jul 3 05:15:02 2020 From: david.holmes at oracle.com (David Holmes) Date: Fri, 3 Jul 2020 15:15:02 +1000 Subject: RFR: 8242428: JVMTI thread operations should use Thread-Local Handshake In-Reply-To: <7dc1903b-6295-3864-6301-4c02aacdb971@oss.nttdata.com> References: <6c263e4c-0a83-be7a-0288-ecb2de0b7cea@oss.nttdata.com> <2ea2f5d8-5c43-a7d3-d525-cd44c4009d25@oss.nttdata.com> <65889ab4-6b7e-86fb-59cc-012520b83138@oracle.com> <4b7df6f8-c8f7-fedf-6366-b885d2235b58@oss.nttdata.com> <74c05dfd-ffb2-b73d-66e5-dc98752729f5@oss.nttdata.com> <763793b1-9506-44c6-0681-1c71c44a44fd@oss.nttdata.com> <5107c478-1de2-7a49-ee71-dfad6a99a667@oracle.com> <90cdfef9-e558-0d25-33f5-25b7d65bb83b@oss.nttdata.com> <0e359819-618f-c17b-a427-bb7e4daa2c58@oracle.com> <3f890bed-6892-e64d-b21b-ca0cbe11784e@oracle.com> <7dc1903b-6295-3864-6301-4c02aacdb971@oss.nttdata.com> Message-ID: <04e09eb7-9483-8f63-4bb4-01c9e814802e@oracle.com> On 3/07/2020 2:27 pm, Yasumasa Suenaga wrote: > On 2020/07/03 12:24, Daniel D. Daugherty wrote: >> On 7/2/20 10:50 PM, David Holmes wrote: >>> Sorry I'm responding here without seeing latest webrev but there is >>> enough context I think ... >>> >>> On 3/07/2020 9:14 am, Yasumasa Suenaga wrote: >>>> Hi Dan, >>>> >>>> Thanks for your comment! >>>> >>>> On 2020/07/03 7:16, Daniel D. Daugherty wrote: >>>>> On 7/2/20 5:19 AM, Yasumasa Suenaga wrote: >>>>>> Hi David, >>>>>> >>>>>> I upload new webrev. Could you review again? >>>>>> >>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.03/ >>>>> >>>>> src/hotspot/share/prims/jvmtiEnv.cpp >>>>> ???? L1542: ??? // Get stack trace with handshake >>>>> ???????? nit - please add a period at the end. >>>> >>>> I will fix it. >>>> >>>> >>>>> ???? L1591: ??? *stack_info_ptr = op.stack_info(); >>>>> ???????? The return parameter should not be touched unless the return >>>>> ???????? code in 'err' == JVMTI_ERROR_NONE. >>>>> >>>>> ???? old L1582: ? if (err == JVMTI_ERROR_NONE) { >>>>> ???????? Please restore this check. The return parameter should not >>>>> ???????? be touched unless the return code in 'err' == >>>>> JVMTI_ERROR_NONE. >>>> >>>> I will fix it. >>> >>> But op.stack_info() will return NULL if the error is not >>> JVMTI_ERROR_NONE. Are you (Dan) concerned about someone passing in a >>> non-null/initialized out-pointer that will be reset to NULL if there >>> was an error? >> >> Actually the way we used to test this in POSIX tests is to call >> an API with known bad parameters and the return parameter ptr >> set to NULL. If the return parameter ptr was touched when an >> error should have been detected on an earlier parameter, then >> the test failed. >> >> >>> >>>> >>>>> ???? L1272: ? if (!jt->is_exiting() && (thread_oop != NULL)) { >>>>> ???????? nit - extra parens around the second expression. >>>> >>>> I will fix it. >>>> >>>> >>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>> ???? old L1532: ? _result = JVMTI_ERROR_THREAD_NOT_ALIVE; >>>>> ???????? This deletion of the _result field threw me for a minute >>>>> and then >>>>> ???? ? ? I figured out that the field is init to >>>>> JVMTI_ERROR_THREAD_NOT_ALIVE >>>>> ???????? in the constructor. >>>>> >>>>> ???? L1553: ? if (!jt->is_exiting() && (jt->threadObj() != NULL)) { >>>>> ???????? nit - extra parens around the second expression. >>>> >>>> I will fix it. >>>> >>>> >>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>> ???? No comments. >>>>> >>>>> src/hotspot/share/runtime/vmOperations.hpp >>>>> ???? No comments. >>>>> >>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/GetThreadListStackTraces.java >>>>> >>>>> ???? No comments. >>>>> >>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/OneGetThreadListStackTraces.java >>>>> >>>>> ???? L64: ??????? startSignal.countDown(); >>>>> ???????? I was expecting this to be a call to await() instead of >>>>> ???????? countDown(). What am I missing here? >>>>> >>>>> ???????? I think this test might be passing by accident right now, >>>>> but... >>>> >>>> Main thread (which call JVMTI functions to test) should wait until >>>> test thread is ready. >>>> So main thread would wait startSignal, and test thread would count >>>> down. >>> >>> No! >>> >>> The test thread that previously called obj.wait() now calls >>> latch.await(). >>> >>> The main thread that previously called obj.notify() now calls >>> latch.countDown(). >>> >>> The main thread continues to spin until it sees the target is WAITING >>> before proceeding with the test. > > If I add spin wait to wait until transit target thread state is WAITING > (as following), we don't need to call SuspendThread(). > Which is better? The original spin-wait loop checking for WAITING is better because it is the only guarantee that the target thread is blocked where you need it to be. suspending the thread is racy as you don't know exactly where the suspend will hit. Thanks, David ----- > > ``` > /* Wait until the thread state transits to "waiting" */ > while (th.getState() != Thread.State.WAITING) { > ??? Thread.onSpinWait(); > } > ``` > > For simplify, spin wait is prefer to OneGetThreadListStackTraces.java in > webrev.03. > > > Thanks, > > Yasumasa > > >> Here's the flow as I see it: >> >> main thread >> ?? - start worker thread >> ?? - startSignal.await() >> ???? - main is now blocked >> >> worker thread >> ?? - startSignal.countDown() >> ???? - main is now unblocked >> ?? - stopSignal.await() >> ???? - worker is now blocked >> >> main thread >> ?? - checkCallStacks(th) >> ?? - stopSignal.countDown() >> ???? - worker is now unblocked >> ?? - th.join >> ???? - main is now blocked >> >> worker thread >> ?? - runs off the end of run() >> ???? - main is now unblocked >> >> main thread >> ?? - run off the end of main() >> >> >>> >>>> >>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libGetThreadListStackTraces.c >>>>> >>>>> ???? L92: ? jthreads = (jthread *)malloc(sizeof(jthread) * >>>>> num_threads); >>>>> ???????? You don't check for malloc() failure. >>>>> ???????? 'jthreads' is allocated but never freed. >>>> >>>> I will fix it. >>>> >>>> >>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.c >>>>> >>>>> ???? L91: ? result = (*jvmti)->SuspendThread(jvmti, thread); >>>>> ???????? Why are you suspending the thread? GetAllStackTraces() and >>>>> ???????? GetThreadListStackTraces() do not require the target >>>>> thread(s) >>>>> ???????? to be suspend. >>>>> >>>>> ???????? If you decide not to SuspendThread, then you don't need the >>>>> ???????? AddCapabilities or the ResumeThread calls. >>>> >>>> Test thread might not be entered following code >>>> (stopSignal.await()). We might see deferent call stack between >>>> GetAllStackTraces() and GetThreadListStackTraces(). We cannot >>>> control to freeze call stack of test thread in Java code. >>>> (I didn't use SuspendThread() at first, but I saw some errors which >>>> causes in above.) >>>> >>>> So we need to call SuspendThread() to ensure we can see same call >>>> stack. >>> >>> If you are checking that the thread is in state WAITING then it >>> cannot escape from that state and you can sample the stack multiple >>> times from any API and get the same result. >>> >>> I suspect the errors you saw were from the apparent incorrect use of >>> the CountDownLatch. >> >> With the flow outlined above, the worker thread should be >> nicely blocked in stopSignal.await() when stuff is sampled. >> >> Dan >> >> >>> >>> Cheers, >>> David >>> ----- >>> >>>> >>>> Thanks, >>>> >>>> Yasumasa >>>> >>>> >>>>> Dan >>>>> >>>>>> >>>>>> On 2020/07/02 15:05, David Holmes wrote: >>>>>>> Hi Yasumasa, >>>>>>> >>>>>>> On 1/07/2020 11:53 am, Yasumasa Suenaga wrote: >>>>>>>> Hi, >>>>>>>> >>>>>>>> I uploaded new webrev. Could review again? >>>>>>>> >>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.02/ >>>>>>> >>>>>>> Updates look fine - thanks. >>>>>>> >>>>>>> One minor nit: >>>>>>> >>>>>>> 1274???? _collector.allocate_and_fill_stacks(1); >>>>>>> 1275???? _collector.set_result(JVMTI_ERROR_NONE); >>>>>>> >>>>>>> In the other places where you use _collector you rely on result >>>>>>> being initialized to JVMTI_ERROR_NONE, rather than setting it >>>>>>> directly after allocate_and_fill_stacks(). >>>>>> >>>>>> Fixed. >>>>>> >>>>>> >>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>> >>>>>>>>>>>>> ? 820 assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>> ? 821 java_thread->is_thread_fully_suspended(false, >>>>>>>>>>>>> &debug_bits) || >>>>>>>>>>>>> ? 822????????? current_thread == >>>>>>>>>>>>> java_thread->active_handshaker(), >>>>>>>>>>>>> ? 823????????? "at safepoint / handshake or target thread >>>>>>>>>>>>> is suspended"); >>>>>>>>>>>>> >>>>>>>>>>>>> I don't think the suspension check is necessary, as even if >>>>>>>>>>>>> the target is suspended we must still be at a safepoint or >>>>>>>>>>>>> in a handshake with it. Makes me wonder if we used to allow >>>>>>>>>>>>> a racy stacktrace operation on a suspended thread, assuming >>>>>>>>>>>>> it would remain suspended? >>>>>>>> >>>>>>>> This function (JvmtiEnvBase::get_stack_trace()) can be called to >>>>>>>> get own stack trace. For example, we can call GetStackTrace() >>>>>>>> for current thread at JVMTI event. >>>>>>>> So I changed assert as below: >>>>>>>> >>>>>>>> ``` >>>>>>>> ??820?? assert(current_thread == java_thread || >>>>>>>> ??821????????? SafepointSynchronize::is_at_safepoint() || >>>>>>>> ??822????????? current_thread == java_thread->active_handshaker(), >>>>>>>> ??823????????? "call by myself / at safepoint / at handshake"); >>>>>>>> ``` >>>>>>> >>>>>>> Yep good catch. I hope current tests caught that. >>>>>> >>>>>> They would be tested in >>>>>> vmTestbase/nsk/jvmti/GetStackTrace/getstacktr001/ (own call >>>>>> stacks), and getstacktr003 (call stacks in other thread). >>>>>> >>>>>> >>>>>>> Speaking of tests ... >>>>>>> >>>>>>> In the native code I think you need to check the success of all >>>>>>> JNI methods that can throw exceptions - otherwise I believe the >>>>>>> tests may trigger warnings if -Xcheck:jni is used with them. See >>>>>>> for example: >>>>>>> >>>>>>> test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/libHeapMonitorTest.cpp >>>>>>> >>>>>> >>>>>> I updated testcases to check JNI and JVMTI function calls. >>>>>> >>>>>> >>>>>>> In the Java code the target thread: >>>>>>> >>>>>>> ?? 45???? public void run() { >>>>>>> ?? 46?????? try { >>>>>>> ?? 47?????????? synchronized (lock) { >>>>>>> ?? 48?????????????? lock.wait(); >>>>>>> ?? 49?????????????? System.out.println("OK"); >>>>>>> ?? 50?????????? } >>>>>>> >>>>>>> is potentially susceptible to spurious wakeups. Using a >>>>>>> CountDownLatch would be robust. >>>>>> >>>>>> Fixed. >>>>>> >>>>>> >>>>>> Thanks, >>>>>> >>>>>> Yasumasa >>>>>> >>>>>> >>>>>>> Thanks, >>>>>>> David >>>>>>> ----- >>>>>>> >>>>>>>> >>>>>>>> Thanks, >>>>>>>> >>>>>>>> Yasumasa >>>>>>>> >>>>>>>> >>>>>>>> On 2020/07/01 8:48, David Holmes wrote: >>>>>>>>> Hi Yasumasa, >>>>>>>>> >>>>>>>>> On 1/07/2020 9:05 am, Yasumasa Suenaga wrote: >>>>>>>>>> Hi David, >>>>>>>>>> >>>>>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>>>>> >>>>>>>>>>>>> IIUC at this point the _calling_thread is the current >>>>>>>>>>>>> thread, so we can use: >>>>>>>>>>>>> >>>>>>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>>>>> >>>>>>>>>> If so, we can call make_local() in L1272 without JavaThread >>>>>>>>>> (or we can pass current thread to make_local()). Is it right? >>>>>>>>>> >>>>>>>>>> ``` >>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>> 1272 >>>>>>>>>> _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, >>>>>>>>>> thread_oop), >>>>>>>>>> 1273??????????????????????????? jt, thread_oop); >>>>>>>>>> ``` >>>>>>>>> >>>>>>>>> Sorry I got confused, _calling_thread may not be the current >>>>>>>>> thread as we could be executing the handshake in the target >>>>>>>>> thread itself. So the ResourceMark is correct as-is (implicitly >>>>>>>>> for current thread). >>>>>>>>> >>>>>>>>> The argument to fill_frames will be used in the jvmtiStackInfo >>>>>>>>> and passed back to the _calling_thread, so it must be created >>>>>>>>> via make_local(_calling_thread, ...) as you presently have. >>>>>>>>> >>>>>>>>> Thanks, >>>>>>>>> David >>>>>>>>> >>>>>>>>>> Thanks, >>>>>>>>>> >>>>>>>>>> Yasumasa >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> On 2020/07/01 7:05, David Holmes wrote: >>>>>>>>>>> On 1/07/2020 12:17 am, Yasumasa Suenaga wrote: >>>>>>>>>>>> Hi David, >>>>>>>>>>>> >>>>>>>>>>>> Thank you for reviewing! I will update new webrev tomorrow. >>>>>>>>>>>> >>>>>>>>>>>>> 466 class MultipleStackTracesCollector : public StackObj { >>>>>>>>>>>>> >>>>>>>>>>>>> ? 498 class VM_GetAllStackTraces : public VM_Operation { >>>>>>>>>>>>> ? 499 private: >>>>>>>>>>>>> ? 500?? JavaThread *_calling_thread; >>>>>>>>>>>>> ? 501?? jint _final_thread_count; >>>>>>>>>>>>> ? 502?? MultipleStackTracesCollector _collector; >>>>>>>>>>>>> >>>>>>>>>>>>> You can't have a StackObj as a member of another class like >>>>>>>>>>>>> that as it may not be on the stack. I think >>>>>>>>>>>>> MultipleStackTracesCollector should not extend any >>>>>>>>>>>>> allocation class, and should always be embedded directly in >>>>>>>>>>>>> another class. >>>>>>>>>>>> >>>>>>>>>>>> I'm not sure what does mean "embedded". >>>>>>>>>>>> Is it ok as below? >>>>>>>>>>>> >>>>>>>>>>>> ``` >>>>>>>>>>>> class MultipleStackTracesCollector { >>>>>>>>>>>> ??? : >>>>>>>>>>>> } >>>>>>>>>>>> >>>>>>>>>>>> class GetAllStackTraces : public VM_Operation { >>>>>>>>>>>> ?? private: >>>>>>>>>>>> ???? MultipleStackTracesCollector _collector; >>>>>>>>>>>> } >>>>>>>>>>>> ``` >>>>>>>>>>> >>>>>>>>>>> Yes that I what I meant. >>>>>>>>>>> >>>>>>>>>>> Thanks, >>>>>>>>>>> David >>>>>>>>>>> ----- >>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> Thanks, >>>>>>>>>>>> >>>>>>>>>>>> Yasumasa >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> On 2020/06/30 22:22, David Holmes wrote: >>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>> >>>>>>>>>>>>> On 30/06/2020 10:05 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>> Hi David, Serguei, >>>>>>>>>>>>>> >>>>>>>>>>>>>> I updated webrev for 8242428. Could you review again? >>>>>>>>>>>>>> This change migrate to use direct handshake for >>>>>>>>>>>>>> GetStackTrace() and GetThreadListStackTraces() (when >>>>>>>>>>>>>> thread_count == 1). >>>>>>>>>>>>>> >>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.01/ >>>>>>>>>>>>> >>>>>>>>>>>>> This looks really good now! I only have a few nits below. >>>>>>>>>>>>> There is one thing I don't like about it but it requires a >>>>>>>>>>>>> change to the main Handshake logic to address - in >>>>>>>>>>>>> JvmtiEnv::GetThreadListStackTraces you have to create a >>>>>>>>>>>>> ThreadsListHandle to convert the jthread to a JavaThread, >>>>>>>>>>>>> but then the Handshake::execute_direct creates another >>>>>>>>>>>>> ThreadsListHandle internally. That's a waste. I will >>>>>>>>>>>>> discuss with Robbin and file a RFE to have an overload of >>>>>>>>>>>>> execute_direct that takes an existing TLH. Actually it's >>>>>>>>>>>>> worse than that because we have another TLH in use at the >>>>>>>>>>>>> entry point for the JVMTI functions, so I think there may >>>>>>>>>>>>> be some scope for simplifying the use of TLH instances - >>>>>>>>>>>>> future RFE. >>>>>>>>>>>>> >>>>>>>>>>>>> --- >>>>>>>>>>>>> >>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>>>>>>>>> >>>>>>>>>>>>> ??451?? GetStackTraceClosure(JvmtiEnv *env, jint >>>>>>>>>>>>> start_depth, jint max_count, >>>>>>>>>>>>> ??452??????????????????????? jvmtiFrameInfo* frame_buffer, >>>>>>>>>>>>> jint* count_ptr) >>>>>>>>>>>>> ??453???? : HandshakeClosure("GetStackTrace"), >>>>>>>>>>>>> ??454?????? _env(env), _start_depth(start_depth), >>>>>>>>>>>>> _max_count(max_count), >>>>>>>>>>>>> ??455?????? _frame_buffer(frame_buffer), >>>>>>>>>>>>> _count_ptr(count_ptr), >>>>>>>>>>>>> ??456 _result(JVMTI_ERROR_THREAD_NOT_ALIVE) { >>>>>>>>>>>>> >>>>>>>>>>>>> Nit: can you do one initializer per line please. >>>>>>>>>>>>> >>>>>>>>>>>>> This looks wrong: >>>>>>>>>>>>> >>>>>>>>>>>>> 466 class MultipleStackTracesCollector : public StackObj { >>>>>>>>>>>>> >>>>>>>>>>>>> ??498 class VM_GetAllStackTraces : public VM_Operation { >>>>>>>>>>>>> ??499 private: >>>>>>>>>>>>> ??500?? JavaThread *_calling_thread; >>>>>>>>>>>>> ??501?? jint _final_thread_count; >>>>>>>>>>>>> ??502?? MultipleStackTracesCollector _collector; >>>>>>>>>>>>> >>>>>>>>>>>>> You can't have a StackObj as a member of another class like >>>>>>>>>>>>> that as it may not be on the stack. I think >>>>>>>>>>>>> MultipleStackTracesCollector should not extend any >>>>>>>>>>>>> allocation class, and should always be embedded directly in >>>>>>>>>>>>> another class. >>>>>>>>>>>>> >>>>>>>>>>>>> 481?? MultipleStackTracesCollector(JvmtiEnv *env, jint >>>>>>>>>>>>> max_frame_count) { >>>>>>>>>>>>> ??482???? _env = env; >>>>>>>>>>>>> ??483???? _max_frame_count = max_frame_count; >>>>>>>>>>>>> ??484???? _frame_count_total = 0; >>>>>>>>>>>>> ??485???? _head = NULL; >>>>>>>>>>>>> ??486???? _stack_info = NULL; >>>>>>>>>>>>> ??487???? _result = JVMTI_ERROR_NONE; >>>>>>>>>>>>> ??488?? } >>>>>>>>>>>>> >>>>>>>>>>>>> As you are touching this can you change it to use an >>>>>>>>>>>>> initializer list as you did for the HandshakeClosure, and >>>>>>>>>>>>> please keep one item per line. >>>>>>>>>>>>> >>>>>>>>>>>>> --- >>>>>>>>>>>>> >>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>> >>>>>>>>>>>>> ??820 assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>> ??821 java_thread->is_thread_fully_suspended(false, >>>>>>>>>>>>> &debug_bits) || >>>>>>>>>>>>> ??822????????? current_thread == >>>>>>>>>>>>> java_thread->active_handshaker(), >>>>>>>>>>>>> ??823????????? "at safepoint / handshake or target thread >>>>>>>>>>>>> is suspended"); >>>>>>>>>>>>> >>>>>>>>>>>>> I don't think the suspension check is necessary, as even if >>>>>>>>>>>>> the target is suspended we must still be at a safepoint or >>>>>>>>>>>>> in a handshake with it. Makes me wonder if we used to allow >>>>>>>>>>>>> a racy stacktrace operation on a suspended thread, assuming >>>>>>>>>>>>> it would remain suspended? >>>>>>>>>>>>> >>>>>>>>>>>>> 1268?? oop thread_oop = jt->threadObj(); >>>>>>>>>>>>> 1269 >>>>>>>>>>>>> 1270?? if (!jt->is_exiting() && (jt->threadObj() != NULL)) { >>>>>>>>>>>>> >>>>>>>>>>>>> You can use thread_oop in line 1270. >>>>>>>>>>>>> >>>>>>>>>>>>> 1272 >>>>>>>>>>>>> _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, >>>>>>>>>>>>> thread_oop), >>>>>>>>>>>>> 1273??????????????????????????? jt, thread_oop); >>>>>>>>>>>>> >>>>>>>>>>>>> It is frustrating that this entire call chain started with >>>>>>>>>>>>> a jthread reference, which we converted to a JavaThread, >>>>>>>>>>>>> only to eventually need to convert it back to a jthread! I >>>>>>>>>>>>> think there is some scope for simplification here but not >>>>>>>>>>>>> as part of this change. >>>>>>>>>>>>> >>>>>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>>>>> >>>>>>>>>>>>> IIUC at this point the _calling_thread is the current >>>>>>>>>>>>> thread, so we can use: >>>>>>>>>>>>> >>>>>>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>>>>>>>> >>>>>>>>>>>>> --- >>>>>>>>>>>>> >>>>>>>>>>>>> Please add @bug lines to the tests. >>>>>>>>>>>>> >>>>>>>>>>>>> I'm still pondering the test logic but wanted to send this >>>>>>>>>>>>> now. >>>>>>>>>>>>> >>>>>>>>>>>>> Thanks, >>>>>>>>>>>>> David >>>>>>>>>>>>> ----- >>>>>>>>>>>>>> VM_GetThreadListStackTrace (for GetThreadListStackTraces) >>>>>>>>>>>>>> and VM_GetAllStackTraces (for GetAllStackTraces) have >>>>>>>>>>>>>> inherited VM_GetMultipleStackTraces VM operation which >>>>>>>>>>>>>> provides the feature to generate jvmtiStackInfo. I >>>>>>>>>>>>>> modified VM_GetMultipleStackTraces to a normal C++ class >>>>>>>>>>>>>> to share with HandshakeClosure for >>>>>>>>>>>>>> GetThreadListStackTraces (GetSingleStackTraceClosure). >>>>>>>>>>>>>> >>>>>>>>>>>>>> Also I added new testcases which test >>>>>>>>>>>>>> GetThreadListStackTraces() with thread_count == 1 and with >>>>>>>>>>>>>> all threads. >>>>>>>>>>>>>> >>>>>>>>>>>>>> This change has been tested in serviceability/jvmti >>>>>>>>>>>>>> serviceability/jdwp vmTestbase/nsk/jvmti >>>>>>>>>>>>>> vmTestbase/nsk/jdi vmTestbase/nsk/jdwp. >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>> >>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> On 2020/06/24 15:50, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>> Hi all, >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Please review this change: >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> ?? JBS: https://bugs.openjdk.java.net/browse/JDK-8242428 >>>>>>>>>>>>>>> ?? webrev: >>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.00/ >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> This change replace following VM operations to direct >>>>>>>>>>>>>>> handshake. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> ??- VM_GetFrameCount (GetFrameCount()) >>>>>>>>>>>>>>> ??- VM_GetFrameLocation (GetFrameLocation()) >>>>>>>>>>>>>>> ??- VM_GetThreadListStackTraces (GetThreadListStackTrace()) >>>>>>>>>>>>>>> ??- VM_GetCurrentLocation >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> GetThreadListStackTrace() uses direct handshake if thread >>>>>>>>>>>>>>> count == 1. In other case (thread count > 1), it would be >>>>>>>>>>>>>>> performed as VM operation (VM_GetThreadListStackTraces). >>>>>>>>>>>>>>> Caller of VM_GetCurrentLocation >>>>>>>>>>>>>>> (JvmtiEnvThreadState::reset_current_location()) might be >>>>>>>>>>>>>>> called at safepoint. So I added safepoint check in its >>>>>>>>>>>>>>> caller. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> This change has been tested in serviceability/jvmti >>>>>>>>>>>>>>> serviceability/jdwp vmTestbase/nsk/jvmti >>>>>>>>>>>>>>> vmTestbase/nsk/jdi vmTestbase/ns >>>>>>>>>>>>>>> k/jdwp. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Also I tested it on submit repo, then it has execution >>>>>>>>>>>>>>> error >>>>>>>>>>>>>>> (mach5-one-ysuenaga-JDK-8242428-20200624-0054-12034717) >>>>>>>>>>>>>>> due to dependency error. So I think it does not occur by >>>>>>>>>>>>>>> this change. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Yasumasa >>>>> >> From chris.plummer at oracle.com Fri Jul 3 05:36:38 2020 From: chris.plummer at oracle.com (Chris Plummer) Date: Thu, 2 Jul 2020 22:36:38 -0700 Subject: RFR(T): 8248746: Undo jhsdb related exclusiveAccess.dirs changes that were done for JDK-8220295 Message-ID: <6d2e0e0e-fda7-b346-1f1c-4e6383f58c1e@oracle.com> Hello, Please review the following trivial change: https://bugs.openjdk.java.net/browse/JDK-8248746 diff --git a/test/jdk/TEST.ROOT b/test/jdk/TEST.ROOT --- a/test/jdk/TEST.ROOT +++ b/test/jdk/TEST.ROOT @@ -24,7 +24,7 @@ ?# Tests that cannot run concurrently ?exclusiveAccess.dirs=java/math/BigInteger/largeMemory \ ?java/rmi/Naming java/util/prefs sun/management/jmxremote \ -sun/tools/jstatd sun/tools/jcmd sun/tools/jhsdb sun/tools/jhsdb/heapconfig \ +sun/tools/jstatd sun/tools/jcmd \ ?sun/tools/jinfo sun/tools/jmap sun/tools/jps sun/tools/jstack sun/tools/jstat \ ?com/sun/tools/attach sun/security/mscapi java/util/stream java/util/Arrays/largeMemory \ ?java/util/BitSet/stream javax/rmi Due to some issues with running multiple Attach API tests at the same time, it was decided to add them all to exclusiveAccess.dirs. This was done under JDK-8220295. However, the jhsdb tests should never have been added since they don't use the Attach API. They use SA Attach, which is completely unrelated. I've been testing with this change for the past 6 weeks or so, and haven't seen any issues, nor would I expect any. thanks, Chris From igor.ignatyev at oracle.com Fri Jul 3 05:40:17 2020 From: igor.ignatyev at oracle.com (Igor Ignatyev) Date: Thu, 2 Jul 2020 22:40:17 -0700 Subject: RFR(T): 8248746: Undo jhsdb related exclusiveAccess.dirs changes that were done for JDK-8220295 In-Reply-To: <6d2e0e0e-fda7-b346-1f1c-4e6383f58c1e@oracle.com> References: <6d2e0e0e-fda7-b346-1f1c-4e6383f58c1e@oracle.com> Message-ID: <641570A2-6CE3-4E3B-AA10-D55386689A58@oracle.com> Hi Chris, looks good and trivial. would you consider pushing it into jdk/jdk15? -- Igor > On Jul 2, 2020, at 10:36 PM, Chris Plummer wrote: > > Hello, > > Please review the following trivial change: > > https://bugs.openjdk.java.net/browse/JDK-8248746 > > diff --git a/test/jdk/TEST.ROOT b/test/jdk/TEST.ROOT > --- a/test/jdk/TEST.ROOT > +++ b/test/jdk/TEST.ROOT > @@ -24,7 +24,7 @@ > # Tests that cannot run concurrently > exclusiveAccess.dirs=java/math/BigInteger/largeMemory \ > java/rmi/Naming java/util/prefs sun/management/jmxremote \ > -sun/tools/jstatd sun/tools/jcmd sun/tools/jhsdb sun/tools/jhsdb/heapconfig \ > +sun/tools/jstatd sun/tools/jcmd \ > sun/tools/jinfo sun/tools/jmap sun/tools/jps sun/tools/jstack sun/tools/jstat \ > com/sun/tools/attach sun/security/mscapi java/util/stream java/util/Arrays/largeMemory \ > java/util/BitSet/stream javax/rmi > > Due to some issues with running multiple Attach API tests at the same time, it was decided to add them all to exclusiveAccess.dirs. This was done under JDK-8220295. However, the jhsdb tests should never have been added since they don't use the Attach API. They use SA Attach, which is completely unrelated. I've been testing with this change for the past 6 weeks or so, and haven't seen any issues, nor would I expect any. > > thanks, > > Chris > From chris.plummer at oracle.com Fri Jul 3 06:10:08 2020 From: chris.plummer at oracle.com (Chris Plummer) Date: Thu, 2 Jul 2020 23:10:08 -0700 Subject: RFR(T): 8248746: Undo jhsdb related exclusiveAccess.dirs changes that were done for JDK-8220295 In-Reply-To: <641570A2-6CE3-4E3B-AA10-D55386689A58@oracle.com> References: <6d2e0e0e-fda7-b346-1f1c-4e6383f58c1e@oracle.com> <641570A2-6CE3-4E3B-AA10-D55386689A58@oracle.com> Message-ID: <59f57ba9-9304-3253-1ee4-5e758ceffd42@oracle.com> I can do that. Chris On 7/2/20 10:40 PM, Igor Ignatyev wrote: > Hi Chris, > > looks good and trivial. would you consider pushing it into jdk/jdk15? > > -- Igor > >> On Jul 2, 2020, at 10:36 PM, Chris Plummer wrote: >> >> Hello, >> >> Please review the following trivial change: >> >> https://bugs.openjdk.java.net/browse/JDK-8248746 >> >> diff --git a/test/jdk/TEST.ROOT b/test/jdk/TEST.ROOT >> --- a/test/jdk/TEST.ROOT >> +++ b/test/jdk/TEST.ROOT >> @@ -24,7 +24,7 @@ >> # Tests that cannot run concurrently >> exclusiveAccess.dirs=java/math/BigInteger/largeMemory \ >> java/rmi/Naming java/util/prefs sun/management/jmxremote \ >> -sun/tools/jstatd sun/tools/jcmd sun/tools/jhsdb sun/tools/jhsdb/heapconfig \ >> +sun/tools/jstatd sun/tools/jcmd \ >> sun/tools/jinfo sun/tools/jmap sun/tools/jps sun/tools/jstack sun/tools/jstat \ >> com/sun/tools/attach sun/security/mscapi java/util/stream java/util/Arrays/largeMemory \ >> java/util/BitSet/stream javax/rmi >> >> Due to some issues with running multiple Attach API tests at the same time, it was decided to add them all to exclusiveAccess.dirs. This was done under JDK-8220295. However, the jhsdb tests should never have been added since they don't use the Attach API. They use SA Attach, which is completely unrelated. I've been testing with this change for the past 6 weeks or so, and haven't seen any issues, nor would I expect any. >> >> thanks, >> >> Chris >> From suenaga at oss.nttdata.com Fri Jul 3 06:29:43 2020 From: suenaga at oss.nttdata.com (Yasumasa Suenaga) Date: Fri, 3 Jul 2020 15:29:43 +0900 Subject: RFR: 8242428: JVMTI thread operations should use Thread-Local Handshake In-Reply-To: <04e09eb7-9483-8f63-4bb4-01c9e814802e@oracle.com> References: <6c263e4c-0a83-be7a-0288-ecb2de0b7cea@oss.nttdata.com> <2ea2f5d8-5c43-a7d3-d525-cd44c4009d25@oss.nttdata.com> <65889ab4-6b7e-86fb-59cc-012520b83138@oracle.com> <4b7df6f8-c8f7-fedf-6366-b885d2235b58@oss.nttdata.com> <74c05dfd-ffb2-b73d-66e5-dc98752729f5@oss.nttdata.com> <763793b1-9506-44c6-0681-1c71c44a44fd@oss.nttdata.com> <5107c478-1de2-7a49-ee71-dfad6a99a667@oracle.com> <90cdfef9-e558-0d25-33f5-25b7d65bb83b@oss.nttdata.com> <0e359819-618f-c17b-a427-bb7e4daa2c58@oracle.com> <3f890bed-6892-e64d-b21b-ca0cbe11784e@oracle.com> <7dc1903b-6295-3864-6301-4c02aacdb971@oss.nttdata.com> <04e09eb7-9483-8f63-4bb4-01c9e814802e@oracle.com> Message-ID: Hi Dan, David, I uploaded new webrev. Could you review again? http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/ OneGetThreadListStackTraces.java in this webrev would wait until thread state is transited to "waiting" with spin wait. CountDownLatch::await call as Dan pointed is fixed in it :) Diff from webrev.03: http://hg.openjdk.java.net/jdk/submit/rev/c9aeb7001e50 Thanks, Yasumasa On 2020/07/03 14:15, David Holmes wrote: > > > On 3/07/2020 2:27 pm, Yasumasa Suenaga wrote: >> On 2020/07/03 12:24, Daniel D. Daugherty wrote: >>> On 7/2/20 10:50 PM, David Holmes wrote: >>>> Sorry I'm responding here without seeing latest webrev but there is enough context I think ... >>>> >>>> On 3/07/2020 9:14 am, Yasumasa Suenaga wrote: >>>>> Hi Dan, >>>>> >>>>> Thanks for your comment! >>>>> >>>>> On 2020/07/03 7:16, Daniel D. Daugherty wrote: >>>>>> On 7/2/20 5:19 AM, Yasumasa Suenaga wrote: >>>>>>> Hi David, >>>>>>> >>>>>>> I upload new webrev. Could you review again? >>>>>>> >>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.03/ >>>>>> >>>>>> src/hotspot/share/prims/jvmtiEnv.cpp >>>>>> ???? L1542: ??? // Get stack trace with handshake >>>>>> ???????? nit - please add a period at the end. >>>>> >>>>> I will fix it. >>>>> >>>>> >>>>>> ???? L1591: ??? *stack_info_ptr = op.stack_info(); >>>>>> ???????? The return parameter should not be touched unless the return >>>>>> ???????? code in 'err' == JVMTI_ERROR_NONE. >>>>>> >>>>>> ???? old L1582: ? if (err == JVMTI_ERROR_NONE) { >>>>>> ???????? Please restore this check. The return parameter should not >>>>>> ???????? be touched unless the return code in 'err' == JVMTI_ERROR_NONE. >>>>> >>>>> I will fix it. >>>> >>>> But op.stack_info() will return NULL if the error is not JVMTI_ERROR_NONE. Are you (Dan) concerned about someone passing in a non-null/initialized out-pointer that will be reset to NULL if there was an error? >>> >>> Actually the way we used to test this in POSIX tests is to call >>> an API with known bad parameters and the return parameter ptr >>> set to NULL. If the return parameter ptr was touched when an >>> error should have been detected on an earlier parameter, then >>> the test failed. >>> >>> >>>> >>>>> >>>>>> ???? L1272: ? if (!jt->is_exiting() && (thread_oop != NULL)) { >>>>>> ???????? nit - extra parens around the second expression. >>>>> >>>>> I will fix it. >>>>> >>>>> >>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>> ???? old L1532: ? _result = JVMTI_ERROR_THREAD_NOT_ALIVE; >>>>>> ???????? This deletion of the _result field threw me for a minute and then >>>>>> ???? ? ? I figured out that the field is init to JVMTI_ERROR_THREAD_NOT_ALIVE >>>>>> ???????? in the constructor. >>>>>> >>>>>> ???? L1553: ? if (!jt->is_exiting() && (jt->threadObj() != NULL)) { >>>>>> ???????? nit - extra parens around the second expression. >>>>> >>>>> I will fix it. >>>>> >>>>> >>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>> ???? No comments. >>>>>> >>>>>> src/hotspot/share/runtime/vmOperations.hpp >>>>>> ???? No comments. >>>>>> >>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/GetThreadListStackTraces.java >>>>>> ???? No comments. >>>>>> >>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/OneGetThreadListStackTraces.java >>>>>> ???? L64: ??????? startSignal.countDown(); >>>>>> ???????? I was expecting this to be a call to await() instead of >>>>>> ???????? countDown(). What am I missing here? >>>>>> >>>>>> ???????? I think this test might be passing by accident right now, but... >>>>> >>>>> Main thread (which call JVMTI functions to test) should wait until test thread is ready. >>>>> So main thread would wait startSignal, and test thread would count down. >>>> >>>> No! >>>> >>>> The test thread that previously called obj.wait() now calls latch.await(). >>>> >>>> The main thread that previously called obj.notify() now calls latch.countDown(). >>>> >>>> The main thread continues to spin until it sees the target is WAITING before proceeding with the test. >> >> If I add spin wait to wait until transit target thread state is WAITING (as following), we don't need to call SuspendThread(). >> Which is better? > > The original spin-wait loop checking for? WAITING is better because it is the only guarantee that the target thread is blocked where you need it to be. suspending the thread is racy as you don't know exactly where the suspend will hit. > > Thanks, > David > ----- > >> >> ``` >> /* Wait until the thread state transits to "waiting" */ >> while (th.getState() != Thread.State.WAITING) { >> ???? Thread.onSpinWait(); >> } >> ``` >> >> For simplify, spin wait is prefer to OneGetThreadListStackTraces.java in webrev.03. >> >> >> Thanks, >> >> Yasumasa >> >> >>> Here's the flow as I see it: >>> >>> main thread >>> ?? - start worker thread >>> ?? - startSignal.await() >>> ???? - main is now blocked >>> >>> worker thread >>> ?? - startSignal.countDown() >>> ???? - main is now unblocked >>> ?? - stopSignal.await() >>> ???? - worker is now blocked >>> >>> main thread >>> ?? - checkCallStacks(th) >>> ?? - stopSignal.countDown() >>> ???? - worker is now unblocked >>> ?? - th.join >>> ???? - main is now blocked >>> >>> worker thread >>> ?? - runs off the end of run() >>> ???? - main is now unblocked >>> >>> main thread >>> ?? - run off the end of main() >>> >>> >>>> >>>>> >>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libGetThreadListStackTraces.c >>>>>> ???? L92: ? jthreads = (jthread *)malloc(sizeof(jthread) * num_threads); >>>>>> ???????? You don't check for malloc() failure. >>>>>> ???????? 'jthreads' is allocated but never freed. >>>>> >>>>> I will fix it. >>>>> >>>>> >>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.c >>>>>> ???? L91: ? result = (*jvmti)->SuspendThread(jvmti, thread); >>>>>> ???????? Why are you suspending the thread? GetAllStackTraces() and >>>>>> ???????? GetThreadListStackTraces() do not require the target thread(s) >>>>>> ???????? to be suspend. >>>>>> >>>>>> ???????? If you decide not to SuspendThread, then you don't need the >>>>>> ???????? AddCapabilities or the ResumeThread calls. >>>>> >>>>> Test thread might not be entered following code (stopSignal.await()). We might see deferent call stack between GetAllStackTraces() and GetThreadListStackTraces(). We cannot control to freeze call stack of test thread in Java code. >>>>> (I didn't use SuspendThread() at first, but I saw some errors which causes in above.) >>>>> >>>>> So we need to call SuspendThread() to ensure we can see same call stack. >>>> >>>> If you are checking that the thread is in state WAITING then it cannot escape from that state and you can sample the stack multiple times from any API and get the same result. >>>> >>>> I suspect the errors you saw were from the apparent incorrect use of the CountDownLatch. >>> >>> With the flow outlined above, the worker thread should be >>> nicely blocked in stopSignal.await() when stuff is sampled. >>> >>> Dan >>> >>> >>>> >>>> Cheers, >>>> David >>>> ----- >>>> >>>>> >>>>> Thanks, >>>>> >>>>> Yasumasa >>>>> >>>>> >>>>>> Dan >>>>>> >>>>>>> >>>>>>> On 2020/07/02 15:05, David Holmes wrote: >>>>>>>> Hi Yasumasa, >>>>>>>> >>>>>>>> On 1/07/2020 11:53 am, Yasumasa Suenaga wrote: >>>>>>>>> Hi, >>>>>>>>> >>>>>>>>> I uploaded new webrev. Could review again? >>>>>>>>> >>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.02/ >>>>>>>> >>>>>>>> Updates look fine - thanks. >>>>>>>> >>>>>>>> One minor nit: >>>>>>>> >>>>>>>> 1274???? _collector.allocate_and_fill_stacks(1); >>>>>>>> 1275???? _collector.set_result(JVMTI_ERROR_NONE); >>>>>>>> >>>>>>>> In the other places where you use _collector you rely on result being initialized to JVMTI_ERROR_NONE, rather than setting it directly after allocate_and_fill_stacks(). >>>>>>> >>>>>>> Fixed. >>>>>>> >>>>>>> >>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>> >>>>>>>>>>>>>> ? 820 assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>> ? 821 java_thread->is_thread_fully_suspended(false, &debug_bits) || >>>>>>>>>>>>>> ? 822????????? current_thread == java_thread->active_handshaker(), >>>>>>>>>>>>>> ? 823????????? "at safepoint / handshake or target thread is suspended"); >>>>>>>>>>>>>> >>>>>>>>>>>>>> I don't think the suspension check is necessary, as even if the target is suspended we must still be at a safepoint or in a handshake with it. Makes me wonder if we used to allow a racy stacktrace operation on a suspended thread, assuming it would remain suspended? >>>>>>>>> >>>>>>>>> This function (JvmtiEnvBase::get_stack_trace()) can be called to get own stack trace. For example, we can call GetStackTrace() for current thread at JVMTI event. >>>>>>>>> So I changed assert as below: >>>>>>>>> >>>>>>>>> ``` >>>>>>>>> ??820?? assert(current_thread == java_thread || >>>>>>>>> ??821????????? SafepointSynchronize::is_at_safepoint() || >>>>>>>>> ??822????????? current_thread == java_thread->active_handshaker(), >>>>>>>>> ??823????????? "call by myself / at safepoint / at handshake"); >>>>>>>>> ``` >>>>>>>> >>>>>>>> Yep good catch. I hope current tests caught that. >>>>>>> >>>>>>> They would be tested in vmTestbase/nsk/jvmti/GetStackTrace/getstacktr001/ (own call stacks), and getstacktr003 (call stacks in other thread). >>>>>>> >>>>>>> >>>>>>>> Speaking of tests ... >>>>>>>> >>>>>>>> In the native code I think you need to check the success of all JNI methods that can throw exceptions - otherwise I believe the tests may trigger warnings if -Xcheck:jni is used with them. See for example: >>>>>>>> >>>>>>>> test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/libHeapMonitorTest.cpp >>>>>>> >>>>>>> I updated testcases to check JNI and JVMTI function calls. >>>>>>> >>>>>>> >>>>>>>> In the Java code the target thread: >>>>>>>> >>>>>>>> ?? 45???? public void run() { >>>>>>>> ?? 46?????? try { >>>>>>>> ?? 47?????????? synchronized (lock) { >>>>>>>> ?? 48?????????????? lock.wait(); >>>>>>>> ?? 49?????????????? System.out.println("OK"); >>>>>>>> ?? 50?????????? } >>>>>>>> >>>>>>>> is potentially susceptible to spurious wakeups. Using a CountDownLatch would be robust. >>>>>>> >>>>>>> Fixed. >>>>>>> >>>>>>> >>>>>>> Thanks, >>>>>>> >>>>>>> Yasumasa >>>>>>> >>>>>>> >>>>>>>> Thanks, >>>>>>>> David >>>>>>>> ----- >>>>>>>> >>>>>>>>> >>>>>>>>> Thanks, >>>>>>>>> >>>>>>>>> Yasumasa >>>>>>>>> >>>>>>>>> >>>>>>>>> On 2020/07/01 8:48, David Holmes wrote: >>>>>>>>>> Hi Yasumasa, >>>>>>>>>> >>>>>>>>>> On 1/07/2020 9:05 am, Yasumasa Suenaga wrote: >>>>>>>>>>> Hi David, >>>>>>>>>>> >>>>>>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>>>>>> >>>>>>>>>>>>>> IIUC at this point the _calling_thread is the current thread, so we can use: >>>>>>>>>>>>>> >>>>>>>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>>>>>> >>>>>>>>>>> If so, we can call make_local() in L1272 without JavaThread (or we can pass current thread to make_local()). Is it right? >>>>>>>>>>> >>>>>>>>>>> ``` >>>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>>> 1272 _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, thread_oop), >>>>>>>>>>> 1273??????????????????????????? jt, thread_oop); >>>>>>>>>>> ``` >>>>>>>>>> >>>>>>>>>> Sorry I got confused, _calling_thread may not be the current thread as we could be executing the handshake in the target thread itself. So the ResourceMark is correct as-is (implicitly for current thread). >>>>>>>>>> >>>>>>>>>> The argument to fill_frames will be used in the jvmtiStackInfo and passed back to the _calling_thread, so it must be created via make_local(_calling_thread, ...) as you presently have. >>>>>>>>>> >>>>>>>>>> Thanks, >>>>>>>>>> David >>>>>>>>>> >>>>>>>>>>> Thanks, >>>>>>>>>>> >>>>>>>>>>> Yasumasa >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> On 2020/07/01 7:05, David Holmes wrote: >>>>>>>>>>>> On 1/07/2020 12:17 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>> Hi David, >>>>>>>>>>>>> >>>>>>>>>>>>> Thank you for reviewing! I will update new webrev tomorrow. >>>>>>>>>>>>> >>>>>>>>>>>>>> 466 class MultipleStackTracesCollector : public StackObj { >>>>>>>>>>>>>> >>>>>>>>>>>>>> ? 498 class VM_GetAllStackTraces : public VM_Operation { >>>>>>>>>>>>>> ? 499 private: >>>>>>>>>>>>>> ? 500?? JavaThread *_calling_thread; >>>>>>>>>>>>>> ? 501?? jint _final_thread_count; >>>>>>>>>>>>>> ? 502?? MultipleStackTracesCollector _collector; >>>>>>>>>>>>>> >>>>>>>>>>>>>> You can't have a StackObj as a member of another class like that as it may not be on the stack. I think MultipleStackTracesCollector should not extend any allocation class, and should always be embedded directly in another class. >>>>>>>>>>>>> >>>>>>>>>>>>> I'm not sure what does mean "embedded". >>>>>>>>>>>>> Is it ok as below? >>>>>>>>>>>>> >>>>>>>>>>>>> ``` >>>>>>>>>>>>> class MultipleStackTracesCollector { >>>>>>>>>>>>> ??? : >>>>>>>>>>>>> } >>>>>>>>>>>>> >>>>>>>>>>>>> class GetAllStackTraces : public VM_Operation { >>>>>>>>>>>>> ?? private: >>>>>>>>>>>>> ???? MultipleStackTracesCollector _collector; >>>>>>>>>>>>> } >>>>>>>>>>>>> ``` >>>>>>>>>>>> >>>>>>>>>>>> Yes that I what I meant. >>>>>>>>>>>> >>>>>>>>>>>> Thanks, >>>>>>>>>>>> David >>>>>>>>>>>> ----- >>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> Thanks, >>>>>>>>>>>>> >>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> On 2020/06/30 22:22, David Holmes wrote: >>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>> >>>>>>>>>>>>>> On 30/06/2020 10:05 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>> Hi David, Serguei, >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> I updated webrev for 8242428. Could you review again? >>>>>>>>>>>>>>> This change migrate to use direct handshake for GetStackTrace() and GetThreadListStackTraces() (when thread_count == 1). >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.01/ >>>>>>>>>>>>>> >>>>>>>>>>>>>> This looks really good now! I only have a few nits below. There is one thing I don't like about it but it requires a change to the main Handshake logic to address - in JvmtiEnv::GetThreadListStackTraces you have to create a ThreadsListHandle to convert the jthread to a JavaThread, but then the Handshake::execute_direct creates another ThreadsListHandle internally. That's a waste. I will discuss with Robbin and file a RFE to have an overload of execute_direct that takes an existing TLH. Actually it's worse than that because we have another TLH in use at the entry point for the JVMTI functions, so I think there may be some scope for simplifying the use of TLH instances - future RFE. >>>>>>>>>>>>>> >>>>>>>>>>>>>> --- >>>>>>>>>>>>>> >>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>>>>>>>>>> >>>>>>>>>>>>>> ??451?? GetStackTraceClosure(JvmtiEnv *env, jint start_depth, jint max_count, >>>>>>>>>>>>>> ??452??????????????????????? jvmtiFrameInfo* frame_buffer, jint* count_ptr) >>>>>>>>>>>>>> ??453???? : HandshakeClosure("GetStackTrace"), >>>>>>>>>>>>>> ??454?????? _env(env), _start_depth(start_depth), _max_count(max_count), >>>>>>>>>>>>>> ??455?????? _frame_buffer(frame_buffer), _count_ptr(count_ptr), >>>>>>>>>>>>>> ??456 _result(JVMTI_ERROR_THREAD_NOT_ALIVE) { >>>>>>>>>>>>>> >>>>>>>>>>>>>> Nit: can you do one initializer per line please. >>>>>>>>>>>>>> >>>>>>>>>>>>>> This looks wrong: >>>>>>>>>>>>>> >>>>>>>>>>>>>> 466 class MultipleStackTracesCollector : public StackObj { >>>>>>>>>>>>>> >>>>>>>>>>>>>> ??498 class VM_GetAllStackTraces : public VM_Operation { >>>>>>>>>>>>>> ??499 private: >>>>>>>>>>>>>> ??500?? JavaThread *_calling_thread; >>>>>>>>>>>>>> ??501?? jint _final_thread_count; >>>>>>>>>>>>>> ??502?? MultipleStackTracesCollector _collector; >>>>>>>>>>>>>> >>>>>>>>>>>>>> You can't have a StackObj as a member of another class like that as it may not be on the stack. I think MultipleStackTracesCollector should not extend any allocation class, and should always be embedded directly in another class. >>>>>>>>>>>>>> >>>>>>>>>>>>>> 481?? MultipleStackTracesCollector(JvmtiEnv *env, jint max_frame_count) { >>>>>>>>>>>>>> ??482???? _env = env; >>>>>>>>>>>>>> ??483???? _max_frame_count = max_frame_count; >>>>>>>>>>>>>> ??484???? _frame_count_total = 0; >>>>>>>>>>>>>> ??485???? _head = NULL; >>>>>>>>>>>>>> ??486???? _stack_info = NULL; >>>>>>>>>>>>>> ??487???? _result = JVMTI_ERROR_NONE; >>>>>>>>>>>>>> ??488?? } >>>>>>>>>>>>>> >>>>>>>>>>>>>> As you are touching this can you change it to use an initializer list as you did for the HandshakeClosure, and please keep one item per line. >>>>>>>>>>>>>> >>>>>>>>>>>>>> --- >>>>>>>>>>>>>> >>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>> >>>>>>>>>>>>>> ??820 assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>> ??821 java_thread->is_thread_fully_suspended(false, &debug_bits) || >>>>>>>>>>>>>> ??822????????? current_thread == java_thread->active_handshaker(), >>>>>>>>>>>>>> ??823????????? "at safepoint / handshake or target thread is suspended"); >>>>>>>>>>>>>> >>>>>>>>>>>>>> I don't think the suspension check is necessary, as even if the target is suspended we must still be at a safepoint or in a handshake with it. Makes me wonder if we used to allow a racy stacktrace operation on a suspended thread, assuming it would remain suspended? >>>>>>>>>>>>>> >>>>>>>>>>>>>> 1268?? oop thread_oop = jt->threadObj(); >>>>>>>>>>>>>> 1269 >>>>>>>>>>>>>> 1270?? if (!jt->is_exiting() && (jt->threadObj() != NULL)) { >>>>>>>>>>>>>> >>>>>>>>>>>>>> You can use thread_oop in line 1270. >>>>>>>>>>>>>> >>>>>>>>>>>>>> 1272 _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, thread_oop), >>>>>>>>>>>>>> 1273??????????????????????????? jt, thread_oop); >>>>>>>>>>>>>> >>>>>>>>>>>>>> It is frustrating that this entire call chain started with a jthread reference, which we converted to a JavaThread, only to eventually need to convert it back to a jthread! I think there is some scope for simplification here but not as part of this change. >>>>>>>>>>>>>> >>>>>>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>>>>>> >>>>>>>>>>>>>> IIUC at this point the _calling_thread is the current thread, so we can use: >>>>>>>>>>>>>> >>>>>>>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>>>>>>>>> >>>>>>>>>>>>>> --- >>>>>>>>>>>>>> >>>>>>>>>>>>>> Please add @bug lines to the tests. >>>>>>>>>>>>>> >>>>>>>>>>>>>> I'm still pondering the test logic but wanted to send this now. >>>>>>>>>>>>>> >>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>> David >>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>> VM_GetThreadListStackTrace (for GetThreadListStackTraces) and VM_GetAllStackTraces (for GetAllStackTraces) have inherited VM_GetMultipleStackTraces VM operation which provides the feature to generate jvmtiStackInfo. I modified VM_GetMultipleStackTraces to a normal C++ class to share with HandshakeClosure for GetThreadListStackTraces (GetSingleStackTraceClosure). >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Also I added new testcases which test GetThreadListStackTraces() with thread_count == 1 and with all threads. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> This change has been tested in serviceability/jvmti serviceability/jdwp vmTestbase/nsk/jvmti vmTestbase/nsk/jdi vmTestbase/nsk/jdwp. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> On 2020/06/24 15:50, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>> Hi all, >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Please review this change: >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> ?? JBS: https://bugs.openjdk.java.net/browse/JDK-8242428 >>>>>>>>>>>>>>>> ?? webrev: http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.00/ >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> This change replace following VM operations to direct handshake. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> ??- VM_GetFrameCount (GetFrameCount()) >>>>>>>>>>>>>>>> ??- VM_GetFrameLocation (GetFrameLocation()) >>>>>>>>>>>>>>>> ??- VM_GetThreadListStackTraces (GetThreadListStackTrace()) >>>>>>>>>>>>>>>> ??- VM_GetCurrentLocation >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> GetThreadListStackTrace() uses direct handshake if thread count == 1. In other case (thread count > 1), it would be performed as VM operation (VM_GetThreadListStackTraces). >>>>>>>>>>>>>>>> Caller of VM_GetCurrentLocation (JvmtiEnvThreadState::reset_current_location()) might be called at safepoint. So I added safepoint check in its caller. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> This change has been tested in serviceability/jvmti serviceability/jdwp vmTestbase/nsk/jvmti vmTestbase/nsk/jdi vmTestbase/ns >>>>>>>>>>>>>>>> k/jdwp. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Also I tested it on submit repo, then it has execution error (mach5-one-ysuenaga-JDK-8242428-20200624-0054-12034717) due to dependency error. So I think it does not occur by this change. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Yasumasa >>>>>> >>> From serguei.spitsyn at oracle.com Fri Jul 3 07:45:40 2020 From: serguei.spitsyn at oracle.com (serguei.spitsyn at oracle.com) Date: Fri, 3 Jul 2020 00:45:40 -0700 Subject: RFR: 8242428: JVMTI thread operations should use Thread-Local Handshake In-Reply-To: References: <6c263e4c-0a83-be7a-0288-ecb2de0b7cea@oss.nttdata.com> <2ea2f5d8-5c43-a7d3-d525-cd44c4009d25@oss.nttdata.com> <65889ab4-6b7e-86fb-59cc-012520b83138@oracle.com> <4b7df6f8-c8f7-fedf-6366-b885d2235b58@oss.nttdata.com> <74c05dfd-ffb2-b73d-66e5-dc98752729f5@oss.nttdata.com> <763793b1-9506-44c6-0681-1c71c44a44fd@oss.nttdata.com> <5107c478-1de2-7a49-ee71-dfad6a99a667@oracle.com> <90cdfef9-e558-0d25-33f5-25b7d65bb83b@oss.nttdata.com> <0e359819-618f-c17b-a427-bb7e4daa2c58@oracle.com> <3f890bed-6892-e64d-b21b-ca0cbe11784e@oracle.com> <7dc1903b-6295-3864-6301-4c02aacdb971@oss.nttdata.com> <04e09eb7-9483-8f63-4bb4-01c9e814802e@oracle.com> Message-ID: <238a89a3-06b1-90e4-d5a4-8dc2f1ed12ab@oracle.com> An HTML attachment was scrubbed... URL: From suenaga at oss.nttdata.com Fri Jul 3 08:16:22 2020 From: suenaga at oss.nttdata.com (Yasumasa Suenaga) Date: Fri, 3 Jul 2020 17:16:22 +0900 Subject: RFR: 8242428: JVMTI thread operations should use Thread-Local Handshake In-Reply-To: <238a89a3-06b1-90e4-d5a4-8dc2f1ed12ab@oracle.com> References: <6c263e4c-0a83-be7a-0288-ecb2de0b7cea@oss.nttdata.com> <2ea2f5d8-5c43-a7d3-d525-cd44c4009d25@oss.nttdata.com> <65889ab4-6b7e-86fb-59cc-012520b83138@oracle.com> <4b7df6f8-c8f7-fedf-6366-b885d2235b58@oss.nttdata.com> <74c05dfd-ffb2-b73d-66e5-dc98752729f5@oss.nttdata.com> <763793b1-9506-44c6-0681-1c71c44a44fd@oss.nttdata.com> <5107c478-1de2-7a49-ee71-dfad6a99a667@oracle.com> <90cdfef9-e558-0d25-33f5-25b7d65bb83b@oss.nttdata.com> <0e359819-618f-c17b-a427-bb7e4daa2c58@oracle.com> <3f890bed-6892-e64d-b21b-ca0cbe11784e@oracle.com> <7dc1903b-6295-3864-6301-4c02aacdb971@oss.nttdata.com> <04e09eb7-9483-8f63-4bb4-01c9e814802e@oracle.com> <238a89a3-06b1-90e4-d5a4-8dc2f1ed12ab@oracle.com> Message-ID: Hi Serguei, Generally I agree with you, but I have concern about the difference of the result of GetStackTrace() and GetThreadListStackTraces(). GetStackTrace: jvmtiFrameInfo GetThreadListStackTraces: jvmtiStackInfo jvmtiStackInfo contains thread state, and it is ensured it is the state of the call stack. If we want to get both call stack and thread state, we need to suspend target thread, and call both GetStackTrace() and GetThreadState(). Is it ok? I was wondering if JDK-8201641 (parent ticket of this change) needed them for profiling (dynatrace?) If it is responsibility of JVMTI agent implementor, I remove this closure. Thanks, Yasumasa On 2020/07/03 16:45, serguei.spitsyn at oracle.com wrote: > Hi Yasumasa, > > After some thinking I've concluded that I do not like this optimization > of the GetThreadListStackTraces with GetSingleStackTraceClosure. > > We may need more opinions on this but these are my points: > ?- it adds some complexity and ugliness > ?- a win is doubtful because it has to be a rare case, so that total overhead should not be high > ?- if it is really high for some use cases then it is up to the user > ?? to optimize it with using GetStackTrace instead > > In such cases with doubtful overhead I usually prefer the simplicity. > > Good examples where it makes sense to optimize are checks for target thread to be current thread. > In such cases there is no need to suspend the target thread, or use a VMop/HandshakeClosure. > For instance, please, see the Monitor functions with the check: (java_thread == calling_thread). > Getting information for current thread is frequently used case, e.g. to get info at an event point. > > Thanks, > Serguei > > > On 7/2/20 23:29, Yasumasa Suenaga wrote: >> Hi Dan, David, >> >> I uploaded new webrev. Could you review again? >> >> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/ >> >> OneGetThreadListStackTraces.java in this webrev would wait until thread state is transited to "waiting" with spin wait. >> CountDownLatch::await call as Dan pointed is fixed in it :) >> >> Diff from webrev.03: >> http://hg.openjdk.java.net/jdk/submit/rev/c9aeb7001e50 >> >> >> Thanks, >> >> Yasumasa >> >> >> On 2020/07/03 14:15, David Holmes wrote: >>> >>> >>> On 3/07/2020 2:27 pm, Yasumasa Suenaga wrote: >>>> On 2020/07/03 12:24, Daniel D. Daugherty wrote: >>>>> On 7/2/20 10:50 PM, David Holmes wrote: >>>>>> Sorry I'm responding here without seeing latest webrev but there is enough context I think ... >>>>>> >>>>>> On 3/07/2020 9:14 am, Yasumasa Suenaga wrote: >>>>>>> Hi Dan, >>>>>>> >>>>>>> Thanks for your comment! >>>>>>> >>>>>>> On 2020/07/03 7:16, Daniel D. Daugherty wrote: >>>>>>>> On 7/2/20 5:19 AM, Yasumasa Suenaga wrote: >>>>>>>>> Hi David, >>>>>>>>> >>>>>>>>> I upload new webrev. Could you review again? >>>>>>>>> >>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.03/ >>>>>>>> >>>>>>>> src/hotspot/share/prims/jvmtiEnv.cpp >>>>>>>> ???? L1542: ??? // Get stack trace with handshake >>>>>>>> ???????? nit - please add a period at the end. >>>>>>> >>>>>>> I will fix it. >>>>>>> >>>>>>> >>>>>>>> ???? L1591: ??? *stack_info_ptr = op.stack_info(); >>>>>>>> ???????? The return parameter should not be touched unless the return >>>>>>>> ???????? code in 'err' == JVMTI_ERROR_NONE. >>>>>>>> >>>>>>>> ???? old L1582: ? if (err == JVMTI_ERROR_NONE) { >>>>>>>> ???????? Please restore this check. The return parameter should not >>>>>>>> ???????? be touched unless the return code in 'err' == JVMTI_ERROR_NONE. >>>>>>> >>>>>>> I will fix it. >>>>>> >>>>>> But op.stack_info() will return NULL if the error is not JVMTI_ERROR_NONE. Are you (Dan) concerned about someone passing in a non-null/initialized out-pointer that will be reset to NULL if there was an error? >>>>> >>>>> Actually the way we used to test this in POSIX tests is to call >>>>> an API with known bad parameters and the return parameter ptr >>>>> set to NULL. If the return parameter ptr was touched when an >>>>> error should have been detected on an earlier parameter, then >>>>> the test failed. >>>>> >>>>> >>>>>> >>>>>>> >>>>>>>> ???? L1272: ? if (!jt->is_exiting() && (thread_oop != NULL)) { >>>>>>>> ???????? nit - extra parens around the second expression. >>>>>>> >>>>>>> I will fix it. >>>>>>> >>>>>>> >>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>> ???? old L1532: ? _result = JVMTI_ERROR_THREAD_NOT_ALIVE; >>>>>>>> ???????? This deletion of the _result field threw me for a minute and then >>>>>>>> ???? ? ? I figured out that the field is init to JVMTI_ERROR_THREAD_NOT_ALIVE >>>>>>>> ???????? in the constructor. >>>>>>>> >>>>>>>> ???? L1553: ? if (!jt->is_exiting() && (jt->threadObj() != NULL)) { >>>>>>>> ???????? nit - extra parens around the second expression. >>>>>>> >>>>>>> I will fix it. >>>>>>> >>>>>>> >>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>>>> ???? No comments. >>>>>>>> >>>>>>>> src/hotspot/share/runtime/vmOperations.hpp >>>>>>>> ???? No comments. >>>>>>>> >>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/GetThreadListStackTraces.java >>>>>>>> ???? No comments. >>>>>>>> >>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/OneGetThreadListStackTraces.java >>>>>>>> ???? L64: ??????? startSignal.countDown(); >>>>>>>> ???????? I was expecting this to be a call to await() instead of >>>>>>>> ???????? countDown(). What am I missing here? >>>>>>>> >>>>>>>> ???????? I think this test might be passing by accident right now, but... >>>>>>> >>>>>>> Main thread (which call JVMTI functions to test) should wait until test thread is ready. >>>>>>> So main thread would wait startSignal, and test thread would count down. >>>>>> >>>>>> No! >>>>>> >>>>>> The test thread that previously called obj.wait() now calls latch.await(). >>>>>> >>>>>> The main thread that previously called obj.notify() now calls latch.countDown(). >>>>>> >>>>>> The main thread continues to spin until it sees the target is WAITING before proceeding with the test. >>>> >>>> If I add spin wait to wait until transit target thread state is WAITING (as following), we don't need to call SuspendThread(). >>>> Which is better? >>> >>> The original spin-wait loop checking for? WAITING is better because it is the only guarantee that the target thread is blocked where you need it to be. suspending the thread is racy as you don't know exactly where the suspend will hit. >>> >>> Thanks, >>> David >>> ----- >>> >>>> >>>> ``` >>>> /* Wait until the thread state transits to "waiting" */ >>>> while (th.getState() != Thread.State.WAITING) { >>>> ???? Thread.onSpinWait(); >>>> } >>>> ``` >>>> >>>> For simplify, spin wait is prefer to OneGetThreadListStackTraces.java in webrev.03. >>>> >>>> >>>> Thanks, >>>> >>>> Yasumasa >>>> >>>> >>>>> Here's the flow as I see it: >>>>> >>>>> main thread >>>>> ?? - start worker thread >>>>> ?? - startSignal.await() >>>>> ???? - main is now blocked >>>>> >>>>> worker thread >>>>> ?? - startSignal.countDown() >>>>> ???? - main is now unblocked >>>>> ?? - stopSignal.await() >>>>> ???? - worker is now blocked >>>>> >>>>> main thread >>>>> ?? - checkCallStacks(th) >>>>> ?? - stopSignal.countDown() >>>>> ???? - worker is now unblocked >>>>> ?? - th.join >>>>> ???? - main is now blocked >>>>> >>>>> worker thread >>>>> ?? - runs off the end of run() >>>>> ???? - main is now unblocked >>>>> >>>>> main thread >>>>> ?? - run off the end of main() >>>>> >>>>> >>>>>> >>>>>>> >>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libGetThreadListStackTraces.c >>>>>>>> ???? L92: ? jthreads = (jthread *)malloc(sizeof(jthread) * num_threads); >>>>>>>> ???????? You don't check for malloc() failure. >>>>>>>> ???????? 'jthreads' is allocated but never freed. >>>>>>> >>>>>>> I will fix it. >>>>>>> >>>>>>> >>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.c >>>>>>>> ???? L91: ? result = (*jvmti)->SuspendThread(jvmti, thread); >>>>>>>> ???????? Why are you suspending the thread? GetAllStackTraces() and >>>>>>>> ???????? GetThreadListStackTraces() do not require the target thread(s) >>>>>>>> ???????? to be suspend. >>>>>>>> >>>>>>>> ???????? If you decide not to SuspendThread, then you don't need the >>>>>>>> ???????? AddCapabilities or the ResumeThread calls. >>>>>>> >>>>>>> Test thread might not be entered following code (stopSignal.await()). We might see deferent call stack between GetAllStackTraces() and GetThreadListStackTraces(). We cannot control to freeze call stack of test thread in Java code. >>>>>>> (I didn't use SuspendThread() at first, but I saw some errors which causes in above.) >>>>>>> >>>>>>> So we need to call SuspendThread() to ensure we can see same call stack. >>>>>> >>>>>> If you are checking that the thread is in state WAITING then it cannot escape from that state and you can sample the stack multiple times from any API and get the same result. >>>>>> >>>>>> I suspect the errors you saw were from the apparent incorrect use of the CountDownLatch. >>>>> >>>>> With the flow outlined above, the worker thread should be >>>>> nicely blocked in stopSignal.await() when stuff is sampled. >>>>> >>>>> Dan >>>>> >>>>> >>>>>> >>>>>> Cheers, >>>>>> David >>>>>> ----- >>>>>> >>>>>>> >>>>>>> Thanks, >>>>>>> >>>>>>> Yasumasa >>>>>>> >>>>>>> >>>>>>>> Dan >>>>>>>> >>>>>>>>> >>>>>>>>> On 2020/07/02 15:05, David Holmes wrote: >>>>>>>>>> Hi Yasumasa, >>>>>>>>>> >>>>>>>>>> On 1/07/2020 11:53 am, Yasumasa Suenaga wrote: >>>>>>>>>>> Hi, >>>>>>>>>>> >>>>>>>>>>> I uploaded new webrev. Could review again? >>>>>>>>>>> >>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.02/ >>>>>>>>>> >>>>>>>>>> Updates look fine - thanks. >>>>>>>>>> >>>>>>>>>> One minor nit: >>>>>>>>>> >>>>>>>>>> 1274???? _collector.allocate_and_fill_stacks(1); >>>>>>>>>> 1275???? _collector.set_result(JVMTI_ERROR_NONE); >>>>>>>>>> >>>>>>>>>> In the other places where you use _collector you rely on result being initialized to JVMTI_ERROR_NONE, rather than setting it directly after allocate_and_fill_stacks(). >>>>>>>>> >>>>>>>>> Fixed. >>>>>>>>> >>>>>>>>> >>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> ? 820 assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>>>> ? 821 java_thread->is_thread_fully_suspended(false, &debug_bits) || >>>>>>>>>>>>>>>> ? 822????????? current_thread == java_thread->active_handshaker(), >>>>>>>>>>>>>>>> ? 823????????? "at safepoint / handshake or target thread is suspended"); >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> I don't think the suspension check is necessary, as even if the target is suspended we must still be at a safepoint or in a handshake with it. Makes me wonder if we used to allow a racy stacktrace operation on a suspended thread, assuming it would remain suspended? >>>>>>>>>>> >>>>>>>>>>> This function (JvmtiEnvBase::get_stack_trace()) can be called to get own stack trace. For example, we can call GetStackTrace() for current thread at JVMTI event. >>>>>>>>>>> So I changed assert as below: >>>>>>>>>>> >>>>>>>>>>> ``` >>>>>>>>>>> ??820?? assert(current_thread == java_thread || >>>>>>>>>>> ??821 SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>> ??822????????? current_thread == java_thread->active_handshaker(), >>>>>>>>>>> ??823????????? "call by myself / at safepoint / at handshake"); >>>>>>>>>>> ``` >>>>>>>>>> >>>>>>>>>> Yep good catch. I hope current tests caught that. >>>>>>>>> >>>>>>>>> They would be tested in vmTestbase/nsk/jvmti/GetStackTrace/getstacktr001/ (own call stacks), and getstacktr003 (call stacks in other thread). >>>>>>>>> >>>>>>>>> >>>>>>>>>> Speaking of tests ... >>>>>>>>>> >>>>>>>>>> In the native code I think you need to check the success of all JNI methods that can throw exceptions - otherwise I believe the tests may trigger warnings if -Xcheck:jni is used with them. See for example: >>>>>>>>>> >>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/libHeapMonitorTest.cpp >>>>>>>>> >>>>>>>>> I updated testcases to check JNI and JVMTI function calls. >>>>>>>>> >>>>>>>>> >>>>>>>>>> In the Java code the target thread: >>>>>>>>>> >>>>>>>>>> ?? 45???? public void run() { >>>>>>>>>> ?? 46?????? try { >>>>>>>>>> ?? 47?????????? synchronized (lock) { >>>>>>>>>> ?? 48?????????????? lock.wait(); >>>>>>>>>> ?? 49?????????????? System.out.println("OK"); >>>>>>>>>> ?? 50?????????? } >>>>>>>>>> >>>>>>>>>> is potentially susceptible to spurious wakeups. Using a CountDownLatch would be robust. >>>>>>>>> >>>>>>>>> Fixed. >>>>>>>>> >>>>>>>>> >>>>>>>>> Thanks, >>>>>>>>> >>>>>>>>> Yasumasa >>>>>>>>> >>>>>>>>> >>>>>>>>>> Thanks, >>>>>>>>>> David >>>>>>>>>> ----- >>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> Thanks, >>>>>>>>>>> >>>>>>>>>>> Yasumasa >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> On 2020/07/01 8:48, David Holmes wrote: >>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>> >>>>>>>>>>>> On 1/07/2020 9:05 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>> Hi David, >>>>>>>>>>>>> >>>>>>>>>>>>>>>> 1271 ResourceMark rm; >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> IIUC at this point the _calling_thread is the current thread, so we can use: >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>>>>>>>> >>>>>>>>>>>>> If so, we can call make_local() in L1272 without JavaThread (or we can pass current thread to make_local()). Is it right? >>>>>>>>>>>>> >>>>>>>>>>>>> ``` >>>>>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>>>>> 1272 _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, thread_oop), >>>>>>>>>>>>> 1273??????????????????????????? jt, thread_oop); >>>>>>>>>>>>> ``` >>>>>>>>>>>> >>>>>>>>>>>> Sorry I got confused, _calling_thread may not be the current thread as we could be executing the handshake in the target thread itself. So the ResourceMark is correct as-is (implicitly for current thread). >>>>>>>>>>>> >>>>>>>>>>>> The argument to fill_frames will be used in the jvmtiStackInfo and passed back to the _calling_thread, so it must be created via make_local(_calling_thread, ...) as you presently have. >>>>>>>>>>>> >>>>>>>>>>>> Thanks, >>>>>>>>>>>> David >>>>>>>>>>>> >>>>>>>>>>>>> Thanks, >>>>>>>>>>>>> >>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> On 2020/07/01 7:05, David Holmes wrote: >>>>>>>>>>>>>> On 1/07/2020 12:17 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Thank you for reviewing! I will update new webrev tomorrow. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> 466 class MultipleStackTracesCollector : public StackObj { >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> ? 498 class VM_GetAllStackTraces : public VM_Operation { >>>>>>>>>>>>>>>> ? 499 private: >>>>>>>>>>>>>>>> ? 500?? JavaThread *_calling_thread; >>>>>>>>>>>>>>>> ? 501?? jint _final_thread_count; >>>>>>>>>>>>>>>> ? 502?? MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> You can't have a StackObj as a member of another class like that as it may not be on the stack. I think MultipleStackTracesCollector should not extend any allocation class, and should always be embedded directly in another class. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> I'm not sure what does mean "embedded". >>>>>>>>>>>>>>> Is it ok as below? >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>> class MultipleStackTracesCollector { >>>>>>>>>>>>>>> ??? : >>>>>>>>>>>>>>> } >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> class GetAllStackTraces : public VM_Operation { >>>>>>>>>>>>>>> ?? private: >>>>>>>>>>>>>>> ???? MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>> } >>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>> >>>>>>>>>>>>>> Yes that I what I meant. >>>>>>>>>>>>>> >>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>> David >>>>>>>>>>>>>> ----- >>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> On 2020/06/30 22:22, David Holmes wrote: >>>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> On 30/06/2020 10:05 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>> Hi David, Serguei, >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> I updated webrev for 8242428. Could you review again? >>>>>>>>>>>>>>>>> This change migrate to use direct handshake for GetStackTrace() and GetThreadListStackTraces() (when thread_count == 1). >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.01/ >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> This looks really good now! I only have a few nits below. There is one thing I don't like about it but it requires a change to the main Handshake logic to address - in JvmtiEnv::GetThreadListStackTraces you have to create a ThreadsListHandle to convert the jthread to a JavaThread, but then the Handshake::execute_direct creates another ThreadsListHandle internally. That's a waste. I will discuss with Robbin and file a RFE to have an overload of execute_direct that takes an existing TLH. Actually it's worse than that because we have another TLH in use at the entry point for the JVMTI functions, so I think there may be some scope for simplifying the use of TLH instances - future RFE. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> ??451?? GetStackTraceClosure(JvmtiEnv *env, jint start_depth, jint max_count, >>>>>>>>>>>>>>>> ??452 jvmtiFrameInfo* frame_buffer, jint* count_ptr) >>>>>>>>>>>>>>>> ??453???? : HandshakeClosure("GetStackTrace"), >>>>>>>>>>>>>>>> ??454?????? _env(env), _start_depth(start_depth), _max_count(max_count), >>>>>>>>>>>>>>>> ??455 _frame_buffer(frame_buffer), _count_ptr(count_ptr), >>>>>>>>>>>>>>>> ??456 _result(JVMTI_ERROR_THREAD_NOT_ALIVE) { >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Nit: can you do one initializer per line please. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> This looks wrong: >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> 466 class MultipleStackTracesCollector : public StackObj { >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> ??498 class VM_GetAllStackTraces : public VM_Operation { >>>>>>>>>>>>>>>> ??499 private: >>>>>>>>>>>>>>>> ??500?? JavaThread *_calling_thread; >>>>>>>>>>>>>>>> ??501?? jint _final_thread_count; >>>>>>>>>>>>>>>> ??502?? MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> You can't have a StackObj as a member of another class like that as it may not be on the stack. I think MultipleStackTracesCollector should not extend any allocation class, and should always be embedded directly in another class. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> 481 MultipleStackTracesCollector(JvmtiEnv *env, jint max_frame_count) { >>>>>>>>>>>>>>>> ??482???? _env = env; >>>>>>>>>>>>>>>> ??483???? _max_frame_count = max_frame_count; >>>>>>>>>>>>>>>> ??484???? _frame_count_total = 0; >>>>>>>>>>>>>>>> ??485???? _head = NULL; >>>>>>>>>>>>>>>> ??486???? _stack_info = NULL; >>>>>>>>>>>>>>>> ??487???? _result = JVMTI_ERROR_NONE; >>>>>>>>>>>>>>>> ??488?? } >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> As you are touching this can you change it to use an initializer list as you did for the HandshakeClosure, and please keep one item per line. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> ??820 assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>>>> ??821 java_thread->is_thread_fully_suspended(false, &debug_bits) || >>>>>>>>>>>>>>>> ??822????????? current_thread == java_thread->active_handshaker(), >>>>>>>>>>>>>>>> ??823????????? "at safepoint / handshake or target thread is suspended"); >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> I don't think the suspension check is necessary, as even if the target is suspended we must still be at a safepoint or in a handshake with it. Makes me wonder if we used to allow a racy stacktrace operation on a suspended thread, assuming it would remain suspended? >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> 1268?? oop thread_oop = jt->threadObj(); >>>>>>>>>>>>>>>> 1269 >>>>>>>>>>>>>>>> 1270?? if (!jt->is_exiting() && (jt->threadObj() != NULL)) { >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> You can use thread_oop in line 1270. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> 1272 _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, thread_oop), >>>>>>>>>>>>>>>> 1273??????????????????????????? jt, thread_oop); >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> It is frustrating that this entire call chain started with a jthread reference, which we converted to a JavaThread, only to eventually need to convert it back to a jthread! I think there is some scope for simplification here but not as part of this change. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> IIUC at this point the _calling_thread is the current thread, so we can use: >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Please add @bug lines to the tests. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> I'm still pondering the test logic but wanted to send this now. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>> VM_GetThreadListStackTrace (for GetThreadListStackTraces) and VM_GetAllStackTraces (for GetAllStackTraces) have inherited VM_GetMultipleStackTraces VM operation which provides the feature to generate jvmtiStackInfo. I modified VM_GetMultipleStackTraces to a normal C++ class to share with HandshakeClosure for GetThreadListStackTraces (GetSingleStackTraceClosure). >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Also I added new testcases which test GetThreadListStackTraces() with thread_count == 1 and with all threads. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> This change has been tested in serviceability/jvmti serviceability/jdwp vmTestbase/nsk/jvmti vmTestbase/nsk/jdi vmTestbase/nsk/jdwp. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> On 2020/06/24 15:50, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>> Hi all, >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Please review this change: >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> ?? JBS: https://bugs.openjdk.java.net/browse/JDK-8242428 >>>>>>>>>>>>>>>>>> ?? webrev: http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.00/ >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> This change replace following VM operations to direct handshake. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> ??- VM_GetFrameCount (GetFrameCount()) >>>>>>>>>>>>>>>>>> ??- VM_GetFrameLocation (GetFrameLocation()) >>>>>>>>>>>>>>>>>> ??- VM_GetThreadListStackTraces (GetThreadListStackTrace()) >>>>>>>>>>>>>>>>>> ??- VM_GetCurrentLocation >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> GetThreadListStackTrace() uses direct handshake if thread count == 1. In other case (thread count > 1), it would be performed as VM operation (VM_GetThreadListStackTraces). >>>>>>>>>>>>>>>>>> Caller of VM_GetCurrentLocation (JvmtiEnvThreadState::reset_current_location()) might be called at safepoint. So I added safepoint check in its caller. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> This change has been tested in serviceability/jvmti serviceability/jdwp vmTestbase/nsk/jvmti vmTestbase/nsk/jdi vmTestbase/ns >>>>>>>>>>>>>>>>>> k/jdwp. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Also I tested it on submit repo, then it has execution error (mach5-one-ysuenaga-JDK-8242428-20200624-0054-12034717) due to dependency error. So I think it does not occur by this change. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>> >>>>> > From vladimir.kozlov at oracle.com Fri Jul 3 18:09:26 2020 From: vladimir.kozlov at oracle.com (Vladimir Kozlov) Date: Fri, 3 Jul 2020 11:09:26 -0700 Subject: [15] RFR(T) 8247527: serviceability/dcmd/gc/HeapDumpCompressedTest.java fails with Graal + ZGC In-Reply-To: <5E33E613-882E-400A-886A-EA4FAD85F2EA@oracle.com> References: <5E33E613-882E-400A-886A-EA4FAD85F2EA@oracle.com> Message-ID: <2bde8004-4ed8-8ca3-b387-05240f423e3f@oracle.com> Thank you, Igor Vladimir K On 7/2/20 7:24 PM, igor.ignatyev at oracle.com wrote: > LGTM > > ? Igor > >> On Jul 2, 2020, at 7:03 PM, Vladimir Kozlov wrote: >> >> ?https://cr.openjdk.java.net/~kvn/8247527/webrev.00/ >> https://bugs.openjdk.java.net/browse/JDK-8247527 >> >> Test should have @requires which excludes running Graal with GC which it does not support. >> >> Testing: hs-tier1,hs-tier4-graal >> >> Thanks, >> Vladimir > From vladimir.kozlov at oracle.com Fri Jul 3 18:30:31 2020 From: vladimir.kozlov at oracle.com (Vladimir Kozlov) Date: Fri, 3 Jul 2020 11:30:31 -0700 Subject: [15] RFR(T) 8247527: serviceability/dcmd/gc/HeapDumpCompressedTest.java fails with Graal + ZGC In-Reply-To: References: Message-ID: Thank you, David, for looking on changes. I will remember to update tests. I filed RFE 8248815 [1] for tracking. Can you approve this fix now? Thanks, Vladimir K [1] https://bugs.openjdk.java.net/browse/JDK-8248815 On 7/2/20 10:09 PM, David Holmes wrote: > Hi Igor, > > On 3/07/2020 12:59 pm, Igor Ignatyev wrote: >> Hi David, >> >> it's in my todo list to improve this situation and have vm.gc.X to take selected JIT into account; and update existing >> (>200) occurrences of 'vm.gc.X & !vm.graal.enabled' > > 200+ ouch! :( > > I guess this fix doesn't make the situation any worse in a practical sense. > > Thanks, > David > ----- > >> -- Igor >> >>> On Jul 2, 2020, at 7:25 PM, David Holmes wrote: >>> >>> Hi Vladimir, >>> >>> On 3/07/2020 12:02 pm, Vladimir Kozlov wrote: >>>> https://cr.openjdk.java.net/~kvn/8247527/webrev.00/ >>>> https://bugs.openjdk.java.net/browse/JDK-8247527 >>>> Test should have @requires which excludes running Graal with GC which it does not support. >>> >>> I find it somewhat disturbing that a generic test has to know about the limitations between GCs and Graal! >>> >>> I would have been more inclined to just exclude this test when running with Graal, even if that theoretically reduced >>> the test coverage in a ting way. >>> >>> If/When Graal supports these other GCs who will remember to re-enable these test cases? >>> >>> Thanks, >>> David >>> >>>> Testing: hs-tier1,hs-tier4-graal >>>> Thanks, >>>> Vladimir >> From serguei.spitsyn at oracle.com Fri Jul 3 19:32:29 2020 From: serguei.spitsyn at oracle.com (serguei.spitsyn at oracle.com) Date: Fri, 3 Jul 2020 12:32:29 -0700 Subject: RFR: 8242428: JVMTI thread operations should use Thread-Local Handshake In-Reply-To: References: <6c263e4c-0a83-be7a-0288-ecb2de0b7cea@oss.nttdata.com> <65889ab4-6b7e-86fb-59cc-012520b83138@oracle.com> <4b7df6f8-c8f7-fedf-6366-b885d2235b58@oss.nttdata.com> <74c05dfd-ffb2-b73d-66e5-dc98752729f5@oss.nttdata.com> <763793b1-9506-44c6-0681-1c71c44a44fd@oss.nttdata.com> <5107c478-1de2-7a49-ee71-dfad6a99a667@oracle.com> <90cdfef9-e558-0d25-33f5-25b7d65bb83b@oss.nttdata.com> <0e359819-618f-c17b-a427-bb7e4daa2c58@oracle.com> <3f890bed-6892-e64d-b21b-ca0cbe11784e@oracle.com> <7dc1903b-6295-3864-6301-4c02aacdb971@oss.nttdata.com> <04e09eb7-9483-8f63-4bb4-01c9e814802e@oracle.com> <238a89a3-06b1-90e4-d5a4-8dc2f1ed12ab@oracle.com> Message-ID: Hi Yasumasa, This difference is not that big to care about. I feel this is really rare case and so, does not worth these complications. Do we have a real request from customers to optimize it? Thanks, Serguei On 7/3/20 01:16, Yasumasa Suenaga wrote: > Hi Serguei, > > Generally I agree with you, but I have concern about the difference of > the result of GetStackTrace() and GetThreadListStackTraces(). > > ? GetStackTrace: jvmtiFrameInfo > ? GetThreadListStackTraces: jvmtiStackInfo > > jvmtiStackInfo contains thread state, and it is ensured it is the > state of the call stack. > If we want to get both call stack and thread state, we need to suspend > target thread, and call both GetStackTrace() and GetThreadState(). Is > it ok? > > I was wondering if JDK-8201641 (parent ticket of this change) needed > them for profiling (dynatrace?) > If it is responsibility of JVMTI agent implementor, I remove this > closure. > > > Thanks, > > Yasumasa > > > On 2020/07/03 16:45, serguei.spitsyn at oracle.com wrote: >> Hi Yasumasa, >> >> After some thinking I've concluded that I do not like this optimization >> of the GetThreadListStackTraces with GetSingleStackTraceClosure. >> >> We may need more opinions on this but these are my points: >> ??- it adds some complexity and ugliness >> ??- a win is doubtful because it has to be a rare case, so that total >> overhead should not be high >> ??- if it is really high for some use cases then it is up to the user >> ??? to optimize it with using GetStackTrace instead >> >> In such cases with doubtful overhead I usually prefer the simplicity. >> >> Good examples where it makes sense to optimize are checks for target >> thread to be current thread. >> In such cases there is no need to suspend the target thread, or use a >> VMop/HandshakeClosure. >> For instance, please, see the Monitor functions with the check: >> (java_thread == calling_thread). >> Getting information for current thread is frequently used case, e.g. >> to get info at an event point. >> >> Thanks, >> Serguei >> >> >> On 7/2/20 23:29, Yasumasa Suenaga wrote: >>> Hi Dan, David, >>> >>> I uploaded new webrev. Could you review again? >>> >>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/ >>> >>> OneGetThreadListStackTraces.java in this webrev would wait until >>> thread state is transited to "waiting" with spin wait. >>> CountDownLatch::await call as Dan pointed is fixed in it :) >>> >>> Diff from webrev.03: >>> http://hg.openjdk.java.net/jdk/submit/rev/c9aeb7001e50 >>> >>> >>> Thanks, >>> >>> Yasumasa >>> >>> >>> On 2020/07/03 14:15, David Holmes wrote: >>>> >>>> >>>> On 3/07/2020 2:27 pm, Yasumasa Suenaga wrote: >>>>> On 2020/07/03 12:24, Daniel D. Daugherty wrote: >>>>>> On 7/2/20 10:50 PM, David Holmes wrote: >>>>>>> Sorry I'm responding here without seeing latest webrev but there >>>>>>> is enough context I think ... >>>>>>> >>>>>>> On 3/07/2020 9:14 am, Yasumasa Suenaga wrote: >>>>>>>> Hi Dan, >>>>>>>> >>>>>>>> Thanks for your comment! >>>>>>>> >>>>>>>> On 2020/07/03 7:16, Daniel D. Daugherty wrote: >>>>>>>>> On 7/2/20 5:19 AM, Yasumasa Suenaga wrote: >>>>>>>>>> Hi David, >>>>>>>>>> >>>>>>>>>> I upload new webrev. Could you review again? >>>>>>>>>> >>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.03/ >>>>>>>>> >>>>>>>>> src/hotspot/share/prims/jvmtiEnv.cpp >>>>>>>>> ???? L1542: ??? // Get stack trace with handshake >>>>>>>>> ???????? nit - please add a period at the end. >>>>>>>> >>>>>>>> I will fix it. >>>>>>>> >>>>>>>> >>>>>>>>> ???? L1591: *stack_info_ptr = op.stack_info(); >>>>>>>>> ???????? The return parameter should not be touched unless the >>>>>>>>> return >>>>>>>>> ???????? code in 'err' == JVMTI_ERROR_NONE. >>>>>>>>> >>>>>>>>> ???? old L1582: ? if (err == JVMTI_ERROR_NONE) { >>>>>>>>> ???????? Please restore this check. The return parameter >>>>>>>>> should not >>>>>>>>> ???????? be touched unless the return code in 'err' == >>>>>>>>> JVMTI_ERROR_NONE. >>>>>>>> >>>>>>>> I will fix it. >>>>>>> >>>>>>> But op.stack_info() will return NULL if the error is not >>>>>>> JVMTI_ERROR_NONE. Are you (Dan) concerned about someone passing >>>>>>> in a non-null/initialized out-pointer that will be reset to NULL >>>>>>> if there was an error? >>>>>> >>>>>> Actually the way we used to test this in POSIX tests is to call >>>>>> an API with known bad parameters and the return parameter ptr >>>>>> set to NULL. If the return parameter ptr was touched when an >>>>>> error should have been detected on an earlier parameter, then >>>>>> the test failed. >>>>>> >>>>>> >>>>>>> >>>>>>>> >>>>>>>>> ???? L1272: ? if (!jt->is_exiting() && (thread_oop != NULL)) { >>>>>>>>> ???????? nit - extra parens around the second expression. >>>>>>>> >>>>>>>> I will fix it. >>>>>>>> >>>>>>>> >>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>> ???? old L1532: ? _result = JVMTI_ERROR_THREAD_NOT_ALIVE; >>>>>>>>> ???????? This deletion of the _result field threw me for a >>>>>>>>> minute and then >>>>>>>>> ???? ? ? I figured out that the field is init to >>>>>>>>> JVMTI_ERROR_THREAD_NOT_ALIVE >>>>>>>>> ???????? in the constructor. >>>>>>>>> >>>>>>>>> ???? L1553: ? if (!jt->is_exiting() && (jt->threadObj() != >>>>>>>>> NULL)) { >>>>>>>>> ???????? nit - extra parens around the second expression. >>>>>>>> >>>>>>>> I will fix it. >>>>>>>> >>>>>>>> >>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>>>>> ???? No comments. >>>>>>>>> >>>>>>>>> src/hotspot/share/runtime/vmOperations.hpp >>>>>>>>> ???? No comments. >>>>>>>>> >>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/GetThreadListStackTraces.java >>>>>>>>> >>>>>>>>> ???? No comments. >>>>>>>>> >>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/OneGetThreadListStackTraces.java >>>>>>>>> >>>>>>>>> ???? L64: ??????? startSignal.countDown(); >>>>>>>>> ???????? I was expecting this to be a call to await() instead of >>>>>>>>> ???????? countDown(). What am I missing here? >>>>>>>>> >>>>>>>>> ???????? I think this test might be passing by accident right >>>>>>>>> now, but... >>>>>>>> >>>>>>>> Main thread (which call JVMTI functions to test) should wait >>>>>>>> until test thread is ready. >>>>>>>> So main thread would wait startSignal, and test thread would >>>>>>>> count down. >>>>>>> >>>>>>> No! >>>>>>> >>>>>>> The test thread that previously called obj.wait() now calls >>>>>>> latch.await(). >>>>>>> >>>>>>> The main thread that previously called obj.notify() now calls >>>>>>> latch.countDown(). >>>>>>> >>>>>>> The main thread continues to spin until it sees the target is >>>>>>> WAITING before proceeding with the test. >>>>> >>>>> If I add spin wait to wait until transit target thread state is >>>>> WAITING (as following), we don't need to call SuspendThread(). >>>>> Which is better? >>>> >>>> The original spin-wait loop checking for? WAITING is better because >>>> it is the only guarantee that the target thread is blocked where >>>> you need it to be. suspending the thread is racy as you don't know >>>> exactly where the suspend will hit. >>>> >>>> Thanks, >>>> David >>>> ----- >>>> >>>>> >>>>> ``` >>>>> /* Wait until the thread state transits to "waiting" */ >>>>> while (th.getState() != Thread.State.WAITING) { >>>>> ???? Thread.onSpinWait(); >>>>> } >>>>> ``` >>>>> >>>>> For simplify, spin wait is prefer to >>>>> OneGetThreadListStackTraces.java in webrev.03. >>>>> >>>>> >>>>> Thanks, >>>>> >>>>> Yasumasa >>>>> >>>>> >>>>>> Here's the flow as I see it: >>>>>> >>>>>> main thread >>>>>> ?? - start worker thread >>>>>> ?? - startSignal.await() >>>>>> ???? - main is now blocked >>>>>> >>>>>> worker thread >>>>>> ?? - startSignal.countDown() >>>>>> ???? - main is now unblocked >>>>>> ?? - stopSignal.await() >>>>>> ???? - worker is now blocked >>>>>> >>>>>> main thread >>>>>> ?? - checkCallStacks(th) >>>>>> ?? - stopSignal.countDown() >>>>>> ???? - worker is now unblocked >>>>>> ?? - th.join >>>>>> ???? - main is now blocked >>>>>> >>>>>> worker thread >>>>>> ?? - runs off the end of run() >>>>>> ???? - main is now unblocked >>>>>> >>>>>> main thread >>>>>> ?? - run off the end of main() >>>>>> >>>>>> >>>>>>> >>>>>>>> >>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libGetThreadListStackTraces.c >>>>>>>>> >>>>>>>>> ???? L92: ? jthreads = (jthread *)malloc(sizeof(jthread) * >>>>>>>>> num_threads); >>>>>>>>> ???????? You don't check for malloc() failure. >>>>>>>>> ???????? 'jthreads' is allocated but never freed. >>>>>>>> >>>>>>>> I will fix it. >>>>>>>> >>>>>>>> >>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.c >>>>>>>>> >>>>>>>>> ???? L91: ? result = (*jvmti)->SuspendThread(jvmti, thread); >>>>>>>>> ???????? Why are you suspending the thread? >>>>>>>>> GetAllStackTraces() and >>>>>>>>> ???????? GetThreadListStackTraces() do not require the target >>>>>>>>> thread(s) >>>>>>>>> ???????? to be suspend. >>>>>>>>> >>>>>>>>> ???????? If you decide not to SuspendThread, then you don't >>>>>>>>> need the >>>>>>>>> ???????? AddCapabilities or the ResumeThread calls. >>>>>>>> >>>>>>>> Test thread might not be entered following code >>>>>>>> (stopSignal.await()). We might see deferent call stack between >>>>>>>> GetAllStackTraces() and GetThreadListStackTraces(). We cannot >>>>>>>> control to freeze call stack of test thread in Java code. >>>>>>>> (I didn't use SuspendThread() at first, but I saw some errors >>>>>>>> which causes in above.) >>>>>>>> >>>>>>>> So we need to call SuspendThread() to ensure we can see same >>>>>>>> call stack. >>>>>>> >>>>>>> If you are checking that the thread is in state WAITING then it >>>>>>> cannot escape from that state and you can sample the stack >>>>>>> multiple times from any API and get the same result. >>>>>>> >>>>>>> I suspect the errors you saw were from the apparent incorrect >>>>>>> use of the CountDownLatch. >>>>>> >>>>>> With the flow outlined above, the worker thread should be >>>>>> nicely blocked in stopSignal.await() when stuff is sampled. >>>>>> >>>>>> Dan >>>>>> >>>>>> >>>>>>> >>>>>>> Cheers, >>>>>>> David >>>>>>> ----- >>>>>>> >>>>>>>> >>>>>>>> Thanks, >>>>>>>> >>>>>>>> Yasumasa >>>>>>>> >>>>>>>> >>>>>>>>> Dan >>>>>>>>> >>>>>>>>>> >>>>>>>>>> On 2020/07/02 15:05, David Holmes wrote: >>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>> >>>>>>>>>>> On 1/07/2020 11:53 am, Yasumasa Suenaga wrote: >>>>>>>>>>>> Hi, >>>>>>>>>>>> >>>>>>>>>>>> I uploaded new webrev. Could review again? >>>>>>>>>>>> >>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.02/ >>>>>>>>>>> >>>>>>>>>>> Updates look fine - thanks. >>>>>>>>>>> >>>>>>>>>>> One minor nit: >>>>>>>>>>> >>>>>>>>>>> 1274 _collector.allocate_and_fill_stacks(1); >>>>>>>>>>> 1275 _collector.set_result(JVMTI_ERROR_NONE); >>>>>>>>>>> >>>>>>>>>>> In the other places where you use _collector you rely on >>>>>>>>>>> result being initialized to JVMTI_ERROR_NONE, rather than >>>>>>>>>>> setting it directly after allocate_and_fill_stacks(). >>>>>>>>>> >>>>>>>>>> Fixed. >>>>>>>>>> >>>>>>>>>> >>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> ? 820 assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>>>>> ? 821 java_thread->is_thread_fully_suspended(false, >>>>>>>>>>>>>>>>> &debug_bits) || >>>>>>>>>>>>>>>>> ? 822????????? current_thread == >>>>>>>>>>>>>>>>> java_thread->active_handshaker(), >>>>>>>>>>>>>>>>> ? 823????????? "at safepoint / handshake or target >>>>>>>>>>>>>>>>> thread is suspended"); >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> I don't think the suspension check is necessary, as >>>>>>>>>>>>>>>>> even if the target is suspended we must still be at a >>>>>>>>>>>>>>>>> safepoint or in a handshake with it. Makes me wonder >>>>>>>>>>>>>>>>> if we used to allow a racy stacktrace operation on a >>>>>>>>>>>>>>>>> suspended thread, assuming it would remain suspended? >>>>>>>>>>>> >>>>>>>>>>>> This function (JvmtiEnvBase::get_stack_trace()) can be >>>>>>>>>>>> called to get own stack trace. For example, we can call >>>>>>>>>>>> GetStackTrace() for current thread at JVMTI event. >>>>>>>>>>>> So I changed assert as below: >>>>>>>>>>>> >>>>>>>>>>>> ``` >>>>>>>>>>>> ??820?? assert(current_thread == java_thread || >>>>>>>>>>>> ??821 SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>> ??822????????? current_thread == >>>>>>>>>>>> java_thread->active_handshaker(), >>>>>>>>>>>> ??823????????? "call by myself / at safepoint / at >>>>>>>>>>>> handshake"); >>>>>>>>>>>> ``` >>>>>>>>>>> >>>>>>>>>>> Yep good catch. I hope current tests caught that. >>>>>>>>>> >>>>>>>>>> They would be tested in >>>>>>>>>> vmTestbase/nsk/jvmti/GetStackTrace/getstacktr001/ (own call >>>>>>>>>> stacks), and getstacktr003 (call stacks in other thread). >>>>>>>>>> >>>>>>>>>> >>>>>>>>>>> Speaking of tests ... >>>>>>>>>>> >>>>>>>>>>> In the native code I think you need to check the success of >>>>>>>>>>> all JNI methods that can throw exceptions - otherwise I >>>>>>>>>>> believe the tests may trigger warnings if -Xcheck:jni is >>>>>>>>>>> used with them. See for example: >>>>>>>>>>> >>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/libHeapMonitorTest.cpp >>>>>>>>>>> >>>>>>>>>> >>>>>>>>>> I updated testcases to check JNI and JVMTI function calls. >>>>>>>>>> >>>>>>>>>> >>>>>>>>>>> In the Java code the target thread: >>>>>>>>>>> >>>>>>>>>>> ?? 45???? public void run() { >>>>>>>>>>> ?? 46?????? try { >>>>>>>>>>> ?? 47?????????? synchronized (lock) { >>>>>>>>>>> ?? 48?????????????? lock.wait(); >>>>>>>>>>> ?? 49?????????????? System.out.println("OK"); >>>>>>>>>>> ?? 50?????????? } >>>>>>>>>>> >>>>>>>>>>> is potentially susceptible to spurious wakeups. Using a >>>>>>>>>>> CountDownLatch would be robust. >>>>>>>>>> >>>>>>>>>> Fixed. >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> Thanks, >>>>>>>>>> >>>>>>>>>> Yasumasa >>>>>>>>>> >>>>>>>>>> >>>>>>>>>>> Thanks, >>>>>>>>>>> David >>>>>>>>>>> ----- >>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> Thanks, >>>>>>>>>>>> >>>>>>>>>>>> Yasumasa >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> On 2020/07/01 8:48, David Holmes wrote: >>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>> >>>>>>>>>>>>> On 1/07/2020 9:05 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> 1271 ResourceMark rm; >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> IIUC at this point the _calling_thread is the current >>>>>>>>>>>>>>>>> thread, so we can use: >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>>>>>>>>> >>>>>>>>>>>>>> If so, we can call make_local() in L1272 without >>>>>>>>>>>>>> JavaThread (or we can pass current thread to >>>>>>>>>>>>>> make_local()). Is it right? >>>>>>>>>>>>>> >>>>>>>>>>>>>> ``` >>>>>>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>>>>>> 1272 >>>>>>>>>>>>>> _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, >>>>>>>>>>>>>> thread_oop), >>>>>>>>>>>>>> 1273??????????????????????????? jt, thread_oop); >>>>>>>>>>>>>> ``` >>>>>>>>>>>>> >>>>>>>>>>>>> Sorry I got confused, _calling_thread may not be the >>>>>>>>>>>>> current thread as we could be executing the handshake in >>>>>>>>>>>>> the target thread itself. So the ResourceMark is correct >>>>>>>>>>>>> as-is (implicitly for current thread). >>>>>>>>>>>>> >>>>>>>>>>>>> The argument to fill_frames will be used in the >>>>>>>>>>>>> jvmtiStackInfo and passed back to the _calling_thread, so >>>>>>>>>>>>> it must be created via make_local(_calling_thread, ...) as >>>>>>>>>>>>> you presently have. >>>>>>>>>>>>> >>>>>>>>>>>>> Thanks, >>>>>>>>>>>>> David >>>>>>>>>>>>> >>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>> >>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> On 2020/07/01 7:05, David Holmes wrote: >>>>>>>>>>>>>>> On 1/07/2020 12:17 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Thank you for reviewing! I will update new webrev >>>>>>>>>>>>>>>> tomorrow. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> 466 class MultipleStackTracesCollector : public >>>>>>>>>>>>>>>>> StackObj { >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> ? 498 class VM_GetAllStackTraces : public VM_Operation { >>>>>>>>>>>>>>>>> ? 499 private: >>>>>>>>>>>>>>>>> ? 500?? JavaThread *_calling_thread; >>>>>>>>>>>>>>>>> ? 501?? jint _final_thread_count; >>>>>>>>>>>>>>>>> ? 502 MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> You can't have a StackObj as a member of another class >>>>>>>>>>>>>>>>> like that as it may not be on the stack. I think >>>>>>>>>>>>>>>>> MultipleStackTracesCollector should not extend any >>>>>>>>>>>>>>>>> allocation class, and should always be embedded >>>>>>>>>>>>>>>>> directly in another class. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> I'm not sure what does mean "embedded". >>>>>>>>>>>>>>>> Is it ok as below? >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>> class MultipleStackTracesCollector { >>>>>>>>>>>>>>>> ??? : >>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> class GetAllStackTraces : public VM_Operation { >>>>>>>>>>>>>>>> ?? private: >>>>>>>>>>>>>>>> ???? MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Yes that I what I meant. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>> David >>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> On 2020/06/30 22:22, David Holmes wrote: >>>>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> On 30/06/2020 10:05 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>> Hi David, Serguei, >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> I updated webrev for 8242428. Could you review again? >>>>>>>>>>>>>>>>>> This change migrate to use direct handshake for >>>>>>>>>>>>>>>>>> GetStackTrace() and GetThreadListStackTraces() (when >>>>>>>>>>>>>>>>>> thread_count == 1). >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.01/ >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> This looks really good now! I only have a few nits >>>>>>>>>>>>>>>>> below. There is one thing I don't like about it but it >>>>>>>>>>>>>>>>> requires a change to the main Handshake logic to >>>>>>>>>>>>>>>>> address - in JvmtiEnv::GetThreadListStackTraces you >>>>>>>>>>>>>>>>> have to create a ThreadsListHandle to convert the >>>>>>>>>>>>>>>>> jthread to a JavaThread, but then the >>>>>>>>>>>>>>>>> Handshake::execute_direct creates another >>>>>>>>>>>>>>>>> ThreadsListHandle internally. That's a waste. I will >>>>>>>>>>>>>>>>> discuss with Robbin and file a RFE to have an overload >>>>>>>>>>>>>>>>> of execute_direct that takes an existing TLH. Actually >>>>>>>>>>>>>>>>> it's worse than that because we have another TLH in >>>>>>>>>>>>>>>>> use at the entry point for the JVMTI functions, so I >>>>>>>>>>>>>>>>> think there may be some scope for simplifying the use >>>>>>>>>>>>>>>>> of TLH instances - future RFE. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> ??451 GetStackTraceClosure(JvmtiEnv *env, jint >>>>>>>>>>>>>>>>> start_depth, jint max_count, >>>>>>>>>>>>>>>>> ??452 jvmtiFrameInfo* frame_buffer, jint* count_ptr) >>>>>>>>>>>>>>>>> ??453???? : HandshakeClosure("GetStackTrace"), >>>>>>>>>>>>>>>>> ??454?????? _env(env), _start_depth(start_depth), >>>>>>>>>>>>>>>>> _max_count(max_count), >>>>>>>>>>>>>>>>> ??455 _frame_buffer(frame_buffer), _count_ptr(count_ptr), >>>>>>>>>>>>>>>>> ??456 _result(JVMTI_ERROR_THREAD_NOT_ALIVE) { >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Nit: can you do one initializer per line please. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> This looks wrong: >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> 466 class MultipleStackTracesCollector : public >>>>>>>>>>>>>>>>> StackObj { >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> ??498 class VM_GetAllStackTraces : public VM_Operation { >>>>>>>>>>>>>>>>> ??499 private: >>>>>>>>>>>>>>>>> ??500?? JavaThread *_calling_thread; >>>>>>>>>>>>>>>>> ??501?? jint _final_thread_count; >>>>>>>>>>>>>>>>> ??502 MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> You can't have a StackObj as a member of another class >>>>>>>>>>>>>>>>> like that as it may not be on the stack. I think >>>>>>>>>>>>>>>>> MultipleStackTracesCollector should not extend any >>>>>>>>>>>>>>>>> allocation class, and should always be embedded >>>>>>>>>>>>>>>>> directly in another class. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> 481 MultipleStackTracesCollector(JvmtiEnv *env, jint >>>>>>>>>>>>>>>>> max_frame_count) { >>>>>>>>>>>>>>>>> ??482???? _env = env; >>>>>>>>>>>>>>>>> ??483???? _max_frame_count = max_frame_count; >>>>>>>>>>>>>>>>> ??484???? _frame_count_total = 0; >>>>>>>>>>>>>>>>> ??485???? _head = NULL; >>>>>>>>>>>>>>>>> ??486???? _stack_info = NULL; >>>>>>>>>>>>>>>>> ??487???? _result = JVMTI_ERROR_NONE; >>>>>>>>>>>>>>>>> ??488?? } >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> As you are touching this can you change it to use an >>>>>>>>>>>>>>>>> initializer list as you did for the HandshakeClosure, >>>>>>>>>>>>>>>>> and please keep one item per line. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> ??820 assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>>>>> ??821 java_thread->is_thread_fully_suspended(false, >>>>>>>>>>>>>>>>> &debug_bits) || >>>>>>>>>>>>>>>>> ??822????????? current_thread == >>>>>>>>>>>>>>>>> java_thread->active_handshaker(), >>>>>>>>>>>>>>>>> ??823????????? "at safepoint / handshake or target >>>>>>>>>>>>>>>>> thread is suspended"); >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> I don't think the suspension check is necessary, as >>>>>>>>>>>>>>>>> even if the target is suspended we must still be at a >>>>>>>>>>>>>>>>> safepoint or in a handshake with it. Makes me wonder >>>>>>>>>>>>>>>>> if we used to allow a racy stacktrace operation on a >>>>>>>>>>>>>>>>> suspended thread, assuming it would remain suspended? >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> 1268?? oop thread_oop = jt->threadObj(); >>>>>>>>>>>>>>>>> 1269 >>>>>>>>>>>>>>>>> 1270?? if (!jt->is_exiting() && (jt->threadObj() != >>>>>>>>>>>>>>>>> NULL)) { >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> You can use thread_oop in line 1270. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> 1272 >>>>>>>>>>>>>>>>> _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, >>>>>>>>>>>>>>>>> thread_oop), >>>>>>>>>>>>>>>>> 1273 jt, thread_oop); >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> It is frustrating that this entire call chain started >>>>>>>>>>>>>>>>> with a jthread reference, which we converted to a >>>>>>>>>>>>>>>>> JavaThread, only to eventually need to convert it back >>>>>>>>>>>>>>>>> to a jthread! I think there is some scope for >>>>>>>>>>>>>>>>> simplification here but not as part of this change. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> IIUC at this point the _calling_thread is the current >>>>>>>>>>>>>>>>> thread, so we can use: >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Please add @bug lines to the tests. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> I'm still pondering the test logic but wanted to send >>>>>>>>>>>>>>>>> this now. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>>> VM_GetThreadListStackTrace (for >>>>>>>>>>>>>>>>>> GetThreadListStackTraces) and VM_GetAllStackTraces >>>>>>>>>>>>>>>>>> (for GetAllStackTraces) have inherited >>>>>>>>>>>>>>>>>> VM_GetMultipleStackTraces VM operation which provides >>>>>>>>>>>>>>>>>> the feature to generate jvmtiStackInfo. I modified >>>>>>>>>>>>>>>>>> VM_GetMultipleStackTraces to a normal C++ class to >>>>>>>>>>>>>>>>>> share with HandshakeClosure for >>>>>>>>>>>>>>>>>> GetThreadListStackTraces (GetSingleStackTraceClosure). >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Also I added new testcases which test >>>>>>>>>>>>>>>>>> GetThreadListStackTraces() with thread_count == 1 and >>>>>>>>>>>>>>>>>> with all threads. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> This change has been tested in serviceability/jvmti >>>>>>>>>>>>>>>>>> serviceability/jdwp vmTestbase/nsk/jvmti >>>>>>>>>>>>>>>>>> vmTestbase/nsk/jdi vmTestbase/nsk/jdwp. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> On 2020/06/24 15:50, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>> Hi all, >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Please review this change: >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> ?? JBS: >>>>>>>>>>>>>>>>>>> https://bugs.openjdk.java.net/browse/JDK-8242428 >>>>>>>>>>>>>>>>>>> ?? webrev: >>>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.00/ >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> This change replace following VM operations to >>>>>>>>>>>>>>>>>>> direct handshake. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> ??- VM_GetFrameCount (GetFrameCount()) >>>>>>>>>>>>>>>>>>> ??- VM_GetFrameLocation (GetFrameLocation()) >>>>>>>>>>>>>>>>>>> ??- VM_GetThreadListStackTraces >>>>>>>>>>>>>>>>>>> (GetThreadListStackTrace()) >>>>>>>>>>>>>>>>>>> ??- VM_GetCurrentLocation >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> GetThreadListStackTrace() uses direct handshake if >>>>>>>>>>>>>>>>>>> thread count == 1. In other case (thread count > 1), >>>>>>>>>>>>>>>>>>> it would be performed as VM operation >>>>>>>>>>>>>>>>>>> (VM_GetThreadListStackTraces). >>>>>>>>>>>>>>>>>>> Caller of VM_GetCurrentLocation >>>>>>>>>>>>>>>>>>> (JvmtiEnvThreadState::reset_current_location()) >>>>>>>>>>>>>>>>>>> might be called at safepoint. So I added safepoint >>>>>>>>>>>>>>>>>>> check in its caller. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> This change has been tested in serviceability/jvmti >>>>>>>>>>>>>>>>>>> serviceability/jdwp vmTestbase/nsk/jvmti >>>>>>>>>>>>>>>>>>> vmTestbase/nsk/jdi vmTestbase/ns >>>>>>>>>>>>>>>>>>> k/jdwp. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Also I tested it on submit repo, then it has >>>>>>>>>>>>>>>>>>> execution error >>>>>>>>>>>>>>>>>>> (mach5-one-ysuenaga-JDK-8242428-20200624-0054-12034717) >>>>>>>>>>>>>>>>>>> due to dependency error. So I think it does not >>>>>>>>>>>>>>>>>>> occur by this change. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>> >>>>>> >> From david.holmes at oracle.com Fri Jul 3 22:18:53 2020 From: david.holmes at oracle.com (David Holmes) Date: Sat, 4 Jul 2020 08:18:53 +1000 Subject: [15] RFR(T) 8247527: serviceability/dcmd/gc/HeapDumpCompressedTest.java fails with Graal + ZGC In-Reply-To: References: Message-ID: <030c19da-616e-3b05-da33-5add5e6da747@oracle.com> On 4/07/2020 4:30 am, Vladimir Kozlov wrote: > Thank you, David, for looking on changes. > > I will remember to update tests. I filed RFE 8248815 [1] for tracking. > > Can you approve this fix now? Yes - thanks. David > Thanks, > Vladimir K > > [1] https://bugs.openjdk.java.net/browse/JDK-8248815 > > On 7/2/20 10:09 PM, David Holmes wrote: >> Hi Igor, >> >> On 3/07/2020 12:59 pm, Igor Ignatyev wrote: >>> Hi David, >>> >>> it's in my todo list to improve this situation and have vm.gc.X to >>> take selected JIT into account; and update existing (>200) >>> occurrences of 'vm.gc.X & !vm.graal.enabled' >> >> 200+ ouch! :( >> >> I guess this fix doesn't make the situation any worse in a practical >> sense. >> >> Thanks, >> David >> ----- >> >>> -- Igor >>> >>>> On Jul 2, 2020, at 7:25 PM, David Holmes >>>> wrote: >>>> >>>> Hi Vladimir, >>>> >>>> On 3/07/2020 12:02 pm, Vladimir Kozlov wrote: >>>>> https://cr.openjdk.java.net/~kvn/8247527/webrev.00/ >>>>> https://bugs.openjdk.java.net/browse/JDK-8247527 >>>>> Test should have @requires which excludes running Graal with GC >>>>> which it does not support. >>>> >>>> I find it somewhat disturbing that a generic test has to know about >>>> the limitations between GCs and Graal! >>>> >>>> I would have been more inclined to just exclude this test when >>>> running with Graal, even if that theoretically reduced the test >>>> coverage in a ting way. >>>> >>>> If/When Graal supports these other GCs who will remember to >>>> re-enable these test cases? >>>> >>>> Thanks, >>>> David >>>> >>>>> Testing: hs-tier1,hs-tier4-graal >>>>> Thanks, >>>>> Vladimir >>> From vladimir.kozlov at oracle.com Fri Jul 3 22:47:24 2020 From: vladimir.kozlov at oracle.com (Vladimir Kozlov) Date: Fri, 3 Jul 2020 15:47:24 -0700 Subject: [15] RFR(T) 8247527: serviceability/dcmd/gc/HeapDumpCompressedTest.java fails with Graal + ZGC In-Reply-To: <030c19da-616e-3b05-da33-5add5e6da747@oracle.com> References: <030c19da-616e-3b05-da33-5add5e6da747@oracle.com> Message-ID: Thank you, David Vladimir K On 7/3/20 3:18 PM, David Holmes wrote: > On 4/07/2020 4:30 am, Vladimir Kozlov wrote: >> Thank you, David, for looking on changes. >> >> I will remember to update tests. I filed RFE 8248815 [1] for tracking. >> >> Can you approve this fix now? > > Yes - thanks. > > David > >> Thanks, >> Vladimir K >> >> [1] https://bugs.openjdk.java.net/browse/JDK-8248815 >> >> On 7/2/20 10:09 PM, David Holmes wrote: >>> Hi Igor, >>> >>> On 3/07/2020 12:59 pm, Igor Ignatyev wrote: >>>> Hi David, >>>> >>>> it's in my todo list to improve this situation and have vm.gc.X to take selected JIT into account; and update >>>> existing (>200) occurrences of 'vm.gc.X & !vm.graal.enabled' >>> >>> 200+ ouch! :( >>> >>> I guess this fix doesn't make the situation any worse in a practical sense. >>> >>> Thanks, >>> David >>> ----- >>> >>>> -- Igor >>>> >>>>> On Jul 2, 2020, at 7:25 PM, David Holmes wrote: >>>>> >>>>> Hi Vladimir, >>>>> >>>>> On 3/07/2020 12:02 pm, Vladimir Kozlov wrote: >>>>>> https://cr.openjdk.java.net/~kvn/8247527/webrev.00/ >>>>>> https://bugs.openjdk.java.net/browse/JDK-8247527 >>>>>> Test should have @requires which excludes running Graal with GC which it does not support. >>>>> >>>>> I find it somewhat disturbing that a generic test has to know about the limitations between GCs and Graal! >>>>> >>>>> I would have been more inclined to just exclude this test when running with Graal, even if that theoretically >>>>> reduced the test coverage in a ting way. >>>>> >>>>> If/When Graal supports these other GCs who will remember to re-enable these test cases? >>>>> >>>>> Thanks, >>>>> David >>>>> >>>>>> Testing: hs-tier1,hs-tier4-graal >>>>>> Thanks, >>>>>> Vladimir >>>> From suenaga at oss.nttdata.com Fri Jul 3 22:55:55 2020 From: suenaga at oss.nttdata.com (Yasumasa Suenaga) Date: Sat, 4 Jul 2020 07:55:55 +0900 Subject: RFR: 8242428: JVMTI thread operations should use Thread-Local Handshake In-Reply-To: References: <6c263e4c-0a83-be7a-0288-ecb2de0b7cea@oss.nttdata.com> <4b7df6f8-c8f7-fedf-6366-b885d2235b58@oss.nttdata.com> <74c05dfd-ffb2-b73d-66e5-dc98752729f5@oss.nttdata.com> <763793b1-9506-44c6-0681-1c71c44a44fd@oss.nttdata.com> <5107c478-1de2-7a49-ee71-dfad6a99a667@oracle.com> <90cdfef9-e558-0d25-33f5-25b7d65bb83b@oss.nttdata.com> <0e359819-618f-c17b-a427-bb7e4daa2c58@oracle.com> <3f890bed-6892-e64d-b21b-ca0cbe11784e@oracle.com> <7dc1903b-6295-3864-6301-4c02aacdb971@oss.nttdata.com> <04e09eb7-9483-8f63-4bb4-01c9e814802e@oracle.com> <238a89a3-06b1-90e4-d5a4-8dc2f1ed12ab@oracle.com> Message-ID: Hi Serguei, I'm not an Oracle employee, so I cannot know real request(s) from your customers. However JDK-8201641 says Dynatrace has requested this enhancement. BTW I haven't heared any request from my customers about this. Thanks, Yasumasa On 2020/07/04 4:32, serguei.spitsyn at oracle.com wrote: > Hi Yasumasa, > > This difference is not that big to care about. > I feel this is really rare case and so, does not worth these complications. > Do we have a real request from customers to optimize it? > > Thanks, > Serguei > > > On 7/3/20 01:16, Yasumasa Suenaga wrote: >> Hi Serguei, >> >> Generally I agree with you, but I have concern about the difference of the result of GetStackTrace() and GetThreadListStackTraces(). >> >> ? GetStackTrace: jvmtiFrameInfo >> ? GetThreadListStackTraces: jvmtiStackInfo >> >> jvmtiStackInfo contains thread state, and it is ensured it is the state of the call stack. >> If we want to get both call stack and thread state, we need to suspend target thread, and call both GetStackTrace() and GetThreadState(). Is it ok? >> >> I was wondering if JDK-8201641 (parent ticket of this change) needed them for profiling (dynatrace?) >> If it is responsibility of JVMTI agent implementor, I remove this closure. >> >> >> Thanks, >> >> Yasumasa >> >> >> On 2020/07/03 16:45, serguei.spitsyn at oracle.com wrote: >>> Hi Yasumasa, >>> >>> After some thinking I've concluded that I do not like this optimization >>> of the GetThreadListStackTraces with GetSingleStackTraceClosure. >>> >>> We may need more opinions on this but these are my points: >>> ??- it adds some complexity and ugliness >>> ??- a win is doubtful because it has to be a rare case, so that total overhead should not be high >>> ??- if it is really high for some use cases then it is up to the user >>> ??? to optimize it with using GetStackTrace instead >>> >>> In such cases with doubtful overhead I usually prefer the simplicity. >>> >>> Good examples where it makes sense to optimize are checks for target thread to be current thread. >>> In such cases there is no need to suspend the target thread, or use a VMop/HandshakeClosure. >>> For instance, please, see the Monitor functions with the check: (java_thread == calling_thread). >>> Getting information for current thread is frequently used case, e.g. to get info at an event point. >>> >>> Thanks, >>> Serguei >>> >>> >>> On 7/2/20 23:29, Yasumasa Suenaga wrote: >>>> Hi Dan, David, >>>> >>>> I uploaded new webrev. Could you review again? >>>> >>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/ >>>> >>>> OneGetThreadListStackTraces.java in this webrev would wait until thread state is transited to "waiting" with spin wait. >>>> CountDownLatch::await call as Dan pointed is fixed in it :) >>>> >>>> Diff from webrev.03: >>>> http://hg.openjdk.java.net/jdk/submit/rev/c9aeb7001e50 >>>> >>>> >>>> Thanks, >>>> >>>> Yasumasa >>>> >>>> >>>> On 2020/07/03 14:15, David Holmes wrote: >>>>> >>>>> >>>>> On 3/07/2020 2:27 pm, Yasumasa Suenaga wrote: >>>>>> On 2020/07/03 12:24, Daniel D. Daugherty wrote: >>>>>>> On 7/2/20 10:50 PM, David Holmes wrote: >>>>>>>> Sorry I'm responding here without seeing latest webrev but there is enough context I think ... >>>>>>>> >>>>>>>> On 3/07/2020 9:14 am, Yasumasa Suenaga wrote: >>>>>>>>> Hi Dan, >>>>>>>>> >>>>>>>>> Thanks for your comment! >>>>>>>>> >>>>>>>>> On 2020/07/03 7:16, Daniel D. Daugherty wrote: >>>>>>>>>> On 7/2/20 5:19 AM, Yasumasa Suenaga wrote: >>>>>>>>>>> Hi David, >>>>>>>>>>> >>>>>>>>>>> I upload new webrev. Could you review again? >>>>>>>>>>> >>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.03/ >>>>>>>>>> >>>>>>>>>> src/hotspot/share/prims/jvmtiEnv.cpp >>>>>>>>>> ???? L1542: ??? // Get stack trace with handshake >>>>>>>>>> ???????? nit - please add a period at the end. >>>>>>>>> >>>>>>>>> I will fix it. >>>>>>>>> >>>>>>>>> >>>>>>>>>> ???? L1591: *stack_info_ptr = op.stack_info(); >>>>>>>>>> ???????? The return parameter should not be touched unless the return >>>>>>>>>> ???????? code in 'err' == JVMTI_ERROR_NONE. >>>>>>>>>> >>>>>>>>>> ???? old L1582: ? if (err == JVMTI_ERROR_NONE) { >>>>>>>>>> ???????? Please restore this check. The return parameter should not >>>>>>>>>> ???????? be touched unless the return code in 'err' == JVMTI_ERROR_NONE. >>>>>>>>> >>>>>>>>> I will fix it. >>>>>>>> >>>>>>>> But op.stack_info() will return NULL if the error is not JVMTI_ERROR_NONE. Are you (Dan) concerned about someone passing in a non-null/initialized out-pointer that will be reset to NULL if there was an error? >>>>>>> >>>>>>> Actually the way we used to test this in POSIX tests is to call >>>>>>> an API with known bad parameters and the return parameter ptr >>>>>>> set to NULL. If the return parameter ptr was touched when an >>>>>>> error should have been detected on an earlier parameter, then >>>>>>> the test failed. >>>>>>> >>>>>>> >>>>>>>> >>>>>>>>> >>>>>>>>>> ???? L1272: ? if (!jt->is_exiting() && (thread_oop != NULL)) { >>>>>>>>>> ???????? nit - extra parens around the second expression. >>>>>>>>> >>>>>>>>> I will fix it. >>>>>>>>> >>>>>>>>> >>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>> ???? old L1532: ? _result = JVMTI_ERROR_THREAD_NOT_ALIVE; >>>>>>>>>> ???????? This deletion of the _result field threw me for a minute and then >>>>>>>>>> ???? ? ? I figured out that the field is init to JVMTI_ERROR_THREAD_NOT_ALIVE >>>>>>>>>> ???????? in the constructor. >>>>>>>>>> >>>>>>>>>> ???? L1553: ? if (!jt->is_exiting() && (jt->threadObj() != NULL)) { >>>>>>>>>> ???????? nit - extra parens around the second expression. >>>>>>>>> >>>>>>>>> I will fix it. >>>>>>>>> >>>>>>>>> >>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>>>>>> ???? No comments. >>>>>>>>>> >>>>>>>>>> src/hotspot/share/runtime/vmOperations.hpp >>>>>>>>>> ???? No comments. >>>>>>>>>> >>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/GetThreadListStackTraces.java >>>>>>>>>> ???? No comments. >>>>>>>>>> >>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/OneGetThreadListStackTraces.java >>>>>>>>>> ???? L64: ??????? startSignal.countDown(); >>>>>>>>>> ???????? I was expecting this to be a call to await() instead of >>>>>>>>>> ???????? countDown(). What am I missing here? >>>>>>>>>> >>>>>>>>>> ???????? I think this test might be passing by accident right now, but... >>>>>>>>> >>>>>>>>> Main thread (which call JVMTI functions to test) should wait until test thread is ready. >>>>>>>>> So main thread would wait startSignal, and test thread would count down. >>>>>>>> >>>>>>>> No! >>>>>>>> >>>>>>>> The test thread that previously called obj.wait() now calls latch.await(). >>>>>>>> >>>>>>>> The main thread that previously called obj.notify() now calls latch.countDown(). >>>>>>>> >>>>>>>> The main thread continues to spin until it sees the target is WAITING before proceeding with the test. >>>>>> >>>>>> If I add spin wait to wait until transit target thread state is WAITING (as following), we don't need to call SuspendThread(). >>>>>> Which is better? >>>>> >>>>> The original spin-wait loop checking for? WAITING is better because it is the only guarantee that the target thread is blocked where you need it to be. suspending the thread is racy as you don't know exactly where the suspend will hit. >>>>> >>>>> Thanks, >>>>> David >>>>> ----- >>>>> >>>>>> >>>>>> ``` >>>>>> /* Wait until the thread state transits to "waiting" */ >>>>>> while (th.getState() != Thread.State.WAITING) { >>>>>> ???? Thread.onSpinWait(); >>>>>> } >>>>>> ``` >>>>>> >>>>>> For simplify, spin wait is prefer to OneGetThreadListStackTraces.java in webrev.03. >>>>>> >>>>>> >>>>>> Thanks, >>>>>> >>>>>> Yasumasa >>>>>> >>>>>> >>>>>>> Here's the flow as I see it: >>>>>>> >>>>>>> main thread >>>>>>> ?? - start worker thread >>>>>>> ?? - startSignal.await() >>>>>>> ???? - main is now blocked >>>>>>> >>>>>>> worker thread >>>>>>> ?? - startSignal.countDown() >>>>>>> ???? - main is now unblocked >>>>>>> ?? - stopSignal.await() >>>>>>> ???? - worker is now blocked >>>>>>> >>>>>>> main thread >>>>>>> ?? - checkCallStacks(th) >>>>>>> ?? - stopSignal.countDown() >>>>>>> ???? - worker is now unblocked >>>>>>> ?? - th.join >>>>>>> ???? - main is now blocked >>>>>>> >>>>>>> worker thread >>>>>>> ?? - runs off the end of run() >>>>>>> ???? - main is now unblocked >>>>>>> >>>>>>> main thread >>>>>>> ?? - run off the end of main() >>>>>>> >>>>>>> >>>>>>>> >>>>>>>>> >>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libGetThreadListStackTraces.c >>>>>>>>>> ???? L92: ? jthreads = (jthread *)malloc(sizeof(jthread) * num_threads); >>>>>>>>>> ???????? You don't check for malloc() failure. >>>>>>>>>> ???????? 'jthreads' is allocated but never freed. >>>>>>>>> >>>>>>>>> I will fix it. >>>>>>>>> >>>>>>>>> >>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.c >>>>>>>>>> ???? L91: ? result = (*jvmti)->SuspendThread(jvmti, thread); >>>>>>>>>> ???????? Why are you suspending the thread? GetAllStackTraces() and >>>>>>>>>> ???????? GetThreadListStackTraces() do not require the target thread(s) >>>>>>>>>> ???????? to be suspend. >>>>>>>>>> >>>>>>>>>> ???????? If you decide not to SuspendThread, then you don't need the >>>>>>>>>> ???????? AddCapabilities or the ResumeThread calls. >>>>>>>>> >>>>>>>>> Test thread might not be entered following code (stopSignal.await()). We might see deferent call stack between GetAllStackTraces() and GetThreadListStackTraces(). We cannot control to freeze call stack of test thread in Java code. >>>>>>>>> (I didn't use SuspendThread() at first, but I saw some errors which causes in above.) >>>>>>>>> >>>>>>>>> So we need to call SuspendThread() to ensure we can see same call stack. >>>>>>>> >>>>>>>> If you are checking that the thread is in state WAITING then it cannot escape from that state and you can sample the stack multiple times from any API and get the same result. >>>>>>>> >>>>>>>> I suspect the errors you saw were from the apparent incorrect use of the CountDownLatch. >>>>>>> >>>>>>> With the flow outlined above, the worker thread should be >>>>>>> nicely blocked in stopSignal.await() when stuff is sampled. >>>>>>> >>>>>>> Dan >>>>>>> >>>>>>> >>>>>>>> >>>>>>>> Cheers, >>>>>>>> David >>>>>>>> ----- >>>>>>>> >>>>>>>>> >>>>>>>>> Thanks, >>>>>>>>> >>>>>>>>> Yasumasa >>>>>>>>> >>>>>>>>> >>>>>>>>>> Dan >>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> On 2020/07/02 15:05, David Holmes wrote: >>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>> >>>>>>>>>>>> On 1/07/2020 11:53 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>> Hi, >>>>>>>>>>>>> >>>>>>>>>>>>> I uploaded new webrev. Could review again? >>>>>>>>>>>>> >>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.02/ >>>>>>>>>>>> >>>>>>>>>>>> Updates look fine - thanks. >>>>>>>>>>>> >>>>>>>>>>>> One minor nit: >>>>>>>>>>>> >>>>>>>>>>>> 1274 _collector.allocate_and_fill_stacks(1); >>>>>>>>>>>> 1275 _collector.set_result(JVMTI_ERROR_NONE); >>>>>>>>>>>> >>>>>>>>>>>> In the other places where you use _collector you rely on result being initialized to JVMTI_ERROR_NONE, rather than setting it directly after allocate_and_fill_stacks(). >>>>>>>>>>> >>>>>>>>>>> Fixed. >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> ? 820 assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>>>>>> ? 821 java_thread->is_thread_fully_suspended(false, &debug_bits) || >>>>>>>>>>>>>>>>>> ? 822????????? current_thread == java_thread->active_handshaker(), >>>>>>>>>>>>>>>>>> ? 823????????? "at safepoint / handshake or target thread is suspended"); >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> I don't think the suspension check is necessary, as even if the target is suspended we must still be at a safepoint or in a handshake with it. Makes me wonder if we used to allow a racy stacktrace operation on a suspended thread, assuming it would remain suspended? >>>>>>>>>>>>> >>>>>>>>>>>>> This function (JvmtiEnvBase::get_stack_trace()) can be called to get own stack trace. For example, we can call GetStackTrace() for current thread at JVMTI event. >>>>>>>>>>>>> So I changed assert as below: >>>>>>>>>>>>> >>>>>>>>>>>>> ``` >>>>>>>>>>>>> ??820?? assert(current_thread == java_thread || >>>>>>>>>>>>> ??821 SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>> ??822????????? current_thread == java_thread->active_handshaker(), >>>>>>>>>>>>> ??823????????? "call by myself / at safepoint / at handshake"); >>>>>>>>>>>>> ``` >>>>>>>>>>>> >>>>>>>>>>>> Yep good catch. I hope current tests caught that. >>>>>>>>>>> >>>>>>>>>>> They would be tested in vmTestbase/nsk/jvmti/GetStackTrace/getstacktr001/ (own call stacks), and getstacktr003 (call stacks in other thread). >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>>> Speaking of tests ... >>>>>>>>>>>> >>>>>>>>>>>> In the native code I think you need to check the success of all JNI methods that can throw exceptions - otherwise I believe the tests may trigger warnings if -Xcheck:jni is used with them. See for example: >>>>>>>>>>>> >>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/libHeapMonitorTest.cpp >>>>>>>>>>> >>>>>>>>>>> I updated testcases to check JNI and JVMTI function calls. >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>>> In the Java code the target thread: >>>>>>>>>>>> >>>>>>>>>>>> ?? 45???? public void run() { >>>>>>>>>>>> ?? 46?????? try { >>>>>>>>>>>> ?? 47?????????? synchronized (lock) { >>>>>>>>>>>> ?? 48?????????????? lock.wait(); >>>>>>>>>>>> ?? 49?????????????? System.out.println("OK"); >>>>>>>>>>>> ?? 50?????????? } >>>>>>>>>>>> >>>>>>>>>>>> is potentially susceptible to spurious wakeups. Using a CountDownLatch would be robust. >>>>>>>>>>> >>>>>>>>>>> Fixed. >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> Thanks, >>>>>>>>>>> >>>>>>>>>>> Yasumasa >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>>> Thanks, >>>>>>>>>>>> David >>>>>>>>>>>> ----- >>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> Thanks, >>>>>>>>>>>>> >>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> On 2020/07/01 8:48, David Holmes wrote: >>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>> >>>>>>>>>>>>>> On 1/07/2020 9:05 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> 1271 ResourceMark rm; >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> IIUC at this point the _calling_thread is the current thread, so we can use: >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> If so, we can call make_local() in L1272 without JavaThread (or we can pass current thread to make_local()). Is it right? >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>>>>>>> 1272 _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, thread_oop), >>>>>>>>>>>>>>> 1273??????????????????????????? jt, thread_oop); >>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>> >>>>>>>>>>>>>> Sorry I got confused, _calling_thread may not be the current thread as we could be executing the handshake in the target thread itself. So the ResourceMark is correct as-is (implicitly for current thread). >>>>>>>>>>>>>> >>>>>>>>>>>>>> The argument to fill_frames will be used in the jvmtiStackInfo and passed back to the _calling_thread, so it must be created via make_local(_calling_thread, ...) as you presently have. >>>>>>>>>>>>>> >>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>> David >>>>>>>>>>>>>> >>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> On 2020/07/01 7:05, David Holmes wrote: >>>>>>>>>>>>>>>> On 1/07/2020 12:17 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Thank you for reviewing! I will update new webrev tomorrow. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> 466 class MultipleStackTracesCollector : public StackObj { >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> ? 498 class VM_GetAllStackTraces : public VM_Operation { >>>>>>>>>>>>>>>>>> ? 499 private: >>>>>>>>>>>>>>>>>> ? 500?? JavaThread *_calling_thread; >>>>>>>>>>>>>>>>>> ? 501?? jint _final_thread_count; >>>>>>>>>>>>>>>>>> ? 502 MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> You can't have a StackObj as a member of another class like that as it may not be on the stack. I think MultipleStackTracesCollector should not extend any allocation class, and should always be embedded directly in another class. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> I'm not sure what does mean "embedded". >>>>>>>>>>>>>>>>> Is it ok as below? >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>> class MultipleStackTracesCollector { >>>>>>>>>>>>>>>>> ??? : >>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> class GetAllStackTraces : public VM_Operation { >>>>>>>>>>>>>>>>> ?? private: >>>>>>>>>>>>>>>>> ???? MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Yes that I what I meant. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> On 2020/06/30 22:22, David Holmes wrote: >>>>>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> On 30/06/2020 10:05 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>> Hi David, Serguei, >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> I updated webrev for 8242428. Could you review again? >>>>>>>>>>>>>>>>>>> This change migrate to use direct handshake for GetStackTrace() and GetThreadListStackTraces() (when thread_count == 1). >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.01/ >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> This looks really good now! I only have a few nits below. There is one thing I don't like about it but it requires a change to the main Handshake logic to address - in JvmtiEnv::GetThreadListStackTraces you have to create a ThreadsListHandle to convert the jthread to a JavaThread, but then the Handshake::execute_direct creates another ThreadsListHandle internally. That's a waste. I will discuss with Robbin and file a RFE to have an overload of execute_direct that takes an existing TLH. Actually it's worse than that because we have another TLH in use at the entry point for the JVMTI functions, so I think there may be some scope for simplifying the use of TLH instances - future RFE. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> ??451 GetStackTraceClosure(JvmtiEnv *env, jint start_depth, jint max_count, >>>>>>>>>>>>>>>>>> ??452 jvmtiFrameInfo* frame_buffer, jint* count_ptr) >>>>>>>>>>>>>>>>>> ??453???? : HandshakeClosure("GetStackTrace"), >>>>>>>>>>>>>>>>>> ??454?????? _env(env), _start_depth(start_depth), _max_count(max_count), >>>>>>>>>>>>>>>>>> ??455 _frame_buffer(frame_buffer), _count_ptr(count_ptr), >>>>>>>>>>>>>>>>>> ??456 _result(JVMTI_ERROR_THREAD_NOT_ALIVE) { >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Nit: can you do one initializer per line please. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> This looks wrong: >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> 466 class MultipleStackTracesCollector : public StackObj { >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> ??498 class VM_GetAllStackTraces : public VM_Operation { >>>>>>>>>>>>>>>>>> ??499 private: >>>>>>>>>>>>>>>>>> ??500?? JavaThread *_calling_thread; >>>>>>>>>>>>>>>>>> ??501?? jint _final_thread_count; >>>>>>>>>>>>>>>>>> ??502 MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> You can't have a StackObj as a member of another class like that as it may not be on the stack. I think MultipleStackTracesCollector should not extend any allocation class, and should always be embedded directly in another class. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> 481 MultipleStackTracesCollector(JvmtiEnv *env, jint max_frame_count) { >>>>>>>>>>>>>>>>>> ??482???? _env = env; >>>>>>>>>>>>>>>>>> ??483???? _max_frame_count = max_frame_count; >>>>>>>>>>>>>>>>>> ??484???? _frame_count_total = 0; >>>>>>>>>>>>>>>>>> ??485???? _head = NULL; >>>>>>>>>>>>>>>>>> ??486???? _stack_info = NULL; >>>>>>>>>>>>>>>>>> ??487???? _result = JVMTI_ERROR_NONE; >>>>>>>>>>>>>>>>>> ??488?? } >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> As you are touching this can you change it to use an initializer list as you did for the HandshakeClosure, and please keep one item per line. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> ??820 assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>>>>>> ??821 java_thread->is_thread_fully_suspended(false, &debug_bits) || >>>>>>>>>>>>>>>>>> ??822????????? current_thread == java_thread->active_handshaker(), >>>>>>>>>>>>>>>>>> ??823????????? "at safepoint / handshake or target thread is suspended"); >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> I don't think the suspension check is necessary, as even if the target is suspended we must still be at a safepoint or in a handshake with it. Makes me wonder if we used to allow a racy stacktrace operation on a suspended thread, assuming it would remain suspended? >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> 1268?? oop thread_oop = jt->threadObj(); >>>>>>>>>>>>>>>>>> 1269 >>>>>>>>>>>>>>>>>> 1270?? if (!jt->is_exiting() && (jt->threadObj() != NULL)) { >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> You can use thread_oop in line 1270. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> 1272 _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, thread_oop), >>>>>>>>>>>>>>>>>> 1273 jt, thread_oop); >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> It is frustrating that this entire call chain started with a jthread reference, which we converted to a JavaThread, only to eventually need to convert it back to a jthread! I think there is some scope for simplification here but not as part of this change. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> IIUC at this point the _calling_thread is the current thread, so we can use: >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Please add @bug lines to the tests. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> I'm still pondering the test logic but wanted to send this now. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>>>> VM_GetThreadListStackTrace (for GetThreadListStackTraces) and VM_GetAllStackTraces (for GetAllStackTraces) have inherited VM_GetMultipleStackTraces VM operation which provides the feature to generate jvmtiStackInfo. I modified VM_GetMultipleStackTraces to a normal C++ class to share with HandshakeClosure for GetThreadListStackTraces (GetSingleStackTraceClosure). >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Also I added new testcases which test GetThreadListStackTraces() with thread_count == 1 and with all threads. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> This change has been tested in serviceability/jvmti serviceability/jdwp vmTestbase/nsk/jvmti vmTestbase/nsk/jdi vmTestbase/nsk/jdwp. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> On 2020/06/24 15:50, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>> Hi all, >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Please review this change: >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> ?? JBS: https://bugs.openjdk.java.net/browse/JDK-8242428 >>>>>>>>>>>>>>>>>>>> ?? webrev: http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.00/ >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> This change replace following VM operations to direct handshake. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> ??- VM_GetFrameCount (GetFrameCount()) >>>>>>>>>>>>>>>>>>>> ??- VM_GetFrameLocation (GetFrameLocation()) >>>>>>>>>>>>>>>>>>>> ??- VM_GetThreadListStackTraces (GetThreadListStackTrace()) >>>>>>>>>>>>>>>>>>>> ??- VM_GetCurrentLocation >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> GetThreadListStackTrace() uses direct handshake if thread count == 1. In other case (thread count > 1), it would be performed as VM operation (VM_GetThreadListStackTraces). >>>>>>>>>>>>>>>>>>>> Caller of VM_GetCurrentLocation (JvmtiEnvThreadState::reset_current_location()) might be called at safepoint. So I added safepoint check in its caller. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> This change has been tested in serviceability/jvmti serviceability/jdwp vmTestbase/nsk/jvmti vmTestbase/nsk/jdi vmTestbase/ns >>>>>>>>>>>>>>>>>>>> k/jdwp. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Also I tested it on submit repo, then it has execution error (mach5-one-ysuenaga-JDK-8242428-20200624-0054-12034717) due to dependency error. So I think it does not occur by this change. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>> >>>>>>> >>> > From serguei.spitsyn at oracle.com Sun Jul 5 05:46:53 2020 From: serguei.spitsyn at oracle.com (serguei.spitsyn at oracle.com) Date: Sat, 4 Jul 2020 22:46:53 -0700 Subject: RFR: 8242428: JVMTI thread operations should use Thread-Local Handshake In-Reply-To: References: <6c263e4c-0a83-be7a-0288-ecb2de0b7cea@oss.nttdata.com> <74c05dfd-ffb2-b73d-66e5-dc98752729f5@oss.nttdata.com> <763793b1-9506-44c6-0681-1c71c44a44fd@oss.nttdata.com> <5107c478-1de2-7a49-ee71-dfad6a99a667@oracle.com> <90cdfef9-e558-0d25-33f5-25b7d65bb83b@oss.nttdata.com> <0e359819-618f-c17b-a427-bb7e4daa2c58@oracle.com> <3f890bed-6892-e64d-b21b-ca0cbe11784e@oracle.com> <7dc1903b-6295-3864-6301-4c02aacdb971@oss.nttdata.com> <04e09eb7-9483-8f63-4bb4-01c9e814802e@oracle.com> <238a89a3-06b1-90e4-d5a4-8dc2f1ed12ab@oracle.com> Message-ID: <4c43bc2c-551e-d042-8fa7-b63e755888d1@oracle.com> Hi Yasumasa, Okay, thanks. Then I'm okay to keep the GetSingleStackTraceClosure. http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libGetThreadListStackTraces.c.html http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.c.html I'm not sure the function 'is_same_thread() is needed. Why do not use the JNI IsSameObject instead? It seems to be a typo at L132 and L137. You, probably. did not want to print the same information for stack_info_1[i].frame_buffer[j].XXX twice. The code at lines 112-142 is not readable. I'd suggest to make a couple of refactoring steps. First step to simplify this a little bit would be with some renaming and getting rid of indexes: ? 71 char err_msg[EXCEPTION_MSG_LEN] = {0}; ?... ?112?? /* Iterate all jvmtiStackInfo to check */ ?113?? for (i = 0; i < num_threads, *exception_msg != '\0'; i++) { ???????? jvmtiStackInfo *si1 = stack_info_1[i]; ???????? jvmtiStackInfo *si2 = stack_info_2[i]; ?114???? if (!IsSameObject(env, si1.thread, si2.thread)) { /* jvmtiStackInfo::thread */ ?115?????? snprintf(err_msg, sizeof(err_msg), ?116??????????????? "thread[%d] is different: stack_info_1 = %p, stack_info_2 = %p", ?117??????????????? i, sinfo1.thread, sinfo2.thread); ?118???? } else if (si1.state != si2.state) { /* jvmtiStackInfo::state */ ?119?????? snprintf(err_msg, sizeof(err_msg), ?120??????????????? "state[%d] is different: stack_info_1 = %d, stack_info_2 = %d", ?121??????????????? i, si1.state, si2.state); ?122???? } else if (si1.frame_count != si2.frame_count) { /* jvmtiStackInfo::frame_count */ ?123?????? snprintf(err_msg, sizeof(err_msg), ?124??????????????? "frame_count[%d] is different: stack_info_1 = %d, stack_info_2 = %d", ?125??????????????? i, si1.frame_count, si2.frame_count); ?126???? } else { ?127?????? /* Iterate all jvmtiFrameInfo to check */ ?128?????? for (j = 0; j < si1.frame_count; j++) { ?129???????? if (si1.frame_buffer[j].method != si1.frame_buffer[j].method) { /* jvmtiFrameInfo::method */ ?130?????????? snprintf(err_msg, sizeof(err_msg), ?131??????????????????? "thread [%d] frame_buffer[%d].method is different: stack_info_1 = %lx, stack_info_2 = %lx", ?132??????????????????? i, j, si1.frame_buffer[j].method, si2.frame_buffer[j].method); ?133?????????? break; ?134???????? } else if (si1.frame_buffer[j].location != si1.frame_buffer[j].location) { /* jvmtiFrameInfo::location */ ?135?????????? snprintf(err_msg, sizeof(err_msg), ?136??????????????????? "thread [%d] frame_buffer[%d].location is different: stack_info_1 = %ld, stack_info_2 = %ld", ?137??????????????????? i, j, si1.frame_buffer[j].location, si2.frame_buffer[j].location); ?138?????????? break; ?139???????? } ?140?????? } ?141???? } ?142?? } Another step would be to create functions that implement a body of each loop. You can use the same techniques to simplify similar place (L127-L138) in the libOneGetThreadListStackTraces.c. Thanks, Serguei On 7/3/20 15:55, Yasumasa Suenaga wrote: > Hi Serguei, > > I'm not an Oracle employee, so I cannot know real request(s) from your > customers. > However JDK-8201641 says Dynatrace has requested this enhancement. > > BTW I haven't heared any request from my customers about this. > > > Thanks, > > Yasumasa > > > On 2020/07/04 4:32, serguei.spitsyn at oracle.com wrote: >> Hi Yasumasa, >> >> This difference is not that big to care about. >> I feel this is really rare case and so, does not worth these >> complications. >> Do we have a real request from customers to optimize it? >> >> Thanks, >> Serguei >> >> >> On 7/3/20 01:16, Yasumasa Suenaga wrote: >>> Hi Serguei, >>> >>> Generally I agree with you, but I have concern about the difference >>> of the result of GetStackTrace() and GetThreadListStackTraces(). >>> >>> ? GetStackTrace: jvmtiFrameInfo >>> ? GetThreadListStackTraces: jvmtiStackInfo >>> >>> jvmtiStackInfo contains thread state, and it is ensured it is the >>> state of the call stack. >>> If we want to get both call stack and thread state, we need to >>> suspend target thread, and call both GetStackTrace() and >>> GetThreadState(). Is it ok? >>> >>> I was wondering if JDK-8201641 (parent ticket of this change) needed >>> them for profiling (dynatrace?) >>> If it is responsibility of JVMTI agent implementor, I remove this >>> closure. >>> >>> >>> Thanks, >>> >>> Yasumasa >>> >>> >>> On 2020/07/03 16:45, serguei.spitsyn at oracle.com wrote: >>>> Hi Yasumasa, >>>> >>>> After some thinking I've concluded that I do not like this >>>> optimization >>>> of the GetThreadListStackTraces with GetSingleStackTraceClosure. >>>> >>>> We may need more opinions on this but these are my points: >>>> ??- it adds some complexity and ugliness >>>> ??- a win is doubtful because it has to be a rare case, so that >>>> total overhead should not be high >>>> ??- if it is really high for some use cases then it is up to the user >>>> ??? to optimize it with using GetStackTrace instead >>>> >>>> In such cases with doubtful overhead I usually prefer the simplicity. >>>> >>>> Good examples where it makes sense to optimize are checks for >>>> target thread to be current thread. >>>> In such cases there is no need to suspend the target thread, or use >>>> a VMop/HandshakeClosure. >>>> For instance, please, see the Monitor functions with the check: >>>> (java_thread == calling_thread). >>>> Getting information for current thread is frequently used case, >>>> e.g. to get info at an event point. >>>> >>>> Thanks, >>>> Serguei >>>> >>>> >>>> On 7/2/20 23:29, Yasumasa Suenaga wrote: >>>>> Hi Dan, David, >>>>> >>>>> I uploaded new webrev. Could you review again? >>>>> >>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/ >>>>> >>>>> OneGetThreadListStackTraces.java in this webrev would wait until >>>>> thread state is transited to "waiting" with spin wait. >>>>> CountDownLatch::await call as Dan pointed is fixed in it :) >>>>> >>>>> Diff from webrev.03: >>>>> http://hg.openjdk.java.net/jdk/submit/rev/c9aeb7001e50 >>>>> >>>>> >>>>> Thanks, >>>>> >>>>> Yasumasa >>>>> >>>>> >>>>> On 2020/07/03 14:15, David Holmes wrote: >>>>>> >>>>>> >>>>>> On 3/07/2020 2:27 pm, Yasumasa Suenaga wrote: >>>>>>> On 2020/07/03 12:24, Daniel D. Daugherty wrote: >>>>>>>> On 7/2/20 10:50 PM, David Holmes wrote: >>>>>>>>> Sorry I'm responding here without seeing latest webrev but >>>>>>>>> there is enough context I think ... >>>>>>>>> >>>>>>>>> On 3/07/2020 9:14 am, Yasumasa Suenaga wrote: >>>>>>>>>> Hi Dan, >>>>>>>>>> >>>>>>>>>> Thanks for your comment! >>>>>>>>>> >>>>>>>>>> On 2020/07/03 7:16, Daniel D. Daugherty wrote: >>>>>>>>>>> On 7/2/20 5:19 AM, Yasumasa Suenaga wrote: >>>>>>>>>>>> Hi David, >>>>>>>>>>>> >>>>>>>>>>>> I upload new webrev. Could you review again? >>>>>>>>>>>> >>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.03/ >>>>>>>>>>> >>>>>>>>>>> src/hotspot/share/prims/jvmtiEnv.cpp >>>>>>>>>>> ???? L1542: ??? // Get stack trace with handshake >>>>>>>>>>> ???????? nit - please add a period at the end. >>>>>>>>>> >>>>>>>>>> I will fix it. >>>>>>>>>> >>>>>>>>>> >>>>>>>>>>> ???? L1591: *stack_info_ptr = op.stack_info(); >>>>>>>>>>> ???????? The return parameter should not be touched unless >>>>>>>>>>> the return >>>>>>>>>>> ???????? code in 'err' == JVMTI_ERROR_NONE. >>>>>>>>>>> >>>>>>>>>>> ???? old L1582: ? if (err == JVMTI_ERROR_NONE) { >>>>>>>>>>> ???????? Please restore this check. The return parameter >>>>>>>>>>> should not >>>>>>>>>>> ???????? be touched unless the return code in 'err' == >>>>>>>>>>> JVMTI_ERROR_NONE. >>>>>>>>>> >>>>>>>>>> I will fix it. >>>>>>>>> >>>>>>>>> But op.stack_info() will return NULL if the error is not >>>>>>>>> JVMTI_ERROR_NONE. Are you (Dan) concerned about someone >>>>>>>>> passing in a non-null/initialized out-pointer that will be >>>>>>>>> reset to NULL if there was an error? >>>>>>>> >>>>>>>> Actually the way we used to test this in POSIX tests is to call >>>>>>>> an API with known bad parameters and the return parameter ptr >>>>>>>> set to NULL. If the return parameter ptr was touched when an >>>>>>>> error should have been detected on an earlier parameter, then >>>>>>>> the test failed. >>>>>>>> >>>>>>>> >>>>>>>>> >>>>>>>>>> >>>>>>>>>>> ???? L1272: ? if (!jt->is_exiting() && (thread_oop != NULL)) { >>>>>>>>>>> ???????? nit - extra parens around the second expression. >>>>>>>>>> >>>>>>>>>> I will fix it. >>>>>>>>>> >>>>>>>>>> >>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>> ???? old L1532: ? _result = JVMTI_ERROR_THREAD_NOT_ALIVE; >>>>>>>>>>> ???????? This deletion of the _result field threw me for a >>>>>>>>>>> minute and then >>>>>>>>>>> ???? ? ? I figured out that the field is init to >>>>>>>>>>> JVMTI_ERROR_THREAD_NOT_ALIVE >>>>>>>>>>> ???????? in the constructor. >>>>>>>>>>> >>>>>>>>>>> ???? L1553: ? if (!jt->is_exiting() && (jt->threadObj() != >>>>>>>>>>> NULL)) { >>>>>>>>>>> ???????? nit - extra parens around the second expression. >>>>>>>>>> >>>>>>>>>> I will fix it. >>>>>>>>>> >>>>>>>>>> >>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>>>>>>> ???? No comments. >>>>>>>>>>> >>>>>>>>>>> src/hotspot/share/runtime/vmOperations.hpp >>>>>>>>>>> ???? No comments. >>>>>>>>>>> >>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/GetThreadListStackTraces.java >>>>>>>>>>> >>>>>>>>>>> ???? No comments. >>>>>>>>>>> >>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/OneGetThreadListStackTraces.java >>>>>>>>>>> >>>>>>>>>>> ???? L64: ??????? startSignal.countDown(); >>>>>>>>>>> ???????? I was expecting this to be a call to await() >>>>>>>>>>> instead of >>>>>>>>>>> ???????? countDown(). What am I missing here? >>>>>>>>>>> >>>>>>>>>>> ???????? I think this test might be passing by accident >>>>>>>>>>> right now, but... >>>>>>>>>> >>>>>>>>>> Main thread (which call JVMTI functions to test) should wait >>>>>>>>>> until test thread is ready. >>>>>>>>>> So main thread would wait startSignal, and test thread would >>>>>>>>>> count down. >>>>>>>>> >>>>>>>>> No! >>>>>>>>> >>>>>>>>> The test thread that previously called obj.wait() now calls >>>>>>>>> latch.await(). >>>>>>>>> >>>>>>>>> The main thread that previously called obj.notify() now calls >>>>>>>>> latch.countDown(). >>>>>>>>> >>>>>>>>> The main thread continues to spin until it sees the target is >>>>>>>>> WAITING before proceeding with the test. >>>>>>> >>>>>>> If I add spin wait to wait until transit target thread state is >>>>>>> WAITING (as following), we don't need to call SuspendThread(). >>>>>>> Which is better? >>>>>> >>>>>> The original spin-wait loop checking for? WAITING is better >>>>>> because it is the only guarantee that the target thread is >>>>>> blocked where you need it to be. suspending the thread is racy as >>>>>> you don't know exactly where the suspend will hit. >>>>>> >>>>>> Thanks, >>>>>> David >>>>>> ----- >>>>>> >>>>>>> >>>>>>> ``` >>>>>>> /* Wait until the thread state transits to "waiting" */ >>>>>>> while (th.getState() != Thread.State.WAITING) { >>>>>>> ???? Thread.onSpinWait(); >>>>>>> } >>>>>>> ``` >>>>>>> >>>>>>> For simplify, spin wait is prefer to >>>>>>> OneGetThreadListStackTraces.java in webrev.03. >>>>>>> >>>>>>> >>>>>>> Thanks, >>>>>>> >>>>>>> Yasumasa >>>>>>> >>>>>>> >>>>>>>> Here's the flow as I see it: >>>>>>>> >>>>>>>> main thread >>>>>>>> ?? - start worker thread >>>>>>>> ?? - startSignal.await() >>>>>>>> ???? - main is now blocked >>>>>>>> >>>>>>>> worker thread >>>>>>>> ?? - startSignal.countDown() >>>>>>>> ???? - main is now unblocked >>>>>>>> ?? - stopSignal.await() >>>>>>>> ???? - worker is now blocked >>>>>>>> >>>>>>>> main thread >>>>>>>> ?? - checkCallStacks(th) >>>>>>>> ?? - stopSignal.countDown() >>>>>>>> ???? - worker is now unblocked >>>>>>>> ?? - th.join >>>>>>>> ???? - main is now blocked >>>>>>>> >>>>>>>> worker thread >>>>>>>> ?? - runs off the end of run() >>>>>>>> ???? - main is now unblocked >>>>>>>> >>>>>>>> main thread >>>>>>>> ?? - run off the end of main() >>>>>>>> >>>>>>>> >>>>>>>>> >>>>>>>>>> >>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libGetThreadListStackTraces.c >>>>>>>>>>> >>>>>>>>>>> ???? L92: ? jthreads = (jthread *)malloc(sizeof(jthread) * >>>>>>>>>>> num_threads); >>>>>>>>>>> ???????? You don't check for malloc() failure. >>>>>>>>>>> ???????? 'jthreads' is allocated but never freed. >>>>>>>>>> >>>>>>>>>> I will fix it. >>>>>>>>>> >>>>>>>>>> >>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.c >>>>>>>>>>> >>>>>>>>>>> ???? L91: ? result = (*jvmti)->SuspendThread(jvmti, thread); >>>>>>>>>>> ???????? Why are you suspending the thread? >>>>>>>>>>> GetAllStackTraces() and >>>>>>>>>>> ???????? GetThreadListStackTraces() do not require the >>>>>>>>>>> target thread(s) >>>>>>>>>>> ???????? to be suspend. >>>>>>>>>>> >>>>>>>>>>> ???????? If you decide not to SuspendThread, then you don't >>>>>>>>>>> need the >>>>>>>>>>> ???????? AddCapabilities or the ResumeThread calls. >>>>>>>>>> >>>>>>>>>> Test thread might not be entered following code >>>>>>>>>> (stopSignal.await()). We might see deferent call stack >>>>>>>>>> between GetAllStackTraces() and GetThreadListStackTraces(). >>>>>>>>>> We cannot control to freeze call stack of test thread in Java >>>>>>>>>> code. >>>>>>>>>> (I didn't use SuspendThread() at first, but I saw some errors >>>>>>>>>> which causes in above.) >>>>>>>>>> >>>>>>>>>> So we need to call SuspendThread() to ensure we can see same >>>>>>>>>> call stack. >>>>>>>>> >>>>>>>>> If you are checking that the thread is in state WAITING then >>>>>>>>> it cannot escape from that state and you can sample the stack >>>>>>>>> multiple times from any API and get the same result. >>>>>>>>> >>>>>>>>> I suspect the errors you saw were from the apparent incorrect >>>>>>>>> use of the CountDownLatch. >>>>>>>> >>>>>>>> With the flow outlined above, the worker thread should be >>>>>>>> nicely blocked in stopSignal.await() when stuff is sampled. >>>>>>>> >>>>>>>> Dan >>>>>>>> >>>>>>>> >>>>>>>>> >>>>>>>>> Cheers, >>>>>>>>> David >>>>>>>>> ----- >>>>>>>>> >>>>>>>>>> >>>>>>>>>> Thanks, >>>>>>>>>> >>>>>>>>>> Yasumasa >>>>>>>>>> >>>>>>>>>> >>>>>>>>>>> Dan >>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> On 2020/07/02 15:05, David Holmes wrote: >>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>> >>>>>>>>>>>>> On 1/07/2020 11:53 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>> Hi, >>>>>>>>>>>>>> >>>>>>>>>>>>>> I uploaded new webrev. Could review again? >>>>>>>>>>>>>> >>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.02/ >>>>>>>>>>>>> >>>>>>>>>>>>> Updates look fine - thanks. >>>>>>>>>>>>> >>>>>>>>>>>>> One minor nit: >>>>>>>>>>>>> >>>>>>>>>>>>> 1274 _collector.allocate_and_fill_stacks(1); >>>>>>>>>>>>> 1275 _collector.set_result(JVMTI_ERROR_NONE); >>>>>>>>>>>>> >>>>>>>>>>>>> In the other places where you use _collector you rely on >>>>>>>>>>>>> result being initialized to JVMTI_ERROR_NONE, rather than >>>>>>>>>>>>> setting it directly after allocate_and_fill_stacks(). >>>>>>>>>>>> >>>>>>>>>>>> Fixed. >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> ? 820 assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>>>>>>> ? 821 java_thread->is_thread_fully_suspended(false, >>>>>>>>>>>>>>>>>>> &debug_bits) || >>>>>>>>>>>>>>>>>>> ? 822????????? current_thread == >>>>>>>>>>>>>>>>>>> java_thread->active_handshaker(), >>>>>>>>>>>>>>>>>>> ? 823????????? "at safepoint / handshake or target >>>>>>>>>>>>>>>>>>> thread is suspended"); >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> I don't think the suspension check is necessary, as >>>>>>>>>>>>>>>>>>> even if the target is suspended we must still be at >>>>>>>>>>>>>>>>>>> a safepoint or in a handshake with it. Makes me >>>>>>>>>>>>>>>>>>> wonder if we used to allow a racy stacktrace >>>>>>>>>>>>>>>>>>> operation on a suspended thread, assuming it would >>>>>>>>>>>>>>>>>>> remain suspended? >>>>>>>>>>>>>> >>>>>>>>>>>>>> This function (JvmtiEnvBase::get_stack_trace()) can be >>>>>>>>>>>>>> called to get own stack trace. For example, we can call >>>>>>>>>>>>>> GetStackTrace() for current thread at JVMTI event. >>>>>>>>>>>>>> So I changed assert as below: >>>>>>>>>>>>>> >>>>>>>>>>>>>> ``` >>>>>>>>>>>>>> ??820?? assert(current_thread == java_thread || >>>>>>>>>>>>>> ??821 SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>> ??822????????? current_thread == >>>>>>>>>>>>>> java_thread->active_handshaker(), >>>>>>>>>>>>>> ??823????????? "call by myself / at safepoint / at >>>>>>>>>>>>>> handshake"); >>>>>>>>>>>>>> ``` >>>>>>>>>>>>> >>>>>>>>>>>>> Yep good catch. I hope current tests caught that. >>>>>>>>>>>> >>>>>>>>>>>> They would be tested in >>>>>>>>>>>> vmTestbase/nsk/jvmti/GetStackTrace/getstacktr001/ (own call >>>>>>>>>>>> stacks), and getstacktr003 (call stacks in other thread). >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>>> Speaking of tests ... >>>>>>>>>>>>> >>>>>>>>>>>>> In the native code I think you need to check the success >>>>>>>>>>>>> of all JNI methods that can throw exceptions - otherwise I >>>>>>>>>>>>> believe the tests may trigger warnings if -Xcheck:jni is >>>>>>>>>>>>> used with them. See for example: >>>>>>>>>>>>> >>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/libHeapMonitorTest.cpp >>>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> I updated testcases to check JNI and JVMTI function calls. >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>>> In the Java code the target thread: >>>>>>>>>>>>> >>>>>>>>>>>>> ?? 45???? public void run() { >>>>>>>>>>>>> ?? 46?????? try { >>>>>>>>>>>>> ?? 47?????????? synchronized (lock) { >>>>>>>>>>>>> ?? 48?????????????? lock.wait(); >>>>>>>>>>>>> ?? 49 System.out.println("OK"); >>>>>>>>>>>>> ?? 50?????????? } >>>>>>>>>>>>> >>>>>>>>>>>>> is potentially susceptible to spurious wakeups. Using a >>>>>>>>>>>>> CountDownLatch would be robust. >>>>>>>>>>>> >>>>>>>>>>>> Fixed. >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> Thanks, >>>>>>>>>>>> >>>>>>>>>>>> Yasumasa >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>>> Thanks, >>>>>>>>>>>>> David >>>>>>>>>>>>> ----- >>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>> >>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> On 2020/07/01 8:48, David Holmes wrote: >>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> On 1/07/2020 9:05 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> 1271 ResourceMark rm; >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> IIUC at this point the _calling_thread is the >>>>>>>>>>>>>>>>>>> current thread, so we can use: >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> If so, we can call make_local() in L1272 without >>>>>>>>>>>>>>>> JavaThread (or we can pass current thread to >>>>>>>>>>>>>>>> make_local()). Is it right? >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>>>>>>>> 1272 >>>>>>>>>>>>>>>> _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, >>>>>>>>>>>>>>>> thread_oop), >>>>>>>>>>>>>>>> 1273??????????????????????????? jt, thread_oop); >>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Sorry I got confused, _calling_thread may not be the >>>>>>>>>>>>>>> current thread as we could be executing the handshake in >>>>>>>>>>>>>>> the target thread itself. So the ResourceMark is correct >>>>>>>>>>>>>>> as-is (implicitly for current thread). >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> The argument to fill_frames will be used in the >>>>>>>>>>>>>>> jvmtiStackInfo and passed back to the _calling_thread, >>>>>>>>>>>>>>> so it must be created via make_local(_calling_thread, >>>>>>>>>>>>>>> ...) as you presently have. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>> David >>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> On 2020/07/01 7:05, David Holmes wrote: >>>>>>>>>>>>>>>>> On 1/07/2020 12:17 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Thank you for reviewing! I will update new webrev >>>>>>>>>>>>>>>>>> tomorrow. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> 466 class MultipleStackTracesCollector : public >>>>>>>>>>>>>>>>>>> StackObj { >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> ? 498 class VM_GetAllStackTraces : public >>>>>>>>>>>>>>>>>>> VM_Operation { >>>>>>>>>>>>>>>>>>> ? 499 private: >>>>>>>>>>>>>>>>>>> ? 500?? JavaThread *_calling_thread; >>>>>>>>>>>>>>>>>>> ? 501?? jint _final_thread_count; >>>>>>>>>>>>>>>>>>> ? 502 MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> You can't have a StackObj as a member of another >>>>>>>>>>>>>>>>>>> class like that as it may not be on the stack. I >>>>>>>>>>>>>>>>>>> think MultipleStackTracesCollector should not extend >>>>>>>>>>>>>>>>>>> any allocation class, and should always be embedded >>>>>>>>>>>>>>>>>>> directly in another class. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> I'm not sure what does mean "embedded". >>>>>>>>>>>>>>>>>> Is it ok as below? >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>> class MultipleStackTracesCollector { >>>>>>>>>>>>>>>>>> ??? : >>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> class GetAllStackTraces : public VM_Operation { >>>>>>>>>>>>>>>>>> ?? private: >>>>>>>>>>>>>>>>>> MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Yes that I what I meant. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> On 2020/06/30 22:22, David Holmes wrote: >>>>>>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> On 30/06/2020 10:05 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>> Hi David, Serguei, >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> I updated webrev for 8242428. Could you review again? >>>>>>>>>>>>>>>>>>>> This change migrate to use direct handshake for >>>>>>>>>>>>>>>>>>>> GetStackTrace() and GetThreadListStackTraces() >>>>>>>>>>>>>>>>>>>> (when thread_count == 1). >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.01/ >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> This looks really good now! I only have a few nits >>>>>>>>>>>>>>>>>>> below. There is one thing I don't like about it but >>>>>>>>>>>>>>>>>>> it requires a change to the main Handshake logic to >>>>>>>>>>>>>>>>>>> address - in JvmtiEnv::GetThreadListStackTraces you >>>>>>>>>>>>>>>>>>> have to create a ThreadsListHandle to convert the >>>>>>>>>>>>>>>>>>> jthread to a JavaThread, but then the >>>>>>>>>>>>>>>>>>> Handshake::execute_direct creates another >>>>>>>>>>>>>>>>>>> ThreadsListHandle internally. That's a waste. I will >>>>>>>>>>>>>>>>>>> discuss with Robbin and file a RFE to have an >>>>>>>>>>>>>>>>>>> overload of execute_direct that takes an existing >>>>>>>>>>>>>>>>>>> TLH. Actually it's worse than that because we have >>>>>>>>>>>>>>>>>>> another TLH in use at the entry point for the JVMTI >>>>>>>>>>>>>>>>>>> functions, so I think there may be some scope for >>>>>>>>>>>>>>>>>>> simplifying the use of TLH instances - future RFE. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> ??451 GetStackTraceClosure(JvmtiEnv *env, jint >>>>>>>>>>>>>>>>>>> start_depth, jint max_count, >>>>>>>>>>>>>>>>>>> ??452 jvmtiFrameInfo* frame_buffer, jint* count_ptr) >>>>>>>>>>>>>>>>>>> ??453???? : HandshakeClosure("GetStackTrace"), >>>>>>>>>>>>>>>>>>> ??454?????? _env(env), _start_depth(start_depth), >>>>>>>>>>>>>>>>>>> _max_count(max_count), >>>>>>>>>>>>>>>>>>> ??455 _frame_buffer(frame_buffer), >>>>>>>>>>>>>>>>>>> _count_ptr(count_ptr), >>>>>>>>>>>>>>>>>>> ??456 _result(JVMTI_ERROR_THREAD_NOT_ALIVE) { >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Nit: can you do one initializer per line please. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> This looks wrong: >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> 466 class MultipleStackTracesCollector : public >>>>>>>>>>>>>>>>>>> StackObj { >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> ??498 class VM_GetAllStackTraces : public >>>>>>>>>>>>>>>>>>> VM_Operation { >>>>>>>>>>>>>>>>>>> ??499 private: >>>>>>>>>>>>>>>>>>> ??500?? JavaThread *_calling_thread; >>>>>>>>>>>>>>>>>>> ??501?? jint _final_thread_count; >>>>>>>>>>>>>>>>>>> ??502 MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> You can't have a StackObj as a member of another >>>>>>>>>>>>>>>>>>> class like that as it may not be on the stack. I >>>>>>>>>>>>>>>>>>> think MultipleStackTracesCollector should not extend >>>>>>>>>>>>>>>>>>> any allocation class, and should always be embedded >>>>>>>>>>>>>>>>>>> directly in another class. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> 481 MultipleStackTracesCollector(JvmtiEnv *env, jint >>>>>>>>>>>>>>>>>>> max_frame_count) { >>>>>>>>>>>>>>>>>>> ??482???? _env = env; >>>>>>>>>>>>>>>>>>> ??483???? _max_frame_count = max_frame_count; >>>>>>>>>>>>>>>>>>> ??484???? _frame_count_total = 0; >>>>>>>>>>>>>>>>>>> ??485???? _head = NULL; >>>>>>>>>>>>>>>>>>> ??486???? _stack_info = NULL; >>>>>>>>>>>>>>>>>>> ??487???? _result = JVMTI_ERROR_NONE; >>>>>>>>>>>>>>>>>>> ??488?? } >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> As you are touching this can you change it to use an >>>>>>>>>>>>>>>>>>> initializer list as you did for the >>>>>>>>>>>>>>>>>>> HandshakeClosure, and please keep one item per line. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> ??820 assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>>>>>>> ??821 java_thread->is_thread_fully_suspended(false, >>>>>>>>>>>>>>>>>>> &debug_bits) || >>>>>>>>>>>>>>>>>>> ??822????????? current_thread == >>>>>>>>>>>>>>>>>>> java_thread->active_handshaker(), >>>>>>>>>>>>>>>>>>> ??823????????? "at safepoint / handshake or target >>>>>>>>>>>>>>>>>>> thread is suspended"); >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> I don't think the suspension check is necessary, as >>>>>>>>>>>>>>>>>>> even if the target is suspended we must still be at >>>>>>>>>>>>>>>>>>> a safepoint or in a handshake with it. Makes me >>>>>>>>>>>>>>>>>>> wonder if we used to allow a racy stacktrace >>>>>>>>>>>>>>>>>>> operation on a suspended thread, assuming it would >>>>>>>>>>>>>>>>>>> remain suspended? >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> 1268?? oop thread_oop = jt->threadObj(); >>>>>>>>>>>>>>>>>>> 1269 >>>>>>>>>>>>>>>>>>> 1270?? if (!jt->is_exiting() && (jt->threadObj() != >>>>>>>>>>>>>>>>>>> NULL)) { >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> You can use thread_oop in line 1270. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> 1272 >>>>>>>>>>>>>>>>>>> _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, >>>>>>>>>>>>>>>>>>> thread_oop), >>>>>>>>>>>>>>>>>>> 1273 jt, thread_oop); >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> It is frustrating that this entire call chain >>>>>>>>>>>>>>>>>>> started with a jthread reference, which we converted >>>>>>>>>>>>>>>>>>> to a JavaThread, only to eventually need to convert >>>>>>>>>>>>>>>>>>> it back to a jthread! I think there is some scope >>>>>>>>>>>>>>>>>>> for simplification here but not as part of this change. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> IIUC at this point the _calling_thread is the >>>>>>>>>>>>>>>>>>> current thread, so we can use: >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Please add @bug lines to the tests. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> I'm still pondering the test logic but wanted to >>>>>>>>>>>>>>>>>>> send this now. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>>>>> VM_GetThreadListStackTrace (for >>>>>>>>>>>>>>>>>>>> GetThreadListStackTraces) and VM_GetAllStackTraces >>>>>>>>>>>>>>>>>>>> (for GetAllStackTraces) have inherited >>>>>>>>>>>>>>>>>>>> VM_GetMultipleStackTraces VM operation which >>>>>>>>>>>>>>>>>>>> provides the feature to generate jvmtiStackInfo. I >>>>>>>>>>>>>>>>>>>> modified VM_GetMultipleStackTraces to a normal C++ >>>>>>>>>>>>>>>>>>>> class to share with HandshakeClosure for >>>>>>>>>>>>>>>>>>>> GetThreadListStackTraces (GetSingleStackTraceClosure). >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Also I added new testcases which test >>>>>>>>>>>>>>>>>>>> GetThreadListStackTraces() with thread_count == 1 >>>>>>>>>>>>>>>>>>>> and with all threads. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> This change has been tested in serviceability/jvmti >>>>>>>>>>>>>>>>>>>> serviceability/jdwp vmTestbase/nsk/jvmti >>>>>>>>>>>>>>>>>>>> vmTestbase/nsk/jdi vmTestbase/nsk/jdwp. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> On 2020/06/24 15:50, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>> Hi all, >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Please review this change: >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> ?? JBS: >>>>>>>>>>>>>>>>>>>>> https://bugs.openjdk.java.net/browse/JDK-8242428 >>>>>>>>>>>>>>>>>>>>> ?? webrev: >>>>>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.00/ >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> This change replace following VM operations to >>>>>>>>>>>>>>>>>>>>> direct handshake. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> ??- VM_GetFrameCount (GetFrameCount()) >>>>>>>>>>>>>>>>>>>>> ??- VM_GetFrameLocation (GetFrameLocation()) >>>>>>>>>>>>>>>>>>>>> ??- VM_GetThreadListStackTraces >>>>>>>>>>>>>>>>>>>>> (GetThreadListStackTrace()) >>>>>>>>>>>>>>>>>>>>> ??- VM_GetCurrentLocation >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> GetThreadListStackTrace() uses direct handshake if >>>>>>>>>>>>>>>>>>>>> thread count == 1. In other case (thread count > >>>>>>>>>>>>>>>>>>>>> 1), it would be performed as VM operation >>>>>>>>>>>>>>>>>>>>> (VM_GetThreadListStackTraces). >>>>>>>>>>>>>>>>>>>>> Caller of VM_GetCurrentLocation >>>>>>>>>>>>>>>>>>>>> (JvmtiEnvThreadState::reset_current_location()) >>>>>>>>>>>>>>>>>>>>> might be called at safepoint. So I added safepoint >>>>>>>>>>>>>>>>>>>>> check in its caller. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> This change has been tested in >>>>>>>>>>>>>>>>>>>>> serviceability/jvmti serviceability/jdwp >>>>>>>>>>>>>>>>>>>>> vmTestbase/nsk/jvmti vmTestbase/nsk/jdi vmTestbase/ns >>>>>>>>>>>>>>>>>>>>> k/jdwp. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Also I tested it on submit repo, then it has >>>>>>>>>>>>>>>>>>>>> execution error >>>>>>>>>>>>>>>>>>>>> (mach5-one-ysuenaga-JDK-8242428-20200624-0054-12034717) >>>>>>>>>>>>>>>>>>>>> due to dependency error. So I think it does not >>>>>>>>>>>>>>>>>>>>> occur by this change. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>> >>>>>>>> >>>> >> From suenaga at oss.nttdata.com Sun Jul 5 13:13:03 2020 From: suenaga at oss.nttdata.com (Yasumasa Suenaga) Date: Sun, 5 Jul 2020 22:13:03 +0900 Subject: RFR: 8242428: JVMTI thread operations should use Thread-Local Handshake In-Reply-To: <4c43bc2c-551e-d042-8fa7-b63e755888d1@oracle.com> References: <6c263e4c-0a83-be7a-0288-ecb2de0b7cea@oss.nttdata.com> <74c05dfd-ffb2-b73d-66e5-dc98752729f5@oss.nttdata.com> <763793b1-9506-44c6-0681-1c71c44a44fd@oss.nttdata.com> <5107c478-1de2-7a49-ee71-dfad6a99a667@oracle.com> <90cdfef9-e558-0d25-33f5-25b7d65bb83b@oss.nttdata.com> <0e359819-618f-c17b-a427-bb7e4daa2c58@oracle.com> <3f890bed-6892-e64d-b21b-ca0cbe11784e@oracle.com> <7dc1903b-6295-3864-6301-4c02aacdb971@oss.nttdata.com> <04e09eb7-9483-8f63-4bb4-01c9e814802e@oracle.com> <238a89a3-06b1-90e4-d5a4-8dc2f1ed12ab@oracle.com> <4c43bc2c-551e-d042-8fa7-b63e755888d1@oracle.com> Message-ID: Hi Serguei, Thanks for your comment! I refactored testcase. Could you review again? http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.05/ It would check Java exception after IsSameObject() call. Does it need? Any exceptions are not described in JNI document[1], and JNI implementation (jni_IsSameObject()) does not seem to throw it. Thanks, Yasumasa [1] https://docs.oracle.com/en/java/javase/14/docs/specs/jni/functions.html#issameobject On 2020/07/05 14:46, serguei.spitsyn at oracle.com wrote: > Hi Yasumasa, > > > Okay, thanks. > Then I'm okay to keep the GetSingleStackTraceClosure. > > > http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libGetThreadListStackTraces.c.html > http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.c.html > > I'm not sure the function 'is_same_thread() is needed. > Why do not use the JNI IsSameObject instead? > > It seems to be a typo at L132 and L137. > You, probably. did not want to print the same information for stack_info_1[i].frame_buffer[j].XXX twice. > > The code at lines 112-142 is not readable. > I'd suggest to make a couple of refactoring steps. > > First step to simplify this a little bit would be with some renaming and getting rid of indexes: > > ? 71 char err_msg[EXCEPTION_MSG_LEN] = {0}; > ?... > ?112?? /* Iterate all jvmtiStackInfo to check */ > ?113?? for (i = 0; i < num_threads, *exception_msg != '\0'; i++) { > ???????? jvmtiStackInfo *si1 = stack_info_1[i]; > ???????? jvmtiStackInfo *si2 = stack_info_2[i]; > ?114???? if (!IsSameObject(env, si1.thread, si2.thread)) { /* jvmtiStackInfo::thread */ > ?115?????? snprintf(err_msg, sizeof(err_msg), > ?116??????????????? "thread[%d] is different: stack_info_1 = %p, stack_info_2 = %p", > ?117??????????????? i, sinfo1.thread, sinfo2.thread); > ?118???? } else if (si1.state != si2.state) { /* jvmtiStackInfo::state */ > ?119?????? snprintf(err_msg, sizeof(err_msg), > ?120??????????????? "state[%d] is different: stack_info_1 = %d, stack_info_2 = %d", > ?121??????????????? i, si1.state, si2.state); > ?122???? } else if (si1.frame_count != si2.frame_count) { /* jvmtiStackInfo::frame_count */ > ?123?????? snprintf(err_msg, sizeof(err_msg), > ?124??????????????? "frame_count[%d] is different: stack_info_1 = %d, stack_info_2 = %d", > ?125??????????????? i, si1.frame_count, si2.frame_count); > ?126???? } else { > ?127?????? /* Iterate all jvmtiFrameInfo to check */ > ?128?????? for (j = 0; j < si1.frame_count; j++) { > ?129???????? if (si1.frame_buffer[j].method != si1.frame_buffer[j].method) { /* jvmtiFrameInfo::method */ > ?130?????????? snprintf(err_msg, sizeof(err_msg), > ?131??????????????????? "thread [%d] frame_buffer[%d].method is different: stack_info_1 = %lx, stack_info_2 = %lx", > ?132??????????????????? i, j, si1.frame_buffer[j].method, si2.frame_buffer[j].method); > ?133?????????? break; > ?134???????? } else if (si1.frame_buffer[j].location != si1.frame_buffer[j].location) { /* jvmtiFrameInfo::location */ > ?135?????????? snprintf(err_msg, sizeof(err_msg), > ?136??????????????????? "thread [%d] frame_buffer[%d].location is different: stack_info_1 = %ld, stack_info_2 = %ld", > ?137??????????????????? i, j, si1.frame_buffer[j].location, si2.frame_buffer[j].location); > ?138?????????? break; > ?139???????? } > ?140?????? } > ?141???? } > ?142?? } > > Another step would be to create functions that implement a body of each loop. > You can use the same techniques to simplify similar place (L127-L138) in the libOneGetThreadListStackTraces.c. > > Thanks, > Serguei > > > On 7/3/20 15:55, Yasumasa Suenaga wrote: >> Hi Serguei, >> >> I'm not an Oracle employee, so I cannot know real request(s) from your customers. >> However JDK-8201641 says Dynatrace has requested this enhancement. >> >> BTW I haven't heared any request from my customers about this. >> >> >> Thanks, >> >> Yasumasa >> >> >> On 2020/07/04 4:32, serguei.spitsyn at oracle.com wrote: >>> Hi Yasumasa, >>> >>> This difference is not that big to care about. >>> I feel this is really rare case and so, does not worth these complications. >>> Do we have a real request from customers to optimize it? >>> >>> Thanks, >>> Serguei >>> >>> >>> On 7/3/20 01:16, Yasumasa Suenaga wrote: >>>> Hi Serguei, >>>> >>>> Generally I agree with you, but I have concern about the difference of the result of GetStackTrace() and GetThreadListStackTraces(). >>>> >>>> ? GetStackTrace: jvmtiFrameInfo >>>> ? GetThreadListStackTraces: jvmtiStackInfo >>>> >>>> jvmtiStackInfo contains thread state, and it is ensured it is the state of the call stack. >>>> If we want to get both call stack and thread state, we need to suspend target thread, and call both GetStackTrace() and GetThreadState(). Is it ok? >>>> >>>> I was wondering if JDK-8201641 (parent ticket of this change) needed them for profiling (dynatrace?) >>>> If it is responsibility of JVMTI agent implementor, I remove this closure. >>>> >>>> >>>> Thanks, >>>> >>>> Yasumasa >>>> >>>> >>>> On 2020/07/03 16:45, serguei.spitsyn at oracle.com wrote: >>>>> Hi Yasumasa, >>>>> >>>>> After some thinking I've concluded that I do not like this optimization >>>>> of the GetThreadListStackTraces with GetSingleStackTraceClosure. >>>>> >>>>> We may need more opinions on this but these are my points: >>>>> ??- it adds some complexity and ugliness >>>>> ??- a win is doubtful because it has to be a rare case, so that total overhead should not be high >>>>> ??- if it is really high for some use cases then it is up to the user >>>>> ??? to optimize it with using GetStackTrace instead >>>>> >>>>> In such cases with doubtful overhead I usually prefer the simplicity. >>>>> >>>>> Good examples where it makes sense to optimize are checks for target thread to be current thread. >>>>> In such cases there is no need to suspend the target thread, or use a VMop/HandshakeClosure. >>>>> For instance, please, see the Monitor functions with the check: (java_thread == calling_thread). >>>>> Getting information for current thread is frequently used case, e.g. to get info at an event point. >>>>> >>>>> Thanks, >>>>> Serguei >>>>> >>>>> >>>>> On 7/2/20 23:29, Yasumasa Suenaga wrote: >>>>>> Hi Dan, David, >>>>>> >>>>>> I uploaded new webrev. Could you review again? >>>>>> >>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/ >>>>>> >>>>>> OneGetThreadListStackTraces.java in this webrev would wait until thread state is transited to "waiting" with spin wait. >>>>>> CountDownLatch::await call as Dan pointed is fixed in it :) >>>>>> >>>>>> Diff from webrev.03: >>>>>> http://hg.openjdk.java.net/jdk/submit/rev/c9aeb7001e50 >>>>>> >>>>>> >>>>>> Thanks, >>>>>> >>>>>> Yasumasa >>>>>> >>>>>> >>>>>> On 2020/07/03 14:15, David Holmes wrote: >>>>>>> >>>>>>> >>>>>>> On 3/07/2020 2:27 pm, Yasumasa Suenaga wrote: >>>>>>>> On 2020/07/03 12:24, Daniel D. Daugherty wrote: >>>>>>>>> On 7/2/20 10:50 PM, David Holmes wrote: >>>>>>>>>> Sorry I'm responding here without seeing latest webrev but there is enough context I think ... >>>>>>>>>> >>>>>>>>>> On 3/07/2020 9:14 am, Yasumasa Suenaga wrote: >>>>>>>>>>> Hi Dan, >>>>>>>>>>> >>>>>>>>>>> Thanks for your comment! >>>>>>>>>>> >>>>>>>>>>> On 2020/07/03 7:16, Daniel D. Daugherty wrote: >>>>>>>>>>>> On 7/2/20 5:19 AM, Yasumasa Suenaga wrote: >>>>>>>>>>>>> Hi David, >>>>>>>>>>>>> >>>>>>>>>>>>> I upload new webrev. Could you review again? >>>>>>>>>>>>> >>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.03/ >>>>>>>>>>>> >>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnv.cpp >>>>>>>>>>>> ???? L1542: ??? // Get stack trace with handshake >>>>>>>>>>>> ???????? nit - please add a period at the end. >>>>>>>>>>> >>>>>>>>>>> I will fix it. >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>>> ???? L1591: *stack_info_ptr = op.stack_info(); >>>>>>>>>>>> ???????? The return parameter should not be touched unless the return >>>>>>>>>>>> ???????? code in 'err' == JVMTI_ERROR_NONE. >>>>>>>>>>>> >>>>>>>>>>>> ???? old L1582: ? if (err == JVMTI_ERROR_NONE) { >>>>>>>>>>>> ???????? Please restore this check. The return parameter should not >>>>>>>>>>>> ???????? be touched unless the return code in 'err' == JVMTI_ERROR_NONE. >>>>>>>>>>> >>>>>>>>>>> I will fix it. >>>>>>>>>> >>>>>>>>>> But op.stack_info() will return NULL if the error is not JVMTI_ERROR_NONE. Are you (Dan) concerned about someone passing in a non-null/initialized out-pointer that will be reset to NULL if there was an error? >>>>>>>>> >>>>>>>>> Actually the way we used to test this in POSIX tests is to call >>>>>>>>> an API with known bad parameters and the return parameter ptr >>>>>>>>> set to NULL. If the return parameter ptr was touched when an >>>>>>>>> error should have been detected on an earlier parameter, then >>>>>>>>> the test failed. >>>>>>>>> >>>>>>>>> >>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>>> ???? L1272: ? if (!jt->is_exiting() && (thread_oop != NULL)) { >>>>>>>>>>>> ???????? nit - extra parens around the second expression. >>>>>>>>>>> >>>>>>>>>>> I will fix it. >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>> ???? old L1532: ? _result = JVMTI_ERROR_THREAD_NOT_ALIVE; >>>>>>>>>>>> ???????? This deletion of the _result field threw me for a minute and then >>>>>>>>>>>> ???? ? ? I figured out that the field is init to JVMTI_ERROR_THREAD_NOT_ALIVE >>>>>>>>>>>> ???????? in the constructor. >>>>>>>>>>>> >>>>>>>>>>>> ???? L1553: ? if (!jt->is_exiting() && (jt->threadObj() != NULL)) { >>>>>>>>>>>> ???????? nit - extra parens around the second expression. >>>>>>>>>>> >>>>>>>>>>> I will fix it. >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>>>>>>>> ???? No comments. >>>>>>>>>>>> >>>>>>>>>>>> src/hotspot/share/runtime/vmOperations.hpp >>>>>>>>>>>> ???? No comments. >>>>>>>>>>>> >>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/GetThreadListStackTraces.java >>>>>>>>>>>> ???? No comments. >>>>>>>>>>>> >>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/OneGetThreadListStackTraces.java >>>>>>>>>>>> ???? L64: ??????? startSignal.countDown(); >>>>>>>>>>>> ???????? I was expecting this to be a call to await() instead of >>>>>>>>>>>> ???????? countDown(). What am I missing here? >>>>>>>>>>>> >>>>>>>>>>>> ???????? I think this test might be passing by accident right now, but... >>>>>>>>>>> >>>>>>>>>>> Main thread (which call JVMTI functions to test) should wait until test thread is ready. >>>>>>>>>>> So main thread would wait startSignal, and test thread would count down. >>>>>>>>>> >>>>>>>>>> No! >>>>>>>>>> >>>>>>>>>> The test thread that previously called obj.wait() now calls latch.await(). >>>>>>>>>> >>>>>>>>>> The main thread that previously called obj.notify() now calls latch.countDown(). >>>>>>>>>> >>>>>>>>>> The main thread continues to spin until it sees the target is WAITING before proceeding with the test. >>>>>>>> >>>>>>>> If I add spin wait to wait until transit target thread state is WAITING (as following), we don't need to call SuspendThread(). >>>>>>>> Which is better? >>>>>>> >>>>>>> The original spin-wait loop checking for? WAITING is better because it is the only guarantee that the target thread is blocked where you need it to be. suspending the thread is racy as you don't know exactly where the suspend will hit. >>>>>>> >>>>>>> Thanks, >>>>>>> David >>>>>>> ----- >>>>>>> >>>>>>>> >>>>>>>> ``` >>>>>>>> /* Wait until the thread state transits to "waiting" */ >>>>>>>> while (th.getState() != Thread.State.WAITING) { >>>>>>>> ???? Thread.onSpinWait(); >>>>>>>> } >>>>>>>> ``` >>>>>>>> >>>>>>>> For simplify, spin wait is prefer to OneGetThreadListStackTraces.java in webrev.03. >>>>>>>> >>>>>>>> >>>>>>>> Thanks, >>>>>>>> >>>>>>>> Yasumasa >>>>>>>> >>>>>>>> >>>>>>>>> Here's the flow as I see it: >>>>>>>>> >>>>>>>>> main thread >>>>>>>>> ?? - start worker thread >>>>>>>>> ?? - startSignal.await() >>>>>>>>> ???? - main is now blocked >>>>>>>>> >>>>>>>>> worker thread >>>>>>>>> ?? - startSignal.countDown() >>>>>>>>> ???? - main is now unblocked >>>>>>>>> ?? - stopSignal.await() >>>>>>>>> ???? - worker is now blocked >>>>>>>>> >>>>>>>>> main thread >>>>>>>>> ?? - checkCallStacks(th) >>>>>>>>> ?? - stopSignal.countDown() >>>>>>>>> ???? - worker is now unblocked >>>>>>>>> ?? - th.join >>>>>>>>> ???? - main is now blocked >>>>>>>>> >>>>>>>>> worker thread >>>>>>>>> ?? - runs off the end of run() >>>>>>>>> ???? - main is now unblocked >>>>>>>>> >>>>>>>>> main thread >>>>>>>>> ?? - run off the end of main() >>>>>>>>> >>>>>>>>> >>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libGetThreadListStackTraces.c >>>>>>>>>>>> ???? L92: ? jthreads = (jthread *)malloc(sizeof(jthread) * num_threads); >>>>>>>>>>>> ???????? You don't check for malloc() failure. >>>>>>>>>>>> ???????? 'jthreads' is allocated but never freed. >>>>>>>>>>> >>>>>>>>>>> I will fix it. >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.c >>>>>>>>>>>> ???? L91: ? result = (*jvmti)->SuspendThread(jvmti, thread); >>>>>>>>>>>> ???????? Why are you suspending the thread? GetAllStackTraces() and >>>>>>>>>>>> ???????? GetThreadListStackTraces() do not require the target thread(s) >>>>>>>>>>>> ???????? to be suspend. >>>>>>>>>>>> >>>>>>>>>>>> ???????? If you decide not to SuspendThread, then you don't need the >>>>>>>>>>>> ???????? AddCapabilities or the ResumeThread calls. >>>>>>>>>>> >>>>>>>>>>> Test thread might not be entered following code (stopSignal.await()). We might see deferent call stack between GetAllStackTraces() and GetThreadListStackTraces(). We cannot control to freeze call stack of test thread in Java code. >>>>>>>>>>> (I didn't use SuspendThread() at first, but I saw some errors which causes in above.) >>>>>>>>>>> >>>>>>>>>>> So we need to call SuspendThread() to ensure we can see same call stack. >>>>>>>>>> >>>>>>>>>> If you are checking that the thread is in state WAITING then it cannot escape from that state and you can sample the stack multiple times from any API and get the same result. >>>>>>>>>> >>>>>>>>>> I suspect the errors you saw were from the apparent incorrect use of the CountDownLatch. >>>>>>>>> >>>>>>>>> With the flow outlined above, the worker thread should be >>>>>>>>> nicely blocked in stopSignal.await() when stuff is sampled. >>>>>>>>> >>>>>>>>> Dan >>>>>>>>> >>>>>>>>> >>>>>>>>>> >>>>>>>>>> Cheers, >>>>>>>>>> David >>>>>>>>>> ----- >>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> Thanks, >>>>>>>>>>> >>>>>>>>>>> Yasumasa >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>>> Dan >>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> On 2020/07/02 15:05, David Holmes wrote: >>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>> >>>>>>>>>>>>>> On 1/07/2020 11:53 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>> Hi, >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> I uploaded new webrev. Could review again? >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.02/ >>>>>>>>>>>>>> >>>>>>>>>>>>>> Updates look fine - thanks. >>>>>>>>>>>>>> >>>>>>>>>>>>>> One minor nit: >>>>>>>>>>>>>> >>>>>>>>>>>>>> 1274 _collector.allocate_and_fill_stacks(1); >>>>>>>>>>>>>> 1275 _collector.set_result(JVMTI_ERROR_NONE); >>>>>>>>>>>>>> >>>>>>>>>>>>>> In the other places where you use _collector you rely on result being initialized to JVMTI_ERROR_NONE, rather than setting it directly after allocate_and_fill_stacks(). >>>>>>>>>>>>> >>>>>>>>>>>>> Fixed. >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> ? 820 assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>>>>>>>> ? 821 java_thread->is_thread_fully_suspended(false, &debug_bits) || >>>>>>>>>>>>>>>>>>>> ? 822????????? current_thread == java_thread->active_handshaker(), >>>>>>>>>>>>>>>>>>>> ? 823????????? "at safepoint / handshake or target thread is suspended"); >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> I don't think the suspension check is necessary, as even if the target is suspended we must still be at a safepoint or in a handshake with it. Makes me wonder if we used to allow a racy stacktrace operation on a suspended thread, assuming it would remain suspended? >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> This function (JvmtiEnvBase::get_stack_trace()) can be called to get own stack trace. For example, we can call GetStackTrace() for current thread at JVMTI event. >>>>>>>>>>>>>>> So I changed assert as below: >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>> ??820?? assert(current_thread == java_thread || >>>>>>>>>>>>>>> ??821 SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>>> ??822????????? current_thread == java_thread->active_handshaker(), >>>>>>>>>>>>>>> ??823????????? "call by myself / at safepoint / at handshake"); >>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>> >>>>>>>>>>>>>> Yep good catch. I hope current tests caught that. >>>>>>>>>>>>> >>>>>>>>>>>>> They would be tested in vmTestbase/nsk/jvmti/GetStackTrace/getstacktr001/ (own call stacks), and getstacktr003 (call stacks in other thread). >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>>> Speaking of tests ... >>>>>>>>>>>>>> >>>>>>>>>>>>>> In the native code I think you need to check the success of all JNI methods that can throw exceptions - otherwise I believe the tests may trigger warnings if -Xcheck:jni is used with them. See for example: >>>>>>>>>>>>>> >>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/libHeapMonitorTest.cpp >>>>>>>>>>>>> >>>>>>>>>>>>> I updated testcases to check JNI and JVMTI function calls. >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>>> In the Java code the target thread: >>>>>>>>>>>>>> >>>>>>>>>>>>>> ?? 45???? public void run() { >>>>>>>>>>>>>> ?? 46?????? try { >>>>>>>>>>>>>> ?? 47?????????? synchronized (lock) { >>>>>>>>>>>>>> ?? 48?????????????? lock.wait(); >>>>>>>>>>>>>> ?? 49 System.out.println("OK"); >>>>>>>>>>>>>> ?? 50?????????? } >>>>>>>>>>>>>> >>>>>>>>>>>>>> is potentially susceptible to spurious wakeups. Using a CountDownLatch would be robust. >>>>>>>>>>>>> >>>>>>>>>>>>> Fixed. >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> Thanks, >>>>>>>>>>>>> >>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>> David >>>>>>>>>>>>>> ----- >>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> On 2020/07/01 8:48, David Holmes wrote: >>>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> On 1/07/2020 9:05 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> 1271 ResourceMark rm; >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> IIUC at this point the _calling_thread is the current thread, so we can use: >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> If so, we can call make_local() in L1272 without JavaThread (or we can pass current thread to make_local()). Is it right? >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>>>>>>>>> 1272 _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, thread_oop), >>>>>>>>>>>>>>>>> 1273??????????????????????????? jt, thread_oop); >>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Sorry I got confused, _calling_thread may not be the current thread as we could be executing the handshake in the target thread itself. So the ResourceMark is correct as-is (implicitly for current thread). >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> The argument to fill_frames will be used in the jvmtiStackInfo and passed back to the _calling_thread, so it must be created via make_local(_calling_thread, ...) as you presently have. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> On 2020/07/01 7:05, David Holmes wrote: >>>>>>>>>>>>>>>>>> On 1/07/2020 12:17 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Thank you for reviewing! I will update new webrev tomorrow. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> 466 class MultipleStackTracesCollector : public StackObj { >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> ? 498 class VM_GetAllStackTraces : public VM_Operation { >>>>>>>>>>>>>>>>>>>> ? 499 private: >>>>>>>>>>>>>>>>>>>> ? 500?? JavaThread *_calling_thread; >>>>>>>>>>>>>>>>>>>> ? 501?? jint _final_thread_count; >>>>>>>>>>>>>>>>>>>> ? 502 MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> You can't have a StackObj as a member of another class like that as it may not be on the stack. I think MultipleStackTracesCollector should not extend any allocation class, and should always be embedded directly in another class. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> I'm not sure what does mean "embedded". >>>>>>>>>>>>>>>>>>> Is it ok as below? >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>> class MultipleStackTracesCollector { >>>>>>>>>>>>>>>>>>> ??? : >>>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> class GetAllStackTraces : public VM_Operation { >>>>>>>>>>>>>>>>>>> ?? private: >>>>>>>>>>>>>>>>>>> MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Yes that I what I meant. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> On 2020/06/30 22:22, David Holmes wrote: >>>>>>>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> On 30/06/2020 10:05 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>> Hi David, Serguei, >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> I updated webrev for 8242428. Could you review again? >>>>>>>>>>>>>>>>>>>>> This change migrate to use direct handshake for GetStackTrace() and GetThreadListStackTraces() (when thread_count == 1). >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.01/ >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> This looks really good now! I only have a few nits below. There is one thing I don't like about it but it requires a change to the main Handshake logic to address - in JvmtiEnv::GetThreadListStackTraces you have to create a ThreadsListHandle to convert the jthread to a JavaThread, but then the Handshake::execute_direct creates another ThreadsListHandle internally. That's a waste. I will discuss with Robbin and file a RFE to have an overload of execute_direct that takes an existing TLH. Actually it's worse than that because we have another TLH in use at the entry point for the JVMTI functions, so I think there may be some scope for simplifying the use of TLH instances - future RFE. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> ??451 GetStackTraceClosure(JvmtiEnv *env, jint start_depth, jint max_count, >>>>>>>>>>>>>>>>>>>> ??452 jvmtiFrameInfo* frame_buffer, jint* count_ptr) >>>>>>>>>>>>>>>>>>>> ??453???? : HandshakeClosure("GetStackTrace"), >>>>>>>>>>>>>>>>>>>> ??454?????? _env(env), _start_depth(start_depth), _max_count(max_count), >>>>>>>>>>>>>>>>>>>> ??455 _frame_buffer(frame_buffer), _count_ptr(count_ptr), >>>>>>>>>>>>>>>>>>>> ??456 _result(JVMTI_ERROR_THREAD_NOT_ALIVE) { >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Nit: can you do one initializer per line please. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> This looks wrong: >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> 466 class MultipleStackTracesCollector : public StackObj { >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> ??498 class VM_GetAllStackTraces : public VM_Operation { >>>>>>>>>>>>>>>>>>>> ??499 private: >>>>>>>>>>>>>>>>>>>> ??500?? JavaThread *_calling_thread; >>>>>>>>>>>>>>>>>>>> ??501?? jint _final_thread_count; >>>>>>>>>>>>>>>>>>>> ??502 MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> You can't have a StackObj as a member of another class like that as it may not be on the stack. I think MultipleStackTracesCollector should not extend any allocation class, and should always be embedded directly in another class. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> 481 MultipleStackTracesCollector(JvmtiEnv *env, jint max_frame_count) { >>>>>>>>>>>>>>>>>>>> ??482???? _env = env; >>>>>>>>>>>>>>>>>>>> ??483???? _max_frame_count = max_frame_count; >>>>>>>>>>>>>>>>>>>> ??484???? _frame_count_total = 0; >>>>>>>>>>>>>>>>>>>> ??485???? _head = NULL; >>>>>>>>>>>>>>>>>>>> ??486???? _stack_info = NULL; >>>>>>>>>>>>>>>>>>>> ??487???? _result = JVMTI_ERROR_NONE; >>>>>>>>>>>>>>>>>>>> ??488?? } >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> As you are touching this can you change it to use an initializer list as you did for the HandshakeClosure, and please keep one item per line. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> ??820 assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>>>>>>>> ??821 java_thread->is_thread_fully_suspended(false, &debug_bits) || >>>>>>>>>>>>>>>>>>>> ??822????????? current_thread == java_thread->active_handshaker(), >>>>>>>>>>>>>>>>>>>> ??823????????? "at safepoint / handshake or target thread is suspended"); >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> I don't think the suspension check is necessary, as even if the target is suspended we must still be at a safepoint or in a handshake with it. Makes me wonder if we used to allow a racy stacktrace operation on a suspended thread, assuming it would remain suspended? >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> 1268?? oop thread_oop = jt->threadObj(); >>>>>>>>>>>>>>>>>>>> 1269 >>>>>>>>>>>>>>>>>>>> 1270?? if (!jt->is_exiting() && (jt->threadObj() != NULL)) { >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> You can use thread_oop in line 1270. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> 1272 _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, thread_oop), >>>>>>>>>>>>>>>>>>>> 1273 jt, thread_oop); >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> It is frustrating that this entire call chain started with a jthread reference, which we converted to a JavaThread, only to eventually need to convert it back to a jthread! I think there is some scope for simplification here but not as part of this change. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> IIUC at this point the _calling_thread is the current thread, so we can use: >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Please add @bug lines to the tests. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> I'm still pondering the test logic but wanted to send this now. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>>>>>> VM_GetThreadListStackTrace (for GetThreadListStackTraces) and VM_GetAllStackTraces (for GetAllStackTraces) have inherited VM_GetMultipleStackTraces VM operation which provides the feature to generate jvmtiStackInfo. I modified VM_GetMultipleStackTraces to a normal C++ class to share with HandshakeClosure for GetThreadListStackTraces (GetSingleStackTraceClosure). >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Also I added new testcases which test GetThreadListStackTraces() with thread_count == 1 and with all threads. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> This change has been tested in serviceability/jvmti serviceability/jdwp vmTestbase/nsk/jvmti vmTestbase/nsk/jdi vmTestbase/nsk/jdwp. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> On 2020/06/24 15:50, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>> Hi all, >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Please review this change: >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> ?? JBS: https://bugs.openjdk.java.net/browse/JDK-8242428 >>>>>>>>>>>>>>>>>>>>>> ?? webrev: http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.00/ >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> This change replace following VM operations to direct handshake. >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> ??- VM_GetFrameCount (GetFrameCount()) >>>>>>>>>>>>>>>>>>>>>> ??- VM_GetFrameLocation (GetFrameLocation()) >>>>>>>>>>>>>>>>>>>>>> ??- VM_GetThreadListStackTraces (GetThreadListStackTrace()) >>>>>>>>>>>>>>>>>>>>>> ??- VM_GetCurrentLocation >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> GetThreadListStackTrace() uses direct handshake if thread count == 1. In other case (thread count > 1), it would be performed as VM operation (VM_GetThreadListStackTraces). >>>>>>>>>>>>>>>>>>>>>> Caller of VM_GetCurrentLocation (JvmtiEnvThreadState::reset_current_location()) might be called at safepoint. So I added safepoint check in its caller. >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> This change has been tested in serviceability/jvmti serviceability/jdwp vmTestbase/nsk/jvmti vmTestbase/nsk/jdi vmTestbase/ns >>>>>>>>>>>>>>>>>>>>>> k/jdwp. >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Also I tested it on submit repo, then it has execution error (mach5-one-ysuenaga-JDK-8242428-20200624-0054-12034717) due to dependency error. So I think it does not occur by this change. >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>> >>>>>>>>> >>>>> >>> > From patric.hedlin at oracle.com Sun Jul 5 15:26:48 2020 From: patric.hedlin at oracle.com (Patric Hedlin) Date: Sun, 5 Jul 2020 17:26:48 +0200 Subject: RFR(S): 8247762: [aarch64] Timeout in .../HeapDumpTestWithActiveProcess.java due to inf. loop in AARCH64CurrentFrameGuess.run() Message-ID: Dear all, I would like to ask for help to review the following change/update: Issue:? https://bugs.openjdk.java.net/browse/JDK-8247762 Webrev: http://cr.openjdk.java.net/~phedlin/tr8247762/ AARCH64CurrentFrameGuess.run() may loop indefinitely in a bad stack-walk. This is JDK-8231635 applied to AArch64. NOTE: This patch is only a partial solution to the various /stack-walk/timeout/ issues in this particular test-case. Testing: HeapDumpTestWithActiveProcess.java Best regards, Patric From serguei.spitsyn at oracle.com Mon Jul 6 07:32:12 2020 From: serguei.spitsyn at oracle.com (serguei.spitsyn at oracle.com) Date: Mon, 6 Jul 2020 00:32:12 -0700 Subject: RFR: 8242428: JVMTI thread operations should use Thread-Local Handshake In-Reply-To: References: <6c263e4c-0a83-be7a-0288-ecb2de0b7cea@oss.nttdata.com> <74c05dfd-ffb2-b73d-66e5-dc98752729f5@oss.nttdata.com> <763793b1-9506-44c6-0681-1c71c44a44fd@oss.nttdata.com> <5107c478-1de2-7a49-ee71-dfad6a99a667@oracle.com> <90cdfef9-e558-0d25-33f5-25b7d65bb83b@oss.nttdata.com> <0e359819-618f-c17b-a427-bb7e4daa2c58@oracle.com> <3f890bed-6892-e64d-b21b-ca0cbe11784e@oracle.com> <7dc1903b-6295-3864-6301-4c02aacdb971@oss.nttdata.com> <04e09eb7-9483-8f63-4bb4-01c9e814802e@oracle.com> <238a89a3-06b1-90e4-d5a4-8dc2f1ed12ab@oracle.com> <4c43bc2c-551e-d042-8fa7-b63e755888d1@oracle.com> Message-ID: An HTML attachment was scrubbed... URL: From aph at redhat.com Mon Jul 6 08:37:35 2020 From: aph at redhat.com (Andrew Haley) Date: Mon, 6 Jul 2020 09:37:35 +0100 Subject: RFR(S): 8247762: [aarch64] Timeout in .../HeapDumpTestWithActiveProcess.java due to inf. loop in AARCH64CurrentFrameGuess.run() In-Reply-To: References: Message-ID: <36c12487-cfc9-3823-c4a3-7605629beca5@redhat.com> On 05/07/2020 16:26, Patric Hedlin wrote: > Issue:? https://bugs.openjdk.java.net/browse/JDK-8247762 > Webrev: http://cr.openjdk.java.net/~phedlin/tr8247762/ > > > AARCH64CurrentFrameGuess.run() may loop indefinitely in a bad > stack-walk. This is JDK-8231635 applied to AArch64. 141 Frame oldFrame = frame; 142 frame = frame.sender(map); 143 if (frame.getSP().lessThanOrEqual(oldFrame.getSP())) { 144 // Frame points to itself or to a location in the wrong direction. 145 // Break the loop and move on to next offset. 146 if (DEBUG) { 147 System.out.println("CurrentFrameGuess: frame <= oldFrame: " + frame); 148 } 149 break; 150 } 151 } OK, that looks like a reasonable thing to do, but I would wonder how the stack got into that mess. -- Andrew Haley (he/him) Java Platform Lead Engineer Red Hat UK Ltd. https://keybase.io/andrewhaley EAC8 43EB D3EF DB98 CC77 2FAD A5CD 6035 332F A671 From suenaga at oss.nttdata.com Mon Jul 6 13:29:23 2020 From: suenaga at oss.nttdata.com (Yasumasa Suenaga) Date: Mon, 6 Jul 2020 22:29:23 +0900 Subject: RFR: 8242428: JVMTI thread operations should use Thread-Local Handshake In-Reply-To: References: <6c263e4c-0a83-be7a-0288-ecb2de0b7cea@oss.nttdata.com> <74c05dfd-ffb2-b73d-66e5-dc98752729f5@oss.nttdata.com> <763793b1-9506-44c6-0681-1c71c44a44fd@oss.nttdata.com> <5107c478-1de2-7a49-ee71-dfad6a99a667@oracle.com> <90cdfef9-e558-0d25-33f5-25b7d65bb83b@oss.nttdata.com> <0e359819-618f-c17b-a427-bb7e4daa2c58@oracle.com> <3f890bed-6892-e64d-b21b-ca0cbe11784e@oracle.com> <7dc1903b-6295-3864-6301-4c02aacdb971@oss.nttdata.com> <04e09eb7-9483-8f63-4bb4-01c9e814802e@oracle.com> <238a89a3-06b1-90e4-d5a4-8dc2f1ed12ab@oracle.com> <4c43bc2c-551e-d042-8fa7-b63e755888d1@oracle.com> Message-ID: <8c387550-a06e-6320-f453-0e898486befb@oss.nttdata.com> Hi Serguei, Thanks for your comment! I think C++ is more simple to implement the test agent as you said. So I implement it in C++ in new webrev. Could you review again? http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.06/ Also I refactored libGetThreadListStackTraces.cpp, and I've kept exception check after IsSameObject(). Thanks, Yasumasa On 2020/07/06 16:32, serguei.spitsyn at oracle.com wrote: > Hi Yasumasa, > > Thank you for the update. > I think, a pending exception after IsSameObject needs to be checked. > > The checkStackInfo() needs one more refactoring as I've already suggested. > The body of the loop at L68-L78 should be converted to a function check_frame_info. > The si1->frame_buffer[i] and si2->frame_buffer[i] will be passed as fi1 and fi2. > The index can be passed as well. > I'm still suggesting to simplify the local exception_msg to something shorter like err_msg or exc_msg. > > I'm not sure using fatal is right here: > > This fragment looks strange: > > 152 if ((*env)->IsSameObject(env, stack_info[i].thread, thread)) { > 153 target_info = &stack_info[i]; > 154 break; > 155 } else if ((*env)->ExceptionOccurred(env)) { > 156 (*env)->ExceptionDescribe(env); > 157 (*env)->FatalError(env, __FILE__); > 158 } > > I expected it to be: > > jboolean same = (*env)->IsSameObject(env, stack_info[i].thread, thread); > if ((*env)->ExceptionOccurred(env)) { > (*env)->ExceptionDescribe(env); > (*env)->FatalError(env, __FILE__); > } > if (same) { > target_info = &stack_info[i]; > ? break; > } > > Would it better to port this agent to C++ to simplify this code nicer? > > Thanks, > Serguei > > > On 7/5/20 06:13, Yasumasa Suenaga wrote: >> Hi Serguei, >> >> Thanks for your comment! >> I refactored testcase. Could you review again? >> >> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.05/ >> >> It would check Java exception after IsSameObject() call. Does it need? >> Any exceptions are not described in JNI document[1], and JNI implementation (jni_IsSameObject()) does not seem to throw it. >> >> >> Thanks, >> >> Yasumasa >> >> >> [1] https://docs.oracle.com/en/java/javase/14/docs/specs/jni/functions.html#issameobject >> >> >> On 2020/07/05 14:46, serguei.spitsyn at oracle.com wrote: >>> Hi Yasumasa, >>> >>> >>> Okay, thanks. >>> Then I'm okay to keep the GetSingleStackTraceClosure. >>> >>> >>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libGetThreadListStackTraces.c.html >>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.c.html >>> >>> I'm not sure the function 'is_same_thread() is needed. >>> Why do not use the JNI IsSameObject instead? >>> >>> It seems to be a typo at L132 and L137. >>> You, probably. did not want to print the same information for stack_info_1[i].frame_buffer[j].XXX twice. >>> >>> The code at lines 112-142 is not readable. >>> I'd suggest to make a couple of refactoring steps. >>> >>> First step to simplify this a little bit would be with some renaming and getting rid of indexes: >>> >>> ?? 71 char err_msg[EXCEPTION_MSG_LEN] = {0}; >>> ??... >>> ??112?? /* Iterate all jvmtiStackInfo to check */ >>> ??113?? for (i = 0; i < num_threads, *exception_msg != '\0'; i++) { >>> ????????? jvmtiStackInfo *si1 = stack_info_1[i]; >>> ????????? jvmtiStackInfo *si2 = stack_info_2[i]; >>> ??114???? if (!IsSameObject(env, si1.thread, si2.thread)) { /* jvmtiStackInfo::thread */ >>> ??115?????? snprintf(err_msg, sizeof(err_msg), >>> ??116??????????????? "thread[%d] is different: stack_info_1 = %p, stack_info_2 = %p", >>> ??117??????????????? i, sinfo1.thread, sinfo2.thread); >>> ??118???? } else if (si1.state != si2.state) { /* jvmtiStackInfo::state */ >>> ??119?????? snprintf(err_msg, sizeof(err_msg), >>> ??120??????????????? "state[%d] is different: stack_info_1 = %d, stack_info_2 = %d", >>> ??121??????????????? i, si1.state, si2.state); >>> ??122???? } else if (si1.frame_count != si2.frame_count) { /* jvmtiStackInfo::frame_count */ >>> ??123?????? snprintf(err_msg, sizeof(err_msg), >>> ??124??????????????? "frame_count[%d] is different: stack_info_1 = %d, stack_info_2 = %d", >>> ??125??????????????? i, si1.frame_count, si2.frame_count); >>> ??126???? } else { >>> ??127?????? /* Iterate all jvmtiFrameInfo to check */ >>> ??128?????? for (j = 0; j < si1.frame_count; j++) { >>> ??129???????? if (si1.frame_buffer[j].method != si1.frame_buffer[j].method) { /* jvmtiFrameInfo::method */ >>> ??130?????????? snprintf(err_msg, sizeof(err_msg), >>> ??131??????????????????? "thread [%d] frame_buffer[%d].method is different: stack_info_1 = %lx, stack_info_2 = %lx", >>> ??132??????????????????? i, j, si1.frame_buffer[j].method, si2.frame_buffer[j].method); >>> ??133?????????? break; >>> ??134???????? } else if (si1.frame_buffer[j].location != si1.frame_buffer[j].location) { /* jvmtiFrameInfo::location */ >>> ??135?????????? snprintf(err_msg, sizeof(err_msg), >>> ??136??????????????????? "thread [%d] frame_buffer[%d].location is different: stack_info_1 = %ld, stack_info_2 = %ld", >>> ??137??????????????????? i, j, si1.frame_buffer[j].location, si2.frame_buffer[j].location); >>> ??138?????????? break; >>> ??139???????? } >>> ??140?????? } >>> ??141???? } >>> ??142?? } >>> >>> Another step would be to create functions that implement a body of each loop. >>> You can use the same techniques to simplify similar place (L127-L138) in the libOneGetThreadListStackTraces.c. >>> >>> Thanks, >>> Serguei >>> >>> >>> On 7/3/20 15:55, Yasumasa Suenaga wrote: >>>> Hi Serguei, >>>> >>>> I'm not an Oracle employee, so I cannot know real request(s) from your customers. >>>> However JDK-8201641 says Dynatrace has requested this enhancement. >>>> >>>> BTW I haven't heared any request from my customers about this. >>>> >>>> >>>> Thanks, >>>> >>>> Yasumasa >>>> >>>> >>>> On 2020/07/04 4:32, serguei.spitsyn at oracle.com wrote: >>>>> Hi Yasumasa, >>>>> >>>>> This difference is not that big to care about. >>>>> I feel this is really rare case and so, does not worth these complications. >>>>> Do we have a real request from customers to optimize it? >>>>> >>>>> Thanks, >>>>> Serguei >>>>> >>>>> >>>>> On 7/3/20 01:16, Yasumasa Suenaga wrote: >>>>>> Hi Serguei, >>>>>> >>>>>> Generally I agree with you, but I have concern about the difference of the result of GetStackTrace() and GetThreadListStackTraces(). >>>>>> >>>>>> ? GetStackTrace: jvmtiFrameInfo >>>>>> ? GetThreadListStackTraces: jvmtiStackInfo >>>>>> >>>>>> jvmtiStackInfo contains thread state, and it is ensured it is the state of the call stack. >>>>>> If we want to get both call stack and thread state, we need to suspend target thread, and call both GetStackTrace() and GetThreadState(). Is it ok? >>>>>> >>>>>> I was wondering if JDK-8201641 (parent ticket of this change) needed them for profiling (dynatrace?) >>>>>> If it is responsibility of JVMTI agent implementor, I remove this closure. >>>>>> >>>>>> >>>>>> Thanks, >>>>>> >>>>>> Yasumasa >>>>>> >>>>>> >>>>>> On 2020/07/03 16:45, serguei.spitsyn at oracle.com wrote: >>>>>>> Hi Yasumasa, >>>>>>> >>>>>>> After some thinking I've concluded that I do not like this optimization >>>>>>> of the GetThreadListStackTraces with GetSingleStackTraceClosure. >>>>>>> >>>>>>> We may need more opinions on this but these are my points: >>>>>>> ??- it adds some complexity and ugliness >>>>>>> ??- a win is doubtful because it has to be a rare case, so that total overhead should not be high >>>>>>> ??- if it is really high for some use cases then it is up to the user >>>>>>> ??? to optimize it with using GetStackTrace instead >>>>>>> >>>>>>> In such cases with doubtful overhead I usually prefer the simplicity. >>>>>>> >>>>>>> Good examples where it makes sense to optimize are checks for target thread to be current thread. >>>>>>> In such cases there is no need to suspend the target thread, or use a VMop/HandshakeClosure. >>>>>>> For instance, please, see the Monitor functions with the check: (java_thread == calling_thread). >>>>>>> Getting information for current thread is frequently used case, e.g. to get info at an event point. >>>>>>> >>>>>>> Thanks, >>>>>>> Serguei >>>>>>> >>>>>>> >>>>>>> On 7/2/20 23:29, Yasumasa Suenaga wrote: >>>>>>>> Hi Dan, David, >>>>>>>> >>>>>>>> I uploaded new webrev. Could you review again? >>>>>>>> >>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/ >>>>>>>> >>>>>>>> OneGetThreadListStackTraces.java in this webrev would wait until thread state is transited to "waiting" with spin wait. >>>>>>>> CountDownLatch::await call as Dan pointed is fixed in it :) >>>>>>>> >>>>>>>> Diff from webrev.03: >>>>>>>> http://hg.openjdk.java.net/jdk/submit/rev/c9aeb7001e50 >>>>>>>> >>>>>>>> >>>>>>>> Thanks, >>>>>>>> >>>>>>>> Yasumasa >>>>>>>> >>>>>>>> >>>>>>>> On 2020/07/03 14:15, David Holmes wrote: >>>>>>>>> >>>>>>>>> >>>>>>>>> On 3/07/2020 2:27 pm, Yasumasa Suenaga wrote: >>>>>>>>>> On 2020/07/03 12:24, Daniel D. Daugherty wrote: >>>>>>>>>>> On 7/2/20 10:50 PM, David Holmes wrote: >>>>>>>>>>>> Sorry I'm responding here without seeing latest webrev but there is enough context I think ... >>>>>>>>>>>> >>>>>>>>>>>> On 3/07/2020 9:14 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>> Hi Dan, >>>>>>>>>>>>> >>>>>>>>>>>>> Thanks for your comment! >>>>>>>>>>>>> >>>>>>>>>>>>> On 2020/07/03 7:16, Daniel D. Daugherty wrote: >>>>>>>>>>>>>> On 7/2/20 5:19 AM, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> I upload new webrev. Could you review again? >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.03/ >>>>>>>>>>>>>> >>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnv.cpp >>>>>>>>>>>>>> ???? L1542: ??? // Get stack trace with handshake >>>>>>>>>>>>>> ???????? nit - please add a period at the end. >>>>>>>>>>>>> >>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>>> ???? L1591: *stack_info_ptr = op.stack_info(); >>>>>>>>>>>>>> ???????? The return parameter should not be touched unless the return >>>>>>>>>>>>>> ???????? code in 'err' == JVMTI_ERROR_NONE. >>>>>>>>>>>>>> >>>>>>>>>>>>>> ???? old L1582: ? if (err == JVMTI_ERROR_NONE) { >>>>>>>>>>>>>> ???????? Please restore this check. The return parameter should not >>>>>>>>>>>>>> ???????? be touched unless the return code in 'err' == JVMTI_ERROR_NONE. >>>>>>>>>>>>> >>>>>>>>>>>>> I will fix it. >>>>>>>>>>>> >>>>>>>>>>>> But op.stack_info() will return NULL if the error is not JVMTI_ERROR_NONE. Are you (Dan) concerned about someone passing in a non-null/initialized out-pointer that will be reset to NULL if there was an error? >>>>>>>>>>> >>>>>>>>>>> Actually the way we used to test this in POSIX tests is to call >>>>>>>>>>> an API with known bad parameters and the return parameter ptr >>>>>>>>>>> set to NULL. If the return parameter ptr was touched when an >>>>>>>>>>> error should have been detected on an earlier parameter, then >>>>>>>>>>> the test failed. >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>>> ???? L1272: ? if (!jt->is_exiting() && (thread_oop != NULL)) { >>>>>>>>>>>>>> ???????? nit - extra parens around the second expression. >>>>>>>>>>>>> >>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>> ???? old L1532: ? _result = JVMTI_ERROR_THREAD_NOT_ALIVE; >>>>>>>>>>>>>> ???????? This deletion of the _result field threw me for a minute and then >>>>>>>>>>>>>> ???? ? ? I figured out that the field is init to JVMTI_ERROR_THREAD_NOT_ALIVE >>>>>>>>>>>>>> ???????? in the constructor. >>>>>>>>>>>>>> >>>>>>>>>>>>>> ???? L1553: ? if (!jt->is_exiting() && (jt->threadObj() != NULL)) { >>>>>>>>>>>>>> ???????? nit - extra parens around the second expression. >>>>>>>>>>>>> >>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>>>>>>>>>> ???? No comments. >>>>>>>>>>>>>> >>>>>>>>>>>>>> src/hotspot/share/runtime/vmOperations.hpp >>>>>>>>>>>>>> ???? No comments. >>>>>>>>>>>>>> >>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/GetThreadListStackTraces.java >>>>>>>>>>>>>> ???? No comments. >>>>>>>>>>>>>> >>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/OneGetThreadListStackTraces.java >>>>>>>>>>>>>> ???? L64: ??????? startSignal.countDown(); >>>>>>>>>>>>>> ???????? I was expecting this to be a call to await() instead of >>>>>>>>>>>>>> ???????? countDown(). What am I missing here? >>>>>>>>>>>>>> >>>>>>>>>>>>>> ???????? I think this test might be passing by accident right now, but... >>>>>>>>>>>>> >>>>>>>>>>>>> Main thread (which call JVMTI functions to test) should wait until test thread is ready. >>>>>>>>>>>>> So main thread would wait startSignal, and test thread would count down. >>>>>>>>>>>> >>>>>>>>>>>> No! >>>>>>>>>>>> >>>>>>>>>>>> The test thread that previously called obj.wait() now calls latch.await(). >>>>>>>>>>>> >>>>>>>>>>>> The main thread that previously called obj.notify() now calls latch.countDown(). >>>>>>>>>>>> >>>>>>>>>>>> The main thread continues to spin until it sees the target is WAITING before proceeding with the test. >>>>>>>>>> >>>>>>>>>> If I add spin wait to wait until transit target thread state is WAITING (as following), we don't need to call SuspendThread(). >>>>>>>>>> Which is better? >>>>>>>>> >>>>>>>>> The original spin-wait loop checking for? WAITING is better because it is the only guarantee that the target thread is blocked where you need it to be. suspending the thread is racy as you don't know exactly where the suspend will hit. >>>>>>>>> >>>>>>>>> Thanks, >>>>>>>>> David >>>>>>>>> ----- >>>>>>>>> >>>>>>>>>> >>>>>>>>>> ``` >>>>>>>>>> /* Wait until the thread state transits to "waiting" */ >>>>>>>>>> while (th.getState() != Thread.State.WAITING) { >>>>>>>>>> ???? Thread.onSpinWait(); >>>>>>>>>> } >>>>>>>>>> ``` >>>>>>>>>> >>>>>>>>>> For simplify, spin wait is prefer to OneGetThreadListStackTraces.java in webrev.03. >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> Thanks, >>>>>>>>>> >>>>>>>>>> Yasumasa >>>>>>>>>> >>>>>>>>>> >>>>>>>>>>> Here's the flow as I see it: >>>>>>>>>>> >>>>>>>>>>> main thread >>>>>>>>>>> ?? - start worker thread >>>>>>>>>>> ?? - startSignal.await() >>>>>>>>>>> ???? - main is now blocked >>>>>>>>>>> >>>>>>>>>>> worker thread >>>>>>>>>>> ?? - startSignal.countDown() >>>>>>>>>>> ???? - main is now unblocked >>>>>>>>>>> ?? - stopSignal.await() >>>>>>>>>>> ???? - worker is now blocked >>>>>>>>>>> >>>>>>>>>>> main thread >>>>>>>>>>> ?? - checkCallStacks(th) >>>>>>>>>>> ?? - stopSignal.countDown() >>>>>>>>>>> ???? - worker is now unblocked >>>>>>>>>>> ?? - th.join >>>>>>>>>>> ???? - main is now blocked >>>>>>>>>>> >>>>>>>>>>> worker thread >>>>>>>>>>> ?? - runs off the end of run() >>>>>>>>>>> ???? - main is now unblocked >>>>>>>>>>> >>>>>>>>>>> main thread >>>>>>>>>>> ?? - run off the end of main() >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libGetThreadListStackTraces.c >>>>>>>>>>>>>> ???? L92: ? jthreads = (jthread *)malloc(sizeof(jthread) * num_threads); >>>>>>>>>>>>>> ???????? You don't check for malloc() failure. >>>>>>>>>>>>>> ???????? 'jthreads' is allocated but never freed. >>>>>>>>>>>>> >>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.c >>>>>>>>>>>>>> ???? L91: ? result = (*jvmti)->SuspendThread(jvmti, thread); >>>>>>>>>>>>>> ???????? Why are you suspending the thread? GetAllStackTraces() and >>>>>>>>>>>>>> ???????? GetThreadListStackTraces() do not require the target thread(s) >>>>>>>>>>>>>> ???????? to be suspend. >>>>>>>>>>>>>> >>>>>>>>>>>>>> ???????? If you decide not to SuspendThread, then you don't need the >>>>>>>>>>>>>> ???????? AddCapabilities or the ResumeThread calls. >>>>>>>>>>>>> >>>>>>>>>>>>> Test thread might not be entered following code (stopSignal.await()). We might see deferent call stack between GetAllStackTraces() and GetThreadListStackTraces(). We cannot control to freeze call stack of test thread in Java code. >>>>>>>>>>>>> (I didn't use SuspendThread() at first, but I saw some errors which causes in above.) >>>>>>>>>>>>> >>>>>>>>>>>>> So we need to call SuspendThread() to ensure we can see same call stack. >>>>>>>>>>>> >>>>>>>>>>>> If you are checking that the thread is in state WAITING then it cannot escape from that state and you can sample the stack multiple times from any API and get the same result. >>>>>>>>>>>> >>>>>>>>>>>> I suspect the errors you saw were from the apparent incorrect use of the CountDownLatch. >>>>>>>>>>> >>>>>>>>>>> With the flow outlined above, the worker thread should be >>>>>>>>>>> nicely blocked in stopSignal.await() when stuff is sampled. >>>>>>>>>>> >>>>>>>>>>> Dan >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> Cheers, >>>>>>>>>>>> David >>>>>>>>>>>> ----- >>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> Thanks, >>>>>>>>>>>>> >>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>>> Dan >>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> On 2020/07/02 15:05, David Holmes wrote: >>>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> On 1/07/2020 11:53 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>> Hi, >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> I uploaded new webrev. Could review again? >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.02/ >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Updates look fine - thanks. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> One minor nit: >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> 1274 _collector.allocate_and_fill_stacks(1); >>>>>>>>>>>>>>>> 1275 _collector.set_result(JVMTI_ERROR_NONE); >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> In the other places where you use _collector you rely on result being initialized to JVMTI_ERROR_NONE, rather than setting it directly after allocate_and_fill_stacks(). >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Fixed. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> ? 820 assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>>>>>>>>>> ? 821 java_thread->is_thread_fully_suspended(false, &debug_bits) || >>>>>>>>>>>>>>>>>>>>>> ? 822 current_thread == java_thread->active_handshaker(), >>>>>>>>>>>>>>>>>>>>>> ? 823????????? "at safepoint / handshake or target thread is suspended"); >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> I don't think the suspension check is necessary, as even if the target is suspended we must still be at a safepoint or in a handshake with it. Makes me wonder if we used to allow a racy stacktrace operation on a suspended thread, assuming it would remain suspended? >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> This function (JvmtiEnvBase::get_stack_trace()) can be called to get own stack trace. For example, we can call GetStackTrace() for current thread at JVMTI event. >>>>>>>>>>>>>>>>> So I changed assert as below: >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>> ??820?? assert(current_thread == java_thread || >>>>>>>>>>>>>>>>> ??821 SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>>>>> ??822????????? current_thread == java_thread->active_handshaker(), >>>>>>>>>>>>>>>>> ??823????????? "call by myself / at safepoint / at handshake"); >>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Yep good catch. I hope current tests caught that. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> They would be tested in vmTestbase/nsk/jvmti/GetStackTrace/getstacktr001/ (own call stacks), and getstacktr003 (call stacks in other thread). >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Speaking of tests ... >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> In the native code I think you need to check the success of all JNI methods that can throw exceptions - otherwise I believe the tests may trigger warnings if -Xcheck:jni is used with them. See for example: >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/libHeapMonitorTest.cpp >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> I updated testcases to check JNI and JVMTI function calls. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> In the Java code the target thread: >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> ?? 45???? public void run() { >>>>>>>>>>>>>>>> ?? 46?????? try { >>>>>>>>>>>>>>>> ?? 47?????????? synchronized (lock) { >>>>>>>>>>>>>>>> ?? 48?????????????? lock.wait(); >>>>>>>>>>>>>>>> ?? 49 System.out.println("OK"); >>>>>>>>>>>>>>>> ?? 50?????????? } >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> is potentially susceptible to spurious wakeups. Using a CountDownLatch would be robust. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Fixed. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> On 2020/07/01 8:48, David Holmes wrote: >>>>>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> On 1/07/2020 9:05 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> 1271 ResourceMark rm; >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> IIUC at this point the _calling_thread is the current thread, so we can use: >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> If so, we can call make_local() in L1272 without JavaThread (or we can pass current thread to make_local()). Is it right? >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>>>>>>>>>>> 1272 _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, thread_oop), >>>>>>>>>>>>>>>>>>> 1273 jt, thread_oop); >>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Sorry I got confused, _calling_thread may not be the current thread as we could be executing the handshake in the target thread itself. So the ResourceMark is correct as-is (implicitly for current thread). >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> The argument to fill_frames will be used in the jvmtiStackInfo and passed back to the _calling_thread, so it must be created via make_local(_calling_thread, ...) as you presently have. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> On 2020/07/01 7:05, David Holmes wrote: >>>>>>>>>>>>>>>>>>>> On 1/07/2020 12:17 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Thank you for reviewing! I will update new webrev tomorrow. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> 466 class MultipleStackTracesCollector : public StackObj { >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> ? 498 class VM_GetAllStackTraces : public VM_Operation { >>>>>>>>>>>>>>>>>>>>>> ? 499 private: >>>>>>>>>>>>>>>>>>>>>> ? 500?? JavaThread *_calling_thread; >>>>>>>>>>>>>>>>>>>>>> ? 501?? jint _final_thread_count; >>>>>>>>>>>>>>>>>>>>>> ? 502 MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> You can't have a StackObj as a member of another class like that as it may not be on the stack. I think MultipleStackTracesCollector should not extend any allocation class, and should always be embedded directly in another class. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> I'm not sure what does mean "embedded". >>>>>>>>>>>>>>>>>>>>> Is it ok as below? >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>> class MultipleStackTracesCollector { >>>>>>>>>>>>>>>>>>>>> ??? : >>>>>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> class GetAllStackTraces : public VM_Operation { >>>>>>>>>>>>>>>>>>>>> ?? private: >>>>>>>>>>>>>>>>>>>>> MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Yes that I what I meant. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> On 2020/06/30 22:22, David Holmes wrote: >>>>>>>>>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> On 30/06/2020 10:05 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>>> Hi David, Serguei, >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> I updated webrev for 8242428. Could you review again? >>>>>>>>>>>>>>>>>>>>>>> This change migrate to use direct handshake for GetStackTrace() and GetThreadListStackTraces() (when thread_count == 1). >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.01/ >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> This looks really good now! I only have a few nits below. There is one thing I don't like about it but it requires a change to the main Handshake logic to address - in JvmtiEnv::GetThreadListStackTraces you have to create a ThreadsListHandle to convert the jthread to a JavaThread, but then the Handshake::execute_direct creates another ThreadsListHandle internally. That's a waste. I will discuss with Robbin and file a RFE to have an overload of execute_direct that takes an existing TLH. Actually it's worse than that because we have another TLH in use at the entry point for the JVMTI functions, so I think there may be some scope for simplifying the use of TLH instances - future RFE. >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> ??451 GetStackTraceClosure(JvmtiEnv *env, jint start_depth, jint max_count, >>>>>>>>>>>>>>>>>>>>>> ??452 jvmtiFrameInfo* frame_buffer, jint* count_ptr) >>>>>>>>>>>>>>>>>>>>>> ??453???? : HandshakeClosure("GetStackTrace"), >>>>>>>>>>>>>>>>>>>>>> ??454?????? _env(env), _start_depth(start_depth), _max_count(max_count), >>>>>>>>>>>>>>>>>>>>>> ??455 _frame_buffer(frame_buffer), _count_ptr(count_ptr), >>>>>>>>>>>>>>>>>>>>>> ??456 _result(JVMTI_ERROR_THREAD_NOT_ALIVE) { >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Nit: can you do one initializer per line please. >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> This looks wrong: >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> 466 class MultipleStackTracesCollector : public StackObj { >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> ??498 class VM_GetAllStackTraces : public VM_Operation { >>>>>>>>>>>>>>>>>>>>>> ??499 private: >>>>>>>>>>>>>>>>>>>>>> ??500?? JavaThread *_calling_thread; >>>>>>>>>>>>>>>>>>>>>> ??501?? jint _final_thread_count; >>>>>>>>>>>>>>>>>>>>>> ??502 MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> You can't have a StackObj as a member of another class like that as it may not be on the stack. I think MultipleStackTracesCollector should not extend any allocation class, and should always be embedded directly in another class. >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> 481 MultipleStackTracesCollector(JvmtiEnv *env, jint max_frame_count) { >>>>>>>>>>>>>>>>>>>>>> ??482???? _env = env; >>>>>>>>>>>>>>>>>>>>>> ??483???? _max_frame_count = max_frame_count; >>>>>>>>>>>>>>>>>>>>>> ??484 _frame_count_total = 0; >>>>>>>>>>>>>>>>>>>>>> ??485???? _head = NULL; >>>>>>>>>>>>>>>>>>>>>> ??486???? _stack_info = NULL; >>>>>>>>>>>>>>>>>>>>>> ??487???? _result = JVMTI_ERROR_NONE; >>>>>>>>>>>>>>>>>>>>>> ??488?? } >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> As you are touching this can you change it to use an initializer list as you did for the HandshakeClosure, and please keep one item per line. >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> ??820 assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>>>>>>>>>> ??821 java_thread->is_thread_fully_suspended(false, &debug_bits) || >>>>>>>>>>>>>>>>>>>>>> ??822 current_thread == java_thread->active_handshaker(), >>>>>>>>>>>>>>>>>>>>>> ??823????????? "at safepoint / handshake or target thread is suspended"); >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> I don't think the suspension check is necessary, as even if the target is suspended we must still be at a safepoint or in a handshake with it. Makes me wonder if we used to allow a racy stacktrace operation on a suspended thread, assuming it would remain suspended? >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> 1268?? oop thread_oop = jt->threadObj(); >>>>>>>>>>>>>>>>>>>>>> 1269 >>>>>>>>>>>>>>>>>>>>>> 1270?? if (!jt->is_exiting() && (jt->threadObj() != NULL)) { >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> You can use thread_oop in line 1270. >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> 1272 _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, thread_oop), >>>>>>>>>>>>>>>>>>>>>> 1273 jt, thread_oop); >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> It is frustrating that this entire call chain started with a jthread reference, which we converted to a JavaThread, only to eventually need to convert it back to a jthread! I think there is some scope for simplification here but not as part of this change. >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> IIUC at this point the _calling_thread is the current thread, so we can use: >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Please add @bug lines to the tests. >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> I'm still pondering the test logic but wanted to send this now. >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>>>>>>>> VM_GetThreadListStackTrace (for GetThreadListStackTraces) and VM_GetAllStackTraces (for GetAllStackTraces) have inherited VM_GetMultipleStackTraces VM operation which provides the feature to generate jvmtiStackInfo. I modified VM_GetMultipleStackTraces to a normal C++ class to share with HandshakeClosure for GetThreadListStackTraces (GetSingleStackTraceClosure). >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Also I added new testcases which test GetThreadListStackTraces() with thread_count == 1 and with all threads. >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> This change has been tested in serviceability/jvmti serviceability/jdwp vmTestbase/nsk/jvmti vmTestbase/nsk/jdi vmTestbase/nsk/jdwp. >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> On 2020/06/24 15:50, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>>>> Hi all, >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Please review this change: >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> ?? JBS: https://bugs.openjdk.java.net/browse/JDK-8242428 >>>>>>>>>>>>>>>>>>>>>>>> ?? webrev: http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.00/ >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> This change replace following VM operations to direct handshake. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> ??- VM_GetFrameCount (GetFrameCount()) >>>>>>>>>>>>>>>>>>>>>>>> ??- VM_GetFrameLocation (GetFrameLocation()) >>>>>>>>>>>>>>>>>>>>>>>> ??- VM_GetThreadListStackTraces (GetThreadListStackTrace()) >>>>>>>>>>>>>>>>>>>>>>>> ??- VM_GetCurrentLocation >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> GetThreadListStackTrace() uses direct handshake if thread count == 1. In other case (thread count > 1), it would be performed as VM operation (VM_GetThreadListStackTraces). >>>>>>>>>>>>>>>>>>>>>>>> Caller of VM_GetCurrentLocation (JvmtiEnvThreadState::reset_current_location()) might be called at safepoint. So I added safepoint check in its caller. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> This change has been tested in serviceability/jvmti serviceability/jdwp vmTestbase/nsk/jvmti vmTestbase/nsk/jdi vmTestbase/ns >>>>>>>>>>>>>>>>>>>>>>>> k/jdwp. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Also I tested it on submit repo, then it has execution error (mach5-one-ysuenaga-JDK-8242428-20200624-0054-12034717) due to dependency error. So I think it does not occur by this change. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>> >>>>>>>>>>> >>>>>>> >>>>> >>> > From chris.plummer at oracle.com Mon Jul 6 15:52:00 2020 From: chris.plummer at oracle.com (Chris Plummer) Date: Mon, 6 Jul 2020 08:52:00 -0700 Subject: RFR(S): 8247762: [aarch64] Timeout in .../HeapDumpTestWithActiveProcess.java due to inf. loop in AARCH64CurrentFrameGuess.run() In-Reply-To: <36c12487-cfc9-3823-c4a3-7605629beca5@redhat.com> References: <36c12487-cfc9-3823-c4a3-7605629beca5@redhat.com> Message-ID: <78a1d527-bd3f-6bc2-7880-ca5f34215267@oracle.com> On 7/6/20 1:37 AM, Andrew Haley wrote: > On 05/07/2020 16:26, Patric Hedlin wrote: >> Issue:? https://bugs.openjdk.java.net/browse/JDK-8247762 >> Webrev: http://cr.openjdk.java.net/~phedlin/tr8247762/ >> >> >> AARCH64CurrentFrameGuess.run() may loop indefinitely in a bad >> stack-walk. This is JDK-8231635 applied to AArch64. > 141 Frame oldFrame = frame; > 142 frame = frame.sender(map); > 143 if (frame.getSP().lessThanOrEqual(oldFrame.getSP())) { > 144 // Frame points to itself or to a location in the wrong direction. > 145 // Break the loop and move on to next offset. > 146 if (DEBUG) { > 147 System.out.println("CurrentFrameGuess: frame <= oldFrame: " + frame); > 148 } > 149 break; > 150 } > 151 } > > OK, that looks like a reasonable thing to do, but I would wonder how the stack got > into that mess. > Hi Patric, The changes look good to me. Andrew, The problem is not the stack per se. AARCH64CurrentFrameGuess.run() tries to find the "current frame". It starts with the specified SP (which I believe comes from the SP register), and validates that it represents the current frame by using it to walk the stack until the first entry frame is found. If it doesn't find it, then it increments SP by a word and tries again. It does this until it either can successfully walk to the first entry frame, or SP leaves the range it is willing to search, at which point it gives up. During this search all manner of bad addresses can be accessed. This is why there is an exception handler that when triggered simply moves on to the next SP to check. So it's not at all surprising that on occasion a bad SP results in frame->sender() pointing to a frame that was already visited. thanks, Chris From hohensee at amazon.com Mon Jul 6 19:03:18 2020 From: hohensee at amazon.com (Hohensee, Paul) Date: Mon, 6 Jul 2020 19:03:18 +0000 Subject: [11u] RFR/A: 8231209: [REDO] JDK-8207266 ThreadMXBean::getThreadAllocatedBytes() can be quicker for self thread In-Reply-To: <09229907-C812-4974-BF5D-8619FEA083BC@amazon.com> References: <09229907-C812-4974-BF5D-8619FEA083BC@amazon.com> Message-ID: The CSRs have been approved, and the JBS issues tagged (8231209, 8231968 and the corresponding backport issues 8247806 and 8247809). Also, Oracle has now committed to backport these to their 11.0.9. Please approve. Thanks, Paul From: serviceability-dev on behalf of "Hohensee, Paul" Date: Thursday, June 18, 2020 at 12:29 PM To: "jdk-updates-dev at openjdk.java.net" Cc: serviceability-dev Subject: [11u] RFR/A: 8231209: [REDO] JDK-8207266 ThreadMXBean::getThreadAllocatedBytes() can be quicker for self thread This request is for a pair of backports. 8231209 is the first (and primary), 8231968 is a minor cleanup. There are CSR?s for both. The effect is to add a convenience method getCurrentThreadAllocatedBytes() to com.sun.management.ThreadMXBean that can be implemented more efficiently than the equivalent getThreadAllocatedBytes(long id), and to make the implementation of getThreadAllocatedBytes(long id) and getThreadAllocatedBytes(long[] id) more efficient. These methods are heavily used by heap profiling tools, including Amazon?s, and their efficiency is important to us. There is no effect on the TCK because com.sun.management is a platform-specific package. See the CSRs for more detail. The patches apply cleanly (in sequence) to 11u, but I?m posting a review/approval request because the backport CSRs need approval. Once the backport CSRs are reviewed, finalized, and approved, l can tag 8231209 and 8231968. Tested with hotspot/jtreg/vmTestbase/nsk/monitoring jdk/com/sun/management jdk/jdk/jfr/event/runtime The same tests pass/fail as with unpatched jdk11u-dev. JDK-8231209: [REDO] JDK-8207266 ThreadMXBean::getThreadAllocatedBytes() can be quicker for self thread Original RFE: https://bugs.openjdk.java.net/browse/JDK-8231209 Original Patch: https://hg.openjdk.java.net/jdk/jdk/rev/c29e49148be7 Original CSR: https://bugs.openjdk.java.net/browse/JDK-8231374 Original review thread: https://mail.openjdk.java.net/pipermail/serviceability-dev/2019-September/029208.html Backport RFE: https://bugs.openjdk.java.net/browse/JDK-8247806 Backport CSR: https://bugs.openjdk.java.net/browse/JDK-8247807 JDK-8231968: getCurrentThreadAllocatedBytes default implementation s/b getThreadAllocatedBytes Original RFE: https://bugs.openjdk.java.net/browse/JDK-8231968 Original Patch: https://hg.openjdk.java.net/jdk/jdk/rev/5bb426e9acc4 Original CSR: https://bugs.openjdk.java.net/browse/JDK-8232072 Original review thread: https://mail.openjdk.java.net/pipermail/serviceability-dev/2019-October/029659.html Backport RFE: https://bugs.openjdk.java.net/browse/JDK-8247809 Backport CSR: https://bugs.openjdk.java.net/browse/JDK-8247810 Thanks, Paul -------------- next part -------------- An HTML attachment was scrubbed... URL: From patric.hedlin at oracle.com Mon Jul 6 19:54:40 2020 From: patric.hedlin at oracle.com (Patric Hedlin) Date: Mon, 6 Jul 2020 21:54:40 +0200 Subject: RFR(S): 8247762: [aarch64] Timeout in .../HeapDumpTestWithActiveProcess.java due to inf. loop in AARCH64CurrentFrameGuess.run() In-Reply-To: <78a1d527-bd3f-6bc2-7880-ca5f34215267@oracle.com> References: <36c12487-cfc9-3823-c4a3-7605629beca5@redhat.com> <78a1d527-bd3f-6bc2-7880-ca5f34215267@oracle.com> Message-ID: <6322edbb-ab38-4956-6a29-5b1c3d48c132@oracle.com> Thanks Chris, for review and laying out the text. Andrew, Something you can live with? /Patric On 2020-07-06 17:52, Chris Plummer wrote: > On 7/6/20 1:37 AM, Andrew Haley wrote: >> On 05/07/2020 16:26, Patric Hedlin wrote: >>> Issue: https://bugs.openjdk.java.net/browse/JDK-8247762 >>> Webrev: http://cr.openjdk.java.net/~phedlin/tr8247762/ >>> >>> >>> AARCH64CurrentFrameGuess.run() may loop indefinitely in a bad >>> stack-walk. This is JDK-8231635 applied to AArch64. >> ? 141?????????????? Frame oldFrame = frame; >> ? 142?????????????? frame = frame.sender(map); >> ? 143?????????????? if >> (frame.getSP().lessThanOrEqual(oldFrame.getSP())) { >> ? 144???????????????? // Frame points to itself or to a location in >> the wrong direction. >> ? 145???????????????? // Break the loop and move on to next offset. >> ? 146???????????????? if (DEBUG) { >> ? 147?????????????????? System.out.println("CurrentFrameGuess: frame >> <= oldFrame: " + frame); >> ? 148???????????????? } >> ? 149???????????????? break; >> ? 150?????????????? } >> ? 151???????????? } >> >> OK, that looks like a reasonable thing to do, but I would wonder how >> the stack got >> into that mess. >> > Hi Patric, > > The changes look good to me. > > Andrew, > > The problem is not the stack per se. AARCH64CurrentFrameGuess.run() > tries to find the "current frame". It starts with the specified SP > (which I believe comes from the SP register), and validates that it > represents the current frame by using it to walk the stack until the > first entry frame is found. If it doesn't find it, then it increments > SP by a word and tries again. It does this until it either can > successfully walk to the first entry frame, or SP leaves the range it > is willing to search, at which point it gives up. During this search > all manner of bad addresses can be accessed. This is why there is an > exception handler that when triggered simply moves on to the next SP > to check. So it's not at all surprising that on occasion a bad SP > results in frame->sender() pointing to a frame that was already visited. > > thanks, > > Chris > From hohensee at amazon.com Mon Jul 6 21:57:10 2020 From: hohensee at amazon.com (Hohensee, Paul) Date: Mon, 6 Jul 2020 21:57:10 +0000 Subject: RFR(L): 8215624: add parallel heap inspection support for jmap histo(G1)(Internet mail) Message-ID: <02415944-2238-4430-A7C2-3625264A5505@amazon.com> I'd like to see this feature added. :) The CSR looks good, as does the basic parallel inspection algorithm. Stefan's done the GC part, so I'll stick to the non-GC part (fwiw, the GC part lgtm). I'd move all the argument parsing code to JMap.java and just pass the results to Hotspot. Both histo() in JMap.java and code in attachListener.* parse the command line arguments, though the code in histo() doesn't parse the argument to "parallel". I'd upgrade the code in histo() to do a complete parse and pass the option values to executeCommandForPid as before: there would just be more of them now. That would allow you to eliminate all the parsing code in attachListener.cpp as well as the change to arguments.hpp. heapInspection.hpp: _shared_miss_count (s/b _missed_count, see below) isn't a size, so it should be a uint instead of a size_t. Same with the new parallel_thread_num argument to heap_inspection() and populate_table(). Comment copy-edit: +// Parallel heap inspection task. Parallel inspection can fail due to +// a native OOM when allocating memory for TL-KlassInfoTable. +// _success will be set false on an OOM, and serial inspection tried. _shared_miss_count should be _missed_count to match the missed_count() getter, or rename missed_count() to be shared_miss_count(). Whichever way you go, the field type should match the getter result type: uint is reasonable. heapInspection.cpp: You might use ResourceMark twice in populate_table, separately for the parallel attempt and the serial code. If the parallel attempt fails and available memory is low, it would be good to clean up the memory used by the parallel attempt before doing the serial code. Style nit in KlassInfoTable::merge_entry(). I'd line up the definitions of k and elt, so "k" is even with "elt". And, because it's two lines shorter, I'd replace + } else { + return false; + } with + return false; KlassInfoTableMergeClosure.is_success() should be just success() (i.e., no "is_" prefix) because it's a getter. I'd reorganize the code in populate_table() to make it more clear, vis (I changed _shared_missed_count to _missed_count) + if (cit.allocation_failed()) { + // fail to allocate memory, stop parallel mode + Atomic::store(&_success, false); + return; + } + RecordInstanceClosure ric(&cit, _filter); + _poi->object_iterate(&ric, worker_id); + missed_count = ric.missed_count(); + { + MutexLocker x(&_mutex); + merge_success = _shared_cit->merge(&cit); + } + if (merge_success) { + Atomic::add(&_missed_count, missed_count); + else { + Atomic::store(&_success, false); + } Thanks, Paul ?On 6/29/20, 7:20 PM, "linzang(??)" wrote: Dear All, Sorry to bother again, I just want to make sure that is this change worth to be continue to work on? If decision is made to not. I think I can drop this work and stop asking for help reviewing... Thanks for all your help about reviewing this previously. BRs, Lin On 2020/5/9, 3:47 PM, "linzang(??)" wrote: Dear All, May I ask your help again for review the latest change? Thanks! BRs, Lin On 2020/4/28, 1:54 PM, "linzang(??)" wrote: Hi Stefan, >> - Adding Atomic::load/store. >> - Removing the time measurement in the run_task. I renamed G1's function >> to run_task_timed. If we need this outside of G1, we can rethink the API >> at that point. >> - ZGC style cleanups Thanks for revising the patch, they are all good to me, and I have made a tiny change based on it: http://cr.openjdk.java.net/~lzang/jmap-8214535/8215624/webrev_04/ http://cr.openjdk.java.net/~lzang/jmap-8214535/8215624/webrev_04-delta/ it reduce the scope of mutex in ParHeapInspectTask, and delete unnecessary comments. BRs, Lin On 2020/4/27, 4:34 PM, "Stefan Karlsson" wrote: Hi Lin, On 2020-04-26 05:10, linzang(??) wrote: > Hi Stefan and Paul? > I have made a new patch based on your comments and Stefan's Poc code: > Webrev: http://cr.openjdk.java.net/~lzang/jmap-8214535/8215624/webrev_03/ > Delta(based on Stefan's change:) : http://cr.openjdk.java.net/~lzang/jmap-8214535/8215624/webrev_03-delta/webrev_03-delta/ Thanks for providing a delta patch. It makes it much easier to look at, and more likely for reviewers to continue reviewing. I'm going to continue focusing on the GC parts, and leave the rest to others to review. > > And Here are main changed I made and want to discuss with you: > 1. changed"parallelThreadNum=" to "parallel=" for jmap -histo options. > 2. Add logic to test where parallelHeapInspection is fail, in heapInspection.cpp > This is because the parHeapInspectTask create thread local KlassInfoTable in it's work() method, and this may fail because of native OOM, in this case, the parallel should fail and serial heap inspection can be tried. > One more thing I want discuss with you is about the member "_success" of parHeapInspectTask, when native OOM happenes, it is set to false. And since this "set" operation can be conducted in multiple threads, should it be atomic ops? IMO, this is not necessary because "_success" can only be set to false, and there is no way to change it from back to true after the ParHeapInspectTask instance is created, so it is save to be non-atomic, do you agree with that? In these situations you should be using the Atomic::load/store primitives. We're moving toward a later C++ standard were data races are considered undefined behavior. > 3. make CollectedHeap::run_task() be an abstract virtual func, so that every subclass of collectedHeap should support it, so later implementation of new collectedHeap will not miss the "parallel" features. > The problem I want to discuss with you is about epsilonHeap and SerialHeap, as they may not need parallel heap iteration, so I only make task->work(0), in case the run_task() is invoked someway in future. Another way is to left run_task() unimplemented, which one do you think is better? I don't have a strong opinion about this. And also please help take a look at the zHeap, as there is a class zTask that wrap the abstractGangTask, and the collectedHeap::run_task() only accept AbstraceGangTask* as argument, so I made a delegate class to adapt it , please see src/hotspot/share/gc/z/zHeap.cpp. > > There maybe other better ways to sovle the above problems, welcome for any comments, Thanks! I've created a few cleanups and changes on top of your latest patch: https://cr.openjdk.java.net/~stefank/8215624/webrev.02.delta https://cr.openjdk.java.net/~stefank/8215624/webrev.02 - Adding Atomic::load/store. - Removing the time measurement in the run_task. I renamed G1's function to run_task_timed. If we need this outside of G1, we can rethink the API at that point. - ZGC style cleanups Thanks, StefanK > > BRs, > Lin > > On 2020/4/23, 11:08 AM, "linzang(??)" wrote: > > Thanks Paul! I agree with using "parallel", will make the update in next patch, Thanks for help update the CSR. > > BRs, > Lin > > On 2020/4/23, 4:42 AM, "Hohensee, Paul" wrote: > > For the interface, I'd use "parallel" instead of "parallelThreadNum". All the other options are lower case, and it's a lot easier to type "parallel". I took the liberty of updating the CSR. If you're ok with it, you might want to change variable names and such, plus of course JMap.usage. > > Thanks, > Paul > > On 4/22/20, 2:29 AM, "serviceability-dev on behalf of linzang(??)" wrote: > > Dear Stefan, > > Thanks a lot! I agree with you to decouple the heap inspection code with GC's. > I will start from your POC code, may discuss with you later. > > > BRs, > Lin > > On 2020/4/22, 5:14 PM, "Stefan Karlsson" wrote: > > Hi Lin, > > I took a look at this earlier and saw that the heap inspection code is > strongly coupled with the CollectedHeap and G1CollectedHeap. I'd prefer > if we'd abstract this away, so that the GCs only provide a "parallel > object iteration" interface, and the heap inspection code is kept elsewhere. > > I started experimenting with doing that, but other higher-priority (to > me) tasks have had to take precedence. > > I've uploaded my work-in-progress / proof-of-concept: > https://cr.openjdk.java.net/~stefank/8215624/webrev.01.delta/ > https://cr.openjdk.java.net/~stefank/8215624/webrev.01/ > > The current code doesn't handle the lifecycle (deletion) of the > ParallelObjectIterators. There's also code left unimplemented in around > CollectedHeap::run_task. However, I think this could work as a basis to > pull out the heap inspection code out of the GCs. > > Thanks, > StefanK > > On 2020-04-22 02:21, linzang(??) wrote: > > Dear all, > > May I ask you help to review? This RFR has been there for quite a while. > > Thanks! > > > > BRs, > > Lin > > > > > On 2020/3/16, 5:18 PM, "linzang(??)" wrote:> > > > >> Just update a new path, my preliminary measure show about 3.5x speedup of jmap histo on a nearly full 4GB G1 heap (8-core platform with parallel thread number set to 4). > >> webrev: http://cr.openjdk.java.net/~lzang/jmap-8214535/8215624/webrev_02/ > >> bug: https://bugs.openjdk.java.net/browse/JDK-8215624 > >> CSR: https://bugs.openjdk.java.net/browse/JDK-8239290 > >> BRs, > >> Lin > >> > On 2020/3/2, 9:56 PM, "linzang(??)" wrote: > >> > > >> > Dear all, > >> > Let me try to ease the reviewing work by some explanation :P > >> > The patch's target is to speed up jmap -histo for heap iteration, from my experience it is necessary for large heap investigation. E.g in bigData scenario I have tried to conduct jmap -histo against 180GB heap, it does take quite a while. > >> > And if my understanding is corrent, even the jmap -histo without "live" option does heap inspection with heap lock acquired. so it is very likely to block mutator thread in allocation-sensitive scenario. I would say the faster the heap inspection does, the shorter the mutator be blocked. This is parallel iteration for jmap is necessary. > >> > I think the parallel heap inspection should be applied to all kind of heap. However, consider the heap layout are different for GCs, much time is required to understand all kinds of the heap layout to make the whole change. IMO, It is not wise to have a huge patch for the whole solution at once, and it is even harder to review it. So I plan to implement it incrementally, the first patch (this one) is going to confirm the implemention detail of how jmap accept the new option, passes it to attachListener of the jvm process and then how to make the parallel inspection closure be generic enough to make it easy to extend to different heap layout. And also how to implement the heap inspection in specific gc's heap. This patch use G1's heap as the begining. > >> > This patch actually do several things: > >> > 1. Add an option "parallelThreadNum=" to jmap -histo, the default behavior is to set N to 0, means let's JVM decide how many threads to use for heap inspection. Set this option to 1 will disable parallel heap inspection. (more details in CSR: https://bugs.openjdk.java.net/browse/JDK-8239290) > >> > 2. Make a change in how Jmap passing arguments, changes in http://cr.openjdk.java.net/~lzang/jmap-8214535/8215624/webrev_01/src/jdk.jcmd/share/classes/sun/tools/jmap/JMap.java.udiff.html, originally it pass options as separate arguments to attachListener, this patch change to that all options be compose to a single string. So the arg_count_max in attachListener.hpp do not need to be changed, and hence avoid the compatibility issue, as disscussed at https://mail.openjdk.java.net/pipermail/serviceability-dev/2019-March/027334.html > >> > 3. Add an abstract class ParHeapInspectTask in heapInspection.hpp / heapInspection.cpp, It's work(uint worker_id) method prepares the data structure (KlassInfoTable) need for every parallel worker thread, and then call do_object_iterate_parallel() which is heap specific implementation. I also added some machenism in KlassInfoTable to support parallel iteration, such as merge(). > >> > 4. In specific heap (G1 in this patch), create a subclass of ParHeapInspectTask, implement the do_object_iterate_parallel() for parallel heap inspection. For G1, it simply invoke g1CollectedHeap's object_iterate_parallel(). > >> > 5. Add related test. > >> > 6. it may be easy to extend this patch for other kinds of heap by creating subclass of ParHeapInspectTask and implement the do_object_iterate_parallel(). > >> > > >> > Hope these info could help on code review and initate the discussion :-) > >> > Thanks! > >> > > >> > BRs, > >> > Lin > >> > >On 2020/2/19, 9:40 AM, "linzang(??)" wrote:. > >> > > > >> > > Re-post this RFR with correct enhancement number to make it trackable. > >> > > please ignore the previous wrong post. sorry for troubles. > >> > > > >> > > webrev: http://cr.openjdk.java.net/~lzang/jmap-8214535/8215624/webrev_01/ > >> > > Hi bug: https://bugs.openjdk.java.net/browse/JDK-8215624 > >> > > CSR: https://bugs.openjdk.java.net/browse/JDK-8239290 > >> > > -------------- > >> > > Lin > >> > > >Hi Lin, > > > > > > > >> > > >Could you, please, re-post your RFR with the right enhancement number in > >> > > >the message subject? > >> > > >It will be more trackable this way. > >> > > > > >> > > >Thanks, > >> > > >Serguei > >> > > > > >> > > > > >> > > >On 2/17/20 10:29 PM, linzang(??) wrote: > >> > > >> Dear David, > >> > > >> Thanks a lot! > >> > > >> I have updated the refined code to http://cr.openjdk.java.net/~lzang/jmap-8214535/8215264/webrev_01/. > >> > > >> IMHO the parallel heap inspection can be extended to all kinds of heap as long as the heap layout can support parallel iteration. > >> > > >> Maybe we can firstly use this webrev to discuss how to implement it, because I am not sure my current implementation is an appropriate way to communicate with collectedHeap, then we can extend the solution to other kinds of heap. > >> > > >> > >> > > >> Thanks, > >> > > >> -------------- > >> > > >> Lin > >> > > >>> Hi Lin, > >> > > >>> > >> > > >>> Adding in hotspot-gc-dev as they need to see how this interacts with GC > >> > > >>> worker threads, and whether it needs to be extended beyond G1. > >> > > >>> > >> > > >>> I happened to spot one nit when browsing: > >> > > >>> > >> > > >>> src/hotspot/share/gc/shared/collectedHeap.hpp > >> > > >>> > >> > > >>> + virtual bool run_par_heap_inspect_task(KlassInfoTable* cit, > >> > > >>> + BoolObjectClosure* filter, > >> > > >>> + size_t* missed_count, > >> > > >>> + size_t thread_num) { > >> > > >>> + return NULL; > >> > > >>> > >> > > >>> s/NULL/false/ > >> > > >>> > >> > > >>> Cheers, > >> > > >>> David > > > > > >>> > >> > > >>> On 18/02/2020 2:15 pm, linzang(??) wrote: > >> > > >>>> Dear All, > >> > > >>>> May I ask your help to review the follow changes: > >> > > >>>> webrev: > >> > > >>>> http://cr.openjdk.java.net/~lzang/jmap-8214535/8215264/webrev_00/ > >> > > >>>> bug: https://bugs.openjdk.java.net/browse/JDK-8215624 > >> > > >>>> related CSR: https://bugs.openjdk.java.net/browse/JDK-8239290 > >> > > >>>> This patch enable parallel heap inspection of G1 for jmap histo. > >> > > >>>> my simple test shown it can speed up 2x of jmap -histo with > >> > > >>>> parallelThreadNum set to 2 for heap at ~500M on 4-core platform. > >> > > >>>> > >> > > >>>> ------------------------------------------------------------------------ > >> > > >>>> BRs, > >> > > >>>> Lin > >> > > >> > > >> > > > > > > > > > > > > > > > From leonid.mesnik at oracle.com Mon Jul 6 22:27:36 2020 From: leonid.mesnik at oracle.com (Leonid Mesnik) Date: Mon, 6 Jul 2020 15:27:36 -0700 Subject: RFR (L): 8248194: Need better support for running SA tests on core files In-Reply-To: <5760b18e-7ba2-2fdd-94af-1e555cef74cc@oracle.com> References: <5760b18e-7ba2-2fdd-94af-1e555cef74cc@oracle.com> Message-ID: Hi The changes look good for me. Leonid > On Jul 2, 2020, at 7:21 AM, Chris Plummer wrote: > > [Note, the following changes only impact serviceability tests, but I am adding some test library code to assist with creating and finding core files, and I thought others on hotspot-dev might have an interest in that.] > > Hello, > > Please help review the following changes to add better support for writing SA tests that work on core files: > > https://bugs.openjdk.java.net/browse/JDK-8248194 > http://cr.openjdk.java.net/~cjplummer/8248194/webrev.01/index.html > > As outlined in the CR, these are the 3 main goals of this CR: > > 1. Add a shared API for locating the path to the core file. This includes parsing the output of the crashed process to locate where the core file was saved, and returning this location to the user. This API will be placed in the new CoreUtils class. > > 2. Add a shared API to support adding the "ulimit -c unlimited" prefix to the command that will produce the core file, allowing the overriding of any lower limit so we can be sure the core file will be produced. This API will also be placed in the new CoreUtils class. > > 3. LingeredApp should include support for producing a core file. > > As proof of concept for these improvements, I'm updating the following 3 tests to make use of them: > > ClhsdbCDSCore.java and TestJmapCore.java: Use the CoreUtils support listed above. These tests do not use LingeredApp, so those improvements don't apply. > > ClhsdbFindPC.java: Use all the above new features, including having LingeredApp produce a core file. This is the only test modified to start testing on core files that didn't previously do so. It still also tests on a live process. > > In the future more Clhsdb tests will be converted to work on core files in a manner similar to ClhsdbFindPC. > > The new CoreUtils code is borrowed from (more like ripped out of) ClhsdbCDSCore.java and TestJmapCore.java. They both had a lot of code dedicated to finding the core file and also applying "ulimit -c unlimited", but didn't do so in quite the same way. Now both these tests share code in CoreUtils.java. One thing I did drop is TestJmapCore.java use of ":KILLED_PID" in the output to help find the core file. It's no longer necessary based on the smarter core locating code I pulled from ClhsdbCDSCore.java. > > One other improvement was to enable windows support for ClhsdbCDSCore. The only reason it was not enabled previously is because the author couldn't figure out how to properly generate the command for the process that produces the core. Since it is launched using "sh -c", the path has to be converted to use forward slashes. This is now done in CoreUtils. > > One other change in ClhsdbCDSCore is that it no longer renames the core file to a well known name in the cwd. This was unnecessary. It originated in code from ciReplayBase.java, which does have a reason to do the rename, but ClhsdbCDSCore does not. > > The new libLingeredApp.c relies on JDK-8248667 [1] being in place in order to have the build system properly compile it. JDK-8248667 will be reviewed separately on build-dev and pushed just before the changes for this CR. > > thanks, > > Chris > > [1] https://bugs.openjdk.java.net/browse/JDK-8248667 From chris.plummer at oracle.com Mon Jul 6 22:41:21 2020 From: chris.plummer at oracle.com (Chris Plummer) Date: Mon, 6 Jul 2020 15:41:21 -0700 Subject: RFR (L): 8248194: Need better support for running SA tests on core files In-Reply-To: References: <5760b18e-7ba2-2fdd-94af-1e555cef74cc@oracle.com> Message-ID: Thanks, Leonid! On 7/6/20 3:27 PM, Leonid Mesnik wrote: > Hi > > The changes look good for me. > > Leonid > >> On Jul 2, 2020, at 7:21 AM, Chris Plummer wrote: >> >> [Note, the following changes only impact serviceability tests, but I am adding some test library code to assist with creating and finding core files, and I thought others on hotspot-dev might have an interest in that.] >> >> Hello, >> >> Please help review the following changes to add better support for writing SA tests that work on core files: >> >> https://bugs.openjdk.java.net/browse/JDK-8248194 >> http://cr.openjdk.java.net/~cjplummer/8248194/webrev.01/index.html >> >> As outlined in the CR, these are the 3 main goals of this CR: >> >> 1. Add a shared API for locating the path to the core file. This includes parsing the output of the crashed process to locate where the core file was saved, and returning this location to the user. This API will be placed in the new CoreUtils class. >> >> 2. Add a shared API to support adding the "ulimit -c unlimited" prefix to the command that will produce the core file, allowing the overriding of any lower limit so we can be sure the core file will be produced. This API will also be placed in the new CoreUtils class. >> >> 3. LingeredApp should include support for producing a core file. >> >> As proof of concept for these improvements, I'm updating the following 3 tests to make use of them: >> >> ClhsdbCDSCore.java and TestJmapCore.java: Use the CoreUtils support listed above. These tests do not use LingeredApp, so those improvements don't apply. >> >> ClhsdbFindPC.java: Use all the above new features, including having LingeredApp produce a core file. This is the only test modified to start testing on core files that didn't previously do so. It still also tests on a live process. >> >> In the future more Clhsdb tests will be converted to work on core files in a manner similar to ClhsdbFindPC. >> >> The new CoreUtils code is borrowed from (more like ripped out of) ClhsdbCDSCore.java and TestJmapCore.java. They both had a lot of code dedicated to finding the core file and also applying "ulimit -c unlimited", but didn't do so in quite the same way. Now both these tests share code in CoreUtils.java. One thing I did drop is TestJmapCore.java use of ":KILLED_PID" in the output to help find the core file. It's no longer necessary based on the smarter core locating code I pulled from ClhsdbCDSCore.java. >> >> One other improvement was to enable windows support for ClhsdbCDSCore. The only reason it was not enabled previously is because the author couldn't figure out how to properly generate the command for the process that produces the core. Since it is launched using "sh -c", the path has to be converted to use forward slashes. This is now done in CoreUtils. >> >> One other change in ClhsdbCDSCore is that it no longer renames the core file to a well known name in the cwd. This was unnecessary. It originated in code from ciReplayBase.java, which does have a reason to do the rename, but ClhsdbCDSCore does not. >> >> The new libLingeredApp.c relies on JDK-8248667 [1] being in place in order to have the build system properly compile it. JDK-8248667 will be reviewed separately on build-dev and pushed just before the changes for this CR. >> >> thanks, >> >> Chris >> >> [1] https://bugs.openjdk.java.net/browse/JDK-8248667 From alexey.menkov at oracle.com Mon Jul 6 23:16:02 2020 From: alexey.menkov at oracle.com (Alex Menkov) Date: Mon, 6 Jul 2020 16:16:02 -0700 Subject: RFR (L): 8248194: Need better support for running SA tests on core files In-Reply-To: <5760b18e-7ba2-2fdd-94af-1e555cef74cc@oracle.com> References: <5760b18e-7ba2-2fdd-94af-1e555cef74cc@oracle.com> Message-ID: <2f2d3b21-8f8e-3c01-1e33-ad68bd39254b@oracle.com> Hi Chris, Generally looks good to me. CoreUtils.java: 86 String[] cmds; - unused var And one question. You use OutputAnalyzer.getStdout() get extract core file location. I thought it should be printed in stderr. Or we have duplicated stdout and stderr in the case? --alex On 07/02/2020 07:21, Chris Plummer wrote: > [Note, the following changes only impact serviceability tests, but I am > adding some test library code to assist with creating and finding core > files, and I thought others on hotspot-dev might have an interest in that.] > > Hello, > > Please help review the following changes to add better support for > writing SA tests that work on core files: > > https://bugs.openjdk.java.net/browse/JDK-8248194 > http://cr.openjdk.java.net/~cjplummer/8248194/webrev.01/index.html > > As outlined in the CR, these are the 3 main goals of this CR: > > 1. Add a shared API for locating the path to the core file. This > includes parsing the output of the crashed process to locate where the > core file was saved, and returning this location to the user. This API > will be placed in the new CoreUtils class. > > 2. Add a shared API to support adding the "ulimit -c unlimited" prefix > to the command that will produce the core file, allowing the overriding > of any lower limit so we can be sure the core file will be produced. > This API will also be placed in the new CoreUtils class. > > 3. LingeredApp should include support for producing a core file. > > As proof of concept for these improvements, I'm updating the following 3 > tests to make use of them: > > ClhsdbCDSCore.java and TestJmapCore.java: Use the CoreUtils support > listed above. These tests do not use LingeredApp, so those improvements > don't apply. > > ClhsdbFindPC.java: Use all the above new features, including having > LingeredApp produce a core file. This is the only test modified to start > testing on core files that didn't previously do so. It still also tests > on a live process. > > In the future more Clhsdb tests will be converted to work on core files > in a manner similar to ClhsdbFindPC. > > The new CoreUtils code is borrowed from (more like ripped out of) > ClhsdbCDSCore.java and TestJmapCore.java. They both had a lot of code > dedicated to finding the core file and also applying "ulimit -c > unlimited", but didn't do so in quite the same way. Now both these tests > share code in CoreUtils.java. One thing I did drop is TestJmapCore.java > use of ":KILLED_PID" in the output to help find the core file. It's no > longer necessary based on the smarter core locating code I pulled from > ClhsdbCDSCore.java. > > One other improvement was to enable windows support for ClhsdbCDSCore. > The only reason it was not enabled previously is because the author > couldn't figure out how to properly generate the command for the process > that produces the core. Since it is launched using "sh -c", the path has > to be converted to use forward slashes. This is now done in CoreUtils. > > One other change in ClhsdbCDSCore is that it no longer renames the core > file to a well known name in the cwd. This was unnecessary. It > originated in code from ciReplayBase.java, which does have a reason to > do the rename, but ClhsdbCDSCore does not. > > The new libLingeredApp.c relies on JDK-8248667 [1] being in place in > order to have the build system properly compile it. JDK-8248667 will be > reviewed separately on build-dev and pushed just before the changes for > this CR. > > thanks, > > Chris > > [1] https://bugs.openjdk.java.net/browse/JDK-8248667 From chris.plummer at oracle.com Tue Jul 7 00:06:09 2020 From: chris.plummer at oracle.com (Chris Plummer) Date: Mon, 6 Jul 2020 17:06:09 -0700 Subject: RFR (L): 8248194: Need better support for running SA tests on core files In-Reply-To: <2f2d3b21-8f8e-3c01-1e33-ad68bd39254b@oracle.com> References: <5760b18e-7ba2-2fdd-94af-1e555cef74cc@oracle.com> <2f2d3b21-8f8e-3c01-1e33-ad68bd39254b@oracle.com> Message-ID: <8bd159c8-1ba4-6b59-6f5d-64fd7b3b392f@oracle.com> Hi Alex, Thanks for the review. I'll cleanup the unused var. The crash output is on stdout, not stderr. From VMError::report_and_die(): ? // File descriptor to tty to print an error summary to. ? // Hard wired to stdout; see JDK-8215004 (compatibility concerns). ? static const int fd_out = 1; // stdout thanks, Chris On 7/6/20 4:16 PM, Alex Menkov wrote: > Hi Chris, > > Generally looks good to me. > > CoreUtils.java: > > 86???????? String[] cmds; > - unused var > > And one question. > You use OutputAnalyzer.getStdout() get extract core file location. > I thought it should be printed in stderr. > Or we have duplicated stdout and stderr in the case? > > --alex > > On 07/02/2020 07:21, Chris Plummer wrote: >> [Note, the following changes only impact serviceability tests, but I >> am adding some test library code to assist with creating and finding >> core files, and I thought others on hotspot-dev might have an >> interest in that.] >> >> Hello, >> >> Please help review the following changes to add better support for >> writing SA tests that work on core files: >> >> https://bugs.openjdk.java.net/browse/JDK-8248194 >> http://cr.openjdk.java.net/~cjplummer/8248194/webrev.01/index.html >> >> As outlined in the CR, these are the 3 main goals of this CR: >> >> 1. Add a shared API for locating the path to the core file. This >> includes parsing the output of the crashed process to locate where >> the core file was saved, and returning this location to the user. >> This API will be placed in the new CoreUtils class. >> >> 2. Add a shared API to support adding the "ulimit -c unlimited" >> prefix to the command that will produce the core file, allowing the >> overriding of any lower limit so we can be sure the core file will be >> produced. This API will also be placed in the new CoreUtils class. >> >> 3. LingeredApp should include support for producing a core file. >> >> As proof of concept for these improvements, I'm updating the >> following 3 tests to make use of them: >> >> ClhsdbCDSCore.java and TestJmapCore.java: Use the CoreUtils support >> listed above. These tests do not use LingeredApp, so those >> improvements don't apply. >> >> ClhsdbFindPC.java: Use all the above new features, including having >> LingeredApp produce a core file. This is the only test modified to >> start testing on core files that didn't previously do so. It still >> also tests on a live process. >> >> In the future more Clhsdb tests will be converted to work on core >> files in a manner similar to ClhsdbFindPC. >> >> The new CoreUtils code is borrowed from (more like ripped out of) >> ClhsdbCDSCore.java and TestJmapCore.java. They both had a lot of code >> dedicated to finding the core file and also applying "ulimit -c >> unlimited", but didn't do so in quite the same way. Now both these >> tests share code in CoreUtils.java. One thing I did drop is >> TestJmapCore.java use of ":KILLED_PID" in the output to help find the >> core file. It's no longer necessary based on the smarter core >> locating code I pulled from ClhsdbCDSCore.java. >> >> One other improvement was to enable windows support for >> ClhsdbCDSCore. The only reason it was not enabled previously is >> because the author couldn't figure out how to properly generate the >> command for the process that produces the core. Since it is launched >> using "sh -c", the path has to be converted to use forward slashes. >> This is now done in CoreUtils. >> >> One other change in ClhsdbCDSCore is that it no longer renames the >> core file to a well known name in the cwd. This was unnecessary. It >> originated in code from ciReplayBase.java, which does have a reason >> to do the rename, but ClhsdbCDSCore does not. >> >> The new libLingeredApp.c relies on JDK-8248667 [1] being in place in >> order to have the build system properly compile it. JDK-8248667 will >> be reviewed separately on build-dev and pushed just before the >> changes for this CR. >> >> thanks, >> >> Chris >> >> [1] https://bugs.openjdk.java.net/browse/JDK-8248667 From david.holmes at oracle.com Tue Jul 7 02:31:15 2020 From: david.holmes at oracle.com (David Holmes) Date: Tue, 7 Jul 2020 12:31:15 +1000 Subject: RFR: 8242428: JVMTI thread operations should use Thread-Local Handshake In-Reply-To: <8c387550-a06e-6320-f453-0e898486befb@oss.nttdata.com> References: <6c263e4c-0a83-be7a-0288-ecb2de0b7cea@oss.nttdata.com> <763793b1-9506-44c6-0681-1c71c44a44fd@oss.nttdata.com> <5107c478-1de2-7a49-ee71-dfad6a99a667@oracle.com> <90cdfef9-e558-0d25-33f5-25b7d65bb83b@oss.nttdata.com> <0e359819-618f-c17b-a427-bb7e4daa2c58@oracle.com> <3f890bed-6892-e64d-b21b-ca0cbe11784e@oracle.com> <7dc1903b-6295-3864-6301-4c02aacdb971@oss.nttdata.com> <04e09eb7-9483-8f63-4bb4-01c9e814802e@oracle.com> <238a89a3-06b1-90e4-d5a4-8dc2f1ed12ab@oracle.com> <4c43bc2c-551e-d042-8fa7-b63e755888d1@oracle.com> <8c387550-a06e-6320-f453-0e898486befb@oss.nttdata.com> Message-ID: Hi Yasumasa, Hard to keep up with the changes - especially without incremental webrevs. If GetSingleStackTraceClosure also took the jthread as a constructor arg, then you wouldn't need to recreate a JNI local handle when calling _collector.fill_frames. It's a small simplification and not essential at this stage. For the test ... I don't see how Java_GetThreadListStackTraces_checkCallStacks is a valid test. It gets the stacks of all live threads, then uses that information to use GetThreadListStackTraces to get the stack for the same set of threads through a different API. It then compares the two sets of stacks for each thread expecting them to be the same, but that need only be the case for the main thread. Other threads could potentially have a different stack (e.g. if this test is run with JFR enabled there will be additional threads found.) Further I would have expected that there already exist tests that check that, for a given thread (which may be suspended or known to be blocked) the same stack is found through the two different APIs. Thanks, David ----- On 6/07/2020 11:29 pm, Yasumasa Suenaga wrote: > Hi Serguei, > > Thanks for your comment! > > I think C++ is more simple to implement the test agent as you said. > So I implement it in C++ in new webrev. Could you review again? > > ? http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.06/ > > Also I refactored libGetThreadListStackTraces.cpp, and I've kept > exception check after IsSameObject(). > > > Thanks, > > Yasumasa > > > On 2020/07/06 16:32, serguei.spitsyn at oracle.com wrote: >> Hi Yasumasa, >> >> Thank you for the update. >> I think, a pending exception after IsSameObject needs to be checked. >> >> The checkStackInfo() needs one more refactoring as I've already >> suggested. >> The body of the loop at L68-L78 should be converted to a function >> check_frame_info. >> The si1->frame_buffer[i] and si2->frame_buffer[i] will be passed as >> fi1 and fi2. >> The index can be passed as well. >> I'm still suggesting to simplify the local exception_msg to something >> shorter like err_msg or exc_msg. >> >> I'm not sure using fatal is right here: >> >> This fragment looks strange: >> >> ? 152???? if ((*env)->IsSameObject(env, stack_info[i].thread, thread)) { >> ? 153?????? target_info = &stack_info[i]; >> ? 154?????? break; >> ? 155???? } else if ((*env)->ExceptionOccurred(env)) { >> ? 156?????? (*env)->ExceptionDescribe(env); >> ? 157?????? (*env)->FatalError(env, __FILE__); >> ? 158???? } >> >> I expected it to be: >> >> ??? jboolean same = (*env)->IsSameObject(env, stack_info[i].thread, >> thread); >> ??? if ((*env)->ExceptionOccurred(env)) { >> ????? (*env)->ExceptionDescribe(env); >> ????? (*env)->FatalError(env, __FILE__); >> ??? } >> ??? if (same) { >> ????? target_info = &stack_info[i]; >> ????? break; >> ??? } >> >> Would it better to port this agent to C++ to simplify this code nicer? >> >> Thanks, >> Serguei >> >> >> On 7/5/20 06:13, Yasumasa Suenaga wrote: >>> Hi Serguei, >>> >>> Thanks for your comment! >>> I refactored testcase. Could you review again? >>> >>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.05/ >>> >>> It would check Java exception after IsSameObject() call. Does it need? >>> Any exceptions are not described in JNI document[1], and JNI >>> implementation (jni_IsSameObject()) does not seem to throw it. >>> >>> >>> Thanks, >>> >>> Yasumasa >>> >>> >>> [1] >>> https://docs.oracle.com/en/java/javase/14/docs/specs/jni/functions.html#issameobject >>> >>> >>> >>> On 2020/07/05 14:46, serguei.spitsyn at oracle.com wrote: >>>> Hi Yasumasa, >>>> >>>> >>>> Okay, thanks. >>>> Then I'm okay to keep the GetSingleStackTraceClosure. >>>> >>>> >>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libGetThreadListStackTraces.c.html >>>> >>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.c.html >>>> >>>> >>>> I'm not sure the function 'is_same_thread() is needed. >>>> Why do not use the JNI IsSameObject instead? >>>> >>>> It seems to be a typo at L132 and L137. >>>> You, probably. did not want to print the same information for >>>> stack_info_1[i].frame_buffer[j].XXX twice. >>>> >>>> The code at lines 112-142 is not readable. >>>> I'd suggest to make a couple of refactoring steps. >>>> >>>> First step to simplify this a little bit would be with some renaming >>>> and getting rid of indexes: >>>> >>>> ?? 71 char err_msg[EXCEPTION_MSG_LEN] = {0}; >>>> ??... >>>> ??112?? /* Iterate all jvmtiStackInfo to check */ >>>> ??113?? for (i = 0; i < num_threads, *exception_msg != '\0'; i++) { >>>> ????????? jvmtiStackInfo *si1 = stack_info_1[i]; >>>> ????????? jvmtiStackInfo *si2 = stack_info_2[i]; >>>> ??114???? if (!IsSameObject(env, si1.thread, si2.thread)) { /* >>>> jvmtiStackInfo::thread */ >>>> ??115?????? snprintf(err_msg, sizeof(err_msg), >>>> ??116??????????????? "thread[%d] is different: stack_info_1 = %p, >>>> stack_info_2 = %p", >>>> ??117??????????????? i, sinfo1.thread, sinfo2.thread); >>>> ??118???? } else if (si1.state != si2.state) { /* >>>> jvmtiStackInfo::state */ >>>> ??119?????? snprintf(err_msg, sizeof(err_msg), >>>> ??120??????????????? "state[%d] is different: stack_info_1 = %d, >>>> stack_info_2 = %d", >>>> ??121??????????????? i, si1.state, si2.state); >>>> ??122???? } else if (si1.frame_count != si2.frame_count) { /* >>>> jvmtiStackInfo::frame_count */ >>>> ??123?????? snprintf(err_msg, sizeof(err_msg), >>>> ??124??????????????? "frame_count[%d] is different: stack_info_1 = >>>> %d, stack_info_2 = %d", >>>> ??125??????????????? i, si1.frame_count, si2.frame_count); >>>> ??126???? } else { >>>> ??127?????? /* Iterate all jvmtiFrameInfo to check */ >>>> ??128?????? for (j = 0; j < si1.frame_count; j++) { >>>> ??129???????? if (si1.frame_buffer[j].method != >>>> si1.frame_buffer[j].method) { /* jvmtiFrameInfo::method */ >>>> ??130?????????? snprintf(err_msg, sizeof(err_msg), >>>> ??131??????????????????? "thread [%d] frame_buffer[%d].method is >>>> different: stack_info_1 = %lx, stack_info_2 = %lx", >>>> ??132??????????????????? i, j, si1.frame_buffer[j].method, >>>> si2.frame_buffer[j].method); >>>> ??133?????????? break; >>>> ??134???????? } else if (si1.frame_buffer[j].location != >>>> si1.frame_buffer[j].location) { /* jvmtiFrameInfo::location */ >>>> ??135?????????? snprintf(err_msg, sizeof(err_msg), >>>> ??136??????????????????? "thread [%d] frame_buffer[%d].location is >>>> different: stack_info_1 = %ld, stack_info_2 = %ld", >>>> ??137??????????????????? i, j, si1.frame_buffer[j].location, >>>> si2.frame_buffer[j].location); >>>> ??138?????????? break; >>>> ??139???????? } >>>> ??140?????? } >>>> ??141???? } >>>> ??142?? } >>>> >>>> Another step would be to create functions that implement a body of >>>> each loop. >>>> You can use the same techniques to simplify similar place >>>> (L127-L138) in the libOneGetThreadListStackTraces.c. >>>> >>>> Thanks, >>>> Serguei >>>> >>>> >>>> On 7/3/20 15:55, Yasumasa Suenaga wrote: >>>>> Hi Serguei, >>>>> >>>>> I'm not an Oracle employee, so I cannot know real request(s) from >>>>> your customers. >>>>> However JDK-8201641 says Dynatrace has requested this enhancement. >>>>> >>>>> BTW I haven't heared any request from my customers about this. >>>>> >>>>> >>>>> Thanks, >>>>> >>>>> Yasumasa >>>>> >>>>> >>>>> On 2020/07/04 4:32, serguei.spitsyn at oracle.com wrote: >>>>>> Hi Yasumasa, >>>>>> >>>>>> This difference is not that big to care about. >>>>>> I feel this is really rare case and so, does not worth these >>>>>> complications. >>>>>> Do we have a real request from customers to optimize it? >>>>>> >>>>>> Thanks, >>>>>> Serguei >>>>>> >>>>>> >>>>>> On 7/3/20 01:16, Yasumasa Suenaga wrote: >>>>>>> Hi Serguei, >>>>>>> >>>>>>> Generally I agree with you, but I have concern about the >>>>>>> difference of the result of GetStackTrace() and >>>>>>> GetThreadListStackTraces(). >>>>>>> >>>>>>> ? GetStackTrace: jvmtiFrameInfo >>>>>>> ? GetThreadListStackTraces: jvmtiStackInfo >>>>>>> >>>>>>> jvmtiStackInfo contains thread state, and it is ensured it is the >>>>>>> state of the call stack. >>>>>>> If we want to get both call stack and thread state, we need to >>>>>>> suspend target thread, and call both GetStackTrace() and >>>>>>> GetThreadState(). Is it ok? >>>>>>> >>>>>>> I was wondering if JDK-8201641 (parent ticket of this change) >>>>>>> needed them for profiling (dynatrace?) >>>>>>> If it is responsibility of JVMTI agent implementor, I remove this >>>>>>> closure. >>>>>>> >>>>>>> >>>>>>> Thanks, >>>>>>> >>>>>>> Yasumasa >>>>>>> >>>>>>> >>>>>>> On 2020/07/03 16:45, serguei.spitsyn at oracle.com wrote: >>>>>>>> Hi Yasumasa, >>>>>>>> >>>>>>>> After some thinking I've concluded that I do not like this >>>>>>>> optimization >>>>>>>> of the GetThreadListStackTraces with GetSingleStackTraceClosure. >>>>>>>> >>>>>>>> We may need more opinions on this but these are my points: >>>>>>>> ??- it adds some complexity and ugliness >>>>>>>> ??- a win is doubtful because it has to be a rare case, so that >>>>>>>> total overhead should not be high >>>>>>>> ??- if it is really high for some use cases then it is up to the >>>>>>>> user >>>>>>>> ??? to optimize it with using GetStackTrace instead >>>>>>>> >>>>>>>> In such cases with doubtful overhead I usually prefer the >>>>>>>> simplicity. >>>>>>>> >>>>>>>> Good examples where it makes sense to optimize are checks for >>>>>>>> target thread to be current thread. >>>>>>>> In such cases there is no need to suspend the target thread, or >>>>>>>> use a VMop/HandshakeClosure. >>>>>>>> For instance, please, see the Monitor functions with the check: >>>>>>>> (java_thread == calling_thread). >>>>>>>> Getting information for current thread is frequently used case, >>>>>>>> e.g. to get info at an event point. >>>>>>>> >>>>>>>> Thanks, >>>>>>>> Serguei >>>>>>>> >>>>>>>> >>>>>>>> On 7/2/20 23:29, Yasumasa Suenaga wrote: >>>>>>>>> Hi Dan, David, >>>>>>>>> >>>>>>>>> I uploaded new webrev. Could you review again? >>>>>>>>> >>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/ >>>>>>>>> >>>>>>>>> OneGetThreadListStackTraces.java in this webrev would wait >>>>>>>>> until thread state is transited to "waiting" with spin wait. >>>>>>>>> CountDownLatch::await call as Dan pointed is fixed in it :) >>>>>>>>> >>>>>>>>> Diff from webrev.03: >>>>>>>>> http://hg.openjdk.java.net/jdk/submit/rev/c9aeb7001e50 >>>>>>>>> >>>>>>>>> >>>>>>>>> Thanks, >>>>>>>>> >>>>>>>>> Yasumasa >>>>>>>>> >>>>>>>>> >>>>>>>>> On 2020/07/03 14:15, David Holmes wrote: >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> On 3/07/2020 2:27 pm, Yasumasa Suenaga wrote: >>>>>>>>>>> On 2020/07/03 12:24, Daniel D. Daugherty wrote: >>>>>>>>>>>> On 7/2/20 10:50 PM, David Holmes wrote: >>>>>>>>>>>>> Sorry I'm responding here without seeing latest webrev but >>>>>>>>>>>>> there is enough context I think ... >>>>>>>>>>>>> >>>>>>>>>>>>> On 3/07/2020 9:14 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>> Hi Dan, >>>>>>>>>>>>>> >>>>>>>>>>>>>> Thanks for your comment! >>>>>>>>>>>>>> >>>>>>>>>>>>>> On 2020/07/03 7:16, Daniel D. Daugherty wrote: >>>>>>>>>>>>>>> On 7/2/20 5:19 AM, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> I upload new webrev. Could you review again? >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.03/ >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnv.cpp >>>>>>>>>>>>>>> ???? L1542: ??? // Get stack trace with handshake >>>>>>>>>>>>>>> ???????? nit - please add a period at the end. >>>>>>>>>>>>>> >>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>>> ???? L1591: *stack_info_ptr = op.stack_info(); >>>>>>>>>>>>>>> ???????? The return parameter should not be touched >>>>>>>>>>>>>>> unless the return >>>>>>>>>>>>>>> ???????? code in 'err' == JVMTI_ERROR_NONE. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> ???? old L1582: ? if (err == JVMTI_ERROR_NONE) { >>>>>>>>>>>>>>> ???????? Please restore this check. The return parameter >>>>>>>>>>>>>>> should not >>>>>>>>>>>>>>> ???????? be touched unless the return code in 'err' == >>>>>>>>>>>>>>> JVMTI_ERROR_NONE. >>>>>>>>>>>>>> >>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>> >>>>>>>>>>>>> But op.stack_info() will return NULL if the error is not >>>>>>>>>>>>> JVMTI_ERROR_NONE. Are you (Dan) concerned about someone >>>>>>>>>>>>> passing in a non-null/initialized out-pointer that will be >>>>>>>>>>>>> reset to NULL if there was an error? >>>>>>>>>>>> >>>>>>>>>>>> Actually the way we used to test this in POSIX tests is to call >>>>>>>>>>>> an API with known bad parameters and the return parameter ptr >>>>>>>>>>>> set to NULL. If the return parameter ptr was touched when an >>>>>>>>>>>> error should have been detected on an earlier parameter, then >>>>>>>>>>>> the test failed. >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>>> ???? L1272: ? if (!jt->is_exiting() && (thread_oop != >>>>>>>>>>>>>>> NULL)) { >>>>>>>>>>>>>>> ???????? nit - extra parens around the second expression. >>>>>>>>>>>>>> >>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>>> ???? old L1532: ? _result = JVMTI_ERROR_THREAD_NOT_ALIVE; >>>>>>>>>>>>>>> ???????? This deletion of the _result field threw me for >>>>>>>>>>>>>>> a minute and then >>>>>>>>>>>>>>> ???? ? ? I figured out that the field is init to >>>>>>>>>>>>>>> JVMTI_ERROR_THREAD_NOT_ALIVE >>>>>>>>>>>>>>> ???????? in the constructor. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> ???? L1553: ? if (!jt->is_exiting() && (jt->threadObj() >>>>>>>>>>>>>>> != NULL)) { >>>>>>>>>>>>>>> ???????? nit - extra parens around the second expression. >>>>>>>>>>>>>> >>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>>>>>>>>>>> ???? No comments. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> src/hotspot/share/runtime/vmOperations.hpp >>>>>>>>>>>>>>> ???? No comments. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/GetThreadListStackTraces.java >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> ???? No comments. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/OneGetThreadListStackTraces.java >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> ???? L64: ??????? startSignal.countDown(); >>>>>>>>>>>>>>> ???????? I was expecting this to be a call to await() >>>>>>>>>>>>>>> instead of >>>>>>>>>>>>>>> ???????? countDown(). What am I missing here? >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> ???????? I think this test might be passing by accident >>>>>>>>>>>>>>> right now, but... >>>>>>>>>>>>>> >>>>>>>>>>>>>> Main thread (which call JVMTI functions to test) should >>>>>>>>>>>>>> wait until test thread is ready. >>>>>>>>>>>>>> So main thread would wait startSignal, and test thread >>>>>>>>>>>>>> would count down. >>>>>>>>>>>>> >>>>>>>>>>>>> No! >>>>>>>>>>>>> >>>>>>>>>>>>> The test thread that previously called obj.wait() now calls >>>>>>>>>>>>> latch.await(). >>>>>>>>>>>>> >>>>>>>>>>>>> The main thread that previously called obj.notify() now >>>>>>>>>>>>> calls latch.countDown(). >>>>>>>>>>>>> >>>>>>>>>>>>> The main thread continues to spin until it sees the target >>>>>>>>>>>>> is WAITING before proceeding with the test. >>>>>>>>>>> >>>>>>>>>>> If I add spin wait to wait until transit target thread state >>>>>>>>>>> is WAITING (as following), we don't need to call >>>>>>>>>>> SuspendThread(). >>>>>>>>>>> Which is better? >>>>>>>>>> >>>>>>>>>> The original spin-wait loop checking for? WAITING is better >>>>>>>>>> because it is the only guarantee that the target thread is >>>>>>>>>> blocked where you need it to be. suspending the thread is racy >>>>>>>>>> as you don't know exactly where the suspend will hit. >>>>>>>>>> >>>>>>>>>> Thanks, >>>>>>>>>> David >>>>>>>>>> ----- >>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> ``` >>>>>>>>>>> /* Wait until the thread state transits to "waiting" */ >>>>>>>>>>> while (th.getState() != Thread.State.WAITING) { >>>>>>>>>>> ???? Thread.onSpinWait(); >>>>>>>>>>> } >>>>>>>>>>> ``` >>>>>>>>>>> >>>>>>>>>>> For simplify, spin wait is prefer to >>>>>>>>>>> OneGetThreadListStackTraces.java in webrev.03. >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> Thanks, >>>>>>>>>>> >>>>>>>>>>> Yasumasa >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>>> Here's the flow as I see it: >>>>>>>>>>>> >>>>>>>>>>>> main thread >>>>>>>>>>>> ?? - start worker thread >>>>>>>>>>>> ?? - startSignal.await() >>>>>>>>>>>> ???? - main is now blocked >>>>>>>>>>>> >>>>>>>>>>>> worker thread >>>>>>>>>>>> ?? - startSignal.countDown() >>>>>>>>>>>> ???? - main is now unblocked >>>>>>>>>>>> ?? - stopSignal.await() >>>>>>>>>>>> ???? - worker is now blocked >>>>>>>>>>>> >>>>>>>>>>>> main thread >>>>>>>>>>>> ?? - checkCallStacks(th) >>>>>>>>>>>> ?? - stopSignal.countDown() >>>>>>>>>>>> ???? - worker is now unblocked >>>>>>>>>>>> ?? - th.join >>>>>>>>>>>> ???? - main is now blocked >>>>>>>>>>>> >>>>>>>>>>>> worker thread >>>>>>>>>>>> ?? - runs off the end of run() >>>>>>>>>>>> ???? - main is now unblocked >>>>>>>>>>>> >>>>>>>>>>>> main thread >>>>>>>>>>>> ?? - run off the end of main() >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libGetThreadListStackTraces.c >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> ???? L92: ? jthreads = (jthread *)malloc(sizeof(jthread) >>>>>>>>>>>>>>> * num_threads); >>>>>>>>>>>>>>> ???????? You don't check for malloc() failure. >>>>>>>>>>>>>>> ???????? 'jthreads' is allocated but never freed. >>>>>>>>>>>>>> >>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.c >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> ???? L91: ? result = (*jvmti)->SuspendThread(jvmti, thread); >>>>>>>>>>>>>>> ???????? Why are you suspending the thread? >>>>>>>>>>>>>>> GetAllStackTraces() and >>>>>>>>>>>>>>> ???????? GetThreadListStackTraces() do not require the >>>>>>>>>>>>>>> target thread(s) >>>>>>>>>>>>>>> ???????? to be suspend. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> ???????? If you decide not to SuspendThread, then you >>>>>>>>>>>>>>> don't need the >>>>>>>>>>>>>>> ???????? AddCapabilities or the ResumeThread calls. >>>>>>>>>>>>>> >>>>>>>>>>>>>> Test thread might not be entered following code >>>>>>>>>>>>>> (stopSignal.await()). We might see deferent call stack >>>>>>>>>>>>>> between GetAllStackTraces() and >>>>>>>>>>>>>> GetThreadListStackTraces(). We cannot control to freeze >>>>>>>>>>>>>> call stack of test thread in Java code. >>>>>>>>>>>>>> (I didn't use SuspendThread() at first, but I saw some >>>>>>>>>>>>>> errors which causes in above.) >>>>>>>>>>>>>> >>>>>>>>>>>>>> So we need to call SuspendThread() to ensure we can see >>>>>>>>>>>>>> same call stack. >>>>>>>>>>>>> >>>>>>>>>>>>> If you are checking that the thread is in state WAITING >>>>>>>>>>>>> then it cannot escape from that state and you can sample >>>>>>>>>>>>> the stack multiple times from any API and get the same result. >>>>>>>>>>>>> >>>>>>>>>>>>> I suspect the errors you saw were from the apparent >>>>>>>>>>>>> incorrect use of the CountDownLatch. >>>>>>>>>>>> >>>>>>>>>>>> With the flow outlined above, the worker thread should be >>>>>>>>>>>> nicely blocked in stopSignal.await() when stuff is sampled. >>>>>>>>>>>> >>>>>>>>>>>> Dan >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> Cheers, >>>>>>>>>>>>> David >>>>>>>>>>>>> ----- >>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>> >>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>>> Dan >>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> On 2020/07/02 15:05, David Holmes wrote: >>>>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> On 1/07/2020 11:53 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>> Hi, >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> I uploaded new webrev. Could review again? >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.02/ >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Updates look fine - thanks. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> One minor nit: >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> 1274 _collector.allocate_and_fill_stacks(1); >>>>>>>>>>>>>>>>> 1275 _collector.set_result(JVMTI_ERROR_NONE); >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> In the other places where you use _collector you rely >>>>>>>>>>>>>>>>> on result being initialized to JVMTI_ERROR_NONE, rather >>>>>>>>>>>>>>>>> than setting it directly after allocate_and_fill_stacks(). >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Fixed. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> ? 820 >>>>>>>>>>>>>>>>>>>>>>> assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>>>>>>>>>>> ? 821 >>>>>>>>>>>>>>>>>>>>>>> java_thread->is_thread_fully_suspended(false, >>>>>>>>>>>>>>>>>>>>>>> &debug_bits) || >>>>>>>>>>>>>>>>>>>>>>> ? 822 current_thread == >>>>>>>>>>>>>>>>>>>>>>> java_thread->active_handshaker(), >>>>>>>>>>>>>>>>>>>>>>> ? 823????????? "at safepoint / handshake or >>>>>>>>>>>>>>>>>>>>>>> target thread is suspended"); >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> I don't think the suspension check is necessary, >>>>>>>>>>>>>>>>>>>>>>> as even if the target is suspended we must still >>>>>>>>>>>>>>>>>>>>>>> be at a safepoint or in a handshake with it. >>>>>>>>>>>>>>>>>>>>>>> Makes me wonder if we used to allow a racy >>>>>>>>>>>>>>>>>>>>>>> stacktrace operation on a suspended thread, >>>>>>>>>>>>>>>>>>>>>>> assuming it would remain suspended? >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> This function (JvmtiEnvBase::get_stack_trace()) can be >>>>>>>>>>>>>>>>>> called to get own stack trace. For example, we can >>>>>>>>>>>>>>>>>> call GetStackTrace() for current thread at JVMTI event. >>>>>>>>>>>>>>>>>> So I changed assert as below: >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>> ??820?? assert(current_thread == java_thread || >>>>>>>>>>>>>>>>>> ??821 SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>>>>>> ??822????????? current_thread == >>>>>>>>>>>>>>>>>> java_thread->active_handshaker(), >>>>>>>>>>>>>>>>>> ??823????????? "call by myself / at safepoint / at >>>>>>>>>>>>>>>>>> handshake"); >>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Yep good catch. I hope current tests caught that. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> They would be tested in >>>>>>>>>>>>>>>> vmTestbase/nsk/jvmti/GetStackTrace/getstacktr001/ (own >>>>>>>>>>>>>>>> call stacks), and getstacktr003 (call stacks in other >>>>>>>>>>>>>>>> thread). >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Speaking of tests ... >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> In the native code I think you need to check the >>>>>>>>>>>>>>>>> success of all JNI methods that can throw exceptions - >>>>>>>>>>>>>>>>> otherwise I believe the tests may trigger warnings if >>>>>>>>>>>>>>>>> -Xcheck:jni is used with them. See for example: >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/libHeapMonitorTest.cpp >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> I updated testcases to check JNI and JVMTI function calls. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> In the Java code the target thread: >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> ?? 45???? public void run() { >>>>>>>>>>>>>>>>> ?? 46?????? try { >>>>>>>>>>>>>>>>> ?? 47?????????? synchronized (lock) { >>>>>>>>>>>>>>>>> ?? 48?????????????? lock.wait(); >>>>>>>>>>>>>>>>> ?? 49 System.out.println("OK"); >>>>>>>>>>>>>>>>> ?? 50?????????? } >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> is potentially susceptible to spurious wakeups. Using a >>>>>>>>>>>>>>>>> CountDownLatch would be robust. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Fixed. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> On 2020/07/01 8:48, David Holmes wrote: >>>>>>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> On 1/07/2020 9:05 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> 1271 ResourceMark rm; >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> IIUC at this point the _calling_thread is the >>>>>>>>>>>>>>>>>>>>>>> current thread, so we can use: >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> If so, we can call make_local() in L1272 without >>>>>>>>>>>>>>>>>>>> JavaThread (or we can pass current thread to >>>>>>>>>>>>>>>>>>>> make_local()). Is it right? >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>>>>>>>>>>>> 1272 >>>>>>>>>>>>>>>>>>>> _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, >>>>>>>>>>>>>>>>>>>> thread_oop), >>>>>>>>>>>>>>>>>>>> 1273 jt, thread_oop); >>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Sorry I got confused, _calling_thread may not be the >>>>>>>>>>>>>>>>>>> current thread as we could be executing the handshake >>>>>>>>>>>>>>>>>>> in the target thread itself. So the ResourceMark is >>>>>>>>>>>>>>>>>>> correct as-is (implicitly for current thread). >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> The argument to fill_frames will be used in the >>>>>>>>>>>>>>>>>>> jvmtiStackInfo and passed back to the >>>>>>>>>>>>>>>>>>> _calling_thread, so it must be created via >>>>>>>>>>>>>>>>>>> make_local(_calling_thread, ...) as you presently have. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> On 2020/07/01 7:05, David Holmes wrote: >>>>>>>>>>>>>>>>>>>>> On 1/07/2020 12:17 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Thank you for reviewing! I will update new webrev >>>>>>>>>>>>>>>>>>>>>> tomorrow. >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> 466 class MultipleStackTracesCollector : public >>>>>>>>>>>>>>>>>>>>>>> StackObj { >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> ? 498 class VM_GetAllStackTraces : public >>>>>>>>>>>>>>>>>>>>>>> VM_Operation { >>>>>>>>>>>>>>>>>>>>>>> ? 499 private: >>>>>>>>>>>>>>>>>>>>>>> ? 500?? JavaThread *_calling_thread; >>>>>>>>>>>>>>>>>>>>>>> ? 501?? jint _final_thread_count; >>>>>>>>>>>>>>>>>>>>>>> ? 502 MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> You can't have a StackObj as a member of another >>>>>>>>>>>>>>>>>>>>>>> class like that as it may not be on the stack. I >>>>>>>>>>>>>>>>>>>>>>> think MultipleStackTracesCollector should not >>>>>>>>>>>>>>>>>>>>>>> extend any allocation class, and should always be >>>>>>>>>>>>>>>>>>>>>>> embedded directly in another class. >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> I'm not sure what does mean "embedded". >>>>>>>>>>>>>>>>>>>>>> Is it ok as below? >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>> class MultipleStackTracesCollector { >>>>>>>>>>>>>>>>>>>>>> ??? : >>>>>>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> class GetAllStackTraces : public VM_Operation { >>>>>>>>>>>>>>>>>>>>>> ?? private: >>>>>>>>>>>>>>>>>>>>>> MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Yes that I what I meant. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> On 2020/06/30 22:22, David Holmes wrote: >>>>>>>>>>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> On 30/06/2020 10:05 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>>>> Hi David, Serguei, >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> I updated webrev for 8242428. Could you review >>>>>>>>>>>>>>>>>>>>>>>> again? >>>>>>>>>>>>>>>>>>>>>>>> This change migrate to use direct handshake for >>>>>>>>>>>>>>>>>>>>>>>> GetStackTrace() and GetThreadListStackTraces() >>>>>>>>>>>>>>>>>>>>>>>> (when thread_count == 1). >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.01/ >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> This looks really good now! I only have a few >>>>>>>>>>>>>>>>>>>>>>> nits below. There is one thing I don't like about >>>>>>>>>>>>>>>>>>>>>>> it but it requires a change to the main Handshake >>>>>>>>>>>>>>>>>>>>>>> logic to address - in >>>>>>>>>>>>>>>>>>>>>>> JvmtiEnv::GetThreadListStackTraces you have to >>>>>>>>>>>>>>>>>>>>>>> create a ThreadsListHandle to convert the jthread >>>>>>>>>>>>>>>>>>>>>>> to a JavaThread, but then the >>>>>>>>>>>>>>>>>>>>>>> Handshake::execute_direct creates another >>>>>>>>>>>>>>>>>>>>>>> ThreadsListHandle internally. That's a waste. I >>>>>>>>>>>>>>>>>>>>>>> will discuss with Robbin and file a RFE to have >>>>>>>>>>>>>>>>>>>>>>> an overload of execute_direct that takes an >>>>>>>>>>>>>>>>>>>>>>> existing TLH. Actually it's worse than that >>>>>>>>>>>>>>>>>>>>>>> because we have another TLH in use at the entry >>>>>>>>>>>>>>>>>>>>>>> point for the JVMTI functions, so I think there >>>>>>>>>>>>>>>>>>>>>>> may be some scope for simplifying the use of TLH >>>>>>>>>>>>>>>>>>>>>>> instances - future RFE. >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> ??451 GetStackTraceClosure(JvmtiEnv *env, jint >>>>>>>>>>>>>>>>>>>>>>> start_depth, jint max_count, >>>>>>>>>>>>>>>>>>>>>>> ??452 jvmtiFrameInfo* frame_buffer, jint* count_ptr) >>>>>>>>>>>>>>>>>>>>>>> ??453???? : HandshakeClosure("GetStackTrace"), >>>>>>>>>>>>>>>>>>>>>>> ??454?????? _env(env), _start_depth(start_depth), >>>>>>>>>>>>>>>>>>>>>>> _max_count(max_count), >>>>>>>>>>>>>>>>>>>>>>> ??455 _frame_buffer(frame_buffer), >>>>>>>>>>>>>>>>>>>>>>> _count_ptr(count_ptr), >>>>>>>>>>>>>>>>>>>>>>> ??456 _result(JVMTI_ERROR_THREAD_NOT_ALIVE) { >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Nit: can you do one initializer per line please. >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> This looks wrong: >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> 466 class MultipleStackTracesCollector : public >>>>>>>>>>>>>>>>>>>>>>> StackObj { >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> ??498 class VM_GetAllStackTraces : public >>>>>>>>>>>>>>>>>>>>>>> VM_Operation { >>>>>>>>>>>>>>>>>>>>>>> ??499 private: >>>>>>>>>>>>>>>>>>>>>>> ??500?? JavaThread *_calling_thread; >>>>>>>>>>>>>>>>>>>>>>> ??501?? jint _final_thread_count; >>>>>>>>>>>>>>>>>>>>>>> ??502 MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> You can't have a StackObj as a member of another >>>>>>>>>>>>>>>>>>>>>>> class like that as it may not be on the stack. I >>>>>>>>>>>>>>>>>>>>>>> think MultipleStackTracesCollector should not >>>>>>>>>>>>>>>>>>>>>>> extend any allocation class, and should always be >>>>>>>>>>>>>>>>>>>>>>> embedded directly in another class. >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> 481 MultipleStackTracesCollector(JvmtiEnv *env, >>>>>>>>>>>>>>>>>>>>>>> jint max_frame_count) { >>>>>>>>>>>>>>>>>>>>>>> ??482???? _env = env; >>>>>>>>>>>>>>>>>>>>>>> ??483???? _max_frame_count = max_frame_count; >>>>>>>>>>>>>>>>>>>>>>> ??484 _frame_count_total = 0; >>>>>>>>>>>>>>>>>>>>>>> ??485???? _head = NULL; >>>>>>>>>>>>>>>>>>>>>>> ??486???? _stack_info = NULL; >>>>>>>>>>>>>>>>>>>>>>> ??487???? _result = JVMTI_ERROR_NONE; >>>>>>>>>>>>>>>>>>>>>>> ??488?? } >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> As you are touching this can you change it to use >>>>>>>>>>>>>>>>>>>>>>> an initializer list as you did for the >>>>>>>>>>>>>>>>>>>>>>> HandshakeClosure, and please keep one item per line. >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> ??820 >>>>>>>>>>>>>>>>>>>>>>> assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>>>>>>>>>>> ??821 >>>>>>>>>>>>>>>>>>>>>>> java_thread->is_thread_fully_suspended(false, >>>>>>>>>>>>>>>>>>>>>>> &debug_bits) || >>>>>>>>>>>>>>>>>>>>>>> ??822 current_thread == >>>>>>>>>>>>>>>>>>>>>>> java_thread->active_handshaker(), >>>>>>>>>>>>>>>>>>>>>>> ??823????????? "at safepoint / handshake or >>>>>>>>>>>>>>>>>>>>>>> target thread is suspended"); >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> I don't think the suspension check is necessary, >>>>>>>>>>>>>>>>>>>>>>> as even if the target is suspended we must still >>>>>>>>>>>>>>>>>>>>>>> be at a safepoint or in a handshake with it. >>>>>>>>>>>>>>>>>>>>>>> Makes me wonder if we used to allow a racy >>>>>>>>>>>>>>>>>>>>>>> stacktrace operation on a suspended thread, >>>>>>>>>>>>>>>>>>>>>>> assuming it would remain suspended? >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> 1268?? oop thread_oop = jt->threadObj(); >>>>>>>>>>>>>>>>>>>>>>> 1269 >>>>>>>>>>>>>>>>>>>>>>> 1270?? if (!jt->is_exiting() && (jt->threadObj() >>>>>>>>>>>>>>>>>>>>>>> != NULL)) { >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> You can use thread_oop in line 1270. >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> 1272 >>>>>>>>>>>>>>>>>>>>>>> _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, >>>>>>>>>>>>>>>>>>>>>>> thread_oop), >>>>>>>>>>>>>>>>>>>>>>> 1273 jt, thread_oop); >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> It is frustrating that this entire call chain >>>>>>>>>>>>>>>>>>>>>>> started with a jthread reference, which we >>>>>>>>>>>>>>>>>>>>>>> converted to a JavaThread, only to eventually >>>>>>>>>>>>>>>>>>>>>>> need to convert it back to a jthread! I think >>>>>>>>>>>>>>>>>>>>>>> there is some scope for simplification here but >>>>>>>>>>>>>>>>>>>>>>> not as part of this change. >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> IIUC at this point the _calling_thread is the >>>>>>>>>>>>>>>>>>>>>>> current thread, so we can use: >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Please add @bug lines to the tests. >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> I'm still pondering the test logic but wanted to >>>>>>>>>>>>>>>>>>>>>>> send this now. >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>>>>>>>>> VM_GetThreadListStackTrace (for >>>>>>>>>>>>>>>>>>>>>>>> GetThreadListStackTraces) and >>>>>>>>>>>>>>>>>>>>>>>> VM_GetAllStackTraces (for GetAllStackTraces) >>>>>>>>>>>>>>>>>>>>>>>> have inherited VM_GetMultipleStackTraces VM >>>>>>>>>>>>>>>>>>>>>>>> operation which provides the feature to generate >>>>>>>>>>>>>>>>>>>>>>>> jvmtiStackInfo. I modified >>>>>>>>>>>>>>>>>>>>>>>> VM_GetMultipleStackTraces to a normal C++ class >>>>>>>>>>>>>>>>>>>>>>>> to share with HandshakeClosure for >>>>>>>>>>>>>>>>>>>>>>>> GetThreadListStackTraces >>>>>>>>>>>>>>>>>>>>>>>> (GetSingleStackTraceClosure). >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Also I added new testcases which test >>>>>>>>>>>>>>>>>>>>>>>> GetThreadListStackTraces() with thread_count == >>>>>>>>>>>>>>>>>>>>>>>> 1 and with all threads. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> This change has been tested in >>>>>>>>>>>>>>>>>>>>>>>> serviceability/jvmti serviceability/jdwp >>>>>>>>>>>>>>>>>>>>>>>> vmTestbase/nsk/jvmti vmTestbase/nsk/jdi >>>>>>>>>>>>>>>>>>>>>>>> vmTestbase/nsk/jdwp. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> On 2020/06/24 15:50, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>>>>> Hi all, >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> Please review this change: >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> ?? JBS: >>>>>>>>>>>>>>>>>>>>>>>>> https://bugs.openjdk.java.net/browse/JDK-8242428 >>>>>>>>>>>>>>>>>>>>>>>>> ?? webrev: >>>>>>>>>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.00/ >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> This change replace following VM operations to >>>>>>>>>>>>>>>>>>>>>>>>> direct handshake. >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> ??- VM_GetFrameCount (GetFrameCount()) >>>>>>>>>>>>>>>>>>>>>>>>> ??- VM_GetFrameLocation (GetFrameLocation()) >>>>>>>>>>>>>>>>>>>>>>>>> ??- VM_GetThreadListStackTraces >>>>>>>>>>>>>>>>>>>>>>>>> (GetThreadListStackTrace()) >>>>>>>>>>>>>>>>>>>>>>>>> ??- VM_GetCurrentLocation >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> GetThreadListStackTrace() uses direct handshake >>>>>>>>>>>>>>>>>>>>>>>>> if thread count == 1. In other case (thread >>>>>>>>>>>>>>>>>>>>>>>>> count > 1), it would be performed as VM >>>>>>>>>>>>>>>>>>>>>>>>> operation (VM_GetThreadListStackTraces). >>>>>>>>>>>>>>>>>>>>>>>>> Caller of VM_GetCurrentLocation >>>>>>>>>>>>>>>>>>>>>>>>> (JvmtiEnvThreadState::reset_current_location()) >>>>>>>>>>>>>>>>>>>>>>>>> might be called at safepoint. So I added >>>>>>>>>>>>>>>>>>>>>>>>> safepoint check in its caller. >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> This change has been tested in >>>>>>>>>>>>>>>>>>>>>>>>> serviceability/jvmti serviceability/jdwp >>>>>>>>>>>>>>>>>>>>>>>>> vmTestbase/nsk/jvmti vmTestbase/nsk/jdi >>>>>>>>>>>>>>>>>>>>>>>>> vmTestbase/ns >>>>>>>>>>>>>>>>>>>>>>>>> k/jdwp. >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> Also I tested it on submit repo, then it has >>>>>>>>>>>>>>>>>>>>>>>>> execution error >>>>>>>>>>>>>>>>>>>>>>>>> (mach5-one-ysuenaga-JDK-8242428-20200624-0054-12034717) >>>>>>>>>>>>>>>>>>>>>>>>> due to dependency error. So I think it does not >>>>>>>>>>>>>>>>>>>>>>>>> occur by this change. >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>> >>>>>> >>>> >> From chris.plummer at oracle.com Tue Jul 7 04:18:15 2020 From: chris.plummer at oracle.com (Chris Plummer) Date: Mon, 6 Jul 2020 21:18:15 -0700 Subject: RFR(XS): 8248878: SA: Implement simple workaround for JDK-8248876 Message-ID: <39ac40d6-a738-3214-d86c-412152a631d4@oracle.com> Hello, Please help review the following: http://cr.openjdk.java.net/~cjplummer/8248878/webrev.00/index.html https://bugs.openjdk.java.net/browse/JDK-8248878 The explanation of the fix is in the CR. The parent CR, JDK-8248876 [1], explains the issue being addressed. There's no test for this fix yet. It requires the changes I'm making for JDK-8247514 [2], which include changes to "findpc" support and the ClhsdbFindPC.java test that trigger this issue. [1] https://bugs.openjdk.java.net/browse/JDK-8248876 [2] https://bugs.openjdk.java.net/browse/JDK-8247514 thanks, Chris From chris.plummer at oracle.com Tue Jul 7 04:31:34 2020 From: chris.plummer at oracle.com (Chris Plummer) Date: Mon, 6 Jul 2020 21:31:34 -0700 Subject: RFR(XS): 8248879: SA core file support on OSX has some bugs trying to locate the jvm libraries Message-ID: <6089f692-152b-8615-dfca-779f2b5028a0@oracle.com> Hello, Please help review the following: http://cr.openjdk.java.net/~cjplummer/8248879/webrev.00/index.html https://bugs.openjdk.java.net/browse/JDK-8248879 The description of the problem and the fix are both in the CR. thanks, Chris From suenaga at oss.nttdata.com Tue Jul 7 04:57:14 2020 From: suenaga at oss.nttdata.com (Yasumasa Suenaga) Date: Tue, 7 Jul 2020 13:57:14 +0900 Subject: RFR: 8242428: JVMTI thread operations should use Thread-Local Handshake In-Reply-To: References: <6c263e4c-0a83-be7a-0288-ecb2de0b7cea@oss.nttdata.com> <763793b1-9506-44c6-0681-1c71c44a44fd@oss.nttdata.com> <5107c478-1de2-7a49-ee71-dfad6a99a667@oracle.com> <90cdfef9-e558-0d25-33f5-25b7d65bb83b@oss.nttdata.com> <0e359819-618f-c17b-a427-bb7e4daa2c58@oracle.com> <3f890bed-6892-e64d-b21b-ca0cbe11784e@oracle.com> <7dc1903b-6295-3864-6301-4c02aacdb971@oss.nttdata.com> <04e09eb7-9483-8f63-4bb4-01c9e814802e@oracle.com> <238a89a3-06b1-90e4-d5a4-8dc2f1ed12ab@oracle.com> <4c43bc2c-551e-d042-8fa7-b63e755888d1@oracle.com> <8c387550-a06e-6320-f453-0e898486befb@oss.nttdata.com> Message-ID: <19cfa2a7-f441-425d-5623-1c11c6a870b6@oss.nttdata.com> Hi David, On 2020/07/07 11:31, David Holmes wrote: > Hi Yasumasa, > > Hard to keep up with the changes - especially without incremental webrevs. Sorry, I will upload diff from previous webrev in the next. > If GetSingleStackTraceClosure also took the jthread as a constructor arg, then you wouldn't need to recreate a JNI local handle when calling _collector.fill_frames. It's a small simplification and not essential at this stage. I think we should get jthread from an argument of do_thread() because do_thread() would pass the thread which are stopped certainly. It might be simplification if we pass _calling_thread to MultipleStackTracesCollector. `jthread` is only needed to store jvmtiStackInfo.thread . What do you think? > For the test ... I don't see how Java_GetThreadListStackTraces_checkCallStacks is a valid test. It gets the stacks of all live threads, then uses that information to use GetThreadListStackTraces to get the stack for the same set of threads through a different API. It then compares the two sets of stacks for each thread expecting them to be the same, but that need only be the case for the main thread. Other threads could potentially have a different stack (e.g. if this test is run with JFR enabled there will be additional threads found.) Further I would have expected that there already exist tests that check that, for a given thread (which may be suspended or known to be blocked) the same stack is found through the two different APIs. vmTestbase/nsk/jvmti/unit/GetAllStackTraces/getallstktr001 would check all of threads via GetThreadListStackTraces() and GetAllStackTraces(), so we might be able to remove GetThreadListStackTraces.java from this webrev. OTOH we don't have testcase for GetThreadListStackTraces() with thread_count == 1, so we need to testcase for it (it is OneGetThreadListStackTraces.java) It would check whether the state of target thread is "waiting" before JNI call to call GetThreadListStackTraces(), and also I expect it would not be run with JFR. (it is not described @run) Of course we can check GetThreadListStackTraces() with main thread, but it is not the test for direct handshake for other thread. Thanks, Yasumasa > Thanks, > David > ----- > > On 6/07/2020 11:29 pm, Yasumasa Suenaga wrote: >> Hi Serguei, >> >> Thanks for your comment! >> >> I think C++ is more simple to implement the test agent as you said. >> So I implement it in C++ in new webrev. Could you review again? >> >> ?? http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.06/ >> >> Also I refactored libGetThreadListStackTraces.cpp, and I've kept exception check after IsSameObject(). >> >> >> Thanks, >> >> Yasumasa >> >> >> On 2020/07/06 16:32, serguei.spitsyn at oracle.com wrote: >>> Hi Yasumasa, >>> >>> Thank you for the update. >>> I think, a pending exception after IsSameObject needs to be checked. >>> >>> The checkStackInfo() needs one more refactoring as I've already suggested. >>> The body of the loop at L68-L78 should be converted to a function check_frame_info. >>> The si1->frame_buffer[i] and si2->frame_buffer[i] will be passed as fi1 and fi2. >>> The index can be passed as well. >>> I'm still suggesting to simplify the local exception_msg to something shorter like err_msg or exc_msg. >>> >>> I'm not sure using fatal is right here: >>> >>> This fragment looks strange: >>> >>> ? 152???? if ((*env)->IsSameObject(env, stack_info[i].thread, thread)) { >>> ? 153?????? target_info = &stack_info[i]; >>> ? 154?????? break; >>> ? 155???? } else if ((*env)->ExceptionOccurred(env)) { >>> ? 156?????? (*env)->ExceptionDescribe(env); >>> ? 157?????? (*env)->FatalError(env, __FILE__); >>> ? 158???? } >>> >>> I expected it to be: >>> >>> ??? jboolean same = (*env)->IsSameObject(env, stack_info[i].thread, thread); >>> ??? if ((*env)->ExceptionOccurred(env)) { >>> ????? (*env)->ExceptionDescribe(env); >>> ????? (*env)->FatalError(env, __FILE__); >>> ??? } >>> ??? if (same) { >>> ????? target_info = &stack_info[i]; >>> ????? break; >>> ??? } >>> >>> Would it better to port this agent to C++ to simplify this code nicer? >>> >>> Thanks, >>> Serguei >>> >>> >>> On 7/5/20 06:13, Yasumasa Suenaga wrote: >>>> Hi Serguei, >>>> >>>> Thanks for your comment! >>>> I refactored testcase. Could you review again? >>>> >>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.05/ >>>> >>>> It would check Java exception after IsSameObject() call. Does it need? >>>> Any exceptions are not described in JNI document[1], and JNI implementation (jni_IsSameObject()) does not seem to throw it. >>>> >>>> >>>> Thanks, >>>> >>>> Yasumasa >>>> >>>> >>>> [1] https://docs.oracle.com/en/java/javase/14/docs/specs/jni/functions.html#issameobject >>>> >>>> >>>> On 2020/07/05 14:46, serguei.spitsyn at oracle.com wrote: >>>>> Hi Yasumasa, >>>>> >>>>> >>>>> Okay, thanks. >>>>> Then I'm okay to keep the GetSingleStackTraceClosure. >>>>> >>>>> >>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libGetThreadListStackTraces.c.html >>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.c.html >>>>> >>>>> I'm not sure the function 'is_same_thread() is needed. >>>>> Why do not use the JNI IsSameObject instead? >>>>> >>>>> It seems to be a typo at L132 and L137. >>>>> You, probably. did not want to print the same information for stack_info_1[i].frame_buffer[j].XXX twice. >>>>> >>>>> The code at lines 112-142 is not readable. >>>>> I'd suggest to make a couple of refactoring steps. >>>>> >>>>> First step to simplify this a little bit would be with some renaming and getting rid of indexes: >>>>> >>>>> ?? 71 char err_msg[EXCEPTION_MSG_LEN] = {0}; >>>>> ??... >>>>> ??112?? /* Iterate all jvmtiStackInfo to check */ >>>>> ??113?? for (i = 0; i < num_threads, *exception_msg != '\0'; i++) { >>>>> ????????? jvmtiStackInfo *si1 = stack_info_1[i]; >>>>> ????????? jvmtiStackInfo *si2 = stack_info_2[i]; >>>>> ??114???? if (!IsSameObject(env, si1.thread, si2.thread)) { /* jvmtiStackInfo::thread */ >>>>> ??115?????? snprintf(err_msg, sizeof(err_msg), >>>>> ??116??????????????? "thread[%d] is different: stack_info_1 = %p, stack_info_2 = %p", >>>>> ??117??????????????? i, sinfo1.thread, sinfo2.thread); >>>>> ??118???? } else if (si1.state != si2.state) { /* jvmtiStackInfo::state */ >>>>> ??119?????? snprintf(err_msg, sizeof(err_msg), >>>>> ??120??????????????? "state[%d] is different: stack_info_1 = %d, stack_info_2 = %d", >>>>> ??121??????????????? i, si1.state, si2.state); >>>>> ??122???? } else if (si1.frame_count != si2.frame_count) { /* jvmtiStackInfo::frame_count */ >>>>> ??123?????? snprintf(err_msg, sizeof(err_msg), >>>>> ??124??????????????? "frame_count[%d] is different: stack_info_1 = %d, stack_info_2 = %d", >>>>> ??125??????????????? i, si1.frame_count, si2.frame_count); >>>>> ??126???? } else { >>>>> ??127?????? /* Iterate all jvmtiFrameInfo to check */ >>>>> ??128?????? for (j = 0; j < si1.frame_count; j++) { >>>>> ??129???????? if (si1.frame_buffer[j].method != si1.frame_buffer[j].method) { /* jvmtiFrameInfo::method */ >>>>> ??130?????????? snprintf(err_msg, sizeof(err_msg), >>>>> ??131??????????????????? "thread [%d] frame_buffer[%d].method is different: stack_info_1 = %lx, stack_info_2 = %lx", >>>>> ??132??????????????????? i, j, si1.frame_buffer[j].method, si2.frame_buffer[j].method); >>>>> ??133?????????? break; >>>>> ??134???????? } else if (si1.frame_buffer[j].location != si1.frame_buffer[j].location) { /* jvmtiFrameInfo::location */ >>>>> ??135?????????? snprintf(err_msg, sizeof(err_msg), >>>>> ??136??????????????????? "thread [%d] frame_buffer[%d].location is different: stack_info_1 = %ld, stack_info_2 = %ld", >>>>> ??137??????????????????? i, j, si1.frame_buffer[j].location, si2.frame_buffer[j].location); >>>>> ??138?????????? break; >>>>> ??139???????? } >>>>> ??140?????? } >>>>> ??141???? } >>>>> ??142?? } >>>>> >>>>> Another step would be to create functions that implement a body of each loop. >>>>> You can use the same techniques to simplify similar place (L127-L138) in the libOneGetThreadListStackTraces.c. >>>>> >>>>> Thanks, >>>>> Serguei >>>>> >>>>> >>>>> On 7/3/20 15:55, Yasumasa Suenaga wrote: >>>>>> Hi Serguei, >>>>>> >>>>>> I'm not an Oracle employee, so I cannot know real request(s) from your customers. >>>>>> However JDK-8201641 says Dynatrace has requested this enhancement. >>>>>> >>>>>> BTW I haven't heared any request from my customers about this. >>>>>> >>>>>> >>>>>> Thanks, >>>>>> >>>>>> Yasumasa >>>>>> >>>>>> >>>>>> On 2020/07/04 4:32, serguei.spitsyn at oracle.com wrote: >>>>>>> Hi Yasumasa, >>>>>>> >>>>>>> This difference is not that big to care about. >>>>>>> I feel this is really rare case and so, does not worth these complications. >>>>>>> Do we have a real request from customers to optimize it? >>>>>>> >>>>>>> Thanks, >>>>>>> Serguei >>>>>>> >>>>>>> >>>>>>> On 7/3/20 01:16, Yasumasa Suenaga wrote: >>>>>>>> Hi Serguei, >>>>>>>> >>>>>>>> Generally I agree with you, but I have concern about the difference of the result of GetStackTrace() and GetThreadListStackTraces(). >>>>>>>> >>>>>>>> ? GetStackTrace: jvmtiFrameInfo >>>>>>>> ? GetThreadListStackTraces: jvmtiStackInfo >>>>>>>> >>>>>>>> jvmtiStackInfo contains thread state, and it is ensured it is the state of the call stack. >>>>>>>> If we want to get both call stack and thread state, we need to suspend target thread, and call both GetStackTrace() and GetThreadState(). Is it ok? >>>>>>>> >>>>>>>> I was wondering if JDK-8201641 (parent ticket of this change) needed them for profiling (dynatrace?) >>>>>>>> If it is responsibility of JVMTI agent implementor, I remove this closure. >>>>>>>> >>>>>>>> >>>>>>>> Thanks, >>>>>>>> >>>>>>>> Yasumasa >>>>>>>> >>>>>>>> >>>>>>>> On 2020/07/03 16:45, serguei.spitsyn at oracle.com wrote: >>>>>>>>> Hi Yasumasa, >>>>>>>>> >>>>>>>>> After some thinking I've concluded that I do not like this optimization >>>>>>>>> of the GetThreadListStackTraces with GetSingleStackTraceClosure. >>>>>>>>> >>>>>>>>> We may need more opinions on this but these are my points: >>>>>>>>> ??- it adds some complexity and ugliness >>>>>>>>> ??- a win is doubtful because it has to be a rare case, so that total overhead should not be high >>>>>>>>> ??- if it is really high for some use cases then it is up to the user >>>>>>>>> ??? to optimize it with using GetStackTrace instead >>>>>>>>> >>>>>>>>> In such cases with doubtful overhead I usually prefer the simplicity. >>>>>>>>> >>>>>>>>> Good examples where it makes sense to optimize are checks for target thread to be current thread. >>>>>>>>> In such cases there is no need to suspend the target thread, or use a VMop/HandshakeClosure. >>>>>>>>> For instance, please, see the Monitor functions with the check: (java_thread == calling_thread). >>>>>>>>> Getting information for current thread is frequently used case, e.g. to get info at an event point. >>>>>>>>> >>>>>>>>> Thanks, >>>>>>>>> Serguei >>>>>>>>> >>>>>>>>> >>>>>>>>> On 7/2/20 23:29, Yasumasa Suenaga wrote: >>>>>>>>>> Hi Dan, David, >>>>>>>>>> >>>>>>>>>> I uploaded new webrev. Could you review again? >>>>>>>>>> >>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/ >>>>>>>>>> >>>>>>>>>> OneGetThreadListStackTraces.java in this webrev would wait until thread state is transited to "waiting" with spin wait. >>>>>>>>>> CountDownLatch::await call as Dan pointed is fixed in it :) >>>>>>>>>> >>>>>>>>>> Diff from webrev.03: >>>>>>>>>> http://hg.openjdk.java.net/jdk/submit/rev/c9aeb7001e50 >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> Thanks, >>>>>>>>>> >>>>>>>>>> Yasumasa >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> On 2020/07/03 14:15, David Holmes wrote: >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> On 3/07/2020 2:27 pm, Yasumasa Suenaga wrote: >>>>>>>>>>>> On 2020/07/03 12:24, Daniel D. Daugherty wrote: >>>>>>>>>>>>> On 7/2/20 10:50 PM, David Holmes wrote: >>>>>>>>>>>>>> Sorry I'm responding here without seeing latest webrev but there is enough context I think ... >>>>>>>>>>>>>> >>>>>>>>>>>>>> On 3/07/2020 9:14 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>> Hi Dan, >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Thanks for your comment! >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> On 2020/07/03 7:16, Daniel D. Daugherty wrote: >>>>>>>>>>>>>>>> On 7/2/20 5:19 AM, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> I upload new webrev. Could you review again? >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.03/ >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnv.cpp >>>>>>>>>>>>>>>> ???? L1542: ??? // Get stack trace with handshake >>>>>>>>>>>>>>>> ???????? nit - please add a period at the end. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> ???? L1591: *stack_info_ptr = op.stack_info(); >>>>>>>>>>>>>>>> ???????? The return parameter should not be touched unless the return >>>>>>>>>>>>>>>> ???????? code in 'err' == JVMTI_ERROR_NONE. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> ???? old L1582: ? if (err == JVMTI_ERROR_NONE) { >>>>>>>>>>>>>>>> ???????? Please restore this check. The return parameter should not >>>>>>>>>>>>>>>> ???????? be touched unless the return code in 'err' == JVMTI_ERROR_NONE. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>> >>>>>>>>>>>>>> But op.stack_info() will return NULL if the error is not JVMTI_ERROR_NONE. Are you (Dan) concerned about someone passing in a non-null/initialized out-pointer that will be reset to NULL if there was an error? >>>>>>>>>>>>> >>>>>>>>>>>>> Actually the way we used to test this in POSIX tests is to call >>>>>>>>>>>>> an API with known bad parameters and the return parameter ptr >>>>>>>>>>>>> set to NULL. If the return parameter ptr was touched when an >>>>>>>>>>>>> error should have been detected on an earlier parameter, then >>>>>>>>>>>>> the test failed. >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> ???? L1272: ? if (!jt->is_exiting() && (thread_oop != NULL)) { >>>>>>>>>>>>>>>> ???????? nit - extra parens around the second expression. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>>>> ???? old L1532: ? _result = JVMTI_ERROR_THREAD_NOT_ALIVE; >>>>>>>>>>>>>>>> ???????? This deletion of the _result field threw me for a minute and then >>>>>>>>>>>>>>>> ???? ? ? I figured out that the field is init to JVMTI_ERROR_THREAD_NOT_ALIVE >>>>>>>>>>>>>>>> ???????? in the constructor. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> ???? L1553: ? if (!jt->is_exiting() && (jt->threadObj() != NULL)) { >>>>>>>>>>>>>>>> ???????? nit - extra parens around the second expression. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>>>>>>>>>>>> ???? No comments. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> src/hotspot/share/runtime/vmOperations.hpp >>>>>>>>>>>>>>>> ???? No comments. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/GetThreadListStackTraces.java >>>>>>>>>>>>>>>> ???? No comments. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/OneGetThreadListStackTraces.java >>>>>>>>>>>>>>>> ???? L64: ??????? startSignal.countDown(); >>>>>>>>>>>>>>>> ???????? I was expecting this to be a call to await() instead of >>>>>>>>>>>>>>>> ???????? countDown(). What am I missing here? >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> ???????? I think this test might be passing by accident right now, but... >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Main thread (which call JVMTI functions to test) should wait until test thread is ready. >>>>>>>>>>>>>>> So main thread would wait startSignal, and test thread would count down. >>>>>>>>>>>>>> >>>>>>>>>>>>>> No! >>>>>>>>>>>>>> >>>>>>>>>>>>>> The test thread that previously called obj.wait() now calls latch.await(). >>>>>>>>>>>>>> >>>>>>>>>>>>>> The main thread that previously called obj.notify() now calls latch.countDown(). >>>>>>>>>>>>>> >>>>>>>>>>>>>> The main thread continues to spin until it sees the target is WAITING before proceeding with the test. >>>>>>>>>>>> >>>>>>>>>>>> If I add spin wait to wait until transit target thread state is WAITING (as following), we don't need to call SuspendThread(). >>>>>>>>>>>> Which is better? >>>>>>>>>>> >>>>>>>>>>> The original spin-wait loop checking for? WAITING is better because it is the only guarantee that the target thread is blocked where you need it to be. suspending the thread is racy as you don't know exactly where the suspend will hit. >>>>>>>>>>> >>>>>>>>>>> Thanks, >>>>>>>>>>> David >>>>>>>>>>> ----- >>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> ``` >>>>>>>>>>>> /* Wait until the thread state transits to "waiting" */ >>>>>>>>>>>> while (th.getState() != Thread.State.WAITING) { >>>>>>>>>>>> ???? Thread.onSpinWait(); >>>>>>>>>>>> } >>>>>>>>>>>> ``` >>>>>>>>>>>> >>>>>>>>>>>> For simplify, spin wait is prefer to OneGetThreadListStackTraces.java in webrev.03. >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> Thanks, >>>>>>>>>>>> >>>>>>>>>>>> Yasumasa >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>>> Here's the flow as I see it: >>>>>>>>>>>>> >>>>>>>>>>>>> main thread >>>>>>>>>>>>> ?? - start worker thread >>>>>>>>>>>>> ?? - startSignal.await() >>>>>>>>>>>>> ???? - main is now blocked >>>>>>>>>>>>> >>>>>>>>>>>>> worker thread >>>>>>>>>>>>> ?? - startSignal.countDown() >>>>>>>>>>>>> ???? - main is now unblocked >>>>>>>>>>>>> ?? - stopSignal.await() >>>>>>>>>>>>> ???? - worker is now blocked >>>>>>>>>>>>> >>>>>>>>>>>>> main thread >>>>>>>>>>>>> ?? - checkCallStacks(th) >>>>>>>>>>>>> ?? - stopSignal.countDown() >>>>>>>>>>>>> ???? - worker is now unblocked >>>>>>>>>>>>> ?? - th.join >>>>>>>>>>>>> ???? - main is now blocked >>>>>>>>>>>>> >>>>>>>>>>>>> worker thread >>>>>>>>>>>>> ?? - runs off the end of run() >>>>>>>>>>>>> ???? - main is now unblocked >>>>>>>>>>>>> >>>>>>>>>>>>> main thread >>>>>>>>>>>>> ?? - run off the end of main() >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libGetThreadListStackTraces.c >>>>>>>>>>>>>>>> ???? L92: ? jthreads = (jthread *)malloc(sizeof(jthread) * num_threads); >>>>>>>>>>>>>>>> ???????? You don't check for malloc() failure. >>>>>>>>>>>>>>>> ???????? 'jthreads' is allocated but never freed. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.c >>>>>>>>>>>>>>>> ???? L91: ? result = (*jvmti)->SuspendThread(jvmti, thread); >>>>>>>>>>>>>>>> ???????? Why are you suspending the thread? GetAllStackTraces() and >>>>>>>>>>>>>>>> ???????? GetThreadListStackTraces() do not require the target thread(s) >>>>>>>>>>>>>>>> ???????? to be suspend. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> ???????? If you decide not to SuspendThread, then you don't need the >>>>>>>>>>>>>>>> ???????? AddCapabilities or the ResumeThread calls. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Test thread might not be entered following code (stopSignal.await()). We might see deferent call stack between GetAllStackTraces() and GetThreadListStackTraces(). We cannot control to freeze call stack of test thread in Java code. >>>>>>>>>>>>>>> (I didn't use SuspendThread() at first, but I saw some errors which causes in above.) >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> So we need to call SuspendThread() to ensure we can see same call stack. >>>>>>>>>>>>>> >>>>>>>>>>>>>> If you are checking that the thread is in state WAITING then it cannot escape from that state and you can sample the stack multiple times from any API and get the same result. >>>>>>>>>>>>>> >>>>>>>>>>>>>> I suspect the errors you saw were from the apparent incorrect use of the CountDownLatch. >>>>>>>>>>>>> >>>>>>>>>>>>> With the flow outlined above, the worker thread should be >>>>>>>>>>>>> nicely blocked in stopSignal.await() when stuff is sampled. >>>>>>>>>>>>> >>>>>>>>>>>>> Dan >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> Cheers, >>>>>>>>>>>>>> David >>>>>>>>>>>>>> ----- >>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Dan >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> On 2020/07/02 15:05, David Holmes wrote: >>>>>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> On 1/07/2020 11:53 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>> Hi, >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> I uploaded new webrev. Could review again? >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.02/ >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Updates look fine - thanks. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> One minor nit: >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> 1274 _collector.allocate_and_fill_stacks(1); >>>>>>>>>>>>>>>>>> 1275 _collector.set_result(JVMTI_ERROR_NONE); >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> In the other places where you use _collector you rely on result being initialized to JVMTI_ERROR_NONE, rather than setting it directly after allocate_and_fill_stacks(). >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Fixed. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> ? 820 assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>>>>>>>>>>>> ? 821 java_thread->is_thread_fully_suspended(false, &debug_bits) || >>>>>>>>>>>>>>>>>>>>>>>> ? 822 current_thread == java_thread->active_handshaker(), >>>>>>>>>>>>>>>>>>>>>>>> ? 823????????? "at safepoint / handshake or target thread is suspended"); >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> I don't think the suspension check is necessary, as even if the target is suspended we must still be at a safepoint or in a handshake with it. Makes me wonder if we used to allow a racy stacktrace operation on a suspended thread, assuming it would remain suspended? >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> This function (JvmtiEnvBase::get_stack_trace()) can be called to get own stack trace. For example, we can call GetStackTrace() for current thread at JVMTI event. >>>>>>>>>>>>>>>>>>> So I changed assert as below: >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>> ??820?? assert(current_thread == java_thread || >>>>>>>>>>>>>>>>>>> ??821 SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>>>>>>> ??822????????? current_thread == java_thread->active_handshaker(), >>>>>>>>>>>>>>>>>>> ??823????????? "call by myself / at safepoint / at handshake"); >>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Yep good catch. I hope current tests caught that. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> They would be tested in vmTestbase/nsk/jvmti/GetStackTrace/getstacktr001/ (own call stacks), and getstacktr003 (call stacks in other thread). >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Speaking of tests ... >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> In the native code I think you need to check the success of all JNI methods that can throw exceptions - otherwise I believe the tests may trigger warnings if -Xcheck:jni is used with them. See for example: >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/libHeapMonitorTest.cpp >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> I updated testcases to check JNI and JVMTI function calls. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> In the Java code the target thread: >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> ?? 45???? public void run() { >>>>>>>>>>>>>>>>>> ?? 46?????? try { >>>>>>>>>>>>>>>>>> ?? 47?????????? synchronized (lock) { >>>>>>>>>>>>>>>>>> ?? 48?????????????? lock.wait(); >>>>>>>>>>>>>>>>>> ?? 49 System.out.println("OK"); >>>>>>>>>>>>>>>>>> ?? 50?????????? } >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> is potentially susceptible to spurious wakeups. Using a CountDownLatch would be robust. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Fixed. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> On 2020/07/01 8:48, David Holmes wrote: >>>>>>>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> On 1/07/2020 9:05 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> 1271 ResourceMark rm; >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> IIUC at this point the _calling_thread is the current thread, so we can use: >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> If so, we can call make_local() in L1272 without JavaThread (or we can pass current thread to make_local()). Is it right? >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>>>>>>>>>>>>> 1272 _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, thread_oop), >>>>>>>>>>>>>>>>>>>>> 1273 jt, thread_oop); >>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Sorry I got confused, _calling_thread may not be the current thread as we could be executing the handshake in the target thread itself. So the ResourceMark is correct as-is (implicitly for current thread). >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> The argument to fill_frames will be used in the jvmtiStackInfo and passed back to the _calling_thread, so it must be created via make_local(_calling_thread, ...) as you presently have. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> On 2020/07/01 7:05, David Holmes wrote: >>>>>>>>>>>>>>>>>>>>>> On 1/07/2020 12:17 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Thank you for reviewing! I will update new webrev tomorrow. >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> 466 class MultipleStackTracesCollector : public StackObj { >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> ? 498 class VM_GetAllStackTraces : public VM_Operation { >>>>>>>>>>>>>>>>>>>>>>>> ? 499 private: >>>>>>>>>>>>>>>>>>>>>>>> ? 500?? JavaThread *_calling_thread; >>>>>>>>>>>>>>>>>>>>>>>> ? 501?? jint _final_thread_count; >>>>>>>>>>>>>>>>>>>>>>>> ? 502 MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> You can't have a StackObj as a member of another class like that as it may not be on the stack. I think MultipleStackTracesCollector should not extend any allocation class, and should always be embedded directly in another class. >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> I'm not sure what does mean "embedded". >>>>>>>>>>>>>>>>>>>>>>> Is it ok as below? >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>>> class MultipleStackTracesCollector { >>>>>>>>>>>>>>>>>>>>>>> ??? : >>>>>>>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> class GetAllStackTraces : public VM_Operation { >>>>>>>>>>>>>>>>>>>>>>> ?? private: >>>>>>>>>>>>>>>>>>>>>>> MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Yes that I what I meant. >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> On 2020/06/30 22:22, David Holmes wrote: >>>>>>>>>>>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> On 30/06/2020 10:05 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>>>>> Hi David, Serguei, >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> I updated webrev for 8242428. Could you review again? >>>>>>>>>>>>>>>>>>>>>>>>> This change migrate to use direct handshake for GetStackTrace() and GetThreadListStackTraces() (when thread_count == 1). >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.01/ >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> This looks really good now! I only have a few nits below. There is one thing I don't like about it but it requires a change to the main Handshake logic to address - in JvmtiEnv::GetThreadListStackTraces you have to create a ThreadsListHandle to convert the jthread to a JavaThread, but then the Handshake::execute_direct creates another ThreadsListHandle internally. That's a waste. I will discuss with Robbin and file a RFE to have an overload of execute_direct that takes an existing TLH. Actually it's worse than that because we have another TLH in use at the entry point for the JVMTI functions, so I think there may be some scope for simplifying the use of TLH instances - future RFE. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> ??451 GetStackTraceClosure(JvmtiEnv *env, jint start_depth, jint max_count, >>>>>>>>>>>>>>>>>>>>>>>> ??452 jvmtiFrameInfo* frame_buffer, jint* count_ptr) >>>>>>>>>>>>>>>>>>>>>>>> ??453???? : HandshakeClosure("GetStackTrace"), >>>>>>>>>>>>>>>>>>>>>>>> ??454?????? _env(env), _start_depth(start_depth), _max_count(max_count), >>>>>>>>>>>>>>>>>>>>>>>> ??455 _frame_buffer(frame_buffer), _count_ptr(count_ptr), >>>>>>>>>>>>>>>>>>>>>>>> ??456 _result(JVMTI_ERROR_THREAD_NOT_ALIVE) { >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Nit: can you do one initializer per line please. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> This looks wrong: >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> 466 class MultipleStackTracesCollector : public StackObj { >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> ??498 class VM_GetAllStackTraces : public VM_Operation { >>>>>>>>>>>>>>>>>>>>>>>> ??499 private: >>>>>>>>>>>>>>>>>>>>>>>> ??500?? JavaThread *_calling_thread; >>>>>>>>>>>>>>>>>>>>>>>> ??501?? jint _final_thread_count; >>>>>>>>>>>>>>>>>>>>>>>> ??502 MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> You can't have a StackObj as a member of another class like that as it may not be on the stack. I think MultipleStackTracesCollector should not extend any allocation class, and should always be embedded directly in another class. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> 481 MultipleStackTracesCollector(JvmtiEnv *env, jint max_frame_count) { >>>>>>>>>>>>>>>>>>>>>>>> ??482???? _env = env; >>>>>>>>>>>>>>>>>>>>>>>> ??483???? _max_frame_count = max_frame_count; >>>>>>>>>>>>>>>>>>>>>>>> ??484 _frame_count_total = 0; >>>>>>>>>>>>>>>>>>>>>>>> ??485???? _head = NULL; >>>>>>>>>>>>>>>>>>>>>>>> ??486???? _stack_info = NULL; >>>>>>>>>>>>>>>>>>>>>>>> ??487???? _result = JVMTI_ERROR_NONE; >>>>>>>>>>>>>>>>>>>>>>>> ??488?? } >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> As you are touching this can you change it to use an initializer list as you did for the HandshakeClosure, and please keep one item per line. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> ??820 assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>>>>>>>>>>>> ??821 java_thread->is_thread_fully_suspended(false, &debug_bits) || >>>>>>>>>>>>>>>>>>>>>>>> ??822 current_thread == java_thread->active_handshaker(), >>>>>>>>>>>>>>>>>>>>>>>> ??823????????? "at safepoint / handshake or target thread is suspended"); >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> I don't think the suspension check is necessary, as even if the target is suspended we must still be at a safepoint or in a handshake with it. Makes me wonder if we used to allow a racy stacktrace operation on a suspended thread, assuming it would remain suspended? >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> 1268?? oop thread_oop = jt->threadObj(); >>>>>>>>>>>>>>>>>>>>>>>> 1269 >>>>>>>>>>>>>>>>>>>>>>>> 1270?? if (!jt->is_exiting() && (jt->threadObj() != NULL)) { >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> You can use thread_oop in line 1270. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> 1272 _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, thread_oop), >>>>>>>>>>>>>>>>>>>>>>>> 1273 jt, thread_oop); >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> It is frustrating that this entire call chain started with a jthread reference, which we converted to a JavaThread, only to eventually need to convert it back to a jthread! I think there is some scope for simplification here but not as part of this change. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> IIUC at this point the _calling_thread is the current thread, so we can use: >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Please add @bug lines to the tests. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> I'm still pondering the test logic but wanted to send this now. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>>>>>>>>>> VM_GetThreadListStackTrace (for GetThreadListStackTraces) and VM_GetAllStackTraces (for GetAllStackTraces) have inherited VM_GetMultipleStackTraces VM operation which provides the feature to generate jvmtiStackInfo. I modified VM_GetMultipleStackTraces to a normal C++ class to share with HandshakeClosure for GetThreadListStackTraces (GetSingleStackTraceClosure). >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> Also I added new testcases which test GetThreadListStackTraces() with thread_count == 1 and with all threads. >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> This change has been tested in serviceability/jvmti serviceability/jdwp vmTestbase/nsk/jvmti vmTestbase/nsk/jdi vmTestbase/nsk/jdwp. >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> On 2020/06/24 15:50, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>>>>>> Hi all, >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> Please review this change: >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> ?? JBS: https://bugs.openjdk.java.net/browse/JDK-8242428 >>>>>>>>>>>>>>>>>>>>>>>>>> ?? webrev: http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.00/ >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> This change replace following VM operations to direct handshake. >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> ??- VM_GetFrameCount (GetFrameCount()) >>>>>>>>>>>>>>>>>>>>>>>>>> ??- VM_GetFrameLocation (GetFrameLocation()) >>>>>>>>>>>>>>>>>>>>>>>>>> ??- VM_GetThreadListStackTraces (GetThreadListStackTrace()) >>>>>>>>>>>>>>>>>>>>>>>>>> ??- VM_GetCurrentLocation >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> GetThreadListStackTrace() uses direct handshake if thread count == 1. In other case (thread count > 1), it would be performed as VM operation (VM_GetThreadListStackTraces). >>>>>>>>>>>>>>>>>>>>>>>>>> Caller of VM_GetCurrentLocation (JvmtiEnvThreadState::reset_current_location()) might be called at safepoint. So I added safepoint check in its caller. >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> This change has been tested in serviceability/jvmti serviceability/jdwp vmTestbase/nsk/jvmti vmTestbase/nsk/jdi vmTestbase/ns >>>>>>>>>>>>>>>>>>>>>>>>>> k/jdwp. >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> Also I tested it on submit repo, then it has execution error (mach5-one-ysuenaga-JDK-8242428-20200624-0054-12034717) due to dependency error. So I think it does not occur by this change. >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>> >>>>>>> >>>>> >>> From chris.plummer at oracle.com Tue Jul 7 05:10:09 2020 From: chris.plummer at oracle.com (Chris Plummer) Date: Mon, 6 Jul 2020 22:10:09 -0700 Subject: RFR(M): 8247515: OSX pc_to_symbol() lookup does not work with core files Message-ID: Hello, Please help review the following: http://cr.openjdk.java.net/~cjplummer/8247515/webrev.00/index.html https://bugs.openjdk.java.net/browse/JDK-8247515 The CR contains a description of the issues being addressed. There is also no test for this symbol lookup support yet. It will be there after I push JDK-8247516 and? JDK-8247514, which are both blocked by the CR. [1] https://bugs.openjdk.java.net/browse/JDK-8247516 [2] https://bugs.openjdk.java.net/browse/JDK-8247514 thanks, Chris From suenaga at oss.nttdata.com Tue Jul 7 05:46:08 2020 From: suenaga at oss.nttdata.com (Yasumasa Suenaga) Date: Tue, 7 Jul 2020 14:46:08 +0900 Subject: RFR(XS): 8248878: SA: Implement simple workaround for JDK-8248876 In-Reply-To: <39ac40d6-a738-3214-d86c-412152a631d4@oracle.com> References: <39ac40d6-a738-3214-d86c-412152a631d4@oracle.com> Message-ID: Hi Chris, Your change looks good. BTW I saw JDK-8248876. I'm not sure, but I guess we can fix this issue if we allow PT_INTERP in L118: ``` 105 uintptr_t find_base_address(int fd, ELF_EHDR* ehdr) { : 115 // the base address of a shared object is the lowest vaddr of 116 // its loadable segments (PT_LOAD) 117 for (phdr = phbuf, cnt = 0; cnt < ehdr->e_phnum; cnt++, phdr++) { 118 if (phdr->p_type == PT_LOAD && phdr->p_vaddr < baseaddr) { 119 baseaddr = phdr->p_vaddr; 120 } 121 } ``` /proc//maps shows top of `java` is 0x56543b9df000: 56543b9df000-56543b9e0000 r--p 00000000 08:10 55770 /usr/lib/jvm/java-11-openjdk-amd64/bin/java `i target` on GDB shows 0x56543b9df000 is .interp section: Local exec file: `/usr/lib/jvm/java-11-openjdk-amd64/bin/java', file type elf64-x86-64. Entry point: 0x56543b9e0330 0x000056543b9df318 - 0x000056543b9df334 is .interp Thanks, Yasumasa On 2020/07/07 13:18, Chris Plummer wrote: > Hello, > > Please help review the following: > > http://cr.openjdk.java.net/~cjplummer/8248878/webrev.00/index.html > https://bugs.openjdk.java.net/browse/JDK-8248878 > > The explanation of the fix is in the CR. The parent CR, JDK-8248876 [1], explains the issue being addressed. > > There's no test for this fix yet. It requires the changes I'm making for JDK-8247514 [2], which include changes to "findpc" support and the ClhsdbFindPC.java test that trigger this issue. > > [1] https://bugs.openjdk.java.net/browse/JDK-8248876 > [2] https://bugs.openjdk.java.net/browse/JDK-8247514 > > thanks, > > Chris From david.holmes at oracle.com Tue Jul 7 06:13:46 2020 From: david.holmes at oracle.com (David Holmes) Date: Tue, 7 Jul 2020 16:13:46 +1000 Subject: RFR: 8242428: JVMTI thread operations should use Thread-Local Handshake In-Reply-To: <19cfa2a7-f441-425d-5623-1c11c6a870b6@oss.nttdata.com> References: <6c263e4c-0a83-be7a-0288-ecb2de0b7cea@oss.nttdata.com> <5107c478-1de2-7a49-ee71-dfad6a99a667@oracle.com> <90cdfef9-e558-0d25-33f5-25b7d65bb83b@oss.nttdata.com> <0e359819-618f-c17b-a427-bb7e4daa2c58@oracle.com> <3f890bed-6892-e64d-b21b-ca0cbe11784e@oracle.com> <7dc1903b-6295-3864-6301-4c02aacdb971@oss.nttdata.com> <04e09eb7-9483-8f63-4bb4-01c9e814802e@oracle.com> <238a89a3-06b1-90e4-d5a4-8dc2f1ed12ab@oracle.com> <4c43bc2c-551e-d042-8fa7-b63e755888d1@oracle.com> <8c387550-a06e-6320-f453-0e898486befb@oss.nttdata.com> <19cfa2a7-f441-425d-5623-1c11c6a870b6@oss.nttdata.com> Message-ID: On 7/07/2020 2:57 pm, Yasumasa Suenaga wrote: > Hi David, > > On 2020/07/07 11:31, David Holmes wrote: >> Hi Yasumasa, >> >> Hard to keep up with the changes - especially without incremental >> webrevs. > > Sorry, I will upload diff from previous webrev in the next. > > >> If GetSingleStackTraceClosure also took the jthread as a constructor >> arg, then you wouldn't need to recreate a JNI local handle when >> calling _collector.fill_frames. It's a small simplification and not >> essential at this stage. > > I think we should get jthread from an argument of do_thread() because > do_thread() would pass the thread which are stopped certainly. > It might be simplification if we pass _calling_thread to > MultipleStackTracesCollector. `jthread` is only needed to store > jvmtiStackInfo.thread . What do you think? I'm not quite sure what you mean. I think there is a bit of a design wart with direct handshakes in that do_thread takes the target JavaThread as an argument. That's useful in a case where you want a HandshakeClosure that can be applied to multiple threads, but that's not typically what is needed with direct handshakes - there is only a single target. With a single-target HandshakeClosure you can capture all the "target" information for the operation in the closure instance. So if the actual do_thread operation wants the jthread corresponding to the target thread then we can store that in the closure rather than recomputing it (you could assert it is the same but that seems overkill to me). > >> For the test ... I don't see how >> Java_GetThreadListStackTraces_checkCallStacks is a valid test. It gets >> the stacks of all live threads, then uses that information to use >> GetThreadListStackTraces to get the stack for the same set of threads >> through a different API. It then compares the two sets of stacks for >> each thread expecting them to be the same, but that need only be the >> case for the main thread. Other threads could potentially have a >> different stack (e.g. if this test is run with JFR enabled there will >> be additional threads found.) Further I would have expected that there >> already exist tests that check that, for a given thread (which may be >> suspended or known to be blocked) the same stack is found through the >> two different APIs. > > vmTestbase/nsk/jvmti/unit/GetAllStackTraces/getallstktr001 would check > all of threads via GetThreadListStackTraces() and GetAllStackTraces(), > so we might be able to remove GetThreadListStackTraces.java from this > webrev. Yes. The existing test only examines a set of test threads that are all blocked on a raw monitor. You do not need to duplicate that test. > OTOH we don't have testcase for GetThreadListStackTraces() with > thread_count == 1, so we need to testcase for it (it is > OneGetThreadListStackTraces.java) It would check whether the state of > target thread is "waiting" before JNI call to call > GetThreadListStackTraces(), Yes we need to test the special cases introduced by your changes - totally agree - and OneGetThreadListStackTraces.java is a good test for that. > and also I expect it would not be run with > JFR. (it is not described @run) The arguments to run with JFR (or a bunch of other things) can be passed to the jtreg test harness to be applied to all tests. > Of course we can check GetThreadListStackTraces() with main thread, but > it is not the test for direct handshake for other thread. Right - that test already exists as per the above. Thanks, David > > Thanks, > > Yasumasa > > >> Thanks, >> David >> ----- >> >> On 6/07/2020 11:29 pm, Yasumasa Suenaga wrote: >>> Hi Serguei, >>> >>> Thanks for your comment! >>> >>> I think C++ is more simple to implement the test agent as you said. >>> So I implement it in C++ in new webrev. Could you review again? >>> >>> ?? http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.06/ >>> >>> Also I refactored libGetThreadListStackTraces.cpp, and I've kept >>> exception check after IsSameObject(). >>> >>> >>> Thanks, >>> >>> Yasumasa >>> >>> >>> On 2020/07/06 16:32, serguei.spitsyn at oracle.com wrote: >>>> Hi Yasumasa, >>>> >>>> Thank you for the update. >>>> I think, a pending exception after IsSameObject needs to be checked. >>>> >>>> The checkStackInfo() needs one more refactoring as I've already >>>> suggested. >>>> The body of the loop at L68-L78 should be converted to a function >>>> check_frame_info. >>>> The si1->frame_buffer[i] and si2->frame_buffer[i] will be passed as >>>> fi1 and fi2. >>>> The index can be passed as well. >>>> I'm still suggesting to simplify the local exception_msg to >>>> something shorter like err_msg or exc_msg. >>>> >>>> I'm not sure using fatal is right here: >>>> >>>> This fragment looks strange: >>>> >>>> ? 152???? if ((*env)->IsSameObject(env, stack_info[i].thread, >>>> thread)) { >>>> ? 153?????? target_info = &stack_info[i]; >>>> ? 154?????? break; >>>> ? 155???? } else if ((*env)->ExceptionOccurred(env)) { >>>> ? 156?????? (*env)->ExceptionDescribe(env); >>>> ? 157?????? (*env)->FatalError(env, __FILE__); >>>> ? 158???? } >>>> >>>> I expected it to be: >>>> >>>> ??? jboolean same = (*env)->IsSameObject(env, stack_info[i].thread, >>>> thread); >>>> ??? if ((*env)->ExceptionOccurred(env)) { >>>> ????? (*env)->ExceptionDescribe(env); >>>> ????? (*env)->FatalError(env, __FILE__); >>>> ??? } >>>> ??? if (same) { >>>> ????? target_info = &stack_info[i]; >>>> ????? break; >>>> ??? } >>>> >>>> Would it better to port this agent to C++ to simplify this code nicer? >>>> >>>> Thanks, >>>> Serguei >>>> >>>> >>>> On 7/5/20 06:13, Yasumasa Suenaga wrote: >>>>> Hi Serguei, >>>>> >>>>> Thanks for your comment! >>>>> I refactored testcase. Could you review again? >>>>> >>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.05/ >>>>> >>>>> It would check Java exception after IsSameObject() call. Does it need? >>>>> Any exceptions are not described in JNI document[1], and JNI >>>>> implementation (jni_IsSameObject()) does not seem to throw it. >>>>> >>>>> >>>>> Thanks, >>>>> >>>>> Yasumasa >>>>> >>>>> >>>>> [1] >>>>> https://docs.oracle.com/en/java/javase/14/docs/specs/jni/functions.html#issameobject >>>>> >>>>> >>>>> >>>>> On 2020/07/05 14:46, serguei.spitsyn at oracle.com wrote: >>>>>> Hi Yasumasa, >>>>>> >>>>>> >>>>>> Okay, thanks. >>>>>> Then I'm okay to keep the GetSingleStackTraceClosure. >>>>>> >>>>>> >>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libGetThreadListStackTraces.c.html >>>>>> >>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.c.html >>>>>> >>>>>> >>>>>> I'm not sure the function 'is_same_thread() is needed. >>>>>> Why do not use the JNI IsSameObject instead? >>>>>> >>>>>> It seems to be a typo at L132 and L137. >>>>>> You, probably. did not want to print the same information for >>>>>> stack_info_1[i].frame_buffer[j].XXX twice. >>>>>> >>>>>> The code at lines 112-142 is not readable. >>>>>> I'd suggest to make a couple of refactoring steps. >>>>>> >>>>>> First step to simplify this a little bit would be with some >>>>>> renaming and getting rid of indexes: >>>>>> >>>>>> ?? 71 char err_msg[EXCEPTION_MSG_LEN] = {0}; >>>>>> ??... >>>>>> ??112?? /* Iterate all jvmtiStackInfo to check */ >>>>>> ??113?? for (i = 0; i < num_threads, *exception_msg != '\0'; i++) { >>>>>> ????????? jvmtiStackInfo *si1 = stack_info_1[i]; >>>>>> ????????? jvmtiStackInfo *si2 = stack_info_2[i]; >>>>>> ??114???? if (!IsSameObject(env, si1.thread, si2.thread)) { /* >>>>>> jvmtiStackInfo::thread */ >>>>>> ??115?????? snprintf(err_msg, sizeof(err_msg), >>>>>> ??116??????????????? "thread[%d] is different: stack_info_1 = %p, >>>>>> stack_info_2 = %p", >>>>>> ??117??????????????? i, sinfo1.thread, sinfo2.thread); >>>>>> ??118???? } else if (si1.state != si2.state) { /* >>>>>> jvmtiStackInfo::state */ >>>>>> ??119?????? snprintf(err_msg, sizeof(err_msg), >>>>>> ??120??????????????? "state[%d] is different: stack_info_1 = %d, >>>>>> stack_info_2 = %d", >>>>>> ??121??????????????? i, si1.state, si2.state); >>>>>> ??122???? } else if (si1.frame_count != si2.frame_count) { /* >>>>>> jvmtiStackInfo::frame_count */ >>>>>> ??123?????? snprintf(err_msg, sizeof(err_msg), >>>>>> ??124??????????????? "frame_count[%d] is different: stack_info_1 = >>>>>> %d, stack_info_2 = %d", >>>>>> ??125??????????????? i, si1.frame_count, si2.frame_count); >>>>>> ??126???? } else { >>>>>> ??127?????? /* Iterate all jvmtiFrameInfo to check */ >>>>>> ??128?????? for (j = 0; j < si1.frame_count; j++) { >>>>>> ??129???????? if (si1.frame_buffer[j].method != >>>>>> si1.frame_buffer[j].method) { /* jvmtiFrameInfo::method */ >>>>>> ??130?????????? snprintf(err_msg, sizeof(err_msg), >>>>>> ??131??????????????????? "thread [%d] frame_buffer[%d].method is >>>>>> different: stack_info_1 = %lx, stack_info_2 = %lx", >>>>>> ??132??????????????????? i, j, si1.frame_buffer[j].method, >>>>>> si2.frame_buffer[j].method); >>>>>> ??133?????????? break; >>>>>> ??134???????? } else if (si1.frame_buffer[j].location != >>>>>> si1.frame_buffer[j].location) { /* jvmtiFrameInfo::location */ >>>>>> ??135?????????? snprintf(err_msg, sizeof(err_msg), >>>>>> ??136??????????????????? "thread [%d] frame_buffer[%d].location is >>>>>> different: stack_info_1 = %ld, stack_info_2 = %ld", >>>>>> ??137??????????????????? i, j, si1.frame_buffer[j].location, >>>>>> si2.frame_buffer[j].location); >>>>>> ??138?????????? break; >>>>>> ??139???????? } >>>>>> ??140?????? } >>>>>> ??141???? } >>>>>> ??142?? } >>>>>> >>>>>> Another step would be to create functions that implement a body of >>>>>> each loop. >>>>>> You can use the same techniques to simplify similar place >>>>>> (L127-L138) in the libOneGetThreadListStackTraces.c. >>>>>> >>>>>> Thanks, >>>>>> Serguei >>>>>> >>>>>> >>>>>> On 7/3/20 15:55, Yasumasa Suenaga wrote: >>>>>>> Hi Serguei, >>>>>>> >>>>>>> I'm not an Oracle employee, so I cannot know real request(s) from >>>>>>> your customers. >>>>>>> However JDK-8201641 says Dynatrace has requested this enhancement. >>>>>>> >>>>>>> BTW I haven't heared any request from my customers about this. >>>>>>> >>>>>>> >>>>>>> Thanks, >>>>>>> >>>>>>> Yasumasa >>>>>>> >>>>>>> >>>>>>> On 2020/07/04 4:32, serguei.spitsyn at oracle.com wrote: >>>>>>>> Hi Yasumasa, >>>>>>>> >>>>>>>> This difference is not that big to care about. >>>>>>>> I feel this is really rare case and so, does not worth these >>>>>>>> complications. >>>>>>>> Do we have a real request from customers to optimize it? >>>>>>>> >>>>>>>> Thanks, >>>>>>>> Serguei >>>>>>>> >>>>>>>> >>>>>>>> On 7/3/20 01:16, Yasumasa Suenaga wrote: >>>>>>>>> Hi Serguei, >>>>>>>>> >>>>>>>>> Generally I agree with you, but I have concern about the >>>>>>>>> difference of the result of GetStackTrace() and >>>>>>>>> GetThreadListStackTraces(). >>>>>>>>> >>>>>>>>> ? GetStackTrace: jvmtiFrameInfo >>>>>>>>> ? GetThreadListStackTraces: jvmtiStackInfo >>>>>>>>> >>>>>>>>> jvmtiStackInfo contains thread state, and it is ensured it is >>>>>>>>> the state of the call stack. >>>>>>>>> If we want to get both call stack and thread state, we need to >>>>>>>>> suspend target thread, and call both GetStackTrace() and >>>>>>>>> GetThreadState(). Is it ok? >>>>>>>>> >>>>>>>>> I was wondering if JDK-8201641 (parent ticket of this change) >>>>>>>>> needed them for profiling (dynatrace?) >>>>>>>>> If it is responsibility of JVMTI agent implementor, I remove >>>>>>>>> this closure. >>>>>>>>> >>>>>>>>> >>>>>>>>> Thanks, >>>>>>>>> >>>>>>>>> Yasumasa >>>>>>>>> >>>>>>>>> >>>>>>>>> On 2020/07/03 16:45, serguei.spitsyn at oracle.com wrote: >>>>>>>>>> Hi Yasumasa, >>>>>>>>>> >>>>>>>>>> After some thinking I've concluded that I do not like this >>>>>>>>>> optimization >>>>>>>>>> of the GetThreadListStackTraces with GetSingleStackTraceClosure. >>>>>>>>>> >>>>>>>>>> We may need more opinions on this but these are my points: >>>>>>>>>> ??- it adds some complexity and ugliness >>>>>>>>>> ??- a win is doubtful because it has to be a rare case, so >>>>>>>>>> that total overhead should not be high >>>>>>>>>> ??- if it is really high for some use cases then it is up to >>>>>>>>>> the user >>>>>>>>>> ??? to optimize it with using GetStackTrace instead >>>>>>>>>> >>>>>>>>>> In such cases with doubtful overhead I usually prefer the >>>>>>>>>> simplicity. >>>>>>>>>> >>>>>>>>>> Good examples where it makes sense to optimize are checks for >>>>>>>>>> target thread to be current thread. >>>>>>>>>> In such cases there is no need to suspend the target thread, >>>>>>>>>> or use a VMop/HandshakeClosure. >>>>>>>>>> For instance, please, see the Monitor functions with the >>>>>>>>>> check: (java_thread == calling_thread). >>>>>>>>>> Getting information for current thread is frequently used >>>>>>>>>> case, e.g. to get info at an event point. >>>>>>>>>> >>>>>>>>>> Thanks, >>>>>>>>>> Serguei >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> On 7/2/20 23:29, Yasumasa Suenaga wrote: >>>>>>>>>>> Hi Dan, David, >>>>>>>>>>> >>>>>>>>>>> I uploaded new webrev. Could you review again? >>>>>>>>>>> >>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/ >>>>>>>>>>> >>>>>>>>>>> OneGetThreadListStackTraces.java in this webrev would wait >>>>>>>>>>> until thread state is transited to "waiting" with spin wait. >>>>>>>>>>> CountDownLatch::await call as Dan pointed is fixed in it :) >>>>>>>>>>> >>>>>>>>>>> Diff from webrev.03: >>>>>>>>>>> http://hg.openjdk.java.net/jdk/submit/rev/c9aeb7001e50 >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> Thanks, >>>>>>>>>>> >>>>>>>>>>> Yasumasa >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> On 2020/07/03 14:15, David Holmes wrote: >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> On 3/07/2020 2:27 pm, Yasumasa Suenaga wrote: >>>>>>>>>>>>> On 2020/07/03 12:24, Daniel D. Daugherty wrote: >>>>>>>>>>>>>> On 7/2/20 10:50 PM, David Holmes wrote: >>>>>>>>>>>>>>> Sorry I'm responding here without seeing latest webrev >>>>>>>>>>>>>>> but there is enough context I think ... >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> On 3/07/2020 9:14 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>> Hi Dan, >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Thanks for your comment! >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> On 2020/07/03 7:16, Daniel D. Daugherty wrote: >>>>>>>>>>>>>>>>> On 7/2/20 5:19 AM, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> I upload new webrev. Could you review again? >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.03/ >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnv.cpp >>>>>>>>>>>>>>>>> ???? L1542: ??? // Get stack trace with handshake >>>>>>>>>>>>>>>>> ???????? nit - please add a period at the end. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> ???? L1591: *stack_info_ptr = op.stack_info(); >>>>>>>>>>>>>>>>> ???????? The return parameter should not be touched >>>>>>>>>>>>>>>>> unless the return >>>>>>>>>>>>>>>>> ???????? code in 'err' == JVMTI_ERROR_NONE. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> ???? old L1582: ? if (err == JVMTI_ERROR_NONE) { >>>>>>>>>>>>>>>>> ???????? Please restore this check. The return >>>>>>>>>>>>>>>>> parameter should not >>>>>>>>>>>>>>>>> ???????? be touched unless the return code in 'err' == >>>>>>>>>>>>>>>>> JVMTI_ERROR_NONE. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> But op.stack_info() will return NULL if the error is not >>>>>>>>>>>>>>> JVMTI_ERROR_NONE. Are you (Dan) concerned about someone >>>>>>>>>>>>>>> passing in a non-null/initialized out-pointer that will >>>>>>>>>>>>>>> be reset to NULL if there was an error? >>>>>>>>>>>>>> >>>>>>>>>>>>>> Actually the way we used to test this in POSIX tests is to >>>>>>>>>>>>>> call >>>>>>>>>>>>>> an API with known bad parameters and the return parameter ptr >>>>>>>>>>>>>> set to NULL. If the return parameter ptr was touched when an >>>>>>>>>>>>>> error should have been detected on an earlier parameter, then >>>>>>>>>>>>>> the test failed. >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> ???? L1272: ? if (!jt->is_exiting() && (thread_oop != >>>>>>>>>>>>>>>>> NULL)) { >>>>>>>>>>>>>>>>> ???????? nit - extra parens around the second expression. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>>>>> ???? old L1532: ? _result = JVMTI_ERROR_THREAD_NOT_ALIVE; >>>>>>>>>>>>>>>>> ???????? This deletion of the _result field threw me >>>>>>>>>>>>>>>>> for a minute and then >>>>>>>>>>>>>>>>> ???? ? ? I figured out that the field is init to >>>>>>>>>>>>>>>>> JVMTI_ERROR_THREAD_NOT_ALIVE >>>>>>>>>>>>>>>>> ???????? in the constructor. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> ???? L1553: ? if (!jt->is_exiting() && (jt->threadObj() >>>>>>>>>>>>>>>>> != NULL)) { >>>>>>>>>>>>>>>>> ???????? nit - extra parens around the second expression. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>>>>>>>>>>>>> ???? No comments. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> src/hotspot/share/runtime/vmOperations.hpp >>>>>>>>>>>>>>>>> ???? No comments. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/GetThreadListStackTraces.java >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> ???? No comments. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/OneGetThreadListStackTraces.java >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> ???? L64: ??????? startSignal.countDown(); >>>>>>>>>>>>>>>>> ???????? I was expecting this to be a call to await() >>>>>>>>>>>>>>>>> instead of >>>>>>>>>>>>>>>>> ???????? countDown(). What am I missing here? >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> ???????? I think this test might be passing by accident >>>>>>>>>>>>>>>>> right now, but... >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Main thread (which call JVMTI functions to test) should >>>>>>>>>>>>>>>> wait until test thread is ready. >>>>>>>>>>>>>>>> So main thread would wait startSignal, and test thread >>>>>>>>>>>>>>>> would count down. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> No! >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> The test thread that previously called obj.wait() now >>>>>>>>>>>>>>> calls latch.await(). >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> The main thread that previously called obj.notify() now >>>>>>>>>>>>>>> calls latch.countDown(). >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> The main thread continues to spin until it sees the >>>>>>>>>>>>>>> target is WAITING before proceeding with the test. >>>>>>>>>>>>> >>>>>>>>>>>>> If I add spin wait to wait until transit target thread >>>>>>>>>>>>> state is WAITING (as following), we don't need to call >>>>>>>>>>>>> SuspendThread(). >>>>>>>>>>>>> Which is better? >>>>>>>>>>>> >>>>>>>>>>>> The original spin-wait loop checking for? WAITING is better >>>>>>>>>>>> because it is the only guarantee that the target thread is >>>>>>>>>>>> blocked where you need it to be. suspending the thread is >>>>>>>>>>>> racy as you don't know exactly where the suspend will hit. >>>>>>>>>>>> >>>>>>>>>>>> Thanks, >>>>>>>>>>>> David >>>>>>>>>>>> ----- >>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> ``` >>>>>>>>>>>>> /* Wait until the thread state transits to "waiting" */ >>>>>>>>>>>>> while (th.getState() != Thread.State.WAITING) { >>>>>>>>>>>>> ???? Thread.onSpinWait(); >>>>>>>>>>>>> } >>>>>>>>>>>>> ``` >>>>>>>>>>>>> >>>>>>>>>>>>> For simplify, spin wait is prefer to >>>>>>>>>>>>> OneGetThreadListStackTraces.java in webrev.03. >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> Thanks, >>>>>>>>>>>>> >>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>>> Here's the flow as I see it: >>>>>>>>>>>>>> >>>>>>>>>>>>>> main thread >>>>>>>>>>>>>> ?? - start worker thread >>>>>>>>>>>>>> ?? - startSignal.await() >>>>>>>>>>>>>> ???? - main is now blocked >>>>>>>>>>>>>> >>>>>>>>>>>>>> worker thread >>>>>>>>>>>>>> ?? - startSignal.countDown() >>>>>>>>>>>>>> ???? - main is now unblocked >>>>>>>>>>>>>> ?? - stopSignal.await() >>>>>>>>>>>>>> ???? - worker is now blocked >>>>>>>>>>>>>> >>>>>>>>>>>>>> main thread >>>>>>>>>>>>>> ?? - checkCallStacks(th) >>>>>>>>>>>>>> ?? - stopSignal.countDown() >>>>>>>>>>>>>> ???? - worker is now unblocked >>>>>>>>>>>>>> ?? - th.join >>>>>>>>>>>>>> ???? - main is now blocked >>>>>>>>>>>>>> >>>>>>>>>>>>>> worker thread >>>>>>>>>>>>>> ?? - runs off the end of run() >>>>>>>>>>>>>> ???? - main is now unblocked >>>>>>>>>>>>>> >>>>>>>>>>>>>> main thread >>>>>>>>>>>>>> ?? - run off the end of main() >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libGetThreadListStackTraces.c >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> ???? L92: ? jthreads = (jthread >>>>>>>>>>>>>>>>> *)malloc(sizeof(jthread) * num_threads); >>>>>>>>>>>>>>>>> ???????? You don't check for malloc() failure. >>>>>>>>>>>>>>>>> ???????? 'jthreads' is allocated but never freed. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.c >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> ???? L91: ? result = (*jvmti)->SuspendThread(jvmti, >>>>>>>>>>>>>>>>> thread); >>>>>>>>>>>>>>>>> ???????? Why are you suspending the thread? >>>>>>>>>>>>>>>>> GetAllStackTraces() and >>>>>>>>>>>>>>>>> ???????? GetThreadListStackTraces() do not require the >>>>>>>>>>>>>>>>> target thread(s) >>>>>>>>>>>>>>>>> ???????? to be suspend. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> ???????? If you decide not to SuspendThread, then you >>>>>>>>>>>>>>>>> don't need the >>>>>>>>>>>>>>>>> ???????? AddCapabilities or the ResumeThread calls. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Test thread might not be entered following code >>>>>>>>>>>>>>>> (stopSignal.await()). We might see deferent call stack >>>>>>>>>>>>>>>> between GetAllStackTraces() and >>>>>>>>>>>>>>>> GetThreadListStackTraces(). We cannot control to freeze >>>>>>>>>>>>>>>> call stack of test thread in Java code. >>>>>>>>>>>>>>>> (I didn't use SuspendThread() at first, but I saw some >>>>>>>>>>>>>>>> errors which causes in above.) >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> So we need to call SuspendThread() to ensure we can see >>>>>>>>>>>>>>>> same call stack. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> If you are checking that the thread is in state WAITING >>>>>>>>>>>>>>> then it cannot escape from that state and you can sample >>>>>>>>>>>>>>> the stack multiple times from any API and get the same >>>>>>>>>>>>>>> result. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> I suspect the errors you saw were from the apparent >>>>>>>>>>>>>>> incorrect use of the CountDownLatch. >>>>>>>>>>>>>> >>>>>>>>>>>>>> With the flow outlined above, the worker thread should be >>>>>>>>>>>>>> nicely blocked in stopSignal.await() when stuff is sampled. >>>>>>>>>>>>>> >>>>>>>>>>>>>> Dan >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Cheers, >>>>>>>>>>>>>>> David >>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Dan >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> On 2020/07/02 15:05, David Holmes wrote: >>>>>>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> On 1/07/2020 11:53 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>> Hi, >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> I uploaded new webrev. Could review again? >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.02/ >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Updates look fine - thanks. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> One minor nit: >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> 1274 _collector.allocate_and_fill_stacks(1); >>>>>>>>>>>>>>>>>>> 1275 _collector.set_result(JVMTI_ERROR_NONE); >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> In the other places where you use _collector you rely >>>>>>>>>>>>>>>>>>> on result being initialized to JVMTI_ERROR_NONE, >>>>>>>>>>>>>>>>>>> rather than setting it directly after >>>>>>>>>>>>>>>>>>> allocate_and_fill_stacks(). >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Fixed. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> ? 820 >>>>>>>>>>>>>>>>>>>>>>>>> assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>>>>>>>>>>>>> ? 821 >>>>>>>>>>>>>>>>>>>>>>>>> java_thread->is_thread_fully_suspended(false, >>>>>>>>>>>>>>>>>>>>>>>>> &debug_bits) || >>>>>>>>>>>>>>>>>>>>>>>>> ? 822 current_thread == >>>>>>>>>>>>>>>>>>>>>>>>> java_thread->active_handshaker(), >>>>>>>>>>>>>>>>>>>>>>>>> ? 823????????? "at safepoint / handshake or >>>>>>>>>>>>>>>>>>>>>>>>> target thread is suspended"); >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> I don't think the suspension check is >>>>>>>>>>>>>>>>>>>>>>>>> necessary, as even if the target is suspended >>>>>>>>>>>>>>>>>>>>>>>>> we must still be at a safepoint or in a >>>>>>>>>>>>>>>>>>>>>>>>> handshake with it. Makes me wonder if we used >>>>>>>>>>>>>>>>>>>>>>>>> to allow a racy stacktrace operation on a >>>>>>>>>>>>>>>>>>>>>>>>> suspended thread, assuming it would remain >>>>>>>>>>>>>>>>>>>>>>>>> suspended? >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> This function (JvmtiEnvBase::get_stack_trace()) can >>>>>>>>>>>>>>>>>>>> be called to get own stack trace. For example, we >>>>>>>>>>>>>>>>>>>> can call GetStackTrace() for current thread at JVMTI >>>>>>>>>>>>>>>>>>>> event. >>>>>>>>>>>>>>>>>>>> So I changed assert as below: >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>> ??820?? assert(current_thread == java_thread || >>>>>>>>>>>>>>>>>>>> ??821 SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>>>>>>>> ??822????????? current_thread == >>>>>>>>>>>>>>>>>>>> java_thread->active_handshaker(), >>>>>>>>>>>>>>>>>>>> ??823????????? "call by myself / at safepoint / at >>>>>>>>>>>>>>>>>>>> handshake"); >>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Yep good catch. I hope current tests caught that. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> They would be tested in >>>>>>>>>>>>>>>>>> vmTestbase/nsk/jvmti/GetStackTrace/getstacktr001/ (own >>>>>>>>>>>>>>>>>> call stacks), and getstacktr003 (call stacks in other >>>>>>>>>>>>>>>>>> thread). >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Speaking of tests ... >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> In the native code I think you need to check the >>>>>>>>>>>>>>>>>>> success of all JNI methods that can throw exceptions >>>>>>>>>>>>>>>>>>> - otherwise I believe the tests may trigger warnings >>>>>>>>>>>>>>>>>>> if -Xcheck:jni is used with them. See for example: >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/libHeapMonitorTest.cpp >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> I updated testcases to check JNI and JVMTI function >>>>>>>>>>>>>>>>>> calls. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> In the Java code the target thread: >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> ?? 45???? public void run() { >>>>>>>>>>>>>>>>>>> ?? 46?????? try { >>>>>>>>>>>>>>>>>>> ?? 47?????????? synchronized (lock) { >>>>>>>>>>>>>>>>>>> ?? 48?????????????? lock.wait(); >>>>>>>>>>>>>>>>>>> ?? 49 System.out.println("OK"); >>>>>>>>>>>>>>>>>>> ?? 50?????????? } >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> is potentially susceptible to spurious wakeups. Using >>>>>>>>>>>>>>>>>>> a CountDownLatch would be robust. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Fixed. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> On 2020/07/01 8:48, David Holmes wrote: >>>>>>>>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> On 1/07/2020 9:05 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> 1271 ResourceMark rm; >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> IIUC at this point the _calling_thread is the >>>>>>>>>>>>>>>>>>>>>>>>> current thread, so we can use: >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> If so, we can call make_local() in L1272 without >>>>>>>>>>>>>>>>>>>>>> JavaThread (or we can pass current thread to >>>>>>>>>>>>>>>>>>>>>> make_local()). Is it right? >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>>>>>>>>>>>>>> 1272 >>>>>>>>>>>>>>>>>>>>>> _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, >>>>>>>>>>>>>>>>>>>>>> thread_oop), >>>>>>>>>>>>>>>>>>>>>> 1273 jt, thread_oop); >>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Sorry I got confused, _calling_thread may not be >>>>>>>>>>>>>>>>>>>>> the current thread as we could be executing the >>>>>>>>>>>>>>>>>>>>> handshake in the target thread itself. So the >>>>>>>>>>>>>>>>>>>>> ResourceMark is correct as-is (implicitly for >>>>>>>>>>>>>>>>>>>>> current thread). >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> The argument to fill_frames will be used in the >>>>>>>>>>>>>>>>>>>>> jvmtiStackInfo and passed back to the >>>>>>>>>>>>>>>>>>>>> _calling_thread, so it must be created via >>>>>>>>>>>>>>>>>>>>> make_local(_calling_thread, ...) as you presently >>>>>>>>>>>>>>>>>>>>> have. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> On 2020/07/01 7:05, David Holmes wrote: >>>>>>>>>>>>>>>>>>>>>>> On 1/07/2020 12:17 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Thank you for reviewing! I will update new >>>>>>>>>>>>>>>>>>>>>>>> webrev tomorrow. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> 466 class MultipleStackTracesCollector : public >>>>>>>>>>>>>>>>>>>>>>>>> StackObj { >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> ? 498 class VM_GetAllStackTraces : public >>>>>>>>>>>>>>>>>>>>>>>>> VM_Operation { >>>>>>>>>>>>>>>>>>>>>>>>> ? 499 private: >>>>>>>>>>>>>>>>>>>>>>>>> ? 500?? JavaThread *_calling_thread; >>>>>>>>>>>>>>>>>>>>>>>>> ? 501?? jint _final_thread_count; >>>>>>>>>>>>>>>>>>>>>>>>> ? 502 MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> You can't have a StackObj as a member of >>>>>>>>>>>>>>>>>>>>>>>>> another class like that as it may not be on the >>>>>>>>>>>>>>>>>>>>>>>>> stack. I think MultipleStackTracesCollector >>>>>>>>>>>>>>>>>>>>>>>>> should not extend any allocation class, and >>>>>>>>>>>>>>>>>>>>>>>>> should always be embedded directly in another >>>>>>>>>>>>>>>>>>>>>>>>> class. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> I'm not sure what does mean "embedded". >>>>>>>>>>>>>>>>>>>>>>>> Is it ok as below? >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>>>> class MultipleStackTracesCollector { >>>>>>>>>>>>>>>>>>>>>>>> ??? : >>>>>>>>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> class GetAllStackTraces : public VM_Operation { >>>>>>>>>>>>>>>>>>>>>>>> ?? private: >>>>>>>>>>>>>>>>>>>>>>>> MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Yes that I what I meant. >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> On 2020/06/30 22:22, David Holmes wrote: >>>>>>>>>>>>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> On 30/06/2020 10:05 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>>>>>> Hi David, Serguei, >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> I updated webrev for 8242428. Could you review >>>>>>>>>>>>>>>>>>>>>>>>>> again? >>>>>>>>>>>>>>>>>>>>>>>>>> This change migrate to use direct handshake >>>>>>>>>>>>>>>>>>>>>>>>>> for GetStackTrace() and >>>>>>>>>>>>>>>>>>>>>>>>>> GetThreadListStackTraces() (when thread_count >>>>>>>>>>>>>>>>>>>>>>>>>> == 1). >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.01/ >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> This looks really good now! I only have a few >>>>>>>>>>>>>>>>>>>>>>>>> nits below. There is one thing I don't like >>>>>>>>>>>>>>>>>>>>>>>>> about it but it requires a change to the main >>>>>>>>>>>>>>>>>>>>>>>>> Handshake logic to address - in >>>>>>>>>>>>>>>>>>>>>>>>> JvmtiEnv::GetThreadListStackTraces you have to >>>>>>>>>>>>>>>>>>>>>>>>> create a ThreadsListHandle to convert the >>>>>>>>>>>>>>>>>>>>>>>>> jthread to a JavaThread, but then the >>>>>>>>>>>>>>>>>>>>>>>>> Handshake::execute_direct creates another >>>>>>>>>>>>>>>>>>>>>>>>> ThreadsListHandle internally. That's a waste. I >>>>>>>>>>>>>>>>>>>>>>>>> will discuss with Robbin and file a RFE to have >>>>>>>>>>>>>>>>>>>>>>>>> an overload of execute_direct that takes an >>>>>>>>>>>>>>>>>>>>>>>>> existing TLH. Actually it's worse than that >>>>>>>>>>>>>>>>>>>>>>>>> because we have another TLH in use at the entry >>>>>>>>>>>>>>>>>>>>>>>>> point for the JVMTI functions, so I think there >>>>>>>>>>>>>>>>>>>>>>>>> may be some scope for simplifying the use of >>>>>>>>>>>>>>>>>>>>>>>>> TLH instances - future RFE. >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> ??451 GetStackTraceClosure(JvmtiEnv *env, jint >>>>>>>>>>>>>>>>>>>>>>>>> start_depth, jint max_count, >>>>>>>>>>>>>>>>>>>>>>>>> ??452 jvmtiFrameInfo* frame_buffer, jint* >>>>>>>>>>>>>>>>>>>>>>>>> count_ptr) >>>>>>>>>>>>>>>>>>>>>>>>> ??453???? : HandshakeClosure("GetStackTrace"), >>>>>>>>>>>>>>>>>>>>>>>>> ??454?????? _env(env), >>>>>>>>>>>>>>>>>>>>>>>>> _start_depth(start_depth), _max_count(max_count), >>>>>>>>>>>>>>>>>>>>>>>>> ??455 _frame_buffer(frame_buffer), >>>>>>>>>>>>>>>>>>>>>>>>> _count_ptr(count_ptr), >>>>>>>>>>>>>>>>>>>>>>>>> ??456 _result(JVMTI_ERROR_THREAD_NOT_ALIVE) { >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> Nit: can you do one initializer per line please. >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> This looks wrong: >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> 466 class MultipleStackTracesCollector : public >>>>>>>>>>>>>>>>>>>>>>>>> StackObj { >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> ??498 class VM_GetAllStackTraces : public >>>>>>>>>>>>>>>>>>>>>>>>> VM_Operation { >>>>>>>>>>>>>>>>>>>>>>>>> ??499 private: >>>>>>>>>>>>>>>>>>>>>>>>> ??500?? JavaThread *_calling_thread; >>>>>>>>>>>>>>>>>>>>>>>>> ??501?? jint _final_thread_count; >>>>>>>>>>>>>>>>>>>>>>>>> ??502 MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> You can't have a StackObj as a member of >>>>>>>>>>>>>>>>>>>>>>>>> another class like that as it may not be on the >>>>>>>>>>>>>>>>>>>>>>>>> stack. I think MultipleStackTracesCollector >>>>>>>>>>>>>>>>>>>>>>>>> should not extend any allocation class, and >>>>>>>>>>>>>>>>>>>>>>>>> should always be embedded directly in another >>>>>>>>>>>>>>>>>>>>>>>>> class. >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> 481 MultipleStackTracesCollector(JvmtiEnv *env, >>>>>>>>>>>>>>>>>>>>>>>>> jint max_frame_count) { >>>>>>>>>>>>>>>>>>>>>>>>> ??482???? _env = env; >>>>>>>>>>>>>>>>>>>>>>>>> ??483???? _max_frame_count = max_frame_count; >>>>>>>>>>>>>>>>>>>>>>>>> ??484 _frame_count_total = 0; >>>>>>>>>>>>>>>>>>>>>>>>> ??485???? _head = NULL; >>>>>>>>>>>>>>>>>>>>>>>>> ??486???? _stack_info = NULL; >>>>>>>>>>>>>>>>>>>>>>>>> ??487???? _result = JVMTI_ERROR_NONE; >>>>>>>>>>>>>>>>>>>>>>>>> ??488?? } >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> As you are touching this can you change it to >>>>>>>>>>>>>>>>>>>>>>>>> use an initializer list as you did for the >>>>>>>>>>>>>>>>>>>>>>>>> HandshakeClosure, and please keep one item per >>>>>>>>>>>>>>>>>>>>>>>>> line. >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> ??820 >>>>>>>>>>>>>>>>>>>>>>>>> assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>>>>>>>>>>>>> ??821 >>>>>>>>>>>>>>>>>>>>>>>>> java_thread->is_thread_fully_suspended(false, >>>>>>>>>>>>>>>>>>>>>>>>> &debug_bits) || >>>>>>>>>>>>>>>>>>>>>>>>> ??822 current_thread == >>>>>>>>>>>>>>>>>>>>>>>>> java_thread->active_handshaker(), >>>>>>>>>>>>>>>>>>>>>>>>> ??823????????? "at safepoint / handshake or >>>>>>>>>>>>>>>>>>>>>>>>> target thread is suspended"); >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> I don't think the suspension check is >>>>>>>>>>>>>>>>>>>>>>>>> necessary, as even if the target is suspended >>>>>>>>>>>>>>>>>>>>>>>>> we must still be at a safepoint or in a >>>>>>>>>>>>>>>>>>>>>>>>> handshake with it. Makes me wonder if we used >>>>>>>>>>>>>>>>>>>>>>>>> to allow a racy stacktrace operation on a >>>>>>>>>>>>>>>>>>>>>>>>> suspended thread, assuming it would remain >>>>>>>>>>>>>>>>>>>>>>>>> suspended? >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> 1268?? oop thread_oop = jt->threadObj(); >>>>>>>>>>>>>>>>>>>>>>>>> 1269 >>>>>>>>>>>>>>>>>>>>>>>>> 1270?? if (!jt->is_exiting() && >>>>>>>>>>>>>>>>>>>>>>>>> (jt->threadObj() != NULL)) { >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> You can use thread_oop in line 1270. >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> 1272 >>>>>>>>>>>>>>>>>>>>>>>>> _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, >>>>>>>>>>>>>>>>>>>>>>>>> thread_oop), >>>>>>>>>>>>>>>>>>>>>>>>> 1273 jt, thread_oop); >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> It is frustrating that this entire call chain >>>>>>>>>>>>>>>>>>>>>>>>> started with a jthread reference, which we >>>>>>>>>>>>>>>>>>>>>>>>> converted to a JavaThread, only to eventually >>>>>>>>>>>>>>>>>>>>>>>>> need to convert it back to a jthread! I think >>>>>>>>>>>>>>>>>>>>>>>>> there is some scope for simplification here but >>>>>>>>>>>>>>>>>>>>>>>>> not as part of this change. >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> IIUC at this point the _calling_thread is the >>>>>>>>>>>>>>>>>>>>>>>>> current thread, so we can use: >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> Please add @bug lines to the tests. >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> I'm still pondering the test logic but wanted >>>>>>>>>>>>>>>>>>>>>>>>> to send this now. >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>>>>>>>>>>> VM_GetThreadListStackTrace (for >>>>>>>>>>>>>>>>>>>>>>>>>> GetThreadListStackTraces) and >>>>>>>>>>>>>>>>>>>>>>>>>> VM_GetAllStackTraces (for GetAllStackTraces) >>>>>>>>>>>>>>>>>>>>>>>>>> have inherited VM_GetMultipleStackTraces VM >>>>>>>>>>>>>>>>>>>>>>>>>> operation which provides the feature to >>>>>>>>>>>>>>>>>>>>>>>>>> generate jvmtiStackInfo. I modified >>>>>>>>>>>>>>>>>>>>>>>>>> VM_GetMultipleStackTraces to a normal C++ >>>>>>>>>>>>>>>>>>>>>>>>>> class to share with HandshakeClosure for >>>>>>>>>>>>>>>>>>>>>>>>>> GetThreadListStackTraces >>>>>>>>>>>>>>>>>>>>>>>>>> (GetSingleStackTraceClosure). >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> Also I added new testcases which test >>>>>>>>>>>>>>>>>>>>>>>>>> GetThreadListStackTraces() with thread_count >>>>>>>>>>>>>>>>>>>>>>>>>> == 1 and with all threads. >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> This change has been tested in >>>>>>>>>>>>>>>>>>>>>>>>>> serviceability/jvmti serviceability/jdwp >>>>>>>>>>>>>>>>>>>>>>>>>> vmTestbase/nsk/jvmti vmTestbase/nsk/jdi >>>>>>>>>>>>>>>>>>>>>>>>>> vmTestbase/nsk/jdwp. >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> On 2020/06/24 15:50, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>>>>>>> Hi all, >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> Please review this change: >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> ?? JBS: >>>>>>>>>>>>>>>>>>>>>>>>>>> https://bugs.openjdk.java.net/browse/JDK-8242428 >>>>>>>>>>>>>>>>>>>>>>>>>>> ?? webrev: >>>>>>>>>>>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.00/ >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> This change replace following VM operations >>>>>>>>>>>>>>>>>>>>>>>>>>> to direct handshake. >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> ??- VM_GetFrameCount (GetFrameCount()) >>>>>>>>>>>>>>>>>>>>>>>>>>> ??- VM_GetFrameLocation (GetFrameLocation()) >>>>>>>>>>>>>>>>>>>>>>>>>>> ??- VM_GetThreadListStackTraces >>>>>>>>>>>>>>>>>>>>>>>>>>> (GetThreadListStackTrace()) >>>>>>>>>>>>>>>>>>>>>>>>>>> ??- VM_GetCurrentLocation >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> GetThreadListStackTrace() uses direct >>>>>>>>>>>>>>>>>>>>>>>>>>> handshake if thread count == 1. In other case >>>>>>>>>>>>>>>>>>>>>>>>>>> (thread count > 1), it would be performed as >>>>>>>>>>>>>>>>>>>>>>>>>>> VM operation (VM_GetThreadListStackTraces). >>>>>>>>>>>>>>>>>>>>>>>>>>> Caller of VM_GetCurrentLocation >>>>>>>>>>>>>>>>>>>>>>>>>>> (JvmtiEnvThreadState::reset_current_location()) >>>>>>>>>>>>>>>>>>>>>>>>>>> might be called at safepoint. So I added >>>>>>>>>>>>>>>>>>>>>>>>>>> safepoint check in its caller. >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> This change has been tested in >>>>>>>>>>>>>>>>>>>>>>>>>>> serviceability/jvmti serviceability/jdwp >>>>>>>>>>>>>>>>>>>>>>>>>>> vmTestbase/nsk/jvmti vmTestbase/nsk/jdi >>>>>>>>>>>>>>>>>>>>>>>>>>> vmTestbase/ns >>>>>>>>>>>>>>>>>>>>>>>>>>> k/jdwp. >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> Also I tested it on submit repo, then it has >>>>>>>>>>>>>>>>>>>>>>>>>>> execution error >>>>>>>>>>>>>>>>>>>>>>>>>>> (mach5-one-ysuenaga-JDK-8242428-20200624-0054-12034717) >>>>>>>>>>>>>>>>>>>>>>>>>>> due to dependency error. So I think it does >>>>>>>>>>>>>>>>>>>>>>>>>>> not occur by this change. >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>> >>>>>>>> >>>>>> >>>> From chris.plummer at oracle.com Tue Jul 7 06:38:27 2020 From: chris.plummer at oracle.com (Chris Plummer) Date: Mon, 6 Jul 2020 23:38:27 -0700 Subject: RFR(XS): 8248878: SA: Implement simple workaround for JDK-8248876 In-Reply-To: References: <39ac40d6-a738-3214-d86c-412152a631d4@oracle.com> Message-ID: <8e89d223-0f65-f26e-3bd7-2ca7421a940b@oracle.com> Hi Yasumasa, Thanks for the review. I tried the following for line 188: ??? if ((phdr->p_type == PT_LOAD || phdr->p_type == PT_INTERP) && phdr->p_vaddr < baseaddr) { However, "base" still ended up being 0. I added some printfs. For the exec file there is both a PT_INTER with p_vaddr of 0x238 and a PT_LOAD with p_vaddr 0. I'm not sure which to use, but in either case that won't be the proper base when added to 0: ? if (add_lib_info_fd(ph, exec_file, ph->core->exec_fd, ????????????????????? (uintptr_t)0 + find_base_address(ph->core->exec_fd, &exec_ehdr)) == NULL) { ??? goto err; ? } So maybe it's the (uintptr_t)0 that is the problem here. For shared libs instead of 0 it computes the value to add: ?????????????? if (lib_base_diff == ZERO_LOAD_ADDRESS ) { ???????????????? lib_base_diff = calc_prelinked_load_address(ph, lib_fd, &elf_ehdr, link_map_addr); ???????????????? if (lib_base_diff == INVALID_LOAD_ADDRESS) { ?????????????????? close(lib_fd); ?????????????????? return false; ???????????????? } ?????????????? } ?????????????? lib_base = lib_base_diff + find_base_address(lib_fd, &elf_ehdr); So in this case we've actually computed lib_base_diff rather than just assumed 0. Chris On 7/6/20 10:46 PM, Yasumasa Suenaga wrote: > Hi Chris, > > Your change looks good. > > > BTW I saw JDK-8248876. I'm not sure, but I guess we can fix this issue > if we allow PT_INTERP in L118: > > ``` > 105 uintptr_t find_base_address(int fd, ELF_EHDR* ehdr) { > ????????????????? : > 115?? // the base address of a shared object is the lowest vaddr of > 116?? // its loadable segments (PT_LOAD) > 117?? for (phdr = phbuf, cnt = 0; cnt < ehdr->e_phnum; cnt++, phdr++) { > 118???? if (phdr->p_type == PT_LOAD && phdr->p_vaddr < baseaddr) { > 119?????? baseaddr = phdr->p_vaddr; > 120???? } > 121?? } > ``` > > /proc//maps shows top of `java` is 0x56543b9df000: > > 56543b9df000-56543b9e0000 r--p 00000000 08:10 55770 > /usr/lib/jvm/java-11-openjdk-amd64/bin/java > > > `i target` on GDB shows 0x56543b9df000 is .interp section: > > Local exec file: > ??????? `/usr/lib/jvm/java-11-openjdk-amd64/bin/java', file type > elf64-x86-64. > ??????? Entry point: 0x56543b9e0330 > ??????? 0x000056543b9df318 - 0x000056543b9df334 is .interp > > > Thanks, > > Yasumasa > > > On 2020/07/07 13:18, Chris Plummer wrote: >> Hello, >> >> Please help review the following: >> >> http://cr.openjdk.java.net/~cjplummer/8248878/webrev.00/index.html >> https://bugs.openjdk.java.net/browse/JDK-8248878 >> >> The explanation of the fix is in the CR. The parent CR, JDK-8248876 >> [1], explains the issue being addressed. >> >> There's no test for this fix yet. It requires the changes I'm making >> for JDK-8247514 [2], which include changes to "findpc" support and >> the ClhsdbFindPC.java test that trigger this issue. >> >> [1] https://bugs.openjdk.java.net/browse/JDK-8248876 >> [2] https://bugs.openjdk.java.net/browse/JDK-8247514 >> >> thanks, >> >> Chris From serguei.spitsyn at oracle.com Tue Jul 7 07:43:29 2020 From: serguei.spitsyn at oracle.com (serguei.spitsyn at oracle.com) Date: Tue, 7 Jul 2020 00:43:29 -0700 Subject: RFR: 8242428: JVMTI thread operations should use Thread-Local Handshake In-Reply-To: <8c387550-a06e-6320-f453-0e898486befb@oss.nttdata.com> References: <6c263e4c-0a83-be7a-0288-ecb2de0b7cea@oss.nttdata.com> <763793b1-9506-44c6-0681-1c71c44a44fd@oss.nttdata.com> <5107c478-1de2-7a49-ee71-dfad6a99a667@oracle.com> <90cdfef9-e558-0d25-33f5-25b7d65bb83b@oss.nttdata.com> <0e359819-618f-c17b-a427-bb7e4daa2c58@oracle.com> <3f890bed-6892-e64d-b21b-ca0cbe11784e@oracle.com> <7dc1903b-6295-3864-6301-4c02aacdb971@oss.nttdata.com> <04e09eb7-9483-8f63-4bb4-01c9e814802e@oracle.com> <238a89a3-06b1-90e4-d5a4-8dc2f1ed12ab@oracle.com> <4c43bc2c-551e-d042-8fa7-b63e755888d1@oracle.com> <8c387550-a06e-6320-f453-0e898486befb@oss.nttdata.com> Message-ID: Hi Yasumasa, Thank you for this update - the test looks much better and is readable now. I'm on vacation this week but will try to look at your fixes a little bit more. As I understand you are going to post one more update. Thanks, Serguei On 7/6/20 06:29, Yasumasa Suenaga wrote: > Hi Serguei, > > Thanks for your comment! > > I think C++ is more simple to implement the test agent as you said. > So I implement it in C++ in new webrev. Could you review again? > > ? http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.06/ > > Also I refactored libGetThreadListStackTraces.cpp, and I've kept > exception check after IsSameObject(). > > > Thanks, > > Yasumasa > > > On 2020/07/06 16:32, serguei.spitsyn at oracle.com wrote: >> Hi Yasumasa, >> >> Thank you for the update. >> I think, a pending exception after IsSameObject needs to be checked. >> >> The checkStackInfo() needs one more refactoring as I've already >> suggested. >> The body of the loop at L68-L78 should be converted to a function >> check_frame_info. >> The si1->frame_buffer[i] and si2->frame_buffer[i] will be passed as >> fi1 and fi2. >> The index can be passed as well. >> I'm still suggesting to simplify the local exception_msg to something >> shorter like err_msg or exc_msg. >> >> I'm not sure using fatal is right here: >> >> This fragment looks strange: >> >> ? 152???? if ((*env)->IsSameObject(env, stack_info[i].thread, thread)) { >> ? 153?????? target_info = &stack_info[i]; >> ? 154?????? break; >> ? 155???? } else if ((*env)->ExceptionOccurred(env)) { >> ? 156?????? (*env)->ExceptionDescribe(env); >> ? 157?????? (*env)->FatalError(env, __FILE__); >> ? 158???? } >> >> I expected it to be: >> >> ??? jboolean same = (*env)->IsSameObject(env, stack_info[i].thread, >> thread); >> ??? if ((*env)->ExceptionOccurred(env)) { >> ????? (*env)->ExceptionDescribe(env); >> ????? (*env)->FatalError(env, __FILE__); >> ??? } >> ??? if (same) { >> ????? target_info = &stack_info[i]; >> ????? break; >> ??? } >> >> Would it better to port this agent to C++ to simplify this code nicer? >> >> Thanks, >> Serguei >> >> >> On 7/5/20 06:13, Yasumasa Suenaga wrote: >>> Hi Serguei, >>> >>> Thanks for your comment! >>> I refactored testcase. Could you review again? >>> >>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.05/ >>> >>> It would check Java exception after IsSameObject() call. Does it need? >>> Any exceptions are not described in JNI document[1], and JNI >>> implementation (jni_IsSameObject()) does not seem to throw it. >>> >>> >>> Thanks, >>> >>> Yasumasa >>> >>> >>> [1] >>> https://docs.oracle.com/en/java/javase/14/docs/specs/jni/functions.html#issameobject >>> >>> >>> On 2020/07/05 14:46, serguei.spitsyn at oracle.com wrote: >>>> Hi Yasumasa, >>>> >>>> >>>> Okay, thanks. >>>> Then I'm okay to keep the GetSingleStackTraceClosure. >>>> >>>> >>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libGetThreadListStackTraces.c.html >>>> >>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.c.html >>>> >>>> >>>> I'm not sure the function 'is_same_thread() is needed. >>>> Why do not use the JNI IsSameObject instead? >>>> >>>> It seems to be a typo at L132 and L137. >>>> You, probably. did not want to print the same information for >>>> stack_info_1[i].frame_buffer[j].XXX twice. >>>> >>>> The code at lines 112-142 is not readable. >>>> I'd suggest to make a couple of refactoring steps. >>>> >>>> First step to simplify this a little bit would be with some >>>> renaming and getting rid of indexes: >>>> >>>> ?? 71 char err_msg[EXCEPTION_MSG_LEN] = {0}; >>>> ??... >>>> ??112?? /* Iterate all jvmtiStackInfo to check */ >>>> ??113?? for (i = 0; i < num_threads, *exception_msg != '\0'; i++) { >>>> ????????? jvmtiStackInfo *si1 = stack_info_1[i]; >>>> ????????? jvmtiStackInfo *si2 = stack_info_2[i]; >>>> ??114???? if (!IsSameObject(env, si1.thread, si2.thread)) { /* >>>> jvmtiStackInfo::thread */ >>>> ??115?????? snprintf(err_msg, sizeof(err_msg), >>>> ??116??????????????? "thread[%d] is different: stack_info_1 = %p, >>>> stack_info_2 = %p", >>>> ??117??????????????? i, sinfo1.thread, sinfo2.thread); >>>> ??118???? } else if (si1.state != si2.state) { /* >>>> jvmtiStackInfo::state */ >>>> ??119?????? snprintf(err_msg, sizeof(err_msg), >>>> ??120??????????????? "state[%d] is different: stack_info_1 = %d, >>>> stack_info_2 = %d", >>>> ??121??????????????? i, si1.state, si2.state); >>>> ??122???? } else if (si1.frame_count != si2.frame_count) { /* >>>> jvmtiStackInfo::frame_count */ >>>> ??123?????? snprintf(err_msg, sizeof(err_msg), >>>> ??124??????????????? "frame_count[%d] is different: stack_info_1 = >>>> %d, stack_info_2 = %d", >>>> ??125??????????????? i, si1.frame_count, si2.frame_count); >>>> ??126???? } else { >>>> ??127?????? /* Iterate all jvmtiFrameInfo to check */ >>>> ??128?????? for (j = 0; j < si1.frame_count; j++) { >>>> ??129???????? if (si1.frame_buffer[j].method != >>>> si1.frame_buffer[j].method) { /* jvmtiFrameInfo::method */ >>>> ??130?????????? snprintf(err_msg, sizeof(err_msg), >>>> ??131??????????????????? "thread [%d] frame_buffer[%d].method is >>>> different: stack_info_1 = %lx, stack_info_2 = %lx", >>>> ??132??????????????????? i, j, si1.frame_buffer[j].method, >>>> si2.frame_buffer[j].method); >>>> ??133?????????? break; >>>> ??134???????? } else if (si1.frame_buffer[j].location != >>>> si1.frame_buffer[j].location) { /* jvmtiFrameInfo::location */ >>>> ??135?????????? snprintf(err_msg, sizeof(err_msg), >>>> ??136??????????????????? "thread [%d] frame_buffer[%d].location is >>>> different: stack_info_1 = %ld, stack_info_2 = %ld", >>>> ??137??????????????????? i, j, si1.frame_buffer[j].location, >>>> si2.frame_buffer[j].location); >>>> ??138?????????? break; >>>> ??139???????? } >>>> ??140?????? } >>>> ??141???? } >>>> ??142?? } >>>> >>>> Another step would be to create functions that implement a body of >>>> each loop. >>>> You can use the same techniques to simplify similar place >>>> (L127-L138) in the libOneGetThreadListStackTraces.c. >>>> >>>> Thanks, >>>> Serguei >>>> >>>> >>>> On 7/3/20 15:55, Yasumasa Suenaga wrote: >>>>> Hi Serguei, >>>>> >>>>> I'm not an Oracle employee, so I cannot know real request(s) from >>>>> your customers. >>>>> However JDK-8201641 says Dynatrace has requested this enhancement. >>>>> >>>>> BTW I haven't heared any request from my customers about this. >>>>> >>>>> >>>>> Thanks, >>>>> >>>>> Yasumasa >>>>> >>>>> >>>>> On 2020/07/04 4:32, serguei.spitsyn at oracle.com wrote: >>>>>> Hi Yasumasa, >>>>>> >>>>>> This difference is not that big to care about. >>>>>> I feel this is really rare case and so, does not worth these >>>>>> complications. >>>>>> Do we have a real request from customers to optimize it? >>>>>> >>>>>> Thanks, >>>>>> Serguei >>>>>> >>>>>> >>>>>> On 7/3/20 01:16, Yasumasa Suenaga wrote: >>>>>>> Hi Serguei, >>>>>>> >>>>>>> Generally I agree with you, but I have concern about the >>>>>>> difference of the result of GetStackTrace() and >>>>>>> GetThreadListStackTraces(). >>>>>>> >>>>>>> ? GetStackTrace: jvmtiFrameInfo >>>>>>> ? GetThreadListStackTraces: jvmtiStackInfo >>>>>>> >>>>>>> jvmtiStackInfo contains thread state, and it is ensured it is >>>>>>> the state of the call stack. >>>>>>> If we want to get both call stack and thread state, we need to >>>>>>> suspend target thread, and call both GetStackTrace() and >>>>>>> GetThreadState(). Is it ok? >>>>>>> >>>>>>> I was wondering if JDK-8201641 (parent ticket of this change) >>>>>>> needed them for profiling (dynatrace?) >>>>>>> If it is responsibility of JVMTI agent implementor, I remove >>>>>>> this closure. >>>>>>> >>>>>>> >>>>>>> Thanks, >>>>>>> >>>>>>> Yasumasa >>>>>>> >>>>>>> >>>>>>> On 2020/07/03 16:45, serguei.spitsyn at oracle.com wrote: >>>>>>>> Hi Yasumasa, >>>>>>>> >>>>>>>> After some thinking I've concluded that I do not like this >>>>>>>> optimization >>>>>>>> of the GetThreadListStackTraces with GetSingleStackTraceClosure. >>>>>>>> >>>>>>>> We may need more opinions on this but these are my points: >>>>>>>> ??- it adds some complexity and ugliness >>>>>>>> ??- a win is doubtful because it has to be a rare case, so that >>>>>>>> total overhead should not be high >>>>>>>> ??- if it is really high for some use cases then it is up to >>>>>>>> the user >>>>>>>> ??? to optimize it with using GetStackTrace instead >>>>>>>> >>>>>>>> In such cases with doubtful overhead I usually prefer the >>>>>>>> simplicity. >>>>>>>> >>>>>>>> Good examples where it makes sense to optimize are checks for >>>>>>>> target thread to be current thread. >>>>>>>> In such cases there is no need to suspend the target thread, or >>>>>>>> use a VMop/HandshakeClosure. >>>>>>>> For instance, please, see the Monitor functions with the check: >>>>>>>> (java_thread == calling_thread). >>>>>>>> Getting information for current thread is frequently used case, >>>>>>>> e.g. to get info at an event point. >>>>>>>> >>>>>>>> Thanks, >>>>>>>> Serguei >>>>>>>> >>>>>>>> >>>>>>>> On 7/2/20 23:29, Yasumasa Suenaga wrote: >>>>>>>>> Hi Dan, David, >>>>>>>>> >>>>>>>>> I uploaded new webrev. Could you review again? >>>>>>>>> >>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/ >>>>>>>>> >>>>>>>>> OneGetThreadListStackTraces.java in this webrev would wait >>>>>>>>> until thread state is transited to "waiting" with spin wait. >>>>>>>>> CountDownLatch::await call as Dan pointed is fixed in it :) >>>>>>>>> >>>>>>>>> Diff from webrev.03: >>>>>>>>> http://hg.openjdk.java.net/jdk/submit/rev/c9aeb7001e50 >>>>>>>>> >>>>>>>>> >>>>>>>>> Thanks, >>>>>>>>> >>>>>>>>> Yasumasa >>>>>>>>> >>>>>>>>> >>>>>>>>> On 2020/07/03 14:15, David Holmes wrote: >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> On 3/07/2020 2:27 pm, Yasumasa Suenaga wrote: >>>>>>>>>>> On 2020/07/03 12:24, Daniel D. Daugherty wrote: >>>>>>>>>>>> On 7/2/20 10:50 PM, David Holmes wrote: >>>>>>>>>>>>> Sorry I'm responding here without seeing latest webrev but >>>>>>>>>>>>> there is enough context I think ... >>>>>>>>>>>>> >>>>>>>>>>>>> On 3/07/2020 9:14 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>> Hi Dan, >>>>>>>>>>>>>> >>>>>>>>>>>>>> Thanks for your comment! >>>>>>>>>>>>>> >>>>>>>>>>>>>> On 2020/07/03 7:16, Daniel D. Daugherty wrote: >>>>>>>>>>>>>>> On 7/2/20 5:19 AM, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> I upload new webrev. Could you review again? >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.03/ >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnv.cpp >>>>>>>>>>>>>>> ???? L1542: ??? // Get stack trace with handshake >>>>>>>>>>>>>>> ???????? nit - please add a period at the end. >>>>>>>>>>>>>> >>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>>> ???? L1591: *stack_info_ptr = op.stack_info(); >>>>>>>>>>>>>>> ???????? The return parameter should not be touched >>>>>>>>>>>>>>> unless the return >>>>>>>>>>>>>>> ???????? code in 'err' == JVMTI_ERROR_NONE. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> ???? old L1582: ? if (err == JVMTI_ERROR_NONE) { >>>>>>>>>>>>>>> ???????? Please restore this check. The return parameter >>>>>>>>>>>>>>> should not >>>>>>>>>>>>>>> ???????? be touched unless the return code in 'err' == >>>>>>>>>>>>>>> JVMTI_ERROR_NONE. >>>>>>>>>>>>>> >>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>> >>>>>>>>>>>>> But op.stack_info() will return NULL if the error is not >>>>>>>>>>>>> JVMTI_ERROR_NONE. Are you (Dan) concerned about someone >>>>>>>>>>>>> passing in a non-null/initialized out-pointer that will be >>>>>>>>>>>>> reset to NULL if there was an error? >>>>>>>>>>>> >>>>>>>>>>>> Actually the way we used to test this in POSIX tests is to >>>>>>>>>>>> call >>>>>>>>>>>> an API with known bad parameters and the return parameter ptr >>>>>>>>>>>> set to NULL. If the return parameter ptr was touched when an >>>>>>>>>>>> error should have been detected on an earlier parameter, then >>>>>>>>>>>> the test failed. >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>>> ???? L1272: ? if (!jt->is_exiting() && (thread_oop != >>>>>>>>>>>>>>> NULL)) { >>>>>>>>>>>>>>> ???????? nit - extra parens around the second expression. >>>>>>>>>>>>>> >>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>>> ???? old L1532: ? _result = JVMTI_ERROR_THREAD_NOT_ALIVE; >>>>>>>>>>>>>>> ???????? This deletion of the _result field threw me for >>>>>>>>>>>>>>> a minute and then >>>>>>>>>>>>>>> ???? ? ? I figured out that the field is init to >>>>>>>>>>>>>>> JVMTI_ERROR_THREAD_NOT_ALIVE >>>>>>>>>>>>>>> ???????? in the constructor. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> ???? L1553: ? if (!jt->is_exiting() && (jt->threadObj() >>>>>>>>>>>>>>> != NULL)) { >>>>>>>>>>>>>>> ???????? nit - extra parens around the second expression. >>>>>>>>>>>>>> >>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>>>>>>>>>>> ???? No comments. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> src/hotspot/share/runtime/vmOperations.hpp >>>>>>>>>>>>>>> ???? No comments. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/GetThreadListStackTraces.java >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> ???? No comments. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/OneGetThreadListStackTraces.java >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> ???? L64: startSignal.countDown(); >>>>>>>>>>>>>>> ???????? I was expecting this to be a call to await() >>>>>>>>>>>>>>> instead of >>>>>>>>>>>>>>> ???????? countDown(). What am I missing here? >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> ???????? I think this test might be passing by accident >>>>>>>>>>>>>>> right now, but... >>>>>>>>>>>>>> >>>>>>>>>>>>>> Main thread (which call JVMTI functions to test) should >>>>>>>>>>>>>> wait until test thread is ready. >>>>>>>>>>>>>> So main thread would wait startSignal, and test thread >>>>>>>>>>>>>> would count down. >>>>>>>>>>>>> >>>>>>>>>>>>> No! >>>>>>>>>>>>> >>>>>>>>>>>>> The test thread that previously called obj.wait() now >>>>>>>>>>>>> calls latch.await(). >>>>>>>>>>>>> >>>>>>>>>>>>> The main thread that previously called obj.notify() now >>>>>>>>>>>>> calls latch.countDown(). >>>>>>>>>>>>> >>>>>>>>>>>>> The main thread continues to spin until it sees the target >>>>>>>>>>>>> is WAITING before proceeding with the test. >>>>>>>>>>> >>>>>>>>>>> If I add spin wait to wait until transit target thread state >>>>>>>>>>> is WAITING (as following), we don't need to call >>>>>>>>>>> SuspendThread(). >>>>>>>>>>> Which is better? >>>>>>>>>> >>>>>>>>>> The original spin-wait loop checking for WAITING is better >>>>>>>>>> because it is the only guarantee that the target thread is >>>>>>>>>> blocked where you need it to be. suspending the thread is >>>>>>>>>> racy as you don't know exactly where the suspend will hit. >>>>>>>>>> >>>>>>>>>> Thanks, >>>>>>>>>> David >>>>>>>>>> ----- >>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> ``` >>>>>>>>>>> /* Wait until the thread state transits to "waiting" */ >>>>>>>>>>> while (th.getState() != Thread.State.WAITING) { >>>>>>>>>>> ???? Thread.onSpinWait(); >>>>>>>>>>> } >>>>>>>>>>> ``` >>>>>>>>>>> >>>>>>>>>>> For simplify, spin wait is prefer to >>>>>>>>>>> OneGetThreadListStackTraces.java in webrev.03. >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> Thanks, >>>>>>>>>>> >>>>>>>>>>> Yasumasa >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>>> Here's the flow as I see it: >>>>>>>>>>>> >>>>>>>>>>>> main thread >>>>>>>>>>>> ?? - start worker thread >>>>>>>>>>>> ?? - startSignal.await() >>>>>>>>>>>> ???? - main is now blocked >>>>>>>>>>>> >>>>>>>>>>>> worker thread >>>>>>>>>>>> ?? - startSignal.countDown() >>>>>>>>>>>> ???? - main is now unblocked >>>>>>>>>>>> ?? - stopSignal.await() >>>>>>>>>>>> ???? - worker is now blocked >>>>>>>>>>>> >>>>>>>>>>>> main thread >>>>>>>>>>>> ?? - checkCallStacks(th) >>>>>>>>>>>> ?? - stopSignal.countDown() >>>>>>>>>>>> ???? - worker is now unblocked >>>>>>>>>>>> ?? - th.join >>>>>>>>>>>> ???? - main is now blocked >>>>>>>>>>>> >>>>>>>>>>>> worker thread >>>>>>>>>>>> ?? - runs off the end of run() >>>>>>>>>>>> ???? - main is now unblocked >>>>>>>>>>>> >>>>>>>>>>>> main thread >>>>>>>>>>>> ?? - run off the end of main() >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libGetThreadListStackTraces.c >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> ???? L92: ? jthreads = (jthread *)malloc(sizeof(jthread) >>>>>>>>>>>>>>> * num_threads); >>>>>>>>>>>>>>> ???????? You don't check for malloc() failure. >>>>>>>>>>>>>>> ???????? 'jthreads' is allocated but never freed. >>>>>>>>>>>>>> >>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.c >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> ???? L91: ? result = (*jvmti)->SuspendThread(jvmti, >>>>>>>>>>>>>>> thread); >>>>>>>>>>>>>>> ???????? Why are you suspending the thread? >>>>>>>>>>>>>>> GetAllStackTraces() and >>>>>>>>>>>>>>> ???????? GetThreadListStackTraces() do not require the >>>>>>>>>>>>>>> target thread(s) >>>>>>>>>>>>>>> ???????? to be suspend. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> ???????? If you decide not to SuspendThread, then you >>>>>>>>>>>>>>> don't need the >>>>>>>>>>>>>>> ???????? AddCapabilities or the ResumeThread calls. >>>>>>>>>>>>>> >>>>>>>>>>>>>> Test thread might not be entered following code >>>>>>>>>>>>>> (stopSignal.await()). We might see deferent call stack >>>>>>>>>>>>>> between GetAllStackTraces() and >>>>>>>>>>>>>> GetThreadListStackTraces(). We cannot control to freeze >>>>>>>>>>>>>> call stack of test thread in Java code. >>>>>>>>>>>>>> (I didn't use SuspendThread() at first, but I saw some >>>>>>>>>>>>>> errors which causes in above.) >>>>>>>>>>>>>> >>>>>>>>>>>>>> So we need to call SuspendThread() to ensure we can see >>>>>>>>>>>>>> same call stack. >>>>>>>>>>>>> >>>>>>>>>>>>> If you are checking that the thread is in state WAITING >>>>>>>>>>>>> then it cannot escape from that state and you can sample >>>>>>>>>>>>> the stack multiple times from any API and get the same >>>>>>>>>>>>> result. >>>>>>>>>>>>> >>>>>>>>>>>>> I suspect the errors you saw were from the apparent >>>>>>>>>>>>> incorrect use of the CountDownLatch. >>>>>>>>>>>> >>>>>>>>>>>> With the flow outlined above, the worker thread should be >>>>>>>>>>>> nicely blocked in stopSignal.await() when stuff is sampled. >>>>>>>>>>>> >>>>>>>>>>>> Dan >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> Cheers, >>>>>>>>>>>>> David >>>>>>>>>>>>> ----- >>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>> >>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>>> Dan >>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> On 2020/07/02 15:05, David Holmes wrote: >>>>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> On 1/07/2020 11:53 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>> Hi, >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> I uploaded new webrev. Could review again? >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.02/ >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Updates look fine - thanks. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> One minor nit: >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> 1274 _collector.allocate_and_fill_stacks(1); >>>>>>>>>>>>>>>>> 1275 _collector.set_result(JVMTI_ERROR_NONE); >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> In the other places where you use _collector you rely >>>>>>>>>>>>>>>>> on result being initialized to JVMTI_ERROR_NONE, >>>>>>>>>>>>>>>>> rather than setting it directly after >>>>>>>>>>>>>>>>> allocate_and_fill_stacks(). >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Fixed. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> ? 820 >>>>>>>>>>>>>>>>>>>>>>> assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>>>>>>>>>>> ? 821 >>>>>>>>>>>>>>>>>>>>>>> java_thread->is_thread_fully_suspended(false, >>>>>>>>>>>>>>>>>>>>>>> &debug_bits) || >>>>>>>>>>>>>>>>>>>>>>> ? 822 current_thread == >>>>>>>>>>>>>>>>>>>>>>> java_thread->active_handshaker(), >>>>>>>>>>>>>>>>>>>>>>> ? 823????????? "at safepoint / handshake or >>>>>>>>>>>>>>>>>>>>>>> target thread is suspended"); >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> I don't think the suspension check is necessary, >>>>>>>>>>>>>>>>>>>>>>> as even if the target is suspended we must still >>>>>>>>>>>>>>>>>>>>>>> be at a safepoint or in a handshake with it. >>>>>>>>>>>>>>>>>>>>>>> Makes me wonder if we used to allow a racy >>>>>>>>>>>>>>>>>>>>>>> stacktrace operation on a suspended thread, >>>>>>>>>>>>>>>>>>>>>>> assuming it would remain suspended? >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> This function (JvmtiEnvBase::get_stack_trace()) can >>>>>>>>>>>>>>>>>> be called to get own stack trace. For example, we can >>>>>>>>>>>>>>>>>> call GetStackTrace() for current thread at JVMTI event. >>>>>>>>>>>>>>>>>> So I changed assert as below: >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>> ??820?? assert(current_thread == java_thread || >>>>>>>>>>>>>>>>>> ??821 SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>>>>>> ??822????????? current_thread == >>>>>>>>>>>>>>>>>> java_thread->active_handshaker(), >>>>>>>>>>>>>>>>>> ??823????????? "call by myself / at safepoint / at >>>>>>>>>>>>>>>>>> handshake"); >>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Yep good catch. I hope current tests caught that. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> They would be tested in >>>>>>>>>>>>>>>> vmTestbase/nsk/jvmti/GetStackTrace/getstacktr001/ (own >>>>>>>>>>>>>>>> call stacks), and getstacktr003 (call stacks in other >>>>>>>>>>>>>>>> thread). >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Speaking of tests ... >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> In the native code I think you need to check the >>>>>>>>>>>>>>>>> success of all JNI methods that can throw exceptions - >>>>>>>>>>>>>>>>> otherwise I believe the tests may trigger warnings if >>>>>>>>>>>>>>>>> -Xcheck:jni is used with them. See for example: >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/libHeapMonitorTest.cpp >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> I updated testcases to check JNI and JVMTI function calls. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> In the Java code the target thread: >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> ?? 45???? public void run() { >>>>>>>>>>>>>>>>> ?? 46?????? try { >>>>>>>>>>>>>>>>> ?? 47?????????? synchronized (lock) { >>>>>>>>>>>>>>>>> ?? 48?????????????? lock.wait(); >>>>>>>>>>>>>>>>> ?? 49 System.out.println("OK"); >>>>>>>>>>>>>>>>> ?? 50?????????? } >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> is potentially susceptible to spurious wakeups. Using >>>>>>>>>>>>>>>>> a CountDownLatch would be robust. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Fixed. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> On 2020/07/01 8:48, David Holmes wrote: >>>>>>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> On 1/07/2020 9:05 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> 1271 ResourceMark rm; >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> IIUC at this point the _calling_thread is the >>>>>>>>>>>>>>>>>>>>>>> current thread, so we can use: >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> If so, we can call make_local() in L1272 without >>>>>>>>>>>>>>>>>>>> JavaThread (or we can pass current thread to >>>>>>>>>>>>>>>>>>>> make_local()). Is it right? >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>>>>>>>>>>>> 1272 >>>>>>>>>>>>>>>>>>>> _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, >>>>>>>>>>>>>>>>>>>> thread_oop), >>>>>>>>>>>>>>>>>>>> 1273 jt, thread_oop); >>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Sorry I got confused, _calling_thread may not be the >>>>>>>>>>>>>>>>>>> current thread as we could be executing the >>>>>>>>>>>>>>>>>>> handshake in the target thread itself. So the >>>>>>>>>>>>>>>>>>> ResourceMark is correct as-is (implicitly for >>>>>>>>>>>>>>>>>>> current thread). >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> The argument to fill_frames will be used in the >>>>>>>>>>>>>>>>>>> jvmtiStackInfo and passed back to the >>>>>>>>>>>>>>>>>>> _calling_thread, so it must be created via >>>>>>>>>>>>>>>>>>> make_local(_calling_thread, ...) as you presently have. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> On 2020/07/01 7:05, David Holmes wrote: >>>>>>>>>>>>>>>>>>>>> On 1/07/2020 12:17 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Thank you for reviewing! I will update new webrev >>>>>>>>>>>>>>>>>>>>>> tomorrow. >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> 466 class MultipleStackTracesCollector : public >>>>>>>>>>>>>>>>>>>>>>> StackObj { >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> ? 498 class VM_GetAllStackTraces : public >>>>>>>>>>>>>>>>>>>>>>> VM_Operation { >>>>>>>>>>>>>>>>>>>>>>> ? 499 private: >>>>>>>>>>>>>>>>>>>>>>> ? 500?? JavaThread *_calling_thread; >>>>>>>>>>>>>>>>>>>>>>> ? 501?? jint _final_thread_count; >>>>>>>>>>>>>>>>>>>>>>> ? 502 MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> You can't have a StackObj as a member of another >>>>>>>>>>>>>>>>>>>>>>> class like that as it may not be on the stack. I >>>>>>>>>>>>>>>>>>>>>>> think MultipleStackTracesCollector should not >>>>>>>>>>>>>>>>>>>>>>> extend any allocation class, and should always >>>>>>>>>>>>>>>>>>>>>>> be embedded directly in another class. >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> I'm not sure what does mean "embedded". >>>>>>>>>>>>>>>>>>>>>> Is it ok as below? >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>> class MultipleStackTracesCollector { >>>>>>>>>>>>>>>>>>>>>> ??? : >>>>>>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> class GetAllStackTraces : public VM_Operation { >>>>>>>>>>>>>>>>>>>>>> ?? private: >>>>>>>>>>>>>>>>>>>>>> MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Yes that I what I meant. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> On 2020/06/30 22:22, David Holmes wrote: >>>>>>>>>>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> On 30/06/2020 10:05 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>>>> Hi David, Serguei, >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> I updated webrev for 8242428. Could you review >>>>>>>>>>>>>>>>>>>>>>>> again? >>>>>>>>>>>>>>>>>>>>>>>> This change migrate to use direct handshake for >>>>>>>>>>>>>>>>>>>>>>>> GetStackTrace() and GetThreadListStackTraces() >>>>>>>>>>>>>>>>>>>>>>>> (when thread_count == 1). >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.01/ >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> This looks really good now! I only have a few >>>>>>>>>>>>>>>>>>>>>>> nits below. There is one thing I don't like >>>>>>>>>>>>>>>>>>>>>>> about it but it requires a change to the main >>>>>>>>>>>>>>>>>>>>>>> Handshake logic to address - in >>>>>>>>>>>>>>>>>>>>>>> JvmtiEnv::GetThreadListStackTraces you have to >>>>>>>>>>>>>>>>>>>>>>> create a ThreadsListHandle to convert the >>>>>>>>>>>>>>>>>>>>>>> jthread to a JavaThread, but then the >>>>>>>>>>>>>>>>>>>>>>> Handshake::execute_direct creates another >>>>>>>>>>>>>>>>>>>>>>> ThreadsListHandle internally. That's a waste. I >>>>>>>>>>>>>>>>>>>>>>> will discuss with Robbin and file a RFE to have >>>>>>>>>>>>>>>>>>>>>>> an overload of execute_direct that takes an >>>>>>>>>>>>>>>>>>>>>>> existing TLH. Actually it's worse than that >>>>>>>>>>>>>>>>>>>>>>> because we have another TLH in use at the entry >>>>>>>>>>>>>>>>>>>>>>> point for the JVMTI functions, so I think there >>>>>>>>>>>>>>>>>>>>>>> may be some scope for simplifying the use of TLH >>>>>>>>>>>>>>>>>>>>>>> instances - future RFE. >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> ??451 GetStackTraceClosure(JvmtiEnv *env, jint >>>>>>>>>>>>>>>>>>>>>>> start_depth, jint max_count, >>>>>>>>>>>>>>>>>>>>>>> ??452 jvmtiFrameInfo* frame_buffer, jint* >>>>>>>>>>>>>>>>>>>>>>> count_ptr) >>>>>>>>>>>>>>>>>>>>>>> ??453???? : HandshakeClosure("GetStackTrace"), >>>>>>>>>>>>>>>>>>>>>>> ??454?????? _env(env), >>>>>>>>>>>>>>>>>>>>>>> _start_depth(start_depth), _max_count(max_count), >>>>>>>>>>>>>>>>>>>>>>> ??455 _frame_buffer(frame_buffer), >>>>>>>>>>>>>>>>>>>>>>> _count_ptr(count_ptr), >>>>>>>>>>>>>>>>>>>>>>> ??456 _result(JVMTI_ERROR_THREAD_NOT_ALIVE) { >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Nit: can you do one initializer per line please. >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> This looks wrong: >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> 466 class MultipleStackTracesCollector : public >>>>>>>>>>>>>>>>>>>>>>> StackObj { >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> ??498 class VM_GetAllStackTraces : public >>>>>>>>>>>>>>>>>>>>>>> VM_Operation { >>>>>>>>>>>>>>>>>>>>>>> ??499 private: >>>>>>>>>>>>>>>>>>>>>>> ??500?? JavaThread *_calling_thread; >>>>>>>>>>>>>>>>>>>>>>> ??501?? jint _final_thread_count; >>>>>>>>>>>>>>>>>>>>>>> ??502 MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> You can't have a StackObj as a member of another >>>>>>>>>>>>>>>>>>>>>>> class like that as it may not be on the stack. I >>>>>>>>>>>>>>>>>>>>>>> think MultipleStackTracesCollector should not >>>>>>>>>>>>>>>>>>>>>>> extend any allocation class, and should always >>>>>>>>>>>>>>>>>>>>>>> be embedded directly in another class. >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> 481 MultipleStackTracesCollector(JvmtiEnv *env, >>>>>>>>>>>>>>>>>>>>>>> jint max_frame_count) { >>>>>>>>>>>>>>>>>>>>>>> ??482???? _env = env; >>>>>>>>>>>>>>>>>>>>>>> ??483 _max_frame_count = max_frame_count; >>>>>>>>>>>>>>>>>>>>>>> ??484 _frame_count_total = 0; >>>>>>>>>>>>>>>>>>>>>>> ??485???? _head = NULL; >>>>>>>>>>>>>>>>>>>>>>> ??486???? _stack_info = NULL; >>>>>>>>>>>>>>>>>>>>>>> ??487???? _result = JVMTI_ERROR_NONE; >>>>>>>>>>>>>>>>>>>>>>> ??488?? } >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> As you are touching this can you change it to >>>>>>>>>>>>>>>>>>>>>>> use an initializer list as you did for the >>>>>>>>>>>>>>>>>>>>>>> HandshakeClosure, and please keep one item per >>>>>>>>>>>>>>>>>>>>>>> line. >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> ??820 >>>>>>>>>>>>>>>>>>>>>>> assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>>>>>>>>>>> ??821 >>>>>>>>>>>>>>>>>>>>>>> java_thread->is_thread_fully_suspended(false, >>>>>>>>>>>>>>>>>>>>>>> &debug_bits) || >>>>>>>>>>>>>>>>>>>>>>> ??822 current_thread == >>>>>>>>>>>>>>>>>>>>>>> java_thread->active_handshaker(), >>>>>>>>>>>>>>>>>>>>>>> ??823????????? "at safepoint / handshake or >>>>>>>>>>>>>>>>>>>>>>> target thread is suspended"); >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> I don't think the suspension check is necessary, >>>>>>>>>>>>>>>>>>>>>>> as even if the target is suspended we must still >>>>>>>>>>>>>>>>>>>>>>> be at a safepoint or in a handshake with it. >>>>>>>>>>>>>>>>>>>>>>> Makes me wonder if we used to allow a racy >>>>>>>>>>>>>>>>>>>>>>> stacktrace operation on a suspended thread, >>>>>>>>>>>>>>>>>>>>>>> assuming it would remain suspended? >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> 1268?? oop thread_oop = jt->threadObj(); >>>>>>>>>>>>>>>>>>>>>>> 1269 >>>>>>>>>>>>>>>>>>>>>>> 1270?? if (!jt->is_exiting() && (jt->threadObj() >>>>>>>>>>>>>>>>>>>>>>> != NULL)) { >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> You can use thread_oop in line 1270. >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> 1272 >>>>>>>>>>>>>>>>>>>>>>> _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, >>>>>>>>>>>>>>>>>>>>>>> thread_oop), >>>>>>>>>>>>>>>>>>>>>>> 1273 jt, thread_oop); >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> It is frustrating that this entire call chain >>>>>>>>>>>>>>>>>>>>>>> started with a jthread reference, which we >>>>>>>>>>>>>>>>>>>>>>> converted to a JavaThread, only to eventually >>>>>>>>>>>>>>>>>>>>>>> need to convert it back to a jthread! I think >>>>>>>>>>>>>>>>>>>>>>> there is some scope for simplification here but >>>>>>>>>>>>>>>>>>>>>>> not as part of this change. >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> IIUC at this point the _calling_thread is the >>>>>>>>>>>>>>>>>>>>>>> current thread, so we can use: >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Please add @bug lines to the tests. >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> I'm still pondering the test logic but wanted to >>>>>>>>>>>>>>>>>>>>>>> send this now. >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>>>>>>>>> VM_GetThreadListStackTrace (for >>>>>>>>>>>>>>>>>>>>>>>> GetThreadListStackTraces) and >>>>>>>>>>>>>>>>>>>>>>>> VM_GetAllStackTraces (for GetAllStackTraces) >>>>>>>>>>>>>>>>>>>>>>>> have inherited VM_GetMultipleStackTraces VM >>>>>>>>>>>>>>>>>>>>>>>> operation which provides the feature to >>>>>>>>>>>>>>>>>>>>>>>> generate jvmtiStackInfo. I modified >>>>>>>>>>>>>>>>>>>>>>>> VM_GetMultipleStackTraces to a normal C++ class >>>>>>>>>>>>>>>>>>>>>>>> to share with HandshakeClosure for >>>>>>>>>>>>>>>>>>>>>>>> GetThreadListStackTraces >>>>>>>>>>>>>>>>>>>>>>>> (GetSingleStackTraceClosure). >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Also I added new testcases which test >>>>>>>>>>>>>>>>>>>>>>>> GetThreadListStackTraces() with thread_count == >>>>>>>>>>>>>>>>>>>>>>>> 1 and with all threads. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> This change has been tested in >>>>>>>>>>>>>>>>>>>>>>>> serviceability/jvmti serviceability/jdwp >>>>>>>>>>>>>>>>>>>>>>>> vmTestbase/nsk/jvmti vmTestbase/nsk/jdi >>>>>>>>>>>>>>>>>>>>>>>> vmTestbase/nsk/jdwp. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> On 2020/06/24 15:50, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>>>>> Hi all, >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> Please review this change: >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> ?? JBS: >>>>>>>>>>>>>>>>>>>>>>>>> https://bugs.openjdk.java.net/browse/JDK-8242428 >>>>>>>>>>>>>>>>>>>>>>>>> ?? webrev: >>>>>>>>>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.00/ >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> This change replace following VM operations to >>>>>>>>>>>>>>>>>>>>>>>>> direct handshake. >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> ??- VM_GetFrameCount (GetFrameCount()) >>>>>>>>>>>>>>>>>>>>>>>>> ??- VM_GetFrameLocation (GetFrameLocation()) >>>>>>>>>>>>>>>>>>>>>>>>> ??- VM_GetThreadListStackTraces >>>>>>>>>>>>>>>>>>>>>>>>> (GetThreadListStackTrace()) >>>>>>>>>>>>>>>>>>>>>>>>> ??- VM_GetCurrentLocation >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> GetThreadListStackTrace() uses direct >>>>>>>>>>>>>>>>>>>>>>>>> handshake if thread count == 1. In other case >>>>>>>>>>>>>>>>>>>>>>>>> (thread count > 1), it would be performed as >>>>>>>>>>>>>>>>>>>>>>>>> VM operation (VM_GetThreadListStackTraces). >>>>>>>>>>>>>>>>>>>>>>>>> Caller of VM_GetCurrentLocation >>>>>>>>>>>>>>>>>>>>>>>>> (JvmtiEnvThreadState::reset_current_location()) >>>>>>>>>>>>>>>>>>>>>>>>> might be called at safepoint. So I added >>>>>>>>>>>>>>>>>>>>>>>>> safepoint check in its caller. >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> This change has been tested in >>>>>>>>>>>>>>>>>>>>>>>>> serviceability/jvmti serviceability/jdwp >>>>>>>>>>>>>>>>>>>>>>>>> vmTestbase/nsk/jvmti vmTestbase/nsk/jdi >>>>>>>>>>>>>>>>>>>>>>>>> vmTestbase/ns >>>>>>>>>>>>>>>>>>>>>>>>> k/jdwp. >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> Also I tested it on submit repo, then it has >>>>>>>>>>>>>>>>>>>>>>>>> execution error >>>>>>>>>>>>>>>>>>>>>>>>> (mach5-one-ysuenaga-JDK-8242428-20200624-0054-12034717) >>>>>>>>>>>>>>>>>>>>>>>>> due to dependency error. So I think it does >>>>>>>>>>>>>>>>>>>>>>>>> not occur by this change. >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>> >>>>>> >>>> >> From suenaga at oss.nttdata.com Tue Jul 7 08:54:13 2020 From: suenaga at oss.nttdata.com (Yasumasa Suenaga) Date: Tue, 7 Jul 2020 17:54:13 +0900 Subject: RFR: 8242428: JVMTI thread operations should use Thread-Local Handshake In-Reply-To: References: <6c263e4c-0a83-be7a-0288-ecb2de0b7cea@oss.nttdata.com> <90cdfef9-e558-0d25-33f5-25b7d65bb83b@oss.nttdata.com> <0e359819-618f-c17b-a427-bb7e4daa2c58@oracle.com> <3f890bed-6892-e64d-b21b-ca0cbe11784e@oracle.com> <7dc1903b-6295-3864-6301-4c02aacdb971@oss.nttdata.com> <04e09eb7-9483-8f63-4bb4-01c9e814802e@oracle.com> <238a89a3-06b1-90e4-d5a4-8dc2f1ed12ab@oracle.com> <4c43bc2c-551e-d042-8fa7-b63e755888d1@oracle.com> <8c387550-a06e-6320-f453-0e898486befb@oss.nttdata.com> <19cfa2a7-f441-425d-5623-1c11c6a870b6@oss.nttdata.com> Message-ID: Hi David, Serguei, Serguei, thank you for replying even though you are on vacaiton! I uploaded new webrev: http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.07/ Diff from previous webrev: http://hg.openjdk.java.net/jdk/submit/rev/77243b1dcbfe c'tor of GetSingleStackTraceClosure has jthread argument in this webrev. Also it does not contain testcase for GetThreadListStackTraces with all threads, and OneGetThreadListStackTraces would test main thread only. Thanks, Yasumasa On 2020/07/07 15:13, David Holmes wrote: > On 7/07/2020 2:57 pm, Yasumasa Suenaga wrote: >> Hi David, >> >> On 2020/07/07 11:31, David Holmes wrote: >>> Hi Yasumasa, >>> >>> Hard to keep up with the changes - especially without incremental webrevs. >> >> Sorry, I will upload diff from previous webrev in the next. >> >> >>> If GetSingleStackTraceClosure also took the jthread as a constructor arg, then you wouldn't need to recreate a JNI local handle when calling _collector.fill_frames. It's a small simplification and not essential at this stage. >> >> I think we should get jthread from an argument of do_thread() because do_thread() would pass the thread which are stopped certainly. >> It might be simplification if we pass _calling_thread to MultipleStackTracesCollector. `jthread` is only needed to store jvmtiStackInfo.thread . What do you think? > > I'm not quite sure what you mean. > > I think there is a bit of a design wart with direct handshakes in that do_thread takes the target JavaThread as an argument. That's useful in a case where you want a HandshakeClosure that can be applied to multiple threads, but that's not typically what is needed with direct handshakes - there is only a single target. With a single-target HandshakeClosure you can capture all the "target" information for the operation in the closure instance. So if the actual do_thread operation wants the jthread corresponding to the target thread then we can store that in the closure rather than recomputing it (you could assert it is the same but that seems overkill to me). > >> >>> For the test ... I don't see how Java_GetThreadListStackTraces_checkCallStacks is a valid test. It gets the stacks of all live threads, then uses that information to use GetThreadListStackTraces to get the stack for the same set of threads through a different API. It then compares the two sets of stacks for each thread expecting them to be the same, but that need only be the case for the main thread. Other threads could potentially have a different stack (e.g. if this test is run with JFR enabled there will be additional threads found.) Further I would have expected that there already exist tests that check that, for a given thread (which may be suspended or known to be blocked) the same stack is found through the two different APIs. >> >> vmTestbase/nsk/jvmti/unit/GetAllStackTraces/getallstktr001 would check all of threads via GetThreadListStackTraces() and GetAllStackTraces(), so we might be able to remove GetThreadListStackTraces.java from this webrev. > > Yes. The existing test only examines a set of test threads that are all blocked on a raw monitor. You do not need to duplicate that test. > >> OTOH we don't have testcase for GetThreadListStackTraces() with thread_count == 1, so we need to testcase for it (it is OneGetThreadListStackTraces.java) It would check whether the state of target thread is "waiting" before JNI call to call GetThreadListStackTraces(), > > Yes we need to test the special cases introduced by your changes - totally agree - and OneGetThreadListStackTraces.java is a good test for that. > >> and also I expect it would not be run with JFR. (it is not described @run) > > The arguments to run with JFR (or a bunch of other things) can be passed to the jtreg test harness to be applied to all tests. > >> Of course we can check GetThreadListStackTraces() with main thread, but it is not the test for direct handshake for other thread. > > Right - that test already exists as per the above. > > Thanks, > David > >> >> Thanks, >> >> Yasumasa >> >> >>> Thanks, >>> David >>> ----- >>> >>> On 6/07/2020 11:29 pm, Yasumasa Suenaga wrote: >>>> Hi Serguei, >>>> >>>> Thanks for your comment! >>>> >>>> I think C++ is more simple to implement the test agent as you said. >>>> So I implement it in C++ in new webrev. Could you review again? >>>> >>>> ?? http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.06/ >>>> >>>> Also I refactored libGetThreadListStackTraces.cpp, and I've kept exception check after IsSameObject(). >>>> >>>> >>>> Thanks, >>>> >>>> Yasumasa >>>> >>>> >>>> On 2020/07/06 16:32, serguei.spitsyn at oracle.com wrote: >>>>> Hi Yasumasa, >>>>> >>>>> Thank you for the update. >>>>> I think, a pending exception after IsSameObject needs to be checked. >>>>> >>>>> The checkStackInfo() needs one more refactoring as I've already suggested. >>>>> The body of the loop at L68-L78 should be converted to a function check_frame_info. >>>>> The si1->frame_buffer[i] and si2->frame_buffer[i] will be passed as fi1 and fi2. >>>>> The index can be passed as well. >>>>> I'm still suggesting to simplify the local exception_msg to something shorter like err_msg or exc_msg. >>>>> >>>>> I'm not sure using fatal is right here: >>>>> >>>>> This fragment looks strange: >>>>> >>>>> ? 152???? if ((*env)->IsSameObject(env, stack_info[i].thread, thread)) { >>>>> ? 153?????? target_info = &stack_info[i]; >>>>> ? 154?????? break; >>>>> ? 155???? } else if ((*env)->ExceptionOccurred(env)) { >>>>> ? 156?????? (*env)->ExceptionDescribe(env); >>>>> ? 157?????? (*env)->FatalError(env, __FILE__); >>>>> ? 158???? } >>>>> >>>>> I expected it to be: >>>>> >>>>> ??? jboolean same = (*env)->IsSameObject(env, stack_info[i].thread, thread); >>>>> ??? if ((*env)->ExceptionOccurred(env)) { >>>>> ????? (*env)->ExceptionDescribe(env); >>>>> ????? (*env)->FatalError(env, __FILE__); >>>>> ??? } >>>>> ??? if (same) { >>>>> ????? target_info = &stack_info[i]; >>>>> ????? break; >>>>> ??? } >>>>> >>>>> Would it better to port this agent to C++ to simplify this code nicer? >>>>> >>>>> Thanks, >>>>> Serguei >>>>> >>>>> >>>>> On 7/5/20 06:13, Yasumasa Suenaga wrote: >>>>>> Hi Serguei, >>>>>> >>>>>> Thanks for your comment! >>>>>> I refactored testcase. Could you review again? >>>>>> >>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.05/ >>>>>> >>>>>> It would check Java exception after IsSameObject() call. Does it need? >>>>>> Any exceptions are not described in JNI document[1], and JNI implementation (jni_IsSameObject()) does not seem to throw it. >>>>>> >>>>>> >>>>>> Thanks, >>>>>> >>>>>> Yasumasa >>>>>> >>>>>> >>>>>> [1] https://docs.oracle.com/en/java/javase/14/docs/specs/jni/functions.html#issameobject >>>>>> >>>>>> >>>>>> On 2020/07/05 14:46, serguei.spitsyn at oracle.com wrote: >>>>>>> Hi Yasumasa, >>>>>>> >>>>>>> >>>>>>> Okay, thanks. >>>>>>> Then I'm okay to keep the GetSingleStackTraceClosure. >>>>>>> >>>>>>> >>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libGetThreadListStackTraces.c.html >>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.c.html >>>>>>> >>>>>>> I'm not sure the function 'is_same_thread() is needed. >>>>>>> Why do not use the JNI IsSameObject instead? >>>>>>> >>>>>>> It seems to be a typo at L132 and L137. >>>>>>> You, probably. did not want to print the same information for stack_info_1[i].frame_buffer[j].XXX twice. >>>>>>> >>>>>>> The code at lines 112-142 is not readable. >>>>>>> I'd suggest to make a couple of refactoring steps. >>>>>>> >>>>>>> First step to simplify this a little bit would be with some renaming and getting rid of indexes: >>>>>>> >>>>>>> ?? 71 char err_msg[EXCEPTION_MSG_LEN] = {0}; >>>>>>> ??... >>>>>>> ??112?? /* Iterate all jvmtiStackInfo to check */ >>>>>>> ??113?? for (i = 0; i < num_threads, *exception_msg != '\0'; i++) { >>>>>>> ????????? jvmtiStackInfo *si1 = stack_info_1[i]; >>>>>>> ????????? jvmtiStackInfo *si2 = stack_info_2[i]; >>>>>>> ??114???? if (!IsSameObject(env, si1.thread, si2.thread)) { /* jvmtiStackInfo::thread */ >>>>>>> ??115?????? snprintf(err_msg, sizeof(err_msg), >>>>>>> ??116??????????????? "thread[%d] is different: stack_info_1 = %p, stack_info_2 = %p", >>>>>>> ??117??????????????? i, sinfo1.thread, sinfo2.thread); >>>>>>> ??118???? } else if (si1.state != si2.state) { /* jvmtiStackInfo::state */ >>>>>>> ??119?????? snprintf(err_msg, sizeof(err_msg), >>>>>>> ??120??????????????? "state[%d] is different: stack_info_1 = %d, stack_info_2 = %d", >>>>>>> ??121??????????????? i, si1.state, si2.state); >>>>>>> ??122???? } else if (si1.frame_count != si2.frame_count) { /* jvmtiStackInfo::frame_count */ >>>>>>> ??123?????? snprintf(err_msg, sizeof(err_msg), >>>>>>> ??124??????????????? "frame_count[%d] is different: stack_info_1 = %d, stack_info_2 = %d", >>>>>>> ??125??????????????? i, si1.frame_count, si2.frame_count); >>>>>>> ??126???? } else { >>>>>>> ??127?????? /* Iterate all jvmtiFrameInfo to check */ >>>>>>> ??128?????? for (j = 0; j < si1.frame_count; j++) { >>>>>>> ??129???????? if (si1.frame_buffer[j].method != si1.frame_buffer[j].method) { /* jvmtiFrameInfo::method */ >>>>>>> ??130?????????? snprintf(err_msg, sizeof(err_msg), >>>>>>> ??131??????????????????? "thread [%d] frame_buffer[%d].method is different: stack_info_1 = %lx, stack_info_2 = %lx", >>>>>>> ??132??????????????????? i, j, si1.frame_buffer[j].method, si2.frame_buffer[j].method); >>>>>>> ??133?????????? break; >>>>>>> ??134???????? } else if (si1.frame_buffer[j].location != si1.frame_buffer[j].location) { /* jvmtiFrameInfo::location */ >>>>>>> ??135?????????? snprintf(err_msg, sizeof(err_msg), >>>>>>> ??136??????????????????? "thread [%d] frame_buffer[%d].location is different: stack_info_1 = %ld, stack_info_2 = %ld", >>>>>>> ??137??????????????????? i, j, si1.frame_buffer[j].location, si2.frame_buffer[j].location); >>>>>>> ??138?????????? break; >>>>>>> ??139???????? } >>>>>>> ??140?????? } >>>>>>> ??141???? } >>>>>>> ??142?? } >>>>>>> >>>>>>> Another step would be to create functions that implement a body of each loop. >>>>>>> You can use the same techniques to simplify similar place (L127-L138) in the libOneGetThreadListStackTraces.c. >>>>>>> >>>>>>> Thanks, >>>>>>> Serguei >>>>>>> >>>>>>> >>>>>>> On 7/3/20 15:55, Yasumasa Suenaga wrote: >>>>>>>> Hi Serguei, >>>>>>>> >>>>>>>> I'm not an Oracle employee, so I cannot know real request(s) from your customers. >>>>>>>> However JDK-8201641 says Dynatrace has requested this enhancement. >>>>>>>> >>>>>>>> BTW I haven't heared any request from my customers about this. >>>>>>>> >>>>>>>> >>>>>>>> Thanks, >>>>>>>> >>>>>>>> Yasumasa >>>>>>>> >>>>>>>> >>>>>>>> On 2020/07/04 4:32, serguei.spitsyn at oracle.com wrote: >>>>>>>>> Hi Yasumasa, >>>>>>>>> >>>>>>>>> This difference is not that big to care about. >>>>>>>>> I feel this is really rare case and so, does not worth these complications. >>>>>>>>> Do we have a real request from customers to optimize it? >>>>>>>>> >>>>>>>>> Thanks, >>>>>>>>> Serguei >>>>>>>>> >>>>>>>>> >>>>>>>>> On 7/3/20 01:16, Yasumasa Suenaga wrote: >>>>>>>>>> Hi Serguei, >>>>>>>>>> >>>>>>>>>> Generally I agree with you, but I have concern about the difference of the result of GetStackTrace() and GetThreadListStackTraces(). >>>>>>>>>> >>>>>>>>>> ? GetStackTrace: jvmtiFrameInfo >>>>>>>>>> ? GetThreadListStackTraces: jvmtiStackInfo >>>>>>>>>> >>>>>>>>>> jvmtiStackInfo contains thread state, and it is ensured it is the state of the call stack. >>>>>>>>>> If we want to get both call stack and thread state, we need to suspend target thread, and call both GetStackTrace() and GetThreadState(). Is it ok? >>>>>>>>>> >>>>>>>>>> I was wondering if JDK-8201641 (parent ticket of this change) needed them for profiling (dynatrace?) >>>>>>>>>> If it is responsibility of JVMTI agent implementor, I remove this closure. >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> Thanks, >>>>>>>>>> >>>>>>>>>> Yasumasa >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> On 2020/07/03 16:45, serguei.spitsyn at oracle.com wrote: >>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>> >>>>>>>>>>> After some thinking I've concluded that I do not like this optimization >>>>>>>>>>> of the GetThreadListStackTraces with GetSingleStackTraceClosure. >>>>>>>>>>> >>>>>>>>>>> We may need more opinions on this but these are my points: >>>>>>>>>>> ??- it adds some complexity and ugliness >>>>>>>>>>> ??- a win is doubtful because it has to be a rare case, so that total overhead should not be high >>>>>>>>>>> ??- if it is really high for some use cases then it is up to the user >>>>>>>>>>> ??? to optimize it with using GetStackTrace instead >>>>>>>>>>> >>>>>>>>>>> In such cases with doubtful overhead I usually prefer the simplicity. >>>>>>>>>>> >>>>>>>>>>> Good examples where it makes sense to optimize are checks for target thread to be current thread. >>>>>>>>>>> In such cases there is no need to suspend the target thread, or use a VMop/HandshakeClosure. >>>>>>>>>>> For instance, please, see the Monitor functions with the check: (java_thread == calling_thread). >>>>>>>>>>> Getting information for current thread is frequently used case, e.g. to get info at an event point. >>>>>>>>>>> >>>>>>>>>>> Thanks, >>>>>>>>>>> Serguei >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> On 7/2/20 23:29, Yasumasa Suenaga wrote: >>>>>>>>>>>> Hi Dan, David, >>>>>>>>>>>> >>>>>>>>>>>> I uploaded new webrev. Could you review again? >>>>>>>>>>>> >>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/ >>>>>>>>>>>> >>>>>>>>>>>> OneGetThreadListStackTraces.java in this webrev would wait until thread state is transited to "waiting" with spin wait. >>>>>>>>>>>> CountDownLatch::await call as Dan pointed is fixed in it :) >>>>>>>>>>>> >>>>>>>>>>>> Diff from webrev.03: >>>>>>>>>>>> http://hg.openjdk.java.net/jdk/submit/rev/c9aeb7001e50 >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> Thanks, >>>>>>>>>>>> >>>>>>>>>>>> Yasumasa >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> On 2020/07/03 14:15, David Holmes wrote: >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> On 3/07/2020 2:27 pm, Yasumasa Suenaga wrote: >>>>>>>>>>>>>> On 2020/07/03 12:24, Daniel D. Daugherty wrote: >>>>>>>>>>>>>>> On 7/2/20 10:50 PM, David Holmes wrote: >>>>>>>>>>>>>>>> Sorry I'm responding here without seeing latest webrev but there is enough context I think ... >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> On 3/07/2020 9:14 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>> Hi Dan, >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Thanks for your comment! >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> On 2020/07/03 7:16, Daniel D. Daugherty wrote: >>>>>>>>>>>>>>>>>> On 7/2/20 5:19 AM, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> I upload new webrev. Could you review again? >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.03/ >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnv.cpp >>>>>>>>>>>>>>>>>> ???? L1542: ??? // Get stack trace with handshake >>>>>>>>>>>>>>>>>> ???????? nit - please add a period at the end. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> ???? L1591: *stack_info_ptr = op.stack_info(); >>>>>>>>>>>>>>>>>> ???????? The return parameter should not be touched unless the return >>>>>>>>>>>>>>>>>> ???????? code in 'err' == JVMTI_ERROR_NONE. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> ???? old L1582: ? if (err == JVMTI_ERROR_NONE) { >>>>>>>>>>>>>>>>>> ???????? Please restore this check. The return parameter should not >>>>>>>>>>>>>>>>>> ???????? be touched unless the return code in 'err' == JVMTI_ERROR_NONE. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> But op.stack_info() will return NULL if the error is not JVMTI_ERROR_NONE. Are you (Dan) concerned about someone passing in a non-null/initialized out-pointer that will be reset to NULL if there was an error? >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Actually the way we used to test this in POSIX tests is to call >>>>>>>>>>>>>>> an API with known bad parameters and the return parameter ptr >>>>>>>>>>>>>>> set to NULL. If the return parameter ptr was touched when an >>>>>>>>>>>>>>> error should have been detected on an earlier parameter, then >>>>>>>>>>>>>>> the test failed. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> ???? L1272: ? if (!jt->is_exiting() && (thread_oop != NULL)) { >>>>>>>>>>>>>>>>>> ???????? nit - extra parens around the second expression. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>>>>>> ???? old L1532: ? _result = JVMTI_ERROR_THREAD_NOT_ALIVE; >>>>>>>>>>>>>>>>>> ???????? This deletion of the _result field threw me for a minute and then >>>>>>>>>>>>>>>>>> ???? ? ? I figured out that the field is init to JVMTI_ERROR_THREAD_NOT_ALIVE >>>>>>>>>>>>>>>>>> ???????? in the constructor. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> ???? L1553: ? if (!jt->is_exiting() && (jt->threadObj() != NULL)) { >>>>>>>>>>>>>>>>>> ???????? nit - extra parens around the second expression. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>>>>>>>>>>>>>> ???? No comments. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> src/hotspot/share/runtime/vmOperations.hpp >>>>>>>>>>>>>>>>>> ???? No comments. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/GetThreadListStackTraces.java >>>>>>>>>>>>>>>>>> ???? No comments. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/OneGetThreadListStackTraces.java >>>>>>>>>>>>>>>>>> ???? L64: ??????? startSignal.countDown(); >>>>>>>>>>>>>>>>>> ???????? I was expecting this to be a call to await() instead of >>>>>>>>>>>>>>>>>> ???????? countDown(). What am I missing here? >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> ???????? I think this test might be passing by accident right now, but... >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Main thread (which call JVMTI functions to test) should wait until test thread is ready. >>>>>>>>>>>>>>>>> So main thread would wait startSignal, and test thread would count down. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> No! >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> The test thread that previously called obj.wait() now calls latch.await(). >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> The main thread that previously called obj.notify() now calls latch.countDown(). >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> The main thread continues to spin until it sees the target is WAITING before proceeding with the test. >>>>>>>>>>>>>> >>>>>>>>>>>>>> If I add spin wait to wait until transit target thread state is WAITING (as following), we don't need to call SuspendThread(). >>>>>>>>>>>>>> Which is better? >>>>>>>>>>>>> >>>>>>>>>>>>> The original spin-wait loop checking for? WAITING is better because it is the only guarantee that the target thread is blocked where you need it to be. suspending the thread is racy as you don't know exactly where the suspend will hit. >>>>>>>>>>>>> >>>>>>>>>>>>> Thanks, >>>>>>>>>>>>> David >>>>>>>>>>>>> ----- >>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> ``` >>>>>>>>>>>>>> /* Wait until the thread state transits to "waiting" */ >>>>>>>>>>>>>> while (th.getState() != Thread.State.WAITING) { >>>>>>>>>>>>>> ???? Thread.onSpinWait(); >>>>>>>>>>>>>> } >>>>>>>>>>>>>> ``` >>>>>>>>>>>>>> >>>>>>>>>>>>>> For simplify, spin wait is prefer to OneGetThreadListStackTraces.java in webrev.03. >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>> >>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>>> Here's the flow as I see it: >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> main thread >>>>>>>>>>>>>>> ?? - start worker thread >>>>>>>>>>>>>>> ?? - startSignal.await() >>>>>>>>>>>>>>> ???? - main is now blocked >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> worker thread >>>>>>>>>>>>>>> ?? - startSignal.countDown() >>>>>>>>>>>>>>> ???? - main is now unblocked >>>>>>>>>>>>>>> ?? - stopSignal.await() >>>>>>>>>>>>>>> ???? - worker is now blocked >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> main thread >>>>>>>>>>>>>>> ?? - checkCallStacks(th) >>>>>>>>>>>>>>> ?? - stopSignal.countDown() >>>>>>>>>>>>>>> ???? - worker is now unblocked >>>>>>>>>>>>>>> ?? - th.join >>>>>>>>>>>>>>> ???? - main is now blocked >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> worker thread >>>>>>>>>>>>>>> ?? - runs off the end of run() >>>>>>>>>>>>>>> ???? - main is now unblocked >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> main thread >>>>>>>>>>>>>>> ?? - run off the end of main() >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libGetThreadListStackTraces.c >>>>>>>>>>>>>>>>>> ???? L92: ? jthreads = (jthread *)malloc(sizeof(jthread) * num_threads); >>>>>>>>>>>>>>>>>> ???????? You don't check for malloc() failure. >>>>>>>>>>>>>>>>>> ???????? 'jthreads' is allocated but never freed. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.c >>>>>>>>>>>>>>>>>> ???? L91: ? result = (*jvmti)->SuspendThread(jvmti, thread); >>>>>>>>>>>>>>>>>> ???????? Why are you suspending the thread? GetAllStackTraces() and >>>>>>>>>>>>>>>>>> ???????? GetThreadListStackTraces() do not require the target thread(s) >>>>>>>>>>>>>>>>>> ???????? to be suspend. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> ???????? If you decide not to SuspendThread, then you don't need the >>>>>>>>>>>>>>>>>> ???????? AddCapabilities or the ResumeThread calls. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Test thread might not be entered following code (stopSignal.await()). We might see deferent call stack between GetAllStackTraces() and GetThreadListStackTraces(). We cannot control to freeze call stack of test thread in Java code. >>>>>>>>>>>>>>>>> (I didn't use SuspendThread() at first, but I saw some errors which causes in above.) >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> So we need to call SuspendThread() to ensure we can see same call stack. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> If you are checking that the thread is in state WAITING then it cannot escape from that state and you can sample the stack multiple times from any API and get the same result. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> I suspect the errors you saw were from the apparent incorrect use of the CountDownLatch. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> With the flow outlined above, the worker thread should be >>>>>>>>>>>>>>> nicely blocked in stopSignal.await() when stuff is sampled. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Dan >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Cheers, >>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Dan >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> On 2020/07/02 15:05, David Holmes wrote: >>>>>>>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> On 1/07/2020 11:53 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>> Hi, >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> I uploaded new webrev. Could review again? >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.02/ >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Updates look fine - thanks. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> One minor nit: >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> 1274 _collector.allocate_and_fill_stacks(1); >>>>>>>>>>>>>>>>>>>> 1275 _collector.set_result(JVMTI_ERROR_NONE); >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> In the other places where you use _collector you rely on result being initialized to JVMTI_ERROR_NONE, rather than setting it directly after allocate_and_fill_stacks(). >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Fixed. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> ? 820 assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>>>>>>>>>>>>>> ? 821 java_thread->is_thread_fully_suspended(false, &debug_bits) || >>>>>>>>>>>>>>>>>>>>>>>>>> ? 822 current_thread == java_thread->active_handshaker(), >>>>>>>>>>>>>>>>>>>>>>>>>> ? 823????????? "at safepoint / handshake or target thread is suspended"); >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> I don't think the suspension check is necessary, as even if the target is suspended we must still be at a safepoint or in a handshake with it. Makes me wonder if we used to allow a racy stacktrace operation on a suspended thread, assuming it would remain suspended? >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> This function (JvmtiEnvBase::get_stack_trace()) can be called to get own stack trace. For example, we can call GetStackTrace() for current thread at JVMTI event. >>>>>>>>>>>>>>>>>>>>> So I changed assert as below: >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>> ??820?? assert(current_thread == java_thread || >>>>>>>>>>>>>>>>>>>>> ??821 SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>>>>>>>>> ??822????????? current_thread == java_thread->active_handshaker(), >>>>>>>>>>>>>>>>>>>>> ??823????????? "call by myself / at safepoint / at handshake"); >>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Yep good catch. I hope current tests caught that. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> They would be tested in vmTestbase/nsk/jvmti/GetStackTrace/getstacktr001/ (own call stacks), and getstacktr003 (call stacks in other thread). >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Speaking of tests ... >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> In the native code I think you need to check the success of all JNI methods that can throw exceptions - otherwise I believe the tests may trigger warnings if -Xcheck:jni is used with them. See for example: >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/libHeapMonitorTest.cpp >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> I updated testcases to check JNI and JVMTI function calls. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> In the Java code the target thread: >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> ?? 45???? public void run() { >>>>>>>>>>>>>>>>>>>> ?? 46?????? try { >>>>>>>>>>>>>>>>>>>> ?? 47?????????? synchronized (lock) { >>>>>>>>>>>>>>>>>>>> ?? 48?????????????? lock.wait(); >>>>>>>>>>>>>>>>>>>> ?? 49 System.out.println("OK"); >>>>>>>>>>>>>>>>>>>> ?? 50?????????? } >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> is potentially susceptible to spurious wakeups. Using a CountDownLatch would be robust. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Fixed. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> On 2020/07/01 8:48, David Holmes wrote: >>>>>>>>>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> On 1/07/2020 9:05 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> 1271 ResourceMark rm; >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> IIUC at this point the _calling_thread is the current thread, so we can use: >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> If so, we can call make_local() in L1272 without JavaThread (or we can pass current thread to make_local()). Is it right? >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>>>>>>>>>>>>>>> 1272 _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, thread_oop), >>>>>>>>>>>>>>>>>>>>>>> 1273 jt, thread_oop); >>>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Sorry I got confused, _calling_thread may not be the current thread as we could be executing the handshake in the target thread itself. So the ResourceMark is correct as-is (implicitly for current thread). >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> The argument to fill_frames will be used in the jvmtiStackInfo and passed back to the _calling_thread, so it must be created via make_local(_calling_thread, ...) as you presently have. >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> On 2020/07/01 7:05, David Holmes wrote: >>>>>>>>>>>>>>>>>>>>>>>> On 1/07/2020 12:17 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> Thank you for reviewing! I will update new webrev tomorrow. >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> 466 class MultipleStackTracesCollector : public StackObj { >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> ? 498 class VM_GetAllStackTraces : public VM_Operation { >>>>>>>>>>>>>>>>>>>>>>>>>> ? 499 private: >>>>>>>>>>>>>>>>>>>>>>>>>> ? 500?? JavaThread *_calling_thread; >>>>>>>>>>>>>>>>>>>>>>>>>> ? 501?? jint _final_thread_count; >>>>>>>>>>>>>>>>>>>>>>>>>> ? 502 MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> You can't have a StackObj as a member of another class like that as it may not be on the stack. I think MultipleStackTracesCollector should not extend any allocation class, and should always be embedded directly in another class. >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> I'm not sure what does mean "embedded". >>>>>>>>>>>>>>>>>>>>>>>>> Is it ok as below? >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>>>>> class MultipleStackTracesCollector { >>>>>>>>>>>>>>>>>>>>>>>>> ??? : >>>>>>>>>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> class GetAllStackTraces : public VM_Operation { >>>>>>>>>>>>>>>>>>>>>>>>> ?? private: >>>>>>>>>>>>>>>>>>>>>>>>> MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Yes that I what I meant. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> On 2020/06/30 22:22, David Holmes wrote: >>>>>>>>>>>>>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> On 30/06/2020 10:05 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>>>>>>> Hi David, Serguei, >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> I updated webrev for 8242428. Could you review again? >>>>>>>>>>>>>>>>>>>>>>>>>>> This change migrate to use direct handshake for GetStackTrace() and GetThreadListStackTraces() (when thread_count == 1). >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.01/ >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> This looks really good now! I only have a few nits below. There is one thing I don't like about it but it requires a change to the main Handshake logic to address - in JvmtiEnv::GetThreadListStackTraces you have to create a ThreadsListHandle to convert the jthread to a JavaThread, but then the Handshake::execute_direct creates another ThreadsListHandle internally. That's a waste. I will discuss with Robbin and file a RFE to have an overload of execute_direct that takes an existing TLH. Actually it's worse than that because we have another TLH in use at the entry point for the JVMTI functions, so I think there may be some scope for simplifying the use of TLH instances - future RFE. >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> ??451 GetStackTraceClosure(JvmtiEnv *env, jint start_depth, jint max_count, >>>>>>>>>>>>>>>>>>>>>>>>>> ??452 jvmtiFrameInfo* frame_buffer, jint* count_ptr) >>>>>>>>>>>>>>>>>>>>>>>>>> ??453???? : HandshakeClosure("GetStackTrace"), >>>>>>>>>>>>>>>>>>>>>>>>>> ??454?????? _env(env), _start_depth(start_depth), _max_count(max_count), >>>>>>>>>>>>>>>>>>>>>>>>>> ??455 _frame_buffer(frame_buffer), _count_ptr(count_ptr), >>>>>>>>>>>>>>>>>>>>>>>>>> ??456 _result(JVMTI_ERROR_THREAD_NOT_ALIVE) { >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> Nit: can you do one initializer per line please. >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> This looks wrong: >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> 466 class MultipleStackTracesCollector : public StackObj { >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> ??498 class VM_GetAllStackTraces : public VM_Operation { >>>>>>>>>>>>>>>>>>>>>>>>>> ??499 private: >>>>>>>>>>>>>>>>>>>>>>>>>> ??500?? JavaThread *_calling_thread; >>>>>>>>>>>>>>>>>>>>>>>>>> ??501?? jint _final_thread_count; >>>>>>>>>>>>>>>>>>>>>>>>>> ??502 MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> You can't have a StackObj as a member of another class like that as it may not be on the stack. I think MultipleStackTracesCollector should not extend any allocation class, and should always be embedded directly in another class. >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> 481 MultipleStackTracesCollector(JvmtiEnv *env, jint max_frame_count) { >>>>>>>>>>>>>>>>>>>>>>>>>> ??482???? _env = env; >>>>>>>>>>>>>>>>>>>>>>>>>> ??483???? _max_frame_count = max_frame_count; >>>>>>>>>>>>>>>>>>>>>>>>>> ??484 _frame_count_total = 0; >>>>>>>>>>>>>>>>>>>>>>>>>> ??485???? _head = NULL; >>>>>>>>>>>>>>>>>>>>>>>>>> ??486???? _stack_info = NULL; >>>>>>>>>>>>>>>>>>>>>>>>>> ??487???? _result = JVMTI_ERROR_NONE; >>>>>>>>>>>>>>>>>>>>>>>>>> ??488?? } >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> As you are touching this can you change it to use an initializer list as you did for the HandshakeClosure, and please keep one item per line. >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> ??820 assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>>>>>>>>>>>>>> ??821 java_thread->is_thread_fully_suspended(false, &debug_bits) || >>>>>>>>>>>>>>>>>>>>>>>>>> ??822 current_thread == java_thread->active_handshaker(), >>>>>>>>>>>>>>>>>>>>>>>>>> ??823????????? "at safepoint / handshake or target thread is suspended"); >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> I don't think the suspension check is necessary, as even if the target is suspended we must still be at a safepoint or in a handshake with it. Makes me wonder if we used to allow a racy stacktrace operation on a suspended thread, assuming it would remain suspended? >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> 1268?? oop thread_oop = jt->threadObj(); >>>>>>>>>>>>>>>>>>>>>>>>>> 1269 >>>>>>>>>>>>>>>>>>>>>>>>>> 1270?? if (!jt->is_exiting() && (jt->threadObj() != NULL)) { >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> You can use thread_oop in line 1270. >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> 1272 _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, thread_oop), >>>>>>>>>>>>>>>>>>>>>>>>>> 1273 jt, thread_oop); >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> It is frustrating that this entire call chain started with a jthread reference, which we converted to a JavaThread, only to eventually need to convert it back to a jthread! I think there is some scope for simplification here but not as part of this change. >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> IIUC at this point the _calling_thread is the current thread, so we can use: >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> Please add @bug lines to the tests. >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> I'm still pondering the test logic but wanted to send this now. >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>>>>>>>>>>>> VM_GetThreadListStackTrace (for GetThreadListStackTraces) and VM_GetAllStackTraces (for GetAllStackTraces) have inherited VM_GetMultipleStackTraces VM operation which provides the feature to generate jvmtiStackInfo. I modified VM_GetMultipleStackTraces to a normal C++ class to share with HandshakeClosure for GetThreadListStackTraces (GetSingleStackTraceClosure). >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> Also I added new testcases which test GetThreadListStackTraces() with thread_count == 1 and with all threads. >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> This change has been tested in serviceability/jvmti serviceability/jdwp vmTestbase/nsk/jvmti vmTestbase/nsk/jdi vmTestbase/nsk/jdwp. >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> On 2020/06/24 15:50, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>>>>>>>> Hi all, >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> Please review this change: >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> ?? JBS: https://bugs.openjdk.java.net/browse/JDK-8242428 >>>>>>>>>>>>>>>>>>>>>>>>>>>> ?? webrev: http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.00/ >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> This change replace following VM operations to direct handshake. >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> ??- VM_GetFrameCount (GetFrameCount()) >>>>>>>>>>>>>>>>>>>>>>>>>>>> ??- VM_GetFrameLocation (GetFrameLocation()) >>>>>>>>>>>>>>>>>>>>>>>>>>>> ??- VM_GetThreadListStackTraces (GetThreadListStackTrace()) >>>>>>>>>>>>>>>>>>>>>>>>>>>> ??- VM_GetCurrentLocation >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> GetThreadListStackTrace() uses direct handshake if thread count == 1. In other case (thread count > 1), it would be performed as VM operation (VM_GetThreadListStackTraces). >>>>>>>>>>>>>>>>>>>>>>>>>>>> Caller of VM_GetCurrentLocation (JvmtiEnvThreadState::reset_current_location()) might be called at safepoint. So I added safepoint check in its caller. >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> This change has been tested in serviceability/jvmti serviceability/jdwp vmTestbase/nsk/jvmti vmTestbase/nsk/jdi vmTestbase/ns >>>>>>>>>>>>>>>>>>>>>>>>>>>> k/jdwp. >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> Also I tested it on submit repo, then it has execution error (mach5-one-ysuenaga-JDK-8242428-20200624-0054-12034717) due to dependency error. So I think it does not occur by this change. >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>> >>>>>>>>> >>>>>>> >>>>> From kevin.walls at oracle.com Tue Jul 7 11:09:13 2020 From: kevin.walls at oracle.com (Kevin Walls) Date: Tue, 7 Jul 2020 12:09:13 +0100 Subject: RFR(M): 8247515: OSX pc_to_symbol() lookup does not work with core files In-Reply-To: References: Message-ID: <092ef5a8-c973-e377-de91-b2002a1b8fe7@oracle.com> Hi Chris, Yes I think this looks good. Question: In nearest_symbol, do we need to initialize lowest_offset_from_sym to something impossibly high, as if it defaults to zero we never find a better/nearer result? Thanks Kevin On 07/07/2020 06:10, Chris Plummer wrote: > Hello, > > Please help review the following: > > http://cr.openjdk.java.net/~cjplummer/8247515/webrev.00/index.html > https://bugs.openjdk.java.net/browse/JDK-8247515 > > The CR contains a description of the issues being addressed. There is > also no test for this symbol lookup support yet. It will be there > after I push JDK-8247516 and? JDK-8247514, which are both blocked by > the CR. > > [1] https://bugs.openjdk.java.net/browse/JDK-8247516 > [2] https://bugs.openjdk.java.net/browse/JDK-8247514 > > thanks, > > Chris > From fairoz.matte at oracle.com Tue Jul 7 14:49:11 2020 From: fairoz.matte at oracle.com (Fairoz Matte) Date: Tue, 7 Jul 2020 07:49:11 -0700 (PDT) Subject: RFR(s): 8236042: [TESTBUG] serviceability/sa/ClhsdbCDSCore.java fails with -Xcomp -XX:TieredStopAtLevel=1 Message-ID: <2abe9fba-e958-4b34-9f92-6bb8d8478f4e@default> Hi, Please review this small test change to consider the scenario when there is no "printmdo" output JBS - https://bugs.openjdk.java.net/browse/JDK-8236042 Webrev - http://cr.openjdk.java.net/~fmatte/8236042/webrev.00/ Thanks, Fairoz From chris.plummer at oracle.com Tue Jul 7 20:17:39 2020 From: chris.plummer at oracle.com (Chris Plummer) Date: Tue, 7 Jul 2020 13:17:39 -0700 Subject: RFR(M): 8247515: OSX pc_to_symbol() lookup does not work with core files In-Reply-To: <092ef5a8-c973-e377-de91-b2002a1b8fe7@oracle.com> References: <092ef5a8-c973-e377-de91-b2002a1b8fe7@oracle.com> Message-ID: <38e1887e-a646-abc0-0b7e-53339af1d684@oracle.com> Hi Kevin, Thanks for the review. Yes, that lack of initialization of lowest_offset_from_sym is a bug. I'm real surprised the compiler didn't catch it as it will be uninitialized garbage the first time it is referenced. Fortunately usually the eventual offset is very small if not 0, so probably this never prevented a proper match. I think there's also another bug: ?415?????? uintptr_t offset_from_sym = offset - sym->offset; "offset" is the passed in offset, essentially the address of the symbol we are interested in, but given as an offset from the start of the DSO. "sym->offset" is also an offset from the start of the DSO. It could be located before or after "offset". This means the math could result in a negative number, which when converted to unsigned would be a very large positive number. This happens whenever you check a symbol that is actually located after the address you are looking up. The end result is harmless, because it just means there's no way we will match that symbol, which is what you want, but it would be good to clean this up. I think what is best is to use ptrdiff_t and initialize lowest_offset_from_sym to -1. I've updated the webrev: http://cr.openjdk.java.net/~cjplummer/8247515/webrev.01/index.html thanks, Chris On 7/7/20 4:09 AM, Kevin Walls wrote: > Hi Chris, > > Yes I think this looks good. > > Question: In nearest_symbol, do we need to initialize > lowest_offset_from_sym to something impossibly high, as if it defaults > to zero we never find a better/nearer result? > > Thanks > Kevin > > > On 07/07/2020 06:10, Chris Plummer wrote: >> Hello, >> >> Please help review the following: >> >> http://cr.openjdk.java.net/~cjplummer/8247515/webrev.00/index.html >> https://bugs.openjdk.java.net/browse/JDK-8247515 >> >> The CR contains a description of the issues being addressed. There is >> also no test for this symbol lookup support yet. It will be there >> after I push JDK-8247516 and? JDK-8247514, which are both blocked by >> the CR. >> >> [1] https://bugs.openjdk.java.net/browse/JDK-8247516 >> [2] https://bugs.openjdk.java.net/browse/JDK-8247514 >> >> thanks, >> >> Chris >> From chris.plummer at oracle.com Tue Jul 7 22:07:49 2020 From: chris.plummer at oracle.com (Chris Plummer) Date: Tue, 7 Jul 2020 15:07:49 -0700 Subject: RFR(s): 8236042: [TESTBUG] serviceability/sa/ClhsdbCDSCore.java fails with -Xcomp -XX:TieredStopAtLevel=1 In-Reply-To: <2abe9fba-e958-4b34-9f92-6bb8d8478f4e@default> References: <2abe9fba-e958-4b34-9f92-6bb8d8478f4e@default> Message-ID: <70057c31-e535-f03a-391d-d181b2ec150b@oracle.com> Hi Fairoz, Looks good, except for the missing space in "if(testJavaOpts...". thanks, Chris On 7/7/20 7:49 AM, Fairoz Matte wrote: > Hi, > > Please review this small test change to consider the scenario when there is no "printmdo" output > > JBS - https://bugs.openjdk.java.net/browse/JDK-8236042 > Webrev - http://cr.openjdk.java.net/~fmatte/8236042/webrev.00/ > > Thanks, > Fairoz From chris.plummer at oracle.com Wed Jul 8 00:32:56 2020 From: chris.plummer at oracle.com (Chris Plummer) Date: Tue, 7 Jul 2020 17:32:56 -0700 Subject: RFR(T): 8249002: New serviceability/sa/ClhsdbFindPC.java #id2 and #id3 tests are failing with ZGC Message-ID: Hello, Please help review this trivial change to problem list a couple of new SA subtests so they are not run with ZGC: diff --git a/test/hotspot/jtreg/ProblemList-zgc.txt b/test/hotspot/jtreg/ProblemList-zgc.txt --- a/test/hotspot/jtreg/ProblemList-zgc.txt +++ b/test/hotspot/jtreg/ProblemList-zgc.txt @@ -34,6 +34,8 @@ ?serviceability/sa/ClhsdbCDSJstackPrintAll.java 8220624?? generic-all ?serviceability/sa/ClhsdbFindPC.java#id0 8220624?? generic-all ?serviceability/sa/ClhsdbFindPC.java#id1 8220624?? generic-all +serviceability/sa/ClhsdbFindPC.java#id2 8220624?? generic-all +serviceability/sa/ClhsdbFindPC.java#id3 8220624?? generic-all ?serviceability/sa/ClhsdbInspect.java 8220624?? generic-all ?serviceability/sa/ClhsdbJdis.java 8220624?? generic-all ?serviceability/sa/ClhsdbJhisto.java 8220624?? generic-all thanks, Chris From chris.plummer at oracle.com Wed Jul 8 00:34:53 2020 From: chris.plummer at oracle.com (Chris Plummer) Date: Tue, 7 Jul 2020 17:34:53 -0700 Subject: RFR(T): 8249002: New serviceability/sa/ClhsdbFindPC.java #id2 and #id3 tests are failing with ZGC In-Reply-To: References: Message-ID: <6cf90b18-52b9-03f3-d62b-a6f179b1a067@oracle.com> Sorry, forgot the link to the CR: https://bugs.openjdk.java.net/browse/JDK-8249002 Chris On 7/7/20 5:32 PM, Chris Plummer wrote: > Hello, > > Please help review this trivial change to problem list a couple of new > SA subtests so they are not run with ZGC: > > diff --git a/test/hotspot/jtreg/ProblemList-zgc.txt > b/test/hotspot/jtreg/ProblemList-zgc.txt > --- a/test/hotspot/jtreg/ProblemList-zgc.txt > +++ b/test/hotspot/jtreg/ProblemList-zgc.txt > @@ -34,6 +34,8 @@ > ?serviceability/sa/ClhsdbCDSJstackPrintAll.java 8220624 generic-all > ?serviceability/sa/ClhsdbFindPC.java#id0 8220624?? generic-all > ?serviceability/sa/ClhsdbFindPC.java#id1 8220624?? generic-all > +serviceability/sa/ClhsdbFindPC.java#id2 8220624?? generic-all > +serviceability/sa/ClhsdbFindPC.java#id3 8220624?? generic-all > ?serviceability/sa/ClhsdbInspect.java 8220624?? generic-all > ?serviceability/sa/ClhsdbJdis.java 8220624?? generic-all > ?serviceability/sa/ClhsdbJhisto.java 8220624?? generic-all > > thanks, > > Chris > From igor.ignatyev at oracle.com Wed Jul 8 00:38:58 2020 From: igor.ignatyev at oracle.com (Igor Ignatyev) Date: Tue, 7 Jul 2020 17:38:58 -0700 Subject: RFR(T): 8249002: New serviceability/sa/ClhsdbFindPC.java #id2 and #id3 tests are failing with ZGC In-Reply-To: <6cf90b18-52b9-03f3-d62b-a6f179b1a067@oracle.com> References: <6cf90b18-52b9-03f3-d62b-a6f179b1a067@oracle.com> Message-ID: <7B15FCA3-97F1-4A51-888F-468C57EF6B7D@oracle.com> Hi Chris, LGTM -- Igor > On Jul 7, 2020, at 5:34 PM, Chris Plummer wrote: > > Sorry, forgot the link to the CR: > > https://bugs.openjdk.java.net/browse/JDK-8249002 > > Chris > > On 7/7/20 5:32 PM, Chris Plummer wrote: >> Hello, >> >> Please help review this trivial change to problem list a couple of new SA subtests so they are not run with ZGC: >> >> diff --git a/test/hotspot/jtreg/ProblemList-zgc.txt b/test/hotspot/jtreg/ProblemList-zgc.txt >> --- a/test/hotspot/jtreg/ProblemList-zgc.txt >> +++ b/test/hotspot/jtreg/ProblemList-zgc.txt >> @@ -34,6 +34,8 @@ >> serviceability/sa/ClhsdbCDSJstackPrintAll.java 8220624 generic-all >> serviceability/sa/ClhsdbFindPC.java#id0 8220624 generic-all >> serviceability/sa/ClhsdbFindPC.java#id1 8220624 generic-all >> +serviceability/sa/ClhsdbFindPC.java#id2 8220624 generic-all >> +serviceability/sa/ClhsdbFindPC.java#id3 8220624 generic-all >> serviceability/sa/ClhsdbInspect.java 8220624 generic-all >> serviceability/sa/ClhsdbJdis.java 8220624 generic-all >> serviceability/sa/ClhsdbJhisto.java 8220624 generic-all >> >> thanks, >> >> Chris >> > > From suenaga at oss.nttdata.com Wed Jul 8 01:18:13 2020 From: suenaga at oss.nttdata.com (Yasumasa Suenaga) Date: Wed, 8 Jul 2020 10:18:13 +0900 Subject: RFR(XS): 8248878: SA: Implement simple workaround for JDK-8248876 In-Reply-To: <8e89d223-0f65-f26e-3bd7-2ca7421a940b@oracle.com> References: <39ac40d6-a738-3214-d86c-412152a631d4@oracle.com> <8e89d223-0f65-f26e-3bd7-2ca7421a940b@oracle.com> Message-ID: Hi Chris, SA would use `link_map` to decide to load address, but it does not seem to contain executable. I set breakpoint to pathmap_open() and I watched the argument of it, then I didn't see any executable (`java`) on it. Maybe current implementation is broken. I guess we can use note section in the core for deciding loading address. I can see valid address (includes executable) from `readelf -n`. Of course it might be big change for SA... Thanks, Yasumasa On 2020/07/07 15:38, Chris Plummer wrote: > Hi Yasumasa, > > Thanks for the review. I tried the following for line 188: > > ??? if ((phdr->p_type == PT_LOAD || phdr->p_type == PT_INTERP) && phdr->p_vaddr < baseaddr) { > > However, "base" still ended up being 0. I added some printfs. For the exec file there is both a PT_INTER with p_vaddr of 0x238 and a PT_LOAD with p_vaddr 0. I'm not sure which to use, but in either case that won't be the proper base when added to 0: > > ? if (add_lib_info_fd(ph, exec_file, ph->core->exec_fd, > ????????????????????? (uintptr_t)0 + find_base_address(ph->core->exec_fd, &exec_ehdr)) == NULL) { > ??? goto err; > ? } > > So maybe it's the (uintptr_t)0 that is the problem here. For shared libs instead of 0 it computes the value to add: > > ?????????????? if (lib_base_diff == ZERO_LOAD_ADDRESS ) { > ???????????????? lib_base_diff = calc_prelinked_load_address(ph, lib_fd, &elf_ehdr, link_map_addr); > ???????????????? if (lib_base_diff == INVALID_LOAD_ADDRESS) { > ?????????????????? close(lib_fd); > ?????????????????? return false; > ???????????????? } > ?????????????? } > > ?????????????? lib_base = lib_base_diff + find_base_address(lib_fd, &elf_ehdr); > > So in this case we've actually computed lib_base_diff rather than just assumed 0. > > Chris > > On 7/6/20 10:46 PM, Yasumasa Suenaga wrote: >> Hi Chris, >> >> Your change looks good. >> >> >> BTW I saw JDK-8248876. I'm not sure, but I guess we can fix this issue if we allow PT_INTERP in L118: >> >> ``` >> 105 uintptr_t find_base_address(int fd, ELF_EHDR* ehdr) { >> ????????????????? : >> 115?? // the base address of a shared object is the lowest vaddr of >> 116?? // its loadable segments (PT_LOAD) >> 117?? for (phdr = phbuf, cnt = 0; cnt < ehdr->e_phnum; cnt++, phdr++) { >> 118???? if (phdr->p_type == PT_LOAD && phdr->p_vaddr < baseaddr) { >> 119?????? baseaddr = phdr->p_vaddr; >> 120???? } >> 121?? } >> ``` >> >> /proc//maps shows top of `java` is 0x56543b9df000: >> >> 56543b9df000-56543b9e0000 r--p 00000000 08:10 55770 /usr/lib/jvm/java-11-openjdk-amd64/bin/java >> >> >> `i target` on GDB shows 0x56543b9df000 is .interp section: >> >> Local exec file: >> ??????? `/usr/lib/jvm/java-11-openjdk-amd64/bin/java', file type elf64-x86-64. >> ??????? Entry point: 0x56543b9e0330 >> ??????? 0x000056543b9df318 - 0x000056543b9df334 is .interp >> >> >> Thanks, >> >> Yasumasa >> >> >> On 2020/07/07 13:18, Chris Plummer wrote: >>> Hello, >>> >>> Please help review the following: >>> >>> http://cr.openjdk.java.net/~cjplummer/8248878/webrev.00/index.html >>> https://bugs.openjdk.java.net/browse/JDK-8248878 >>> >>> The explanation of the fix is in the CR. The parent CR, JDK-8248876 [1], explains the issue being addressed. >>> >>> There's no test for this fix yet. It requires the changes I'm making for JDK-8247514 [2], which include changes to "findpc" support and the ClhsdbFindPC.java test that trigger this issue. >>> >>> [1] https://bugs.openjdk.java.net/browse/JDK-8248876 >>> [2] https://bugs.openjdk.java.net/browse/JDK-8247514 >>> >>> thanks, >>> >>> Chris > From chris.plummer at oracle.com Wed Jul 8 02:17:23 2020 From: chris.plummer at oracle.com (Chris Plummer) Date: Tue, 7 Jul 2020 19:17:23 -0700 Subject: RFR(T): 8249002: New serviceability/sa/ClhsdbFindPC.java #id2 and #id3 tests are failing with ZGC In-Reply-To: <7B15FCA3-97F1-4A51-888F-468C57EF6B7D@oracle.com> References: <6cf90b18-52b9-03f3-d62b-a6f179b1a067@oracle.com> <7B15FCA3-97F1-4A51-888F-468C57EF6B7D@oracle.com> Message-ID: <7fc7dbd3-b86e-0afc-ca30-a52259f53476@oracle.com> Thanks! On 7/7/20 5:38 PM, Igor Ignatyev wrote: > Hi Chris, > > LGTM > > -- Igor > >> On Jul 7, 2020, at 5:34 PM, Chris Plummer wrote: >> >> Sorry, forgot the link to the CR: >> >> https://bugs.openjdk.java.net/browse/JDK-8249002 >> >> Chris >> >> On 7/7/20 5:32 PM, Chris Plummer wrote: >>> Hello, >>> >>> Please help review this trivial change to problem list a couple of new SA subtests so they are not run with ZGC: >>> >>> diff --git a/test/hotspot/jtreg/ProblemList-zgc.txt b/test/hotspot/jtreg/ProblemList-zgc.txt >>> --- a/test/hotspot/jtreg/ProblemList-zgc.txt >>> +++ b/test/hotspot/jtreg/ProblemList-zgc.txt >>> @@ -34,6 +34,8 @@ >>> serviceability/sa/ClhsdbCDSJstackPrintAll.java 8220624 generic-all >>> serviceability/sa/ClhsdbFindPC.java#id0 8220624 generic-all >>> serviceability/sa/ClhsdbFindPC.java#id1 8220624 generic-all >>> +serviceability/sa/ClhsdbFindPC.java#id2 8220624 generic-all >>> +serviceability/sa/ClhsdbFindPC.java#id3 8220624 generic-all >>> serviceability/sa/ClhsdbInspect.java 8220624 generic-all >>> serviceability/sa/ClhsdbJdis.java 8220624 generic-all >>> serviceability/sa/ClhsdbJhisto.java 8220624 generic-all >>> >>> thanks, >>> >>> Chris >>> >> From chris.plummer at oracle.com Wed Jul 8 02:29:16 2020 From: chris.plummer at oracle.com (Chris Plummer) Date: Tue, 7 Jul 2020 19:29:16 -0700 Subject: RFR(XS): 8248878: SA: Implement simple workaround for JDK-8248876 In-Reply-To: References: <39ac40d6-a738-3214-d86c-412152a631d4@oracle.com> <8e89d223-0f65-f26e-3bd7-2ca7421a940b@oracle.com> Message-ID: <6d2610d6-5ca1-8455-ddc6-d7f02b21c0d5@oracle.com> Hi Yasumasa, The executable is not opened with pathmap_open: ? if ((ph->core->exec_fd = open(exec_file, O_RDONLY)) < 0) { I think pathmap_open() is just used for libraries. thanks, Chris On 7/7/20 6:18 PM, Yasumasa Suenaga wrote: > Hi Chris, > > SA would use `link_map` to decide to load address, but it does not > seem to contain executable. > I set breakpoint to pathmap_open() and I watched the argument of it, > then I didn't see any executable (`java`) on it. > Maybe current implementation is broken. > > I guess we can use note section in the core for deciding loading address. > I can see valid address (includes executable) from `readelf -n`. > Of course it might be big change for SA... > > > Thanks, > > Yasumasa > > > On 2020/07/07 15:38, Chris Plummer wrote: >> Hi Yasumasa, >> >> Thanks for the review. I tried the following for line 188: >> >> ???? if ((phdr->p_type == PT_LOAD || phdr->p_type == PT_INTERP) && >> phdr->p_vaddr < baseaddr) { >> >> However, "base" still ended up being 0. I added some printfs. For the >> exec file there is both a PT_INTER with p_vaddr of 0x238 and a >> PT_LOAD with p_vaddr 0. I'm not sure which to use, but in either case >> that won't be the proper base when added to 0: >> >> ?? if (add_lib_info_fd(ph, exec_file, ph->core->exec_fd, >> ?????????????????????? (uintptr_t)0 + >> find_base_address(ph->core->exec_fd, &exec_ehdr)) == NULL) { >> ???? goto err; >> ?? } >> >> So maybe it's the (uintptr_t)0 that is the problem here. For shared >> libs instead of 0 it computes the value to add: >> >> ??????????????? if (lib_base_diff == ZERO_LOAD_ADDRESS ) { >> ????????????????? lib_base_diff = calc_prelinked_load_address(ph, >> lib_fd, &elf_ehdr, link_map_addr); >> ????????????????? if (lib_base_diff == INVALID_LOAD_ADDRESS) { >> ??????????????????? close(lib_fd); >> ??????????????????? return false; >> ????????????????? } >> ??????????????? } >> >> ??????????????? lib_base = lib_base_diff + find_base_address(lib_fd, >> &elf_ehdr); >> >> So in this case we've actually computed lib_base_diff rather than >> just assumed 0. >> >> Chris >> >> On 7/6/20 10:46 PM, Yasumasa Suenaga wrote: >>> Hi Chris, >>> >>> Your change looks good. >>> >>> >>> BTW I saw JDK-8248876. I'm not sure, but I guess we can fix this >>> issue if we allow PT_INTERP in L118: >>> >>> ``` >>> 105 uintptr_t find_base_address(int fd, ELF_EHDR* ehdr) { >>> ????????????????? : >>> 115?? // the base address of a shared object is the lowest vaddr of >>> 116?? // its loadable segments (PT_LOAD) >>> 117?? for (phdr = phbuf, cnt = 0; cnt < ehdr->e_phnum; cnt++, phdr++) { >>> 118???? if (phdr->p_type == PT_LOAD && phdr->p_vaddr < baseaddr) { >>> 119?????? baseaddr = phdr->p_vaddr; >>> 120???? } >>> 121?? } >>> ``` >>> >>> /proc//maps shows top of `java` is 0x56543b9df000: >>> >>> 56543b9df000-56543b9e0000 r--p 00000000 08:10 55770 >>> /usr/lib/jvm/java-11-openjdk-amd64/bin/java >>> >>> >>> `i target` on GDB shows 0x56543b9df000 is .interp section: >>> >>> Local exec file: >>> ??????? `/usr/lib/jvm/java-11-openjdk-amd64/bin/java', file type >>> elf64-x86-64. >>> ??????? Entry point: 0x56543b9e0330 >>> ??????? 0x000056543b9df318 - 0x000056543b9df334 is .interp >>> >>> >>> Thanks, >>> >>> Yasumasa >>> >>> >>> On 2020/07/07 13:18, Chris Plummer wrote: >>>> Hello, >>>> >>>> Please help review the following: >>>> >>>> http://cr.openjdk.java.net/~cjplummer/8248878/webrev.00/index.html >>>> https://bugs.openjdk.java.net/browse/JDK-8248878 >>>> >>>> The explanation of the fix is in the CR. The parent CR, JDK-8248876 >>>> [1], explains the issue being addressed. >>>> >>>> There's no test for this fix yet. It requires the changes I'm >>>> making for JDK-8247514 [2], which include changes to "findpc" >>>> support and the ClhsdbFindPC.java test that trigger this issue. >>>> >>>> [1] https://bugs.openjdk.java.net/browse/JDK-8248876 >>>> [2] https://bugs.openjdk.java.net/browse/JDK-8247514 >>>> >>>> thanks, >>>> >>>> Chris >> From fairoz.matte at oracle.com Wed Jul 8 03:47:48 2020 From: fairoz.matte at oracle.com (Fairoz Matte) Date: Tue, 7 Jul 2020 20:47:48 -0700 (PDT) Subject: RFR(s): 8236042: [TESTBUG] serviceability/sa/ClhsdbCDSCore.java fails with -Xcomp -XX:TieredStopAtLevel=1 In-Reply-To: <70057c31-e535-f03a-391d-d181b2ec150b@oracle.com> References: <2abe9fba-e958-4b34-9f92-6bb8d8478f4e@default> <70057c31-e535-f03a-391d-d181b2ec150b@oracle.com> Message-ID: <958fecdf-d7a1-4b22-835e-a75fadda0a84@default> Thanks Chris, for the review comments. I have updated the suggested change. Thanks, Fairoz > -----Original Message----- > From: Chris Plummer > Sent: Wednesday, July 8, 2020 3:38 AM > To: Fairoz Matte ; hotspot-compiler- > dev at openjdk.java.net; serviceability-dev at openjdk.java.net > Subject: Re: RFR(s): 8236042: [TESTBUG] serviceability/sa/ClhsdbCDSCore.java > fails with -Xcomp -XX:TieredStopAtLevel=1 > > Hi Fairoz, > > Looks good, except for the missing space in "if(testJavaOpts...". > > thanks, > > Chris > > On 7/7/20 7:49 AM, Fairoz Matte wrote: > > Hi, > > > > Please review this small test change to consider the scenario when there is no > "printmdo" output > > > > JBS - https://bugs.openjdk.java.net/browse/JDK-8236042 > > Webrev - http://cr.openjdk.java.net/~fmatte/8236042/webrev.00/ > > > > Thanks, > > Fairoz > From chris.plummer at oracle.com Wed Jul 8 06:20:59 2020 From: chris.plummer at oracle.com (Chris Plummer) Date: Tue, 7 Jul 2020 23:20:59 -0700 Subject: RFR(M): 8247272: SA ELF file support has never worked for 64-bit causing address to symbol name mapping to fail Message-ID: <338118cb-37ff-9d03-f22e-c96322bfd7a6@oracle.com> Hello, Please help review the following: http://cr.openjdk.java.net/~cjplummer/8247272/webrev.00/index.html https://bugs.openjdk.java.net/browse/JDK-8247272 The short story is that SA address to native symbol name mapping/lookup has never worked on 64-bit, and this is due to the java level ELF file support only supporting 32-bit. This CR fixes that, and I believe also maintains 32-bit compatibility, although I have no way of testing that. There is more to the story however on how we got here. Before going into the gory detail below, I just want to point out that currently nothing is using this support, and therefore it is technically not fixing anything, although I did verify that the fixes work (see details below). Also, I intend to remove all the java level ELF file support as part of JDK-8247516 [1]. The only reason I want to push these changes first is because I already did the work to get it working with 64-bit, and would like to get it archived before removing it in case for some reason it is revived in the future. Now for the ugly details on how we got here (and you really don't need to read this unless you have any concerns with what I stated above). It starts with the clhsdb "whatis" command, which was the only (indirect) user of this java level ELF file support. It's implementation is in javascript, so we have not had access to it ever since JDK9 module support broke the SA javascript support (and javascript support is now removed). I started the process of converting "whatis" to java. It is basically the same as the clhsdb "findpc" command, except it also checks for native symbols, which it does with the following code: ? var dso = loadObjectContainingPC(addr); ? var sym = dso.closestSymbolToPC(addr); ? return sym.name + '+' + sym.offset; Converting this to java was trivial. I just stuck support for it in the PointerFinder class, which is what findpc relies on. However, it always failed to successfully lookup a symbol. I found that DSO.closestSymbolToPC() called into the java level ELF support, and that was failing badly. After some debugging I noticed that the values read in for various ELF headers were mostly garbage. It then occurred to me that it was reading in 32-bit values that probably needed to be 64-bit. Sure enough, this code was never converted to 64-bit support. I then went and tried "whatis" on JDK8, the last version where it was available, and it failed there also with 64-bit binaries. So this is why I initially fixed it to work with 64-bit, and also how I tested it (using the modified findpc on a native symbol). But the story continues... DSO.java, and as a consequence the java ELF file support, is used by all our posix ports to do address to symbol lookups. So I figured that after fixing the java level ELF file support for 64-bit, my improved findpc would start working on OSX also. No such luck, and for obvious reasons. OSX uses mach-o files. This ELF code should never have been used for it, and of course has never worked. So I was left trying to figure out how to do OSX address to native symbol lookups. I then recalled that there was a CFrame.closestSymbolToPC() API that did address to native symbol lookups for native stack traces, and wondered how it was ever working (even on linux with the broken ELF 64-bit support). It turns out this takes a very different path to do the lookups, ending up in native code in libsaproc, where we also have ELF file support. I then converted DSO.closestSymbolToPC(addr) to use this libsaproc code instead, and it worked fine. So now there was no need for the java level ELF file support since its only user was DSO.closestSymbolToPC(addr). I should also add that this is the approach that has always been used on windows, with both CFrame.closestSymbolToPC() and DSO.closestSymbolToPC(addr) using the same libsaproc support. There is still a bit more to the story. After diverting DSO.closestSymbolToPC(addr) to the libsaproc lookup code, it still didn't work for OSX. I thought it would just work since the native BsdDebuggerLocal.lookupByName0() is implemented, and it seems to trickle down to the proper lower level APIs to find the symbol, but there were two issues. The first is that for processes there is no support for looking up all the libraries and populating the list of ps_prochandle structures that are used to do the symbol lookups. This was just never implemented (also is why PMap does not work for OSX processes). For core files the ps_prochandle structs are there, but the lookup code was badly broken. That has now been fixed by JDK-8247515 [2], currently out for review. So the end result is we'll have address to native symbol lookup for everything but OSX processes. If? your still here, thanks for listening! Chris [1] https://bugs.openjdk.java.net/browse/JDK-8247516 [2] https://bugs.openjdk.java.net/browse/JDK-8247515 From david.holmes at oracle.com Wed Jul 8 06:27:51 2020 From: david.holmes at oracle.com (David Holmes) Date: Wed, 8 Jul 2020 16:27:51 +1000 Subject: RFR: 8242428: JVMTI thread operations should use Thread-Local Handshake In-Reply-To: References: <6c263e4c-0a83-be7a-0288-ecb2de0b7cea@oss.nttdata.com> <0e359819-618f-c17b-a427-bb7e4daa2c58@oracle.com> <3f890bed-6892-e64d-b21b-ca0cbe11784e@oracle.com> <7dc1903b-6295-3864-6301-4c02aacdb971@oss.nttdata.com> <04e09eb7-9483-8f63-4bb4-01c9e814802e@oracle.com> <238a89a3-06b1-90e4-d5a4-8dc2f1ed12ab@oracle.com> <4c43bc2c-551e-d042-8fa7-b63e755888d1@oracle.com> <8c387550-a06e-6320-f453-0e898486befb@oss.nttdata.com> <19cfa2a7-f441-425d-5623-1c11c6a870b6@oss.nttdata.com> Message-ID: <237e8d26-d185-1008-6e07-5b9f36314534@oracle.com> Hi Yasumasa, On 7/07/2020 6:54 pm, Yasumasa Suenaga wrote: > Hi David, Serguei, > > Serguei, thank you for replying even though you are on vacaiton! > > I uploaded new webrev: > > ? http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.07/ > ? Diff from previous webrev: > http://hg.openjdk.java.net/jdk/submit/rev/77243b1dcbfe > > c'tor of GetSingleStackTraceClosure has jthread argument in this webrev. > Also it does not contain testcase for GetThreadListStackTraces with all > threads, and OneGetThreadListStackTraces would test main thread only. All those changes are fine in principle for me. One nit/suggestion: src/hotspot/share/prims/jvmtiEnvBase.hpp 544 jthread _java_thread; elsewhere "java_thread" refers to a JavaThread, so to avoid confusion may I suggest this member be named _jthread. I'm going to be away for the next couple of days - sorry - but will try to check email on this if I can. Thanks, David ----- > > Thanks, > > Yasumasa > > > On 2020/07/07 15:13, David Holmes wrote: >> On 7/07/2020 2:57 pm, Yasumasa Suenaga wrote: >>> Hi David, >>> >>> On 2020/07/07 11:31, David Holmes wrote: >>>> Hi Yasumasa, >>>> >>>> Hard to keep up with the changes - especially without incremental >>>> webrevs. >>> >>> Sorry, I will upload diff from previous webrev in the next. >>> >>> >>>> If GetSingleStackTraceClosure also took the jthread as a constructor >>>> arg, then you wouldn't need to recreate a JNI local handle when >>>> calling _collector.fill_frames. It's a small simplification and not >>>> essential at this stage. >>> >>> I think we should get jthread from an argument of do_thread() because >>> do_thread() would pass the thread which are stopped certainly. >>> It might be simplification if we pass _calling_thread to >>> MultipleStackTracesCollector. `jthread` is only needed to store >>> jvmtiStackInfo.thread . What do you think? >> >> I'm not quite sure what you mean. >> >> I think there is a bit of a design wart with direct handshakes in that >> do_thread takes the target JavaThread as an argument. That's useful in >> a case where you want a HandshakeClosure that can be applied to >> multiple threads, but that's not typically what is needed with direct >> handshakes - there is only a single target. With a single-target >> HandshakeClosure you can capture all the "target" information for the >> operation in the closure instance. So if the actual do_thread >> operation wants the jthread corresponding to the target thread then we >> can store that in the closure rather than recomputing it (you could >> assert it is the same but that seems overkill to me). >> >>> >>>> For the test ... I don't see how >>>> Java_GetThreadListStackTraces_checkCallStacks is a valid test. It >>>> gets the stacks of all live threads, then uses that information to >>>> use GetThreadListStackTraces to get the stack for the same set of >>>> threads through a different API. It then compares the two sets of >>>> stacks for each thread expecting them to be the same, but that need >>>> only be the case for the main thread. Other threads could >>>> potentially have a different stack (e.g. if this test is run with >>>> JFR enabled there will be additional threads found.) Further I would >>>> have expected that there already exist tests that check that, for a >>>> given thread (which may be suspended or known to be blocked) the >>>> same stack is found through the two different APIs. >>> >>> vmTestbase/nsk/jvmti/unit/GetAllStackTraces/getallstktr001 would >>> check all of threads via GetThreadListStackTraces() and >>> GetAllStackTraces(), so we might be able to remove >>> GetThreadListStackTraces.java from this webrev. >> >> Yes. The existing test only examines a set of test threads that are >> all blocked on a raw monitor. You do not need to duplicate that test. >> >>> OTOH we don't have testcase for GetThreadListStackTraces() with >>> thread_count == 1, so we need to testcase for it (it is >>> OneGetThreadListStackTraces.java) It would check whether the state of >>> target thread is "waiting" before JNI call to call >>> GetThreadListStackTraces(), >> >> Yes we need to test the special cases introduced by your changes - >> totally agree - and OneGetThreadListStackTraces.java is a good test >> for that. >> >>> and also I expect it would not be run with JFR. (it is not described >>> @run) >> >> The arguments to run with JFR (or a bunch of other things) can be >> passed to the jtreg test harness to be applied to all tests. >> >>> Of course we can check GetThreadListStackTraces() with main thread, >>> but it is not the test for direct handshake for other thread. >> >> Right - that test already exists as per the above. >> >> Thanks, >> David >> >>> >>> Thanks, >>> >>> Yasumasa >>> >>> >>>> Thanks, >>>> David >>>> ----- >>>> >>>> On 6/07/2020 11:29 pm, Yasumasa Suenaga wrote: >>>>> Hi Serguei, >>>>> >>>>> Thanks for your comment! >>>>> >>>>> I think C++ is more simple to implement the test agent as you said. >>>>> So I implement it in C++ in new webrev. Could you review again? >>>>> >>>>> ?? http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.06/ >>>>> >>>>> Also I refactored libGetThreadListStackTraces.cpp, and I've kept >>>>> exception check after IsSameObject(). >>>>> >>>>> >>>>> Thanks, >>>>> >>>>> Yasumasa >>>>> >>>>> >>>>> On 2020/07/06 16:32, serguei.spitsyn at oracle.com wrote: >>>>>> Hi Yasumasa, >>>>>> >>>>>> Thank you for the update. >>>>>> I think, a pending exception after IsSameObject needs to be checked. >>>>>> >>>>>> The checkStackInfo() needs one more refactoring as I've already >>>>>> suggested. >>>>>> The body of the loop at L68-L78 should be converted to a function >>>>>> check_frame_info. >>>>>> The si1->frame_buffer[i] and si2->frame_buffer[i] will be passed >>>>>> as fi1 and fi2. >>>>>> The index can be passed as well. >>>>>> I'm still suggesting to simplify the local exception_msg to >>>>>> something shorter like err_msg or exc_msg. >>>>>> >>>>>> I'm not sure using fatal is right here: >>>>>> >>>>>> This fragment looks strange: >>>>>> >>>>>> ? 152???? if ((*env)->IsSameObject(env, stack_info[i].thread, >>>>>> thread)) { >>>>>> ? 153?????? target_info = &stack_info[i]; >>>>>> ? 154?????? break; >>>>>> ? 155???? } else if ((*env)->ExceptionOccurred(env)) { >>>>>> ? 156?????? (*env)->ExceptionDescribe(env); >>>>>> ? 157?????? (*env)->FatalError(env, __FILE__); >>>>>> ? 158???? } >>>>>> >>>>>> I expected it to be: >>>>>> >>>>>> ??? jboolean same = (*env)->IsSameObject(env, >>>>>> stack_info[i].thread, thread); >>>>>> ??? if ((*env)->ExceptionOccurred(env)) { >>>>>> ????? (*env)->ExceptionDescribe(env); >>>>>> ????? (*env)->FatalError(env, __FILE__); >>>>>> ??? } >>>>>> ??? if (same) { >>>>>> ????? target_info = &stack_info[i]; >>>>>> ????? break; >>>>>> ??? } >>>>>> >>>>>> Would it better to port this agent to C++ to simplify this code >>>>>> nicer? >>>>>> >>>>>> Thanks, >>>>>> Serguei >>>>>> >>>>>> >>>>>> On 7/5/20 06:13, Yasumasa Suenaga wrote: >>>>>>> Hi Serguei, >>>>>>> >>>>>>> Thanks for your comment! >>>>>>> I refactored testcase. Could you review again? >>>>>>> >>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.05/ >>>>>>> >>>>>>> It would check Java exception after IsSameObject() call. Does it >>>>>>> need? >>>>>>> Any exceptions are not described in JNI document[1], and JNI >>>>>>> implementation (jni_IsSameObject()) does not seem to throw it. >>>>>>> >>>>>>> >>>>>>> Thanks, >>>>>>> >>>>>>> Yasumasa >>>>>>> >>>>>>> >>>>>>> [1] >>>>>>> https://docs.oracle.com/en/java/javase/14/docs/specs/jni/functions.html#issameobject >>>>>>> >>>>>>> >>>>>>> >>>>>>> On 2020/07/05 14:46, serguei.spitsyn at oracle.com wrote: >>>>>>>> Hi Yasumasa, >>>>>>>> >>>>>>>> >>>>>>>> Okay, thanks. >>>>>>>> Then I'm okay to keep the GetSingleStackTraceClosure. >>>>>>>> >>>>>>>> >>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libGetThreadListStackTraces.c.html >>>>>>>> >>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.c.html >>>>>>>> >>>>>>>> >>>>>>>> I'm not sure the function 'is_same_thread() is needed. >>>>>>>> Why do not use the JNI IsSameObject instead? >>>>>>>> >>>>>>>> It seems to be a typo at L132 and L137. >>>>>>>> You, probably. did not want to print the same information for >>>>>>>> stack_info_1[i].frame_buffer[j].XXX twice. >>>>>>>> >>>>>>>> The code at lines 112-142 is not readable. >>>>>>>> I'd suggest to make a couple of refactoring steps. >>>>>>>> >>>>>>>> First step to simplify this a little bit would be with some >>>>>>>> renaming and getting rid of indexes: >>>>>>>> >>>>>>>> ?? 71 char err_msg[EXCEPTION_MSG_LEN] = {0}; >>>>>>>> ??... >>>>>>>> ??112?? /* Iterate all jvmtiStackInfo to check */ >>>>>>>> ??113?? for (i = 0; i < num_threads, *exception_msg != '\0'; i++) { >>>>>>>> ????????? jvmtiStackInfo *si1 = stack_info_1[i]; >>>>>>>> ????????? jvmtiStackInfo *si2 = stack_info_2[i]; >>>>>>>> ??114???? if (!IsSameObject(env, si1.thread, si2.thread)) { /* >>>>>>>> jvmtiStackInfo::thread */ >>>>>>>> ??115?????? snprintf(err_msg, sizeof(err_msg), >>>>>>>> ??116??????????????? "thread[%d] is different: stack_info_1 = >>>>>>>> %p, stack_info_2 = %p", >>>>>>>> ??117??????????????? i, sinfo1.thread, sinfo2.thread); >>>>>>>> ??118???? } else if (si1.state != si2.state) { /* >>>>>>>> jvmtiStackInfo::state */ >>>>>>>> ??119?????? snprintf(err_msg, sizeof(err_msg), >>>>>>>> ??120??????????????? "state[%d] is different: stack_info_1 = %d, >>>>>>>> stack_info_2 = %d", >>>>>>>> ??121??????????????? i, si1.state, si2.state); >>>>>>>> ??122???? } else if (si1.frame_count != si2.frame_count) { /* >>>>>>>> jvmtiStackInfo::frame_count */ >>>>>>>> ??123?????? snprintf(err_msg, sizeof(err_msg), >>>>>>>> ??124??????????????? "frame_count[%d] is different: stack_info_1 >>>>>>>> = %d, stack_info_2 = %d", >>>>>>>> ??125??????????????? i, si1.frame_count, si2.frame_count); >>>>>>>> ??126???? } else { >>>>>>>> ??127?????? /* Iterate all jvmtiFrameInfo to check */ >>>>>>>> ??128?????? for (j = 0; j < si1.frame_count; j++) { >>>>>>>> ??129???????? if (si1.frame_buffer[j].method != >>>>>>>> si1.frame_buffer[j].method) { /* jvmtiFrameInfo::method */ >>>>>>>> ??130?????????? snprintf(err_msg, sizeof(err_msg), >>>>>>>> ??131??????????????????? "thread [%d] frame_buffer[%d].method is >>>>>>>> different: stack_info_1 = %lx, stack_info_2 = %lx", >>>>>>>> ??132??????????????????? i, j, si1.frame_buffer[j].method, >>>>>>>> si2.frame_buffer[j].method); >>>>>>>> ??133?????????? break; >>>>>>>> ??134???????? } else if (si1.frame_buffer[j].location != >>>>>>>> si1.frame_buffer[j].location) { /* jvmtiFrameInfo::location */ >>>>>>>> ??135?????????? snprintf(err_msg, sizeof(err_msg), >>>>>>>> ??136??????????????????? "thread [%d] frame_buffer[%d].location >>>>>>>> is different: stack_info_1 = %ld, stack_info_2 = %ld", >>>>>>>> ??137??????????????????? i, j, si1.frame_buffer[j].location, >>>>>>>> si2.frame_buffer[j].location); >>>>>>>> ??138?????????? break; >>>>>>>> ??139???????? } >>>>>>>> ??140?????? } >>>>>>>> ??141???? } >>>>>>>> ??142?? } >>>>>>>> >>>>>>>> Another step would be to create functions that implement a body >>>>>>>> of each loop. >>>>>>>> You can use the same techniques to simplify similar place >>>>>>>> (L127-L138) in the libOneGetThreadListStackTraces.c. >>>>>>>> >>>>>>>> Thanks, >>>>>>>> Serguei >>>>>>>> >>>>>>>> >>>>>>>> On 7/3/20 15:55, Yasumasa Suenaga wrote: >>>>>>>>> Hi Serguei, >>>>>>>>> >>>>>>>>> I'm not an Oracle employee, so I cannot know real request(s) >>>>>>>>> from your customers. >>>>>>>>> However JDK-8201641 says Dynatrace has requested this enhancement. >>>>>>>>> >>>>>>>>> BTW I haven't heared any request from my customers about this. >>>>>>>>> >>>>>>>>> >>>>>>>>> Thanks, >>>>>>>>> >>>>>>>>> Yasumasa >>>>>>>>> >>>>>>>>> >>>>>>>>> On 2020/07/04 4:32, serguei.spitsyn at oracle.com wrote: >>>>>>>>>> Hi Yasumasa, >>>>>>>>>> >>>>>>>>>> This difference is not that big to care about. >>>>>>>>>> I feel this is really rare case and so, does not worth these >>>>>>>>>> complications. >>>>>>>>>> Do we have a real request from customers to optimize it? >>>>>>>>>> >>>>>>>>>> Thanks, >>>>>>>>>> Serguei >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> On 7/3/20 01:16, Yasumasa Suenaga wrote: >>>>>>>>>>> Hi Serguei, >>>>>>>>>>> >>>>>>>>>>> Generally I agree with you, but I have concern about the >>>>>>>>>>> difference of the result of GetStackTrace() and >>>>>>>>>>> GetThreadListStackTraces(). >>>>>>>>>>> >>>>>>>>>>> ? GetStackTrace: jvmtiFrameInfo >>>>>>>>>>> ? GetThreadListStackTraces: jvmtiStackInfo >>>>>>>>>>> >>>>>>>>>>> jvmtiStackInfo contains thread state, and it is ensured it is >>>>>>>>>>> the state of the call stack. >>>>>>>>>>> If we want to get both call stack and thread state, we need >>>>>>>>>>> to suspend target thread, and call both GetStackTrace() and >>>>>>>>>>> GetThreadState(). Is it ok? >>>>>>>>>>> >>>>>>>>>>> I was wondering if JDK-8201641 (parent ticket of this change) >>>>>>>>>>> needed them for profiling (dynatrace?) >>>>>>>>>>> If it is responsibility of JVMTI agent implementor, I remove >>>>>>>>>>> this closure. >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> Thanks, >>>>>>>>>>> >>>>>>>>>>> Yasumasa >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> On 2020/07/03 16:45, serguei.spitsyn at oracle.com wrote: >>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>> >>>>>>>>>>>> After some thinking I've concluded that I do not like this >>>>>>>>>>>> optimization >>>>>>>>>>>> of the GetThreadListStackTraces with >>>>>>>>>>>> GetSingleStackTraceClosure. >>>>>>>>>>>> >>>>>>>>>>>> We may need more opinions on this but these are my points: >>>>>>>>>>>> ??- it adds some complexity and ugliness >>>>>>>>>>>> ??- a win is doubtful because it has to be a rare case, so >>>>>>>>>>>> that total overhead should not be high >>>>>>>>>>>> ??- if it is really high for some use cases then it is up to >>>>>>>>>>>> the user >>>>>>>>>>>> ??? to optimize it with using GetStackTrace instead >>>>>>>>>>>> >>>>>>>>>>>> In such cases with doubtful overhead I usually prefer the >>>>>>>>>>>> simplicity. >>>>>>>>>>>> >>>>>>>>>>>> Good examples where it makes sense to optimize are checks >>>>>>>>>>>> for target thread to be current thread. >>>>>>>>>>>> In such cases there is no need to suspend the target thread, >>>>>>>>>>>> or use a VMop/HandshakeClosure. >>>>>>>>>>>> For instance, please, see the Monitor functions with the >>>>>>>>>>>> check: (java_thread == calling_thread). >>>>>>>>>>>> Getting information for current thread is frequently used >>>>>>>>>>>> case, e.g. to get info at an event point. >>>>>>>>>>>> >>>>>>>>>>>> Thanks, >>>>>>>>>>>> Serguei >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> On 7/2/20 23:29, Yasumasa Suenaga wrote: >>>>>>>>>>>>> Hi Dan, David, >>>>>>>>>>>>> >>>>>>>>>>>>> I uploaded new webrev. Could you review again? >>>>>>>>>>>>> >>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/ >>>>>>>>>>>>> >>>>>>>>>>>>> OneGetThreadListStackTraces.java in this webrev would wait >>>>>>>>>>>>> until thread state is transited to "waiting" with spin wait. >>>>>>>>>>>>> CountDownLatch::await call as Dan pointed is fixed in it :) >>>>>>>>>>>>> >>>>>>>>>>>>> Diff from webrev.03: >>>>>>>>>>>>> http://hg.openjdk.java.net/jdk/submit/rev/c9aeb7001e50 >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> Thanks, >>>>>>>>>>>>> >>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> On 2020/07/03 14:15, David Holmes wrote: >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> On 3/07/2020 2:27 pm, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>> On 2020/07/03 12:24, Daniel D. Daugherty wrote: >>>>>>>>>>>>>>>> On 7/2/20 10:50 PM, David Holmes wrote: >>>>>>>>>>>>>>>>> Sorry I'm responding here without seeing latest webrev >>>>>>>>>>>>>>>>> but there is enough context I think ... >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> On 3/07/2020 9:14 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>> Hi Dan, >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Thanks for your comment! >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> On 2020/07/03 7:16, Daniel D. Daugherty wrote: >>>>>>>>>>>>>>>>>>> On 7/2/20 5:19 AM, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> I upload new webrev. Could you review again? >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.03/ >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnv.cpp >>>>>>>>>>>>>>>>>>> ???? L1542: ??? // Get stack trace with handshake >>>>>>>>>>>>>>>>>>> ???????? nit - please add a period at the end. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> ???? L1591: *stack_info_ptr = op.stack_info(); >>>>>>>>>>>>>>>>>>> ???????? The return parameter should not be touched >>>>>>>>>>>>>>>>>>> unless the return >>>>>>>>>>>>>>>>>>> ???????? code in 'err' == JVMTI_ERROR_NONE. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> ???? old L1582: ? if (err == JVMTI_ERROR_NONE) { >>>>>>>>>>>>>>>>>>> ???????? Please restore this check. The return >>>>>>>>>>>>>>>>>>> parameter should not >>>>>>>>>>>>>>>>>>> ???????? be touched unless the return code in 'err' >>>>>>>>>>>>>>>>>>> == JVMTI_ERROR_NONE. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> But op.stack_info() will return NULL if the error is >>>>>>>>>>>>>>>>> not JVMTI_ERROR_NONE. Are you (Dan) concerned about >>>>>>>>>>>>>>>>> someone passing in a non-null/initialized out-pointer >>>>>>>>>>>>>>>>> that will be reset to NULL if there was an error? >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Actually the way we used to test this in POSIX tests is >>>>>>>>>>>>>>>> to call >>>>>>>>>>>>>>>> an API with known bad parameters and the return >>>>>>>>>>>>>>>> parameter ptr >>>>>>>>>>>>>>>> set to NULL. If the return parameter ptr was touched >>>>>>>>>>>>>>>> when an >>>>>>>>>>>>>>>> error should have been detected on an earlier parameter, >>>>>>>>>>>>>>>> then >>>>>>>>>>>>>>>> the test failed. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> ???? L1272: ? if (!jt->is_exiting() && (thread_oop != >>>>>>>>>>>>>>>>>>> NULL)) { >>>>>>>>>>>>>>>>>>> ???????? nit - extra parens around the second >>>>>>>>>>>>>>>>>>> expression. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>>>>>>> ???? old L1532: ? _result = >>>>>>>>>>>>>>>>>>> JVMTI_ERROR_THREAD_NOT_ALIVE; >>>>>>>>>>>>>>>>>>> ???????? This deletion of the _result field threw me >>>>>>>>>>>>>>>>>>> for a minute and then >>>>>>>>>>>>>>>>>>> ???? ? ? I figured out that the field is init to >>>>>>>>>>>>>>>>>>> JVMTI_ERROR_THREAD_NOT_ALIVE >>>>>>>>>>>>>>>>>>> ???????? in the constructor. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> ???? L1553: ? if (!jt->is_exiting() && >>>>>>>>>>>>>>>>>>> (jt->threadObj() != NULL)) { >>>>>>>>>>>>>>>>>>> ???????? nit - extra parens around the second >>>>>>>>>>>>>>>>>>> expression. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>>>>>>>>>>>>>>> ???? No comments. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> src/hotspot/share/runtime/vmOperations.hpp >>>>>>>>>>>>>>>>>>> ???? No comments. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/GetThreadListStackTraces.java >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> ???? No comments. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/OneGetThreadListStackTraces.java >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> ???? L64: ??????? startSignal.countDown(); >>>>>>>>>>>>>>>>>>> ???????? I was expecting this to be a call to await() >>>>>>>>>>>>>>>>>>> instead of >>>>>>>>>>>>>>>>>>> ???????? countDown(). What am I missing here? >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> ???????? I think this test might be passing by >>>>>>>>>>>>>>>>>>> accident right now, but... >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Main thread (which call JVMTI functions to test) >>>>>>>>>>>>>>>>>> should wait until test thread is ready. >>>>>>>>>>>>>>>>>> So main thread would wait startSignal, and test thread >>>>>>>>>>>>>>>>>> would count down. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> No! >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> The test thread that previously called obj.wait() now >>>>>>>>>>>>>>>>> calls latch.await(). >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> The main thread that previously called obj.notify() now >>>>>>>>>>>>>>>>> calls latch.countDown(). >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> The main thread continues to spin until it sees the >>>>>>>>>>>>>>>>> target is WAITING before proceeding with the test. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> If I add spin wait to wait until transit target thread >>>>>>>>>>>>>>> state is WAITING (as following), we don't need to call >>>>>>>>>>>>>>> SuspendThread(). >>>>>>>>>>>>>>> Which is better? >>>>>>>>>>>>>> >>>>>>>>>>>>>> The original spin-wait loop checking for? WAITING is >>>>>>>>>>>>>> better because it is the only guarantee that the target >>>>>>>>>>>>>> thread is blocked where you need it to be. suspending the >>>>>>>>>>>>>> thread is racy as you don't know exactly where the suspend >>>>>>>>>>>>>> will hit. >>>>>>>>>>>>>> >>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>> David >>>>>>>>>>>>>> ----- >>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>> /* Wait until the thread state transits to "waiting" */ >>>>>>>>>>>>>>> while (th.getState() != Thread.State.WAITING) { >>>>>>>>>>>>>>> ???? Thread.onSpinWait(); >>>>>>>>>>>>>>> } >>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> For simplify, spin wait is prefer to >>>>>>>>>>>>>>> OneGetThreadListStackTraces.java in webrev.03. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Here's the flow as I see it: >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> main thread >>>>>>>>>>>>>>>> ?? - start worker thread >>>>>>>>>>>>>>>> ?? - startSignal.await() >>>>>>>>>>>>>>>> ???? - main is now blocked >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> worker thread >>>>>>>>>>>>>>>> ?? - startSignal.countDown() >>>>>>>>>>>>>>>> ???? - main is now unblocked >>>>>>>>>>>>>>>> ?? - stopSignal.await() >>>>>>>>>>>>>>>> ???? - worker is now blocked >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> main thread >>>>>>>>>>>>>>>> ?? - checkCallStacks(th) >>>>>>>>>>>>>>>> ?? - stopSignal.countDown() >>>>>>>>>>>>>>>> ???? - worker is now unblocked >>>>>>>>>>>>>>>> ?? - th.join >>>>>>>>>>>>>>>> ???? - main is now blocked >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> worker thread >>>>>>>>>>>>>>>> ?? - runs off the end of run() >>>>>>>>>>>>>>>> ???? - main is now unblocked >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> main thread >>>>>>>>>>>>>>>> ?? - run off the end of main() >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libGetThreadListStackTraces.c >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> ???? L92: ? jthreads = (jthread >>>>>>>>>>>>>>>>>>> *)malloc(sizeof(jthread) * num_threads); >>>>>>>>>>>>>>>>>>> ???????? You don't check for malloc() failure. >>>>>>>>>>>>>>>>>>> ???????? 'jthreads' is allocated but never freed. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.c >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> ???? L91: ? result = (*jvmti)->SuspendThread(jvmti, >>>>>>>>>>>>>>>>>>> thread); >>>>>>>>>>>>>>>>>>> ???????? Why are you suspending the thread? >>>>>>>>>>>>>>>>>>> GetAllStackTraces() and >>>>>>>>>>>>>>>>>>> ???????? GetThreadListStackTraces() do not require >>>>>>>>>>>>>>>>>>> the target thread(s) >>>>>>>>>>>>>>>>>>> ???????? to be suspend. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> ???????? If you decide not to SuspendThread, then you >>>>>>>>>>>>>>>>>>> don't need the >>>>>>>>>>>>>>>>>>> ???????? AddCapabilities or the ResumeThread calls. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Test thread might not be entered following code >>>>>>>>>>>>>>>>>> (stopSignal.await()). We might see deferent call stack >>>>>>>>>>>>>>>>>> between GetAllStackTraces() and >>>>>>>>>>>>>>>>>> GetThreadListStackTraces(). We cannot control to >>>>>>>>>>>>>>>>>> freeze call stack of test thread in Java code. >>>>>>>>>>>>>>>>>> (I didn't use SuspendThread() at first, but I saw some >>>>>>>>>>>>>>>>>> errors which causes in above.) >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> So we need to call SuspendThread() to ensure we can >>>>>>>>>>>>>>>>>> see same call stack. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> If you are checking that the thread is in state WAITING >>>>>>>>>>>>>>>>> then it cannot escape from that state and you can >>>>>>>>>>>>>>>>> sample the stack multiple times from any API and get >>>>>>>>>>>>>>>>> the same result. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> I suspect the errors you saw were from the apparent >>>>>>>>>>>>>>>>> incorrect use of the CountDownLatch. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> With the flow outlined above, the worker thread should be >>>>>>>>>>>>>>>> nicely blocked in stopSignal.await() when stuff is sampled. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Dan >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Cheers, >>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Dan >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> On 2020/07/02 15:05, David Holmes wrote: >>>>>>>>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> On 1/07/2020 11:53 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>> Hi, >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> I uploaded new webrev. Could review again? >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.02/ >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Updates look fine - thanks. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> One minor nit: >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> 1274 _collector.allocate_and_fill_stacks(1); >>>>>>>>>>>>>>>>>>>>> 1275 _collector.set_result(JVMTI_ERROR_NONE); >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> In the other places where you use _collector you >>>>>>>>>>>>>>>>>>>>> rely on result being initialized to >>>>>>>>>>>>>>>>>>>>> JVMTI_ERROR_NONE, rather than setting it directly >>>>>>>>>>>>>>>>>>>>> after allocate_and_fill_stacks(). >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Fixed. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> ? 820 >>>>>>>>>>>>>>>>>>>>>>>>>>> assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> ? 821 >>>>>>>>>>>>>>>>>>>>>>>>>>> java_thread->is_thread_fully_suspended(false, >>>>>>>>>>>>>>>>>>>>>>>>>>> &debug_bits) || >>>>>>>>>>>>>>>>>>>>>>>>>>> ? 822 current_thread == >>>>>>>>>>>>>>>>>>>>>>>>>>> java_thread->active_handshaker(), >>>>>>>>>>>>>>>>>>>>>>>>>>> ? 823????????? "at safepoint / handshake or >>>>>>>>>>>>>>>>>>>>>>>>>>> target thread is suspended"); >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> I don't think the suspension check is >>>>>>>>>>>>>>>>>>>>>>>>>>> necessary, as even if the target is suspended >>>>>>>>>>>>>>>>>>>>>>>>>>> we must still be at a safepoint or in a >>>>>>>>>>>>>>>>>>>>>>>>>>> handshake with it. Makes me wonder if we used >>>>>>>>>>>>>>>>>>>>>>>>>>> to allow a racy stacktrace operation on a >>>>>>>>>>>>>>>>>>>>>>>>>>> suspended thread, assuming it would remain >>>>>>>>>>>>>>>>>>>>>>>>>>> suspended? >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> This function (JvmtiEnvBase::get_stack_trace()) >>>>>>>>>>>>>>>>>>>>>> can be called to get own stack trace. For example, >>>>>>>>>>>>>>>>>>>>>> we can call GetStackTrace() for current thread at >>>>>>>>>>>>>>>>>>>>>> JVMTI event. >>>>>>>>>>>>>>>>>>>>>> So I changed assert as below: >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>> ??820?? assert(current_thread == java_thread || >>>>>>>>>>>>>>>>>>>>>> ??821 SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>>>>>>>>>> ??822????????? current_thread == >>>>>>>>>>>>>>>>>>>>>> java_thread->active_handshaker(), >>>>>>>>>>>>>>>>>>>>>> ??823????????? "call by myself / at safepoint / at >>>>>>>>>>>>>>>>>>>>>> handshake"); >>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Yep good catch. I hope current tests caught that. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> They would be tested in >>>>>>>>>>>>>>>>>>>> vmTestbase/nsk/jvmti/GetStackTrace/getstacktr001/ >>>>>>>>>>>>>>>>>>>> (own call stacks), and getstacktr003 (call stacks in >>>>>>>>>>>>>>>>>>>> other thread). >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Speaking of tests ... >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> In the native code I think you need to check the >>>>>>>>>>>>>>>>>>>>> success of all JNI methods that can throw >>>>>>>>>>>>>>>>>>>>> exceptions - otherwise I believe the tests may >>>>>>>>>>>>>>>>>>>>> trigger warnings if -Xcheck:jni is used with them. >>>>>>>>>>>>>>>>>>>>> See for example: >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/libHeapMonitorTest.cpp >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> I updated testcases to check JNI and JVMTI function >>>>>>>>>>>>>>>>>>>> calls. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> In the Java code the target thread: >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> ?? 45???? public void run() { >>>>>>>>>>>>>>>>>>>>> ?? 46?????? try { >>>>>>>>>>>>>>>>>>>>> ?? 47?????????? synchronized (lock) { >>>>>>>>>>>>>>>>>>>>> ?? 48?????????????? lock.wait(); >>>>>>>>>>>>>>>>>>>>> ?? 49 System.out.println("OK"); >>>>>>>>>>>>>>>>>>>>> ?? 50?????????? } >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> is potentially susceptible to spurious wakeups. >>>>>>>>>>>>>>>>>>>>> Using a CountDownLatch would be robust. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Fixed. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> On 2020/07/01 8:48, David Holmes wrote: >>>>>>>>>>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> On 1/07/2020 9:05 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> 1271 ResourceMark rm; >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> IIUC at this point the _calling_thread is the >>>>>>>>>>>>>>>>>>>>>>>>>>> current thread, so we can use: >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> If so, we can call make_local() in L1272 without >>>>>>>>>>>>>>>>>>>>>>>> JavaThread (or we can pass current thread to >>>>>>>>>>>>>>>>>>>>>>>> make_local()). Is it right? >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>>>>>>>>>>>>>>>> 1272 >>>>>>>>>>>>>>>>>>>>>>>> _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, >>>>>>>>>>>>>>>>>>>>>>>> thread_oop), >>>>>>>>>>>>>>>>>>>>>>>> 1273 jt, thread_oop); >>>>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Sorry I got confused, _calling_thread may not be >>>>>>>>>>>>>>>>>>>>>>> the current thread as we could be executing the >>>>>>>>>>>>>>>>>>>>>>> handshake in the target thread itself. So the >>>>>>>>>>>>>>>>>>>>>>> ResourceMark is correct as-is (implicitly for >>>>>>>>>>>>>>>>>>>>>>> current thread). >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> The argument to fill_frames will be used in the >>>>>>>>>>>>>>>>>>>>>>> jvmtiStackInfo and passed back to the >>>>>>>>>>>>>>>>>>>>>>> _calling_thread, so it must be created via >>>>>>>>>>>>>>>>>>>>>>> make_local(_calling_thread, ...) as you presently >>>>>>>>>>>>>>>>>>>>>>> have. >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> On 2020/07/01 7:05, David Holmes wrote: >>>>>>>>>>>>>>>>>>>>>>>>> On 1/07/2020 12:17 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> Thank you for reviewing! I will update new >>>>>>>>>>>>>>>>>>>>>>>>>> webrev tomorrow. >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> 466 class MultipleStackTracesCollector : >>>>>>>>>>>>>>>>>>>>>>>>>>> public StackObj { >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> ? 498 class VM_GetAllStackTraces : public >>>>>>>>>>>>>>>>>>>>>>>>>>> VM_Operation { >>>>>>>>>>>>>>>>>>>>>>>>>>> ? 499 private: >>>>>>>>>>>>>>>>>>>>>>>>>>> ? 500?? JavaThread *_calling_thread; >>>>>>>>>>>>>>>>>>>>>>>>>>> ? 501?? jint _final_thread_count; >>>>>>>>>>>>>>>>>>>>>>>>>>> ? 502 MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> You can't have a StackObj as a member of >>>>>>>>>>>>>>>>>>>>>>>>>>> another class like that as it may not be on >>>>>>>>>>>>>>>>>>>>>>>>>>> the stack. I think >>>>>>>>>>>>>>>>>>>>>>>>>>> MultipleStackTracesCollector should not >>>>>>>>>>>>>>>>>>>>>>>>>>> extend any allocation class, and should >>>>>>>>>>>>>>>>>>>>>>>>>>> always be embedded directly in another class. >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> I'm not sure what does mean "embedded". >>>>>>>>>>>>>>>>>>>>>>>>>> Is it ok as below? >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>>>>>> class MultipleStackTracesCollector { >>>>>>>>>>>>>>>>>>>>>>>>>> ??? : >>>>>>>>>>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> class GetAllStackTraces : public VM_Operation { >>>>>>>>>>>>>>>>>>>>>>>>>> ?? private: >>>>>>>>>>>>>>>>>>>>>>>>>> MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> Yes that I what I meant. >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> On 2020/06/30 22:22, David Holmes wrote: >>>>>>>>>>>>>>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> On 30/06/2020 10:05 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>>>>>>>> Hi David, Serguei, >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> I updated webrev for 8242428. Could you >>>>>>>>>>>>>>>>>>>>>>>>>>>> review again? >>>>>>>>>>>>>>>>>>>>>>>>>>>> This change migrate to use direct handshake >>>>>>>>>>>>>>>>>>>>>>>>>>>> for GetStackTrace() and >>>>>>>>>>>>>>>>>>>>>>>>>>>> GetThreadListStackTraces() (when >>>>>>>>>>>>>>>>>>>>>>>>>>>> thread_count == 1). >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.01/ >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> This looks really good now! I only have a few >>>>>>>>>>>>>>>>>>>>>>>>>>> nits below. There is one thing I don't like >>>>>>>>>>>>>>>>>>>>>>>>>>> about it but it requires a change to the main >>>>>>>>>>>>>>>>>>>>>>>>>>> Handshake logic to address - in >>>>>>>>>>>>>>>>>>>>>>>>>>> JvmtiEnv::GetThreadListStackTraces you have >>>>>>>>>>>>>>>>>>>>>>>>>>> to create a ThreadsListHandle to convert the >>>>>>>>>>>>>>>>>>>>>>>>>>> jthread to a JavaThread, but then the >>>>>>>>>>>>>>>>>>>>>>>>>>> Handshake::execute_direct creates another >>>>>>>>>>>>>>>>>>>>>>>>>>> ThreadsListHandle internally. That's a waste. >>>>>>>>>>>>>>>>>>>>>>>>>>> I will discuss with Robbin and file a RFE to >>>>>>>>>>>>>>>>>>>>>>>>>>> have an overload of execute_direct that takes >>>>>>>>>>>>>>>>>>>>>>>>>>> an existing TLH. Actually it's worse than >>>>>>>>>>>>>>>>>>>>>>>>>>> that because we have another TLH in use at >>>>>>>>>>>>>>>>>>>>>>>>>>> the entry point for the JVMTI functions, so I >>>>>>>>>>>>>>>>>>>>>>>>>>> think there may be some scope for simplifying >>>>>>>>>>>>>>>>>>>>>>>>>>> the use of TLH instances - future RFE. >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> ??451 GetStackTraceClosure(JvmtiEnv *env, >>>>>>>>>>>>>>>>>>>>>>>>>>> jint start_depth, jint max_count, >>>>>>>>>>>>>>>>>>>>>>>>>>> ??452 jvmtiFrameInfo* frame_buffer, jint* >>>>>>>>>>>>>>>>>>>>>>>>>>> count_ptr) >>>>>>>>>>>>>>>>>>>>>>>>>>> ??453???? : HandshakeClosure("GetStackTrace"), >>>>>>>>>>>>>>>>>>>>>>>>>>> ??454?????? _env(env), >>>>>>>>>>>>>>>>>>>>>>>>>>> _start_depth(start_depth), >>>>>>>>>>>>>>>>>>>>>>>>>>> _max_count(max_count), >>>>>>>>>>>>>>>>>>>>>>>>>>> ??455 _frame_buffer(frame_buffer), >>>>>>>>>>>>>>>>>>>>>>>>>>> _count_ptr(count_ptr), >>>>>>>>>>>>>>>>>>>>>>>>>>> ??456 _result(JVMTI_ERROR_THREAD_NOT_ALIVE) { >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> Nit: can you do one initializer per line please. >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> This looks wrong: >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> 466 class MultipleStackTracesCollector : >>>>>>>>>>>>>>>>>>>>>>>>>>> public StackObj { >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> ??498 class VM_GetAllStackTraces : public >>>>>>>>>>>>>>>>>>>>>>>>>>> VM_Operation { >>>>>>>>>>>>>>>>>>>>>>>>>>> ??499 private: >>>>>>>>>>>>>>>>>>>>>>>>>>> ??500?? JavaThread *_calling_thread; >>>>>>>>>>>>>>>>>>>>>>>>>>> ??501?? jint _final_thread_count; >>>>>>>>>>>>>>>>>>>>>>>>>>> ??502 MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> You can't have a StackObj as a member of >>>>>>>>>>>>>>>>>>>>>>>>>>> another class like that as it may not be on >>>>>>>>>>>>>>>>>>>>>>>>>>> the stack. I think >>>>>>>>>>>>>>>>>>>>>>>>>>> MultipleStackTracesCollector should not >>>>>>>>>>>>>>>>>>>>>>>>>>> extend any allocation class, and should >>>>>>>>>>>>>>>>>>>>>>>>>>> always be embedded directly in another class. >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> 481 MultipleStackTracesCollector(JvmtiEnv >>>>>>>>>>>>>>>>>>>>>>>>>>> *env, jint max_frame_count) { >>>>>>>>>>>>>>>>>>>>>>>>>>> ??482???? _env = env; >>>>>>>>>>>>>>>>>>>>>>>>>>> ??483???? _max_frame_count = max_frame_count; >>>>>>>>>>>>>>>>>>>>>>>>>>> ??484 _frame_count_total = 0; >>>>>>>>>>>>>>>>>>>>>>>>>>> ??485???? _head = NULL; >>>>>>>>>>>>>>>>>>>>>>>>>>> ??486???? _stack_info = NULL; >>>>>>>>>>>>>>>>>>>>>>>>>>> ??487???? _result = JVMTI_ERROR_NONE; >>>>>>>>>>>>>>>>>>>>>>>>>>> ??488?? } >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> As you are touching this can you change it to >>>>>>>>>>>>>>>>>>>>>>>>>>> use an initializer list as you did for the >>>>>>>>>>>>>>>>>>>>>>>>>>> HandshakeClosure, and please keep one item >>>>>>>>>>>>>>>>>>>>>>>>>>> per line. >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> ??820 >>>>>>>>>>>>>>>>>>>>>>>>>>> assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> ??821 >>>>>>>>>>>>>>>>>>>>>>>>>>> java_thread->is_thread_fully_suspended(false, >>>>>>>>>>>>>>>>>>>>>>>>>>> &debug_bits) || >>>>>>>>>>>>>>>>>>>>>>>>>>> ??822 current_thread == >>>>>>>>>>>>>>>>>>>>>>>>>>> java_thread->active_handshaker(), >>>>>>>>>>>>>>>>>>>>>>>>>>> ??823????????? "at safepoint / handshake or >>>>>>>>>>>>>>>>>>>>>>>>>>> target thread is suspended"); >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> I don't think the suspension check is >>>>>>>>>>>>>>>>>>>>>>>>>>> necessary, as even if the target is suspended >>>>>>>>>>>>>>>>>>>>>>>>>>> we must still be at a safepoint or in a >>>>>>>>>>>>>>>>>>>>>>>>>>> handshake with it. Makes me wonder if we used >>>>>>>>>>>>>>>>>>>>>>>>>>> to allow a racy stacktrace operation on a >>>>>>>>>>>>>>>>>>>>>>>>>>> suspended thread, assuming it would remain >>>>>>>>>>>>>>>>>>>>>>>>>>> suspended? >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> 1268?? oop thread_oop = jt->threadObj(); >>>>>>>>>>>>>>>>>>>>>>>>>>> 1269 >>>>>>>>>>>>>>>>>>>>>>>>>>> 1270?? if (!jt->is_exiting() && >>>>>>>>>>>>>>>>>>>>>>>>>>> (jt->threadObj() != NULL)) { >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> You can use thread_oop in line 1270. >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> 1272 >>>>>>>>>>>>>>>>>>>>>>>>>>> _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, >>>>>>>>>>>>>>>>>>>>>>>>>>> thread_oop), >>>>>>>>>>>>>>>>>>>>>>>>>>> 1273 jt, thread_oop); >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> It is frustrating that this entire call chain >>>>>>>>>>>>>>>>>>>>>>>>>>> started with a jthread reference, which we >>>>>>>>>>>>>>>>>>>>>>>>>>> converted to a JavaThread, only to eventually >>>>>>>>>>>>>>>>>>>>>>>>>>> need to convert it back to a jthread! I think >>>>>>>>>>>>>>>>>>>>>>>>>>> there is some scope for simplification here >>>>>>>>>>>>>>>>>>>>>>>>>>> but not as part of this change. >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> IIUC at this point the _calling_thread is the >>>>>>>>>>>>>>>>>>>>>>>>>>> current thread, so we can use: >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> Please add @bug lines to the tests. >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> I'm still pondering the test logic but wanted >>>>>>>>>>>>>>>>>>>>>>>>>>> to send this now. >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>>>>>>>>>>>>> VM_GetThreadListStackTrace (for >>>>>>>>>>>>>>>>>>>>>>>>>>>> GetThreadListStackTraces) and >>>>>>>>>>>>>>>>>>>>>>>>>>>> VM_GetAllStackTraces (for GetAllStackTraces) >>>>>>>>>>>>>>>>>>>>>>>>>>>> have inherited VM_GetMultipleStackTraces VM >>>>>>>>>>>>>>>>>>>>>>>>>>>> operation which provides the feature to >>>>>>>>>>>>>>>>>>>>>>>>>>>> generate jvmtiStackInfo. I modified >>>>>>>>>>>>>>>>>>>>>>>>>>>> VM_GetMultipleStackTraces to a normal C++ >>>>>>>>>>>>>>>>>>>>>>>>>>>> class to share with HandshakeClosure for >>>>>>>>>>>>>>>>>>>>>>>>>>>> GetThreadListStackTraces >>>>>>>>>>>>>>>>>>>>>>>>>>>> (GetSingleStackTraceClosure). >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> Also I added new testcases which test >>>>>>>>>>>>>>>>>>>>>>>>>>>> GetThreadListStackTraces() with thread_count >>>>>>>>>>>>>>>>>>>>>>>>>>>> == 1 and with all threads. >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> This change has been tested in >>>>>>>>>>>>>>>>>>>>>>>>>>>> serviceability/jvmti serviceability/jdwp >>>>>>>>>>>>>>>>>>>>>>>>>>>> vmTestbase/nsk/jvmti vmTestbase/nsk/jdi >>>>>>>>>>>>>>>>>>>>>>>>>>>> vmTestbase/nsk/jdwp. >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> On 2020/06/24 15:50, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>>>>>>>>> Hi all, >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> Please review this change: >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ?? JBS: >>>>>>>>>>>>>>>>>>>>>>>>>>>>> https://bugs.openjdk.java.net/browse/JDK-8242428 >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ?? webrev: >>>>>>>>>>>>>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.00/ >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> This change replace following VM operations >>>>>>>>>>>>>>>>>>>>>>>>>>>>> to direct handshake. >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??- VM_GetFrameCount (GetFrameCount()) >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??- VM_GetFrameLocation (GetFrameLocation()) >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??- VM_GetThreadListStackTraces >>>>>>>>>>>>>>>>>>>>>>>>>>>>> (GetThreadListStackTrace()) >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??- VM_GetCurrentLocation >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> GetThreadListStackTrace() uses direct >>>>>>>>>>>>>>>>>>>>>>>>>>>>> handshake if thread count == 1. In other >>>>>>>>>>>>>>>>>>>>>>>>>>>>> case (thread count > 1), it would be >>>>>>>>>>>>>>>>>>>>>>>>>>>>> performed as VM operation >>>>>>>>>>>>>>>>>>>>>>>>>>>>> (VM_GetThreadListStackTraces). >>>>>>>>>>>>>>>>>>>>>>>>>>>>> Caller of VM_GetCurrentLocation >>>>>>>>>>>>>>>>>>>>>>>>>>>>> (JvmtiEnvThreadState::reset_current_location()) >>>>>>>>>>>>>>>>>>>>>>>>>>>>> might be called at safepoint. So I added >>>>>>>>>>>>>>>>>>>>>>>>>>>>> safepoint check in its caller. >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> This change has been tested in >>>>>>>>>>>>>>>>>>>>>>>>>>>>> serviceability/jvmti serviceability/jdwp >>>>>>>>>>>>>>>>>>>>>>>>>>>>> vmTestbase/nsk/jvmti vmTestbase/nsk/jdi >>>>>>>>>>>>>>>>>>>>>>>>>>>>> vmTestbase/ns >>>>>>>>>>>>>>>>>>>>>>>>>>>>> k/jdwp. >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> Also I tested it on submit repo, then it >>>>>>>>>>>>>>>>>>>>>>>>>>>>> has execution error >>>>>>>>>>>>>>>>>>>>>>>>>>>>> (mach5-one-ysuenaga-JDK-8242428-20200624-0054-12034717) >>>>>>>>>>>>>>>>>>>>>>>>>>>>> due to dependency error. So I think it does >>>>>>>>>>>>>>>>>>>>>>>>>>>>> not occur by this change. >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>> >>>>>>>> >>>>>> From suenaga at oss.nttdata.com Wed Jul 8 08:04:09 2020 From: suenaga at oss.nttdata.com (Yasumasa Suenaga) Date: Wed, 8 Jul 2020 17:04:09 +0900 Subject: RFR: 8242428: JVMTI thread operations should use Thread-Local Handshake In-Reply-To: <237e8d26-d185-1008-6e07-5b9f36314534@oracle.com> References: <6c263e4c-0a83-be7a-0288-ecb2de0b7cea@oss.nttdata.com> <3f890bed-6892-e64d-b21b-ca0cbe11784e@oracle.com> <7dc1903b-6295-3864-6301-4c02aacdb971@oss.nttdata.com> <04e09eb7-9483-8f63-4bb4-01c9e814802e@oracle.com> <238a89a3-06b1-90e4-d5a4-8dc2f1ed12ab@oracle.com> <4c43bc2c-551e-d042-8fa7-b63e755888d1@oracle.com> <8c387550-a06e-6320-f453-0e898486befb@oss.nttdata.com> <19cfa2a7-f441-425d-5623-1c11c6a870b6@oss.nttdata.com> <237e8d26-d185-1008-6e07-5b9f36314534@oracle.com> Message-ID: Hi David, On 2020/07/08 15:27, David Holmes wrote: > Hi Yasumasa, > > On 7/07/2020 6:54 pm, Yasumasa Suenaga wrote: >> Hi David, Serguei, >> >> Serguei, thank you for replying even though you are on vacaiton! >> >> I uploaded new webrev: >> >> ?? http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.07/ >> ?? Diff from previous webrev: http://hg.openjdk.java.net/jdk/submit/rev/77243b1dcbfe >> >> c'tor of GetSingleStackTraceClosure has jthread argument in this webrev. >> Also it does not contain testcase for GetThreadListStackTraces with all threads, and OneGetThreadListStackTraces would test main thread only. > > All those changes are fine in principle for me. One nit/suggestion: > > src/hotspot/share/prims/jvmtiEnvBase.hpp > > ?544?? jthread _java_thread; > > elsewhere "java_thread" refers to a JavaThread, so to avoid confusion may I suggest this member be named _jthread. I uploaded new webrev: http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.08/ Diff from previous webrev: http://hg.openjdk.java.net/jdk/submit/rev/ca6263dbdc87 > I'm going to be away for the next couple of days - sorry - but will try to check email on this if I can. Thanks! Yasumasa > Thanks, > David > ----- > >> >> Thanks, >> >> Yasumasa >> >> >> On 2020/07/07 15:13, David Holmes wrote: >>> On 7/07/2020 2:57 pm, Yasumasa Suenaga wrote: >>>> Hi David, >>>> >>>> On 2020/07/07 11:31, David Holmes wrote: >>>>> Hi Yasumasa, >>>>> >>>>> Hard to keep up with the changes - especially without incremental webrevs. >>>> >>>> Sorry, I will upload diff from previous webrev in the next. >>>> >>>> >>>>> If GetSingleStackTraceClosure also took the jthread as a constructor arg, then you wouldn't need to recreate a JNI local handle when calling _collector.fill_frames. It's a small simplification and not essential at this stage. >>>> >>>> I think we should get jthread from an argument of do_thread() because do_thread() would pass the thread which are stopped certainly. >>>> It might be simplification if we pass _calling_thread to MultipleStackTracesCollector. `jthread` is only needed to store jvmtiStackInfo.thread . What do you think? >>> >>> I'm not quite sure what you mean. >>> >>> I think there is a bit of a design wart with direct handshakes in that do_thread takes the target JavaThread as an argument. That's useful in a case where you want a HandshakeClosure that can be applied to multiple threads, but that's not typically what is needed with direct handshakes - there is only a single target. With a single-target HandshakeClosure you can capture all the "target" information for the operation in the closure instance. So if the actual do_thread operation wants the jthread corresponding to the target thread then we can store that in the closure rather than recomputing it (you could assert it is the same but that seems overkill to me). >>> >>>> >>>>> For the test ... I don't see how Java_GetThreadListStackTraces_checkCallStacks is a valid test. It gets the stacks of all live threads, then uses that information to use GetThreadListStackTraces to get the stack for the same set of threads through a different API. It then compares the two sets of stacks for each thread expecting them to be the same, but that need only be the case for the main thread. Other threads could potentially have a different stack (e.g. if this test is run with JFR enabled there will be additional threads found.) Further I would have expected that there already exist tests that check that, for a given thread (which may be suspended or known to be blocked) the same stack is found through the two different APIs. >>>> >>>> vmTestbase/nsk/jvmti/unit/GetAllStackTraces/getallstktr001 would check all of threads via GetThreadListStackTraces() and GetAllStackTraces(), so we might be able to remove GetThreadListStackTraces.java from this webrev. >>> >>> Yes. The existing test only examines a set of test threads that are all blocked on a raw monitor. You do not need to duplicate that test. >>> >>>> OTOH we don't have testcase for GetThreadListStackTraces() with thread_count == 1, so we need to testcase for it (it is OneGetThreadListStackTraces.java) It would check whether the state of target thread is "waiting" before JNI call to call GetThreadListStackTraces(), >>> >>> Yes we need to test the special cases introduced by your changes - totally agree - and OneGetThreadListStackTraces.java is a good test for that. >>> >>>> and also I expect it would not be run with JFR. (it is not described @run) >>> >>> The arguments to run with JFR (or a bunch of other things) can be passed to the jtreg test harness to be applied to all tests. >>> >>>> Of course we can check GetThreadListStackTraces() with main thread, but it is not the test for direct handshake for other thread. >>> >>> Right - that test already exists as per the above. >>> >>> Thanks, >>> David >>> >>>> >>>> Thanks, >>>> >>>> Yasumasa >>>> >>>> >>>>> Thanks, >>>>> David >>>>> ----- >>>>> >>>>> On 6/07/2020 11:29 pm, Yasumasa Suenaga wrote: >>>>>> Hi Serguei, >>>>>> >>>>>> Thanks for your comment! >>>>>> >>>>>> I think C++ is more simple to implement the test agent as you said. >>>>>> So I implement it in C++ in new webrev. Could you review again? >>>>>> >>>>>> ?? http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.06/ >>>>>> >>>>>> Also I refactored libGetThreadListStackTraces.cpp, and I've kept exception check after IsSameObject(). >>>>>> >>>>>> >>>>>> Thanks, >>>>>> >>>>>> Yasumasa >>>>>> >>>>>> >>>>>> On 2020/07/06 16:32, serguei.spitsyn at oracle.com wrote: >>>>>>> Hi Yasumasa, >>>>>>> >>>>>>> Thank you for the update. >>>>>>> I think, a pending exception after IsSameObject needs to be checked. >>>>>>> >>>>>>> The checkStackInfo() needs one more refactoring as I've already suggested. >>>>>>> The body of the loop at L68-L78 should be converted to a function check_frame_info. >>>>>>> The si1->frame_buffer[i] and si2->frame_buffer[i] will be passed as fi1 and fi2. >>>>>>> The index can be passed as well. >>>>>>> I'm still suggesting to simplify the local exception_msg to something shorter like err_msg or exc_msg. >>>>>>> >>>>>>> I'm not sure using fatal is right here: >>>>>>> >>>>>>> This fragment looks strange: >>>>>>> >>>>>>> ? 152???? if ((*env)->IsSameObject(env, stack_info[i].thread, thread)) { >>>>>>> ? 153?????? target_info = &stack_info[i]; >>>>>>> ? 154?????? break; >>>>>>> ? 155???? } else if ((*env)->ExceptionOccurred(env)) { >>>>>>> ? 156?????? (*env)->ExceptionDescribe(env); >>>>>>> ? 157?????? (*env)->FatalError(env, __FILE__); >>>>>>> ? 158???? } >>>>>>> >>>>>>> I expected it to be: >>>>>>> >>>>>>> ??? jboolean same = (*env)->IsSameObject(env, stack_info[i].thread, thread); >>>>>>> ??? if ((*env)->ExceptionOccurred(env)) { >>>>>>> ????? (*env)->ExceptionDescribe(env); >>>>>>> ????? (*env)->FatalError(env, __FILE__); >>>>>>> ??? } >>>>>>> ??? if (same) { >>>>>>> ????? target_info = &stack_info[i]; >>>>>>> ????? break; >>>>>>> ??? } >>>>>>> >>>>>>> Would it better to port this agent to C++ to simplify this code nicer? >>>>>>> >>>>>>> Thanks, >>>>>>> Serguei >>>>>>> >>>>>>> >>>>>>> On 7/5/20 06:13, Yasumasa Suenaga wrote: >>>>>>>> Hi Serguei, >>>>>>>> >>>>>>>> Thanks for your comment! >>>>>>>> I refactored testcase. Could you review again? >>>>>>>> >>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.05/ >>>>>>>> >>>>>>>> It would check Java exception after IsSameObject() call. Does it need? >>>>>>>> Any exceptions are not described in JNI document[1], and JNI implementation (jni_IsSameObject()) does not seem to throw it. >>>>>>>> >>>>>>>> >>>>>>>> Thanks, >>>>>>>> >>>>>>>> Yasumasa >>>>>>>> >>>>>>>> >>>>>>>> [1] https://docs.oracle.com/en/java/javase/14/docs/specs/jni/functions.html#issameobject >>>>>>>> >>>>>>>> >>>>>>>> On 2020/07/05 14:46, serguei.spitsyn at oracle.com wrote: >>>>>>>>> Hi Yasumasa, >>>>>>>>> >>>>>>>>> >>>>>>>>> Okay, thanks. >>>>>>>>> Then I'm okay to keep the GetSingleStackTraceClosure. >>>>>>>>> >>>>>>>>> >>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libGetThreadListStackTraces.c.html >>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.c.html >>>>>>>>> >>>>>>>>> I'm not sure the function 'is_same_thread() is needed. >>>>>>>>> Why do not use the JNI IsSameObject instead? >>>>>>>>> >>>>>>>>> It seems to be a typo at L132 and L137. >>>>>>>>> You, probably. did not want to print the same information for stack_info_1[i].frame_buffer[j].XXX twice. >>>>>>>>> >>>>>>>>> The code at lines 112-142 is not readable. >>>>>>>>> I'd suggest to make a couple of refactoring steps. >>>>>>>>> >>>>>>>>> First step to simplify this a little bit would be with some renaming and getting rid of indexes: >>>>>>>>> >>>>>>>>> ?? 71 char err_msg[EXCEPTION_MSG_LEN] = {0}; >>>>>>>>> ??... >>>>>>>>> ??112?? /* Iterate all jvmtiStackInfo to check */ >>>>>>>>> ??113?? for (i = 0; i < num_threads, *exception_msg != '\0'; i++) { >>>>>>>>> ????????? jvmtiStackInfo *si1 = stack_info_1[i]; >>>>>>>>> ????????? jvmtiStackInfo *si2 = stack_info_2[i]; >>>>>>>>> ??114???? if (!IsSameObject(env, si1.thread, si2.thread)) { /* jvmtiStackInfo::thread */ >>>>>>>>> ??115?????? snprintf(err_msg, sizeof(err_msg), >>>>>>>>> ??116??????????????? "thread[%d] is different: stack_info_1 = %p, stack_info_2 = %p", >>>>>>>>> ??117??????????????? i, sinfo1.thread, sinfo2.thread); >>>>>>>>> ??118???? } else if (si1.state != si2.state) { /* jvmtiStackInfo::state */ >>>>>>>>> ??119?????? snprintf(err_msg, sizeof(err_msg), >>>>>>>>> ??120??????????????? "state[%d] is different: stack_info_1 = %d, stack_info_2 = %d", >>>>>>>>> ??121??????????????? i, si1.state, si2.state); >>>>>>>>> ??122???? } else if (si1.frame_count != si2.frame_count) { /* jvmtiStackInfo::frame_count */ >>>>>>>>> ??123?????? snprintf(err_msg, sizeof(err_msg), >>>>>>>>> ??124??????????????? "frame_count[%d] is different: stack_info_1 = %d, stack_info_2 = %d", >>>>>>>>> ??125??????????????? i, si1.frame_count, si2.frame_count); >>>>>>>>> ??126???? } else { >>>>>>>>> ??127?????? /* Iterate all jvmtiFrameInfo to check */ >>>>>>>>> ??128?????? for (j = 0; j < si1.frame_count; j++) { >>>>>>>>> ??129???????? if (si1.frame_buffer[j].method != si1.frame_buffer[j].method) { /* jvmtiFrameInfo::method */ >>>>>>>>> ??130?????????? snprintf(err_msg, sizeof(err_msg), >>>>>>>>> ??131??????????????????? "thread [%d] frame_buffer[%d].method is different: stack_info_1 = %lx, stack_info_2 = %lx", >>>>>>>>> ??132??????????????????? i, j, si1.frame_buffer[j].method, si2.frame_buffer[j].method); >>>>>>>>> ??133?????????? break; >>>>>>>>> ??134???????? } else if (si1.frame_buffer[j].location != si1.frame_buffer[j].location) { /* jvmtiFrameInfo::location */ >>>>>>>>> ??135?????????? snprintf(err_msg, sizeof(err_msg), >>>>>>>>> ??136??????????????????? "thread [%d] frame_buffer[%d].location is different: stack_info_1 = %ld, stack_info_2 = %ld", >>>>>>>>> ??137??????????????????? i, j, si1.frame_buffer[j].location, si2.frame_buffer[j].location); >>>>>>>>> ??138?????????? break; >>>>>>>>> ??139???????? } >>>>>>>>> ??140?????? } >>>>>>>>> ??141???? } >>>>>>>>> ??142?? } >>>>>>>>> >>>>>>>>> Another step would be to create functions that implement a body of each loop. >>>>>>>>> You can use the same techniques to simplify similar place (L127-L138) in the libOneGetThreadListStackTraces.c. >>>>>>>>> >>>>>>>>> Thanks, >>>>>>>>> Serguei >>>>>>>>> >>>>>>>>> >>>>>>>>> On 7/3/20 15:55, Yasumasa Suenaga wrote: >>>>>>>>>> Hi Serguei, >>>>>>>>>> >>>>>>>>>> I'm not an Oracle employee, so I cannot know real request(s) from your customers. >>>>>>>>>> However JDK-8201641 says Dynatrace has requested this enhancement. >>>>>>>>>> >>>>>>>>>> BTW I haven't heared any request from my customers about this. >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> Thanks, >>>>>>>>>> >>>>>>>>>> Yasumasa >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> On 2020/07/04 4:32, serguei.spitsyn at oracle.com wrote: >>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>> >>>>>>>>>>> This difference is not that big to care about. >>>>>>>>>>> I feel this is really rare case and so, does not worth these complications. >>>>>>>>>>> Do we have a real request from customers to optimize it? >>>>>>>>>>> >>>>>>>>>>> Thanks, >>>>>>>>>>> Serguei >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> On 7/3/20 01:16, Yasumasa Suenaga wrote: >>>>>>>>>>>> Hi Serguei, >>>>>>>>>>>> >>>>>>>>>>>> Generally I agree with you, but I have concern about the difference of the result of GetStackTrace() and GetThreadListStackTraces(). >>>>>>>>>>>> >>>>>>>>>>>> ? GetStackTrace: jvmtiFrameInfo >>>>>>>>>>>> ? GetThreadListStackTraces: jvmtiStackInfo >>>>>>>>>>>> >>>>>>>>>>>> jvmtiStackInfo contains thread state, and it is ensured it is the state of the call stack. >>>>>>>>>>>> If we want to get both call stack and thread state, we need to suspend target thread, and call both GetStackTrace() and GetThreadState(). Is it ok? >>>>>>>>>>>> >>>>>>>>>>>> I was wondering if JDK-8201641 (parent ticket of this change) needed them for profiling (dynatrace?) >>>>>>>>>>>> If it is responsibility of JVMTI agent implementor, I remove this closure. >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> Thanks, >>>>>>>>>>>> >>>>>>>>>>>> Yasumasa >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> On 2020/07/03 16:45, serguei.spitsyn at oracle.com wrote: >>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>> >>>>>>>>>>>>> After some thinking I've concluded that I do not like this optimization >>>>>>>>>>>>> of the GetThreadListStackTraces with GetSingleStackTraceClosure. >>>>>>>>>>>>> >>>>>>>>>>>>> We may need more opinions on this but these are my points: >>>>>>>>>>>>> ??- it adds some complexity and ugliness >>>>>>>>>>>>> ??- a win is doubtful because it has to be a rare case, so that total overhead should not be high >>>>>>>>>>>>> ??- if it is really high for some use cases then it is up to the user >>>>>>>>>>>>> ??? to optimize it with using GetStackTrace instead >>>>>>>>>>>>> >>>>>>>>>>>>> In such cases with doubtful overhead I usually prefer the simplicity. >>>>>>>>>>>>> >>>>>>>>>>>>> Good examples where it makes sense to optimize are checks for target thread to be current thread. >>>>>>>>>>>>> In such cases there is no need to suspend the target thread, or use a VMop/HandshakeClosure. >>>>>>>>>>>>> For instance, please, see the Monitor functions with the check: (java_thread == calling_thread). >>>>>>>>>>>>> Getting information for current thread is frequently used case, e.g. to get info at an event point. >>>>>>>>>>>>> >>>>>>>>>>>>> Thanks, >>>>>>>>>>>>> Serguei >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> On 7/2/20 23:29, Yasumasa Suenaga wrote: >>>>>>>>>>>>>> Hi Dan, David, >>>>>>>>>>>>>> >>>>>>>>>>>>>> I uploaded new webrev. Could you review again? >>>>>>>>>>>>>> >>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/ >>>>>>>>>>>>>> >>>>>>>>>>>>>> OneGetThreadListStackTraces.java in this webrev would wait until thread state is transited to "waiting" with spin wait. >>>>>>>>>>>>>> CountDownLatch::await call as Dan pointed is fixed in it :) >>>>>>>>>>>>>> >>>>>>>>>>>>>> Diff from webrev.03: >>>>>>>>>>>>>> http://hg.openjdk.java.net/jdk/submit/rev/c9aeb7001e50 >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>> >>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> On 2020/07/03 14:15, David Holmes wrote: >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> On 3/07/2020 2:27 pm, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>> On 2020/07/03 12:24, Daniel D. Daugherty wrote: >>>>>>>>>>>>>>>>> On 7/2/20 10:50 PM, David Holmes wrote: >>>>>>>>>>>>>>>>>> Sorry I'm responding here without seeing latest webrev but there is enough context I think ... >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> On 3/07/2020 9:14 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>> Hi Dan, >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Thanks for your comment! >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> On 2020/07/03 7:16, Daniel D. Daugherty wrote: >>>>>>>>>>>>>>>>>>>> On 7/2/20 5:19 AM, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> I upload new webrev. Could you review again? >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.03/ >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnv.cpp >>>>>>>>>>>>>>>>>>>> ???? L1542: ??? // Get stack trace with handshake >>>>>>>>>>>>>>>>>>>> ???????? nit - please add a period at the end. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> ???? L1591: *stack_info_ptr = op.stack_info(); >>>>>>>>>>>>>>>>>>>> ???????? The return parameter should not be touched unless the return >>>>>>>>>>>>>>>>>>>> ???????? code in 'err' == JVMTI_ERROR_NONE. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> ???? old L1582: ? if (err == JVMTI_ERROR_NONE) { >>>>>>>>>>>>>>>>>>>> ???????? Please restore this check. The return parameter should not >>>>>>>>>>>>>>>>>>>> ???????? be touched unless the return code in 'err' == JVMTI_ERROR_NONE. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> But op.stack_info() will return NULL if the error is not JVMTI_ERROR_NONE. Are you (Dan) concerned about someone passing in a non-null/initialized out-pointer that will be reset to NULL if there was an error? >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Actually the way we used to test this in POSIX tests is to call >>>>>>>>>>>>>>>>> an API with known bad parameters and the return parameter ptr >>>>>>>>>>>>>>>>> set to NULL. If the return parameter ptr was touched when an >>>>>>>>>>>>>>>>> error should have been detected on an earlier parameter, then >>>>>>>>>>>>>>>>> the test failed. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> ???? L1272: ? if (!jt->is_exiting() && (thread_oop != NULL)) { >>>>>>>>>>>>>>>>>>>> ???????? nit - extra parens around the second expression. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>>>>>>>> ???? old L1532: ? _result = JVMTI_ERROR_THREAD_NOT_ALIVE; >>>>>>>>>>>>>>>>>>>> ???????? This deletion of the _result field threw me for a minute and then >>>>>>>>>>>>>>>>>>>> ???? ? ? I figured out that the field is init to JVMTI_ERROR_THREAD_NOT_ALIVE >>>>>>>>>>>>>>>>>>>> ???????? in the constructor. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> ???? L1553: ? if (!jt->is_exiting() && (jt->threadObj() != NULL)) { >>>>>>>>>>>>>>>>>>>> ???????? nit - extra parens around the second expression. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>>>>>>>>>>>>>>>> ???? No comments. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> src/hotspot/share/runtime/vmOperations.hpp >>>>>>>>>>>>>>>>>>>> ???? No comments. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/GetThreadListStackTraces.java >>>>>>>>>>>>>>>>>>>> ???? No comments. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/OneGetThreadListStackTraces.java >>>>>>>>>>>>>>>>>>>> ???? L64: ??????? startSignal.countDown(); >>>>>>>>>>>>>>>>>>>> ???????? I was expecting this to be a call to await() instead of >>>>>>>>>>>>>>>>>>>> ???????? countDown(). What am I missing here? >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> ???????? I think this test might be passing by accident right now, but... >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Main thread (which call JVMTI functions to test) should wait until test thread is ready. >>>>>>>>>>>>>>>>>>> So main thread would wait startSignal, and test thread would count down. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> No! >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> The test thread that previously called obj.wait() now calls latch.await(). >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> The main thread that previously called obj.notify() now calls latch.countDown(). >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> The main thread continues to spin until it sees the target is WAITING before proceeding with the test. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> If I add spin wait to wait until transit target thread state is WAITING (as following), we don't need to call SuspendThread(). >>>>>>>>>>>>>>>> Which is better? >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> The original spin-wait loop checking for? WAITING is better because it is the only guarantee that the target thread is blocked where you need it to be. suspending the thread is racy as you don't know exactly where the suspend will hit. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>> David >>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>> /* Wait until the thread state transits to "waiting" */ >>>>>>>>>>>>>>>> while (th.getState() != Thread.State.WAITING) { >>>>>>>>>>>>>>>> ???? Thread.onSpinWait(); >>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> For simplify, spin wait is prefer to OneGetThreadListStackTraces.java in webrev.03. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Here's the flow as I see it: >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> main thread >>>>>>>>>>>>>>>>> ?? - start worker thread >>>>>>>>>>>>>>>>> ?? - startSignal.await() >>>>>>>>>>>>>>>>> ???? - main is now blocked >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> worker thread >>>>>>>>>>>>>>>>> ?? - startSignal.countDown() >>>>>>>>>>>>>>>>> ???? - main is now unblocked >>>>>>>>>>>>>>>>> ?? - stopSignal.await() >>>>>>>>>>>>>>>>> ???? - worker is now blocked >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> main thread >>>>>>>>>>>>>>>>> ?? - checkCallStacks(th) >>>>>>>>>>>>>>>>> ?? - stopSignal.countDown() >>>>>>>>>>>>>>>>> ???? - worker is now unblocked >>>>>>>>>>>>>>>>> ?? - th.join >>>>>>>>>>>>>>>>> ???? - main is now blocked >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> worker thread >>>>>>>>>>>>>>>>> ?? - runs off the end of run() >>>>>>>>>>>>>>>>> ???? - main is now unblocked >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> main thread >>>>>>>>>>>>>>>>> ?? - run off the end of main() >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libGetThreadListStackTraces.c >>>>>>>>>>>>>>>>>>>> ???? L92: ? jthreads = (jthread *)malloc(sizeof(jthread) * num_threads); >>>>>>>>>>>>>>>>>>>> ???????? You don't check for malloc() failure. >>>>>>>>>>>>>>>>>>>> ???????? 'jthreads' is allocated but never freed. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.c >>>>>>>>>>>>>>>>>>>> ???? L91: ? result = (*jvmti)->SuspendThread(jvmti, thread); >>>>>>>>>>>>>>>>>>>> ???????? Why are you suspending the thread? GetAllStackTraces() and >>>>>>>>>>>>>>>>>>>> ???????? GetThreadListStackTraces() do not require the target thread(s) >>>>>>>>>>>>>>>>>>>> ???????? to be suspend. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> ???????? If you decide not to SuspendThread, then you don't need the >>>>>>>>>>>>>>>>>>>> ???????? AddCapabilities or the ResumeThread calls. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Test thread might not be entered following code (stopSignal.await()). We might see deferent call stack between GetAllStackTraces() and GetThreadListStackTraces(). We cannot control to freeze call stack of test thread in Java code. >>>>>>>>>>>>>>>>>>> (I didn't use SuspendThread() at first, but I saw some errors which causes in above.) >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> So we need to call SuspendThread() to ensure we can see same call stack. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> If you are checking that the thread is in state WAITING then it cannot escape from that state and you can sample the stack multiple times from any API and get the same result. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> I suspect the errors you saw were from the apparent incorrect use of the CountDownLatch. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> With the flow outlined above, the worker thread should be >>>>>>>>>>>>>>>>> nicely blocked in stopSignal.await() when stuff is sampled. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Dan >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Cheers, >>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Dan >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> On 2020/07/02 15:05, David Holmes wrote: >>>>>>>>>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> On 1/07/2020 11:53 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>>> Hi, >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> I uploaded new webrev. Could review again? >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.02/ >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Updates look fine - thanks. >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> One minor nit: >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> 1274 _collector.allocate_and_fill_stacks(1); >>>>>>>>>>>>>>>>>>>>>> 1275 _collector.set_result(JVMTI_ERROR_NONE); >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> In the other places where you use _collector you rely on result being initialized to JVMTI_ERROR_NONE, rather than setting it directly after allocate_and_fill_stacks(). >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Fixed. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 820 assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 821 java_thread->is_thread_fully_suspended(false, &debug_bits) || >>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 822 current_thread == java_thread->active_handshaker(), >>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 823????????? "at safepoint / handshake or target thread is suspended"); >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> I don't think the suspension check is necessary, as even if the target is suspended we must still be at a safepoint or in a handshake with it. Makes me wonder if we used to allow a racy stacktrace operation on a suspended thread, assuming it would remain suspended? >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> This function (JvmtiEnvBase::get_stack_trace()) can be called to get own stack trace. For example, we can call GetStackTrace() for current thread at JVMTI event. >>>>>>>>>>>>>>>>>>>>>>> So I changed assert as below: >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>>> ??820?? assert(current_thread == java_thread || >>>>>>>>>>>>>>>>>>>>>>> ??821 SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>>>>>>>>>>> ??822????????? current_thread == java_thread->active_handshaker(), >>>>>>>>>>>>>>>>>>>>>>> ??823????????? "call by myself / at safepoint / at handshake"); >>>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Yep good catch. I hope current tests caught that. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> They would be tested in vmTestbase/nsk/jvmti/GetStackTrace/getstacktr001/ (own call stacks), and getstacktr003 (call stacks in other thread). >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Speaking of tests ... >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> In the native code I think you need to check the success of all JNI methods that can throw exceptions - otherwise I believe the tests may trigger warnings if -Xcheck:jni is used with them. See for example: >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/libHeapMonitorTest.cpp >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> I updated testcases to check JNI and JVMTI function calls. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> In the Java code the target thread: >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> ?? 45???? public void run() { >>>>>>>>>>>>>>>>>>>>>> ?? 46?????? try { >>>>>>>>>>>>>>>>>>>>>> ?? 47?????????? synchronized (lock) { >>>>>>>>>>>>>>>>>>>>>> ?? 48?????????????? lock.wait(); >>>>>>>>>>>>>>>>>>>>>> ?? 49 System.out.println("OK"); >>>>>>>>>>>>>>>>>>>>>> ?? 50?????????? } >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> is potentially susceptible to spurious wakeups. Using a CountDownLatch would be robust. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Fixed. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> On 2020/07/01 8:48, David Holmes wrote: >>>>>>>>>>>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> On 1/07/2020 9:05 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> 1271 ResourceMark rm; >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> IIUC at this point the _calling_thread is the current thread, so we can use: >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> If so, we can call make_local() in L1272 without JavaThread (or we can pass current thread to make_local()). Is it right? >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>>>>>>>>>>>>>>>>> 1272 _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, thread_oop), >>>>>>>>>>>>>>>>>>>>>>>>> 1273 jt, thread_oop); >>>>>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Sorry I got confused, _calling_thread may not be the current thread as we could be executing the handshake in the target thread itself. So the ResourceMark is correct as-is (implicitly for current thread). >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> The argument to fill_frames will be used in the jvmtiStackInfo and passed back to the _calling_thread, so it must be created via make_local(_calling_thread, ...) as you presently have. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> On 2020/07/01 7:05, David Holmes wrote: >>>>>>>>>>>>>>>>>>>>>>>>>> On 1/07/2020 12:17 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> Thank you for reviewing! I will update new webrev tomorrow. >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> 466 class MultipleStackTracesCollector : public StackObj { >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 498 class VM_GetAllStackTraces : public VM_Operation { >>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 499 private: >>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 500?? JavaThread *_calling_thread; >>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 501?? jint _final_thread_count; >>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 502 MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> You can't have a StackObj as a member of another class like that as it may not be on the stack. I think MultipleStackTracesCollector should not extend any allocation class, and should always be embedded directly in another class. >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> I'm not sure what does mean "embedded". >>>>>>>>>>>>>>>>>>>>>>>>>>> Is it ok as below? >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>>>>>>> class MultipleStackTracesCollector { >>>>>>>>>>>>>>>>>>>>>>>>>>> ??? : >>>>>>>>>>>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> class GetAllStackTraces : public VM_Operation { >>>>>>>>>>>>>>>>>>>>>>>>>>> ?? private: >>>>>>>>>>>>>>>>>>>>>>>>>>> MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> Yes that I what I meant. >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> On 2020/06/30 22:22, David Holmes wrote: >>>>>>>>>>>>>>>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> On 30/06/2020 10:05 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>>>>>>>>> Hi David, Serguei, >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> I updated webrev for 8242428. Could you review again? >>>>>>>>>>>>>>>>>>>>>>>>>>>>> This change migrate to use direct handshake for GetStackTrace() and GetThreadListStackTraces() (when thread_count == 1). >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.01/ >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> This looks really good now! I only have a few nits below. There is one thing I don't like about it but it requires a change to the main Handshake logic to address - in JvmtiEnv::GetThreadListStackTraces you have to create a ThreadsListHandle to convert the jthread to a JavaThread, but then the Handshake::execute_direct creates another ThreadsListHandle internally. That's a waste. I will discuss with Robbin and file a RFE to have an overload of execute_direct that takes an existing TLH. Actually it's worse than that because we have another TLH in use at the entry point for the JVMTI functions, so I think there may be some scope for simplifying the use of TLH instances - future RFE. >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> ??451 GetStackTraceClosure(JvmtiEnv *env, jint start_depth, jint max_count, >>>>>>>>>>>>>>>>>>>>>>>>>>>> ??452 jvmtiFrameInfo* frame_buffer, jint* count_ptr) >>>>>>>>>>>>>>>>>>>>>>>>>>>> ??453???? : HandshakeClosure("GetStackTrace"), >>>>>>>>>>>>>>>>>>>>>>>>>>>> ??454?????? _env(env), _start_depth(start_depth), _max_count(max_count), >>>>>>>>>>>>>>>>>>>>>>>>>>>> ??455 _frame_buffer(frame_buffer), _count_ptr(count_ptr), >>>>>>>>>>>>>>>>>>>>>>>>>>>> ??456 _result(JVMTI_ERROR_THREAD_NOT_ALIVE) { >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> Nit: can you do one initializer per line please. >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> This looks wrong: >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> 466 class MultipleStackTracesCollector : public StackObj { >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> ??498 class VM_GetAllStackTraces : public VM_Operation { >>>>>>>>>>>>>>>>>>>>>>>>>>>> ??499 private: >>>>>>>>>>>>>>>>>>>>>>>>>>>> ??500?? JavaThread *_calling_thread; >>>>>>>>>>>>>>>>>>>>>>>>>>>> ??501?? jint _final_thread_count; >>>>>>>>>>>>>>>>>>>>>>>>>>>> ??502 MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> You can't have a StackObj as a member of another class like that as it may not be on the stack. I think MultipleStackTracesCollector should not extend any allocation class, and should always be embedded directly in another class. >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> 481 MultipleStackTracesCollector(JvmtiEnv *env, jint max_frame_count) { >>>>>>>>>>>>>>>>>>>>>>>>>>>> ??482???? _env = env; >>>>>>>>>>>>>>>>>>>>>>>>>>>> ??483???? _max_frame_count = max_frame_count; >>>>>>>>>>>>>>>>>>>>>>>>>>>> ??484 _frame_count_total = 0; >>>>>>>>>>>>>>>>>>>>>>>>>>>> ??485???? _head = NULL; >>>>>>>>>>>>>>>>>>>>>>>>>>>> ??486???? _stack_info = NULL; >>>>>>>>>>>>>>>>>>>>>>>>>>>> ??487???? _result = JVMTI_ERROR_NONE; >>>>>>>>>>>>>>>>>>>>>>>>>>>> ??488?? } >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> As you are touching this can you change it to use an initializer list as you did for the HandshakeClosure, and please keep one item per line. >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> ??820 assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>>>>>>>>>>>>>>>> ??821 java_thread->is_thread_fully_suspended(false, &debug_bits) || >>>>>>>>>>>>>>>>>>>>>>>>>>>> ??822 current_thread == java_thread->active_handshaker(), >>>>>>>>>>>>>>>>>>>>>>>>>>>> ??823????????? "at safepoint / handshake or target thread is suspended"); >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> I don't think the suspension check is necessary, as even if the target is suspended we must still be at a safepoint or in a handshake with it. Makes me wonder if we used to allow a racy stacktrace operation on a suspended thread, assuming it would remain suspended? >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> 1268?? oop thread_oop = jt->threadObj(); >>>>>>>>>>>>>>>>>>>>>>>>>>>> 1269 >>>>>>>>>>>>>>>>>>>>>>>>>>>> 1270?? if (!jt->is_exiting() && (jt->threadObj() != NULL)) { >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> You can use thread_oop in line 1270. >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> 1272 _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, thread_oop), >>>>>>>>>>>>>>>>>>>>>>>>>>>> 1273 jt, thread_oop); >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> It is frustrating that this entire call chain started with a jthread reference, which we converted to a JavaThread, only to eventually need to convert it back to a jthread! I think there is some scope for simplification here but not as part of this change. >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> IIUC at this point the _calling_thread is the current thread, so we can use: >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> Please add @bug lines to the tests. >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> I'm still pondering the test logic but wanted to send this now. >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>>>>>>>>>>>>>> VM_GetThreadListStackTrace (for GetThreadListStackTraces) and VM_GetAllStackTraces (for GetAllStackTraces) have inherited VM_GetMultipleStackTraces VM operation which provides the feature to generate jvmtiStackInfo. I modified VM_GetMultipleStackTraces to a normal C++ class to share with HandshakeClosure for GetThreadListStackTraces (GetSingleStackTraceClosure). >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> Also I added new testcases which test GetThreadListStackTraces() with thread_count == 1 and with all threads. >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> This change has been tested in serviceability/jvmti serviceability/jdwp vmTestbase/nsk/jvmti vmTestbase/nsk/jdi vmTestbase/nsk/jdwp. >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> On 2020/06/24 15:50, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Hi all, >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Please review this change: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ?? JBS: https://bugs.openjdk.java.net/browse/JDK-8242428 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ?? webrev: http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.00/ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> This change replace following VM operations to direct handshake. >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??- VM_GetFrameCount (GetFrameCount()) >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??- VM_GetFrameLocation (GetFrameLocation()) >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??- VM_GetThreadListStackTraces (GetThreadListStackTrace()) >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??- VM_GetCurrentLocation >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> GetThreadListStackTrace() uses direct handshake if thread count == 1. In other case (thread count > 1), it would be performed as VM operation (VM_GetThreadListStackTraces). >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Caller of VM_GetCurrentLocation (JvmtiEnvThreadState::reset_current_location()) might be called at safepoint. So I added safepoint check in its caller. >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> This change has been tested in serviceability/jvmti serviceability/jdwp vmTestbase/nsk/jvmti vmTestbase/nsk/jdi vmTestbase/ns >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> k/jdwp. >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Also I tested it on submit repo, then it has execution error (mach5-one-ysuenaga-JDK-8242428-20200624-0054-12034717) due to dependency error. So I think it does not occur by this change. >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>> >>>>>>>>> >>>>>>> From aph at redhat.com Wed Jul 8 09:49:35 2020 From: aph at redhat.com (Andrew Haley) Date: Wed, 8 Jul 2020 10:49:35 +0100 Subject: RFR(S): 8247762: [aarch64] Timeout in .../HeapDumpTestWithActiveProcess.java due to inf. loop in AARCH64CurrentFrameGuess.run() In-Reply-To: <6322edbb-ab38-4956-6a29-5b1c3d48c132@oracle.com> References: <36c12487-cfc9-3823-c4a3-7605629beca5@redhat.com> <78a1d527-bd3f-6bc2-7880-ca5f34215267@oracle.com> <6322edbb-ab38-4956-6a29-5b1c3d48c132@oracle.com> Message-ID: <24bcb11a-ae3e-a29c-bcc0-a377eb90e19b@redhat.com> On 06/07/2020 20:54, Patric Hedlin wrote: > Andrew, > > Something you can live with? Totally. Great explanation too. -- Andrew Haley (he/him) Java Platform Lead Engineer Red Hat UK Ltd. https://keybase.io/andrewhaley EAC8 43EB D3EF DB98 CC77 2FAD A5CD 6035 332F A671 From patric.hedlin at oracle.com Wed Jul 8 10:07:14 2020 From: patric.hedlin at oracle.com (Patric Hedlin) Date: Wed, 8 Jul 2020 12:07:14 +0200 Subject: RFR(S): 8247762: [aarch64] Timeout in .../HeapDumpTestWithActiveProcess.java due to inf. loop in AARCH64CurrentFrameGuess.run() In-Reply-To: <24bcb11a-ae3e-a29c-bcc0-a377eb90e19b@redhat.com> References: <36c12487-cfc9-3823-c4a3-7605629beca5@redhat.com> <78a1d527-bd3f-6bc2-7880-ca5f34215267@oracle.com> <6322edbb-ab38-4956-6a29-5b1c3d48c132@oracle.com> <24bcb11a-ae3e-a29c-bcc0-a377eb90e19b@redhat.com> Message-ID: <0d569e36-5a8e-df1a-ab34-63ebe864f9ec@oracle.com> Thanks for reviewing Andrew. /Patric On 2020-07-08 11:49, Andrew Haley wrote: > On 06/07/2020 20:54, Patric Hedlin wrote: >> Andrew, >> >> Something you can live with? > Totally. Great explanation too. > From kevin.walls at oracle.com Wed Jul 8 10:23:57 2020 From: kevin.walls at oracle.com (Kevin Walls) Date: Wed, 8 Jul 2020 11:23:57 +0100 Subject: RFR(M): 8247515: OSX pc_to_symbol() lookup does not work with core files In-Reply-To: <38e1887e-a646-abc0-0b7e-53339af1d684@oracle.com> References: <092ef5a8-c973-e377-de91-b2002a1b8fe7@oracle.com> <38e1887e-a646-abc0-0b7e-53339af1d684@oracle.com> Message-ID: <3c31622b-831e-d46f-daa6-d641cbf755b1@oracle.com> Sure -- I was thinking lowest_offset_from_sym initialising starting at a high positive integer (that would now be PTRDIFF_MAX I think) to save a comparison with e.g. -1, you can just check if the new offset is less than lowest_offset_from_sym With the ptrdiff_t change you made, this all looks good to me however you decide. 8-) On 07/07/2020 21:17, Chris Plummer wrote: > Hi Kevin, > > Thanks for the review. Yes, that lack of initialization of > lowest_offset_from_sym is a bug. I'm real surprised the compiler > didn't catch it as it will be uninitialized garbage the first time it > is referenced. Fortunately usually the eventual offset is very small > if not 0, so probably this never prevented a proper match. I think > there's also another bug: > > ?415?????? uintptr_t offset_from_sym = offset - sym->offset; > > "offset" is the passed in offset, essentially the address of the > symbol we are interested in, but given as an offset from the start of > the DSO. "sym->offset" is also an offset from the start of the DSO. It > could be located before or after "offset". This means the math could > result in a negative number, which when converted to unsigned would be > a very large positive number. This happens whenever you check a symbol > that is actually located after the address you are looking up. The end > result is harmless, because it just means there's no way we will match > that symbol, which is what you want, but it would be good to clean > this up. > > I think what is best is to use ptrdiff_t and initialize > lowest_offset_from_sym to -1. I've updated the webrev: > > http://cr.openjdk.java.net/~cjplummer/8247515/webrev.01/index.html > > thanks, > > Chris > > On 7/7/20 4:09 AM, Kevin Walls wrote: >> Hi Chris, >> >> Yes I think this looks good. >> >> Question: In nearest_symbol, do we need to initialize >> lowest_offset_from_sym to something impossibly high, as if it >> defaults to zero we never find a better/nearer result? >> >> Thanks >> Kevin >> >> >> On 07/07/2020 06:10, Chris Plummer wrote: >>> Hello, >>> >>> Please help review the following: >>> >>> http://cr.openjdk.java.net/~cjplummer/8247515/webrev.00/index.html >>> https://bugs.openjdk.java.net/browse/JDK-8247515 >>> >>> The CR contains a description of the issues being addressed. There >>> is also no test for this symbol lookup support yet. It will be there >>> after I push JDK-8247516 and? JDK-8247514, which are both blocked by >>> the CR. >>> >>> [1] https://bugs.openjdk.java.net/browse/JDK-8247516 >>> [2] https://bugs.openjdk.java.net/browse/JDK-8247514 >>> >>> thanks, >>> >>> Chris >>> > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From kevin.walls at oracle.com Wed Jul 8 10:47:30 2020 From: kevin.walls at oracle.com (Kevin Walls) Date: Wed, 8 Jul 2020 11:47:30 +0100 Subject: RFR(M): 8247272: SA ELF file support has never worked for 64-bit causing address to symbol name mapping to fail In-Reply-To: <338118cb-37ff-9d03-f22e-c96322bfd7a6@oracle.com> References: <338118cb-37ff-9d03-f22e-c96322bfd7a6@oracle.com> Message-ID: Hi Chris -- This is a great story/history lesson. You could if you like, edit those comments in ElfFileParser.java so "Elf32_Addr" as they will contain either "Elf64_Addr or Elf32_Addr", similarly Elf64_Off.? The other Elf64 fields are the same as the 32 bit ones. Yes, the symbol fields are ordered differently. So all looks good to me! Thanks Kevin On 08/07/2020 07:20, Chris Plummer wrote: > Hello, > > Please help review the following: > > http://cr.openjdk.java.net/~cjplummer/8247272/webrev.00/index.html > https://bugs.openjdk.java.net/browse/JDK-8247272 > > The short story is that SA address to native symbol name > mapping/lookup has never worked on 64-bit, and this is due to the java > level ELF file support only supporting 32-bit. This CR fixes that, and > I believe also maintains 32-bit compatibility, although I have no way > of testing that. > > There is more to the story however on how we got here. Before going > into the gory detail below, I just want to point out that currently > nothing is using this support, and therefore it is technically not > fixing anything, although I did verify that the fixes work (see > details below). Also, I intend to remove all the java level ELF file > support as part of JDK-8247516 [1]. The only reason I want to push > these changes first is because I already did the work to get it > working with 64-bit, and would like to get it archived before removing > it in case for some reason it is revived in the future. > > Now for the ugly details on how we got here (and you really don't need > to read this unless you have any concerns with what I stated above). > It starts with the clhsdb "whatis" command, which was the only > (indirect) user of this java level ELF file support. It's > implementation is in javascript, so we have not had access to it ever > since JDK9 module support broke the SA javascript support (and > javascript support is now removed). I started the process of > converting "whatis" to java. It is basically the same as the clhsdb > "findpc" command, except it also checks for native symbols, which it > does with the following code: > > ? var dso = loadObjectContainingPC(addr); > ? var sym = dso.closestSymbolToPC(addr); > ? return sym.name + '+' + sym.offset; > > Converting this to java was trivial. I just stuck support for it in > the PointerFinder class, which is what findpc relies on. However, it > always failed to successfully lookup a symbol. I found that > DSO.closestSymbolToPC() called into the java level ELF support, and > that was failing badly. After some debugging I noticed that the values > read in for various ELF headers were mostly garbage. It then occurred > to me that it was reading in 32-bit values that probably needed to be > 64-bit. Sure enough, this code was never converted to 64-bit support. > I then went and tried "whatis" on JDK8, the last version where it was > available, and it failed there also with 64-bit binaries. So this is > why I initially fixed it to work with 64-bit, and also how I tested it > (using the modified findpc on a native symbol). But the story > continues... > > DSO.java, and as a consequence the java ELF file support, is used by > all our posix ports to do address to symbol lookups. So I figured that > after fixing the java level ELF file support for 64-bit, my improved > findpc would start working on OSX also. No such luck, and for obvious > reasons. OSX uses mach-o files. This ELF code should never have been > used for it, and of course has never worked. > > So I was left trying to figure out how to do OSX address to native > symbol lookups. I then recalled that there was a > CFrame.closestSymbolToPC() API that did address to native symbol > lookups for native stack traces, and wondered how it was ever working > (even on linux with the broken ELF 64-bit support). It turns out this > takes a very different path to do the lookups, ending up in native > code in libsaproc, where we also have ELF file support. I then > converted DSO.closestSymbolToPC(addr) to use this libsaproc code > instead, and it worked fine. So now there was no need for the java > level ELF file support since its only user was > DSO.closestSymbolToPC(addr). I should also add that this is the > approach that has always been used on windows, with both > CFrame.closestSymbolToPC() and DSO.closestSymbolToPC(addr) using the > same libsaproc support. > > There is still a bit more to the story. After diverting > DSO.closestSymbolToPC(addr) to the libsaproc lookup code, it still > didn't work for OSX. I thought it would just work since the native > BsdDebuggerLocal.lookupByName0() is implemented, and it seems to > trickle down to the proper lower level APIs to find the symbol, but > there were two issues. The first is that for processes there is no > support for looking up all the libraries and populating the list of > ps_prochandle structures that are used to do the symbol lookups. This > was just never implemented (also is why PMap does not work for OSX > processes). For core files the ps_prochandle structs are there, but > the lookup code was badly broken. That has now been fixed by > JDK-8247515 [2], currently out for review. So the end result is we'll > have address to native symbol lookup for everything but OSX processes. > > If? your still here, thanks for listening! > > Chris > > [1] https://bugs.openjdk.java.net/browse/JDK-8247516 > [2] https://bugs.openjdk.java.net/browse/JDK-8247515 > > > > From david.holmes at oracle.com Wed Jul 8 12:29:23 2020 From: david.holmes at oracle.com (David Holmes) Date: Wed, 8 Jul 2020 22:29:23 +1000 Subject: RFR: 8242428: JVMTI thread operations should use Thread-Local Handshake In-Reply-To: References: <6c263e4c-0a83-be7a-0288-ecb2de0b7cea@oss.nttdata.com> <7dc1903b-6295-3864-6301-4c02aacdb971@oss.nttdata.com> <04e09eb7-9483-8f63-4bb4-01c9e814802e@oracle.com> <238a89a3-06b1-90e4-d5a4-8dc2f1ed12ab@oracle.com> <4c43bc2c-551e-d042-8fa7-b63e755888d1@oracle.com> <8c387550-a06e-6320-f453-0e898486befb@oss.nttdata.com> <19cfa2a7-f441-425d-5623-1c11c6a870b6@oss.nttdata.com> <237e8d26-d185-1008-6e07-5b9f36314534@oracle.com> Message-ID: <0fb1d65e-d888-7fcf-548b-58172d507ea8@oracle.com> On 8/07/2020 6:04 pm, Yasumasa Suenaga wrote: > Hi David, > > On 2020/07/08 15:27, David Holmes wrote: >> Hi Yasumasa, >> >> On 7/07/2020 6:54 pm, Yasumasa Suenaga wrote: >>> Hi David, Serguei, >>> >>> Serguei, thank you for replying even though you are on vacaiton! >>> >>> I uploaded new webrev: >>> >>> ?? http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.07/ >>> ?? Diff from previous webrev: >>> http://hg.openjdk.java.net/jdk/submit/rev/77243b1dcbfe >>> >>> c'tor of GetSingleStackTraceClosure has jthread argument in this webrev. >>> Also it does not contain testcase for GetThreadListStackTraces with >>> all threads, and OneGetThreadListStackTraces would test main thread >>> only. >> >> All those changes are fine in principle for me. One nit/suggestion: >> >> src/hotspot/share/prims/jvmtiEnvBase.hpp >> >> ??544?? jthread _java_thread; >> >> elsewhere "java_thread" refers to a JavaThread, so to avoid confusion >> may I suggest this member be named _jthread. > > I uploaded new webrev: > > ? http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.08/ > ? Diff from previous webrev: > http://hg.openjdk.java.net/jdk/submit/rev/ca6263dbdc87 That looks fine. Thanks, David ----- > >> I'm going to be away for the next couple of days - sorry - but will >> try to check email on this if I can. > > Thanks! > > > Yasumasa > > >> Thanks, >> David >> ----- >> >>> >>> Thanks, >>> >>> Yasumasa >>> >>> >>> On 2020/07/07 15:13, David Holmes wrote: >>>> On 7/07/2020 2:57 pm, Yasumasa Suenaga wrote: >>>>> Hi David, >>>>> >>>>> On 2020/07/07 11:31, David Holmes wrote: >>>>>> Hi Yasumasa, >>>>>> >>>>>> Hard to keep up with the changes - especially without incremental >>>>>> webrevs. >>>>> >>>>> Sorry, I will upload diff from previous webrev in the next. >>>>> >>>>> >>>>>> If GetSingleStackTraceClosure also took the jthread as a >>>>>> constructor arg, then you wouldn't need to recreate a JNI local >>>>>> handle when calling _collector.fill_frames. It's a small >>>>>> simplification and not essential at this stage. >>>>> >>>>> I think we should get jthread from an argument of do_thread() >>>>> because do_thread() would pass the thread which are stopped certainly. >>>>> It might be simplification if we pass _calling_thread to >>>>> MultipleStackTracesCollector. `jthread` is only needed to store >>>>> jvmtiStackInfo.thread . What do you think? >>>> >>>> I'm not quite sure what you mean. >>>> >>>> I think there is a bit of a design wart with direct handshakes in >>>> that do_thread takes the target JavaThread as an argument. That's >>>> useful in a case where you want a HandshakeClosure that can be >>>> applied to multiple threads, but that's not typically what is needed >>>> with direct handshakes - there is only a single target. With a >>>> single-target HandshakeClosure you can capture all the "target" >>>> information for the operation in the closure instance. So if the >>>> actual do_thread operation wants the jthread corresponding to the >>>> target thread then we can store that in the closure rather than >>>> recomputing it (you could assert it is the same but that seems >>>> overkill to me). >>>> >>>>> >>>>>> For the test ... I don't see how >>>>>> Java_GetThreadListStackTraces_checkCallStacks is a valid test. It >>>>>> gets the stacks of all live threads, then uses that information to >>>>>> use GetThreadListStackTraces to get the stack for the same set of >>>>>> threads through a different API. It then compares the two sets of >>>>>> stacks for each thread expecting them to be the same, but that >>>>>> need only be the case for the main thread. Other threads could >>>>>> potentially have a different stack (e.g. if this test is run with >>>>>> JFR enabled there will be additional threads found.) Further I >>>>>> would have expected that there already exist tests that check >>>>>> that, for a given thread (which may be suspended or known to be >>>>>> blocked) the same stack is found through the two different APIs. >>>>> >>>>> vmTestbase/nsk/jvmti/unit/GetAllStackTraces/getallstktr001 would >>>>> check all of threads via GetThreadListStackTraces() and >>>>> GetAllStackTraces(), so we might be able to remove >>>>> GetThreadListStackTraces.java from this webrev. >>>> >>>> Yes. The existing test only examines a set of test threads that are >>>> all blocked on a raw monitor. You do not need to duplicate that test. >>>> >>>>> OTOH we don't have testcase for GetThreadListStackTraces() with >>>>> thread_count == 1, so we need to testcase for it (it is >>>>> OneGetThreadListStackTraces.java) It would check whether the state >>>>> of target thread is "waiting" before JNI call to call >>>>> GetThreadListStackTraces(), >>>> >>>> Yes we need to test the special cases introduced by your changes - >>>> totally agree - and OneGetThreadListStackTraces.java is a good test >>>> for that. >>>> >>>>> and also I expect it would not be run with JFR. (it is not >>>>> described @run) >>>> >>>> The arguments to run with JFR (or a bunch of other things) can be >>>> passed to the jtreg test harness to be applied to all tests. >>>> >>>>> Of course we can check GetThreadListStackTraces() with main thread, >>>>> but it is not the test for direct handshake for other thread. >>>> >>>> Right - that test already exists as per the above. >>>> >>>> Thanks, >>>> David >>>> >>>>> >>>>> Thanks, >>>>> >>>>> Yasumasa >>>>> >>>>> >>>>>> Thanks, >>>>>> David >>>>>> ----- >>>>>> >>>>>> On 6/07/2020 11:29 pm, Yasumasa Suenaga wrote: >>>>>>> Hi Serguei, >>>>>>> >>>>>>> Thanks for your comment! >>>>>>> >>>>>>> I think C++ is more simple to implement the test agent as you said. >>>>>>> So I implement it in C++ in new webrev. Could you review again? >>>>>>> >>>>>>> ?? http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.06/ >>>>>>> >>>>>>> Also I refactored libGetThreadListStackTraces.cpp, and I've kept >>>>>>> exception check after IsSameObject(). >>>>>>> >>>>>>> >>>>>>> Thanks, >>>>>>> >>>>>>> Yasumasa >>>>>>> >>>>>>> >>>>>>> On 2020/07/06 16:32, serguei.spitsyn at oracle.com wrote: >>>>>>>> Hi Yasumasa, >>>>>>>> >>>>>>>> Thank you for the update. >>>>>>>> I think, a pending exception after IsSameObject needs to be >>>>>>>> checked. >>>>>>>> >>>>>>>> The checkStackInfo() needs one more refactoring as I've already >>>>>>>> suggested. >>>>>>>> The body of the loop at L68-L78 should be converted to a >>>>>>>> function check_frame_info. >>>>>>>> The si1->frame_buffer[i] and si2->frame_buffer[i] will be passed >>>>>>>> as fi1 and fi2. >>>>>>>> The index can be passed as well. >>>>>>>> I'm still suggesting to simplify the local exception_msg to >>>>>>>> something shorter like err_msg or exc_msg. >>>>>>>> >>>>>>>> I'm not sure using fatal is right here: >>>>>>>> >>>>>>>> This fragment looks strange: >>>>>>>> >>>>>>>> ? 152???? if ((*env)->IsSameObject(env, stack_info[i].thread, >>>>>>>> thread)) { >>>>>>>> ? 153?????? target_info = &stack_info[i]; >>>>>>>> ? 154?????? break; >>>>>>>> ? 155???? } else if ((*env)->ExceptionOccurred(env)) { >>>>>>>> ? 156?????? (*env)->ExceptionDescribe(env); >>>>>>>> ? 157?????? (*env)->FatalError(env, __FILE__); >>>>>>>> ? 158???? } >>>>>>>> >>>>>>>> I expected it to be: >>>>>>>> >>>>>>>> ??? jboolean same = (*env)->IsSameObject(env, >>>>>>>> stack_info[i].thread, thread); >>>>>>>> ??? if ((*env)->ExceptionOccurred(env)) { >>>>>>>> ????? (*env)->ExceptionDescribe(env); >>>>>>>> ????? (*env)->FatalError(env, __FILE__); >>>>>>>> ??? } >>>>>>>> ??? if (same) { >>>>>>>> ????? target_info = &stack_info[i]; >>>>>>>> ????? break; >>>>>>>> ??? } >>>>>>>> >>>>>>>> Would it better to port this agent to C++ to simplify this code >>>>>>>> nicer? >>>>>>>> >>>>>>>> Thanks, >>>>>>>> Serguei >>>>>>>> >>>>>>>> >>>>>>>> On 7/5/20 06:13, Yasumasa Suenaga wrote: >>>>>>>>> Hi Serguei, >>>>>>>>> >>>>>>>>> Thanks for your comment! >>>>>>>>> I refactored testcase. Could you review again? >>>>>>>>> >>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.05/ >>>>>>>>> >>>>>>>>> It would check Java exception after IsSameObject() call. Does >>>>>>>>> it need? >>>>>>>>> Any exceptions are not described in JNI document[1], and JNI >>>>>>>>> implementation (jni_IsSameObject()) does not seem to throw it. >>>>>>>>> >>>>>>>>> >>>>>>>>> Thanks, >>>>>>>>> >>>>>>>>> Yasumasa >>>>>>>>> >>>>>>>>> >>>>>>>>> [1] >>>>>>>>> https://docs.oracle.com/en/java/javase/14/docs/specs/jni/functions.html#issameobject >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> On 2020/07/05 14:46, serguei.spitsyn at oracle.com wrote: >>>>>>>>>> Hi Yasumasa, >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> Okay, thanks. >>>>>>>>>> Then I'm okay to keep the GetSingleStackTraceClosure. >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libGetThreadListStackTraces.c.html >>>>>>>>>> >>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.c.html >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> I'm not sure the function 'is_same_thread() is needed. >>>>>>>>>> Why do not use the JNI IsSameObject instead? >>>>>>>>>> >>>>>>>>>> It seems to be a typo at L132 and L137. >>>>>>>>>> You, probably. did not want to print the same information for >>>>>>>>>> stack_info_1[i].frame_buffer[j].XXX twice. >>>>>>>>>> >>>>>>>>>> The code at lines 112-142 is not readable. >>>>>>>>>> I'd suggest to make a couple of refactoring steps. >>>>>>>>>> >>>>>>>>>> First step to simplify this a little bit would be with some >>>>>>>>>> renaming and getting rid of indexes: >>>>>>>>>> >>>>>>>>>> ?? 71 char err_msg[EXCEPTION_MSG_LEN] = {0}; >>>>>>>>>> ??... >>>>>>>>>> ??112?? /* Iterate all jvmtiStackInfo to check */ >>>>>>>>>> ??113?? for (i = 0; i < num_threads, *exception_msg != '\0'; >>>>>>>>>> i++) { >>>>>>>>>> ????????? jvmtiStackInfo *si1 = stack_info_1[i]; >>>>>>>>>> ????????? jvmtiStackInfo *si2 = stack_info_2[i]; >>>>>>>>>> ??114???? if (!IsSameObject(env, si1.thread, si2.thread)) { /* >>>>>>>>>> jvmtiStackInfo::thread */ >>>>>>>>>> ??115?????? snprintf(err_msg, sizeof(err_msg), >>>>>>>>>> ??116??????????????? "thread[%d] is different: stack_info_1 = >>>>>>>>>> %p, stack_info_2 = %p", >>>>>>>>>> ??117??????????????? i, sinfo1.thread, sinfo2.thread); >>>>>>>>>> ??118???? } else if (si1.state != si2.state) { /* >>>>>>>>>> jvmtiStackInfo::state */ >>>>>>>>>> ??119?????? snprintf(err_msg, sizeof(err_msg), >>>>>>>>>> ??120??????????????? "state[%d] is different: stack_info_1 = >>>>>>>>>> %d, stack_info_2 = %d", >>>>>>>>>> ??121??????????????? i, si1.state, si2.state); >>>>>>>>>> ??122???? } else if (si1.frame_count != si2.frame_count) { /* >>>>>>>>>> jvmtiStackInfo::frame_count */ >>>>>>>>>> ??123?????? snprintf(err_msg, sizeof(err_msg), >>>>>>>>>> ??124??????????????? "frame_count[%d] is different: >>>>>>>>>> stack_info_1 = %d, stack_info_2 = %d", >>>>>>>>>> ??125??????????????? i, si1.frame_count, si2.frame_count); >>>>>>>>>> ??126???? } else { >>>>>>>>>> ??127?????? /* Iterate all jvmtiFrameInfo to check */ >>>>>>>>>> ??128?????? for (j = 0; j < si1.frame_count; j++) { >>>>>>>>>> ??129???????? if (si1.frame_buffer[j].method != >>>>>>>>>> si1.frame_buffer[j].method) { /* jvmtiFrameInfo::method */ >>>>>>>>>> ??130?????????? snprintf(err_msg, sizeof(err_msg), >>>>>>>>>> ??131??????????????????? "thread [%d] frame_buffer[%d].method >>>>>>>>>> is different: stack_info_1 = %lx, stack_info_2 = %lx", >>>>>>>>>> ??132??????????????????? i, j, si1.frame_buffer[j].method, >>>>>>>>>> si2.frame_buffer[j].method); >>>>>>>>>> ??133?????????? break; >>>>>>>>>> ??134???????? } else if (si1.frame_buffer[j].location != >>>>>>>>>> si1.frame_buffer[j].location) { /* jvmtiFrameInfo::location */ >>>>>>>>>> ??135?????????? snprintf(err_msg, sizeof(err_msg), >>>>>>>>>> ??136??????????????????? "thread [%d] >>>>>>>>>> frame_buffer[%d].location is different: stack_info_1 = %ld, >>>>>>>>>> stack_info_2 = %ld", >>>>>>>>>> ??137??????????????????? i, j, si1.frame_buffer[j].location, >>>>>>>>>> si2.frame_buffer[j].location); >>>>>>>>>> ??138?????????? break; >>>>>>>>>> ??139???????? } >>>>>>>>>> ??140?????? } >>>>>>>>>> ??141???? } >>>>>>>>>> ??142?? } >>>>>>>>>> >>>>>>>>>> Another step would be to create functions that implement a >>>>>>>>>> body of each loop. >>>>>>>>>> You can use the same techniques to simplify similar place >>>>>>>>>> (L127-L138) in the libOneGetThreadListStackTraces.c. >>>>>>>>>> >>>>>>>>>> Thanks, >>>>>>>>>> Serguei >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> On 7/3/20 15:55, Yasumasa Suenaga wrote: >>>>>>>>>>> Hi Serguei, >>>>>>>>>>> >>>>>>>>>>> I'm not an Oracle employee, so I cannot know real request(s) >>>>>>>>>>> from your customers. >>>>>>>>>>> However JDK-8201641 says Dynatrace has requested this >>>>>>>>>>> enhancement. >>>>>>>>>>> >>>>>>>>>>> BTW I haven't heared any request from my customers about this. >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> Thanks, >>>>>>>>>>> >>>>>>>>>>> Yasumasa >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> On 2020/07/04 4:32, serguei.spitsyn at oracle.com wrote: >>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>> >>>>>>>>>>>> This difference is not that big to care about. >>>>>>>>>>>> I feel this is really rare case and so, does not worth these >>>>>>>>>>>> complications. >>>>>>>>>>>> Do we have a real request from customers to optimize it? >>>>>>>>>>>> >>>>>>>>>>>> Thanks, >>>>>>>>>>>> Serguei >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> On 7/3/20 01:16, Yasumasa Suenaga wrote: >>>>>>>>>>>>> Hi Serguei, >>>>>>>>>>>>> >>>>>>>>>>>>> Generally I agree with you, but I have concern about the >>>>>>>>>>>>> difference of the result of GetStackTrace() and >>>>>>>>>>>>> GetThreadListStackTraces(). >>>>>>>>>>>>> >>>>>>>>>>>>> ? GetStackTrace: jvmtiFrameInfo >>>>>>>>>>>>> ? GetThreadListStackTraces: jvmtiStackInfo >>>>>>>>>>>>> >>>>>>>>>>>>> jvmtiStackInfo contains thread state, and it is ensured it >>>>>>>>>>>>> is the state of the call stack. >>>>>>>>>>>>> If we want to get both call stack and thread state, we need >>>>>>>>>>>>> to suspend target thread, and call both GetStackTrace() and >>>>>>>>>>>>> GetThreadState(). Is it ok? >>>>>>>>>>>>> >>>>>>>>>>>>> I was wondering if JDK-8201641 (parent ticket of this >>>>>>>>>>>>> change) needed them for profiling (dynatrace?) >>>>>>>>>>>>> If it is responsibility of JVMTI agent implementor, I >>>>>>>>>>>>> remove this closure. >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> Thanks, >>>>>>>>>>>>> >>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> On 2020/07/03 16:45, serguei.spitsyn at oracle.com wrote: >>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>> >>>>>>>>>>>>>> After some thinking I've concluded that I do not like this >>>>>>>>>>>>>> optimization >>>>>>>>>>>>>> of the GetThreadListStackTraces with >>>>>>>>>>>>>> GetSingleStackTraceClosure. >>>>>>>>>>>>>> >>>>>>>>>>>>>> We may need more opinions on this but these are my points: >>>>>>>>>>>>>> ??- it adds some complexity and ugliness >>>>>>>>>>>>>> ??- a win is doubtful because it has to be a rare case, so >>>>>>>>>>>>>> that total overhead should not be high >>>>>>>>>>>>>> ??- if it is really high for some use cases then it is up >>>>>>>>>>>>>> to the user >>>>>>>>>>>>>> ??? to optimize it with using GetStackTrace instead >>>>>>>>>>>>>> >>>>>>>>>>>>>> In such cases with doubtful overhead I usually prefer the >>>>>>>>>>>>>> simplicity. >>>>>>>>>>>>>> >>>>>>>>>>>>>> Good examples where it makes sense to optimize are checks >>>>>>>>>>>>>> for target thread to be current thread. >>>>>>>>>>>>>> In such cases there is no need to suspend the target >>>>>>>>>>>>>> thread, or use a VMop/HandshakeClosure. >>>>>>>>>>>>>> For instance, please, see the Monitor functions with the >>>>>>>>>>>>>> check: (java_thread == calling_thread). >>>>>>>>>>>>>> Getting information for current thread is frequently used >>>>>>>>>>>>>> case, e.g. to get info at an event point. >>>>>>>>>>>>>> >>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>> Serguei >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> On 7/2/20 23:29, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>> Hi Dan, David, >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> I uploaded new webrev. Could you review again? >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/ >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> OneGetThreadListStackTraces.java in this webrev would >>>>>>>>>>>>>>> wait until thread state is transited to "waiting" with >>>>>>>>>>>>>>> spin wait. >>>>>>>>>>>>>>> CountDownLatch::await call as Dan pointed is fixed in it :) >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Diff from webrev.03: >>>>>>>>>>>>>>> http://hg.openjdk.java.net/jdk/submit/rev/c9aeb7001e50 >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> On 2020/07/03 14:15, David Holmes wrote: >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> On 3/07/2020 2:27 pm, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>> On 2020/07/03 12:24, Daniel D. Daugherty wrote: >>>>>>>>>>>>>>>>>> On 7/2/20 10:50 PM, David Holmes wrote: >>>>>>>>>>>>>>>>>>> Sorry I'm responding here without seeing latest >>>>>>>>>>>>>>>>>>> webrev but there is enough context I think ... >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> On 3/07/2020 9:14 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>> Hi Dan, >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Thanks for your comment! >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> On 2020/07/03 7:16, Daniel D. Daugherty wrote: >>>>>>>>>>>>>>>>>>>>> On 7/2/20 5:19 AM, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> I upload new webrev. Could you review again? >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.03/ >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnv.cpp >>>>>>>>>>>>>>>>>>>>> ???? L1542: ??? // Get stack trace with handshake >>>>>>>>>>>>>>>>>>>>> ???????? nit - please add a period at the end. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> ???? L1591: *stack_info_ptr = op.stack_info(); >>>>>>>>>>>>>>>>>>>>> ???????? The return parameter should not be touched >>>>>>>>>>>>>>>>>>>>> unless the return >>>>>>>>>>>>>>>>>>>>> ???????? code in 'err' == JVMTI_ERROR_NONE. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> ???? old L1582: ? if (err == JVMTI_ERROR_NONE) { >>>>>>>>>>>>>>>>>>>>> ???????? Please restore this check. The return >>>>>>>>>>>>>>>>>>>>> parameter should not >>>>>>>>>>>>>>>>>>>>> ???????? be touched unless the return code in 'err' >>>>>>>>>>>>>>>>>>>>> == JVMTI_ERROR_NONE. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> But op.stack_info() will return NULL if the error is >>>>>>>>>>>>>>>>>>> not JVMTI_ERROR_NONE. Are you (Dan) concerned about >>>>>>>>>>>>>>>>>>> someone passing in a non-null/initialized out-pointer >>>>>>>>>>>>>>>>>>> that will be reset to NULL if there was an error? >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Actually the way we used to test this in POSIX tests >>>>>>>>>>>>>>>>>> is to call >>>>>>>>>>>>>>>>>> an API with known bad parameters and the return >>>>>>>>>>>>>>>>>> parameter ptr >>>>>>>>>>>>>>>>>> set to NULL. If the return parameter ptr was touched >>>>>>>>>>>>>>>>>> when an >>>>>>>>>>>>>>>>>> error should have been detected on an earlier >>>>>>>>>>>>>>>>>> parameter, then >>>>>>>>>>>>>>>>>> the test failed. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> ???? L1272: ? if (!jt->is_exiting() && (thread_oop >>>>>>>>>>>>>>>>>>>>> != NULL)) { >>>>>>>>>>>>>>>>>>>>> ???????? nit - extra parens around the second >>>>>>>>>>>>>>>>>>>>> expression. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>>>>>>>>> ???? old L1532: ? _result = >>>>>>>>>>>>>>>>>>>>> JVMTI_ERROR_THREAD_NOT_ALIVE; >>>>>>>>>>>>>>>>>>>>> ???????? This deletion of the _result field threw >>>>>>>>>>>>>>>>>>>>> me for a minute and then >>>>>>>>>>>>>>>>>>>>> ???? ? ? I figured out that the field is init to >>>>>>>>>>>>>>>>>>>>> JVMTI_ERROR_THREAD_NOT_ALIVE >>>>>>>>>>>>>>>>>>>>> ???????? in the constructor. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> ???? L1553: ? if (!jt->is_exiting() && >>>>>>>>>>>>>>>>>>>>> (jt->threadObj() != NULL)) { >>>>>>>>>>>>>>>>>>>>> ???????? nit - extra parens around the second >>>>>>>>>>>>>>>>>>>>> expression. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>>>>>>>>>>>>>>>>> ???? No comments. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> src/hotspot/share/runtime/vmOperations.hpp >>>>>>>>>>>>>>>>>>>>> ???? No comments. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/GetThreadListStackTraces.java >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> ???? No comments. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/OneGetThreadListStackTraces.java >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> ???? L64: ??????? startSignal.countDown(); >>>>>>>>>>>>>>>>>>>>> ???????? I was expecting this to be a call to >>>>>>>>>>>>>>>>>>>>> await() instead of >>>>>>>>>>>>>>>>>>>>> ???????? countDown(). What am I missing here? >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> ???????? I think this test might be passing by >>>>>>>>>>>>>>>>>>>>> accident right now, but... >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Main thread (which call JVMTI functions to test) >>>>>>>>>>>>>>>>>>>> should wait until test thread is ready. >>>>>>>>>>>>>>>>>>>> So main thread would wait startSignal, and test >>>>>>>>>>>>>>>>>>>> thread would count down. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> No! >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> The test thread that previously called obj.wait() now >>>>>>>>>>>>>>>>>>> calls latch.await(). >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> The main thread that previously called obj.notify() >>>>>>>>>>>>>>>>>>> now calls latch.countDown(). >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> The main thread continues to spin until it sees the >>>>>>>>>>>>>>>>>>> target is WAITING before proceeding with the test. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> If I add spin wait to wait until transit target thread >>>>>>>>>>>>>>>>> state is WAITING (as following), we don't need to call >>>>>>>>>>>>>>>>> SuspendThread(). >>>>>>>>>>>>>>>>> Which is better? >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> The original spin-wait loop checking for? WAITING is >>>>>>>>>>>>>>>> better because it is the only guarantee that the target >>>>>>>>>>>>>>>> thread is blocked where you need it to be. suspending >>>>>>>>>>>>>>>> the thread is racy as you don't know exactly where the >>>>>>>>>>>>>>>> suspend will hit. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>> /* Wait until the thread state transits to "waiting" */ >>>>>>>>>>>>>>>>> while (th.getState() != Thread.State.WAITING) { >>>>>>>>>>>>>>>>> ???? Thread.onSpinWait(); >>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> For simplify, spin wait is prefer to >>>>>>>>>>>>>>>>> OneGetThreadListStackTraces.java in webrev.03. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Here's the flow as I see it: >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> main thread >>>>>>>>>>>>>>>>>> ?? - start worker thread >>>>>>>>>>>>>>>>>> ?? - startSignal.await() >>>>>>>>>>>>>>>>>> ???? - main is now blocked >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> worker thread >>>>>>>>>>>>>>>>>> ?? - startSignal.countDown() >>>>>>>>>>>>>>>>>> ???? - main is now unblocked >>>>>>>>>>>>>>>>>> ?? - stopSignal.await() >>>>>>>>>>>>>>>>>> ???? - worker is now blocked >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> main thread >>>>>>>>>>>>>>>>>> ?? - checkCallStacks(th) >>>>>>>>>>>>>>>>>> ?? - stopSignal.countDown() >>>>>>>>>>>>>>>>>> ???? - worker is now unblocked >>>>>>>>>>>>>>>>>> ?? - th.join >>>>>>>>>>>>>>>>>> ???? - main is now blocked >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> worker thread >>>>>>>>>>>>>>>>>> ?? - runs off the end of run() >>>>>>>>>>>>>>>>>> ???? - main is now unblocked >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> main thread >>>>>>>>>>>>>>>>>> ?? - run off the end of main() >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libGetThreadListStackTraces.c >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> ???? L92: ? jthreads = (jthread >>>>>>>>>>>>>>>>>>>>> *)malloc(sizeof(jthread) * num_threads); >>>>>>>>>>>>>>>>>>>>> ???????? You don't check for malloc() failure. >>>>>>>>>>>>>>>>>>>>> ???????? 'jthreads' is allocated but never freed. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.c >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> ???? L91: ? result = (*jvmti)->SuspendThread(jvmti, >>>>>>>>>>>>>>>>>>>>> thread); >>>>>>>>>>>>>>>>>>>>> ???????? Why are you suspending the thread? >>>>>>>>>>>>>>>>>>>>> GetAllStackTraces() and >>>>>>>>>>>>>>>>>>>>> ???????? GetThreadListStackTraces() do not require >>>>>>>>>>>>>>>>>>>>> the target thread(s) >>>>>>>>>>>>>>>>>>>>> ???????? to be suspend. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> ???????? If you decide not to SuspendThread, then >>>>>>>>>>>>>>>>>>>>> you don't need the >>>>>>>>>>>>>>>>>>>>> ???????? AddCapabilities or the ResumeThread calls. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Test thread might not be entered following code >>>>>>>>>>>>>>>>>>>> (stopSignal.await()). We might see deferent call >>>>>>>>>>>>>>>>>>>> stack between GetAllStackTraces() and >>>>>>>>>>>>>>>>>>>> GetThreadListStackTraces(). We cannot control to >>>>>>>>>>>>>>>>>>>> freeze call stack of test thread in Java code. >>>>>>>>>>>>>>>>>>>> (I didn't use SuspendThread() at first, but I saw >>>>>>>>>>>>>>>>>>>> some errors which causes in above.) >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> So we need to call SuspendThread() to ensure we can >>>>>>>>>>>>>>>>>>>> see same call stack. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> If you are checking that the thread is in state >>>>>>>>>>>>>>>>>>> WAITING then it cannot escape from that state and you >>>>>>>>>>>>>>>>>>> can sample the stack multiple times from any API and >>>>>>>>>>>>>>>>>>> get the same result. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> I suspect the errors you saw were from the apparent >>>>>>>>>>>>>>>>>>> incorrect use of the CountDownLatch. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> With the flow outlined above, the worker thread should be >>>>>>>>>>>>>>>>>> nicely blocked in stopSignal.await() when stuff is >>>>>>>>>>>>>>>>>> sampled. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Dan >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Cheers, >>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Dan >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> On 2020/07/02 15:05, David Holmes wrote: >>>>>>>>>>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> On 1/07/2020 11:53 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>>>> Hi, >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> I uploaded new webrev. Could review again? >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.02/ >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Updates look fine - thanks. >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> One minor nit: >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> 1274 _collector.allocate_and_fill_stacks(1); >>>>>>>>>>>>>>>>>>>>>>> 1275 _collector.set_result(JVMTI_ERROR_NONE); >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> In the other places where you use _collector you >>>>>>>>>>>>>>>>>>>>>>> rely on result being initialized to >>>>>>>>>>>>>>>>>>>>>>> JVMTI_ERROR_NONE, rather than setting it directly >>>>>>>>>>>>>>>>>>>>>>> after allocate_and_fill_stacks(). >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Fixed. >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 820 >>>>>>>>>>>>>>>>>>>>>>>>>>>>> assert(SafepointSynchronize::is_at_safepoint() >>>>>>>>>>>>>>>>>>>>>>>>>>>>> || >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 821 >>>>>>>>>>>>>>>>>>>>>>>>>>>>> java_thread->is_thread_fully_suspended(false, >>>>>>>>>>>>>>>>>>>>>>>>>>>>> &debug_bits) || >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 822 current_thread == >>>>>>>>>>>>>>>>>>>>>>>>>>>>> java_thread->active_handshaker(), >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 823????????? "at safepoint / handshake or >>>>>>>>>>>>>>>>>>>>>>>>>>>>> target thread is suspended"); >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> I don't think the suspension check is >>>>>>>>>>>>>>>>>>>>>>>>>>>>> necessary, as even if the target is >>>>>>>>>>>>>>>>>>>>>>>>>>>>> suspended we must still be at a safepoint >>>>>>>>>>>>>>>>>>>>>>>>>>>>> or in a handshake with it. Makes me wonder >>>>>>>>>>>>>>>>>>>>>>>>>>>>> if we used to allow a racy stacktrace >>>>>>>>>>>>>>>>>>>>>>>>>>>>> operation on a suspended thread, assuming >>>>>>>>>>>>>>>>>>>>>>>>>>>>> it would remain suspended? >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> This function (JvmtiEnvBase::get_stack_trace()) >>>>>>>>>>>>>>>>>>>>>>>> can be called to get own stack trace. For >>>>>>>>>>>>>>>>>>>>>>>> example, we can call GetStackTrace() for current >>>>>>>>>>>>>>>>>>>>>>>> thread at JVMTI event. >>>>>>>>>>>>>>>>>>>>>>>> So I changed assert as below: >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>>>> ??820?? assert(current_thread == java_thread || >>>>>>>>>>>>>>>>>>>>>>>> ??821 SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>>>>>>>>>>>> ??822????????? current_thread == >>>>>>>>>>>>>>>>>>>>>>>> java_thread->active_handshaker(), >>>>>>>>>>>>>>>>>>>>>>>> ??823????????? "call by myself / at safepoint / >>>>>>>>>>>>>>>>>>>>>>>> at handshake"); >>>>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Yep good catch. I hope current tests caught that. >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> They would be tested in >>>>>>>>>>>>>>>>>>>>>> vmTestbase/nsk/jvmti/GetStackTrace/getstacktr001/ >>>>>>>>>>>>>>>>>>>>>> (own call stacks), and getstacktr003 (call stacks >>>>>>>>>>>>>>>>>>>>>> in other thread). >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Speaking of tests ... >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> In the native code I think you need to check the >>>>>>>>>>>>>>>>>>>>>>> success of all JNI methods that can throw >>>>>>>>>>>>>>>>>>>>>>> exceptions - otherwise I believe the tests may >>>>>>>>>>>>>>>>>>>>>>> trigger warnings if -Xcheck:jni is used with >>>>>>>>>>>>>>>>>>>>>>> them. See for example: >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/libHeapMonitorTest.cpp >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> I updated testcases to check JNI and JVMTI >>>>>>>>>>>>>>>>>>>>>> function calls. >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> In the Java code the target thread: >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> ?? 45???? public void run() { >>>>>>>>>>>>>>>>>>>>>>> ?? 46?????? try { >>>>>>>>>>>>>>>>>>>>>>> ?? 47?????????? synchronized (lock) { >>>>>>>>>>>>>>>>>>>>>>> ?? 48?????????????? lock.wait(); >>>>>>>>>>>>>>>>>>>>>>> ?? 49 System.out.println("OK"); >>>>>>>>>>>>>>>>>>>>>>> ?? 50?????????? } >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> is potentially susceptible to spurious wakeups. >>>>>>>>>>>>>>>>>>>>>>> Using a CountDownLatch would be robust. >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Fixed. >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> On 2020/07/01 8:48, David Holmes wrote: >>>>>>>>>>>>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> On 1/07/2020 9:05 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> 1271 ResourceMark rm; >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> IIUC at this point the _calling_thread is >>>>>>>>>>>>>>>>>>>>>>>>>>>>> the current thread, so we can use: >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> If so, we can call make_local() in L1272 >>>>>>>>>>>>>>>>>>>>>>>>>> without JavaThread (or we can pass current >>>>>>>>>>>>>>>>>>>>>>>>>> thread to make_local()). Is it right? >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>>>>>>>>>>>>>>>>>> 1272 >>>>>>>>>>>>>>>>>>>>>>>>>> _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, >>>>>>>>>>>>>>>>>>>>>>>>>> thread_oop), >>>>>>>>>>>>>>>>>>>>>>>>>> 1273 jt, thread_oop); >>>>>>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> Sorry I got confused, _calling_thread may not >>>>>>>>>>>>>>>>>>>>>>>>> be the current thread as we could be executing >>>>>>>>>>>>>>>>>>>>>>>>> the handshake in the target thread itself. So >>>>>>>>>>>>>>>>>>>>>>>>> the ResourceMark is correct as-is (implicitly >>>>>>>>>>>>>>>>>>>>>>>>> for current thread). >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> The argument to fill_frames will be used in the >>>>>>>>>>>>>>>>>>>>>>>>> jvmtiStackInfo and passed back to the >>>>>>>>>>>>>>>>>>>>>>>>> _calling_thread, so it must be created via >>>>>>>>>>>>>>>>>>>>>>>>> make_local(_calling_thread, ...) as you >>>>>>>>>>>>>>>>>>>>>>>>> presently have. >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> On 2020/07/01 7:05, David Holmes wrote: >>>>>>>>>>>>>>>>>>>>>>>>>>> On 1/07/2020 12:17 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> Thank you for reviewing! I will update new >>>>>>>>>>>>>>>>>>>>>>>>>>>> webrev tomorrow. >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> 466 class MultipleStackTracesCollector : >>>>>>>>>>>>>>>>>>>>>>>>>>>>> public StackObj { >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 498 class VM_GetAllStackTraces : public >>>>>>>>>>>>>>>>>>>>>>>>>>>>> VM_Operation { >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 499 private: >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 500?? JavaThread *_calling_thread; >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 501?? jint _final_thread_count; >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 502 MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> You can't have a StackObj as a member of >>>>>>>>>>>>>>>>>>>>>>>>>>>>> another class like that as it may not be on >>>>>>>>>>>>>>>>>>>>>>>>>>>>> the stack. I think >>>>>>>>>>>>>>>>>>>>>>>>>>>>> MultipleStackTracesCollector should not >>>>>>>>>>>>>>>>>>>>>>>>>>>>> extend any allocation class, and should >>>>>>>>>>>>>>>>>>>>>>>>>>>>> always be embedded directly in another class. >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> I'm not sure what does mean "embedded". >>>>>>>>>>>>>>>>>>>>>>>>>>>> Is it ok as below? >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>>>>>>>> class MultipleStackTracesCollector { >>>>>>>>>>>>>>>>>>>>>>>>>>>> ??? : >>>>>>>>>>>>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> class GetAllStackTraces : public VM_Operation { >>>>>>>>>>>>>>>>>>>>>>>>>>>> ?? private: >>>>>>>>>>>>>>>>>>>>>>>>>>>> MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> Yes that I what I meant. >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> On 2020/06/30 22:22, David Holmes wrote: >>>>>>>>>>>>>>>>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> On 30/06/2020 10:05 am, Yasumasa Suenaga >>>>>>>>>>>>>>>>>>>>>>>>>>>>> wrote: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Hi David, Serguei, >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> I updated webrev for 8242428. Could you >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> review again? >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> This change migrate to use direct >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> handshake for GetStackTrace() and >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> GetThreadListStackTraces() (when >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> thread_count == 1). >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.01/ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> This looks really good now! I only have a >>>>>>>>>>>>>>>>>>>>>>>>>>>>> few nits below. There is one thing I don't >>>>>>>>>>>>>>>>>>>>>>>>>>>>> like about it but it requires a change to >>>>>>>>>>>>>>>>>>>>>>>>>>>>> the main Handshake logic to address - in >>>>>>>>>>>>>>>>>>>>>>>>>>>>> JvmtiEnv::GetThreadListStackTraces you have >>>>>>>>>>>>>>>>>>>>>>>>>>>>> to create a ThreadsListHandle to convert >>>>>>>>>>>>>>>>>>>>>>>>>>>>> the jthread to a JavaThread, but then the >>>>>>>>>>>>>>>>>>>>>>>>>>>>> Handshake::execute_direct creates another >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ThreadsListHandle internally. That's a >>>>>>>>>>>>>>>>>>>>>>>>>>>>> waste. I will discuss with Robbin and file >>>>>>>>>>>>>>>>>>>>>>>>>>>>> a RFE to have an overload of execute_direct >>>>>>>>>>>>>>>>>>>>>>>>>>>>> that takes an existing TLH. Actually it's >>>>>>>>>>>>>>>>>>>>>>>>>>>>> worse than that because we have another TLH >>>>>>>>>>>>>>>>>>>>>>>>>>>>> in use at the entry point for the JVMTI >>>>>>>>>>>>>>>>>>>>>>>>>>>>> functions, so I think there may be some >>>>>>>>>>>>>>>>>>>>>>>>>>>>> scope for simplifying the use of TLH >>>>>>>>>>>>>>>>>>>>>>>>>>>>> instances - future RFE. >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??451 GetStackTraceClosure(JvmtiEnv *env, >>>>>>>>>>>>>>>>>>>>>>>>>>>>> jint start_depth, jint max_count, >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??452 jvmtiFrameInfo* frame_buffer, jint* >>>>>>>>>>>>>>>>>>>>>>>>>>>>> count_ptr) >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??453???? : HandshakeClosure("GetStackTrace"), >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??454?????? _env(env), >>>>>>>>>>>>>>>>>>>>>>>>>>>>> _start_depth(start_depth), >>>>>>>>>>>>>>>>>>>>>>>>>>>>> _max_count(max_count), >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??455 _frame_buffer(frame_buffer), >>>>>>>>>>>>>>>>>>>>>>>>>>>>> _count_ptr(count_ptr), >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??456 _result(JVMTI_ERROR_THREAD_NOT_ALIVE) { >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> Nit: can you do one initializer per line >>>>>>>>>>>>>>>>>>>>>>>>>>>>> please. >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> This looks wrong: >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> 466 class MultipleStackTracesCollector : >>>>>>>>>>>>>>>>>>>>>>>>>>>>> public StackObj { >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??498 class VM_GetAllStackTraces : public >>>>>>>>>>>>>>>>>>>>>>>>>>>>> VM_Operation { >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??499 private: >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??500?? JavaThread *_calling_thread; >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??501?? jint _final_thread_count; >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??502 MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> You can't have a StackObj as a member of >>>>>>>>>>>>>>>>>>>>>>>>>>>>> another class like that as it may not be on >>>>>>>>>>>>>>>>>>>>>>>>>>>>> the stack. I think >>>>>>>>>>>>>>>>>>>>>>>>>>>>> MultipleStackTracesCollector should not >>>>>>>>>>>>>>>>>>>>>>>>>>>>> extend any allocation class, and should >>>>>>>>>>>>>>>>>>>>>>>>>>>>> always be embedded directly in another class. >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> 481 MultipleStackTracesCollector(JvmtiEnv >>>>>>>>>>>>>>>>>>>>>>>>>>>>> *env, jint max_frame_count) { >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??482???? _env = env; >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??483???? _max_frame_count = max_frame_count; >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??484 _frame_count_total = 0; >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??485???? _head = NULL; >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??486???? _stack_info = NULL; >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??487???? _result = JVMTI_ERROR_NONE; >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??488?? } >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> As you are touching this can you change it >>>>>>>>>>>>>>>>>>>>>>>>>>>>> to use an initializer list as you did for >>>>>>>>>>>>>>>>>>>>>>>>>>>>> the HandshakeClosure, and please keep one >>>>>>>>>>>>>>>>>>>>>>>>>>>>> item per line. >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??820 >>>>>>>>>>>>>>>>>>>>>>>>>>>>> assert(SafepointSynchronize::is_at_safepoint() >>>>>>>>>>>>>>>>>>>>>>>>>>>>> || >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??821 >>>>>>>>>>>>>>>>>>>>>>>>>>>>> java_thread->is_thread_fully_suspended(false, >>>>>>>>>>>>>>>>>>>>>>>>>>>>> &debug_bits) || >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??822 current_thread == >>>>>>>>>>>>>>>>>>>>>>>>>>>>> java_thread->active_handshaker(), >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??823????????? "at safepoint / handshake or >>>>>>>>>>>>>>>>>>>>>>>>>>>>> target thread is suspended"); >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> I don't think the suspension check is >>>>>>>>>>>>>>>>>>>>>>>>>>>>> necessary, as even if the target is >>>>>>>>>>>>>>>>>>>>>>>>>>>>> suspended we must still be at a safepoint >>>>>>>>>>>>>>>>>>>>>>>>>>>>> or in a handshake with it. Makes me wonder >>>>>>>>>>>>>>>>>>>>>>>>>>>>> if we used to allow a racy stacktrace >>>>>>>>>>>>>>>>>>>>>>>>>>>>> operation on a suspended thread, assuming >>>>>>>>>>>>>>>>>>>>>>>>>>>>> it would remain suspended? >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> 1268?? oop thread_oop = jt->threadObj(); >>>>>>>>>>>>>>>>>>>>>>>>>>>>> 1269 >>>>>>>>>>>>>>>>>>>>>>>>>>>>> 1270?? if (!jt->is_exiting() && >>>>>>>>>>>>>>>>>>>>>>>>>>>>> (jt->threadObj() != NULL)) { >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> You can use thread_oop in line 1270. >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> 1272 >>>>>>>>>>>>>>>>>>>>>>>>>>>>> _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, >>>>>>>>>>>>>>>>>>>>>>>>>>>>> thread_oop), >>>>>>>>>>>>>>>>>>>>>>>>>>>>> 1273 jt, thread_oop); >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> It is frustrating that this entire call >>>>>>>>>>>>>>>>>>>>>>>>>>>>> chain started with a jthread reference, >>>>>>>>>>>>>>>>>>>>>>>>>>>>> which we converted to a JavaThread, only to >>>>>>>>>>>>>>>>>>>>>>>>>>>>> eventually need to convert it back to a >>>>>>>>>>>>>>>>>>>>>>>>>>>>> jthread! I think there is some scope for >>>>>>>>>>>>>>>>>>>>>>>>>>>>> simplification here but not as part of this >>>>>>>>>>>>>>>>>>>>>>>>>>>>> change. >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> IIUC at this point the _calling_thread is >>>>>>>>>>>>>>>>>>>>>>>>>>>>> the current thread, so we can use: >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> Please add @bug lines to the tests. >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> I'm still pondering the test logic but >>>>>>>>>>>>>>>>>>>>>>>>>>>>> wanted to send this now. >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> VM_GetThreadListStackTrace (for >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> GetThreadListStackTraces) and >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> VM_GetAllStackTraces (for >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> GetAllStackTraces) have inherited >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> VM_GetMultipleStackTraces VM operation >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> which provides the feature to generate >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> jvmtiStackInfo. I modified >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> VM_GetMultipleStackTraces to a normal C++ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> class to share with HandshakeClosure for >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> GetThreadListStackTraces >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> (GetSingleStackTraceClosure). >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Also I added new testcases which test >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> GetThreadListStackTraces() with >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> thread_count == 1 and with all threads. >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> This change has been tested in >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> serviceability/jvmti serviceability/jdwp >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> vmTestbase/nsk/jvmti vmTestbase/nsk/jdi >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> vmTestbase/nsk/jdwp. >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> On 2020/06/24 15:50, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Hi all, >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Please review this change: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ?? JBS: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> https://bugs.openjdk.java.net/browse/JDK-8242428 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ?? webrev: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.00/ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> This change replace following VM >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> operations to direct handshake. >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??- VM_GetFrameCount (GetFrameCount()) >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??- VM_GetFrameLocation (GetFrameLocation()) >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??- VM_GetThreadListStackTraces >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> (GetThreadListStackTrace()) >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??- VM_GetCurrentLocation >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> GetThreadListStackTrace() uses direct >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> handshake if thread count == 1. In other >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> case (thread count > 1), it would be >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> performed as VM operation >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> (VM_GetThreadListStackTraces). >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Caller of VM_GetCurrentLocation >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> (JvmtiEnvThreadState::reset_current_location()) >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> might be called at safepoint. So I added >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> safepoint check in its caller. >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> This change has been tested in >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> serviceability/jvmti serviceability/jdwp >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> vmTestbase/nsk/jvmti vmTestbase/nsk/jdi >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> vmTestbase/ns >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> k/jdwp. >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Also I tested it on submit repo, then it >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> has execution error >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> (mach5-one-ysuenaga-JDK-8242428-20200624-0054-12034717) >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> due to dependency error. So I think it >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> does not occur by this change. >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>> >>>>>>>> From suenaga at oss.nttdata.com Wed Jul 8 14:00:46 2020 From: suenaga at oss.nttdata.com (Yasumasa Suenaga) Date: Wed, 8 Jul 2020 23:00:46 +0900 Subject: RFR: 8242428: JVMTI thread operations should use Thread-Local Handshake In-Reply-To: <0fb1d65e-d888-7fcf-548b-58172d507ea8@oracle.com> References: <6c263e4c-0a83-be7a-0288-ecb2de0b7cea@oss.nttdata.com> <04e09eb7-9483-8f63-4bb4-01c9e814802e@oracle.com> <238a89a3-06b1-90e4-d5a4-8dc2f1ed12ab@oracle.com> <4c43bc2c-551e-d042-8fa7-b63e755888d1@oracle.com> <8c387550-a06e-6320-f453-0e898486befb@oss.nttdata.com> <19cfa2a7-f441-425d-5623-1c11c6a870b6@oss.nttdata.com> <237e8d26-d185-1008-6e07-5b9f36314534@oracle.com> <0fb1d65e-d888-7fcf-548b-58172d507ea8@oracle.com> Message-ID: Thanks David! Yasumasa On 2020/07/08 21:29, David Holmes wrote: > On 8/07/2020 6:04 pm, Yasumasa Suenaga wrote: >> Hi David, >> >> On 2020/07/08 15:27, David Holmes wrote: >>> Hi Yasumasa, >>> >>> On 7/07/2020 6:54 pm, Yasumasa Suenaga wrote: >>>> Hi David, Serguei, >>>> >>>> Serguei, thank you for replying even though you are on vacaiton! >>>> >>>> I uploaded new webrev: >>>> >>>> ?? http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.07/ >>>> ?? Diff from previous webrev: http://hg.openjdk.java.net/jdk/submit/rev/77243b1dcbfe >>>> >>>> c'tor of GetSingleStackTraceClosure has jthread argument in this webrev. >>>> Also it does not contain testcase for GetThreadListStackTraces with all threads, and OneGetThreadListStackTraces would test main thread only. >>> >>> All those changes are fine in principle for me. One nit/suggestion: >>> >>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>> >>> ??544?? jthread _java_thread; >>> >>> elsewhere "java_thread" refers to a JavaThread, so to avoid confusion may I suggest this member be named _jthread. >> >> I uploaded new webrev: >> >> ?? http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.08/ >> ?? Diff from previous webrev: http://hg.openjdk.java.net/jdk/submit/rev/ca6263dbdc87 > > That looks fine. > > Thanks, > David > ----- > >> >>> I'm going to be away for the next couple of days - sorry - but will try to check email on this if I can. >> >> Thanks! >> >> >> Yasumasa >> >> >>> Thanks, >>> David >>> ----- >>> >>>> >>>> Thanks, >>>> >>>> Yasumasa >>>> >>>> >>>> On 2020/07/07 15:13, David Holmes wrote: >>>>> On 7/07/2020 2:57 pm, Yasumasa Suenaga wrote: >>>>>> Hi David, >>>>>> >>>>>> On 2020/07/07 11:31, David Holmes wrote: >>>>>>> Hi Yasumasa, >>>>>>> >>>>>>> Hard to keep up with the changes - especially without incremental webrevs. >>>>>> >>>>>> Sorry, I will upload diff from previous webrev in the next. >>>>>> >>>>>> >>>>>>> If GetSingleStackTraceClosure also took the jthread as a constructor arg, then you wouldn't need to recreate a JNI local handle when calling _collector.fill_frames. It's a small simplification and not essential at this stage. >>>>>> >>>>>> I think we should get jthread from an argument of do_thread() because do_thread() would pass the thread which are stopped certainly. >>>>>> It might be simplification if we pass _calling_thread to MultipleStackTracesCollector. `jthread` is only needed to store jvmtiStackInfo.thread . What do you think? >>>>> >>>>> I'm not quite sure what you mean. >>>>> >>>>> I think there is a bit of a design wart with direct handshakes in that do_thread takes the target JavaThread as an argument. That's useful in a case where you want a HandshakeClosure that can be applied to multiple threads, but that's not typically what is needed with direct handshakes - there is only a single target. With a single-target HandshakeClosure you can capture all the "target" information for the operation in the closure instance. So if the actual do_thread operation wants the jthread corresponding to the target thread then we can store that in the closure rather than recomputing it (you could assert it is the same but that seems overkill to me). >>>>> >>>>>> >>>>>>> For the test ... I don't see how Java_GetThreadListStackTraces_checkCallStacks is a valid test. It gets the stacks of all live threads, then uses that information to use GetThreadListStackTraces to get the stack for the same set of threads through a different API. It then compares the two sets of stacks for each thread expecting them to be the same, but that need only be the case for the main thread. Other threads could potentially have a different stack (e.g. if this test is run with JFR enabled there will be additional threads found.) Further I would have expected that there already exist tests that check that, for a given thread (which may be suspended or known to be blocked) the same stack is found through the two different APIs. >>>>>> >>>>>> vmTestbase/nsk/jvmti/unit/GetAllStackTraces/getallstktr001 would check all of threads via GetThreadListStackTraces() and GetAllStackTraces(), so we might be able to remove GetThreadListStackTraces.java from this webrev. >>>>> >>>>> Yes. The existing test only examines a set of test threads that are all blocked on a raw monitor. You do not need to duplicate that test. >>>>> >>>>>> OTOH we don't have testcase for GetThreadListStackTraces() with thread_count == 1, so we need to testcase for it (it is OneGetThreadListStackTraces.java) It would check whether the state of target thread is "waiting" before JNI call to call GetThreadListStackTraces(), >>>>> >>>>> Yes we need to test the special cases introduced by your changes - totally agree - and OneGetThreadListStackTraces.java is a good test for that. >>>>> >>>>>> and also I expect it would not be run with JFR. (it is not described @run) >>>>> >>>>> The arguments to run with JFR (or a bunch of other things) can be passed to the jtreg test harness to be applied to all tests. >>>>> >>>>>> Of course we can check GetThreadListStackTraces() with main thread, but it is not the test for direct handshake for other thread. >>>>> >>>>> Right - that test already exists as per the above. >>>>> >>>>> Thanks, >>>>> David >>>>> >>>>>> >>>>>> Thanks, >>>>>> >>>>>> Yasumasa >>>>>> >>>>>> >>>>>>> Thanks, >>>>>>> David >>>>>>> ----- >>>>>>> >>>>>>> On 6/07/2020 11:29 pm, Yasumasa Suenaga wrote: >>>>>>>> Hi Serguei, >>>>>>>> >>>>>>>> Thanks for your comment! >>>>>>>> >>>>>>>> I think C++ is more simple to implement the test agent as you said. >>>>>>>> So I implement it in C++ in new webrev. Could you review again? >>>>>>>> >>>>>>>> ?? http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.06/ >>>>>>>> >>>>>>>> Also I refactored libGetThreadListStackTraces.cpp, and I've kept exception check after IsSameObject(). >>>>>>>> >>>>>>>> >>>>>>>> Thanks, >>>>>>>> >>>>>>>> Yasumasa >>>>>>>> >>>>>>>> >>>>>>>> On 2020/07/06 16:32, serguei.spitsyn at oracle.com wrote: >>>>>>>>> Hi Yasumasa, >>>>>>>>> >>>>>>>>> Thank you for the update. >>>>>>>>> I think, a pending exception after IsSameObject needs to be checked. >>>>>>>>> >>>>>>>>> The checkStackInfo() needs one more refactoring as I've already suggested. >>>>>>>>> The body of the loop at L68-L78 should be converted to a function check_frame_info. >>>>>>>>> The si1->frame_buffer[i] and si2->frame_buffer[i] will be passed as fi1 and fi2. >>>>>>>>> The index can be passed as well. >>>>>>>>> I'm still suggesting to simplify the local exception_msg to something shorter like err_msg or exc_msg. >>>>>>>>> >>>>>>>>> I'm not sure using fatal is right here: >>>>>>>>> >>>>>>>>> This fragment looks strange: >>>>>>>>> >>>>>>>>> ? 152???? if ((*env)->IsSameObject(env, stack_info[i].thread, thread)) { >>>>>>>>> ? 153?????? target_info = &stack_info[i]; >>>>>>>>> ? 154?????? break; >>>>>>>>> ? 155???? } else if ((*env)->ExceptionOccurred(env)) { >>>>>>>>> ? 156?????? (*env)->ExceptionDescribe(env); >>>>>>>>> ? 157?????? (*env)->FatalError(env, __FILE__); >>>>>>>>> ? 158???? } >>>>>>>>> >>>>>>>>> I expected it to be: >>>>>>>>> >>>>>>>>> ??? jboolean same = (*env)->IsSameObject(env, stack_info[i].thread, thread); >>>>>>>>> ??? if ((*env)->ExceptionOccurred(env)) { >>>>>>>>> ????? (*env)->ExceptionDescribe(env); >>>>>>>>> ????? (*env)->FatalError(env, __FILE__); >>>>>>>>> ??? } >>>>>>>>> ??? if (same) { >>>>>>>>> ????? target_info = &stack_info[i]; >>>>>>>>> ????? break; >>>>>>>>> ??? } >>>>>>>>> >>>>>>>>> Would it better to port this agent to C++ to simplify this code nicer? >>>>>>>>> >>>>>>>>> Thanks, >>>>>>>>> Serguei >>>>>>>>> >>>>>>>>> >>>>>>>>> On 7/5/20 06:13, Yasumasa Suenaga wrote: >>>>>>>>>> Hi Serguei, >>>>>>>>>> >>>>>>>>>> Thanks for your comment! >>>>>>>>>> I refactored testcase. Could you review again? >>>>>>>>>> >>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.05/ >>>>>>>>>> >>>>>>>>>> It would check Java exception after IsSameObject() call. Does it need? >>>>>>>>>> Any exceptions are not described in JNI document[1], and JNI implementation (jni_IsSameObject()) does not seem to throw it. >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> Thanks, >>>>>>>>>> >>>>>>>>>> Yasumasa >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> [1] https://docs.oracle.com/en/java/javase/14/docs/specs/jni/functions.html#issameobject >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> On 2020/07/05 14:46, serguei.spitsyn at oracle.com wrote: >>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> Okay, thanks. >>>>>>>>>>> Then I'm okay to keep the GetSingleStackTraceClosure. >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libGetThreadListStackTraces.c.html >>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.c.html >>>>>>>>>>> >>>>>>>>>>> I'm not sure the function 'is_same_thread() is needed. >>>>>>>>>>> Why do not use the JNI IsSameObject instead? >>>>>>>>>>> >>>>>>>>>>> It seems to be a typo at L132 and L137. >>>>>>>>>>> You, probably. did not want to print the same information for stack_info_1[i].frame_buffer[j].XXX twice. >>>>>>>>>>> >>>>>>>>>>> The code at lines 112-142 is not readable. >>>>>>>>>>> I'd suggest to make a couple of refactoring steps. >>>>>>>>>>> >>>>>>>>>>> First step to simplify this a little bit would be with some renaming and getting rid of indexes: >>>>>>>>>>> >>>>>>>>>>> ?? 71 char err_msg[EXCEPTION_MSG_LEN] = {0}; >>>>>>>>>>> ??... >>>>>>>>>>> ??112?? /* Iterate all jvmtiStackInfo to check */ >>>>>>>>>>> ??113?? for (i = 0; i < num_threads, *exception_msg != '\0'; i++) { >>>>>>>>>>> ????????? jvmtiStackInfo *si1 = stack_info_1[i]; >>>>>>>>>>> ????????? jvmtiStackInfo *si2 = stack_info_2[i]; >>>>>>>>>>> ??114???? if (!IsSameObject(env, si1.thread, si2.thread)) { /* jvmtiStackInfo::thread */ >>>>>>>>>>> ??115?????? snprintf(err_msg, sizeof(err_msg), >>>>>>>>>>> ??116??????????????? "thread[%d] is different: stack_info_1 = %p, stack_info_2 = %p", >>>>>>>>>>> ??117??????????????? i, sinfo1.thread, sinfo2.thread); >>>>>>>>>>> ??118???? } else if (si1.state != si2.state) { /* jvmtiStackInfo::state */ >>>>>>>>>>> ??119?????? snprintf(err_msg, sizeof(err_msg), >>>>>>>>>>> ??120??????????????? "state[%d] is different: stack_info_1 = %d, stack_info_2 = %d", >>>>>>>>>>> ??121??????????????? i, si1.state, si2.state); >>>>>>>>>>> ??122???? } else if (si1.frame_count != si2.frame_count) { /* jvmtiStackInfo::frame_count */ >>>>>>>>>>> ??123?????? snprintf(err_msg, sizeof(err_msg), >>>>>>>>>>> ??124??????????????? "frame_count[%d] is different: stack_info_1 = %d, stack_info_2 = %d", >>>>>>>>>>> ??125??????????????? i, si1.frame_count, si2.frame_count); >>>>>>>>>>> ??126???? } else { >>>>>>>>>>> ??127?????? /* Iterate all jvmtiFrameInfo to check */ >>>>>>>>>>> ??128?????? for (j = 0; j < si1.frame_count; j++) { >>>>>>>>>>> ??129???????? if (si1.frame_buffer[j].method != si1.frame_buffer[j].method) { /* jvmtiFrameInfo::method */ >>>>>>>>>>> ??130?????????? snprintf(err_msg, sizeof(err_msg), >>>>>>>>>>> ??131??????????????????? "thread [%d] frame_buffer[%d].method is different: stack_info_1 = %lx, stack_info_2 = %lx", >>>>>>>>>>> ??132??????????????????? i, j, si1.frame_buffer[j].method, si2.frame_buffer[j].method); >>>>>>>>>>> ??133?????????? break; >>>>>>>>>>> ??134???????? } else if (si1.frame_buffer[j].location != si1.frame_buffer[j].location) { /* jvmtiFrameInfo::location */ >>>>>>>>>>> ??135?????????? snprintf(err_msg, sizeof(err_msg), >>>>>>>>>>> ??136??????????????????? "thread [%d] frame_buffer[%d].location is different: stack_info_1 = %ld, stack_info_2 = %ld", >>>>>>>>>>> ??137??????????????????? i, j, si1.frame_buffer[j].location, si2.frame_buffer[j].location); >>>>>>>>>>> ??138?????????? break; >>>>>>>>>>> ??139???????? } >>>>>>>>>>> ??140?????? } >>>>>>>>>>> ??141???? } >>>>>>>>>>> ??142?? } >>>>>>>>>>> >>>>>>>>>>> Another step would be to create functions that implement a body of each loop. >>>>>>>>>>> You can use the same techniques to simplify similar place (L127-L138) in the libOneGetThreadListStackTraces.c. >>>>>>>>>>> >>>>>>>>>>> Thanks, >>>>>>>>>>> Serguei >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> On 7/3/20 15:55, Yasumasa Suenaga wrote: >>>>>>>>>>>> Hi Serguei, >>>>>>>>>>>> >>>>>>>>>>>> I'm not an Oracle employee, so I cannot know real request(s) from your customers. >>>>>>>>>>>> However JDK-8201641 says Dynatrace has requested this enhancement. >>>>>>>>>>>> >>>>>>>>>>>> BTW I haven't heared any request from my customers about this. >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> Thanks, >>>>>>>>>>>> >>>>>>>>>>>> Yasumasa >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> On 2020/07/04 4:32, serguei.spitsyn at oracle.com wrote: >>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>> >>>>>>>>>>>>> This difference is not that big to care about. >>>>>>>>>>>>> I feel this is really rare case and so, does not worth these complications. >>>>>>>>>>>>> Do we have a real request from customers to optimize it? >>>>>>>>>>>>> >>>>>>>>>>>>> Thanks, >>>>>>>>>>>>> Serguei >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> On 7/3/20 01:16, Yasumasa Suenaga wrote: >>>>>>>>>>>>>> Hi Serguei, >>>>>>>>>>>>>> >>>>>>>>>>>>>> Generally I agree with you, but I have concern about the difference of the result of GetStackTrace() and GetThreadListStackTraces(). >>>>>>>>>>>>>> >>>>>>>>>>>>>> ? GetStackTrace: jvmtiFrameInfo >>>>>>>>>>>>>> ? GetThreadListStackTraces: jvmtiStackInfo >>>>>>>>>>>>>> >>>>>>>>>>>>>> jvmtiStackInfo contains thread state, and it is ensured it is the state of the call stack. >>>>>>>>>>>>>> If we want to get both call stack and thread state, we need to suspend target thread, and call both GetStackTrace() and GetThreadState(). Is it ok? >>>>>>>>>>>>>> >>>>>>>>>>>>>> I was wondering if JDK-8201641 (parent ticket of this change) needed them for profiling (dynatrace?) >>>>>>>>>>>>>> If it is responsibility of JVMTI agent implementor, I remove this closure. >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>> >>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> On 2020/07/03 16:45, serguei.spitsyn at oracle.com wrote: >>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> After some thinking I've concluded that I do not like this optimization >>>>>>>>>>>>>>> of the GetThreadListStackTraces with GetSingleStackTraceClosure. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> We may need more opinions on this but these are my points: >>>>>>>>>>>>>>> ??- it adds some complexity and ugliness >>>>>>>>>>>>>>> ??- a win is doubtful because it has to be a rare case, so that total overhead should not be high >>>>>>>>>>>>>>> ??- if it is really high for some use cases then it is up to the user >>>>>>>>>>>>>>> ??? to optimize it with using GetStackTrace instead >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> In such cases with doubtful overhead I usually prefer the simplicity. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Good examples where it makes sense to optimize are checks for target thread to be current thread. >>>>>>>>>>>>>>> In such cases there is no need to suspend the target thread, or use a VMop/HandshakeClosure. >>>>>>>>>>>>>>> For instance, please, see the Monitor functions with the check: (java_thread == calling_thread). >>>>>>>>>>>>>>> Getting information for current thread is frequently used case, e.g. to get info at an event point. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>> Serguei >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> On 7/2/20 23:29, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>> Hi Dan, David, >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> I uploaded new webrev. Could you review again? >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/ >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> OneGetThreadListStackTraces.java in this webrev would wait until thread state is transited to "waiting" with spin wait. >>>>>>>>>>>>>>>> CountDownLatch::await call as Dan pointed is fixed in it :) >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Diff from webrev.03: >>>>>>>>>>>>>>>> http://hg.openjdk.java.net/jdk/submit/rev/c9aeb7001e50 >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> On 2020/07/03 14:15, David Holmes wrote: >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> On 3/07/2020 2:27 pm, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>> On 2020/07/03 12:24, Daniel D. Daugherty wrote: >>>>>>>>>>>>>>>>>>> On 7/2/20 10:50 PM, David Holmes wrote: >>>>>>>>>>>>>>>>>>>> Sorry I'm responding here without seeing latest webrev but there is enough context I think ... >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> On 3/07/2020 9:14 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>> Hi Dan, >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Thanks for your comment! >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> On 2020/07/03 7:16, Daniel D. Daugherty wrote: >>>>>>>>>>>>>>>>>>>>>> On 7/2/20 5:19 AM, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> I upload new webrev. Could you review again? >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.03/ >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnv.cpp >>>>>>>>>>>>>>>>>>>>>> ???? L1542: ??? // Get stack trace with handshake >>>>>>>>>>>>>>>>>>>>>> ???????? nit - please add a period at the end. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> ???? L1591: *stack_info_ptr = op.stack_info(); >>>>>>>>>>>>>>>>>>>>>> ???????? The return parameter should not be touched unless the return >>>>>>>>>>>>>>>>>>>>>> ???????? code in 'err' == JVMTI_ERROR_NONE. >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> ???? old L1582: ? if (err == JVMTI_ERROR_NONE) { >>>>>>>>>>>>>>>>>>>>>> ???????? Please restore this check. The return parameter should not >>>>>>>>>>>>>>>>>>>>>> ???????? be touched unless the return code in 'err' == JVMTI_ERROR_NONE. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> But op.stack_info() will return NULL if the error is not JVMTI_ERROR_NONE. Are you (Dan) concerned about someone passing in a non-null/initialized out-pointer that will be reset to NULL if there was an error? >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Actually the way we used to test this in POSIX tests is to call >>>>>>>>>>>>>>>>>>> an API with known bad parameters and the return parameter ptr >>>>>>>>>>>>>>>>>>> set to NULL. If the return parameter ptr was touched when an >>>>>>>>>>>>>>>>>>> error should have been detected on an earlier parameter, then >>>>>>>>>>>>>>>>>>> the test failed. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> ???? L1272: ? if (!jt->is_exiting() && (thread_oop != NULL)) { >>>>>>>>>>>>>>>>>>>>>> ???????? nit - extra parens around the second expression. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>>>>>>>>>> ???? old L1532: ? _result = JVMTI_ERROR_THREAD_NOT_ALIVE; >>>>>>>>>>>>>>>>>>>>>> ???????? This deletion of the _result field threw me for a minute and then >>>>>>>>>>>>>>>>>>>>>> ???? ? ? I figured out that the field is init to JVMTI_ERROR_THREAD_NOT_ALIVE >>>>>>>>>>>>>>>>>>>>>> ???????? in the constructor. >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> ???? L1553: ? if (!jt->is_exiting() && (jt->threadObj() != NULL)) { >>>>>>>>>>>>>>>>>>>>>> ???????? nit - extra parens around the second expression. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>>>>>>>>>>>>>>>>>> ???? No comments. >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> src/hotspot/share/runtime/vmOperations.hpp >>>>>>>>>>>>>>>>>>>>>> ???? No comments. >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/GetThreadListStackTraces.java >>>>>>>>>>>>>>>>>>>>>> ???? No comments. >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/OneGetThreadListStackTraces.java >>>>>>>>>>>>>>>>>>>>>> ???? L64: ??????? startSignal.countDown(); >>>>>>>>>>>>>>>>>>>>>> ???????? I was expecting this to be a call to await() instead of >>>>>>>>>>>>>>>>>>>>>> ???????? countDown(). What am I missing here? >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> ???????? I think this test might be passing by accident right now, but... >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Main thread (which call JVMTI functions to test) should wait until test thread is ready. >>>>>>>>>>>>>>>>>>>>> So main thread would wait startSignal, and test thread would count down. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> No! >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> The test thread that previously called obj.wait() now calls latch.await(). >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> The main thread that previously called obj.notify() now calls latch.countDown(). >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> The main thread continues to spin until it sees the target is WAITING before proceeding with the test. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> If I add spin wait to wait until transit target thread state is WAITING (as following), we don't need to call SuspendThread(). >>>>>>>>>>>>>>>>>> Which is better? >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> The original spin-wait loop checking for? WAITING is better because it is the only guarantee that the target thread is blocked where you need it to be. suspending the thread is racy as you don't know exactly where the suspend will hit. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>> /* Wait until the thread state transits to "waiting" */ >>>>>>>>>>>>>>>>>> while (th.getState() != Thread.State.WAITING) { >>>>>>>>>>>>>>>>>> ???? Thread.onSpinWait(); >>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> For simplify, spin wait is prefer to OneGetThreadListStackTraces.java in webrev.03. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Here's the flow as I see it: >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> main thread >>>>>>>>>>>>>>>>>>> ?? - start worker thread >>>>>>>>>>>>>>>>>>> ?? - startSignal.await() >>>>>>>>>>>>>>>>>>> ???? - main is now blocked >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> worker thread >>>>>>>>>>>>>>>>>>> ?? - startSignal.countDown() >>>>>>>>>>>>>>>>>>> ???? - main is now unblocked >>>>>>>>>>>>>>>>>>> ?? - stopSignal.await() >>>>>>>>>>>>>>>>>>> ???? - worker is now blocked >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> main thread >>>>>>>>>>>>>>>>>>> ?? - checkCallStacks(th) >>>>>>>>>>>>>>>>>>> ?? - stopSignal.countDown() >>>>>>>>>>>>>>>>>>> ???? - worker is now unblocked >>>>>>>>>>>>>>>>>>> ?? - th.join >>>>>>>>>>>>>>>>>>> ???? - main is now blocked >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> worker thread >>>>>>>>>>>>>>>>>>> ?? - runs off the end of run() >>>>>>>>>>>>>>>>>>> ???? - main is now unblocked >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> main thread >>>>>>>>>>>>>>>>>>> ?? - run off the end of main() >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libGetThreadListStackTraces.c >>>>>>>>>>>>>>>>>>>>>> ???? L92: ? jthreads = (jthread *)malloc(sizeof(jthread) * num_threads); >>>>>>>>>>>>>>>>>>>>>> ???????? You don't check for malloc() failure. >>>>>>>>>>>>>>>>>>>>>> ???????? 'jthreads' is allocated but never freed. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.c >>>>>>>>>>>>>>>>>>>>>> ???? L91: ? result = (*jvmti)->SuspendThread(jvmti, thread); >>>>>>>>>>>>>>>>>>>>>> ???????? Why are you suspending the thread? GetAllStackTraces() and >>>>>>>>>>>>>>>>>>>>>> ???????? GetThreadListStackTraces() do not require the target thread(s) >>>>>>>>>>>>>>>>>>>>>> ???????? to be suspend. >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> ???????? If you decide not to SuspendThread, then you don't need the >>>>>>>>>>>>>>>>>>>>>> ???????? AddCapabilities or the ResumeThread calls. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Test thread might not be entered following code (stopSignal.await()). We might see deferent call stack between GetAllStackTraces() and GetThreadListStackTraces(). We cannot control to freeze call stack of test thread in Java code. >>>>>>>>>>>>>>>>>>>>> (I didn't use SuspendThread() at first, but I saw some errors which causes in above.) >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> So we need to call SuspendThread() to ensure we can see same call stack. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> If you are checking that the thread is in state WAITING then it cannot escape from that state and you can sample the stack multiple times from any API and get the same result. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> I suspect the errors you saw were from the apparent incorrect use of the CountDownLatch. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> With the flow outlined above, the worker thread should be >>>>>>>>>>>>>>>>>>> nicely blocked in stopSignal.await() when stuff is sampled. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Dan >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Cheers, >>>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Dan >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> On 2020/07/02 15:05, David Holmes wrote: >>>>>>>>>>>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> On 1/07/2020 11:53 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>>>>> Hi, >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> I uploaded new webrev. Could review again? >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.02/ >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Updates look fine - thanks. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> One minor nit: >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> 1274 _collector.allocate_and_fill_stacks(1); >>>>>>>>>>>>>>>>>>>>>>>> 1275 _collector.set_result(JVMTI_ERROR_NONE); >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> In the other places where you use _collector you rely on result being initialized to JVMTI_ERROR_NONE, rather than setting it directly after allocate_and_fill_stacks(). >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Fixed. >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 820 assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 821 java_thread->is_thread_fully_suspended(false, &debug_bits) || >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 822 current_thread == java_thread->active_handshaker(), >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 823????????? "at safepoint / handshake or target thread is suspended"); >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> I don't think the suspension check is necessary, as even if the target is suspended we must still be at a safepoint or in a handshake with it. Makes me wonder if we used to allow a racy stacktrace operation on a suspended thread, assuming it would remain suspended? >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> This function (JvmtiEnvBase::get_stack_trace()) can be called to get own stack trace. For example, we can call GetStackTrace() for current thread at JVMTI event. >>>>>>>>>>>>>>>>>>>>>>>>> So I changed assert as below: >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>>>>> ??820?? assert(current_thread == java_thread || >>>>>>>>>>>>>>>>>>>>>>>>> ??821 SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>>>>>>>>>>>>> ??822????????? current_thread == java_thread->active_handshaker(), >>>>>>>>>>>>>>>>>>>>>>>>> ??823????????? "call by myself / at safepoint / at handshake"); >>>>>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Yep good catch. I hope current tests caught that. >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> They would be tested in vmTestbase/nsk/jvmti/GetStackTrace/getstacktr001/ (own call stacks), and getstacktr003 (call stacks in other thread). >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Speaking of tests ... >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> In the native code I think you need to check the success of all JNI methods that can throw exceptions - otherwise I believe the tests may trigger warnings if -Xcheck:jni is used with them. See for example: >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/libHeapMonitorTest.cpp >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> I updated testcases to check JNI and JVMTI function calls. >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> In the Java code the target thread: >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> ?? 45???? public void run() { >>>>>>>>>>>>>>>>>>>>>>>> ?? 46?????? try { >>>>>>>>>>>>>>>>>>>>>>>> ?? 47?????????? synchronized (lock) { >>>>>>>>>>>>>>>>>>>>>>>> ?? 48?????????????? lock.wait(); >>>>>>>>>>>>>>>>>>>>>>>> ?? 49 System.out.println("OK"); >>>>>>>>>>>>>>>>>>>>>>>> ?? 50?????????? } >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> is potentially susceptible to spurious wakeups. Using a CountDownLatch would be robust. >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Fixed. >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> On 2020/07/01 8:48, David Holmes wrote: >>>>>>>>>>>>>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> On 1/07/2020 9:05 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 1271 ResourceMark rm; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> IIUC at this point the _calling_thread is the current thread, so we can use: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> If so, we can call make_local() in L1272 without JavaThread (or we can pass current thread to make_local()). Is it right? >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>>>>>>>>>>>>>>>>>>> 1272 _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, thread_oop), >>>>>>>>>>>>>>>>>>>>>>>>>>> 1273 jt, thread_oop); >>>>>>>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> Sorry I got confused, _calling_thread may not be the current thread as we could be executing the handshake in the target thread itself. So the ResourceMark is correct as-is (implicitly for current thread). >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> The argument to fill_frames will be used in the jvmtiStackInfo and passed back to the _calling_thread, so it must be created via make_local(_calling_thread, ...) as you presently have. >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> On 2020/07/01 7:05, David Holmes wrote: >>>>>>>>>>>>>>>>>>>>>>>>>>>> On 1/07/2020 12:17 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> Thank you for reviewing! I will update new webrev tomorrow. >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 466 class MultipleStackTracesCollector : public StackObj { >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 498 class VM_GetAllStackTraces : public VM_Operation { >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 499 private: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 500?? JavaThread *_calling_thread; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 501?? jint _final_thread_count; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 502 MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> You can't have a StackObj as a member of another class like that as it may not be on the stack. I think MultipleStackTracesCollector should not extend any allocation class, and should always be embedded directly in another class. >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> I'm not sure what does mean "embedded". >>>>>>>>>>>>>>>>>>>>>>>>>>>>> Is it ok as below? >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>>>>>>>>> class MultipleStackTracesCollector { >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??? : >>>>>>>>>>>>>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> class GetAllStackTraces : public VM_Operation { >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ?? private: >>>>>>>>>>>>>>>>>>>>>>>>>>>>> MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> Yes that I what I meant. >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> On 2020/06/30 22:22, David Holmes wrote: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> On 30/06/2020 10:05 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Hi David, Serguei, >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> I updated webrev for 8242428. Could you review again? >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> This change migrate to use direct handshake for GetStackTrace() and GetThreadListStackTraces() (when thread_count == 1). >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.01/ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> This looks really good now! I only have a few nits below. There is one thing I don't like about it but it requires a change to the main Handshake logic to address - in JvmtiEnv::GetThreadListStackTraces you have to create a ThreadsListHandle to convert the jthread to a JavaThread, but then the Handshake::execute_direct creates another ThreadsListHandle internally. That's a waste. I will discuss with Robbin and file a RFE to have an overload of execute_direct that takes an existing TLH. Actually it's worse than that because we have another TLH in use at the entry point for the JVMTI functions, so I think there may be some scope for simplifying the use of TLH instances - future RFE. >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??451 GetStackTraceClosure(JvmtiEnv *env, jint start_depth, jint max_count, >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??452 jvmtiFrameInfo* frame_buffer, jint* count_ptr) >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??453???? : HandshakeClosure("GetStackTrace"), >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??454?????? _env(env), _start_depth(start_depth), _max_count(max_count), >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??455 _frame_buffer(frame_buffer), _count_ptr(count_ptr), >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??456 _result(JVMTI_ERROR_THREAD_NOT_ALIVE) { >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Nit: can you do one initializer per line please. >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> This looks wrong: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 466 class MultipleStackTracesCollector : public StackObj { >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??498 class VM_GetAllStackTraces : public VM_Operation { >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??499 private: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??500?? JavaThread *_calling_thread; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??501?? jint _final_thread_count; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??502 MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> You can't have a StackObj as a member of another class like that as it may not be on the stack. I think MultipleStackTracesCollector should not extend any allocation class, and should always be embedded directly in another class. >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 481 MultipleStackTracesCollector(JvmtiEnv *env, jint max_frame_count) { >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??482???? _env = env; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??483???? _max_frame_count = max_frame_count; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??484 _frame_count_total = 0; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??485???? _head = NULL; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??486???? _stack_info = NULL; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??487???? _result = JVMTI_ERROR_NONE; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??488?? } >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> As you are touching this can you change it to use an initializer list as you did for the HandshakeClosure, and please keep one item per line. >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??820 assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??821 java_thread->is_thread_fully_suspended(false, &debug_bits) || >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??822 current_thread == java_thread->active_handshaker(), >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??823????????? "at safepoint / handshake or target thread is suspended"); >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> I don't think the suspension check is necessary, as even if the target is suspended we must still be at a safepoint or in a handshake with it. Makes me wonder if we used to allow a racy stacktrace operation on a suspended thread, assuming it would remain suspended? >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 1268?? oop thread_oop = jt->threadObj(); >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 1269 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 1270?? if (!jt->is_exiting() && (jt->threadObj() != NULL)) { >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> You can use thread_oop in line 1270. >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 1272 _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, thread_oop), >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 1273 jt, thread_oop); >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> It is frustrating that this entire call chain started with a jthread reference, which we converted to a JavaThread, only to eventually need to convert it back to a jthread! I think there is some scope for simplification here but not as part of this change. >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 1271???? ResourceMark rm; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> IIUC at this point the _calling_thread is the current thread, so we can use: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ???? ResourceMark rm(_calling_thread); >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Please add @bug lines to the tests. >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> I'm still pondering the test logic but wanted to send this now. >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> VM_GetThreadListStackTrace (for GetThreadListStackTraces) and VM_GetAllStackTraces (for GetAllStackTraces) have inherited VM_GetMultipleStackTraces VM operation which provides the feature to generate jvmtiStackInfo. I modified VM_GetMultipleStackTraces to a normal C++ class to share with HandshakeClosure for GetThreadListStackTraces (GetSingleStackTraceClosure). >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Also I added new testcases which test GetThreadListStackTraces() with thread_count == 1 and with all threads. >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> This change has been tested in serviceability/jvmti serviceability/jdwp vmTestbase/nsk/jvmti vmTestbase/nsk/jdi vmTestbase/nsk/jdwp. >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> On 2020/06/24 15:50, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Hi all, >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Please review this change: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ?? JBS: https://bugs.openjdk.java.net/browse/JDK-8242428 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ?? webrev: http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.00/ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> This change replace following VM operations to direct handshake. >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??- VM_GetFrameCount (GetFrameCount()) >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??- VM_GetFrameLocation (GetFrameLocation()) >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??- VM_GetThreadListStackTraces (GetThreadListStackTrace()) >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??- VM_GetCurrentLocation >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> GetThreadListStackTrace() uses direct handshake if thread count == 1. In other case (thread count > 1), it would be performed as VM operation (VM_GetThreadListStackTraces). >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Caller of VM_GetCurrentLocation (JvmtiEnvThreadState::reset_current_location()) might be called at safepoint. So I added safepoint check in its caller. >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> This change has been tested in serviceability/jvmti serviceability/jdwp vmTestbase/nsk/jvmti vmTestbase/nsk/jdi vmTestbase/ns >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> k/jdwp. >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Also I tested it on submit repo, then it has execution error (mach5-one-ysuenaga-JDK-8242428-20200624-0054-12034717) due to dependency error. So I think it does not occur by this change. >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>> >>>>>>>>> From daniel.daugherty at oracle.com Wed Jul 8 16:42:42 2020 From: daniel.daugherty at oracle.com (Daniel D. Daugherty) Date: Wed, 8 Jul 2020 12:42:42 -0400 Subject: RFR: 8242428: JVMTI thread operations should use Thread-Local Handshake In-Reply-To: References: <6c263e4c-0a83-be7a-0288-ecb2de0b7cea@oss.nttdata.com> <7dc1903b-6295-3864-6301-4c02aacdb971@oss.nttdata.com> <04e09eb7-9483-8f63-4bb4-01c9e814802e@oracle.com> <238a89a3-06b1-90e4-d5a4-8dc2f1ed12ab@oracle.com> <4c43bc2c-551e-d042-8fa7-b63e755888d1@oracle.com> <8c387550-a06e-6320-f453-0e898486befb@oss.nttdata.com> <19cfa2a7-f441-425d-5623-1c11c6a870b6@oss.nttdata.com> <237e8d26-d185-1008-6e07-5b9f36314534@oracle.com> Message-ID: > http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.08/ src/hotspot/share/prims/jvmtiEnv.cpp ??? No comments. src/hotspot/share/prims/jvmtiEnvBase.cpp ??? L1159: ? Thread *current_thread = Thread::current(); ??????? Please add "#ifdef ASSERT" above and "#endif" below since ??????? current_thread is only used for the assert() in this function. src/hotspot/share/prims/jvmtiEnvBase.hpp ??? L549: ???????????????????????????? jthread java_thread, jint max_frame_count) ??? L552: ????? _jthread(java_thread), ??????? Please: s/java_thread/thread/ on both lines. src/hotspot/share/runtime/vmOperations.hpp ??? No comments. test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/OneGetThreadListStackTraces.java ??? No comments. test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.cpp ??? L27: #include ??????? This include is out of order; should be first in the list. ??? This file doesn't compile on my MBP13: ./open/test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.cpp:49:14: error: format specifies type 'unsigned long' but the argument has type 'jmethodID' (aka '_jmethodID *') [-Werror,-Wformat] ???????????? fi1->method, fi2->method); ???????????? ^~~~~~~~~~~ ./open/test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.cpp:49:27: error: format specifies type 'unsigned long' but the argument has type 'jmethodID' (aka '_jmethodID *') [-Werror,-Wformat] ???????????? fi1->method, fi2->method); ????????????????????????? ^~~~~~~~~~~ ??? 2 errors generated. ??? This change made it compile on my MBP13, but that may break it on ??? other platforms: ??? $ hg diff ??? diff -r 560847c69fbe test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.cpp ??? --- a/test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.cpp Wed Jul 08 12:13:32 2020 -0400 ??? +++ b/test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.cpp Wed Jul 08 12:40:42 2020 -0400 ??? @@ -46,7 +46,7 @@ ? ?? ? if (fi1->method != fi2->method) { /* jvmtiFrameInfo::method */ ? ?? ??? snprintf(err_msg, sizeof(err_msg), ? ? ? ??????????? "method is different: fi1 = %lx, fi2 = %lx", ??? -???????????? fi1->method, fi2->method); ??? +???????????? (unsigned long) fi1->method, (unsigned long) fi2->method); ? ?? ??? env->FatalError(err_msg); ? ?? ? } else if (fi1->location != fi2->location) { /* jvmtiFrameInfo::location */ ? ?? ??? snprintf(err_msg, sizeof(err_msg), ??? I'm not sure of the right platform independent way to output ??? the 'method' field. Dan On 7/8/20 4:04 AM, Yasumasa Suenaga wrote: > Hi David, > > On 2020/07/08 15:27, David Holmes wrote: >> Hi Yasumasa, >> >> On 7/07/2020 6:54 pm, Yasumasa Suenaga wrote: >>> Hi David, Serguei, >>> >>> Serguei, thank you for replying even though you are on vacaiton! >>> >>> I uploaded new webrev: >>> >>> ?? http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.07/ >>> ?? Diff from previous webrev: >>> http://hg.openjdk.java.net/jdk/submit/rev/77243b1dcbfe >>> >>> c'tor of GetSingleStackTraceClosure has jthread argument in this >>> webrev. >>> Also it does not contain testcase for GetThreadListStackTraces with >>> all threads, and OneGetThreadListStackTraces would test main thread >>> only. >> >> All those changes are fine in principle for me. One nit/suggestion: >> >> src/hotspot/share/prims/jvmtiEnvBase.hpp >> >> ??544?? jthread _java_thread; >> >> elsewhere "java_thread" refers to a JavaThread, so to avoid confusion >> may I suggest this member be named _jthread. > > I uploaded new webrev: > > ? http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.08/ > ? Diff from previous webrev: > http://hg.openjdk.java.net/jdk/submit/rev/ca6263dbdc87 > > >> I'm going to be away for the next couple of days - sorry - but will >> try to check email on this if I can. > > Thanks! > > > Yasumasa > > >> Thanks, >> David >> ----- >> >>> >>> Thanks, >>> >>> Yasumasa >>> >>> >>> On 2020/07/07 15:13, David Holmes wrote: >>>> On 7/07/2020 2:57 pm, Yasumasa Suenaga wrote: >>>>> Hi David, >>>>> >>>>> On 2020/07/07 11:31, David Holmes wrote: >>>>>> Hi Yasumasa, >>>>>> >>>>>> Hard to keep up with the changes - especially without incremental >>>>>> webrevs. >>>>> >>>>> Sorry, I will upload diff from previous webrev in the next. >>>>> >>>>> >>>>>> If GetSingleStackTraceClosure also took the jthread as a >>>>>> constructor arg, then you wouldn't need to recreate a JNI local >>>>>> handle when calling _collector.fill_frames. It's a small >>>>>> simplification and not essential at this stage. >>>>> >>>>> I think we should get jthread from an argument of do_thread() >>>>> because do_thread() would pass the thread which are stopped >>>>> certainly. >>>>> It might be simplification if we pass _calling_thread to >>>>> MultipleStackTracesCollector. `jthread` is only needed to store >>>>> jvmtiStackInfo.thread . What do you think? >>>> >>>> I'm not quite sure what you mean. >>>> >>>> I think there is a bit of a design wart with direct handshakes in >>>> that do_thread takes the target JavaThread as an argument. That's >>>> useful in a case where you want a HandshakeClosure that can be >>>> applied to multiple threads, but that's not typically what is >>>> needed with direct handshakes - there is only a single target. With >>>> a single-target HandshakeClosure you can capture all the "target" >>>> information for the operation in the closure instance. So if the >>>> actual do_thread operation wants the jthread corresponding to the >>>> target thread then we can store that in the closure rather than >>>> recomputing it (you could assert it is the same but that seems >>>> overkill to me). >>>> >>>>> >>>>>> For the test ... I don't see how >>>>>> Java_GetThreadListStackTraces_checkCallStacks is a valid test. It >>>>>> gets the stacks of all live threads, then uses that information >>>>>> to use GetThreadListStackTraces to get the stack for the same set >>>>>> of threads through a different API. It then compares the two sets >>>>>> of stacks for each thread expecting them to be the same, but that >>>>>> need only be the case for the main thread. Other threads could >>>>>> potentially have a different stack (e.g. if this test is run with >>>>>> JFR enabled there will be additional threads found.) Further I >>>>>> would have expected that there already exist tests that check >>>>>> that, for a given thread (which may be suspended or known to be >>>>>> blocked) the same stack is found through the two different APIs. >>>>> >>>>> vmTestbase/nsk/jvmti/unit/GetAllStackTraces/getallstktr001 would >>>>> check all of threads via GetThreadListStackTraces() and >>>>> GetAllStackTraces(), so we might be able to remove >>>>> GetThreadListStackTraces.java from this webrev. >>>> >>>> Yes. The existing test only examines a set of test threads that are >>>> all blocked on a raw monitor. You do not need to duplicate that test. >>>> >>>>> OTOH we don't have testcase for GetThreadListStackTraces() with >>>>> thread_count == 1, so we need to testcase for it (it is >>>>> OneGetThreadListStackTraces.java) It would check whether the state >>>>> of target thread is "waiting" before JNI call to call >>>>> GetThreadListStackTraces(), >>>> >>>> Yes we need to test the special cases introduced by your changes - >>>> totally agree - and OneGetThreadListStackTraces.java is a good test >>>> for that. >>>> >>>>> and also I expect it would not be run with JFR. (it is not >>>>> described @run) >>>> >>>> The arguments to run with JFR (or a bunch of other things) can be >>>> passed to the jtreg test harness to be applied to all tests. >>>> >>>>> Of course we can check GetThreadListStackTraces() with main >>>>> thread, but it is not the test for direct handshake for other thread. >>>> >>>> Right - that test already exists as per the above. >>>> >>>> Thanks, >>>> David >>>> >>>>> >>>>> Thanks, >>>>> >>>>> Yasumasa >>>>> >>>>> >>>>>> Thanks, >>>>>> David >>>>>> ----- >>>>>> >>>>>> On 6/07/2020 11:29 pm, Yasumasa Suenaga wrote: >>>>>>> Hi Serguei, >>>>>>> >>>>>>> Thanks for your comment! >>>>>>> >>>>>>> I think C++ is more simple to implement the test agent as you said. >>>>>>> So I implement it in C++ in new webrev. Could you review again? >>>>>>> >>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.06/ >>>>>>> >>>>>>> Also I refactored libGetThreadListStackTraces.cpp, and I've kept >>>>>>> exception check after IsSameObject(). >>>>>>> >>>>>>> >>>>>>> Thanks, >>>>>>> >>>>>>> Yasumasa >>>>>>> >>>>>>> >>>>>>> On 2020/07/06 16:32, serguei.spitsyn at oracle.com wrote: >>>>>>>> Hi Yasumasa, >>>>>>>> >>>>>>>> Thank you for the update. >>>>>>>> I think, a pending exception after IsSameObject needs to be >>>>>>>> checked. >>>>>>>> >>>>>>>> The checkStackInfo() needs one more refactoring as I've already >>>>>>>> suggested. >>>>>>>> The body of the loop at L68-L78 should be converted to a >>>>>>>> function check_frame_info. >>>>>>>> The si1->frame_buffer[i] and si2->frame_buffer[i] will be >>>>>>>> passed as fi1 and fi2. >>>>>>>> The index can be passed as well. >>>>>>>> I'm still suggesting to simplify the local exception_msg to >>>>>>>> something shorter like err_msg or exc_msg. >>>>>>>> >>>>>>>> I'm not sure using fatal is right here: >>>>>>>> >>>>>>>> This fragment looks strange: >>>>>>>> >>>>>>>> ? 152???? if ((*env)->IsSameObject(env, stack_info[i].thread, >>>>>>>> thread)) { >>>>>>>> ? 153?????? target_info = &stack_info[i]; >>>>>>>> ? 154?????? break; >>>>>>>> ? 155???? } else if ((*env)->ExceptionOccurred(env)) { >>>>>>>> ? 156?????? (*env)->ExceptionDescribe(env); >>>>>>>> ? 157?????? (*env)->FatalError(env, __FILE__); >>>>>>>> ? 158???? } >>>>>>>> >>>>>>>> I expected it to be: >>>>>>>> >>>>>>>> ??? jboolean same = (*env)->IsSameObject(env, >>>>>>>> stack_info[i].thread, thread); >>>>>>>> ??? if ((*env)->ExceptionOccurred(env)) { >>>>>>>> ????? (*env)->ExceptionDescribe(env); >>>>>>>> ????? (*env)->FatalError(env, __FILE__); >>>>>>>> ??? } >>>>>>>> ??? if (same) { >>>>>>>> ????? target_info = &stack_info[i]; >>>>>>>> ????? break; >>>>>>>> ??? } >>>>>>>> >>>>>>>> Would it better to port this agent to C++ to simplify this code >>>>>>>> nicer? >>>>>>>> >>>>>>>> Thanks, >>>>>>>> Serguei >>>>>>>> >>>>>>>> >>>>>>>> On 7/5/20 06:13, Yasumasa Suenaga wrote: >>>>>>>>> Hi Serguei, >>>>>>>>> >>>>>>>>> Thanks for your comment! >>>>>>>>> I refactored testcase. Could you review again? >>>>>>>>> >>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.05/ >>>>>>>>> >>>>>>>>> It would check Java exception after IsSameObject() call. Does >>>>>>>>> it need? >>>>>>>>> Any exceptions are not described in JNI document[1], and JNI >>>>>>>>> implementation (jni_IsSameObject()) does not seem to throw it. >>>>>>>>> >>>>>>>>> >>>>>>>>> Thanks, >>>>>>>>> >>>>>>>>> Yasumasa >>>>>>>>> >>>>>>>>> >>>>>>>>> [1] >>>>>>>>> https://docs.oracle.com/en/java/javase/14/docs/specs/jni/functions.html#issameobject >>>>>>>>> >>>>>>>>> >>>>>>>>> On 2020/07/05 14:46, serguei.spitsyn at oracle.com wrote: >>>>>>>>>> Hi Yasumasa, >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> Okay, thanks. >>>>>>>>>> Then I'm okay to keep the GetSingleStackTraceClosure. >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libGetThreadListStackTraces.c.html >>>>>>>>>> >>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.c.html >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> I'm not sure the function 'is_same_thread() is needed. >>>>>>>>>> Why do not use the JNI IsSameObject instead? >>>>>>>>>> >>>>>>>>>> It seems to be a typo at L132 and L137. >>>>>>>>>> You, probably. did not want to print the same information for >>>>>>>>>> stack_info_1[i].frame_buffer[j].XXX twice. >>>>>>>>>> >>>>>>>>>> The code at lines 112-142 is not readable. >>>>>>>>>> I'd suggest to make a couple of refactoring steps. >>>>>>>>>> >>>>>>>>>> First step to simplify this a little bit would be with some >>>>>>>>>> renaming and getting rid of indexes: >>>>>>>>>> >>>>>>>>>> ?? 71 char err_msg[EXCEPTION_MSG_LEN] = {0}; >>>>>>>>>> ??... >>>>>>>>>> ??112?? /* Iterate all jvmtiStackInfo to check */ >>>>>>>>>> ??113?? for (i = 0; i < num_threads, *exception_msg != '\0'; >>>>>>>>>> i++) { >>>>>>>>>> ????????? jvmtiStackInfo *si1 = stack_info_1[i]; >>>>>>>>>> ????????? jvmtiStackInfo *si2 = stack_info_2[i]; >>>>>>>>>> ??114???? if (!IsSameObject(env, si1.thread, si2.thread)) { >>>>>>>>>> /* jvmtiStackInfo::thread */ >>>>>>>>>> ??115?????? snprintf(err_msg, sizeof(err_msg), >>>>>>>>>> ??116??????????????? "thread[%d] is different: stack_info_1 = >>>>>>>>>> %p, stack_info_2 = %p", >>>>>>>>>> ??117??????????????? i, sinfo1.thread, sinfo2.thread); >>>>>>>>>> ??118???? } else if (si1.state != si2.state) { /* >>>>>>>>>> jvmtiStackInfo::state */ >>>>>>>>>> ??119?????? snprintf(err_msg, sizeof(err_msg), >>>>>>>>>> ??120??????????????? "state[%d] is different: stack_info_1 = >>>>>>>>>> %d, stack_info_2 = %d", >>>>>>>>>> ??121??????????????? i, si1.state, si2.state); >>>>>>>>>> ??122???? } else if (si1.frame_count != si2.frame_count) { /* >>>>>>>>>> jvmtiStackInfo::frame_count */ >>>>>>>>>> ??123?????? snprintf(err_msg, sizeof(err_msg), >>>>>>>>>> ??124??????????????? "frame_count[%d] is different: >>>>>>>>>> stack_info_1 = %d, stack_info_2 = %d", >>>>>>>>>> ??125??????????????? i, si1.frame_count, si2.frame_count); >>>>>>>>>> ??126???? } else { >>>>>>>>>> ??127?????? /* Iterate all jvmtiFrameInfo to check */ >>>>>>>>>> ??128?????? for (j = 0; j < si1.frame_count; j++) { >>>>>>>>>> ??129???????? if (si1.frame_buffer[j].method != >>>>>>>>>> si1.frame_buffer[j].method) { /* jvmtiFrameInfo::method */ >>>>>>>>>> ??130?????????? snprintf(err_msg, sizeof(err_msg), >>>>>>>>>> ??131??????????????????? "thread [%d] frame_buffer[%d].method >>>>>>>>>> is different: stack_info_1 = %lx, stack_info_2 = %lx", >>>>>>>>>> ??132??????????????????? i, j, si1.frame_buffer[j].method, >>>>>>>>>> si2.frame_buffer[j].method); >>>>>>>>>> ??133?????????? break; >>>>>>>>>> ??134???????? } else if (si1.frame_buffer[j].location != >>>>>>>>>> si1.frame_buffer[j].location) { /* jvmtiFrameInfo::location */ >>>>>>>>>> ??135?????????? snprintf(err_msg, sizeof(err_msg), >>>>>>>>>> ??136??????????????????? "thread [%d] >>>>>>>>>> frame_buffer[%d].location is different: stack_info_1 = %ld, >>>>>>>>>> stack_info_2 = %ld", >>>>>>>>>> ??137??????????????????? i, j, si1.frame_buffer[j].location, >>>>>>>>>> si2.frame_buffer[j].location); >>>>>>>>>> ??138?????????? break; >>>>>>>>>> ??139???????? } >>>>>>>>>> ??140?????? } >>>>>>>>>> ??141???? } >>>>>>>>>> ??142?? } >>>>>>>>>> >>>>>>>>>> Another step would be to create functions that implement a >>>>>>>>>> body of each loop. >>>>>>>>>> You can use the same techniques to simplify similar place >>>>>>>>>> (L127-L138) in the libOneGetThreadListStackTraces.c. >>>>>>>>>> >>>>>>>>>> Thanks, >>>>>>>>>> Serguei >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> On 7/3/20 15:55, Yasumasa Suenaga wrote: >>>>>>>>>>> Hi Serguei, >>>>>>>>>>> >>>>>>>>>>> I'm not an Oracle employee, so I cannot know real request(s) >>>>>>>>>>> from your customers. >>>>>>>>>>> However JDK-8201641 says Dynatrace has requested this >>>>>>>>>>> enhancement. >>>>>>>>>>> >>>>>>>>>>> BTW I haven't heared any request from my customers about this. >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> Thanks, >>>>>>>>>>> >>>>>>>>>>> Yasumasa >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> On 2020/07/04 4:32, serguei.spitsyn at oracle.com wrote: >>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>> >>>>>>>>>>>> This difference is not that big to care about. >>>>>>>>>>>> I feel this is really rare case and so, does not worth >>>>>>>>>>>> these complications. >>>>>>>>>>>> Do we have a real request from customers to optimize it? >>>>>>>>>>>> >>>>>>>>>>>> Thanks, >>>>>>>>>>>> Serguei >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> On 7/3/20 01:16, Yasumasa Suenaga wrote: >>>>>>>>>>>>> Hi Serguei, >>>>>>>>>>>>> >>>>>>>>>>>>> Generally I agree with you, but I have concern about the >>>>>>>>>>>>> difference of the result of GetStackTrace() and >>>>>>>>>>>>> GetThreadListStackTraces(). >>>>>>>>>>>>> >>>>>>>>>>>>> ? GetStackTrace: jvmtiFrameInfo >>>>>>>>>>>>> ? GetThreadListStackTraces: jvmtiStackInfo >>>>>>>>>>>>> >>>>>>>>>>>>> jvmtiStackInfo contains thread state, and it is ensured it >>>>>>>>>>>>> is the state of the call stack. >>>>>>>>>>>>> If we want to get both call stack and thread state, we >>>>>>>>>>>>> need to suspend target thread, and call both >>>>>>>>>>>>> GetStackTrace() and GetThreadState(). Is it ok? >>>>>>>>>>>>> >>>>>>>>>>>>> I was wondering if JDK-8201641 (parent ticket of this >>>>>>>>>>>>> change) needed them for profiling (dynatrace?) >>>>>>>>>>>>> If it is responsibility of JVMTI agent implementor, I >>>>>>>>>>>>> remove this closure. >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> Thanks, >>>>>>>>>>>>> >>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> On 2020/07/03 16:45, serguei.spitsyn at oracle.com wrote: >>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>> >>>>>>>>>>>>>> After some thinking I've concluded that I do not like >>>>>>>>>>>>>> this optimization >>>>>>>>>>>>>> of the GetThreadListStackTraces with >>>>>>>>>>>>>> GetSingleStackTraceClosure. >>>>>>>>>>>>>> >>>>>>>>>>>>>> We may need more opinions on this but these are my points: >>>>>>>>>>>>>> ??- it adds some complexity and ugliness >>>>>>>>>>>>>> ??- a win is doubtful because it has to be a rare case, >>>>>>>>>>>>>> so that total overhead should not be high >>>>>>>>>>>>>> ??- if it is really high for some use cases then it is up >>>>>>>>>>>>>> to the user >>>>>>>>>>>>>> ??? to optimize it with using GetStackTrace instead >>>>>>>>>>>>>> >>>>>>>>>>>>>> In such cases with doubtful overhead I usually prefer the >>>>>>>>>>>>>> simplicity. >>>>>>>>>>>>>> >>>>>>>>>>>>>> Good examples where it makes sense to optimize are checks >>>>>>>>>>>>>> for target thread to be current thread. >>>>>>>>>>>>>> In such cases there is no need to suspend the target >>>>>>>>>>>>>> thread, or use a VMop/HandshakeClosure. >>>>>>>>>>>>>> For instance, please, see the Monitor functions with the >>>>>>>>>>>>>> check: (java_thread == calling_thread). >>>>>>>>>>>>>> Getting information for current thread is frequently used >>>>>>>>>>>>>> case, e.g. to get info at an event point. >>>>>>>>>>>>>> >>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>> Serguei >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> On 7/2/20 23:29, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>> Hi Dan, David, >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> I uploaded new webrev. Could you review again? >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/ >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> OneGetThreadListStackTraces.java in this webrev would >>>>>>>>>>>>>>> wait until thread state is transited to "waiting" with >>>>>>>>>>>>>>> spin wait. >>>>>>>>>>>>>>> CountDownLatch::await call as Dan pointed is fixed in it :) >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Diff from webrev.03: >>>>>>>>>>>>>>> http://hg.openjdk.java.net/jdk/submit/rev/c9aeb7001e50 >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> On 2020/07/03 14:15, David Holmes wrote: >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> On 3/07/2020 2:27 pm, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>> On 2020/07/03 12:24, Daniel D. Daugherty wrote: >>>>>>>>>>>>>>>>>> On 7/2/20 10:50 PM, David Holmes wrote: >>>>>>>>>>>>>>>>>>> Sorry I'm responding here without seeing latest >>>>>>>>>>>>>>>>>>> webrev but there is enough context I think ... >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> On 3/07/2020 9:14 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>> Hi Dan, >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Thanks for your comment! >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> On 2020/07/03 7:16, Daniel D. Daugherty wrote: >>>>>>>>>>>>>>>>>>>>> On 7/2/20 5:19 AM, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> I upload new webrev. Could you review again? >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.03/ >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnv.cpp >>>>>>>>>>>>>>>>>>>>> ???? L1542: ??? // Get stack trace with handshake >>>>>>>>>>>>>>>>>>>>> ???????? nit - please add a period at the end. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> L1591: *stack_info_ptr = op.stack_info(); >>>>>>>>>>>>>>>>>>>>> ???????? The return parameter should not be >>>>>>>>>>>>>>>>>>>>> touched unless the return >>>>>>>>>>>>>>>>>>>>> ???????? code in 'err' == JVMTI_ERROR_NONE. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> ???? old L1582: ? if (err == JVMTI_ERROR_NONE) { >>>>>>>>>>>>>>>>>>>>> ???????? Please restore this check. The return >>>>>>>>>>>>>>>>>>>>> parameter should not >>>>>>>>>>>>>>>>>>>>> ???????? be touched unless the return code in >>>>>>>>>>>>>>>>>>>>> 'err' == JVMTI_ERROR_NONE. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> But op.stack_info() will return NULL if the error is >>>>>>>>>>>>>>>>>>> not JVMTI_ERROR_NONE. Are you (Dan) concerned about >>>>>>>>>>>>>>>>>>> someone passing in a non-null/initialized >>>>>>>>>>>>>>>>>>> out-pointer that will be reset to NULL if there was >>>>>>>>>>>>>>>>>>> an error? >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Actually the way we used to test this in POSIX tests >>>>>>>>>>>>>>>>>> is to call >>>>>>>>>>>>>>>>>> an API with known bad parameters and the return >>>>>>>>>>>>>>>>>> parameter ptr >>>>>>>>>>>>>>>>>> set to NULL. If the return parameter ptr was touched >>>>>>>>>>>>>>>>>> when an >>>>>>>>>>>>>>>>>> error should have been detected on an earlier >>>>>>>>>>>>>>>>>> parameter, then >>>>>>>>>>>>>>>>>> the test failed. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> L1272: ? if (!jt->is_exiting() && (thread_oop != >>>>>>>>>>>>>>>>>>>>> NULL)) { >>>>>>>>>>>>>>>>>>>>> ???????? nit - extra parens around the second >>>>>>>>>>>>>>>>>>>>> expression. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>>>>>>>>> ???? old L1532: ? _result = >>>>>>>>>>>>>>>>>>>>> JVMTI_ERROR_THREAD_NOT_ALIVE; >>>>>>>>>>>>>>>>>>>>> ???????? This deletion of the _result field threw >>>>>>>>>>>>>>>>>>>>> me for a minute and then >>>>>>>>>>>>>>>>>>>>> ???? ? ? I figured out that the field is init to >>>>>>>>>>>>>>>>>>>>> JVMTI_ERROR_THREAD_NOT_ALIVE >>>>>>>>>>>>>>>>>>>>> ???????? in the constructor. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> ???? L1553: ? if (!jt->is_exiting() && >>>>>>>>>>>>>>>>>>>>> (jt->threadObj() != NULL)) { >>>>>>>>>>>>>>>>>>>>> ???????? nit - extra parens around the second >>>>>>>>>>>>>>>>>>>>> expression. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>>>>>>>>>>>>>>>>> ???? No comments. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> src/hotspot/share/runtime/vmOperations.hpp >>>>>>>>>>>>>>>>>>>>> ???? No comments. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/GetThreadListStackTraces.java >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> ???? No comments. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/OneGetThreadListStackTraces.java >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> ???? L64: startSignal.countDown(); >>>>>>>>>>>>>>>>>>>>> ???????? I was expecting this to be a call to >>>>>>>>>>>>>>>>>>>>> await() instead of >>>>>>>>>>>>>>>>>>>>> ???????? countDown(). What am I missing here? >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> ???????? I think this test might be passing by >>>>>>>>>>>>>>>>>>>>> accident right now, but... >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Main thread (which call JVMTI functions to test) >>>>>>>>>>>>>>>>>>>> should wait until test thread is ready. >>>>>>>>>>>>>>>>>>>> So main thread would wait startSignal, and test >>>>>>>>>>>>>>>>>>>> thread would count down. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> No! >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> The test thread that previously called obj.wait() >>>>>>>>>>>>>>>>>>> now calls latch.await(). >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> The main thread that previously called obj.notify() >>>>>>>>>>>>>>>>>>> now calls latch.countDown(). >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> The main thread continues to spin until it sees the >>>>>>>>>>>>>>>>>>> target is WAITING before proceeding with the test. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> If I add spin wait to wait until transit target thread >>>>>>>>>>>>>>>>> state is WAITING (as following), we don't need to call >>>>>>>>>>>>>>>>> SuspendThread(). >>>>>>>>>>>>>>>>> Which is better? >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> The original spin-wait loop checking for? WAITING is >>>>>>>>>>>>>>>> better because it is the only guarantee that the target >>>>>>>>>>>>>>>> thread is blocked where you need it to be. suspending >>>>>>>>>>>>>>>> the thread is racy as you don't know exactly where the >>>>>>>>>>>>>>>> suspend will hit. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>> /* Wait until the thread state transits to "waiting" */ >>>>>>>>>>>>>>>>> while (th.getState() != Thread.State.WAITING) { >>>>>>>>>>>>>>>>> ???? Thread.onSpinWait(); >>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> For simplify, spin wait is prefer to >>>>>>>>>>>>>>>>> OneGetThreadListStackTraces.java in webrev.03. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Here's the flow as I see it: >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> main thread >>>>>>>>>>>>>>>>>> ?? - start worker thread >>>>>>>>>>>>>>>>>> ?? - startSignal.await() >>>>>>>>>>>>>>>>>> ???? - main is now blocked >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> worker thread >>>>>>>>>>>>>>>>>> ?? - startSignal.countDown() >>>>>>>>>>>>>>>>>> ???? - main is now unblocked >>>>>>>>>>>>>>>>>> ?? - stopSignal.await() >>>>>>>>>>>>>>>>>> ???? - worker is now blocked >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> main thread >>>>>>>>>>>>>>>>>> ?? - checkCallStacks(th) >>>>>>>>>>>>>>>>>> ?? - stopSignal.countDown() >>>>>>>>>>>>>>>>>> ???? - worker is now unblocked >>>>>>>>>>>>>>>>>> ?? - th.join >>>>>>>>>>>>>>>>>> ???? - main is now blocked >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> worker thread >>>>>>>>>>>>>>>>>> ?? - runs off the end of run() >>>>>>>>>>>>>>>>>> ???? - main is now unblocked >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> main thread >>>>>>>>>>>>>>>>>> ?? - run off the end of main() >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libGetThreadListStackTraces.c >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> ???? L92: ? jthreads = (jthread >>>>>>>>>>>>>>>>>>>>> *)malloc(sizeof(jthread) * num_threads); >>>>>>>>>>>>>>>>>>>>> ???????? You don't check for malloc() failure. >>>>>>>>>>>>>>>>>>>>> ???????? 'jthreads' is allocated but never freed. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.c >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> ???? L91: ? result = >>>>>>>>>>>>>>>>>>>>> (*jvmti)->SuspendThread(jvmti, thread); >>>>>>>>>>>>>>>>>>>>> ???????? Why are you suspending the thread? >>>>>>>>>>>>>>>>>>>>> GetAllStackTraces() and >>>>>>>>>>>>>>>>>>>>> GetThreadListStackTraces() do not require the >>>>>>>>>>>>>>>>>>>>> target thread(s) >>>>>>>>>>>>>>>>>>>>> ???????? to be suspend. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> ???????? If you decide not to SuspendThread, then >>>>>>>>>>>>>>>>>>>>> you don't need the >>>>>>>>>>>>>>>>>>>>> ???????? AddCapabilities or the ResumeThread calls. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Test thread might not be entered following code >>>>>>>>>>>>>>>>>>>> (stopSignal.await()). We might see deferent call >>>>>>>>>>>>>>>>>>>> stack between GetAllStackTraces() and >>>>>>>>>>>>>>>>>>>> GetThreadListStackTraces(). We cannot control to >>>>>>>>>>>>>>>>>>>> freeze call stack of test thread in Java code. >>>>>>>>>>>>>>>>>>>> (I didn't use SuspendThread() at first, but I saw >>>>>>>>>>>>>>>>>>>> some errors which causes in above.) >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> So we need to call SuspendThread() to ensure we can >>>>>>>>>>>>>>>>>>>> see same call stack. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> If you are checking that the thread is in state >>>>>>>>>>>>>>>>>>> WAITING then it cannot escape from that state and >>>>>>>>>>>>>>>>>>> you can sample the stack multiple times from any API >>>>>>>>>>>>>>>>>>> and get the same result. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> I suspect the errors you saw were from the apparent >>>>>>>>>>>>>>>>>>> incorrect use of the CountDownLatch. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> With the flow outlined above, the worker thread >>>>>>>>>>>>>>>>>> should be >>>>>>>>>>>>>>>>>> nicely blocked in stopSignal.await() when stuff is >>>>>>>>>>>>>>>>>> sampled. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Dan >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Cheers, >>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Dan >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> On 2020/07/02 15:05, David Holmes wrote: >>>>>>>>>>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> On 1/07/2020 11:53 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>>>> Hi, >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> I uploaded new webrev. Could review again? >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.02/ >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Updates look fine - thanks. >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> One minor nit: >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> 1274 _collector.allocate_and_fill_stacks(1); >>>>>>>>>>>>>>>>>>>>>>> 1275 _collector.set_result(JVMTI_ERROR_NONE); >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> In the other places where you use _collector you >>>>>>>>>>>>>>>>>>>>>>> rely on result being initialized to >>>>>>>>>>>>>>>>>>>>>>> JVMTI_ERROR_NONE, rather than setting it >>>>>>>>>>>>>>>>>>>>>>> directly after allocate_and_fill_stacks(). >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Fixed. >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 820 >>>>>>>>>>>>>>>>>>>>>>>>>>>>> assert(SafepointSynchronize::is_at_safepoint() >>>>>>>>>>>>>>>>>>>>>>>>>>>>> || >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 821 >>>>>>>>>>>>>>>>>>>>>>>>>>>>> java_thread->is_thread_fully_suspended(false, >>>>>>>>>>>>>>>>>>>>>>>>>>>>> &debug_bits) || >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 822 current_thread == >>>>>>>>>>>>>>>>>>>>>>>>>>>>> java_thread->active_handshaker(), >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 823 "at safepoint / handshake or target >>>>>>>>>>>>>>>>>>>>>>>>>>>>> thread is suspended"); >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> I don't think the suspension check is >>>>>>>>>>>>>>>>>>>>>>>>>>>>> necessary, as even if the target is >>>>>>>>>>>>>>>>>>>>>>>>>>>>> suspended we must still be at a safepoint >>>>>>>>>>>>>>>>>>>>>>>>>>>>> or in a handshake with it. Makes me wonder >>>>>>>>>>>>>>>>>>>>>>>>>>>>> if we used to allow a racy stacktrace >>>>>>>>>>>>>>>>>>>>>>>>>>>>> operation on a suspended thread, assuming >>>>>>>>>>>>>>>>>>>>>>>>>>>>> it would remain suspended? >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> This function (JvmtiEnvBase::get_stack_trace()) >>>>>>>>>>>>>>>>>>>>>>>> can be called to get own stack trace. For >>>>>>>>>>>>>>>>>>>>>>>> example, we can call GetStackTrace() for >>>>>>>>>>>>>>>>>>>>>>>> current thread at JVMTI event. >>>>>>>>>>>>>>>>>>>>>>>> So I changed assert as below: >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>>>> ??820 assert(current_thread == java_thread || >>>>>>>>>>>>>>>>>>>>>>>> ??821 SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>>>>>>>>>>>> ??822 current_thread == >>>>>>>>>>>>>>>>>>>>>>>> java_thread->active_handshaker(), >>>>>>>>>>>>>>>>>>>>>>>> ??823????????? "call by myself / at safepoint / >>>>>>>>>>>>>>>>>>>>>>>> at handshake"); >>>>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Yep good catch. I hope current tests caught that. >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> They would be tested in >>>>>>>>>>>>>>>>>>>>>> vmTestbase/nsk/jvmti/GetStackTrace/getstacktr001/ >>>>>>>>>>>>>>>>>>>>>> (own call stacks), and getstacktr003 (call stacks >>>>>>>>>>>>>>>>>>>>>> in other thread). >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Speaking of tests ... >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> In the native code I think you need to check the >>>>>>>>>>>>>>>>>>>>>>> success of all JNI methods that can throw >>>>>>>>>>>>>>>>>>>>>>> exceptions - otherwise I believe the tests may >>>>>>>>>>>>>>>>>>>>>>> trigger warnings if -Xcheck:jni is used with >>>>>>>>>>>>>>>>>>>>>>> them. See for example: >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/libHeapMonitorTest.cpp >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> I updated testcases to check JNI and JVMTI >>>>>>>>>>>>>>>>>>>>>> function calls. >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> In the Java code the target thread: >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> ?? 45???? public void run() { >>>>>>>>>>>>>>>>>>>>>>> ?? 46?????? try { >>>>>>>>>>>>>>>>>>>>>>> ?? 47 synchronized (lock) { >>>>>>>>>>>>>>>>>>>>>>> ?? 48 lock.wait(); >>>>>>>>>>>>>>>>>>>>>>> ?? 49 System.out.println("OK"); >>>>>>>>>>>>>>>>>>>>>>> ?? 50?????????? } >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> is potentially susceptible to spurious wakeups. >>>>>>>>>>>>>>>>>>>>>>> Using a CountDownLatch would be robust. >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Fixed. >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> On 2020/07/01 8:48, David Holmes wrote: >>>>>>>>>>>>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> On 1/07/2020 9:05 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> 1271 ResourceMark rm; >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> IIUC at this point the _calling_thread is >>>>>>>>>>>>>>>>>>>>>>>>>>>>> the current thread, so we can use: >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ResourceMark rm(_calling_thread); >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> If so, we can call make_local() in L1272 >>>>>>>>>>>>>>>>>>>>>>>>>> without JavaThread (or we can pass current >>>>>>>>>>>>>>>>>>>>>>>>>> thread to make_local()). Is it right? >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>>>>>> 1271 ResourceMark rm; >>>>>>>>>>>>>>>>>>>>>>>>>> 1272 >>>>>>>>>>>>>>>>>>>>>>>>>> _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, >>>>>>>>>>>>>>>>>>>>>>>>>> thread_oop), >>>>>>>>>>>>>>>>>>>>>>>>>> 1273 jt, thread_oop); >>>>>>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> Sorry I got confused, _calling_thread may not >>>>>>>>>>>>>>>>>>>>>>>>> be the current thread as we could be executing >>>>>>>>>>>>>>>>>>>>>>>>> the handshake in the target thread itself. So >>>>>>>>>>>>>>>>>>>>>>>>> the ResourceMark is correct as-is (implicitly >>>>>>>>>>>>>>>>>>>>>>>>> for current thread). >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> The argument to fill_frames will be used in >>>>>>>>>>>>>>>>>>>>>>>>> the jvmtiStackInfo and passed back to the >>>>>>>>>>>>>>>>>>>>>>>>> _calling_thread, so it must be created via >>>>>>>>>>>>>>>>>>>>>>>>> make_local(_calling_thread, ...) as you >>>>>>>>>>>>>>>>>>>>>>>>> presently have. >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> On 2020/07/01 7:05, David Holmes wrote: >>>>>>>>>>>>>>>>>>>>>>>>>>> On 1/07/2020 12:17 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> Thank you for reviewing! I will update new >>>>>>>>>>>>>>>>>>>>>>>>>>>> webrev tomorrow. >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> 466 class MultipleStackTracesCollector : >>>>>>>>>>>>>>>>>>>>>>>>>>>>> public StackObj { >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 498 class VM_GetAllStackTraces : public >>>>>>>>>>>>>>>>>>>>>>>>>>>>> VM_Operation { >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 499 private: >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 500 JavaThread *_calling_thread; >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 501?? jint _final_thread_count; >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 502 MultipleStackTracesCollector >>>>>>>>>>>>>>>>>>>>>>>>>>>>> _collector; >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> You can't have a StackObj as a member of >>>>>>>>>>>>>>>>>>>>>>>>>>>>> another class like that as it may not be >>>>>>>>>>>>>>>>>>>>>>>>>>>>> on the stack. I think >>>>>>>>>>>>>>>>>>>>>>>>>>>>> MultipleStackTracesCollector should not >>>>>>>>>>>>>>>>>>>>>>>>>>>>> extend any allocation class, and should >>>>>>>>>>>>>>>>>>>>>>>>>>>>> always be embedded directly in another class. >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> I'm not sure what does mean "embedded". >>>>>>>>>>>>>>>>>>>>>>>>>>>> Is it ok as below? >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>>>>>>>> class MultipleStackTracesCollector { >>>>>>>>>>>>>>>>>>>>>>>>>>>> ??? : >>>>>>>>>>>>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> class GetAllStackTraces : public >>>>>>>>>>>>>>>>>>>>>>>>>>>> VM_Operation { >>>>>>>>>>>>>>>>>>>>>>>>>>>> ?? private: >>>>>>>>>>>>>>>>>>>>>>>>>>>> MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> Yes that I what I meant. >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> On 2020/06/30 22:22, David Holmes wrote: >>>>>>>>>>>>>>>>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> On 30/06/2020 10:05 am, Yasumasa Suenaga >>>>>>>>>>>>>>>>>>>>>>>>>>>>> wrote: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Hi David, Serguei, >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> I updated webrev for 8242428. Could you >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> review again? >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> This change migrate to use direct >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> handshake for GetStackTrace() and >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> GetThreadListStackTraces() (when >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> thread_count == 1). >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.01/ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> This looks really good now! I only have a >>>>>>>>>>>>>>>>>>>>>>>>>>>>> few nits below. There is one thing I don't >>>>>>>>>>>>>>>>>>>>>>>>>>>>> like about it but it requires a change to >>>>>>>>>>>>>>>>>>>>>>>>>>>>> the main Handshake logic to address - in >>>>>>>>>>>>>>>>>>>>>>>>>>>>> JvmtiEnv::GetThreadListStackTraces you >>>>>>>>>>>>>>>>>>>>>>>>>>>>> have to create a ThreadsListHandle to >>>>>>>>>>>>>>>>>>>>>>>>>>>>> convert the jthread to a JavaThread, but >>>>>>>>>>>>>>>>>>>>>>>>>>>>> then the Handshake::execute_direct creates >>>>>>>>>>>>>>>>>>>>>>>>>>>>> another ThreadsListHandle internally. >>>>>>>>>>>>>>>>>>>>>>>>>>>>> That's a waste. I will discuss with Robbin >>>>>>>>>>>>>>>>>>>>>>>>>>>>> and file a RFE to have an overload of >>>>>>>>>>>>>>>>>>>>>>>>>>>>> execute_direct that takes an existing TLH. >>>>>>>>>>>>>>>>>>>>>>>>>>>>> Actually it's worse than that because we >>>>>>>>>>>>>>>>>>>>>>>>>>>>> have another TLH in use at the entry point >>>>>>>>>>>>>>>>>>>>>>>>>>>>> for the JVMTI functions, so I think there >>>>>>>>>>>>>>>>>>>>>>>>>>>>> may be some scope for simplifying the use >>>>>>>>>>>>>>>>>>>>>>>>>>>>> of TLH instances - future RFE. >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??451 GetStackTraceClosure(JvmtiEnv *env, >>>>>>>>>>>>>>>>>>>>>>>>>>>>> jint start_depth, jint max_count, >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??452 jvmtiFrameInfo* frame_buffer, jint* >>>>>>>>>>>>>>>>>>>>>>>>>>>>> count_ptr) >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??453???? : >>>>>>>>>>>>>>>>>>>>>>>>>>>>> HandshakeClosure("GetStackTrace"), >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??454 _env(env), >>>>>>>>>>>>>>>>>>>>>>>>>>>>> _start_depth(start_depth), >>>>>>>>>>>>>>>>>>>>>>>>>>>>> _max_count(max_count), >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??455 _frame_buffer(frame_buffer), >>>>>>>>>>>>>>>>>>>>>>>>>>>>> _count_ptr(count_ptr), >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??456 _result(JVMTI_ERROR_THREAD_NOT_ALIVE) { >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> Nit: can you do one initializer per line >>>>>>>>>>>>>>>>>>>>>>>>>>>>> please. >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> This looks wrong: >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> 466 class MultipleStackTracesCollector : >>>>>>>>>>>>>>>>>>>>>>>>>>>>> public StackObj { >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??498 class VM_GetAllStackTraces : public >>>>>>>>>>>>>>>>>>>>>>>>>>>>> VM_Operation { >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??499 private: >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??500 JavaThread *_calling_thread; >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??501?? jint _final_thread_count; >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??502 MultipleStackTracesCollector >>>>>>>>>>>>>>>>>>>>>>>>>>>>> _collector; >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> You can't have a StackObj as a member of >>>>>>>>>>>>>>>>>>>>>>>>>>>>> another class like that as it may not be >>>>>>>>>>>>>>>>>>>>>>>>>>>>> on the stack. I think >>>>>>>>>>>>>>>>>>>>>>>>>>>>> MultipleStackTracesCollector should not >>>>>>>>>>>>>>>>>>>>>>>>>>>>> extend any allocation class, and should >>>>>>>>>>>>>>>>>>>>>>>>>>>>> always be embedded directly in another class. >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> 481 MultipleStackTracesCollector(JvmtiEnv >>>>>>>>>>>>>>>>>>>>>>>>>>>>> *env, jint max_frame_count) { >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??482???? _env = env; >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??483 _max_frame_count = max_frame_count; >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??484 _frame_count_total = 0; >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??485 _head = NULL; >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??486 _stack_info = NULL; >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??487 _result = JVMTI_ERROR_NONE; >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??488?? } >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> As you are touching this can you change it >>>>>>>>>>>>>>>>>>>>>>>>>>>>> to use an initializer list as you did for >>>>>>>>>>>>>>>>>>>>>>>>>>>>> the HandshakeClosure, and please keep one >>>>>>>>>>>>>>>>>>>>>>>>>>>>> item per line. >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??820 >>>>>>>>>>>>>>>>>>>>>>>>>>>>> assert(SafepointSynchronize::is_at_safepoint() >>>>>>>>>>>>>>>>>>>>>>>>>>>>> || >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??821 >>>>>>>>>>>>>>>>>>>>>>>>>>>>> java_thread->is_thread_fully_suspended(false, >>>>>>>>>>>>>>>>>>>>>>>>>>>>> &debug_bits) || >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??822 current_thread == >>>>>>>>>>>>>>>>>>>>>>>>>>>>> java_thread->active_handshaker(), >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??823 "at safepoint / handshake or target >>>>>>>>>>>>>>>>>>>>>>>>>>>>> thread is suspended"); >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> I don't think the suspension check is >>>>>>>>>>>>>>>>>>>>>>>>>>>>> necessary, as even if the target is >>>>>>>>>>>>>>>>>>>>>>>>>>>>> suspended we must still be at a safepoint >>>>>>>>>>>>>>>>>>>>>>>>>>>>> or in a handshake with it. Makes me wonder >>>>>>>>>>>>>>>>>>>>>>>>>>>>> if we used to allow a racy stacktrace >>>>>>>>>>>>>>>>>>>>>>>>>>>>> operation on a suspended thread, assuming >>>>>>>>>>>>>>>>>>>>>>>>>>>>> it would remain suspended? >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> 1268?? oop thread_oop = jt->threadObj(); >>>>>>>>>>>>>>>>>>>>>>>>>>>>> 1269 >>>>>>>>>>>>>>>>>>>>>>>>>>>>> 1270?? if (!jt->is_exiting() && >>>>>>>>>>>>>>>>>>>>>>>>>>>>> (jt->threadObj() != NULL)) { >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> You can use thread_oop in line 1270. >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> 1272 >>>>>>>>>>>>>>>>>>>>>>>>>>>>> _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, >>>>>>>>>>>>>>>>>>>>>>>>>>>>> thread_oop), >>>>>>>>>>>>>>>>>>>>>>>>>>>>> 1273 jt, thread_oop); >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> It is frustrating that this entire call >>>>>>>>>>>>>>>>>>>>>>>>>>>>> chain started with a jthread reference, >>>>>>>>>>>>>>>>>>>>>>>>>>>>> which we converted to a JavaThread, only >>>>>>>>>>>>>>>>>>>>>>>>>>>>> to eventually need to convert it back to a >>>>>>>>>>>>>>>>>>>>>>>>>>>>> jthread! I think there is some scope for >>>>>>>>>>>>>>>>>>>>>>>>>>>>> simplification here but not as part of >>>>>>>>>>>>>>>>>>>>>>>>>>>>> this change. >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> 1271 ResourceMark rm; >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> IIUC at this point the _calling_thread is >>>>>>>>>>>>>>>>>>>>>>>>>>>>> the current thread, so we can use: >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ResourceMark rm(_calling_thread); >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> Please add @bug lines to the tests. >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> I'm still pondering the test logic but >>>>>>>>>>>>>>>>>>>>>>>>>>>>> wanted to send this now. >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> VM_GetThreadListStackTrace (for >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> GetThreadListStackTraces) and >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> VM_GetAllStackTraces (for >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> GetAllStackTraces) have inherited >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> VM_GetMultipleStackTraces VM operation >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> which provides the feature to generate >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> jvmtiStackInfo. I modified >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> VM_GetMultipleStackTraces to a normal C++ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> class to share with HandshakeClosure for >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> GetThreadListStackTraces >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> (GetSingleStackTraceClosure). >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Also I added new testcases which test >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> GetThreadListStackTraces() with >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> thread_count == 1 and with all threads. >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> This change has been tested in >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> serviceability/jvmti serviceability/jdwp >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> vmTestbase/nsk/jvmti vmTestbase/nsk/jdi >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> vmTestbase/nsk/jdwp. >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> On 2020/06/24 15:50, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Hi all, >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Please review this change: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ?? JBS: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> https://bugs.openjdk.java.net/browse/JDK-8242428 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ?? webrev: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.00/ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> This change replace following VM >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> operations to direct handshake. >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??- VM_GetFrameCount (GetFrameCount()) >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??- VM_GetFrameLocation >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> (GetFrameLocation()) >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??- VM_GetThreadListStackTraces >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> (GetThreadListStackTrace()) >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??- VM_GetCurrentLocation >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> GetThreadListStackTrace() uses direct >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> handshake if thread count == 1. In other >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> case (thread count > 1), it would be >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> performed as VM operation >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> (VM_GetThreadListStackTraces). >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Caller of VM_GetCurrentLocation >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> (JvmtiEnvThreadState::reset_current_location()) >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> might be called at safepoint. So I added >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> safepoint check in its caller. >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> This change has been tested in >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> serviceability/jvmti serviceability/jdwp >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> vmTestbase/nsk/jvmti vmTestbase/nsk/jdi >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> vmTestbase/ns >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> k/jdwp. >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Also I tested it on submit repo, then it >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> has execution error >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> (mach5-one-ysuenaga-JDK-8242428-20200624-0054-12034717) >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> due to dependency error. So I think it >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> does not occur by this change. >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>> >>>>>>>> From igor.ignatyev at oracle.com Wed Jul 8 17:21:11 2020 From: igor.ignatyev at oracle.com (Igor Ignatyev) Date: Wed, 8 Jul 2020 10:21:11 -0700 Subject: RFR [15] : 8249028 : clean up FileInstaller $test.src $cwd in vmTestbase_nsk_monitoring tests Message-ID: http://cr.openjdk.java.net/~iignatyev/8249028/webrev.00/ > 547 lines changed: 0 ins; 361 del; 186 mod; Hi all, could you please review the patch which removes `FileInstaller . .` jtreg action from :vmTestbase_nsk_monitoring tests? from the main issue(8204985): > all vmTestbase tests have '@run driver jdk.test.lib.FileInstaller . .' to mimic old test harness behavior and copy all files from a test source directory to a current work directory. some tests depend on this step, so we need 1st identify such tests and then either rewrite them not to have this dependency or leave FileInstaller only in these tests. effectively, the patch is just `ag -l '@run driver jdk.test.lib.FileInstaller . .' vmTestbase/nsk/monitoring | xargs -I{} gsed -i '/@run driver jdk.test.lib.FileInstaller \. \./d' {}` testing: :vmTestbase_nsk_monitoring on linux-x64 webrev: http://cr.openjdk.java.net/~iignatyev//8249018/webrev.00 JBS: https://bugs.openjdk.java.net/browse/JDK-8249028 Thanks, -- Igor From chris.plummer at oracle.com Wed Jul 8 18:04:12 2020 From: chris.plummer at oracle.com (Chris Plummer) Date: Wed, 8 Jul 2020 11:04:12 -0700 Subject: RFR(M): 8247272: SA ELF file support has never worked for 64-bit causing address to symbol name mapping to fail In-Reply-To: References: <338118cb-37ff-9d03-f22e-c96322bfd7a6@oracle.com> Message-ID: <54ca0720-61f2-4580-80e5-b2a0da966cc0@oracle.com> Hi Kevin, Thanks for the review. I'll add the additional Elf64_Addr and Elf64_Off comments. Probably the others should be updated too. Although they are the same size, they do have different names. For example: /* Type for a 16-bit quantity.? */ typedef uint16_t Elf32_Half; typedef uint16_t Elf64_Half; thanks, Chris On 7/8/20 3:47 AM, Kevin Walls wrote: > Hi Chris -- > > This is a great story/history lesson. > > You could if you like, edit those comments in ElfFileParser.java so > "Elf32_Addr" as they will contain either "Elf64_Addr or Elf32_Addr", > similarly Elf64_Off.? The other Elf64 fields are the same as the 32 > bit ones. > > Yes, the symbol fields are ordered differently. > > So all looks good to me! > > Thanks > Kevin > > > > On 08/07/2020 07:20, Chris Plummer wrote: >> Hello, >> >> Please help review the following: >> >> http://cr.openjdk.java.net/~cjplummer/8247272/webrev.00/index.html >> https://bugs.openjdk.java.net/browse/JDK-8247272 >> >> The short story is that SA address to native symbol name >> mapping/lookup has never worked on 64-bit, and this is due to the >> java level ELF file support only supporting 32-bit. This CR fixes >> that, and I believe also maintains 32-bit compatibility, although I >> have no way of testing that. >> >> There is more to the story however on how we got here. Before going >> into the gory detail below, I just want to point out that currently >> nothing is using this support, and therefore it is technically not >> fixing anything, although I did verify that the fixes work (see >> details below). Also, I intend to remove all the java level ELF file >> support as part of JDK-8247516 [1]. The only reason I want to push >> these changes first is because I already did the work to get it >> working with 64-bit, and would like to get it archived before >> removing it in case for some reason it is revived in the future. >> >> Now for the ugly details on how we got here (and you really don't >> need to read this unless you have any concerns with what I stated >> above). It starts with the clhsdb "whatis" command, which was the >> only (indirect) user of this java level ELF file support. It's >> implementation is in javascript, so we have not had access to it ever >> since JDK9 module support broke the SA javascript support (and >> javascript support is now removed). I started the process of >> converting "whatis" to java. It is basically the same as the clhsdb >> "findpc" command, except it also checks for native symbols, which it >> does with the following code: >> >> ? var dso = loadObjectContainingPC(addr); >> ? var sym = dso.closestSymbolToPC(addr); >> ? return sym.name + '+' + sym.offset; >> >> Converting this to java was trivial. I just stuck support for it in >> the PointerFinder class, which is what findpc relies on. However, it >> always failed to successfully lookup a symbol. I found that >> DSO.closestSymbolToPC() called into the java level ELF support, and >> that was failing badly. After some debugging I noticed that the >> values read in for various ELF headers were mostly garbage. It then >> occurred to me that it was reading in 32-bit values that probably >> needed to be 64-bit. Sure enough, this code was never converted to >> 64-bit support. I then went and tried "whatis" on JDK8, the last >> version where it was available, and it failed there also with 64-bit >> binaries. So this is why I initially fixed it to work with 64-bit, >> and also how I tested it (using the modified findpc on a native >> symbol). But the story continues... >> >> DSO.java, and as a consequence the java ELF file support, is used by >> all our posix ports to do address to symbol lookups. So I figured >> that after fixing the java level ELF file support for 64-bit, my >> improved findpc would start working on OSX also. No such luck, and >> for obvious reasons. OSX uses mach-o files. This ELF code should >> never have been used for it, and of course has never worked. >> >> So I was left trying to figure out how to do OSX address to native >> symbol lookups. I then recalled that there was a >> CFrame.closestSymbolToPC() API that did address to native symbol >> lookups for native stack traces, and wondered how it was ever working >> (even on linux with the broken ELF 64-bit support). It turns out this >> takes a very different path to do the lookups, ending up in native >> code in libsaproc, where we also have ELF file support. I then >> converted DSO.closestSymbolToPC(addr) to use this libsaproc code >> instead, and it worked fine. So now there was no need for the java >> level ELF file support since its only user was >> DSO.closestSymbolToPC(addr). I should also add that this is the >> approach that has always been used on windows, with both >> CFrame.closestSymbolToPC() and DSO.closestSymbolToPC(addr) using the >> same libsaproc support. >> >> There is still a bit more to the story. After diverting >> DSO.closestSymbolToPC(addr) to the libsaproc lookup code, it still >> didn't work for OSX. I thought it would just work since the native >> BsdDebuggerLocal.lookupByName0() is implemented, and it seems to >> trickle down to the proper lower level APIs to find the symbol, but >> there were two issues. The first is that for processes there is no >> support for looking up all the libraries and populating the list of >> ps_prochandle structures that are used to do the symbol lookups. This >> was just never implemented (also is why PMap does not work for OSX >> processes). For core files the ps_prochandle structs are there, but >> the lookup code was badly broken. That has now been fixed by >> JDK-8247515 [2], currently out for review. So the end result is we'll >> have address to native symbol lookup for everything but OSX processes. >> >> If? your still here, thanks for listening! >> >> Chris >> >> [1] https://bugs.openjdk.java.net/browse/JDK-8247516 >> [2] https://bugs.openjdk.java.net/browse/JDK-8247515 >> >> >> >> From chris.plummer at oracle.com Wed Jul 8 19:26:27 2020 From: chris.plummer at oracle.com (Chris Plummer) Date: Wed, 8 Jul 2020 12:26:27 -0700 Subject: RFR(M): 8247272: SA ELF file support has never worked for 64-bit causing address to symbol name mapping to fail In-Reply-To: <54ca0720-61f2-4580-80e5-b2a0da966cc0@oracle.com> References: <338118cb-37ff-9d03-f22e-c96322bfd7a6@oracle.com> <54ca0720-61f2-4580-80e5-b2a0da966cc0@oracle.com> Message-ID: <9d743570-7e55-df53-abfc-77a62af4d136@oracle.com> Webrev has been updated with the suggested comment changes. Note to new reviewers, look in webrev.00 first since it doesn't have the clutter of the comment changes, making it easier to see which lines actually have code changes. http://cr.openjdk.java.net/~cjplummer/8247272/webrev.01/index.html thanks, Chris On 7/8/20 11:04 AM, Chris Plummer wrote: > Hi Kevin, > > Thanks for the review. I'll add the additional Elf64_Addr and > Elf64_Off comments. Probably the others should be updated too. > Although they are the same size, they do have different names. For > example: > > /* Type for a 16-bit quantity.? */ > typedef uint16_t Elf32_Half; > typedef uint16_t Elf64_Half; > > thanks, > > Chris > > On 7/8/20 3:47 AM, Kevin Walls wrote: >> Hi Chris -- >> >> This is a great story/history lesson. >> >> You could if you like, edit those comments in ElfFileParser.java so >> "Elf32_Addr" as they will contain either "Elf64_Addr or Elf32_Addr", >> similarly Elf64_Off.? The other Elf64 fields are the same as the 32 >> bit ones. >> >> Yes, the symbol fields are ordered differently. >> >> So all looks good to me! >> >> Thanks >> Kevin >> >> >> >> On 08/07/2020 07:20, Chris Plummer wrote: >>> Hello, >>> >>> Please help review the following: >>> >>> http://cr.openjdk.java.net/~cjplummer/8247272/webrev.00/index.html >>> https://bugs.openjdk.java.net/browse/JDK-8247272 >>> >>> The short story is that SA address to native symbol name >>> mapping/lookup has never worked on 64-bit, and this is due to the >>> java level ELF file support only supporting 32-bit. This CR fixes >>> that, and I believe also maintains 32-bit compatibility, although I >>> have no way of testing that. >>> >>> There is more to the story however on how we got here. Before going >>> into the gory detail below, I just want to point out that currently >>> nothing is using this support, and therefore it is technically not >>> fixing anything, although I did verify that the fixes work (see >>> details below). Also, I intend to remove all the java level ELF file >>> support as part of JDK-8247516 [1]. The only reason I want to push >>> these changes first is because I already did the work to get it >>> working with 64-bit, and would like to get it archived before >>> removing it in case for some reason it is revived in the future. >>> >>> Now for the ugly details on how we got here (and you really don't >>> need to read this unless you have any concerns with what I stated >>> above). It starts with the clhsdb "whatis" command, which was the >>> only (indirect) user of this java level ELF file support. It's >>> implementation is in javascript, so we have not had access to it >>> ever since JDK9 module support broke the SA javascript support (and >>> javascript support is now removed). I started the process of >>> converting "whatis" to java. It is basically the same as the clhsdb >>> "findpc" command, except it also checks for native symbols, which it >>> does with the following code: >>> >>> ? var dso = loadObjectContainingPC(addr); >>> ? var sym = dso.closestSymbolToPC(addr); >>> ? return sym.name + '+' + sym.offset; >>> >>> Converting this to java was trivial. I just stuck support for it in >>> the PointerFinder class, which is what findpc relies on. However, it >>> always failed to successfully lookup a symbol. I found that >>> DSO.closestSymbolToPC() called into the java level ELF support, and >>> that was failing badly. After some debugging I noticed that the >>> values read in for various ELF headers were mostly garbage. It then >>> occurred to me that it was reading in 32-bit values that probably >>> needed to be 64-bit. Sure enough, this code was never converted to >>> 64-bit support. I then went and tried "whatis" on JDK8, the last >>> version where it was available, and it failed there also with 64-bit >>> binaries. So this is why I initially fixed it to work with 64-bit, >>> and also how I tested it (using the modified findpc on a native >>> symbol). But the story continues... >>> >>> DSO.java, and as a consequence the java ELF file support, is used by >>> all our posix ports to do address to symbol lookups. So I figured >>> that after fixing the java level ELF file support for 64-bit, my >>> improved findpc would start working on OSX also. No such luck, and >>> for obvious reasons. OSX uses mach-o files. This ELF code should >>> never have been used for it, and of course has never worked. >>> >>> So I was left trying to figure out how to do OSX address to native >>> symbol lookups. I then recalled that there was a >>> CFrame.closestSymbolToPC() API that did address to native symbol >>> lookups for native stack traces, and wondered how it was ever >>> working (even on linux with the broken ELF 64-bit support). It turns >>> out this takes a very different path to do the lookups, ending up in >>> native code in libsaproc, where we also have ELF file support. I >>> then converted DSO.closestSymbolToPC(addr) to use this libsaproc >>> code instead, and it worked fine. So now there was no need for the >>> java level ELF file support since its only user was >>> DSO.closestSymbolToPC(addr). I should also add that this is the >>> approach that has always been used on windows, with both >>> CFrame.closestSymbolToPC() and DSO.closestSymbolToPC(addr) using the >>> same libsaproc support. >>> >>> There is still a bit more to the story. After diverting >>> DSO.closestSymbolToPC(addr) to the libsaproc lookup code, it still >>> didn't work for OSX. I thought it would just work since the native >>> BsdDebuggerLocal.lookupByName0() is implemented, and it seems to >>> trickle down to the proper lower level APIs to find the symbol, but >>> there were two issues. The first is that for processes there is no >>> support for looking up all the libraries and populating the list of >>> ps_prochandle structures that are used to do the symbol lookups. >>> This was just never implemented (also is why PMap does not work for >>> OSX processes). For core files the ps_prochandle structs are there, >>> but the lookup code was badly broken. That has now been fixed by >>> JDK-8247515 [2], currently out for review. So the end result is >>> we'll have address to native symbol lookup for everything but OSX >>> processes. >>> >>> If? your still here, thanks for listening! >>> >>> Chris >>> >>> [1] https://bugs.openjdk.java.net/browse/JDK-8247516 >>> [2] https://bugs.openjdk.java.net/browse/JDK-8247515 >>> >>> >>> >>> > > From kevin.walls at oracle.com Wed Jul 8 21:07:24 2020 From: kevin.walls at oracle.com (Kevin Walls) Date: Wed, 8 Jul 2020 22:07:24 +0100 Subject: RFR(M): 8247272: SA ELF file support has never worked for 64-bit causing address to symbol name mapping to fail In-Reply-To: <9d743570-7e55-df53-abfc-77a62af4d136@oracle.com> References: <338118cb-37ff-9d03-f22e-c96322bfd7a6@oracle.com> <54ca0720-61f2-4580-80e5-b2a0da966cc0@oracle.com> <9d743570-7e55-df53-abfc-77a62af4d136@oracle.com> Message-ID: Thanks Chris, it's a bit of clutter, but truthful clutter. 8-) On 08/07/2020 20:26, Chris Plummer wrote: > Webrev has been updated with the suggested comment changes. Note to > new reviewers, look in webrev.00 first since it doesn't have the > clutter of the comment changes, making it easier to see which lines > actually have code changes. > > http://cr.openjdk.java.net/~cjplummer/8247272/webrev.01/index.html > > thanks, > > Chris > > On 7/8/20 11:04 AM, Chris Plummer wrote: >> Hi Kevin, >> >> Thanks for the review. I'll add the additional Elf64_Addr and >> Elf64_Off comments. Probably the others should be updated too. >> Although they are the same size, they do have different names. For >> example: >> >> /* Type for a 16-bit quantity.? */ >> typedef uint16_t Elf32_Half; >> typedef uint16_t Elf64_Half; >> >> thanks, >> >> Chris >> >> On 7/8/20 3:47 AM, Kevin Walls wrote: >>> Hi Chris -- >>> >>> This is a great story/history lesson. >>> >>> You could if you like, edit those comments in ElfFileParser.java so >>> "Elf32_Addr" as they will contain either "Elf64_Addr or Elf32_Addr", >>> similarly Elf64_Off.? The other Elf64 fields are the same as the 32 >>> bit ones. >>> >>> Yes, the symbol fields are ordered differently. >>> >>> So all looks good to me! >>> >>> Thanks >>> Kevin >>> >>> >>> >>> On 08/07/2020 07:20, Chris Plummer wrote: >>>> Hello, >>>> >>>> Please help review the following: >>>> >>>> http://cr.openjdk.java.net/~cjplummer/8247272/webrev.00/index.html >>>> https://bugs.openjdk.java.net/browse/JDK-8247272 >>>> >>>> The short story is that SA address to native symbol name >>>> mapping/lookup has never worked on 64-bit, and this is due to the >>>> java level ELF file support only supporting 32-bit. This CR fixes >>>> that, and I believe also maintains 32-bit compatibility, although I >>>> have no way of testing that. >>>> >>>> There is more to the story however on how we got here. Before going >>>> into the gory detail below, I just want to point out that currently >>>> nothing is using this support, and therefore it is technically not >>>> fixing anything, although I did verify that the fixes work (see >>>> details below). Also, I intend to remove all the java level ELF >>>> file support as part of JDK-8247516 [1]. The only reason I want to >>>> push these changes first is because I already did the work to get >>>> it working with 64-bit, and would like to get it archived before >>>> removing it in case for some reason it is revived in the future. >>>> >>>> Now for the ugly details on how we got here (and you really don't >>>> need to read this unless you have any concerns with what I stated >>>> above). It starts with the clhsdb "whatis" command, which was the >>>> only (indirect) user of this java level ELF file support. It's >>>> implementation is in javascript, so we have not had access to it >>>> ever since JDK9 module support broke the SA javascript support (and >>>> javascript support is now removed). I started the process of >>>> converting "whatis" to java. It is basically the same as the clhsdb >>>> "findpc" command, except it also checks for native symbols, which >>>> it does with the following code: >>>> >>>> ? var dso = loadObjectContainingPC(addr); >>>> ? var sym = dso.closestSymbolToPC(addr); >>>> ? return sym.name + '+' + sym.offset; >>>> >>>> Converting this to java was trivial. I just stuck support for it in >>>> the PointerFinder class, which is what findpc relies on. However, >>>> it always failed to successfully lookup a symbol. I found that >>>> DSO.closestSymbolToPC() called into the java level ELF support, and >>>> that was failing badly. After some debugging I noticed that the >>>> values read in for various ELF headers were mostly garbage. It then >>>> occurred to me that it was reading in 32-bit values that probably >>>> needed to be 64-bit. Sure enough, this code was never converted to >>>> 64-bit support. I then went and tried "whatis" on JDK8, the last >>>> version where it was available, and it failed there also with >>>> 64-bit binaries. So this is why I initially fixed it to work with >>>> 64-bit, and also how I tested it (using the modified findpc on a >>>> native symbol). But the story continues... >>>> >>>> DSO.java, and as a consequence the java ELF file support, is used >>>> by all our posix ports to do address to symbol lookups. So I >>>> figured that after fixing the java level ELF file support for >>>> 64-bit, my improved findpc would start working on OSX also. No such >>>> luck, and for obvious reasons. OSX uses mach-o files. This ELF code >>>> should never have been used for it, and of course has never worked. >>>> >>>> So I was left trying to figure out how to do OSX address to native >>>> symbol lookups. I then recalled that there was a >>>> CFrame.closestSymbolToPC() API that did address to native symbol >>>> lookups for native stack traces, and wondered how it was ever >>>> working (even on linux with the broken ELF 64-bit support). It >>>> turns out this takes a very different path to do the lookups, >>>> ending up in native code in libsaproc, where we also have ELF file >>>> support. I then converted DSO.closestSymbolToPC(addr) to use this >>>> libsaproc code instead, and it worked fine. So now there was no >>>> need for the java level ELF file support since its only user was >>>> DSO.closestSymbolToPC(addr). I should also add that this is the >>>> approach that has always been used on windows, with both >>>> CFrame.closestSymbolToPC() and DSO.closestSymbolToPC(addr) using >>>> the same libsaproc support. >>>> >>>> There is still a bit more to the story. After diverting >>>> DSO.closestSymbolToPC(addr) to the libsaproc lookup code, it still >>>> didn't work for OSX. I thought it would just work since the native >>>> BsdDebuggerLocal.lookupByName0() is implemented, and it seems to >>>> trickle down to the proper lower level APIs to find the symbol, but >>>> there were two issues. The first is that for processes there is no >>>> support for looking up all the libraries and populating the list of >>>> ps_prochandle structures that are used to do the symbol lookups. >>>> This was just never implemented (also is why PMap does not work for >>>> OSX processes). For core files the ps_prochandle structs are there, >>>> but the lookup code was badly broken. That has now been fixed by >>>> JDK-8247515 [2], currently out for review. So the end result is >>>> we'll have address to native symbol lookup for everything but OSX >>>> processes. >>>> >>>> If? your still here, thanks for listening! >>>> >>>> Chris >>>> >>>> [1] https://bugs.openjdk.java.net/browse/JDK-8247516 >>>> [2] https://bugs.openjdk.java.net/browse/JDK-8247515 >>>> >>>> >>>> >>>> >> >> > > From suenaga at oss.nttdata.com Thu Jul 9 00:25:38 2020 From: suenaga at oss.nttdata.com (Yasumasa Suenaga) Date: Thu, 9 Jul 2020 09:25:38 +0900 Subject: RFR: 8242428: JVMTI thread operations should use Thread-Local Handshake In-Reply-To: References: <6c263e4c-0a83-be7a-0288-ecb2de0b7cea@oss.nttdata.com> <04e09eb7-9483-8f63-4bb4-01c9e814802e@oracle.com> <238a89a3-06b1-90e4-d5a4-8dc2f1ed12ab@oracle.com> <4c43bc2c-551e-d042-8fa7-b63e755888d1@oracle.com> <8c387550-a06e-6320-f453-0e898486befb@oss.nttdata.com> <19cfa2a7-f441-425d-5623-1c11c6a870b6@oss.nttdata.com> <237e8d26-d185-1008-6e07-5b9f36314534@oracle.com> Message-ID: Hi Dan, Thanks for your comment! I uploaded new webrev: http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.09/ Diff from previous webrev: http://hg.openjdk.java.net/jdk/submit/rev/5d167adf8524 I saw similar build errors in libOneGetThreadListStackTraces.cpp on Windows. This webrev fixes them. Thanks, Yasumasa On 2020/07/09 1:42, Daniel D. Daugherty wrote: > > http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.08/ > > src/hotspot/share/prims/jvmtiEnv.cpp > ??? No comments. > > src/hotspot/share/prims/jvmtiEnvBase.cpp > ??? L1159: ? Thread *current_thread = Thread::current(); > ??????? Please add "#ifdef ASSERT" above and "#endif" below since > ??????? current_thread is only used for the assert() in this function. > > src/hotspot/share/prims/jvmtiEnvBase.hpp > ??? L549: ???????????????????????????? jthread java_thread, jint max_frame_count) > ??? L552: ????? _jthread(java_thread), > ??????? Please: s/java_thread/thread/ on both lines. > > src/hotspot/share/runtime/vmOperations.hpp > ??? No comments. > > test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/OneGetThreadListStackTraces.java > ??? No comments. > > test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.cpp > ??? L27: #include > ??????? This include is out of order; should be first in the list. > > ??? This file doesn't compile on my MBP13: > > ./open/test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.cpp:49:14: error: format specifies type 'unsigned long' but the argument has type 'jmethodID' (aka '_jmethodID *') [-Werror,-Wformat] > ???????????? fi1->method, fi2->method); > ???????????? ^~~~~~~~~~~ > ./open/test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.cpp:49:27: error: format specifies type 'unsigned long' but the argument has type 'jmethodID' (aka '_jmethodID *') [-Werror,-Wformat] > ???????????? fi1->method, fi2->method); > ????????????????????????? ^~~~~~~~~~~ > ??? 2 errors generated. > > ??? This change made it compile on my MBP13, but that may break it on > ??? other platforms: > > ??? $ hg diff > ??? diff -r 560847c69fbe test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.cpp > ??? --- a/test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.cpp Wed Jul 08 12:13:32 2020 -0400 > ??? +++ b/test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.cpp Wed Jul 08 12:40:42 2020 -0400 > ??? @@ -46,7 +46,7 @@ > ? ?? ? if (fi1->method != fi2->method) { /* jvmtiFrameInfo::method */ > ? ?? ??? snprintf(err_msg, sizeof(err_msg), > ? ? ? ??????????? "method is different: fi1 = %lx, fi2 = %lx", > ??? -???????????? fi1->method, fi2->method); > ??? +???????????? (unsigned long) fi1->method, (unsigned long) fi2->method); > ? ?? ??? env->FatalError(err_msg); > ? ?? ? } else if (fi1->location != fi2->location) { /* jvmtiFrameInfo::location */ > ? ?? ??? snprintf(err_msg, sizeof(err_msg), > > ??? I'm not sure of the right platform independent way to output > ??? the 'method' field. > > Dan > > > On 7/8/20 4:04 AM, Yasumasa Suenaga wrote: >> Hi David, >> >> On 2020/07/08 15:27, David Holmes wrote: >>> Hi Yasumasa, >>> >>> On 7/07/2020 6:54 pm, Yasumasa Suenaga wrote: >>>> Hi David, Serguei, >>>> >>>> Serguei, thank you for replying even though you are on vacaiton! >>>> >>>> I uploaded new webrev: >>>> >>>> ?? http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.07/ >>>> ?? Diff from previous webrev: http://hg.openjdk.java.net/jdk/submit/rev/77243b1dcbfe >>>> >>>> c'tor of GetSingleStackTraceClosure has jthread argument in this webrev. >>>> Also it does not contain testcase for GetThreadListStackTraces with all threads, and OneGetThreadListStackTraces would test main thread only. >>> >>> All those changes are fine in principle for me. One nit/suggestion: >>> >>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>> >>> ??544?? jthread _java_thread; >>> >>> elsewhere "java_thread" refers to a JavaThread, so to avoid confusion may I suggest this member be named _jthread. >> >> I uploaded new webrev: >> >> ? http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.08/ >> ? Diff from previous webrev: http://hg.openjdk.java.net/jdk/submit/rev/ca6263dbdc87 >> >> >>> I'm going to be away for the next couple of days - sorry - but will try to check email on this if I can. >> >> Thanks! >> >> >> Yasumasa >> >> >>> Thanks, >>> David >>> ----- >>> >>>> >>>> Thanks, >>>> >>>> Yasumasa >>>> >>>> >>>> On 2020/07/07 15:13, David Holmes wrote: >>>>> On 7/07/2020 2:57 pm, Yasumasa Suenaga wrote: >>>>>> Hi David, >>>>>> >>>>>> On 2020/07/07 11:31, David Holmes wrote: >>>>>>> Hi Yasumasa, >>>>>>> >>>>>>> Hard to keep up with the changes - especially without incremental webrevs. >>>>>> >>>>>> Sorry, I will upload diff from previous webrev in the next. >>>>>> >>>>>> >>>>>>> If GetSingleStackTraceClosure also took the jthread as a constructor arg, then you wouldn't need to recreate a JNI local handle when calling _collector.fill_frames. It's a small simplification and not essential at this stage. >>>>>> >>>>>> I think we should get jthread from an argument of do_thread() because do_thread() would pass the thread which are stopped certainly. >>>>>> It might be simplification if we pass _calling_thread to MultipleStackTracesCollector. `jthread` is only needed to store jvmtiStackInfo.thread . What do you think? >>>>> >>>>> I'm not quite sure what you mean. >>>>> >>>>> I think there is a bit of a design wart with direct handshakes in that do_thread takes the target JavaThread as an argument. That's useful in a case where you want a HandshakeClosure that can be applied to multiple threads, but that's not typically what is needed with direct handshakes - there is only a single target. With a single-target HandshakeClosure you can capture all the "target" information for the operation in the closure instance. So if the actual do_thread operation wants the jthread corresponding to the target thread then we can store that in the closure rather than recomputing it (you could assert it is the same but that seems overkill to me). >>>>> >>>>>> >>>>>>> For the test ... I don't see how Java_GetThreadListStackTraces_checkCallStacks is a valid test. It gets the stacks of all live threads, then uses that information to use GetThreadListStackTraces to get the stack for the same set of threads through a different API. It then compares the two sets of stacks for each thread expecting them to be the same, but that need only be the case for the main thread. Other threads could potentially have a different stack (e.g. if this test is run with JFR enabled there will be additional threads found.) Further I would have expected that there already exist tests that check that, for a given thread (which may be suspended or known to be blocked) the same stack is found through the two different APIs. >>>>>> >>>>>> vmTestbase/nsk/jvmti/unit/GetAllStackTraces/getallstktr001 would check all of threads via GetThreadListStackTraces() and GetAllStackTraces(), so we might be able to remove GetThreadListStackTraces.java from this webrev. >>>>> >>>>> Yes. The existing test only examines a set of test threads that are all blocked on a raw monitor. You do not need to duplicate that test. >>>>> >>>>>> OTOH we don't have testcase for GetThreadListStackTraces() with thread_count == 1, so we need to testcase for it (it is OneGetThreadListStackTraces.java) It would check whether the state of target thread is "waiting" before JNI call to call GetThreadListStackTraces(), >>>>> >>>>> Yes we need to test the special cases introduced by your changes - totally agree - and OneGetThreadListStackTraces.java is a good test for that. >>>>> >>>>>> and also I expect it would not be run with JFR. (it is not described @run) >>>>> >>>>> The arguments to run with JFR (or a bunch of other things) can be passed to the jtreg test harness to be applied to all tests. >>>>> >>>>>> Of course we can check GetThreadListStackTraces() with main thread, but it is not the test for direct handshake for other thread. >>>>> >>>>> Right - that test already exists as per the above. >>>>> >>>>> Thanks, >>>>> David >>>>> >>>>>> >>>>>> Thanks, >>>>>> >>>>>> Yasumasa >>>>>> >>>>>> >>>>>>> Thanks, >>>>>>> David >>>>>>> ----- >>>>>>> >>>>>>> On 6/07/2020 11:29 pm, Yasumasa Suenaga wrote: >>>>>>>> Hi Serguei, >>>>>>>> >>>>>>>> Thanks for your comment! >>>>>>>> >>>>>>>> I think C++ is more simple to implement the test agent as you said. >>>>>>>> So I implement it in C++ in new webrev. Could you review again? >>>>>>>> >>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.06/ >>>>>>>> >>>>>>>> Also I refactored libGetThreadListStackTraces.cpp, and I've kept exception check after IsSameObject(). >>>>>>>> >>>>>>>> >>>>>>>> Thanks, >>>>>>>> >>>>>>>> Yasumasa >>>>>>>> >>>>>>>> >>>>>>>> On 2020/07/06 16:32, serguei.spitsyn at oracle.com wrote: >>>>>>>>> Hi Yasumasa, >>>>>>>>> >>>>>>>>> Thank you for the update. >>>>>>>>> I think, a pending exception after IsSameObject needs to be checked. >>>>>>>>> >>>>>>>>> The checkStackInfo() needs one more refactoring as I've already suggested. >>>>>>>>> The body of the loop at L68-L78 should be converted to a function check_frame_info. >>>>>>>>> The si1->frame_buffer[i] and si2->frame_buffer[i] will be passed as fi1 and fi2. >>>>>>>>> The index can be passed as well. >>>>>>>>> I'm still suggesting to simplify the local exception_msg to something shorter like err_msg or exc_msg. >>>>>>>>> >>>>>>>>> I'm not sure using fatal is right here: >>>>>>>>> >>>>>>>>> This fragment looks strange: >>>>>>>>> >>>>>>>>> ? 152???? if ((*env)->IsSameObject(env, stack_info[i].thread, thread)) { >>>>>>>>> ? 153?????? target_info = &stack_info[i]; >>>>>>>>> ? 154?????? break; >>>>>>>>> ? 155???? } else if ((*env)->ExceptionOccurred(env)) { >>>>>>>>> ? 156?????? (*env)->ExceptionDescribe(env); >>>>>>>>> ? 157?????? (*env)->FatalError(env, __FILE__); >>>>>>>>> ? 158???? } >>>>>>>>> >>>>>>>>> I expected it to be: >>>>>>>>> >>>>>>>>> ??? jboolean same = (*env)->IsSameObject(env, stack_info[i].thread, thread); >>>>>>>>> ??? if ((*env)->ExceptionOccurred(env)) { >>>>>>>>> ????? (*env)->ExceptionDescribe(env); >>>>>>>>> ????? (*env)->FatalError(env, __FILE__); >>>>>>>>> ??? } >>>>>>>>> ??? if (same) { >>>>>>>>> ????? target_info = &stack_info[i]; >>>>>>>>> ????? break; >>>>>>>>> ??? } >>>>>>>>> >>>>>>>>> Would it better to port this agent to C++ to simplify this code nicer? >>>>>>>>> >>>>>>>>> Thanks, >>>>>>>>> Serguei >>>>>>>>> >>>>>>>>> >>>>>>>>> On 7/5/20 06:13, Yasumasa Suenaga wrote: >>>>>>>>>> Hi Serguei, >>>>>>>>>> >>>>>>>>>> Thanks for your comment! >>>>>>>>>> I refactored testcase. Could you review again? >>>>>>>>>> >>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.05/ >>>>>>>>>> >>>>>>>>>> It would check Java exception after IsSameObject() call. Does it need? >>>>>>>>>> Any exceptions are not described in JNI document[1], and JNI implementation (jni_IsSameObject()) does not seem to throw it. >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> Thanks, >>>>>>>>>> >>>>>>>>>> Yasumasa >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> [1] https://docs.oracle.com/en/java/javase/14/docs/specs/jni/functions.html#issameobject >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> On 2020/07/05 14:46, serguei.spitsyn at oracle.com wrote: >>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> Okay, thanks. >>>>>>>>>>> Then I'm okay to keep the GetSingleStackTraceClosure. >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libGetThreadListStackTraces.c.html >>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.c.html >>>>>>>>>>> >>>>>>>>>>> I'm not sure the function 'is_same_thread() is needed. >>>>>>>>>>> Why do not use the JNI IsSameObject instead? >>>>>>>>>>> >>>>>>>>>>> It seems to be a typo at L132 and L137. >>>>>>>>>>> You, probably. did not want to print the same information for stack_info_1[i].frame_buffer[j].XXX twice. >>>>>>>>>>> >>>>>>>>>>> The code at lines 112-142 is not readable. >>>>>>>>>>> I'd suggest to make a couple of refactoring steps. >>>>>>>>>>> >>>>>>>>>>> First step to simplify this a little bit would be with some renaming and getting rid of indexes: >>>>>>>>>>> >>>>>>>>>>> ?? 71 char err_msg[EXCEPTION_MSG_LEN] = {0}; >>>>>>>>>>> ??... >>>>>>>>>>> ??112?? /* Iterate all jvmtiStackInfo to check */ >>>>>>>>>>> ??113?? for (i = 0; i < num_threads, *exception_msg != '\0'; i++) { >>>>>>>>>>> ????????? jvmtiStackInfo *si1 = stack_info_1[i]; >>>>>>>>>>> ????????? jvmtiStackInfo *si2 = stack_info_2[i]; >>>>>>>>>>> ??114???? if (!IsSameObject(env, si1.thread, si2.thread)) { /* jvmtiStackInfo::thread */ >>>>>>>>>>> ??115?????? snprintf(err_msg, sizeof(err_msg), >>>>>>>>>>> ??116??????????????? "thread[%d] is different: stack_info_1 = %p, stack_info_2 = %p", >>>>>>>>>>> ??117??????????????? i, sinfo1.thread, sinfo2.thread); >>>>>>>>>>> ??118???? } else if (si1.state != si2.state) { /* jvmtiStackInfo::state */ >>>>>>>>>>> ??119?????? snprintf(err_msg, sizeof(err_msg), >>>>>>>>>>> ??120??????????????? "state[%d] is different: stack_info_1 = %d, stack_info_2 = %d", >>>>>>>>>>> ??121??????????????? i, si1.state, si2.state); >>>>>>>>>>> ??122???? } else if (si1.frame_count != si2.frame_count) { /* jvmtiStackInfo::frame_count */ >>>>>>>>>>> ??123?????? snprintf(err_msg, sizeof(err_msg), >>>>>>>>>>> ??124??????????????? "frame_count[%d] is different: stack_info_1 = %d, stack_info_2 = %d", >>>>>>>>>>> ??125??????????????? i, si1.frame_count, si2.frame_count); >>>>>>>>>>> ??126???? } else { >>>>>>>>>>> ??127?????? /* Iterate all jvmtiFrameInfo to check */ >>>>>>>>>>> ??128?????? for (j = 0; j < si1.frame_count; j++) { >>>>>>>>>>> ??129???????? if (si1.frame_buffer[j].method != si1.frame_buffer[j].method) { /* jvmtiFrameInfo::method */ >>>>>>>>>>> ??130?????????? snprintf(err_msg, sizeof(err_msg), >>>>>>>>>>> ??131??????????????????? "thread [%d] frame_buffer[%d].method is different: stack_info_1 = %lx, stack_info_2 = %lx", >>>>>>>>>>> ??132??????????????????? i, j, si1.frame_buffer[j].method, si2.frame_buffer[j].method); >>>>>>>>>>> ??133?????????? break; >>>>>>>>>>> ??134???????? } else if (si1.frame_buffer[j].location != si1.frame_buffer[j].location) { /* jvmtiFrameInfo::location */ >>>>>>>>>>> ??135?????????? snprintf(err_msg, sizeof(err_msg), >>>>>>>>>>> ??136??????????????????? "thread [%d] frame_buffer[%d].location is different: stack_info_1 = %ld, stack_info_2 = %ld", >>>>>>>>>>> ??137??????????????????? i, j, si1.frame_buffer[j].location, si2.frame_buffer[j].location); >>>>>>>>>>> ??138?????????? break; >>>>>>>>>>> ??139???????? } >>>>>>>>>>> ??140?????? } >>>>>>>>>>> ??141???? } >>>>>>>>>>> ??142?? } >>>>>>>>>>> >>>>>>>>>>> Another step would be to create functions that implement a body of each loop. >>>>>>>>>>> You can use the same techniques to simplify similar place (L127-L138) in the libOneGetThreadListStackTraces.c. >>>>>>>>>>> >>>>>>>>>>> Thanks, >>>>>>>>>>> Serguei >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> On 7/3/20 15:55, Yasumasa Suenaga wrote: >>>>>>>>>>>> Hi Serguei, >>>>>>>>>>>> >>>>>>>>>>>> I'm not an Oracle employee, so I cannot know real request(s) from your customers. >>>>>>>>>>>> However JDK-8201641 says Dynatrace has requested this enhancement. >>>>>>>>>>>> >>>>>>>>>>>> BTW I haven't heared any request from my customers about this. >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> Thanks, >>>>>>>>>>>> >>>>>>>>>>>> Yasumasa >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> On 2020/07/04 4:32, serguei.spitsyn at oracle.com wrote: >>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>> >>>>>>>>>>>>> This difference is not that big to care about. >>>>>>>>>>>>> I feel this is really rare case and so, does not worth these complications. >>>>>>>>>>>>> Do we have a real request from customers to optimize it? >>>>>>>>>>>>> >>>>>>>>>>>>> Thanks, >>>>>>>>>>>>> Serguei >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> On 7/3/20 01:16, Yasumasa Suenaga wrote: >>>>>>>>>>>>>> Hi Serguei, >>>>>>>>>>>>>> >>>>>>>>>>>>>> Generally I agree with you, but I have concern about the difference of the result of GetStackTrace() and GetThreadListStackTraces(). >>>>>>>>>>>>>> >>>>>>>>>>>>>> ? GetStackTrace: jvmtiFrameInfo >>>>>>>>>>>>>> ? GetThreadListStackTraces: jvmtiStackInfo >>>>>>>>>>>>>> >>>>>>>>>>>>>> jvmtiStackInfo contains thread state, and it is ensured it is the state of the call stack. >>>>>>>>>>>>>> If we want to get both call stack and thread state, we need to suspend target thread, and call both GetStackTrace() and GetThreadState(). Is it ok? >>>>>>>>>>>>>> >>>>>>>>>>>>>> I was wondering if JDK-8201641 (parent ticket of this change) needed them for profiling (dynatrace?) >>>>>>>>>>>>>> If it is responsibility of JVMTI agent implementor, I remove this closure. >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>> >>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> On 2020/07/03 16:45, serguei.spitsyn at oracle.com wrote: >>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> After some thinking I've concluded that I do not like this optimization >>>>>>>>>>>>>>> of the GetThreadListStackTraces with GetSingleStackTraceClosure. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> We may need more opinions on this but these are my points: >>>>>>>>>>>>>>> ??- it adds some complexity and ugliness >>>>>>>>>>>>>>> ??- a win is doubtful because it has to be a rare case, so that total overhead should not be high >>>>>>>>>>>>>>> ??- if it is really high for some use cases then it is up to the user >>>>>>>>>>>>>>> ??? to optimize it with using GetStackTrace instead >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> In such cases with doubtful overhead I usually prefer the simplicity. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Good examples where it makes sense to optimize are checks for target thread to be current thread. >>>>>>>>>>>>>>> In such cases there is no need to suspend the target thread, or use a VMop/HandshakeClosure. >>>>>>>>>>>>>>> For instance, please, see the Monitor functions with the check: (java_thread == calling_thread). >>>>>>>>>>>>>>> Getting information for current thread is frequently used case, e.g. to get info at an event point. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>> Serguei >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> On 7/2/20 23:29, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>> Hi Dan, David, >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> I uploaded new webrev. Could you review again? >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.04/ >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> OneGetThreadListStackTraces.java in this webrev would wait until thread state is transited to "waiting" with spin wait. >>>>>>>>>>>>>>>> CountDownLatch::await call as Dan pointed is fixed in it :) >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Diff from webrev.03: >>>>>>>>>>>>>>>> http://hg.openjdk.java.net/jdk/submit/rev/c9aeb7001e50 >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> On 2020/07/03 14:15, David Holmes wrote: >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> On 3/07/2020 2:27 pm, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>> On 2020/07/03 12:24, Daniel D. Daugherty wrote: >>>>>>>>>>>>>>>>>>> On 7/2/20 10:50 PM, David Holmes wrote: >>>>>>>>>>>>>>>>>>>> Sorry I'm responding here without seeing latest webrev but there is enough context I think ... >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> On 3/07/2020 9:14 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>> Hi Dan, >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Thanks for your comment! >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> On 2020/07/03 7:16, Daniel D. Daugherty wrote: >>>>>>>>>>>>>>>>>>>>>> On 7/2/20 5:19 AM, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> I upload new webrev. Could you review again? >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.03/ >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnv.cpp >>>>>>>>>>>>>>>>>>>>>> ???? L1542: ??? // Get stack trace with handshake >>>>>>>>>>>>>>>>>>>>>> ???????? nit - please add a period at the end. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> L1591: *stack_info_ptr = op.stack_info(); >>>>>>>>>>>>>>>>>>>>>> ???????? The return parameter should not be touched unless the return >>>>>>>>>>>>>>>>>>>>>> ???????? code in 'err' == JVMTI_ERROR_NONE. >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> ???? old L1582: ? if (err == JVMTI_ERROR_NONE) { >>>>>>>>>>>>>>>>>>>>>> ???????? Please restore this check. The return parameter should not >>>>>>>>>>>>>>>>>>>>>> ???????? be touched unless the return code in 'err' == JVMTI_ERROR_NONE. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> But op.stack_info() will return NULL if the error is not JVMTI_ERROR_NONE. Are you (Dan) concerned about someone passing in a non-null/initialized out-pointer that will be reset to NULL if there was an error? >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Actually the way we used to test this in POSIX tests is to call >>>>>>>>>>>>>>>>>>> an API with known bad parameters and the return parameter ptr >>>>>>>>>>>>>>>>>>> set to NULL. If the return parameter ptr was touched when an >>>>>>>>>>>>>>>>>>> error should have been detected on an earlier parameter, then >>>>>>>>>>>>>>>>>>> the test failed. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> L1272: ? if (!jt->is_exiting() && (thread_oop != NULL)) { >>>>>>>>>>>>>>>>>>>>>> ???????? nit - extra parens around the second expression. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>>>>>>>>>> ???? old L1532: ? _result = JVMTI_ERROR_THREAD_NOT_ALIVE; >>>>>>>>>>>>>>>>>>>>>> ???????? This deletion of the _result field threw me for a minute and then >>>>>>>>>>>>>>>>>>>>>> ???? ? ? I figured out that the field is init to JVMTI_ERROR_THREAD_NOT_ALIVE >>>>>>>>>>>>>>>>>>>>>> ???????? in the constructor. >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> ???? L1553: ? if (!jt->is_exiting() && (jt->threadObj() != NULL)) { >>>>>>>>>>>>>>>>>>>>>> ???????? nit - extra parens around the second expression. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.hpp >>>>>>>>>>>>>>>>>>>>>> ???? No comments. >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> src/hotspot/share/runtime/vmOperations.hpp >>>>>>>>>>>>>>>>>>>>>> ???? No comments. >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/GetThreadListStackTraces.java >>>>>>>>>>>>>>>>>>>>>> ???? No comments. >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/OneGetThreadListStackTraces.java >>>>>>>>>>>>>>>>>>>>>> ???? L64: startSignal.countDown(); >>>>>>>>>>>>>>>>>>>>>> ???????? I was expecting this to be a call to await() instead of >>>>>>>>>>>>>>>>>>>>>> ???????? countDown(). What am I missing here? >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> ???????? I think this test might be passing by accident right now, but... >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Main thread (which call JVMTI functions to test) should wait until test thread is ready. >>>>>>>>>>>>>>>>>>>>> So main thread would wait startSignal, and test thread would count down. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> No! >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> The test thread that previously called obj.wait() now calls latch.await(). >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> The main thread that previously called obj.notify() now calls latch.countDown(). >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> The main thread continues to spin until it sees the target is WAITING before proceeding with the test. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> If I add spin wait to wait until transit target thread state is WAITING (as following), we don't need to call SuspendThread(). >>>>>>>>>>>>>>>>>> Which is better? >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> The original spin-wait loop checking for? WAITING is better because it is the only guarantee that the target thread is blocked where you need it to be. suspending the thread is racy as you don't know exactly where the suspend will hit. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>> /* Wait until the thread state transits to "waiting" */ >>>>>>>>>>>>>>>>>> while (th.getState() != Thread.State.WAITING) { >>>>>>>>>>>>>>>>>> ???? Thread.onSpinWait(); >>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> For simplify, spin wait is prefer to OneGetThreadListStackTraces.java in webrev.03. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Here's the flow as I see it: >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> main thread >>>>>>>>>>>>>>>>>>> ?? - start worker thread >>>>>>>>>>>>>>>>>>> ?? - startSignal.await() >>>>>>>>>>>>>>>>>>> ???? - main is now blocked >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> worker thread >>>>>>>>>>>>>>>>>>> ?? - startSignal.countDown() >>>>>>>>>>>>>>>>>>> ???? - main is now unblocked >>>>>>>>>>>>>>>>>>> ?? - stopSignal.await() >>>>>>>>>>>>>>>>>>> ???? - worker is now blocked >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> main thread >>>>>>>>>>>>>>>>>>> ?? - checkCallStacks(th) >>>>>>>>>>>>>>>>>>> ?? - stopSignal.countDown() >>>>>>>>>>>>>>>>>>> ???? - worker is now unblocked >>>>>>>>>>>>>>>>>>> ?? - th.join >>>>>>>>>>>>>>>>>>> ???? - main is now blocked >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> worker thread >>>>>>>>>>>>>>>>>>> ?? - runs off the end of run() >>>>>>>>>>>>>>>>>>> ???? - main is now unblocked >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> main thread >>>>>>>>>>>>>>>>>>> ?? - run off the end of main() >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libGetThreadListStackTraces.c >>>>>>>>>>>>>>>>>>>>>> ???? L92: ? jthreads = (jthread *)malloc(sizeof(jthread) * num_threads); >>>>>>>>>>>>>>>>>>>>>> ???????? You don't check for malloc() failure. >>>>>>>>>>>>>>>>>>>>>> ???????? 'jthreads' is allocated but never freed. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> I will fix it. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/GetThreadListStackTraces/libOneGetThreadListStackTraces.c >>>>>>>>>>>>>>>>>>>>>> ???? L91: ? result = (*jvmti)->SuspendThread(jvmti, thread); >>>>>>>>>>>>>>>>>>>>>> ???????? Why are you suspending the thread? GetAllStackTraces() and >>>>>>>>>>>>>>>>>>>>>> GetThreadListStackTraces() do not require the target thread(s) >>>>>>>>>>>>>>>>>>>>>> ???????? to be suspend. >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> ???????? If you decide not to SuspendThread, then you don't need the >>>>>>>>>>>>>>>>>>>>>> ???????? AddCapabilities or the ResumeThread calls. >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Test thread might not be entered following code (stopSignal.await()). We might see deferent call stack between GetAllStackTraces() and GetThreadListStackTraces(). We cannot control to freeze call stack of test thread in Java code. >>>>>>>>>>>>>>>>>>>>> (I didn't use SuspendThread() at first, but I saw some errors which causes in above.) >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> So we need to call SuspendThread() to ensure we can see same call stack. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> If you are checking that the thread is in state WAITING then it cannot escape from that state and you can sample the stack multiple times from any API and get the same result. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> I suspect the errors you saw were from the apparent incorrect use of the CountDownLatch. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> With the flow outlined above, the worker thread should be >>>>>>>>>>>>>>>>>>> nicely blocked in stopSignal.await() when stuff is sampled. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Dan >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Cheers, >>>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Dan >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> On 2020/07/02 15:05, David Holmes wrote: >>>>>>>>>>>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> On 1/07/2020 11:53 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>>>>> Hi, >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> I uploaded new webrev. Could review again? >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.02/ >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Updates look fine - thanks. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> One minor nit: >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> 1274 _collector.allocate_and_fill_stacks(1); >>>>>>>>>>>>>>>>>>>>>>>> 1275 _collector.set_result(JVMTI_ERROR_NONE); >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> In the other places where you use _collector you rely on result being initialized to JVMTI_ERROR_NONE, rather than setting it directly after allocate_and_fill_stacks(). >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Fixed. >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> src/hotspot/share/prims/jvmtiEnvBase.cpp >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 820 assert(SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 821 java_thread->is_thread_fully_suspended(false, &debug_bits) || >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 822 current_thread == java_thread->active_handshaker(), >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 823 "at safepoint / handshake or target thread is suspended"); >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> I don't think the suspension check is necessary, as even if the target is suspended we must still be at a safepoint or in a handshake with it. Makes me wonder if we used to allow a racy stacktrace operation on a suspended thread, assuming it would remain suspended? >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> This function (JvmtiEnvBase::get_stack_trace()) can be called to get own stack trace. For example, we can call GetStackTrace() for current thread at JVMTI event. >>>>>>>>>>>>>>>>>>>>>>>>> So I changed assert as below: >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>>>>> ??820 assert(current_thread == java_thread || >>>>>>>>>>>>>>>>>>>>>>>>> ??821 SafepointSynchronize::is_at_safepoint() || >>>>>>>>>>>>>>>>>>>>>>>>> ??822 current_thread == java_thread->active_handshaker(), >>>>>>>>>>>>>>>>>>>>>>>>> ??823????????? "call by myself / at safepoint / at handshake"); >>>>>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Yep good catch. I hope current tests caught that. >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> They would be tested in vmTestbase/nsk/jvmti/GetStackTrace/getstacktr001/ (own call stacks), and getstacktr003 (call stacks in other thread). >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Speaking of tests ... >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> In the native code I think you need to check the success of all JNI methods that can throw exceptions - otherwise I believe the tests may trigger warnings if -Xcheck:jni is used with them. See for example: >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/libHeapMonitorTest.cpp >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> I updated testcases to check JNI and JVMTI function calls. >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> In the Java code the target thread: >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> ?? 45???? public void run() { >>>>>>>>>>>>>>>>>>>>>>>> ?? 46?????? try { >>>>>>>>>>>>>>>>>>>>>>>> ?? 47 synchronized (lock) { >>>>>>>>>>>>>>>>>>>>>>>> ?? 48 lock.wait(); >>>>>>>>>>>>>>>>>>>>>>>> ?? 49 System.out.println("OK"); >>>>>>>>>>>>>>>>>>>>>>>> ?? 50?????????? } >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> is potentially susceptible to spurious wakeups. Using a CountDownLatch would be robust. >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Fixed. >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> On 2020/07/01 8:48, David Holmes wrote: >>>>>>>>>>>>>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> On 1/07/2020 9:05 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 1271 ResourceMark rm; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> IIUC at this point the _calling_thread is the current thread, so we can use: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ResourceMark rm(_calling_thread); >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> If so, we can call make_local() in L1272 without JavaThread (or we can pass current thread to make_local()). Is it right? >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>>>>>>> 1271 ResourceMark rm; >>>>>>>>>>>>>>>>>>>>>>>>>>> 1272 _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, thread_oop), >>>>>>>>>>>>>>>>>>>>>>>>>>> 1273 jt, thread_oop); >>>>>>>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> Sorry I got confused, _calling_thread may not be the current thread as we could be executing the handshake in the target thread itself. So the ResourceMark is correct as-is (implicitly for current thread). >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> The argument to fill_frames will be used in the jvmtiStackInfo and passed back to the _calling_thread, so it must be created via make_local(_calling_thread, ...) as you presently have. >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>> On 2020/07/01 7:05, David Holmes wrote: >>>>>>>>>>>>>>>>>>>>>>>>>>>> On 1/07/2020 12:17 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>>>>>>>>> Hi David, >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> Thank you for reviewing! I will update new webrev tomorrow. >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 466 class MultipleStackTracesCollector : public StackObj { >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 498 class VM_GetAllStackTraces : public VM_Operation { >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 499 private: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 500 JavaThread *_calling_thread; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 501?? jint _final_thread_count; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ? 502 MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> You can't have a StackObj as a member of another class like that as it may not be on the stack. I think MultipleStackTracesCollector should not extend any allocation class, and should always be embedded directly in another class. >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> I'm not sure what does mean "embedded". >>>>>>>>>>>>>>>>>>>>>>>>>>>>> Is it ok as below? >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>>>>>>>>> class MultipleStackTracesCollector { >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ??? : >>>>>>>>>>>>>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> class GetAllStackTraces : public VM_Operation { >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ?? private: >>>>>>>>>>>>>>>>>>>>>>>>>>>>> MultipleStackTracesCollector _collector; >>>>>>>>>>>>>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>>>>>>>>>>>>> ``` >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> Yes that I what I meant. >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>>>>> David >>>>>>>>>>>>>>>>>>>>>>>>>>>> ----- >>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> Yasumasa >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>> On 2020/06/30 22:22, David Holmes wrote: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Hi Yasumasa, >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> On 30/06/2020 10:05 am, Yasumasa Suenaga wrote: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Hi David, Serguei, >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> I updated webrev for 8242428. Could you review again? >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> This change migrate to use direct handshake for GetStackTrace() and GetThreadListStackTraces() (when thread_count == 1). >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.01/ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>