changeset 10608:95bccc5efc6a

Merge
author andrew
date Mon, 27 Jan 2020 05:10:29 +0000
parents 43c1f20ba33f (current diff) 0cf14bdd73fe (diff)
children d975dfffada6
files .hgtags
diffstat 14 files changed, 171 insertions(+), 341 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Fri Jan 17 19:08:14 2020 +0000
+++ b/.hgtags	Mon Jan 27 05:10:29 2020 +0000
@@ -1294,3 +1294,5 @@
 8b80409d5840142a27e274d33948f483a6406a50 jdk8u242-b07
 7c9f6b5f8d119dc1ba3c5536595ce3ae7414599d jdk8u242-b08
 7c9f6b5f8d119dc1ba3c5536595ce3ae7414599d jdk8u242-ga
+8c0733543544bbcd32c4404630d764d280299056 jdk8u252-b00
+a67e9c6edcdd73cb860a16990f0905e102c282d7 jdk8u252-b01
--- a/agent/src/os/linux/ps_core.c	Fri Jan 17 19:08:14 2020 +0000
+++ b/agent/src/os/linux/ps_core.c	Mon Jan 27 05:10:29 2020 +0000
@@ -868,6 +868,9 @@
 #define LINK_MAP_LD_OFFSET    offsetof(struct link_map, l_ld)
 #define LINK_MAP_NEXT_OFFSET  offsetof(struct link_map, l_next)
 
+#define INVALID_LOAD_ADDRESS -1L
+#define ZERO_LOAD_ADDRESS 0x0L
+
 // Calculate the load address of shared library
 // on prelink-enabled environment.
 //
@@ -884,7 +887,7 @@
   phbuf = read_program_header_table(lib_fd, elf_ehdr);
   if (phbuf == NULL) {
     print_debug("can't read program header of shared object\n");
-    return 0L;
+    return INVALID_LOAD_ADDRESS;
   }
 
   // Get the address of .dynamic section from shared library.
@@ -900,7 +903,7 @@
   if (ps_pdread(ph, (psaddr_t)link_map_addr + LINK_MAP_LD_OFFSET,
                &lib_ld, sizeof(uintptr_t)) != PS_OK) {
     print_debug("can't read address of dynamic section in shared object\n");
-    return 0L;
+    return INVALID_LOAD_ADDRESS;
   }
 
   // Return the load address which is calculated by the address of .dynamic
