Merge
authordsamersoff
Thu, 10 Dec 2015 19:59:10 +0000
changeset 35054 309d5a6a63e9
parent 35052 e115919465d0 (diff)
parent 35053 cd0fc9dee122 (current diff)
child 35057 71b977f05ea6
Merge
--- 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);
--- 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);
--- 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;
--- 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));
--- 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");
          }
--- 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 (<num>)" for an invalid signal number
+// NULL for an invalid signal number
 // "SIG<num>" 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) {
--- 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);
   }
--- 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);
   }
--- 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 <G1Barrier barrier, G1Mark do_mark_object>
+template <G1Barrier barrier, G1Mark do_mark_object, bool use_ext>
 class G1ParCopyClosure : public G1ParCopyHelper {
 public:
   G1ParCopyClosure(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) :
--- 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 <G1Barrier barrier, G1Mark do_mark_object>
+template <G1Barrier barrier, G1Mark do_mark_object, bool use_ext>
 template <class T>
-void G1ParCopyClosure<barrier, do_mark_object>::do_oop_nv(T* p) {
+void G1ParCopyClosure<barrier, do_mark_object, use_ext>::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) {
--- 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 <class T> void do_oop_ext(T* ref);
   template <class T> void push_on_queue(T* ref);
 
   template <class T> void update_rs(HeapRegion* from, T* p, oop o) {
--- 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");
--- 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 <typename T>
+void G1ParScanThreadState::do_oop_ext(T* ref) {
+}
+
+template void G1ParScanThreadState::do_oop_ext<oop>(oop* ref);
+template void G1ParScanThreadState::do_oop_ext<narrowOop>(narrowOop* ref);
--- 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 <G1Mark Mark>
+template <G1Mark Mark, bool use_ext = false>
 class G1SharedClosures VALUE_OBJ_CLASS_SPEC {
 public:
-  G1ParCopyClosure<G1BarrierNone,  Mark> _oops;
-  G1ParCopyClosure<G1BarrierKlass, Mark> _oop_in_klass;
-  G1KlassScanClosure                     _klass_in_cld_closure;
-  CLDToKlassAndOopClosure                _clds;
-  G1CodeBlobClosure                      _codeblobs;
-  BufferingOopClosure                    _buffered_oops;
+  G1ParCopyClosure<G1BarrierNone,  Mark, use_ext> _oops;
+  G1ParCopyClosure<G1BarrierKlass, Mark, use_ext> _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),
--- 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