Merge
This commit is contained in:
commit
32b042e285
@ -1,22 +1,22 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>
|
<title>
|
||||||
C2 Replay
|
Replay
|
||||||
</title>
|
</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<h1>C2 compiler replay</h1>
|
<h1>Compiler replay</h1>
|
||||||
<p>
|
<p>
|
||||||
The C2 compiler replay is a function to repeat the compiling process from a crashed java process in compiled method<br>
|
The compiler replay is a function to repeat the compiling process from a crashed java process in compiled method<br>
|
||||||
This function only exists in debug version of VM
|
This function only exists in debug version of VM
|
||||||
</p>
|
</p>
|
||||||
<h2>Usage</h2>
|
<h2>Usage</h2>
|
||||||
<pre>
|
<pre>
|
||||||
First, use SA to attach to the core file, if suceeded, do
|
First, use SA to attach to the core file, if succeeded, do
|
||||||
clhsdb>dumpreplaydata <address> | -a | <thread_id> [> replay.txt]
|
hsdb> dumpreplaydata <address> | -a | <thread_id> [> replay.txt]
|
||||||
create file replay.txt, address is address of Method, or nmethod(CodeBlob)
|
create file replay.txt, address is address of Method, or nmethod(CodeBlob)
|
||||||
clhsdb>buildreplayjars [all | boot | app]
|
hsdb> buildreplayjars [all | boot | app]
|
||||||
create files:
|
create files:
|
||||||
all:
|
all:
|
||||||
app.jar, boot.jar
|
app.jar, boot.jar
|
||||||
@ -26,16 +26,16 @@ First, use SA to attach to the core file, if suceeded, do
|
|||||||
app.jar
|
app.jar
|
||||||
exit SA now.
|
exit SA now.
|
||||||
Second, use the obtained replay text file, replay.txt and jar files, app.jar and boot.jar, using debug version of java
|
Second, use the obtained replay text file, replay.txt and jar files, app.jar and boot.jar, using debug version of java
|
||||||
java -Xbootclasspath/p:boot.jar -cp app.jar -XX:ReplayDataFile=<datafile> -XX:+ReplayCompiles ....
|
java -Xbootclasspath/p:boot.jar -cp app.jar -XX:ReplayDataFile=<datafile> -XX:+ReplayCompiles ....
|
||||||
This will replay the compiling process.
|
This will replay the compiling process.
|
||||||
|
|
||||||
With ReplayCompiles, the replay will recompile all the methods in app.jar, and in boot.jar to emulate the process in java app.
|
With ReplayCompiles, the replay will recompile all the methods in app.jar, and in boot.jar to emulate the process in java app.
|
||||||
|
|
||||||
notes:
|
notes:
|
||||||
1) Most time, we don't need the boot.jar which is the classes loaded from JDK. It will be only modified when an agent(JVMDI) is running and modifies the classes.
|
1) Most time, we don't need the boot.jar which is the classes loaded from JDK. It will be only modified when an agent(JVMDI) is running and modifies the classes.
|
||||||
2) If encounter error as "<flag>" not found, that means the SA is using a VMStructs which is different from the one with corefile. In this case, SA has a utility tool vmstructsdump which is located at agent/src/os/<os>/proc/<os_platform>
|
2) If encounter error as "<flag>" not found, that means the SA is using a VMStructs which is different from the one with corefile. In this case, SA has a utility tool vmstructsdump which is located at agent/src/os/<os>/proc/<os_platform>
|
||||||
|
|
||||||
Use this tool to dump VM type library:
|
Use this tool to dump VM type library:
|
||||||
vmstructsdump libjvm.so > <type_name>.db
|
vmstructsdump libjvm.so > <type_name>.db
|
||||||
|
|
||||||
set env SA_TYPEDB=<type_name>.db (refer different shell for set envs)
|
set env SA_TYPEDB=<type_name>.db (refer different shell for set envs)
|
@ -15,7 +15,7 @@ GUI tools. Command line HSDB (CLHSDB) tool is alternative to SA GUI tool HSDB.
|
|||||||
<p>
|
<p>
|
||||||
There is also JavaScript based SA command line interface called <a href="jsdb.html">jsdb</a>.
|
There is also JavaScript based SA command line interface called <a href="jsdb.html">jsdb</a>.
|
||||||
But, CLHSDB supports Unix shell-like (or dbx/gdb-like) command line interface with
|
But, CLHSDB supports Unix shell-like (or dbx/gdb-like) command line interface with
|
||||||
support for output redirection/appending (familiar >, >>), command history and so on.
|
support for output redirection/appending (familiar >, >>), command history and so on.
|
||||||
Each CLHSDB command can have zero or more arguments and optionally end with output redirection
|
Each CLHSDB command can have zero or more arguments and optionally end with output redirection
|
||||||
(or append) to a file. Commands may be stored in a file and run using <b>source</b> command.
|
(or append) to a file. Commands may be stored in a file and run using <b>source</b> command.
|
||||||
<b>help</b> command prints usage message for all supported commands (or a specific command)
|
<b>help</b> command prints usage message for all supported commands (or a specific command)
|
||||||
@ -49,7 +49,7 @@ Available commands:
|
|||||||
dumpheap [ file ] <font color="red">dump heap in hprof binary format</font>
|
dumpheap [ file ] <font color="red">dump heap in hprof binary format</font>
|
||||||
dumpideal -a | id <font color="red">dump ideal graph like debug flag -XX:+PrintIdeal</font>
|
dumpideal -a | id <font color="red">dump ideal graph like debug flag -XX:+PrintIdeal</font>
|
||||||
dumpilt -a | id <font color="red">dump inline tree for C2 compilation</font>
|
dumpilt -a | id <font color="red">dump inline tree for C2 compilation</font>
|
||||||
dumpreplaydata <address> | -a | <thread_id> [>replay.txt] <font color="red">dump replay data into a file</font>
|
dumpreplaydata <address> | -a | <thread_id> [>replay.txt] <font color="red">dump replay data into a file</font>
|
||||||
echo [ true | false ] <font color="red">turn on/off command echo mode</font>
|
echo [ true | false ] <font color="red">turn on/off command echo mode</font>
|
||||||
examine [ address/count ] | [ address,address] <font color="red">show contents of memory from given address</font>
|
examine [ address/count ] | [ address,address] <font color="red">show contents of memory from given address</font>
|
||||||
field [ type [ name fieldtype isStatic offset address ] ] <font color="red">print info about a field of HotSpot type</font>
|
field [ type [ name fieldtype isStatic offset address ] ] <font color="red">print info about a field of HotSpot type</font>
|
||||||
@ -96,11 +96,11 @@ Available commands:
|
|||||||
|
|
||||||
<h3>JavaScript integration</h3>
|
<h3>JavaScript integration</h3>
|
||||||
|
|
||||||
<p>Few CLHSDB commands are already implemented in JavaScript. It is possible to extend CLHSDB command set
|
<p>Few CLHSDB commands are already implemented in JavaScript. It is possible to extend CLHSDB command set
|
||||||
by implementing more commands in a JavaScript file and by loading it by <b>jsload</b> command. <b>jseval</b>
|
by implementing more commands in a JavaScript file and by loading it by <b>jsload</b> command. <b>jseval</b>
|
||||||
command may be used to evaluate arbitrary JavaScript expression from a string. Any JavaScript function
|
command may be used to evaluate arbitrary JavaScript expression from a string. Any JavaScript function
|
||||||
may be exposed as a CLHSDB command by registering it using JavaScript <b><code>registerCommand</code></b>
|
may be exposed as a CLHSDB command by registering it using JavaScript <b><code>registerCommand</code></b>
|
||||||
function. This function accepts command name, usage and name of the JavaScript implementation function
|
function. This function accepts command name, usage and name of the JavaScript implementation function
|
||||||
as arguments.
|
as arguments.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@ -127,11 +127,11 @@ hsdb> jsload test.js
|
|||||||
</code>
|
</code>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<h3>C2 Compilation Replay</h3>
|
<h3>Compilation Replay</h3>
|
||||||
<p>
|
<p>
|
||||||
When a java process crashes in compiled method, usually a core file is saved.
|
When a java process crashes in compiled method, usually a core file is saved.
|
||||||
The C2 replay function can reproduce the compiling process in the core.
|
The replay function can reproduce the compiling process in the core.
|
||||||
<a href="c2replay.html">c2replay.html</a>
|
<a href="cireplay.html">cireplay.html</a>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -93,10 +93,11 @@ public class ciEnv extends VMObject {
|
|||||||
CompileTask task = task();
|
CompileTask task = task();
|
||||||
Method method = task.method();
|
Method method = task.method();
|
||||||
int entryBci = task.osrBci();
|
int entryBci = task.osrBci();
|
||||||
|
int compLevel = task.compLevel();
|
||||||
Klass holder = method.getMethodHolder();
|
Klass holder = method.getMethodHolder();
|
||||||
out.println("compile " + holder.getName().asString() + " " +
|
out.println("compile " + holder.getName().asString() + " " +
|
||||||
OopUtilities.escapeString(method.getName().asString()) + " " +
|
OopUtilities.escapeString(method.getName().asString()) + " " +
|
||||||
method.getSignature().asString() + " " +
|
method.getSignature().asString() + " " +
|
||||||
entryBci);
|
entryBci + " " + compLevel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,6 +78,8 @@ public class NMethod extends CodeBlob {
|
|||||||
current sweep traversal index. */
|
current sweep traversal index. */
|
||||||
private static CIntegerField stackTraversalMarkField;
|
private static CIntegerField stackTraversalMarkField;
|
||||||
|
|
||||||
|
private static CIntegerField compLevelField;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
VM.registerVMInitializedObserver(new Observer() {
|
VM.registerVMInitializedObserver(new Observer() {
|
||||||
public void update(Observable o, Object data) {
|
public void update(Observable o, Object data) {
|
||||||
@ -113,7 +115,7 @@ public class NMethod extends CodeBlob {
|
|||||||
osrEntryPointField = type.getAddressField("_osr_entry_point");
|
osrEntryPointField = type.getAddressField("_osr_entry_point");
|
||||||
lockCountField = type.getJIntField("_lock_count");
|
lockCountField = type.getJIntField("_lock_count");
|
||||||
stackTraversalMarkField = type.getCIntegerField("_stack_traversal_mark");
|
stackTraversalMarkField = type.getCIntegerField("_stack_traversal_mark");
|
||||||
|
compLevelField = type.getCIntegerField("_comp_level");
|
||||||
pcDescSize = db.lookupType("PcDesc").getSize();
|
pcDescSize = db.lookupType("PcDesc").getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -530,7 +532,7 @@ public class NMethod extends CodeBlob {
|
|||||||
out.println("compile " + holder.getName().asString() + " " +
|
out.println("compile " + holder.getName().asString() + " " +
|
||||||
OopUtilities.escapeString(method.getName().asString()) + " " +
|
OopUtilities.escapeString(method.getName().asString()) + " " +
|
||||||
method.getSignature().asString() + " " +
|
method.getSignature().asString() + " " +
|
||||||
getEntryBCI());
|
getEntryBCI() + " " + getCompLevel());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -551,4 +553,5 @@ public class NMethod extends CodeBlob {
|
|||||||
private int getHandlerTableOffset() { return (int) handlerTableOffsetField.getValue(addr); }
|
private int getHandlerTableOffset() { return (int) handlerTableOffsetField.getValue(addr); }
|
||||||
private int getNulChkTableOffset() { return (int) nulChkTableOffsetField .getValue(addr); }
|
private int getNulChkTableOffset() { return (int) nulChkTableOffsetField .getValue(addr); }
|
||||||
private int getNMethodEndOffset() { return (int) nmethodEndOffsetField .getValue(addr); }
|
private int getNMethodEndOffset() { return (int) nmethodEndOffsetField .getValue(addr); }
|
||||||
|
private int getCompLevel() { return (int) compLevelField .getValue(addr); }
|
||||||
}
|
}
|
||||||
|
@ -46,10 +46,12 @@ public class CompileTask extends VMObject {
|
|||||||
Type type = db.lookupType("CompileTask");
|
Type type = db.lookupType("CompileTask");
|
||||||
methodField = type.getAddressField("_method");
|
methodField = type.getAddressField("_method");
|
||||||
osrBciField = new CIntField(type.getCIntegerField("_osr_bci"), 0);
|
osrBciField = new CIntField(type.getCIntegerField("_osr_bci"), 0);
|
||||||
|
compLevelField = new CIntField(type.getCIntegerField("_comp_level"), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static AddressField methodField;
|
private static AddressField methodField;
|
||||||
private static CIntField osrBciField;
|
private static CIntField osrBciField;
|
||||||
|
private static CIntField compLevelField;
|
||||||
|
|
||||||
public CompileTask(Address addr) {
|
public CompileTask(Address addr) {
|
||||||
super(addr);
|
super(addr);
|
||||||
@ -63,4 +65,8 @@ public class CompileTask extends VMObject {
|
|||||||
public int osrBci() {
|
public int osrBci() {
|
||||||
return (int)osrBciField.getValue(getAddress());
|
return (int)osrBciField.getValue(getAddress());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int compLevel() {
|
||||||
|
return (int)compLevelField.getValue(getAddress());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1230,10 +1230,6 @@ bool os::dll_build_name(char* buffer, size_t buflen,
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* os::get_current_directory(char *buf, int buflen) {
|
|
||||||
return getcwd(buf, buflen);
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if addr is inside libjvm.so
|
// check if addr is inside libjvm.so
|
||||||
bool os::address_is_in_vm(address addr) {
|
bool os::address_is_in_vm(address addr) {
|
||||||
static address libjvm_base_addr;
|
static address libjvm_base_addr;
|
||||||
|
@ -1662,10 +1662,6 @@ bool os::dll_build_name(char* buffer, size_t buflen,
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* os::get_current_directory(char *buf, int buflen) {
|
|
||||||
return getcwd(buf, buflen);
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if addr is inside libjvm.so
|
// check if addr is inside libjvm.so
|
||||||
bool os::address_is_in_vm(address addr) {
|
bool os::address_is_in_vm(address addr) {
|
||||||
static address libjvm_base_addr;
|
static address libjvm_base_addr;
|
||||||
|
@ -251,3 +251,11 @@ bool os::has_allocatable_memory_limit(julong* limit) {
|
|||||||
return true;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* os::get_current_directory(char *buf, size_t buflen) {
|
||||||
|
return getcwd(buf, buflen);
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE* os::open(int fd, const char* mode) {
|
||||||
|
return ::fdopen(fd, mode);
|
||||||
|
}
|
||||||
|
@ -1915,10 +1915,6 @@ bool os::dll_build_name(char* buffer, size_t buflen,
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* os::get_current_directory(char *buf, int buflen) {
|
|
||||||
return getcwd(buf, buflen);
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if addr is inside libjvm.so
|
// check if addr is inside libjvm.so
|
||||||
bool os::address_is_in_vm(address addr) {
|
bool os::address_is_in_vm(address addr) {
|
||||||
static address libjvm_base_addr;
|
static address libjvm_base_addr;
|
||||||
|
@ -1221,8 +1221,10 @@ bool os::dll_build_name(char *buffer, size_t buflen,
|
|||||||
|
|
||||||
// Needs to be in os specific directory because windows requires another
|
// Needs to be in os specific directory because windows requires another
|
||||||
// header file <direct.h>
|
// header file <direct.h>
|
||||||
const char* os::get_current_directory(char *buf, int buflen) {
|
const char* os::get_current_directory(char *buf, size_t buflen) {
|
||||||
return _getcwd(buf, buflen);
|
int n = static_cast<int>(buflen);
|
||||||
|
if (buflen > INT_MAX) n = INT_MAX;
|
||||||
|
return _getcwd(buf, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------
|
//-----------------------------------------------------------
|
||||||
@ -4098,6 +4100,10 @@ int os::open(const char *path, int oflag, int mode) {
|
|||||||
return ::open(pathbuf, oflag | O_BINARY | O_NOINHERIT, mode);
|
return ::open(pathbuf, oflag | O_BINARY | O_NOINHERIT, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FILE* os::open(int fd, const char* mode) {
|
||||||
|
return ::_fdopen(fd, mode);
|
||||||
|
}
|
||||||
|
|
||||||
// Is a (classpath) directory empty?
|
// Is a (classpath) directory empty?
|
||||||
bool os::dir_is_empty(const char* path) {
|
bool os::dir_is_empty(const char* path) {
|
||||||
WIN32_FIND_DATA fd;
|
WIN32_FIND_DATA fd;
|
||||||
|
@ -1149,23 +1149,9 @@ void ciEnv::record_out_of_memory_failure() {
|
|||||||
record_method_not_compilable("out of memory");
|
record_method_not_compilable("out of memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
fileStream* ciEnv::_replay_data_stream = NULL;
|
void ciEnv::dump_replay_data(outputStream* out) {
|
||||||
|
|
||||||
void ciEnv::dump_replay_data() {
|
|
||||||
VM_ENTRY_MARK;
|
VM_ENTRY_MARK;
|
||||||
MutexLocker ml(Compile_lock);
|
MutexLocker ml(Compile_lock);
|
||||||
if (_replay_data_stream == NULL) {
|
|
||||||
_replay_data_stream = new (ResourceObj::C_HEAP, mtCompiler) fileStream(ReplayDataFile);
|
|
||||||
if (_replay_data_stream == NULL) {
|
|
||||||
fatal(err_msg("Can't open %s for replay data", ReplayDataFile));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dump_replay_data(_replay_data_stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ciEnv::dump_replay_data(outputStream* out) {
|
|
||||||
ASSERT_IN_VM;
|
|
||||||
ResourceMark rm;
|
ResourceMark rm;
|
||||||
#if INCLUDE_JVMTI
|
#if INCLUDE_JVMTI
|
||||||
out->print_cr("JvmtiExport can_access_local_variables %d", _jvmti_can_access_local_variables);
|
out->print_cr("JvmtiExport can_access_local_variables %d", _jvmti_can_access_local_variables);
|
||||||
@ -1178,13 +1164,15 @@ void ciEnv::dump_replay_data(outputStream* out) {
|
|||||||
for (int i = 0; i < objects->length(); i++) {
|
for (int i = 0; i < objects->length(); i++) {
|
||||||
objects->at(i)->dump_replay_data(out);
|
objects->at(i)->dump_replay_data(out);
|
||||||
}
|
}
|
||||||
Method* method = task()->method();
|
CompileTask* task = this->task();
|
||||||
int entry_bci = task()->osr_bci();
|
Method* method = task->method();
|
||||||
|
int entry_bci = task->osr_bci();
|
||||||
|
int comp_level = task->comp_level();
|
||||||
// Klass holder = method->method_holder();
|
// Klass holder = method->method_holder();
|
||||||
out->print_cr("compile %s %s %s %d",
|
out->print_cr("compile %s %s %s %d %d",
|
||||||
method->klass_name()->as_quoted_ascii(),
|
method->klass_name()->as_quoted_ascii(),
|
||||||
method->name()->as_quoted_ascii(),
|
method->name()->as_quoted_ascii(),
|
||||||
method->signature()->as_quoted_ascii(),
|
method->signature()->as_quoted_ascii(),
|
||||||
entry_bci);
|
entry_bci, comp_level);
|
||||||
out->flush();
|
out->flush();
|
||||||
}
|
}
|
||||||
|
@ -46,8 +46,6 @@ class ciEnv : StackObj {
|
|||||||
friend class CompileBroker;
|
friend class CompileBroker;
|
||||||
friend class Dependencies; // for get_object, during logging
|
friend class Dependencies; // for get_object, during logging
|
||||||
|
|
||||||
static fileStream* _replay_data_stream;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Arena* _arena; // Alias for _ciEnv_arena except in init_shared_objects()
|
Arena* _arena; // Alias for _ciEnv_arena except in init_shared_objects()
|
||||||
Arena _ciEnv_arena;
|
Arena _ciEnv_arena;
|
||||||
@ -451,10 +449,6 @@ public:
|
|||||||
// RedefineClasses support
|
// RedefineClasses support
|
||||||
void metadata_do(void f(Metadata*)) { _factory->metadata_do(f); }
|
void metadata_do(void f(Metadata*)) { _factory->metadata_do(f); }
|
||||||
|
|
||||||
// Dump the compilation replay data for this ciEnv to
|
|
||||||
// ReplayDataFile, creating the file if needed.
|
|
||||||
void dump_replay_data();
|
|
||||||
|
|
||||||
// Dump the compilation replay data for the ciEnv to the stream.
|
// Dump the compilation replay data for the ciEnv to the stream.
|
||||||
void dump_replay_data(outputStream* out);
|
void dump_replay_data(outputStream* out);
|
||||||
};
|
};
|
||||||
|
@ -196,7 +196,6 @@ class ciMethod : public ciMetadata {
|
|||||||
// Analysis and profiling.
|
// Analysis and profiling.
|
||||||
//
|
//
|
||||||
// Usage note: liveness_at_bci and init_vars should be wrapped in ResourceMarks.
|
// Usage note: liveness_at_bci and init_vars should be wrapped in ResourceMarks.
|
||||||
bool uses_monitors() const { return _uses_monitors; } // this one should go away, it has a misleading name
|
|
||||||
bool has_monitor_bytecodes() const { return _uses_monitors; }
|
bool has_monitor_bytecodes() const { return _uses_monitors; }
|
||||||
bool has_balanced_monitors();
|
bool has_balanced_monitors();
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ class CompileReplay : public StackObj {
|
|||||||
loader = Handle(thread, SystemDictionary::java_system_loader());
|
loader = Handle(thread, SystemDictionary::java_system_loader());
|
||||||
stream = fopen(filename, "rt");
|
stream = fopen(filename, "rt");
|
||||||
if (stream == NULL) {
|
if (stream == NULL) {
|
||||||
fprintf(stderr, "Can't open replay file %s\n", filename);
|
fprintf(stderr, "ERROR: Can't open replay file %s\n", filename);
|
||||||
}
|
}
|
||||||
buffer_length = 32;
|
buffer_length = 32;
|
||||||
buffer = NEW_RESOURCE_ARRAY(char, buffer_length);
|
buffer = NEW_RESOURCE_ARRAY(char, buffer_length);
|
||||||
@ -327,7 +327,6 @@ class CompileReplay : public StackObj {
|
|||||||
if (had_error()) {
|
if (had_error()) {
|
||||||
tty->print_cr("Error while parsing line %d: %s\n", line_no, _error_message);
|
tty->print_cr("Error while parsing line %d: %s\n", line_no, _error_message);
|
||||||
tty->print_cr("%s", buffer);
|
tty->print_cr("%s", buffer);
|
||||||
assert(false, "error");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pos = 0;
|
pos = 0;
|
||||||
@ -370,11 +369,47 @@ class CompileReplay : public StackObj {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// compile <klass> <name> <signature> <entry_bci>
|
// validation of comp_level
|
||||||
|
bool is_valid_comp_level(int comp_level) {
|
||||||
|
const int msg_len = 256;
|
||||||
|
char* msg = NULL;
|
||||||
|
if (!is_compile(comp_level)) {
|
||||||
|
msg = NEW_RESOURCE_ARRAY(char, msg_len);
|
||||||
|
jio_snprintf(msg, msg_len, "%d isn't compilation level", comp_level);
|
||||||
|
} else if (!TieredCompilation && (comp_level != CompLevel_highest_tier)) {
|
||||||
|
msg = NEW_RESOURCE_ARRAY(char, msg_len);
|
||||||
|
switch (comp_level) {
|
||||||
|
case CompLevel_simple:
|
||||||
|
jio_snprintf(msg, msg_len, "compilation level %d requires Client VM or TieredCompilation", comp_level);
|
||||||
|
break;
|
||||||
|
case CompLevel_full_optimization:
|
||||||
|
jio_snprintf(msg, msg_len, "compilation level %d requires Server VM", comp_level);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
jio_snprintf(msg, msg_len, "compilation level %d requires TieredCompilation", comp_level);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (msg != NULL) {
|
||||||
|
report_error(msg);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// compile <klass> <name> <signature> <entry_bci> <comp_level>
|
||||||
void process_compile(TRAPS) {
|
void process_compile(TRAPS) {
|
||||||
// methodHandle method;
|
// methodHandle method;
|
||||||
Method* method = parse_method(CHECK);
|
Method* method = parse_method(CHECK);
|
||||||
int entry_bci = parse_int("entry_bci");
|
int entry_bci = parse_int("entry_bci");
|
||||||
|
const char* comp_level_label = "comp_level";
|
||||||
|
int comp_level = parse_int(comp_level_label);
|
||||||
|
// old version w/o comp_level
|
||||||
|
if (had_error() && (error_message() == comp_level_label)) {
|
||||||
|
comp_level = CompLevel_full_optimization;
|
||||||
|
}
|
||||||
|
if (!is_valid_comp_level(comp_level)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
Klass* k = method->method_holder();
|
Klass* k = method->method_holder();
|
||||||
((InstanceKlass*)k)->initialize(THREAD);
|
((InstanceKlass*)k)->initialize(THREAD);
|
||||||
if (HAS_PENDING_EXCEPTION) {
|
if (HAS_PENDING_EXCEPTION) {
|
||||||
@ -389,12 +424,12 @@ class CompileReplay : public StackObj {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Make sure the existence of a prior compile doesn't stop this one
|
// Make sure the existence of a prior compile doesn't stop this one
|
||||||
nmethod* nm = (entry_bci != InvocationEntryBci) ? method->lookup_osr_nmethod_for(entry_bci, CompLevel_full_optimization, true) : method->code();
|
nmethod* nm = (entry_bci != InvocationEntryBci) ? method->lookup_osr_nmethod_for(entry_bci, comp_level, true) : method->code();
|
||||||
if (nm != NULL) {
|
if (nm != NULL) {
|
||||||
nm->make_not_entrant();
|
nm->make_not_entrant();
|
||||||
}
|
}
|
||||||
replay_state = this;
|
replay_state = this;
|
||||||
CompileBroker::compile_method(method, entry_bci, CompLevel_full_optimization,
|
CompileBroker::compile_method(method, entry_bci, comp_level,
|
||||||
methodHandle(), 0, "replay", THREAD);
|
methodHandle(), 0, "replay", THREAD);
|
||||||
replay_state = NULL;
|
replay_state = NULL;
|
||||||
reset();
|
reset();
|
||||||
@ -551,7 +586,7 @@ class CompileReplay : public StackObj {
|
|||||||
if (parsed_two_word == i) continue;
|
if (parsed_two_word == i) continue;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ShouldNotReachHere();
|
fatal(err_msg_res("Unexpected tag: %d", cp->tag_at(i).value()));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -819,6 +854,11 @@ int ciReplay::replay_impl(TRAPS) {
|
|||||||
ReplaySuppressInitializers = 1;
|
ReplaySuppressInitializers = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (FLAG_IS_DEFAULT(ReplayDataFile)) {
|
||||||
|
tty->print_cr("ERROR: no compiler replay data file specified (use -XX:ReplayDataFile=replay_pid12345.txt).");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// Load and parse the replay data
|
// Load and parse the replay data
|
||||||
CompileReplay rp(ReplayDataFile, THREAD);
|
CompileReplay rp(ReplayDataFile, THREAD);
|
||||||
int exit_code = 0;
|
int exit_code = 0;
|
||||||
|
@ -1842,6 +1842,8 @@ void CompileBroker::invoke_compiler_on_method(CompileTask* task) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// simulate crash during compilation
|
||||||
|
assert(task->compile_id() != CICrashAt, "just as planned");
|
||||||
}
|
}
|
||||||
pop_jni_handle_block();
|
pop_jni_handle_block();
|
||||||
|
|
||||||
|
@ -436,9 +436,29 @@ JVM_ENTRY(void, JVM_RegisterWhiteBoxMethods(JNIEnv* env, jclass wbclass))
|
|||||||
instanceKlassHandle ikh = instanceKlassHandle(JNIHandles::resolve(wbclass)->klass());
|
instanceKlassHandle ikh = instanceKlassHandle(JNIHandles::resolve(wbclass)->klass());
|
||||||
Handle loader(ikh->class_loader());
|
Handle loader(ikh->class_loader());
|
||||||
if (loader.is_null()) {
|
if (loader.is_null()) {
|
||||||
|
ResourceMark rm;
|
||||||
ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
|
ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
|
||||||
jint result = env->RegisterNatives(wbclass, methods, sizeof(methods)/sizeof(methods[0]));
|
bool result = true;
|
||||||
if (result == 0) {
|
// one by one registration natives for exception catching
|
||||||
|
jclass exceptionKlass = env->FindClass(vmSymbols::java_lang_NoSuchMethodError()->as_C_string());
|
||||||
|
for (int i = 0, n = sizeof(methods) / sizeof(methods[0]); i < n; ++i) {
|
||||||
|
if (env->RegisterNatives(wbclass, methods + i, 1) != 0) {
|
||||||
|
result = false;
|
||||||
|
if (env->ExceptionCheck() && env->IsInstanceOf(env->ExceptionOccurred(), exceptionKlass)) {
|
||||||
|
// j.l.NoSuchMethodError is thrown when a method can't be found or a method is not native
|
||||||
|
// ignoring the exception
|
||||||
|
tty->print_cr("Warning: 'NoSuchMethodError' on register of sun.hotspot.WhiteBox::%s%s", methods[i].name, methods[i].signature);
|
||||||
|
env->ExceptionClear();
|
||||||
|
} else {
|
||||||
|
// register is failed w/o exception or w/ unexpected exception
|
||||||
|
tty->print_cr("Warning: unexpected error on register of sun.hotspot.WhiteBox::%s%s. All methods will be unregistered", methods[i].name, methods[i].signature);
|
||||||
|
env->UnregisterNatives(wbclass);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result) {
|
||||||
WhiteBox::set_used();
|
WhiteBox::set_used();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3223,8 +3223,9 @@ class CommandLineFlags {
|
|||||||
develop(bool, ReplayCompiles, false, \
|
develop(bool, ReplayCompiles, false, \
|
||||||
"Enable replay of compilations from ReplayDataFile") \
|
"Enable replay of compilations from ReplayDataFile") \
|
||||||
\
|
\
|
||||||
develop(ccstr, ReplayDataFile, "replay.txt", \
|
product(ccstr, ReplayDataFile, NULL, \
|
||||||
"file containing compilation replay information") \
|
"File containing compilation replay information" \
|
||||||
|
"[default: ./replay_pid%p.log] (%p replaced with pid)") \
|
||||||
\
|
\
|
||||||
develop(intx, ReplaySuppressInitializers, 2, \
|
develop(intx, ReplaySuppressInitializers, 2, \
|
||||||
"Controls handling of class initialization during replay" \
|
"Controls handling of class initialization during replay" \
|
||||||
@ -3237,8 +3238,8 @@ class CommandLineFlags {
|
|||||||
develop(bool, ReplayIgnoreInitErrors, false, \
|
develop(bool, ReplayIgnoreInitErrors, false, \
|
||||||
"Ignore exceptions thrown during initialization for replay") \
|
"Ignore exceptions thrown during initialization for replay") \
|
||||||
\
|
\
|
||||||
develop(bool, DumpReplayDataOnError, true, \
|
product(bool, DumpReplayDataOnError, true, \
|
||||||
"record replay data for crashing compiler threads") \
|
"Record replay data for crashing compiler threads") \
|
||||||
\
|
\
|
||||||
product(bool, CICompilerCountPerCPU, false, \
|
product(bool, CICompilerCountPerCPU, false, \
|
||||||
"1 compiler thread for log(N CPUs)") \
|
"1 compiler thread for log(N CPUs)") \
|
||||||
@ -3247,7 +3248,9 @@ class CommandLineFlags {
|
|||||||
"Fire OutOfMemoryErrors throughout CI for testing the compiler " \
|
"Fire OutOfMemoryErrors throughout CI for testing the compiler " \
|
||||||
"(non-negative value throws OOM after this many CI accesses " \
|
"(non-negative value throws OOM after this many CI accesses " \
|
||||||
"in each compile)") \
|
"in each compile)") \
|
||||||
\
|
notproduct(intx, CICrashAt, -1, \
|
||||||
|
"id of compilation to trigger assert in compiler thread for " \
|
||||||
|
"the purpose of testing, e.g. generation of replay data") \
|
||||||
notproduct(bool, CIObjectFactoryVerify, false, \
|
notproduct(bool, CIObjectFactoryVerify, false, \
|
||||||
"enable potentially expensive verification in ciObjectFactory") \
|
"enable potentially expensive verification in ciObjectFactory") \
|
||||||
\
|
\
|
||||||
|
@ -454,6 +454,7 @@ class os: AllStatic {
|
|||||||
// File i/o operations
|
// File i/o operations
|
||||||
static const int default_file_open_flags();
|
static const int default_file_open_flags();
|
||||||
static int open(const char *path, int oflag, int mode);
|
static int open(const char *path, int oflag, int mode);
|
||||||
|
static FILE* open(int fd, const char* mode);
|
||||||
static int close(int fd);
|
static int close(int fd);
|
||||||
static jlong lseek(int fd, jlong offset, int whence);
|
static jlong lseek(int fd, jlong offset, int whence);
|
||||||
static char* native_path(char *path);
|
static char* native_path(char *path);
|
||||||
@ -477,7 +478,7 @@ class os: AllStatic {
|
|||||||
static const char* dll_file_extension();
|
static const char* dll_file_extension();
|
||||||
|
|
||||||
static const char* get_temp_directory();
|
static const char* get_temp_directory();
|
||||||
static const char* get_current_directory(char *buf, int buflen);
|
static const char* get_current_directory(char *buf, size_t buflen);
|
||||||
|
|
||||||
// Builds a platform-specific full library path given a ld path and lib name
|
// Builds a platform-specific full library path given a ld path and lib name
|
||||||
// Returns true if buffer contains full path to existing file, false otherwise
|
// Returns true if buffer contains full path to existing file, false otherwise
|
||||||
|
@ -1316,12 +1316,6 @@ JRT_BLOCK_ENTRY(address, SharedRuntime::handle_wrong_method(JavaThread* thread))
|
|||||||
assert(stub_frame.is_runtime_frame(), "sanity check");
|
assert(stub_frame.is_runtime_frame(), "sanity check");
|
||||||
frame caller_frame = stub_frame.sender(®_map);
|
frame caller_frame = stub_frame.sender(®_map);
|
||||||
|
|
||||||
// MethodHandle invokes don't have a CompiledIC and should always
|
|
||||||
// simply redispatch to the callee_target.
|
|
||||||
address sender_pc = caller_frame.pc();
|
|
||||||
CodeBlob* sender_cb = caller_frame.cb();
|
|
||||||
nmethod* sender_nm = sender_cb->as_nmethod_or_null();
|
|
||||||
|
|
||||||
if (caller_frame.is_interpreted_frame() ||
|
if (caller_frame.is_interpreted_frame() ||
|
||||||
caller_frame.is_entry_frame()) {
|
caller_frame.is_entry_frame()) {
|
||||||
Method* callee = thread->callee_target();
|
Method* callee = thread->callee_target();
|
||||||
|
@ -828,6 +828,7 @@ typedef BinaryTreeDictionary<Metablock, FreeList> MetablockTreeDictionary;
|
|||||||
nonstatic_field(nmethod, _lock_count, jint) \
|
nonstatic_field(nmethod, _lock_count, jint) \
|
||||||
nonstatic_field(nmethod, _stack_traversal_mark, long) \
|
nonstatic_field(nmethod, _stack_traversal_mark, long) \
|
||||||
nonstatic_field(nmethod, _compile_id, int) \
|
nonstatic_field(nmethod, _compile_id, int) \
|
||||||
|
nonstatic_field(nmethod, _comp_level, int) \
|
||||||
nonstatic_field(nmethod, _exception_cache, ExceptionCache*) \
|
nonstatic_field(nmethod, _exception_cache, ExceptionCache*) \
|
||||||
nonstatic_field(nmethod, _marked_for_deoptimization, bool) \
|
nonstatic_field(nmethod, _marked_for_deoptimization, bool) \
|
||||||
\
|
\
|
||||||
|
@ -196,7 +196,7 @@ class fileStream : public outputStream {
|
|||||||
fileStream() { _file = NULL; _need_close = false; }
|
fileStream() { _file = NULL; _need_close = false; }
|
||||||
fileStream(const char* file_name);
|
fileStream(const char* file_name);
|
||||||
fileStream(const char* file_name, const char* opentype);
|
fileStream(const char* file_name, const char* opentype);
|
||||||
fileStream(FILE* file) { _file = file; _need_close = false; }
|
fileStream(FILE* file, bool need_close = false) { _file = file; _need_close = need_close; }
|
||||||
~fileStream();
|
~fileStream();
|
||||||
bool is_open() const { return _file != NULL; }
|
bool is_open() const { return _file != NULL; }
|
||||||
void set_need_close(bool b) { _need_close = b;}
|
void set_need_close(bool b) { _need_close = b;}
|
||||||
|
@ -796,6 +796,56 @@ void VMError::report(outputStream* st) {
|
|||||||
VMError* volatile VMError::first_error = NULL;
|
VMError* volatile VMError::first_error = NULL;
|
||||||
volatile jlong VMError::first_error_tid = -1;
|
volatile jlong VMError::first_error_tid = -1;
|
||||||
|
|
||||||
|
/** Expand a pattern into a buffer starting at pos and open a file using constructed path */
|
||||||
|
static int expand_and_open(const char* pattern, char* buf, size_t buflen, size_t pos) {
|
||||||
|
int fd = -1;
|
||||||
|
if (Arguments::copy_expand_pid(pattern, strlen(pattern), &buf[pos], buflen - pos)) {
|
||||||
|
fd = open(buf, O_RDWR | O_CREAT | O_TRUNC, 0666);
|
||||||
|
}
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct file name for a log file and return it's file descriptor.
|
||||||
|
* Name and location depends on pattern, default_pattern params and access
|
||||||
|
* permissions.
|
||||||
|
*/
|
||||||
|
static int prepare_log_file(const char* pattern, const char* default_pattern, char* buf, size_t buflen) {
|
||||||
|
int fd = -1;
|
||||||
|
|
||||||
|
// If possible, use specified pattern to construct log file name
|
||||||
|
if (pattern != NULL) {
|
||||||
|
fd = expand_and_open(pattern, buf, buflen, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Either user didn't specify, or the user's location failed,
|
||||||
|
// so use the default name in the current directory
|
||||||
|
if (fd == -1) {
|
||||||
|
const char* cwd = os::get_current_directory(buf, buflen);
|
||||||
|
if (cwd != NULL) {
|
||||||
|
size_t pos = strlen(cwd);
|
||||||
|
int fsep_len = jio_snprintf(&buf[pos], buflen-pos, "%s", os::file_separator());
|
||||||
|
pos += fsep_len;
|
||||||
|
if (fsep_len > 0) {
|
||||||
|
fd = expand_and_open(default_pattern, buf, buflen, pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// try temp directory if it exists.
|
||||||
|
if (fd == -1) {
|
||||||
|
const char* tmpdir = os::get_temp_directory();
|
||||||
|
if (tmpdir != NULL && strlen(tmpdir) > 0) {
|
||||||
|
int pos = jio_snprintf(buf, buflen, "%s%s", tmpdir, os::file_separator());
|
||||||
|
if (pos > 0) {
|
||||||
|
fd = expand_and_open(default_pattern, buf, buflen, pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
void VMError::report_and_die() {
|
void VMError::report_and_die() {
|
||||||
// Don't allocate large buffer on stack
|
// Don't allocate large buffer on stack
|
||||||
static char buffer[O_BUFLEN];
|
static char buffer[O_BUFLEN];
|
||||||
@ -905,36 +955,7 @@ void VMError::report_and_die() {
|
|||||||
// see if log file is already open
|
// see if log file is already open
|
||||||
if (!log.is_open()) {
|
if (!log.is_open()) {
|
||||||
// open log file
|
// open log file
|
||||||
int fd = -1;
|
int fd = prepare_log_file(ErrorFile, "hs_err_pid%p.log", buffer, sizeof(buffer));
|
||||||
|
|
||||||
if (ErrorFile != NULL) {
|
|
||||||
bool copy_ok =
|
|
||||||
Arguments::copy_expand_pid(ErrorFile, strlen(ErrorFile), buffer, sizeof(buffer));
|
|
||||||
if (copy_ok) {
|
|
||||||
fd = open(buffer, O_RDWR | O_CREAT | O_TRUNC, 0666);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fd == -1) {
|
|
||||||
const char *cwd = os::get_current_directory(buffer, sizeof(buffer));
|
|
||||||
size_t len = strlen(cwd);
|
|
||||||
// either user didn't specify, or the user's location failed,
|
|
||||||
// so use the default name in the current directory
|
|
||||||
jio_snprintf(&buffer[len], sizeof(buffer)-len, "%shs_err_pid%u.log",
|
|
||||||
os::file_separator(), os::current_process_id());
|
|
||||||
fd = open(buffer, O_RDWR | O_CREAT | O_TRUNC, 0666);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fd == -1) {
|
|
||||||
const char * tmpdir = os::get_temp_directory();
|
|
||||||
// try temp directory if it exists.
|
|
||||||
if (tmpdir != NULL && tmpdir[0] != '\0') {
|
|
||||||
jio_snprintf(buffer, sizeof(buffer), "%s%shs_err_pid%u.log",
|
|
||||||
tmpdir, os::file_separator(), os::current_process_id());
|
|
||||||
fd = open(buffer, O_RDWR | O_CREAT | O_TRUNC, 0666);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fd != -1) {
|
if (fd != -1) {
|
||||||
out.print_raw("# An error report file with more information is saved as:\n# ");
|
out.print_raw("# An error report file with more information is saved as:\n# ");
|
||||||
out.print_raw_cr(buffer);
|
out.print_raw_cr(buffer);
|
||||||
@ -958,7 +979,7 @@ void VMError::report_and_die() {
|
|||||||
// Run error reporting to determine whether or not to report the crash.
|
// Run error reporting to determine whether or not to report the crash.
|
||||||
if (!transmit_report_done && should_report_bug(first_error->_id)) {
|
if (!transmit_report_done && should_report_bug(first_error->_id)) {
|
||||||
transmit_report_done = true;
|
transmit_report_done = true;
|
||||||
FILE* hs_err = ::fdopen(log.fd(), "r");
|
FILE* hs_err = os::open(log.fd(), "r");
|
||||||
if (NULL != hs_err) {
|
if (NULL != hs_err) {
|
||||||
ErrorReporter er;
|
ErrorReporter er;
|
||||||
er.call(hs_err, buffer, O_BUFLEN);
|
er.call(hs_err, buffer, O_BUFLEN);
|
||||||
@ -1008,7 +1029,19 @@ void VMError::report_and_die() {
|
|||||||
skip_replay = true;
|
skip_replay = true;
|
||||||
ciEnv* env = ciEnv::current();
|
ciEnv* env = ciEnv::current();
|
||||||
if (env != NULL) {
|
if (env != NULL) {
|
||||||
env->dump_replay_data();
|
int fd = prepare_log_file(ReplayDataFile, "replay_pid%p.log", buffer, sizeof(buffer));
|
||||||
|
if (fd != -1) {
|
||||||
|
FILE* replay_data_file = os::open(fd, "w");
|
||||||
|
if (replay_data_file != NULL) {
|
||||||
|
fileStream replay_data_stream(replay_data_file, /*need_close=*/true);
|
||||||
|
env->dump_replay_data(&replay_data_stream);
|
||||||
|
out.print_raw("#\n# Compiler replay data is saved as:\n# ");
|
||||||
|
out.print_raw_cr(buffer);
|
||||||
|
} else {
|
||||||
|
out.print_raw("#\n# Can't open file to dump replay data. Error: ");
|
||||||
|
out.print_raw_cr(strerror(os::get_last_error()));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
92
hotspot/test/compiler/ciReplay/TestSA.sh
Normal file
92
hotspot/test/compiler/ciReplay/TestSA.sh
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# Copyright (c) 2013, 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 8011675
|
||||||
|
## @summary testing of ciReplay with using generated by SA replay.txt
|
||||||
|
## @author igor.ignatyev@oracle.com
|
||||||
|
## @run shell TestSA.sh
|
||||||
|
##
|
||||||
|
|
||||||
|
if [ "${TESTSRC}" = "" ]
|
||||||
|
then
|
||||||
|
TESTSRC=${PWD}
|
||||||
|
echo "TESTSRC not set. Using "${TESTSRC}" as default"
|
||||||
|
fi
|
||||||
|
echo "TESTSRC=${TESTSRC}"
|
||||||
|
|
||||||
|
## Adding common setup Variables for running shell tests.
|
||||||
|
. ${TESTSRC}/../../test_env.sh
|
||||||
|
|
||||||
|
. ${TESTSRC}/common.sh
|
||||||
|
|
||||||
|
generate_replay
|
||||||
|
|
||||||
|
${MV} ${replay_data} replay_vm.txt
|
||||||
|
|
||||||
|
if [ -z "${core_file}" -o ! -r "${core_file}" ]
|
||||||
|
then
|
||||||
|
# skip test if MacOS host isn't configured for core dumping
|
||||||
|
if [ "$OS" = "Darwin" ]
|
||||||
|
then
|
||||||
|
if [ ! -d "/cores" ]
|
||||||
|
then
|
||||||
|
echo TEST SKIPPED: \'/cores\' dir doens\'t exist
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
if [ ! -w "/cores" ]
|
||||||
|
then
|
||||||
|
echo TEST SKIPPED: \'/cores\' dir exists but is not writable
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
test_fail 2 "CHECK :: CORE GENERATION" "core wasn't generated on $OS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "dumpreplaydata -a > ${replay_data}" | \
|
||||||
|
${JAVA} ${TESTVMOPTS} \
|
||||||
|
-cp ${TESTJAVA}${FS}lib${FS}sa-jdi.jar \
|
||||||
|
sun.jvm.hotspot.CLHSDB ${JAVA} ${core_file}
|
||||||
|
|
||||||
|
if [ ! -s ${replay_data} ]
|
||||||
|
then
|
||||||
|
test_fail 1 "CHECK :: REPLAY DATA GENERATION" \
|
||||||
|
"replay data wasn't generated by SA"
|
||||||
|
fi
|
||||||
|
|
||||||
|
diff --brief ${replay_data} replay_vm.txt
|
||||||
|
if [ $? -ne 0 ]
|
||||||
|
then
|
||||||
|
echo WARNING: replay.txt from SA != replay.txt from VM
|
||||||
|
fi
|
||||||
|
|
||||||
|
common_tests 10
|
||||||
|
${VM_TYPE}_tests 20
|
||||||
|
|
||||||
|
cleanup
|
||||||
|
|
||||||
|
echo TEST PASSED
|
||||||
|
|
86
hotspot/test/compiler/ciReplay/TestVM.sh
Normal file
86
hotspot/test/compiler/ciReplay/TestVM.sh
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# Copyright (c) 2013, 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 8011675
|
||||||
|
## @summary testing of ciReplay with using generated by VM replay.txt
|
||||||
|
## @author igor.ignatyev@oracle.com
|
||||||
|
## @run shell TestVM.sh
|
||||||
|
##
|
||||||
|
|
||||||
|
if [ "${TESTSRC}" = "" ]
|
||||||
|
then
|
||||||
|
TESTSRC=${PWD}
|
||||||
|
echo "TESTSRC not set. Using "${TESTSRC}" as default"
|
||||||
|
fi
|
||||||
|
echo "TESTSRC=${TESTSRC}"
|
||||||
|
|
||||||
|
## Adding common setup Variables for running shell tests.
|
||||||
|
. ${TESTSRC}/../../test_env.sh
|
||||||
|
|
||||||
|
. ${TESTSRC}/common.sh
|
||||||
|
|
||||||
|
generate_replay
|
||||||
|
|
||||||
|
if [ ! -s ${replay_data} ]
|
||||||
|
then
|
||||||
|
test_fail 1 "CHECK :: REPLAY DATA GENERATION" \
|
||||||
|
"replay data wasn't generated by VM"
|
||||||
|
fi
|
||||||
|
|
||||||
|
common_tests 10
|
||||||
|
${VM_TYPE}_tests 20
|
||||||
|
|
||||||
|
cleanup
|
||||||
|
|
||||||
|
if [ $is_tiered -eq 1 ]
|
||||||
|
then
|
||||||
|
stop_level=1
|
||||||
|
while [ $stop_level -le $server_level ]
|
||||||
|
do
|
||||||
|
generate_replay "-XX:TieredStopAtLevel=$stop_level"
|
||||||
|
if [ ! -s ${replay_data} ]
|
||||||
|
then
|
||||||
|
test_fail `expr $stop_level + 30` \
|
||||||
|
"TIERED LEVEL $stop_level :: REPLAY DATA GENERATION" \
|
||||||
|
"replay data wasn't generated by VM with stop_level=$stop_level"
|
||||||
|
fi
|
||||||
|
level=`grep "^compile " $replay_data | awk '{print $6}'`
|
||||||
|
if [ $level -gt $stop_level ]
|
||||||
|
then
|
||||||
|
test_fail `expr $stop_level + 40` \
|
||||||
|
"TIERED LEVEL $stop_level :: COMP_LEVEL VERIFICATION" \
|
||||||
|
"comp_level in replay[$level] is greater than stop_level[$stop_level]"
|
||||||
|
fi
|
||||||
|
positive_test `expr $stop_level + 50` "TIERED LEVEL $stop_level :: REPLAY" \
|
||||||
|
"-XX:TieredStopAtLevel=$stop_level"
|
||||||
|
stop_level=`expr $stop_level + 1`
|
||||||
|
done
|
||||||
|
cleanup
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo TEST PASSED
|
||||||
|
|
74
hotspot/test/compiler/ciReplay/TestVM_no_comp_level.sh
Normal file
74
hotspot/test/compiler/ciReplay/TestVM_no_comp_level.sh
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# Copyright (c) 2013, 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 8011675
|
||||||
|
## @summary testing of ciReplay with using generated by VM replay.txt w/o comp_level
|
||||||
|
## @author igor.ignatyev@oracle.com
|
||||||
|
## @run shell TestVM_no_comp_level.sh
|
||||||
|
##
|
||||||
|
|
||||||
|
if [ "${TESTSRC}" = "" ]
|
||||||
|
then
|
||||||
|
TESTSRC=${PWD}
|
||||||
|
echo "TESTSRC not set. Using "${TESTSRC}" as default"
|
||||||
|
fi
|
||||||
|
echo "TESTSRC=${TESTSRC}"
|
||||||
|
|
||||||
|
## Adding common setup Variables for running shell tests.
|
||||||
|
. ${TESTSRC}/../../test_env.sh
|
||||||
|
|
||||||
|
. ${TESTSRC}/common.sh
|
||||||
|
|
||||||
|
generate_replay
|
||||||
|
|
||||||
|
if [ ! -s ${replay_data} ]
|
||||||
|
then
|
||||||
|
test_fail 1 "CHECK :: REPLAY DATA GENERATION" \
|
||||||
|
"replay data wasn't generated by VM"
|
||||||
|
fi
|
||||||
|
|
||||||
|
${CP} ${replay_data} replay_vm.txt
|
||||||
|
|
||||||
|
sed 's/^\(compile *[^ ][^ ]* *[^ ][^ ]* [^ ][^ ]* [^ ][^ ]*\).*$/\1/' \
|
||||||
|
replay_vm.txt > ${replay_data}
|
||||||
|
|
||||||
|
if [ $client_available -eq 1 ]
|
||||||
|
then
|
||||||
|
# tiered is unavailable in client vm, so results w/ flags will be the same as w/o flags
|
||||||
|
negative_test 10 "CLIENT" -client
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $server_available -eq 1 ]
|
||||||
|
then
|
||||||
|
positive_test 21 "SERVER :: NON-TIERED" -XX:-TieredCompilation -server
|
||||||
|
positive_test 22 "SERVER :: TIERED" -XX:+TieredCompilation -server
|
||||||
|
fi
|
||||||
|
|
||||||
|
cleanup
|
||||||
|
|
||||||
|
echo TEST PASSED
|
||||||
|
|
253
hotspot/test/compiler/ciReplay/common.sh
Normal file
253
hotspot/test/compiler/ciReplay/common.sh
Normal file
@ -0,0 +1,253 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# Copyright (c) 2013, 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.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
|
||||||
|
# $1 - error code
|
||||||
|
# $2 - test name
|
||||||
|
# $3,.. - decription
|
||||||
|
test_fail() {
|
||||||
|
error=$1
|
||||||
|
shift
|
||||||
|
name=$1
|
||||||
|
shift
|
||||||
|
echo "TEST [$name] FAILED:"
|
||||||
|
echo "$@"
|
||||||
|
exit $error
|
||||||
|
}
|
||||||
|
|
||||||
|
# $@ - additional vm opts
|
||||||
|
start_test() {
|
||||||
|
# disable core dump on *nix
|
||||||
|
ulimit -S -c 0
|
||||||
|
# disable core dump on windows
|
||||||
|
VMOPTS="$@ -XX:-CreateMinidumpOnCrash"
|
||||||
|
cmd="${JAVA} ${VMOPTS} -XX:+ReplayCompiles -XX:ReplayDataFile=${replay_data}"
|
||||||
|
echo $cmd
|
||||||
|
$cmd
|
||||||
|
return $?
|
||||||
|
}
|
||||||
|
|
||||||
|
# $1 - error_code
|
||||||
|
# $2 - test name
|
||||||
|
# $3,.. - additional vm opts
|
||||||
|
positive_test() {
|
||||||
|
error=$1
|
||||||
|
shift
|
||||||
|
name=$1
|
||||||
|
shift
|
||||||
|
VMOPTS="${TESTVMOPTS} $@"
|
||||||
|
echo "POSITIVE TEST [$name]"
|
||||||
|
start_test ${VMOPTS}
|
||||||
|
exit_code=$?
|
||||||
|
if [ ${exit_code} -ne 0 ]
|
||||||
|
then
|
||||||
|
test_fail $error "$name" "exit_code[${exit_code}] != 0 during replay "\
|
||||||
|
"w/ vmopts: ${VMOPTS}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# $1 - error_code
|
||||||
|
# $2 - test name
|
||||||
|
# $2,.. - additional vm opts
|
||||||
|
negative_test() {
|
||||||
|
error=$1
|
||||||
|
shift
|
||||||
|
name=$1
|
||||||
|
shift
|
||||||
|
VMOPTS="${TESTVMOPTS} $@"
|
||||||
|
echo "NEGATIVE TEST [$name]"
|
||||||
|
start_test ${VMOPTS}
|
||||||
|
exit_code=$?
|
||||||
|
if [ ${exit_code} -eq 0 ]
|
||||||
|
then
|
||||||
|
test_fail $error "$name" "exit_code[${exit_code}] == 0 during replay "\
|
||||||
|
"w/ vmopts: ${VMOPTS}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# $1 - initial error_code
|
||||||
|
common_tests() {
|
||||||
|
positive_test $1 "COMMON :: THE SAME FLAGS"
|
||||||
|
positive_test `expr $1 + 1` "COMMON :: TIERED" -XX:+TieredCompilation
|
||||||
|
}
|
||||||
|
|
||||||
|
# $1 - initial error_code
|
||||||
|
# $2 - non-tiered comp_level
|
||||||
|
nontiered_tests() {
|
||||||
|
level=`grep "^compile " $replay_data | awk '{print $6}'`
|
||||||
|
# is level available in non-tiere
|
||||||
|
if [ "$level" -eq $2 ]
|
||||||
|
then
|
||||||
|
positive_test $1 "NON-TIERED :: AVAILABLE COMP_LEVEL" \
|
||||||
|
-XX:-TieredCompilation
|
||||||
|
else
|
||||||
|
negative_test `expr $1 + 1` "NON-TIERED :: UNAVAILABLE COMP_LEVEL" \
|
||||||
|
negative_test `expr $1 + 1` "NON-TIERED :: UNAVAILABLE COMP_LEVEL" \
|
||||||
|
-XX:-TieredCompilation
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# $1 - initial error_code
|
||||||
|
client_tests() {
|
||||||
|
# testing in opposite VM
|
||||||
|
if [ $server_available -eq 1 ]
|
||||||
|
then
|
||||||
|
negative_test $1 "SERVER :: NON-TIERED" -XX:-TieredCompilation \
|
||||||
|
-server
|
||||||
|
positive_test `expr $1 + 1` "SERVER :: TIERED" -XX:+TieredCompilation \
|
||||||
|
-server
|
||||||
|
fi
|
||||||
|
nontiered_tests `expr $1 + 2` $client_level
|
||||||
|
}
|
||||||
|
|
||||||
|
# $1 - initial error_code
|
||||||
|
server_tests() {
|
||||||
|
# testing in opposite VM
|
||||||
|
if [ $client_available -eq 1 ]
|
||||||
|
then
|
||||||
|
# tiered is unavailable in client vm, so results w/ flags will be the same as w/o flags
|
||||||
|
negative_test $1 "CLIENT" -client
|
||||||
|
fi
|
||||||
|
nontiered_tests `expr $1 + 2` $server_level
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
${RM} -f core*
|
||||||
|
${RM} -f replay*.txt
|
||||||
|
${RM} -f hs_err_pid*.log
|
||||||
|
${RM} -f test_core
|
||||||
|
${RM} -f test_replay.txt
|
||||||
|
}
|
||||||
|
|
||||||
|
JAVA=${TESTJAVA}${FS}bin${FS}java
|
||||||
|
|
||||||
|
replay_data=test_replay.txt
|
||||||
|
|
||||||
|
${JAVA} ${TESTVMOPTS} -Xinternalversion 2>&1 | grep debug
|
||||||
|
|
||||||
|
# Only test fastdebug
|
||||||
|
if [ $? -ne 0 ]
|
||||||
|
then
|
||||||
|
echo TEST SKIPPED: product build
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
is_int=`${JAVA} ${TESTVMOPTS} -version 2>&1 | grep -c "interpreted mode"`
|
||||||
|
# Not applicable for Xint
|
||||||
|
if [ $is_int -ne 0 ]
|
||||||
|
then
|
||||||
|
echo TEST SKIPPED: interpreted mode
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
cleanup
|
||||||
|
|
||||||
|
client_available=`${JAVA} ${TESTVMOPTS} -client -Xinternalversion 2>&1 | \
|
||||||
|
grep -c Client`
|
||||||
|
server_available=`${JAVA} ${TESTVMOPTS} -server -Xinternalversion 2>&1 | \
|
||||||
|
grep -c Server`
|
||||||
|
is_tiered=`${JAVA} ${TESTVMOPTS} -XX:+PrintFlagsFinal -version | \
|
||||||
|
grep TieredCompilation | \
|
||||||
|
grep -c true`
|
||||||
|
# CompLevel_simple -- C1
|
||||||
|
client_level=1
|
||||||
|
# CompLevel_full_optimization -- C2 or Shark
|
||||||
|
server_level=4
|
||||||
|
|
||||||
|
echo "client_available=$client_available"
|
||||||
|
echo "server_available=$server_available"
|
||||||
|
echo "is_tiered=$is_tiered"
|
||||||
|
|
||||||
|
# crash vm in compiler thread with generation replay data and 'small' dump-file
|
||||||
|
# $@ - additional vm opts
|
||||||
|
generate_replay() {
|
||||||
|
# enable core dump
|
||||||
|
ulimit -c unlimited
|
||||||
|
|
||||||
|
cmd="${JAVA} ${TESTVMOPTS} $@ \
|
||||||
|
-Xms8m \
|
||||||
|
-Xmx32m \
|
||||||
|
-XX:MetaspaceSize=4m \
|
||||||
|
-XX:MaxMetaspaceSize=16m \
|
||||||
|
-XX:InitialCodeCacheSize=512k \
|
||||||
|
-XX:ReservedCodeCacheSize=4m \
|
||||||
|
-XX:ThreadStackSize=512 \
|
||||||
|
-XX:VMThreadStackSize=512 \
|
||||||
|
-XX:CompilerThreadStackSize=512 \
|
||||||
|
-XX:ParallelGCThreads=1 \
|
||||||
|
-XX:CICompilerCount=1 \
|
||||||
|
-Xcomp \
|
||||||
|
-XX:CICrashAt=1 \
|
||||||
|
-XX:+CreateMinidumpOnCrash \
|
||||||
|
-XX:+DumpReplayDataOnError \
|
||||||
|
-XX:ReplayDataFile=${replay_data} \
|
||||||
|
-version"
|
||||||
|
echo GENERATION OF REPLAY.TXT:
|
||||||
|
echo $cmd
|
||||||
|
|
||||||
|
${cmd} 2>&1 > crash.out
|
||||||
|
|
||||||
|
core_locations=`grep -i core crash.out | grep "location:" | \
|
||||||
|
sed -e 's/.*location: //'`
|
||||||
|
rm crash.out
|
||||||
|
# processing core locations for *nix
|
||||||
|
if [ $OS != "windows" ]
|
||||||
|
then
|
||||||
|
# remove 'or' between '/core.<pid>' and 'core'
|
||||||
|
core_locations=`echo $core_locations | \
|
||||||
|
sed -e 's/\([^ ]*\) or \([^ ]*\)/\1 \2/'`
|
||||||
|
# add <core_path>/core.<pid> core.<pid>
|
||||||
|
core=`echo $core_locations | awk '{print $1}'`
|
||||||
|
dir=`dirname $core`
|
||||||
|
core=`basename $core`
|
||||||
|
if [ -n ${core} ]
|
||||||
|
then
|
||||||
|
core_locations="$core_locations $dir${FS}$core"
|
||||||
|
fi
|
||||||
|
core=`echo $core_locations | awk '{print $2}'`
|
||||||
|
if [ -n ${core} ]
|
||||||
|
then
|
||||||
|
core_locations="$core_locations $dir${FS}$core"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "LOOKING FOR CORE IN ${core_locations}"
|
||||||
|
for core in $core_locations
|
||||||
|
do
|
||||||
|
if [ -r "$core" ]
|
||||||
|
then
|
||||||
|
core_file=$core
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# core-file was found
|
||||||
|
if [ -n "$core_file" ]
|
||||||
|
then
|
||||||
|
${MV} "${core_file}" test_core
|
||||||
|
core_file=test_core
|
||||||
|
fi
|
||||||
|
|
||||||
|
${RM} -f hs_err_pid*.log
|
||||||
|
}
|
||||||
|
|
58
hotspot/test/sanity/WhiteBox.java
Normal file
58
hotspot/test/sanity/WhiteBox.java
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013, 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 WhiteBox
|
||||||
|
* @bug 8011675
|
||||||
|
* @summary verify that whitebox can be used even if not all functions are declared in java-part
|
||||||
|
* @author igor.ignatyev@oracle.com
|
||||||
|
* @library /testlibrary
|
||||||
|
* @compile WhiteBox.java
|
||||||
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI sun.hotspot.WhiteBox
|
||||||
|
* @clean sun.hotspot.WhiteBox
|
||||||
|
*/
|
||||||
|
|
||||||
|
package sun.hotspot;
|
||||||
|
|
||||||
|
public class WhiteBox {
|
||||||
|
private static native void registerNatives();
|
||||||
|
static { registerNatives(); }
|
||||||
|
public native int notExistedMethod();
|
||||||
|
public native int getHeapOopSize();
|
||||||
|
public static void main(String[] args) {
|
||||||
|
WhiteBox wb = new WhiteBox();
|
||||||
|
if (wb.getHeapOopSize() < 0) {
|
||||||
|
throw new Error("wb.getHeapOopSize() < 0");
|
||||||
|
}
|
||||||
|
boolean catched = false;
|
||||||
|
try {
|
||||||
|
wb.notExistedMethod();
|
||||||
|
} catch (UnsatisfiedLinkError e) {
|
||||||
|
catched = true;
|
||||||
|
}
|
||||||
|
if (!catched) {
|
||||||
|
throw new Error("wb.notExistedMethod() was invoked");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user