# HG changeset patch # User psomashe # Date 1518198965 28800 # Node ID e999964446d76ba3904f66a9981b83a1e40fd6ec # Parent 950c35ea6237afd834d02345a2878e5dc30750e0 8193150: Create a jtreg version of the test from JDK-8187143. Summary: Create a new jtreg test based on the test attached to the bug and add it to the ProblemsList. Reviewed-by: sspitsyn, cjplummer diff -r 950c35ea6237 -r e999964446d7 test/jdk/ProblemList.txt --- a/test/jdk/ProblemList.txt Fri Feb 09 08:23:42 2018 -0500 +++ b/test/jdk/ProblemList.txt Fri Feb 09 09:56:05 2018 -0800 @@ -481,6 +481,8 @@ com/sun/jdi/sde/SourceDebugExtensionTest.java 8158066 windows-all +com/sun/jdi/NashornPopFrameTest.java 8187143 generic-all + ############################################################################ # jdk_time diff -r 950c35ea6237 -r e999964446d7 test/jdk/com/sun/jdi/NashornPopFrameTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jdk/com/sun/jdi/NashornPopFrameTest.java Fri Feb 09 09:56:05 2018 -0800 @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8187143 + * @summary JDI crash in ~BufferBlob::MethodHandles adapters + * + * @run build TestScaffold VMConnection TargetListener TargetAdapter + * @run compile -g NashornPopFrameTest.java + * @run driver NashornPopFrameTest + */ +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import jdk.nashorn.api.scripting.NashornScriptEngineFactory; +import javax.script.*; + +import java.io.PrintStream; + + +// The debuggee, creates and uses a Nashorn engine to evaluate a simple script. + +// The debugger tries to set a breakpoint in Nashorn internal DEBUGGER method. +// When the breakpoint is reached, it looks for stack frame whose method's +// declaring type name starts with jdk.nashorn.internal.scripts.Script$. +// (nashorn dynamically generated classes) +// It then pops stack frames using the ThreadReference.popFrames() call, up to +// and including the above stackframe. +// The execution of the debuggee application is resumed after the needed +// frames have been popped. + +class ScriptDebuggee { + public final static int BKPT_LINE = 74; + static ScriptEngine engine = new NashornScriptEngineFactory().getScriptEngine(); + static public String failReason = null; + + static void doit() throws Exception { + System.out.println("Debugee: started!"); + String script = + "function f() {\r\n" + + " debugger;\r\n" + + " debugger;\r\n" + + "}\r\n" + + "f();"; + try { + engine.eval(script); + } catch (Exception ex) { + failReason = "ScriptDebuggee failed: Exception in engine.eval(): " + + ex.toString(); + ex.printStackTrace(); + } + System.out.println("Debugee: finished!"); // BKPT_LINE + } + + public static void main(String[] args) throws Exception { + doit(); + } +} + +/********** test program **********/ + +public class NashornPopFrameTest extends TestScaffold { + static PrintStream out = System.out; + static boolean breakpointReached = false; + String debuggeeFailReason = null; + ClassType targetClass; + ThreadReference mainThread; + BreakpointRequest bkptRequest; + + NashornPopFrameTest(String args[]) { + super(args); + } + + public static void main(String[] args) throws Exception { + NashornPopFrameTest nashornPopFrameTest = new NashornPopFrameTest(args); + nashornPopFrameTest.startTests(); + } + + /********** test core **********/ + + protected void runTests() throws Exception { + /* + * Get to the top of main() to determine targetClass and mainThread + */ + BreakpointEvent bpe = startToMain("ScriptDebuggee"); + targetClass = (ClassType)bpe.location().declaringType(); + out.println("Agent: runTests: after startToMain()"); + + mainThread = bpe.thread(); + EventRequestManager erm = vm().eventRequestManager(); + + Location loc = findLocation(targetClass, ScriptDebuggee.BKPT_LINE); + + try { + addListener(this); + } catch (Exception ex){ + ex.printStackTrace(); + failure("Failed: Could not add listener"); + throw new Exception("NashornPopFrameTest: failed with Exception in AddListener"); + } + + pauseAtDebugger(vm()); + bkptRequest = erm.createBreakpointRequest(loc); + bkptRequest.enable(); + + vm().resume(); + + try { + listen(vm()); + } catch (Exception exp) { + exp.printStackTrace(); + failure("Failed: Caught Exception while Listening"); + throw new Exception("NashornPopFrameTest: failed with Exception in listen()"); + } + + // Debugger continues to run until it receives a VMdisconnect event either because + // the Debuggee crashed / got exception / finished successfully. + while (!vmDisconnected) { + try { + Thread.sleep(100); + } catch (InterruptedException ee) { + } + } + + removeListener(this); + + if (breakpointReached) { + if (debuggeeFailReason != null) { + failure(debuggeeFailReason); + } + } else { + failure("Expected breakpoint in ScriptDebuggee:" + + ScriptDebuggee.BKPT_LINE + " was not reached"); + } + if (testFailed) { + throw new Exception("NashornPopFrameTest: failed"); + } + out.println("NashornPopFrameTest: passed"); + } + + private static void pauseAtDebugger(VirtualMachine vm) throws AbsentInformationException { + for (ReferenceType t : vm.allClasses()) pauseAtDebugger(t); + } + + // Set a breakpoint in Nashorn internal DEBUGGER method. + private static void pauseAtDebugger(ReferenceType t) throws AbsentInformationException { + if (!t.name().endsWith(".ScriptRuntime")) { + return; + } + for (Location l : t.allLineLocations()) { + if (!l.method().name().equals("DEBUGGER")) continue; + BreakpointRequest bkptReq = t.virtualMachine().eventRequestManager().createBreakpointRequest(l); + out.println("Setting breakpoint for " + l); + bkptReq.enable(); + break; + } + } + + private static void listen(VirtualMachine vm) throws Exception { + EventQueue eventQueue = vm.eventQueue(); + EventSet es = eventQueue.remove(); + if (es != null) { + handle(es); + } + } + + // Handle event when breakpoint is reached + private static void handle(EventSet eventSet) throws Exception { + out.println("Agent handle(): started"); + for (Event event : eventSet) { + if (event instanceof BreakpointEvent) { + findFrameAndPop(event); + } + } + eventSet.resume(); + out.println("Agent handle(): finished"); + } + + private static void findFrameAndPop(Event event) throws Exception { + ThreadReference thread = ((BreakpointEvent) event).thread(); + out.println("Agent: handling Breakpoint " + " at " + + ((BreakpointEvent) event).location() + + " in thread: " + thread); + StackFrame sf = findScriptFrame(thread); + if (sf != null) { + out.println("Thread Pop Frame on StackFrame = " + sf); + thread.popFrames(sf); + } + } + + // Find stack frame whose method's declaring type name starts with + // jdk.nashorn.internal.scripts.Script$ and return that frame + private static StackFrame findScriptFrame(ThreadReference t) throws IncompatibleThreadStateException { + for (int i = 0; i < t.frameCount(); i++) { + StackFrame sf = t.frame(i); + String typeName = sf.location().method().declaringType().name(); + if (typeName.startsWith("jdk.nashorn.internal.scripts.Script$")) { + out.println("Agent: in findScriptFrame: TypeName = " + typeName); + return sf; + } + } + throw new RuntimeException("no script frame"); + } + + static int bkptCount = 0; + + /********** event handlers **********/ + + public void breakpointReached(BreakpointEvent event) { + ThreadReference thread = ((BreakpointEvent) event).thread(); + String locStr = "" + ((BreakpointEvent) event).location(); + out.println("Agent: BreakpointEvent #" + (bkptCount++) + + " at " + locStr + " in thread: " + thread); + if (locStr.equals("ScriptDebuggee:" + ScriptDebuggee.BKPT_LINE)) { + breakpointReached = true; + Field failReasonField = targetClass.fieldByName("failReason"); + Value failReasonVal = targetClass.getValue(failReasonField); + if (failReasonVal != null) { + debuggeeFailReason = ((StringReference)failReasonVal).value(); + } + bkptRequest.disable(); + } + } + + public void eventSetComplete(EventSet set) { + set.resume(); + } + + public void vmDisconnected(VMDisconnectEvent event) { + println("Agent: Got VMDisconnectEvent"); + } + +}