/* * Copyright (c) 2015, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. * */ #include "precompiled.hpp" #include "classfile/backtrace.hpp" #include "classfile/javaClasses.hpp" #include "runtime/atomic.hpp" #include "runtime/jniHandles.hpp" void Backtrace::oops_do(OopClosure* f) { f->do_oop(&_throwable); } // List of backtraces to mark Method pointers for RedefineClasses. Backtrace* BacktraceList::_backtraces_head = NULL; volatile int BacktraceList::_bt_count = 0; void BacktraceList::add(oop throwable) { Backtrace* bt = new Backtrace(throwable); Backtrace* next = _backtraces_head; do { bt->set_next(next); Backtrace* exchanged = (Backtrace*)Atomic::cmpxchg_ptr(bt, &_backtraces_head, next); if (exchanged == next) { // added the backtrace to the list. Atomic::inc(&_bt_count); return; } next = exchanged; } while (true); } void BacktraceList::oops_do(OopClosure* f) { Backtrace* bt = _backtraces_head; while (bt != NULL) { bt->oops_do(f); bt = bt->next(); } } void BacktraceList::mark_on_stack() { Backtrace* bt = _backtraces_head; while (bt != NULL) { assert(bt->throwable() != NULL, "shouldn't have null throwable"); java_lang_Throwable::mark_on_stack(bt->throwable()); bt = bt->next(); } } void BacktraceList::unlink(BoolObjectClosure* is_alive) { assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint"); Backtrace* bt = _backtraces_head; Backtrace* prev = NULL; while (bt != NULL) { if (!is_alive->do_object_b(bt->throwable())) { // delete this backtrace object Backtrace* next = bt->next(); // Delete bt object delete bt; // Remove from throwable list. bt = next; if (prev != NULL) { prev->set_next(bt); } else { _backtraces_head = bt; } Atomic::dec(&_bt_count); } else { prev = bt; bt = bt->next(); } } }