/
githubmirror
/
panama-vector
Обзор
Документация
Войти
/
githubmirror
/
panama-vector
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/hotspot/share/cds/aotArtifactFinder.cpp
344 строки
12 KB
Ioi Lam
8381710: Avoid using lambdas in ModuleBootstrap in AOT training mode
19 май 2026, 22:20
19 май 2026, 22:20
a37b02b
Код
Авторство
О чём код?
/* * Copyright (c) 2025, 2026, 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 "cds/aotArtifactFinder.hpp" #include "cds/aotClassInitializer.hpp" #include "cds/aotClassLinker.hpp" #include "cds/aotLogging.hpp" #include "cds/aotReferenceObjSupport.hpp" #include "cds/dumpTimeClassInfo.inline.hpp" #include "cds/heapShared.hpp" #include "cds/lambdaProxyClassDictionary.hpp" #include "cds/regeneratedClasses.hpp" #include "classfile/systemDictionaryShared.hpp" #include "classfile/vmClasses.hpp" #include "logging/log.hpp" #include "memory/metaspaceClosure.hpp" #include "oops/instanceKlass.hpp" #include "oops/objArrayKlass.hpp" #include "oops/trainingData.hpp" #include "utilities/hashTable.hpp" // All the classes that should be included in the AOT cache (in at least the "allocated" state) static GrowableArrayCHeap<Klass*, mtClassShared>* _all_cached_classes = nullptr; // This is a stack that tracks all the AOT-inited classes that are waiting to be passed // to HeapShared::copy_and_rescan_aot_inited_mirror(). static GrowableArrayCHeap<InstanceKlass*, mtClassShared>* _pending_aot_inited_classes = nullptr; static const int TABLE_SIZE = 15889; // prime number using ClassesTable = HashTable<Klass*, bool, TABLE_SIZE, AnyObj::C_HEAP, mtClassShared>; static ClassesTable* _seen_classes; // all classes that have been seen by AOTArtifactFinder static ClassesTable* _aot_inited_classes; // all classes that need to be AOT-initialized. void AOTArtifactFinder::initialize() { _all_cached_classes = new GrowableArrayCHeap<Klass*, mtClassShared>(); _pending_aot_inited_classes = new GrowableArrayCHeap<InstanceKlass*, mtClassShared>(); _seen_classes = new (mtClass)ClassesTable(); _aot_inited_classes = new (mtClass)ClassesTable(); } void AOTArtifactFinder::dispose() { delete _all_cached_classes; delete _seen_classes; delete _aot_inited_classes; delete _pending_aot_inited_classes; _all_cached_classes = nullptr; _seen_classes = nullptr; _aot_inited_classes = nullptr; _pending_aot_inited_classes = nullptr; } // Find all Klasses and oops that should be included in the AOT cache. See aotArtifactFinder.hpp void AOTArtifactFinder::find_artifacts() { // Some classes might have been marked as excluded as a side effect of running // AOTConstantPoolResolver. Make sure we check all the remaining ones. // // Note, if a class is not excluded, it does NOT mean it will be automatically included // into the AOT cache -- that will be decided by the code below. SystemDictionaryShared::finish_exclusion_checks(); AOTReferenceObjSupport::init_keep_alive_objs_table(); start_scanning_for_oops(); // Add the primitive array classes for (int i = T_BOOLEAN; i < T_VOID+1; i++) { BasicType bt = (BasicType)i; if (is_java_primitive(bt)) { add_cached_type_array_class(Universe::typeArrayKlass(bt)); } } #if INCLUDE_CDS_JAVA_HEAP // Add the mirrors that aren't associated with a Klass // - primitive mirrors (E.g., "int.class" in Java code) // - mirror of fillerArrayKlass if (CDSConfig::is_dumping_heap()) { for (int i = T_BOOLEAN; i < T_VOID+1; i++) { BasicType bt = (BasicType)i; if (!is_reference_type(bt)) { oop orig_mirror = Universe::java_mirror(bt); oop scratch_mirror = HeapShared::scratch_java_mirror(bt); HeapShared::scan_java_mirror(orig_mirror); log_trace(aot, heap, mirror)( "Archived %s mirror object from " PTR_FORMAT, type2name(bt), p2i(scratch_mirror)); Universe::set_archived_basic_type_mirror_index(bt, HeapShared::append_root(scratch_mirror)); } } // Universe::fillerArrayKlass() isn't in the class hierarchy, so handle it specially. HeapShared::scan_java_mirror(Universe::fillerArrayKlass()->java_mirror()); } #endif // Add all the InstanceKlasses (and their array classes) that are always included. SystemDictionaryShared::dumptime_table()->iterate_all_live_classes([&] (InstanceKlass* ik, DumpTimeClassInfo& info) { bool skip = info.is_excluded(); if (!(ik->is_initialized() && ik->has_aot_safe_initializer())) { if (info.is_aot_tooling_class()) { // This class is loading only by AOT tooling (not as part of the app's training run). // Skip this class for now, but it might be added later if // - One of its subtypes is included // - One of its instances is found by HeapShared. skip = true; } } if (!skip) { bool add = false; if (!ik->is_hidden()) { // All non-hidden classes are always included into the AOT cache add = true; } else { if (CDSConfig::is_dumping_lambdas_in_legacy_mode()) { // Legacy support of lambda proxies -- these are always included into the AOT cache if (LambdaProxyClassDictionary::is_registered_lambda_proxy_class(ik)) { add = true; } } else { assert(!LambdaProxyClassDictionary::is_registered_lambda_proxy_class(ik), "registered lambda proxies are only for legacy lambda proxy support"); } } if (add) { add_cached_instance_class(ik); if (AOTClassInitializer::can_archive_initialized_mirror(ik)) { add_aot_inited_class(ik); } } } }); #if INCLUDE_CDS_JAVA_HEAP // Keep scanning until we discover no more class that need to be AOT-initialized. if (CDSConfig::is_dumping_aot_linked_classes()) { while (_pending_aot_inited_classes->length() > 0) { InstanceKlass* ik = _pending_aot_inited_classes->pop(); HeapShared::copy_and_rescan_aot_inited_mirror(ik); } } #endif // Exclude all the (hidden) classes that have not been discovered by the code above. SystemDictionaryShared::dumptime_table()->iterate_all_live_classes([&] (InstanceKlass* k, DumpTimeClassInfo& info) { if (!info.is_excluded() && _seen_classes->get(k) == nullptr) { info.set_excluded(); info.set_has_checked_exclusion(); if (aot_log_is_enabled(Debug, aot)) { ResourceMark rm; aot_log_debug(aot)("Skipping %s: %s class", k->name()->as_C_string(), k->is_hidden() ? "Unreferenced hidden" : "AOT tooling"); } } }); end_scanning_for_oops(); TrainingData::cleanup_training_data(); check_critical_classes(); } void AOTArtifactFinder::start_scanning_for_oops() { #if INCLUDE_CDS_JAVA_HEAP if (CDSConfig::is_dumping_heap()) { HeapShared::start_scanning_for_oops(); } #endif } void AOTArtifactFinder::end_scanning_for_oops() { #if INCLUDE_CDS_JAVA_HEAP if (CDSConfig::is_dumping_heap()) { HeapShared::end_scanning_for_oops(); } #endif } void AOTArtifactFinder::add_aot_inited_class(InstanceKlass* ik) { if (CDSConfig::is_dumping_aot_linked_classes()) { if (RegeneratedClasses::is_regenerated_object(ik)) { precond(RegeneratedClasses::get_original_object(ik)->is_initialized()); } else { precond(ik->is_initialized()); } add_cached_instance_class(ik); bool created; _aot_inited_classes->put_if_absent(ik, &created); if (created) { _pending_aot_inited_classes->push(ik); InstanceKlass* s = ik->super(); if (s != nullptr) { add_aot_inited_class(s); } Array<InstanceKlass*>* interfaces = ik->local_interfaces(); int len = interfaces->length(); for (int i = 0; i < len; i++) { InstanceKlass* intf = interfaces->at(i); if (intf->is_initialized()) { add_aot_inited_class(intf); } } } } } void AOTArtifactFinder::append_to_all_cached_classes(Klass* k) { precond(!SystemDictionaryShared::should_be_excluded(k)); _all_cached_classes->append(k); } void AOTArtifactFinder::add_cached_instance_class(InstanceKlass* ik) { if (CDSConfig::is_dumping_dynamic_archive() && ik->in_aot_cache()) { // This class is already included in the base archive. No need to cache // it again in the dynamic archive. return; } bool created; _seen_classes->put_if_absent(ik, &created); if (created) { check_critical_class(ik); append_to_all_cached_classes(ik); // All super types must be added. InstanceKlass* s = ik->super(); if (s != nullptr) { add_cached_instance_class(s); } Array<InstanceKlass*>* interfaces = ik->local_interfaces(); int len = interfaces->length(); for (int i = 0; i < len; i++) { InstanceKlass* intf = interfaces->at(i); add_cached_instance_class(intf); } InstanceKlass* nest_host = ik->nest_host_or_null(); if (nest_host != nullptr) { add_cached_instance_class(nest_host); } if (CDSConfig::is_dumping_final_static_archive() && ik->defined_by_other_loaders()) { // The following are not appliable to unregistered classes return; } scan_oops_in_instance_class(ik); if (ik->is_hidden() && CDSConfig::is_dumping_aot_linked_classes()) { bool succeed = AOTClassLinker::try_add_candidate(ik); guarantee(succeed, "All cached hidden classes must be aot-linkable"); add_aot_inited_class(ik); } } } void AOTArtifactFinder::add_cached_type_array_class(TypeArrayKlass* tak) { bool created; _seen_classes->put_if_absent(tak, &created); if (created) { append_to_all_cached_classes(tak); scan_oops_in_array_class(tak); } } void AOTArtifactFinder::add_cached_class(Klass* k) { if (k->is_typeArray_klass()) { add_cached_type_array_class(TypeArrayKlass::cast(k)); } else if (k->is_objArray_klass()) { add_cached_class(ObjArrayKlass::cast(k)->element_klass()); } else { add_cached_instance_class(InstanceKlass::cast(k)); } } void AOTArtifactFinder::scan_oops_in_instance_class(InstanceKlass* ik) { #if INCLUDE_CDS_JAVA_HEAP if (CDSConfig::is_dumping_heap()) { HeapShared::scan_java_class(ik); scan_oops_in_array_class(ik->array_klasses()); } #endif } void AOTArtifactFinder::scan_oops_in_array_class(ArrayKlass* ak) { #if INCLUDE_CDS_JAVA_HEAP if (CDSConfig::is_dumping_heap()) { while (ak != nullptr) { HeapShared::scan_java_class(ak); ak = ak->array_klass_or_null(); } } #endif } void AOTArtifactFinder::all_cached_classes_do(MetaspaceClosure* it) { for (int i = 0; i < _all_cached_classes->length(); i++) { it->push(_all_cached_classes->adr_at(i)); } } void AOTArtifactFinder::check_critical_classes() { if (CDSConfig::is_dumping_static_archive()) { // vmClasses are store in the AOT cache (or AOT config file, or static archive). // If any of the vmClasses is excluded, (usually due to incompatible JVMTI agent), // the resulting cache/config/archive is unusable. for (auto id : EnumRange<vmClassID>{}) { check_critical_class(vmClasses::klass_at(id)); } } } void AOTArtifactFinder::check_critical_class(InstanceKlass* ik) { if (SystemDictionaryShared::is_excluded_class(ik)) { ResourceMark rm; const char* msg = err_msg("Critical class %s has been excluded. %s cannot be written.", ik->external_name(), CDSConfig::type_of_archive_being_written()); AOTMetaspace::unrecoverable_writing_error(msg); } }