blob: 43af687d13351b97f8f14d6e3f3832bab10cd901 [file] [log] [blame]
/*
* Copyright (c) 2007, 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.
*/
package nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn009;
import nsk.share.Log;
import nsk.share.jdi.*;
public class forceEarlyReturn009a extends AbstractJDIDebuggee {
public static void main(String args[]) {
new forceEarlyReturn009a().doTest(args);
}
public final static String testThreadWithSingleFrameName = "forceEarlyReturn009aTestThreadWithSingleFrame";
// command:[inlineType]
public final static String COMMAND_RUN_THREAD_WITH_SINGLE_FRAME = "runThreadWithSingleFrame";
public final static String COMMAND_JOIN_THREAD_WITH_SINGLE_FRAME = "joinThreadWithSingleFrame";
// type of inlined methods
enum InlineType {
// method return const values
INLINE_METHOD_RETURNING_CONST,
// method access only internal fields
INLINE_METHOD_ACCESSIN_INTERNAL_FIELDS,
// method which should be executed a certain number of times before it is compiled
INLINE_HOT_METHOD
}
/*
* Thread can has single frame on the stack because of methods which this thread calls was inlined
*
* inlineType - type of inlined methods which test thread calls
*/
private InlineType inlineType;
public boolean parseCommand(String command) {
if (super.parseCommand(command))
return true;
if (command.startsWith(COMMAND_RUN_THREAD_WITH_SINGLE_FRAME)) {
int index = command.indexOf(':');
if (index < 0) {
inlineType = null;
} else {
inlineType = InlineType.valueOf(command.substring(index + 1));
log.display("InlineType: " + inlineType);
}
runThreadWithSingleFrame();
return true;
} else if (command.equals(COMMAND_JOIN_THREAD_WITH_SINGLE_FRAME)) {
joinThreadWithSingleFrame();
return true;
}
return false;
}
private ThreadWithSingleFrame threadWithSingleFrame;
static class ThreadWithSingleFrame extends Thread {
volatile boolean isSingleFrameThreadStarted;
// this variable is used to stop thread with signle frame if debugger can't stop it by forceEarlyReturn
// (for example if inlining was not done)
volatile boolean isSingleFrameThreadStoped;
private Log log;
private InlineType inlineType;
public ThreadWithSingleFrame(Log log, InlineType inlineType) {
this.log = log;
this.inlineType = inlineType;
if (inlineType == InlineType.INLINE_HOT_METHOD) {
// call inlinedHotMethod1() and inlinedHotMethod2() 20000 times to be sure that this method was compiled/inlined
for (long i = 0; i < 20000; i++) {
inlinedHotMethod1();
inlinedHotMethod2();
}
}
}
private int internalField1;
private int inlinedMethodAccessingInternalFields1() {
return internalField1++ + internalField2;
}
private int internalField2;
private int inlinedMethodAccessingInternalFields2() {
return internalField2++ + internalField1;
}
private int inlinedMethodReturningInt() {
return 0;
}
private boolean inlinedMethodReturningBoolean() {
return true;
}
private Object inlinedMethodReturningObject() {
return null;
}
public int publicField1;
public int publicField2;
public int inlinedHotMethod1() {
return publicField1++ + publicField2 * 2;
}
public int inlinedHotMethod2() {
return publicField2++ + publicField1 * 2;
}
public void run() {
Thread.currentThread().setName(testThreadWithSingleFrameName);
log.display("Thread with single frame started");
// if inlineType was specified call methods which should be inlined
if (inlineType == InlineType.INLINE_METHOD_ACCESSIN_INTERNAL_FIELDS) {
while (!isSingleFrameThreadStoped) {
inlinedMethodAccessingInternalFields1();
inlinedMethodAccessingInternalFields2();
isSingleFrameThreadStarted = true;
}
} else if (inlineType == InlineType.INLINE_METHOD_RETURNING_CONST) {
while (!isSingleFrameThreadStoped) {
boolean bool = inlinedMethodReturningBoolean();
int integer = inlinedMethodReturningInt();
Object object = inlinedMethodReturningObject();
isSingleFrameThreadStarted = true;
}
} else if (inlineType == InlineType.INLINE_HOT_METHOD) {
while (!isSingleFrameThreadStoped) {
int temp = inlinedHotMethod1() + inlinedHotMethod2();
isSingleFrameThreadStarted = true;
}
} else {
while (!isSingleFrameThreadStoped)
isSingleFrameThreadStarted = true;
}
}
}
private void runThreadWithSingleFrame() {
threadWithSingleFrame = new ThreadWithSingleFrame(log, inlineType);
threadWithSingleFrame.start();
while (!threadWithSingleFrame.isSingleFrameThreadStarted)
Thread.yield();
}
private void joinThreadWithSingleFrame() {
try {
threadWithSingleFrame.isSingleFrameThreadStoped = true;
threadWithSingleFrame.join(argHandler.getWaitTime() * 60000);
if (threadWithSingleFrame.getState() != Thread.State.TERMINATED) {
setSuccess(false);
log.complain("ThreadWithSingleThread didn'f finish execution as expected");
}
} catch (InterruptedException e) {
setSuccess(false);
log.complain("Unexpected exception: " + e);
}
}
}