unhandledOops.cpp revision 1472:c18cbe5936b8
1/*
2 * Copyright (c) 2005, 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 "incls/_precompiled.incl"
26# include "incls/_unhandledOops.cpp.incl"
27
28#ifdef CHECK_UNHANDLED_OOPS
29const int free_list_size = 256;
30
31
32UnhandledOops::UnhandledOops(Thread* thread) {
33  _thread = thread;
34  _oop_list = new (ResourceObj::C_HEAP)
35                    GrowableArray<UnhandledOopEntry>(free_list_size, true);
36  _level = 0;
37}
38
39UnhandledOops::~UnhandledOops() {
40  delete _oop_list;
41}
42
43
44void UnhandledOops::dump_oops(UnhandledOops *list) {
45  for (int k = 0; k < list->_oop_list->length(); k++) {
46    UnhandledOopEntry entry = list->_oop_list->at(k);
47    tty->print(" " INTPTR_FORMAT, entry._oop_ptr);
48  }
49  tty->cr();
50}
51
52// For debugging unhandled oop detector _in the debugger_
53// You don't want to turn it on in compiled code here.
54static bool unhandled_oop_print=0;
55
56void UnhandledOops::register_unhandled_oop(oop* op, address pc) {
57  if (!_thread->is_in_stack((address)op))
58    return;
59
60  _level ++;
61  if (unhandled_oop_print) {
62    for (int i=0; i<_level; i++) tty->print(" ");
63    tty->print_cr("r " INTPTR_FORMAT, op);
64  }
65  UnhandledOopEntry entry(op, pc);
66  _oop_list->push(entry);
67}
68
69
70bool match_oop_entry(void *op, UnhandledOopEntry e) {
71  return (e.oop_ptr() == op);
72}
73
74// Mark unhandled oop as okay for GC - the containing struct has an oops_do and
75// for some reason the oop has to be on the stack.
76// May not be called for the current thread, as in the case of
77// VM_GetOrSetLocal in jvmti.
78void UnhandledOops::allow_unhandled_oop(oop* op) {
79  assert (CheckUnhandledOops, "should only be called with checking option");
80
81  int i = _oop_list->find_at_end(op, match_oop_entry);
82  assert(i!=-1, "safe for gc oop not in unhandled_oop_list");
83
84  UnhandledOopEntry entry = _oop_list->at(i);
85  assert(!entry._ok_for_gc, "duplicate entry");
86  entry._ok_for_gc = true;
87  _oop_list->at_put(i, entry);
88}
89
90
91// Called by the oop destructor to remove unhandled oop from the thread's
92// oop list.  All oops given are assumed to be on the list.  If not,
93// there's a bug in the unhandled oop detector.
94void UnhandledOops::unregister_unhandled_oop(oop* op) {
95  if (!_thread->is_in_stack((address)op)) return;
96
97  _level --;
98  if (unhandled_oop_print) {
99    for (int i=0; i<_level; i++) tty->print(" ");
100    tty->print_cr("u "INTPTR_FORMAT, op);
101  }
102
103  int i = _oop_list->find_at_end(op, match_oop_entry);
104  assert(i!=-1, "oop not in unhandled_oop_list");
105  _oop_list->remove_at(i);
106}
107
108void UnhandledOops::clear_unhandled_oops() {
109  assert (CheckUnhandledOops, "should only be called with checking option");
110  if (_thread->is_gc_locked_out()) {
111    return;
112  }
113  for (int k = 0; k < _oop_list->length(); k++) {
114    UnhandledOopEntry entry = _oop_list->at(k);
115    // If an entry is on the unhandled oop list but isn't on the stack
116    // anymore, it must not have gotten unregistered properly and it's a bug
117    // in the unhandled oop generator.
118    if(!_thread->is_in_stack((address)entry._oop_ptr)) {
119      tty->print_cr("oop_ptr is " INTPTR_FORMAT, (address)entry._oop_ptr);
120      tty->print_cr("thread is " INTPTR_FORMAT " from pc " INTPTR_FORMAT,
121                     (address)_thread, (address)entry._pc);
122      assert(false, "heap is corrupted by the unhandled oop detector");
123    }
124    // Set unhandled oops to a pattern that will crash distinctively
125    if (!entry._ok_for_gc) *(intptr_t*)(entry._oop_ptr) = BAD_OOP_ADDR;
126  }
127}
128#endif // CHECK_UNHANDLED_OOPS
129