1 /*
  2  * Copyright (c) 2024, 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 "precompiled.hpp"
 26 #include "cds/aotClassLinker.hpp"
 27 #include "cds/aotConstantPoolResolver.hpp"
 28 #include "cds/aotLinkedClassTable.hpp"
 29 #include "cds/archiveBuilder.hpp"
 30 #include "cds/archiveUtils.inline.hpp"
 31 #include "cds/cdsConfig.hpp"
 32 #include "cds/heapShared.hpp"
 33 #include "cds/lambdaFormInvokers.inline.hpp"
 34 #include "classfile/classLoader.hpp"
 35 #include "classfile/dictionary.hpp"
 36 #include "classfile/systemDictionary.hpp"
 37 #include "classfile/systemDictionaryShared.hpp"
 38 #include "classfile/vmClasses.hpp"
 39 #include "memory/resourceArea.hpp"
 40 #include "oops/constantPool.inline.hpp"
 41 #include "oops/instanceKlass.hpp"
 42 #include "oops/klass.inline.hpp"
 43 #include "runtime/handles.inline.hpp"
 44 
 45 AOTClassLinker::ClassesTable* AOTClassLinker::_vm_classes = nullptr;
 46 AOTClassLinker::ClassesTable* AOTClassLinker::_candidates = nullptr;
 47 GrowableArrayCHeap<InstanceKlass*, mtClassShared>* AOTClassLinker::_sorted_candidates = nullptr;
 48 
 49 #ifdef ASSERT
 50 bool AOTClassLinker::is_initialized() {
 51   assert(CDSConfig::is_dumping_archive(), "AOTClassLinker is for CDS dumping only");
 52   return _vm_classes != nullptr;
 53 }
 54 #endif
 55 
 56 void AOTClassLinker::initialize() {
 57   assert(!is_initialized(), "sanity");
 58 
 59   _vm_classes = new (mtClass)ClassesTable();
 60   _candidates = new (mtClass)ClassesTable();
 61   _sorted_candidates = new GrowableArrayCHeap<InstanceKlass*, mtClassShared>(1000);
 62 
 63   for (auto id : EnumRange<vmClassID>{}) {
 64     add_vm_class(vmClasses::klass_at(id));
 65   }
 66 
 67   assert(is_initialized(), "sanity");
 68 
 69   AOTConstantPoolResolver::initialize();
 70 }
 71 
 72 void AOTClassLinker::dispose() {
 73   assert(is_initialized(), "sanity");
 74 
 75   delete _vm_classes;
 76   delete _candidates;
 77   delete _sorted_candidates;
 78   _vm_classes = nullptr;
 79   _candidates = nullptr;
 80   _sorted_candidates = nullptr;
 81 
 82   assert(!is_initialized(), "sanity");
 83 
 84   AOTConstantPoolResolver::dispose();
 85 }
 86 
 87 bool AOTClassLinker::is_vm_class(InstanceKlass* ik) {
 88   assert(is_initialized(), "sanity");
 89   return (_vm_classes->get(ik) != nullptr);
 90 }
 91 
 92 void AOTClassLinker::add_vm_class(InstanceKlass* ik) {
 93   assert(is_initialized(), "sanity");
 94   bool created;
 95   _vm_classes->put_if_absent(ik, &created);
 96   if (created) {
 97     if (CDSConfig::is_dumping_aot_linked_classes()) {
 98       bool v = try_add_candidate(ik);
 99       assert(v, "must succeed for VM class");
100     }
101     InstanceKlass* super = ik->java_super();
102     if (super != nullptr) {
103       add_vm_class(super);
104     }
105     Array<InstanceKlass*>* ifs = ik->local_interfaces();
106     for (int i = 0; i < ifs->length(); i++) {
107       add_vm_class(ifs->at(i));
108     }
109   }
110 }
111 
112 bool AOTClassLinker::is_candidate(InstanceKlass* ik) {
113   return (_candidates->get(ik) != nullptr);
114 }
115 
116 void AOTClassLinker::add_candidate(InstanceKlass* ik) {
117   _candidates->put_when_absent(ik, true);
118   _sorted_candidates->append(ik);
119 }
120 
121 bool AOTClassLinker::try_add_candidate(InstanceKlass* ik) {
122   assert(is_initialized(), "sanity");
123   assert(CDSConfig::is_dumping_aot_linked_classes(), "sanity");
124 
125   if (!SystemDictionaryShared::is_builtin(ik)) {
126     return false;
127   }
128 
129   if (is_candidate(ik)) { // already checked.
130     return true;
131   }
132 
133   if (ik->is_hidden()) {
134     assert(ik->shared_class_loader_type() != ClassLoader::OTHER, "must have been set");
135     if (!CDSConfig::is_dumping_invokedynamic()) {
136       return false;
137     }
138     if (!SystemDictionaryShared::should_hidden_class_be_archived(ik)) {
139       return false;
140     }
141   }
142 
143   InstanceKlass* s = ik->java_super();
144   if (s != nullptr && !try_add_candidate(s)) {
145     return false;
146   }
147 
148   Array<InstanceKlass*>* interfaces = ik->local_interfaces();
149   int num_interfaces = interfaces->length();
150   for (int index = 0; index < num_interfaces; index++) {
151     InstanceKlass* intf = interfaces->at(index);
152     if (!try_add_candidate(intf)) {
153       return false;
154     }
155   }
156 
157   add_candidate(ik);
158 
159   if (log_is_enabled(Info, cds, aot, load)) {
160     ResourceMark rm;
161     log_info(cds, aot, load)("%s %s", ArchiveUtils::class_category(ik), ik->external_name());
162   }
163 
164   return true;
165 }
166 
167 void AOTClassLinker::add_candidates() {
168   assert_at_safepoint();
169   if (CDSConfig::is_dumping_aot_linked_classes()) {
170     GrowableArray<Klass*>* klasses = ArchiveBuilder::current()->klasses();
171     for (GrowableArrayIterator<Klass*> it = klasses->begin(); it != klasses->end(); ++it) {
172       Klass* k = *it;
173       if (k->is_instance_klass()) {
174         try_add_candidate(InstanceKlass::cast(k));
175       }
176     }
177   }
178 }
179 
180 void AOTClassLinker::write_to_archive() {
181   assert(is_initialized(), "sanity");
182   assert_at_safepoint();
183 
184   if (CDSConfig::is_dumping_aot_linked_classes()) {
185     AOTLinkedClassTable* table = AOTLinkedClassTable::get(CDSConfig::is_dumping_static_archive());
186     table->set_boot(write_classes(nullptr, true));
187     table->set_boot2(write_classes(nullptr, false));
188     table->set_platform(write_classes(SystemDictionary::java_platform_loader(), false));
189     table->set_app(write_classes(SystemDictionary::java_system_loader(), false));
190   }
191 }
192 
193 Array<InstanceKlass*>* AOTClassLinker::write_classes(oop class_loader, bool is_javabase) {
194   ResourceMark rm;
195   GrowableArray<InstanceKlass*> list;
196 
197   for (int i = 0; i < _sorted_candidates->length(); i++) {
198     InstanceKlass* ik = _sorted_candidates->at(i);
199     if (ik->class_loader() != class_loader) {
200       continue;
201     }
202     if ((ik->module() == ModuleEntryTable::javabase_moduleEntry()) != is_javabase) {
203       continue;
204     }
205 
206     if (ik->is_shared() && CDSConfig::is_dumping_dynamic_archive()) {
207       if (CDSConfig::is_using_aot_linked_classes()) {
208         // This class was recorded as a AOT-linked for the base archive,
209         // so there's no need to do so again for the dynamic archive.
210       } else {
211         list.append(ik);
212       }
213     } else {
214       list.append(ArchiveBuilder::current()->get_buffered_addr(ik));
215     }
216   }
217 
218   if (list.length() == 0) {
219     return nullptr;
220   } else {
221     const char* category = ArchiveUtils::class_category(list.at(0));
222     log_info(cds, aot, load)("written %d class(es) for category %s", list.length(), category);
223     return ArchiveUtils::archive_array(&list);
224   }
225 }
226 
227 int AOTClassLinker::num_platform_initiated_classes() {
228   // AOTLinkedClassBulkLoader will initiate loading of all public boot classes in the platform loader.
229   return num_initiated_classes(nullptr, nullptr);
230 }
231 
232 int AOTClassLinker::num_app_initiated_classes() {
233   // AOTLinkedClassBulkLoader will initiate loading of all public boot/platform classes in the app loader.
234   return num_initiated_classes(nullptr, SystemDictionary::java_platform_loader());
235 }
236 
237 int AOTClassLinker::num_initiated_classes(oop loader1, oop loader2) {
238   int n = 0;
239   for (int i = 0; i < _sorted_candidates->length(); i++) {
240     InstanceKlass* ik = _sorted_candidates->at(i);
241     if (ik->is_public() && !ik->is_hidden() &&
242         (ik->class_loader() == loader1 || ik->class_loader() == loader2)) {
243       n++;
244     }
245   }
246 
247   return n;
248 }