# HG changeset patch # User vlivanov # Date 1366912952 25200 # Node ID e12c9b3740db4fb30a8bf2e94660da8fead0f0d7 # Parent 47766e2d2527c7006e50f178e7dd549b0d64b61a 8012260: ciReplay: Include PID into the name of replay data file Reviewed-by: kvn, twisti diff -r 47766e2d2527 -r e12c9b3740db src/os/bsd/vm/os_bsd.cpp --- a/src/os/bsd/vm/os_bsd.cpp Wed Apr 24 18:20:04 2013 -0400 +++ b/src/os/bsd/vm/os_bsd.cpp Thu Apr 25 11:02:32 2013 -0700 @@ -1230,10 +1230,6 @@ return retval; } -const char* os::get_current_directory(char *buf, int buflen) { - return getcwd(buf, buflen); -} - // check if addr is inside libjvm.so bool os::address_is_in_vm(address addr) { static address libjvm_base_addr; diff -r 47766e2d2527 -r e12c9b3740db src/os/linux/vm/os_linux.cpp --- a/src/os/linux/vm/os_linux.cpp Wed Apr 24 18:20:04 2013 -0400 +++ b/src/os/linux/vm/os_linux.cpp Thu Apr 25 11:02:32 2013 -0700 @@ -1662,10 +1662,6 @@ return retval; } -const char* os::get_current_directory(char *buf, int buflen) { - return getcwd(buf, buflen); -} - // check if addr is inside libjvm.so bool os::address_is_in_vm(address addr) { static address libjvm_base_addr; diff -r 47766e2d2527 -r e12c9b3740db src/os/posix/vm/os_posix.cpp --- a/src/os/posix/vm/os_posix.cpp Wed Apr 24 18:20:04 2013 -0400 +++ b/src/os/posix/vm/os_posix.cpp Thu Apr 25 11:02:32 2013 -0700 @@ -251,3 +251,11 @@ return true; #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); +} diff -r 47766e2d2527 -r e12c9b3740db src/os/solaris/vm/os_solaris.cpp --- a/src/os/solaris/vm/os_solaris.cpp Wed Apr 24 18:20:04 2013 -0400 +++ b/src/os/solaris/vm/os_solaris.cpp Thu Apr 25 11:02:32 2013 -0700 @@ -1915,10 +1915,6 @@ return retval; } -const char* os::get_current_directory(char *buf, int buflen) { - return getcwd(buf, buflen); -} - // check if addr is inside libjvm.so bool os::address_is_in_vm(address addr) { static address libjvm_base_addr; diff -r 47766e2d2527 -r e12c9b3740db src/os/windows/vm/os_windows.cpp --- a/src/os/windows/vm/os_windows.cpp Wed Apr 24 18:20:04 2013 -0400 +++ b/src/os/windows/vm/os_windows.cpp Thu Apr 25 11:02:32 2013 -0700 @@ -1221,8 +1221,10 @@ // Needs to be in os specific directory because windows requires another // header file -const char* os::get_current_directory(char *buf, int buflen) { - return _getcwd(buf, buflen); +const char* os::get_current_directory(char *buf, size_t buflen) { + int n = static_cast(buflen); + if (buflen > INT_MAX) n = INT_MAX; + return _getcwd(buf, n); } //----------------------------------------------------------- @@ -4098,6 +4100,10 @@ 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? bool os::dir_is_empty(const char* path) { WIN32_FIND_DATA fd; diff -r 47766e2d2527 -r e12c9b3740db src/share/vm/ci/ciEnv.cpp --- a/src/share/vm/ci/ciEnv.cpp Wed Apr 24 18:20:04 2013 -0400 +++ b/src/share/vm/ci/ciEnv.cpp Thu Apr 25 11:02:32 2013 -0700 @@ -1149,23 +1149,9 @@ record_method_not_compilable("out of memory"); } -fileStream* ciEnv::_replay_data_stream = NULL; - -void ciEnv::dump_replay_data() { +void ciEnv::dump_replay_data(outputStream* out) { VM_ENTRY_MARK; 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; #if INCLUDE_JVMTI out->print_cr("JvmtiExport can_access_local_variables %d", _jvmti_can_access_local_variables); diff -r 47766e2d2527 -r e12c9b3740db src/share/vm/ci/ciEnv.hpp --- a/src/share/vm/ci/ciEnv.hpp Wed Apr 24 18:20:04 2013 -0400 +++ b/src/share/vm/ci/ciEnv.hpp Thu Apr 25 11:02:32 2013 -0700 @@ -46,8 +46,6 @@ friend class CompileBroker; friend class Dependencies; // for get_object, during logging - static fileStream* _replay_data_stream; - private: Arena* _arena; // Alias for _ciEnv_arena except in init_shared_objects() Arena _ciEnv_arena; @@ -451,10 +449,6 @@ // RedefineClasses support 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. void dump_replay_data(outputStream* out); }; diff -r 47766e2d2527 -r e12c9b3740db src/share/vm/ci/ciReplay.cpp --- a/src/share/vm/ci/ciReplay.cpp Wed Apr 24 18:20:04 2013 -0400 +++ b/src/share/vm/ci/ciReplay.cpp Thu Apr 25 11:02:32 2013 -0700 @@ -89,7 +89,7 @@ loader = Handle(thread, SystemDictionary::java_system_loader()); stream = fopen(filename, "rt"); 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 = NEW_RESOURCE_ARRAY(char, buffer_length); @@ -327,7 +327,6 @@ if (had_error()) { tty->print_cr("Error while parsing line %d: %s\n", line_no, _error_message); tty->print_cr("%s", buffer); - assert(false, "error"); return; } pos = 0; @@ -551,7 +550,7 @@ if (parsed_two_word == i) continue; default: - ShouldNotReachHere(); + fatal(err_msg_res("Unexpected tag: %d", cp->tag_at(i).value())); break; } @@ -819,6 +818,11 @@ 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 CompileReplay rp(ReplayDataFile, THREAD); int exit_code = 0; diff -r 47766e2d2527 -r e12c9b3740db src/share/vm/runtime/globals.hpp --- a/src/share/vm/runtime/globals.hpp Wed Apr 24 18:20:04 2013 -0400 +++ b/src/share/vm/runtime/globals.hpp Thu Apr 25 11:02:32 2013 -0700 @@ -3223,8 +3223,9 @@ develop(bool, ReplayCompiles, false, \ "Enable replay of compilations from ReplayDataFile") \ \ - develop(ccstr, ReplayDataFile, "replay.txt", \ - "file containing compilation replay information") \ + product(ccstr, ReplayDataFile, NULL, \ + "File containing compilation replay information" \ + "[default: ./replay_pid%p.log] (%p replaced with pid)") \ \ develop(intx, ReplaySuppressInitializers, 2, \ "Controls handling of class initialization during replay" \ @@ -3237,8 +3238,8 @@ develop(bool, ReplayIgnoreInitErrors, false, \ "Ignore exceptions thrown during initialization for replay") \ \ - develop(bool, DumpReplayDataOnError, true, \ - "record replay data for crashing compiler threads") \ + product(bool, DumpReplayDataOnError, true, \ + "Record replay data for crashing compiler threads") \ \ product(bool, CICompilerCountPerCPU, false, \ "1 compiler thread for log(N CPUs)") \ diff -r 47766e2d2527 -r e12c9b3740db src/share/vm/runtime/os.hpp --- a/src/share/vm/runtime/os.hpp Wed Apr 24 18:20:04 2013 -0400 +++ b/src/share/vm/runtime/os.hpp Thu Apr 25 11:02:32 2013 -0700 @@ -454,6 +454,7 @@ // File i/o operations static const int default_file_open_flags(); static int open(const char *path, int oflag, int mode); + static FILE* open(int fd, const char* mode); static int close(int fd); static jlong lseek(int fd, jlong offset, int whence); static char* native_path(char *path); @@ -477,7 +478,7 @@ static const char* dll_file_extension(); 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 // Returns true if buffer contains full path to existing file, false otherwise diff -r 47766e2d2527 -r e12c9b3740db src/share/vm/utilities/ostream.hpp --- a/src/share/vm/utilities/ostream.hpp Wed Apr 24 18:20:04 2013 -0400 +++ b/src/share/vm/utilities/ostream.hpp Thu Apr 25 11:02:32 2013 -0700 @@ -196,7 +196,7 @@ fileStream() { _file = NULL; _need_close = false; } fileStream(const char* file_name); 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(); bool is_open() const { return _file != NULL; } void set_need_close(bool b) { _need_close = b;} diff -r 47766e2d2527 -r e12c9b3740db src/share/vm/utilities/vmError.cpp --- a/src/share/vm/utilities/vmError.cpp Wed Apr 24 18:20:04 2013 -0400 +++ b/src/share/vm/utilities/vmError.cpp Thu Apr 25 11:02:32 2013 -0700 @@ -796,6 +796,56 @@ VMError* volatile VMError::first_error = NULL; 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() { // Don't allocate large buffer on stack static char buffer[O_BUFLEN]; @@ -905,36 +955,7 @@ // see if log file is already open if (!log.is_open()) { // open log file - int fd = -1; - - 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); - } - } - + int fd = prepare_log_file(ErrorFile, "hs_err_pid%p.log", buffer, sizeof(buffer)); if (fd != -1) { out.print_raw("# An error report file with more information is saved as:\n# "); out.print_raw_cr(buffer); @@ -958,7 +979,7 @@ // Run error reporting to determine whether or not to report the crash. if (!transmit_report_done && should_report_bug(first_error->_id)) { transmit_report_done = true; - FILE* hs_err = ::fdopen(log.fd(), "r"); + FILE* hs_err = os::open(log.fd(), "r"); if (NULL != hs_err) { ErrorReporter er; er.call(hs_err, buffer, O_BUFLEN); @@ -1008,7 +1029,19 @@ skip_replay = true; ciEnv* env = ciEnv::current(); 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())); + } + } } }