--- make/autoconf/jvm-features.m4 | 2 + make/data/hotspot-symbols/symbols-unix | 3 +- make/modules/jdk.jbooster/Launcher.gmk | 25 ++- src/hotspot/share/aot/aotCodeHeap.cpp | 27 ++-- src/hotspot/share/aot/aotCodeHeap.hpp | 6 +- src/hotspot/share/aot/aotLoader.cpp | 22 ++- src/hotspot/share/aot/aotLoader.hpp | 2 +- src/hotspot/share/gc/parallel/psScavenge.cpp | 1 + src/hotspot/share/include/jvm.h | 6 + src/hotspot/share/interpreter/rewriter.cpp | 15 +- src/hotspot/share/interpreter/rewriter.hpp | 6 +- .../jbooster/client/clientDataManager.cpp | 16 +- .../jbooster/client/clientDataManager.hpp | 6 +- .../share/jbooster/jClientArguments.cpp | 4 + .../share/jbooster/jClientArguments.hpp | 1 + src/hotspot/share/jbooster/jClientVMFlags.hpp | 2 + .../share/jbooster/jbooster_globals.hpp | 2 +- src/hotspot/share/jbooster/lazyAot.cpp | 117 ++++++++------ src/hotspot/share/jbooster/lazyAot.hpp | 32 ++-- .../share/jbooster/net/serialization.cpp | 16 ++ .../jbooster/server/serverDataManager.cpp | 5 +- .../jbooster/server/serverDataManager.hpp | 3 + .../jbooster/server/serverMessageHandler.cpp | 8 +- .../jbooster/server/serverMessageHandler.hpp | 1 + src/hotspot/share/oops/compressedOops.cpp | 46 ++++-- src/hotspot/share/oops/instanceKlass.hpp | 2 +- src/hotspot/share/oops/method.cpp | 9 +- src/hotspot/share/oops/methodData.cpp | 2 +- src/hotspot/share/prims/jvm.cpp | 11 +- .../share/prims/jvmtiRedefineClasses.cpp | 2 +- .../share/lib/security/default.policy | 35 +++++ .../tools/jaotc/binformat/elf/ElfSection.java | 34 +++- .../src/jdk/tools/jaotc/AOTBackend.java | 13 +- .../jdk/tools/jaotc/AOTCompilationTask.java | 4 + .../src/jdk/tools/jaotc/AOTCompiledClass.java | 58 ++++++- .../src/jdk/tools/jaotc/AOTCompiler.java | 147 +++++++++++++++++- .../src/jdk/tools/jaotc/Collector.java | 18 ++- .../src/jdk/tools/jaotc/CompilationSpec.java | 9 ++ .../jdk/tools/jaotc/CompiledMethodInfo.java | 13 ++ .../src/jdk/tools/jaotc/DataBuilder.java | 5 +- .../jdk/tools/jaotc/DataPatchProcessor.java | 17 +- .../src/jdk/tools/jaotc/Main.java | 118 ++++++++++++-- .../src/jdk/tools/jaotc/MetadataBuilder.java | 6 + .../src/jdk/tools/jaotc/Options.java | 19 +++ ...JBoosterHotSpotAOTInvokeDynamicPlugin.java | 46 ++++++ src/jdk.aot/share/classes/module-info.java | 4 + .../sun/jvm/hotspot/oops/InstanceKlass.java | 9 +- .../classes/jdk/vm/ci/aarch64/AArch64.java | 8 + .../share/classes/jdk/vm/ci/amd64/AMD64.java | 8 + .../DirectHotSpotObjectConstantImpl.java | 16 ++ .../ci/hotspot/HotSpotConstantPoolObject.java | 2 +- .../vm/ci/hotspot/HotSpotJVMCIRuntime.java | 4 +- .../vm/ci/hotspot/HotSpotProfilingInfo.java | 16 +- .../HotSpotResolvedJavaMethodImpl.java | 31 +++- .../share/classes/module-info.java | 4 +- .../graalvm/compiler/code/DataSection.java | 13 +- .../hotspot/aarch64/AArch64HotSpotMove.java | 8 +- .../AArch64HotSpotStrategySwitchOp.java | 11 +- .../hotspot/amd64/AMD64HotSpotMove.java | 7 +- .../hotspot/test/CheckGraalIntrinsics.java | 1 - .../hotspot/AOTGraalHotSpotVMConfig.java | 7 +- .../meta/DefaultHotSpotLoweringProvider.java | 4 +- .../graalvm/compiler/java/BytecodeParser.java | 4 +- .../graalvm/compiler/nodes/InliningLog.java | 7 +- .../common/inlining/walker/InliningData.java | 20 ++- .../share/classes/jdk/jbooster/JBooster.java | 13 +- .../share/classes/module-info.java | 3 +- .../share/native/libjbooster/JBooster.c | 6 + .../jtreg/compiler/aot/TestAotPrint.java | 63 ++++++++ .../compiler/aot/TestAotWithRetransform.java | 143 +++++++++++++++++ .../jdk/internal/jimage/JImageOpenTest.java | 2 +- .../modules/etc/JdkQualifiedExportTest.java | 1 + test/jdk/tools/launcher/HelpFlagsTest.java | 2 +- test/jdk/tools/launcher/VersionCheck.java | 2 - 74 files changed, 1166 insertions(+), 195 deletions(-) create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/jbooster/JBoosterHotSpotAOTInvokeDynamicPlugin.java create mode 100644 test/hotspot/jtreg/compiler/aot/TestAotPrint.java create mode 100644 test/hotspot/jtreg/compiler/aot/TestAotWithRetransform.java diff --git a/make/autoconf/jvm-features.m4 b/make/autoconf/jvm-features.m4 index 6e81c84d9..6f8341432 100644 --- a/make/autoconf/jvm-features.m4 +++ b/make/autoconf/jvm-features.m4 @@ -332,6 +332,8 @@ AC_DEFUN_ONCE([JVM_FEATURES_CHECK_JBOOSTER], AC_MSG_CHECKING([if platform is supported by JBOOSTER]) if test "x$OPENJDK_TARGET_CPU" = "xx86_64"; then AC_MSG_RESULT([yes]) + elif test "x$OPENJDK_TARGET_CPU" = "xaarch64"; then + AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no, $OPENJDK_TARGET_CPU]) AVAILABLE=false diff --git a/make/data/hotspot-symbols/symbols-unix b/make/data/hotspot-symbols/symbols-unix index d731017ab..63e5a6946 100644 --- a/make/data/hotspot-symbols/symbols-unix +++ b/make/data/hotspot-symbols/symbols-unix @@ -1,5 +1,5 @@ # -# Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2016, 2023, 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 @@ -211,4 +211,5 @@ JVM_SetBootLoaderUnnamedModule JVM_JBoosterInitVM JVM_JBoosterHandleConnection JVM_JBoosterPrintStoredClientData +JVM_JBoosterGetMetaspaceMethodData JVM_JBoosterStartupNativeCallback diff --git a/make/modules/jdk.jbooster/Launcher.gmk b/make/modules/jdk.jbooster/Launcher.gmk index 1b03ec55e..550ade0f4 100644 --- a/make/modules/jdk.jbooster/Launcher.gmk +++ b/make/modules/jdk.jbooster/Launcher.gmk @@ -26,9 +26,26 @@ include LauncherCommon.gmk $(eval $(call SetupBuildLauncher, jbooster, \ - MAIN_CLASS := jdk.jbooster.Main, \ - JAVA_ARGS := \ - -XX:+UnlockExperimentalVMOptions \ - -XX:+AsJBooster \ + MAIN_CLASS := jdk.jbooster.JBooster, \ + EXTRA_JAVA_ARGS := -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI \ + --add-exports=jdk.internal.vm.ci/jdk.vm.ci.aarch64=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ + --add-exports=jdk.internal.vm.ci/jdk.vm.ci.amd64=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ + --add-exports=jdk.internal.vm.ci/jdk.vm.ci.code=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ + --add-exports=jdk.internal.vm.ci/jdk.vm.ci.code.site=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ + --add-exports=jdk.internal.vm.ci/jdk.vm.ci.code.stack=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ + --add-exports=jdk.internal.vm.ci/jdk.vm.ci.common=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ + --add-exports=jdk.internal.vm.ci/jdk.vm.ci.hotspot=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ + , \ + JAVA_ARGS := -XX:+UnlockExperimentalVMOptions -XX:+UseAOT -XX:+AsJBooster \ + --add-exports=jdk.internal.vm.ci/jdk.vm.ci.hotspot.aarch64=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ + --add-exports=jdk.internal.vm.ci/jdk.vm.ci.hotspot.amd64=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ + --add-exports=jdk.internal.vm.ci/jdk.vm.ci.hotspot.aarch64=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ + --add-exports=jdk.internal.vm.ci/jdk.vm.ci.meta=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ + --add-exports=jdk.internal.vm.ci/jdk.vm.ci.runtime=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ + -XX:+CalculateClassFingerprint \ + -Dgraal.UseExceptionProbability=false \ + -Dgraal.RemoveNeverExecutedCode=false \ + -Djvmci.Compiler=graal \ + --add-modules ALL-DEFAULT \ , \ )) diff --git a/src/hotspot/share/aot/aotCodeHeap.cpp b/src/hotspot/share/aot/aotCodeHeap.cpp index 153ef67bb..efe12ac74 100644 --- a/src/hotspot/share/aot/aotCodeHeap.cpp +++ b/src/hotspot/share/aot/aotCodeHeap.cpp @@ -57,6 +57,7 @@ #include "utilities/sizes.hpp" bool AOTLib::_narrow_oop_shift_initialized = false; +bool AOTLib::_narrow_klass_shift_initialized = false; int AOTLib::_narrow_oop_shift = 0; int AOTLib::_narrow_klass_shift = 0; @@ -197,15 +198,18 @@ void AOTLib::verify_config() { if (UseCompressedOops && _valid) { if (!_narrow_oop_shift_initialized) { _narrow_oop_shift = _config->_narrowOopShift; - if (UseCompressedClassPointers) { // It is set only if UseCompressedOops is set - _narrow_klass_shift = _config->_narrowKlassShift; - } _narrow_oop_shift_initialized = true; } else { verify_flag(_config->_narrowOopShift, _narrow_oop_shift, "aot_config->_narrowOopShift"); - if (UseCompressedClassPointers) { // It is set only if UseCompressedOops is set - verify_flag(_config->_narrowKlassShift, _narrow_klass_shift, "aot_config->_narrowKlassShift"); - } + } + } + + if (UseCompressedClassPointers && _valid) { + if (!_narrow_klass_shift_initialized) { + _narrow_klass_shift = _config->_narrowKlassShift; + _narrow_klass_shift_initialized = true; + } else { + verify_flag(_config->_narrowKlassShift, _narrow_klass_shift, "aot_config->_narrowKlassShift"); } } } @@ -618,7 +622,7 @@ void AOTCodeHeap::print_statistics() { } #endif -Method* AOTCodeHeap::find_method(Klass* klass, TRAPS, const char* method_name) { +Method* AOTCodeHeap::find_method(Klass* klass, Thread* THREAD, const char* method_name) { int method_name_len = Bytes::get_Java_u2((address)method_name); method_name += 2; const char* signature_name = method_name + method_name_len; @@ -656,11 +660,6 @@ Method* AOTCodeHeap::find_method(Klass* klass, TRAPS, const char* method_name) { memcpy(&meta_name[klass_len + 1], method_name, method_name_len); memcpy(&meta_name[klass_len + 1 + method_name_len], signature_name, signature_name_len); meta_name[klass_len + 1 + method_name_len + signature_name_len] = '\0'; - Handle exception = Exceptions::new_exception(THREAD, vmSymbols::java_lang_NoSuchMethodError(), meta_name); - java_lang_Throwable::print(exception(), tty); - tty->cr(); - java_lang_Throwable::print_stack_trace(exception, tty); - tty->cr(); fatal("Failed to find method '%s'", meta_name); } NOT_PRODUCT( aot_methods_found++; ) @@ -771,14 +770,14 @@ void AOTCodeHeap::sweep_method(AOTCompiledMethod *aot) { } -bool AOTCodeHeap::load_klass_data(InstanceKlass* ik, TRAPS) { +bool AOTCodeHeap::load_klass_data(InstanceKlass* ik, Thread* THREAD) { ResourceMark rm; NOT_PRODUCT( klasses_seen++; ) // AOT does not support custom class loaders. ClassLoaderData* cld = ik->class_loader_data(); - if (!cld->is_builtin_class_loader_data()) { + if (!cld->is_builtin_class_loader_data() JBOOSTER_ONLY(&& !UseJBooster)) { log_trace(aot, class, load)("skip class %s for custom classloader %s (%p) tid=" INTPTR_FORMAT, ik->internal_name(), cld->loader_name(), cld, p2i(THREAD)); return false; diff --git a/src/hotspot/share/aot/aotCodeHeap.hpp b/src/hotspot/share/aot/aotCodeHeap.hpp index 40c187ec7..357ce9fb7 100644 --- a/src/hotspot/share/aot/aotCodeHeap.hpp +++ b/src/hotspot/share/aot/aotCodeHeap.hpp @@ -112,6 +112,7 @@ typedef struct { class AOTLib : public CHeapObj { static bool _narrow_oop_shift_initialized; + static bool _narrow_klass_shift_initialized; static int _narrow_oop_shift; static int _narrow_klass_shift; @@ -130,6 +131,7 @@ public: static int narrow_oop_shift() { return _narrow_oop_shift; } static int narrow_klass_shift() { return _narrow_klass_shift; } static bool narrow_oop_shift_initialized() { return _narrow_oop_shift_initialized; } + static bool narrow_klass_shift_initialized() { return _narrow_klass_shift_initialized; } bool is_valid() const { return _valid; @@ -235,7 +237,7 @@ public: virtual void* next(void *p) const; AOTKlassData* find_klass(InstanceKlass* ik); - bool load_klass_data(InstanceKlass* ik, TRAPS); + bool load_klass_data(InstanceKlass* ik, Thread* THREAD); Klass* get_klass_from_got(const char* klass_name, int klass_len, const Method* method); bool is_dependent_method(Klass* dependee, AOTCompiledMethod* aot); @@ -273,7 +275,7 @@ public: return NULL; } - static Method* find_method(Klass* klass, TRAPS, const char* method_name); + static Method* find_method(Klass* klass, Thread* THREAD, const char* method_name); void cleanup_inline_caches(); diff --git a/src/hotspot/share/aot/aotLoader.cpp b/src/hotspot/share/aot/aotLoader.cpp index 4e12ee95a..f8e89e634 100644 --- a/src/hotspot/share/aot/aotLoader.cpp +++ b/src/hotspot/share/aot/aotLoader.cpp @@ -47,7 +47,7 @@ GrowableArray* AOTLoader::_libraries = new(ResourceObj::C_HEAP, mtCode) // Iterate over all AOT Libraries #define FOR_ALL_AOT_LIBRARIES(lib) for (GrowableArrayIterator lib = libraries()->begin(); lib != libraries()->end(); ++lib) -void AOTLoader::load_for_klass(InstanceKlass* ik, TRAPS) { +void AOTLoader::load_for_klass(InstanceKlass* ik, Thread* THREAD) { if (ik->is_hidden()) { // don't even bother return; @@ -155,6 +155,7 @@ void AOTLoader::initialize() { if (AOTLibrary != NULL) { const int len = (int)strlen(AOTLibrary); char* cp = NEW_C_HEAP_ARRAY(char, len+1, mtCode); + char* cp_start = cp; memcpy(cp, AOTLibrary, len); cp[len] = '\0'; char* end = cp + len; @@ -165,6 +166,7 @@ void AOTLoader::initialize() { cp++; load_library(name, true); } + FREE_C_HEAP_ARRAY(char, cp_start); } // Load well-know AOT libraries from Java installation directory. @@ -191,11 +193,11 @@ void AOTLoader::universe_init() { FOR_ALL_AOT_LIBRARIES(lib) { (*lib)->verify_flag((*lib)->config()->_narrowOopShift, oop_shift, "CompressedOops::shift"); } - if (UseCompressedClassPointers) { // It is set only if UseCompressedOops is set - int klass_shift = CompressedKlassPointers::shift(); - FOR_ALL_AOT_LIBRARIES(lib) { - (*lib)->verify_flag((*lib)->config()->_narrowKlassShift, klass_shift, "CompressedKlassPointers::shift"); - } + } + if (UseCompressedClassPointers && AOTLib::narrow_klass_shift_initialized()) { + int klass_shift = CompressedKlassPointers::shift(); + FOR_ALL_AOT_LIBRARIES(lib) { + (*lib)->verify_flag((*lib)->config()->_narrowKlassShift, klass_shift, "CompressedKlassPointers::shift"); } } // Create heaps for all valid libraries @@ -239,11 +241,15 @@ void AOTLoader::set_narrow_oop_shift() { void AOTLoader::set_narrow_klass_shift() { // This method is called from Metaspace::set_narrow_klass_base_and_shift(). if (UseAOT && libraries_count() > 0 && - UseCompressedOops && AOTLib::narrow_oop_shift_initialized() && - UseCompressedClassPointers) { + UseCompressedClassPointers && AOTLib::narrow_klass_shift_initialized()) { +#ifdef AARCH64 + // the shift in aarch64 cannot be altered, just check it + guarantee(CompressedKlassPointers::shift() == AOTLib::narrow_klass_shift(), "sanity"); +#else if (CompressedKlassPointers::shift() == 0) { CompressedKlassPointers::set_shift(AOTLib::narrow_klass_shift()); } +#endif } } diff --git a/src/hotspot/share/aot/aotLoader.hpp b/src/hotspot/share/aot/aotLoader.hpp index cf03ea087..6273c3fe3 100644 --- a/src/hotspot/share/aot/aotLoader.hpp +++ b/src/hotspot/share/aot/aotLoader.hpp @@ -59,7 +59,7 @@ public: static void universe_init() NOT_AOT_RETURN; static void set_narrow_oop_shift() NOT_AOT_RETURN; static void set_narrow_klass_shift() NOT_AOT_RETURN; - static void load_for_klass(InstanceKlass* ik, TRAPS) NOT_AOT_RETURN; + static void load_for_klass(InstanceKlass* ik, Thread* THREAD) NOT_AOT_RETURN; static uint64_t get_saved_fingerprint(InstanceKlass* ik) NOT_AOT({ return 0; }); static void oops_do(OopClosure* f) NOT_AOT_RETURN; static void metadata_do(MetadataClosure* f) NOT_AOT_RETURN; diff --git a/src/hotspot/share/gc/parallel/psScavenge.cpp b/src/hotspot/share/gc/parallel/psScavenge.cpp index 98ec438ad..98ab42022 100644 --- a/src/hotspot/share/gc/parallel/psScavenge.cpp +++ b/src/hotspot/share/gc/parallel/psScavenge.cpp @@ -91,6 +91,7 @@ static void scavenge_roots_work(ParallelRootType::Value root_type, uint worker_i assert(ParallelScavengeHeap::heap()->is_gc_active(), "called outside gc"); PSPromotionManager* pm = PSPromotionManager::gc_thread_promotion_manager(worker_id); + PSScavengeRootsClosure roots_closure(pm); PSPromoteRootsClosure roots_to_old_closure(pm); switch (root_type) { diff --git a/src/hotspot/share/include/jvm.h b/src/hotspot/share/include/jvm.h index 49c932aec..0f6fba8ba 100644 --- a/src/hotspot/share/include/jvm.h +++ b/src/hotspot/share/include/jvm.h @@ -1119,6 +1119,12 @@ JVM_JBoosterHandleConnection(JNIEnv *env, jint connection_fd); JNIEXPORT void JNICALL JVM_JBoosterPrintStoredClientData(JNIEnv *env, jboolean print_all); +/** + * Get metaspaceMethodData. + */ +JNIEXPORT long JNICALL +JVM_JBoosterGetMetaspaceMethodData(JNIEnv *env, jint session_id, jlong metaspace_method); + /** * Callback of startup signal. */ diff --git a/src/hotspot/share/interpreter/rewriter.cpp b/src/hotspot/share/interpreter/rewriter.cpp index 080735ba4..3908e43bd 100644 --- a/src/hotspot/share/interpreter/rewriter.cpp +++ b/src/hotspot/share/interpreter/rewriter.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2023, 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 @@ -168,14 +168,14 @@ void Rewriter::rewrite_Object_init(const methodHandle& method, TRAPS) { // Rewrite a classfile-order CP index into a native-order CPC index. -void Rewriter::rewrite_member_reference(address bcp, int offset, bool reverse) { +void Rewriter::rewrite_member_reference(address bcp, int offset, bool reverse, Method* current_method) { address p = bcp + offset; if (!reverse) { int cp_index = Bytes::get_Java_u2(p); int cache_index = cp_entry_to_cp_cache(cp_index); Bytes::put_native_u2(p, cache_index); if (!_method_handle_invokers.is_empty()) - maybe_rewrite_invokehandle(p - 1, cp_index, cache_index, reverse); + maybe_rewrite_invokehandle(p - 1, cp_index, cache_index, reverse, current_method); } else { int cache_index = Bytes::get_native_u2(p); int pool_index = cp_cache_entry_pool_index(cache_index); @@ -209,7 +209,7 @@ void Rewriter::rewrite_invokespecial(address bcp, int offset, bool reverse, bool // Adjust the invocation bytecode for a signature-polymorphic method (MethodHandle.invoke, etc.) -void Rewriter::maybe_rewrite_invokehandle(address opc, int cp_index, int cache_index, bool reverse) { +void Rewriter::maybe_rewrite_invokehandle(address opc, int cp_index, int cache_index, bool reverse, Method* current_method) { if (!reverse) { if ((*opc) == (u1)Bytecodes::_invokevirtual || // allow invokespecial as an alias, although it would be very odd: @@ -242,6 +242,11 @@ void Rewriter::maybe_rewrite_invokehandle(address opc, int cp_index, int cache_i // to transmit the call site's intended call type. if (status > 0) { (*opc) = (u1)Bytecodes::_invokehandle; +#if INCLUDE_JBOOSTER + if (!_klass->is_hidden() && current_method != nullptr) { + current_method->set_rewrite_invokehandle(true); + } +#endif // INCLUDE_JBOOSTER } } } else { @@ -472,7 +477,7 @@ void Rewriter::scan_method(Thread* thread, Method* method, bool reverse, bool* i case Bytecodes::_invokestatic : case Bytecodes::_invokeinterface: case Bytecodes::_invokehandle : // if reverse=true - rewrite_member_reference(bcp, prefix_length+1, reverse); + rewrite_member_reference(bcp, prefix_length+1, reverse, method); break; case Bytecodes::_invokedynamic: rewrite_invokedynamic(bcp, prefix_length+1, reverse); diff --git a/src/hotspot/share/interpreter/rewriter.hpp b/src/hotspot/share/interpreter/rewriter.hpp index 928e15ac1..2de251ce2 100644 --- a/src/hotspot/share/interpreter/rewriter.hpp +++ b/src/hotspot/share/interpreter/rewriter.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2023, 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 @@ -186,8 +186,8 @@ class Rewriter: public StackObj { void make_constant_pool_cache(TRAPS); void scan_method(Thread* thread, Method* m, bool reverse, bool* invokespecial_error); void rewrite_Object_init(const methodHandle& m, TRAPS); - void rewrite_member_reference(address bcp, int offset, bool reverse); - void maybe_rewrite_invokehandle(address opc, int cp_index, int cache_index, bool reverse); + void rewrite_member_reference(address bcp, int offset, bool reverse, Method* current_method = nullptr); + void maybe_rewrite_invokehandle(address opc, int cp_index, int cache_index, bool reverse, Method* current_method = nullptr); void rewrite_invokedynamic(address bcp, int offset, bool reverse); void maybe_rewrite_ldc(address bcp, int offset, bool is_wide, bool reverse); void rewrite_invokespecial(address bcp, int offset, bool reverse, bool* invokespecial_error); diff --git a/src/hotspot/share/jbooster/client/clientDataManager.cpp b/src/hotspot/share/jbooster/client/clientDataManager.cpp index 6326b6e8d..1e4c8f2b5 100644 --- a/src/hotspot/share/jbooster/client/clientDataManager.cpp +++ b/src/hotspot/share/jbooster/client/clientDataManager.cpp @@ -44,10 +44,12 @@ ClientDataManager::ClientDataManager() { _allow_aot = false; _allow_cds = false; _allow_clr = false; + _allow_pgo = false; _using_aot = false; _using_cds = false; _using_clr = false; + _using_pgo = false; _cache_clr_path = nullptr; _cache_cds_path = nullptr; @@ -110,7 +112,8 @@ void ClientDataManager::init_const() { _program_args->hash()); _cache_clr_path = JBoosterManager::calc_cache_path(_cache_dir_path, _program_str_id, "clr.log"); _cache_cds_path = JBoosterManager::calc_cache_path(_cache_dir_path, _program_str_id, "cds.jsa"); - _cache_aot_path = JBoosterManager::calc_cache_path(_cache_dir_path, _program_str_id, "aot.so"); + const char* aot_path_suffix = _allow_pgo ? "aot-pgo.so" : "aot.so"; + _cache_aot_path = JBoosterManager::calc_cache_path(_cache_dir_path, _program_str_id, aot_path_suffix); } void ClientDataManager::init_client_duty() { @@ -142,11 +145,22 @@ jint ClientDataManager::init_cds_options() { jint ClientDataManager::init_aot_options() { if (!is_aot_allowed()) return JNI_OK; + if (FLAG_SET_CMDLINE(UseAOT, true) != JVMFlag::SUCCESS) { + return JNI_EINVAL; + } + if (is_aot_being_used()) { + if (FLAG_SET_CMDLINE(AOTLibrary, cache_aot_path()) != JVMFlag::SUCCESS) { + return JNI_EINVAL; + } + } return JNI_OK; } jint ClientDataManager::init_pgo_options() { if (!is_pgo_allowed()) return JNI_OK; + if (FLAG_SET_CMDLINE(TypeProfileWidth, 8) != JVMFlag::SUCCESS) { + return JNI_EINVAL; + } return JNI_OK; } diff --git a/src/hotspot/share/jbooster/client/clientDataManager.hpp b/src/hotspot/share/jbooster/client/clientDataManager.hpp index 0a778a07e..07be0dc2a 100644 --- a/src/hotspot/share/jbooster/client/clientDataManager.hpp +++ b/src/hotspot/share/jbooster/client/clientDataManager.hpp @@ -42,10 +42,12 @@ class ClientDataManager: public CHeapObj { bool _allow_clr; bool _allow_cds; bool _allow_aot; + bool _allow_pgo; bool _using_clr; bool _using_cds; bool _using_aot; + bool _using_pgo; const char* _cache_clr_path; const char* _cache_cds_path; @@ -103,16 +105,18 @@ public: bool is_clr_allowed() { return _allow_clr; } bool is_cds_allowed() { return _allow_cds; } bool is_aot_allowed() { return _allow_aot; } + bool is_pgo_allowed() { return _allow_pgo; } bool is_clr_being_used() { return _using_clr; } bool is_cds_being_used() { return _using_cds; } bool is_aot_being_used() { return _using_aot; } + bool is_pgo_being_used() { return _using_pgo; } // /client/cache--clr.log const char* cache_clr_path() { return _cache_clr_path; } // /client/cache--cds.jsa const char* cache_cds_path() { return _cache_cds_path; } - // /client/cache--aot.so + // /client/cache--aot[-pgo].so const char* cache_aot_path() { return _cache_aot_path; } uint32_t session_id() { return _session_id; } diff --git a/src/hotspot/share/jbooster/jClientArguments.cpp b/src/hotspot/share/jbooster/jClientArguments.cpp index 2c32b6482..1ae91674f 100644 --- a/src/hotspot/share/jbooster/jClientArguments.cpp +++ b/src/hotspot/share/jbooster/jClientArguments.cpp @@ -212,6 +212,7 @@ void JClientArguments::init_for_client() { _jbooster_allow_clr = ClientDataManager::get().is_clr_allowed(); _jbooster_allow_cds = ClientDataManager::get().is_cds_allowed(); _jbooster_allow_aot = ClientDataManager::get().is_aot_allowed(); + _jbooster_allow_pgo = ClientDataManager::get().is_pgo_allowed(); _related_flags = new JClientVMFlags(true); _hash = calc_hash(); @@ -234,6 +235,7 @@ uint32_t JClientArguments::calc_hash() { result = calc_new_hash(result, primitive_hash(_jbooster_allow_clr)); result = calc_new_hash(result, primitive_hash(_jbooster_allow_cds)); result = calc_new_hash(result, primitive_hash(_jbooster_allow_aot)); + result = calc_new_hash(result, primitive_hash(_jbooster_allow_pgo)); result = calc_new_hash(result, _related_flags->hash(_jbooster_allow_clr, _jbooster_allow_cds, _jbooster_allow_aot)); return result; @@ -309,6 +311,7 @@ int JClientArguments::serialize(MessageBuffer& buf) const { JB_RETURN(buf.serialize_no_meta(_jbooster_allow_clr)); JB_RETURN(buf.serialize_no_meta(_jbooster_allow_cds)); JB_RETURN(buf.serialize_no_meta(_jbooster_allow_aot)); + JB_RETURN(buf.serialize_no_meta(_jbooster_allow_pgo)); JB_RETURN(buf.serialize_with_meta(_related_flags)); JB_RETURN(buf.serialize_no_meta(_hash)); @@ -351,6 +354,7 @@ int JClientArguments::deserialize(MessageBuffer& buf) { JB_RETURN(buf.deserialize_ref_no_meta(_jbooster_allow_clr)); JB_RETURN(buf.deserialize_ref_no_meta(_jbooster_allow_cds)); JB_RETURN(buf.deserialize_ref_no_meta(_jbooster_allow_aot)); + JB_RETURN(buf.deserialize_ref_no_meta(_jbooster_allow_pgo)); _related_flags = new JClientVMFlags(false); JB_RETURN(buf.deserialize_with_meta(_related_flags)); diff --git a/src/hotspot/share/jbooster/jClientArguments.hpp b/src/hotspot/share/jbooster/jClientArguments.hpp index e3574db02..7a0db1738 100644 --- a/src/hotspot/share/jbooster/jClientArguments.hpp +++ b/src/hotspot/share/jbooster/jClientArguments.hpp @@ -67,6 +67,7 @@ private: bool _jbooster_allow_clr; bool _jbooster_allow_cds; bool _jbooster_allow_aot; + bool _jbooster_allow_pgo; JClientVMFlags* _related_flags; // ========================= end ========================= diff --git a/src/hotspot/share/jbooster/jClientVMFlags.hpp b/src/hotspot/share/jbooster/jClientVMFlags.hpp index 3cdbc59cf..71da58934 100644 --- a/src/hotspot/share/jbooster/jClientVMFlags.hpp +++ b/src/hotspot/share/jbooster/jClientVMFlags.hpp @@ -56,6 +56,8 @@ f(intx, MaxVectorSize ) \ f(bool, UseTLAB ) \ f(bool, UseG1GC ) \ + f(bool, BytecodeVerificationLocal ) \ + f(bool, BytecodeVerificationRemote ) \ #define JCLIENT_VM_FLAGS(f) \ JCLIENT_CDS_VM_FLAGS(f) \ diff --git a/src/hotspot/share/jbooster/jbooster_globals.hpp b/src/hotspot/share/jbooster/jbooster_globals.hpp index 45aa00db5..e9ba39e2d 100644 --- a/src/hotspot/share/jbooster/jbooster_globals.hpp +++ b/src/hotspot/share/jbooster/jbooster_globals.hpp @@ -83,7 +83,7 @@ range(0, 4) \ \ product(ccstr, UseBoostPackages, "all", DIAGNOSTIC, \ - "\"all\" means \"aot+cds+clr\".") \ + "\"all\" means \"aot+cds+clr+pgo\".") \ \ product(bool, JBoosterClientStrictMatch, false, DIAGNOSTIC, \ "Be strict when matching the client data.") \ diff --git a/src/hotspot/share/jbooster/lazyAot.cpp b/src/hotspot/share/jbooster/lazyAot.cpp index ca79f1816..91c570328 100644 --- a/src/hotspot/share/jbooster/lazyAot.cpp +++ b/src/hotspot/share/jbooster/lazyAot.cpp @@ -31,7 +31,7 @@ #include "jbooster/lazyAot.hpp" #include "jbooster/server/serverDataManager.hpp" #include "jbooster/utilities/debugUtils.hpp" -#include "jbooster/utilities/ptrHashSet.inline.hpp" +#include "jbooster/utilities/scalarHashMap.inline.hpp" #include "memory/resourceArea.inline.hpp" #include "oops/instanceKlass.inline.hpp" #include "oops/method.inline.hpp" @@ -48,6 +48,22 @@ enum { INITIALIZED_KLASSES }; +ClassLoaderKeepAliveMark::~ClassLoaderKeepAliveMark() { + for (GrowableArrayIterator iter = _handles.begin(); iter != _handles.end(); ++iter) { + (*iter).release(Universe::vm_global()); + } +} + +void ClassLoaderKeepAliveMark::add(ClassLoaderData* cld){ + _handles.append(OopHandle(Universe::vm_global(), cld->holder_phantom())); +} + +void ClassLoaderKeepAliveMark::add_all(GrowableArray* clds){ + for (GrowableArrayIterator iter = clds->begin(); iter != clds->end(); ++iter) { + add(*iter); + } +} + InstanceKlass* LazyAOT::get_klass_from_class_tag(const constantPoolHandle& cp, int index, Handle loader, @@ -65,12 +81,14 @@ InstanceKlass* LazyAOT::get_klass_from_class_tag(const constantPoolHandle& cp, Symbol* name = cp->symbol_at(name_index); klass = SystemDictionary::resolve_or_fail(name, loader, Handle(), true, THREAD); if (HAS_PENDING_EXCEPTION) { - log_trace(jbooster, compilation)("Class in constant pool not found: " - "class=\"%s\", loader=\"%s\", holder=\"%s\"", - name->as_C_string(), - ClassLoaderData::class_loader_data_or_null(loader()) - ->loader_name(), - cp->pool_holder()->internal_name()); + if (PENDING_EXCEPTION->is_a(vmClasses::OutOfMemoryError_klass())) return nullptr; + LogTarget(Trace, jbooster, compilation) lt; + if (lt.is_enabled()) { + lt.print("Class in constant pool not found: class=\"%s\", loader=\"%s\", holder=\"%s\"", + name->as_C_string(), + ClassLoaderData::class_loader_data_or_null(loader())->loader_name(), + cp->pool_holder()->internal_name()); + } CLEAR_PENDING_EXCEPTION; return nullptr; } @@ -107,13 +125,16 @@ void LazyAOT::get_klasses_from_name_and_type_tag(const constantPoolHandle& cp, : SignatureStream::CachedOrNull; Klass* klass = ss.as_klass(loader, Handle(), mode, THREAD); if (HAS_PENDING_EXCEPTION) { - ResourceMark rm; - log_trace(jbooster, compilation)("Class in constant pool not found: " - "method=\"%s\", loader=\"%s\", holder=\"%s\"", - sym->as_C_string(), - ClassLoaderData::class_loader_data_or_null(loader()) - ->loader_name(), - cp->pool_holder()->internal_name()); + if (PENDING_EXCEPTION->is_a(vmClasses::OutOfMemoryError_klass())) return; + LogTarget(Trace, jbooster, compilation) lt; + if (lt.is_enabled()) { + ResourceMark rm; + lt.print("Class in constant pool not found: method=\"%s\", loader=\"%s\", holder=\"%s\"", + sym->as_C_string(), + ClassLoaderData::class_loader_data_or_null(loader()) + ->loader_name(), + cp->pool_holder()->internal_name()); + } CLEAR_PENDING_EXCEPTION; continue; } @@ -128,24 +149,24 @@ void LazyAOT::get_klasses_from_name_and_type_tag(const constantPoolHandle& cp, } void LazyAOT::collect_klasses_by_inheritance(GrowableArray* dst, - PtrHashSet* vis, + ScalarHashSet* vis, InstanceKlass* ik, TRAPS) { if (!vis->add(ik)) return; InstanceKlass* super = ik->java_super(); if (super != nullptr) { - collect_klasses_by_inheritance(dst, vis, super, THREAD); + collect_klasses_by_inheritance(dst, vis, super, CHECK); } Array* interfaces = ik->local_interfaces(); for (int i = 0; i < interfaces->length(); ++i) { InstanceKlass* interface = interfaces->at(i); - collect_klasses_by_inheritance(dst, vis, interface, THREAD); + collect_klasses_by_inheritance(dst, vis, interface, CHECK); } dst->append(ik); } void LazyAOT::collect_klasses_in_constant_pool(GrowableArray* dst, - PtrHashSet* vis, + ScalarHashSet* vis, InstanceKlass* ik, int which_klasses, TRAPS) { @@ -154,31 +175,31 @@ void LazyAOT::collect_klasses_in_constant_pool(GrowableArray* ds for (int i = 0; i < cp->length(); ++i) { constantTag tag = cp->tag_at(i); if (tag.is_unresolved_klass() || tag.is_klass()) { - InstanceKlass* next = get_klass_from_class_tag(cp, i, class_loader, which_klasses, THREAD); + InstanceKlass* next = get_klass_from_class_tag(cp, i, class_loader, which_klasses, CHECK); if (next != nullptr) { // next is null when it is not a InstanceKlass - collect_klasses_by_inheritance(dst, vis, next, THREAD); + collect_klasses_by_inheritance(dst, vis, next, CHECK); } } else if (tag.is_name_and_type()) { GrowableArray next_list; - get_klasses_from_name_and_type_tag(cp, i, class_loader, next_list, which_klasses, THREAD); + get_klasses_from_name_and_type_tag(cp, i, class_loader, next_list, which_klasses, CHECK); for (GrowableArrayIterator iter = next_list.begin(); iter != next_list.end(); ++iter) { - collect_klasses_by_inheritance(dst, vis, *iter, THREAD); + collect_klasses_by_inheritance(dst, vis, *iter, CHECK); } } } } void LazyAOT::collect_klasses_in_constant_pool(GrowableArray* dst, - PtrHashSet* vis, + ScalarHashSet* vis, TRAPS) { int last_len = 0; for (int lvl = _compilation_related_klasses_layers; lvl > 0; --lvl) { int len = dst->length(); for (int i = last_len; i < len; ++i) { ThreadInVMfromNative tiv(THREAD); - collect_klasses_in_constant_pool(dst, vis, dst->at(i), ALL_KLASSES, THREAD); + collect_klasses_in_constant_pool(dst, vis, dst->at(i), ALL_KLASSES, CHECK); } last_len = len; } @@ -186,10 +207,10 @@ void LazyAOT::collect_klasses_in_constant_pool(GrowableArray* ds void LazyAOT::collect_klasses_in_method_data(GrowableArray* dst_ik, GrowableArray* dst_ak, - PtrHashSet* ik_vis, + ScalarHashSet* ik_vis, TRAPS) { int last_len = 0; - PtrHashSet ak_vis; + ScalarHashSet ak_vis; for (int lvl = _compilation_related_klasses_layers; lvl > 0; --lvl) { int len = dst_ik->length(); for (int i = last_len; i < len; ++i) { @@ -198,7 +219,7 @@ void LazyAOT::collect_klasses_in_method_data(GrowableArray* dst_ MethodData* method_data = methods->at(j)->method_data(); if (method_data != nullptr) { collect_klasses_in_method_data(dst_ik, dst_ak, ik_vis, &ak_vis, - method_data, ALL_KLASSES, THREAD); + method_data, ALL_KLASSES, CHECK); } } } @@ -208,8 +229,8 @@ void LazyAOT::collect_klasses_in_method_data(GrowableArray* dst_ void LazyAOT::collect_klasses_in_method_data(GrowableArray* dst_ik, GrowableArray* dst_ak, - PtrHashSet* ik_vis, - PtrHashSet* ak_vis, + ScalarHashSet* ik_vis, + ScalarHashSet* ak_vis, MethodData* method_data, int which_klasses, TRAPS) { @@ -225,7 +246,7 @@ void LazyAOT::collect_klasses_in_method_data(GrowableArray* dst_ if (which_klasses == INITIALIZED_KLASSES && !(*iter)->is_initialized()) { continue; } - collect_klasses_by_inheritance(dst_ik, ik_vis, *iter, THREAD); + collect_klasses_by_inheritance(dst_ik, ik_vis, *iter, CHECK); } for (GrowableArrayIterator iter = ak_array.begin(); iter != ak_array.end(); @@ -237,26 +258,25 @@ void LazyAOT::collect_klasses_in_method_data(GrowableArray* dst_ } } -bool LazyAOT::sort_klasses_by_inheritance(GrowableArray* dst_ik, +void LazyAOT::sort_klasses_by_inheritance(GrowableArray* dst_ik, GrowableArray* dst_ak, GrowableArray* src, bool reverse_scan_src, TRAPS) { - PtrHashSet visited; + ScalarHashSet visited; if (reverse_scan_src) { for (int i = src->length() - 1; i >= 0; --i) { - collect_klasses_by_inheritance(dst_ik, &visited, src->at(i), THREAD); + collect_klasses_by_inheritance(dst_ik, &visited, src->at(i), CHECK); } } else { for (GrowableArrayIterator iter = src->begin(); iter != src->end(); ++iter) { - collect_klasses_by_inheritance(dst_ik, &visited, *iter, THREAD); + collect_klasses_by_inheritance(dst_ik, &visited, *iter, CHECK); } } - collect_klasses_in_constant_pool(dst_ik, &visited, THREAD); - collect_klasses_in_method_data(dst_ik, dst_ak, &visited, THREAD); - return true; + collect_klasses_in_constant_pool(dst_ik, &visited, CHECK); + collect_klasses_in_method_data(dst_ik, dst_ak, &visited, CHECK); } bool LazyAOT::can_be_compiled(const methodHandle& mh) { @@ -280,17 +300,17 @@ bool LazyAOT::can_be_compiled(InstanceKlass* ik, bool check_cld) { } bool LazyAOT::can_be_compiled(ClassLoaderData* cld) { - oop loader_oop = cld->class_loader(); + Handle loader_h(JavaThread::current(), cld->class_loader()); // Skip the bootstrap loaders used by LambdaForm. // Each LambdaForm has its own bootstrap class loader. // @see ClassLoaderData::is_boot_class_loader_data() if (cld->is_the_null_class_loader_data()) return true; - if (loader_oop == nullptr) return false; + if (loader_h.is_null()) return false; // Skip klasses like GeneratedMethodAccessor, GeneratedConstructorAccessor // and GeneratedSerializationConstructorAccessor. - if (loader_oop->is_a(vmClasses::reflect_DelegatingClassLoader_klass())) { + if (loader_h->is_a(vmClasses::reflect_DelegatingClassLoader_klass())) { return false; } @@ -372,7 +392,7 @@ private: BOOL_TO_STR(LazyAOT::can_be_compiled(cld))); tty->print_cr(" -"); } - if (LazyAOT::can_be_compiled(cld)) { + if (!cld->has_class_mirror_holder() && LazyAOT::can_be_compiled(cld)) { if (_loaders != nullptr) _loaders->append(cld); KlassGetAllInstanceKlassesClosure cl(_klasses, _methods_to_compile, _methods_not_compile); cld->classes_do(&cl); @@ -393,7 +413,8 @@ public: void do_cld(ClassLoaderData* cld) override { for_each(cld); } }; -void LazyAOT::collect_all_klasses_to_compile(GrowableArray* all_loaders, +void LazyAOT::collect_all_klasses_to_compile(ClassLoaderKeepAliveMark& clka, + GrowableArray* all_loaders, GrowableArray* klasses_to_compile, GrowableArray* methods_to_compile, GrowableArray* methods_not_compile, @@ -406,11 +427,12 @@ void LazyAOT::collect_all_klasses_to_compile(GrowableArray* al CLDGetAllInstanceKlassesClosure cl(all_loaders, klasses_to_compile, methods_to_compile, methods_not_compile); ThreadInVMfromNative tivm(THREAD); MutexLocker ml(THREAD, ClassLoaderDataGraph_lock); - ClassLoaderDataGraph::cld_do(&cl); + ClassLoaderDataGraph::loaded_cld_do(&cl); + clka.add_all(all_loaders); } TraceTime tt("Sort klasses", TRACETIME_LOG(Info, jbooster, aot)); sort_klasses_by_inheritance(all_sorted_klasses, array_klasses, klasses_to_compile, - /* reverse_scan_src */ true, CATCH); + /* reverse_scan_src */ true, CHECK); } log_info(jbooster, compilation)("Klasses to send: %d", all_sorted_klasses->length()); log_info(jbooster, compilation)("Klasses to compile: %d", klasses_to_compile->length()); @@ -443,7 +465,6 @@ static Handle add_klasses_to_java_hash_set(GrowableArray* klasse vmSymbols::object_boolean_signature(), Handle(THREAD, (*iter)->java_mirror()), CHECK_NH); - guarantee((bool)result.get_jboolean() == true, "sanity"); } return hash_set_h; } @@ -467,7 +488,6 @@ static Handle add_methods_names_to_java_hash_set(GrowableArray* methods vmSymbols::add_method_name(), vmSymbols::object_boolean_signature(), s_h, CHECK_NH); - guarantee((bool)result.get_jboolean() == true, "sanity"); } return hash_set_h; } @@ -475,6 +495,7 @@ static Handle add_methods_names_to_java_hash_set(GrowableArray* methods bool LazyAOT::compile_classes_by_graal(int session_id, const char* file_path, GrowableArray* klasses, + bool use_pgo, TRAPS) { DebugUtils::assert_thread_in_vm(); @@ -504,6 +525,7 @@ bool LazyAOT::compile_methods_by_graal(int session_id, GrowableArray* klasses, GrowableArray* methods_to_compile, GrowableArray* methods_not_compile, + bool use_pgo, TRAPS) { DebugUtils::assert_thread_in_vm(); @@ -526,9 +548,10 @@ bool LazyAOT::compile_methods_by_graal(int session_id, java_args.push_oop(klass_set_h); java_args.push_oop(method_name_set_h); java_args.push_oop(not_method_name_set_h); + java_args.push_int(use_pgo); TempNewSymbol compile_methods_name = SymbolTable::new_symbol("compileMethods"); - TempNewSymbol compile_methods_signature = SymbolTable::new_symbol("(ILjava/lang/String;Ljava/util/Set;Ljava/util/Set;Ljava/util/Set;)Z"); + TempNewSymbol compile_methods_signature = SymbolTable::new_symbol("(ILjava/lang/String;Ljava/util/Set;Ljava/util/Set;Ljava/util/Set;Z)Z"); JavaCalls::call_static(&result, ServerDataManager::get().main_klass(), compile_methods_name, compile_methods_signature, diff --git a/src/hotspot/share/jbooster/lazyAot.hpp b/src/hotspot/share/jbooster/lazyAot.hpp index f9adc6596..1d2a49351 100644 --- a/src/hotspot/share/jbooster/lazyAot.hpp +++ b/src/hotspot/share/jbooster/lazyAot.hpp @@ -24,7 +24,7 @@ #ifndef SHARE_JBOOSTER_LAZYAOT_HPP #define SHARE_JBOOSTER_LAZYAOT_HPP -#include "jbooster/utilities/ptrHashSet.hpp" +#include "jbooster/utilities/scalarHashMap.hpp" #include "memory/allocation.hpp" #include "runtime/handles.hpp" #include "runtime/thread.hpp" @@ -36,6 +36,17 @@ template class GrowableArray; class InstanceKlass; class Method; class MethodData; +class OopHandle; + +class ClassLoaderKeepAliveMark: public StackObj { + GrowableArray _handles; + +public: + ~ClassLoaderKeepAliveMark(); + + void add(ClassLoaderData* cld); + void add_all(GrowableArray* clds); +}; class LazyAOT: public AllStatic { private: @@ -55,29 +66,29 @@ private: TRAPS); static void collect_klasses_by_inheritance(GrowableArray* dst, - PtrHashSet* vis, + ScalarHashSet* vis, InstanceKlass* ik, TRAPS); static void collect_klasses_in_constant_pool(GrowableArray* dst, - PtrHashSet* vis, + ScalarHashSet* vis, InstanceKlass* ik, int which_klasses, TRAPS); static void collect_klasses_in_constant_pool(GrowableArray* dst, - PtrHashSet* vis, + ScalarHashSet* vis, TRAPS); static void collect_klasses_in_method_data(GrowableArray* dst_ik, GrowableArray* dst_ak, - PtrHashSet* ik_vis, + ScalarHashSet* ik_vis, TRAPS); static void collect_klasses_in_method_data(GrowableArray* dst_ik, GrowableArray* dst_ak, - PtrHashSet* ik_vis, - PtrHashSet* ak_vis, + ScalarHashSet* ik_vis, + ScalarHashSet* ak_vis, MethodData* method_data, int which_klasses, TRAPS); - static bool sort_klasses_by_inheritance(GrowableArray* dst_ik, + static void sort_klasses_by_inheritance(GrowableArray* dst_ik, GrowableArray* dst_ak, GrowableArray* src, bool reverse_scan_src, @@ -88,7 +99,8 @@ public: static bool can_be_compiled(InstanceKlass* ik, bool check_cld = true); static bool can_be_compiled(ClassLoaderData* cld); - static void collect_all_klasses_to_compile(GrowableArray* all_loaders, + static void collect_all_klasses_to_compile(ClassLoaderKeepAliveMark& clka, + GrowableArray* all_loaders, GrowableArray* klasses_to_compile, GrowableArray* methods_to_compile, GrowableArray* methods_not_compile, @@ -99,12 +111,14 @@ public: static bool compile_classes_by_graal(int session_id, const char* file_path, GrowableArray* klasses, + bool use_pgo, TRAPS); static bool compile_methods_by_graal(int session_id, const char* file_path, GrowableArray* klasses, GrowableArray* methods_to_compile, GrowableArray* methods_not_compile, + bool use_pgo, TRAPS); }; diff --git a/src/hotspot/share/jbooster/net/serialization.cpp b/src/hotspot/share/jbooster/net/serialization.cpp index b0db65e68..d95edd7df 100644 --- a/src/hotspot/share/jbooster/net/serialization.cpp +++ b/src/hotspot/share/jbooster/net/serialization.cpp @@ -136,6 +136,12 @@ int SerializationImpl::serialize(MessageBuffer& buf, const Instan } MemoryWrapper mw((void*) cf_buf, cf_size); JB_RETURN(buf.serialize_no_meta(mw)); + + if (should_send_class_file) { + // fingerprint of ClassFileStream + InstanceKlass* ik = const_cast(&arg); + JB_RETURN(buf.serialize_no_meta(ik->get_stored_fingerprint())); + } } return 0; @@ -269,6 +275,16 @@ int SerializationImpl::deserialize_ptr(MessageBuffer& buf, Instan session_data->add_klass_address((address) client_klass, (address) res, THREAD); arg_ptr = res; } + + if (!mw.is_null()) { + // fingerprint of ClassFileStream + uint64_t fingerprint; + JB_RETURN(buf.deserialize_ref_no_meta(fingerprint)); + if (res != nullptr) { + // force to set the fingerprint that from client + res->store_fingerprint(fingerprint); + } + } return 0; } diff --git a/src/hotspot/share/jbooster/server/serverDataManager.cpp b/src/hotspot/share/jbooster/server/serverDataManager.cpp index b4a11dc5c..33d6faf4c 100644 --- a/src/hotspot/share/jbooster/server/serverDataManager.cpp +++ b/src/hotspot/share/jbooster/server/serverDataManager.cpp @@ -279,12 +279,15 @@ JClientProgramData::JClientProgramData(uint32_t program_id, JClientArguments* pr bool allow_clr = _program_args->jbooster_allow_clr(); bool allow_cds = _program_args->jbooster_allow_cds(); bool allow_aot = _program_args->jbooster_allow_aot(); + bool allow_pgo = _program_args->jbooster_allow_pgo(); const char* clr_path = JBoosterManager::calc_cache_path(sd, _program_str_id, "clr.log"); const char* cds_path = JBoosterManager::calc_cache_path(sd, _program_str_id, "cds.jsa"); - const char* aot_path = JBoosterManager::calc_cache_path(sd, _program_str_id, "aot.so"); + const char* aot_path_suffix = allow_pgo ? "aot-pgo.so" : "aot.so"; + const char* aot_path = JBoosterManager::calc_cache_path(sd, _program_str_id, aot_path_suffix); clr_cache_state().init(allow_clr, clr_path); cds_cache_state().init(allow_cds, cds_path); aot_cache_state().init(allow_aot, aot_path); + _using_pgo = allow_pgo; } JClientProgramData::~JClientProgramData() { diff --git a/src/hotspot/share/jbooster/server/serverDataManager.hpp b/src/hotspot/share/jbooster/server/serverDataManager.hpp index 22b416cd9..9181acd10 100644 --- a/src/hotspot/share/jbooster/server/serverDataManager.hpp +++ b/src/hotspot/share/jbooster/server/serverDataManager.hpp @@ -191,6 +191,8 @@ private: JClientCacheState _cds_cache_state; JClientCacheState _aot_cache_state; + bool _using_pgo; // use pgo if or not, as boost level 4 + NONCOPYABLE(JClientProgramData); public: @@ -211,6 +213,7 @@ public: JClientCacheState& clr_cache_state() { return _clr_cache_state; } JClientCacheState& cds_cache_state() { return _cds_cache_state; } JClientCacheState& aot_cache_state() { return _aot_cache_state; } + bool using_pgo() { return _using_pgo; } }; /** diff --git a/src/hotspot/share/jbooster/server/serverMessageHandler.cpp b/src/hotspot/share/jbooster/server/serverMessageHandler.cpp index 9e66b6d4c..a92d1c6a4 100644 --- a/src/hotspot/share/jbooster/server/serverMessageHandler.cpp +++ b/src/hotspot/share/jbooster/server/serverMessageHandler.cpp @@ -321,8 +321,10 @@ int ServerMessageHandler::handle_lazy_aot_compilation_task(TRAPS) { JB_THROW(request_missing_class_loaders(THREAD)); JB_THROW(request_missing_klasses(THREAD)); JB_THROW(request_methods_to_compile(&klasses_to_compile, &methods_to_compile, THREAD)); - JB_THROW(request_methods_not_compile(&methods_not_compile, THREAD)); - JB_THROW(request_method_data(THREAD)); + if (pd->using_pgo()) { + JB_THROW(request_methods_not_compile(&methods_not_compile, THREAD)); + JB_THROW(request_method_data(THREAD)); + } JB_THROW(ss().send_request(MessageType::EndOfCurrentPhase)); } } JB_TRY_END JB_CATCH_REST() { @@ -336,6 +338,7 @@ int ServerMessageHandler::handle_lazy_aot_compilation_task(TRAPS) { JB_RETURN(try_to_compile_lazy_aot(&klasses_to_compile, &methods_to_compile, &methods_not_compile, + pd->using_pgo(), THREAD)); } else { // not compile in current thread if (aot_cache_state.is_being_generated()) { @@ -356,6 +359,7 @@ int ServerMessageHandler::handle_lazy_aot_compilation_task(TRAPS) { int ServerMessageHandler::try_to_compile_lazy_aot(GrowableArray* klasses_to_compile, GrowableArray* methods_to_compile, GrowableArray* methods_not_compile, + bool use_pgo, TRAPS) { JClientProgramData* pd = ss().session_data()->program_data(); JClientCacheState& aot_cache_state = pd->aot_cache_state(); diff --git a/src/hotspot/share/jbooster/server/serverMessageHandler.hpp b/src/hotspot/share/jbooster/server/serverMessageHandler.hpp index 6d510c6ca..26926dd41 100644 --- a/src/hotspot/share/jbooster/server/serverMessageHandler.hpp +++ b/src/hotspot/share/jbooster/server/serverMessageHandler.hpp @@ -59,6 +59,7 @@ private: int try_to_compile_lazy_aot(GrowableArray* klasses_to_compile, GrowableArray* methods_to_compile, GrowableArray* methods_not_compile, + bool use_pgo, TRAPS); public: ServerMessageHandler(ServerStream* server_stream); diff --git a/src/hotspot/share/oops/compressedOops.cpp b/src/hotspot/share/oops/compressedOops.cpp index 03dbf5966..a9ee02efc 100644 --- a/src/hotspot/share/oops/compressedOops.cpp +++ b/src/hotspot/share/oops/compressedOops.cpp @@ -243,25 +243,39 @@ void CompressedKlassPointers::initialize(address addr, size_t len) { range = 4 * G; } else { +#if defined(AARCH64) && INCLUDE_AOT + if (UseAOT && AOTLoader::libraries_count() > 0) { + constexpr uint64_t unscaled_max = nth_bit(32); + assert(len <= unscaled_max, "Klass range larger than 32 bits?"); - // Otherwise we attempt to use a zero base if the range fits in lower 32G. - if (end <= (address)KlassEncodingMetaspaceMax) { - base = 0; - } else { - base = addr; - } - - // Highest offset a Klass* can ever have in relation to base. - range = end - base; - - // We may not even need a shift if the range fits into 32bit: - const uint64_t UnscaledClassSpaceMax = (uint64_t(max_juint) + 1); - if (range < UnscaledClassSpaceMax) { + // Shift is always 0 on aarch64(AOT enabled). shift = 0; - } else { - shift = LogKlassAlignmentInBytes; - } + // On aarch64(AOT enabled), we don't bother with zero-based encoding (base=0 shift>0). + base = (end <= (address)unscaled_max) ? nullptr : addr; + + range = end - base; + } else +#endif // defined(AARCH64) && INCLUDE_AOT + { + // Otherwise we attempt to use a zero base if the range fits in lower 32G. + if (end <= (address)KlassEncodingMetaspaceMax) { + base = 0; + } else { + base = addr; + } + + // Highest offset a Klass* can ever have in relation to base. + range = end - base; + + // We may not even need a shift if the range fits into 32bit: + const uint64_t UnscaledClassSpaceMax = (uint64_t(max_juint) + 1); + if (range < UnscaledClassSpaceMax) { + shift = 0; + } else { + shift = LogKlassAlignmentInBytes; + } + } } set_base(base); diff --git a/src/hotspot/share/oops/instanceKlass.hpp b/src/hotspot/share/oops/instanceKlass.hpp index 047b81a0c..9d798972e 100644 --- a/src/hotspot/share/oops/instanceKlass.hpp +++ b/src/hotspot/share/oops/instanceKlass.hpp @@ -1072,7 +1072,7 @@ public: nonstatic_oop_map_size + (is_interface ? (int)sizeof(Klass*)/wordSize : 0) + (has_stored_fingerprint ? (int)sizeof(uint64_t*)/wordSize : 0) + - AOT_ONLY(sizeof(u1)) NOT_AOT(0)); + AOT_ONLY((int)align_up(sizeof(u1),wordSize)/wordSize) NOT_AOT(0)); } int size() const { return size(vtable_length(), diff --git a/src/hotspot/share/oops/method.cpp b/src/hotspot/share/oops/method.cpp index fa3a2f2db..c52a7e1e6 100644 --- a/src/hotspot/share/oops/method.cpp +++ b/src/hotspot/share/oops/method.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2023, 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 @@ -104,6 +104,9 @@ Method::Method(ConstMethod* xconst, AccessFlags access_flags) { set_hidden(false); set_dont_inline(false); set_has_injected_profile(false); +#if INCLUDE_JBOOSTER + set_rewrite_invokehandle(false); +#endif set_method_data(NULL); clear_method_counters(); set_vtable_index(Method::garbage_vtable_index); @@ -1170,6 +1173,10 @@ void Method::unlink_method() { _from_compiled_entry = NULL; _from_interpreted_entry = NULL; +#if INCLUDE_AOT + _aot_code = NULL; +#endif + if (is_native()) { *native_function_addr() = NULL; set_signature_handler(NULL); diff --git a/src/hotspot/share/oops/methodData.cpp b/src/hotspot/share/oops/methodData.cpp index 266c48a5e..58432f1eb 100644 --- a/src/hotspot/share/oops/methodData.cpp +++ b/src/hotspot/share/oops/methodData.cpp @@ -1975,7 +1975,7 @@ MethodData* MethodData::create_instance_for_jbooster(Method* method, int size, c // memcpy int start = in_bytes(byte_offset_of(MethodData, _method)) + sizeof(res->_method); - memcpy((void*) (((char*) res) + start), mem + start, size); + memcpy((void*) (((char*) res) + start), mem + start, size - start); // restore memcpy((void*) &res->_extra_data_lock, lock_bak, sizeof(res->_extra_data_lock)); diff --git a/src/hotspot/share/prims/jvm.cpp b/src/hotspot/share/prims/jvm.cpp index 8ceca7cd3..0d501e494 100644 --- a/src/hotspot/share/prims/jvm.cpp +++ b/src/hotspot/share/prims/jvm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2023, 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 @@ -3882,6 +3882,15 @@ JVM_ENTRY(void, JVM_JBoosterPrintStoredClientData(JNIEnv *env, jboolean print_al #endif // INCLUDE_JBOOSTER JVM_END +JVM_ENTRY(jlong, JVM_JBoosterGetMetaspaceMethodData(JNIEnv *env, jint session_id, jlong metaspace_method)) +#if INCLUDE_JBOOSTER + TempJClientSessionData session_data = ServerDataManager::get().get_session(session_id, THREAD); + return (jlong) session_data->method_data_address((address) metaspace_method, THREAD); +#else + return 0; +#endif // INCLUDE_JBOOSTER +JVM_END + JVM_ENTRY(void, JVM_JBoosterStartupNativeCallback(JNIEnv *env)) #if INCLUDE_JBOOSTER if (!UseJBooster) return; diff --git a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp index c4c03ab8d..1c52bb06a 100644 --- a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp +++ b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp @@ -4432,7 +4432,7 @@ void VM_RedefineClasses::redefine_single_class(Thread* current, jclass the_jclas if (!the_class->should_be_initialized()) { // Class was already initialized, so AOT has only seen the original version. // We need to let AOT look at it again. - AOTLoader::load_for_klass(the_class, current->as_Java_thread()); + AOTLoader::load_for_klass(the_class, current); } #endif diff --git a/src/java.base/share/lib/security/default.policy b/src/java.base/share/lib/security/default.policy index 1c58b7797..06f0307f1 100644 --- a/src/java.base/share/lib/security/default.policy +++ b/src/java.base/share/lib/security/default.policy @@ -110,6 +110,41 @@ grant codeBase "jrt:/jdk.accessibility" { permission java.lang.RuntimePermission "accessClassInPackage.sun.awt"; }; +grant codeBase "jrt:/jdk.aot" { + permission java.lang.RuntimePermission "accessClassInPackage.org.graalvm.compiler.api.directives"; + permission java.lang.RuntimePermission "accessClassInPackage.org.graalvm.compiler.api.runtime"; + permission java.lang.RuntimePermission "accessClassInPackage.org.graalvm.compiler.api.replacements"; + permission java.lang.RuntimePermission "accessClassInPackage.org.graalvm.compiler.asm.amd64"; + permission java.lang.RuntimePermission "accessClassInPackage.org.graalvm.compiler.asm.aarch64"; + permission java.lang.RuntimePermission "accessClassInPackage.org.graalvm.compiler.bytecode"; + permission java.lang.RuntimePermission "accessClassInPackage.org.graalvm.compiler.code"; + permission java.lang.RuntimePermission "accessClassInPackage.org.graalvm.compiler.core"; + permission java.lang.RuntimePermission "accessClassInPackage.org.graalvm.compiler.core.common"; + permission java.lang.RuntimePermission "accessClassInPackage.org.graalvm.compiler.core.target"; + permission java.lang.RuntimePermission "accessClassInPackage.org.graalvm.compiler.debug"; + permission java.lang.RuntimePermission "accessClassInPackage.org.graalvm.compiler.graph"; + permission java.lang.RuntimePermission "accessClassInPackage.org.graalvm.compiler.hotspot"; + permission java.lang.RuntimePermission "accessClassInPackage.org.graalvm.compiler.hotspot.meta"; + permission java.lang.RuntimePermission "accessClassInPackage.org.graalvm.compiler.hotspot.replacements"; + permission java.lang.RuntimePermission "accessClassInPackage.org.graalvm.compiler.hotspot.stubs"; + permission java.lang.RuntimePermission "accessClassInPackage.org.graalvm.compiler.hotspot.word"; + permission java.lang.RuntimePermission "accessClassInPackage.org.graalvm.compiler.java"; + permission java.lang.RuntimePermission "accessClassInPackage.org.graalvm.compiler.lir.asm"; + permission java.lang.RuntimePermission "accessClassInPackage.org.graalvm.compiler.lir.phases"; + permission java.lang.RuntimePermission "accessClassInPackage.org.graalvm.compiler.nodes"; + permission java.lang.RuntimePermission "accessClassInPackage.org.graalvm.compiler.nodes.graphbuilderconf"; + permission java.lang.RuntimePermission "accessClassInPackage.org.graalvm.compiler.options"; + permission java.lang.RuntimePermission "accessClassInPackage.org.graalvm.compiler.phases"; + permission java.lang.RuntimePermission "accessClassInPackage.org.graalvm.compiler.phases.tiers"; + permission java.lang.RuntimePermission "accessClassInPackage.org.graalvm.compiler.printer"; + permission java.lang.RuntimePermission "accessClassInPackage.org.graalvm.compiler.runtime"; + permission java.lang.RuntimePermission "accessClassInPackage.org.graalvm.compiler.replacements"; + permission java.lang.RuntimePermission "accessClassInPackage.org.graalvm.compiler.serviceprovider"; + permission java.lang.RuntimePermission "accessClassInPackage.org.graalvm.compiler.word"; + permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.vm.compiler.word"; + permission java.lang.RuntimePermission "accessClassInPackage.jdk.vm.ci.jbooster"; +}; + grant codeBase "jrt:/jdk.charsets" { permission java.util.PropertyPermission "os.name", "read"; permission java.lang.RuntimePermission "charsetProvider"; diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSection.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSection.java index 7e0168a85..8b72dad28 100644 --- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSection.java +++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSection.java @@ -31,8 +31,9 @@ import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rel; import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rela; import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Shdr; import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Sym; +import jdk.vm.ci.jbooster.JBoosterCompilationContext; -final class ElfSection { +public final class ElfSection { private final String name; private final ByteBuffer section; private final byte[] data; @@ -53,6 +54,17 @@ final class ElfSection { ElfSection(String sectName, byte[] sectData, int sectFlags, int sectType, boolean hasRelocations, int align, int sectIndex) { + JBoosterCompilationContext ctx = JBoosterCompilationContext.get(); + StringBuilder sectNameTab; + int shStrTabNrOfBytes; + if (ctx != null) { + sectNameTab = ctx.getElfSectionSectNameTab(); + shStrTabNrOfBytes = ctx.getElfSectionShStrTabNrOfBytes().get(); + } else { + sectNameTab = ElfSection.sectNameTab; + shStrTabNrOfBytes = ElfSection.shStrTabNrOfBytes; + } + section = ElfByteBuffer.allocate(Elf64_Shdr.totalsize); name = sectName; // Return all 0's for NULL section @@ -62,6 +74,12 @@ final class ElfSection { data = null; hasrelocations = false; sectionIndex = 0; + + if (ctx != null) { + ctx.getElfSectionShStrTabNrOfBytes().set(shStrTabNrOfBytes); + } else { + ElfSection.shStrTabNrOfBytes = shStrTabNrOfBytes; + } return; } @@ -103,6 +121,12 @@ final class ElfSection { hasrelocations = hasRelocations; sectionIndex = sectIndex; + + if (ctx != null) { + ctx.getElfSectionShStrTabNrOfBytes().set(shStrTabNrOfBytes); + } else { + ElfSection.shStrTabNrOfBytes = shStrTabNrOfBytes; + } } String getName() { @@ -154,4 +178,12 @@ final class ElfSection { return sectionIndex; } + public static void guaranteeStaticNotUsed() { + if (sectNameTab.length() != 0) { + throw new IllegalStateException("Static sectNameTab should be empty for JBooster!"); + } + if (shStrTabNrOfBytes != 0) { + throw new IllegalStateException("Static shStrTabNrOfBytes should be 0 for JBooster!"); + } + } } diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTBackend.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTBackend.java index 45ad9a594..eec021d5d 100644 --- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTBackend.java +++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTBackend.java @@ -50,6 +50,7 @@ import org.graalvm.compiler.phases.tiers.Suites; import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; +import jdk.vm.ci.jbooster.JBoosterCompilationContext; import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; import jdk.vm.ci.meta.DefaultProfilingInfo; import jdk.vm.ci.meta.ProfilingInfo; @@ -116,7 +117,9 @@ final class AOTBackend { @SuppressWarnings("try") private StructuredGraph buildStructuredGraph(ResolvedJavaMethod javaMethod, DebugContext debug) { try (DebugContext.Scope s = debug.scope("AOTParseMethod")) { - StructuredGraph graph = new StructuredGraph.Builder(graalOptions, debug).method(javaMethod).useProfilingInfo(false).build(); + JBoosterCompilationContext ctx = JBoosterCompilationContext.get(); + boolean useProfilingInfo = ctx != null ? ctx.usePGO() : false; + StructuredGraph graph = new StructuredGraph.Builder(graalOptions, debug).method(javaMethod).useProfilingInfo(useProfilingInfo).build(); graphBuilderSuite.apply(graph, highTierContext); return graph; } catch (Throwable e) { @@ -128,7 +131,13 @@ final class AOTBackend { @SuppressWarnings("try") private CompilationResult compileGraph(ResolvedJavaMethod resolvedMethod, StructuredGraph graph, DebugContext debug) { try (DebugContext.Scope s = debug.scope("AOTCompileMethod")) { - ProfilingInfo profilingInfo = DefaultProfilingInfo.get(TriState.FALSE); + ProfilingInfo profilingInfo; + JBoosterCompilationContext ctx = JBoosterCompilationContext.get(); + if (ctx != null && ctx.usePGO()) { + profilingInfo = resolvedMethod.getProfilingInfo(true, true); + } else { + profilingInfo = DefaultProfilingInfo.get(TriState.FALSE); + } final boolean isImmutablePIC = true; CompilationIdentifier id = new CompilationIdentifier() { diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompilationTask.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompilationTask.java index b3a72f981..b5f391ec1 100644 --- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompilationTask.java +++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompilationTask.java @@ -160,6 +160,10 @@ final class AOTCompilationTask implements Runnable, Comparable { return JVMCICompiler.INVOCATION_ENTRY_BCI; } + Main getMain() { + return main; + } + ResolvedJavaMethod getMethod() { return method; } diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiledClass.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiledClass.java index 416d332fc..0e33d5f02 100644 --- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiledClass.java +++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiledClass.java @@ -38,6 +38,7 @@ import jdk.tools.jaotc.binformat.Symbol.Binding; import jdk.tools.jaotc.binformat.Symbol.Kind; import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; +import jdk.vm.ci.jbooster.JBoosterCompilationContext; import jdk.vm.ci.meta.ResolvedJavaField; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; @@ -82,6 +83,13 @@ final class AOTCompiledClass { private String[] getMetaspaceNames() { String name = metadataName; + AOTDynamicTypeStore dynoStore; + if (JBoosterCompilationContext.get() != null) { + dynoStore = (AOTDynamicTypeStore) JBoosterCompilationContext.get() + .getAOTCompiledClassAOTDynamicTypeStore(); + } else { + dynoStore = AOTCompiledClass.dynoStore; + } Set locs = dynoStore.getDynamicClassLocationsForType(type); if (locs == null) { return new String[]{name}; @@ -263,6 +271,9 @@ final class AOTCompiledClass { * Get the number of all AOT classes. */ static int getClassesCount() { + if (JBoosterCompilationContext.get() != null) { + return JBoosterCompilationContext.get().getAOTCompiledClassClassesCount().get(); + } return classesCount; } @@ -322,7 +333,19 @@ final class AOTCompiledClass { static synchronized AOTKlassData addAOTKlassData(BinaryContainer binaryContainer, HotSpotResolvedObjectType type) { AOTKlassData data = getAOTKlassData(type); if (data == null) { - data = new AOTKlassData(binaryContainer, type, classesCount++); + int cnt; + HashMap klassData; + JBoosterCompilationContext ctx = JBoosterCompilationContext.get(); + if (ctx != null) { + cnt = ctx.getAOTCompiledClassClassesCount().getAndIncrement(); + @SuppressWarnings({"unchecked"}) + HashMap kd = (HashMap) ctx.getAOTCompiledClassKlassData(); + klassData = kd; + } else { + cnt = classesCount++; + klassData = AOTCompiledClass.klassData; + } + data = new AOTKlassData(binaryContainer, type, cnt); klassData.put(type.getName(), data); } return data; @@ -330,6 +353,15 @@ final class AOTCompiledClass { static synchronized AOTKlassData getAOTKlassData(HotSpotResolvedObjectType type) { String name = type.getName(); + HashMap klassData; + JBoosterCompilationContext ctx = JBoosterCompilationContext.get(); + if (ctx != null) { + @SuppressWarnings({"unchecked"}) + HashMap kd = (HashMap) ctx.getAOTCompiledClassKlassData(); + klassData = kd; + } else { + klassData = AOTCompiledClass.klassData; + } AOTKlassData data = klassData.get(name); if (data != null) { HotSpotResolvedObjectType oldType = data.getType(); @@ -417,6 +449,19 @@ final class AOTCompiledClass { } static void putAOTKlassData(BinaryContainer binaryContainer) { + AOTDynamicTypeStore dynoStore; + HashMap klassData; + JBoosterCompilationContext ctx = JBoosterCompilationContext.get(); + if (ctx != null) { + dynoStore = (AOTDynamicTypeStore) ctx.getAOTCompiledClassAOTDynamicTypeStore(); + @SuppressWarnings({"unchecked"}) + HashMap kd = (HashMap) ctx.getAOTCompiledClassKlassData(); + klassData = kd; + } else { + dynoStore = AOTCompiledClass.dynoStore; + klassData = AOTCompiledClass.klassData; + } + // record dynamic types Set dynoTypes = dynoStore.getDynamicTypes(); if (dynoTypes != null) { @@ -468,4 +513,15 @@ final class AOTCompiledClass { this.methods = null; } + public static void guaranteeStaticNotUsed() { + if (dynoStore != null) { + throw new IllegalStateException("Static dynoStore should be null for JBooster!"); + } + if (classesCount != 0) { + throw new IllegalStateException("Static classesCount should be 0 for JBooster!"); + } + if (!klassData.isEmpty()) { + throw new IllegalStateException("Static klassData should be empty for JBooster!"); + } + } } diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiler.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiler.java index 4bf9047a4..680bccb26 100644 --- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiler.java +++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiler.java @@ -35,6 +35,7 @@ import java.util.concurrent.atomic.AtomicInteger; import org.graalvm.compiler.options.OptionValues; +import jdk.vm.ci.jbooster.JBoosterCompilationContext; import jdk.vm.ci.meta.ResolvedJavaMethod; final class AOTCompiler { @@ -50,7 +51,7 @@ final class AOTCompiler { /** * Compile queue. */ - private class CompileQueue extends ThreadPoolExecutor { + private static class CompileQueue extends ThreadPoolExecutor { /** * Time of the start of this queue. @@ -67,21 +68,59 @@ final class AOTCompiler { */ private final AtomicInteger failedMethodCount = new AtomicInteger(); + /** + * The printer to use. + */ + private final LogPrinter printer; + /** * Create a compile queue with the given number of threads. */ - CompileQueue(final int threads) { + CompileQueue(LogPrinter printer, final int threads) { super(threads, threads, 0L, TimeUnit.MILLISECONDS, new PriorityBlockingQueue<>()); + this.printer = printer; startTime = System.currentTimeMillis(); } + @Override + protected void beforeExecute(Thread t, Runnable r) { + AOTCompilationTask task = (AOTCompilationTask) r; + + JBoosterCompilationContext ctx = task.getMain().getJBoosterCompilationContext(); + if (ctx != null) { + // Every run() is executed in a new thread in the thread pool. + // - Some code of JAOTC use global static variables, which makes it impossible to process + // multiple AOTCompilationTasks in parallel. + // - Some code of VM.CI should be patched by JBooster, but it's difficult to pass the ctx + // through method calls. + // So we use the thread-local JBoosterCompilationContext for each thread. And different + // threads can share the same ctx. + JBoosterCompilationContext.set(ctx); + } + } + @Override protected void afterExecute(Runnable r, Throwable t) { AOTCompilationTask task = (AOTCompilationTask) r; + + AtomicInteger successfulMethodCount; + AtomicInteger failedMethodCount; + JBoosterCompilationContext ctx = task.getMain().getJBoosterCompilationContext(); + if (ctx != null) { + successfulMethodCount = ctx.getCompileQueueSuccessfulMethodCount(); + failedMethodCount = ctx.getCompileQueueFailedMethodCount(); + + ctx.getAOTCompilerRemainingTaskCount().countDown(); + JBoosterCompilationContext.set(null); + } else { + successfulMethodCount = this.successfulMethodCount; + failedMethodCount = this.failedMethodCount; + } + if (task.getResult() != null) { final int count = successfulMethodCount.incrementAndGet(); if (count % 100 == 0) { - main.printer.printInfo("."); + printer.printInfo("."); } CompiledMethodInfo result = task.getResult(); if (result != null) { @@ -89,21 +128,33 @@ final class AOTCompiler { } } else { failedMethodCount.incrementAndGet(); - main.printer.printlnVerbose(""); + printer.printlnVerbose(""); ResolvedJavaMethod method = task.getMethod(); - main.printer.printlnVerbose(" failed " + method.getName() + method.getSignature().toMethodDescriptor()); + printer.printlnVerbose(" failed " + method.getName() + method.getSignature().toMethodDescriptor()); } } @Override protected void terminated() { + if (jboosterGlobalCompileQueue != null) { + printer.printlnInfo("JBooster global AOT compilation queue terminated."); + return; + } final long endTime = System.currentTimeMillis(); final int success = successfulMethodCount.get(); final int failed = failedMethodCount.get(); - main.printer.printlnInfo(""); - main.printer.printlnInfo(success + " methods compiled, " + failed + " methods failed (" + (endTime - startTime) + " ms)"); + printer.printlnInfo(""); + printer.printlnInfo(success + " methods compiled, " + failed + " methods failed (" + (endTime - startTime) + " ms)"); } + public void guaranteeStaticNotUsed() { + if (successfulMethodCount.get() != 0) { + throw new IllegalStateException("Static successfulMethodCount should be 0 for JBooster!"); + } + if (failedMethodCount.get() != 0) { + throw new IllegalStateException("Static failedMethodCount should be 0 for JBooster!"); + } + } } /** @@ -115,7 +166,7 @@ final class AOTCompiler { AOTCompiler(Main main, OptionValues graalOptions, AOTBackend aotBackend, final int threads) { this.main = main; this.graalOptions = graalOptions; - this.compileQueue = new CompileQueue(threads); + this.compileQueue = new CompileQueue(main.printer, threads); this.backend = aotBackend; } @@ -166,4 +217,84 @@ final class AOTCompiler { LogPrinter.writeLog(message + " " + methodName); } + private static CompileQueue jboosterGlobalCompileQueue = null; + + static ThreadPoolExecutor getJBoosterGlobalCompileQueue() { + return jboosterGlobalCompileQueue; + } + + /** + * Compile classes by the jboosterGlobalCompileQueue. So different classes + * set can use the same thread pool. + */ + static List compileClassesInJBooster( + Main main, OptionValues options, AOTBackend backend, List classes) + throws InterruptedException { + main.printer.printlnInfo("Compiling with " + jboosterGlobalCompileQueue.getCorePoolSize() + " threads"); + main.printer.printInfo("."); // Compilation progress indication. + + final long startTime = System.currentTimeMillis(); + + JBoosterCompilationContext ctx = main.getJBoosterCompilationContext(); + List tasks = getMethodCompilationTasks(main, options, backend, classes); + ctx.setAOTCompilerTotalTaskCount(tasks.size()); + enqueueMethods(main, tasks); + + ctx.getAOTCompilerRemainingTaskCount().await(); + + final long endTime = System.currentTimeMillis(); + final int success = ctx.getCompileQueueSuccessfulMethodCount().get(); + final int failed = ctx.getCompileQueueFailedMethodCount().get(); + main.printer.printlnInfo(""); + main.printer.printlnInfo(success + " methods compiled, " + failed + " methods failed (" + (endTime - startTime) + " ms)"); + jboosterGlobalCompileQueue.guaranteeStaticNotUsed(); + + List compiledClasses = new ArrayList<>(); + for (AOTCompiledClass compiledClass : classes) { + if (compiledClass.hasCompiledMethods()) { + compiledClasses.add(compiledClass); + } + } + return compiledClasses; + } + + static void initJBoosterGlobalCompileQueue() { + if (jboosterGlobalCompileQueue != null) { + throw new InternalError("Init twice?"); + } + + int globalThreads = Integer.max(Runtime.getRuntime().availableProcessors() - 4, 1); + Main commonMain = new Main(); + commonMain.options.info = true; + commonMain.options.verbose = false; + commonMain.options.debug = false; + jboosterGlobalCompileQueue = new CompileQueue(commonMain.printer, globalThreads); + } + + private static List getMethodCompilationTasks(Main main, OptionValues options, + AOTBackend backend, List classes) { + List list = new ArrayList<>(); + for (AOTCompiledClass aotClass : classes) { + for (ResolvedJavaMethod method : aotClass.getMethods()) { + AOTCompilationTask task = new AOTCompilationTask(main, options, aotClass, method, backend); + list.add(task); + } + } + return list; + } + + private static void enqueueMethods(Main main, List tasks) throws InterruptedException { + for (AOTCompilationTask task : tasks) { + try { + jboosterGlobalCompileQueue.execute(task); + } catch (RejectedExecutionException e) { + main.getJBoosterCompilationContext().getAOTCompilerRemainingTaskCount().countDown(); + if (jboosterGlobalCompileQueue.isShutdown()) { + throw new InterruptedException(); + } else { + e.printStackTrace(); + } + } + } + } } diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Collector.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Collector.java index bd127b308..8c2083f4e 100644 --- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Collector.java +++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Collector.java @@ -54,7 +54,15 @@ final class Collector { } Set> collectClassesToCompile() { - Set> classesToCompile = new HashSet<>(); + Set> classesToCompile; + if (main.options.getClassesToCompile() != null) { + if (main.options.files.isEmpty()) { + return main.options.getClassesToCompile(); + } + classesToCompile = main.options.getClassesToCompile(); + } else { + classesToCompile = new HashSet<>(); + } FileSupport fileSupport = new FileSupport(); ClassSearch lookup = new ClassSearch(); lookup.addProvider(new ModuleSourceProvider()); @@ -104,11 +112,11 @@ final class Collector { * * @return array list of AOT classes which have compiled methods. */ - List collectMethodsToCompile(Set> classesToCompile, MetaAccessProvider metaAccess) { + List collectMethodsToCompile(Set> classesToCompile, Set methodsToCompile, Set methodsNotToCompile, MetaAccessProvider metaAccess) { int total = 0; int count = 0; List classes = new ArrayList<>(); - CompilationSpec compilationRestrictions = collectSpecifiedMethods(); + CompilationSpec compilationRestrictions = collectSpecifiedMethods(methodsToCompile, methodsNotToCompile); for (Class c : classesToCompile) { ResolvedJavaType resolvedJavaType = metaAccess.lookupJavaType(c); @@ -160,8 +168,8 @@ final class Collector { * If a file with compilation limitations is specified using flag --compile-commands, read the * file's contents and collect the restrictions. */ - private CompilationSpec collectSpecifiedMethods() { - CompilationSpec compilationRestrictions = new CompilationSpec(); + private CompilationSpec collectSpecifiedMethods(Set methodsToCompile, Set methodsNotToCompile) { + CompilationSpec compilationRestrictions = new CompilationSpec((HashSet) methodsToCompile, (HashSet) methodsNotToCompile); String methodListFileName = main.options.methodList; if (methodListFileName != null && !methodListFileName.equals("")) { diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CompilationSpec.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CompilationSpec.java index 19662c52b..17ea7fd58 100644 --- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CompilationSpec.java +++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CompilationSpec.java @@ -48,6 +48,15 @@ final class CompilationSpec { private HashSet excludeStrings = new HashSet<>(); private HashSet excludePatterns = new HashSet<>(); + CompilationSpec(HashSet compileOnlyStrings, HashSet excludeStrings) { + if (compileOnlyStrings != null) { + this.compileOnlyStrings = compileOnlyStrings; + } + if (excludeStrings != null) { + this.excludeStrings = excludeStrings; + } + } + /** * Add a {@code compileOnly} directive to the compile-only list. * diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CompiledMethodInfo.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CompiledMethodInfo.java index 49db6afbb..6da934117 100644 --- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CompiledMethodInfo.java +++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CompiledMethodInfo.java @@ -38,6 +38,7 @@ import jdk.tools.jaotc.binformat.ReadOnlyDataContainer; import jdk.vm.ci.code.site.Call; import jdk.vm.ci.hotspot.HotSpotCompiledCode; import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; +import jdk.vm.ci.jbooster.JBoosterCompilationContext; final class CompiledMethodInfo { @@ -243,10 +244,16 @@ final class CompiledMethodInfo { } static int getMethodsCount() { + if (JBoosterCompilationContext.get() != null) { + return JBoosterCompilationContext.get().getCompiledMethodInfoMethodsCount().get(); + } return methodsCount.get(); } static int getNextCodeId() { + if (JBoosterCompilationContext.get() != null) { + return JBoosterCompilationContext.get().getCompiledMethodInfoMethodsCount().getAndIncrement(); + } return methodsCount.getAndIncrement(); } @@ -338,4 +345,10 @@ final class CompiledMethodInfo { this.compilationResult = null; this.methodInfo = null; } + + public static void guaranteeStaticNotUsed() { + if (methodsCount.get() != 0) { + throw new IllegalStateException("Static methodsCount should be 0 for JBooster!"); + } + } } diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataBuilder.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataBuilder.java index 949124ffe..1a6de8758 100644 --- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataBuilder.java +++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataBuilder.java @@ -58,12 +58,15 @@ final class DataBuilder { private static final HashMap vmAddresses = new HashMap<>(); + static { + fillVMAddresses(HotSpotJVMCIRuntime.runtime().getConfigStore()); + } + DataBuilder(Main main, HotSpotHostBackend backend, List classes, BinaryContainer binaryContainer) { this.main = main; this.backend = backend; this.classes = classes; this.binaryContainer = binaryContainer; - fillVMAddresses(HotSpotJVMCIRuntime.runtime().getConfigStore()); } /** diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataPatchProcessor.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataPatchProcessor.java index c6b141b1f..1055294ac 100644 --- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataPatchProcessor.java +++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataPatchProcessor.java @@ -148,15 +148,24 @@ final class DataPatchProcessor { int alignment = data.getAlignment(); byte[] value = new byte[size]; ByteBuffer buffer = ByteBuffer.wrap(value).order(ByteOrder.nativeOrder()); - DataSection.emit(buffer, data, (p, c) -> { + final String[] targetSymbol = {""}; + DataSection.emit(buffer, data, (position, constant) -> { + assert constant instanceof HotSpotMetaspaceConstant : "unknown type:" + constant; + HotSpotMetaspaceConstant metaspaceConstant = (HotSpotMetaspaceConstant) constant; + HotSpotResolvedObjectType type = metaspaceConstant.asResolvedJavaType(); + assert type != null : "unexpected null type"; + methodInfo.addDependentKlassData(binaryContainer, type); + targetSymbol[0] = "got." + AOTCompiledClass.metadataName(type); }); - String targetSymbol = "data.M" + methodInfo.getCodeId() + "." + dataOffset; - Symbol relocationSymbol = binaryContainer.getSymbol(targetSymbol); + if ("".equals(targetSymbol[0])) { + targetSymbol[0] = "data.M" + methodInfo.getCodeId() + "." + dataOffset; + } + Symbol relocationSymbol = binaryContainer.getSymbol(targetSymbol[0]); if (relocationSymbol == null) { int symSize = Math.max(8, size); int symAlig = Math.max(8, alignment); int offsetInConstantDataSection = binaryContainer.addConstantData(value, symAlig); - relocationSymbol = binaryContainer.getConstantDataContainer().createSymbol(offsetInConstantDataSection, Kind.OBJECT, Binding.LOCAL, symSize, targetSymbol); + relocationSymbol = binaryContainer.getConstantDataContainer().createSymbol(offsetInConstantDataSection, Kind.OBJECT, Binding.LOCAL, symSize, targetSymbol[0]); } Relocation reloc = new Relocation(relocOffset, RelocType.METASPACE_GOT_REFERENCE, 0, binaryContainer.getCodeContainer(), relocationSymbol); binaryContainer.addRelocation(reloc); diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java index bb9bc1667..7e44c0cdb 100644 --- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java +++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java @@ -29,6 +29,7 @@ import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; import static org.graalvm.compiler.hotspot.meta.HotSpotAOTProfilingPlugin.Options.TieredAOT; +import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.nio.file.Files; @@ -40,6 +41,7 @@ import java.util.List; import java.util.ListIterator; import java.util.Set; import java.util.StringTokenizer; +import java.util.concurrent.ThreadPoolExecutor; import java.util.stream.Stream; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; @@ -68,6 +70,9 @@ import org.graalvm.compiler.runtime.RuntimeProvider; import jdk.tools.jaotc.Options.Option; import jdk.tools.jaotc.binformat.BinaryContainer; +import jdk.tools.jaotc.binformat.elf.ElfSection; +import jdk.tools.jaotc.jbooster.JBoosterHotSpotAOTInvokeDynamicPlugin; +import jdk.vm.ci.jbooster.JBoosterCompilationContext; import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.runtime.JVMCI; @@ -79,6 +84,8 @@ public final class Main { LogPrinter printer; GraalFilters filters; + private final JBoosterCompilationContext jboosterContext; + private static final int EXIT_OK = 0; // No errors. private static final int EXIT_CMDERR = 2; // Bad command-line arguments and/or switches. private static final int EXIT_ABNORMAL = 4; // Terminated abnormally. @@ -93,6 +100,81 @@ public final class Main { System.exit(exitCode); } + public static void initForJBooster() { + AOTCompiler.initJBoosterGlobalCompileQueue(); + } + + public static ThreadPoolExecutor getJBoosterGlobalCompileQueue() { + return AOTCompiler.getJBoosterGlobalCompileQueue(); + } + + public Main() { + this(null); + } + + public Main(JBoosterCompilationContext jboosterContext) { + this.jboosterContext = jboosterContext; + log = new PrintWriter(System.out); + printer = new LogPrinter(this, log); + } + + public JBoosterCompilationContext getJBoosterCompilationContext() { + return jboosterContext; + } + + /** + * This method is for JBooster. + * Compile all specified methods to one lib. + * This method can only be invoked once for each Main instance. + */ + @SuppressWarnings("try") + public boolean compileForJBooster() { + JBoosterCompilationContext.set(jboosterContext); + + options.asJBooster = true; + options.outputName = jboosterContext.getFilePath(); + options.classesToCompile = jboosterContext.getClassesToCompile(); + options.methodsToCompile = jboosterContext.getMethodsToCompile(); + options.methodsNotToCompile = jboosterContext.getMethodsNotToCompile(); + options.dynamicInvokeSupported = true; + + options.info = true; + options.verbose = false; + options.debug = false; + + options.tiered = false; + options.ignoreClassLoadingErrors = true; + + try (Timer t = new Timer(this, "Total time of compilation")) { + File compiledFile = new File(options.outputName); + if (compiledFile.isFile()) { + compiledFile.delete(); + } + + if (run()) { + return true; + } else { + if (compiledFile.isFile()) { + compiledFile.delete(); + } + return false; + } + } catch (InterruptedException e) { + printer.printlnInfo("Compilation interrupted."); + } catch (Exception e) { + e.printStackTrace(); + } finally { + log.flush(); + JBoosterCompilationContext.set(null); + + // Make sure the static fields are not used. + CompiledMethodInfo.guaranteeStaticNotUsed(); + AOTCompiledClass.guaranteeStaticNotUsed(); + ElfSection.guaranteeStaticNotUsed(); + } + return false; + } + /** * Expands '@file' in command line arguments by replacing '@file' with the content of 'file' * parsed by StringTokenizer. '@' character can be quoted as '@@'. @@ -194,7 +276,7 @@ public final class Main { List classes; try (Timer t = new Timer(this, "")) { - classes = collector.collectMethodsToCompile(classesToCompile, metaAccess); + classes = collector.collectMethodsToCompile(classesToCompile, options.methodsToCompile, options.methodsNotToCompile, metaAccess); } // Free memory! @@ -205,23 +287,39 @@ public final class Main { } AOTDynamicTypeStore dynoStore = new AOTDynamicTypeStore(); - AOTCompiledClass.setDynamicTypeStore(dynoStore); + if (!options.isAsJBooster()) { + AOTCompiledClass.setDynamicTypeStore(dynoStore); + } else { + jboosterContext.setAotCompiledClassAOTDynamicTypeStore(dynoStore); + } // AOTBackend aotBackend = new AOTBackend(this, graalOptions, backend, new // HotSpotInvokeDynamicPlugin(dynoStore)); // Temporary workaround until JDK-8223533 is fixed. // Disable invokedynamic support. - var indyPlugin = new HotSpotInvokeDynamicPlugin(dynoStore) { - @Override - public boolean supportsDynamicInvoke(GraphBuilderContext builder, int index, int opcode) { - return false; - } - }; + HotSpotInvokeDynamicPlugin indyPlugin; + if (options.isDynamicInvokeSupported()) { + printer.printlnInfo("Using JBoosterHotSpotAOTInvokeDynamicPlugin."); + indyPlugin = new JBoosterHotSpotAOTInvokeDynamicPlugin(dynoStore); + } else { + indyPlugin = new HotSpotInvokeDynamicPlugin(dynoStore) { + @Override + public boolean supportsDynamicInvoke(GraphBuilderContext builder, int index, int opcode) { + return false; + } + }; + } AOTBackend aotBackend = new AOTBackend(this, graalOptions, backend, indyPlugin); SnippetReflectionProvider snippetReflection = aotBackend.getProviders().getSnippetReflection(); - AOTCompiler compiler = new AOTCompiler(this, graalOptions, aotBackend, options.threads); - classes = compiler.compileClasses(classes); + AOTCompiler compiler; + if (!options.isAsJBooster()) { + compiler = new AOTCompiler(this, graalOptions, aotBackend, options.threads); + classes = compiler.compileClasses(classes); + } else { + compiler = null; + classes = AOTCompiler.compileClassesInJBooster(this, graalOptions, aotBackend, classes); + } PhaseSuite graphBuilderSuite = aotBackend.getGraphBuilderSuite(); ListIterator> iterator = graphBuilderSuite.findPhase(GraphBuilderPhase.class); diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MetadataBuilder.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MetadataBuilder.java index 817f6a2e2..b03d93b68 100644 --- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MetadataBuilder.java +++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MetadataBuilder.java @@ -198,6 +198,12 @@ final class MetadataBuilder { for (int index = 0; index < metaDataEntries.length; index++) { Object ref = metaDataEntries[index]; + + // types that brought by agentlib should be added in here + if (methodInfo.getDependentKlassData(getType(ref)) == null) { + methodInfo.addDependentKlassData(binaryContainer, getType(ref)); + } + String name = metadataName(ref); // Create GOT cells for klasses referenced in metadata addMetadataEntry(binaryContainer, name); diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Options.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Options.java index e5dcda118..517edc1df 100644 --- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Options.java +++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Options.java @@ -29,6 +29,7 @@ import java.text.MessageFormat; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; +import java.util.Set; import jdk.tools.jaotc.collect.ClassSearch; import jdk.tools.jaotc.collect.ClassSource; @@ -65,6 +66,24 @@ final class Options { boolean compileWithAssertions; boolean tiered; + boolean asJBooster = false; + Set> classesToCompile = null; + Set methodsToCompile = null; + Set methodsNotToCompile = null; + boolean dynamicInvokeSupported = false; + + public boolean isAsJBooster() { + return asJBooster; + } + + public Set> getClassesToCompile() { + return classesToCompile; + } + + public boolean isDynamicInvokeSupported() { + return isAsJBooster() && dynamicInvokeSupported; + } + private String defaultOutputName() { osName = System.getProperty("os.name"); String name = "unnamed."; diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/jbooster/JBoosterHotSpotAOTInvokeDynamicPlugin.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/jbooster/JBoosterHotSpotAOTInvokeDynamicPlugin.java new file mode 100644 index 000000000..5c616458b --- /dev/null +++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/jbooster/JBoosterHotSpotAOTInvokeDynamicPlugin.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2023, Huawei Technologies Co., Ltd. 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. + */ + +package jdk.tools.jaotc.jbooster; + +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; +import org.graalvm.compiler.bytecode.Bytecodes; +import org.graalvm.compiler.hotspot.meta.HotSpotInvokeDynamicPlugin; +import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; + +/** + * JBoosterHotSpotAOTInvokeDynamicPlugin + */ +public class JBoosterHotSpotAOTInvokeDynamicPlugin extends HotSpotInvokeDynamicPlugin { + public JBoosterHotSpotAOTInvokeDynamicPlugin(DynamicTypeStore dynoStore) { + super(dynoStore); + } + + @Override + public boolean supportsDynamicInvoke(GraphBuilderContext builder, int index, int opcode) { + // Support ConstantCallSite of invokedynamic only. + if (opcode != Bytecodes.INVOKEDYNAMIC) return false; + HotSpotResolvedJavaMethod target = (HotSpotResolvedJavaMethod) builder.getCode().getConstantPool().lookupMethod(index, opcode); + return "linkToTargetMethod".equals(target.getName()); + } +} diff --git a/src/jdk.aot/share/classes/module-info.java b/src/jdk.aot/share/classes/module-info.java index f6341b8ae..ca6edae24 100644 --- a/src/jdk.aot/share/classes/module-info.java +++ b/src/jdk.aot/share/classes/module-info.java @@ -34,4 +34,8 @@ module jdk.aot { requires jdk.internal.vm.ci; requires jdk.internal.vm.compiler; requires jdk.management; + + exports jdk.tools.jaotc to jdk.jbooster; + exports jdk.tools.jaotc.collect to jdk.jbooster; + exports jdk.tools.jaotc.collect.module to jdk.jbooster; } diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java index f2e998c56..268cedc41 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java @@ -74,7 +74,6 @@ public class InstanceKlass extends Klass { private static int MISC_HAS_NONSTATIC_CONCRETE_METHODS; private static int MISC_DECLARES_NONSTATIC_CONCRETE_METHODS; private static int MISC_HAS_BEEN_REDEFINED; - private static int MISC_HAS_PASSED_FINGERPRINT_CHECK; private static int MISC_IS_SCRATCH_CLASS; private static int MISC_IS_SHARED_BOOT_CLASS; private static int MISC_IS_SHARED_PLATFORM_CLASS; @@ -132,7 +131,6 @@ public class InstanceKlass extends Klass { MISC_HAS_NONSTATIC_CONCRETE_METHODS = db.lookupIntConstant("InstanceKlass::_misc_has_nonstatic_concrete_methods").intValue(); MISC_DECLARES_NONSTATIC_CONCRETE_METHODS = db.lookupIntConstant("InstanceKlass::_misc_declares_nonstatic_concrete_methods").intValue(); MISC_HAS_BEEN_REDEFINED = db.lookupIntConstant("InstanceKlass::_misc_has_been_redefined").intValue(); - MISC_HAS_PASSED_FINGERPRINT_CHECK = db.lookupIntConstant("InstanceKlass::_misc_has_passed_fingerprint_check").intValue(); MISC_IS_SCRATCH_CLASS = db.lookupIntConstant("InstanceKlass::_misc_is_scratch_class").intValue(); MISC_IS_SHARED_BOOT_CLASS = db.lookupIntConstant("InstanceKlass::_misc_is_shared_boot_class").intValue(); MISC_IS_SHARED_PLATFORM_CLASS = db.lookupIntConstant("InstanceKlass::_misc_is_shared_platform_class").intValue(); @@ -288,6 +286,10 @@ public class InstanceKlass extends Klass { size += 8; // uint64_t } + if (VM.getVM().hasAOT()) { + size += 1; // u1 aot_flags + } + return alignSize(size); } @@ -303,6 +305,9 @@ public class InstanceKlass extends Klass { if (vm.getCommandLineBooleanFlag("DumpSharedSpaces")) { return true; } + if (vm.getCommandLineBooleanFlag("CalculateClassFingerprint")) { + return true; + } return false; } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/aarch64/AArch64.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/aarch64/AArch64.java index c2a7fa2b5..d65b9b272 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/aarch64/AArch64.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/aarch64/AArch64.java @@ -30,6 +30,7 @@ import jdk.vm.ci.code.CPUFeatureName; import jdk.vm.ci.code.Register; import jdk.vm.ci.code.Register.RegisterCategory; import jdk.vm.ci.code.RegisterArray; +import jdk.vm.ci.jbooster.JBoosterCompilationContext; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.PlatformKind; @@ -206,10 +207,17 @@ public class AArch64 extends Architecture { @Override public EnumSet getFeatures() { + if (JBoosterCompilationContext.get() != null) { + // [AArch64]can't get features from client now, just return empty set + return EnumSet.noneOf(CPUFeature.class); + } return features; } public EnumSet getFlags() { + if (JBoosterCompilationContext.get() != null) { + return EnumSet.noneOf(Flag.class); + } return flags; } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/amd64/AMD64.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/amd64/AMD64.java index 3fc5b6e79..b01824af3 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/amd64/AMD64.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/amd64/AMD64.java @@ -35,6 +35,7 @@ import jdk.vm.ci.code.CPUFeatureName; import jdk.vm.ci.code.Register; import jdk.vm.ci.code.Register.RegisterCategory; import jdk.vm.ci.code.RegisterArray; +import jdk.vm.ci.jbooster.JBoosterCompilationContext; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.PlatformKind; @@ -253,10 +254,17 @@ public class AMD64 extends Architecture { @Override public EnumSet getFeatures() { + if (JBoosterCompilationContext.get() != null) { + // [AMD64]can't get features from client now, just return empty set + return EnumSet.noneOf(CPUFeature.class); + } return features; } public EnumSet getFlags() { + if (JBoosterCompilationContext.get() != null) { + return EnumSet.noneOf(Flag.class); + } return flags; } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/DirectHotSpotObjectConstantImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/DirectHotSpotObjectConstantImpl.java index cc553a39f..df87221da 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/DirectHotSpotObjectConstantImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/DirectHotSpotObjectConstantImpl.java @@ -45,10 +45,26 @@ final class DirectHotSpotObjectConstantImpl extends HotSpotObjectConstantImpl { super(compressed); assert object != null; this.object = object; + this.holderType = null; + this.cpi = -1; + } + + static JavaConstant forObject(HotSpotResolvedObjectType type, int cpi, JavaConstant object) { + return new DirectHotSpotObjectConstantImpl(type, cpi, object); + } + + private DirectHotSpotObjectConstantImpl(HotSpotResolvedObjectType type, int cpi, JavaConstant constant) { + super(((DirectHotSpotObjectConstantImpl) constant).compressed); + this.object = ((DirectHotSpotObjectConstantImpl) constant).object; + this.holderType = type; + this.cpi = cpi; } final Object object; + private final HotSpotResolvedObjectType holderType; + private final int cpi; + @Override public JavaConstant compress() { assert !compressed; diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotConstantPoolObject.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotConstantPoolObject.java index ce82af7e5..eaf2bcc9b 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotConstantPoolObject.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotConstantPoolObject.java @@ -32,7 +32,7 @@ import jdk.vm.ci.meta.JavaKind; public final class HotSpotConstantPoolObject implements JavaConstant { public static JavaConstant forObject(HotSpotResolvedObjectType type, int cpi, JavaConstant object) { - return new HotSpotConstantPoolObject(type, cpi, object); + return DirectHotSpotObjectConstantImpl.forObject(type, cpi, object); } private final JavaConstant constant; diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java index 079dacefd..74be52e13 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2023, 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 @@ -301,7 +301,7 @@ public final class HotSpotJVMCIRuntime implements JVMCIRuntime { "Enables tracing of profiling info when read by JVMCI.", "Empty value: trace all methods", "Non-empty value: trace methods whose fully qualified name contains the value."), - UseProfilingInformation(Boolean.class, true, ""); + UseProfilingInformation(Boolean.class, true, "Use ProfilingInformation for compiler"); // @formatter:on /** diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotProfilingInfo.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotProfilingInfo.java index dec8c0e89..28e46e64e 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotProfilingInfo.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotProfilingInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2023, 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 @@ -22,6 +22,7 @@ */ package jdk.vm.ci.hotspot; +import jdk.vm.ci.jbooster.JBoosterCompilationContext; import jdk.vm.ci.meta.DeoptimizationReason; import jdk.vm.ci.meta.JavaMethodProfile; import jdk.vm.ci.meta.JavaTypeProfile; @@ -50,7 +51,12 @@ final class HotSpotProfilingInfo implements ProfilingInfo { } this.includeNormal = includeNormal; this.includeOSR = includeOSR; - this.isMature = methodData.isProfileMature(); + if (methodData.isProfileMature()) { + this.isMature = true; + } else { + JBoosterCompilationContext ctx = JBoosterCompilationContext.get(); + this.isMature = ctx != null && ctx.usePGO(); + } hintPosition = 0; hintBCI = -1; } @@ -110,7 +116,11 @@ final class HotSpotProfilingInfo implements ProfilingInfo { @Override public TriState getExceptionSeen(int bci) { - findBCI(bci, true); + if (JBoosterCompilationContext.get() != null) { + findBCI(bci, false); + } else { + findBCI(bci, true); + } return dataAccessor.getExceptionSeen(methodData, position); } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java index fc370ba75..fb281f98d 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2023, 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 @@ -38,6 +38,7 @@ import java.lang.reflect.Type; import jdk.vm.ci.common.JVMCIError; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.Option; +import jdk.vm.ci.jbooster.JBoosterCompilationContext; import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.ConstantPool; import jdk.vm.ci.meta.DefaultProfilingInfo; @@ -472,26 +473,40 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp @Override public ProfilingInfo getProfilingInfo(boolean includeNormal, boolean includeOSR) { ProfilingInfo info; - - if (Option.UseProfilingInformation.getBoolean() && methodData == null) { - long metaspaceMethodData = UNSAFE.getAddress(getMetaspaceMethod() + config().methodDataOffset); + HotSpotMethodData currentMethodData = null; + JBoosterCompilationContext ctx = JBoosterCompilationContext.get(); + if (ctx == null || !ctx.usePGO()) { + currentMethodData = methodData; + } + + if (Option.UseProfilingInformation.getBoolean() && (ctx != null && ctx.usePGO() || methodData == null)) { + long metaspaceMethodData = 0L; + if (ctx == null) { + metaspaceMethodData = UNSAFE.getAddress(getMetaspaceMethod() + config().methodDataOffset); + } else if (ctx.usePGO()) { + // force to get MethodData everytime when use JBooster + metaspaceMethodData = JBoosterCompilationContext.get().getMetaspaceMethodData(getMetaspaceMethod()); + } if (metaspaceMethodData != 0) { - methodData = new HotSpotMethodData(metaspaceMethodData, this); + currentMethodData = new HotSpotMethodData(metaspaceMethodData, this); + if (ctx == null) { + methodData = currentMethodData; + } String methodDataFilter = Option.TraceMethodDataFilter.getString(); if (methodDataFilter != null && this.format("%H.%n").contains(methodDataFilter)) { - String line = methodData.toString() + System.lineSeparator(); + String line = currentMethodData.toString() + System.lineSeparator(); byte[] lineBytes = line.getBytes(); HotSpotJVMCIRuntime.runtime().writeDebugOutput(lineBytes, 0, lineBytes.length, true, true); } } } - if (methodData == null || (!methodData.hasNormalData() && !methodData.hasExtraData())) { + if (currentMethodData == null || (!currentMethodData.hasNormalData() && !currentMethodData.hasExtraData())) { // Be optimistic and return false for exceptionSeen. A methodDataOop is allocated in // case of a deoptimization. info = DefaultProfilingInfo.get(TriState.FALSE); } else { - info = new HotSpotProfilingInfo(methodData, this, includeNormal, includeOSR); + info = new HotSpotProfilingInfo(currentMethodData, this, includeNormal, includeOSR); } return info; } diff --git a/src/jdk.internal.vm.ci/share/classes/module-info.java b/src/jdk.internal.vm.ci/share/classes/module-info.java index 9f9122cf8..111ad997f 100644 --- a/src/jdk.internal.vm.ci/share/classes/module-info.java +++ b/src/jdk.internal.vm.ci/share/classes/module-info.java @@ -32,8 +32,8 @@ module jdk.internal.vm.ci { jdk.internal.vm.compiler.management; exports jdk.vm.ci.meta to jdk.internal.vm.compiler; exports jdk.vm.ci.code to jdk.internal.vm.compiler; - exports jdk.vm.ci.hotspot to jdk.internal.vm.compiler; - exports jdk.vm.ci.jbooster to jdk.jbooster, jdk.internal.vm.compiler; + exports jdk.vm.ci.hotspot to jdk.internal.vm.compiler, jdk.jbooster; + exports jdk.vm.ci.jbooster to jdk.aot, jdk.jbooster, jdk.internal.vm.compiler; uses jdk.vm.ci.services.JVMCIServiceLocator; uses jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/DataSection.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/DataSection.java index 0d99acf0f..a20fd5b9b 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/DataSection.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/DataSection.java @@ -47,6 +47,17 @@ public final class DataSection implements Iterable { } public abstract static class Data { + public static final int MIN_ALIGNMENT; + static { + String archStr = System.getProperty("os.arch").toLowerCase(); + if ("aarch64".equals(archStr)) { + // AArch64 Relocations are 4-aligned + // see relocInfo_aarch64.hpp -> offset_unit + MIN_ALIGNMENT = 4; + } else { + MIN_ALIGNMENT = 1; + } + } private int alignment; private final int size; @@ -54,7 +65,7 @@ public final class DataSection implements Iterable { private DataSectionReference ref; protected Data(int alignment, int size) { - this.alignment = alignment; + this.alignment = lcm(alignment, MIN_ALIGNMENT); this.size = size; // initialized in DataSection.insertData(Data) diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotMove.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotMove.java index c9b7bc9bc..b78ae697d 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotMove.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotMove.java @@ -71,7 +71,13 @@ public class AArch64HotSpotMove { // masm.forceMov(asRegister(result), 0); masm.movNarrowAddress(asRegister(result), 0); } else { - masm.movNativeAddress(asRegister(result), 0); + Register resultRegister = asRegister(result); + if (crb.compilationResult.isImmutablePIC()) { + masm.addressOf(resultRegister); + masm.ldr(64, resultRegister, AArch64Address.createBaseRegisterOnlyAddress(resultRegister)); + } else { + masm.movNativeAddress(resultRegister, 0); + } } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotStrategySwitchOp.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotStrategySwitchOp.java index 447a48b60..92c68ddac 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotStrategySwitchOp.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotStrategySwitchOp.java @@ -28,6 +28,7 @@ import static jdk.vm.ci.code.ValueUtil.asRegister; import java.util.function.Function; +import org.graalvm.compiler.asm.aarch64.AArch64Address; import org.graalvm.compiler.asm.aarch64.AArch64Assembler; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; import org.graalvm.compiler.core.common.calc.Condition; @@ -71,8 +72,14 @@ final class AArch64HotSpotStrategySwitchOp extends AArch64ControlFlow.StrategySw throw GraalError.unimplemented(); } else { crb.recordInlineDataInCode(meta); - masm.movNativeAddress(asRegister(scratch), 0x0000_DEAD_DEAD_DEADL); - masm.cmp(64, keyRegister, asRegister(scratch)); + Register scratchRegister = asRegister(scratch); + if (crb.compilationResult.isImmutablePIC()) { + masm.addressOf(scratchRegister); + masm.ldr(64, scratchRegister, AArch64Address.createBaseRegisterOnlyAddress(scratchRegister)); + } else { + masm.movNativeAddress(scratchRegister, 0x0000_DEAD_DEAD_DEADL); + } + masm.cmp(64, keyRegister, scratchRegister); } } else { super.emitComparison(c); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMove.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMove.java index e839243be..0c1be69d8 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMove.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMove.java @@ -44,6 +44,7 @@ import org.graalvm.compiler.lir.amd64.AMD64LIRInstruction; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import jdk.vm.ci.code.Register; +import jdk.vm.ci.jbooster.JBoosterCompilationContext; import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; import jdk.vm.ci.hotspot.HotSpotObjectConstant; import jdk.vm.ci.meta.AllocatableValue; @@ -65,7 +66,8 @@ public class AMD64HotSpotMove { @Override public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - if (GeneratePIC.getValue(crb.getOptions())) { + JBoosterCompilationContext ctx = JBoosterCompilationContext.get(); + if (GeneratePIC.getValue(crb.getOptions()) && (ctx == null || !ctx.usePGO())) { throw GraalError.shouldNotReachHere("Object constant load should not be happening directly"); } boolean compressed = input.isCompressed(); @@ -142,7 +144,8 @@ public class AMD64HotSpotMove { @Override public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - if (GeneratePIC.getValue(crb.getOptions())) { + JBoosterCompilationContext ctx = JBoosterCompilationContext.get(); + if (GeneratePIC.getValue(crb.getOptions()) && (ctx == null || !ctx.usePGO())) { throw GraalError.shouldNotReachHere("Metaspace constant load should not be happening directly"); } boolean compressed = input.isCompressed(); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java index d5b23edd1..c580616eb 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java @@ -471,7 +471,6 @@ public class CheckGraalIntrinsics extends GraalTest { if (!(arch instanceof AMD64)) { // Can we implement these on non-AMD64 platforms? C2 seems to. add(toBeInvestigated, - "com/sun/crypto/provider/CounterMode.implCrypt([BII[BI)I", "java/lang/String.compareTo(Ljava/lang/String;)I", "java/lang/StringLatin1.indexOf([B[B)I", "java/lang/StringLatin1.inflate([BI[BII)V", diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/AOTGraalHotSpotVMConfig.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/AOTGraalHotSpotVMConfig.java index 2305d5eb5..ffc883c12 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/AOTGraalHotSpotVMConfig.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/AOTGraalHotSpotVMConfig.java @@ -41,8 +41,13 @@ public class AOTGraalHotSpotVMConfig extends GraalHotSpotVMConfig { // always equal to alignment to avoid emitting zero-shift AOT code. CompressEncoding vmOopEncoding = super.getOopEncoding(); aotOopEncoding = new CompressEncoding(vmOopEncoding.getBase(), logMinObjAlignment()); + + // For compressed klass, there is always zero-shift in aarch64 CompressEncoding vmKlassEncoding = super.getKlassEncoding(); - aotKlassEncoding = new CompressEncoding(vmKlassEncoding.getBase(), logKlassAlignment); + String archStr = System.getProperty("os.arch").toLowerCase(); + int zeroShift = 0; + aotKlassEncoding = new CompressEncoding(vmKlassEncoding.getBase(), "aarch64".equals(archStr) ? zeroShift : logKlassAlignment); + assert check(); reportErrors(); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java index 423c2f95e..6199d921b 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java @@ -178,6 +178,7 @@ import jdk.vm.ci.hotspot.HotSpotCallingConventionType; import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider; import jdk.vm.ci.hotspot.HotSpotResolvedJavaField; import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; +import jdk.vm.ci.jbooster.JBoosterCompilationContext; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.JavaType; @@ -526,7 +527,8 @@ public abstract class DefaultHotSpotLoweringProvider extends DefaultJavaLowering LoweredCallTargetNode loweredCallTarget = null; OptionValues options = graph.getOptions(); - if (InlineVTableStubs.getValue(options) && callTarget.invokeKind().isIndirect() && (AlwaysInlineVTableStubs.getValue(options) || invoke.isPolymorphic())) { + JBoosterCompilationContext ctx = JBoosterCompilationContext.get(); + if ((ctx == null || !ctx.usePGO()) && InlineVTableStubs.getValue(options) && callTarget.invokeKind().isIndirect() && (AlwaysInlineVTableStubs.getValue(options) || invoke.isPolymorphic())) { HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) callTarget.targetMethod(); ResolvedJavaType receiverType = invoke.getReceiverType(); if (hsMethod.isInVirtualMethodTable(receiverType)) { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java index 6b8e63229..e429e43e8 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java @@ -444,6 +444,7 @@ import jdk.vm.ci.code.BailoutException; import jdk.vm.ci.code.BytecodeFrame; import jdk.vm.ci.code.CodeUtil; import jdk.vm.ci.code.site.InfopointReason; +import jdk.vm.ci.jbooster.JBoosterCompilationContext; import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.ConstantPool; import jdk.vm.ci.meta.ConstantReflectionProvider; @@ -4432,7 +4433,8 @@ public class BytecodeParser implements GraphBuilderContext { } private JavaTypeProfile getProfileForTypeCheck(TypeReference type) { - if (parsingIntrinsic() || profilingInfo == null || !optimisticOpts.useTypeCheckHints(getOptions()) || type.isExact()) { + JBoosterCompilationContext ctx = JBoosterCompilationContext.get(); + if ((ctx != null && ctx.usePGO()) || parsingIntrinsic() || profilingInfo == null || !optimisticOpts.useTypeCheckHints(getOptions()) || type.isExact()) { return null; } else { return profilingInfo.getTypeProfile(bci()); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InliningLog.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InliningLog.java index bda34e6a7..40b1ac3b8 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InliningLog.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InliningLog.java @@ -171,10 +171,15 @@ public class InliningLog { if (!enabled) { return; } - assert leaves.containsKey(invoke); + if (!leaves.containsKey(invoke)) { + trackNewCallsite(invoke); + } assert (!positive && replacements == null && calleeLog == null) || (positive && replacements != null && calleeLog != null) || (positive && replacements == null && calleeLog == null); Callsite callsite = leaves.get(invoke); + if (callsite == null) { + return; + } callsite.target = callsite.invoke.getTargetMethod(); Decision decision = new Decision(positive, String.format(reason, args), phase, invoke.getTargetMethod()); callsite.decisions.add(decision); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/InliningData.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/InliningData.java index 9d24764a6..d2f7b99cc 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/InliningData.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/InliningData.java @@ -70,6 +70,7 @@ import org.graalvm.compiler.phases.common.inlining.policy.InliningPolicy; import org.graalvm.compiler.phases.tiers.HighTierContext; import jdk.vm.ci.code.BailoutException; +import jdk.vm.ci.jbooster.JBoosterCompilationContext; import jdk.vm.ci.meta.Assumptions.AssumptionResult; import jdk.vm.ci.meta.JavaTypeProfile; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -152,7 +153,7 @@ public class InliningData { return "it is a non-intrinsic native method"; } else if (method.isAbstract()) { return "it is an abstract method"; - } else if (!method.getDeclaringClass().isInitialized()) { + } else if (!method.getDeclaringClass().isInitialized() && (JBoosterCompilationContext.get() == null || !JBoosterCompilationContext.get().usePGO())) { return "the method's class is not initialized"; } else if (!method.canBeInlined()) { return "it is marked non-inlinable"; @@ -193,6 +194,16 @@ public class InliningData { MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget(); ResolvedJavaMethod targetMethod = callTarget.targetMethod(); + JBoosterCompilationContext ctx = JBoosterCompilationContext.get(); + if (ctx != null && ctx.usePGO()) { + String methodName = targetMethod.getDeclaringClass().toClassName() + "." + targetMethod.getName() + targetMethod.getSignature().toMethodDescriptor(); + if (JBoosterCompilationContext.get().isInlineExcluded(methodName)) { + InliningUtil.traceNotInlinedMethod(invoke, inliningDepth(), targetMethod, "can not inline invokehandle calls"); + invoke.asNode().graph().getInliningLog().addDecision(invoke, false, "InliningPhase", null, null, "can not inline invokehandle calls"); + return null; + } + } + InvokeKind invokeKind = callTarget.invokeKind(); if (invokeKind == CallTargetNode.InvokeKind.Special || invokeKind == CallTargetNode.InvokeKind.Static || targetMethod.canBeStaticallyBound()) { return getExactInlineInfo(invoke, targetMethod); @@ -271,7 +282,8 @@ public class InliningData { double notRecordedTypeProbability = typeProfile.getNotRecordedProbability(); final OptimisticOptimizations optimisticOpts = context.getOptimisticOptimizations(); OptionValues options = invoke.asNode().getOptions(); - if (ptypes.length == 1 && notRecordedTypeProbability == 0) { + JBoosterCompilationContext ctx = JBoosterCompilationContext.get(); + if ((ctx == null || !ctx.usePGO()) && ptypes.length == 1 && notRecordedTypeProbability == 0) { if (!optimisticOpts.inlineMonomorphicCalls(options)) { InliningUtil.traceNotInlinedMethod(invoke, inliningDepth(), targetMethod, "inlining monomorphic calls is disabled"); invoke.asNode().graph().getInliningLog().addDecision(invoke, false, "InliningPhase", null, null, "inlining monomorphic calls is disabled"); @@ -385,6 +397,10 @@ public class InliningData { return null; } } + if (ctx != null && ctx.usePGO() && notRecordedTypeProbability == 0) { + // always inline with megamorphic, never deopt + notRecordedTypeProbability = 0.01D; + } return new MultiTypeGuardInlineInfo(invoke, concreteMethods, usedTypes, typesToConcretes, notRecordedTypeProbability); } } diff --git a/src/jdk.jbooster/share/classes/jdk/jbooster/JBooster.java b/src/jdk.jbooster/share/classes/jdk/jbooster/JBooster.java index 49cdbb28a..642fbafa6 100644 --- a/src/jdk.jbooster/share/classes/jdk/jbooster/JBooster.java +++ b/src/jdk.jbooster/share/classes/jdk/jbooster/JBooster.java @@ -29,8 +29,7 @@ import java.util.Set; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; -import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; -import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.Option; +import jdk.tools.jaotc.Main; import sun.misc.Signal; import sun.misc.SignalHandler; @@ -175,22 +174,24 @@ public final class JBooster { /** * This method is invoked only in C++. */ - private static boolean compileClasses(int sessionId, String filePath, Set> classes) { - return compileMethods(sessionId, filePath, classes, null, null); + private static boolean compileClasses(int sessionId, String filePath, Set> classes, boolean usePGO) { + return compileMethods(sessionId, filePath, classes, null, null, usePGO); } /** * This method is invoked only in C++. */ private static boolean compileMethods(int sessionId, String filePath, Set> classes, - Set methodsToCompile, Set methodsNotToCompile) { + Set methodsToCompile, Set methodsNotToCompile, boolean usePGO) { LOGGER.log(INFO, "Compilation task received: classes_to_compile={0}, methods_to_compile={1}, methods_not_compile={2}, session_id={3}.", classes.size(), (methodsToCompile == null ? "all" : String.valueOf(methodsToCompile.size())), (methodsNotToCompile == null ? "none" : String.valueOf(methodsNotToCompile.size())), sessionId); try { - // [JBOOSTER TODO] jaotc logic + JBoosterCompilationContextImpl ctx = new JBoosterCompilationContextImpl( + sessionId, filePath, classes, methodsToCompile, methodsNotToCompile, usePGO); + return new Main(ctx).compileForJBooster(); } catch (Exception e) { e.printStackTrace(); } diff --git a/src/jdk.jbooster/share/classes/module-info.java b/src/jdk.jbooster/share/classes/module-info.java index 5a7c685b5..648eb9641 100644 --- a/src/jdk.jbooster/share/classes/module-info.java +++ b/src/jdk.jbooster/share/classes/module-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2023, Huawei Technologies Co., Ltd. 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 @@ -28,6 +28,7 @@ * @since 9 */ module jdk.jbooster { + requires jdk.aot; requires jdk.internal.vm.ci; requires jdk.unsupported; requires java.logging; diff --git a/src/jdk.jbooster/share/native/libjbooster/JBooster.c b/src/jdk.jbooster/share/native/libjbooster/JBooster.c index 385e8780b..664c761ff 100644 --- a/src/jdk.jbooster/share/native/libjbooster/JBooster.c +++ b/src/jdk.jbooster/share/native/libjbooster/JBooster.c @@ -43,3 +43,9 @@ Java_jdk_jbooster_JBooster_printStoredClientData(JNIEnv * env, jclass unused, jb { JVM_JBoosterPrintStoredClientData(env, print_all); } + +JNIEXPORT long JNICALL +Java_jdk_jbooster_JBoosterCompilationContextImpl_getMetaspaceMethodData(JNIEnv * env, jclass unused, jint session_id, jlong metaspace_method) +{ + return JVM_JBoosterGetMetaspaceMethodData(env, session_id, metaspace_method); +} diff --git a/test/hotspot/jtreg/compiler/aot/TestAotPrint.java b/test/hotspot/jtreg/compiler/aot/TestAotPrint.java new file mode 100644 index 000000000..12d966e1b --- /dev/null +++ b/test/hotspot/jtreg/compiler/aot/TestAotPrint.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2024, Huawei Technologies Co., Ltd. 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. + */ + +/* + * @test + * @requires vm.aot + * @library /test/lib /testlibrary / + * @build compiler.aot.TestAotPrint + * jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run driver compiler.aot.AotCompiler -libname libAotString.so + * -class java.lang.String + * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseAOT + * -XX:AOTLibrary=./libAotString.so -XX:+PrintCompilation + * -XX:+UnlockDiagnosticVMOptions -XX:+LogCompilation + * -XX:+WhiteBoxAPI -Xbootclasspath/a:. + * -XX:+PrintAOT compiler.aot.TestAotPrint + * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseAOT + * -XX:AOTLibrary=./libAotString.so -XX:+PrintCompilation + * -XX:+UnlockDiagnosticVMOptions -XX:+LogCompilation + * -XX:+WhiteBoxAPI -Xbootclasspath/a:. + * -XX:+PrintAOT compiler.aot.TestAotPrint true + */ + +package compiler.aot; + +import compiler.aot.HelloWorldPrinter; +import jdk.test.lib.cli.CommandLineOptionTest; +import jdk.test.lib.process.ExitCode; +import jdk.test.whitebox.WhiteBox; + +public class TestAotPrint { + private static final WhiteBox WB = WhiteBox.getWhiteBox(); + + public static void main(String[] args) throws Throwable { + boolean preserve_static_stubs = false; + if (args.length > 0 && "true".equals(args[0])) { + preserve_static_stubs = true; + } + HelloWorldPrinter.print(); + WB.clearInlineCaches(preserve_static_stubs); + } +} diff --git a/test/hotspot/jtreg/compiler/aot/TestAotWithRetransform.java b/test/hotspot/jtreg/compiler/aot/TestAotWithRetransform.java new file mode 100644 index 000000000..295f52579 --- /dev/null +++ b/test/hotspot/jtreg/compiler/aot/TestAotWithRetransform.java @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2024, Huawei Technologies Co., Ltd. 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. + */ + +/* + * @test + * @requires vm.aot + * @library /test/lib /testlibrary / + * @build compiler.aot.TestAotWithRetransform + * compiler.aot.AotCompiler + * @run driver compiler.aot.AotCompiler -libname libTestAotWithRetransform.so + * -class compiler.aot.HelloWorldPrinter + * -compile compiler.aot.HelloWorldPrinter.print()V + * @run driver jdk.test.lib.util.JavaAgentBuilder + * compiler.aot.TestAotWithRetransform TestAotWithRetransform.jar + * @run driver compiler.aot.TestAotWithRetransform + */ + +package compiler.aot; + +import compiler.aot.HelloWorldPrinter; +import java.lang.instrument.ClassFileTransformer; +import java.lang.instrument.IllegalClassFormatException; +import java.lang.instrument.Instrumentation; +import java.security.ProtectionDomain; +import java.util.ArrayList; +import java.util.List; +import jdk.test.lib.cli.CommandLineOptionTest; +import jdk.test.lib.process.ExitCode; + +public class TestAotWithRetransform { + private final static String LIB_NAME = "libTestAotWithRetransform.so"; + private final static String JAR_NAME = "TestAotWithRetransform.jar"; + private final static String CLASS_NAME = "compiler/aot/HelloWorldPrinter"; + private final static String UPDATED_MESSAGE = "Hello earth"; + + private final static String[] UNEXPECTED_MESSAGES = new String[] { + HelloWorldPrinter.CLINIT_MESSAGE, + HelloWorldPrinter.MESSAGE, + CLASS_NAME + }; + + private final static String[] EXPECTED_MESSAGES = new String[] { + LIB_NAME, + UPDATED_MESSAGE + }; + + public static class Bytes { + public final static byte[] WORLD = Bytes.asBytes("world"); + public final static byte[] EARTH = Bytes.asBytes("earth"); + + public static byte[] asBytes(String string) { + byte[] result = new byte[string.length()]; + for (int i = 0; i < string.length(); i++) { + result[i] = (byte)string.charAt(i); + } + return result; + } + + public static byte[] replaceAll(byte[] input, byte[] target, byte[] replacement) { + List result = new ArrayList<>(); + for (int i = 0; i < input.length; i++) { + if (hasTarget(input, i, target)) { + for (int j = 0; j < replacement.length; j++) { + result.add(replacement[j]); + } + i += target.length - 1; + } else { + result.add(input[i]); + } + } + byte[] resultArray = new byte[result.size()]; + for (int i = 0; i < resultArray.length; i++) { + resultArray[i] = result.get(i); + } + return resultArray; + } + + private static boolean hasTarget(byte[] input, int start, byte[] target) { + for (int i = 0; i < target.length; i++) { + if (start + i == input.length) { + return false; + } + if (input[start + i] != target[i]) { + return false; + } + } + return true; + } + } + + public static class TestClassFileTransformer implements ClassFileTransformer { + public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { + if (CLASS_NAME.equals(className)) { + return Bytes.replaceAll(classfileBuffer, Bytes.WORLD, Bytes.EARTH); + } + return classfileBuffer; + } + } + + // Called when agent is loaded at startup + public static void premain(String agentArgs, Instrumentation instrumentation) throws Exception { + // don't init HelloWorldPrinter here, just Load in advance + HelloWorldPrinter.class.getName(); + instrumentation.addTransformer(new TestClassFileTransformer(), true); + // retransform HelloWorldPrinter + instrumentation.retransformClasses(HelloWorldPrinter.class); + } + + public static void main(String[] args) throws Throwable { + try { + boolean addTestVMOptions = true; + CommandLineOptionTest.verifyJVMStartup(EXPECTED_MESSAGES, + UNEXPECTED_MESSAGES, "Unexpected exit code", + "Unexpected output", ExitCode.OK, addTestVMOptions, + "-XX:+UnlockExperimentalVMOptions", "-XX:+UseAOT", "-XX:+PrintAOT", + "-XX:AOTLibrary=./" + LIB_NAME, + "-javaagent:./" + JAR_NAME, + HelloWorldPrinter.class.getName()); + } catch (Throwable t) { + throw new Error("Problems executing test " + t, t); + } + } +} diff --git a/test/jdk/jdk/internal/jimage/JImageOpenTest.java b/test/jdk/jdk/internal/jimage/JImageOpenTest.java index 5dd304db1..769902cb0 100644 --- a/test/jdk/jdk/internal/jimage/JImageOpenTest.java +++ b/test/jdk/jdk/internal/jimage/JImageOpenTest.java @@ -33,7 +33,7 @@ import java.util.stream.Stream; /* * @test * @summary Test to see if thread interrupt handling interferes with other threads. - * @run main/othervm -Djdk.image.map.all=false JImageOpenTest + * @run main/othervm --add-exports jdk.internal.vm.ci/jdk.vm.ci.code.site=jdk.internal.vm.compiler -Djdk.image.map.all=false JImageOpenTest */ public class JImageOpenTest { private static final int NTHREADS = 10; diff --git a/test/jdk/jdk/modules/etc/JdkQualifiedExportTest.java b/test/jdk/jdk/modules/etc/JdkQualifiedExportTest.java index 4718e10e8..a64b0efd1 100644 --- a/test/jdk/jdk/modules/etc/JdkQualifiedExportTest.java +++ b/test/jdk/jdk/modules/etc/JdkQualifiedExportTest.java @@ -72,6 +72,7 @@ public class JdkQualifiedExportTest { Set.of("jdk.internal.vm.ci/jdk.vm.ci.services", "jdk.internal.vm.ci/jdk.vm.ci.runtime", "jdk.internal.vm.ci/jdk.vm.ci.hotspot", + "jdk.internal.vm.ci/jdk.vm.ci.jbooster", "jdk.internal.vm.ci/jdk.vm.ci.meta", "jdk.internal.vm.ci/jdk.vm.ci.code", "java.base/jdk.internal.javac"); diff --git a/test/jdk/tools/launcher/HelpFlagsTest.java b/test/jdk/tools/launcher/HelpFlagsTest.java index f7a4acd0c..7e7cf47f9 100644 --- a/test/jdk/tools/launcher/HelpFlagsTest.java +++ b/test/jdk/tools/launcher/HelpFlagsTest.java @@ -130,7 +130,7 @@ public class HelpFlagsTest extends TestHelper { new ToolHelpSpec("javadoc", 1, 1, 1, 0, 1, 1, 1), // -?, -h, --help -help, Documents -help new ToolHelpSpec("javap", 1, 1, 1, 0, 1, 1, 2), // -?, -h, --help -help, Documents -help new ToolHelpSpec("javaw", 1, 1, 1, 0, 1, 1, 1), // -?, -h, --help -help, Documents -help, win only - new ToolHelpSpec("jbooster", 0, 0, 0, 0, 0, 0, 1), // none. + new ToolHelpSpec("jbooster", 1, 1, 1, 0, 1, 1, 1), // -?, -h, --help -help, Documents -help new ToolHelpSpec("jcmd", 1, 1, 1, 0, 1, 0, 1), // -?, -h, --help, -help accepted but not documented. new ToolHelpSpec("jdb", 1, 1, 1, 0, 1, 1, 0), // -?, -h, --help -help, Documents -help new ToolHelpSpec("jdeprscan", 1, 1, 1, 0, 0, 0, 1), // -?, -h, --help diff --git a/test/jdk/tools/launcher/VersionCheck.java b/test/jdk/tools/launcher/VersionCheck.java index 1fd5dd99a..48ec0890f 100644 --- a/test/jdk/tools/launcher/VersionCheck.java +++ b/test/jdk/tools/launcher/VersionCheck.java @@ -54,10 +54,8 @@ public class VersionCheck extends TestHelper { "jaccessinspector-32", "jaccesswalker", "jaccesswalker-32", - "jaotc", "javaw", "javaws", - "jbooster", "jcontrol", "jmc", "jmc.ini", -- 2.19.1