1 | /* |
2 | * Copyright (c) 2016, 2019, 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 | #include "precompiled.hpp" |
25 | #include "aot/aotCodeHeap.hpp" |
26 | #include "aot/aotLoader.inline.hpp" |
27 | #include "classfile/javaClasses.hpp" |
28 | #include "jvm.h" |
29 | #include "memory/allocation.inline.hpp" |
30 | #include "memory/resourceArea.hpp" |
31 | #include "oops/compressedOops.hpp" |
32 | #include "oops/method.hpp" |
33 | #include "runtime/handles.inline.hpp" |
34 | #include "runtime/os.inline.hpp" |
35 | #include "runtime/timerTrace.hpp" |
36 | |
37 | GrowableArray<AOTCodeHeap*>* AOTLoader::_heaps = new(ResourceObj::C_HEAP, mtCode) GrowableArray<AOTCodeHeap*> (2, true); |
38 | GrowableArray<AOTLib*>* AOTLoader::_libraries = new(ResourceObj::C_HEAP, mtCode) GrowableArray<AOTLib*> (2, true); |
39 | |
40 | // Iterate over all AOT CodeHeaps |
41 | #define FOR_ALL_AOT_HEAPS(heap) for (GrowableArrayIterator<AOTCodeHeap*> heap = heaps()->begin(); heap != heaps()->end(); ++heap) |
42 | // Iterate over all AOT Libraries |
43 | #define FOR_ALL_AOT_LIBRARIES(lib) for (GrowableArrayIterator<AOTLib*> lib = libraries()->begin(); lib != libraries()->end(); ++lib) |
44 | |
45 | void AOTLoader::load_for_klass(InstanceKlass* ik, Thread* thread) { |
46 | if (ik->is_unsafe_anonymous()) { |
47 | // don't even bother |
48 | return; |
49 | } |
50 | if (UseAOT) { |
51 | // We allow hotswap to be enabled after the onload phase, but not breakpoints |
52 | assert(!JvmtiExport::can_post_breakpoint(), "AOT should have been disabled." ); |
53 | FOR_ALL_AOT_HEAPS(heap) { |
54 | (*heap)->load_klass_data(ik, thread); |
55 | } |
56 | } |
57 | } |
58 | |
59 | uint64_t AOTLoader::get_saved_fingerprint(InstanceKlass* ik) { |
60 | assert(UseAOT, "called only when AOT is enabled" ); |
61 | if (ik->is_unsafe_anonymous()) { |
62 | // don't even bother |
63 | return 0; |
64 | } |
65 | FOR_ALL_AOT_HEAPS(heap) { |
66 | AOTKlassData* klass_data = (*heap)->find_klass(ik); |
67 | if (klass_data != NULL) { |
68 | return klass_data->_fingerprint; |
69 | } |
70 | } |
71 | return 0; |
72 | } |
73 | |
74 | void AOTLoader::oops_do(OopClosure* f) { |
75 | if (UseAOT) { |
76 | FOR_ALL_AOT_HEAPS(heap) { |
77 | (*heap)->oops_do(f); |
78 | } |
79 | } |
80 | } |
81 | |
82 | void AOTLoader::metadata_do(MetadataClosure* f) { |
83 | if (UseAOT) { |
84 | FOR_ALL_AOT_HEAPS(heap) { |
85 | (*heap)->metadata_do(f); |
86 | } |
87 | } |
88 | } |
89 | |
90 | void AOTLoader::mark_evol_dependent_methods(InstanceKlass* dependee) { |
91 | if (UseAOT) { |
92 | FOR_ALL_AOT_HEAPS(heap) { |
93 | (*heap)->mark_evol_dependent_methods(dependee); |
94 | } |
95 | } |
96 | } |
97 | |
98 | /** |
99 | * List of core modules for which we search for shared libraries. |
100 | */ |
101 | static const char* modules[] = { |
102 | "java.base" , |
103 | "java.logging" , |
104 | "jdk.compiler" , |
105 | "jdk.scripting.nashorn" , |
106 | "jdk.internal.vm.ci" , |
107 | "jdk.internal.vm.compiler" |
108 | }; |
109 | |
110 | void AOTLoader::initialize() { |
111 | TraceTime timer("AOT initialization" , TRACETIME_LOG(Info, aot, startuptime)); |
112 | |
113 | if (FLAG_IS_DEFAULT(UseAOT) && AOTLibrary != NULL) { |
114 | // Don't need to set UseAOT on command line when AOTLibrary is specified |
115 | FLAG_SET_DEFAULT(UseAOT, true); |
116 | } |
117 | if (UseAOT) { |
118 | // EagerInitialization is not compatible with AOT |
119 | if (EagerInitialization) { |
120 | if (PrintAOT) { |
121 | warning("EagerInitialization is not compatible with AOT (switching AOT off)" ); |
122 | } |
123 | FLAG_SET_DEFAULT(UseAOT, false); |
124 | return; |
125 | } |
126 | |
127 | if (JvmtiExport::can_post_breakpoint()) { |
128 | if (PrintAOT) { |
129 | warning("JVMTI capability to post breakpoint is not compatible with AOT (switching AOT off)" ); |
130 | } |
131 | FLAG_SET_DEFAULT(UseAOT, false); |
132 | return; |
133 | } |
134 | |
135 | // -Xint is not compatible with AOT |
136 | if (Arguments::is_interpreter_only()) { |
137 | if (PrintAOT) { |
138 | warning("-Xint is not compatible with AOT (switching AOT off)" ); |
139 | } |
140 | FLAG_SET_DEFAULT(UseAOT, false); |
141 | return; |
142 | } |
143 | |
144 | #ifdef _WINDOWS |
145 | const char pathSep = ';'; |
146 | #else |
147 | const char pathSep = ':'; |
148 | #endif |
149 | |
150 | // Scan the AOTLibrary option. |
151 | if (AOTLibrary != NULL) { |
152 | const int len = (int)strlen(AOTLibrary); |
153 | char* cp = NEW_C_HEAP_ARRAY(char, len+1, mtCode); |
154 | if (cp != NULL) { // No memory? |
155 | memcpy(cp, AOTLibrary, len); |
156 | cp[len] = '\0'; |
157 | char* end = cp + len; |
158 | while (cp < end) { |
159 | const char* name = cp; |
160 | while ((*cp) != '\0' && (*cp) != '\n' && (*cp) != ',' && (*cp) != pathSep) cp++; |
161 | cp[0] = '\0'; // Terminate name |
162 | cp++; |
163 | load_library(name, true); |
164 | } |
165 | } |
166 | } |
167 | |
168 | // Load well-know AOT libraries from Java installation directory. |
169 | const char* home = Arguments::get_java_home(); |
170 | const char* file_separator = os::file_separator(); |
171 | |
172 | for (int i = 0; i < (int) (sizeof(modules) / sizeof(const char*)); i++) { |
173 | char library[JVM_MAXPATHLEN]; |
174 | jio_snprintf(library, sizeof(library), "%s%slib%slib%s%s%s%s" , home, file_separator, file_separator, modules[i], UseCompressedOops ? "-coop" : "" , UseG1GC ? "" : "-nong1" , os::dll_file_extension()); |
175 | load_library(library, false); |
176 | } |
177 | } |
178 | } |
179 | |
180 | void AOTLoader::universe_init() { |
181 | if (UseAOT && libraries_count() > 0) { |
182 | // Shifts are static values which initialized by 0 until java heap initialization. |
183 | // AOT libs are loaded before heap initialized so shift values are not set. |
184 | // It is okay since ObjectAlignmentInBytes flag which defines shifts value is set before AOT libs are loaded. |
185 | // AOT sets shift values during heap and metaspace initialization. |
186 | // Check shifts value to make sure thay did not change. |
187 | if (UseCompressedOops && AOTLib::narrow_oop_shift_initialized()) { |
188 | int oop_shift = CompressedOops::shift(); |
189 | FOR_ALL_AOT_LIBRARIES(lib) { |
190 | (*lib)->verify_flag((*lib)->config()->_narrowOopShift, oop_shift, "CompressedOops::shift" ); |
191 | } |
192 | if (UseCompressedClassPointers) { // It is set only if UseCompressedOops is set |
193 | int klass_shift = CompressedKlassPointers::shift(); |
194 | FOR_ALL_AOT_LIBRARIES(lib) { |
195 | (*lib)->verify_flag((*lib)->config()->_narrowKlassShift, klass_shift, "CompressedKlassPointers::shift" ); |
196 | } |
197 | } |
198 | } |
199 | // Create heaps for all valid libraries |
200 | FOR_ALL_AOT_LIBRARIES(lib) { |
201 | if ((*lib)->is_valid()) { |
202 | AOTCodeHeap* heap = new AOTCodeHeap(*lib); |
203 | { |
204 | MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); |
205 | add_heap(heap); |
206 | CodeCache::add_heap(heap); |
207 | } |
208 | } else { |
209 | // Unload invalid libraries |
210 | os::dll_unload((*lib)->dl_handle()); |
211 | } |
212 | } |
213 | } |
214 | if (heaps_count() == 0) { |
215 | if (FLAG_IS_DEFAULT(UseAOT)) { |
216 | FLAG_SET_DEFAULT(UseAOT, false); |
217 | } |
218 | } |
219 | } |
220 | |
221 | // Set shift value for compressed oops and classes based on first AOT library config. |
222 | // AOTLoader::universe_init(), which is called later, will check the shift value again to make sure nobody change it. |
223 | // This code is not executed during CDS dump because it runs in Interpreter mode and AOT is disabled in this mode. |
224 | |
225 | void AOTLoader::set_narrow_oop_shift() { |
226 | // This method is called from Universe::initialize_heap(). |
227 | if (UseAOT && libraries_count() > 0 && |
228 | UseCompressedOops && AOTLib::narrow_oop_shift_initialized()) { |
229 | if (CompressedOops::shift() == 0) { |
230 | // 0 is valid shift value for small heap but we can safely increase it |
231 | // at this point when nobody used it yet. |
232 | CompressedOops::set_shift(AOTLib::narrow_oop_shift()); |
233 | } |
234 | } |
235 | } |
236 | |
237 | void AOTLoader::set_narrow_klass_shift() { |
238 | // This method is called from Metaspace::set_narrow_klass_base_and_shift(). |
239 | if (UseAOT && libraries_count() > 0 && |
240 | UseCompressedOops && AOTLib::narrow_oop_shift_initialized() && |
241 | UseCompressedClassPointers) { |
242 | if (CompressedKlassPointers::shift() == 0) { |
243 | CompressedKlassPointers::set_shift(AOTLib::narrow_klass_shift()); |
244 | } |
245 | } |
246 | } |
247 | |
248 | void AOTLoader::load_library(const char* name, bool exit_on_error) { |
249 | // Skip library if a library with the same name is already loaded. |
250 | const int file_separator = *os::file_separator(); |
251 | const char* start = strrchr(name, file_separator); |
252 | const char* new_name = (start == NULL) ? name : (start + 1); |
253 | FOR_ALL_AOT_LIBRARIES(lib) { |
254 | const char* lib_name = (*lib)->name(); |
255 | start = strrchr(lib_name, file_separator); |
256 | const char* old_name = (start == NULL) ? lib_name : (start + 1); |
257 | if (strcmp(old_name, new_name) == 0) { |
258 | if (PrintAOT) { |
259 | warning("AOT library %s is already loaded as %s." , name, lib_name); |
260 | } |
261 | return; |
262 | } |
263 | } |
264 | char ebuf[1024]; |
265 | void* handle = os::dll_load(name, ebuf, sizeof ebuf); |
266 | if (handle == NULL) { |
267 | if (exit_on_error) { |
268 | tty->print_cr("error opening file: %s" , ebuf); |
269 | vm_exit(1); |
270 | } |
271 | return; |
272 | } |
273 | const int dso_id = libraries_count() + 1; |
274 | AOTLib* lib = new AOTLib(handle, name, dso_id); |
275 | if (!lib->is_valid()) { |
276 | delete lib; |
277 | os::dll_unload(handle); |
278 | return; |
279 | } |
280 | add_library(lib); |
281 | } |
282 | |
283 | #ifndef PRODUCT |
284 | void AOTLoader::print_statistics() { |
285 | { ttyLocker ttyl; |
286 | tty->print_cr("--- AOT Statistics ---" ); |
287 | tty->print_cr("AOT libraries loaded: %d" , heaps_count()); |
288 | AOTCodeHeap::print_statistics(); |
289 | } |
290 | } |
291 | #endif |
292 | |
293 | |
294 | bool AOTLoader::reconcile_dynamic_invoke(InstanceKlass* holder, int index, Method* adapter_method, Klass* appendix_klass) { |
295 | if (!UseAOT) { |
296 | return true; |
297 | } |
298 | JavaThread* thread = JavaThread::current(); |
299 | ResourceMark rm(thread); |
300 | RegisterMap map(thread, false); |
301 | frame caller_frame = thread->last_frame().sender(&map); // Skip stub |
302 | CodeBlob* caller_cb = caller_frame.cb(); |
303 | guarantee(caller_cb != NULL && caller_cb->is_compiled(), "must be called from compiled method" ); |
304 | CompiledMethod* cm = caller_cb->as_compiled_method(); |
305 | |
306 | if (!cm->is_aot()) { |
307 | return true; |
308 | } |
309 | AOTCompiledMethod* aot = (AOTCompiledMethod*)cm; |
310 | |
311 | AOTCodeHeap* caller_heap = NULL; |
312 | FOR_ALL_AOT_HEAPS(heap) { |
313 | if ((*heap)->contains_blob(aot)) { |
314 | caller_heap = *heap; |
315 | break; |
316 | } |
317 | } |
318 | guarantee(caller_heap != NULL, "CodeHeap not found" ); |
319 | bool success = caller_heap->reconcile_dynamic_invoke(aot, holder, index, adapter_method, appendix_klass); |
320 | vmassert(success || thread->last_frame().sender(&map).is_deoptimized_frame(), "caller not deoptimized on failure" ); |
321 | return success; |
322 | } |
323 | |
324 | |
325 | // This should be called very early during startup before any of the AOTed methods that use boxes can deoptimize. |
326 | // Deoptimization machinery expects the caches to be present and populated. |
327 | void AOTLoader::initialize_box_caches(TRAPS) { |
328 | if (!UseAOT || libraries_count() == 0) { |
329 | return; |
330 | } |
331 | TraceTime timer("AOT initialization of box caches" , TRACETIME_LOG(Info, aot, startuptime)); |
332 | Symbol* box_classes[] = { java_lang_Boolean::symbol(), java_lang_Byte_ByteCache::symbol(), |
333 | java_lang_Short_ShortCache::symbol(), java_lang_Character_CharacterCache::symbol(), |
334 | java_lang_Integer_IntegerCache::symbol(), java_lang_Long_LongCache::symbol() }; |
335 | |
336 | for (unsigned i = 0; i < sizeof(box_classes) / sizeof(Symbol*); i++) { |
337 | Klass* k = SystemDictionary::resolve_or_fail(box_classes[i], true, CHECK); |
338 | InstanceKlass* ik = InstanceKlass::cast(k); |
339 | if (ik->is_not_initialized()) { |
340 | ik->initialize(CHECK); |
341 | } |
342 | } |
343 | } |
344 | |