diff src/share/vm/runtime/unhandledOops.cpp @ 0:a61af66fc99e jdk7-b24

Initial load
author duke
date Sat, 01 Dec 2007 00:00:00 +0000
parents
children c18cbe5936b8
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/runtime/unhandledOops.cpp	Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc.  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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+# include "incls/_precompiled.incl"
+# include "incls/_unhandledOops.cpp.incl"
+
+#ifdef CHECK_UNHANDLED_OOPS
+const int free_list_size = 256;
+
+
+UnhandledOops::UnhandledOops(Thread* thread) {
+  _thread = thread;
+  _oop_list = new (ResourceObj::C_HEAP)
+                    GrowableArray<UnhandledOopEntry>(free_list_size, true);
+  _level = 0;
+}
+
+UnhandledOops::~UnhandledOops() {
+  delete _oop_list;
+}
+
+
+void UnhandledOops::dump_oops(UnhandledOops *list) {
+  for (int k = 0; k < list->_oop_list->length(); k++) {
+    UnhandledOopEntry entry = list->_oop_list->at(k);
+    tty->print(" " INTPTR_FORMAT, entry._oop_ptr);
+  }
+  tty->cr();
+}
+
+// For debugging unhandled oop detector _in the debugger_
+// You don't want to turn it on in compiled code here.
+static bool unhandled_oop_print=0;
+
+void UnhandledOops::register_unhandled_oop(oop* op, address pc) {
+  if (!_thread->is_in_stack((address)op))
+    return;
+
+  _level ++;
+  if (unhandled_oop_print) {
+    for (int i=0; i<_level; i++) tty->print(" ");
+    tty->print_cr("r " INTPTR_FORMAT, op);
+  }
+  UnhandledOopEntry entry(op, pc);
+  _oop_list->push(entry);
+}
+
+
+bool match_oop_entry(void *op, UnhandledOopEntry e) {
+  return (e.oop_ptr() == op);
+}
+
+// Mark unhandled oop as okay for GC - the containing struct has an oops_do and
+// for some reason the oop has to be on the stack.
+// May not be called for the current thread, as in the case of
+// VM_GetOrSetLocal in jvmti.
+void UnhandledOops::allow_unhandled_oop(oop* op) {
+  assert (CheckUnhandledOops, "should only be called with checking option");
+
+  int i = _oop_list->find_at_end(op, match_oop_entry);
+  assert(i!=-1, "safe for gc oop not in unhandled_oop_list");
+
+  UnhandledOopEntry entry = _oop_list->at(i);
+  assert(!entry._ok_for_gc, "duplicate entry");
+  entry._ok_for_gc = true;
+  _oop_list->at_put(i, entry);
+}
+
+
+// Called by the oop destructor to remove unhandled oop from the thread's
+// oop list.  All oops given are assumed to be on the list.  If not,
+// there's a bug in the unhandled oop detector.
+void UnhandledOops::unregister_unhandled_oop(oop* op) {
+  if (!_thread->is_in_stack((address)op)) return;
+
+  _level --;
+  if (unhandled_oop_print) {
+    for (int i=0; i<_level; i++) tty->print(" ");
+    tty->print_cr("u "INTPTR_FORMAT, op);
+  }
+
+  int i = _oop_list->find_at_end(op, match_oop_entry);
+  assert(i!=-1, "oop not in unhandled_oop_list");
+  _oop_list->remove_at(i);
+}
+
+void UnhandledOops::clear_unhandled_oops() {
+  assert (CheckUnhandledOops, "should only be called with checking option");
+  if (_thread->is_gc_locked_out()) {
+    return;
+  }
+  for (int k = 0; k < _oop_list->length(); k++) {
+    UnhandledOopEntry entry = _oop_list->at(k);
+    // If an entry is on the unhandled oop list but isn't on the stack
+    // anymore, it must not have gotten unregistered properly and it's a bug
+    // in the unhandled oop generator.
+    if(!_thread->is_in_stack((address)entry._oop_ptr)) {
+      tty->print_cr("oop_ptr is " INTPTR_FORMAT, (address)entry._oop_ptr);
+      tty->print_cr("thread is " INTPTR_FORMAT " from pc " INTPTR_FORMAT,
+                     (address)_thread, (address)entry._pc);
+      assert(false, "heap is corrupted by the unhandled oop detector");
+    }
+    // Set unhandled oops to a pattern that will crash distinctively
+    if (!entry._ok_for_gc) *(intptr_t*)(entry._oop_ptr) = BAD_OOP_ADDR;
+  }
+}
+#endif // CHECK_UNHANDLED_OOPS