| 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 | |