@@ -1011,9 +1014,9 @@
             // continue with other libraries...
          } else {
             if (read_elf_header(lib_fd, &elf_ehdr)) {
-               if (lib_base_diff == 0x0L) {
+               if (lib_base_diff == ZERO_LOAD_ADDRESS) {
                  lib_base_diff = calc_prelinked_load_address(ph, lib_fd, &elf_ehdr, link_map_addr);
-                 if (lib_base_diff == 0x0L) {
+                 if (lib_base_diff == INVALID_LOAD_ADDRESS) {
                    close(lib_fd);
                    return false;
                  }
--- a/make/aix/makefiles/vm.make	Fri Jan 17 19:08:14 2020 +0000
+++ b/make/aix/makefiles/vm.make	Mon Jan 27 05:10:29 2020 +0000
@@ -119,6 +119,7 @@
 # Extra flags from gnumake's invocation or environment
 CFLAGS += $(EXTRA_CFLAGS)
 LFLAGS += $(EXTRA_CFLAGS) $(EXTRA_LDFLAGS)
+ASFLAGS += $(EXTRA_ASFLAGS)
 
 # Don't set excutable bit on stack segment
 # the same could be done by separate execstack command
--- a/make/bsd/makefiles/vm.make	Fri Jan 17 19:08:14 2020 +0000
+++ b/make/bsd/makefiles/vm.make	Mon Jan 27 05:10:29 2020 +0000
@@ -121,6 +121,7 @@
 # Extra flags from gnumake's invocation or environment
 CFLAGS += $(EXTRA_CFLAGS)
 LFLAGS += $(EXTRA_CFLAGS) $(EXTRA_LDFLAGS)
+ASFLAGS += $(EXTRA_ASFLAGS)
 
 # Don't set excutable bit on stack segment
 # the same could be done by separate execstack command
--- a/make/linux/makefiles/vm.make	Fri Jan 17 19:08:14 2020 +0000
+++ b/make/linux/makefiles/vm.make	Mon Jan 27 05:10:29 2020 +0000
@@ -124,6 +124,7 @@
 # Extra flags from gnumake's invocation or environment
 CFLAGS += $(EXTRA_CFLAGS)
 LFLAGS += $(EXTRA_CFLAGS) $(EXTRA_LDFLAGS)
+ASFLAGS += $(EXTRA_ASFLAGS)
 
 # Don't set excutable bit on stack segment
 # the same could be done by separate execstack command
--- a/make/solaris/makefiles/vm.make	Fri Jan 17 19:08:14 2020 +0000
+++ b/make/solaris/makefiles/vm.make	Mon Jan 27 05:10:29 2020 +0000
@@ -109,6 +109,7 @@
 
 # Extra flags from gnumake's invocation or environment
 CFLAGS += $(EXTRA_CFLAGS)
+ASFLAGS += $(EXTRA_ASFLAGS)
 
 # Math Library (libm.so), do not use -lm.
 #    There might be two versions of libm.so on the build system:
--- a/src/share/vm/adlc/filebuff.cpp	Fri Jan 17 19:08:14 2020 +0000
+++ b/src/share/vm/adlc/filebuff.cpp	Mon Jan 27 05:10:29 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, 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
@@ -89,200 +89,6 @@
   return retval;
 }
 
-//------------------------------FileBuffRegion---------------------------------
-// Create a new region in a FileBuff.
-FileBuffRegion::FileBuffRegion( FileBuff* bufr, int soln, int ln,
-                                int off, int len)
-: _bfr(bufr), _sol(soln), _line(ln), _offset(off), _length(len) {
-  _next = NULL;                 // No chained regions
-}
-
-//------------------------------~FileBuffRegion--------------------------------
-// Delete the entire linked list of buffer regions.
-FileBuffRegion::~FileBuffRegion() {
-  if( _next ) delete _next;
-}
-
-//------------------------------copy-------------------------------------------
-// Deep copy a FileBuffRegion
-FileBuffRegion *FileBuffRegion::copy() {
-  if( !this ) return NULL;      // The empty buffer region
-  FileBuffRegion *br = new FileBuffRegion(_bfr,_sol,_line,_offset,_length);
-  if( _next ) br->_next = _next->copy();
-  return br;
-}
-
-//------------------------------merge------------------------------------------
-// Merge another buffer region into this buffer region.  Make overlapping areas
-// become a single region.  Remove (delete) the input FileBuffRegion.
-// Since the buffer regions are sorted by file offset, this is a varient of a
-// "sorted-merge" running in linear time.
-FileBuffRegion *FileBuffRegion::merge( FileBuffRegion *br ) {
-  if( !br ) return this;        // Merging nothing
-  if( !this ) return br;        // Merging into nothing
-
-  assert( _bfr == br->_bfr, "" );     // Check for pointer-equivalent buffers
-
-  if( _offset < br->_offset ) { // "this" starts before "br"
-    if( _offset+_length < br->_offset ) { // "this" ends before "br"
-      if( _next ) _next->merge( br );    // Merge with remainder of list
-      else _next = br;                 // No more in this list; just append.
-    } else {                           // Regions overlap.
-      int l = br->_offset + br->_length - _offset;
-      if( l > _length ) _length = l;     // Pick larger region
-      FileBuffRegion *nr = br->_next;     // Get rest of region
-      br->_next = NULL;         // Remove indication of rest of region
-      delete br;                // Delete this region (it's been subsumed).
-      if( nr ) merge( nr );     // Merge with rest of region
-    }                           // End of if regions overlap or not.
-  } else {                      // "this" starts after "br"
-    if( br->_offset+br->_length < _offset ) {    // "br" ends before "this"
-      FileBuffRegion *nr = new FileBuffRegion(_bfr,_sol,_line,_offset,_length);
-      nr->_next = _next;                // Structure copy "this" guy to "nr"
-      *this = *br;              // Structure copy "br" over "this".
-      br->_next = NULL;         // Remove indication of rest of region
-      delete br;                // Delete this region (it's been copied)
-      merge( nr );              // Finish merging
-    } else {                    // Regions overlap.
-      int l = _offset + _length - br->_offset;
-      if( l > _length ) _length = l;    // Pick larger region
-      _offset = br->_offset;            // Start with earlier region
-      _sol = br->_sol;                  // Also use earlier line start
-      _line = br->_line;                        // Also use earlier line
-      FileBuffRegion *nr = br->_next;   // Get rest of region
-      br->_next = NULL;         // Remove indication of rest of region
-      delete br;                // Delete this region (it's been subsumed).
-      if( nr ) merge( nr );     // Merge with rest of region
-    }                           // End of if regions overlap or not.
-  }
-  return this;
-}
-
-//------------------------------expandtab--------------------------------------
-static int expandtab( ostream &os, int off, char c, char fill1, char fill2 ) {
-  if( c == '\t' ) {             // Tab?
-    do os << fill1;             // Expand the tab; Output space
-    while( (++off) & 7 );       // Expand to tab stop
-  } else {                      // Normal character
-    os << fill2;                // Display normal character
-    off++;                      // Increment "cursor" offset
-  }
-  return off;
-}
-
-//------------------------------printline--------------------------------------
-// Print and highlite a region of a line.  Return the amount of highliting left
-// to do (i.e. highlite length minus length of line).
-static int printline( ostream& os, const char *fname, int line,
-                        const char *_sol, int skip, int len ) {
-
-  // Display the entire tab-expanded line
-  os << fname << ":" << line << ": ";
-  const char *t = strchr(_sol,'\n')+1; // End of line
-  int off = 0;                  // Cursor offset for tab expansion
-  const char *s = _sol;         // Nice string pointer
-  while( t-s ) {                // Display whole line
-    char c = *s++;              // Get next character to display
-    off = expandtab(os,off,c,' ',c);
-  }
-
-  // Display the tab-expanded skippings before underlining.
-  os << fname << ":" << line << ": ";
-  off = 0;                      // Cursor offset for tab expansion
-  s = _sol;                     // Restart string pointer
-
-  // Start underlining.
-  if( skip != -1 ) {            // The no-start-indicating flag
-    const char *u = _sol+skip;  // Amount to skip
-    while( u-s )                // Display skipped part
-      off = expandtab(os,off,*s++,' ',' ');
-    os << '^';                  // Start region
-    off++;                      // Moved cursor
-    len--;                      // 1 less char to do
-    if( *s++ == '\t' )          // Starting character is a tab?
-      off = expandtab(os,off,'\t','-','^');
-  }
-
-  // Long region doesn't end on this line
-  int llen = (int)(t-s);        // Length of line, minus what's already done
-  if( len > llen ) {            // Doing entire rest of line?
-    while( t-s )                // Display rest of line
-      off = expandtab(os,off,*s++,'-','-');
-    os << '\n';                 // EOL
-    return len-llen;            // Return what's not yet done.
-  }
-
-  // Region does end on this line.  This code fails subtly if the region ends
-  // in a tab character.
-  int i;
-  for( i=1; i<len; i++ )        // Underline just what's needed
-    off = expandtab(os,off,*s++,'-','-');
-  if( i == len ) os << '^';     // Mark end of region
-  os << '\n';                   // End of marked line
-  return 0;                     // All done
-}
-
-//------------------------------print------------------------------------------
-//std::ostream& operator<< ( std::ostream& os, FileBuffRegion &br ) {
-ostream& operator<< ( ostream& os, FileBuffRegion &br ) {
-  if( &br == NULL ) return os;  // The empty buffer region
-  FileBuffRegion *brp = &br;    // Pointer to region
-  while( brp ) {                // While have chained regions
-    brp->print(os);             // Print region
-    brp = brp->_next;           // Chain to next
-  }
-  return os;                    // Return final stream
-}
-
-//------------------------------print------------------------------------------
-// Print the FileBuffRegion to a stream. FileBuffRegions are printed with the
-// filename and line number to the left, and complete text lines to the right.
-// Selected portions (portions of a line actually in the FileBuffRegion are
-// underlined.  Ellipses are used for long multi-line regions.
-//void FileBuffRegion::print( std::ostream& os ) {
-void FileBuffRegion::print( ostream& os ) {
-  if( !this ) return;           // Nothing to print
-  char *s = _bfr->get_line();
-  int skip = (int)(_offset - _sol);     // Amount to skip to start of data
-  int len = printline( os, _bfr->_fp->_name, _line, s, skip, _length );
-
-  if( !len ) return;                    // All done; exit
-
-  // Here we require at least 2 lines
-  int off1 = _length - len + skip;      // Length of line 1
-  int off2 = off1 + _sol;               // Offset to start of line 2
-  char *s2 = _bfr->get_line();           // Start of line 2
-  char *s3 = strchr( s2, '\n' )+1;      // Start of line 3 (unread)
-  if( len <= (s3-s2) ) {                // It all fits on the next line
-    printline( os, _bfr->_fp->_name, _line+1, s2, -1, len ); // Print&underline
-    return;
-  }
-
-  // Here we require at least 3 lines
-  int off3 = off2 + (int)(s3-s2);       // Offset to start of line 3
-  s3 = _bfr->get_line();                // Start of line 3 (read)
-  const char *s4 = strchr( s3, '\n' )+1;// Start of line 4 (unread)
-  if( len < (s4-s3) ) {                 // It all fits on the next 2 lines
-    s2 = _bfr->get_line();
-    len = printline( os, _bfr->_fp->_name, _line+1, s2, -1, len ); // Line 2
-    s3 = _bfr->get_line();
-    printline( os, _bfr->_fp->_name, _line+2, s3, -1, len );     // Line 3
-    return;
-  }
-
-  // Here we require at least 4 lines.
-  // Print only the 1st and last line, with ellipses in middle.
-  os << "...\n";                // The ellipses
-  int cline = _line+1;          // Skipped 2 lines
-  do {                          // Do until find last line
-    len -= (int)(s3-s2);        // Remove length of line
-    cline++;                    // Next line
-    s2 = _bfr->get_line();      // Get next line from end of this line
-    s3 = strchr( s2, '\n' ) + 1;// Get end of next line
-  } while( len > (s3-s2) );     // Repeat until last line
-  printline( os, _bfr->_fp->_name, cline, s2, -1, len ); // Print & underline
-}
-
 //------------------------------file_error-------------------------------------
 void FileBuff::file_error(int flag, int linenum, const char *fmt, ...)
 {
--- a/src/share/vm/adlc/filebuff.hpp	Fri Jan 17 19:08:14 2020 +0000
+++ b/src/share/vm/adlc/filebuff.hpp	Mon Jan 27 05:10:29 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, 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
@@ -46,7 +46,6 @@
 // This class defines a nicely behaved buffer of text.  Entire file of text
 // is read into buffer at creation, with sentinels at start and end.
 class FileBuff {
-  friend class FileBuffRegion;
  private:
   long  _bufferSize;            // Size of text holding buffer.
   long  _offset;                // Expected filepointer offset.
@@ -82,29 +81,4 @@
   // when the pointer is valid (i.e. just obtained from getline()).
   long getoff(const char* s) { return _bufoff + (long)(s - _buf); }
 };
-
-//------------------------------FileBuffRegion---------------------------------
-// A buffer region is really a region of some file, specified as a linked list
-// of offsets and lengths.  These regions can be merged; overlapping regions
-// will coalesce.
-class FileBuffRegion {
- public:                        // Workaround dev-studio friend/private bug
-  FileBuffRegion *_next;        // Linked list of regions sorted by offset.
- private:
-  FileBuff       *_bfr;         // The Buffer of the file
-  int _offset, _length;         // The file area
-  int             _sol;         // Start of line where the file area starts
-  int             _line;        // First line of region
-
- public:
-  FileBuffRegion(FileBuff*, int sol, int line, int offset, int len);
-  ~FileBuffRegion();
-
-  FileBuffRegion *copy();                   // Deep copy
-  FileBuffRegion *merge(FileBuffRegion*); // Merge 2 regions; delete input
-
-  void print(ostream&);
-  friend ostream& operator<< (ostream&, FileBuffRegion&);
-};
-
 #endif // SHARE_VM_ADLC_FILEBUFF_HPP
--- a/src/share/vm/opto/c2_globals.hpp	Fri Jan 17 19:08:14 2020 +0000
+++ b/src/share/vm/opto/c2_globals.hpp	Mon Jan 27 05:10:29 2020 +0000
@@ -360,9 +360,6 @@
           "File to dump ideal graph to.  If set overrides the "             \
           "use of the network")                                             \
                                                                             \
-  product(bool, UseOldInlining, true,                                       \
-          "Enable the 1.3 inlining strategy")                               \
-                                                                            \
   product(bool, UseBimorphicInlining, true,                                 \
           "Profiling based inlining for two receivers")                     \
                                                                             \
--- a/src/share/vm/opto/memnode.cpp	Fri Jan 17 19:08:14 2020 +0000
+++ b/src/share/vm/opto/memnode.cpp	Mon Jan 27 05:10:29 2020 +0000
@@ -2485,7 +2485,8 @@
     assert(mem != mem->in(MemNode::Memory), "dead loop in StoreNode::Ideal");
 
     assert(Opcode() == mem->Opcode() ||
-           phase->C->get_alias_index(adr_type()) == Compile::AliasIdxRaw,
+           phase->C->get_alias_index(adr_type()) == Compile::AliasIdxRaw ||
+           (is_mismatched_access() || mem->as_Store()->is_mismatched_access()),
            "no mismatched stores, except on raw memory");
 
     if (mem->outcnt() == 1 &&           // check for intervening uses
--- a/src/share/vm/runtime/arguments.cpp	Fri Jan 17 19:08:14 2020 +0000
+++ b/src/share/vm/runtime/arguments.cpp	Mon Jan 27 05:10:29 2020 +0000
@@ -302,9 +302,10 @@
   { "UsePermISM",                    JDK_Version::jdk(8), JDK_Version::jdk(9) },
   { "UseMPSS",                       JDK_Version::jdk(8), JDK_Version::jdk(9) },
   { "UseStringCache",                JDK_Version::jdk(8), JDK_Version::jdk(9) },
-  { "UseOldInlining",                JDK_Version::jdk(9), JDK_Version::jdk(10) },
-  { "AutoShutdownNMT",               JDK_Version::jdk(9), JDK_Version::jdk(10) },
+  { "UseOldInlining",                JDK_Version::jdk_update(8, 20), JDK_Version::jdk(10) },
+  { "AutoShutdownNMT",               JDK_Version::jdk_update(8, 40), JDK_Version::jdk(10) },
   { "CompilationRepeat",             JDK_Version::jdk(8), JDK_Version::jdk(9) },
+  { "SegmentedHeapDumpThreshold",    JDK_Version::jdk_update(8, 252), JDK_Version::jdk(10) },
 #ifdef PRODUCT
   { "DesiredMethodLimit",
                            JDK_Version::jdk_update(7, 2), JDK_Version::jdk(8) },
--- a/src/share/vm/runtime/vmThread.cpp	Fri Jan 17 19:08:14 2020 +0000
+++ b/src/share/vm/runtime/vmThread.cpp	Mon Jan 27 05:10:29 2020 +0000
@@ -507,6 +507,7 @@
           _cur_vm_operation = safepoint_ops;
           if (_cur_vm_operation != NULL) {
             do {
+              EventMark em("Executing coalesced safepoint VM operation: %s", _cur_vm_operation->name());
               // evaluate_operation deletes the op object so we have
               // to grab the next op now
               VM_Operation* next = _cur_vm_operation->next();
--- a/src/share/vm/services/heapDumper.cpp	Fri Jan 17 19:08:14 2020 +0000
+++ b/src/share/vm/services/heapDumper.cpp	Mon Jan 27 05:10:29 2020 +0000
@@ -50,8 +50,7 @@
  *   src/share/demo/jvmti/hprof/hprof_io.c
  *
  *
- *  header    "JAVA PROFILE 1.0.1" or "JAVA PROFILE 1.0.2"
- *            (0-terminated)
+ *  header    "JAVA PROFILE 1.0.2" (0-terminated)
  *
  *  u4        size of identifiers. Identifiers are used to represent
  *            UTF8 strings, objects, stack traces, etc. They usually
@@ -382,6 +381,8 @@
   size_t _size;
   size_t _pos;
 
+  jlong _dump_start;
+
   char* _error;   // error message when I/O fails
 
   void set_file_descriptor(int fd)              { _fd = fd; }
@@ -405,6 +406,10 @@
   bool is_open() const                  { return file_descriptor() >= 0; }
   void flush();
 
+  jlong dump_start() const                      { return _dump_start; }
+  void set_dump_start(jlong pos);
+  julong current_record_length();
+
   // total number of bytes written to the disk
   julong bytes_written() const          { return _bytes_written; }
 
@@ -446,6 +451,7 @@
   _pos = 0;
   _error = NULL;
   _bytes_written = 0L;
+  _dump_start = (jlong)-1;
   _fd = os::create_binary_file(path, false);    // don't replace existing file
 
   // if the open failed we record the error
@@ -473,6 +479,22 @@
   }
 }
 
+// sets the dump starting position
+void DumpWriter::set_dump_start(jlong pos) {
+  _dump_start = pos;
+}
+
+julong DumpWriter::current_record_length() {
+  if (is_open()) {
+    // calculate the size of the dump record
+    julong dump_end = bytes_written() + bytes_unwritten();
+    assert(dump_end == (size_t)current_offset(), "checking");
+    julong dump_len = dump_end - dump_start() - 4;
+    return dump_len;
+  }
+  return 0;
+}
+
 // write directly to the file
 void DumpWriter::write_internal(void* s, size_t len) {
   if (is_open()) {
@@ -641,6 +663,18 @@
   static void dump_prim_array(DumpWriter* writer, typeArrayOop array);
   // create HPROF_FRAME record for the given method and bci
   static void dump_stack_frame(DumpWriter* writer, int frame_serial_num, int class_serial_num, Method* m, int bci);
+
+  // check if we need to truncate an array
+  static int calculate_array_max_length(DumpWriter* writer, arrayOop array, short header_size);
+
+  // writes a HPROF_HEAP_DUMP_SEGMENT record
+  static void write_dump_header(DumpWriter* writer);
+
+  // fixes up the length of the current dump record
+  static void write_current_dump_record_length(DumpWriter* writer);
+
+  // fixes up the current dump record and writes HPROF_HEAP_DUMP_END record
+  static void end_of_dump(DumpWriter* writer);
 };
 
 // write a header of the given type
@@ -1047,50 +1081,103 @@
   }
 }
 
+// Hprof uses an u4 as record length field,
+// which means we need to truncate arrays that are too long.
+int DumperSupport::calculate_array_max_length(DumpWriter* writer, arrayOop array, short header_size) {
+  BasicType type = ArrayKlass::cast(array->klass())->element_type();
+  assert(type >= T_BOOLEAN && type <= T_OBJECT, "invalid array element type");
+
+  int length = array->length();
+
+  int type_size;
+  if (type == T_OBJECT) {
+    type_size = sizeof(address);
+  } else {
+    type_size = type2aelembytes(type);
+  }
+
+  size_t length_in_bytes = (size_t)length * type_size;
+
+  // Create a new record if the current record is non-empty and the array can't fit.
+  julong current_record_length = writer->current_record_length();
+  if (current_record_length > 0 &&
+      (current_record_length + header_size + length_in_bytes) > max_juint) {
+    write_current_dump_record_length(writer);
+    write_dump_header(writer);
+
+    // We now have an empty record.
+    current_record_length = 0;
+  }
+
+  // Calculate max bytes we can use.
+  uint max_bytes = max_juint - (header_size + current_record_length);
+
+  // Array too long for the record?
+  // Calculate max length and return it.
+  if (length_in_bytes > max_bytes) {
+    length = max_bytes / type_size;
+    length_in_bytes = (size_t)length * type_size;
+
+    warning("cannot dump array of type %s[] with length %d; truncating to length %d",
+            type2name_tab[type], array->length(), length);
+  }
+  return length;
+}
+
 // creates HPROF_GC_OBJ_ARRAY_DUMP record for the given object array
 void DumperSupport::dump_object_array(DumpWriter* writer, objArrayOop array) {
+  // sizeof(u1) + 2 * sizeof(u4) + sizeof(objectID) + sizeof(classID)
+  short header_size = 1 + 2 * 4 + 2 * sizeof(address);
+
+  int length = calculate_array_max_length(writer, array, header_size);
 
   writer->write_u1(HPROF_GC_OBJ_ARRAY_DUMP);
   writer->write_objectID(array);
   writer->write_u4(STACK_TRACE_ID);
-  writer->write_u4((u4)array->length());
+  writer->write_u4(length);
+
 
   // array class ID
   writer->write_classID(array->klass());
 
   // [id]* elements
-  for (int index=0; index<array->length(); index++) {
+  for (int index = 0; index < length; index++) {
     oop o = array->obj_at(index);
     writer->write_objectID(o);
   }
 }
 
-#define WRITE_ARRAY(Array, Type, Size) \
-  for (int i=0; i<Array->length(); i++) { writer->write_##Size((Size)array->Type##_at(i)); }
-
+#define WRITE_ARRAY(Array, Type, Size, Length) \
+  for (int i = 0; i < Length; i++) { writer->write_##Size((Size)array->Type##_at(i)); }
 
 // creates HPROF_GC_PRIM_ARRAY_DUMP record for the given type array
 void DumperSupport::dump_prim_array(DumpWriter* writer, typeArrayOop array) {
   BasicType type = TypeArrayKlass::cast(array->klass())->element_type();
 
+  // 2 * sizeof(u1) + 2 * sizeof(u4) + sizeof(objectID)
+  short header_size = 2 * 1 + 2 * 4 + sizeof(address);
+
+  int length = calculate_array_max_length(writer, array, header_size);
+  int type_size = type2aelembytes(type);
+  u4 length_in_bytes = (u4)length * type_size;
+
   writer->write_u1(HPROF_GC_PRIM_ARRAY_DUMP);
   writer->write_objectID(array);
   writer->write_u4(STACK_TRACE_ID);
-  writer->write_u4((u4)array->length());
+  writer->write_u4(length);
   writer->write_u1(type2tag(type));
 
   // nothing to copy
-  if (array->length() == 0) {
+  if (length == 0) {
     return;
   }
 
   // If the byte ordering is big endian then we can copy most types directly
-  u4 length_in_bytes = (u4)array->length() * type2aelembytes(type);
 
   switch (type) {
     case T_INT : {
       if (Bytes::is_Java_byte_ordering_different()) {
-        WRITE_ARRAY(array, int, u4);
+        WRITE_ARRAY(array, int, u4, length);
       } else {
         writer->write_raw((void*)(array->int_at_addr(0)), length_in_bytes);
       }
@@ -1102,7 +1189,7 @@
     }
     case T_CHAR : {
       if (Bytes::is_Java_byte_ordering_different()) {
-        WRITE_ARRAY(array, char, u2);
+        WRITE_ARRAY(array, char, u2, length);
       } else {
         writer->write_raw((void*)(array->char_at_addr(0)), length_in_bytes);
       }
@@ -1110,7 +1197,7 @@
     }
     case T_SHORT : {
       if (Bytes::is_Java_byte_ordering_different()) {
-        WRITE_ARRAY(array, short, u2);
+        WRITE_ARRAY(array, short, u2, length);
       } else {
         writer->write_raw((void*)(array->short_at_addr(0)), length_in_bytes);
       }
@@ -1118,7 +1205,7 @@
     }
     case T_BOOLEAN : {
       if (Bytes::is_Java_byte_ordering_different()) {
-        WRITE_ARRAY(array, bool, u1);
+        WRITE_ARRAY(array, bool, u1, length);
       } else {
         writer->write_raw((void*)(array->bool_at_addr(0)), length_in_bytes);
       }
@@ -1126,7 +1213,7 @@
     }
     case T_LONG : {
       if (Bytes::is_Java_byte_ordering_different()) {
-        WRITE_ARRAY(array, long, u8);
+        WRITE_ARRAY(array, long, u8, length);
       } else {
         writer->write_raw((void*)(array->long_at_addr(0)), length_in_bytes);
       }
@@ -1138,14 +1225,14 @@
     // use IEEE 754.
 
     case T_FLOAT : {
-      for (int i=0; i<array->length(); i++) {
-        dump_float( writer, array->float_at(i) );
+      for (int i = 0; i < length; i++) {
+        dump_float(writer, array->float_at(i));
       }
       break;
     }
     case T_DOUBLE : {
-      for (int i=0; i<array->length(); i++) {
-        dump_double( writer, array->double_at(i) );
+      for (int i = 0; i < length; i++) {
+        dump_double(writer, array->double_at(i));
       }
       break;
     }
@@ -1362,8 +1449,6 @@
   JavaThread*           _oome_thread;
   Method*               _oome_constructor;
   bool _gc_before_heap_dump;
-  bool _is_segmented_dump;
-  jlong _dump_start;
   GrowableArray<Klass*>* _klass_map;
   ThreadStackTrace** _stack_traces;
   int _num_threads;
@@ -1382,11 +1467,6 @@
   void clear_global_dumper() { _global_dumper = NULL; }
   void clear_global_writer() { _global_writer = NULL; }
 
-  bool is_segmented_dump() const                { return _is_segmented_dump; }
-  void set_segmented_dump()                     { _is_segmented_dump = true; }
-  jlong dump_start() const                      { return _dump_start; }
-  void set_dump_start(jlong pos);
-
   bool skip_operation() const;
 
   // writes a HPROF_LOAD_CLASS record
@@ -1411,16 +1491,6 @@
   // HPROF_TRACE and HPROF_FRAME records
   void dump_stack_traces();
 
-  // writes a HPROF_HEAP_DUMP or HPROF_HEAP_DUMP_SEGMENT record
-  void write_dump_header();
-
-  // fixes up the length of the current dump record
-  void write_current_dump_record_length();
-
-  // fixes up the current dump record )and writes HPROF_HEAP_DUMP_END
-  // record in the case of a segmented heap dump)
-  void end_of_dump();
-
  public:
   VM_HeapDumper(DumpWriter* writer, bool gc_before_heap_dump, bool oome) :
     VM_GC_Operation(0 /* total collections,      dummy, ignored */,
@@ -1429,8 +1499,6 @@
                     gc_before_heap_dump) {
     _local_writer = writer;
     _gc_before_heap_dump = gc_before_heap_dump;
-    _is_segmented_dump = false;
-    _dump_start = (jlong)-1;
     _klass_map = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<Klass*>(INITIAL_CLASS_COUNT, true);
     _stack_traces = NULL;
     _num_threads = 0;
@@ -1470,35 +1538,23 @@
   return false;
 }
 
-// sets the dump starting position
-void VM_HeapDumper::set_dump_start(jlong pos) {
-  _dump_start = pos;
-}
-
- // writes a HPROF_HEAP_DUMP or HPROF_HEAP_DUMP_SEGMENT record
-void VM_HeapDumper::write_dump_header() {
-  if (writer()->is_open()) {
-    if (is_segmented_dump()) {
-      writer()->write_u1(HPROF_HEAP_DUMP_SEGMENT);
-    } else {
-      writer()->write_u1(HPROF_HEAP_DUMP);
-    }
-    writer()->write_u4(0); // current ticks
+ // writes a HPROF_HEAP_DUMP_SEGMENT record
+void DumperSupport::write_dump_header(DumpWriter* writer) {
+  if (writer->is_open()) {
+    writer->write_u1(HPROF_HEAP_DUMP_SEGMENT);
+    writer->write_u4(0); // current ticks
 
     // record the starting position for the dump (its length will be fixed up later)
-    set_dump_start(writer()->current_offset());
-    writer()->write_u4(0);
+    writer->set_dump_start(writer->current_offset());
+    writer->write_u4(0);
   }
 }
 
 // fixes up the length of the current dump record
-void VM_HeapDumper::write_current_dump_record_length() {
-  if (writer()->is_open()) {
-    assert(dump_start() >= 0, "no dump start recorded");
-
-    // calculate the size of the dump record
-    julong dump_end = writer()->current_offset();
-    julong dump_len = (dump_end - dump_start() - 4);
+void DumperSupport::write_current_dump_record_length(DumpWriter* writer) {
+  if (writer->is_open()) {
+    julong dump_end = writer->bytes_written() + writer->bytes_unwritten();
+    julong dump_len = writer->current_record_length();
 
     // record length must fit in a u4
     if (dump_len > max_juint) {
@@ -1506,17 +1562,18 @@
     }
 
     // seek to the dump start and fix-up the length
-    writer()->seek_to_offset(dump_start());
-    writer()->write_u4((u4)dump_len);
+    assert(writer->dump_start() >= 0, "no dump start recorded");
+    writer->seek_to_offset(writer->dump_start());
+    writer->write_u4((u4)dump_len);
 
     // adjust the total size written to keep the bytes written correct.
-    writer()->adjust_bytes_written(-((jlong) sizeof(u4)));
+    writer->adjust_bytes_written(-((jlong) sizeof(u4)));
 
     // seek to dump end so we can continue
-    writer()->seek_to_offset(dump_end);
+    writer->seek_to_offset(dump_end);
 
     // no current dump record
-    set_dump_start((jlong)-1);
+    writer->set_dump_start((jlong)-1);
   }
 }
 
@@ -1524,33 +1581,23 @@
 // new segment.
 void VM_HeapDumper::check_segment_length() {
   if (writer()->is_open()) {
-    if (is_segmented_dump()) {
-      // don't use current_offset that would be too expensive on a per record basis
-      julong dump_end = writer()->bytes_written() + writer()->bytes_unwritten();
-      assert(dump_end == (julong)writer()->current_offset(), "checking");
-      julong dump_len = (dump_end - dump_start() - 4);
-      assert(dump_len <= max_juint, "bad dump length");
+    julong dump_len = writer()->current_record_length();
 
-      if (dump_len > HeapDumpSegmentSize) {
-        write_current_dump_record_length();
-        write_dump_header();
-      }
+    if (dump_len > 2UL*G) {
+      DumperSupport::write_current_dump_record_length(writer());
+      DumperSupport::write_dump_header(writer());
     }
   }
 }
 
-// fixes up the current dump record )and writes HPROF_HEAP_DUMP_END
-// record in the case of a segmented heap dump)
-void VM_HeapDumper::end_of_dump() {
-  if (writer()->is_open()) {
-    write_current_dump_record_length();
+// fixes up the current dump record and writes HPROF_HEAP_DUMP_END record
+void DumperSupport::end_of_dump(DumpWriter* writer) {
+  if (writer->is_open()) {
+    write_current_dump_record_length(writer);
 
-    // for segmented dump we write the end record
-    if (is_segmented_dump()) {
-      writer()->write_u1(HPROF_HEAP_DUMP_END);
-      writer()->write_u4(0);
-      writer()->write_u4(0);
-    }
+    writer->write_u1(HPROF_HEAP_DUMP_END);
+    writer->write_u4(0);
+    writer->write_u4(0);
   }
 }
 
@@ -1716,16 +1763,17 @@
 //  [HPROF_LOAD_CLASS]*
 //  [[HPROF_FRAME]*|HPROF_TRACE]*
 //  [HPROF_GC_CLASS_DUMP]*
-//  HPROF_HEAP_DUMP
+//  [HPROF_HEAP_DUMP_SEGMENT]*
+//  HPROF_HEAP_DUMP_END
 //
 // The HPROF_TRACE records represent the stack traces where the heap dump
 // is generated and a "dummy trace" record which does not include
 // any frames. The dummy trace record is used to be referenced as the
 // unknown object alloc site.
 //
-// The HPROF_HEAP_DUMP record has a length following by sub-records. To allow
-// the heap dump be generated in a single pass we remember the position of
-// the dump length and fix it up after all sub-records have been written.
+// Each HPROF_HEAP_DUMP_SEGMENT record has a length followed by sub-records.
+// To allow the heap dump be generated in a single pass we remember the position
+// of the dump length and fix it up after all sub-records have been written.
 // To generate the sub-records we iterate over the heap, writing
 // HPROF_GC_INSTANCE_DUMP, HPROF_GC_OBJ_ARRAY_DUMP, and HPROF_GC_PRIM_ARRAY_DUMP
 // records as we go. Once that is done we write records for some of the GC
@@ -1752,15 +1800,9 @@
   set_global_dumper();
   set_global_writer();
 
-  // Write the file header - use 1.0.2 for large heaps, otherwise 1.0.1
+  // Write the file header - we always use 1.0.2
   size_t used = ch->used();
-  const char* header;
-  if (used > (size_t)SegmentedHeapDumpThreshold) {
-    set_segmented_dump();
-    header = "JAVA PROFILE 1.0.2";
-  } else {
-    header = "JAVA PROFILE 1.0.1";
-  }
+  const char* header = "JAVA PROFILE 1.0.2";
 
   // header is few bytes long - no chance to overflow int
   writer()->write_raw((void*)header, (int)strlen(header));
@@ -1780,8 +1822,8 @@
   // this must be called after _klass_map is built when iterating the classes above.
   dump_stack_traces();
 
-  // write HPROF_HEAP_DUMP or HPROF_HEAP_DUMP_SEGMENT
-  write_dump_header();
+  // write HPROF_HEAP_DUMP_SEGMENT
+  DumperSupport::write_dump_header(writer());
 
   // Writes HPROF_GC_CLASS_DUMP records
   ClassLoaderDataGraph::classes_do(&do_class_dump);
@@ -1789,9 +1831,9 @@
   check_segment_length();
 
   // writes HPROF_GC_INSTANCE_DUMP records.
-  // After each sub-record is written check_segment_length will be invoked. When
-  // generated a segmented heap dump this allows us to check if the current
-  // segment exceeds a threshold and if so, then a new segment is started.
+  // After each sub-record is written check_segment_length will be invoked
+  // to check if the current segment exceeds a threshold. If so, a new
+  // segment is started.
   // The HPROF_GC_CLASS_DUMP and HPROF_GC_INSTANCE_DUMP are the vast bulk
   // of the heap dump.
   HeapObjectDumper obj_dumper(this, writer());
@@ -1817,9 +1859,8 @@
   StickyClassDumper class_dumper(writer());
   SystemDictionary::always_strong_classes_do(&class_dumper);
 
-  // fixes up the length of the dump record. In the case of a segmented
-  // heap then the HPROF_HEAP_DUMP_END record is also written.
-  end_of_dump();
+  // fixes up the length of the dump record and writes the HPROF_HEAP_DUMP_END record.
+  DumperSupport::end_of_dump(writer());
 
   // Now we clear the global variables, so that a future dumper might run.
   clear_global_dumper();
--- a/src/share/vm/utilities/vmError.cpp	Fri Jan 17 19:08:14 2020 +0000
+++ b/src/share/vm/utilities/vmError.cpp	Mon Jan 27 05:10:29 2020 +0000
@@ -1060,7 +1060,7 @@
       out.print_raw   (cmd);
       out.print_raw_cr("\" ...");
 
-      if (os::fork_and_exec(cmd, true) < 0) {
+      if (os::fork_and_exec(cmd) < 0) {
         out.print_cr("os::fork_and_exec failed: %s (%d)", strerror(errno), errno);
       }
     }
@@ -1147,7 +1147,7 @@
 #endif
     tty->print_cr("\"%s\"...", cmd);
 
-    if (os::fork_and_exec(cmd) < 0) {
+    if (os::fork_and_exec(cmd, true) < 0) {
       tty->print_cr("os::fork_and_exec failed: %s (%d)", strerror(errno), errno);
     }
   }