# HG changeset patch # User zgu # Date 1343858450 25200 # Node ID b27675afea119dcf9d7da99be78d4c5f6324b35d # Parent 4acebbe310e1bd868c96efa3d50b60a67b69f5e4# Parent 5e2dc722e70d748f1a7bafc0ba9f3b566e9f9227 Merge diff -r 4acebbe310e1 -r b27675afea11 .hgtags --- a/.hgtags Wed Aug 01 17:19:30 2012 -0400 +++ b/.hgtags Wed Aug 01 15:00:50 2012 -0700 @@ -263,3 +263,5 @@ 66b0450071c1534e014b131892cc86b63f1d009c hs24-b16 1e26f61bbb521642639f56fae11326f1932f5a7d jdk8-b48 bd54fe36b5e50f9ef1e30a5047b27fee5297e268 hs24-b17 +e3619706a7253540a2d94e9e841acaab8ace7038 jdk8-b49 +72e0362c3f0cfacbbac8af8a5b9d2e182f21c17b hs24-b18 diff -r 4acebbe310e1 -r b27675afea11 make/hotspot_version --- a/make/hotspot_version Wed Aug 01 17:19:30 2012 -0400 +++ b/make/hotspot_version Wed Aug 01 15:00:50 2012 -0700 @@ -35,7 +35,7 @@ HS_MAJOR_VER=24 HS_MINOR_VER=0 -HS_BUILD_NUMBER=18 +HS_BUILD_NUMBER=19 JDK_MAJOR_VER=1 JDK_MINOR_VER=8 diff -r 4acebbe310e1 -r b27675afea11 make/solaris/makefiles/fastdebug.make --- a/make/solaris/makefiles/fastdebug.make Wed Aug 01 17:19:30 2012 -0400 +++ b/make/solaris/makefiles/fastdebug.make Wed Aug 01 15:00:50 2012 -0700 @@ -36,6 +36,11 @@ ifeq ("${Platform_compiler}", "sparcWorks") OPT_CFLAGS/SLOWER = -xO2 +ifeq ($(COMPILER_REV_NUMERIC), 510) +# CC 5.10 has bug XXXXX with -xO4 +OPT_CFLAGS/jvmtiClassFileReconstituter.o = $(OPT_CFLAGS/SLOWER) +endif # COMPILER_REV_NUMERIC == 510 + ifeq ($(COMPILER_REV_NUMERIC), 509) # To avoid jvm98 crash OPT_CFLAGS/instanceKlass.o = $(OPT_CFLAGS/SLOWER) diff -r 4acebbe310e1 -r b27675afea11 make/solaris/makefiles/optimized.make --- a/make/solaris/makefiles/optimized.make Wed Aug 01 17:19:30 2012 -0400 +++ b/make/solaris/makefiles/optimized.make Wed Aug 01 15:00:50 2012 -0700 @@ -32,6 +32,11 @@ # (OPT_CFLAGS/SLOWER is also available, to alter compilation of buggy files) ifeq ("${Platform_compiler}", "sparcWorks") +ifeq ($(COMPILER_REV_NUMERIC), 510) +# CC 5.10 has bug XXXXX with -xO4 +OPT_CFLAGS/jvmtiClassFileReconstituter.o = $(OPT_CFLAGS/O2) +endif # COMPILER_REV_NUMERIC == 510 + ifeq ($(shell expr $(COMPILER_REV_NUMERIC) \>= 509), 1) # dtrace cannot handle tail call optimization (6672627, 6693876) OPT_CFLAGS/jni.o = $(OPT_CFLAGS/DEFAULT) $(OPT_CCFLAGS/NO_TAIL_CALL_OPT) diff -r 4acebbe310e1 -r b27675afea11 make/solaris/makefiles/product.make --- a/make/solaris/makefiles/product.make Wed Aug 01 17:19:30 2012 -0400 +++ b/make/solaris/makefiles/product.make Wed Aug 01 15:00:50 2012 -0700 @@ -40,6 +40,11 @@ # (OPT_CFLAGS/SLOWER is also available, to alter compilation of buggy files) ifeq ("${Platform_compiler}", "sparcWorks") +ifeq ($(COMPILER_REV_NUMERIC), 510) +# CC 5.10 has bug XXXXX with -xO4 +OPT_CFLAGS/jvmtiClassFileReconstituter.o = $(OPT_CFLAGS/O2) +endif # COMPILER_REV_NUMERIC == 510 + ifeq ($(shell expr $(COMPILER_REV_NUMERIC) \>= 509), 1) # dtrace cannot handle tail call optimization (6672627, 6693876) OPT_CFLAGS/jni.o = $(OPT_CFLAGS/DEFAULT) $(OPT_CCFLAGS/NO_TAIL_CALL_OPT) diff -r 4acebbe310e1 -r b27675afea11 src/os/bsd/vm/decoder_machO.cpp --- a/src/os/bsd/vm/decoder_machO.cpp Wed Aug 01 17:19:30 2012 -0400 +++ b/src/os/bsd/vm/decoder_machO.cpp Wed Aug 01 15:00:50 2012 -0700 @@ -26,6 +26,139 @@ #ifdef __APPLE__ #include "decoder_machO.hpp" + +#include +#include +#include + + +bool MachODecoder::demangle(const char* symbol, char *buf, int buflen) { + int status; + char* result; + size_t size = (size_t)buflen; + // Don't pass buf to __cxa_demangle. In case of the 'buf' is too small, + // __cxa_demangle will call system "realloc" for additional memory, which + // may use different malloc/realloc mechanism that allocates 'buf'. + if ((result = abi::__cxa_demangle(symbol, NULL, NULL, &status)) != NULL) { + jio_snprintf(buf, buflen, "%s", result); + // call c library's free + ::free(result); + return true; + } + return false; +} + +bool MachODecoder::decode(address addr, char *buf, + int buflen, int *offset, const void *mach_base) { + struct symtab_command * symt = (struct symtab_command *) + mach_find_command((struct mach_header_64 *)mach_base, LC_SYMTAB); + if (symt == NULL) { + DEBUG_ONLY(tty->print_cr("no symtab in mach file at 0x%lx", mach_base)); + return false; + } + uint32_t off = symt->symoff; /* symbol table offset (within this mach file) */ + uint32_t nsyms = symt->nsyms; /* number of symbol table entries */ + uint32_t stroff = symt->stroff; /* string table offset */ + uint32_t strsize = symt->strsize; /* string table size in bytes */ + + // iterate through symbol table trying to match our offset + + uint32_t addr_relative = (uintptr_t) mach_base - (uintptr_t) addr; // offset we seek in the symtab + void * symtab_addr = (void*) ((uintptr_t) mach_base + off); + struct nlist_64 *cur_nlist = (struct nlist_64 *) symtab_addr; + struct nlist_64 *last_nlist = cur_nlist; // no size stored in an entry, so keep previously seen nlist + + int32_t found_strx = 0; + int32_t found_symval = 0; + + for (uint32_t i=0; i < nsyms; i++) { + uint32_t this_value = cur_nlist->n_value; + + if (addr_relative == this_value) { + found_strx = cur_nlist->n_un.n_strx; + found_symval = this_value; + break; + } else if (addr_relative > this_value) { + // gone past it, use previously seen nlist: + found_strx = last_nlist->n_un.n_strx; + found_symval = last_nlist->n_value; + break; + } + last_nlist = cur_nlist; + cur_nlist = cur_nlist + sizeof(struct nlist_64); + } + if (found_strx == 0) { + return false; + } + // write the offset: + *offset = addr_relative - found_symval; + + // lookup found_strx in the string table + char * symname = mach_find_in_stringtable((char*) ((uintptr_t)mach_base + stroff), strsize, found_strx); + if (symname) { + strncpy(buf, symname, buflen); + return true; + } + DEBUG_ONLY(tty->print_cr("no string or null string found.")); + return false; +} + +void* MachODecoder::mach_find_command(struct mach_header_64 * mach_base, uint32_t command_wanted) { + // possibly verify it is a mach_header, use magic number. + // commands begin immediately after the header. + struct load_command *pos = (struct load_command *) mach_base + sizeof(struct mach_header_64); + for (uint32_t i = 0; i < mach_base->ncmds; i++) { + struct load_command *this_cmd = (struct load_command *) pos; + if (this_cmd->cmd == command_wanted) { + return pos; + } + int cmdsize = this_cmd->cmdsize; + pos += cmdsize; + } + return NULL; +} + +char* MachODecoder::mach_find_in_stringtable(char *strtab, uint32_t tablesize, int strx_wanted) { + + if (strx_wanted == 0) { + return NULL; + } + char *strtab_end = strtab + tablesize; + + // find the first string, skip over the space char + // (or the four zero bytes we see e.g. in libclient) + if (*strtab == ' ') { + strtab++; + if (*strtab != 0) { + DEBUG_ONLY(tty->print_cr("string table has leading space but no following zero.")); + return NULL; + } + strtab++; + } else { + if ((uint32_t) *strtab != 0) { + DEBUG_ONLY(tty->print_cr("string table without leading space or leading int of zero.")); + return NULL; + } + strtab+=4; + } + // read the real strings starting at index 1 + int cur_strx = 1; + while (strtab < strtab_end) { + if (cur_strx == strx_wanted) { + return strtab; + } + // find start of next string + while (*strtab != 0) { + strtab++; + } + strtab++; // skip the terminating zero + cur_strx++; + } + DEBUG_ONLY(tty->print_cr("string number %d not found.", strx_wanted)); + return NULL; +} + + #endif diff -r 4acebbe310e1 -r b27675afea11 src/os/bsd/vm/decoder_machO.hpp --- a/src/os/bsd/vm/decoder_machO.hpp Wed Aug 01 17:19:30 2012 -0400 +++ b/src/os/bsd/vm/decoder_machO.hpp Wed Aug 01 15:00:50 2012 -0700 @@ -31,10 +31,25 @@ // Just a placehold for now, a real implementation should derive // from AbstractDecoder -class MachODecoder : public NullDecoder { -public: +class MachODecoder : public AbstractDecoder { + public: MachODecoder() { } ~MachODecoder() { } + virtual bool can_decode_C_frame_in_vm() const { + return true; + } + virtual bool demangle(const char* symbol, char* buf, int buflen); + virtual bool decode(address pc, char* buf, int buflen, int* offset, + const void* base); + virtual bool decode(address pc, char* buf, int buflen, int* offset, + const char* module_path = NULL) { + ShouldNotReachHere(); + return false; + } + + private: + void * mach_find_command(struct mach_header_64 * mach_base, uint32_t command_wanted); + char * mach_find_in_stringtable(char *strtab, uint32_t tablesize, int strx_wanted); }; #endif diff -r 4acebbe310e1 -r b27675afea11 src/os/bsd/vm/os_bsd.cpp --- a/src/os/bsd/vm/os_bsd.cpp Wed Aug 01 17:19:30 2012 -0400 +++ b/src/os/bsd/vm/os_bsd.cpp Wed Aug 01 15:00:50 2012 -0700 @@ -1946,10 +1946,16 @@ return false; } + +#define MACH_MAXSYMLEN 256 + bool os::dll_address_to_function_name(address addr, char *buf, int buflen, int *offset) { Dl_info dlinfo; - + char localbuf[MACH_MAXSYMLEN]; + + // dladdr will find names of dynamic functions only, but does + // it set dli_fbase with mach_header address when it "fails" ? if (dladdr((void*)addr, &dlinfo) && dlinfo.dli_sname != NULL) { if (buf != NULL) { if(!Decoder::demangle(dlinfo.dli_sname, buf, buflen)) { @@ -1965,6 +1971,14 @@ } } + // Handle non-dymanic manually: + if (dlinfo.dli_fbase != NULL && + Decoder::decode(addr, localbuf, MACH_MAXSYMLEN, offset, dlinfo.dli_fbase)) { + if(!Decoder::demangle(localbuf, buf, buflen)) { + jio_snprintf(buf, buflen, "%s", localbuf); + } + return true; + } if (buf != NULL) buf[0] = '\0'; if (offset != NULL) *offset = -1; return false; diff -r 4acebbe310e1 -r b27675afea11 src/os/windows/vm/decoder_windows.cpp --- a/src/os/windows/vm/decoder_windows.cpp Wed Aug 01 17:19:30 2012 -0400 +++ b/src/os/windows/vm/decoder_windows.cpp Wed Aug 01 15:00:50 2012 -0700 @@ -72,10 +72,10 @@ // find out if jvm.dll contains private symbols, by decoding // current function and comparing the result - address addr = (address)Decoder::decode; + address addr = (address)Decoder::demangle; char buf[MAX_PATH]; if (decode(addr, buf, sizeof(buf), NULL)) { - _can_decode_in_vm = !strcmp(buf, "Decoder::decode"); + _can_decode_in_vm = !strcmp(buf, "Decoder::demangle"); } } } diff -r 4acebbe310e1 -r b27675afea11 src/os/windows/vm/decoder_windows.hpp --- a/src/os/windows/vm/decoder_windows.hpp Wed Aug 01 17:19:30 2012 -0400 +++ b/src/os/windows/vm/decoder_windows.hpp Wed Aug 01 15:00:50 2012 -0700 @@ -45,6 +45,10 @@ bool can_decode_C_frame_in_vm() const; bool demangle(const char* symbol, char *buf, int buflen); bool decode(address addr, char *buf, int buflen, int* offset, const char* modulepath = NULL); + bool decode(address addr, char *buf, int buflen, int* offset, const void* base) { + ShouldNotReachHere(); + return false; + } private: void initialize(); diff -r 4acebbe310e1 -r b27675afea11 src/share/vm/opto/phaseX.cpp --- a/src/share/vm/opto/phaseX.cpp Wed Aug 01 17:19:30 2012 -0400 +++ b/src/share/vm/opto/phaseX.cpp Wed Aug 01 15:00:50 2012 -0700 @@ -757,6 +757,7 @@ //------------------------------PhaseIterGVN----------------------------------- // Initialize hash table to fresh and clean for +VerifyOpto PhaseIterGVN::PhaseIterGVN( PhaseIterGVN *igvn, const char *dummy ) : PhaseGVN(igvn,dummy), _worklist( ), + _stack(C->unique() >> 1), _delay_transform(false) { } @@ -764,6 +765,7 @@ // Initialize with previous PhaseIterGVN info; used by PhaseCCP PhaseIterGVN::PhaseIterGVN( PhaseIterGVN *igvn ) : PhaseGVN(igvn), _worklist( igvn->_worklist ), + _stack( igvn->_stack ), _delay_transform(igvn->_delay_transform) { } @@ -772,6 +774,7 @@ // Initialize with previous PhaseGVN info from Parser PhaseIterGVN::PhaseIterGVN( PhaseGVN *gvn ) : PhaseGVN(gvn), _worklist(*C->for_igvn()), + _stack(C->unique() >> 1), _delay_transform(false) { uint max; @@ -1138,51 +1141,77 @@ // Kill a globally dead Node. All uses are also globally dead and are // aggressively trimmed. void PhaseIterGVN::remove_globally_dead_node( Node *dead ) { - assert(dead != C->root(), "killing root, eh?"); - if (dead->is_top()) return; - NOT_PRODUCT( set_progress(); ) - // Remove from iterative worklist - _worklist.remove(dead); - if (!dead->is_Con()) { // Don't kill cons but uses - // Remove from hash table - _table.hash_delete( dead ); - // Smash all inputs to 'dead', isolating him completely - for( uint i = 0; i < dead->req(); i++ ) { - Node *in = dead->in(i); - if( in ) { // Points to something? - dead->set_req(i,NULL); // Kill the edge - if (in->outcnt() == 0 && in != C->top()) {// Made input go dead? - remove_dead_node(in); // Recursively remove - } else if (in->outcnt() == 1 && - in->has_special_unique_user()) { - _worklist.push(in->unique_out()); - } else if (in->outcnt() <= 2 && dead->is_Phi()) { - if( in->Opcode() == Op_Region ) - _worklist.push(in); - else if( in->is_Store() ) { - DUIterator_Fast imax, i = in->fast_outs(imax); - _worklist.push(in->fast_out(i)); - i++; - if(in->outcnt() == 2) { - _worklist.push(in->fast_out(i)); - i++; + enum DeleteProgress { + PROCESS_INPUTS, + PROCESS_OUTPUTS + }; + assert(_stack.is_empty(), "not empty"); + _stack.push(dead, PROCESS_INPUTS); + + while (_stack.is_nonempty()) { + dead = _stack.node(); + uint progress_state = _stack.index(); + assert(dead != C->root(), "killing root, eh?"); + assert(!dead->is_top(), "add check for top when pushing"); + NOT_PRODUCT( set_progress(); ) + if (progress_state == PROCESS_INPUTS) { + // After following inputs, continue to outputs + _stack.set_index(PROCESS_OUTPUTS); + // Remove from iterative worklist + _worklist.remove(dead); + if (!dead->is_Con()) { // Don't kill cons but uses + bool recurse = false; + // Remove from hash table + _table.hash_delete( dead ); + // Smash all inputs to 'dead', isolating him completely + for( uint i = 0; i < dead->req(); i++ ) { + Node *in = dead->in(i); + if( in ) { // Points to something? + dead->set_req(i,NULL); // Kill the edge + if (in->outcnt() == 0 && in != C->top()) {// Made input go dead? + _stack.push(in, PROCESS_INPUTS); // Recursively remove + recurse = true; + } else if (in->outcnt() == 1 && + in->has_special_unique_user()) { + _worklist.push(in->unique_out()); + } else if (in->outcnt() <= 2 && dead->is_Phi()) { + if( in->Opcode() == Op_Region ) + _worklist.push(in); + else if( in->is_Store() ) { + DUIterator_Fast imax, i = in->fast_outs(imax); + _worklist.push(in->fast_out(i)); + i++; + if(in->outcnt() == 2) { + _worklist.push(in->fast_out(i)); + i++; + } + assert(!(i < imax), "sanity"); + } } - assert(!(i < imax), "sanity"); } } + + if (dead->is_macro()) { + C->remove_macro_node(dead); + } + + if (recurse) { + continue; + } } } - if (dead->is_macro()) { - C->remove_macro_node(dead); + // Aggressively kill globally dead uses + // (Rather than pushing all the outs at once, we push one at a time, + // plus the parent to resume later, because of the indefinite number + // of edge deletions per loop trip.) + if (dead->outcnt() > 0) { + // Recursively remove + _stack.push(dead->raw_out(0), PROCESS_INPUTS); + } else { + _stack.pop(); } } - // Aggressively kill globally dead uses - // (Cannot use DUIterator_Last because of the indefinite number - // of edge deletions per loop trip.) - while (dead->outcnt() > 0) { - remove_globally_dead_node(dead->raw_out(0)); - } } //------------------------------subsume_node----------------------------------- diff -r 4acebbe310e1 -r b27675afea11 src/share/vm/opto/phaseX.hpp --- a/src/share/vm/opto/phaseX.hpp Wed Aug 01 17:19:30 2012 -0400 +++ b/src/share/vm/opto/phaseX.hpp Wed Aug 01 15:00:50 2012 -0700 @@ -403,6 +403,8 @@ // Subsume users of node 'old' into node 'nn' void subsume_node( Node *old, Node *nn ); + Node_Stack _stack; // Stack used to avoid recursion + protected: // Idealize new Node 'n' with respect to its inputs and its value @@ -438,8 +440,8 @@ // It is significant only for debugging and profiling. Node* register_new_node_with_optimizer(Node* n, Node* orig = NULL); - // Kill a globally dead Node. It is allowed to have uses which are - // assumed dead and left 'in limbo'. + // Kill a globally dead Node. All uses are also globally dead and are + // aggressively trimmed. void remove_globally_dead_node( Node *dead ); // Kill all inputs to a dead node, recursively making more dead nodes. diff -r 4acebbe310e1 -r b27675afea11 src/share/vm/utilities/decoder.cpp --- a/src/share/vm/utilities/decoder.cpp Wed Aug 01 17:19:30 2012 -0400 +++ b/src/share/vm/utilities/decoder.cpp Wed Aug 01 15:00:50 2012 -0700 @@ -91,6 +91,18 @@ return decoder->decode(addr, buf, buflen, offset, modulepath); } +bool Decoder::decode(address addr, char* buf, int buflen, int* offset, const void* base) { + assert(_shared_decoder_lock != NULL, "Just check"); + bool error_handling_thread = os::current_thread_id() == VMError::first_error_tid; + MutexLockerEx locker(error_handling_thread ? NULL : _shared_decoder_lock, true); + AbstractDecoder* decoder = error_handling_thread ? + get_error_handler_instance(): get_shared_instance(); + assert(decoder != NULL, "null decoder"); + + return decoder->decode(addr, buf, buflen, offset, base); +} + + bool Decoder::demangle(const char* symbol, char* buf, int buflen) { assert(_shared_decoder_lock != NULL, "Just check"); bool error_handling_thread = os::current_thread_id() == VMError::first_error_tid; diff -r 4acebbe310e1 -r b27675afea11 src/share/vm/utilities/decoder.hpp --- a/src/share/vm/utilities/decoder.hpp Wed Aug 01 17:19:30 2012 -0400 +++ b/src/share/vm/utilities/decoder.hpp Wed Aug 01 15:00:50 2012 -0700 @@ -47,6 +47,8 @@ // the function virtual bool decode(address pc, char* buf, int buflen, int* offset, const char* modulepath = NULL) = 0; + virtual bool decode(address pc, char* buf, int buflen, int* offset, const void* base) = 0; + // demangle a C++ symbol virtual bool demangle(const char* symbol, char* buf, int buflen) = 0; // if the decoder can decode symbols in vm @@ -82,6 +84,10 @@ return false; } + virtual bool decode(address pc, char* buf, int buflen, int* offset, const void* base) { + return false; + } + virtual bool demangle(const char* symbol, char* buf, int buflen) { return false; } @@ -95,6 +101,7 @@ class Decoder : AllStatic { public: static bool decode(address pc, char* buf, int buflen, int* offset, const char* modulepath = NULL); + static bool decode(address pc, char* buf, int buflen, int* offset, const void* base); static bool demangle(const char* symbol, char* buf, int buflen); static bool can_decode_C_frame_in_vm(); diff -r 4acebbe310e1 -r b27675afea11 src/share/vm/utilities/decoder_elf.hpp --- a/src/share/vm/utilities/decoder_elf.hpp Wed Aug 01 17:19:30 2012 -0400 +++ b/src/share/vm/utilities/decoder_elf.hpp Wed Aug 01 15:00:50 2012 -0700 @@ -43,6 +43,10 @@ bool demangle(const char* symbol, char *buf, int buflen); bool decode(address addr, char *buf, int buflen, int* offset, const char* filepath = NULL); + bool decode(address addr, char *buf, int buflen, int* offset, const void *base) { + ShouldNotReachHere(); + return false; + } private: ElfFile* get_elf_file(const char* filepath); diff -r 4acebbe310e1 -r b27675afea11 src/share/vm/utilities/hashtable.cpp --- a/src/share/vm/utilities/hashtable.cpp Wed Aug 01 17:19:30 2012 -0400 +++ b/src/share/vm/utilities/hashtable.cpp Wed Aug 01 15:00:50 2012 -0700 @@ -135,7 +135,7 @@ // walking the hashtable past these entries requires // BasicHashtableEntry::make_ptr() call. bool keep_shared = p->is_shared(); - unlink_entry(p); + this->unlink_entry(p); new_table->add_entry(index, p); if (keep_shared) { p->set_shared(); diff -r 4acebbe310e1 -r b27675afea11 src/share/vm/utilities/hashtable.hpp --- a/src/share/vm/utilities/hashtable.hpp Wed Aug 01 17:19:30 2012 -0400 +++ b/src/share/vm/utilities/hashtable.hpp Wed Aug 01 15:00:50 2012 -0700 @@ -260,7 +260,7 @@ } int index_for(Symbol* name) { - return hash_to_index(compute_hash(name)); + return this->hash_to_index(compute_hash(name)); } // Table entry management