unhandledOops.cpp revision 3465:d2a62e0f25eb
1/*
2 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25#include "precompiled.hpp"
26#include "gc_interface/collectedHeap.hpp"
27#include "memory/gcLocker.inline.hpp"
28#include "memory/universe.hpp"
29#include "oops/oop.inline.hpp"
30#include "runtime/thread.hpp"
31#include "runtime/unhandledOops.hpp"
32#include "utilities/globalDefinitions.hpp"
33
34#ifdef CHECK_UNHANDLED_OOPS
35const int free_list_size = 256;
36
37
38UnhandledOops::UnhandledOops(Thread* thread) {
39  _thread = thread;
40  _oop_list = new (ResourceObj::C_HEAP, mtInternal)
41                    GrowableArray<UnhandledOopEntry>(free_list_size, true);
42  _level = 0;
43}
44
45UnhandledOops::~UnhandledOops() {
46  delete _oop_list;
47}
48
49
50void UnhandledOops::dump_oops(UnhandledOops *list) {
51  for (int k = 0; k < list->_oop_list->length(); k++) {
52    UnhandledOopEntry entry = list->_oop_list->at(k);
53    tty->print(" " INTPTR_FORMAT, entry._oop_ptr);
54  }
55  tty->cr();
56}
57
58// For debugging unhandled oop detector _in the debugger_
59// You don't want to turn it on in compiled code here.
60static bool unhandled_oop_print=0;
61
62void UnhandledOops::register_unhandled_oop(oop* op, address pc) {
63  if (!_thread->is_in_stack((address)op))
64    return;
65
66  _level ++;
67  if (unhandled_oop_print) {
68    for (int i=0; i<_level; i++) tty->print(" ");
69    tty->print_cr("r " INTPTR_FORMAT, op);
70  }
71  UnhandledOopEntry entry(op, pc);
72  _oop_list->push(entry);
73}
74
75
76bool match_oop_entry(void *op, UnhandledOopEntry e) {
77  return (e.oop_ptr() == op);
78}
79
80// Mark unhandled oop as okay for GC - the containing struct has an oops_do and
81// for some reason the oop has to be on the stack.
82// May not be called for the current thread, as in the case of
83// VM_GetOrSetLocal in jvmti.
84void UnhandledOops::allow_unhandled_oop(oop* op) {
85  assert (CheckUnhandledOops, "should only be called with checking option");
86
87  int i = _oop_list->find_at_end(op, match_oop_entry);
88  assert(i!=-1, "safe for gc oop not in unhandled_oop_list");
89
90  UnhandledOopEntry entry = _oop_list->at(i);
91  assert(!entry._ok_for_gc, "duplicate entry");
92  entry._ok_for_gc = true;
93  _oop_list->at_put(i, entry);
94}
95
96
97// Called by the oop destructor to remove unhandled oop from the thread's
98// oop list.  All oops given are assumed to be on the list.  If not,
99// there's a bug in the unhandled oop detector.
100void UnhandledOops::unregister_unhandled_oop(oop* op) {
101  if (!_thread->is_in_stack((address)op)) return;
102
103  _level --;
104  if (unhandled_oop_print) {
105    for (int i=0; i<_level; i++) tty->print(" ");
106    tty->print_cr("u "INTPTR_FORMAT, op);
107  }
108
109  int i = _oop_list->find_at_end(op, match_oop_entry);
110  assert(i!=-1, "oop not in unhandled_oop_list");
111  _oop_list->remove_at(i);
112}
113
114void UnhandledOops::clear_unhandled_oops() {
115  assert (CheckUnhandledOops, "should only be called with checking option");
116  if (_thread->is_gc_locked_out()) {
117    return;
118  }
119  for (int k = 0; k < _oop_list->length(); k++) {
120    UnhandledOopEntry entry = _oop_list->at(k);
121    // If an entry is on the unhandled oop list but isn't on the stack
122    // anymore, it must not have gotten unregistered properly and it's a bug
123    // in the unhandled oop generator.
124    if(!_thread->is_in_stack((address)entry._oop_ptr)) {
125      tty->print_cr("oop_ptr is " INTPTR_FORMAT, (address)entry._oop_ptr);
126      tty->print_cr("thread is " INTPTR_FORMAT " from pc " INTPTR_FORMAT,
127                     (address)_thread, (address)entry._pc);
128      assert(false, "heap is corrupted by the unhandled oop detector");
129    }
130    // Set unhandled oops to a pattern that will crash distinctively
131    if (!entry._ok_for_gc) *(intptr_t*)(entry._oop_ptr) = BAD_OOP_ADDR;
132  }
133}
134#endif // CHECK_UNHANDLED_OOPS
135