# HG changeset patch # User dsamersoff # Date 1449777550 0 # Node ID 309d5a6a63e9e37124894f9af486b0b262d21c91 # Parent e115919465d02c1159d367c07ddfa03d841c07dd# Parent cd0fc9dee122bcf119ca66674408d2bfa26638db Merge diff -r cd0fc9dee122 -r 309d5a6a63e9 hotspot/agent/src/os/linux/LinuxDebuggerLocal.c --- a/hotspot/agent/src/os/linux/LinuxDebuggerLocal.c Thu Dec 10 12:05:53 2015 +0300 +++ b/hotspot/agent/src/os/linux/LinuxDebuggerLocal.c Thu Dec 10 19:59:10 2015 +0000 @@ -223,9 +223,12 @@ verifyBitness(env, (char *) &buf); CHECK_EXCEPTION; + char err_buf[200]; struct ps_prochandle* ph; - if ( (ph = Pgrab(jpid)) == NULL) { - THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the process"); + if ( (ph = Pgrab(jpid, err_buf, sizeof(err_buf))) == NULL) { + char msg[230]; + snprintf(msg, sizeof(msg), "Can't attach to the process: %s", err_buf); + THROW_NEW_DEBUGGER_EXCEPTION(msg); } (*env)->SetLongField(env, this_obj, p_ps_prochandle_ID, (jlong)(intptr_t)ph); fillThreadsAndLoadObjects(env, this_obj, ph); diff -r cd0fc9dee122 -r 309d5a6a63e9 hotspot/agent/src/os/linux/libproc.h --- a/hotspot/agent/src/os/linux/libproc.h Thu Dec 10 12:05:53 2015 +0300 +++ b/hotspot/agent/src/os/linux/libproc.h Thu Dec 10 19:59:10 2015 +0000 @@ -86,7 +86,7 @@ struct ps_prochandle; // attach to a process -struct ps_prochandle* Pgrab(pid_t pid); +struct ps_prochandle* Pgrab(pid_t pid, char* err_buf, size_t err_buf_len); // attach to a core dump struct ps_prochandle* Pgrab_core(const char* execfile, const char* corefile); diff -r cd0fc9dee122 -r 309d5a6a63e9 hotspot/agent/src/os/linux/ps_proc.c --- a/hotspot/agent/src/os/linux/ps_proc.c Thu Dec 10 12:05:53 2015 +0300 +++ b/hotspot/agent/src/os/linux/ps_proc.c Thu Dec 10 19:59:10 2015 +0000 @@ -215,9 +215,12 @@ } // attach to a process/thread specified by "pid" -static bool ptrace_attach(pid_t pid) { +static bool ptrace_attach(pid_t pid, char* err_buf, size_t err_buf_len) { if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) { - print_debug("ptrace(PTRACE_ATTACH, ..) failed for %d\n", pid); + char buf[200]; + char* msg = strerror_r(errno, buf, sizeof(buf)); + snprintf(err_buf, err_buf_len, "ptrace(PTRACE_ATTACH, ..) failed for %d: %s", pid, msg); + print_debug("%s\n", err_buf); return false; } else { return ptrace_waitpid(pid); @@ -370,16 +373,17 @@ }; // attach to the process. One and only one exposed stuff -struct ps_prochandle* Pgrab(pid_t pid) { +struct ps_prochandle* Pgrab(pid_t pid, char* err_buf, size_t err_buf_len) { struct ps_prochandle* ph = NULL; thread_info* thr = NULL; if ( (ph = (struct ps_prochandle*) calloc(1, sizeof(struct ps_prochandle))) == NULL) { - print_debug("can't allocate memory for ps_prochandle\n"); + snprintf(err_buf, err_buf_len, "can't allocate memory for ps_prochandle"); + print_debug("%s\n", err_buf); return NULL; } - if (ptrace_attach(pid) != true) { + if (ptrace_attach(pid, err_buf, err_buf_len) != true) { free(ph); return NULL; } @@ -402,7 +406,7 @@ thr = ph->threads; while (thr) { // don't attach to the main thread again - if (ph->pid != thr->lwp_id && ptrace_attach(thr->lwp_id) != true) { + if (ph->pid != thr->lwp_id && ptrace_attach(thr->lwp_id, err_buf, err_buf_len) != true) { // even if one attach fails, we get return NULL Prelease(ph); return NULL; diff -r cd0fc9dee122 -r 309d5a6a63e9 hotspot/agent/src/share/classes/sun/jvm/hotspot/HSDB.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/HSDB.java Thu Dec 10 12:05:53 2015 +0300 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/HSDB.java Thu Dec 10 19:59:10 2015 +0000 @@ -125,10 +125,14 @@ } } - // close this tool without calling System.exit - protected void closeUI() { - workerThread.shutdown(); - frame.dispose(); + private class CloseUI extends WindowAdapter { + + @Override + public void windowClosing(WindowEvent e) { + workerThread.shutdown(); + frame.dispose(); + } + } public void run() { @@ -144,7 +148,8 @@ frame = new JFrame("HSDB - HotSpot Debugger"); frame.setSize(800, 600); - frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); + frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); + frame.addWindowListener(new CloseUI()); JMenuBar menuBar = new JMenuBar(); @@ -207,7 +212,8 @@ item = createMenuItem("Exit", new ActionListener() { public void actionPerformed(ActionEvent e) { - closeUI(); + workerThread.shutdown(); + frame.dispose(); } }); item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, ActionEvent.ALT_MASK)); diff -r cd0fc9dee122 -r 309d5a6a63e9 hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java Thu Dec 10 12:05:53 2015 +0300 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java Thu Dec 10 19:59:10 2015 +0000 @@ -1921,6 +1921,15 @@ buf.link(genPCHref(addressToLong(pc)), pc.toString()); } + if (!method.isStatic() && !method.isNative()) { + OopHandle oopHandle = vf.getLocals().oopHandleAt(0); + + if (oopHandle != null) { + buf.append(", oop = "); + buf.append(oopHandle.toString()); + } + } + if (vf.isCompiledFrame()) { buf.append(" (Compiled"); } diff -r cd0fc9dee122 -r 309d5a6a63e9 hotspot/src/os/posix/vm/os_posix.cpp --- a/hotspot/src/os/posix/vm/os_posix.cpp Thu Dec 10 12:05:53 2015 +0300 +++ b/hotspot/src/os/posix/vm/os_posix.cpp Thu Dec 10 19:59:10 2015 +0000 @@ -736,12 +736,12 @@ } // Returns: -// "invalid ()" for an invalid signal number +// NULL for an invalid signal number // "SIG" for a valid but unknown signal number // signal name otherwise. const char* os::exception_name(int sig, char* buf, size_t size) { if (!os::Posix::is_valid_signal(sig)) { - jio_snprintf(buf, size, "invalid (%d)", sig); + return NULL; } const char* const name = os::Posix::get_signal_name(sig, buf, size); if (strcmp(name, "UNKNOWN") == 0) { diff -r cd0fc9dee122 -r 309d5a6a63e9 hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp Thu Dec 10 12:05:53 2015 +0300 +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp Thu Dec 10 19:59:10 2015 +0000 @@ -573,6 +573,9 @@ void register_old_region_with_cset(HeapRegion* r) { _in_cset_fast_test.set_in_old(r->hrm_index()); } + inline void register_ext_region_with_cset(HeapRegion* r) { + _in_cset_fast_test.set_ext(r->hrm_index()); + } void clear_in_cset(const HeapRegion* hr) { _in_cset_fast_test.clear(hr); } diff -r cd0fc9dee122 -r 309d5a6a63e9 hotspot/src/share/vm/gc/g1/g1InCSetState.hpp --- a/hotspot/src/share/vm/gc/g1/g1InCSetState.hpp Thu Dec 10 12:05:53 2015 +0300 +++ b/hotspot/src/share/vm/gc/g1/g1InCSetState.hpp Thu Dec 10 19:59:10 2015 +0000 @@ -53,8 +53,12 @@ // frequency of the checks. // The most common check is whether the region is in the collection set or not, // this encoding allows us to use an > 0 check. - // The other values are simply encoded in increasing generation order, which - // makes getting the next generation fast by a simple increment. + // The positive values are encoded in increasing generation order, which + // makes getting the next generation fast by a simple increment. They are also + // used to index into arrays. + // The negative values are used for objects requiring various special cases, + // for example eager reclamation of humongous objects. + Ext = -2, // Extension point Humongous = -1, // The region is humongous NotInCSet = 0, // The region is not in the collection set. Young = 1, // The region is in the collection set and a young region. @@ -76,10 +80,11 @@ bool is_humongous() const { return _value == Humongous; } bool is_young() const { return _value == Young; } bool is_old() const { return _value == Old; } + bool is_ext() const { return _value == Ext; } #ifdef ASSERT - bool is_default() const { return !is_in_cset_or_humongous(); } - bool is_valid() const { return (_value >= Humongous) && (_value < Num); } + bool is_default() const { return _value == NotInCSet; } + bool is_valid() const { return (_value >= Ext) && (_value < Num); } bool is_valid_gen() const { return (_value >= Young && _value <= Old); } #endif }; @@ -105,6 +110,12 @@ set_by_index(index, InCSetState::Humongous); } + void set_ext(uintptr_t index) { + assert(get_by_index(index).is_default(), + "State at index " INTPTR_FORMAT " should be default but is " CSETSTATE_FORMAT, index, get_by_index(index).value()); + set_by_index(index, InCSetState::Ext); + } + void clear_humongous(uintptr_t index) { set_by_index(index, InCSetState::NotInCSet); } diff -r cd0fc9dee122 -r 309d5a6a63e9 hotspot/src/share/vm/gc/g1/g1OopClosures.hpp --- a/hotspot/src/share/vm/gc/g1/g1OopClosures.hpp Thu Dec 10 12:05:53 2015 +0300 +++ b/hotspot/src/share/vm/gc/g1/g1OopClosures.hpp Thu Dec 10 19:59:10 2015 +0000 @@ -121,7 +121,7 @@ G1MarkPromotedFromRoot }; -template +template class G1ParCopyClosure : public G1ParCopyHelper { public: G1ParCopyClosure(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) : diff -r cd0fc9dee122 -r 309d5a6a63e9 hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp --- a/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp Thu Dec 10 12:05:53 2015 +0300 +++ b/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp Thu Dec 10 19:59:10 2015 +0000 @@ -90,6 +90,8 @@ } else { if (state.is_humongous()) { _g1->set_humongous_is_live(obj); + } else if (state.is_ext()) { + _par_scan_state->do_oop_ext(p); } _par_scan_state->update_rs(_from, p, obj); } @@ -102,12 +104,15 @@ if (!oopDesc::is_null(heap_oop)) { oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); - if (_g1->is_in_cset_or_humongous(obj)) { + const InCSetState state = _g1->in_cset_state(obj); + if (state.is_in_cset_or_humongous()) { Prefetch::write(obj->mark_addr(), 0); Prefetch::read(obj->mark_addr(), (HeapWordSize*2)); // Place on the references queue _par_scan_state->push_on_queue(p); + } else if (state.is_ext()) { + _par_scan_state->do_oop_ext(p); } else { assert(!_g1->obj_in_cs(obj), "checking"); } @@ -249,9 +254,9 @@ _cm->grayRoot(to_obj, (size_t) from_obj->size(), _worker_id); } -template +template template -void G1ParCopyClosure::do_oop_nv(T* p) { +void G1ParCopyClosure::do_oop_nv(T* p) { T heap_oop = oopDesc::load_heap_oop(p); if (oopDesc::is_null(heap_oop)) { @@ -286,6 +291,10 @@ if (state.is_humongous()) { _g1->set_humongous_is_live(obj); } + + if (use_ext && state.is_ext()) { + _par_scan_state->do_oop_ext(p); + } // The object is not in collection set. If we're a root scanning // closure during an initial mark pause then attempt to mark the object. if (do_mark_object == G1MarkFromRoot) { diff -r cd0fc9dee122 -r 309d5a6a63e9 hotspot/src/share/vm/gc/g1/g1ParScanThreadState.hpp --- a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.hpp Thu Dec 10 12:05:53 2015 +0300 +++ b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.hpp Thu Dec 10 19:59:10 2015 +0000 @@ -96,6 +96,7 @@ bool verify_task(StarTask ref) const; #endif // ASSERT + template void do_oop_ext(T* ref); template void push_on_queue(T* ref); template void update_rs(HeapRegion* from, T* p, oop o) { diff -r cd0fc9dee122 -r 309d5a6a63e9 hotspot/src/share/vm/gc/g1/g1ParScanThreadState.inline.hpp --- a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.inline.hpp Thu Dec 10 12:05:53 2015 +0300 +++ b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.inline.hpp Thu Dec 10 19:59:10 2015 +0000 @@ -50,8 +50,8 @@ } else if (in_cset_state.is_humongous()) { _g1h->set_humongous_is_live(obj); } else { - assert(!in_cset_state.is_in_cset_or_humongous(), - "In_cset_state must be NotInCSet here, but is " CSETSTATE_FORMAT, in_cset_state.value()); + assert(in_cset_state.is_default() || in_cset_state.is_ext(), + "In_cset_state must be NotInCSet or Ext here, but is " CSETSTATE_FORMAT, in_cset_state.value()); } assert(obj != NULL, "Must be"); diff -r cd0fc9dee122 -r 309d5a6a63e9 hotspot/src/share/vm/gc/g1/g1ParScanThreadState_ext.cpp --- a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState_ext.cpp Thu Dec 10 12:05:53 2015 +0300 +++ b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState_ext.cpp Thu Dec 10 19:59:10 2015 +0000 @@ -29,3 +29,10 @@ G1ParScanThreadState* G1ParScanThreadStateSet::new_par_scan_state(uint worker_id, size_t young_cset_length) { return new G1ParScanThreadState(_g1h, worker_id, young_cset_length); } + +template +void G1ParScanThreadState::do_oop_ext(T* ref) { +} + +template void G1ParScanThreadState::do_oop_ext(oop* ref); +template void G1ParScanThreadState::do_oop_ext(narrowOop* ref); diff -r cd0fc9dee122 -r 309d5a6a63e9 hotspot/src/share/vm/gc/g1/g1SharedClosures.hpp --- a/hotspot/src/share/vm/gc/g1/g1SharedClosures.hpp Thu Dec 10 12:05:53 2015 +0300 +++ b/hotspot/src/share/vm/gc/g1/g1SharedClosures.hpp Thu Dec 10 19:59:10 2015 +0000 @@ -31,15 +31,15 @@ class G1ParScanThreadState; // Simple holder object for a complete set of closures used by the G1 evacuation code. -template +template class G1SharedClosures VALUE_OBJ_CLASS_SPEC { public: - G1ParCopyClosure _oops; - G1ParCopyClosure _oop_in_klass; - G1KlassScanClosure _klass_in_cld_closure; - CLDToKlassAndOopClosure _clds; - G1CodeBlobClosure _codeblobs; - BufferingOopClosure _buffered_oops; + G1ParCopyClosure _oops; + G1ParCopyClosure _oop_in_klass; + G1KlassScanClosure _klass_in_cld_closure; + CLDToKlassAndOopClosure _clds; + G1CodeBlobClosure _codeblobs; + BufferingOopClosure _buffered_oops; G1SharedClosures(G1CollectedHeap* g1h, G1ParScanThreadState* pss, bool process_only_dirty_klasses, bool must_claim_cld) : _oops(g1h, pss), diff -r cd0fc9dee122 -r 309d5a6a63e9 hotspot/src/share/vm/runtime/arguments.cpp --- a/hotspot/src/share/vm/runtime/arguments.cpp Thu Dec 10 12:05:53 2015 +0300 +++ b/hotspot/src/share/vm/runtime/arguments.cpp Thu Dec 10 19:59:10 2015 +0000 @@ -1308,18 +1308,20 @@ PropertyList_unique_add(&_system_properties, key, value, true); } else { if (strcmp(key, "sun.java.command") == 0) { - if (_java_command != NULL) { - os::free(_java_command); + char *old_java_command = _java_command; + _java_command = os::strdup_check_oom(value, mtInternal); + if (old_java_command != NULL) { + os::free(old_java_command); } - _java_command = os::strdup_check_oom(value, mtInternal); } else if (strcmp(key, "java.vendor.url.bug") == 0) { - if (_java_vendor_url_bug != DEFAULT_VENDOR_URL_BUG) { - assert(_java_vendor_url_bug != NULL, "_java_vendor_url_bug is NULL"); - os::free((void *)_java_vendor_url_bug); - } + const char* old_java_vendor_url_bug = _java_vendor_url_bug; // save it in _java_vendor_url_bug, so JVM fatal error handler can access // its value without going through the property list or making a Java call. _java_vendor_url_bug = os::strdup_check_oom(value, mtInternal); + if (old_java_vendor_url_bug != DEFAULT_VENDOR_URL_BUG) { + assert(old_java_vendor_url_bug != NULL, "_java_vendor_url_bug is NULL"); + os::free((void *)old_java_vendor_url_bug); + } } // Create new property and add at the end of the list