aoqi@0: /* aoqi@0: * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: * aoqi@0: */ aoqi@0: aoqi@0: #ifndef SHARE_VM_RUNTIME_UNHANDLEDOOPS_HPP aoqi@0: #define SHARE_VM_RUNTIME_UNHANDLEDOOPS_HPP aoqi@0: aoqi@0: #ifdef CHECK_UNHANDLED_OOPS aoqi@0: aoqi@0: // Detect unhanded oops in VM code aoqi@0: aoqi@0: // The design is that when an oop is declared on the stack as a local aoqi@0: // variable, the oop is actually a C++ struct with constructor and aoqi@0: // destructor. The constructor adds the oop address on a list aoqi@0: // off each thread and the destructor removes the oop. At a potential aoqi@0: // safepoint, the stack addresses of the local variable oops are trashed aoqi@0: // with a recognizeable value. If the local variable is used again, it aoqi@0: // will segfault, indicating an unsafe use of that oop. aoqi@0: // eg: aoqi@0: // oop o; //register &o on list aoqi@0: // funct(); // if potential safepoint - causes clear_naked_oops() aoqi@0: // // which trashes o above. aoqi@0: // o->do_something(); // Crashes because o is unsafe. aoqi@0: // aoqi@0: // This code implements the details of the unhandled oop list on the thread. aoqi@0: // aoqi@0: aoqi@0: class oop; aoqi@0: class Thread; aoqi@0: aoqi@0: class UnhandledOopEntry : public CHeapObj { aoqi@0: friend class UnhandledOops; aoqi@0: private: aoqi@0: oop* _oop_ptr; aoqi@0: bool _ok_for_gc; aoqi@0: address _pc; aoqi@0: public: aoqi@0: oop* oop_ptr() { return _oop_ptr; } aoqi@0: UnhandledOopEntry() : _oop_ptr(NULL), _ok_for_gc(false), _pc(NULL) {} aoqi@0: UnhandledOopEntry(oop* op, address pc) : aoqi@0: _oop_ptr(op), _ok_for_gc(false), _pc(pc) {} aoqi@0: }; aoqi@0: aoqi@0: aoqi@0: class UnhandledOops : public CHeapObj { aoqi@0: friend class Thread; aoqi@0: private: aoqi@0: Thread* _thread; aoqi@0: int _level; aoqi@0: GrowableArray *_oop_list; aoqi@0: void allow_unhandled_oop(oop* op); aoqi@0: void clear_unhandled_oops(); aoqi@0: UnhandledOops(Thread* thread); aoqi@0: ~UnhandledOops(); aoqi@0: aoqi@0: public: aoqi@0: static void dump_oops(UnhandledOops* list); aoqi@0: void register_unhandled_oop(oop* op, address pc); aoqi@0: void unregister_unhandled_oop(oop* op); aoqi@0: }; aoqi@0: aoqi@0: #ifdef _LP64 aoqi@0: const intptr_t BAD_OOP_ADDR = 0xfffffffffffffff1; aoqi@0: #else aoqi@0: const intptr_t BAD_OOP_ADDR = 0xfffffff1; aoqi@0: #endif // _LP64 aoqi@0: #endif // CHECK_UNHANDLED_OOPS aoqi@0: aoqi@0: #endif // SHARE_VM_RUNTIME_UNHANDLEDOOPS_HPP