8012260: ciReplay: Include PID into the name of replay data file
authorvlivanov
Thu, 25 Apr 2013 11:02:32 -0700
changeset 17121 e40a97c700d9
parent 17037 34baf792b14d
child 17122 6ceb071b96de
8012260: ciReplay: Include PID into the name of replay data file Reviewed-by: kvn, twisti
hotspot/src/os/bsd/vm/os_bsd.cpp
hotspot/src/os/linux/vm/os_linux.cpp
hotspot/src/os/posix/vm/os_posix.cpp
hotspot/src/os/solaris/vm/os_solaris.cpp
hotspot/src/os/windows/vm/os_windows.cpp
hotspot/src/share/vm/ci/ciEnv.cpp
hotspot/src/share/vm/ci/ciEnv.hpp
hotspot/src/share/vm/ci/ciReplay.cpp
hotspot/src/share/vm/runtime/globals.hpp
hotspot/src/share/vm/runtime/os.hpp
hotspot/src/share/vm/utilities/ostream.hpp
hotspot/src/share/vm/utilities/vmError.cpp
--- a/hotspot/src/os/bsd/vm/os_bsd.cpp	Wed Apr 24 18:20:04 2013 -0400
+++ b/hotspot/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;
--- a/hotspot/src/os/linux/vm/os_linux.cpp	Wed Apr 24 18:20:04 2013 -0400
+++ b/hotspot/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;
--- a/hotspot/src/os/posix/vm/os_posix.cpp	Wed Apr 24 18:20:04 2013 -0400
+++ b/hotspot/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);
+}
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp	Wed Apr 24 18:20:04 2013 -0400
+++ b/hotspot/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;
--- a/hotspot/src/os/windows/vm/os_windows.cpp	Wed Apr 24 18:20:04 2013 -0400
+++ b/hotspot/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 <direct.h>
-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<int>(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;
--- a/hotspot/src/share/vm/ci/ciEnv.cpp	Wed Apr 24 18:20:04 2013 -0400
+++ b/hotspot/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);
--- a/hotspot/src/share/vm/ci/ciEnv.hpp	Wed Apr 24 18:20:04 2013 -0400
+++ b/hotspot/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);
 };
--- a/hotspot/src/share/vm/ci/ciReplay.cpp	Wed Apr 24 18:20:04 2013 -0400
+++ b/hotspot/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;
--- a/hotspot/src/share/vm/runtime/globals.hpp	Wed Apr 24 18:20:04 2013 -0400
+++ b/hotspot/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)")                              \
--- a/hotspot/src/share/vm/runtime/os.hpp	Wed Apr 24 18:20:04 2013 -0400
+++ b/hotspot/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
--- a/hotspot/src/share/vm/utilities/ostream.hpp	Wed Apr 24 18:20:04 2013 -0400
+++ b/hotspot/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;}
--- a/hotspot/src/share/vm/utilities/vmError.cpp	Wed Apr 24 18:20:04 2013 -0400
+++ b/hotspot/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()));
+        }
+      }
     }
   }