Mercurial > hg > icedtea8-forest > hotspot
changeset 10598:efb699b681a1 icedtea-3.16.0pre01
Merge jdk8u252-b01
author | andrew |
---|---|
date | Sun, 01 Mar 2020 15:37:36 +0000 |
parents | b207c67eecef (current diff) a67e9c6edcdd (diff) |
children | df300dafe8de |
files | .hgtags agent/src/os/linux/ps_core.c make/aix/makefiles/vm.make make/bsd/makefiles/vm.make make/linux/makefiles/vm.make make/solaris/makefiles/vm.make src/share/vm/opto/c2_globals.hpp src/share/vm/opto/memnode.cpp src/share/vm/runtime/arguments.cpp src/share/vm/services/heapDumper.cpp src/share/vm/utilities/vmError.cpp |
diffstat | 14 files changed, 170 insertions(+), 341 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Tue Jan 21 03:15:18 2020 +0000 +++ b/.hgtags Sun Mar 01 15:37:36 2020 +0000 @@ -1374,3 +1374,4 @@ 7c9f6b5f8d119dc1ba3c5536595ce3ae7414599d jdk8u242-ga f767447146983e6d1110c3f65eefb043b788e906 icedtea-3.15.0 f767447146983e6d1110c3f65eefb043b788e906 icedtea-3.16.0pre00 +8c0733543544bbcd32c4404630d764d280299056 jdk8u252-b00
--- a/agent/src/os/linux/ps_core.c Tue Jan 21 03:15:18 2020 +0000 +++ b/agent/src/os/linux/ps_core.c Sun Mar 01 15:37:36 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 Tue Jan 21 03:15:18 2020 +0000 +++ b/make/aix/makefiles/vm.make Sun Mar 01 15:37:36 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 Tue Jan 21 03:15:18 2020 +0000 +++ b/make/bsd/makefiles/vm.make Sun Mar 01 15:37:36 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 Tue Jan 21 03:15:18 2020 +0000 +++ b/make/linux/makefiles/vm.make Sun Mar 01 15:37:36 2020 +0000 @@ -132,6 +132,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 Tue Jan 21 03:15:18 2020 +0000 +++ b/make/solaris/makefiles/vm.make Sun Mar 01 15:37:36 2020 +0000 @@ -117,6 +117,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 Tue Jan 21 03:15:18 2020 +0000 +++ b/src/share/vm/adlc/filebuff.cpp Sun Mar 01 15:37:36 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 Tue Jan 21 03:15:18 2020 +0000 +++ b/src/share/vm/adlc/filebuff.hpp Sun Mar 01 15:37:36 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 Tue Jan 21 03:15:18 2020 +0000 +++ b/src/share/vm/opto/c2_globals.hpp Sun Mar 01 15:37:36 2020 +0000 @@ -363,9 +363,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 Tue Jan 21 03:15:18 2020 +0000 +++ b/src/share/vm/opto/memnode.cpp Sun Mar 01 15:37:36 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 Tue Jan 21 03:15:18 2020 +0000 +++ b/src/share/vm/runtime/arguments.cpp Sun Mar 01 15:37:36 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 Tue Jan 21 03:15:18 2020 +0000 +++ b/src/share/vm/runtime/vmThread.cpp Sun Mar 01 15:37:36 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 Tue Jan 21 03:15:18 2020 +0000 +++ b/src/share/vm/services/heapDumper.cpp Sun Mar 01 15:37:36 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 Tue Jan 21 03:15:18 2020 +0000 +++ b/src/share/vm/utilities/vmError.cpp Sun Mar 01 15:37:36 2020 +0000 @@ -1061,7 +1061,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); } } @@ -1148,7 +1148,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); } }