1 /*
  2  * Copyright (c) 2025, 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 "cds/aotClassLinker.hpp"
 26 #include "cds/aotArtifactFinder.hpp"
 27 #include "cds/aotClassInitializer.hpp"
 28 #include "cds/dumpTimeClassInfo.inline.hpp"
 29 #include "cds/heapShared.hpp"
 30 #include "classfile/systemDictionaryShared.hpp"
 31 #include "logging/log.hpp"
 32 #include "memory/metaspaceClosure.hpp"
 33 #include "oops/instanceKlass.hpp"
 34 #include "oops/objArrayKlass.hpp"
 35 #include "utilities/resourceHash.hpp"
 36 
 37 // All the classes that should be included in the AOT cache (in at least the "allocated" state)
 38 static GrowableArrayCHeap<Klass*, mtClassShared>* _all_cached_classes = nullptr;
 39 
 40 // This is a stack that tracks all the AOT-inited classes that are waiting to be passed
 41 // to HeapShared::copy_and_rescan_aot_inited_mirror().
 42 static GrowableArrayCHeap<InstanceKlass*, mtClassShared>* _pending_aot_inited_classes = nullptr;
 43 
 44 static const int TABLE_SIZE = 15889; // prime number
 45 using ClassesTable = ResourceHashtable<Klass*, bool, TABLE_SIZE, AnyObj::C_HEAP, mtClassShared>;
 46 static ClassesTable* _seen_classes;       // all classes that have been seen by AOTArtifactFinder
 47 static ClassesTable* _aot_inited_classes; // all classes that need to be AOT-initialized.
 48 
 49 void AOTArtifactFinder::initialize() {
 50   _all_cached_classes = new GrowableArrayCHeap<Klass*, mtClassShared>();
 51   _pending_aot_inited_classes = new GrowableArrayCHeap<InstanceKlass*, mtClassShared>();
 52   _seen_classes = new (mtClass)ClassesTable();
 53   _aot_inited_classes = new (mtClass)ClassesTable();
 54 }
 55 
 56 void AOTArtifactFinder::dispose() {
 57   delete _all_cached_classes;
 58   delete _seen_classes;
 59   delete _aot_inited_classes;
 60   delete _pending_aot_inited_classes;
 61   _all_cached_classes = nullptr;
 62   _seen_classes = nullptr;
 63   _aot_inited_classes = nullptr;
 64   _pending_aot_inited_classes = nullptr;
 65 }
 66 
 67 // Find all Klasses and oops that should be included in the AOT cache. See aotArtifactFinder.hpp
 68 void AOTArtifactFinder::find_artifacts() {
 69   // Some classes might have been marked as excluded as a side effect of running
 70   // AOTConstantPoolResolver. Make sure we check all the remaining ones.
 71   //
 72   // Note, if a class is not excluded, it does NOT mean it will be automatically included
 73   // into the AOT cache -- that will be decided by the code below.
 74   SystemDictionaryShared::finish_exclusion_checks();
 75 
 76   start_scanning_for_oops();
 77 
 78   // Add the primitive array classes
 79   for (int i = T_BOOLEAN; i < T_VOID+1; i++) {
 80     BasicType bt = (BasicType)i;
 81     if (is_java_primitive(bt)) {
 82       add_cached_type_array_class(Universe::typeArrayKlass(bt));
 83     }
 84   }
 85 
 86 #if INCLUDE_CDS_JAVA_HEAP
 87   // Add the mirrors that aren't associated with a Klass
 88   //    - primitive mirrors (E.g., "int.class" in Java code)
 89   //    - mirror of fillerArrayKlass
 90   if (CDSConfig::is_dumping_heap()) {
 91     for (int i = T_BOOLEAN; i < T_VOID+1; i++) {
 92       BasicType bt = (BasicType)i;
 93       if (!is_reference_type(bt)) {
 94         oop orig_mirror = Universe::java_mirror(bt);
 95         oop scratch_mirror = HeapShared::scratch_java_mirror(bt);
 96         HeapShared::scan_java_mirror(orig_mirror);
 97         log_trace(cds, heap, mirror)(
 98             "Archived %s mirror object from " PTR_FORMAT,
 99             type2name(bt), p2i(scratch_mirror));
100         Universe::set_archived_basic_type_mirror_index(bt, HeapShared::append_root(scratch_mirror));
101       }
102     }
103 
104     // Universe::fillerArrayKlass() isn't in the class hierarchy, so handle it specially.
105     HeapShared::scan_java_mirror(Universe::fillerArrayKlass()->java_mirror());
106   }
107 #endif
108 
109   // Add all the InstanceKlasses (and their array classes) that are always included.
110   SystemDictionaryShared::dumptime_table()->iterate_all_live_classes([&] (InstanceKlass* ik, DumpTimeClassInfo& info) {
111     if (!info.is_excluded()) {
112       bool add = false;
113       if (!ik->is_hidden()) {
114         // All non-hidden classes are always included into the AOT cache
115         add = true;
116       } else {
117         if (!CDSConfig::is_dumping_invokedynamic()) {
118           // Legacy support of lambda proxies -- these are always included into the AOT cache
119           if (SystemDictionaryShared::is_registered_lambda_proxy_class(ik)) {
120             add = true;
121           }
122         } else {
123           assert(!SystemDictionaryShared::is_registered_lambda_proxy_class(ik),
124                  "registered lambda proxies are only for legacy lambda proxy support");
125         }
126       }
127 
128       if (add) {
129         add_cached_instance_class(ik);
130         if (AOTClassInitializer::can_archive_initialized_mirror(ik)) {
131           add_aot_inited_class(ik);
132         }
133       }
134     }
135   });
136 
137 #if INCLUDE_CDS_JAVA_HEAP
138   // Keep scanning until we discover no more class that need to be AOT-initialized.
139   if (CDSConfig::is_initing_classes_at_dump_time()) {
140     while (_pending_aot_inited_classes->length() > 0) {
141       InstanceKlass* ik = _pending_aot_inited_classes->pop();
142       HeapShared::copy_and_rescan_aot_inited_mirror(ik);
143     }
144   }
145 #endif
146 
147   // Exclude all the (hidden) classes that have not been discovered by the code above.
148   SystemDictionaryShared::dumptime_table()->iterate_all_live_classes([&] (InstanceKlass* k, DumpTimeClassInfo& info) {
149     if (!info.is_excluded() && _seen_classes->get(k) == nullptr) {
150       info.set_excluded();
151       assert(k->is_hidden(), "must be");
152       if (log_is_enabled(Info, cds)) {
153         ResourceMark rm;
154         log_info(cds)("Skipping %s: Hidden class", k->name()->as_C_string());
155       }
156     }
157   });
158 
159   end_scanning_for_oops();
160 }
161 
162 void AOTArtifactFinder::start_scanning_for_oops() {
163 #if INCLUDE_CDS_JAVA_HEAP
164   if (CDSConfig::is_dumping_heap()) {
165     HeapShared::start_scanning_for_oops();
166   }
167 #endif
168 }
169 
170 void AOTArtifactFinder::end_scanning_for_oops() {
171 #if INCLUDE_CDS_JAVA_HEAP
172   if (CDSConfig::is_dumping_heap()) {
173     HeapShared::end_scanning_for_oops();
174   }
175 #endif
176 }
177 
178 void AOTArtifactFinder::add_aot_inited_class(InstanceKlass* ik) {
179   if (CDSConfig::is_initing_classes_at_dump_time()) {
180     assert(ik->is_initialized(), "must be");
181     add_cached_instance_class(ik);
182 
183     bool created;
184     _aot_inited_classes->put_if_absent(ik, &created);
185     if (created) {
186       _pending_aot_inited_classes->push(ik);
187 
188       InstanceKlass* s = ik->java_super();
189       if (s != nullptr) {
190         add_aot_inited_class(s);
191       }
192 
193       Array<InstanceKlass*>* interfaces = ik->local_interfaces();
194       int len = interfaces->length();
195       for (int i = 0; i < len; i++) {
196         InstanceKlass* intf = interfaces->at(i);
197         if (intf->is_initialized()) {
198           add_aot_inited_class(intf);
199         }
200       }
201     }
202   }
203 }
204 
205 void AOTArtifactFinder::add_cached_instance_class(InstanceKlass* ik) {
206   bool created;
207   _seen_classes->put_if_absent(ik, &created);
208   if (created) {
209     _all_cached_classes->append(ik);
210     scan_oops_in_instance_class(ik);
211     if (ik->is_hidden() && CDSConfig::is_initing_classes_at_dump_time()) {
212       bool succeed = AOTClassLinker::try_add_candidate(ik);
213       guarantee(succeed, "All cached hidden classes must be aot-linkable");
214       add_aot_inited_class(ik);
215     }
216   }
217 }
218 
219 void AOTArtifactFinder::add_cached_type_array_class(TypeArrayKlass* tak) {
220   bool created;
221   _seen_classes->put_if_absent(tak, &created);
222   if (created) {
223     _all_cached_classes->append(tak);
224     scan_oops_in_array_class(tak);
225   }
226 }
227 
228 void AOTArtifactFinder::add_cached_class(Klass* k) {
229   if (k->is_typeArray_klass()) {
230     add_cached_type_array_class(TypeArrayKlass::cast(k));
231   } else if (k->is_objArray_klass()) {
232     add_cached_class(ObjArrayKlass::cast(k)->element_klass());
233   } else {
234     add_cached_instance_class(InstanceKlass::cast(k));
235   }
236 }
237 
238 void AOTArtifactFinder::scan_oops_in_instance_class(InstanceKlass* ik) {
239 #if INCLUDE_CDS_JAVA_HEAP
240   if (CDSConfig::is_dumping_heap()) {
241     HeapShared::scan_java_class(ik);
242     scan_oops_in_array_class(ik->array_klasses());
243   }
244 #endif
245 }
246 
247 void AOTArtifactFinder::scan_oops_in_array_class(ArrayKlass* ak) {
248 #if INCLUDE_CDS_JAVA_HEAP
249   if (CDSConfig::is_dumping_heap()) {
250     while (ak != nullptr) {
251       HeapShared::scan_java_class(ak);
252       ak = ak->array_klass_or_null();
253     }
254   }
255 #endif
256 }
257 
258 void AOTArtifactFinder::all_cached_classes_do(MetaspaceClosure* it) {
259   for (int i = 0; i < _all_cached_classes->length(); i++) {
260     it->push(_all_cached_classes->adr_at(i));
261   }
262 }