/
githubmirror
/
panama-vector
Обзор
Документация
Войти
/
githubmirror
/
panama-vector
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/hotspot/share/gc/shared/scavengableNMethods.cpp
242 строки
7 KB
Aleksey Shipilev
8355617: Remove historical debug_only macro in favor of DEBUG_ONLY
28 апр 2025, 11:43
28 апр 2025, 11:43
db6fa59
Код
Авторство
О чём код?
/* * Copyright (c) 2019, 2025, 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 "code/codeCache.hpp" #include "code/nmethod.hpp" #include "gc/shared/scavengableNMethods.hpp" #include "gc/shared/scavengableNMethodsData.hpp" #include "runtime/mutexLocker.hpp" #include "utilities/debug.hpp" static ScavengableNMethodsData gc_data(nmethod* nm) { return ScavengableNMethodsData(nm); } nmethod* ScavengableNMethods::_head = nullptr; BoolObjectClosure* ScavengableNMethods::_is_scavengable = nullptr; void ScavengableNMethods::initialize(BoolObjectClosure* is_scavengable) { _is_scavengable = is_scavengable; } // Conditionally adds the nmethod to the list if it is // not already on the list and has a scavengeable root. void ScavengableNMethods::register_nmethod(nmethod* nm) { assert_locked_or_safepoint(CodeCache_lock); ScavengableNMethodsData data = gc_data(nm); if (data.on_list() || !has_scavengable_oops(nm)) { return; } data.set_on_list(); data.set_next(_head); _head = nm; } void ScavengableNMethods::unregister_nmethod(nmethod* nm) { // All users of this method only unregister in bulk during code unloading. ShouldNotReachHere(); } #ifndef PRODUCT class DebugScavengableOops: public OopClosure { BoolObjectClosure* _is_scavengable; nmethod* _nm; bool _ok; public: DebugScavengableOops(BoolObjectClosure* is_scavengable, nmethod* nm) : _is_scavengable(is_scavengable), _nm(nm), _ok(true) { } bool ok() { return _ok; } virtual void do_oop(oop* p) { if (*p == nullptr || !_is_scavengable->do_object_b(*p)) { return; } if (_ok) { _nm->print_nmethod(true); _ok = false; } tty->print_cr("*** scavengable oop " PTR_FORMAT " found at " PTR_FORMAT " (offset %d)", p2i(*p), p2i(p), (int)((intptr_t)p - (intptr_t)_nm)); (*p)->print(); } virtual void do_oop(narrowOop* p) { ShouldNotReachHere(); } }; #endif // PRODUCT void ScavengableNMethods::verify_nmethod(nmethod* nm) { #ifndef PRODUCT if (!gc_data(nm).on_list()) { // Actually look inside, to verify the claim that it's clean. DebugScavengableOops cl(_is_scavengable, nm); nm->oops_do(&cl); if (!cl.ok()) fatal("found an unadvertised bad scavengable oop in the code cache"); } assert(gc_data(nm).not_marked(), ""); #endif // PRODUCT } bool ScavengableNMethods::has_scavengable_oops(nmethod* nm) { struct HasScavengableOops: public OopClosure { BoolObjectClosure* _is_scavengable; bool _found; explicit HasScavengableOops(BoolObjectClosure* is_scavengable) : _is_scavengable(is_scavengable), _found(false) {} virtual void do_oop(oop* p) { if (!_found && *p != nullptr && _is_scavengable->do_object_b(*p)) { _found = true; } } virtual void do_oop(narrowOop* p) { ShouldNotReachHere(); } } cl {_is_scavengable}; nm->oops_do(&cl); return cl._found; } // Walk the list of methods which might contain oops to the java heap. void ScavengableNMethods::nmethods_do_and_prune(NMethodToOopClosure* cl) { assert_locked_or_safepoint(CodeCache_lock); DEBUG_ONLY(mark_on_list_nmethods()); nmethod* prev = nullptr; nmethod* cur = _head; while (cur != nullptr) { ScavengableNMethodsData data = gc_data(cur); DEBUG_ONLY(data.clear_marked()); assert(data.on_list(), "else shouldn't be on this list"); if (cl != nullptr) { cl->do_nmethod(cur); } nmethod* const next = data.next(); if (!has_scavengable_oops(cur)) { unlist_nmethod(cur, prev); } else { prev = cur; } cur = next; } // Check for stray marks. DEBUG_ONLY(verify_nmethods()); } void ScavengableNMethods::prune_nmethods_not_into_young() { nmethods_do_and_prune(nullptr /* No closure */); } void ScavengableNMethods::prune_unlinked_nmethods() { assert_locked_or_safepoint(CodeCache_lock); DEBUG_ONLY(mark_on_list_nmethods()); nmethod* prev = nullptr; nmethod* cur = _head; while (cur != nullptr) { ScavengableNMethodsData data = gc_data(cur); DEBUG_ONLY(data.clear_marked()); assert(data.on_list(), "else shouldn't be on this list"); nmethod* const next = data.next(); if (cur->is_unlinked()) { unlist_nmethod(cur, prev); } else { prev = cur; } cur = next; } // Check for stray marks. DEBUG_ONLY(verify_nmethods()); } // Walk the list of methods which might contain oops to the java heap. void ScavengableNMethods::nmethods_do(NMethodToOopClosure* cl) { nmethods_do_and_prune(cl); } void ScavengableNMethods::unlist_nmethod(nmethod* nm, nmethod* prev) { assert_locked_or_safepoint(CodeCache_lock); assert((prev == nullptr && _head == nm) || (prev != nullptr && gc_data(prev).next() == nm), "precondition"); ScavengableNMethodsData data = gc_data(nm); if (prev == nullptr) { _head = data.next(); } else { gc_data(prev).set_next(data.next()); } data.set_next(nullptr); data.clear_on_list(); } #ifndef PRODUCT // Temporarily mark nmethods that are claimed to be on the scavenge list. void ScavengableNMethods::mark_on_list_nmethods() { NMethodIterator iter(NMethodIterator::all); while(iter.next()) { nmethod* nm = iter.method(); ScavengableNMethodsData data = gc_data(nm); assert(data.not_marked(), "clean state"); if (data.on_list()) { data.set_marked(); } } } // Make sure that the effects of mark_on_list_nmethods is gone. void ScavengableNMethods::verify_nmethods() { NMethodIterator iter(NMethodIterator::all); while(iter.next()) { nmethod* nm = iter.method(); // Can not verify already unlinked nmethods as they are partially invalid already. if (!nm->is_unlinked()) { verify_nmethod(nm); } } } #endif //PRODUCT