33087 lines
1.3 MiB
33087 lines
1.3 MiB
---
|
|
make/RunTests.gmk | 124 +-
|
|
make/RunTestsPrebuilt.gmk | 24 +-
|
|
make/autoconf/jvm-features.m4 | 62 +-
|
|
make/autoconf/spec.gmk.in | 6 +-
|
|
make/autoconf/toolchain.m4 | 6 +
|
|
make/common/Modules.gmk | 7 +-
|
|
make/conf/build-module-sets.conf | 3 +-
|
|
make/conf/jib-profiles.js | 3 +-
|
|
make/conf/module-loader-map.conf | 3 +-
|
|
make/hotspot/lib/JvmFeatures.gmk | 10 +-
|
|
.../visualstudio/hotspot/CreateVSProject.gmk | 3 +-
|
|
make/modules/jdk.aot/Java.gmk | 54 +
|
|
make/modules/jdk.aot/Launcher.gmk | 54 +
|
|
.../modules/jdk.internal.vm.compiler/Java.gmk | 3 +-
|
|
src/hotspot/cpu/aarch64/aarch64.ad | 6 +-
|
|
.../cpu/aarch64/c1_LIRAssembler_aarch64.hpp | 3 +-
|
|
.../cpu/aarch64/c1_LIRGenerator_aarch64.cpp | 2 +-
|
|
.../cpu/aarch64/compiledIC_aarch64.cpp | 78 +-
|
|
.../cpu/aarch64/compiledIC_aot_aarch64.cpp | 104 ++
|
|
.../c1/shenandoahBarrierSetC1_aarch64.cpp | 4 +-
|
|
.../cpu/aarch64/macroAssembler_aarch64.hpp | 6 +-
|
|
.../cpu/aarch64/nativeInst_aarch64.cpp | 17 +-
|
|
.../cpu/aarch64/nativeInst_aarch64.hpp | 14 +-
|
|
.../cpu/aarch64/sharedRuntime_aarch64.cpp | 16 +-
|
|
.../templateInterpreterGenerator_aarch64.cpp | 6 +-
|
|
.../cpu/aarch64/templateTable_aarch64.cpp | 10 +-
|
|
src/hotspot/cpu/arm/c1_LIRAssembler_arm.hpp | 3 +-
|
|
src/hotspot/cpu/arm/compiledIC_arm.cpp | 6 +-
|
|
src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.hpp | 11 +-
|
|
src/hotspot/cpu/ppc/compiledIC_ppc.cpp | 8 +-
|
|
src/hotspot/cpu/s390/c1_LIRAssembler_s390.hpp | 5 +-
|
|
src/hotspot/cpu/s390/compiledIC_s390.cpp | 8 +-
|
|
src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp | 14 +-
|
|
src/hotspot/cpu/x86/c1_LIRAssembler_x86.hpp | 3 +-
|
|
src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp | 4 +-
|
|
src/hotspot/cpu/x86/c1_Runtime1_x86.cpp | 4 +-
|
|
src/hotspot/cpu/x86/compiledIC_aot_x86_64.cpp | 122 ++
|
|
src/hotspot/cpu/x86/compiledIC_x86.cpp | 76 +-
|
|
src/hotspot/cpu/x86/globalDefinitions_x86.hpp | 4 +-
|
|
src/hotspot/cpu/x86/nativeInst_x86.hpp | 9 +-
|
|
src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp | 12 +-
|
|
.../x86/templateInterpreterGenerator_x86.cpp | 4 +-
|
|
src/hotspot/cpu/x86/x86_64.ad | 5 +-
|
|
src/hotspot/os/windows/os_windows.cpp | 21 +-
|
|
src/hotspot/share/aot/aotCodeHeap.cpp | 1116 +++++++++++++++++
|
|
src/hotspot/share/aot/aotCodeHeap.hpp | 310 +++++
|
|
src/hotspot/share/aot/aotCompiledMethod.cpp | 415 ++++++
|
|
src/hotspot/share/aot/aotCompiledMethod.hpp | 320 +++++
|
|
src/hotspot/share/aot/aotLoader.cpp | 335 +++++
|
|
src/hotspot/share/aot/aotLoader.hpp | 74 ++
|
|
src/hotspot/share/aot/aotLoader.inline.hpp | 39 +
|
|
src/hotspot/share/aot/compiledIC_aot.cpp | 37 +
|
|
src/hotspot/share/aot/compiledIC_aot.hpp | 83 ++
|
|
src/hotspot/share/asm/codeBuffer.hpp | 14 +
|
|
src/hotspot/share/c1/c1_Compilation.hpp | 4 +-
|
|
src/hotspot/share/c1/c1_LIRAssembler.cpp | 4 +-
|
|
src/hotspot/share/c1/c1_LIRAssembler.hpp | 8 +-
|
|
src/hotspot/share/c1/c1_LIRGenerator.cpp | 6 +-
|
|
.../share/classfile/classFileParser.cpp | 25 +-
|
|
.../share/classfile/classFileStream.cpp | 11 +-
|
|
.../share/classfile/systemDictionary.cpp | 22 +-
|
|
src/hotspot/share/code/codeBlob.hpp | 18 +-
|
|
src/hotspot/share/code/codeCache.cpp | 29 +-
|
|
src/hotspot/share/code/codeCache.hpp | 8 +-
|
|
src/hotspot/share/code/compiledIC.cpp | 51 +-
|
|
src/hotspot/share/code/compiledIC.hpp | 34 +-
|
|
src/hotspot/share/code/compiledMethod.cpp | 3 +-
|
|
src/hotspot/share/code/compiledMethod.hpp | 7 +-
|
|
src/hotspot/share/code/nmethod.cpp | 26 +-
|
|
src/hotspot/share/code/relocInfo.cpp | 18 +-
|
|
src/hotspot/share/code/relocInfo.hpp | 16 +-
|
|
.../share/compiler/compilationPolicy.cpp | 86 +-
|
|
.../share/compiler/compilationPolicy.hpp | 4 +-
|
|
.../share/compiler/compilerDefinitions.cpp | 31 +-
|
|
.../share/compiler/compilerDefinitions.hpp | 17 +-
|
|
.../share/compiler/compiler_globals.hpp | 29 +-
|
|
src/hotspot/share/compiler/disassembler.cpp | 22 +-
|
|
src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp | 3 +-
|
|
src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp | 3 +-
|
|
src/hotspot/share/gc/g1/g1RootProcessor.cpp | 14 +-
|
|
src/hotspot/share/gc/g1/g1RootProcessor.hpp | 3 +-
|
|
.../share/gc/parallel/psParallelCompact.cpp | 16 +-
|
|
src/hotspot/share/gc/parallel/psScavenge.cpp | 8 +-
|
|
.../share/gc/shared/genCollectedHeap.cpp | 11 +-
|
|
.../gc/shenandoah/shenandoahArguments.cpp | 10 +-
|
|
.../leakprofiler/chains/rootSetClosure.cpp | 8 +-
|
|
.../leakprofiler/checkpoint/rootResolver.cpp | 24 +-
|
|
.../jfr/leakprofiler/utilities/rootType.cpp | 4 +-
|
|
.../jfr/leakprofiler/utilities/rootType.hpp | 3 +-
|
|
src/hotspot/share/jvmci/compilerRuntime.cpp | 283 +++++
|
|
src/hotspot/share/jvmci/compilerRuntime.hpp | 51 +
|
|
.../share/jvmci/jvmciCodeInstaller.cpp | 175 ++-
|
|
.../share/jvmci/jvmciCodeInstaller.hpp | 63 +-
|
|
src/hotspot/share/jvmci/jvmciCompiler.cpp | 4 +-
|
|
src/hotspot/share/jvmci/jvmciCompilerToVM.cpp | 92 +-
|
|
.../jvmci/vmStructs_compiler_runtime.hpp | 45 +
|
|
src/hotspot/share/jvmci/vmStructs_jvmci.cpp | 7 +-
|
|
src/hotspot/share/logging/logTag.hpp | 6 +-
|
|
src/hotspot/share/memory/heap.hpp | 13 +-
|
|
src/hotspot/share/memory/metaspace.cpp | 8 +-
|
|
src/hotspot/share/memory/universe.cpp | 9 +-
|
|
src/hotspot/share/memory/virtualspace.hpp | 10 +-
|
|
src/hotspot/share/oops/compressedOops.cpp | 15 +-
|
|
src/hotspot/share/oops/instanceKlass.cpp | 92 +-
|
|
src/hotspot/share/oops/instanceKlass.hpp | 54 +-
|
|
.../share/oops/instanceKlass.inline.hpp | 31 +-
|
|
src/hotspot/share/oops/method.hpp | 20 +-
|
|
src/hotspot/share/oops/methodCounters.cpp | 13 +-
|
|
src/hotspot/share/oops/methodCounters.hpp | 10 +-
|
|
src/hotspot/share/opto/c2compiler.cpp | 4 +-
|
|
src/hotspot/share/opto/output.cpp | 6 +-
|
|
.../share/prims/jvmtiRedefineClasses.cpp | 17 +-
|
|
src/hotspot/share/prims/jvmtiTagMap.cpp | 4 +-
|
|
src/hotspot/share/prims/whitebox.cpp | 17 +-
|
|
.../share/runtime/abstract_vm_version.cpp | 10 +-
|
|
src/hotspot/share/runtime/arguments.cpp | 17 +-
|
|
src/hotspot/share/runtime/deoptimization.cpp | 12 +-
|
|
src/hotspot/share/runtime/frame.cpp | 10 +-
|
|
src/hotspot/share/runtime/globals.hpp | 19 +
|
|
src/hotspot/share/runtime/init.cpp | 8 +-
|
|
src/hotspot/share/runtime/java.cpp | 11 +-
|
|
src/hotspot/share/runtime/sharedRuntime.cpp | 9 +-
|
|
src/hotspot/share/runtime/thread.cpp | 15 +-
|
|
src/hotspot/share/runtime/vframe_hp.cpp | 4 +-
|
|
src/hotspot/share/runtime/vmStructs.cpp | 4 +-
|
|
src/hotspot/share/utilities/macros.hpp | 20 +-
|
|
src/hotspot/share/utilities/vmError.cpp | 6 +-
|
|
.../jaotc/binformat/BinaryContainer.java | 959 ++++++++++++++
|
|
.../tools/jaotc/binformat/ByteContainer.java | 261 ++++
|
|
.../tools/jaotc/binformat/CodeContainer.java | 36 +
|
|
.../jdk/tools/jaotc/binformat/Container.java | 34 +
|
|
.../jdk/tools/jaotc/binformat/GotSymbol.java | 64 +
|
|
.../jaotc/binformat/HeaderContainer.java | 94 ++
|
|
.../tools/jaotc/binformat/NativeSymbol.java | 53 +
|
|
.../binformat/ReadOnlyDataContainer.java | 33 +
|
|
.../jdk/tools/jaotc/binformat/Relocation.java | 97 ++
|
|
.../src/jdk/tools/jaotc/binformat/Symbol.java | 154 +++
|
|
.../tools/jaotc/binformat/SymbolTable.java | 34 +
|
|
.../binformat/elf/AArch64JELFRelocObject.java | 118 ++
|
|
.../binformat/elf/AMD64JELFRelocObject.java | 111 ++
|
|
.../jdk/tools/jaotc/binformat/elf/Elf.java | 277 ++++
|
|
.../jaotc/binformat/elf/ElfByteBuffer.java | 45 +
|
|
.../jaotc/binformat/elf/ElfContainer.java | 89 ++
|
|
.../tools/jaotc/binformat/elf/ElfHeader.java | 75 ++
|
|
.../jaotc/binformat/elf/ElfRelocEntry.java | 47 +
|
|
.../jaotc/binformat/elf/ElfRelocTable.java | 70 ++
|
|
.../tools/jaotc/binformat/elf/ElfSection.java | 157 +++
|
|
.../tools/jaotc/binformat/elf/ElfSymbol.java | 53 +
|
|
.../tools/jaotc/binformat/elf/ElfSymtab.java | 146 +++
|
|
.../jaotc/binformat/elf/ElfTargetInfo.java | 85 ++
|
|
.../jaotc/binformat/elf/JELFRelocObject.java | 328 +++++
|
|
.../binformat/macho/JMachORelocObject.java | 429 +++++++
|
|
.../tools/jaotc/binformat/macho/MachO.java | 311 +++++
|
|
.../binformat/macho/MachOByteBuffer.java | 43 +
|
|
.../jaotc/binformat/macho/MachOContainer.java | 83 ++
|
|
.../jaotc/binformat/macho/MachODySymtab.java | 51 +
|
|
.../jaotc/binformat/macho/MachOHeader.java | 57 +
|
|
.../binformat/macho/MachORelocEntry.java | 55 +
|
|
.../binformat/macho/MachORelocTable.java | 75 ++
|
|
.../jaotc/binformat/macho/MachOSection.java | 109 ++
|
|
.../jaotc/binformat/macho/MachOSegment.java | 53 +
|
|
.../jaotc/binformat/macho/MachOSymbol.java | 52 +
|
|
.../jaotc/binformat/macho/MachOSymtab.java | 209 +++
|
|
.../binformat/macho/MachOTargetInfo.java | 87 ++
|
|
.../jaotc/binformat/macho/MachOVersion.java | 47 +
|
|
.../binformat/pecoff/JPECoffRelocObject.java | 365 ++++++
|
|
.../tools/jaotc/binformat/pecoff/PECoff.java | 207 +++
|
|
.../binformat/pecoff/PECoffByteBuffer.java | 40 +
|
|
.../binformat/pecoff/PECoffContainer.java | 89 ++
|
|
.../jaotc/binformat/pecoff/PECoffHeader.java | 65 +
|
|
.../binformat/pecoff/PECoffRelocEntry.java | 47 +
|
|
.../binformat/pecoff/PECoffRelocTable.java | 86 ++
|
|
.../jaotc/binformat/pecoff/PECoffSection.java | 133 ++
|
|
.../jaotc/binformat/pecoff/PECoffSymbol.java | 58 +
|
|
.../jaotc/binformat/pecoff/PECoffSymtab.java | 150 +++
|
|
.../binformat/pecoff/PECoffTargetInfo.java | 74 ++
|
|
.../src/jdk/tools/jaotc/test/HelloWorld.java | 31 +
|
|
.../test/NativeOrderOutputStreamTest.java | 136 ++
|
|
.../jaotc/test/collect/ClassSearchTest.java | 219 ++++
|
|
.../jaotc/test/collect/ClassSourceTest.java | 66 +
|
|
.../jaotc/test/collect/FakeFileSupport.java | 114 ++
|
|
.../jaotc/test/collect/FakeSearchPath.java | 51 +
|
|
.../jaotc/test/collect/SearchPathTest.java | 122 ++
|
|
.../jdk/tools/jaotc/test/collect/Utils.java | 62 +
|
|
.../DirectorySourceProviderTest.java | 91 ++
|
|
.../collect/jar/JarSourceProviderTest.java | 127 ++
|
|
.../module/ModuleSourceProviderTest.java | 102 ++
|
|
.../src/jdk/tools/jaotc/AOTBackend.java | 176 +++
|
|
.../jdk/tools/jaotc/AOTCompilationTask.java | 211 ++++
|
|
.../src/jdk/tools/jaotc/AOTCompiledClass.java | 471 +++++++
|
|
.../src/jdk/tools/jaotc/AOTCompiler.java | 169 +++
|
|
.../jdk/tools/jaotc/AOTDynamicTypeStore.java | 172 +++
|
|
.../jaotc/AOTHotSpotResolvedJavaMethod.java | 64 +
|
|
.../src/jdk/tools/jaotc/AOTStub.java | 63 +
|
|
.../src/jdk/tools/jaotc/CallInfo.java | 105 ++
|
|
.../tools/jaotc/CallSiteRelocationInfo.java | 44 +
|
|
.../tools/jaotc/CallSiteRelocationSymbol.java | 84 ++
|
|
.../src/jdk/tools/jaotc/CodeOffsets.java | 102 ++
|
|
.../jdk/tools/jaotc/CodeSectionProcessor.java | 149 +++
|
|
.../src/jdk/tools/jaotc/Collector.java | 214 ++++
|
|
.../src/jdk/tools/jaotc/CompilationSpec.java | 127 ++
|
|
.../jdk/tools/jaotc/CompiledMethodInfo.java | 341 +++++
|
|
.../src/jdk/tools/jaotc/DataBuilder.java | 243 ++++
|
|
.../jdk/tools/jaotc/DataPatchProcessor.java | 165 +++
|
|
.../jdk/tools/jaotc/ELFMacroAssembler.java | 58 +
|
|
.../jaotc/ForeignCallSiteRelocationInfo.java | 75 ++
|
|
.../ForeignCallSiteRelocationSymbol.java | 41 +
|
|
.../ForeignGotCallSiteRelocationSymbol.java | 72 ++
|
|
.../src/jdk/tools/jaotc/GraalFilters.java | 147 +++
|
|
.../jdk/tools/jaotc/InfopointProcessor.java | 149 +++
|
|
.../jdk/tools/jaotc/InstructionDecoder.java | 53 +
|
|
.../jaotc/JavaCallSiteRelocationInfo.java | 43 +
|
|
.../jaotc/JavaCallSiteRelocationSymbol.java | 155 +++
|
|
.../src/jdk/tools/jaotc/JavaMethodInfo.java | 61 +
|
|
.../src/jdk/tools/jaotc/Linker.java | 261 ++++
|
|
.../src/jdk/tools/jaotc/LoadedClass.java | 73 ++
|
|
.../src/jdk/tools/jaotc/LogPrinter.java | 198 +++
|
|
.../src/jdk/tools/jaotc/Main.java | 356 ++++++
|
|
.../src/jdk/tools/jaotc/MarkProcessor.java | 137 ++
|
|
.../src/jdk/tools/jaotc/MetadataBuilder.java | 251 ++++
|
|
.../src/jdk/tools/jaotc/Options.java | 300 +++++
|
|
.../StubDirectCallSiteRelocationSymbol.java | 41 +
|
|
.../src/jdk/tools/jaotc/StubInformation.java | 124 ++
|
|
.../src/jdk/tools/jaotc/Timer.java | 45 +
|
|
.../aarch64/AArch64ELFMacroAssembler.java | 131 ++
|
|
.../aarch64/AArch64InstructionDecoder.java | 47 +
|
|
.../jaotc/amd64/AMD64ELFMacroAssembler.java | 122 ++
|
|
.../jaotc/amd64/AMD64InstructionDecoder.java | 569 +++++++++
|
|
.../jdk/tools/jaotc/collect/ClassSearch.java | 116 ++
|
|
.../jdk/tools/jaotc/collect/ClassSource.java | 66 +
|
|
.../jdk/tools/jaotc/collect/FileSupport.java | 103 ++
|
|
.../tools/jaotc/collect/FileSystemFinder.java | 83 ++
|
|
.../jdk/tools/jaotc/collect/SearchFor.java | 57 +
|
|
.../jdk/tools/jaotc/collect/SearchPath.java | 89 ++
|
|
.../tools/jaotc/collect/SourceProvider.java | 32 +
|
|
.../collect/classname/ClassNameSource.java | 45 +
|
|
.../classname/ClassNameSourceProvider.java | 70 ++
|
|
.../collect/directory/DirectorySource.java | 56 +
|
|
.../directory/DirectorySourceProvider.java | 71 ++
|
|
.../jaotc/collect/jar/JarFileSource.java | 58 +
|
|
.../jaotc/collect/jar/JarSourceProvider.java | 86 ++
|
|
.../jaotc/collect/module/ModuleSource.java | 60 +
|
|
.../collect/module/ModuleSourceProvider.java | 85 ++
|
|
.../jaotc/utils/NativeOrderOutputStream.java | 193 +++
|
|
src/jdk.aot/share/classes/module-info.java | 37 +
|
|
src/jdk.aot/share/man/jaotc.1 | 209 +++
|
|
.../sun/jvm/hotspot/code/CodeBlob.java | 4 +-
|
|
.../sun/jvm/hotspot/oops/InstanceKlass.java | 29 +-
|
|
.../classes/sun/jvm/hotspot/runtime/VM.java | 19 +-
|
|
.../share/classes/module-info.java | 31 +
|
|
.../core/test/CheckGraalInvariants.java | 1 +
|
|
.../core/test/VerifySystemPropertyUsage.java | 4 +
|
|
test/hotspot/jtreg/ProblemList-aot.txt | 82 ++
|
|
test/hotspot/jtreg/TEST.ROOT | 2 +
|
|
test/hotspot/jtreg/TEST.groups | 7 +-
|
|
.../applications/ctw/modules/jdk_aot.java | 38 +
|
|
.../jtreg/compiler/aot/AotCompiler.java | 280 +++++
|
|
.../compiler/aot/DeoptimizationTest.java | 86 ++
|
|
.../jtreg/compiler/aot/HelloWorldPrinter.java | 41 +
|
|
.../jtreg/compiler/aot/RecompilationTest.java | 110 ++
|
|
.../jtreg/compiler/aot/SharedUsageTest.java | 79 ++
|
|
.../jtreg/compiler/aot/TestHeapBase.java | 81 ++
|
|
.../fromAot/AotInvokeDynamic2AotTest.java | 43 +
|
|
.../AotInvokeDynamic2CompiledTest.java | 48 +
|
|
.../AotInvokeDynamic2InterpretedTest.java | 44 +
|
|
.../fromAot/AotInvokeDynamic2NativeTest.java | 42 +
|
|
.../fromAot/AotInvokeInterface2AotTest.java | 41 +
|
|
.../AotInvokeInterface2CompiledTest.java | 47 +
|
|
.../AotInvokeInterface2InterpretedTest.java | 42 +
|
|
.../AotInvokeInterface2NativeTest.java | 40 +
|
|
.../fromAot/AotInvokeSpecial2AotTest.java | 41 +
|
|
.../AotInvokeSpecial2CompiledTest.java | 46 +
|
|
.../AotInvokeSpecial2InterpretedTest.java | 42 +
|
|
.../fromAot/AotInvokeSpecial2NativeTest.java | 40 +
|
|
.../fromAot/AotInvokeStatic2AotTest.java | 41 +
|
|
.../fromAot/AotInvokeStatic2CompiledTest.java | 46 +
|
|
.../AotInvokeStatic2InterpretedTest.java | 42 +
|
|
.../fromAot/AotInvokeStatic2NativeTest.java | 40 +
|
|
.../fromAot/AotInvokeVirtual2AotTest.java | 41 +
|
|
.../AotInvokeVirtual2CompiledTest.java | 46 +
|
|
.../AotInvokeVirtual2InterpretedTest.java | 42 +
|
|
.../fromAot/AotInvokeVirtual2NativeTest.java | 40 +
|
|
.../CompiledInvokeDynamic2AotTest.java | 48 +
|
|
.../CompiledInvokeInterface2AotTest.java | 47 +
|
|
.../CompiledInvokeSpecial2AotTest.java | 46 +
|
|
.../CompiledInvokeStatic2AotTest.java | 46 +
|
|
.../CompiledInvokeVirtual2AotTest.java | 46 +
|
|
.../InterpretedInvokeDynamic2AotTest.java | 44 +
|
|
.../InterpretedInvokeInterface2AotTest.java | 42 +
|
|
.../InterpretedInvokeSpecial2AotTest.java | 42 +
|
|
.../InterpretedInvokeStatic2AotTest.java | 42 +
|
|
.../InterpretedInvokeVirtual2AotTest.java | 42 +
|
|
.../NativeInvokeSpecial2AotTest.java | 40 +
|
|
.../NativeInvokeStatic2AotTest.java | 40 +
|
|
.../NativeInvokeVirtual2AotTest.java | 40 +
|
|
.../aot/cli/AotLibraryNegativeBase.java | 49 +
|
|
.../aot/cli/DisabledAOTWithLibraryTest.java | 66 +
|
|
.../aot/cli/IncorrectAOTLibraryTest.java | 48 +
|
|
.../aot/cli/MultipleAOTLibraryTest.java | 96 ++
|
|
.../aot/cli/NonExistingAOTLibraryTest.java | 50 +
|
|
.../aot/cli/SingleAOTLibraryTest.java | 77 ++
|
|
.../compiler/aot/cli/SingleAOTOptionTest.java | 86 ++
|
|
.../compiler/aot/cli/jaotc/AtFileTest.java | 60 +
|
|
.../ClasspathOptionUnknownClassTest.java | 47 +
|
|
.../jaotc/CompileAbsoluteDirectoryTest.java | 60 +
|
|
.../aot/cli/jaotc/CompileClassTest.java | 52 +
|
|
.../cli/jaotc/CompileClassWithDebugTest.java | 52 +
|
|
.../aot/cli/jaotc/CompileDirectoryTest.java | 53 +
|
|
.../aot/cli/jaotc/CompileJarTest.java | 75 ++
|
|
.../aot/cli/jaotc/CompileModuleTest.java | 75 ++
|
|
.../aot/cli/jaotc/IgnoreErrorsTest.java | 88 ++
|
|
.../compiler/aot/cli/jaotc/IllegalClass.jasm | 27 +
|
|
.../aot/cli/jaotc/JaotcTestHelper.java | 93 ++
|
|
.../cli/jaotc/ListOptionNotExistingTest.java | 54 +
|
|
.../aot/cli/jaotc/ListOptionTest.java | 76 ++
|
|
.../cli/jaotc/ListOptionWrongFileTest.java | 63 +
|
|
.../aot/cli/jaotc/data/HelloWorldOne.java | 32 +
|
|
.../aot/cli/jaotc/data/HelloWorldTwo.java | 33 +
|
|
.../compiler/aot/fingerprint/CDSDumper.java | 69 +
|
|
.../compiler/aot/fingerprint/CDSRunner.java | 42 +
|
|
.../compiler/aot/fingerprint/SelfChanged.java | 132 ++
|
|
.../aot/fingerprint/SelfChangedCDS.java | 90 ++
|
|
.../aot/fingerprint/SuperChanged.java | 113 ++
|
|
.../test/NativeOrderOutputStreamTest.java | 131 ++
|
|
.../jaotc/test/collect/ClassSearchTest.java | 211 ++++
|
|
.../jaotc/test/collect/ClassSourceTest.java | 64 +
|
|
.../jaotc/test/collect/FakeFileSupport.java | 112 ++
|
|
.../jaotc/test/collect/FakeSearchPath.java | 49 +
|
|
.../jaotc/test/collect/SearchPathTest.java | 118 ++
|
|
.../jdk/tools/jaotc/test/collect/Utils.java | 58 +
|
|
.../DirectorySourceProviderTest.java | 89 ++
|
|
.../collect/jar/JarSourceProviderTest.java | 128 ++
|
|
.../module/ModuleSourceProviderTest.java | 103 ++
|
|
.../compiler/aot/scripts/HelloWorld.java | 5 +
|
|
.../jtreg/compiler/aot/scripts/InitGraal.java | 30 +
|
|
.../hotspot/jtreg/compiler/aot/scripts/README | 32 +
|
|
.../compiler/aot/scripts/build-bootmodules.sh | 106 ++
|
|
.../aot/scripts/build-jdk.vm-modules.sh | 110 ++
|
|
.../jtreg/compiler/aot/scripts/empty.js | 1 +
|
|
.../compiler/aot/scripts/java.base-list.txt | 20 +
|
|
.../scripts/jdk.internal.vm.compiler-list.txt | 45 +
|
|
.../jtreg/compiler/aot/scripts/test-env.sh | 42 +
|
|
.../jtreg/compiler/aot/scripts/test-graal.sh | 62 +
|
|
.../compiler/aot/scripts/test-helloworld.sh | 97 ++
|
|
.../jtreg/compiler/aot/scripts/test-jaotc.sh | 43 +
|
|
.../jtreg/compiler/aot/scripts/test-javac.sh | 157 +++
|
|
.../ClassAndLibraryNotMatchTest.java | 124 ++
|
|
.../vmflags/BasicFlagsChange.java | 112 ++
|
|
.../vmflags/NotTrackedFlagTest.java | 33 +
|
|
.../verification/vmflags/TrackedFlagTest.java | 34 +
|
|
.../intrinsics/bigInteger/TestMulAdd.java | 2 +
|
|
.../sha/sanity/TestMD5Intrinsics.java | 4 +-
|
|
.../sanity/TestMD5MultiBlockIntrinsics.java | 4 +-
|
|
.../sha/sanity/TestSHA1Intrinsics.java | 4 +-
|
|
.../sanity/TestSHA1MultiBlockIntrinsics.java | 4 +-
|
|
.../sha/sanity/TestSHA256Intrinsics.java | 4 +-
|
|
.../TestSHA256MultiBlockIntrinsics.java | 4 +-
|
|
.../sha/sanity/TestSHA3Intrinsics.java | 6 +-
|
|
.../sanity/TestSHA3MultiBlockIntrinsics.java | 6 +-
|
|
.../sha/sanity/TestSHA512Intrinsics.java | 4 +-
|
|
.../TestSHA512MultiBlockIntrinsics.java | 4 +-
|
|
.../whitebox/CompilerWhiteBoxTest.java | 4 +-
|
|
.../CompressedClassPointers.java | 5 +-
|
|
.../cds/TestInterpreterMethodEntries.java | 4 +-
|
|
.../dcmd/compiler/CodelistTest.java | 4 +-
|
|
.../jtreg/testlibrary/jittester/Makefile | 13 +-
|
|
.../jittester/conf/default.properties | 2 +-
|
|
.../jittester/AotTestGeneratorsFactory.java | 72 ++
|
|
.../vm/compiler/CodeCacheInfo/Test.java | 11 +-
|
|
test/jdk/ProblemList-aot.txt | 34 +
|
|
.../FieldSetAccessibleTest.java | 6 +-
|
|
.../jdk/modules/etc/UpgradeableModules.java | 3 +-
|
|
test/jdk/tools/jimage/VerifyJimage.java | 2 +-
|
|
test/jdk/tools/launcher/HelpFlagsTest.java | 5 +-
|
|
test/jdk/tools/launcher/VersionCheck.java | 4 +-
|
|
test/jtreg-ext/requires/VMProps.java | 42 +
|
|
test/lib/jdk/test/whitebox/WhiteBox.java | 3 +
|
|
test/lib/jdk/test/whitebox/code/CodeBlob.java | 10 +-
|
|
378 files changed, 27158 insertions(+), 310 deletions(-)
|
|
create mode 100644 make/modules/jdk.aot/Java.gmk
|
|
create mode 100644 make/modules/jdk.aot/Launcher.gmk
|
|
create mode 100644 src/hotspot/cpu/aarch64/compiledIC_aot_aarch64.cpp
|
|
create mode 100644 src/hotspot/cpu/x86/compiledIC_aot_x86_64.cpp
|
|
create mode 100644 src/hotspot/share/aot/aotCodeHeap.cpp
|
|
create mode 100644 src/hotspot/share/aot/aotCodeHeap.hpp
|
|
create mode 100644 src/hotspot/share/aot/aotCompiledMethod.cpp
|
|
create mode 100644 src/hotspot/share/aot/aotCompiledMethod.hpp
|
|
create mode 100644 src/hotspot/share/aot/aotLoader.cpp
|
|
create mode 100644 src/hotspot/share/aot/aotLoader.hpp
|
|
create mode 100644 src/hotspot/share/aot/aotLoader.inline.hpp
|
|
create mode 100644 src/hotspot/share/aot/compiledIC_aot.cpp
|
|
create mode 100644 src/hotspot/share/aot/compiledIC_aot.hpp
|
|
create mode 100644 src/hotspot/share/jvmci/compilerRuntime.cpp
|
|
create mode 100644 src/hotspot/share/jvmci/compilerRuntime.hpp
|
|
create mode 100644 src/hotspot/share/jvmci/vmStructs_compiler_runtime.hpp
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/ByteContainer.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/CodeContainer.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/Container.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/GotSymbol.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/HeaderContainer.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/NativeSymbol.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/ReadOnlyDataContainer.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/Relocation.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/Symbol.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/SymbolTable.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/AArch64JELFRelocObject.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/AMD64JELFRelocObject.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/Elf.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfByteBuffer.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfContainer.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfHeader.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfRelocEntry.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfRelocTable.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSection.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSymbol.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSymtab.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfTargetInfo.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/JELFRelocObject.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/JMachORelocObject.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachO.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOByteBuffer.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOContainer.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachODySymtab.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOHeader.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachORelocEntry.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachORelocTable.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSection.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSegment.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSymbol.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSymtab.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOTargetInfo.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOVersion.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/JPECoffRelocObject.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoff.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffByteBuffer.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffContainer.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffHeader.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffRelocEntry.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffRelocTable.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSection.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSymbol.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSymtab.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffTargetInfo.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/HelloWorld.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/NativeOrderOutputStreamTest.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/ClassSearchTest.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/ClassSourceTest.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/FakeFileSupport.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/FakeSearchPath.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/SearchPathTest.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/Utils.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/directory/DirectorySourceProviderTest.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/jar/JarSourceProviderTest.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/module/ModuleSourceProviderTest.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTBackend.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompilationTask.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiledClass.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiler.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTDynamicTypeStore.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTHotSpotResolvedJavaMethod.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTStub.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CallInfo.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CallSiteRelocationInfo.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CallSiteRelocationSymbol.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CodeOffsets.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CodeSectionProcessor.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Collector.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CompilationSpec.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CompiledMethodInfo.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataBuilder.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataPatchProcessor.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/ELFMacroAssembler.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/ForeignCallSiteRelocationInfo.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/ForeignCallSiteRelocationSymbol.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/ForeignGotCallSiteRelocationSymbol.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/GraalFilters.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/InfopointProcessor.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/InstructionDecoder.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/JavaCallSiteRelocationInfo.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/JavaCallSiteRelocationSymbol.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/JavaMethodInfo.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Linker.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/LoadedClass.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/LogPrinter.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MarkProcessor.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MetadataBuilder.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Options.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/StubDirectCallSiteRelocationSymbol.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/StubInformation.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Timer.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/aarch64/AArch64ELFMacroAssembler.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/aarch64/AArch64InstructionDecoder.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/amd64/AMD64ELFMacroAssembler.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/amd64/AMD64InstructionDecoder.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassSearch.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassSource.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/FileSupport.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/FileSystemFinder.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/SearchFor.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/SearchPath.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/SourceProvider.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/classname/ClassNameSource.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/classname/ClassNameSourceProvider.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/directory/DirectorySource.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/directory/DirectorySourceProvider.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/jar/JarFileSource.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/jar/JarSourceProvider.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/module/ModuleSource.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/module/ModuleSourceProvider.java
|
|
create mode 100644 src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/utils/NativeOrderOutputStream.java
|
|
create mode 100644 src/jdk.aot/share/classes/module-info.java
|
|
create mode 100644 src/jdk.aot/share/man/jaotc.1
|
|
create mode 100644 test/hotspot/jtreg/ProblemList-aot.txt
|
|
create mode 100644 test/hotspot/jtreg/applications/ctw/modules/jdk_aot.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/AotCompiler.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/DeoptimizationTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/HelloWorldPrinter.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/RecompilationTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/SharedUsageTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/TestHeapBase.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeDynamic2AotTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeDynamic2CompiledTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeDynamic2InterpretedTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeDynamic2NativeTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeInterface2AotTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeInterface2CompiledTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeInterface2InterpretedTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeInterface2NativeTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeSpecial2AotTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeSpecial2CompiledTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeSpecial2InterpretedTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeSpecial2NativeTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeStatic2AotTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeStatic2CompiledTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeStatic2InterpretedTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeStatic2NativeTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeVirtual2AotTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeVirtual2CompiledTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeVirtual2InterpretedTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeVirtual2NativeTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/calls/fromCompiled/CompiledInvokeDynamic2AotTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/calls/fromCompiled/CompiledInvokeInterface2AotTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/calls/fromCompiled/CompiledInvokeSpecial2AotTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/calls/fromCompiled/CompiledInvokeStatic2AotTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/calls/fromCompiled/CompiledInvokeVirtual2AotTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/calls/fromInterpreted/InterpretedInvokeDynamic2AotTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/calls/fromInterpreted/InterpretedInvokeInterface2AotTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/calls/fromInterpreted/InterpretedInvokeSpecial2AotTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/calls/fromInterpreted/InterpretedInvokeStatic2AotTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/calls/fromInterpreted/InterpretedInvokeVirtual2AotTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/calls/fromNative/NativeInvokeSpecial2AotTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/calls/fromNative/NativeInvokeStatic2AotTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/calls/fromNative/NativeInvokeVirtual2AotTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/cli/AotLibraryNegativeBase.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/cli/DisabledAOTWithLibraryTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/cli/IncorrectAOTLibraryTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/cli/MultipleAOTLibraryTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/cli/NonExistingAOTLibraryTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/cli/SingleAOTLibraryTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/cli/SingleAOTOptionTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/cli/jaotc/AtFileTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/cli/jaotc/ClasspathOptionUnknownClassTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/cli/jaotc/CompileAbsoluteDirectoryTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/cli/jaotc/CompileClassTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/cli/jaotc/CompileClassWithDebugTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/cli/jaotc/CompileDirectoryTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/cli/jaotc/CompileJarTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/cli/jaotc/CompileModuleTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/cli/jaotc/IgnoreErrorsTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/cli/jaotc/IllegalClass.jasm
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/cli/jaotc/JaotcTestHelper.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/cli/jaotc/ListOptionNotExistingTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/cli/jaotc/ListOptionTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/cli/jaotc/ListOptionWrongFileTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/cli/jaotc/data/HelloWorldOne.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/cli/jaotc/data/HelloWorldTwo.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/fingerprint/CDSDumper.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/fingerprint/CDSRunner.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/fingerprint/SelfChanged.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/fingerprint/SelfChangedCDS.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/fingerprint/SuperChanged.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/NativeOrderOutputStreamTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/ClassSearchTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/ClassSourceTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/FakeFileSupport.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/FakeSearchPath.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/SearchPathTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/Utils.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/directory/DirectorySourceProviderTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/jar/JarSourceProviderTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/module/ModuleSourceProviderTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/scripts/HelloWorld.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/scripts/InitGraal.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/scripts/README
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/scripts/build-bootmodules.sh
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/scripts/build-jdk.vm-modules.sh
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/scripts/empty.js
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/scripts/java.base-list.txt
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/scripts/jdk.internal.vm.compiler-list.txt
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/scripts/test-env.sh
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/scripts/test-graal.sh
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/scripts/test-helloworld.sh
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/scripts/test-jaotc.sh
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/scripts/test-javac.sh
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/verification/ClassAndLibraryNotMatchTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/verification/vmflags/BasicFlagsChange.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/verification/vmflags/NotTrackedFlagTest.java
|
|
create mode 100644 test/hotspot/jtreg/compiler/aot/verification/vmflags/TrackedFlagTest.java
|
|
create mode 100644 test/hotspot/jtreg/testlibrary/jittester/src/jdk/test/lib/jittester/AotTestGeneratorsFactory.java
|
|
create mode 100644 test/jdk/ProblemList-aot.txt
|
|
|
|
diff --git a/make/RunTests.gmk b/make/RunTests.gmk
|
|
index 57a282bfd..9fad1ed43 100644
|
|
--- a/make/RunTests.gmk
|
|
+++ b/make/RunTests.gmk
|
|
@@ -46,7 +46,7 @@ endif
|
|
|
|
$(eval $(call ParseKeywordVariable, TEST_OPTS, \
|
|
SINGLE_KEYWORDS := JOBS TIMEOUT_FACTOR JCOV JCOV_DIFF_CHANGESET, \
|
|
- STRING_KEYWORDS := VM_OPTIONS JAVA_OPTIONS, \
|
|
+ STRING_KEYWORDS := VM_OPTIONS JAVA_OPTIONS AOT_MODULES, \
|
|
))
|
|
|
|
# Helper function to propagate TEST_OPTS values.
|
|
@@ -134,6 +134,96 @@ ifeq ($(GCOV_ENABLED), true)
|
|
JTREG_COV_OPTIONS += -e:GCOV_PREFIX="$(GCOV_OUTPUT_DIR)"
|
|
endif
|
|
|
|
+################################################################################
|
|
+# Optionally create AOT libraries for specified modules before running tests.
|
|
+# Note, this could not be done during JDK build time.
|
|
+################################################################################
|
|
+# Parameter 1 is the name of the rule.
|
|
+#
|
|
+# Remaining parameters are named arguments.
|
|
+# MODULE The module to generate a library for
|
|
+# BIN Output directory in which to put the library
|
|
+# VM_OPTIONS List of JVM arguments to use when creating library
|
|
+# OPTIONS_VAR Name of variable to put AOT java options in
|
|
+# PREREQS_VAR Name of variable to put all AOT prerequisite rule targets in
|
|
+# for test rules to depend on
|
|
+#
|
|
+SetupAotModule = $(NamedParamsMacroTemplate)
|
|
+define SetupAotModuleBody
|
|
+ $1_AOT_LIB := $$($1_BIN)/$$(call SHARED_LIBRARY,$$($1_MODULE))
|
|
+ $1_AOT_CCLIST := $$(wildcard $$(TOPDIR)/test/hotspot/jtreg/compiler/aot/scripts/$$($1_MODULE)-list.txt)
|
|
+
|
|
+ # Create jaotc flags.
|
|
+ # VM flags which don't affect AOT code generation are filtered out:
|
|
+ # -Xcomp, -XX:+-TieredCompilation
|
|
+ $1_JAOTC_OPTS := \
|
|
+ -J-Xmx4g --info \
|
|
+ $$(addprefix -J, $$(filter-out -Xcomp %TieredCompilation, $$($1_VM_OPTIONS))) \
|
|
+ $$(addprefix --compile-commands$(SPACE), $$($1_AOT_CCLIST)) \
|
|
+ --linker-path $$(LD_JAOTC) \
|
|
+ #
|
|
+
|
|
+ ifneq ($$(filter -ea, $$($1_VM_OPTIONS)), )
|
|
+ $1_JAOTC_OPTS += --compile-with-assertions
|
|
+ endif
|
|
+
|
|
+ ifneq ($$(filter -XX:+VerifyOops, $$($1_VM_OPTIONS)), )
|
|
+ $1_JAOTC_OPTS += -J-Dgraal.AOTVerifyOops=true
|
|
+ endif
|
|
+
|
|
+ $$($1_AOT_LIB): $$(JDK_UNDER_TEST)/release \
|
|
+ $$(call DependOnVariable, $1_JAOTC_OPTS) \
|
|
+ $$(call DependOnVariable, JDK_UNDER_TEST)
|
|
+ $$(call LogWarn, Generating $$(patsubst $$(OUTPUTDIR)/%, %, $$@))
|
|
+ $$(call MakeTargetDir)
|
|
+ $$(call ExecuteWithLog, $$@, \
|
|
+ $((COV_ENVIRONMENT) \
|
|
+ $$(FIXPATH) $$(JDK_UNDER_TEST)/bin/jaotc \
|
|
+ $$($1_JAOTC_OPTS) --output $$@ --module $$($1_MODULE) \
|
|
+ )
|
|
+ $$(call ExecuteWithLog, $$@.check, ( \
|
|
+ $$(FIXPATH) $$(JDK_UNDER_TEST)/bin/java \
|
|
+ $$($1_VM_OPTIONS) -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions \
|
|
+ -XX:+PrintAOT -XX:+UseAOTStrictLoading \
|
|
+ -XX:AOTLibrary=$$@ -version \
|
|
+ > $$@.verify-aot \
|
|
+ ))
|
|
+
|
|
+ $1_AOT_OPTIONS += -XX:+UnlockExperimentalVMOptions
|
|
+ $1_AOT_OPTIONS += -XX:AOTLibrary=$$($1_AOT_LIB)
|
|
+ $1_AOT_TARGETS += $$($1_AOT_LIB)
|
|
+endef
|
|
+
|
|
+################################################################################
|
|
+# Optionally create AOT libraries before running tests.
|
|
+# Note, this could not be done during JDK build time.
|
|
+################################################################################
|
|
+# Parameter 1 is the name of the rule.
|
|
+#
|
|
+# Remaining parameters are named arguments.
|
|
+# MODULES The modules to generate a library for
|
|
+# VM_OPTIONS List of JVM arguments to use when creating libraries
|
|
+#
|
|
+# After calling this, the following variables are defined
|
|
+# $1_AOT_OPTIONS List of all java options needed to use the AOT libraries
|
|
+# $1_AOT_TARGETS List of all targets that the test rule will need to depend on
|
|
+#
|
|
+SetupAot = $(NamedParamsMacroTemplate)
|
|
+define SetupAotBody
|
|
+ $$(info Running with AOTd libraries for $$($1_MODULES))
|
|
+ # Put aot libraries in a separate directory so they are not deleted between
|
|
+ # test runs and may be reused between make invocations.
|
|
+ $$(foreach m, $$($1_MODULES), \
|
|
+ $$(eval $$(call SetupAotModule, $1_$$m, \
|
|
+ MODULE := $$m, \
|
|
+ BIN := $$(TEST_SUPPORT_DIR)/aot/$1, \
|
|
+ VM_OPTIONS := $$($1_VM_OPTIONS), \
|
|
+ )) \
|
|
+ $$(eval $1_AOT_OPTIONS += $$($1_$$m_AOT_OPTIONS)) \
|
|
+ $$(eval $1_AOT_TARGETS += $$($1_$$m_AOT_TARGETS)) \
|
|
+ )
|
|
+endef
|
|
+
|
|
################################################################################
|
|
# Setup global test running parameters
|
|
################################################################################
|
|
@@ -192,6 +282,7 @@ endif
|
|
|
|
$(eval $(call SetTestOpt,VM_OPTIONS,JTREG))
|
|
$(eval $(call SetTestOpt,JAVA_OPTIONS,JTREG))
|
|
+$(eval $(call SetTestOpt,AOT_MODULES,JTREG))
|
|
|
|
$(eval $(call SetTestOpt,JOBS,JTREG))
|
|
$(eval $(call SetTestOpt,TIMEOUT_FACTOR,JTREG))
|
|
@@ -202,7 +293,7 @@ $(eval $(call ParseKeywordVariable, JTREG, \
|
|
TEST_MODE ASSERT VERBOSE RETAIN MAX_MEM RUN_PROBLEM_LISTS \
|
|
RETRY_COUNT REPEAT_COUNT MAX_OUTPUT $(CUSTOM_JTREG_SINGLE_KEYWORDS), \
|
|
STRING_KEYWORDS := OPTIONS JAVA_OPTIONS VM_OPTIONS KEYWORDS \
|
|
- EXTRA_PROBLEM_LISTS LAUNCHER_OPTIONS\
|
|
+ EXTRA_PROBLEM_LISTS AOT_MODULES LAUNCHER_OPTIONS\
|
|
$(CUSTOM_JTREG_STRING_KEYWORDS), \
|
|
))
|
|
|
|
@@ -306,10 +306,11 @@ endif
|
|
|
|
$(eval $(call SetTestOpt,VM_OPTIONS,GTEST))
|
|
$(eval $(call SetTestOpt,JAVA_OPTIONS,GTEST))
|
|
+$(eval $(call SetTestOpt,AOT_MODULES,GTEST))
|
|
|
|
$(eval $(call ParseKeywordVariable, GTEST, \
|
|
SINGLE_KEYWORDS := REPEAT, \
|
|
- STRING_KEYWORDS := OPTIONS VM_OPTIONS JAVA_OPTIONS, \
|
|
+ STRING_KEYWORDS := OPTIONS VM_OPTIONS JAVA_OPTIONS AOT_MODULES, \
|
|
))
|
|
|
|
ifneq ($(GTEST), )
|
|
@@ -499,7 +590,14 @@ define SetupRunGtestTestBody
|
|
$1_GTEST_REPEAT :=--gtest_repeat=$$(GTEST_REPEAT)
|
|
endif
|
|
|
|
- run-test-$1: pre-run-test
|
|
+ ifneq ($$(GTEST_AOT_MODULES), )
|
|
+ $$(eval $$(call SetupAot, $1, \
|
|
+ MODULES := $$(GTEST_AOT_MODULES), \
|
|
+ VM_OPTIONS := $$(GTEST_VM_OPTIONS) $$(GTEST_JAVA_OPTIONS), \
|
|
+ ))
|
|
+ endif
|
|
+
|
|
+ run-test-$1: pre-run-test $$($1_AOT_TARGETS)
|
|
$$(call LogWarn)
|
|
$$(call LogWarn, Running test '$$($1_TEST)')
|
|
$$(call MakeDir, $$($1_TEST_RESULTS_DIR) $$($1_TEST_SUPPORT_DIR))
|
|
@@ -510,7 +608,7 @@ define SetupRunGtestTestBody
|
|
--gtest_output=xml:$$($1_TEST_RESULTS_DIR)/gtest.xml \
|
|
--gtest_catch_exceptions=0 \
|
|
$$($1_GTEST_REPEAT) $$(GTEST_OPTIONS) $$(GTEST_VM_OPTIONS) \
|
|
- $$(GTEST_JAVA_OPTIONS) \
|
|
+ $$(GTEST_JAVA_OPTIONS) $$($1_AOT_OPTIONS) \
|
|
> >($(TEE) $$($1_TEST_RESULTS_DIR)/gtest.txt) \
|
|
&& $$(ECHO) $$$$? > $$($1_EXITCODE) \
|
|
|| $$(ECHO) $$$$? > $$($1_EXITCODE) \
|
|
@@ -874,6 +972,17 @@ define SetupRunJtregTestBody
|
|
|
|
JTREG_TIMEOUT_FACTOR ?= $$(JTREG_AUTO_TIMEOUT_FACTOR)
|
|
|
|
+ ifneq ($$(JTREG_AOT_MODULES), )
|
|
+ $$(eval $$(call SetupAot, $1, \
|
|
+ MODULES := $$(JTREG_AOT_MODULES), \
|
|
+ VM_OPTIONS := $$(JTREG_VM_OPTIONS) $$(JTREG_JAVA_OPTIONS), \
|
|
+ ))
|
|
+ endif
|
|
+
|
|
+ ifneq ($$($1_AOT_OPTIONS), )
|
|
+ $1_JTREG_BASIC_OPTIONS += -vmoptions:"$$($1_AOT_OPTIONS)"
|
|
+ endif
|
|
+
|
|
clean-outputdirs-$1:
|
|
$$(RM) -r $$($1_TEST_SUPPORT_DIR)
|
|
$$(RM) -r $$($1_TEST_RESULTS_DIR)
|
|
@@ -921,7 +1030,7 @@ define SetupRunJtregTestBody
|
|
done
|
|
endif
|
|
|
|
- run-test-$1: pre-run-test clean-outputdirs-$1
|
|
+ run-test-$1: pre-run-test clean-outputdirs-$1 $$($1_AOT_TARGETS)
|
|
$$(call LogWarn)
|
|
$$(call LogWarn, Running test '$$($1_TEST)')
|
|
$$(call MakeDir, $$($1_TEST_RESULTS_DIR) $$($1_TEST_SUPPORT_DIR) \
|
|
diff --git a/make/RunTestsPrebuilt.gmk b/make/RunTestsPrebuilt.gmk
|
|
index 7c1c55b20..c5f4453cd 100644
|
|
--- a/make/RunTestsPrebuilt.gmk
|
|
+++ b/make/RunTestsPrebuilt.gmk
|
|
@@ -1,5 +1,5 @@
|
|
#
|
|
-# Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
+# Copyright (c) 2017, 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
|
|
@@ -230,6 +230,25 @@ ifeq ($(MEMORY_SIZE), )
|
|
MEMORY_SIZE := 1024
|
|
endif
|
|
|
|
+# Setup LD for AOT support
|
|
+ifneq ($(DEVKIT_HOME), )
|
|
+ ifeq ($(OPENJDK_TARGET_OS), windows)
|
|
+ LD_JAOTC := $(DEVKIT_HOME)/VC/bin/x64/link.exe
|
|
+ LIBRARY_PREFIX :=
|
|
+ SHARED_LIBRARY_SUFFIX := .dll
|
|
+ else ifeq ($(OPENJDK_TARGET_OS), linux)
|
|
+ LD_JAOTC := $(DEVKIT_HOME)/bin/ld
|
|
+ LIBRARY_PREFIX := lib
|
|
+ SHARED_LIBRARY_SUFFIX := .so
|
|
+ else ifeq ($(OPENJDK_TARGET_OS), macosx)
|
|
+ LD_JAOTC := $(DEVKIT_HOME)/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld
|
|
+ LIBRARY_PREFIX := lib
|
|
+ SHARED_LIBRARY_SUFFIX := .dylib
|
|
+ endif
|
|
+else
|
|
+ LD := ld
|
|
+endif
|
|
+
|
|
ifneq ($(wildcard $(JDK_IMAGE_DIR)/template.xml), )
|
|
TEST_OPTS_JCOV := true
|
|
JCOV_IMAGE_DIR := $(JDK_IMAGE_DIR)
|
|
@@ -276,6 +295,9 @@ $(call CreateNewSpec, $(NEW_SPEC), \
|
|
OPENJDK_TARGET_CPU_ENDIAN := $(OPENJDK_TARGET_CPU_ENDIAN), \
|
|
NUM_CORES := $(NUM_CORES), \
|
|
MEMORY_SIZE := $(MEMORY_SIZE), \
|
|
+ LD_JAOTC := $(LD_JAOTC), \
|
|
+ LIBRARY_PREFIX := $(LIBRARY_PREFIX), \
|
|
+ SHARED_LIBRARY_SUFFIX := $(SHARED_LIBRARY_SUFFIX), \
|
|
include $(TOPDIR)/make/RunTestsPrebuiltSpec.gmk, \
|
|
TEST_OPTS_JCOV := $(TEST_OPTS_JCOV), \
|
|
$(CUSTOM_NEW_SPEC_LINE), \
|
|
diff --git a/make/autoconf/jvm-features.m4 b/make/autoconf/jvm-features.m4
|
|
index 86dec71d0..6e81c84d9 100644
|
|
--- a/make/autoconf/jvm-features.m4
|
|
+++ b/make/autoconf/jvm-features.m4
|
|
@@ -44,7 +44,7 @@
|
|
m4_define(jvm_features_valid, m4_normalize( \
|
|
ifdef([custom_jvm_features_valid], custom_jvm_features_valid) \
|
|
\
|
|
- cds compiler1 compiler2 dtrace epsilongc g1gc graal jbooster jfr jni-check \
|
|
+ aot cds compiler1 compiler2 dtrace epsilongc g1gc graal jbooster jfr jni-check \
|
|
jvmci jvmti link-time-opt management minimal nmt opt-size parallelgc \
|
|
serialgc services shenandoahgc static-build vm-structs zero zgc \
|
|
))
|
|
@@ -55,6 +55,7 @@ m4_define(jvm_features_deprecated, m4_normalize(
|
|
))
|
|
|
|
# Feature descriptions
|
|
+m4_define(jvm_feature_desc_aot, [enable ahead of time compilation (AOT)])
|
|
m4_define(jvm_feature_desc_cds, [enable class data sharing (CDS)])
|
|
m4_define(jvm_feature_desc_compiler1, [enable hotspot compiler C1])
|
|
m4_define(jvm_feature_desc_compiler2, [enable hotspot compiler C2])
|
|
@@ -94,6 +95,7 @@ AC_DEFUN_ONCE([JVM_FEATURES_PARSE_OPTIONS],
|
|
|
|
# For historical reasons, some jvm features have their own, shorter names.
|
|
# Keep those as aliases for the --enable-jvm-feature-* style arguments.
|
|
+ UTIL_ALIASED_ARG_ENABLE(aot, --enable-jvm-feature-aot)
|
|
UTIL_ALIASED_ARG_ENABLE(cds, --enable-jvm-feature-cds)
|
|
UTIL_ALIASED_ARG_ENABLE(dtrace, --enable-jvm-feature-dtrace)
|
|
|
|
@@ -145,9 +147,9 @@ AC_DEFUN_ONCE([JVM_FEATURES_PARSE_OPTIONS],
|
|
|
|
if test "x$FEATURE_SHELL" = xyes; then
|
|
JVM_FEATURES_ENABLED="$JVM_FEATURES_ENABLED FEATURE"
|
|
- # Attach graal feature
|
|
+ # Attach aot and graal feature
|
|
if test FEATURE = jbooster; then
|
|
- JVM_FEATURES_ENABLED="$JVM_FEATURES_ENABLED graal"
|
|
+ JVM_FEATURES_ENABLED="$JVM_FEATURES_ENABLED aot graal"
|
|
fi
|
|
elif test "x$FEATURE_SHELL" = xno; then
|
|
JVM_FEATURES_DISABLED="$JVM_FEATURES_DISABLED FEATURE"
|
|
@@ -232,6 +234,34 @@ AC_DEFUN([JVM_FEATURES_CHECK_AVAILABILITY],
|
|
fi
|
|
])
|
|
|
|
+###############################################################################
|
|
+# Check if the feature 'aot' is available on this platform.
|
|
+#
|
|
+AC_DEFUN_ONCE([JVM_FEATURES_CHECK_AOT],
|
|
+[
|
|
+ JVM_FEATURES_CHECK_AVAILABILITY(aot, [
|
|
+ AC_MSG_CHECKING([if platform is supported by AOT])
|
|
+ # AOT is only available where JVMCI is available since it requires JVMCI.
|
|
+ if test "x$OPENJDK_TARGET_CPU" = "xx86_64"; then
|
|
+ AC_MSG_RESULT([yes])
|
|
+ elif test "x$OPENJDK_TARGET_OS-$OPENJDK_TARGET_CPU" = "xlinux-aarch64"; then
|
|
+ AC_MSG_RESULT([yes])
|
|
+ else
|
|
+ AC_MSG_RESULT([no, $OPENJDK_TARGET_OS-$OPENJDK_TARGET_CPU])
|
|
+ AVAILABLE=false
|
|
+ fi
|
|
+
|
|
+ AC_MSG_CHECKING([if AOT source code is present])
|
|
+ if test -e "${TOPDIR}/src/jdk.internal.vm.compiler" && \
|
|
+ test -e "${TOPDIR}/src/jdk.aot"; then
|
|
+ AC_MSG_RESULT([yes])
|
|
+ else
|
|
+ AC_MSG_RESULT([no, missing src/jdk.internal.vm.compiler or src/jdk.aot])
|
|
+ AVAILABLE=false
|
|
+ fi
|
|
+ ])
|
|
+])
|
|
+
|
|
###############################################################################
|
|
# Check if the feature 'cds' is available on this platform.
|
|
#
|
|
@@ -444,6 +474,7 @@ AC_DEFUN_ONCE([JVM_FEATURES_PREPARE_PLATFORM],
|
|
# The checks below should add unavailable features to
|
|
# JVM_FEATURES_PLATFORM_UNAVAILABLE.
|
|
|
|
+ JVM_FEATURES_CHECK_AOT
|
|
JVM_FEATURES_CHECK_CDS
|
|
JVM_FEATURES_CHECK_DTRACE
|
|
JVM_FEATURES_CHECK_GRAAL
|
|
@@ -480,7 +511,7 @@ AC_DEFUN([JVM_FEATURES_PREPARE_VARIANT],
|
|
elif test "x$variant" = "xcore"; then
|
|
JVM_FEATURES_VARIANT_UNAVAILABLE="cds jbooster minimal zero"
|
|
elif test "x$variant" = "xzero"; then
|
|
- JVM_FEATURES_VARIANT_UNAVAILABLE="cds compiler1 compiler2 \
|
|
+ JVM_FEATURES_VARIANT_UNAVAILABLE="aot cds compiler1 compiler2 \
|
|
graal jbooster jvmci minimal zgc"
|
|
else
|
|
JVM_FEATURES_VARIANT_UNAVAILABLE="minimal zero"
|
|
@@ -488,9 +519,9 @@ AC_DEFUN([JVM_FEATURES_PREPARE_VARIANT],
|
|
|
|
# Check which features should be off by default for this JVM variant.
|
|
if test "x$variant" = "xclient"; then
|
|
- JVM_FEATURES_VARIANT_FILTER="compiler2 graal jbooster jvmci link-time-opt opt-size"
|
|
+ JVM_FEATURES_VARIANT_FILTER="aot compiler2 graal jbooster jvmci link-time-opt opt-size"
|
|
elif test "x$variant" = "xminimal"; then
|
|
- JVM_FEATURES_VARIANT_FILTER="cds compiler2 dtrace epsilongc g1gc graal jbooster \
|
|
+ JVM_FEATURES_VARIANT_FILTER="aot cds compiler2 dtrace epsilongc g1gc graal jbooster \
|
|
jfr jni-check jvmci jvmti management nmt parallelgc services \
|
|
shenandoahgc vm-structs zgc"
|
|
if test "x$OPENJDK_TARGET_CPU" = xarm ; then
|
|
@@ -501,12 +532,12 @@ AC_DEFUN([JVM_FEATURES_PREPARE_VARIANT],
|
|
link-time-opt"
|
|
fi
|
|
elif test "x$variant" = "xcore"; then
|
|
- JVM_FEATURES_VARIANT_FILTER="compiler1 compiler2 graal jbooster jvmci \
|
|
+ JVM_FEATURES_VARIANT_FILTER="aot compiler1 compiler2 graal jbooster jvmci \
|
|
link-time-opt opt-size"
|
|
elif test "x$variant" = "xzero"; then
|
|
- JVM_FEATURES_VARIANT_FILTER="graal jbooster jfr link-time-opt opt-size"
|
|
+ JVM_FEATURES_VARIANT_FILTER="aot graal jbooster jfr link-time-opt opt-size"
|
|
else
|
|
- JVM_FEATURES_VARIANT_FILTER="graal jbooster link-time-opt opt-size"
|
|
+ JVM_FEATURES_VARIANT_FILTER="aot graal jbooster link-time-opt opt-size"
|
|
fi
|
|
])
|
|
|
|
@@ -578,14 +609,18 @@ AC_DEFUN([JVM_FEATURES_VERIFY],
|
|
variant=$1
|
|
|
|
# Verify that dependencies are met for inter-feature relations.
|
|
+ if JVM_FEATURES_IS_ACTIVE(aot) && ! JVM_FEATURES_IS_ACTIVE(graal); then
|
|
+ AC_MSG_ERROR([Specified JVM feature 'aot' requires feature 'graal' for variant '$variant'])
|
|
+ fi
|
|
+
|
|
if JVM_FEATURES_IS_ACTIVE(graal) && ! JVM_FEATURES_IS_ACTIVE(jvmci); then
|
|
AC_MSG_ERROR([Specified JVM feature 'graal' requires feature 'jvmci' for variant '$variant'])
|
|
fi
|
|
|
|
# FIX ME: Fill up the dependencies with aot module
|
|
if JVM_FEATURES_IS_ACTIVE(jbooster) && ! (JVM_FEATURES_IS_ACTIVE(cds) && \
|
|
- JVM_FEATURES_IS_ACTIVE(graal)); then
|
|
- AC_MSG_ERROR([Specified JVM feature 'jbooster' requires feature 'cds' and 'graal' for variant '$variant'])
|
|
+ JVM_FEATURES_IS_ACTIVE(graal) && JVM_FEATURES_IS_ACTIVE(aot)); then
|
|
+ AC_MSG_ERROR([Specified JVM feature 'jbooster' requires feature 'cds', 'aot' and 'graal' for variant '$variant'])
|
|
fi
|
|
|
|
if JVM_FEATURES_IS_ACTIVE(jvmci) && ! (JVM_FEATURES_IS_ACTIVE(compiler1) || \
|
|
@@ -603,6 +638,9 @@ AC_DEFUN([JVM_FEATURES_VERIFY],
|
|
|
|
# For backwards compatibility, disable a feature "globally" if one variant
|
|
# is missing the feature.
|
|
+ if JVM_FEATURES_IS_ACTIVE(aot); then
|
|
+ ENABLE_AOT="true"
|
|
+ fi
|
|
if ! JVM_FEATURES_IS_ACTIVE(cds); then
|
|
ENABLE_CDS="false"
|
|
fi
|
|
@@ -639,6 +677,7 @@ AC_DEFUN_ONCE([JVM_FEATURES_SETUP],
|
|
# For backwards compatibility, tentatively enable these features "globally",
|
|
# and disable them in JVM_FEATURES_VERIFY if a variant is found that are
|
|
# missing any of them.
|
|
+ ENABLE_AOT="false"
|
|
ENABLE_CDS="true"
|
|
INCLUDE_GRAAL="false"
|
|
INCLUDE_JVMCI="true"
|
|
@@ -679,6 +718,7 @@ AC_DEFUN_ONCE([JVM_FEATURES_SETUP],
|
|
AC_SUBST(JVM_FEATURES_zero)
|
|
AC_SUBST(JVM_FEATURES_custom)
|
|
|
|
+ AC_SUBST(ENABLE_AOT)
|
|
AC_SUBST(INCLUDE_GRAAL)
|
|
AC_SUBST(INCLUDE_JVMCI)
|
|
AC_SUBST(INCLUDE_COMPILER2)
|
|
diff --git a/make/autoconf/spec.gmk.in b/make/autoconf/spec.gmk.in
|
|
index 0842774cf..e3f43ebf0 100644
|
|
--- a/make/autoconf/spec.gmk.in
|
|
+++ b/make/autoconf/spec.gmk.in
|
|
@@ -1,5 +1,5 @@
|
|
#
|
|
-# Copyright (c) 2011, 2021, 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
|
|
@@ -533,6 +533,9 @@ CPP := @CPP@
|
|
# The linker can be gcc or ld on unix systems, or link.exe on windows systems.
|
|
LD := @LD@
|
|
|
|
+# Linker used by the jaotc tool for AOT compilation.
|
|
+LD_JAOTC:=@LD_JAOTC@
|
|
+
|
|
# Xcode SDK path
|
|
SDKROOT:=@SDKROOT@
|
|
|
|
@@ -777,6 +780,7 @@ TAR_SUPPORTS_TRANSFORM:=@TAR_SUPPORTS_TRANSFORM@
|
|
|
|
# Build setup
|
|
ENABLE_KAE:=@ENABLE_KAE@
|
|
+ENABLE_AOT:=@ENABLE_AOT@
|
|
USE_EXTERNAL_LIBJPEG:=@USE_EXTERNAL_LIBJPEG@
|
|
USE_EXTERNAL_LIBGIF:=@USE_EXTERNAL_LIBGIF@
|
|
USE_EXTERNAL_LIBZ:=@USE_EXTERNAL_LIBZ@
|
|
diff --git a/make/autoconf/toolchain.m4 b/make/autoconf/toolchain.m4
|
|
index 8105ce9e8..3a83873b9 100644
|
|
--- a/make/autoconf/toolchain.m4
|
|
+++ b/make/autoconf/toolchain.m4
|
|
@@ -674,12 +674,18 @@ AC_DEFUN_ONCE([TOOLCHAIN_DETECT_TOOLCHAIN_CORE],
|
|
UTIL_LOOKUP_TOOLCHAIN_PROGS(LD, link)
|
|
TOOLCHAIN_VERIFY_LINK_BINARY(LD)
|
|
LDCXX="$LD"
|
|
+ # jaotc being a windows program expects the linker to be supplied with exe suffix.but without
|
|
+ # fixpath
|
|
+ LD_JAOTC="${LD##$FIXPATH }"
|
|
else
|
|
# All other toolchains use the compiler to link.
|
|
LD="$CC"
|
|
LDCXX="$CXX"
|
|
+ # jaotc expects 'ld' as the linker rather than the compiler.
|
|
+ UTIL_LOOKUP_TOOLCHAIN_PROGS(LD_JAOTC, ld)
|
|
fi
|
|
AC_SUBST(LD)
|
|
+ AC_SUBST(LD_JAOTC)
|
|
# FIXME: it should be CXXLD, according to standard (cf CXXCPP)
|
|
AC_SUBST(LDCXX)
|
|
|
|
diff --git a/make/common/Modules.gmk b/make/common/Modules.gmk
|
|
index 20d224d1e..ebb5756e3 100644
|
|
--- a/make/common/Modules.gmk
|
|
+++ b/make/common/Modules.gmk
|
|
@@ -1,5 +1,5 @@
|
|
#
|
|
-# Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
+# Copyright (c) 2014, 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
|
|
@@ -70,6 +70,11 @@ ifeq ($(INCLUDE_GRAAL), false)
|
|
MODULES_FILTER += jdk.internal.vm.compiler.management
|
|
endif
|
|
|
|
+# Filter out aot specific modules if aot is disabled
|
|
+ifeq ($(ENABLE_AOT), false)
|
|
+ MODULES_FILTER += jdk.aot
|
|
+endif
|
|
+
|
|
# Filter out jbooster specific modules if jbooster is disabled
|
|
ifeq ($(INCLUDE_JBOOSTER), false)
|
|
MODULES_FILTER += jdk.jbooster
|
|
diff --git a/make/conf/build-module-sets.conf b/make/conf/build-module-sets.conf
|
|
index d6f1c25cf..853a29012 100644
|
|
--- a/make/conf/build-module-sets.conf
|
|
+++ b/make/conf/build-module-sets.conf
|
|
@@ -1,5 +1,5 @@
|
|
#
|
|
-# Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
+# Copyright (c) 2014, 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
|
|
@@ -44,6 +44,7 @@ LANGTOOLS_MODULES= \
|
|
|
|
# These models require buildtools-hotspot to process for gensrc
|
|
HOTSPOT_MODULES= \
|
|
+ jdk.aot \
|
|
jdk.hotspot.agent \
|
|
jdk.internal.vm.ci \
|
|
jdk.internal.vm.compiler \
|
|
diff --git a/make/conf/jib-profiles.js b/make/conf/jib-profiles.js
|
|
index 17cf101db..92bcb1b72 100644
|
|
--- a/make/conf/jib-profiles.js
|
|
+++ b/make/conf/jib-profiles.js
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2015, 2021, 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
|
|
@@ -252,6 +252,7 @@ var getJibProfilesCommon = function (input, data) {
|
|
configure_args: concat("--enable-jtreg-failure-handler",
|
|
"--with-exclude-translations=es,fr,it,ko,pt_BR,sv,ca,tr,cs,sk,ja_JP_A,ja_JP_HA,ja_JP_HI,ja_JP_I,zh_TW,zh_HK",
|
|
"--disable-manpages",
|
|
+ "--disable-jvm-feature-aot",
|
|
"--disable-jvm-feature-graal",
|
|
"--disable-jvm-feature-shenandoahgc",
|
|
versionArgs(input, common))
|
|
diff --git a/make/conf/module-loader-map.conf b/make/conf/module-loader-map.conf
|
|
index 051ca4dc8..847e01ade 100644
|
|
--- a/make/conf/module-loader-map.conf
|
|
+++ b/make/conf/module-loader-map.conf
|
|
@@ -1,5 +1,5 @@
|
|
#
|
|
-# Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
+# Copyright (c) 2014, 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
|
|
@@ -61,6 +61,7 @@ BOOT_MODULES= \
|
|
# should carefully be considered if it should be upgradeable or not.
|
|
UPGRADEABLE_PLATFORM_MODULES= \
|
|
java.compiler \
|
|
+ jdk.aot \
|
|
jdk.internal.vm.compiler \
|
|
jdk.internal.vm.compiler.management \
|
|
#
|
|
diff --git a/make/hotspot/lib/JvmFeatures.gmk b/make/hotspot/lib/JvmFeatures.gmk
|
|
index 0c83ec254..ff5b243ae 100644
|
|
--- a/make/hotspot/lib/JvmFeatures.gmk
|
|
+++ b/make/hotspot/lib/JvmFeatures.gmk
|
|
@@ -1,5 +1,5 @@
|
|
#
|
|
-# Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
+# Copyright (c) 2013, 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
|
|
@@ -129,6 +129,14 @@ ifneq ($(call check-jvm-feature, nmt), true)
|
|
memTracker.cpp nmtDCmd.cpp mallocSiteTable.cpp threadStackTracker.cpp
|
|
endif
|
|
|
|
+ifneq ($(call check-jvm-feature, aot), true)
|
|
+ JVM_CFLAGS_FEATURES += -DINCLUDE_AOT=0
|
|
+ JVM_EXCLUDE_FILES += \
|
|
+ compiledIC_aot_x86_64.cpp compiledIC_aot_aarch64.cpp \
|
|
+ compilerRuntime.cpp aotCodeHeap.cpp aotCompiledMethod.cpp \
|
|
+ aotLoader.cpp compiledIC_aot.cpp
|
|
+endif
|
|
+
|
|
ifneq ($(call check-jvm-feature, g1gc), true)
|
|
JVM_CFLAGS_FEATURES += -DINCLUDE_G1GC=0
|
|
JVM_EXCLUDE_PATTERNS += gc/g1
|
|
diff --git a/make/ide/visualstudio/hotspot/CreateVSProject.gmk b/make/ide/visualstudio/hotspot/CreateVSProject.gmk
|
|
index e7a1dcc5b..2e2b95d2f 100644
|
|
--- a/make/ide/visualstudio/hotspot/CreateVSProject.gmk
|
|
+++ b/make/ide/visualstudio/hotspot/CreateVSProject.gmk
|
|
@@ -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
|
|
@@ -111,6 +111,7 @@ ifeq ($(call isTargetOs, windows), true)
|
|
-relativeSrcInclude hotspot \
|
|
-hidePath .hg \
|
|
-hidePath .jcheck \
|
|
+ -hidePath jdk.aot \
|
|
-hidePath jdk.hotspot.agent \
|
|
-hidePath jdk.internal.vm.ci \
|
|
-hidePath jdk.internal.vm.compiler \
|
|
diff --git a/make/modules/jdk.aot/Java.gmk b/make/modules/jdk.aot/Java.gmk
|
|
new file mode 100644
|
|
index 000000000..9fcbaed43
|
|
--- /dev/null
|
|
+++ b/make/modules/jdk.aot/Java.gmk
|
|
@@ -0,0 +1,54 @@
|
|
+#
|
|
+# Copyright (c) 2020, 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
|
|
+# under the terms of the GNU General Public License version 2 only, as
|
|
+# published by the Free Software Foundation. Oracle designates this
|
|
+# particular file as subject to the "Classpath" exception as provided
|
|
+# by Oracle in the LICENSE file that accompanied this code.
|
|
+#
|
|
+# 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.
|
|
+#
|
|
+
|
|
+# -parameters provides method's parameters information in class file,
|
|
+# JVMCI compilers make use of that information for various sanity checks.
|
|
+# Don't use Indy strings concatenation to have good JAOTC startup performance.
|
|
+# The exports are needed since JVMCI is dynamically exported (see
|
|
+# jdk.vm.ci.services.internal.ReflectionAccessJDK::openJVMCITo).
|
|
+
|
|
+JAVAC_FLAGS += -parameters -XDstringConcat=inline \
|
|
+ --add-exports jdk.internal.vm.ci/jdk.vm.ci.aarch64=jdk.internal.vm.compiler,jdk.aot \
|
|
+ --add-exports jdk.internal.vm.ci/jdk.vm.ci.amd64=jdk.internal.vm.compiler,jdk.aot \
|
|
+ --add-exports jdk.internal.vm.ci/jdk.vm.ci.code=jdk.internal.vm.compiler,jdk.aot \
|
|
+ --add-exports jdk.internal.vm.ci/jdk.vm.ci.code.site=jdk.internal.vm.compiler,jdk.aot \
|
|
+ --add-exports jdk.internal.vm.ci/jdk.vm.ci.code.stack=jdk.internal.vm.compiler,jdk.aot \
|
|
+ --add-exports jdk.internal.vm.ci/jdk.vm.ci.common=jdk.internal.vm.compiler,jdk.aot \
|
|
+ --add-exports jdk.internal.vm.ci/jdk.vm.ci.hotspot=jdk.internal.vm.compiler,jdk.aot \
|
|
+ --add-exports jdk.internal.vm.ci/jdk.vm.ci.hotspot.aarch64=jdk.internal.vm.compiler,jdk.aot \
|
|
+ --add-exports jdk.internal.vm.ci/jdk.vm.ci.hotspot.amd64=jdk.internal.vm.compiler,jdk.aot \
|
|
+ --add-exports jdk.internal.vm.ci/jdk.vm.ci.meta=jdk.internal.vm.compiler,jdk.aot \
|
|
+ --add-exports jdk.internal.vm.ci/jdk.vm.ci.runtime=jdk.internal.vm.compiler,jdk.aot \
|
|
+ #
|
|
+
|
|
+EXCLUDES += \
|
|
+ jdk.tools.jaotc.test
|
|
+ #
|
|
+
|
|
+## WORKAROUND jdk.aot source structure issue
|
|
+AOT_MODULESOURCEPATH := $(MODULESOURCEPATH) \
|
|
+ $(subst /$(MODULE)/,/*/, $(filter-out %processor/src, \
|
|
+ $(wildcard $(TOPDIR)/src/$(MODULE)/share/classes/*/src)))
|
|
+MODULESOURCEPATH := $(call PathList, $(AOT_MODULESOURCEPATH))
|
|
diff --git a/make/modules/jdk.aot/Launcher.gmk b/make/modules/jdk.aot/Launcher.gmk
|
|
new file mode 100644
|
|
index 000000000..4b7e843b1
|
|
--- /dev/null
|
|
+++ b/make/modules/jdk.aot/Launcher.gmk
|
|
@@ -0,0 +1,54 @@
|
|
+#
|
|
+# 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
|
|
+# under the terms of the GNU General Public License version 2 only, as
|
|
+# published by the Free Software Foundation. Oracle designates this
|
|
+# particular file as subject to the "Classpath" exception as provided
|
|
+# by Oracle in the LICENSE file that accompanied this code.
|
|
+#
|
|
+# 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.
|
|
+#
|
|
+
|
|
+include LauncherCommon.gmk
|
|
+
|
|
+# The JVMCI exports are needed since JVMCI is normally dynamically exported
|
|
+# (see jdk.vm.ci.services.internal.ReflectionAccessJDK::openJVMCITo).
|
|
+
|
|
+$(eval $(call SetupBuildLauncher, jaotc, \
|
|
+ MAIN_CLASS := jdk.tools.jaotc.Main, \
|
|
+ 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 := --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:+UnlockExperimentalVMOptions -XX:+UseAOT \
|
|
+ -XX:+CalculateClassFingerprint \
|
|
+ -Djvmci.UseProfilingInformation=false \
|
|
+ -Dgraal.UseExceptionProbability=false \
|
|
+ -Djvmci.Compiler=graal \
|
|
+ --add-modules ALL-DEFAULT \
|
|
+ , \
|
|
+))
|
|
diff --git a/make/modules/jdk.internal.vm.compiler/Java.gmk b/make/modules/jdk.internal.vm.compiler/Java.gmk
|
|
index c2b92597a..3b4672956 100644
|
|
--- a/make/modules/jdk.internal.vm.compiler/Java.gmk
|
|
+++ b/make/modules/jdk.internal.vm.compiler/Java.gmk
|
|
@@ -1,5 +1,5 @@
|
|
#
|
|
-# Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
+# Copyright (c) 2020, 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
|
|
@@ -39,6 +39,7 @@ JAVAC_FLAGS += -parameters -XDstringConcat=inline \
|
|
|
|
EXCLUDES += \
|
|
jdk.internal.vm.compiler.collections.test \
|
|
+ jdk.tools.jaotc.test \
|
|
org.graalvm.compiler.api.directives.test \
|
|
org.graalvm.compiler.api.test \
|
|
org.graalvm.compiler.asm.aarch64.test \
|
|
diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad
|
|
index f28cc9cd6..350e4cad0 100644
|
|
--- a/src/hotspot/cpu/aarch64/aarch64.ad
|
|
+++ b/src/hotspot/cpu/aarch64/aarch64.ad
|
|
@@ -1,6 +1,6 @@
|
|
//
|
|
-// Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
-// Copyright (c) 2014, 2021, Red Hat, Inc. All rights reserved.
|
|
+// Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
|
|
+// Copyright (c) 2014, 2023, Red Hat, Inc. 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
|
|
@@ -1360,7 +1360,7 @@ source %{
|
|
|
|
// r27 is not allocatable when compressed oops is on and heapbase is not
|
|
// zero, compressed klass pointers doesn't use r27 after JDK-8234794
|
|
- if (UseCompressedOops && (CompressedOops::ptrs_base() != NULL)) {
|
|
+ if (UseCompressedOops && (CompressedOops::ptrs_base() != NULL || UseAOT)) {
|
|
_NO_SPECIAL_REG32_mask.Remove(OptoReg::as_OptoReg(r27->as_VMReg()));
|
|
_NO_SPECIAL_REG_mask.SUBTRACT(_HEAPBASE_REG_mask);
|
|
_NO_SPECIAL_PTR_REG_mask.SUBTRACT(_HEAPBASE_REG_mask);
|
|
diff --git a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.hpp
|
|
index d39f57087..2bbfe91ee 100644
|
|
--- a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.hpp
|
|
+++ b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.hpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved.
|
|
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
@@ -75,6 +75,7 @@ friend class ArrayCopyStub;
|
|
static int _call_stub_size;
|
|
|
|
enum {
|
|
+ _call_aot_stub_size = 0,
|
|
_exception_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(175),
|
|
_deopt_handler_size = 7 * NativeInstruction::instruction_size
|
|
};
|
|
diff --git a/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp
|
|
index 209f50efe..5dbb59a1c 100644
|
|
--- a/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp
|
|
+++ b/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp
|
|
@@ -1384,7 +1384,7 @@ void LIRGenerator::volatile_field_load(LIR_Address* address, LIR_Opr result,
|
|
// membar it's possible for a simple Dekker test to fail if loads
|
|
// use LD;DMB but stores use STLR. This can happen if C2 compiles
|
|
// the stores in one method and C1 compiles the loads in another.
|
|
- if (!CompilerConfig::is_c1_only_no_jvmci()) {
|
|
+ if (!CompilerConfig::is_c1_only_no_aot_or_jvmci()) {
|
|
__ membar();
|
|
}
|
|
__ volatile_load_mem_reg(address, result, info);
|
|
diff --git a/src/hotspot/cpu/aarch64/compiledIC_aarch64.cpp b/src/hotspot/cpu/aarch64/compiledIC_aarch64.cpp
|
|
index c6a9d8387..dd8cf4981 100644
|
|
--- a/src/hotspot/cpu/aarch64/compiledIC_aarch64.cpp
|
|
+++ b/src/hotspot/cpu/aarch64/compiledIC_aarch64.cpp
|
|
@@ -1,6 +1,6 @@
|
|
/*
|
|
- * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
- * Copyright (c) 2014, 2018, Red Hat Inc. All rights reserved.
|
|
+ * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2014, 2023, Red Hat Inc. 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
|
|
@@ -60,6 +60,15 @@ address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark)
|
|
// static stub relocation stores the instruction address of the call
|
|
__ relocate(static_stub_Relocation::spec(mark));
|
|
|
|
+#if INCLUDE_AOT
|
|
+ // Don't create a Metadata reloc if we're generating immutable PIC.
|
|
+ if (cbuf.immutable_PIC()) {
|
|
+ __ movptr(rmethod, 0);
|
|
+ __ movptr(rscratch1, 0);
|
|
+ __ br(rscratch1);
|
|
+
|
|
+ } else
|
|
+#endif
|
|
{
|
|
__ emit_static_call_stub();
|
|
}
|
|
@@ -92,8 +101,63 @@ int CompiledStaticCall::reloc_to_interp_stub() {
|
|
return 4; // 3 in emit_to_interp_stub + 1 in emit_call
|
|
}
|
|
|
|
+#if INCLUDE_AOT
|
|
+#define __ _masm.
|
|
+void CompiledStaticCall::emit_to_aot_stub(CodeBuffer &cbuf, address mark) {
|
|
+ if (!UseAOT) {
|
|
+ return;
|
|
+ }
|
|
+ // Stub is fixed up when the corresponding call is converted from
|
|
+ // calling compiled code to calling aot code.
|
|
+ // mov r, imm64_aot_code_address
|
|
+ // jmp r
|
|
+
|
|
+ if (mark == NULL) {
|
|
+ mark = cbuf.insts_mark(); // Get mark within main instrs section.
|
|
+ }
|
|
+
|
|
+ // Note that the code buffer's insts_mark is always relative to insts.
|
|
+ // That's why we must use the macroassembler to generate a stub.
|
|
+ MacroAssembler _masm(&cbuf);
|
|
+
|
|
+ address base =
|
|
+ __ start_a_stub(to_aot_stub_size());
|
|
+ guarantee(base != NULL, "out of space");
|
|
+
|
|
+ // Static stub relocation stores the instruction address of the call.
|
|
+ __ relocate(static_stub_Relocation::spec(mark, true /* is_aot */));
|
|
+ // Load destination AOT code address.
|
|
+ __ movptr(rscratch1, 0); // address is zapped till fixup time.
|
|
+ // This is recognized as unresolved by relocs/nativeinst/ic code.
|
|
+ __ br(rscratch1);
|
|
+
|
|
+ assert(__ pc() - base <= to_aot_stub_size(), "wrong stub size");
|
|
+
|
|
+ // Update current stubs pointer and restore insts_end.
|
|
+ __ end_a_stub();
|
|
+}
|
|
+#undef __
|
|
+
|
|
+int CompiledStaticCall::to_aot_stub_size() {
|
|
+ if (UseAOT) {
|
|
+ return 5 * 4; // movz; movk; movk; movk; br
|
|
+ } else {
|
|
+ return 0;
|
|
+ }
|
|
+}
|
|
+
|
|
+// Relocation entries for call stub, compiled java to aot.
|
|
+int CompiledStaticCall::reloc_to_aot_stub() {
|
|
+ if (UseAOT) {
|
|
+ return 5 * 4; // movz; movk; movk; movk; br
|
|
+ } else {
|
|
+ return 0;
|
|
+ }
|
|
+}
|
|
+#endif // INCLUDE_AOT
|
|
+
|
|
void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, address entry) {
|
|
- address stub = find_stub();
|
|
+ address stub = find_stub(false /* is_aot */);
|
|
guarantee(stub != NULL, "stub not found");
|
|
|
|
if (TraceICs) {
|
|
@@ -129,8 +193,10 @@ void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_
|
|
NativeMovConstReg* method_holder
|
|
= nativeMovConstReg_at(stub + NativeInstruction::instruction_size);
|
|
method_holder->set_data(0);
|
|
- NativeJump* jump = nativeJump_at(method_holder->next_instruction_address());
|
|
- jump->set_jump_destination((address)-1);
|
|
+ if (!static_stub->is_aot()) {
|
|
+ NativeJump* jump = nativeJump_at(method_holder->next_instruction_address());
|
|
+ jump->set_jump_destination((address)-1);
|
|
+ }
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
@@ -143,7 +209,7 @@ void CompiledDirectStaticCall::verify() {
|
|
_call->verify_alignment();
|
|
|
|
// Verify stub.
|
|
- address stub = find_stub();
|
|
+ address stub = find_stub(false /* is_aot */);
|
|
assert(stub != NULL, "no stub found for static call");
|
|
// Creation also verifies the object.
|
|
NativeMovConstReg* method_holder
|
|
diff --git a/src/hotspot/cpu/aarch64/compiledIC_aot_aarch64.cpp b/src/hotspot/cpu/aarch64/compiledIC_aot_aarch64.cpp
|
|
new file mode 100644
|
|
index 000000000..bfd81cc96
|
|
--- /dev/null
|
|
+++ b/src/hotspot/cpu/aarch64/compiledIC_aot_aarch64.cpp
|
|
@@ -0,0 +1,104 @@
|
|
+/*
|
|
+ * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2018, 2023, Red Hat Inc. 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.
|
|
+ */
|
|
+
|
|
+#include "aot/compiledIC_aot.hpp"
|
|
+#include "code/codeCache.hpp"
|
|
+#include "memory/resourceArea.hpp"
|
|
+#include "memory/universe.hpp"
|
|
+
|
|
+void CompiledDirectStaticCall::set_to_far(const methodHandle& callee, address entry) {
|
|
+ if (TraceICs) {
|
|
+ ResourceMark rm;
|
|
+ tty->print_cr("CompiledDirectStaticCall@" INTPTR_FORMAT ": set_to_far %s",
|
|
+ p2i(instruction_address()),
|
|
+ callee->name_and_sig_as_C_string());
|
|
+ }
|
|
+
|
|
+ set_destination_mt_safe(entry);
|
|
+}
|
|
+
|
|
+void CompiledPltStaticCall::set_to_interpreted(const methodHandle& callee, address entry) {
|
|
+ address stub = find_stub();
|
|
+ guarantee(stub != NULL, "stub not found");
|
|
+ if (TraceICs) {
|
|
+ ResourceMark rm;
|
|
+ tty->print_cr("CompiledPltStaticCall@" INTPTR_FORMAT ": set_to_interpreted %s",
|
|
+ p2i(instruction_address()),
|
|
+ callee->name_and_sig_as_C_string());
|
|
+ }
|
|
+
|
|
+ // Creation also verifies the object.
|
|
+ NativeLoadGot* method_loader = nativeLoadGot_at(stub);
|
|
+ NativeGotJump* jump = nativeGotJump_at(method_loader->next_instruction_address());
|
|
+
|
|
+ intptr_t data = method_loader->data();
|
|
+ address destination = jump->destination();
|
|
+ assert(data == 0 || data == (intptr_t)callee(),
|
|
+ "a) MT-unsafe modification of inline cache");
|
|
+ assert(destination == (address)Universe::non_oop_word()
|
|
+ || destination == entry,
|
|
+ "b) MT-unsafe modification of inline cache");
|
|
+
|
|
+ // Update stub.
|
|
+ method_loader->set_data((intptr_t)callee());
|
|
+ jump->set_jump_destination(entry);
|
|
+
|
|
+ // Update jump to call.
|
|
+ set_destination_mt_safe(stub);
|
|
+}
|
|
+
|
|
+#ifdef NEVER_CALLED
|
|
+void CompiledPltStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
|
|
+ // Reset stub.
|
|
+ address stub = static_stub->addr();
|
|
+ assert(stub != NULL, "stub not found");
|
|
+ assert(CompiledICLocker::is_safe(stub), "mt unsafe call");
|
|
+ // Creation also verifies the object.
|
|
+ NativeLoadGot* method_loader = nativeLoadGot_at(stub);
|
|
+ NativeGotJump* jump = nativeGotJump_at(method_loader->next_instruction_address());
|
|
+ method_loader->set_data(0);
|
|
+ jump->set_jump_destination((address)-1);
|
|
+}
|
|
+#endif
|
|
+
|
|
+#ifndef PRODUCT
|
|
+void CompiledPltStaticCall::verify() {
|
|
+ // Verify call.
|
|
+ _call->verify();
|
|
+
|
|
+#ifdef ASSERT
|
|
+ CodeBlob *cb = CodeCache::find_blob_unsafe((address) _call);
|
|
+ assert(cb && cb->is_aot(), "CompiledPltStaticCall can only be used on AOTCompiledMethod");
|
|
+#endif
|
|
+
|
|
+ // Verify stub.
|
|
+ address stub = find_stub();
|
|
+ assert(stub != NULL, "no stub found for static call");
|
|
+ // Creation also verifies the object.
|
|
+ NativeLoadGot* method_loader = nativeLoadGot_at(stub);
|
|
+ NativeGotJump* jump = nativeGotJump_at(method_loader->next_instruction_address());
|
|
+ // Verify state.
|
|
+ assert(is_clean() || is_call_to_compiled() || is_call_to_interpreted(), "sanity check");
|
|
+}
|
|
+#endif // !PRODUCT
|
|
diff --git a/src/hotspot/cpu/aarch64/gc/shenandoah/c1/shenandoahBarrierSetC1_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/shenandoah/c1/shenandoahBarrierSetC1_aarch64.cpp
|
|
index a56b13264..3c01c29e0 100644
|
|
--- a/src/hotspot/cpu/aarch64/gc/shenandoah/c1/shenandoahBarrierSetC1_aarch64.cpp
|
|
+++ b/src/hotspot/cpu/aarch64/gc/shenandoah/c1/shenandoahBarrierSetC1_aarch64.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2018, 2021, Red Hat, Inc. All rights reserved.
|
|
+ * Copyright (c) 2018, 2023, Red Hat, Inc. 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
|
|
@@ -51,7 +51,7 @@ void LIR_OpShenandoahCompareAndSwap::emit_code(LIR_Assembler* masm) {
|
|
|
|
ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm->masm(), addr, cmpval, newval, /*acquire*/ true, /*release*/ true, /*is_cae*/ false, result);
|
|
|
|
- if (CompilerConfig::is_c1_only_no_jvmci()) {
|
|
+ if (CompilerConfig::is_c1_only_no_aot_or_jvmci()) {
|
|
// The membar here is necessary to prevent reordering between the
|
|
// release store in the CAS above and a subsequent volatile load.
|
|
// However for tiered compilation C1 inserts a full barrier before
|
|
diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp
|
|
index 5e8cd1b37..9eb05d8c3 100644
|
|
--- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp
|
|
+++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp
|
|
@@ -1,6 +1,6 @@
|
|
/*
|
|
- * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
- * Copyright (c) 2014, 2021, Red Hat Inc. All rights reserved.
|
|
+ * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2014, 2023, Red Hat Inc. 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
|
|
@@ -1083,7 +1083,7 @@ public:
|
|
address trampoline_call(Address entry, CodeBuffer* cbuf = NULL);
|
|
|
|
static bool far_branches() {
|
|
- return ReservedCodeCacheSize > branch_range;
|
|
+ return ReservedCodeCacheSize > branch_range || UseAOT;
|
|
}
|
|
|
|
// Jumps that can reach anywhere in the code cache.
|
|
diff --git a/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp b/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp
|
|
index c75c65f66..90c36a115 100644
|
|
--- a/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp
|
|
+++ b/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp
|
|
@@ -1,6 +1,6 @@
|
|
/*
|
|
- * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
- * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved.
|
|
+ * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2014, 2023, Red Hat Inc. 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
|
|
@@ -496,9 +496,16 @@ bool NativeInstruction::is_stop() {
|
|
void NativeJump::patch_verified_entry(address entry, address verified_entry, address dest) {
|
|
|
|
assert(dest == SharedRuntime::get_handle_wrong_method_stub(), "expected fixed destination of patch");
|
|
- assert(nativeInstruction_at(verified_entry)->is_jump_or_nop()
|
|
- || nativeInstruction_at(verified_entry)->is_sigill_zombie_not_entrant(),
|
|
- "Aarch64 cannot replace non-jump with jump");
|
|
+
|
|
+#ifdef ASSERT
|
|
+ // This may be the temporary nmethod generated while we're AOT
|
|
+ // compiling. Such an nmethod doesn't begin with a NOP but with an ADRP.
|
|
+ if (! (CalculateClassFingerprint && UseAOT && is_adrp_at(verified_entry))) {
|
|
+ assert(nativeInstruction_at(verified_entry)->is_jump_or_nop()
|
|
+ || nativeInstruction_at(verified_entry)->is_sigill_zombie_not_entrant(),
|
|
+ "Aarch64 cannot replace non-jump with jump");
|
|
+ }
|
|
+#endif
|
|
|
|
// Patch this nmethod atomically.
|
|
if (Assembler::reachable_from_branch_at(verified_entry, dest)) {
|
|
diff --git a/src/hotspot/cpu/aarch64/nativeInst_aarch64.hpp b/src/hotspot/cpu/aarch64/nativeInst_aarch64.hpp
|
|
index 243bf6c68..60dc3be3a 100644
|
|
--- a/src/hotspot/cpu/aarch64/nativeInst_aarch64.hpp
|
|
+++ b/src/hotspot/cpu/aarch64/nativeInst_aarch64.hpp
|
|
@@ -1,6 +1,6 @@
|
|
/*
|
|
- * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
- * Copyright (c) 2014, 2108, Red Hat Inc. All rights reserved.
|
|
+ * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2014, 2023, Red Hat Inc. 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
|
|
@@ -235,6 +235,16 @@ public:
|
|
return is_call_at(return_address - NativeCall::return_address_offset);
|
|
}
|
|
|
|
+#if INCLUDE_AOT
|
|
+ // Return true iff a call from instr to target is out of range.
|
|
+ // Used for calls from JIT- to AOT-compiled code.
|
|
+ static bool is_far_call(address instr, address target) {
|
|
+ // On AArch64 we use trampolines which can reach anywhere in the
|
|
+ // address space, so calls are never out of range.
|
|
+ return false;
|
|
+ }
|
|
+#endif
|
|
+
|
|
// MT-safe patching of a call instruction.
|
|
static void insert(address code_pos, address entry);
|
|
|
|
diff --git a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp
|
|
index 83e9be0b0..7ea60b273 100644
|
|
--- a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp
|
|
+++ b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp
|
|
@@ -1,7 +1,7 @@
|
|
/*
|
|
- * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
- * Copyright (c) 2014, 2021, Red Hat Inc. All rights reserved.
|
|
- * Copyright (c) 2021, Azul Systems, Inc. All rights reserved.
|
|
+ * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2014, 2023, Red Hat Inc. All rights reserved.
|
|
+ * Copyright (c) 2021, 2023, Azul Systems, Inc. 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
|
|
@@ -594,7 +594,7 @@ void SharedRuntime::gen_i2c_adapter(MacroAssembler *masm,
|
|
__ ldr(rscratch1, Address(rmethod, in_bytes(Method::from_compiled_offset())));
|
|
|
|
#if INCLUDE_JVMCI
|
|
- if (EnableJVMCI) {
|
|
+ if (EnableJVMCI || UseAOT) {
|
|
// check if this call should be routed towards a specific entry point
|
|
__ ldr(rscratch2, Address(rthread, in_bytes(JavaThread::jvmci_alternate_call_target_offset())));
|
|
Label no_alternative_target;
|
|
@@ -2179,7 +2179,7 @@ void SharedRuntime::generate_deopt_blob() {
|
|
// Setup code generation tools
|
|
int pad = 0;
|
|
#if INCLUDE_JVMCI
|
|
- if (EnableJVMCI) {
|
|
+ if (EnableJVMCI || UseAOT) {
|
|
pad += 512; // Increase the buffer size when compiling for JVMCI
|
|
}
|
|
#endif
|
|
@@ -2254,7 +2254,7 @@ void SharedRuntime::generate_deopt_blob() {
|
|
int implicit_exception_uncommon_trap_offset = 0;
|
|
int uncommon_trap_offset = 0;
|
|
|
|
- if (EnableJVMCI) {
|
|
+ if (EnableJVMCI || UseAOT) {
|
|
implicit_exception_uncommon_trap_offset = __ pc() - start;
|
|
|
|
__ ldr(lr, Address(rthread, in_bytes(JavaThread::jvmci_implicit_exception_pc_offset())));
|
|
@@ -2379,7 +2379,7 @@ void SharedRuntime::generate_deopt_blob() {
|
|
__ reset_last_Java_frame(false);
|
|
|
|
#if INCLUDE_JVMCI
|
|
- if (EnableJVMCI) {
|
|
+ if (EnableJVMCI || UseAOT) {
|
|
__ bind(after_fetch_unroll_info_call);
|
|
}
|
|
#endif
|
|
@@ -2542,7 +2542,7 @@ void SharedRuntime::generate_deopt_blob() {
|
|
_deopt_blob = DeoptimizationBlob::create(&buffer, oop_maps, 0, exception_offset, reexecute_offset, frame_size_in_words);
|
|
_deopt_blob->set_unpack_with_exception_in_tls_offset(exception_in_tls_offset);
|
|
#if INCLUDE_JVMCI
|
|
- if (EnableJVMCI) {
|
|
+ if (EnableJVMCI || UseAOT) {
|
|
_deopt_blob->set_uncommon_trap_offset(uncommon_trap_offset);
|
|
_deopt_blob->set_implicit_exception_uncommon_trap_offset(implicit_exception_uncommon_trap_offset);
|
|
}
|
|
diff --git a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp
|
|
index e20cffd57..8482dc73c 100644
|
|
--- a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp
|
|
+++ b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp
|
|
@@ -1,6 +1,6 @@
|
|
/*
|
|
- * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
- * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved.
|
|
+ * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2014, 2023, Red Hat Inc. 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
|
|
@@ -502,7 +502,7 @@ address TemplateInterpreterGenerator::generate_deopt_entry_for(TosState state,
|
|
#if INCLUDE_JVMCI
|
|
// Check if we need to take lock at entry of synchronized method. This can
|
|
// only occur on method entry so emit it only for vtos with step 0.
|
|
- if (EnableJVMCI && state == vtos && step == 0) {
|
|
+ if ((EnableJVMCI || UseAOT) && state == vtos && step == 0) {
|
|
Label L;
|
|
__ ldrb(rscratch1, Address(rthread, JavaThread::pending_monitorenter_offset()));
|
|
__ cbz(rscratch1, L);
|
|
diff --git a/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp b/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp
|
|
index 4666b42b9..8d573760e 100644
|
|
--- a/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp
|
|
+++ b/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp
|
|
@@ -1,6 +1,6 @@
|
|
/*
|
|
- * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
- * Copyright (c) 2014, Red Hat Inc. All rights reserved.
|
|
+ * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2014, 2023, Red Hat Inc. 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
|
|
@@ -2413,7 +2413,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteContr
|
|
// membar it's possible for a simple Dekker test to fail if loads
|
|
// use LDR;DMB but stores use STLR. This can happen if C2 compiles
|
|
// the stores in one method and we interpret the loads in another.
|
|
- if (!CompilerConfig::is_c1_or_interpreter_only_no_jvmci()){
|
|
+ if (!CompilerConfig::is_c1_or_interpreter_only_no_aot_or_jvmci()){
|
|
Label notVolatile;
|
|
__ tbz(raw_flags, ConstantPoolCacheEntry::is_volatile_shift, notVolatile);
|
|
__ membar(MacroAssembler::AnyAny);
|
|
@@ -3016,7 +3016,7 @@ void TemplateTable::fast_accessfield(TosState state)
|
|
// membar it's possible for a simple Dekker test to fail if loads
|
|
// use LDR;DMB but stores use STLR. This can happen if C2 compiles
|
|
// the stores in one method and we interpret the loads in another.
|
|
- if (!CompilerConfig::is_c1_or_interpreter_only_no_jvmci()) {
|
|
+ if (!CompilerConfig::is_c1_or_interpreter_only_no_aot_or_jvmci()) {
|
|
Label notVolatile;
|
|
__ tbz(r3, ConstantPoolCacheEntry::is_volatile_shift, notVolatile);
|
|
__ membar(MacroAssembler::AnyAny);
|
|
@@ -3078,7 +3078,7 @@ void TemplateTable::fast_xaccess(TosState state)
|
|
// membar it's possible for a simple Dekker test to fail if loads
|
|
// use LDR;DMB but stores use STLR. This can happen if C2 compiles
|
|
// the stores in one method and we interpret the loads in another.
|
|
- if (!CompilerConfig::is_c1_or_interpreter_only_no_jvmci()) {
|
|
+ if (!CompilerConfig::is_c1_or_interpreter_only_no_aot_or_jvmci()) {
|
|
Label notVolatile;
|
|
__ ldrw(r3, Address(r2, in_bytes(ConstantPoolCache::base_offset() +
|
|
ConstantPoolCacheEntry::flags_offset())));
|
|
diff --git a/src/hotspot/cpu/arm/c1_LIRAssembler_arm.hpp b/src/hotspot/cpu/arm/c1_LIRAssembler_arm.hpp
|
|
index 77d135326..85ae89aed 100644
|
|
--- a/src/hotspot/cpu/arm/c1_LIRAssembler_arm.hpp
|
|
+++ b/src/hotspot/cpu/arm/c1_LIRAssembler_arm.hpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2008, 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
|
|
@@ -53,6 +53,7 @@
|
|
|
|
enum {
|
|
_call_stub_size = 16,
|
|
+ _call_aot_stub_size = 0,
|
|
_exception_handler_size = PRODUCT_ONLY(68) NOT_PRODUCT(68+60),
|
|
_deopt_handler_size = 16
|
|
};
|
|
diff --git a/src/hotspot/cpu/arm/compiledIC_arm.cpp b/src/hotspot/cpu/arm/compiledIC_arm.cpp
|
|
index f0272db02..e2860c940 100644
|
|
--- a/src/hotspot/cpu/arm/compiledIC_arm.cpp
|
|
+++ b/src/hotspot/cpu/arm/compiledIC_arm.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 1997, 2021, 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
|
|
@@ -102,7 +102,7 @@ int CompiledStaticCall::to_interp_stub_size() {
|
|
}
|
|
|
|
void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, address entry) {
|
|
- address stub = find_stub();
|
|
+ address stub = find_stub(/*is_aot*/ false);
|
|
guarantee(stub != NULL, "stub not found");
|
|
|
|
if (TraceICs) {
|
|
@@ -149,7 +149,7 @@ void CompiledDirectStaticCall::verify() {
|
|
_call->verify_alignment();
|
|
|
|
// Verify stub.
|
|
- address stub = find_stub();
|
|
+ address stub = find_stub(/*is_aot*/ false);
|
|
assert(stub != NULL, "no stub found for static call");
|
|
// Creation also verifies the object.
|
|
NativeMovConstReg* method_holder = nativeMovConstReg_at(stub);
|
|
diff --git a/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.hpp b/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.hpp
|
|
index 861430b79..6a0e090d1 100644
|
|
--- a/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.hpp
|
|
+++ b/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.hpp
|
|
@@ -1,6 +1,6 @@
|
|
/*
|
|
- * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
- * Copyright (c) 2012, 2015 SAP SE. All rights reserved.
|
|
+ * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2012, 2023 SAP SE. 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
|
|
@@ -62,6 +62,7 @@
|
|
enum {
|
|
_static_call_stub_size = 4 * BytesPerInstWord + MacroAssembler::b64_patchable_size, // or smaller
|
|
_call_stub_size = _static_call_stub_size + MacroAssembler::trampoline_stub_size, // or smaller
|
|
+ _call_aot_stub_size = 0,
|
|
_exception_handler_size = MacroAssembler::b64_patchable_size, // or smaller
|
|
_deopt_handler_size = MacroAssembler::bl64_patchable_size
|
|
};
|
|
@@ -69,7 +70,11 @@ enum {
|
|
// '_static_call_stub_size' is only used on ppc (see LIR_Assembler::emit_static_call_stub()
|
|
// in c1_LIRAssembler_ppc.cpp. The other, shared getters are defined in c1_LIRAssembler.hpp
|
|
static int static_call_stub_size() {
|
|
- return _static_call_stub_size;
|
|
+ if (UseAOT) {
|
|
+ return _static_call_stub_size + _call_aot_stub_size;
|
|
+ } else {
|
|
+ return _static_call_stub_size;
|
|
+ }
|
|
}
|
|
|
|
#endif // CPU_PPC_C1_LIRASSEMBLER_PPC_HPP
|
|
diff --git a/src/hotspot/cpu/ppc/compiledIC_ppc.cpp b/src/hotspot/cpu/ppc/compiledIC_ppc.cpp
|
|
index a112e472e..457ff485d 100644
|
|
--- a/src/hotspot/cpu/ppc/compiledIC_ppc.cpp
|
|
+++ b/src/hotspot/cpu/ppc/compiledIC_ppc.cpp
|
|
@@ -1,6 +1,6 @@
|
|
/*
|
|
- * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
- * Copyright (c) 2012, 2015 SAP SE. All rights reserved.
|
|
+ * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2012, 2023 SAP SE. 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
|
|
@@ -164,7 +164,7 @@ int CompiledStaticCall::reloc_to_interp_stub() {
|
|
}
|
|
|
|
void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, address entry) {
|
|
- address stub = find_stub();
|
|
+ address stub = find_stub(/*is_aot*/ false);
|
|
guarantee(stub != NULL, "stub not found");
|
|
|
|
if (TraceICs) {
|
|
@@ -210,7 +210,7 @@ void CompiledDirectStaticCall::verify() {
|
|
_call->verify_alignment();
|
|
|
|
// Verify stub.
|
|
- address stub = find_stub();
|
|
+ address stub = find_stub(/*is_aot*/ false);
|
|
assert(stub != NULL, "no stub found for static call");
|
|
// Creation also verifies the object.
|
|
NativeMovConstReg* method_holder = nativeMovConstReg_at(stub + IC_pos_in_java_to_interp_stub);
|
|
diff --git a/src/hotspot/cpu/s390/c1_LIRAssembler_s390.hpp b/src/hotspot/cpu/s390/c1_LIRAssembler_s390.hpp
|
|
index 7ca94d2d9..bba78a4d2 100644
|
|
--- a/src/hotspot/cpu/s390/c1_LIRAssembler_s390.hpp
|
|
+++ b/src/hotspot/cpu/s390/c1_LIRAssembler_s390.hpp
|
|
@@ -1,6 +1,6 @@
|
|
/*
|
|
- * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
- * Copyright (c) 2016 SAP SE. All rights reserved.
|
|
+ * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2016, 2023 SAP SE. 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
|
|
@@ -47,6 +47,7 @@
|
|
|
|
enum {
|
|
_call_stub_size = 512, // See Compile::MAX_stubs_size and CompiledStaticCall::emit_to_interp_stub.
|
|
+ _call_aot_stub_size = 0,
|
|
_exception_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(128),
|
|
_deopt_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(64)
|
|
};
|
|
diff --git a/src/hotspot/cpu/s390/compiledIC_s390.cpp b/src/hotspot/cpu/s390/compiledIC_s390.cpp
|
|
index 6660a34ae..1cd1582bb 100644
|
|
--- a/src/hotspot/cpu/s390/compiledIC_s390.cpp
|
|
+++ b/src/hotspot/cpu/s390/compiledIC_s390.cpp
|
|
@@ -1,6 +1,6 @@
|
|
/*
|
|
- * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
- * Copyright (c) 2016, 2019 SAP SE. All rights reserved.
|
|
+ * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2016, 2023 SAP SE. 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
|
|
@@ -92,7 +92,7 @@ int CompiledStaticCall::reloc_to_interp_stub() {
|
|
}
|
|
|
|
void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, address entry) {
|
|
- address stub = find_stub();
|
|
+ address stub = find_stub(/*is_aot*/ false);
|
|
guarantee(stub != NULL, "stub not found");
|
|
|
|
if (TraceICs) {
|
|
@@ -137,7 +137,7 @@ void CompiledDirectStaticCall::verify() {
|
|
_call->verify_alignment();
|
|
|
|
// Verify stub.
|
|
- address stub = find_stub();
|
|
+ address stub = find_stub(/*is_aot*/ false);
|
|
assert(stub != NULL, "no stub found for static call");
|
|
// Creation also verifies the object.
|
|
NativeMovConstReg* method_holder = nativeMovConstReg_at(stub + NativeCall::get_IC_pos_in_java_to_interp_stub());
|
|
diff --git a/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp b/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp
|
|
index 592efea82..c079c65a9 100644
|
|
--- a/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp
|
|
+++ b/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2000, 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
|
|
@@ -2894,13 +2894,23 @@ void LIR_Assembler::emit_static_call_stub() {
|
|
|
|
// make sure that the displacement word of the call ends up word aligned
|
|
__ align(BytesPerWord, __ offset() + NativeMovConstReg::instruction_size + NativeCall::displacement_offset);
|
|
- __ relocate(static_stub_Relocation::spec(call_pc));
|
|
+ __ relocate(static_stub_Relocation::spec(call_pc, false /* is_aot */));
|
|
__ mov_metadata(rbx, (Metadata*)NULL);
|
|
// must be set to -1 at code generation time
|
|
assert(((__ offset() + 1) % BytesPerWord) == 0, "must be aligned");
|
|
// On 64bit this will die since it will take a movq & jmp, must be only a jmp
|
|
__ jump(RuntimeAddress(__ pc()));
|
|
|
|
+ if (UseAOT) {
|
|
+ // Trampoline to aot code
|
|
+ __ relocate(static_stub_Relocation::spec(call_pc, true /* is_aot */));
|
|
+#ifdef _LP64
|
|
+ __ mov64(rax, CONST64(0)); // address is zapped till fixup time.
|
|
+#else
|
|
+ __ movl(rax, 0xdeadffff); // address is zapped till fixup time.
|
|
+#endif
|
|
+ __ jmp(rax);
|
|
+ }
|
|
assert(__ offset() - start <= call_stub_size(), "stub too big");
|
|
__ end_a_stub();
|
|
}
|
|
diff --git a/src/hotspot/cpu/x86/c1_LIRAssembler_x86.hpp b/src/hotspot/cpu/x86/c1_LIRAssembler_x86.hpp
|
|
index 10270f4fb..40322f669 100644
|
|
--- a/src/hotspot/cpu/x86/c1_LIRAssembler_x86.hpp
|
|
+++ b/src/hotspot/cpu/x86/c1_LIRAssembler_x86.hpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2000, 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
|
|
@@ -48,6 +48,7 @@
|
|
|
|
enum {
|
|
_call_stub_size = NOT_LP64(15) LP64_ONLY(28),
|
|
+ _call_aot_stub_size = NOT_LP64(7) LP64_ONLY(12),
|
|
_exception_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(175),
|
|
_deopt_handler_size = NOT_LP64(10) LP64_ONLY(17)
|
|
};
|
|
diff --git a/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp
|
|
index b022f1199..70cd943a5 100644
|
|
--- a/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp
|
|
+++ b/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 1999, 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
|
|
@@ -336,7 +336,7 @@ void C1_MacroAssembler::build_frame(int frame_size_in_bytes, int bang_size_in_by
|
|
mov(rbp, rsp);
|
|
}
|
|
#if !defined(_LP64) && defined(COMPILER2)
|
|
- if (UseSSE < 2 && !CompilerConfig::is_c1_only_no_jvmci()) {
|
|
+ if (UseSSE < 2 && !CompilerConfig::is_c1_only_no_aot_or_jvmci()) {
|
|
// c2 leaves fpu stack dirty. Clean it on entry
|
|
empty_FPU_stack();
|
|
}
|
|
diff --git a/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp b/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp
|
|
index 42c46496d..031ba9c1c 100644
|
|
--- a/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp
|
|
+++ b/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 1999, 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
|
|
@@ -723,7 +723,7 @@ OopMapSet* Runtime1::generate_handle_exception(StubID id, StubAssembler *sasm) {
|
|
}
|
|
|
|
#if !defined(_LP64) && defined(COMPILER2)
|
|
- if (UseSSE < 2 && !CompilerConfig::is_c1_only_no_jvmci()) {
|
|
+ if (UseSSE < 2 && !CompilerConfig::is_c1_only_no_aot_or_jvmci()) {
|
|
// C2 can leave the fpu stack dirty
|
|
__ empty_FPU_stack();
|
|
}
|
|
diff --git a/src/hotspot/cpu/x86/compiledIC_aot_x86_64.cpp b/src/hotspot/cpu/x86/compiledIC_aot_x86_64.cpp
|
|
new file mode 100644
|
|
index 000000000..9e3e87de7
|
|
--- /dev/null
|
|
+++ b/src/hotspot/cpu/x86/compiledIC_aot_x86_64.cpp
|
|
@@ -0,0 +1,122 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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.
|
|
+ */
|
|
+
|
|
+#include "precompiled.hpp"
|
|
+
|
|
+#include "aot/compiledIC_aot.hpp"
|
|
+#include "code/codeCache.hpp"
|
|
+#include "memory/resourceArea.hpp"
|
|
+
|
|
+void CompiledDirectStaticCall::set_to_far(const methodHandle& callee, address entry) {
|
|
+ address stub = find_stub(true /* is_far */);
|
|
+ guarantee(stub != NULL, "stub not found");
|
|
+
|
|
+ if (TraceICs) {
|
|
+ ResourceMark rm;
|
|
+ tty->print_cr("CompiledDirectStaticCall@" INTPTR_FORMAT ": set_to_far %s",
|
|
+ p2i(instruction_address()),
|
|
+ callee->name_and_sig_as_C_string());
|
|
+ }
|
|
+
|
|
+ // Creation also verifies the object.
|
|
+ // mov rax,imm_aot_addr
|
|
+ // jmp rax
|
|
+ NativeMovConstReg* destination_holder = nativeMovConstReg_at(stub);
|
|
+
|
|
+#ifdef ASSERT
|
|
+ // read the value once
|
|
+ intptr_t data = destination_holder->data();
|
|
+ assert(data == 0 || data == (intptr_t)entry,
|
|
+ "MT-unsafe modification of inline cache");
|
|
+#endif
|
|
+
|
|
+ // Update stub.
|
|
+ destination_holder->set_data((intptr_t)entry);
|
|
+
|
|
+ // Update jump to call.
|
|
+ set_destination_mt_safe(stub);
|
|
+}
|
|
+
|
|
+void CompiledPltStaticCall::set_to_interpreted(const methodHandle& callee, address entry) {
|
|
+ address stub = find_stub();
|
|
+ guarantee(stub != NULL, "stub not found");
|
|
+ if (TraceICs) {
|
|
+ ResourceMark rm;
|
|
+ tty->print_cr("CompiledPltStaticCall@" INTPTR_FORMAT ": set_to_interpreted %s",
|
|
+ p2i(instruction_address()),
|
|
+ callee->name_and_sig_as_C_string());
|
|
+ }
|
|
+
|
|
+ // Creation also verifies the object.
|
|
+ NativeLoadGot* method_loader = nativeLoadGot_at(stub);
|
|
+ NativeGotJump* jump = nativeGotJump_at(method_loader->next_instruction_address());
|
|
+
|
|
+ intptr_t data = method_loader->data();
|
|
+ address destination = jump->destination();
|
|
+ assert(data == 0 || data == (intptr_t)callee(),
|
|
+ "a) MT-unsafe modification of inline cache");
|
|
+ assert(destination == (address)-1 || destination == entry,
|
|
+ "b) MT-unsafe modification of inline cache");
|
|
+
|
|
+ // Update stub.
|
|
+ method_loader->set_data((intptr_t)callee());
|
|
+ jump->set_jump_destination(entry);
|
|
+
|
|
+ // Update jump to call.
|
|
+ set_destination_mt_safe(stub);
|
|
+}
|
|
+
|
|
+#ifdef NEVER_CALLED
|
|
+void CompiledPltStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
|
|
+ // Reset stub.
|
|
+ address stub = static_stub->addr();
|
|
+ assert(stub != NULL, "stub not found");
|
|
+ assert(CompiledICLocker::is_safe(stub), "mt unsafe call");
|
|
+ // Creation also verifies the object.
|
|
+ NativeLoadGot* method_loader = nativeLoadGot_at(stub);
|
|
+ NativeGotJump* jump = nativeGotJump_at(method_loader->next_instruction_address());
|
|
+ method_loader->set_data(0);
|
|
+ jump->set_jump_destination((address)-1);
|
|
+}
|
|
+#endif
|
|
+
|
|
+#ifndef PRODUCT
|
|
+void CompiledPltStaticCall::verify() {
|
|
+ // Verify call.
|
|
+ _call->verify();
|
|
+
|
|
+#ifdef ASSERT
|
|
+ CodeBlob *cb = CodeCache::find_blob_unsafe((address) _call);
|
|
+ assert(cb && cb->is_aot(), "CompiledPltStaticCall can only be used on AOTCompiledMethod");
|
|
+#endif
|
|
+
|
|
+ // Verify stub.
|
|
+ address stub = find_stub();
|
|
+ assert(stub != NULL, "no stub found for static call");
|
|
+ // Creation also verifies the object.
|
|
+ NativeLoadGot* method_loader = nativeLoadGot_at(stub);
|
|
+ NativeGotJump* jump = nativeGotJump_at(method_loader->next_instruction_address());
|
|
+ // Verify state.
|
|
+ assert(is_clean() || is_call_to_compiled() || is_call_to_interpreted(), "sanity check");
|
|
+}
|
|
+#endif // !PRODUCT
|
|
diff --git a/src/hotspot/cpu/x86/compiledIC_x86.cpp b/src/hotspot/cpu/x86/compiledIC_x86.cpp
|
|
index e898e523c..504973517 100644
|
|
--- a/src/hotspot/cpu/x86/compiledIC_x86.cpp
|
|
+++ b/src/hotspot/cpu/x86/compiledIC_x86.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 1997, 2021, 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
|
|
@@ -54,7 +54,7 @@ address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark)
|
|
return NULL; // CodeBuffer::expand failed.
|
|
}
|
|
// Static stub relocation stores the instruction address of the call.
|
|
- __ relocate(static_stub_Relocation::spec(mark), Assembler::imm_operand);
|
|
+ __ relocate(static_stub_Relocation::spec(mark, false), Assembler::imm_operand);
|
|
// Static stub relocation also tags the Method* in the code-stream.
|
|
__ mov_metadata(rbx, (Metadata*) NULL); // Method is zapped till fixup time.
|
|
// This is recognized as unresolved by relocs/nativeinst/ic code.
|
|
@@ -83,8 +83,68 @@ int CompiledStaticCall::reloc_to_interp_stub() {
|
|
return 4; // 3 in emit_to_interp_stub + 1 in emit_call
|
|
}
|
|
|
|
+#if INCLUDE_AOT
|
|
+#define __ _masm.
|
|
+void CompiledStaticCall::emit_to_aot_stub(CodeBuffer &cbuf, address mark) {
|
|
+ if (!UseAOT) {
|
|
+ return;
|
|
+ }
|
|
+ // Stub is fixed up when the corresponding call is converted from
|
|
+ // calling compiled code to calling aot code.
|
|
+ // movq rax, imm64_aot_code_address
|
|
+ // jmp rax
|
|
+
|
|
+ if (mark == NULL) {
|
|
+ mark = cbuf.insts_mark(); // Get mark within main instrs section.
|
|
+ }
|
|
+
|
|
+ // Note that the code buffer's insts_mark is always relative to insts.
|
|
+ // That's why we must use the macroassembler to generate a stub.
|
|
+ MacroAssembler _masm(&cbuf);
|
|
+
|
|
+ address base =
|
|
+ __ start_a_stub(to_aot_stub_size());
|
|
+ guarantee(base != NULL, "out of space");
|
|
+
|
|
+ // Static stub relocation stores the instruction address of the call.
|
|
+ __ relocate(static_stub_Relocation::spec(mark, true /* is_aot */), Assembler::imm_operand);
|
|
+ // Load destination AOT code address.
|
|
+#ifdef _LP64
|
|
+ __ mov64(rax, CONST64(0)); // address is zapped till fixup time.
|
|
+#else
|
|
+ __ movl(rax, 0); // address is zapped till fixup time.
|
|
+#endif
|
|
+ // This is recognized as unresolved by relocs/nativeinst/ic code.
|
|
+ __ jmp(rax);
|
|
+
|
|
+ assert(__ pc() - base <= to_aot_stub_size(), "wrong stub size");
|
|
+
|
|
+ // Update current stubs pointer and restore insts_end.
|
|
+ __ end_a_stub();
|
|
+}
|
|
+#undef __
|
|
+
|
|
+int CompiledStaticCall::to_aot_stub_size() {
|
|
+ if (UseAOT) {
|
|
+ return NOT_LP64(7) // movl; jmp
|
|
+ LP64_ONLY(12); // movq (1+1+8); jmp (2)
|
|
+ } else {
|
|
+ return 0;
|
|
+ }
|
|
+}
|
|
+
|
|
+// Relocation entries for call stub, compiled java to aot.
|
|
+int CompiledStaticCall::reloc_to_aot_stub() {
|
|
+ if (UseAOT) {
|
|
+ return 2; // 1 in emit_to_aot_stub + 1 in emit_call
|
|
+ } else {
|
|
+ return 0;
|
|
+ }
|
|
+}
|
|
+#endif // INCLUDE_AOT
|
|
+
|
|
void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, address entry) {
|
|
- address stub = find_stub();
|
|
+ address stub = find_stub(false /* is_aot */);
|
|
guarantee(stub != NULL, "stub not found");
|
|
|
|
if (TraceICs) {
|
|
@@ -115,8 +175,10 @@ void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_
|
|
// Creation also verifies the object.
|
|
NativeMovConstReg* method_holder = nativeMovConstReg_at(stub);
|
|
method_holder->set_data(0);
|
|
- NativeJump* jump = nativeJump_at(method_holder->next_instruction_address());
|
|
- jump->set_jump_destination((address)-1);
|
|
+ if (!static_stub->is_aot()) {
|
|
+ NativeJump* jump = nativeJump_at(method_holder->next_instruction_address());
|
|
+ jump->set_jump_destination((address)-1);
|
|
+ }
|
|
}
|
|
|
|
|
|
@@ -131,11 +193,11 @@ void CompiledDirectStaticCall::verify() {
|
|
|
|
#ifdef ASSERT
|
|
CodeBlob *cb = CodeCache::find_blob_unsafe((address) _call);
|
|
- assert(cb != NULL, "sanity");
|
|
+ assert(cb && !cb->is_aot(), "CompiledDirectStaticCall cannot be used on AOTCompiledMethod");
|
|
#endif
|
|
|
|
// Verify stub.
|
|
- address stub = find_stub();
|
|
+ address stub = find_stub(false /* is_aot */);
|
|
assert(stub != NULL, "no stub found for static call");
|
|
// Creation also verifies the object.
|
|
NativeMovConstReg* method_holder = nativeMovConstReg_at(stub);
|
|
diff --git a/src/hotspot/cpu/x86/globalDefinitions_x86.hpp b/src/hotspot/cpu/x86/globalDefinitions_x86.hpp
|
|
index 60e8b0d22..d27f68c7a 100644
|
|
--- a/src/hotspot/cpu/x86/globalDefinitions_x86.hpp
|
|
+++ b/src/hotspot/cpu/x86/globalDefinitions_x86.hpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 1999, 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
|
|
@@ -70,7 +70,7 @@ const bool CCallingConventionRequiresIntsAsLongs = false;
|
|
#endif
|
|
|
|
#if INCLUDE_JVMCI
|
|
-#define COMPRESSED_CLASS_POINTERS_DEPENDS_ON_COMPRESSED_OOPS EnableJVMCI
|
|
+#define COMPRESSED_CLASS_POINTERS_DEPENDS_ON_COMPRESSED_OOPS (EnableJVMCI || UseAOT)
|
|
#else
|
|
#define COMPRESSED_CLASS_POINTERS_DEPENDS_ON_COMPRESSED_OOPS false
|
|
#endif
|
|
diff --git a/src/hotspot/cpu/x86/nativeInst_x86.hpp b/src/hotspot/cpu/x86/nativeInst_x86.hpp
|
|
index a86128e7e..a7fc40732 100644
|
|
--- a/src/hotspot/cpu/x86/nativeInst_x86.hpp
|
|
+++ b/src/hotspot/cpu/x86/nativeInst_x86.hpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 1997, 2021, 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
|
|
@@ -198,6 +198,13 @@ class NativeCall: public NativeInstruction {
|
|
nativeCall_at(instr)->destination() == target;
|
|
}
|
|
|
|
+#if INCLUDE_AOT
|
|
+ static bool is_far_call(address instr, address target) {
|
|
+ intptr_t disp = target - (instr + sizeof(int32_t));
|
|
+ return !Assembler::is_simm32(disp);
|
|
+ }
|
|
+#endif
|
|
+
|
|
// MT-safe patching of a call instruction.
|
|
static void insert(address code_pos, address entry);
|
|
|
|
diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp
|
|
index f912b7650..5dd8f952a 100644
|
|
--- a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp
|
|
+++ b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2003, 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
|
|
@@ -847,7 +847,7 @@ void SharedRuntime::gen_i2c_adapter(MacroAssembler *masm,
|
|
__ movptr(r11, Address(rbx, in_bytes(Method::from_compiled_offset())));
|
|
|
|
#if INCLUDE_JVMCI
|
|
- if (EnableJVMCI) {
|
|
+ if (EnableJVMCI || UseAOT) {
|
|
// check if this call should be routed towards a specific entry point
|
|
__ cmpptr(Address(r15_thread, in_bytes(JavaThread::jvmci_alternate_call_target_offset())), 0);
|
|
Label no_alternative_target;
|
|
@@ -2456,7 +2456,7 @@ void SharedRuntime::generate_deopt_blob() {
|
|
pad += 1024;
|
|
}
|
|
#if INCLUDE_JVMCI
|
|
- if (EnableJVMCI) {
|
|
+ if (EnableJVMCI || UseAOT) {
|
|
pad += 512; // Increase the buffer size when compiling for JVMCI
|
|
}
|
|
#endif
|
|
@@ -2530,7 +2530,7 @@ void SharedRuntime::generate_deopt_blob() {
|
|
int implicit_exception_uncommon_trap_offset = 0;
|
|
int uncommon_trap_offset = 0;
|
|
|
|
- if (EnableJVMCI) {
|
|
+ if (EnableJVMCI || UseAOT) {
|
|
implicit_exception_uncommon_trap_offset = __ pc() - start;
|
|
|
|
__ pushptr(Address(r15_thread, in_bytes(JavaThread::jvmci_implicit_exception_pc_offset())));
|
|
@@ -2645,7 +2645,7 @@ void SharedRuntime::generate_deopt_blob() {
|
|
__ reset_last_Java_frame(false);
|
|
|
|
#if INCLUDE_JVMCI
|
|
- if (EnableJVMCI) {
|
|
+ if (EnableJVMCI || UseAOT) {
|
|
__ bind(after_fetch_unroll_info_call);
|
|
}
|
|
#endif
|
|
@@ -2808,7 +2808,7 @@ void SharedRuntime::generate_deopt_blob() {
|
|
_deopt_blob = DeoptimizationBlob::create(&buffer, oop_maps, 0, exception_offset, reexecute_offset, frame_size_in_words);
|
|
_deopt_blob->set_unpack_with_exception_in_tls_offset(exception_in_tls_offset);
|
|
#if INCLUDE_JVMCI
|
|
- if (EnableJVMCI) {
|
|
+ if (EnableJVMCI || UseAOT) {
|
|
_deopt_blob->set_uncommon_trap_offset(uncommon_trap_offset);
|
|
_deopt_blob->set_implicit_exception_uncommon_trap_offset(implicit_exception_uncommon_trap_offset);
|
|
}
|
|
diff --git a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp
|
|
index dcbb37333..59d2c1938 100644
|
|
--- a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp
|
|
+++ b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2003, 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
|
|
@@ -261,7 +261,7 @@ address TemplateInterpreterGenerator::generate_deopt_entry_for(TosState state, i
|
|
#if INCLUDE_JVMCI
|
|
// Check if we need to take lock at entry of synchronized method. This can
|
|
// only occur on method entry so emit it only for vtos with step 0.
|
|
- if (EnableJVMCI && state == vtos && step == 0) {
|
|
+ if ((EnableJVMCI || UseAOT) && state == vtos && step == 0) {
|
|
Label L;
|
|
__ cmpb(Address(thread, JavaThread::pending_monitorenter_offset()), 0);
|
|
__ jcc(Assembler::zero, L);
|
|
diff --git a/src/hotspot/cpu/x86/x86_64.ad b/src/hotspot/cpu/x86/x86_64.ad
|
|
index 654b92db5..a6b419111 100644
|
|
--- a/src/hotspot/cpu/x86/x86_64.ad
|
|
+++ b/src/hotspot/cpu/x86/x86_64.ad
|
|
@@ -1,5 +1,5 @@
|
|
//
|
|
-// Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
+// Copyright (c) 2003, 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
|
|
@@ -2158,6 +2158,9 @@ encode %{
|
|
ciEnv::current()->record_failure("CodeCache is full");
|
|
return;
|
|
}
|
|
+#if INCLUDE_AOT
|
|
+ CompiledStaticCall::emit_to_aot_stub(cbuf, mark);
|
|
+#endif
|
|
}
|
|
%}
|
|
|
|
diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp
|
|
index 535b795fa..c9b9e2676 100644
|
|
--- a/src/hotspot/os/windows/os_windows.cpp
|
|
+++ b/src/hotspot/os/windows/os_windows.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
|
|
@@ -131,6 +131,9 @@ static FILETIME process_kernel_time;
|
|
#if defined(USE_VECTORED_EXCEPTION_HANDLING)
|
|
PVOID topLevelVectoredExceptionHandler = NULL;
|
|
LPTOP_LEVEL_EXCEPTION_FILTER previousUnhandledExceptionFilter = NULL;
|
|
+#elif INCLUDE_AOT
|
|
+PVOID topLevelVectoredExceptionHandler = NULL;
|
|
+LONG WINAPI topLevelVectoredExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo);
|
|
#endif
|
|
|
|
// save DLL module handle, used by GetModuleFileName
|
|
@@ -151,7 +154,7 @@ BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, LPVOID reserved) {
|
|
if (ForceTimeHighResolution) {
|
|
timeEndPeriod(1L);
|
|
}
|
|
-#if defined(USE_VECTORED_EXCEPTION_HANDLING)
|
|
+#if defined(USE_VECTORED_EXCEPTION_HANDLING) || INCLUDE_AOT
|
|
if (topLevelVectoredExceptionHandler != NULL) {
|
|
RemoveVectoredExceptionHandler(topLevelVectoredExceptionHandler);
|
|
topLevelVectoredExceptionHandler = NULL;
|
|
@@ -2833,7 +2836,7 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
|
|
return EXCEPTION_CONTINUE_SEARCH;
|
|
}
|
|
|
|
-#if defined(USE_VECTORED_EXCEPTION_HANDLING)
|
|
+#if defined(USE_VECTORED_EXCEPTION_HANDLING) || INCLUDE_AOT
|
|
LONG WINAPI topLevelVectoredExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
|
|
PEXCEPTION_RECORD exceptionRecord = exceptionInfo->ExceptionRecord;
|
|
#if defined(_M_ARM64)
|
|
@@ -2849,7 +2852,9 @@ LONG WINAPI topLevelVectoredExceptionFilter(struct _EXCEPTION_POINTERS* exceptio
|
|
return topLevelExceptionFilter(exceptionInfo);
|
|
}
|
|
|
|
- // If the exception occurred in the codeCache, pass control
|
|
+ // Handle the case where we get an implicit exception in AOT generated
|
|
+ // code. AOT DLL's loaded are not registered for structured exceptions.
|
|
+ // If the exception occurred in the codeCache or AOT code, pass control
|
|
// to our normal exception handler.
|
|
CodeBlob* cb = CodeCache::find_blob(pc);
|
|
if (cb != NULL) {
|
|
@@ -4354,6 +4359,14 @@ jint os::init_2(void) {
|
|
#if defined(USE_VECTORED_EXCEPTION_HANDLING)
|
|
topLevelVectoredExceptionHandler = AddVectoredExceptionHandler(1, topLevelVectoredExceptionFilter);
|
|
previousUnhandledExceptionFilter = SetUnhandledExceptionFilter(topLevelUnhandledExceptionFilter);
|
|
+#elif INCLUDE_AOT
|
|
+ // If AOT is enabled we need to install a vectored exception handler
|
|
+ // in order to forward implicit exceptions from code in AOT
|
|
+ // generated DLLs. This is necessary since these DLLs are not
|
|
+ // registered for structured exceptions like codecache methods are.
|
|
+ if (AOTLibrary != NULL && (UseAOT || FLAG_IS_DEFAULT(UseAOT))) {
|
|
+ topLevelVectoredExceptionHandler = AddVectoredExceptionHandler( 1, topLevelVectoredExceptionFilter);
|
|
+ }
|
|
#endif
|
|
|
|
// for debugging float code generation bugs
|
|
diff --git a/src/hotspot/share/aot/aotCodeHeap.cpp b/src/hotspot/share/aot/aotCodeHeap.cpp
|
|
new file mode 100644
|
|
index 000000000..153ef67bb
|
|
--- /dev/null
|
|
+++ b/src/hotspot/share/aot/aotCodeHeap.cpp
|
|
@@ -0,0 +1,1116 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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.
|
|
+ */
|
|
+
|
|
+#include "precompiled.hpp"
|
|
+#include "jvm_io.h"
|
|
+#include "aot/aotCodeHeap.hpp"
|
|
+#include "aot/aotLoader.hpp"
|
|
+#include "ci/ciUtilities.inline.hpp"
|
|
+#include "classfile/javaAssertions.hpp"
|
|
+#include "classfile/systemDictionary.hpp"
|
|
+#include "classfile/vmClasses.hpp"
|
|
+#include "classfile/vmSymbols.hpp"
|
|
+#include "gc/shared/cardTable.hpp"
|
|
+#include "gc/shared/cardTableBarrierSet.hpp"
|
|
+#include "gc/shared/gcConfig.hpp"
|
|
+#include "gc/shared/tlab_globals.hpp"
|
|
+#include "gc/g1/heapRegion.hpp"
|
|
+#include "interpreter/abstractInterpreter.hpp"
|
|
+#include "jvmci/compilerRuntime.hpp"
|
|
+#include "jvmci/jvmciRuntime.hpp"
|
|
+#include "logging/log.hpp"
|
|
+#include "memory/allocation.inline.hpp"
|
|
+#include "memory/universe.hpp"
|
|
+#include "oops/compressedOops.hpp"
|
|
+#include "oops/klass.inline.hpp"
|
|
+#include "oops/method.inline.hpp"
|
|
+#include "runtime/atomic.hpp"
|
|
+#include "runtime/deoptimization.hpp"
|
|
+#include "runtime/handles.inline.hpp"
|
|
+#include "runtime/os.hpp"
|
|
+#include "runtime/java.hpp"
|
|
+#include "runtime/safepointVerifiers.hpp"
|
|
+#include "runtime/sharedRuntime.hpp"
|
|
+#include "runtime/stubRoutines.hpp"
|
|
+#include "runtime/vmOperations.hpp"
|
|
+#include "utilities/powerOfTwo.hpp"
|
|
+#include "utilities/sizes.hpp"
|
|
+
|
|
+bool AOTLib::_narrow_oop_shift_initialized = false;
|
|
+int AOTLib::_narrow_oop_shift = 0;
|
|
+int AOTLib::_narrow_klass_shift = 0;
|
|
+
|
|
+address AOTLib::load_symbol(const char *name) {
|
|
+ address symbol = (address) os::dll_lookup(_dl_handle, name);
|
|
+ if (symbol == NULL) {
|
|
+ tty->print_cr("Shared file %s error: missing %s", _name, name);
|
|
+ vm_exit(1);
|
|
+ }
|
|
+ return symbol;
|
|
+}
|
|
+
|
|
+Klass* AOTCodeHeap::get_klass_from_got(const char* klass_name, int klass_len, const Method* method) {
|
|
+ AOTKlassData* klass_data = (AOTKlassData*)_lib->load_symbol(klass_name);
|
|
+ Klass* k = (Klass*)_klasses_got[klass_data->_got_index];
|
|
+ if (k == NULL) {
|
|
+ Thread* thread = Thread::current();
|
|
+ k = lookup_klass(klass_name, klass_len, method, thread);
|
|
+ // Note, exceptions are cleared.
|
|
+ if (k == NULL) {
|
|
+ fatal("Shared file %s error: klass %s should be resolved already", _lib->name(), klass_name);
|
|
+ vm_exit(1);
|
|
+ }
|
|
+ // Patch now to avoid extra runtime lookup
|
|
+ _klasses_got[klass_data->_got_index] = k;
|
|
+ if (k->is_instance_klass()) {
|
|
+ InstanceKlass* ik = InstanceKlass::cast(k);
|
|
+ if (ik->is_initialized()) {
|
|
+ _klasses_got[klass_data->_got_index - 1] = ik;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ return k;
|
|
+}
|
|
+
|
|
+Klass* AOTCodeHeap::lookup_klass(const char* name, int len, const Method* method, Thread* thread) {
|
|
+ ResourceMark rm(thread);
|
|
+ assert(method != NULL, "incorrect call parameter");
|
|
+ methodHandle caller(thread, (Method*)method);
|
|
+
|
|
+ // Use class loader of aot method.
|
|
+ Handle loader(thread, caller->method_holder()->class_loader());
|
|
+ Handle protection_domain(thread, caller->method_holder()->protection_domain());
|
|
+
|
|
+ // Ignore wrapping L and ;
|
|
+ if (name[0] == JVM_SIGNATURE_CLASS) {
|
|
+ assert(len > 2, "small name %s", name);
|
|
+ name++;
|
|
+ len -= 2;
|
|
+ }
|
|
+ TempNewSymbol sym = SymbolTable::probe(name, len);
|
|
+ if (sym == NULL) {
|
|
+ log_debug(aot, class, resolve)("Probe failed for AOT class %s", name);
|
|
+ return NULL;
|
|
+ }
|
|
+ Klass* k = SystemDictionary::find_instance_or_array_klass(sym, loader, protection_domain);
|
|
+
|
|
+ if (k != NULL) {
|
|
+ log_info(aot, class, resolve)("%s %s (lookup)", caller->method_holder()->external_name(), k->external_name());
|
|
+ }
|
|
+ return k;
|
|
+}
|
|
+
|
|
+void AOTLib::handle_config_error(const char* format, ...) {
|
|
+ if (PrintAOT) {
|
|
+ va_list ap;
|
|
+ va_start(ap, format);
|
|
+ tty->vprint_cr(format, ap);
|
|
+ va_end(ap);
|
|
+ }
|
|
+ if (UseAOTStrictLoading) {
|
|
+ vm_exit(1);
|
|
+ }
|
|
+ _valid = false;
|
|
+}
|
|
+
|
|
+void AOTLib::verify_flag(bool aot_flag, bool flag, const char* name) {
|
|
+ if (_valid && aot_flag != flag) {
|
|
+ handle_config_error("Shared file %s error: %s has different value '%s' from current '%s'", _name, name , (aot_flag ? "true" : "false"), (flag ? "true" : "false"));
|
|
+ }
|
|
+}
|
|
+
|
|
+void AOTLib::verify_flag(int aot_flag, int flag, const char* name) {
|
|
+ if (_valid && aot_flag != flag) {
|
|
+ handle_config_error("Shared file %s error: %s has different value '%d' from current '%d'", _name, name , aot_flag, flag);
|
|
+ }
|
|
+}
|
|
+
|
|
+void AOTLib::verify_config() {
|
|
+ GrowableArray<AOTLib*>* libraries = AOTLoader::libraries();
|
|
+ for (GrowableArrayIterator<AOTLib*> lib = libraries->begin(); lib != libraries->end(); ++lib) {
|
|
+ if ((*lib)->_config == _config) {
|
|
+ handle_config_error("AOT library %s already loaded.", (*lib)->_name);
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (_header->_version != AOTHeader::AOT_SHARED_VERSION) {
|
|
+ handle_config_error("Invalid version of the shared file %s. Expected %d but was %d", _name, _header->_version, AOTHeader::AOT_SHARED_VERSION);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ const char* aot_jvm_version = (const char*)_header + _header->_jvm_version_offset + 2;
|
|
+ if (strcmp(aot_jvm_version, VM_Version::jre_release_version()) != 0) {
|
|
+ handle_config_error("JVM version '%s' recorded in the shared file %s does not match current version '%s'", aot_jvm_version, _name, VM_Version::jre_release_version());
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ // Debug VM has different layout of runtime and metadata structures
|
|
+#ifdef ASSERT
|
|
+ verify_flag(_config->_debug_VM, true, "Debug VM version");
|
|
+#else
|
|
+ verify_flag(!(_config->_debug_VM), true, "Product VM version");
|
|
+#endif
|
|
+ // Check configuration size
|
|
+ verify_flag(_config->_config_size, AOTConfiguration::CONFIG_SIZE, "AOT configuration size");
|
|
+
|
|
+ // Check GC
|
|
+ CollectedHeap::Name gc = (CollectedHeap::Name)_config->_gc;
|
|
+ if (_valid && !GCConfig::is_gc_selected(gc)) {
|
|
+ handle_config_error("Shared file %s error: used '%s' is different from current '%s'", _name, GCConfig::hs_err_name(gc), GCConfig::hs_err_name());
|
|
+ }
|
|
+
|
|
+ // Check flags
|
|
+ verify_flag(_config->_useCompressedOops, UseCompressedOops, "UseCompressedOops");
|
|
+ verify_flag(_config->_useCompressedClassPointers, UseCompressedClassPointers, "UseCompressedClassPointers");
|
|
+ verify_flag(_config->_useTLAB, UseTLAB, "UseTLAB");
|
|
+ verify_flag(_config->_useBiasedLocking, UseBiasedLocking, "UseBiasedLocking");
|
|
+ verify_flag(_config->_objectAlignment, ObjectAlignmentInBytes, "ObjectAlignmentInBytes");
|
|
+ verify_flag(_config->_contendedPaddingWidth, ContendedPaddingWidth, "ContendedPaddingWidth");
|
|
+ verify_flag(_config->_enableContended, EnableContended, "EnableContended");
|
|
+ verify_flag(_config->_restrictContended, RestrictContended, "RestrictContended");
|
|
+
|
|
+ // Shifts are static values which initialized by 0 until java heap initialization.
|
|
+ // AOT libs are loaded before heap initialized so shift values are not set.
|
|
+ // It is okay since ObjectAlignmentInBytes flag which defines shifts value is set before AOT libs are loaded.
|
|
+ // Set shifts value based on first AOT library 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");
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+AOTLib::~AOTLib() {
|
|
+ os::free((void*) _name);
|
|
+}
|
|
+
|
|
+AOTCodeHeap::~AOTCodeHeap() {
|
|
+ FREE_C_HEAP_ARRAY(AOTClass, _classes);
|
|
+ FREE_C_HEAP_ARRAY(CodeToAMethod, _code_to_aot);
|
|
+}
|
|
+
|
|
+AOTLib::AOTLib(void* handle, const char* name, int dso_id) : _valid(true), _dl_handle(handle), _dso_id(dso_id) {
|
|
+ _name = (const char*) os::strdup(name);
|
|
+
|
|
+ // Verify that VM runs with the same parameters as AOT tool.
|
|
+ _config = (AOTConfiguration*) load_symbol("A.config");
|
|
+ _header = (AOTHeader*) load_symbol("A.header");
|
|
+
|
|
+ verify_config();
|
|
+
|
|
+ if (!_valid && PrintAOT) {
|
|
+ tty->print("%7d ", (int) tty->time_stamp().milliseconds());
|
|
+ tty->print_cr("%4d skipped %s aot library", _dso_id, _name);
|
|
+ }
|
|
+}
|
|
+
|
|
+AOTCodeHeap::AOTCodeHeap(AOTLib* lib) :
|
|
+ CodeHeap("CodeHeap 'AOT'", CodeBlobType::AOT), _lib(lib), _classes(NULL), _code_to_aot(NULL) {
|
|
+ assert(_lib->is_valid(), "invalid library");
|
|
+
|
|
+ _lib_symbols_initialized = false;
|
|
+ _aot_id = 0;
|
|
+
|
|
+ _class_count = _lib->header()->_class_count;
|
|
+ _method_count = _lib->header()->_method_count;
|
|
+
|
|
+ // Collect metaspace info: names -> address in .got section
|
|
+ _metaspace_names = (const char*) _lib->load_symbol("A.meta.names");
|
|
+ _method_metadata = (address) _lib->load_symbol("A.meth.metadata");
|
|
+ _methods_offsets = (address) _lib->load_symbol("A.meth.offsets");
|
|
+ _klasses_offsets = (address) _lib->load_symbol("A.kls.offsets");
|
|
+ _dependencies = (address) _lib->load_symbol("A.kls.dependencies");
|
|
+ _code_space = (address) _lib->load_symbol("A.text");
|
|
+
|
|
+ // First cell is number of elements.
|
|
+ _klasses_got = (Metadata**) _lib->load_symbol("A.kls.got");
|
|
+ _klasses_got_size = _lib->header()->_klasses_got_size;
|
|
+
|
|
+ _metadata_got = (Metadata**) _lib->load_symbol("A.meta.got");
|
|
+ _metadata_got_size = _lib->header()->_metadata_got_size;
|
|
+
|
|
+ _oop_got = (oop*) _lib->load_symbol("A.oop.got");
|
|
+ _oop_got_size = _lib->header()->_oop_got_size;
|
|
+
|
|
+ // Collect stubs info
|
|
+ _stubs_offsets = (int*) _lib->load_symbol("A.stubs.offsets");
|
|
+
|
|
+ // code segments table
|
|
+ _code_segments = (address) _lib->load_symbol("A.code.segments");
|
|
+
|
|
+ // method state
|
|
+ _method_state = (jlong*) _lib->load_symbol("A.meth.state");
|
|
+
|
|
+ // Create a table for mapping classes
|
|
+ _classes = NEW_C_HEAP_ARRAY(AOTClass, _class_count, mtCode);
|
|
+ memset(_classes, 0, _class_count * sizeof(AOTClass));
|
|
+
|
|
+ // Create table for searching AOTCompiledMethod based on pc.
|
|
+ _code_to_aot = NEW_C_HEAP_ARRAY(CodeToAMethod, _method_count, mtCode);
|
|
+ memset(_code_to_aot, 0, _method_count * sizeof(CodeToAMethod));
|
|
+
|
|
+ _memory.set_low_boundary((char *)_code_space);
|
|
+ _memory.set_high_boundary((char *)_code_space);
|
|
+ _memory.set_low((char *)_code_space);
|
|
+ _memory.set_high((char *)_code_space);
|
|
+
|
|
+ _segmap.set_low_boundary((char *)_code_segments);
|
|
+ _segmap.set_low((char *)_code_segments);
|
|
+
|
|
+ _log2_segment_size = exact_log2(_lib->config()->_codeSegmentSize);
|
|
+
|
|
+ // Register aot stubs
|
|
+ register_stubs();
|
|
+
|
|
+ if (PrintAOT || (PrintCompilation && PrintAOT)) {
|
|
+ tty->print("%7d ", (int) tty->time_stamp().milliseconds());
|
|
+ tty->print_cr("%4d loaded %s aot library", _lib->id(), _lib->name());
|
|
+ }
|
|
+}
|
|
+
|
|
+void AOTCodeHeap::publish_aot(const methodHandle& mh, AOTMethodData* method_data, int code_id) {
|
|
+ // The method may be explicitly excluded by the user.
|
|
+ // Or Interpreter uses an intrinsic for this method.
|
|
+ // Or method has breakpoints.
|
|
+ if (CompilerOracle::should_exclude(mh) ||
|
|
+ !AbstractInterpreter::can_be_compiled(mh) ||
|
|
+ (mh->number_of_breakpoints() > 0)) {
|
|
+ return;
|
|
+ }
|
|
+ // Make sure no break points were set in the method in case of a safepoint
|
|
+ // in the following code until aot code is registered.
|
|
+ NoSafepointVerifier nsv;
|
|
+
|
|
+ address code = method_data->_code;
|
|
+ const char* name = method_data->_name;
|
|
+ aot_metadata* meta = method_data->_meta;
|
|
+
|
|
+ if (meta->scopes_pcs_begin() == meta->scopes_pcs_end()) {
|
|
+ // Switch off NoSafepointVerifier because log_info() may cause safepoint
|
|
+ // and it is fine because aot code will not be registered here.
|
|
+ PauseNoSafepointVerifier pnsv(&nsv);
|
|
+
|
|
+ // When the AOT compiler compiles something big we fail to generate metadata
|
|
+ // in CodeInstaller::gather_metadata. In that case the scopes_pcs_begin == scopes_pcs_end.
|
|
+ // In all successful cases we always have 2 entries of scope pcs.
|
|
+ log_info(aot, class, resolve)("Failed to load %s (no metadata available)", mh->name_and_sig_as_C_string());
|
|
+ _code_to_aot[code_id]._state = invalid;
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ jlong* state_adr = &_method_state[code_id];
|
|
+ address metadata_table = method_data->_metadata_table;
|
|
+ int metadata_size = method_data->_metadata_size;
|
|
+ assert(code_id < _method_count, "sanity");
|
|
+ _aot_id++;
|
|
+
|
|
+#ifdef ASSERT
|
|
+ if (_aot_id > CIStop || _aot_id < CIStart) {
|
|
+ // Skip compilation
|
|
+ return;
|
|
+ }
|
|
+#endif
|
|
+ // Check one more time.
|
|
+ if (_code_to_aot[code_id]._state == invalid) {
|
|
+ return;
|
|
+ }
|
|
+ AOTCompiledMethod *aot = new AOTCompiledMethod(code, mh(), meta, metadata_table, metadata_size, state_adr, this, name, code_id, _aot_id);
|
|
+ assert(_code_to_aot[code_id]._aot == NULL, "should be not initialized");
|
|
+ _code_to_aot[code_id]._aot = aot; // Should set this first
|
|
+ if (Atomic::cmpxchg(&_code_to_aot[code_id]._state, not_set, in_use) != not_set) {
|
|
+ _code_to_aot[code_id]._aot = NULL; // Clean
|
|
+ } else { // success
|
|
+ // Publish method
|
|
+#if COMPILER1_OR_COMPILER2
|
|
+ mh->set_aot_code(aot);
|
|
+#endif
|
|
+ {
|
|
+ MutexLocker pl(CompiledMethod_lock, Mutex::_no_safepoint_check_flag);
|
|
+ Method::set_code(mh, aot);
|
|
+ }
|
|
+ if (PrintAOT || (PrintCompilation && PrintAOT)) {
|
|
+ PauseNoSafepointVerifier pnsv(&nsv); // aot code is registered already
|
|
+ aot->print_on(tty, NULL);
|
|
+ }
|
|
+ // Publish oop only after we are visible to CompiledMethodIterator
|
|
+ aot->set_oop(mh()->method_holder()->klass_holder());
|
|
+ }
|
|
+}
|
|
+
|
|
+void AOTCodeHeap::link_klass(const Klass* klass) {
|
|
+ ResourceMark rm;
|
|
+ assert(klass != NULL, "Should be given a klass");
|
|
+ AOTKlassData* klass_data = (AOTKlassData*) os::dll_lookup(_lib->dl_handle(), klass->signature_name());
|
|
+ if (klass_data != NULL) {
|
|
+ // Set both GOT cells, resolved and initialized klass pointers.
|
|
+ // _got_index points to second cell - resolved klass pointer.
|
|
+ _klasses_got[klass_data->_got_index-1] = (Metadata*)klass; // Initialized
|
|
+ _klasses_got[klass_data->_got_index ] = (Metadata*)klass; // Resolved
|
|
+ if (PrintAOT) {
|
|
+ tty->print_cr("[Found %s in %s]", klass->internal_name(), _lib->name());
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+void AOTCodeHeap::link_known_klasses() {
|
|
+ for (int i = T_BOOLEAN; i <= T_CONFLICT; i++) {
|
|
+ BasicType t = (BasicType)i;
|
|
+ if (is_java_primitive(t)) {
|
|
+ const Klass* arr_klass = Universe::typeArrayKlassObj(t);
|
|
+ link_klass(arr_klass);
|
|
+ }
|
|
+ }
|
|
+ link_klass(vmClasses::Reference_klass());
|
|
+}
|
|
+
|
|
+void AOTCodeHeap::register_stubs() {
|
|
+ int stubs_count = _stubs_offsets[0]; // contains number
|
|
+ _stubs_offsets++;
|
|
+ AOTMethodOffsets* stub_offsets = (AOTMethodOffsets*)_stubs_offsets;
|
|
+ for (int i = 0; i < stubs_count; ++i) {
|
|
+ const char* stub_name = _metaspace_names + stub_offsets[i]._name_offset;
|
|
+ address entry = _code_space + stub_offsets[i]._code_offset;
|
|
+ aot_metadata* meta = (aot_metadata *) (_method_metadata + stub_offsets[i]._meta_offset);
|
|
+ address metadata_table = (address)_metadata_got + stub_offsets[i]._metadata_got_offset;
|
|
+ int metadata_size = stub_offsets[i]._metadata_got_size;
|
|
+ int code_id = stub_offsets[i]._code_id;
|
|
+ assert(code_id < _method_count, "sanity");
|
|
+ jlong* state_adr = &_method_state[code_id];
|
|
+ int len = Bytes::get_Java_u2((address)stub_name);
|
|
+ stub_name += 2;
|
|
+ char* full_name = NEW_C_HEAP_ARRAY(char, len+5, mtCode);
|
|
+ memcpy(full_name, "AOT ", 4);
|
|
+ memcpy(full_name+4, stub_name, len);
|
|
+ full_name[len+4] = 0;
|
|
+ guarantee(_code_to_aot[code_id]._state != invalid, "stub %s can't be invalidated", full_name);
|
|
+ AOTCompiledMethod* aot = new AOTCompiledMethod(entry, NULL, meta, metadata_table, metadata_size, state_adr, this, full_name, code_id, i);
|
|
+ assert(_code_to_aot[code_id]._aot == NULL, "should be not initialized");
|
|
+ _code_to_aot[code_id]._aot = aot;
|
|
+ if (Atomic::cmpxchg(&_code_to_aot[code_id]._state, not_set, in_use) != not_set) {
|
|
+ fatal("stab '%s' code state is %d", full_name, _code_to_aot[code_id]._state);
|
|
+ }
|
|
+ // Adjust code buffer boundaries only for stubs because they are last in the buffer.
|
|
+ adjust_boundaries(aot);
|
|
+ if (PrintAOT && Verbose) {
|
|
+ aot->print_on(tty, NULL);
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+#define SET_AOT_GLOBAL_SYMBOL_VALUE(AOTSYMNAME, AOTSYMTYPE, VMSYMVAL) \
|
|
+ { \
|
|
+ AOTSYMTYPE * adr = (AOTSYMTYPE *) os::dll_lookup(_lib->dl_handle(), AOTSYMNAME); \
|
|
+ /* Check for a lookup error */ \
|
|
+ guarantee(adr != NULL, "AOT Symbol not found %s", AOTSYMNAME); \
|
|
+ *adr = (AOTSYMTYPE) VMSYMVAL; \
|
|
+ }
|
|
+
|
|
+void AOTCodeHeap::link_graal_runtime_symbols() {
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_monitorenter", address, JVMCIRuntime::monitorenter);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_monitorexit", address, JVMCIRuntime::monitorexit);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_log_object", address, JVMCIRuntime::log_object);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_log_printf", address, JVMCIRuntime::log_printf);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_log_primitive", address, JVMCIRuntime::log_primitive);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_new_instance", address, JVMCIRuntime::new_instance);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_new_array", address, JVMCIRuntime::new_array);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_new_multi_array", address, JVMCIRuntime::new_multi_array);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_dynamic_new_instance", address, JVMCIRuntime::dynamic_new_instance);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_dynamic_new_array", address, JVMCIRuntime::dynamic_new_array);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_new_instance_or_null", address, JVMCIRuntime::new_instance_or_null);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_new_array_or_null", address, JVMCIRuntime::new_array_or_null);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_new_multi_array_or_null", address, JVMCIRuntime::new_multi_array_or_null);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_dynamic_new_instance_or_null", address, JVMCIRuntime::dynamic_new_instance_or_null);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_dynamic_new_array_or_null", address, JVMCIRuntime::dynamic_new_array_or_null);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_validate_object", address, JVMCIRuntime::validate_object);
|
|
+#if INCLUDE_G1GC
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_write_barrier_pre", address, JVMCIRuntime::write_barrier_pre);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_write_barrier_post", address, JVMCIRuntime::write_barrier_post);
|
|
+#endif
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_identity_hash_code", address, JVMCIRuntime::identity_hash_code);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_exception_handler_for_pc", address, JVMCIRuntime::exception_handler_for_pc);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_test_deoptimize_call_int", address, JVMCIRuntime::test_deoptimize_call_int);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_throw_and_post_jvmti_exception", address, JVMCIRuntime::throw_and_post_jvmti_exception);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_throw_klass_external_name_exception", address, JVMCIRuntime::throw_klass_external_name_exception);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_throw_class_cast_exception", address, JVMCIRuntime::throw_class_cast_exception);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_vm_message", address, JVMCIRuntime::vm_message);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_vm_error", address, JVMCIRuntime::vm_error);
|
|
+}
|
|
+
|
|
+void AOTCodeHeap::link_shared_runtime_symbols() {
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_resolve_static_entry", address, SharedRuntime::get_resolve_static_call_stub());
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_resolve_virtual_entry", address, SharedRuntime::get_resolve_virtual_call_stub());
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_resolve_opt_virtual_entry", address, SharedRuntime::get_resolve_opt_virtual_call_stub());
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_deopt_blob_unpack", address, SharedRuntime::deopt_blob()->unpack());
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_deopt_blob_unpack_with_exception_in_tls", address, SharedRuntime::deopt_blob()->unpack_with_exception_in_tls());
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_deopt_blob_uncommon_trap", address, SharedRuntime::deopt_blob()->uncommon_trap());
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_ic_miss_stub", address, SharedRuntime::get_ic_miss_stub());
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_handle_wrong_method_stub", address, SharedRuntime::get_handle_wrong_method_stub());
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_exception_handler_for_return_address", address, SharedRuntime::exception_handler_for_return_address);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_register_finalizer", address, SharedRuntime::register_finalizer);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_object_notify", address, JVMCIRuntime::object_notify);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_object_notifyAll", address, JVMCIRuntime::object_notifyAll);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_OSR_migration_end", address, SharedRuntime::OSR_migration_end);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_enable_stack_reserved_zone", address, SharedRuntime::enable_stack_reserved_zone);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_resolve_dynamic_invoke", address, CompilerRuntime::resolve_dynamic_invoke);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_resolve_string_by_symbol", address, CompilerRuntime::resolve_string_by_symbol);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_resolve_klass_by_symbol", address, CompilerRuntime::resolve_klass_by_symbol);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_resolve_method_by_symbol_and_load_counters", address, CompilerRuntime::resolve_method_by_symbol_and_load_counters);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_initialize_klass_by_symbol", address, CompilerRuntime::initialize_klass_by_symbol);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_invocation_event", address, CompilerRuntime::invocation_event);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_backedge_event", address, CompilerRuntime::backedge_event);
|
|
+
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_shared_runtime_dpow", address, SharedRuntime::dpow);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_shared_runtime_dexp", address, SharedRuntime::dexp);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_shared_runtime_dcos", address, SharedRuntime::dcos);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_shared_runtime_dsin", address, SharedRuntime::dsin);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_shared_runtime_dtan", address, SharedRuntime::dtan);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_shared_runtime_dlog", address, SharedRuntime::dlog);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_shared_runtime_dlog10", address, SharedRuntime::dlog10);
|
|
+}
|
|
+
|
|
+void AOTCodeHeap::link_stub_routines_symbols() {
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_jbyte_arraycopy", address, StubRoutines::_jbyte_arraycopy);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_jshort_arraycopy", address, StubRoutines::_jshort_arraycopy);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_jint_arraycopy", address, StubRoutines::_jint_arraycopy);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_jlong_arraycopy", address, StubRoutines::_jlong_arraycopy);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_oop_arraycopy", address, StubRoutines::_oop_arraycopy);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_oop_arraycopy_uninit", address, StubRoutines::_oop_arraycopy_uninit);
|
|
+
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_jbyte_disjoint_arraycopy", address, StubRoutines::_jbyte_disjoint_arraycopy);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_jshort_disjoint_arraycopy", address, StubRoutines::_jshort_disjoint_arraycopy);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_jint_disjoint_arraycopy", address, StubRoutines::_jint_disjoint_arraycopy);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_jlong_disjoint_arraycopy", address, StubRoutines::_jlong_disjoint_arraycopy);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_oop_disjoint_arraycopy", address, StubRoutines::_oop_disjoint_arraycopy);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_oop_disjoint_arraycopy_uninit", address, StubRoutines::_oop_disjoint_arraycopy_uninit);
|
|
+
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_arrayof_jbyte_arraycopy", address, StubRoutines::_arrayof_jbyte_arraycopy);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_arrayof_jshort_arraycopy", address, StubRoutines::_arrayof_jshort_arraycopy);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_arrayof_jint_arraycopy", address, StubRoutines::_arrayof_jint_arraycopy);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_arrayof_jlong_arraycopy", address, StubRoutines::_arrayof_jlong_arraycopy);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_arrayof_oop_arraycopy", address, StubRoutines::_arrayof_oop_arraycopy);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_arrayof_oop_arraycopy_uninit", address, StubRoutines::_arrayof_oop_arraycopy_uninit);
|
|
+
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_arrayof_jbyte_disjoint_arraycopy", address, StubRoutines::_arrayof_jbyte_disjoint_arraycopy);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_arrayof_jshort_disjoint_arraycopy", address, StubRoutines::_arrayof_jshort_disjoint_arraycopy);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_arrayof_jint_disjoint_arraycopy", address, StubRoutines::_arrayof_jint_disjoint_arraycopy);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_arrayof_jlong_disjoint_arraycopy", address, StubRoutines::_arrayof_jlong_disjoint_arraycopy);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_arrayof_oop_disjoint_arraycopy", address, StubRoutines::_arrayof_oop_disjoint_arraycopy);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_arrayof_oop_disjoint_arraycopy_uninit", address, StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit);
|
|
+
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_unsafe_arraycopy", address, StubRoutines::_unsafe_arraycopy);
|
|
+
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_checkcast_arraycopy", address, StubRoutines::_checkcast_arraycopy);
|
|
+
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_generic_arraycopy", address, StubRoutines::_generic_arraycopy);
|
|
+
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_aescrypt_encryptBlock", address, StubRoutines::_aescrypt_encryptBlock);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_aescrypt_decryptBlock", address, StubRoutines::_aescrypt_decryptBlock);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_cipherBlockChaining_encryptAESCrypt", address, StubRoutines::_cipherBlockChaining_encryptAESCrypt);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_cipherBlockChaining_decryptAESCrypt", address, StubRoutines::_cipherBlockChaining_decryptAESCrypt);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_electronicCodeBook_encryptAESCrypt", address, StubRoutines::_electronicCodeBook_encryptAESCrypt);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_electronicCodeBook_decryptAESCrypt", address, StubRoutines::_electronicCodeBook_decryptAESCrypt);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_update_bytes_crc32", address, StubRoutines::_updateBytesCRC32);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_crc_table_adr", address, StubRoutines::_crc_table_adr);
|
|
+
|
|
+
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_sha1_implCompress", address, StubRoutines::_sha1_implCompress);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_sha1_implCompressMB", address, StubRoutines::_sha1_implCompressMB);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_sha256_implCompress", address, StubRoutines::_sha256_implCompress);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_sha256_implCompressMB", address, StubRoutines::_sha256_implCompressMB);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_sha512_implCompress", address, StubRoutines::_sha512_implCompress);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_sha512_implCompressMB", address, StubRoutines::_sha512_implCompressMB);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_multiplyToLen", address, StubRoutines::_multiplyToLen);
|
|
+
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_counterMode_AESCrypt", address, StubRoutines::_counterMode_AESCrypt);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_ghash_processBlocks", address, StubRoutines::_ghash_processBlocks);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_base64_encodeBlock", address, StubRoutines::_base64_encodeBlock);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_crc32c_table_addr", address, StubRoutines::_crc32c_table_addr);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_updateBytesCRC32C", address, StubRoutines::_updateBytesCRC32C);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_updateBytesAdler32", address, StubRoutines::_updateBytesAdler32);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_squareToLen", address, StubRoutines::_squareToLen);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_mulAdd", address, StubRoutines::_mulAdd);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_montgomeryMultiply", address, StubRoutines::_montgomeryMultiply);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_montgomerySquare", address, StubRoutines::_montgomerySquare);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_vectorizedMismatch", address, StubRoutines::_vectorizedMismatch);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_bigIntegerRightShiftWorker", address, StubRoutines::_bigIntegerRightShiftWorker);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_bigIntegerLeftShiftWorker", address, StubRoutines::_bigIntegerLeftShiftWorker);
|
|
+
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_throw_delayed_StackOverflowError_entry", address, StubRoutines::_throw_delayed_StackOverflowError_entry);
|
|
+
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_verify_oops", intptr_t, VerifyOops);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_verify_oop_count_address", jint *, &StubRoutines::_verify_oop_count);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_verify_oop_bits", intptr_t, Universe::verify_oop_bits());
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_verify_oop_mask", intptr_t, Universe::verify_oop_mask());
|
|
+}
|
|
+
|
|
+void AOTCodeHeap::link_os_symbols() {
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_os_javaTimeMillis", address, os::javaTimeMillis);
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_os_javaTimeNanos", address, os::javaTimeNanos);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Link any global symbols in precompiled DSO with dlopen() _dl_handle
|
|
+ * dso_handle.
|
|
+ */
|
|
+
|
|
+void AOTCodeHeap::link_global_lib_symbols() {
|
|
+ if (!_lib_symbols_initialized) {
|
|
+ _lib_symbols_initialized = true;
|
|
+
|
|
+ CollectedHeap* heap = Universe::heap();
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_card_table_address", address, (BarrierSet::barrier_set()->is_a(BarrierSet::CardTableBarrierSet) ? ci_card_table_address() : NULL));
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_heap_top_address", address, (heap->supports_inline_contig_alloc() ? heap->top_addr() : NULL));
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_heap_end_address", address, (heap->supports_inline_contig_alloc() ? heap->end_addr() : NULL));
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_narrow_klass_base_address", address, CompressedKlassPointers::base());
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_narrow_oop_base_address", address, CompressedOops::base());
|
|
+#if INCLUDE_G1GC
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_log_of_heap_region_grain_bytes", int, HeapRegion::LogOfHRGrainBytes);
|
|
+#endif
|
|
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_inline_contiguous_allocation_supported", bool, heap->supports_inline_contig_alloc());
|
|
+ link_shared_runtime_symbols();
|
|
+ link_stub_routines_symbols();
|
|
+ link_os_symbols();
|
|
+ link_graal_runtime_symbols();
|
|
+ link_known_klasses();
|
|
+ }
|
|
+}
|
|
+
|
|
+#ifndef PRODUCT
|
|
+int AOTCodeHeap::klasses_seen = 0;
|
|
+int AOTCodeHeap::aot_klasses_found = 0;
|
|
+int AOTCodeHeap::aot_klasses_fp_miss = 0;
|
|
+int AOTCodeHeap::aot_klasses_cl_miss = 0;
|
|
+int AOTCodeHeap::aot_methods_found = 0;
|
|
+
|
|
+void AOTCodeHeap::print_statistics() {
|
|
+ tty->print_cr("Classes seen: %d AOT classes found: %d AOT methods found: %d", klasses_seen, aot_klasses_found, aot_methods_found);
|
|
+ tty->print_cr("AOT fingerprint mismatches: %d AOT class loader mismatches: %d", aot_klasses_fp_miss, aot_klasses_cl_miss);
|
|
+}
|
|
+#endif
|
|
+
|
|
+Method* AOTCodeHeap::find_method(Klass* klass, TRAPS, 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;
|
|
+ int signature_name_len = Bytes::get_Java_u2((address)signature_name);
|
|
+ signature_name += 2;
|
|
+ // The class should have been loaded so the method and signature should already be
|
|
+ // in the symbol table. If they're not there, the method doesn't exist.
|
|
+ TempNewSymbol name = SymbolTable::probe(method_name, method_name_len);
|
|
+ TempNewSymbol signature = SymbolTable::probe(signature_name, signature_name_len);
|
|
+
|
|
+ Method* m;
|
|
+ if (name == NULL || signature == NULL) {
|
|
+ m = NULL;
|
|
+ } else if (name == vmSymbols::object_initializer_name() ||
|
|
+ name == vmSymbols::class_initializer_name()) {
|
|
+ // Never search superclasses for constructors
|
|
+ if (klass->is_instance_klass()) {
|
|
+ m = InstanceKlass::cast(klass)->find_method(name, signature);
|
|
+ } else {
|
|
+ m = NULL;
|
|
+ }
|
|
+ } else {
|
|
+ m = klass->lookup_method(name, signature);
|
|
+ if (m == NULL && klass->is_instance_klass()) {
|
|
+ m = InstanceKlass::cast(klass)->lookup_method_in_ordered_interfaces(name, signature);
|
|
+ }
|
|
+ }
|
|
+ if (m == NULL) {
|
|
+ // Fatal error because we assume classes and methods should not be changed since aot compilation.
|
|
+ const char* klass_name = klass->external_name();
|
|
+ int klass_len = (int)strlen(klass_name);
|
|
+ char* meta_name = NEW_RESOURCE_ARRAY(char, klass_len + 1 + method_name_len + signature_name_len + 1);
|
|
+ memcpy(meta_name, klass_name, klass_len);
|
|
+ meta_name[klass_len] = '.';
|
|
+ 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++; )
|
|
+ return m;
|
|
+}
|
|
+
|
|
+AOTKlassData* AOTCodeHeap::find_klass(const char *name) {
|
|
+ return (AOTKlassData*) os::dll_lookup(_lib->dl_handle(), name);
|
|
+}
|
|
+
|
|
+AOTKlassData* AOTCodeHeap::find_klass(InstanceKlass* ik) {
|
|
+ ResourceMark rm;
|
|
+ AOTKlassData* klass_data = find_klass(ik->signature_name());
|
|
+ return klass_data;
|
|
+}
|
|
+
|
|
+bool AOTCodeHeap::is_dependent_method(Klass* dependee, AOTCompiledMethod* aot) {
|
|
+ InstanceKlass *dependee_ik = InstanceKlass::cast(dependee);
|
|
+ AOTKlassData* klass_data = find_klass(dependee_ik);
|
|
+ if (klass_data == NULL) {
|
|
+ return false; // no AOT records for this class - no dependencies
|
|
+ }
|
|
+ if (!dependee_ik->has_passed_fingerprint_check()) {
|
|
+ return false; // different class
|
|
+ }
|
|
+
|
|
+ int methods_offset = klass_data->_dependent_methods_offset;
|
|
+ if (methods_offset >= 0) {
|
|
+ address methods_cnt_adr = _dependencies + methods_offset;
|
|
+ int methods_cnt = *(int*)methods_cnt_adr;
|
|
+ int* indexes = (int*)(methods_cnt_adr + 4);
|
|
+ for (int i = 0; i < methods_cnt; ++i) {
|
|
+ int code_id = indexes[i];
|
|
+ if (_code_to_aot[code_id]._aot == aot) {
|
|
+ return true; // found dependent method
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ return false;
|
|
+}
|
|
+
|
|
+void AOTCodeHeap::mark_evol_dependent_methods(InstanceKlass* dependee) {
|
|
+ AOTKlassData* klass_data = find_klass(dependee);
|
|
+ if (klass_data == NULL) {
|
|
+ return; // no AOT records for this class - no dependencies
|
|
+ }
|
|
+ if (!dependee->has_passed_fingerprint_check()) {
|
|
+ return; // different class
|
|
+ }
|
|
+
|
|
+ int methods_offset = klass_data->_dependent_methods_offset;
|
|
+ if (methods_offset >= 0) {
|
|
+ address methods_cnt_adr = _dependencies + methods_offset;
|
|
+ int methods_cnt = *(int*)methods_cnt_adr;
|
|
+ int* indexes = (int*)(methods_cnt_adr + 4);
|
|
+ for (int i = 0; i < methods_cnt; ++i) {
|
|
+ int code_id = indexes[i];
|
|
+ AOTCompiledMethod* aot = _code_to_aot[code_id]._aot;
|
|
+ if (aot != NULL) {
|
|
+ aot->mark_for_deoptimization(false);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+void AOTCodeHeap::sweep_dependent_methods(int* indexes, int methods_cnt) {
|
|
+ int marked = 0;
|
|
+ for (int i = 0; i < methods_cnt; ++i) {
|
|
+ int code_id = indexes[i];
|
|
+ // Invalidate aot code.
|
|
+ if (Atomic::cmpxchg(&_code_to_aot[code_id]._state, not_set, invalid) != not_set) {
|
|
+ if (_code_to_aot[code_id]._state == in_use) {
|
|
+ AOTCompiledMethod* aot = _code_to_aot[code_id]._aot;
|
|
+ assert(aot != NULL, "aot should be set");
|
|
+ if (!aot->is_runtime_stub()) { // Something is wrong - should not invalidate stubs.
|
|
+ aot->mark_for_deoptimization(false);
|
|
+ marked++;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ if (marked > 0) {
|
|
+ Deoptimization::deoptimize_all_marked();
|
|
+ }
|
|
+}
|
|
+
|
|
+void AOTCodeHeap::sweep_dependent_methods(AOTKlassData* klass_data) {
|
|
+ // Make dependent methods non_entrant forever.
|
|
+ int methods_offset = klass_data->_dependent_methods_offset;
|
|
+ if (methods_offset >= 0) {
|
|
+ address methods_cnt_adr = _dependencies + methods_offset;
|
|
+ int methods_cnt = *(int*)methods_cnt_adr;
|
|
+ int* indexes = (int*)(methods_cnt_adr + 4);
|
|
+ sweep_dependent_methods(indexes, methods_cnt);
|
|
+ }
|
|
+}
|
|
+
|
|
+void AOTCodeHeap::sweep_dependent_methods(InstanceKlass* ik) {
|
|
+ AOTKlassData* klass_data = find_klass(ik);
|
|
+ vmassert(klass_data != NULL, "dependency data missing");
|
|
+ sweep_dependent_methods(klass_data);
|
|
+}
|
|
+
|
|
+void AOTCodeHeap::sweep_method(AOTCompiledMethod *aot) {
|
|
+ int indexes[] = {aot->method_index()};
|
|
+ sweep_dependent_methods(indexes, 1);
|
|
+ vmassert(aot->method()->code() != aot COMPILER1_OR_COMPILER2_PRESENT( && aot->method()->aot_code() == NULL), "method still active");
|
|
+}
|
|
+
|
|
+
|
|
+bool AOTCodeHeap::load_klass_data(InstanceKlass* ik, TRAPS) {
|
|
+ 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()) {
|
|
+ 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;
|
|
+ }
|
|
+
|
|
+ AOTKlassData* klass_data = find_klass(ik);
|
|
+ if (klass_data == NULL) {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ if (!ik->has_passed_fingerprint_check()) {
|
|
+ NOT_PRODUCT( aot_klasses_fp_miss++; )
|
|
+ log_trace(aot, class, fingerprint)("class %s%s has bad fingerprint in %s tid=" INTPTR_FORMAT,
|
|
+ ik->internal_name(), ik->is_shared() ? " (shared)" : "",
|
|
+ _lib->name(), p2i(THREAD));
|
|
+ sweep_dependent_methods(klass_data);
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ if (ik->has_been_redefined()) {
|
|
+ log_trace(aot, class, load)("class %s%s in %s has been redefined tid=" INTPTR_FORMAT,
|
|
+ ik->internal_name(), ik->is_shared() ? " (shared)" : "",
|
|
+ _lib->name(), p2i(THREAD));
|
|
+ sweep_dependent_methods(klass_data);
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ assert(klass_data->_class_id < _class_count, "invalid class id");
|
|
+ AOTClass* aot_class = &_classes[klass_data->_class_id];
|
|
+ ClassLoaderData* aot_cld = aot_class->_classloader;
|
|
+ if (aot_cld != NULL && aot_cld != cld) {
|
|
+ log_trace(aot, class, load)("class %s in %s already loaded for classloader %s (%p) vs %s (%p) tid=" INTPTR_FORMAT,
|
|
+ ik->internal_name(), _lib->name(), aot_cld->loader_name(), aot_cld, cld->loader_name(), cld, p2i(THREAD));
|
|
+ NOT_PRODUCT( aot_klasses_cl_miss++; )
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ if (_lib->config()->_omitAssertions && JavaAssertions::enabled(ik->name()->as_C_string(), ik->class_loader() == NULL)) {
|
|
+ log_trace(aot, class, load)("class %s in %s does not have java assertions in compiled code, but assertions are enabled for this execution.", ik->internal_name(), _lib->name());
|
|
+ sweep_dependent_methods(klass_data);
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ NOT_PRODUCT( aot_klasses_found++; )
|
|
+
|
|
+ log_trace(aot, class, load)("found %s in %s for classloader %s (%p) tid=" INTPTR_FORMAT, ik->internal_name(), _lib->name(), cld->loader_name(), cld, p2i(THREAD));
|
|
+
|
|
+ aot_class->_classloader = cld;
|
|
+ // Set klass's Resolve (second) got cell.
|
|
+ _klasses_got[klass_data->_got_index] = ik;
|
|
+ if (ik->is_initialized()) {
|
|
+ _klasses_got[klass_data->_got_index - 1] = ik;
|
|
+ }
|
|
+
|
|
+ // Initialize global symbols of the DSO to the corresponding VM symbol values.
|
|
+ link_global_lib_symbols();
|
|
+
|
|
+ int methods_offset = klass_data->_compiled_methods_offset;
|
|
+ if (methods_offset >= 0) {
|
|
+ address methods_cnt_adr = _methods_offsets + methods_offset;
|
|
+ int methods_cnt = *(int*)methods_cnt_adr;
|
|
+ // Collect data about compiled methods
|
|
+ AOTMethodData* methods_data = NEW_RESOURCE_ARRAY(AOTMethodData, methods_cnt);
|
|
+ AOTMethodOffsets* methods_offsets = (AOTMethodOffsets*)(methods_cnt_adr + 4);
|
|
+ for (int i = 0; i < methods_cnt; ++i) {
|
|
+ AOTMethodOffsets* method_offsets = &methods_offsets[i];
|
|
+ int code_id = method_offsets->_code_id;
|
|
+ if (_code_to_aot[code_id]._state == invalid) {
|
|
+ continue; // skip AOT methods slots which have been invalidated
|
|
+ }
|
|
+ AOTMethodData* method_data = &methods_data[i];
|
|
+ const char* aot_name = _metaspace_names + method_offsets->_name_offset;
|
|
+ method_data->_name = aot_name;
|
|
+ method_data->_code = _code_space + method_offsets->_code_offset;
|
|
+ method_data->_meta = (aot_metadata*)(_method_metadata + method_offsets->_meta_offset);
|
|
+ method_data->_metadata_table = (address)_metadata_got + method_offsets->_metadata_got_offset;
|
|
+ method_data->_metadata_size = method_offsets->_metadata_got_size;
|
|
+ // aot_name format: "<u2_size>Ljava/lang/ThreadGroup;<u2_size>addUnstarted<u2_size>()V"
|
|
+ int klass_len = Bytes::get_Java_u2((address)aot_name);
|
|
+ const char* method_name = aot_name + 2 + klass_len;
|
|
+ Method* m = AOTCodeHeap::find_method(ik, THREAD, method_name);
|
|
+ methodHandle mh(THREAD, m);
|
|
+ if (mh->code() != NULL) { // Does it have already compiled code?
|
|
+ continue; // Don't overwrite
|
|
+ }
|
|
+ publish_aot(mh, method_data, code_id);
|
|
+ }
|
|
+ }
|
|
+ return true;
|
|
+}
|
|
+
|
|
+AOTCompiledMethod* AOTCodeHeap::next_in_use_at(int start) const {
|
|
+ for (int index = start; index < _method_count; index++) {
|
|
+ if (_code_to_aot[index]._state != in_use) {
|
|
+ continue; // Skip uninitialized entries.
|
|
+ }
|
|
+ AOTCompiledMethod* aot = _code_to_aot[index]._aot;
|
|
+ return aot;
|
|
+ }
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+void* AOTCodeHeap::first() const {
|
|
+ return next_in_use_at(0);
|
|
+}
|
|
+
|
|
+void* AOTCodeHeap::next(void* p) const {
|
|
+ AOTCompiledMethod *aot = (AOTCompiledMethod *)p;
|
|
+ int next_index = aot->method_index() + 1;
|
|
+ assert(next_index <= _method_count, "");
|
|
+ if (next_index == _method_count) {
|
|
+ return NULL;
|
|
+ }
|
|
+ return next_in_use_at(next_index);
|
|
+}
|
|
+
|
|
+void* AOTCodeHeap::find_start(void* p) const {
|
|
+ if (!contains(p)) {
|
|
+ return NULL;
|
|
+ }
|
|
+ size_t offset = pointer_delta(p, low_boundary(), 1);
|
|
+ // Use segments table
|
|
+ size_t seg_idx = offset / _lib->config()->_codeSegmentSize;
|
|
+ if ((int)(_code_segments[seg_idx]) == 0xff) {
|
|
+ return NULL;
|
|
+ }
|
|
+ while (_code_segments[seg_idx] > 0) {
|
|
+ seg_idx -= (int)_code_segments[seg_idx];
|
|
+ }
|
|
+ int code_offset = (int)seg_idx * _lib->config()->_codeSegmentSize;
|
|
+ int aot_index = *(int*)(_code_space + code_offset);
|
|
+ AOTCompiledMethod* aot = _code_to_aot[aot_index]._aot;
|
|
+ assert(aot != NULL, "should find registered aot method");
|
|
+ return aot;
|
|
+}
|
|
+
|
|
+AOTCompiledMethod* AOTCodeHeap::find_aot(address p) const {
|
|
+ assert(contains(p), "should be here");
|
|
+ return (AOTCompiledMethod *)find_start(p);
|
|
+}
|
|
+
|
|
+CodeBlob* AOTCodeHeap::find_blob_unsafe(void* start) const {
|
|
+ return (CodeBlob*)AOTCodeHeap::find_start(start);
|
|
+}
|
|
+
|
|
+void AOTCodeHeap::oops_do(OopClosure* f) {
|
|
+ for (int i = 0; i < _oop_got_size; i++) {
|
|
+ oop* p = &_oop_got[i];
|
|
+ if (*p == NULL) continue; // skip non-oops
|
|
+ f->do_oop(p);
|
|
+ }
|
|
+ for (int index = 0; index < _method_count; index++) {
|
|
+ if (_code_to_aot[index]._state != in_use) {
|
|
+ continue; // Skip uninitialized entries.
|
|
+ }
|
|
+ AOTCompiledMethod* aot = _code_to_aot[index]._aot;
|
|
+ aot->do_oops(f);
|
|
+ }
|
|
+}
|
|
+
|
|
+// Scan only klasses_got cells which should have only Klass*,
|
|
+// metadata_got cells are scanned only for alive AOT methods
|
|
+// by AOTCompiledMethod::metadata_do().
|
|
+void AOTCodeHeap::got_metadata_do(MetadataClosure* f) {
|
|
+ for (int i = 1; i < _klasses_got_size; i++) {
|
|
+ Metadata** p = &_klasses_got[i];
|
|
+ Metadata* md = *p;
|
|
+ if (md == NULL) continue; // skip non-oops
|
|
+ if (Metaspace::contains(md)) {
|
|
+ f->do_metadata(md);
|
|
+ } else {
|
|
+ intptr_t meta = (intptr_t)md;
|
|
+ fatal("Invalid value in _klasses_got[%d] = " INTPTR_FORMAT, i, meta);
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+void AOTCodeHeap::cleanup_inline_caches() {
|
|
+ for (int index = 0; index < _method_count; index++) {
|
|
+ if (_code_to_aot[index]._state != in_use) {
|
|
+ continue; // Skip uninitialized entries.
|
|
+ }
|
|
+ AOTCompiledMethod* aot = _code_to_aot[index]._aot;
|
|
+ aot->cleanup_inline_caches(false);
|
|
+ }
|
|
+}
|
|
+
|
|
+#ifdef ASSERT
|
|
+int AOTCodeHeap::verify_icholder_relocations() {
|
|
+ int count = 0;
|
|
+ for (int index = 0; index < _method_count; index++) {
|
|
+ if (_code_to_aot[index]._state != in_use) {
|
|
+ continue; // Skip uninitialized entries.
|
|
+ }
|
|
+ AOTCompiledMethod* aot = _code_to_aot[index]._aot;
|
|
+ count += aot->verify_icholder_relocations();
|
|
+ }
|
|
+ return count;
|
|
+}
|
|
+#endif
|
|
+
|
|
+void AOTCodeHeap::metadata_do(MetadataClosure* f) {
|
|
+ for (int index = 0; index < _method_count; index++) {
|
|
+ if (_code_to_aot[index]._state != in_use) {
|
|
+ continue; // Skip uninitialized entries.
|
|
+ }
|
|
+ AOTCompiledMethod* aot = _code_to_aot[index]._aot;
|
|
+ if (aot->_is_alive()) {
|
|
+ aot->metadata_do(f);
|
|
+ }
|
|
+ }
|
|
+ // Scan klasses_got cells.
|
|
+ got_metadata_do(f);
|
|
+}
|
|
+
|
|
+bool AOTCodeHeap::reconcile_dynamic_klass(AOTCompiledMethod *caller, InstanceKlass* holder, int index, Klass *dyno_klass, const char *descriptor1, const char *descriptor2) {
|
|
+ const char * const descriptors[2] = {descriptor1, descriptor2};
|
|
+ JavaThread *thread = JavaThread::current();
|
|
+ ResourceMark rm(thread);
|
|
+
|
|
+ AOTKlassData* holder_data = find_klass(holder);
|
|
+ vmassert(holder_data != NULL, "klass %s not found", holder->signature_name());
|
|
+ vmassert(is_dependent_method(holder, caller), "sanity");
|
|
+
|
|
+ AOTKlassData* dyno_data = NULL;
|
|
+ bool adapter_failed = false;
|
|
+ char buf[64];
|
|
+ int descriptor_index = 0;
|
|
+ // descriptors[0] specific name ("adapter:<method_id>") for matching
|
|
+ // descriptors[1] fall-back name ("adapter") for depdencies
|
|
+ while (descriptor_index < 2) {
|
|
+ const char *descriptor = descriptors[descriptor_index];
|
|
+ if (descriptor == NULL) {
|
|
+ break;
|
|
+ }
|
|
+ jio_snprintf(buf, sizeof buf, "%s<%d:%d>", descriptor, holder_data->_class_id, index);
|
|
+ dyno_data = find_klass(buf);
|
|
+ if (dyno_data != NULL) {
|
|
+ break;
|
|
+ }
|
|
+ // If match failed then try fall-back for dependencies
|
|
+ ++descriptor_index;
|
|
+ adapter_failed = true;
|
|
+ }
|
|
+
|
|
+ if (dyno_data == NULL && dyno_klass == NULL) {
|
|
+ // all is well, no (appendix) at compile-time, and still none
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ if (dyno_data == NULL) {
|
|
+ // no (appendix) at build-time, but now there is
|
|
+ sweep_dependent_methods(holder_data);
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ if (adapter_failed) {
|
|
+ // adapter method mismatch
|
|
+ sweep_dependent_methods(holder_data);
|
|
+ sweep_dependent_methods(dyno_data);
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ if (dyno_klass == NULL) {
|
|
+ // (appendix) at build-time, none now
|
|
+ sweep_dependent_methods(holder_data);
|
|
+ sweep_dependent_methods(dyno_data);
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ // TODO: support array appendix object
|
|
+ if (!dyno_klass->is_instance_klass()) {
|
|
+ sweep_dependent_methods(holder_data);
|
|
+ sweep_dependent_methods(dyno_data);
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ InstanceKlass* dyno = InstanceKlass::cast(dyno_klass);
|
|
+
|
|
+ if (!dyno->is_hidden()) {
|
|
+ if (_klasses_got[dyno_data->_got_index] != dyno) {
|
|
+ // compile-time class different from runtime class, fail and deoptimize
|
|
+ sweep_dependent_methods(holder_data);
|
|
+ sweep_dependent_methods(dyno_data);
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ if (dyno->is_initialized()) {
|
|
+ _klasses_got[dyno_data->_got_index - 1] = dyno;
|
|
+ }
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ // TODO: support anonymous supers
|
|
+ if (!dyno->supers_have_passed_fingerprint_checks() || dyno->get_stored_fingerprint() != dyno_data->_fingerprint) {
|
|
+ NOT_PRODUCT( aot_klasses_fp_miss++; )
|
|
+ log_trace(aot, class, fingerprint)("class %s%s has bad fingerprint in %s tid=" INTPTR_FORMAT,
|
|
+ dyno->internal_name(), dyno->is_shared() ? " (shared)" : "",
|
|
+ _lib->name(), p2i(thread));
|
|
+ sweep_dependent_methods(holder_data);
|
|
+ sweep_dependent_methods(dyno_data);
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ _klasses_got[dyno_data->_got_index] = dyno;
|
|
+ if (dyno->is_initialized()) {
|
|
+ _klasses_got[dyno_data->_got_index - 1] = dyno;
|
|
+ }
|
|
+
|
|
+ // TODO: hook up any AOT code
|
|
+ // load_klass_data(dyno_data, thread);
|
|
+ return true;
|
|
+}
|
|
+
|
|
+bool AOTCodeHeap::reconcile_dynamic_method(AOTCompiledMethod *caller, InstanceKlass* holder, int index, Method *adapter_method) {
|
|
+ InstanceKlass *adapter_klass = adapter_method->method_holder();
|
|
+ char buf[64];
|
|
+ jio_snprintf(buf, sizeof buf, "adapter:%d", adapter_method->method_idnum());
|
|
+ if (!reconcile_dynamic_klass(caller, holder, index, adapter_klass, buf, "adapter")) {
|
|
+ return false;
|
|
+ }
|
|
+ return true;
|
|
+}
|
|
+
|
|
+bool AOTCodeHeap::reconcile_dynamic_invoke(AOTCompiledMethod* caller, InstanceKlass* holder, int index, Method* adapter_method, Klass *appendix_klass) {
|
|
+ if (!reconcile_dynamic_klass(caller, holder, index, appendix_klass, "appendix")) {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ if (!reconcile_dynamic_method(caller, holder, index, adapter_method)) {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ return true;
|
|
+}
|
|
diff --git a/src/hotspot/share/aot/aotCodeHeap.hpp b/src/hotspot/share/aot/aotCodeHeap.hpp
|
|
new file mode 100644
|
|
index 000000000..40c187ec7
|
|
--- /dev/null
|
|
+++ b/src/hotspot/share/aot/aotCodeHeap.hpp
|
|
@@ -0,0 +1,310 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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.
|
|
+ */
|
|
+
|
|
+#ifndef SHARE_AOT_AOTCODEHEAP_HPP
|
|
+#define SHARE_AOT_AOTCODEHEAP_HPP
|
|
+
|
|
+#include "aot/aotCompiledMethod.hpp"
|
|
+#include "classfile/symbolTable.hpp"
|
|
+//#include "metaprogramming/integralConstant.hpp"
|
|
+#include "oops/metadata.hpp"
|
|
+#include "oops/method.hpp"
|
|
+
|
|
+enum CodeState {
|
|
+ not_set = 0, // _aot fields is not set yet
|
|
+ in_use = 1, // _aot field is set to corresponding AOTCompiledMethod
|
|
+ invalid = 2 // AOT code is invalidated because dependencies failed
|
|
+};
|
|
+
|
|
+typedef struct {
|
|
+ AOTCompiledMethod* _aot;
|
|
+ CodeState _state; // State change cases: not_set->in_use, not_set->invalid
|
|
+} CodeToAMethod;
|
|
+
|
|
+class ClassLoaderData;
|
|
+
|
|
+class AOTClass {
|
|
+public:
|
|
+ ClassLoaderData* _classloader;
|
|
+};
|
|
+
|
|
+typedef struct {
|
|
+ int _name_offset;
|
|
+ int _code_offset;
|
|
+ int _meta_offset;
|
|
+ int _metadata_got_offset;
|
|
+ int _metadata_got_size;
|
|
+ int _code_id;
|
|
+} AOTMethodOffsets;
|
|
+
|
|
+typedef struct {
|
|
+ const char* _name;
|
|
+ address _code;
|
|
+ aot_metadata* _meta;
|
|
+ jlong* _state_adr;
|
|
+ address _metadata_table;
|
|
+ int _metadata_size;
|
|
+} AOTMethodData;
|
|
+
|
|
+typedef struct {
|
|
+ int _got_index;
|
|
+ int _class_id;
|
|
+ int _compiled_methods_offset;
|
|
+ int _dependent_methods_offset;
|
|
+ uint64_t _fingerprint;
|
|
+} AOTKlassData;
|
|
+
|
|
+typedef struct {
|
|
+ int _version;
|
|
+ int _class_count;
|
|
+ int _method_count;
|
|
+ int _klasses_got_size;
|
|
+ int _metadata_got_size;
|
|
+ int _oop_got_size;
|
|
+ int _jvm_version_offset;
|
|
+
|
|
+ enum {
|
|
+ AOT_SHARED_VERSION = 1
|
|
+ };
|
|
+} AOTHeader;
|
|
+
|
|
+typedef struct {
|
|
+ enum { CONFIG_SIZE = 7 * jintSize + 9 };
|
|
+ // 7 int values
|
|
+ int _config_size;
|
|
+ int _narrowOopShift;
|
|
+ int _narrowKlassShift;
|
|
+ int _contendedPaddingWidth;
|
|
+ int _objectAlignment;
|
|
+ int _codeSegmentSize;
|
|
+ int _gc;
|
|
+ // byte[9] array map to boolean values here
|
|
+ bool _debug_VM;
|
|
+ bool _useCompressedOops;
|
|
+ bool _useCompressedClassPointers;
|
|
+ bool _useTLAB;
|
|
+ bool _useBiasedLocking;
|
|
+ bool _tieredAOT;
|
|
+ bool _enableContended;
|
|
+ bool _restrictContended;
|
|
+ bool _omitAssertions;
|
|
+} AOTConfiguration;
|
|
+
|
|
+class AOTLib : public CHeapObj<mtCode> {
|
|
+ static bool _narrow_oop_shift_initialized;
|
|
+ static int _narrow_oop_shift;
|
|
+ static int _narrow_klass_shift;
|
|
+
|
|
+ bool _valid;
|
|
+ void* _dl_handle;
|
|
+ const int _dso_id;
|
|
+ const char* _name;
|
|
+ // VM configuration during AOT compilation
|
|
+ AOTConfiguration* _config;
|
|
+ AOTHeader* _header;
|
|
+
|
|
+ void handle_config_error(const char* format, ...) ATTRIBUTE_PRINTF(2, 3);
|
|
+public:
|
|
+ AOTLib(void* handle, const char* name, int dso_id);
|
|
+ virtual ~AOTLib();
|
|
+ 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; }
|
|
+
|
|
+ bool is_valid() const {
|
|
+ return _valid;
|
|
+ }
|
|
+ const char* name() const {
|
|
+ return _name;
|
|
+ }
|
|
+ void* dl_handle() const {
|
|
+ return _dl_handle;
|
|
+ }
|
|
+ int id() const {
|
|
+ return _dso_id;
|
|
+ }
|
|
+ AOTHeader* header() const {
|
|
+ return _header;
|
|
+ }
|
|
+ AOTConfiguration* config() const {
|
|
+ return _config;
|
|
+ }
|
|
+ void verify_config();
|
|
+ void verify_flag(bool aot_flag, bool flag, const char* name);
|
|
+ void verify_flag(int aot_flag, int flag, const char* name);
|
|
+
|
|
+ address load_symbol(const char *name);
|
|
+};
|
|
+
|
|
+
|
|
+class AOTCodeHeap : public CodeHeap {
|
|
+ AOTLib* _lib;
|
|
+ int _aot_id;
|
|
+
|
|
+ int _class_count;
|
|
+ int _method_count;
|
|
+ AOTClass* _classes;
|
|
+ CodeToAMethod* _code_to_aot;
|
|
+
|
|
+ address _code_space;
|
|
+ address _code_segments;
|
|
+ jlong* _method_state;
|
|
+
|
|
+
|
|
+ // Collect metaspace info: names -> address in .got section
|
|
+ const char* _metaspace_names;
|
|
+ address _method_metadata;
|
|
+
|
|
+ address _methods_offsets;
|
|
+ address _klasses_offsets;
|
|
+ address _dependencies;
|
|
+
|
|
+ Metadata** _klasses_got;
|
|
+ Metadata** _metadata_got;
|
|
+ oop* _oop_got;
|
|
+
|
|
+ int _klasses_got_size;
|
|
+ int _metadata_got_size;
|
|
+ int _oop_got_size;
|
|
+
|
|
+ // Collect stubs info
|
|
+ int* _stubs_offsets;
|
|
+
|
|
+ bool _lib_symbols_initialized;
|
|
+
|
|
+ void adjust_boundaries(AOTCompiledMethod* method) {
|
|
+ char* low = (char*)method->code_begin();
|
|
+ if (low < low_boundary()) {
|
|
+ _memory.set_low_boundary(low);
|
|
+ _memory.set_low(low);
|
|
+ }
|
|
+ char* high = (char *)method->code_end();
|
|
+ if (high > high_boundary()) {
|
|
+ _memory.set_high_boundary(high);
|
|
+ _memory.set_high(high);
|
|
+ }
|
|
+ assert(_method_count > 0, "methods count should be set already");
|
|
+ }
|
|
+
|
|
+ void register_stubs();
|
|
+
|
|
+ void link_shared_runtime_symbols();
|
|
+ void link_stub_routines_symbols();
|
|
+ void link_os_symbols();
|
|
+ void link_graal_runtime_symbols();
|
|
+
|
|
+ void link_global_lib_symbols();
|
|
+ void link_klass(const Klass* klass);
|
|
+ void link_known_klasses();
|
|
+ void publish_aot(const methodHandle& mh, AOTMethodData* method_data, int code_id);
|
|
+
|
|
+
|
|
+ AOTCompiledMethod* next_in_use_at(int index) const;
|
|
+
|
|
+ // Find klass in SystemDictionary for aot metadata.
|
|
+ static Klass* lookup_klass(const char* name, int len, const Method* method, Thread* THREAD);
|
|
+public:
|
|
+ AOTCodeHeap(AOTLib* lib);
|
|
+ virtual ~AOTCodeHeap();
|
|
+
|
|
+ AOTCompiledMethod* find_aot(address p) const;
|
|
+
|
|
+ virtual void* find_start(void* p) const;
|
|
+ virtual CodeBlob* find_blob_unsafe(void* start) const;
|
|
+ virtual void* first() const;
|
|
+ virtual void* next(void *p) const;
|
|
+
|
|
+ AOTKlassData* find_klass(InstanceKlass* ik);
|
|
+ bool load_klass_data(InstanceKlass* ik, TRAPS);
|
|
+ Klass* get_klass_from_got(const char* klass_name, int klass_len, const Method* method);
|
|
+
|
|
+ bool is_dependent_method(Klass* dependee, AOTCompiledMethod* aot);
|
|
+ void mark_evol_dependent_methods(InstanceKlass* dependee);
|
|
+
|
|
+ const char* get_name_at(int offset) {
|
|
+ return _metaspace_names + offset;
|
|
+ }
|
|
+
|
|
+
|
|
+ void oops_do(OopClosure* f);
|
|
+ void metadata_do(MetadataClosure* f);
|
|
+ void got_metadata_do(MetadataClosure* f);
|
|
+
|
|
+#ifdef ASSERT
|
|
+ bool got_contains(Metadata **p) {
|
|
+ return (p >= &_metadata_got[0] && p < &_metadata_got[_metadata_got_size]) ||
|
|
+ (p >= &_klasses_got[0] && p < &_klasses_got[_klasses_got_size]);
|
|
+ }
|
|
+#endif
|
|
+
|
|
+ int dso_id() const { return _lib->id(); }
|
|
+ int aot_id() const { return _aot_id; }
|
|
+
|
|
+ int method_count() { return _method_count; }
|
|
+
|
|
+ AOTCompiledMethod* get_code_desc_at_index(int index) {
|
|
+ if (index < _method_count && _code_to_aot[index]._state == in_use) {
|
|
+ AOTCompiledMethod* m = _code_to_aot[index]._aot;
|
|
+ assert(m != NULL, "AOT method should be set");
|
|
+ if (!m->is_runtime_stub()) {
|
|
+ return m;
|
|
+ }
|
|
+ }
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ static Method* find_method(Klass* klass, TRAPS, const char* method_name);
|
|
+
|
|
+ void cleanup_inline_caches();
|
|
+
|
|
+ DEBUG_ONLY( int verify_icholder_relocations(); )
|
|
+
|
|
+ void alive_methods_do(void f(CompiledMethod* nm));
|
|
+
|
|
+#ifndef PRODUCT
|
|
+ static int klasses_seen;
|
|
+ static int aot_klasses_found;
|
|
+ static int aot_klasses_fp_miss;
|
|
+ static int aot_klasses_cl_miss;
|
|
+ static int aot_methods_found;
|
|
+
|
|
+ static void print_statistics();
|
|
+#endif
|
|
+
|
|
+ bool reconcile_dynamic_invoke(AOTCompiledMethod* caller, InstanceKlass* holder, int index, Method* adapter_method, Klass *appendix_klass);
|
|
+
|
|
+private:
|
|
+ AOTKlassData* find_klass(const char* name);
|
|
+
|
|
+ void sweep_dependent_methods(int* indexes, int methods_cnt);
|
|
+ void sweep_dependent_methods(AOTKlassData* klass_data);
|
|
+ void sweep_dependent_methods(InstanceKlass* ik);
|
|
+ void sweep_method(AOTCompiledMethod* aot);
|
|
+
|
|
+ bool reconcile_dynamic_klass(AOTCompiledMethod *caller, InstanceKlass* holder, int index, Klass *dyno, const char *descriptor1, const char *descriptor2 = NULL);
|
|
+
|
|
+ bool reconcile_dynamic_method(AOTCompiledMethod *caller, InstanceKlass* holder, int index, Method *adapter_method);
|
|
+
|
|
+};
|
|
+
|
|
+#endif // SHARE_AOT_AOTCODEHEAP_HPP
|
|
diff --git a/src/hotspot/share/aot/aotCompiledMethod.cpp b/src/hotspot/share/aot/aotCompiledMethod.cpp
|
|
new file mode 100644
|
|
index 000000000..ec7a501ec
|
|
--- /dev/null
|
|
+++ b/src/hotspot/share/aot/aotCompiledMethod.cpp
|
|
@@ -0,0 +1,415 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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.
|
|
+ */
|
|
+
|
|
+#include "precompiled.hpp"
|
|
+
|
|
+#include "aot/aotCodeHeap.hpp"
|
|
+#include "aot/aotLoader.hpp"
|
|
+#include "aot/compiledIC_aot.hpp"
|
|
+#include "code/codeCache.hpp"
|
|
+#include "code/compiledIC.hpp"
|
|
+#include "code/nativeInst.hpp"
|
|
+#include "compiler/compilerOracle.hpp"
|
|
+#include "gc/shared/cardTableBarrierSet.hpp"
|
|
+#include "gc/shared/collectedHeap.hpp"
|
|
+#include "oops/klass.inline.hpp"
|
|
+#include "oops/method.inline.hpp"
|
|
+#include "runtime/frame.inline.hpp"
|
|
+#include "runtime/handles.inline.hpp"
|
|
+#include "runtime/java.hpp"
|
|
+#include "runtime/orderAccess.hpp"
|
|
+#include "runtime/os.hpp"
|
|
+#include "runtime/safepointVerifiers.hpp"
|
|
+#include "runtime/sharedRuntime.hpp"
|
|
+#include "utilities/sizes.hpp"
|
|
+#include "utilities/xmlstream.hpp"
|
|
+
|
|
+#include <stdio.h>
|
|
+
|
|
+address* AOTCompiledMethod::orig_pc_addr(const frame* fr) {
|
|
+ return (address*) ((address)fr->unextended_sp() + _meta->orig_pc_offset());
|
|
+}
|
|
+
|
|
+oop AOTCompiledMethod::oop_at(int index) const {
|
|
+ if (index == 0) { // 0 is reserved
|
|
+ return NULL;
|
|
+ }
|
|
+ Metadata** entry = _metadata_got + (index - 1);
|
|
+ intptr_t meta = (intptr_t)*entry;
|
|
+ if ((meta & 1) == 1) {
|
|
+ // already resolved
|
|
+ Klass* k = (Klass*)(meta & ~1);
|
|
+ return k->java_mirror();
|
|
+ }
|
|
+ // The entry is string which we need to resolve.
|
|
+ const char* meta_name = _heap->get_name_at((int)meta);
|
|
+ int klass_len = Bytes::get_Java_u2((address)meta_name);
|
|
+ const char* klass_name = meta_name + 2;
|
|
+ // Quick check the current method's holder.
|
|
+ Klass* k = _method->method_holder();
|
|
+
|
|
+ ResourceMark rm; // for signature_name()
|
|
+ if (strncmp(k->signature_name(), klass_name, klass_len) != 0) { // Does not match?
|
|
+ // Search klass in got cells in DSO which have this compiled method.
|
|
+ k = _heap->get_klass_from_got(klass_name, klass_len, _method);
|
|
+ }
|
|
+ int method_name_len = Bytes::get_Java_u2((address)klass_name + klass_len);
|
|
+ guarantee(method_name_len == 0, "only klass is expected here");
|
|
+ meta = ((intptr_t)k) | 1;
|
|
+ *entry = (Metadata*)meta; // Should be atomic on x64
|
|
+ return k->java_mirror();
|
|
+}
|
|
+
|
|
+Metadata* AOTCompiledMethod::metadata_at(int index) const {
|
|
+ if (index == 0) { // 0 is reserved
|
|
+ return NULL;
|
|
+ }
|
|
+ assert(index - 1 < _metadata_size, "");
|
|
+ {
|
|
+ Metadata** entry = _metadata_got + (index - 1);
|
|
+ intptr_t meta = (intptr_t)*entry;
|
|
+ if ((meta & 1) == 1) {
|
|
+ // already resolved
|
|
+ Metadata *m = (Metadata*)(meta & ~1);
|
|
+ return m;
|
|
+ }
|
|
+ // The entry is string which we need to resolve.
|
|
+ const char* meta_name = _heap->get_name_at((int)meta);
|
|
+ int klass_len = Bytes::get_Java_u2((address)meta_name);
|
|
+ const char* klass_name = meta_name + 2;
|
|
+ // Quick check the current method's holder.
|
|
+ Klass* k = _method->method_holder();
|
|
+ bool klass_matched = true;
|
|
+
|
|
+ ResourceMark rm; // for signature_name() and find_method()
|
|
+ if (strncmp(k->signature_name(), klass_name, klass_len) != 0) { // Does not match?
|
|
+ // Search klass in got cells in DSO which have this compiled method.
|
|
+ k = _heap->get_klass_from_got(klass_name, klass_len, _method);
|
|
+ klass_matched = false;
|
|
+ }
|
|
+ int method_name_len = Bytes::get_Java_u2((address)klass_name + klass_len);
|
|
+ if (method_name_len == 0) { // Array or Klass name only?
|
|
+ meta = ((intptr_t)k) | 1;
|
|
+ *entry = (Metadata*)meta; // Should be atomic on x64
|
|
+ return (Metadata*)k;
|
|
+ } else { // Method
|
|
+ // Quick check the current method's name.
|
|
+ Method* m = _method;
|
|
+ int signature_len = Bytes::get_Java_u2((address)klass_name + klass_len + 2 + method_name_len);
|
|
+ int full_len = 2 + klass_len + 2 + method_name_len + 2 + signature_len;
|
|
+ if (!klass_matched || memcmp(_name, meta_name, full_len) != 0) { // Does not match?
|
|
+ JavaThread* THREAD = JavaThread::current();
|
|
+ const char* method_name = klass_name + klass_len;
|
|
+ m = AOTCodeHeap::find_method(k, THREAD, method_name);
|
|
+ }
|
|
+ meta = ((intptr_t)m) | 1;
|
|
+ *entry = (Metadata*)meta; // Should be atomic on x64
|
|
+ return (Metadata*)m;
|
|
+ }
|
|
+ }
|
|
+ ShouldNotReachHere(); return NULL;
|
|
+}
|
|
+
|
|
+void AOTCompiledMethod::do_unloading(bool unloading_occurred) {
|
|
+ unload_nmethod_caches(unloading_occurred);
|
|
+}
|
|
+
|
|
+bool AOTCompiledMethod::make_not_entrant_helper(int new_state) {
|
|
+ NoSafepointVerifier nsv;
|
|
+
|
|
+ {
|
|
+ // Enter critical section. Does not block for safepoint.
|
|
+ MutexLocker pl(CompiledMethod_lock, Mutex::_no_safepoint_check_flag);
|
|
+
|
|
+ if (*_state_adr == new_state) {
|
|
+ // another thread already performed this transition so nothing
|
|
+ // to do, but return false to indicate this.
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ // Change state
|
|
+ OrderAccess::storestore();
|
|
+ *_state_adr = new_state;
|
|
+
|
|
+ // Log the transition once
|
|
+ log_state_change();
|
|
+
|
|
+#if COMPILER1_OR_COMPILER2
|
|
+ // Remain non-entrant forever
|
|
+ if (new_state == not_entrant && method() != NULL) {
|
|
+ method()->set_aot_code(NULL);
|
|
+ }
|
|
+#endif // COMPILER1_OR_COMPILER2
|
|
+
|
|
+ // Remove AOTCompiledMethod from method.
|
|
+ if (method() != NULL) {
|
|
+ method()->unlink_code(this);
|
|
+ }
|
|
+ } // leave critical region under CompiledMethod_lock
|
|
+
|
|
+
|
|
+ if (TraceCreateZombies) {
|
|
+ ResourceMark m;
|
|
+ const char *new_state_str = (new_state == not_entrant) ? "not entrant" : "not used";
|
|
+ tty->print_cr("aot method <" INTPTR_FORMAT "> %s code made %s", p2i(this), this->method() ? this->method()->name_and_sig_as_C_string() : "null", new_state_str);
|
|
+ }
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+bool AOTCompiledMethod::make_entrant() {
|
|
+#if COMPILER1_OR_COMPILER2
|
|
+ assert(!method()->is_old(), "reviving evolved method!");
|
|
+
|
|
+ NoSafepointVerifier nsv;
|
|
+ {
|
|
+ // Enter critical section. Does not block for safepoint.
|
|
+ MutexLocker pl(CompiledMethod_lock, Mutex::_no_safepoint_check_flag);
|
|
+
|
|
+ if (*_state_adr == in_use || *_state_adr == not_entrant) {
|
|
+ // another thread already performed this transition so nothing
|
|
+ // to do, but return false to indicate this.
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ // Change state
|
|
+ OrderAccess::storestore();
|
|
+ *_state_adr = in_use;
|
|
+
|
|
+ // Log the transition once
|
|
+ log_state_change();
|
|
+ } // leave critical region under CompiledMethod_lock
|
|
+
|
|
+
|
|
+ if (TraceCreateZombies) {
|
|
+ ResourceMark m;
|
|
+ tty->print_cr("aot method <" INTPTR_FORMAT "> %s code made entrant", p2i(this), this->method() ? this->method()->name_and_sig_as_C_string() : "null");
|
|
+ }
|
|
+
|
|
+ return true;
|
|
+#else
|
|
+ return false;
|
|
+#endif // COMPILER1_OR_COMPILER2
|
|
+}
|
|
+
|
|
+// Iterate over metadata calling this function. Used by RedefineClasses
|
|
+// Copied from nmethod::metadata_do
|
|
+void AOTCompiledMethod::metadata_do(MetadataClosure* f) {
|
|
+ address low_boundary = verified_entry_point();
|
|
+ {
|
|
+ // Visit all immediate references that are embedded in the instruction stream.
|
|
+ RelocIterator iter(this, low_boundary);
|
|
+ while (iter.next()) {
|
|
+ if (iter.type() == relocInfo::metadata_type ) {
|
|
+ metadata_Relocation* r = iter.metadata_reloc();
|
|
+ // In this metadata, we must only follow those metadatas directly embedded in
|
|
+ // the code. Other metadatas (oop_index>0) are seen as part of
|
|
+ // the metadata section below.
|
|
+ assert(1 == (r->metadata_is_immediate()) +
|
|
+ (r->metadata_addr() >= metadata_begin() && r->metadata_addr() < metadata_end()),
|
|
+ "metadata must be found in exactly one place");
|
|
+ if (r->metadata_is_immediate() && r->metadata_value() != NULL) {
|
|
+ Metadata* md = r->metadata_value();
|
|
+ if (md != _method) f->do_metadata(md);
|
|
+ }
|
|
+ } else if (iter.type() == relocInfo::virtual_call_type) {
|
|
+ ResourceMark rm;
|
|
+ // Check compiledIC holders associated with this nmethod
|
|
+ CompiledIC *ic = CompiledIC_at(&iter);
|
|
+ if (ic->is_icholder_call()) {
|
|
+ CompiledICHolder* cichk = ic->cached_icholder();
|
|
+ f->do_metadata(cichk->holder_metadata());
|
|
+ f->do_metadata(cichk->holder_klass());
|
|
+ } else {
|
|
+ // Get Klass* or NULL (if value is -1) from GOT cell of virtual call PLT stub.
|
|
+ Metadata* ic_oop = ic->cached_metadata();
|
|
+ if (ic_oop != NULL) {
|
|
+ f->do_metadata(ic_oop);
|
|
+ }
|
|
+ }
|
|
+ } else if (iter.type() == relocInfo::static_call_type ||
|
|
+ iter.type() == relocInfo::opt_virtual_call_type) {
|
|
+ // Check Method* in AOT c2i stub for other calls.
|
|
+ Metadata* meta = (Metadata*)nativeLoadGot_at(nativePltCall_at(iter.addr())->plt_c2i_stub())->data();
|
|
+ if (meta != NULL) {
|
|
+ f->do_metadata(meta);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // Visit the metadata section
|
|
+ for (Metadata** p = metadata_begin(); p < metadata_end(); p++) {
|
|
+ Metadata* m = *p;
|
|
+
|
|
+ intptr_t meta = (intptr_t)m;
|
|
+ if ((meta & 1) == 1) {
|
|
+ // already resolved
|
|
+ m = (Metadata*)(meta & ~1);
|
|
+ } else {
|
|
+ continue;
|
|
+ }
|
|
+ assert(Metaspace::contains(m), "");
|
|
+ f->do_metadata(m);
|
|
+ }
|
|
+
|
|
+ // Visit metadata not embedded in the other places.
|
|
+ if (_method != NULL) f->do_metadata(_method);
|
|
+}
|
|
+
|
|
+void AOTCompiledMethod::print() const {
|
|
+ print_on(tty, "AOTCompiledMethod");
|
|
+}
|
|
+
|
|
+void AOTCompiledMethod::print_on(outputStream* st) const {
|
|
+ print_on(st, "AOTCompiledMethod");
|
|
+}
|
|
+
|
|
+// Print out more verbose output usually for a newly created aot method.
|
|
+void AOTCompiledMethod::print_on(outputStream* st, const char* msg) const {
|
|
+ if (st != NULL) {
|
|
+ ttyLocker ttyl;
|
|
+ st->print("%7d ", (int) tty->time_stamp().milliseconds());
|
|
+ st->print("%4d ", _aot_id); // print compilation number
|
|
+ st->print(" aot[%2d]", _heap->dso_id());
|
|
+ // Stubs have _method == NULL
|
|
+ if (_method == NULL) {
|
|
+ st->print(" %s", _name);
|
|
+ } else {
|
|
+ ResourceMark m;
|
|
+ st->print(" %s", _method->name_and_sig_as_C_string());
|
|
+ }
|
|
+ if (Verbose) {
|
|
+ st->print(" entry at " INTPTR_FORMAT, p2i(_code));
|
|
+ }
|
|
+ if (msg != NULL) {
|
|
+ st->print(" %s", msg);
|
|
+ }
|
|
+ st->cr();
|
|
+ }
|
|
+}
|
|
+
|
|
+void AOTCompiledMethod::print_value_on(outputStream* st) const {
|
|
+ st->print("AOTCompiledMethod ");
|
|
+ print_on(st, NULL);
|
|
+}
|
|
+
|
|
+// Print a short set of xml attributes to identify this aot method. The
|
|
+// output should be embedded in some other element.
|
|
+void AOTCompiledMethod::log_identity(xmlStream* log) const {
|
|
+ log->print(" aot_id='%d'", _aot_id);
|
|
+ log->print(" aot='%2d'", _heap->dso_id());
|
|
+}
|
|
+
|
|
+void AOTCompiledMethod::log_state_change() const {
|
|
+ if (LogCompilation) {
|
|
+ ResourceMark m;
|
|
+ if (xtty != NULL) {
|
|
+ ttyLocker ttyl; // keep the following output all in one block
|
|
+ if (*_state_adr == not_entrant) {
|
|
+ xtty->begin_elem("make_not_entrant thread='" UINTX_FORMAT "'",
|
|
+ os::current_thread_id());
|
|
+ } else if (*_state_adr == not_used) {
|
|
+ xtty->begin_elem("make_not_used thread='" UINTX_FORMAT "'",
|
|
+ os::current_thread_id());
|
|
+ } else if (*_state_adr == in_use) {
|
|
+ xtty->begin_elem("make_entrant thread='" UINTX_FORMAT "'",
|
|
+ os::current_thread_id());
|
|
+ }
|
|
+ log_identity(xtty);
|
|
+ xtty->stamp();
|
|
+ xtty->end_elem();
|
|
+ }
|
|
+ }
|
|
+ if (PrintCompilation) {
|
|
+ ResourceMark m;
|
|
+ if (*_state_adr == not_entrant) {
|
|
+ print_on(tty, "made not entrant");
|
|
+ } else if (*_state_adr == not_used) {
|
|
+ print_on(tty, "made not used");
|
|
+ } else if (*_state_adr == in_use) {
|
|
+ print_on(tty, "made entrant");
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+NativeInstruction* PltNativeCallWrapper::get_load_instruction(virtual_call_Relocation* r) const {
|
|
+ return nativeLoadGot_at(_call->plt_load_got());
|
|
+}
|
|
+
|
|
+void PltNativeCallWrapper::verify_resolve_call(address dest) const {
|
|
+ CodeBlob* db = CodeCache::find_blob_unsafe(dest);
|
|
+ if (db == NULL) {
|
|
+ assert(dest == _call->plt_resolve_call(), "sanity");
|
|
+ }
|
|
+}
|
|
+
|
|
+void PltNativeCallWrapper::set_to_interpreted(const methodHandle& method, CompiledICInfo& info) {
|
|
+ assert(!info.to_aot(), "only for nmethod");
|
|
+ CompiledPltStaticCall* csc = CompiledPltStaticCall::at(instruction_address());
|
|
+ csc->set_to_interpreted(method, info.entry());
|
|
+}
|
|
+
|
|
+NativeCallWrapper* AOTCompiledMethod::call_wrapper_at(address call) const {
|
|
+ return new PltNativeCallWrapper((NativePltCall*) call);
|
|
+}
|
|
+
|
|
+NativeCallWrapper* AOTCompiledMethod::call_wrapper_before(address return_pc) const {
|
|
+ return new PltNativeCallWrapper(nativePltCall_before(return_pc));
|
|
+}
|
|
+
|
|
+CompiledStaticCall* AOTCompiledMethod::compiledStaticCall_at(Relocation* call_site) const {
|
|
+ return CompiledPltStaticCall::at(call_site);
|
|
+}
|
|
+
|
|
+CompiledStaticCall* AOTCompiledMethod::compiledStaticCall_at(address call_site) const {
|
|
+ return CompiledPltStaticCall::at(call_site);
|
|
+}
|
|
+
|
|
+CompiledStaticCall* AOTCompiledMethod::compiledStaticCall_before(address return_addr) const {
|
|
+ return CompiledPltStaticCall::before(return_addr);
|
|
+}
|
|
+
|
|
+address AOTCompiledMethod::call_instruction_address(address pc) const {
|
|
+ NativePltCall* pltcall = nativePltCall_before(pc);
|
|
+ return pltcall->instruction_address();
|
|
+}
|
|
+
|
|
+void AOTCompiledMethod::clear_inline_caches() {
|
|
+ assert(SafepointSynchronize::is_at_safepoint(), "cleaning of IC's only allowed at safepoint");
|
|
+ if (is_zombie()) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ ResourceMark rm;
|
|
+ RelocIterator iter(this);
|
|
+ while (iter.next()) {
|
|
+ iter.reloc()->clear_inline_cache();
|
|
+ if (iter.type() == relocInfo::opt_virtual_call_type) {
|
|
+ CompiledIC* cic = CompiledIC_at(&iter);
|
|
+ assert(cic->is_clean(), "!");
|
|
+ nativePltCall_at(iter.addr())->set_stub_to_clean();
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/src/hotspot/share/aot/aotCompiledMethod.hpp b/src/hotspot/share/aot/aotCompiledMethod.hpp
|
|
new file mode 100644
|
|
index 000000000..c9136a36a
|
|
--- /dev/null
|
|
+++ b/src/hotspot/share/aot/aotCompiledMethod.hpp
|
|
@@ -0,0 +1,320 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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.
|
|
+ */
|
|
+
|
|
+#ifndef SHARE_AOT_AOTCOMPILEDMETHOD_HPP
|
|
+#define SHARE_AOT_AOTCOMPILEDMETHOD_HPP
|
|
+
|
|
+#include "code/codeCache.hpp"
|
|
+#include "code/compiledIC.hpp"
|
|
+#include "code/compiledMethod.hpp"
|
|
+#include "code/pcDesc.hpp"
|
|
+#include "code/relocInfo.hpp"
|
|
+
|
|
+class AOTCodeHeap;
|
|
+
|
|
+class aot_metadata {
|
|
+private:
|
|
+ int _size;
|
|
+ int _code_size;
|
|
+ int _entry;
|
|
+ int _verified_entry;
|
|
+ int _exception_handler_offset;
|
|
+ int _deopt_handler_offset;
|
|
+ int _deopt_mh_handler_offset;
|
|
+ int _stubs_offset;
|
|
+ int _frame_size;
|
|
+ // location in frame (offset for sp) that deopt can store the original
|
|
+ // pc during a deopt.
|
|
+ int _orig_pc_offset;
|
|
+ int _unsafe_access;
|
|
+
|
|
+ int _pc_desc_begin;
|
|
+ int _scopes_begin;
|
|
+ int _reloc_begin;
|
|
+ int _exception_table_begin;
|
|
+ int _nul_chk_table_begin;
|
|
+ int _oopmap_begin;
|
|
+ address at_offset(size_t offset) const { return ((address) this) + offset; }
|
|
+public:
|
|
+ int code_size() const { return _code_size; }
|
|
+ int frame_size() const { return _frame_size / HeapWordSize; }
|
|
+ PcDesc *scopes_pcs_begin() const { return (PcDesc *) at_offset(_pc_desc_begin); }
|
|
+ PcDesc *scopes_pcs_end() const { return (PcDesc *) at_offset(_scopes_begin); }
|
|
+ address scopes_data_begin() const { return at_offset(_scopes_begin); }
|
|
+ address scopes_data_end() const { return at_offset(_reloc_begin); }
|
|
+ relocInfo* relocation_begin() const { return (relocInfo*) at_offset(_reloc_begin); }
|
|
+ relocInfo* relocation_end() const { return (relocInfo*) at_offset(_exception_table_begin); }
|
|
+ address handler_table_begin () const { return at_offset(_exception_table_begin); }
|
|
+ address handler_table_end() const { return at_offset(_nul_chk_table_begin); }
|
|
+
|
|
+ address nul_chk_table_begin() const { return at_offset(_nul_chk_table_begin); }
|
|
+ address nul_chk_table_end() const { return at_offset(_oopmap_begin); }
|
|
+
|
|
+ ImmutableOopMapSet* oopmap_set() const { return (ImmutableOopMapSet*) at_offset(_oopmap_begin); }
|
|
+
|
|
+ address consts_begin() const { return at_offset(_size); }
|
|
+ address consts_end() const { return at_offset(_size); }
|
|
+ int stub_offset() const { return _stubs_offset; }
|
|
+ int entry_offset() const { return _entry; }
|
|
+ int verified_entry_offset() const { return _verified_entry; }
|
|
+ int exception_handler_offset() const { return _exception_handler_offset; }
|
|
+ int deopt_handler_offset() const { return _deopt_handler_offset; }
|
|
+ int deopt_mh_handler_offset() const { return _deopt_mh_handler_offset; }
|
|
+ int orig_pc_offset() const { return _orig_pc_offset; }
|
|
+
|
|
+ int handler_table_size() const { return handler_table_end() - handler_table_begin(); }
|
|
+ int nul_chk_table_size() const { return nul_chk_table_end() - nul_chk_table_begin(); }
|
|
+ bool has_unsafe_access() const { return _unsafe_access != 0; }
|
|
+
|
|
+};
|
|
+
|
|
+/*
|
|
+ * Use this for AOTCompiledMethods since a lot of the fields in CodeBlob gets the same
|
|
+ * value when they come from AOT. code_begin == content_begin, etc... */
|
|
+class AOTCompiledMethodLayout : public CodeBlobLayout {
|
|
+public:
|
|
+ AOTCompiledMethodLayout(address code_begin, address code_end, address relocation_begin, address relocation_end) :
|
|
+ CodeBlobLayout(
|
|
+ code_begin, // code_begin
|
|
+ code_end, // code_end
|
|
+ code_begin, // content_begin
|
|
+ code_end, // content_end
|
|
+ code_end, // data_end
|
|
+ relocation_begin, // relocation_begin
|
|
+ relocation_end
|
|
+ ) {
|
|
+ }
|
|
+};
|
|
+
|
|
+class AOTCompiledMethod : public CompiledMethod, public CHeapObj<mtCode> {
|
|
+private:
|
|
+ address _code;
|
|
+ aot_metadata* _meta;
|
|
+ Metadata** _metadata_got;
|
|
+ jlong* _state_adr; // Address of cell to indicate aot method state (in_use or not_entrant)
|
|
+ AOTCodeHeap* _heap; // code heap which has this method
|
|
+ const char* _name; // For stub: "AOT Stub<name>" for stub,
|
|
+ // For nmethod: "<u2_size>Ljava/lang/ThreadGroup;<u2_size>addUnstarted<u2_size>()V"
|
|
+ const int _metadata_size; // size of _metadata_got
|
|
+ const int _aot_id;
|
|
+ const int _method_index;
|
|
+ oop _oop; // method()->method_holder()->klass_holder()
|
|
+
|
|
+ address* orig_pc_addr(const frame* fr);
|
|
+ bool make_not_entrant_helper(int new_state);
|
|
+
|
|
+ public:
|
|
+ using CHeapObj<mtCode>::operator new;
|
|
+ using CHeapObj<mtCode>::operator delete;
|
|
+
|
|
+ int method_index() const { return _method_index; }
|
|
+ void set_oop(oop o) { _oop = o; }
|
|
+
|
|
+ AOTCompiledMethod(address code, Method* method, aot_metadata* meta, address metadata_got, int metadata_size, jlong* state_adr, AOTCodeHeap* heap, const char* name, int method_index, int aot_id) :
|
|
+ CompiledMethod(method, name, compiler_jvmci, // AOT code is generated by JVMCI compiler
|
|
+ AOTCompiledMethodLayout(code, code + meta->code_size(), (address) meta->relocation_begin(), (address) meta->relocation_end()),
|
|
+ 0 /* frame_complete_offset */, meta->frame_size() /* frame_size */, meta->oopmap_set(), false /* caller_must_gc_arguments */),
|
|
+ _code(code),
|
|
+ _meta(meta),
|
|
+ _metadata_got((Metadata**) metadata_got),
|
|
+ _state_adr(state_adr),
|
|
+ _heap(heap),
|
|
+ _name(name),
|
|
+ _metadata_size(metadata_size),
|
|
+ _aot_id(aot_id),
|
|
+ _method_index(method_index) {
|
|
+
|
|
+ _is_far_code = CodeCache::is_far_target(code) ||
|
|
+ CodeCache::is_far_target(code + meta->code_size());
|
|
+ _exception_cache = NULL;
|
|
+
|
|
+ _scopes_data_begin = (address) _meta->scopes_data_begin();
|
|
+ _deopt_handler_begin = (address) _code + _meta->deopt_handler_offset();
|
|
+ if (_meta->deopt_mh_handler_offset() != -1) {
|
|
+ _deopt_mh_handler_begin = (address) _code + _meta->deopt_mh_handler_offset();
|
|
+ } else {
|
|
+ _deopt_mh_handler_begin = (address) this;
|
|
+ }
|
|
+
|
|
+ _pc_desc_container.reset_to(scopes_pcs_begin());
|
|
+
|
|
+ // Mark the AOTCompiledMethod as in_use
|
|
+ *_state_adr = nmethod::in_use;
|
|
+ set_has_unsafe_access(_meta->has_unsafe_access());
|
|
+ _oop = NULL;
|
|
+ }
|
|
+
|
|
+ virtual bool is_aot() const { return true; }
|
|
+ virtual bool is_runtime_stub() const { return is_aot_runtime_stub(); }
|
|
+
|
|
+ virtual bool is_compiled() const { return !is_aot_runtime_stub(); }
|
|
+
|
|
+ virtual bool is_locked_by_vm() const { return false; }
|
|
+
|
|
+ int state() const { return *_state_adr; }
|
|
+
|
|
+ // Non-virtual for speed
|
|
+ bool _is_alive() const { return state() < unloaded; }
|
|
+
|
|
+ virtual bool is_zombie() const { return state() == zombie; }
|
|
+ virtual bool is_unloaded() const { return state() == unloaded; }
|
|
+ virtual bool is_not_entrant() const { return state() == not_entrant ||
|
|
+ state() == not_used; }
|
|
+ virtual bool is_alive() const { return _is_alive(); }
|
|
+ virtual bool is_in_use() const { return state() == in_use; }
|
|
+
|
|
+ virtual bool is_unloading() { return false; }
|
|
+
|
|
+ address exception_begin() const { return (address) _code + _meta->exception_handler_offset(); }
|
|
+
|
|
+ virtual const char* name() const { return _name; }
|
|
+
|
|
+ virtual int compile_id() const { return _aot_id; }
|
|
+
|
|
+ void print_on(outputStream* st) const;
|
|
+ void print_on(outputStream* st, const char* msg) const;
|
|
+ void print() const;
|
|
+
|
|
+ virtual void print_value_on(outputStream *stream) const;
|
|
+ virtual void print_block_comment(outputStream *stream, address block_begin) const { }
|
|
+ virtual void verify() {}
|
|
+
|
|
+ virtual int comp_level() const { return CompLevel_aot; }
|
|
+ virtual address verified_entry_point() const { return _code + _meta->verified_entry_offset(); }
|
|
+ virtual void log_identity(xmlStream* stream) const;
|
|
+ virtual void log_state_change() const;
|
|
+ virtual bool make_entrant();
|
|
+ virtual bool make_not_entrant() { return make_not_entrant_helper(not_entrant); }
|
|
+ virtual bool make_not_used() { return make_not_entrant_helper(not_used); }
|
|
+ virtual address entry_point() const { return _code + _meta->entry_offset(); }
|
|
+ virtual bool make_zombie() { ShouldNotReachHere(); return false; }
|
|
+ virtual bool is_osr_method() const { return false; }
|
|
+ virtual int osr_entry_bci() const { ShouldNotReachHere(); return -1; }
|
|
+ // AOT compiled methods do not get into zombie state
|
|
+ virtual bool can_convert_to_zombie() { return false; }
|
|
+
|
|
+ virtual bool is_dependent_on_method(Method* dependee) { return true; }
|
|
+
|
|
+ virtual void clear_inline_caches();
|
|
+
|
|
+ virtual void print_pcs() {}
|
|
+
|
|
+ virtual address scopes_data_end() const { return _meta->scopes_data_end(); }
|
|
+
|
|
+ virtual oop oop_at(int index) const;
|
|
+ virtual Metadata* metadata_at(int index) const;
|
|
+
|
|
+ virtual PcDesc* scopes_pcs_begin() const { return _meta->scopes_pcs_begin(); }
|
|
+ virtual PcDesc* scopes_pcs_end() const { return _meta->scopes_pcs_end(); }
|
|
+
|
|
+ virtual address handler_table_begin() const { return _meta->handler_table_begin(); }
|
|
+ virtual address handler_table_end() const { return _meta->handler_table_end(); }
|
|
+
|
|
+ virtual address nul_chk_table_begin() const { return _meta->nul_chk_table_begin(); }
|
|
+ virtual address nul_chk_table_end() const { return _meta->nul_chk_table_end(); }
|
|
+
|
|
+ virtual address consts_begin() const { return _meta->consts_begin(); }
|
|
+ virtual address consts_end() const { return _meta->consts_end(); }
|
|
+
|
|
+ virtual address stub_begin() const { return code_begin() + _meta->stub_offset(); }
|
|
+ virtual address stub_end() const { return code_end(); }
|
|
+
|
|
+ virtual oop* oop_addr_at(int index) const { ShouldNotReachHere(); return NULL; }
|
|
+ virtual Metadata** metadata_addr_at(int index) const { ShouldNotReachHere(); return NULL; }
|
|
+
|
|
+ // Accessor/mutator for the original pc of a frame before a frame was deopted.
|
|
+ address get_original_pc(const frame* fr) { return *orig_pc_addr(fr); }
|
|
+ void set_original_pc(const frame* fr, address pc) { *orig_pc_addr(fr) = pc; }
|
|
+
|
|
+ virtual void metadata_do(MetadataClosure* f);
|
|
+
|
|
+ bool metadata_got_contains(Metadata **p) {
|
|
+ return p >= &_metadata_got[0] && p < &_metadata_got[_metadata_size];
|
|
+ }
|
|
+
|
|
+ Metadata** metadata_begin() const { return &_metadata_got[0] ; }
|
|
+ Metadata** metadata_end() const { return &_metadata_got[_metadata_size] ; }
|
|
+ const char* compile_kind() const { return "AOT"; }
|
|
+
|
|
+ int get_state() const {
|
|
+ return (int) (*_state_adr);
|
|
+ }
|
|
+
|
|
+ // inlined and non-virtual for AOTCodeHeap::oops_do
|
|
+ void do_oops(OopClosure* f) {
|
|
+ assert(_is_alive(), "");
|
|
+ if (_oop != NULL) {
|
|
+ f->do_oop(&_oop);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ virtual void do_unloading(bool unloading_occurred);
|
|
+
|
|
+protected:
|
|
+ // AOT compiled methods are not flushed
|
|
+ void flush() {};
|
|
+
|
|
+ NativeCallWrapper* call_wrapper_at(address call) const;
|
|
+ NativeCallWrapper* call_wrapper_before(address return_pc) const;
|
|
+ address call_instruction_address(address pc) const;
|
|
+
|
|
+ CompiledStaticCall* compiledStaticCall_at(Relocation* call_site) const;
|
|
+ CompiledStaticCall* compiledStaticCall_at(address addr) const;
|
|
+ CompiledStaticCall* compiledStaticCall_before(address addr) const;
|
|
+private:
|
|
+ bool is_aot_runtime_stub() const { return _method == NULL; }
|
|
+};
|
|
+
|
|
+class PltNativeCallWrapper: public NativeCallWrapper {
|
|
+private:
|
|
+ NativePltCall* _call;
|
|
+
|
|
+public:
|
|
+ PltNativeCallWrapper(NativePltCall* call) : _call(call) {}
|
|
+
|
|
+ virtual address destination() const { return _call->destination(); }
|
|
+ virtual address instruction_address() const { return _call->instruction_address(); }
|
|
+ virtual address next_instruction_address() const { return _call->next_instruction_address(); }
|
|
+ virtual address return_address() const { return _call->return_address(); }
|
|
+ virtual address get_resolve_call_stub(bool is_optimized) const { return _call->plt_resolve_call(); }
|
|
+ virtual void set_destination_mt_safe(address dest) { _call->set_destination_mt_safe(dest); }
|
|
+ virtual void set_to_interpreted(const methodHandle& method, CompiledICInfo& info);
|
|
+ virtual void verify() const { _call->verify(); }
|
|
+ virtual void verify_resolve_call(address dest) const;
|
|
+
|
|
+ virtual bool is_call_to_interpreted(address dest) const { return (dest == _call->plt_c2i_stub()); }
|
|
+ // TODO: assume for now that patching of aot code (got cell) is safe.
|
|
+ virtual bool is_safe_for_patching() const { return true; }
|
|
+
|
|
+ virtual NativeInstruction* get_load_instruction(virtual_call_Relocation* r) const;
|
|
+
|
|
+ virtual void *get_data(NativeInstruction* instruction) const {
|
|
+ return (void*)((NativeLoadGot*) instruction)->data();
|
|
+ }
|
|
+
|
|
+ virtual void set_data(NativeInstruction* instruction, intptr_t data) {
|
|
+ ((NativeLoadGot*) instruction)->set_data(data);
|
|
+ }
|
|
+};
|
|
+
|
|
+#endif // SHARE_AOT_AOTCOMPILEDMETHOD_HPP
|
|
diff --git a/src/hotspot/share/aot/aotLoader.cpp b/src/hotspot/share/aot/aotLoader.cpp
|
|
new file mode 100644
|
|
index 000000000..4e12ee95a
|
|
--- /dev/null
|
|
+++ b/src/hotspot/share/aot/aotLoader.cpp
|
|
@@ -0,0 +1,335 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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.
|
|
+ */
|
|
+
|
|
+#include "precompiled.hpp"
|
|
+#include "aot/aotCodeHeap.hpp"
|
|
+#include "aot/aotLoader.inline.hpp"
|
|
+#include "classfile/javaClasses.hpp"
|
|
+#include "jvm.h"
|
|
+#include "jvmci/jvmci.hpp"
|
|
+#include "memory/allocation.inline.hpp"
|
|
+#include "memory/resourceArea.hpp"
|
|
+#include "oops/compressedOops.hpp"
|
|
+#include "oops/method.hpp"
|
|
+#include "prims/jvmtiExport.hpp"
|
|
+#include "runtime/arguments.hpp"
|
|
+#include "runtime/globals_extension.hpp"
|
|
+#include "runtime/handles.inline.hpp"
|
|
+#include "runtime/os.inline.hpp"
|
|
+#include "runtime/registerMap.hpp"
|
|
+#include "runtime/timerTrace.hpp"
|
|
+
|
|
+GrowableArray<AOTCodeHeap*>* AOTLoader::_heaps = new(ResourceObj::C_HEAP, mtCode) GrowableArray<AOTCodeHeap*> (2, mtCode);
|
|
+GrowableArray<AOTLib*>* AOTLoader::_libraries = new(ResourceObj::C_HEAP, mtCode) GrowableArray<AOTLib*> (2, mtCode);
|
|
+
|
|
+// Iterate over all AOT CodeHeaps
|
|
+#define FOR_ALL_AOT_HEAPS(heap) for (GrowableArrayIterator<AOTCodeHeap*> heap = heaps()->begin(); heap != heaps()->end(); ++heap)
|
|
+// Iterate over all AOT Libraries
|
|
+#define FOR_ALL_AOT_LIBRARIES(lib) for (GrowableArrayIterator<AOTLib*> lib = libraries()->begin(); lib != libraries()->end(); ++lib)
|
|
+
|
|
+void AOTLoader::load_for_klass(InstanceKlass* ik, TRAPS) {
|
|
+ if (ik->is_hidden()) {
|
|
+ // don't even bother
|
|
+ return;
|
|
+ }
|
|
+ if (UseAOT) {
|
|
+ // We allow hotswap to be enabled after the onload phase, but not breakpoints
|
|
+ assert(!JvmtiExport::can_post_breakpoint(), "AOT should have been disabled.");
|
|
+ FOR_ALL_AOT_HEAPS(heap) {
|
|
+ (*heap)->load_klass_data(ik, THREAD);
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+uint64_t AOTLoader::get_saved_fingerprint(InstanceKlass* ik) {
|
|
+ assert(UseAOT, "called only when AOT is enabled");
|
|
+ if (ik->is_hidden()) {
|
|
+ // don't even bother
|
|
+ return 0;
|
|
+ }
|
|
+ FOR_ALL_AOT_HEAPS(heap) {
|
|
+ AOTKlassData* klass_data = (*heap)->find_klass(ik);
|
|
+ if (klass_data != NULL) {
|
|
+ return klass_data->_fingerprint;
|
|
+ }
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+void AOTLoader::oops_do(OopClosure* f) {
|
|
+ if (UseAOT) {
|
|
+ FOR_ALL_AOT_HEAPS(heap) {
|
|
+ (*heap)->oops_do(f);
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+void AOTLoader::metadata_do(MetadataClosure* f) {
|
|
+ if (UseAOT) {
|
|
+ FOR_ALL_AOT_HEAPS(heap) {
|
|
+ (*heap)->metadata_do(f);
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+void AOTLoader::mark_evol_dependent_methods(InstanceKlass* dependee) {
|
|
+ if (UseAOT) {
|
|
+ FOR_ALL_AOT_HEAPS(heap) {
|
|
+ (*heap)->mark_evol_dependent_methods(dependee);
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+/**
|
|
+ * List of core modules for which we search for shared libraries.
|
|
+ */
|
|
+static const char* modules[] = {
|
|
+ "java.base",
|
|
+ "java.logging",
|
|
+ "jdk.compiler",
|
|
+ "jdk.internal.vm.ci",
|
|
+ "jdk.internal.vm.compiler"
|
|
+};
|
|
+
|
|
+void AOTLoader::initialize() {
|
|
+ TraceTime timer("AOT initialization", TRACETIME_LOG(Info, aot, startuptime));
|
|
+
|
|
+ if (FLAG_IS_DEFAULT(UseAOT) && AOTLibrary != NULL) {
|
|
+ // Don't need to set UseAOT on command line when AOTLibrary is specified
|
|
+ FLAG_SET_DEFAULT(UseAOT, true);
|
|
+ }
|
|
+ if (UseAOT) {
|
|
+ // EagerInitialization is not compatible with AOT
|
|
+ if (EagerInitialization) {
|
|
+ if (PrintAOT) {
|
|
+ warning("EagerInitialization is not compatible with AOT (switching AOT off)");
|
|
+ }
|
|
+ FLAG_SET_DEFAULT(UseAOT, false);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (JvmtiExport::can_post_breakpoint()) {
|
|
+ if (PrintAOT) {
|
|
+ warning("JVMTI capability to post breakpoint is not compatible with AOT (switching AOT off)");
|
|
+ }
|
|
+ FLAG_SET_DEFAULT(UseAOT, false);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ // -Xint is not compatible with AOT
|
|
+ if (Arguments::is_interpreter_only()) {
|
|
+ if (PrintAOT) {
|
|
+ warning("-Xint is not compatible with AOT (switching AOT off)");
|
|
+ }
|
|
+ FLAG_SET_DEFAULT(UseAOT, false);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+#ifdef _WINDOWS
|
|
+ const char pathSep = ';';
|
|
+#else
|
|
+ const char pathSep = ':';
|
|
+#endif
|
|
+
|
|
+ // Scan the AOTLibrary option.
|
|
+ if (AOTLibrary != NULL) {
|
|
+ const int len = (int)strlen(AOTLibrary);
|
|
+ char* cp = NEW_C_HEAP_ARRAY(char, len+1, mtCode);
|
|
+ memcpy(cp, AOTLibrary, len);
|
|
+ cp[len] = '\0';
|
|
+ char* end = cp + len;
|
|
+ while (cp < end) {
|
|
+ const char* name = cp;
|
|
+ while ((*cp) != '\0' && (*cp) != '\n' && (*cp) != ',' && (*cp) != pathSep) cp++;
|
|
+ cp[0] = '\0'; // Terminate name
|
|
+ cp++;
|
|
+ load_library(name, true);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // Load well-know AOT libraries from Java installation directory.
|
|
+ const char* home = Arguments::get_java_home();
|
|
+ const char* file_separator = os::file_separator();
|
|
+
|
|
+ for (int i = 0; i < (int) (sizeof(modules) / sizeof(const char*)); i++) {
|
|
+ char library[JVM_MAXPATHLEN];
|
|
+ jio_snprintf(library, sizeof(library), "%s%slib%slib%s%s%s%s", home, file_separator, file_separator, modules[i], UseCompressedOops ? "-coop" : "", UseG1GC ? "" : "-nong1", os::dll_file_extension());
|
|
+ load_library(library, false);
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+void AOTLoader::universe_init() {
|
|
+ if (UseAOT && libraries_count() > 0) {
|
|
+ // Shifts are static values which initialized by 0 until java heap initialization.
|
|
+ // AOT libs are loaded before heap initialized so shift values are not set.
|
|
+ // It is okay since ObjectAlignmentInBytes flag which defines shifts value is set before AOT libs are loaded.
|
|
+ // AOT sets shift values during heap and metaspace initialization.
|
|
+ // Check shifts value to make sure thay did not change.
|
|
+ if (UseCompressedOops && AOTLib::narrow_oop_shift_initialized()) {
|
|
+ int oop_shift = CompressedOops::shift();
|
|
+ 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");
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ // Create heaps for all valid libraries
|
|
+ FOR_ALL_AOT_LIBRARIES(lib) {
|
|
+ if ((*lib)->is_valid()) {
|
|
+ AOTCodeHeap* heap = new AOTCodeHeap(*lib);
|
|
+ {
|
|
+ MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
|
|
+ add_heap(heap);
|
|
+ CodeCache::add_heap(heap);
|
|
+ }
|
|
+ } else {
|
|
+ // Unload invalid libraries
|
|
+ os::dll_unload((*lib)->dl_handle());
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ if (heaps_count() == 0) {
|
|
+ if (FLAG_IS_DEFAULT(UseAOT)) {
|
|
+ FLAG_SET_DEFAULT(UseAOT, false);
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+// Set shift value for compressed oops and classes based on first AOT library config.
|
|
+// AOTLoader::universe_init(), which is called later, will check the shift value again to make sure nobody change it.
|
|
+// This code is not executed during CDS dump because it runs in Interpreter mode and AOT is disabled in this mode.
|
|
+
|
|
+void AOTLoader::set_narrow_oop_shift() {
|
|
+ // This method is called from Universe::initialize_heap().
|
|
+ if (UseAOT && libraries_count() > 0 &&
|
|
+ UseCompressedOops && AOTLib::narrow_oop_shift_initialized()) {
|
|
+ if (CompressedOops::shift() == 0) {
|
|
+ // 0 is valid shift value for small heap but we can safely increase it
|
|
+ // at this point when nobody used it yet.
|
|
+ CompressedOops::set_shift(AOTLib::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) {
|
|
+ if (CompressedKlassPointers::shift() == 0) {
|
|
+ CompressedKlassPointers::set_shift(AOTLib::narrow_klass_shift());
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+void AOTLoader::load_library(const char* name, bool exit_on_error) {
|
|
+ // Skip library if a library with the same name is already loaded.
|
|
+ const int file_separator = *os::file_separator();
|
|
+ const char* start = strrchr(name, file_separator);
|
|
+ const char* new_name = (start == NULL) ? name : (start + 1);
|
|
+ FOR_ALL_AOT_LIBRARIES(lib) {
|
|
+ const char* lib_name = (*lib)->name();
|
|
+ start = strrchr(lib_name, file_separator);
|
|
+ const char* old_name = (start == NULL) ? lib_name : (start + 1);
|
|
+ if (strcmp(old_name, new_name) == 0) {
|
|
+ if (PrintAOT) {
|
|
+ warning("AOT library %s is already loaded as %s.", name, lib_name);
|
|
+ }
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+ char ebuf[1024];
|
|
+ void* handle = os::dll_load(name, ebuf, sizeof ebuf);
|
|
+ if (handle == NULL) {
|
|
+ if (exit_on_error) {
|
|
+ tty->print_cr("error opening file: %s", ebuf);
|
|
+ vm_exit(1);
|
|
+ }
|
|
+ return;
|
|
+ }
|
|
+ const int dso_id = libraries_count() + 1;
|
|
+ AOTLib* lib = new AOTLib(handle, name, dso_id);
|
|
+ if (!lib->is_valid()) {
|
|
+ delete lib;
|
|
+ os::dll_unload(handle);
|
|
+ return;
|
|
+ }
|
|
+ add_library(lib);
|
|
+}
|
|
+
|
|
+#ifndef PRODUCT
|
|
+void AOTLoader::print_statistics() {
|
|
+ { ttyLocker ttyl;
|
|
+ tty->print_cr("--- AOT Statistics ---");
|
|
+ tty->print_cr("AOT libraries loaded: %d", heaps_count());
|
|
+ AOTCodeHeap::print_statistics();
|
|
+ }
|
|
+}
|
|
+#endif
|
|
+
|
|
+
|
|
+bool AOTLoader::reconcile_dynamic_invoke(InstanceKlass* holder, int index, Method* adapter_method, Klass* appendix_klass) {
|
|
+ if (!UseAOT) {
|
|
+ return true;
|
|
+ }
|
|
+ JavaThread* thread = JavaThread::current();
|
|
+ ResourceMark rm(thread);
|
|
+ RegisterMap map(thread, false);
|
|
+ frame caller_frame = thread->last_frame().sender(&map); // Skip stub
|
|
+ CodeBlob* caller_cb = caller_frame.cb();
|
|
+ guarantee(caller_cb != NULL && caller_cb->is_compiled(), "must be called from compiled method");
|
|
+ CompiledMethod* cm = caller_cb->as_compiled_method();
|
|
+
|
|
+ if (!cm->is_aot()) {
|
|
+ return true;
|
|
+ }
|
|
+ AOTCompiledMethod* aot = (AOTCompiledMethod*)cm;
|
|
+
|
|
+ AOTCodeHeap* caller_heap = NULL;
|
|
+ FOR_ALL_AOT_HEAPS(heap) {
|
|
+ if ((*heap)->contains_blob(aot)) {
|
|
+ caller_heap = *heap;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ guarantee(caller_heap != NULL, "CodeHeap not found");
|
|
+ bool success = caller_heap->reconcile_dynamic_invoke(aot, holder, index, adapter_method, appendix_klass);
|
|
+ vmassert(success || thread->last_frame().sender(&map).is_deoptimized_frame(), "caller not deoptimized on failure");
|
|
+ return success;
|
|
+}
|
|
+
|
|
+
|
|
+// This should be called very early during startup before any of the AOTed methods that use boxes can deoptimize.
|
|
+// Deoptimization machinery expects the caches to be present and populated.
|
|
+void AOTLoader::initialize_box_caches(TRAPS) {
|
|
+ if (!UseAOT || libraries_count() == 0) {
|
|
+ return;
|
|
+ }
|
|
+ TraceTime timer("AOT initialization of box caches", TRACETIME_LOG(Info, aot, startuptime));
|
|
+ JVMCI::ensure_box_caches_initialized(CHECK);
|
|
+}
|
|
diff --git a/src/hotspot/share/aot/aotLoader.hpp b/src/hotspot/share/aot/aotLoader.hpp
|
|
new file mode 100644
|
|
index 000000000..cf03ea087
|
|
--- /dev/null
|
|
+++ b/src/hotspot/share/aot/aotLoader.hpp
|
|
@@ -0,0 +1,74 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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.
|
|
+ */
|
|
+
|
|
+#ifndef SHARE_AOT_AOTLOADER_HPP
|
|
+#define SHARE_AOT_AOTLOADER_HPP
|
|
+
|
|
+#include "runtime/globals_extension.hpp"
|
|
+#include "runtime/handles.hpp"
|
|
+
|
|
+class AOTCodeHeap;
|
|
+class AOTCompiledMethod;
|
|
+class AOTLib;
|
|
+class CodeBlob;
|
|
+template <class T> class GrowableArray;
|
|
+class InstanceKlass;
|
|
+class JavaThread;
|
|
+class Metadata;
|
|
+class OopClosure;
|
|
+
|
|
+class AOTLoader {
|
|
+private:
|
|
+#if INCLUDE_AOT
|
|
+ static GrowableArray<AOTCodeHeap*>* _heaps;
|
|
+ static GrowableArray<AOTLib*>* _libraries;
|
|
+#endif
|
|
+ static void load_library(const char* name, bool exit_on_error);
|
|
+
|
|
+public:
|
|
+#if INCLUDE_AOT
|
|
+ static GrowableArray<AOTCodeHeap*>* heaps();
|
|
+ static GrowableArray<AOTLib*>* libraries();
|
|
+ static int heaps_count();
|
|
+ static int libraries_count();
|
|
+ static void add_heap(AOTCodeHeap *heap);
|
|
+ static void add_library(AOTLib *lib);
|
|
+#endif
|
|
+ static void initialize() NOT_AOT({ FLAG_SET_ERGO(UseAOT, false); });
|
|
+
|
|
+ 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 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;
|
|
+ static void mark_evol_dependent_methods(InstanceKlass* dependee) NOT_AOT_RETURN;
|
|
+ static void initialize_box_caches(TRAPS) NOT_AOT_RETURN;
|
|
+
|
|
+ NOT_PRODUCT( static void print_statistics() NOT_AOT_RETURN; )
|
|
+
|
|
+ static bool reconcile_dynamic_invoke(InstanceKlass* holder, int index, Method* adapter_method, Klass *appendix_klass) NOT_AOT({ return true; });
|
|
+};
|
|
+
|
|
+#endif // SHARE_AOT_AOTLOADER_HPP
|
|
diff --git a/src/hotspot/share/aot/aotLoader.inline.hpp b/src/hotspot/share/aot/aotLoader.inline.hpp
|
|
new file mode 100644
|
|
index 000000000..708634940
|
|
--- /dev/null
|
|
+++ b/src/hotspot/share/aot/aotLoader.inline.hpp
|
|
@@ -0,0 +1,39 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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.
|
|
+ */
|
|
+
|
|
+#ifndef SHARE_AOT_AOTLOADER_INLINE_HPP
|
|
+#define SHARE_AOT_AOTLOADER_INLINE_HPP
|
|
+
|
|
+#include "aot/aotLoader.hpp"
|
|
+#include "utilities/growableArray.hpp"
|
|
+
|
|
+#if INCLUDE_AOT
|
|
+GrowableArray<AOTCodeHeap*>* AOTLoader::heaps() { return _heaps; }
|
|
+GrowableArray<AOTLib*>* AOTLoader::libraries() { return _libraries; }
|
|
+int AOTLoader::heaps_count() { return heaps()->length(); }
|
|
+int AOTLoader::libraries_count() { return libraries()->length(); }
|
|
+void AOTLoader::add_heap(AOTCodeHeap *heap) { heaps()->append(heap); }
|
|
+void AOTLoader::add_library(AOTLib *lib) { libraries()->append(lib); }
|
|
+#endif
|
|
+
|
|
+#endif // SHARE_AOT_AOTLOADER_INLINE_HPP
|
|
diff --git a/src/hotspot/share/aot/compiledIC_aot.cpp b/src/hotspot/share/aot/compiledIC_aot.cpp
|
|
new file mode 100644
|
|
index 000000000..dec97e5c2
|
|
--- /dev/null
|
|
+++ b/src/hotspot/share/aot/compiledIC_aot.cpp
|
|
@@ -0,0 +1,37 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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.
|
|
+ */
|
|
+
|
|
+#include "precompiled.hpp"
|
|
+
|
|
+#include "aot/compiledIC_aot.hpp"
|
|
+
|
|
+bool CompiledPltStaticCall::is_call_to_interpreted() const {
|
|
+ // It is a call to interpreted, if it calls to a stub. Hence, the destination
|
|
+ // must be in the stub part of the nmethod that contains the call
|
|
+ return destination() == _call->plt_c2i_stub();
|
|
+}
|
|
+
|
|
+address CompiledPltStaticCall::find_stub() {
|
|
+ // It is static NativePltCall. Return c2i stub address.
|
|
+ return _call->plt_c2i_stub();
|
|
+}
|
|
diff --git a/src/hotspot/share/aot/compiledIC_aot.hpp b/src/hotspot/share/aot/compiledIC_aot.hpp
|
|
new file mode 100644
|
|
index 000000000..664377c1c
|
|
--- /dev/null
|
|
+++ b/src/hotspot/share/aot/compiledIC_aot.hpp
|
|
@@ -0,0 +1,83 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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.
|
|
+ */
|
|
+
|
|
+#ifndef SHARE_AOT_COMPILEDIC_AOT_HPP
|
|
+#define SHARE_AOT_COMPILEDIC_AOT_HPP
|
|
+
|
|
+#include "code/compiledIC.hpp"
|
|
+#include "code/nativeInst.hpp"
|
|
+#include "interpreter/linkResolver.hpp"
|
|
+#include "oops/compiledICHolder.hpp"
|
|
+
|
|
+class CompiledPltStaticCall: public CompiledStaticCall {
|
|
+ friend class CompiledIC;
|
|
+ friend class PltNativeCallWrapper;
|
|
+
|
|
+ // Also used by CompiledIC
|
|
+ void set_to_interpreted(const methodHandle& callee, address entry);
|
|
+
|
|
+ address instruction_address() const { return _call->instruction_address(); }
|
|
+ void set_destination_mt_safe(address dest) { _call->set_destination_mt_safe(dest); }
|
|
+
|
|
+ NativePltCall* _call;
|
|
+
|
|
+ CompiledPltStaticCall(NativePltCall* call) : _call(call) {}
|
|
+
|
|
+ public:
|
|
+
|
|
+ inline static CompiledPltStaticCall* before(address return_addr) {
|
|
+ CompiledPltStaticCall* st = new CompiledPltStaticCall(nativePltCall_before(return_addr));
|
|
+ st->verify();
|
|
+ return st;
|
|
+ }
|
|
+
|
|
+ static inline CompiledPltStaticCall* at(address native_call) {
|
|
+ CompiledPltStaticCall* st = new CompiledPltStaticCall(nativePltCall_at(native_call));
|
|
+ st->verify();
|
|
+ return st;
|
|
+ }
|
|
+
|
|
+ static inline CompiledPltStaticCall* at(Relocation* call_site) {
|
|
+ return at(call_site->addr());
|
|
+ }
|
|
+
|
|
+ // Delegation
|
|
+ address destination() const { return _call->destination(); }
|
|
+
|
|
+ virtual bool is_call_to_interpreted() const;
|
|
+
|
|
+ // Stub support
|
|
+ address find_stub();
|
|
+ static void set_stub_to_clean(static_stub_Relocation* static_stub);
|
|
+
|
|
+ // Misc.
|
|
+ void print() PRODUCT_RETURN;
|
|
+ void verify() PRODUCT_RETURN;
|
|
+
|
|
+ protected:
|
|
+ virtual address resolve_call_stub() const { return _call->plt_resolve_call(); }
|
|
+ virtual void set_to_far(const methodHandle& callee, address entry) { set_to_compiled(entry); }
|
|
+ virtual const char* name() const { return "CompiledPltStaticCall"; }
|
|
+};
|
|
+
|
|
+#endif // SHARE_AOT_COMPILEDIC_AOT_HPP
|
|
diff --git a/src/hotspot/share/asm/codeBuffer.hpp b/src/hotspot/share/asm/codeBuffer.hpp
|
|
index be1e14ad8..359b8a051 100644
|
|
--- a/src/hotspot/share/asm/codeBuffer.hpp
|
|
+++ b/src/hotspot/share/asm/codeBuffer.hpp
|
|
@@ -406,6 +406,10 @@ class CodeBuffer: public StackObj {
|
|
|
|
address _last_insn; // used to merge consecutive memory barriers, loads or stores.
|
|
|
|
+#if INCLUDE_AOT
|
|
+ bool _immutable_PIC;
|
|
+#endif
|
|
+
|
|
#ifndef PRODUCT
|
|
CodeStrings _code_strings;
|
|
bool _collect_comments; // Indicate if we need to collect block comments at all.
|
|
@@ -422,6 +426,9 @@ class CodeBuffer: public StackObj {
|
|
_oop_recorder = NULL;
|
|
_overflow_arena = NULL;
|
|
_last_insn = NULL;
|
|
+#if INCLUDE_AOT
|
|
+ _immutable_PIC = false;
|
|
+#endif
|
|
|
|
#ifndef PRODUCT
|
|
_decode_begin = NULL;
|
|
@@ -668,6 +675,13 @@ class CodeBuffer: public StackObj {
|
|
// Log a little info about section usage in the CodeBuffer
|
|
void log_section_sizes(const char* name);
|
|
|
|
+#if INCLUDE_AOT
|
|
+ // True if this is a code buffer used for immutable PIC, i.e. AOT
|
|
+ // compilation.
|
|
+ bool immutable_PIC() { return _immutable_PIC; }
|
|
+ void set_immutable_PIC(bool pic) { _immutable_PIC = pic; }
|
|
+#endif
|
|
+
|
|
#ifndef PRODUCT
|
|
public:
|
|
// Printing / Decoding
|
|
diff --git a/src/hotspot/share/c1/c1_Compilation.hpp b/src/hotspot/share/c1/c1_Compilation.hpp
|
|
index dd0f8ed8c..aa9e33493 100644
|
|
--- a/src/hotspot/share/c1/c1_Compilation.hpp
|
|
+++ b/src/hotspot/share/c1/c1_Compilation.hpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 1999, 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
|
|
@@ -266,7 +266,7 @@ class Compilation: public StackObj {
|
|
// will compilation make optimistic assumptions that might lead to
|
|
// deoptimization and that the runtime will account for?
|
|
bool is_optimistic() {
|
|
- return CompilerConfig::is_c1_only_no_jvmci() && !is_profiling() &&
|
|
+ return CompilerConfig::is_c1_only_no_aot_or_jvmci() && !is_profiling() &&
|
|
(RangeCheckElimination || UseLoopInvariantCodeMotion) &&
|
|
method()->method_data()->trap_count(Deoptimization::Reason_none) == 0;
|
|
}
|
|
diff --git a/src/hotspot/share/c1/c1_LIRAssembler.cpp b/src/hotspot/share/c1/c1_LIRAssembler.cpp
|
|
index 989a6f8ad..7f5655dcb 100644
|
|
--- a/src/hotspot/share/c1/c1_LIRAssembler.cpp
|
|
+++ b/src/hotspot/share/c1/c1_LIRAssembler.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2000, 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
|
|
@@ -483,7 +483,7 @@ void LIR_Assembler::emit_call(LIR_OpJavaCall* op) {
|
|
|
|
#if defined(IA32) && defined(COMPILER2)
|
|
// C2 leave fpu stack dirty clean it
|
|
- if (UseSSE < 2 && !CompilerConfig::is_c1_only_no_jvmci()) {
|
|
+ if (UseSSE < 2 && !CompilerConfig::is_c1_only_no_aot_or_jvmci()) {
|
|
int i;
|
|
for ( i = 1; i <= 7 ; i++ ) {
|
|
ffree(i);
|
|
diff --git a/src/hotspot/share/c1/c1_LIRAssembler.hpp b/src/hotspot/share/c1/c1_LIRAssembler.hpp
|
|
index c82baa15f..28cff1448 100644
|
|
--- a/src/hotspot/share/c1/c1_LIRAssembler.hpp
|
|
+++ b/src/hotspot/share/c1/c1_LIRAssembler.hpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2000, 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
|
|
@@ -267,7 +267,11 @@ class LIR_Assembler: public CompilationResourceObj {
|
|
public:
|
|
|
|
static int call_stub_size() {
|
|
- return _call_stub_size;
|
|
+ if (UseAOT) {
|
|
+ return _call_stub_size + _call_aot_stub_size;
|
|
+ } else {
|
|
+ return _call_stub_size;
|
|
+ }
|
|
}
|
|
|
|
static int exception_handler_size() {
|
|
diff --git a/src/hotspot/share/c1/c1_LIRGenerator.cpp b/src/hotspot/share/c1/c1_LIRGenerator.cpp
|
|
index 4c33bcf30..ce9d70b24 100644
|
|
--- a/src/hotspot/share/c1/c1_LIRGenerator.cpp
|
|
+++ b/src/hotspot/share/c1/c1_LIRGenerator.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2005, 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
|
|
@@ -462,7 +462,7 @@ void LIRGenerator::klass2reg_with_patching(LIR_Opr r, ciMetadata* obj, CodeEmitI
|
|
/* C2 relies on constant pool entries being resolved (ciTypeFlow), so if tiered compilation
|
|
* is active and the class hasn't yet been resolved we need to emit a patch that resolves
|
|
* the class. */
|
|
- if ((!CompilerConfig::is_c1_only_no_jvmci() && need_resolve) || !obj->is_loaded() || PatchALot) {
|
|
+ if ((!CompilerConfig::is_c1_only_no_aot_or_jvmci() && need_resolve) || !obj->is_loaded() || PatchALot) {
|
|
assert(info != NULL, "info must be set if class is not loaded");
|
|
__ klass2reg_patch(NULL, r, info);
|
|
} else {
|
|
@@ -646,7 +646,7 @@ void LIRGenerator::monitor_exit(LIR_Opr object, LIR_Opr lock, LIR_Opr new_hdr, L
|
|
void LIRGenerator::print_if_not_loaded(const NewInstance* new_instance) {
|
|
if (PrintNotLoaded && !new_instance->klass()->is_loaded()) {
|
|
tty->print_cr(" ###class not loaded at new bci %d", new_instance->printable_bci());
|
|
- } else if (PrintNotLoaded && (!CompilerConfig::is_c1_only_no_jvmci() && new_instance->is_unresolved())) {
|
|
+ } else if (PrintNotLoaded && (!CompilerConfig::is_c1_only_no_aot_or_jvmci() && new_instance->is_unresolved())) {
|
|
tty->print_cr(" ###class not resolved at new bci %d", new_instance->printable_bci());
|
|
}
|
|
}
|
|
diff --git a/src/hotspot/share/classfile/classFileParser.cpp b/src/hotspot/share/classfile/classFileParser.cpp
|
|
index 052d01336..3835a3f17 100644
|
|
--- a/src/hotspot/share/classfile/classFileParser.cpp
|
|
+++ b/src/hotspot/share/classfile/classFileParser.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 1997, 2021, 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
|
|
@@ -90,6 +90,9 @@
|
|
#if INCLUDE_JFR
|
|
#include "jfr/support/jfrTraceIdExtension.hpp"
|
|
#endif
|
|
+#if INCLUDE_AOT
|
|
+#include "aot/aotLoader.hpp"
|
|
+#endif
|
|
|
|
// We generally try to create the oops directly when parsing, rather than
|
|
// allocating temporary data structures and copying the bytes twice. A
|
|
@@ -5237,6 +5240,26 @@ InstanceKlass* ClassFileParser::create_instance_klass(bool changed_by_loadhook,
|
|
|
|
assert(_klass == ik, "invariant");
|
|
|
|
+#if INCLUDE_AOT
|
|
+ if (ik->should_store_fingerprint()) {
|
|
+ ik->store_fingerprint(_stream->compute_fingerprint());
|
|
+ }
|
|
+
|
|
+ ik->set_has_passed_fingerprint_check(false);
|
|
+ if (UseAOT && ik->supers_have_passed_fingerprint_checks()) {
|
|
+ uint64_t aot_fp = AOTLoader::get_saved_fingerprint(ik);
|
|
+ uint64_t fp = ik->has_stored_fingerprint() ? ik->get_stored_fingerprint() : _stream->compute_fingerprint();
|
|
+ if (aot_fp != 0 && aot_fp == fp) {
|
|
+ // This class matches with a class saved in an AOT library
|
|
+ ik->set_has_passed_fingerprint_check(true);
|
|
+ } else {
|
|
+ ResourceMark rm;
|
|
+ log_info(class, fingerprint)("%s : expected = " PTR64_FORMAT " actual = " PTR64_FORMAT,
|
|
+ ik->external_name(), aot_fp, _stream->compute_fingerprint());
|
|
+ }
|
|
+ }
|
|
+#endif
|
|
+
|
|
return ik;
|
|
}
|
|
|
|
diff --git a/src/hotspot/share/classfile/classFileStream.cpp b/src/hotspot/share/classfile/classFileStream.cpp
|
|
index b65b827c5..a9ac5fcc2 100644
|
|
--- a/src/hotspot/share/classfile/classFileStream.cpp
|
|
+++ b/src/hotspot/share/classfile/classFileStream.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 1997, 2021, 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
|
|
@@ -75,3 +75,12 @@ const ClassFileStream* ClassFileStream::clone() const {
|
|
need_verify(),
|
|
from_boot_loader_modules_image());
|
|
}
|
|
+
|
|
+uint64_t ClassFileStream::compute_fingerprint() const {
|
|
+ int classfile_size = length();
|
|
+ int classfile_crc = ClassLoader::crc32(0, (const char*)buffer(), length());
|
|
+ uint64_t fingerprint = (uint64_t(classfile_size) << 32) | uint64_t(uint32_t(classfile_crc));
|
|
+ assert(fingerprint != 0, "must not be zero");
|
|
+
|
|
+ return fingerprint;
|
|
+}
|
|
diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp
|
|
index 7cdc25406..94cf3af68 100644
|
|
--- a/src/hotspot/share/classfile/systemDictionary.cpp
|
|
+++ b/src/hotspot/share/classfile/systemDictionary.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 1997, 2021, 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
|
|
@@ -89,6 +89,9 @@
|
|
#if INCLUDE_JBOOSTER
|
|
#include "jbooster/client/clientStartupSignal.hpp"
|
|
#endif // INCLUDE_JBOOSTER
|
|
+#if INCLUDE_AOT
|
|
+#include "aot/aotLoader.hpp"
|
|
+#endif
|
|
|
|
ResolutionErrorTable* SystemDictionary::_resolution_errors = NULL;
|
|
SymbolPropertyTable* SystemDictionary::_invoke_method_table = NULL;
|
|
@@ -1215,6 +1218,23 @@ void SystemDictionary::load_shared_class_misc(InstanceKlass* ik, ClassLoaderData
|
|
|
|
// notify a class loaded from shared object
|
|
ClassLoadingService::notify_class_loaded(ik, true /* shared class */);
|
|
+
|
|
+#if INCLUDE_AOT
|
|
+ ik->set_has_passed_fingerprint_check(false);
|
|
+ if (UseAOT && ik->supers_have_passed_fingerprint_checks()) {
|
|
+ uint64_t aot_fp = AOTLoader::get_saved_fingerprint(ik);
|
|
+ uint64_t cds_fp = ik->get_stored_fingerprint();
|
|
+ if (aot_fp != 0 && aot_fp == cds_fp) {
|
|
+ // This class matches with a class saved in an AOT library
|
|
+ ik->set_has_passed_fingerprint_check(true);
|
|
+ } else {
|
|
+ if (log_is_enabled(Info, class, fingerprint)) {
|
|
+ ResourceMark rm;
|
|
+ log_info(class, fingerprint)("%s : expected = " PTR64_FORMAT " actual = " PTR64_FORMAT, ik->external_name(), aot_fp, cds_fp);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+#endif
|
|
}
|
|
|
|
#endif // INCLUDE_CDS
|
|
diff --git a/src/hotspot/share/code/codeBlob.hpp b/src/hotspot/share/code/codeBlob.hpp
|
|
index 104e04fba..54258da76 100644
|
|
--- a/src/hotspot/share/code/codeBlob.hpp
|
|
+++ b/src/hotspot/share/code/codeBlob.hpp
|
|
@@ -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
|
|
@@ -46,7 +46,8 @@ struct CodeBlobType {
|
|
MethodProfiled = 1, // Execution level 2 and 3 (profiled) nmethods
|
|
NonNMethod = 2, // Non-nmethods like Buffers, Adapters and Runtime Stubs
|
|
All = 3, // All types (No code cache segmentation)
|
|
- NumTypes = 4 // Number of CodeBlobTypes
|
|
+ AOT = 4, // AOT methods
|
|
+ NumTypes = 5 // Number of CodeBlobTypes
|
|
};
|
|
};
|
|
|
|
@@ -55,6 +56,10 @@ struct CodeBlobType {
|
|
// Subtypes are:
|
|
// CompiledMethod : Compiled Java methods (include method that calls to native code)
|
|
// nmethod : JIT Compiled Java methods
|
|
+// AOTCompiledMethod : AOT Compiled Java methods - Not in the CodeCache!
|
|
+// AOTCompiledMethod objects are allocated in the C-Heap, the code they
|
|
+// point to is allocated in the AOTCodeHeap which is in the C-Heap as
|
|
+// well (i.e. it's the memory where the shared library was loaded to)
|
|
// RuntimeBlob : Non-compiled method code; generated glue code
|
|
// BufferBlob : Used for non-relocatable code such as interpreter, stubroutines, etc.
|
|
// AdapterBlob : Used to hold C2I/I2C adapters
|
|
@@ -69,12 +74,17 @@ struct CodeBlobType {
|
|
// UncommonTrapBlob : Used to handle uncommon traps
|
|
//
|
|
//
|
|
-// Layout : continuous in the CodeCache
|
|
+// Layout (all except AOTCompiledMethod) : continuous in the CodeCache
|
|
// - header
|
|
// - relocation
|
|
// - content space
|
|
// - instruction space
|
|
// - data space
|
|
+//
|
|
+// Layout (AOTCompiledMethod) : in the C-Heap
|
|
+// - header -\
|
|
+// ... |
|
|
+// - code <-/
|
|
|
|
|
|
class CodeBlobLayout;
|
|
@@ -140,6 +150,7 @@ public:
|
|
virtual bool is_adapter_blob() const { return false; }
|
|
virtual bool is_vtable_blob() const { return false; }
|
|
virtual bool is_method_handles_adapter_blob() const { return false; }
|
|
+ virtual bool is_aot() const { return false; }
|
|
virtual bool is_compiled() const { return false; }
|
|
virtual bool is_optimized_entry_blob() const { return false; }
|
|
|
|
@@ -242,6 +253,7 @@ public:
|
|
|
|
#ifndef PRODUCT
|
|
void set_strings(CodeStrings& strings) {
|
|
+ assert(!is_aot(), "invalid on aot");
|
|
_strings.copy(strings);
|
|
}
|
|
#endif
|
|
diff --git a/src/hotspot/share/code/codeCache.cpp b/src/hotspot/share/code/codeCache.cpp
|
|
index 61f8c0f51..254ddbf5c 100644
|
|
--- a/src/hotspot/share/code/codeCache.cpp
|
|
+++ b/src/hotspot/share/code/codeCache.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
|
|
@@ -72,6 +72,9 @@
|
|
#include "opto/compile.hpp"
|
|
#include "opto/node.hpp"
|
|
#endif
|
|
+#if INCLUDE_AOT
|
|
+#include "aot/aotLoader.hpp"
|
|
+#endif
|
|
|
|
// Helper class for printing in CodeCache
|
|
class CodeBlob_sizes {
|
|
@@ -698,6 +701,9 @@ void CodeCache::metadata_do(MetadataClosure* f) {
|
|
while(iter.next()) {
|
|
iter.method()->metadata_do(f);
|
|
}
|
|
+#if INCLUDE_AOT
|
|
+ AOTLoader::metadata_do(f);
|
|
+#endif
|
|
}
|
|
|
|
int CodeCache::alignment_unit() {
|
|
@@ -983,6 +989,13 @@ void codeCache_init() {
|
|
CodeCache::initialize();
|
|
}
|
|
|
|
+#if INCLUDE_AOT
|
|
+void AOTLoader_init() {
|
|
+ // Load AOT libraries and add AOT code heaps.
|
|
+ AOTLoader::initialize();
|
|
+}
|
|
+#endif
|
|
+
|
|
//------------------------------------------------------------------------------------------------
|
|
|
|
int CodeCache::number_of_nmethods_with_dependencies() {
|
|
@@ -1044,6 +1057,13 @@ CompiledMethod* CodeCache::find_compiled(void* start) {
|
|
return (CompiledMethod*)cb;
|
|
}
|
|
|
|
+#if INCLUDE_AOT
|
|
+bool CodeCache::is_far_target(address target) {
|
|
+ return NativeCall::is_far_call(_low_bound, target) ||
|
|
+ NativeCall::is_far_call(_high_bound, target);
|
|
+}
|
|
+#endif
|
|
+
|
|
#if INCLUDE_JVMTI
|
|
// RedefineClasses support for saving nmethods that are dependent on "old" methods.
|
|
// We don't really expect this table to grow very large. If it does, it can become a hashtable.
|
|
@@ -1093,6 +1113,13 @@ void CodeCache::old_nmethods_do(MetadataClosure* f) {
|
|
// Just marks the methods in this class as needing deoptimization
|
|
void CodeCache::mark_for_evol_deoptimization(InstanceKlass* dependee) {
|
|
assert(SafepointSynchronize::is_at_safepoint(), "Can only do this at a safepoint!");
|
|
+
|
|
+#if INCLUDE_AOT
|
|
+ // Mark dependent AOT nmethods, which are only found via the class redefined.
|
|
+ // TODO: add dependencies to aotCompiledMethod's metadata section so this isn't
|
|
+ // needed.
|
|
+ AOTLoader::mark_evol_dependent_methods(dependee);
|
|
+#endif
|
|
}
|
|
|
|
|
|
diff --git a/src/hotspot/share/code/codeCache.hpp b/src/hotspot/share/code/codeCache.hpp
|
|
index 4825b63df..8ff8dc765 100644
|
|
--- a/src/hotspot/share/code/codeCache.hpp
|
|
+++ b/src/hotspot/share/code/codeCache.hpp
|
|
@@ -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
|
|
@@ -205,6 +205,11 @@ class CodeCache : AllStatic {
|
|
static address high_bound() { return _high_bound; }
|
|
static address high_bound(int code_blob_type);
|
|
|
|
+#if INCLUDE_AOT
|
|
+ // Have to use far call instructions to call this pc.
|
|
+ static bool is_far_target(address pc);
|
|
+#endif
|
|
+
|
|
// Profiling
|
|
static size_t capacity();
|
|
static size_t unallocated_capacity(int code_blob_type);
|
|
@@ -226,6 +231,7 @@ class CodeCache : AllStatic {
|
|
|
|
static bool code_blob_type_accepts_compiled(int type) {
|
|
bool result = type == CodeBlobType::All || type <= CodeBlobType::MethodProfiled;
|
|
+ AOT_ONLY( result = result || type == CodeBlobType::AOT; )
|
|
return result;
|
|
}
|
|
|
|
diff --git a/src/hotspot/share/code/compiledIC.cpp b/src/hotspot/share/code/compiledIC.cpp
|
|
index 8ed42270c..396c40ce9 100644
|
|
--- a/src/hotspot/share/code/compiledIC.cpp
|
|
+++ b/src/hotspot/share/code/compiledIC.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 1997, 2021, 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
|
|
@@ -425,7 +425,7 @@ bool CompiledIC::set_to_monomorphic(CompiledICInfo& info) {
|
|
// transitions are mt_safe
|
|
|
|
Thread *thread = Thread::current();
|
|
- if (info.to_interpreter()) {
|
|
+ if (info.to_interpreter() || info.to_aot()) {
|
|
// Call to interpreter
|
|
if (info.is_optimized() && is_optimized()) {
|
|
assert(is_clean(), "unsafe IC path");
|
|
@@ -439,8 +439,9 @@ bool CompiledIC::set_to_monomorphic(CompiledICInfo& info) {
|
|
|
|
if (TraceICs) {
|
|
ResourceMark rm(thread);
|
|
- tty->print_cr ("IC@" INTPTR_FORMAT ": monomorphic to interpreter: %s",
|
|
+ tty->print_cr ("IC@" INTPTR_FORMAT ": monomorphic to %s: %s",
|
|
p2i(instruction_address()),
|
|
+ (info.to_aot() ? "aot" : "interpreter"),
|
|
method->print_value_string());
|
|
}
|
|
} else {
|
|
@@ -540,13 +541,19 @@ void CompiledIC::compute_monomorphic_entry(const methodHandle& method,
|
|
entry = method_code->entry_point();
|
|
}
|
|
}
|
|
- if (entry != NULL) {
|
|
- // Call to near compiled code.
|
|
+ bool far_c2a = entry != NULL && caller_is_nmethod && method_code->is_far_code();
|
|
+ if (entry != NULL && !far_c2a) {
|
|
+ // Call to near compiled code (nmethod or aot).
|
|
info.set_compiled_entry(entry, is_optimized ? NULL : receiver_klass, is_optimized);
|
|
} else {
|
|
if (is_optimized) {
|
|
- // Use stub entry
|
|
- info.set_interpreter_entry(method()->get_c2i_entry(), method());
|
|
+ if (far_c2a) {
|
|
+ // Call to aot code from nmethod.
|
|
+ info.set_aot_entry(entry, method());
|
|
+ } else {
|
|
+ // Use stub entry
|
|
+ info.set_interpreter_entry(method()->get_c2i_entry(), method());
|
|
+ }
|
|
} else {
|
|
// Use icholder entry
|
|
assert(method_code == NULL || method_code->is_compiled(), "must be compiled");
|
|
@@ -607,6 +614,13 @@ bool CompiledDirectStaticCall::is_call_to_interpreted() const {
|
|
return cm->stub_contains(destination());
|
|
}
|
|
|
|
+bool CompiledDirectStaticCall::is_call_to_far() const {
|
|
+ // It is a call to aot method, if it calls to a stub. Hence, the destination
|
|
+ // must be in the stub part of the nmethod that contains the call
|
|
+ CodeBlob* desc = CodeCache::find_blob(instruction_address());
|
|
+ return desc->as_compiled_method()->stub_contains(destination());
|
|
+}
|
|
+
|
|
void CompiledStaticCall::set_to_compiled(address entry) {
|
|
if (TraceICs) {
|
|
ResourceMark rm;
|
|
@@ -631,6 +645,11 @@ void CompiledStaticCall::set(const StaticCallInfo& info) {
|
|
if (info._to_interpreter) {
|
|
// Call to interpreted code
|
|
set_to_interpreted(info.callee(), info.entry());
|
|
+#if INCLUDE_AOT
|
|
+ } else if (info._to_aot) {
|
|
+ // Call to far code
|
|
+ set_to_far(info.callee(), info.entry());
|
|
+#endif
|
|
} else {
|
|
set_to_compiled(info.entry());
|
|
}
|
|
@@ -642,6 +661,12 @@ void CompiledStaticCall::compute_entry(const methodHandle& m, bool caller_is_nme
|
|
CompiledMethod* m_code = m->code();
|
|
info._callee = m;
|
|
if (m_code != NULL && m_code->is_in_use() && !m_code->is_unloading()) {
|
|
+ if (caller_is_nmethod && m_code->is_far_code()) {
|
|
+ // Call to far aot code from nmethod.
|
|
+ info._to_aot = true;
|
|
+ } else {
|
|
+ info._to_aot = false;
|
|
+ }
|
|
info._to_interpreter = false;
|
|
info._entry = m_code->verified_entry_point();
|
|
} else {
|
|
@@ -653,18 +678,18 @@ void CompiledStaticCall::compute_entry(const methodHandle& m, bool caller_is_nme
|
|
}
|
|
}
|
|
|
|
-address CompiledDirectStaticCall::find_stub_for(address instruction) {
|
|
+address CompiledDirectStaticCall::find_stub_for(address instruction, bool is_aot) {
|
|
// Find reloc. information containing this call-site
|
|
RelocIterator iter((nmethod*)NULL, instruction);
|
|
while (iter.next()) {
|
|
if (iter.addr() == instruction) {
|
|
switch(iter.type()) {
|
|
case relocInfo::static_call_type:
|
|
- return iter.static_call_reloc()->static_stub();
|
|
+ return iter.static_call_reloc()->static_stub(is_aot);
|
|
// We check here for opt_virtual_call_type, since we reuse the code
|
|
// from the CompiledIC implementation
|
|
case relocInfo::opt_virtual_call_type:
|
|
- return iter.opt_virtual_call_reloc()->static_stub();
|
|
+ return iter.opt_virtual_call_reloc()->static_stub(is_aot);
|
|
case relocInfo::poll_type:
|
|
case relocInfo::poll_return_type: // A safepoint can't overlap a call.
|
|
default:
|
|
@@ -675,8 +700,8 @@ address CompiledDirectStaticCall::find_stub_for(address instruction) {
|
|
return NULL;
|
|
}
|
|
|
|
-address CompiledDirectStaticCall::find_stub() {
|
|
- return CompiledDirectStaticCall::find_stub_for(instruction_address());
|
|
+address CompiledDirectStaticCall::find_stub(bool is_aot) {
|
|
+ return CompiledDirectStaticCall::find_stub_for(instruction_address(), is_aot);
|
|
}
|
|
|
|
address CompiledDirectStaticCall::resolve_call_stub() const {
|
|
@@ -709,6 +734,8 @@ void CompiledDirectStaticCall::print() {
|
|
tty->print("clean");
|
|
} else if (is_call_to_compiled()) {
|
|
tty->print("compiled");
|
|
+ } else if (is_call_to_far()) {
|
|
+ tty->print("far");
|
|
} else if (is_call_to_interpreted()) {
|
|
tty->print("interpreted");
|
|
}
|
|
diff --git a/src/hotspot/share/code/compiledIC.hpp b/src/hotspot/share/code/compiledIC.hpp
|
|
index ca4190abc..534cec05f 100644
|
|
--- a/src/hotspot/share/code/compiledIC.hpp
|
|
+++ b/src/hotspot/share/code/compiledIC.hpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 1997, 2021, 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
|
|
@@ -84,6 +84,7 @@ class CompiledICInfo : public StackObj {
|
|
bool _is_icholder; // Is the cached value a CompiledICHolder*
|
|
bool _is_optimized; // it is an optimized virtual call (i.e., can be statically bound)
|
|
bool _to_interpreter; // Call it to interpreter
|
|
+ bool _to_aot; // Call it to aot code
|
|
bool _release_icholder;
|
|
public:
|
|
address entry() const { return _entry; }
|
|
@@ -98,11 +99,13 @@ class CompiledICInfo : public StackObj {
|
|
}
|
|
bool is_optimized() const { return _is_optimized; }
|
|
bool to_interpreter() const { return _to_interpreter; }
|
|
+ bool to_aot() const { return _to_aot; }
|
|
|
|
void set_compiled_entry(address entry, Klass* klass, bool is_optimized) {
|
|
_entry = entry;
|
|
_cached_value = (void*)klass;
|
|
_to_interpreter = false;
|
|
+ _to_aot = false;
|
|
_is_icholder = false;
|
|
_is_optimized = is_optimized;
|
|
_release_icholder = false;
|
|
@@ -112,6 +115,17 @@ class CompiledICInfo : public StackObj {
|
|
_entry = entry;
|
|
_cached_value = (void*)method;
|
|
_to_interpreter = true;
|
|
+ _to_aot = false;
|
|
+ _is_icholder = false;
|
|
+ _is_optimized = true;
|
|
+ _release_icholder = false;
|
|
+ }
|
|
+
|
|
+ void set_aot_entry(address entry, Method* method) {
|
|
+ _entry = entry;
|
|
+ _cached_value = (void*)method;
|
|
+ _to_interpreter = false;
|
|
+ _to_aot = true;
|
|
_is_icholder = false;
|
|
_is_optimized = true;
|
|
_release_icholder = false;
|
|
@@ -121,13 +135,14 @@ class CompiledICInfo : public StackObj {
|
|
_entry = entry;
|
|
_cached_value = (void*)icholder;
|
|
_to_interpreter = true;
|
|
+ _to_aot = false;
|
|
_is_icholder = true;
|
|
_is_optimized = false;
|
|
_release_icholder = true;
|
|
}
|
|
|
|
CompiledICInfo(): _entry(NULL), _cached_value(NULL), _is_icholder(false),
|
|
- _is_optimized(false), _to_interpreter(false), _release_icholder(false) {
|
|
+ _is_optimized(false), _to_interpreter(false), _to_aot(false), _release_icholder(false) {
|
|
}
|
|
~CompiledICInfo() {
|
|
// In rare cases the info is computed but not used, so release any
|
|
@@ -326,6 +341,7 @@ class StaticCallInfo {
|
|
address _entry; // Entrypoint
|
|
methodHandle _callee; // Callee (used when calling interpreter)
|
|
bool _to_interpreter; // call to interpreted method (otherwise compiled)
|
|
+ bool _to_aot; // call to aot method (otherwise compiled)
|
|
|
|
friend class CompiledStaticCall;
|
|
friend class CompiledDirectStaticCall;
|
|
@@ -344,6 +360,9 @@ class CompiledStaticCall : public ResourceObj {
|
|
static int to_interp_stub_size();
|
|
static int to_trampoline_stub_size();
|
|
static int reloc_to_interp_stub();
|
|
+ static void emit_to_aot_stub(CodeBuffer &cbuf, address mark = NULL);
|
|
+ static int to_aot_stub_size();
|
|
+ static int reloc_to_aot_stub();
|
|
|
|
// Compute entry point given a method
|
|
static void compute_entry(const methodHandle& m, bool caller_is_nmethod, StaticCallInfo& info);
|
|
@@ -369,6 +388,9 @@ public:
|
|
protected:
|
|
virtual address resolve_call_stub() const = 0;
|
|
virtual void set_destination_mt_safe(address dest) = 0;
|
|
+#if INCLUDE_AOT
|
|
+ virtual void set_to_far(const methodHandle& callee, address entry) = 0;
|
|
+#endif
|
|
virtual void set_to_interpreted(const methodHandle& callee, address entry) = 0;
|
|
virtual const char* name() const = 0;
|
|
|
|
@@ -385,6 +407,9 @@ private:
|
|
void verify_mt_safe(const methodHandle& callee, address entry,
|
|
NativeMovConstReg* method_holder,
|
|
NativeJump* jump) PRODUCT_RETURN;
|
|
+#if INCLUDE_AOT
|
|
+ void set_to_far(const methodHandle& callee, address entry);
|
|
+#endif
|
|
address instruction_address() const { return _call->instruction_address(); }
|
|
void set_destination_mt_safe(address dest) { _call->set_destination_mt_safe(dest); }
|
|
|
|
@@ -414,10 +439,11 @@ private:
|
|
|
|
// State
|
|
virtual bool is_call_to_interpreted() const;
|
|
+ bool is_call_to_far() const;
|
|
|
|
// Stub support
|
|
- static address find_stub_for(address instruction);
|
|
- address find_stub();
|
|
+ static address find_stub_for(address instruction, bool is_aot);
|
|
+ address find_stub(bool is_aot);
|
|
static void set_stub_to_clean(static_stub_Relocation* static_stub);
|
|
|
|
// Misc.
|
|
diff --git a/src/hotspot/share/code/compiledMethod.cpp b/src/hotspot/share/code/compiledMethod.cpp
|
|
index 4e42b555d..bda6d74c6 100644
|
|
--- a/src/hotspot/share/code/compiledMethod.cpp
|
|
+++ b/src/hotspot/share/code/compiledMethod.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2015, 2021, 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
|
|
@@ -72,6 +72,7 @@ CompiledMethod::CompiledMethod(Method* method, const char* name, CompilerType ty
|
|
|
|
void CompiledMethod::init_defaults() {
|
|
{ // avoid uninitialized fields, even for short time periods
|
|
+ _is_far_code = false;
|
|
_scopes_data_begin = NULL;
|
|
_deopt_handler_begin = NULL;
|
|
_deopt_mh_handler_begin = NULL;
|
|
diff --git a/src/hotspot/share/code/compiledMethod.hpp b/src/hotspot/share/code/compiledMethod.hpp
|
|
index 6c979f67a..737e4bc15 100644
|
|
--- a/src/hotspot/share/code/compiledMethod.hpp
|
|
+++ b/src/hotspot/share/code/compiledMethod.hpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2015, 2021, 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
|
|
@@ -152,6 +152,9 @@ protected:
|
|
|
|
MarkForDeoptimizationStatus _mark_for_deoptimization_status; // Used for stack deoptimization
|
|
|
|
+ bool _is_far_code; // Code is far from CodeCache.
|
|
+ // Have to use far call instructions to call it from code in CodeCache.
|
|
+
|
|
// set during construction
|
|
unsigned int _has_unsafe_access:1; // May fault due to unsafe access.
|
|
unsigned int _has_method_handle_invokes:1; // Has this method MethodHandle invokes?
|
|
@@ -331,6 +334,8 @@ public:
|
|
|
|
const char* state() const;
|
|
|
|
+ bool is_far_code() const { return _is_far_code; }
|
|
+
|
|
bool inlinecache_check_contains(address addr) const {
|
|
return (addr >= code_begin() && addr < verified_entry_point());
|
|
}
|
|
diff --git a/src/hotspot/share/code/nmethod.cpp b/src/hotspot/share/code/nmethod.cpp
|
|
index eef8e6b4b..f45270b01 100644
|
|
--- a/src/hotspot/share/code/nmethod.cpp
|
|
+++ b/src/hotspot/share/code/nmethod.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 1997, 2021, 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
|
|
@@ -441,6 +441,7 @@ void nmethod::init_defaults() {
|
|
_stack_traversal_mark = 0;
|
|
_load_reported = false; // jvmti state
|
|
_unload_reported = false;
|
|
+ _is_far_code = false; // nmethods are located in CodeCache
|
|
|
|
#ifdef ASSERT
|
|
_oops_are_stale = false;
|
|
@@ -2379,6 +2380,7 @@ nmethodLocker::nmethodLocker(address pc) {
|
|
// should pass zombie_ok == true.
|
|
void nmethodLocker::lock_nmethod(CompiledMethod* cm, bool zombie_ok) {
|
|
if (cm == NULL) return;
|
|
+ if (cm->is_aot()) return; // FIXME: Revisit once _lock_count is added to aot_method
|
|
nmethod* nm = cm->as_nmethod();
|
|
Atomic::inc(&nm->_lock_count);
|
|
assert(zombie_ok || !nm->is_zombie(), "cannot lock a zombie method: %p", nm);
|
|
@@ -2386,6 +2388,7 @@ void nmethodLocker::lock_nmethod(CompiledMethod* cm, bool zombie_ok) {
|
|
|
|
void nmethodLocker::unlock_nmethod(CompiledMethod* cm) {
|
|
if (cm == NULL) return;
|
|
+ if (cm->is_aot()) return; // FIXME: Revisit once _lock_count is added to aot_method
|
|
nmethod* nm = cm->as_nmethod();
|
|
Atomic::dec(&nm->_lock_count);
|
|
assert(nm->_lock_count >= 0, "unmatched nmethod lock/unlock");
|
|
@@ -2533,11 +2536,11 @@ void nmethod::verify_scopes() {
|
|
verify_interrupt_point(iter.addr());
|
|
break;
|
|
case relocInfo::opt_virtual_call_type:
|
|
- stub = iter.opt_virtual_call_reloc()->static_stub();
|
|
+ stub = iter.opt_virtual_call_reloc()->static_stub(false);
|
|
verify_interrupt_point(iter.addr());
|
|
break;
|
|
case relocInfo::static_call_type:
|
|
- stub = iter.static_call_reloc()->static_stub();
|
|
+ stub = iter.static_call_reloc()->static_stub(false);
|
|
//verify_interrupt_point(iter.addr());
|
|
break;
|
|
case relocInfo::runtime_call_type:
|
|
@@ -3480,11 +3483,28 @@ public:
|
|
}
|
|
|
|
virtual void set_destination_mt_safe(address dest) {
|
|
+#if INCLUDE_AOT
|
|
+ if (UseAOT) {
|
|
+ CodeBlob* callee = CodeCache::find_blob(dest);
|
|
+ CompiledMethod* cm = callee->as_compiled_method_or_null();
|
|
+ if (cm != NULL && cm->is_far_code()) {
|
|
+ // Temporary fix, see JDK-8143106
|
|
+ CompiledDirectStaticCall* csc = CompiledDirectStaticCall::at(instruction_address());
|
|
+ csc->set_to_far(methodHandle(Thread::current(), cm->method()), dest);
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+#endif
|
|
_call->set_destination_mt_safe(dest);
|
|
}
|
|
|
|
virtual void set_to_interpreted(const methodHandle& method, CompiledICInfo& info) {
|
|
CompiledDirectStaticCall* csc = CompiledDirectStaticCall::at(instruction_address());
|
|
+#if INCLUDE_AOT
|
|
+ if (info.to_aot()) {
|
|
+ csc->set_to_far(method, info.entry());
|
|
+ } else
|
|
+#endif
|
|
{
|
|
csc->set_to_interpreted(method, info.entry());
|
|
}
|
|
diff --git a/src/hotspot/share/code/relocInfo.cpp b/src/hotspot/share/code/relocInfo.cpp
|
|
index 47769c53a..4e9e3177d 100644
|
|
--- a/src/hotspot/share/code/relocInfo.cpp
|
|
+++ b/src/hotspot/share/code/relocInfo.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 1997, 2021, 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
|
|
@@ -415,14 +415,18 @@ void static_stub_Relocation::pack_data_to(CodeSection* dest) {
|
|
short* p = (short*) dest->locs_end();
|
|
CodeSection* insts = dest->outer()->insts();
|
|
normalize_address(_static_call, insts);
|
|
- p = pack_1_int_to(p, scaled_offset(_static_call, insts->start()));
|
|
+ jint is_aot = _is_aot ? 1 : 0;
|
|
+ p = pack_2_ints_to(p, scaled_offset(_static_call, insts->start()), is_aot);
|
|
dest->set_locs_end((relocInfo*) p);
|
|
}
|
|
|
|
void static_stub_Relocation::unpack_data() {
|
|
address base = binding()->section_start(CodeBuffer::SECT_INSTS);
|
|
- jint offset = unpack_1_int();
|
|
+ jint offset;
|
|
+ jint is_aot;
|
|
+ unpack_2_ints(offset, is_aot);
|
|
_static_call = address_from_scaled_offset(offset, base);
|
|
+ _is_aot = (is_aot == 1);
|
|
}
|
|
|
|
void trampoline_stub_Relocation::pack_data_to(CodeSection* dest ) {
|
|
@@ -644,14 +648,14 @@ bool opt_virtual_call_Relocation::clear_inline_cache() {
|
|
return set_to_clean_no_ic_refill(icache);
|
|
}
|
|
|
|
-address opt_virtual_call_Relocation::static_stub() {
|
|
+address opt_virtual_call_Relocation::static_stub(bool is_aot) {
|
|
// search for the static stub who points back to this static call
|
|
address static_call_addr = addr();
|
|
RelocIterator iter(code());
|
|
while (iter.next()) {
|
|
if (iter.type() == relocInfo::static_stub_type) {
|
|
static_stub_Relocation* stub_reloc = iter.static_stub_reloc();
|
|
- if (stub_reloc->static_call() == static_call_addr) {
|
|
+ if (stub_reloc->static_call() == static_call_addr && stub_reloc->is_aot() == is_aot) {
|
|
return iter.addr();
|
|
}
|
|
}
|
|
@@ -685,14 +689,14 @@ bool static_call_Relocation::clear_inline_cache() {
|
|
}
|
|
|
|
|
|
-address static_call_Relocation::static_stub() {
|
|
+address static_call_Relocation::static_stub(bool is_aot) {
|
|
// search for the static stub who points back to this static call
|
|
address static_call_addr = addr();
|
|
RelocIterator iter(code());
|
|
while (iter.next()) {
|
|
if (iter.type() == relocInfo::static_stub_type) {
|
|
static_stub_Relocation* stub_reloc = iter.static_stub_reloc();
|
|
- if (stub_reloc->static_call() == static_call_addr) {
|
|
+ if (stub_reloc->static_call() == static_call_addr && stub_reloc->is_aot() == is_aot) {
|
|
return iter.addr();
|
|
}
|
|
}
|
|
diff --git a/src/hotspot/share/code/relocInfo.hpp b/src/hotspot/share/code/relocInfo.hpp
|
|
index 57d2126fb..9a1f5327c 100644
|
|
--- a/src/hotspot/share/code/relocInfo.hpp
|
|
+++ b/src/hotspot/share/code/relocInfo.hpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 1997, 2021, 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
|
|
@@ -1091,7 +1091,7 @@ class opt_virtual_call_Relocation : public CallRelocation {
|
|
bool clear_inline_cache();
|
|
|
|
// find the matching static_stub
|
|
- address static_stub();
|
|
+ address static_stub(bool is_aot);
|
|
};
|
|
|
|
|
|
@@ -1123,23 +1123,24 @@ class static_call_Relocation : public CallRelocation {
|
|
bool clear_inline_cache();
|
|
|
|
// find the matching static_stub
|
|
- address static_stub();
|
|
+ address static_stub(bool is_aot);
|
|
};
|
|
|
|
class static_stub_Relocation : public Relocation {
|
|
public:
|
|
- static RelocationHolder spec(address static_call) {
|
|
+ static RelocationHolder spec(address static_call, bool is_aot = false) {
|
|
RelocationHolder rh = newHolder();
|
|
- new(rh) static_stub_Relocation(static_call);
|
|
+ new(rh) static_stub_Relocation(static_call, is_aot);
|
|
return rh;
|
|
}
|
|
|
|
private:
|
|
address _static_call; // location of corresponding static_call
|
|
+ bool _is_aot; // trampoline to aot code
|
|
|
|
- static_stub_Relocation(address static_call)
|
|
+ static_stub_Relocation(address static_call, bool is_aot)
|
|
: Relocation(relocInfo::static_stub_type),
|
|
- _static_call(static_call) { }
|
|
+ _static_call(static_call), _is_aot(is_aot) { }
|
|
|
|
friend class RelocIterator;
|
|
static_stub_Relocation() : Relocation(relocInfo::static_stub_type) { }
|
|
@@ -1148,6 +1149,7 @@ class static_stub_Relocation : public Relocation {
|
|
bool clear_inline_cache();
|
|
|
|
address static_call() { return _static_call; }
|
|
+ bool is_aot() { return _is_aot; }
|
|
|
|
// data is packed as a scaled offset in "1_int" format: [c] or [Cc]
|
|
void pack_data_to(CodeSection* dest);
|
|
diff --git a/src/hotspot/share/compiler/compilationPolicy.cpp b/src/hotspot/share/compiler/compilationPolicy.cpp
|
|
index 026915246..68297a5d0 100644
|
|
--- a/src/hotspot/share/compiler/compilationPolicy.cpp
|
|
+++ b/src/hotspot/share/compiler/compilationPolicy.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2010, 2022, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2010, 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
|
|
@@ -235,6 +235,8 @@ public:
|
|
scale *= threshold_scaling;
|
|
}
|
|
switch(cur_level) {
|
|
+ case CompLevel_aot:
|
|
+ return b >= Tier3AOTBackEdgeThreshold * scale;
|
|
case CompLevel_none:
|
|
case CompLevel_limited_profile:
|
|
return b >= Tier3BackEdgeThreshold * scale;
|
|
@@ -248,6 +250,10 @@ public:
|
|
static bool apply(const methodHandle& method, CompLevel cur_level, int i, int b) {
|
|
double k = 1;
|
|
switch(cur_level) {
|
|
+ case CompLevel_aot: {
|
|
+ k = CompilationModeFlag::disable_intermediate() ? 1 : CompilationPolicy::threshold_scale(CompLevel_full_profile, Tier3LoadFeedback);
|
|
+ break;
|
|
+ }
|
|
case CompLevel_none:
|
|
// Fall through
|
|
case CompLevel_limited_profile: {
|
|
@@ -273,6 +279,9 @@ public:
|
|
scale *= threshold_scaling;
|
|
}
|
|
switch(cur_level) {
|
|
+ case CompLevel_aot:
|
|
+ return (i >= Tier3AOTInvocationThreshold * scale) ||
|
|
+ (i >= Tier3AOTMinInvocationThreshold * scale && i + b >= Tier3AOTCompileThreshold * scale);
|
|
case CompLevel_none:
|
|
case CompLevel_limited_profile:
|
|
return (i >= Tier3InvocationThreshold * scale) ||
|
|
@@ -288,6 +297,10 @@ public:
|
|
static bool apply(const methodHandle& method, CompLevel cur_level, int i, int b) {
|
|
double k = 1;
|
|
switch(cur_level) {
|
|
+ case CompLevel_aot: {
|
|
+ k = CompilationModeFlag::disable_intermediate() ? 1 : CompilationPolicy::threshold_scale(CompLevel_full_profile, Tier3LoadFeedback);
|
|
+ break;
|
|
+ }
|
|
case CompLevel_none:
|
|
case CompLevel_limited_profile: {
|
|
k = CompilationPolicy::threshold_scale(CompLevel_full_profile, Tier3LoadFeedback);
|
|
@@ -507,8 +520,8 @@ bool CompilationPolicy::verify_level(CompLevel level) {
|
|
return false;
|
|
}
|
|
|
|
- // Interpreter level is always valid.
|
|
- if (level == CompLevel_none) {
|
|
+ // AOT and interpreter levels are always valid.
|
|
+ if (level == CompLevel_aot || level == CompLevel_none) {
|
|
return true;
|
|
}
|
|
if (CompilationModeFlag::normal()) {
|
|
@@ -750,7 +763,7 @@ void CompilationPolicy::compile(const methodHandle& mh, int bci, CompLevel level
|
|
|
|
if (level == CompLevel_none) {
|
|
if (mh->has_compiled_code()) {
|
|
- // Happens when we switch to interpreter to profile.
|
|
+ // Happens when we switch from AOT to interpreter to profile.
|
|
MutexLocker ml(Compile_lock);
|
|
NoSafepointVerifier nsv;
|
|
if (mh->has_compiled_code()) {
|
|
@@ -764,6 +777,24 @@ void CompilationPolicy::compile(const methodHandle& mh, int bci, CompLevel level
|
|
}
|
|
return;
|
|
}
|
|
+ if (level == CompLevel_aot) {
|
|
+ if (mh->has_aot_code()) {
|
|
+ if (PrintTieredEvents) {
|
|
+ print_event(COMPILE, mh(), mh(), bci, level);
|
|
+ }
|
|
+ MutexLocker ml(Compile_lock);
|
|
+ NoSafepointVerifier nsv;
|
|
+ if (mh->has_aot_code() && mh->code() != mh->aot_code()) {
|
|
+ mh->aot_code()->make_entrant();
|
|
+ if (mh->has_compiled_code()) {
|
|
+ mh->code()->make_not_entrant();
|
|
+ }
|
|
+ MutexLocker pl(CompiledMethod_lock, Mutex::_no_safepoint_check_flag);
|
|
+ Method::set_code(mh, mh->aot_code());
|
|
+ }
|
|
+ }
|
|
+ return;
|
|
+ }
|
|
|
|
if (!CompilationModeFlag::disable_intermediate()) {
|
|
// Check if the method can be compiled. If it cannot be compiled with C1, continue profiling
|
|
@@ -1016,6 +1047,16 @@ CompLevel CompilationPolicy::common(const methodHandle& method, CompLevel cur_le
|
|
} else {
|
|
switch(cur_level) {
|
|
default: break;
|
|
+ case CompLevel_aot:
|
|
+ // If we were at full profile level, would we switch to full opt?
|
|
+ if (common<Predicate>(method, CompLevel_full_profile, disable_feedback) == CompLevel_full_optimization) {
|
|
+ next_level = CompLevel_full_optimization;
|
|
+ } else if (disable_feedback || (CompileBroker::queue_size(CompLevel_full_optimization) <=
|
|
+ Tier3DelayOff * compiler_count(CompLevel_full_optimization) &&
|
|
+ Predicate::apply(method, cur_level, i, b))) {
|
|
+ next_level = CompilationModeFlag::disable_intermediate() ? CompLevel_none : CompLevel_full_profile;
|
|
+ }
|
|
+ break;
|
|
case CompLevel_none:
|
|
// If we were at full profile level, would we switch to full opt?
|
|
if (common<Predicate>(method, CompLevel_full_profile, disable_feedback) == CompLevel_full_optimization) {
|
|
@@ -1120,6 +1161,26 @@ CompLevel CompilationPolicy::loop_event(const methodHandle& method, CompLevel cu
|
|
return next_level;
|
|
}
|
|
|
|
+bool CompilationPolicy::maybe_switch_to_aot(const methodHandle& mh, CompLevel cur_level, CompLevel next_level, TRAPS) {
|
|
+ if (UseAOT) {
|
|
+ if (cur_level == CompLevel_full_profile || cur_level == CompLevel_none) {
|
|
+ // If the current level is full profile or interpreter and we're switching to any other level,
|
|
+ // activate the AOT code back first so that we won't waste time overprofiling.
|
|
+ compile(mh, InvocationEntryBci, CompLevel_aot, THREAD);
|
|
+ // Fall through for JIT compilation.
|
|
+ }
|
|
+ if (next_level == CompLevel_limited_profile && cur_level != CompLevel_aot && mh->has_aot_code()) {
|
|
+ // If the next level is limited profile, use the aot code (if there is any),
|
|
+ // since it's essentially the same thing.
|
|
+ compile(mh, InvocationEntryBci, CompLevel_aot, THREAD);
|
|
+ // Not need to JIT, we're done.
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+ return false;
|
|
+}
|
|
+
|
|
+
|
|
// Handle the invocation event.
|
|
void CompilationPolicy::method_invocation_event(const methodHandle& mh, const methodHandle& imh,
|
|
CompLevel level, CompiledMethod* nm, TRAPS) {
|
|
@@ -1128,6 +1189,10 @@ void CompilationPolicy::method_invocation_event(const methodHandle& mh, const me
|
|
}
|
|
CompLevel next_level = call_event(mh, level, THREAD);
|
|
if (next_level != level) {
|
|
+ if (maybe_switch_to_aot(mh, level, next_level, THREAD)) {
|
|
+ // No JITting necessary
|
|
+ return;
|
|
+ }
|
|
if (is_compilation_enabled() && !CompileBroker::compilation_is_in_queue(mh)) {
|
|
compile(mh, InvocationEntryBci, next_level, THREAD);
|
|
}
|
|
@@ -1158,7 +1223,14 @@ void CompilationPolicy::method_back_branch_event(const methodHandle& mh, const m
|
|
// enough calls.
|
|
CompLevel cur_level, next_level;
|
|
if (mh() != imh()) { // If there is an enclosing method
|
|
- {
|
|
+ if (level == CompLevel_aot) {
|
|
+ // Recompile the enclosing method to prevent infinite OSRs. Stay at AOT level while it's compiling.
|
|
+ if (max_osr_level != CompLevel_none && !CompileBroker::compilation_is_in_queue(mh)) {
|
|
+ CompLevel enclosing_level = limit_level(CompLevel_full_profile);
|
|
+ compile(mh, InvocationEntryBci, enclosing_level, THREAD);
|
|
+ }
|
|
+ } else {
|
|
+ // Current loop event level is not AOT
|
|
guarantee(nm != NULL, "Should have nmethod here");
|
|
cur_level = comp_level(mh());
|
|
next_level = call_event(mh, cur_level, THREAD);
|
|
@@ -1190,7 +1262,7 @@ void CompilationPolicy::method_back_branch_event(const methodHandle& mh, const m
|
|
next_level = CompLevel_full_profile;
|
|
}
|
|
if (cur_level != next_level) {
|
|
- if (!CompileBroker::compilation_is_in_queue(mh)) {
|
|
+ if (!maybe_switch_to_aot(mh, cur_level, next_level, THREAD) && !CompileBroker::compilation_is_in_queue(mh)) {
|
|
compile(mh, InvocationEntryBci, next_level, THREAD);
|
|
}
|
|
}
|
|
@@ -1199,7 +1271,7 @@ void CompilationPolicy::method_back_branch_event(const methodHandle& mh, const m
|
|
cur_level = comp_level(mh());
|
|
next_level = call_event(mh, cur_level, THREAD);
|
|
if (next_level != cur_level) {
|
|
- if (!CompileBroker::compilation_is_in_queue(mh)) {
|
|
+ if (!maybe_switch_to_aot(mh, cur_level, next_level, THREAD) && !CompileBroker::compilation_is_in_queue(mh)) {
|
|
compile(mh, InvocationEntryBci, next_level, THREAD);
|
|
}
|
|
}
|
|
diff --git a/src/hotspot/share/compiler/compilationPolicy.hpp b/src/hotspot/share/compiler/compilationPolicy.hpp
|
|
index 75571674f..8e870da38 100644
|
|
--- a/src/hotspot/share/compiler/compilationPolicy.hpp
|
|
+++ b/src/hotspot/share/compiler/compilationPolicy.hpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2010, 2022, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2010, 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
|
|
@@ -210,6 +210,8 @@ class CompilationPolicy : AllStatic {
|
|
// Is method profiled enough?
|
|
static bool is_method_profiled(const methodHandle& method);
|
|
|
|
+ static bool maybe_switch_to_aot(const methodHandle& mh, CompLevel cur_level, CompLevel next_level, TRAPS);
|
|
+
|
|
static void set_c1_count(int x) { _c1_count = x; }
|
|
static void set_c2_count(int x) { _c2_count = x; }
|
|
|
|
diff --git a/src/hotspot/share/compiler/compilerDefinitions.cpp b/src/hotspot/share/compiler/compilerDefinitions.cpp
|
|
index 2784d6a96..23b550192 100644
|
|
--- a/src/hotspot/share/compiler/compilerDefinitions.cpp
|
|
+++ b/src/hotspot/share/compiler/compilerDefinitions.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2016, 2022, 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
|
|
@@ -174,6 +174,9 @@ void CompilerConfig::set_client_emulation_mode_flags() {
|
|
#if INCLUDE_JVMCI
|
|
FLAG_SET_ERGO(EnableJVMCI, false);
|
|
FLAG_SET_ERGO(UseJVMCICompiler, false);
|
|
+#endif
|
|
+#if INCLUDE_AOT
|
|
+ FLAG_SET_ERGO(UseAOT, false);
|
|
#endif
|
|
if (FLAG_IS_DEFAULT(NeverActAsServerClassMachine)) {
|
|
FLAG_SET_ERGO(NeverActAsServerClassMachine, true);
|
|
@@ -209,6 +212,7 @@ void CompilerConfig::set_client_emulation_mode_flags() {
|
|
bool CompilerConfig::is_compilation_mode_selected() {
|
|
return !FLAG_IS_DEFAULT(TieredCompilation) ||
|
|
!FLAG_IS_DEFAULT(TieredStopAtLevel) ||
|
|
+ !FLAG_IS_DEFAULT(UseAOT) ||
|
|
!FLAG_IS_DEFAULT(CompilationMode)
|
|
JVMCI_ONLY(|| !FLAG_IS_DEFAULT(EnableJVMCI)
|
|
|| !FLAG_IS_DEFAULT(UseJVMCICompiler));
|
|
@@ -278,6 +282,14 @@ void CompilerConfig::set_legacy_emulation_flags() {
|
|
FLAG_SET_ERGO(Tier4BackEdgeThreshold, osr_threshold);
|
|
FLAG_SET_ERGO(Tier0ProfilingStartPercentage, InterpreterProfilePercentage);
|
|
}
|
|
+#if INCLUDE_AOT
|
|
+ if (UseAOT) {
|
|
+ FLAG_SET_ERGO(Tier3AOTInvocationThreshold, threshold);
|
|
+ FLAG_SET_ERGO(Tier3AOTMinInvocationThreshold, threshold);
|
|
+ FLAG_SET_ERGO(Tier3AOTCompileThreshold, threshold);
|
|
+ FLAG_SET_ERGO(Tier3AOTBackEdgeThreshold, CompilerConfig::is_c1_only() ? osr_threshold : osr_profile_threshold);
|
|
+ }
|
|
+#endif
|
|
} else {
|
|
// Normal tiered mode, ignore legacy flags
|
|
}
|
|
@@ -325,6 +337,23 @@ void CompilerConfig::set_compilation_policy_flags() {
|
|
FLAG_SET_DEFAULT(Tier0ProfilingStartPercentage, 33);
|
|
}
|
|
|
|
+#if INCLUDE_AOT
|
|
+ if (UseAOT) {
|
|
+ if (FLAG_IS_DEFAULT(Tier3AOTInvocationThreshold)) {
|
|
+ FLAG_SET_DEFAULT(Tier3AOTInvocationThreshold, 200);
|
|
+ }
|
|
+ if (FLAG_IS_DEFAULT(Tier3AOTMinInvocationThreshold)) {
|
|
+ FLAG_SET_DEFAULT(Tier3AOTMinInvocationThreshold, 100);
|
|
+ }
|
|
+ if (FLAG_IS_DEFAULT(Tier3AOTCompileThreshold)) {
|
|
+ FLAG_SET_DEFAULT(Tier3AOTCompileThreshold, 2000);
|
|
+ }
|
|
+ if (FLAG_IS_DEFAULT(Tier3AOTBackEdgeThreshold)) {
|
|
+ FLAG_SET_DEFAULT(Tier3AOTBackEdgeThreshold, 2000);
|
|
+ }
|
|
+ }
|
|
+#endif
|
|
+
|
|
if (FLAG_IS_DEFAULT(Tier4InvocationThreshold)) {
|
|
FLAG_SET_DEFAULT(Tier4InvocationThreshold, 5000);
|
|
}
|
|
diff --git a/src/hotspot/share/compiler/compilerDefinitions.hpp b/src/hotspot/share/compiler/compilerDefinitions.hpp
|
|
index 1c8096918..1f8d3f1a6 100644
|
|
--- a/src/hotspot/share/compiler/compilerDefinitions.hpp
|
|
+++ b/src/hotspot/share/compiler/compilerDefinitions.hpp
|
|
@@ -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
|
|
@@ -55,6 +55,7 @@ enum MethodCompilation {
|
|
|
|
// Enumeration to distinguish tiers of compilation
|
|
enum CompLevel {
|
|
+ CompLevel_aot = -2,
|
|
CompLevel_any = -1, // Used for querying the state
|
|
CompLevel_all = -1, // Used for changing the state
|
|
CompLevel_none = 0, // Interpreter
|
|
@@ -137,16 +138,18 @@ public:
|
|
constexpr static bool has_c2() { return COMPILER2_PRESENT(true) NOT_COMPILER2(false); }
|
|
constexpr static bool has_jvmci() { return JVMCI_ONLY(true) NOT_JVMCI(false); }
|
|
constexpr static bool has_tiered() { return has_c1() && (has_c2() || has_jvmci()); }
|
|
+ constexpr static bool has_aot() { return AOT_ONLY(true) NOT_AOT(false); }
|
|
|
|
+ static bool is_aot() { return AOT_ONLY(has_aot() && UseAOT) NOT_AOT(false); }
|
|
static bool is_jvmci_compiler() { return JVMCI_ONLY(has_jvmci() && UseJVMCICompiler) NOT_JVMCI(false); }
|
|
static bool is_jvmci() { return JVMCI_ONLY(has_jvmci() && EnableJVMCI) NOT_JVMCI(false); }
|
|
static bool is_interpreter_only();
|
|
|
|
// is_*_only() functions describe situations in which the JVM is in one way or another
|
|
// forced to use a particular compiler or their combination. The constraint functions
|
|
- // deliberately ignore the fact that there may also be methods installed
|
|
+ // deliberately ignore the fact that there may also be AOT methods and methods installed
|
|
// through JVMCI (where the JVMCI compiler was invoked not through the broker). Be sure
|
|
- // to check for those (using is_jvmci()) in situations where it matters.
|
|
+ // to check for those (using is_jvmci() and is_aot()) in situations where it matters.
|
|
//
|
|
|
|
// Is the JVM in a configuration that permits only c1-compiled methods (level 1,2,3)?
|
|
@@ -160,13 +163,13 @@ public:
|
|
return false;
|
|
}
|
|
|
|
- static bool is_c1_or_interpreter_only_no_jvmci() {
|
|
+ static bool is_c1_or_interpreter_only_no_aot_or_jvmci() {
|
|
assert(is_jvmci_compiler() && is_jvmci() || !is_jvmci_compiler(), "JVMCI compiler implies enabled JVMCI");
|
|
- return !is_jvmci() && (is_interpreter_only() || is_c1_only());
|
|
+ return !is_aot() && !is_jvmci() && (is_interpreter_only() || is_c1_only());
|
|
}
|
|
|
|
- static bool is_c1_only_no_jvmci() {
|
|
- return is_c1_only() && !is_jvmci();
|
|
+ static bool is_c1_only_no_aot_or_jvmci() {
|
|
+ return is_c1_only() && !is_aot() && !is_jvmci();
|
|
}
|
|
|
|
// Is the JVM in a configuration that permits only c1-compiled methods at level 1?
|
|
diff --git a/src/hotspot/share/compiler/compiler_globals.hpp b/src/hotspot/share/compiler/compiler_globals.hpp
|
|
index 6ec87001a..19c80e82a 100644
|
|
--- a/src/hotspot/share/compiler/compiler_globals.hpp
|
|
+++ b/src/hotspot/share/compiler/compiler_globals.hpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 1997, 2021, 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
|
|
@@ -190,6 +190,33 @@
|
|
"Back edge threshold at which tier 3 OSR compilation is invoked") \
|
|
range(0, max_jint) \
|
|
\
|
|
+ product(intx, Tier3AOTInvocationThreshold, 10000, \
|
|
+ "Compile if number of method invocations crosses this " \
|
|
+ "threshold if coming from AOT;" \
|
|
+ "with CompilationMode=high-only|high-only-quick-internal)" \
|
|
+ "determines when to transition from AOT to interpreter") \
|
|
+ range(0, max_jint) \
|
|
+ \
|
|
+ product(intx, Tier3AOTMinInvocationThreshold, 1000, \
|
|
+ "Minimum invocation to compile at tier 3 if coming from AOT;" \
|
|
+ "with CompilationMode=high-only|high-only-quick-internal)" \
|
|
+ "determines when to transition from AOT to interpreter") \
|
|
+ range(0, max_jint) \
|
|
+ \
|
|
+ product(intx, Tier3AOTCompileThreshold, 15000, \
|
|
+ "Threshold at which tier 3 compilation is invoked (invocation " \
|
|
+ "minimum must be satisfied) if coming from AOT;" \
|
|
+ "with CompilationMode=high-only|high-only-quick-internal)" \
|
|
+ "determines when to transition from AOT to interpreter") \
|
|
+ range(0, max_jint) \
|
|
+ \
|
|
+ product(intx, Tier3AOTBackEdgeThreshold, 120000, \
|
|
+ "Back edge threshold at which tier 3 OSR compilation is invoked " \
|
|
+ "if coming from AOT;" \
|
|
+ "with CompilationMode=high-only|high-only-quick-internal)" \
|
|
+ "determines when to transition from AOT to interpreter") \
|
|
+ range(0, max_jint) \
|
|
+ \
|
|
product(intx, Tier4InvocationThreshold, 5000, \
|
|
"Compile if number of method invocations crosses this " \
|
|
"threshold") \
|
|
diff --git a/src/hotspot/share/compiler/disassembler.cpp b/src/hotspot/share/compiler/disassembler.cpp
|
|
index 4cc2f8781..d41d159fd 100644
|
|
--- a/src/hotspot/share/compiler/disassembler.cpp
|
|
+++ b/src/hotspot/share/compiler/disassembler.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2008, 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
|
|
@@ -893,9 +893,23 @@ void Disassembler::decode(CodeBlob* cb, outputStream* st) {
|
|
|
|
decode_env env(cb, st);
|
|
env.output()->print_cr("--------------------------------------------------------------------------------");
|
|
- env.output()->print("Decoding CodeBlob");
|
|
- if (cb->name() != NULL) {
|
|
- env.output()->print(", name: %s,", cb->name());
|
|
+ if (cb->is_aot()) {
|
|
+ env.output()->print("A ");
|
|
+ if (cb->is_compiled()) {
|
|
+ CompiledMethod* cm = (CompiledMethod*)cb;
|
|
+ env.output()->print("%d ",cm->compile_id());
|
|
+ cm->method()->method_holder()->name()->print_symbol_on(env.output());
|
|
+ env.output()->print(".");
|
|
+ cm->method()->name()->print_symbol_on(env.output());
|
|
+ cm->method()->signature()->print_symbol_on(env.output());
|
|
+ } else {
|
|
+ env.output()->print_cr("%s", cb->name());
|
|
+ }
|
|
+ } else {
|
|
+ env.output()->print("Decoding CodeBlob");
|
|
+ if (cb->name() != NULL) {
|
|
+ env.output()->print(", name: %s,", cb->name());
|
|
+ }
|
|
}
|
|
env.output()->print_cr(" at [" PTR_FORMAT ", " PTR_FORMAT "] " JLONG_FORMAT " bytes", p2i(cb->code_begin()), p2i(cb->code_end()), ((jlong)(cb->code_end() - cb->code_begin())));
|
|
|
|
diff --git a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp
|
|
index f6fd08bdc..52c004f45 100644
|
|
--- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp
|
|
+++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2013, 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
|
|
@@ -56,6 +56,7 @@ G1GCPhaseTimes::G1GCPhaseTimes(STWGCTimer* gc_timer, uint max_gc_threads) :
|
|
// Root scanning phases
|
|
_gc_par_phases[ThreadRoots] = new WorkerDataArray<double>("ThreadRoots", "Thread Roots (ms):", max_gc_threads);
|
|
_gc_par_phases[CLDGRoots] = new WorkerDataArray<double>("CLDGRoots", "CLDG Roots (ms):", max_gc_threads);
|
|
+ AOT_ONLY(_gc_par_phases[AOTCodeRoots] = new WorkerDataArray<double>("AOTCodeRoots", "AOT Root Scan (ms):", max_gc_threads);)
|
|
_gc_par_phases[CMRefRoots] = new WorkerDataArray<double>("CMRefRoots", "CM RefProcessor Roots (ms):", max_gc_threads);
|
|
|
|
for (auto id : EnumRange<OopStorageSet::StrongId>()) {
|
|
diff --git a/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp b/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp
|
|
index f374399df..395ff0593 100644
|
|
--- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp
|
|
+++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2013, 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
|
|
@@ -50,6 +50,7 @@ class G1GCPhaseTimes : public CHeapObj<mtGC> {
|
|
ExtRootScan,
|
|
ThreadRoots,
|
|
CLDGRoots,
|
|
+ AOT_ONLY(AOTCodeRoots COMMA)
|
|
CMRefRoots,
|
|
// For every strong OopStorage there will be one element in this enum,
|
|
// starting with StrongOopStorageSetRoots.
|
|
diff --git a/src/hotspot/share/gc/g1/g1RootProcessor.cpp b/src/hotspot/share/gc/g1/g1RootProcessor.cpp
|
|
index c8609718c..bad78b562 100644
|
|
--- a/src/hotspot/share/gc/g1/g1RootProcessor.cpp
|
|
+++ b/src/hotspot/share/gc/g1/g1RootProcessor.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2015, 2021, 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
|
|
@@ -45,6 +45,9 @@
|
|
#include "runtime/mutex.hpp"
|
|
#include "utilities/enumIterator.hpp"
|
|
#include "utilities/macros.hpp"
|
|
+#if INCLUDE_AOT
|
|
+#include "aot/aotLoader.hpp"
|
|
+#endif
|
|
|
|
G1RootProcessor::G1RootProcessor(G1CollectedHeap* g1h, uint n_workers) :
|
|
_g1h(g1h),
|
|
@@ -198,6 +201,15 @@ void G1RootProcessor::process_vm_roots(G1RootClosures* closures,
|
|
uint worker_id) {
|
|
OopClosure* strong_roots = closures->strong_oops();
|
|
|
|
+#if INCLUDE_AOT
|
|
+ if (_process_strong_tasks.try_claim_task(G1RP_PS_aot_oops_do)) {
|
|
+ if (UseAOT) {
|
|
+ G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::AOTCodeRoots, worker_id);
|
|
+ AOTLoader::oops_do(strong_roots);
|
|
+ }
|
|
+ }
|
|
+#endif
|
|
+
|
|
for (auto id : EnumRange<OopStorageSet::StrongId>()) {
|
|
G1GCPhaseTimes::GCParPhases phase = G1GCPhaseTimes::strong_oopstorage_phase(id);
|
|
G1GCParPhaseTimesTracker x(phase_times, phase, worker_id);
|
|
diff --git a/src/hotspot/share/gc/g1/g1RootProcessor.hpp b/src/hotspot/share/gc/g1/g1RootProcessor.hpp
|
|
index cdb843e57..403c36c5f 100644
|
|
--- a/src/hotspot/share/gc/g1/g1RootProcessor.hpp
|
|
+++ b/src/hotspot/share/gc/g1/g1RootProcessor.hpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2015, 2021, 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
|
|
@@ -55,6 +55,7 @@ class G1RootProcessor : public StackObj {
|
|
enum G1H_process_roots_tasks {
|
|
G1RP_PS_ClassLoaderDataGraph_oops_do,
|
|
G1RP_PS_CodeCache_oops_do,
|
|
+ AOT_ONLY(G1RP_PS_aot_oops_do COMMA)
|
|
G1RP_PS_refProcessor_oops_do,
|
|
// Leave this one last.
|
|
G1RP_PS_NumElements
|
|
diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.cpp b/src/hotspot/share/gc/parallel/psParallelCompact.cpp
|
|
index e588cae89..f5e64b844 100644
|
|
--- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp
|
|
+++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2005, 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
|
|
@@ -89,6 +89,9 @@
|
|
#if INCLUDE_JVMCI
|
|
#include "jvmci/jvmci.hpp"
|
|
#endif
|
|
+#if INCLUDE_AOT
|
|
+#include "aot/aotLoader.hpp"
|
|
+#endif
|
|
|
|
#include <math.h>
|
|
|
|
@@ -1987,6 +1990,9 @@ static void mark_from_roots_work(ParallelRootType::Value root_type, uint worker_
|
|
case ParallelRootType::code_cache:
|
|
// Do not treat nmethods as strong roots for mark/sweep, since we can unload them.
|
|
//ScavengableNMethods::scavengable_nmethods_do(CodeBlobToOopClosure(&mark_and_push_closure));
|
|
+#if INCLUDE_AOT
|
|
+ AOTLoader::oops_do(&mark_and_push_closure);
|
|
+#endif
|
|
break;
|
|
|
|
case ParallelRootType::sentinel:
|
|
@@ -2165,6 +2171,9 @@ class PSAdjustTask final : public AbstractGangTask {
|
|
|
|
enum PSAdjustSubTask {
|
|
PSAdjustSubTask_code_cache,
|
|
+#if INCLUDE_AOT
|
|
+ PSAdjustSubTask_aot,
|
|
+#endif
|
|
PSAdjustSubTask_old_ref_process,
|
|
PSAdjustSubTask_young_ref_process,
|
|
|
|
@@ -2208,6 +2217,11 @@ public:
|
|
CodeBlobToOopClosure adjust_code(&adjust, CodeBlobToOopClosure::FixRelocations);
|
|
CodeCache::blobs_do(&adjust_code);
|
|
}
|
|
+#if INCLUDE_AOT
|
|
+ if (_sub_tasks.try_claim_task(PSAdjustSubTask_aot)) {
|
|
+ AOTLoader::oops_do(&adjust);
|
|
+ }
|
|
+#endif
|
|
if (_sub_tasks.try_claim_task(PSAdjustSubTask_old_ref_process)) {
|
|
PSParallelCompact::ref_processor()->weak_oops_do(&adjust);
|
|
}
|
|
diff --git a/src/hotspot/share/gc/parallel/psScavenge.cpp b/src/hotspot/share/gc/parallel/psScavenge.cpp
|
|
index c4011fff4..98ec438ad 100644
|
|
--- a/src/hotspot/share/gc/parallel/psScavenge.cpp
|
|
+++ b/src/hotspot/share/gc/parallel/psScavenge.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2002, 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
|
|
@@ -69,6 +69,9 @@
|
|
#include "runtime/vmOperations.hpp"
|
|
#include "services/memoryService.hpp"
|
|
#include "utilities/stack.inline.hpp"
|
|
+#if INCLUDE_AOT
|
|
+#include "aot/aotLoader.hpp"
|
|
+#endif
|
|
|
|
HeapWord* PSScavenge::_to_space_top_before_gc = NULL;
|
|
int PSScavenge::_consecutive_skipped_scavenges = 0;
|
|
@@ -102,6 +105,9 @@ static void scavenge_roots_work(ParallelRootType::Value root_type, uint worker_i
|
|
{
|
|
MarkingCodeBlobClosure code_closure(&roots_to_old_closure, CodeBlobToOopClosure::FixRelocations);
|
|
ScavengableNMethods::nmethods_do(&code_closure);
|
|
+#if INCLUDE_AOT
|
|
+ AOTLoader::oops_do(&roots_closure);
|
|
+#endif
|
|
}
|
|
break;
|
|
|
|
diff --git a/src/hotspot/share/gc/shared/genCollectedHeap.cpp b/src/hotspot/share/gc/shared/genCollectedHeap.cpp
|
|
index 12a835554..ab050aa06 100644
|
|
--- a/src/hotspot/share/gc/shared/genCollectedHeap.cpp
|
|
+++ b/src/hotspot/share/gc/shared/genCollectedHeap.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2000, 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
|
|
@@ -78,6 +78,9 @@
|
|
#if INCLUDE_JVMCI
|
|
#include "jvmci/jvmci.hpp"
|
|
#endif
|
|
+#if INCLUDE_AOT
|
|
+#include "aot/aotLoader.hpp"
|
|
+#endif
|
|
|
|
GenCollectedHeap::GenCollectedHeap(Generation::Name young,
|
|
Generation::Name old,
|
|
@@ -789,6 +792,12 @@ void GenCollectedHeap::process_roots(ScanningOption so,
|
|
|
|
Threads::oops_do(strong_roots, roots_from_code_p);
|
|
|
|
+#if INCLUDE_AOT
|
|
+ if (UseAOT) {
|
|
+ AOTLoader::oops_do(strong_roots);
|
|
+ }
|
|
+#endif
|
|
+
|
|
OopStorageSet::strong_oops_do(strong_roots);
|
|
|
|
if (so & SO_ScavengeCodeCache) {
|
|
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp b/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp
|
|
index 7d31ff02e..e861ef569 100644
|
|
--- a/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp
|
|
+++ b/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2018, 2022, Red Hat, Inc. All rights reserved.
|
|
+ * Copyright (c) 2018, 2023, Red Hat, Inc. 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
|
|
@@ -159,6 +159,14 @@ void ShenandoahArguments::initialize() {
|
|
FLAG_SET_DEFAULT(ClassUnloadingWithConcurrentMark, false);
|
|
}
|
|
|
|
+ // AOT is not supported yet
|
|
+ if (UseAOT) {
|
|
+ if (!FLAG_IS_DEFAULT(UseAOT)) {
|
|
+ warning("Shenandoah does not support AOT at this moment, disabling UseAOT");
|
|
+ }
|
|
+ FLAG_SET_DEFAULT(UseAOT, false);
|
|
+ }
|
|
+
|
|
// TLAB sizing policy makes resizing decisions before each GC cycle. It averages
|
|
// historical data, assigning more recent data the weight according to TLABAllocationWeight.
|
|
// Current default is good for generational collectors that run frequent young GCs.
|
|
diff --git a/src/hotspot/share/jfr/leakprofiler/chains/rootSetClosure.cpp b/src/hotspot/share/jfr/leakprofiler/chains/rootSetClosure.cpp
|
|
index 9a76d3b40..15199a86b 100644
|
|
--- a/src/hotspot/share/jfr/leakprofiler/chains/rootSetClosure.cpp
|
|
+++ b/src/hotspot/share/jfr/leakprofiler/chains/rootSetClosure.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2014, 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
|
|
@@ -39,6 +39,9 @@
|
|
#include "runtime/thread.hpp"
|
|
#include "services/management.hpp"
|
|
#include "utilities/align.hpp"
|
|
+#if INCLUDE_AOT
|
|
+#include "aot/aotLoader.hpp"
|
|
+#endif
|
|
|
|
template <typename Delegate>
|
|
RootSetClosure<Delegate>::RootSetClosure(Delegate* delegate) : _delegate(delegate) {}
|
|
@@ -71,6 +74,9 @@ void RootSetClosure<Delegate>::process() {
|
|
// We don't follow code blob oops, because they have misaligned oops.
|
|
Threads::oops_do(this, NULL);
|
|
OopStorageSet::strong_oops_do(this);
|
|
+#if INCLUDE_AOT
|
|
+ AOTLoader::oops_do(this);
|
|
+#endif
|
|
}
|
|
|
|
template class RootSetClosure<BFSClosure>;
|
|
diff --git a/src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.cpp b/src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.cpp
|
|
index d66e9236d..5b779b4b4 100644
|
|
--- a/src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.cpp
|
|
+++ b/src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2014, 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
|
|
@@ -44,6 +44,9 @@
|
|
#include "services/management.hpp"
|
|
#include "utilities/enumIterator.hpp"
|
|
#include "utilities/growableArray.hpp"
|
|
+#if INCLUDE_AOT
|
|
+#include "aot/aotLoader.hpp"
|
|
+#endif
|
|
|
|
class ReferenceLocateClosure : public OopClosure {
|
|
protected:
|
|
@@ -100,6 +103,9 @@ class ReferenceToRootClosure : public StackObj {
|
|
bool do_cldg_roots();
|
|
bool do_oop_storage_roots();
|
|
bool do_string_table_roots();
|
|
+#if INCLUDE_AOT
|
|
+ bool do_aot_loader_roots();
|
|
+#endif
|
|
|
|
bool do_roots();
|
|
|
|
@@ -148,6 +154,15 @@ bool ReferenceToRootClosure::do_oop_storage_roots() {
|
|
return false;
|
|
}
|
|
|
|
+#if INCLUDE_AOT
|
|
+bool ReferenceToRootClosure::do_aot_loader_roots() {
|
|
+ assert(!complete(), "invariant");
|
|
+ ReferenceLocateClosure rcl(_callback, OldObjectRoot::_aot, OldObjectRoot::_type_undetermined, NULL);
|
|
+ AOTLoader::oops_do(&rcl);
|
|
+ return rcl.complete();
|
|
+}
|
|
+#endif
|
|
+
|
|
bool ReferenceToRootClosure::do_roots() {
|
|
assert(!complete(), "invariant");
|
|
assert(OldObjectRoot::_system_undetermined == _info._system, "invariant");
|
|
@@ -163,6 +178,13 @@ bool ReferenceToRootClosure::do_roots() {
|
|
return true;
|
|
}
|
|
|
|
+#if INCLUDE_AOT
|
|
+ if (do_aot_loader_roots()) {
|
|
+ _complete = true;
|
|
+ return true;
|
|
+ }
|
|
+#endif
|
|
+
|
|
return false;
|
|
}
|
|
|
|
diff --git a/src/hotspot/share/jfr/leakprofiler/utilities/rootType.cpp b/src/hotspot/share/jfr/leakprofiler/utilities/rootType.cpp
|
|
index aefbc59a5..6827d3856 100644
|
|
--- a/src/hotspot/share/jfr/leakprofiler/utilities/rootType.cpp
|
|
+++ b/src/hotspot/share/jfr/leakprofiler/utilities/rootType.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2020, 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
|
|
@@ -57,6 +57,8 @@ const char* OldObjectRoot::system_description(System system) {
|
|
return "Class Loader Data";
|
|
case _code_cache:
|
|
return "Code Cache";
|
|
+ case _aot:
|
|
+ return "AOT";
|
|
#if INCLUDE_JVMCI
|
|
case _jvmci:
|
|
return "JVMCI";
|
|
diff --git a/src/hotspot/share/jfr/leakprofiler/utilities/rootType.hpp b/src/hotspot/share/jfr/leakprofiler/utilities/rootType.hpp
|
|
index ffc47c7b8..bcd7f5b6c 100644
|
|
--- a/src/hotspot/share/jfr/leakprofiler/utilities/rootType.hpp
|
|
+++ b/src/hotspot/share/jfr/leakprofiler/utilities/rootType.hpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2017, 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
|
|
@@ -39,6 +39,7 @@ class OldObjectRoot : public AllStatic {
|
|
_strong_oop_storage_set_last = _strong_oop_storage_set_first + EnumRange<OopStorageSet::StrongId>().size() - 1,
|
|
_class_loader_data,
|
|
_code_cache,
|
|
+ _aot,
|
|
JVMCI_ONLY(_jvmci COMMA)
|
|
_number_of_systems
|
|
};
|
|
diff --git a/src/hotspot/share/jvmci/compilerRuntime.cpp b/src/hotspot/share/jvmci/compilerRuntime.cpp
|
|
new file mode 100644
|
|
index 000000000..cf48aa862
|
|
--- /dev/null
|
|
+++ b/src/hotspot/share/jvmci/compilerRuntime.cpp
|
|
@@ -0,0 +1,283 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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.
|
|
+ */
|
|
+
|
|
+#include "precompiled.hpp"
|
|
+#include "classfile/stringTable.hpp"
|
|
+#include "classfile/symbolTable.hpp"
|
|
+#include "classfile/systemDictionary.hpp"
|
|
+#include "classfile/vmSymbols.hpp"
|
|
+#include "compiler/compilationPolicy.hpp"
|
|
+#include "interpreter/linkResolver.hpp"
|
|
+#include "jvmci/compilerRuntime.hpp"
|
|
+#include "oops/cpCache.inline.hpp"
|
|
+#include "oops/klass.inline.hpp"
|
|
+#include "oops/oop.inline.hpp"
|
|
+#include "runtime/deoptimization.hpp"
|
|
+#include "runtime/frame.inline.hpp"
|
|
+#include "runtime/handles.inline.hpp"
|
|
+#include "runtime/interfaceSupport.inline.hpp"
|
|
+#include "runtime/vframe.inline.hpp"
|
|
+#include "utilities/sizes.hpp"
|
|
+#if INCLUDE_AOT
|
|
+#include "aot/aotLoader.hpp"
|
|
+#endif
|
|
+
|
|
+// Resolve and allocate String
|
|
+JRT_BLOCK_ENTRY(void, CompilerRuntime::resolve_string_by_symbol(JavaThread* current, void* string_result, const char* name))
|
|
+ JRT_BLOCK
|
|
+ oop str = *(oop*)string_result; // Is it resolved already?
|
|
+ if (str == NULL) { // Do resolution
|
|
+ // First 2 bytes of name contains length (number of bytes).
|
|
+ int len = Bytes::get_Java_u2((address)name);
|
|
+ name += 2;
|
|
+ TempNewSymbol sym = SymbolTable::new_symbol(name, len);
|
|
+ str = StringTable::intern(sym, CHECK);
|
|
+ assert(java_lang_String::is_instance(str), "must be string");
|
|
+ *(oop*)string_result = str; // Store result
|
|
+ }
|
|
+ assert(str != NULL, "Should be allocated!");
|
|
+ current->set_vm_result(str);
|
|
+ JRT_BLOCK_END
|
|
+JRT_END
|
|
+
|
|
+
|
|
+
|
|
+Klass* CompilerRuntime::resolve_klass_helper(const char* name, int len, TRAPS) {
|
|
+ JavaThread* current = THREAD->as_Java_thread();
|
|
+ ResourceMark rm(current);
|
|
+ // last java frame on stack (which includes native call frames)
|
|
+ RegisterMap cbl_map(current, false);
|
|
+ // Skip stub
|
|
+ frame caller_frame = current->last_frame().sender(&cbl_map);
|
|
+ CodeBlob* caller_cb = caller_frame.cb();
|
|
+ guarantee(caller_cb != NULL && caller_cb->is_compiled(), "must be called from compiled method");
|
|
+ CompiledMethod* caller_nm = caller_cb->as_compiled_method_or_null();
|
|
+ methodHandle caller(current, caller_nm->method());
|
|
+
|
|
+ // Use class loader of aot method.
|
|
+ Handle loader(current, caller->method_holder()->class_loader());
|
|
+ Handle protection_domain(current, caller->method_holder()->protection_domain());
|
|
+
|
|
+ TempNewSymbol sym = SymbolTable::new_symbol(name, len);
|
|
+ if (sym != NULL && Signature::has_envelope(sym)) {
|
|
+ // Ignore wrapping L and ;
|
|
+ sym = Signature::strip_envelope(sym);
|
|
+ }
|
|
+ if (sym == NULL) {
|
|
+ return NULL;
|
|
+ }
|
|
+ Klass* k = SystemDictionary::resolve_or_fail(sym, loader, protection_domain, true, CHECK_NULL);
|
|
+
|
|
+ return k;
|
|
+}
|
|
+
|
|
+// Resolve Klass
|
|
+JRT_BLOCK_ENTRY(Klass*, CompilerRuntime::resolve_klass_by_symbol(JavaThread* current, Klass** klass_result, const char* name))
|
|
+ Klass* k = NULL;
|
|
+ JRT_BLOCK
|
|
+ k = *klass_result; // Is it resolved already?
|
|
+ if (k == NULL) { // Do resolution
|
|
+ // First 2 bytes of name contains length (number of bytes).
|
|
+ int len = Bytes::get_Java_u2((address)name);
|
|
+ name += 2;
|
|
+ k = CompilerRuntime::resolve_klass_helper(name, len, CHECK_NULL);
|
|
+ *klass_result = k; // Store result
|
|
+ }
|
|
+ JRT_BLOCK_END
|
|
+ assert(k != NULL, " Should be loaded!");
|
|
+ return k;
|
|
+JRT_END
|
|
+
|
|
+
|
|
+Method* CompilerRuntime::resolve_method_helper(Klass* klass, const char* method_name, int method_name_len,
|
|
+ const char* signature_name, int signature_name_len) {
|
|
+ Method* m = NULL;
|
|
+ TempNewSymbol name_symbol = SymbolTable::probe(method_name, method_name_len);
|
|
+ TempNewSymbol signature_symbol = SymbolTable::probe(signature_name, signature_name_len);
|
|
+ if (name_symbol != NULL && signature_symbol != NULL) {
|
|
+ if (name_symbol == vmSymbols::object_initializer_name() ||
|
|
+ name_symbol == vmSymbols::class_initializer_name()) {
|
|
+ // Never search superclasses for constructors
|
|
+ if (klass->is_instance_klass()) {
|
|
+ m = InstanceKlass::cast(klass)->find_method(name_symbol, signature_symbol);
|
|
+ }
|
|
+ } else {
|
|
+ m = klass->lookup_method(name_symbol, signature_symbol);
|
|
+ if (m == NULL && klass->is_instance_klass()) {
|
|
+ m = InstanceKlass::cast(klass)->lookup_method_in_ordered_interfaces(name_symbol, signature_symbol);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ return m;
|
|
+}
|
|
+
|
|
+JRT_BLOCK_ENTRY(void, CompilerRuntime::resolve_dynamic_invoke(JavaThread* current, oop* appendix_result))
|
|
+ JRT_BLOCK
|
|
+ {
|
|
+ ResourceMark rm(current);
|
|
+ vframeStream vfst(current, true); // Do not skip and javaCalls
|
|
+ assert(!vfst.at_end(), "Java frame must exist");
|
|
+ methodHandle caller(current, vfst.method());
|
|
+ InstanceKlass* holder = caller->method_holder();
|
|
+ int bci = vfst.bci();
|
|
+ Bytecode_invoke bytecode(caller, bci);
|
|
+ int index = bytecode.index();
|
|
+
|
|
+ // Make sure it's resolved first
|
|
+ CallInfo callInfo;
|
|
+ constantPoolHandle cp(current, holder->constants());
|
|
+ ConstantPoolCacheEntry* cp_cache_entry = cp->cache()->entry_at(cp->decode_cpcache_index(index, true));
|
|
+ Bytecodes::Code invoke_code = bytecode.invoke_code();
|
|
+ if (!cp_cache_entry->is_resolved(invoke_code)) {
|
|
+ LinkResolver::resolve_invoke(callInfo, Handle(), cp, index, invoke_code, CHECK);
|
|
+ if (bytecode.is_invokedynamic()) {
|
|
+ cp_cache_entry->set_dynamic_call(cp, callInfo);
|
|
+ } else {
|
|
+ cp_cache_entry->set_method_handle(cp, callInfo);
|
|
+ }
|
|
+ vmassert(cp_cache_entry->is_resolved(invoke_code), "sanity");
|
|
+ }
|
|
+
|
|
+ Handle appendix(current, cp_cache_entry->appendix_if_resolved(cp));
|
|
+ Klass *appendix_klass = appendix.is_null() ? NULL : appendix->klass();
|
|
+
|
|
+ methodHandle adapter_method(current, cp_cache_entry->f1_as_method());
|
|
+ InstanceKlass *adapter_klass = adapter_method->method_holder();
|
|
+
|
|
+ if (appendix_klass != NULL && appendix_klass->is_instance_klass()) {
|
|
+ vmassert(InstanceKlass::cast(appendix_klass)->is_initialized(), "sanity");
|
|
+ }
|
|
+ if (!adapter_klass->is_initialized()) {
|
|
+ // Force initialization of adapter class
|
|
+ adapter_klass->initialize(CHECK);
|
|
+ // Double-check that it was really initialized,
|
|
+ // because we could be doing a recursive call
|
|
+ // from inside <clinit>.
|
|
+ }
|
|
+
|
|
+ int cpi = cp_cache_entry->constant_pool_index();
|
|
+ if (!AOTLoader::reconcile_dynamic_invoke(holder, cpi, adapter_method(),
|
|
+ appendix_klass)) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ *appendix_result = appendix();
|
|
+ current->set_vm_result(appendix());
|
|
+ }
|
|
+ JRT_BLOCK_END
|
|
+JRT_END
|
|
+
|
|
+JRT_BLOCK_ENTRY(MethodCounters*, CompilerRuntime::resolve_method_by_symbol_and_load_counters(JavaThread* current, MethodCounters** counters_result, Klass* klass, const char* data))
|
|
+ MethodCounters* c = *counters_result; // Is it resolved already?
|
|
+ JRT_BLOCK
|
|
+ if (c == NULL) { // Do resolution
|
|
+ // Get method name and its length
|
|
+ int method_name_len = Bytes::get_Java_u2((address)data);
|
|
+ data += sizeof(u2);
|
|
+ const char* method_name = data;
|
|
+ data += method_name_len;
|
|
+
|
|
+ // Get signature and its length
|
|
+ int signature_name_len = Bytes::get_Java_u2((address)data);
|
|
+ data += sizeof(u2);
|
|
+ const char* signature_name = data;
|
|
+
|
|
+ assert(klass != NULL, "Klass parameter must not be null");
|
|
+ Method* m = resolve_method_helper(klass, method_name, method_name_len, signature_name, signature_name_len);
|
|
+ assert(m != NULL, "Method must resolve successfully");
|
|
+
|
|
+ // Create method counters immediately to avoid check at runtime.
|
|
+ c = m->get_method_counters(current);
|
|
+ if (c == NULL) {
|
|
+ THROW_MSG_NULL(vmSymbols::java_lang_OutOfMemoryError(), "Cannot allocate method counters");
|
|
+ }
|
|
+
|
|
+ *counters_result = c;
|
|
+ }
|
|
+ JRT_BLOCK_END
|
|
+ return c;
|
|
+JRT_END
|
|
+
|
|
+// Resolve and initialize Klass
|
|
+JRT_BLOCK_ENTRY(Klass*, CompilerRuntime::initialize_klass_by_symbol(JavaThread* current, Klass** klass_result, const char* name))
|
|
+ Klass* k = NULL;
|
|
+ JRT_BLOCK
|
|
+ k = klass_result[0]; // Is it initialized already?
|
|
+ if (k == NULL) { // Do initialized
|
|
+ k = klass_result[1]; // Is it resolved already?
|
|
+ if (k == NULL) { // Do resolution
|
|
+ // First 2 bytes of name contains length (number of bytes).
|
|
+ int len = Bytes::get_Java_u2((address)name);
|
|
+ const char *cname = name + 2;
|
|
+ k = CompilerRuntime::resolve_klass_helper(cname, len, CHECK_NULL);
|
|
+ klass_result[1] = k; // Store resolved result
|
|
+ }
|
|
+ Klass* k0 = klass_result[0]; // Is it initialized already?
|
|
+ if (k0 == NULL && k != NULL && k->is_instance_klass()) {
|
|
+ // Force initialization of instance class
|
|
+ InstanceKlass::cast(k)->initialize(CHECK_NULL);
|
|
+ // Double-check that it was really initialized,
|
|
+ // because we could be doing a recursive call
|
|
+ // from inside <clinit>.
|
|
+ if (InstanceKlass::cast(k)->is_initialized()) {
|
|
+ klass_result[0] = k; // Store initialized result
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ JRT_BLOCK_END
|
|
+ assert(k != NULL, " Should be loaded!");
|
|
+ return k;
|
|
+JRT_END
|
|
+
|
|
+
|
|
+JRT_BLOCK_ENTRY(void, CompilerRuntime::invocation_event(JavaThread* current, MethodCounters* counters))
|
|
+ JRT_BLOCK
|
|
+ methodHandle mh(current, counters->method());
|
|
+ RegisterMap map(current, false);
|
|
+ // Compute the enclosing method
|
|
+ frame fr = current->last_frame().sender(&map);
|
|
+ CompiledMethod* cm = fr.cb()->as_compiled_method_or_null();
|
|
+ assert(cm != NULL && cm->is_compiled(), "Sanity check");
|
|
+ methodHandle emh(current, cm->method());
|
|
+ CompilationPolicy::event(emh, mh, InvocationEntryBci, InvocationEntryBci, CompLevel_aot, cm, CHECK);
|
|
+ JRT_BLOCK_END
|
|
+JRT_END
|
|
+
|
|
+JRT_BLOCK_ENTRY(void, CompilerRuntime::backedge_event(JavaThread* current, MethodCounters* counters, int branch_bci, int target_bci))
|
|
+ assert(branch_bci != InvocationEntryBci && target_bci != InvocationEntryBci, "Wrong bci");
|
|
+ assert(target_bci <= branch_bci, "Expected a back edge");
|
|
+ JRT_BLOCK
|
|
+ methodHandle mh(current, counters->method());
|
|
+ RegisterMap map(current, false);
|
|
+
|
|
+ // Compute the enclosing method
|
|
+ frame fr = current->last_frame().sender(&map);
|
|
+ CompiledMethod* cm = fr.cb()->as_compiled_method_or_null();
|
|
+ assert(cm != NULL && cm->is_compiled(), "Sanity check");
|
|
+ methodHandle emh(current, cm->method());
|
|
+ nmethod* osr_nm = CompilationPolicy::event(emh, mh, branch_bci, target_bci, CompLevel_aot, cm, CHECK);
|
|
+ if (osr_nm != NULL) {
|
|
+ Deoptimization::deoptimize_frame(current, fr.id());
|
|
+ }
|
|
+ JRT_BLOCK_END
|
|
+JRT_END
|
|
diff --git a/src/hotspot/share/jvmci/compilerRuntime.hpp b/src/hotspot/share/jvmci/compilerRuntime.hpp
|
|
new file mode 100644
|
|
index 000000000..98c2a5583
|
|
--- /dev/null
|
|
+++ b/src/hotspot/share/jvmci/compilerRuntime.hpp
|
|
@@ -0,0 +1,51 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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.
|
|
+ */
|
|
+
|
|
+#ifndef SHARE_JVMCI_COMPILERRUNTIME_HPP
|
|
+#define SHARE_JVMCI_COMPILERRUNTIME_HPP
|
|
+
|
|
+#include "memory/allocation.hpp"
|
|
+#include "memory/resourceArea.hpp"
|
|
+#include "oops/klass.hpp"
|
|
+#include "oops/method.hpp"
|
|
+#include "utilities/exceptions.hpp"
|
|
+
|
|
+class CompilerRuntime : AllStatic {
|
|
+ public:
|
|
+ // Resolves klass for aot compiled method.
|
|
+ static Klass* resolve_klass_helper(const char* name, int len, TRAPS);
|
|
+ // Resolves method for aot compiled method.
|
|
+ static Method* resolve_method_helper(Klass* klass, const char* method_name, int method_name_len,
|
|
+ const char* signature_name, int signature_name_len);
|
|
+ // Resolution methods for aot compiled code.
|
|
+ static void resolve_string_by_symbol(JavaThread* current, void* string_result, const char* name);
|
|
+ static void resolve_dynamic_invoke(JavaThread* current, oop* appendix_result);
|
|
+
|
|
+ static Klass* resolve_klass_by_symbol(JavaThread* current, Klass** klass_result, const char* name);
|
|
+ static Klass* initialize_klass_by_symbol(JavaThread* current, Klass** klass_result, const char* name);
|
|
+ static MethodCounters* resolve_method_by_symbol_and_load_counters(JavaThread* current, MethodCounters** counters_result, Klass* klass_hint, const char* data);
|
|
+ static void invocation_event(JavaThread* current, MethodCounters* counters);
|
|
+ static void backedge_event(JavaThread* current, MethodCounters* counters, int branch_bci, int target_bci);
|
|
+};
|
|
+
|
|
+#endif // SHARE_JVMCI_COMPILERRUNTIME_HPP
|
|
diff --git a/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp b/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp
|
|
index 3c8abb36e..2eff43b52 100644
|
|
--- a/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp
|
|
+++ b/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2011, 2021, 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
|
|
@@ -173,6 +173,70 @@ OopMap* CodeInstaller::create_oop_map(JVMCIObject debug_info, JVMCI_TRAPS) {
|
|
return map;
|
|
}
|
|
|
|
+#if INCLUDE_AOT
|
|
+AOTOopRecorder::AOTOopRecorder(CodeInstaller* code_inst, Arena* arena, bool deduplicate) : OopRecorder(arena, deduplicate) {
|
|
+ _code_inst = code_inst;
|
|
+ _meta_refs = new GrowableArray<jobject>();
|
|
+}
|
|
+
|
|
+int AOTOopRecorder::nr_meta_refs() const {
|
|
+ return _meta_refs->length();
|
|
+}
|
|
+
|
|
+jobject AOTOopRecorder::meta_element(int pos) const {
|
|
+ return _meta_refs->at(pos);
|
|
+}
|
|
+
|
|
+int AOTOopRecorder::find_index(Metadata* h) {
|
|
+ JavaThread* THREAD = JavaThread::current();
|
|
+ JVMCIEnv* JVMCIENV = _code_inst->jvmci_env();
|
|
+ int oldCount = metadata_count();
|
|
+ int index = this->OopRecorder::find_index(h);
|
|
+ int newCount = metadata_count();
|
|
+
|
|
+ if (oldCount == newCount) {
|
|
+ // found a match
|
|
+ return index;
|
|
+ }
|
|
+
|
|
+ vmassert(index + 1 == newCount, "must be last");
|
|
+
|
|
+ JVMCIKlassHandle klass(THREAD);
|
|
+ JVMCIObject result;
|
|
+ guarantee(h != NULL,
|
|
+ "If DebugInformationRecorder::describe_scope passes NULL oldCount == newCount must hold.");
|
|
+ if (h->is_klass()) {
|
|
+ klass = (Klass*) h;
|
|
+ result = JVMCIENV->get_jvmci_type(klass, JVMCI_CATCH);
|
|
+ } else if (h->is_method()) {
|
|
+ Method* method = (Method*) h;
|
|
+ methodHandle mh(THREAD, method);
|
|
+ result = JVMCIENV->get_jvmci_method(mh, JVMCI_CATCH);
|
|
+ }
|
|
+ jobject ref = JVMCIENV->get_jobject(result);
|
|
+ record_meta_ref(ref, index);
|
|
+
|
|
+ return index;
|
|
+}
|
|
+
|
|
+int AOTOopRecorder::find_index(jobject h) {
|
|
+ if (h == NULL) {
|
|
+ return 0;
|
|
+ }
|
|
+ oop javaMirror = JNIHandles::resolve(h);
|
|
+ Klass* klass = java_lang_Class::as_Klass(javaMirror);
|
|
+ return find_index(klass);
|
|
+}
|
|
+
|
|
+void AOTOopRecorder::record_meta_ref(jobject o, int index) {
|
|
+ assert(index > 0, "must be 1..n");
|
|
+ index -= 1; // reduce by one to convert to array index
|
|
+
|
|
+ assert(index == _meta_refs->length(), "must be last");
|
|
+ _meta_refs->append(o);
|
|
+}
|
|
+#endif // INCLUDE_AOT
|
|
+
|
|
void* CodeInstaller::record_metadata_reference(CodeSection* section, address dest, JVMCIObject constant, JVMCI_TRAPS) {
|
|
/*
|
|
* This method needs to return a raw (untyped) pointer, since the value of a pointer to the base
|
|
@@ -475,6 +539,69 @@ void CodeInstaller::initialize_dependencies(JVMCIObject compiled_code, OopRecord
|
|
}
|
|
}
|
|
|
|
+#if INCLUDE_AOT
|
|
+RelocBuffer::~RelocBuffer() {
|
|
+ FREE_C_HEAP_ARRAY(char, _buffer);
|
|
+}
|
|
+
|
|
+address RelocBuffer::begin() const {
|
|
+ if (_buffer != NULL) {
|
|
+ return (address) _buffer;
|
|
+ }
|
|
+ return (address) _static_buffer;
|
|
+}
|
|
+
|
|
+void RelocBuffer::set_size(size_t bytes) {
|
|
+ assert(bytes <= _size, "can't grow in size!");
|
|
+ _size = bytes;
|
|
+}
|
|
+
|
|
+void RelocBuffer::ensure_size(size_t bytes) {
|
|
+ assert(_buffer == NULL, "can only be used once");
|
|
+ assert(_size == 0, "can only be used once");
|
|
+ if (bytes >= RelocBuffer::stack_size) {
|
|
+ _buffer = NEW_C_HEAP_ARRAY(char, bytes, mtJVMCI);
|
|
+ }
|
|
+ _size = bytes;
|
|
+}
|
|
+
|
|
+JVMCI::CodeInstallResult CodeInstaller::gather_metadata(JVMCIObject target, JVMCIObject compiled_code, CodeMetadata& metadata, JVMCI_TRAPS) {
|
|
+ assert(JVMCIENV->is_hotspot(), "AOT code is executed only in HotSpot mode");
|
|
+ CodeBuffer buffer("JVMCI Compiler CodeBuffer for Metadata");
|
|
+ AOTOopRecorder* recorder = new AOTOopRecorder(this, &_arena, true);
|
|
+ initialize_dependencies(compiled_code, recorder, JVMCI_CHECK_OK);
|
|
+
|
|
+ metadata.set_oop_recorder(recorder);
|
|
+
|
|
+ // Get instructions and constants CodeSections early because we need it.
|
|
+ _instructions = buffer.insts();
|
|
+ _constants = buffer.consts();
|
|
+ buffer.set_immutable_PIC(_immutable_pic_compilation);
|
|
+
|
|
+ initialize_fields(target, compiled_code, JVMCI_CHECK_OK);
|
|
+ JVMCI::CodeInstallResult result = initialize_buffer(buffer, false, JVMCI_CHECK_OK);
|
|
+ if (result != JVMCI::ok) {
|
|
+ return result;
|
|
+ }
|
|
+
|
|
+ _debug_recorder->pcs_size(); // create the sentinel record
|
|
+
|
|
+ assert(_debug_recorder->pcs_length() >= 2, "must be at least 2");
|
|
+
|
|
+ metadata.set_pc_desc(_debug_recorder->pcs(), _debug_recorder->pcs_length());
|
|
+ metadata.set_scopes(_debug_recorder->stream()->buffer(), _debug_recorder->data_size());
|
|
+ metadata.set_exception_table(&_exception_handler_table);
|
|
+ metadata.set_implicit_exception_table(&_implicit_exception_table);
|
|
+
|
|
+ RelocBuffer* reloc_buffer = metadata.get_reloc_buffer();
|
|
+
|
|
+ reloc_buffer->ensure_size(buffer.total_relocation_size());
|
|
+ size_t size = (size_t) buffer.copy_relocations_to(reloc_buffer->begin(), (CodeBuffer::csize_t) reloc_buffer->size(), true);
|
|
+ reloc_buffer->set_size(size);
|
|
+ return JVMCI::ok;
|
|
+}
|
|
+#endif // INCLUDE_AOT
|
|
+
|
|
// constructor used to create a method
|
|
JVMCI::CodeInstallResult CodeInstaller::install(JVMCICompiler* compiler,
|
|
JVMCIObject target,
|
|
@@ -494,6 +621,9 @@ JVMCI::CodeInstallResult CodeInstaller::install(JVMCICompiler* compiler,
|
|
// Get instructions and constants CodeSections early because we need it.
|
|
_instructions = buffer.insts();
|
|
_constants = buffer.consts();
|
|
+#if INCLUDE_AOT
|
|
+ buffer.set_immutable_PIC(_immutable_pic_compilation);
|
|
+#endif
|
|
|
|
initialize_fields(target, compiled_code, JVMCI_CHECK_OK);
|
|
JVMCI::CodeInstallResult result = initialize_buffer(buffer, true, JVMCI_CHECK_OK);
|
|
@@ -615,8 +745,9 @@ void CodeInstaller::initialize_fields(JVMCIObject target, JVMCIObject compiled_c
|
|
}
|
|
|
|
int CodeInstaller::estimate_stubs_size(JVMCI_TRAPS) {
|
|
- // Estimate the number of static call stubs that might be emitted.
|
|
+ // Estimate the number of static and aot call stubs that might be emitted.
|
|
int static_call_stubs = 0;
|
|
+ int aot_call_stubs = 0;
|
|
int trampoline_stubs = 0;
|
|
JVMCIObjectArray sites = this->sites();
|
|
for (int i = 0; i < JVMCIENV->get_length(sites); i++) {
|
|
@@ -644,10 +775,22 @@ int CodeInstaller::estimate_stubs_size(JVMCI_TRAPS) {
|
|
}
|
|
}
|
|
}
|
|
+#if INCLUDE_AOT
|
|
+ if (UseAOT && jvmci_env()->isa_site_Call(site)) {
|
|
+ JVMCIObject target = jvmci_env()-> get_site_Call_target(site);
|
|
+ if (!jvmci_env()->isa_HotSpotForeignCallTarget(target)) {
|
|
+ // Add far aot trampolines.
|
|
+ aot_call_stubs++;
|
|
+ }
|
|
+ }
|
|
+#endif
|
|
}
|
|
}
|
|
int size = static_call_stubs * CompiledStaticCall::to_interp_stub_size();
|
|
size += trampoline_stubs * CompiledStaticCall::to_trampoline_stub_size();
|
|
+#if INCLUDE_AOT
|
|
+ size += aot_call_stubs * CompiledStaticCall::to_aot_stub_size();
|
|
+#endif
|
|
return size;
|
|
}
|
|
|
|
@@ -1137,6 +1280,10 @@ void CodeInstaller::site_Call(CodeBuffer& buffer, jint pc_offset, JVMCIObject si
|
|
|
|
if (foreign_call.is_non_null()) {
|
|
jlong foreign_call_destination = jvmci_env()->get_HotSpotForeignCallTarget_address(foreign_call);
|
|
+ if (_immutable_pic_compilation) {
|
|
+ // Use fake short distance during PIC compilation.
|
|
+ foreign_call_destination = (jlong)(_instructions->start() + pc_offset);
|
|
+ }
|
|
CodeInstaller::pd_relocate_ForeignCall(inst, foreign_call_destination, JVMCI_CHECK);
|
|
} else { // method != NULL
|
|
if (debug_info.is_null()) {
|
|
@@ -1151,6 +1298,10 @@ void CodeInstaller::site_Call(CodeBuffer& buffer, jint pc_offset, JVMCIObject si
|
|
JVMCI_ERROR("could not emit to_interp stub - code cache is full");
|
|
}
|
|
}
|
|
+#if INCLUDE_AOT
|
|
+ // Trampoline to far aot code.
|
|
+ CompiledStaticCall::emit_to_aot_stub(buffer, _instructions->start() + pc_offset);
|
|
+#endif
|
|
}
|
|
|
|
_next_call_type = INVOKE_INVALID;
|
|
@@ -1174,11 +1325,25 @@ void CodeInstaller::site_DataPatch(CodeBuffer& buffer, jint pc_offset, JVMCIObje
|
|
const char* to_string = JVMCIENV->as_utf8_string(string);
|
|
JVMCI_THROW_MSG(IllegalArgumentException, err_msg("Direct object constant reached the backend: %s", to_string));
|
|
}
|
|
- pd_patch_OopConstant(pc_offset, constant, JVMCI_CHECK);
|
|
+ if (!_immutable_pic_compilation) {
|
|
+ // Do not patch during PIC compilation.
|
|
+ pd_patch_OopConstant(pc_offset, constant, JVMCI_CHECK);
|
|
+ }
|
|
} else if (jvmci_env()->isa_IndirectHotSpotObjectConstantImpl(constant)) {
|
|
- pd_patch_OopConstant(pc_offset, constant, JVMCI_CHECK);
|
|
+ if (!_immutable_pic_compilation) {
|
|
+ // Do not patch during PIC compilation.
|
|
+ pd_patch_OopConstant(pc_offset, constant, JVMCI_CHECK);
|
|
+ }
|
|
} else if (jvmci_env()->isa_HotSpotMetaspaceConstantImpl(constant)) {
|
|
- pd_patch_MetaspaceConstant(pc_offset, constant, JVMCI_CHECK);
|
|
+ if (!_immutable_pic_compilation) {
|
|
+ pd_patch_MetaspaceConstant(pc_offset, constant, JVMCI_CHECK);
|
|
+ }
|
|
+#if INCLUDE_AOT
|
|
+ } else if (jvmci_env()->isa_HotSpotSentinelConstant(constant)) {
|
|
+ if (!_immutable_pic_compilation) {
|
|
+ JVMCI_ERROR("sentinel constant not supported for normal compiles: %s", jvmci_env()->klass_name(constant));
|
|
+ }
|
|
+#endif
|
|
} else {
|
|
JVMCI_ERROR("unknown constant type in data patch: %s", jvmci_env()->klass_name(constant));
|
|
}
|
|
diff --git a/src/hotspot/share/jvmci/jvmciCodeInstaller.hpp b/src/hotspot/share/jvmci/jvmciCodeInstaller.hpp
|
|
index 2c8e231c7..5ac7769b8 100644
|
|
--- a/src/hotspot/share/jvmci/jvmciCodeInstaller.hpp
|
|
+++ b/src/hotspot/share/jvmci/jvmciCodeInstaller.hpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2011, 2021, 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
|
|
@@ -30,6 +30,42 @@
|
|
#include "jvmci/jvmci.hpp"
|
|
#include "jvmci/jvmciEnv.hpp"
|
|
|
|
+#if INCLUDE_AOT
|
|
+class RelocBuffer : public StackObj {
|
|
+ enum { stack_size = 1024 };
|
|
+public:
|
|
+ RelocBuffer() : _size(0), _buffer(0) {}
|
|
+ ~RelocBuffer();
|
|
+ void ensure_size(size_t bytes);
|
|
+ void set_size(size_t bytes);
|
|
+ address begin() const;
|
|
+ size_t size() const { return _size; }
|
|
+private:
|
|
+ size_t _size;
|
|
+ char _static_buffer[stack_size];
|
|
+ char *_buffer;
|
|
+};
|
|
+
|
|
+class CodeInstaller;
|
|
+
|
|
+class AOTOopRecorder : public OopRecorder {
|
|
+public:
|
|
+ AOTOopRecorder(CodeInstaller* code_inst, Arena* arena = NULL, bool deduplicate = false);
|
|
+
|
|
+ virtual int find_index(Metadata* h);
|
|
+ virtual int find_index(jobject h);
|
|
+ int nr_meta_refs() const;
|
|
+ jobject meta_element(int pos) const;
|
|
+
|
|
+private:
|
|
+ void record_meta_ref(jobject ref, int index);
|
|
+
|
|
+ GrowableArray<jobject>* _meta_refs;
|
|
+
|
|
+ CodeInstaller* _code_inst;
|
|
+};
|
|
+#endif // INCLUDE_AOT
|
|
+
|
|
class CodeMetadata {
|
|
public:
|
|
CodeMetadata() {}
|
|
@@ -42,6 +78,11 @@ public:
|
|
u_char* get_scopes_desc() const { return _scopes_desc; }
|
|
int get_scopes_size() const { return _nr_scopes_desc; }
|
|
|
|
+#if INCLUDE_AOT
|
|
+ RelocBuffer* get_reloc_buffer() { return &_reloc_buffer; }
|
|
+ AOTOopRecorder* get_oop_recorder() { return _oop_recorder; }
|
|
+#endif
|
|
+
|
|
ExceptionHandlerTable* get_exception_table() { return _exception_table; }
|
|
|
|
ImplicitExceptionTable* get_implicit_exception_table() { return _implicit_exception_table; }
|
|
@@ -56,6 +97,12 @@ public:
|
|
_nr_scopes_desc = size;
|
|
}
|
|
|
|
+#if INCLUDE_AOT
|
|
+ void set_oop_recorder(AOTOopRecorder* recorder) {
|
|
+ _oop_recorder = recorder;
|
|
+ }
|
|
+#endif
|
|
+
|
|
void set_exception_table(ExceptionHandlerTable* table) {
|
|
_exception_table = table;
|
|
}
|
|
@@ -72,6 +119,10 @@ private:
|
|
u_char* _scopes_desc;
|
|
int _nr_scopes_desc;
|
|
|
|
+#if INCLUDE_AOT
|
|
+ RelocBuffer _reloc_buffer;
|
|
+ AOTOopRecorder* _oop_recorder;
|
|
+#endif
|
|
ExceptionHandlerTable* _exception_table;
|
|
ImplicitExceptionTable* _implicit_exception_table;
|
|
};
|
|
@@ -151,6 +202,8 @@ private:
|
|
ImplicitExceptionTable _implicit_exception_table;
|
|
bool _has_auto_box;
|
|
|
|
+ bool _immutable_pic_compilation; // Installer is called for Immutable PIC compilation.
|
|
+
|
|
static ConstantOopWriteValue* _oop_null_scope_value;
|
|
static ConstantIntValue* _int_m1_scope_value;
|
|
static ConstantIntValue* _int_0_scope_value;
|
|
@@ -178,11 +231,15 @@ private:
|
|
|
|
public:
|
|
|
|
- CodeInstaller(JVMCIEnv* jvmci_env) :
|
|
+ CodeInstaller(JVMCIEnv* jvmci_env, bool immutable_pic_compilation) :
|
|
_arena(mtJVMCI),
|
|
_jvmci_env(jvmci_env),
|
|
- _has_auto_box(false) {}
|
|
+ _has_auto_box(false),
|
|
+ _immutable_pic_compilation(immutable_pic_compilation) {}
|
|
|
|
+#if INCLUDE_AOT
|
|
+ JVMCI::CodeInstallResult gather_metadata(JVMCIObject target, JVMCIObject compiled_code, CodeMetadata& metadata, JVMCI_TRAPS);
|
|
+#endif
|
|
JVMCI::CodeInstallResult install(JVMCICompiler* compiler,
|
|
JVMCIObject target,
|
|
JVMCIObject compiled_code,
|
|
diff --git a/src/hotspot/share/jvmci/jvmciCompiler.cpp b/src/hotspot/share/jvmci/jvmciCompiler.cpp
|
|
index faaab84d9..c5055e607 100644
|
|
--- a/src/hotspot/share/jvmci/jvmciCompiler.cpp
|
|
+++ b/src/hotspot/share/jvmci/jvmciCompiler.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2011, 2021, 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
|
|
@@ -57,7 +57,7 @@ JVMCICompiler* JVMCICompiler::instance(bool require_non_null, TRAPS) {
|
|
|
|
// Initialization
|
|
void JVMCICompiler::initialize() {
|
|
- assert(!CompilerConfig::is_c1_or_interpreter_only_no_jvmci(), "JVMCI is launched, it's not c1/interpreter only mode");
|
|
+ assert(!CompilerConfig::is_c1_or_interpreter_only_no_aot_or_jvmci(), "JVMCI is launched, it's not c1/interpreter only mode");
|
|
if (!UseCompiler || !EnableJVMCI || !UseJVMCICompiler || !should_perform_init()) {
|
|
return;
|
|
}
|
|
diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp
|
|
index decedf67b..42b4a07da 100644
|
|
--- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp
|
|
+++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp
|
|
@@ -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
|
|
@@ -886,9 +886,10 @@ C2V_VMENTRY_0(jint, installCode, (JNIEnv *env, jobject, jobject target, jobject
|
|
JVMCICompiler* compiler = JVMCICompiler::instance(true, CHECK_JNI_ERR);
|
|
|
|
TraceTime install_time("installCode", JVMCICompiler::codeInstallTimer(!thread->is_Compiler_thread()));
|
|
+ bool is_immutable_PIC = JVMCIENV->get_HotSpotCompiledCode_isImmutablePIC(compiled_code_handle) > 0;
|
|
|
|
nmethodLocker nmethod_handle;
|
|
- CodeInstaller installer(JVMCIENV);
|
|
+ CodeInstaller installer(JVMCIENV, is_immutable_PIC);
|
|
JVMCI::CodeInstallResult result = installer.install(compiler,
|
|
target_handle,
|
|
compiled_code_handle,
|
|
@@ -931,7 +932,85 @@ C2V_VMENTRY_0(jint, installCode, (JNIEnv *env, jobject, jobject target, jobject
|
|
C2V_END
|
|
|
|
C2V_VMENTRY_0(jint, getMetadata, (JNIEnv *env, jobject, jobject target, jobject compiled_code, jobject metadata))
|
|
+#if INCLUDE_AOT
|
|
+ HandleMark hm(THREAD);
|
|
+ assert(JVMCIENV->is_hotspot(), "AOT code is executed only in HotSpot mode");
|
|
+
|
|
+ JVMCIObject target_handle = JVMCIENV->wrap(target);
|
|
+ JVMCIObject compiled_code_handle = JVMCIENV->wrap(compiled_code);
|
|
+ JVMCIObject metadata_handle = JVMCIENV->wrap(metadata);
|
|
+
|
|
+ CodeMetadata code_metadata;
|
|
+
|
|
+ CodeInstaller installer(JVMCIENV, true /* immutable PIC compilation */);
|
|
+ JVMCI::CodeInstallResult result = installer.gather_metadata(target_handle, compiled_code_handle, code_metadata, JVMCI_CHECK_0);
|
|
+ if (result != JVMCI::ok) {
|
|
+ return result;
|
|
+ }
|
|
+
|
|
+ if (code_metadata.get_nr_pc_desc() > 0) {
|
|
+ int size = sizeof(PcDesc) * code_metadata.get_nr_pc_desc();
|
|
+ JVMCIPrimitiveArray array = JVMCIENV->new_byteArray(size, JVMCI_CHECK_(JVMCI::cache_full));
|
|
+ JVMCIENV->copy_bytes_from((jbyte*) code_metadata.get_pc_desc(), array, 0, size);
|
|
+ HotSpotJVMCI::HotSpotMetaData::set_pcDescBytes(JVMCIENV, metadata_handle, array);
|
|
+ }
|
|
+
|
|
+ if (code_metadata.get_scopes_size() > 0) {
|
|
+ int size = code_metadata.get_scopes_size();
|
|
+ JVMCIPrimitiveArray array = JVMCIENV->new_byteArray(size, JVMCI_CHECK_(JVMCI::cache_full));
|
|
+ JVMCIENV->copy_bytes_from((jbyte*) code_metadata.get_scopes_desc(), array, 0, size);
|
|
+ HotSpotJVMCI::HotSpotMetaData::set_scopesDescBytes(JVMCIENV, metadata_handle, array);
|
|
+ }
|
|
+
|
|
+ RelocBuffer* reloc_buffer = code_metadata.get_reloc_buffer();
|
|
+ int size = (int) reloc_buffer->size();
|
|
+ JVMCIPrimitiveArray array = JVMCIENV->new_byteArray(size, JVMCI_CHECK_(JVMCI::cache_full));
|
|
+ JVMCIENV->copy_bytes_from((jbyte*) reloc_buffer->begin(), array, 0, size);
|
|
+ HotSpotJVMCI::HotSpotMetaData::set_relocBytes(JVMCIENV, metadata_handle, array);
|
|
+
|
|
+ const OopMapSet* oopMapSet = installer.oopMapSet();
|
|
+ {
|
|
+ ResourceMark mark;
|
|
+ ImmutableOopMapBuilder builder(oopMapSet);
|
|
+ int size = builder.heap_size();
|
|
+ JVMCIPrimitiveArray array = JVMCIENV->new_byteArray(size, JVMCI_CHECK_(JVMCI::cache_full));
|
|
+ builder.generate_into((address) HotSpotJVMCI::resolve(array)->byte_at_addr(0));
|
|
+ HotSpotJVMCI::HotSpotMetaData::set_oopMaps(JVMCIENV, metadata_handle, array);
|
|
+ }
|
|
+
|
|
+ AOTOopRecorder* recorder = code_metadata.get_oop_recorder();
|
|
+
|
|
+ int nr_meta_refs = recorder->nr_meta_refs();
|
|
+ JVMCIObjectArray metadataArray = JVMCIENV->new_Object_array(nr_meta_refs, JVMCI_CHECK_(JVMCI::cache_full));
|
|
+ for (int i = 0; i < nr_meta_refs; ++i) {
|
|
+ jobject element = recorder->meta_element(i);
|
|
+ if (element == NULL) {
|
|
+ return JVMCI::cache_full;
|
|
+ }
|
|
+ JVMCIENV->put_object_at(metadataArray, i, JVMCIENV->wrap(element));
|
|
+ }
|
|
+ HotSpotJVMCI::HotSpotMetaData::set_metadata(JVMCIENV, metadata_handle, metadataArray);
|
|
+
|
|
+ ExceptionHandlerTable* handler = code_metadata.get_exception_table();
|
|
+ int table_size = handler->size_in_bytes();
|
|
+ JVMCIPrimitiveArray exceptionArray = JVMCIENV->new_byteArray(table_size, JVMCI_CHECK_(JVMCI::cache_full));
|
|
+ if (table_size > 0) {
|
|
+ handler->copy_bytes_to((address) HotSpotJVMCI::resolve(exceptionArray)->byte_at_addr(0));
|
|
+ }
|
|
+ HotSpotJVMCI::HotSpotMetaData::set_exceptionBytes(JVMCIENV, metadata_handle, exceptionArray);
|
|
+
|
|
+ ImplicitExceptionTable* implicit = code_metadata.get_implicit_exception_table();
|
|
+ int implicit_table_size = implicit->size_in_bytes();
|
|
+ JVMCIPrimitiveArray implicitExceptionArray = JVMCIENV->new_byteArray(implicit_table_size, JVMCI_CHECK_(JVMCI::cache_full));
|
|
+ if (implicit_table_size > 0) {
|
|
+ implicit->copy_bytes_to((address) HotSpotJVMCI::resolve(implicitExceptionArray)->byte_at_addr(0), implicit_table_size);
|
|
+ }
|
|
+ HotSpotJVMCI::HotSpotMetaData::set_implicitExceptionBytes(JVMCIENV, metadata_handle, implicitExceptionArray);
|
|
+
|
|
+ return result;
|
|
+#else
|
|
JVMCI_THROW_MSG_0(InternalError, "unimplemented");
|
|
+#endif
|
|
C2V_END
|
|
|
|
C2V_VMENTRY(void, resetCompilationStatistics, (JNIEnv* env, jobject))
|
|
@@ -1578,7 +1657,16 @@ C2V_VMENTRY_0(jint, methodDataProfileDataSize, (JNIEnv* env, jobject, jlong meta
|
|
C2V_END
|
|
|
|
C2V_VMENTRY_0(jlong, getFingerprint, (JNIEnv* env, jobject, jlong metaspace_klass))
|
|
+#if INCLUDE_AOT
|
|
+ Klass *k = (Klass*) (address) metaspace_klass;
|
|
+ if (k->is_instance_klass()) {
|
|
+ return InstanceKlass::cast(k)->get_stored_fingerprint();
|
|
+ } else {
|
|
+ return 0;
|
|
+ }
|
|
+#else
|
|
JVMCI_THROW_MSG_0(InternalError, "unimplemented");
|
|
+#endif
|
|
C2V_END
|
|
|
|
C2V_VMENTRY_NULL(jobject, getInterfaces, (JNIEnv* env, jobject, jobject jvmci_type))
|
|
diff --git a/src/hotspot/share/jvmci/vmStructs_compiler_runtime.hpp b/src/hotspot/share/jvmci/vmStructs_compiler_runtime.hpp
|
|
new file mode 100644
|
|
index 000000000..07ccfe06e
|
|
--- /dev/null
|
|
+++ b/src/hotspot/share/jvmci/vmStructs_compiler_runtime.hpp
|
|
@@ -0,0 +1,45 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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.
|
|
+ */
|
|
+
|
|
+#ifndef SHARE_JVMCI_VMSTRUCTS_COMPILER_RUNTIME_HPP
|
|
+#define SHARE_JVMCI_VMSTRUCTS_COMPILER_RUNTIME_HPP
|
|
+
|
|
+#if INCLUDE_AOT
|
|
+#include "jvmci/compilerRuntime.hpp"
|
|
+
|
|
+#define VM_ADDRESSES_COMPILER_RUNTIME(declare_address, declare_preprocessor_address, declare_function) \
|
|
+ declare_function(CompilerRuntime::resolve_dynamic_invoke) \
|
|
+ declare_function(CompilerRuntime::resolve_string_by_symbol) \
|
|
+ declare_function(CompilerRuntime::resolve_klass_by_symbol) \
|
|
+ declare_function(CompilerRuntime::resolve_method_by_symbol_and_load_counters) \
|
|
+ declare_function(CompilerRuntime::initialize_klass_by_symbol) \
|
|
+ declare_function(CompilerRuntime::invocation_event) \
|
|
+ declare_function(CompilerRuntime::backedge_event)
|
|
+
|
|
+#else // INCLUDE_AOT
|
|
+
|
|
+#define VM_ADDRESSES_COMPILER_RUNTIME(declare_address, declare_preprocessor_address, declare_function)
|
|
+
|
|
+#endif // INCLUDE_AOT
|
|
+
|
|
+#endif // SHARE_JVMCI_VMSTRUCTS_COMPILER_RUNTIME_HPP
|
|
diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp
|
|
index 3f57d487b..3cd545532 100644
|
|
--- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp
|
|
+++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2015, 2021, 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
|
|
@@ -29,6 +29,7 @@
|
|
#include "jvmci/jvmciCodeInstaller.hpp"
|
|
#include "jvmci/jvmciCompilerToVM.hpp"
|
|
#include "jvmci/jvmciRuntime.hpp"
|
|
+#include "jvmci/vmStructs_compiler_runtime.hpp"
|
|
#include "jvmci/vmStructs_jvmci.hpp"
|
|
#include "oops/klassVtable.hpp"
|
|
#include "oops/objArrayKlass.hpp"
|
|
@@ -234,6 +235,7 @@
|
|
JVMTI_ONLY(nonstatic_field(MethodCounters, _number_of_breakpoints, u2)) \
|
|
nonstatic_field(MethodCounters, _invocation_counter, InvocationCounter) \
|
|
nonstatic_field(MethodCounters, _backedge_counter, InvocationCounter) \
|
|
+ AOT_ONLY(nonstatic_field(MethodCounters, _method, Method*)) \
|
|
\
|
|
nonstatic_field(MethodData, _size, int) \
|
|
nonstatic_field(MethodData, _method, Method*) \
|
|
@@ -870,6 +872,9 @@ VMAddressEntry JVMCIVMStructs::localHotSpotVMAddresses[] = {
|
|
VM_ADDRESSES(GENERATE_VM_ADDRESS_ENTRY,
|
|
GENERATE_PREPROCESSOR_VM_ADDRESS_ENTRY,
|
|
GENERATE_VM_FUNCTION_ENTRY)
|
|
+ VM_ADDRESSES_COMPILER_RUNTIME(GENERATE_VM_ADDRESS_ENTRY,
|
|
+ GENERATE_PREPROCESSOR_VM_ADDRESS_ENTRY,
|
|
+ GENERATE_VM_FUNCTION_ENTRY)
|
|
VM_ADDRESSES_OS(GENERATE_VM_ADDRESS_ENTRY,
|
|
GENERATE_PREPROCESSOR_VM_ADDRESS_ENTRY,
|
|
GENERATE_VM_FUNCTION_ENTRY)
|
|
diff --git a/src/hotspot/share/logging/logTag.hpp b/src/hotspot/share/logging/logTag.hpp
|
|
index d8ae64bc8..8bcdd16a7 100644
|
|
--- a/src/hotspot/share/logging/logTag.hpp
|
|
+++ b/src/hotspot/share/logging/logTag.hpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2015, 2021, 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
|
|
@@ -36,7 +36,7 @@
|
|
LOG_TAG(age) \
|
|
LOG_TAG(alloc) \
|
|
LOG_TAG(annotation) \
|
|
- JBOOSTER_ONLY(LOG_TAG(aot)) \
|
|
+ AOT_ONLY(LOG_TAG(aot)) \
|
|
LOG_TAG(arguments) \
|
|
LOG_TAG(attach) \
|
|
LOG_TAG(barrier) \
|
|
@@ -45,7 +45,7 @@
|
|
LOG_TAG(bot) \
|
|
LOG_TAG(breakpoint) \
|
|
LOG_TAG(bytecode) \
|
|
- LOG_TAG(cds) \
|
|
+ CDS_ONLY(LOG_TAG(cds)) \
|
|
LOG_TAG(census) \
|
|
LOG_TAG(class) \
|
|
LOG_TAG(classhisto) \
|
|
diff --git a/src/hotspot/share/memory/heap.hpp b/src/hotspot/share/memory/heap.hpp
|
|
index 7405cfe59..155bf4446 100644
|
|
--- a/src/hotspot/share/memory/heap.hpp
|
|
+++ b/src/hotspot/share/memory/heap.hpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 1997, 2021, 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
|
|
@@ -171,7 +171,16 @@ class CodeHeap : public CHeapObj<mtCode> {
|
|
// Containment means "contained in committed space".
|
|
bool contains(const void* p) const { return low() <= p && p < high(); }
|
|
bool contains_blob(const CodeBlob* blob) const {
|
|
- return contains((void*)blob);
|
|
+ // AOT CodeBlobs (i.e. AOTCompiledMethod) objects aren't allocated in the AOTCodeHeap but on the C-Heap.
|
|
+ // Only the code they are pointing to is located in the AOTCodeHeap. All other CodeBlobs are allocated
|
|
+ // directly in their corresponding CodeHeap with their code appended to the actual C++ object.
|
|
+ // So all CodeBlobs except AOTCompiledMethod are continuous in memory with their data and code while
|
|
+ // AOTCompiledMethod and their code/data is distributed in the C-Heap. This means we can use the
|
|
+ // address of a CodeBlob object in order to locate it in its heap while we have to use the address
|
|
+ // of the actual code an AOTCompiledMethod object is pointing to in order to locate it.
|
|
+ // Notice that for an ordinary CodeBlob with code size zero, code_begin() may point beyond the object!
|
|
+ const void* start = AOT_ONLY( (code_blob_type() == CodeBlobType::AOT) ? blob->code_begin() : ) (void*)blob;
|
|
+ return contains(start);
|
|
}
|
|
|
|
virtual void* find_start(void* p) const; // returns the block containing p or NULL
|
|
diff --git a/src/hotspot/share/memory/metaspace.cpp b/src/hotspot/share/memory/metaspace.cpp
|
|
index 1e897615e..7e5898e6d 100644
|
|
--- a/src/hotspot/share/memory/metaspace.cpp
|
|
+++ b/src/hotspot/share/memory/metaspace.cpp
|
|
@@ -1,6 +1,6 @@
|
|
/*
|
|
- * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
- * Copyright (c) 2017, 2021 SAP SE. All rights reserved.
|
|
+ * Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2017, 2023 SAP SE. 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
|
|
@@ -57,7 +57,9 @@
|
|
#include "utilities/debug.hpp"
|
|
#include "utilities/formatBuffer.hpp"
|
|
#include "utilities/globalDefinitions.hpp"
|
|
-
|
|
+#if INCLUDE_AOT
|
|
+#include "aot/aotLoader.hpp"
|
|
+#endif
|
|
using metaspace::ChunkManager;
|
|
using metaspace::CommitLimiter;
|
|
using metaspace::MetaspaceContext;
|
|
diff --git a/src/hotspot/share/memory/universe.cpp b/src/hotspot/share/memory/universe.cpp
|
|
index 8ba5fae9c..31d86d95a 100644
|
|
--- a/src/hotspot/share/memory/universe.cpp
|
|
+++ b/src/hotspot/share/memory/universe.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 1997, 2021, 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
|
|
@@ -79,6 +79,9 @@
|
|
#include "utilities/macros.hpp"
|
|
#include "utilities/ostream.hpp"
|
|
#include "utilities/preserveException.hpp"
|
|
+#if INCLUDE_AOT
|
|
+#include "aot/aotLoader.hpp"
|
|
+#endif
|
|
|
|
// Known objects
|
|
Klass* Universe::_typeArrayKlassObjs[T_LONG+1] = { NULL /*, NULL...*/ };
|
|
@@ -743,6 +746,10 @@ jint universe_init() {
|
|
// Initialize performance counters for metaspaces
|
|
MetaspaceCounters::initialize_performance_counters();
|
|
|
|
+#if INCLUDE_AOT
|
|
+ AOTLoader::universe_init();
|
|
+#endif
|
|
+
|
|
// Checks 'AfterMemoryInit' constraints.
|
|
if (!JVMFlagLimit::check_all_constraints(JVMFlagConstraintPhase::AfterMemoryInit)) {
|
|
return JNI_EINVAL;
|
|
diff --git a/src/hotspot/share/memory/virtualspace.hpp b/src/hotspot/share/memory/virtualspace.hpp
|
|
index a3b8683d3..4dece6743 100644
|
|
--- a/src/hotspot/share/memory/virtualspace.hpp
|
|
+++ b/src/hotspot/share/memory/virtualspace.hpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 1997, 2021, 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
|
|
@@ -209,6 +209,14 @@ class VirtualSpace {
|
|
char* low_boundary() const { return _low_boundary; }
|
|
char* high_boundary() const { return _high_boundary; }
|
|
|
|
+#if INCLUDE_AOT
|
|
+ // Set boundaries for code section in AOT library.
|
|
+ void set_low_boundary(char *p) { _low_boundary = p; }
|
|
+ void set_high_boundary(char *p) { _high_boundary = p; }
|
|
+ void set_low(char *p) { _low = p; }
|
|
+ void set_high(char *p) { _high = p; }
|
|
+#endif
|
|
+
|
|
bool special() const { return _special; }
|
|
|
|
public:
|
|
diff --git a/src/hotspot/share/oops/compressedOops.cpp b/src/hotspot/share/oops/compressedOops.cpp
|
|
index bb050673e..03dbf5966 100644
|
|
--- a/src/hotspot/share/oops/compressedOops.cpp
|
|
+++ b/src/hotspot/share/oops/compressedOops.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2019, 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
|
|
@@ -33,6 +33,9 @@
|
|
#include "gc/shared/collectedHeap.hpp"
|
|
#include "runtime/arguments.hpp"
|
|
#include "runtime/globals.hpp"
|
|
+#if INCLUDE_AOT
|
|
+#include "aot/aotLoader.hpp"
|
|
+#endif
|
|
|
|
// For UseCompressedOops.
|
|
NarrowPtrStruct CompressedOops::_narrow_oop = { NULL, 0, true };
|
|
@@ -64,6 +67,10 @@ void CompressedOops::initialize(const ReservedHeapSpace& heap_space) {
|
|
set_base((address)heap_space.compressed_oop_base());
|
|
}
|
|
|
|
+#if INCLUDE_AOT
|
|
+ AOTLoader::set_narrow_oop_shift();
|
|
+#endif
|
|
+
|
|
_heap_address_range = heap_space.region();
|
|
|
|
LogTarget(Debug, gc, heap, coops) lt;
|
|
@@ -260,6 +267,12 @@ void CompressedKlassPointers::initialize(address addr, size_t len) {
|
|
set_base(base);
|
|
set_shift(shift);
|
|
set_range(range);
|
|
+
|
|
+#if INCLUDE_AOT
|
|
+ // Note: this may modify our shift.
|
|
+ AOTLoader::set_narrow_klass_shift();
|
|
+#endif // INCLUDE_AOT
|
|
+
|
|
#else
|
|
fatal("64bit only.");
|
|
#endif
|
|
diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp
|
|
index 47c4d31c1..462505851 100644
|
|
--- a/src/hotspot/share/oops/instanceKlass.cpp
|
|
+++ b/src/hotspot/share/oops/instanceKlass.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 1997, 2021, 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
|
|
@@ -95,7 +95,9 @@
|
|
#if INCLUDE_JFR
|
|
#include "jfr/jfrEvents.hpp"
|
|
#endif
|
|
-
|
|
+#if INCLUDE_AOT
|
|
+#include "aot/aotLoader.hpp"
|
|
+#endif
|
|
|
|
#ifdef DTRACE_ENABLED
|
|
|
|
@@ -426,7 +428,8 @@ InstanceKlass* InstanceKlass::allocate_instance_klass(const ClassFileParser& par
|
|
const int size = InstanceKlass::size(parser.vtable_size(),
|
|
parser.itable_size(),
|
|
nonstatic_oop_map_size(parser.total_oop_map_count()),
|
|
- parser.is_interface());
|
|
+ parser.is_interface(),
|
|
+ AOT_ONLY(should_store_fingerprint(parser.is_hidden())) NOT_AOT(false));
|
|
|
|
const Symbol* const class_name = parser.class_name();
|
|
assert(class_name != NULL, "invariant");
|
|
@@ -1170,6 +1173,11 @@ void InstanceKlass::initialize_impl(TRAPS) {
|
|
}
|
|
|
|
|
|
+#if INCLUDE_AOT
|
|
+ // Look for aot compiled methods for this klass, including class initializer.
|
|
+ AOTLoader::load_for_klass(this, THREAD);
|
|
+#endif
|
|
+
|
|
// Step 8
|
|
{
|
|
DTRACE_CLASSINIT_PROBE_WAIT(clinit, -1, wait);
|
|
@@ -2391,6 +2399,84 @@ void InstanceKlass::clean_method_data() {
|
|
}
|
|
}
|
|
|
|
+#if INCLUDE_AOT
|
|
+bool InstanceKlass::supers_have_passed_fingerprint_checks() {
|
|
+ if (java_super() != NULL && !java_super()->has_passed_fingerprint_check()) {
|
|
+ ResourceMark rm;
|
|
+ log_trace(class, fingerprint)("%s : super %s not fingerprinted", external_name(), java_super()->external_name());
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ Array<InstanceKlass*>* local_interfaces = this->local_interfaces();
|
|
+ if (local_interfaces != NULL) {
|
|
+ int length = local_interfaces->length();
|
|
+ for (int i = 0; i < length; i++) {
|
|
+ InstanceKlass* intf = local_interfaces->at(i);
|
|
+ if (!intf->has_passed_fingerprint_check()) {
|
|
+ ResourceMark rm;
|
|
+ log_trace(class, fingerprint)("%s : interface %s not fingerprinted", external_name(), intf->external_name());
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+u1 InstanceKlass::get_aot_flags() const {
|
|
+ address adr = adr_aot_flags();
|
|
+ return (u1)(*adr);
|
|
+}
|
|
+
|
|
+void InstanceKlass::set_aot_flags(u1 aot_flags) {
|
|
+ address adr = adr_aot_flags();
|
|
+ *(u1*)adr = aot_flags;
|
|
+}
|
|
+
|
|
+
|
|
+bool InstanceKlass::should_store_fingerprint(bool is_hidden) {
|
|
+ // We store the fingerprint into the InstanceKlass only in the following 2 cases:
|
|
+ if (CalculateClassFingerprint) {
|
|
+ // (1) We are running AOT to generate a shared library.
|
|
+ return true;
|
|
+ }
|
|
+ if (Arguments::is_dumping_archive()) {
|
|
+ // (2) We are running -Xshare:dump or -XX:ArchiveClassesAtExit to create a shared archive
|
|
+ return true;
|
|
+ }
|
|
+ if (UseAOT && is_hidden) {
|
|
+ // (3) We are using AOT code from a shared library and see a hidden class
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ // In all other cases we might set the _has_passed_fingerprint_check bit,
|
|
+ // but do not store the 64-bit fingerprint to save space.
|
|
+ return false;
|
|
+}
|
|
+
|
|
+bool InstanceKlass::has_stored_fingerprint() const {
|
|
+ return should_store_fingerprint() || is_shared();
|
|
+}
|
|
+
|
|
+uint64_t InstanceKlass::get_stored_fingerprint() const {
|
|
+ address adr = adr_fingerprint();
|
|
+ if (adr != NULL) {
|
|
+ return (uint64_t)Bytes::get_native_u8(adr); // adr may not be 64-bit aligned
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+void InstanceKlass::store_fingerprint(uint64_t fingerprint) {
|
|
+ address adr = adr_fingerprint();
|
|
+ if (adr != NULL) {
|
|
+ Bytes::put_native_u8(adr, (u8)fingerprint); // adr may not be 64-bit aligned
|
|
+
|
|
+ ResourceMark rm;
|
|
+ log_trace(class, fingerprint)("stored as " PTR64_FORMAT " for class %s", fingerprint, external_name());
|
|
+ }
|
|
+}
|
|
+#endif
|
|
+
|
|
void InstanceKlass::metaspace_pointers_do(MetaspaceClosure* it) {
|
|
Klass::metaspace_pointers_do(it);
|
|
|
|
diff --git a/src/hotspot/share/oops/instanceKlass.hpp b/src/hotspot/share/oops/instanceKlass.hpp
|
|
index c111a6ab5..047b81a0c 100644
|
|
--- a/src/hotspot/share/oops/instanceKlass.hpp
|
|
+++ b/src/hotspot/share/oops/instanceKlass.hpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 1997, 2021, 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
|
|
@@ -50,6 +50,8 @@ class RecordComponent;
|
|
// The embedded nonstatic oop-map blocks are short pairs (offset, length)
|
|
// indicating where oops are located in instances of this klass.
|
|
// [EMBEDDED implementor of the interface] only exist for interface
|
|
+// [EMBEDDED fingerprint] only if should_store_fingerprint() == true
|
|
+// [EMBEDDED aot_flags ] only if INCLUDE_AOT == true
|
|
|
|
|
|
// forward declaration for class -- see below for definition
|
|
@@ -329,6 +331,13 @@ class InstanceKlass: public Klass {
|
|
|
|
static bool _disable_method_binary_search;
|
|
|
|
+#if INCLUDE_AOT
|
|
+ enum {
|
|
+ _aot_has_passed_fingerprint_check = 1 << 0 // when this class was loaded, the fingerprint computed from its
|
|
+ // code source was found to be matching the value recorded by AOT.
|
|
+ };
|
|
+#endif
|
|
+
|
|
public:
|
|
// The three BUILTIN class loader types
|
|
bool is_shared_boot_class() const {
|
|
@@ -775,6 +784,30 @@ public:
|
|
_misc_flags |= _misc_has_been_redefined;
|
|
}
|
|
|
|
+#if INCLUDE_AOT
|
|
+ bool has_passed_fingerprint_check() const {
|
|
+ return (get_aot_flags() & _aot_has_passed_fingerprint_check) != 0;
|
|
+ }
|
|
+ void set_has_passed_fingerprint_check(bool b) {
|
|
+ u1 aot_flags = get_aot_flags();
|
|
+ if (b) {
|
|
+ aot_flags |= _aot_has_passed_fingerprint_check;
|
|
+ } else {
|
|
+ aot_flags &= ~_aot_has_passed_fingerprint_check;
|
|
+ }
|
|
+ set_aot_flags(aot_flags);
|
|
+ }
|
|
+ bool supers_have_passed_fingerprint_checks();
|
|
+ u1 get_aot_flags() const;
|
|
+ void set_aot_flags(u1 aot_flags);
|
|
+
|
|
+ static bool should_store_fingerprint(bool is_hidden);
|
|
+ bool should_store_fingerprint() const { return should_store_fingerprint(is_hidden()); }
|
|
+ bool has_stored_fingerprint() const;
|
|
+ uint64_t get_stored_fingerprint() const;
|
|
+ void store_fingerprint(uint64_t fingerprint);
|
|
+#endif
|
|
+
|
|
bool is_scratch_class() const {
|
|
return (_misc_flags & _misc_is_scratch_class) != 0;
|
|
}
|
|
@@ -1032,18 +1065,21 @@ public:
|
|
|
|
static int size(int vtable_length, int itable_length,
|
|
int nonstatic_oop_map_size,
|
|
- bool is_interface) {
|
|
+ bool is_interface, bool has_stored_fingerprint) {
|
|
return align_metadata_size(header_size() +
|
|
vtable_length +
|
|
itable_length +
|
|
nonstatic_oop_map_size +
|
|
- (is_interface ? (int)sizeof(Klass*)/wordSize : 0));
|
|
+ (is_interface ? (int)sizeof(Klass*)/wordSize : 0) +
|
|
+ (has_stored_fingerprint ? (int)sizeof(uint64_t*)/wordSize : 0) +
|
|
+ AOT_ONLY(sizeof(u1)) NOT_AOT(0));
|
|
}
|
|
|
|
int size() const { return size(vtable_length(),
|
|
itable_length(),
|
|
nonstatic_oop_map_size(),
|
|
- is_interface());
|
|
+ is_interface(),
|
|
+ AOT_ONLY(has_stored_fingerprint()) NOT_AOT(false));
|
|
}
|
|
|
|
|
|
@@ -1056,6 +1092,10 @@ public:
|
|
inline Klass** end_of_nonstatic_oop_maps() const;
|
|
|
|
inline InstanceKlass* volatile* adr_implementor() const;
|
|
+#if INCLUDE_AOT
|
|
+ inline address adr_fingerprint() const;
|
|
+ inline address adr_aot_flags() const ;
|
|
+#endif
|
|
|
|
// Use this to return the size of an instance in heap words:
|
|
int size_helper() const {
|
|
@@ -1277,12 +1317,6 @@ public:
|
|
|
|
#if INCLUDE_JBOOSTER
|
|
bool is_dynamic_proxy() const;
|
|
-
|
|
- // [JBOOSTER TODO] aot
|
|
- bool should_store_fingerprint() const { return true; }
|
|
- bool has_stored_fingerprint() const { return true; }
|
|
- uint64_t get_stored_fingerprint() const { return 0u; }
|
|
- void store_fingerprint(uint64_t fingerprint) {}
|
|
#endif // INCLUDE_JBOOSTER
|
|
};
|
|
|
|
diff --git a/src/hotspot/share/oops/instanceKlass.inline.hpp b/src/hotspot/share/oops/instanceKlass.inline.hpp
|
|
index 8b6e2c335..192c2bb9e 100644
|
|
--- a/src/hotspot/share/oops/instanceKlass.inline.hpp
|
|
+++ b/src/hotspot/share/oops/instanceKlass.inline.hpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2015, 2021, 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
|
|
@@ -62,6 +62,35 @@ inline InstanceKlass* volatile* InstanceKlass::adr_implementor() const {
|
|
}
|
|
}
|
|
|
|
+#if INCLUDE_AOT
|
|
+inline address InstanceKlass::adr_fingerprint() const {
|
|
+ if (has_stored_fingerprint()) {
|
|
+ InstanceKlass* volatile* adr_impl = adr_implementor();
|
|
+ if (adr_impl != NULL) {
|
|
+ return (address)(adr_impl + 1);
|
|
+ } else {
|
|
+ return (address)end_of_nonstatic_oop_maps();
|
|
+ }
|
|
+ } else {
|
|
+ return NULL;
|
|
+ }
|
|
+}
|
|
+
|
|
+inline u1* InstanceKlass::adr_aot_flags() const {
|
|
+ address fingerprint = adr_fingerprint();
|
|
+ if (fingerprint != NULL) {
|
|
+ return (u1*)(fingerprint + sizeof(uint64_t));
|
|
+ }
|
|
+
|
|
+ InstanceKlass* volatile* adr_impl = adr_implementor();
|
|
+ if (adr_impl != NULL) {
|
|
+ return (u1*)(adr_impl + 1);
|
|
+ } else {
|
|
+ return (u1*)end_of_nonstatic_oop_maps();
|
|
+ }
|
|
+}
|
|
+#endif
|
|
+
|
|
inline ObjArrayKlass* InstanceKlass::array_klasses_acquire() const {
|
|
return Atomic::load_acquire(&_array_klasses);
|
|
}
|
|
diff --git a/src/hotspot/share/oops/method.hpp b/src/hotspot/share/oops/method.hpp
|
|
index d3e77ba70..1155f33a4 100644
|
|
--- a/src/hotspot/share/oops/method.hpp
|
|
+++ b/src/hotspot/share/oops/method.hpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 1997, 2021, 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
|
|
@@ -116,6 +116,10 @@ class Method : public Metadata {
|
|
CompiledMethod* volatile _code; // Points to the corresponding piece of native code
|
|
volatile address _from_interpreted_entry; // Cache of _code ? _adapter->i2c_entry() : _i2i_entry
|
|
|
|
+#if INCLUDE_AOT
|
|
+ CompiledMethod* _aot_code;
|
|
+#endif
|
|
+
|
|
// Constructor
|
|
Method(ConstMethod* xconst, AccessFlags access_flags);
|
|
public:
|
|
@@ -401,6 +405,18 @@ class Method : public Metadata {
|
|
}
|
|
}
|
|
|
|
+#if INCLUDE_AOT
|
|
+ void set_aot_code(CompiledMethod* aot_code) {
|
|
+ _aot_code = aot_code;
|
|
+ }
|
|
+
|
|
+ CompiledMethod* aot_code() const {
|
|
+ return _aot_code;
|
|
+ }
|
|
+#else
|
|
+ CompiledMethod* aot_code() const { return NULL; }
|
|
+#endif // INCLUDE_AOT
|
|
+
|
|
int nmethod_age() const {
|
|
if (method_counters() == NULL) {
|
|
return INT_MAX;
|
|
@@ -659,6 +675,8 @@ public:
|
|
// simultaneously. Use with caution.
|
|
bool has_compiled_code() const;
|
|
|
|
+ bool has_aot_code() const { return aot_code() != NULL; }
|
|
+
|
|
bool needs_clinit_barrier() const;
|
|
|
|
// sizing
|
|
diff --git a/src/hotspot/share/oops/methodCounters.cpp b/src/hotspot/share/oops/methodCounters.cpp
|
|
index 67b2ef960..23a6c91b9 100644
|
|
--- a/src/hotspot/share/oops/methodCounters.cpp
|
|
+++ b/src/hotspot/share/oops/methodCounters.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2013, 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
|
|
@@ -23,11 +23,15 @@
|
|
*/
|
|
#include "precompiled.hpp"
|
|
#include "compiler/compiler_globals.hpp"
|
|
+#include "memory/metaspaceClosure.hpp"
|
|
#include "oops/method.hpp"
|
|
#include "oops/methodCounters.hpp"
|
|
#include "runtime/handles.inline.hpp"
|
|
|
|
MethodCounters::MethodCounters(const methodHandle& mh) :
|
|
+#if INCLUDE_AOT
|
|
+ _method(mh()),
|
|
+#endif
|
|
_prev_time(0),
|
|
_rate(0),
|
|
_nmethod_age(INT_MAX),
|
|
@@ -73,6 +77,13 @@ void MethodCounters::clear_counters() {
|
|
set_highest_osr_comp_level(0);
|
|
}
|
|
|
|
+void MethodCounters::metaspace_pointers_do(MetaspaceClosure* it) {
|
|
+ log_trace(cds)("Iter(MethodCounters): %p", this);
|
|
+#if INCLUDE_AOT
|
|
+ it->push(&_method);
|
|
+#endif
|
|
+}
|
|
+
|
|
void MethodCounters::print_value_on(outputStream* st) const {
|
|
assert(is_methodCounters(), "must be methodCounters");
|
|
st->print("method counters");
|
|
diff --git a/src/hotspot/share/oops/methodCounters.hpp b/src/hotspot/share/oops/methodCounters.hpp
|
|
index 2698ce3d3..b75b50e31 100644
|
|
--- a/src/hotspot/share/oops/methodCounters.hpp
|
|
+++ b/src/hotspot/share/oops/methodCounters.hpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2013, 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
|
|
@@ -37,6 +37,11 @@ class MethodCounters : public Metadata {
|
|
private:
|
|
InvocationCounter _invocation_counter; // Incremented before each activation of the method - used to trigger frequency-based optimizations
|
|
InvocationCounter _backedge_counter; // Incremented before each backedge taken - used to trigger frequency-based optimizations
|
|
+ // If you add a new field that points to any metaspace object, you
|
|
+ // must add this field to MethodCounters::metaspace_pointers_do().
|
|
+#if INCLUDE_AOT
|
|
+ Method* _method; // Back link to Method
|
|
+#endif
|
|
jlong _prev_time; // Previous time the rate was acquired
|
|
float _rate; // Events (invocation and backedge counter increments) per millisecond
|
|
int _nmethod_age;
|
|
@@ -69,12 +74,15 @@ class MethodCounters : public Metadata {
|
|
|
|
void deallocate_contents(ClassLoaderData* loader_data) {}
|
|
|
|
+ AOT_ONLY(Method* method() const { return _method; })
|
|
+
|
|
static int method_counters_size() {
|
|
return align_up((int)sizeof(MethodCounters), wordSize) / wordSize;
|
|
}
|
|
virtual int size() const {
|
|
return method_counters_size();
|
|
}
|
|
+ void metaspace_pointers_do(MetaspaceClosure* it);
|
|
MetaspaceObj::Type type() const { return MethodCountersType; }
|
|
void clear_counters();
|
|
|
|
diff --git a/src/hotspot/share/opto/c2compiler.cpp b/src/hotspot/share/opto/c2compiler.cpp
|
|
index 473684107..13de7651e 100644
|
|
--- a/src/hotspot/share/opto/c2compiler.cpp
|
|
+++ b/src/hotspot/share/opto/c2compiler.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 1999, 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
|
|
@@ -79,7 +79,7 @@ bool C2Compiler::init_c2_runtime() {
|
|
}
|
|
|
|
void C2Compiler::initialize() {
|
|
- assert(!CompilerConfig::is_c1_or_interpreter_only_no_jvmci(), "C2 compiler is launched, it's not c1/interpreter only mode");
|
|
+ assert(!CompilerConfig::is_c1_or_interpreter_only_no_aot_or_jvmci(), "C2 compiler is launched, it's not c1/interpreter only mode");
|
|
// The first compiler thread that gets here will initialize the
|
|
// small amount of global state (and runtime stubs) that C2 needs.
|
|
|
|
diff --git a/src/hotspot/share/opto/output.cpp b/src/hotspot/share/opto/output.cpp
|
|
index 8a1ed0d31..cab6d0067 100644
|
|
--- a/src/hotspot/share/opto/output.cpp
|
|
+++ b/src/hotspot/share/opto/output.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
|
|
@@ -575,6 +575,10 @@ void PhaseOutput::shorten_branches(uint* blk_starts) {
|
|
if (mcall->is_MachCallJava() && mcall->as_MachCallJava()->_method) {
|
|
stub_size += CompiledStaticCall::to_interp_stub_size();
|
|
reloc_size += CompiledStaticCall::reloc_to_interp_stub();
|
|
+#if INCLUDE_AOT
|
|
+ stub_size += CompiledStaticCall::to_aot_stub_size();
|
|
+ reloc_size += CompiledStaticCall::reloc_to_aot_stub();
|
|
+#endif
|
|
}
|
|
} else if (mach->is_MachSafePoint()) {
|
|
// If call/safepoint are adjacent, account for possible
|
|
diff --git a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp
|
|
index 5922dd979..c4c03ab8d 100644
|
|
--- a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp
|
|
+++ b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2003, 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
|
|
@@ -63,6 +63,9 @@
|
|
#include "runtime/safepointVerifiers.hpp"
|
|
#include "utilities/bitMap.inline.hpp"
|
|
#include "utilities/events.hpp"
|
|
+#if INCLUDE_AOT
|
|
+#include "aot/aotLoader.hpp"
|
|
+#endif
|
|
|
|
Array<Method*>* VM_RedefineClasses::_old_methods = NULL;
|
|
Array<Method*>* VM_RedefineClasses::_new_methods = NULL;
|
|
@@ -4421,6 +4424,18 @@ void VM_RedefineClasses::redefine_single_class(Thread* current, jclass the_jclas
|
|
// Scratch class is unloaded but still needs cleaning, and skipping for CDS.
|
|
scratch_class->set_is_scratch_class();
|
|
|
|
+#if INCLUDE_AOT
|
|
+ // Replace fingerprint data
|
|
+ the_class->set_has_passed_fingerprint_check(scratch_class->has_passed_fingerprint_check());
|
|
+ the_class->store_fingerprint(scratch_class->get_stored_fingerprint());
|
|
+
|
|
+ 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());
|
|
+ }
|
|
+#endif
|
|
+
|
|
// keep track of previous versions of this class
|
|
the_class->add_previous_version(scratch_class, emcp_method_count);
|
|
|
|
diff --git a/src/hotspot/share/prims/jvmtiTagMap.cpp b/src/hotspot/share/prims/jvmtiTagMap.cpp
|
|
index 68228f514..0de584980 100644
|
|
--- a/src/hotspot/share/prims/jvmtiTagMap.cpp
|
|
+++ b/src/hotspot/share/prims/jvmtiTagMap.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2003, 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
|
|
@@ -2628,7 +2628,7 @@ inline bool VM_HeapWalkOperation::iterate_over_class(oop java_class) {
|
|
} else if (tag.is_klass()) {
|
|
entry = pool->resolved_klass_at(i)->java_mirror();
|
|
} else {
|
|
- // Code generated by JIT compilers might not resolve constant
|
|
+ // Code generated by JIT and AOT compilers might not resolve constant
|
|
// pool entries. Treat them as resolved if they are loaded.
|
|
assert(tag.is_unresolved_klass(), "must be");
|
|
constantPoolHandle cp(Thread::current(), pool);
|
|
diff --git a/src/hotspot/share/prims/whitebox.cpp b/src/hotspot/share/prims/whitebox.cpp
|
|
index 5466ff988..86a9493a9 100644
|
|
--- a/src/hotspot/share/prims/whitebox.cpp
|
|
+++ b/src/hotspot/share/prims/whitebox.cpp
|
|
@@ -113,6 +113,9 @@
|
|
#include "jvmci/jvmciEnv.hpp"
|
|
#include "jvmci/jvmciRuntime.hpp"
|
|
#endif
|
|
+#if INCLUDE_AOT
|
|
+#include "aot/aotLoader.hpp"
|
|
+#endif // INCLUDE_AOT
|
|
|
|
#ifdef LINUX
|
|
#include "os_linux.hpp"
|
|
@@ -1411,6 +1414,9 @@ WB_END
|
|
|
|
int WhiteBox::get_blob_type(const CodeBlob* code) {
|
|
guarantee(WhiteBoxAPI, "internal testing API :: WhiteBox has to be enabled");
|
|
+ if (code->is_aot()) {
|
|
+ return -1;
|
|
+ }
|
|
return CodeCache::get_code_heap(code)->code_blob_type();
|
|
}
|
|
|
|
@@ -1468,7 +1474,7 @@ WB_ENTRY(jobjectArray, WB_GetNMethod(JNIEnv* env, jobject o, jobject method, jbo
|
|
return result;
|
|
}
|
|
int comp_level = code->comp_level();
|
|
- int insts_size = code->insts_size();
|
|
+ int insts_size = comp_level == CompLevel_aot ? code->code_end() - code->code_begin() : code->insts_size();
|
|
|
|
ThreadToNativeFromVM ttn(thread);
|
|
jclass clazz = env->FindClass(vmSymbols::java_lang_Object()->as_C_string());
|
|
@@ -2257,6 +2263,14 @@ WB_ENTRY(jint, WB_ProtectionDomainRemovedCount(JNIEnv* env, jobject o))
|
|
return (jint) SystemDictionary::pd_cache_table()->removed_entries_count();
|
|
WB_END
|
|
|
|
+WB_ENTRY(jint, WB_AotLibrariesCount(JNIEnv* env, jobject o))
|
|
+ jint result = 0;
|
|
+#if INCLUDE_AOT
|
|
+ result = (jint) AOTLoader::heaps_count();
|
|
+#endif
|
|
+ return result;
|
|
+WB_END
|
|
+
|
|
WB_ENTRY(jint, WB_GetKlassMetadataSize(JNIEnv* env, jobject wb, jclass mirror))
|
|
Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve(mirror));
|
|
// Return size in bytes.
|
|
@@ -2620,6 +2634,7 @@ static JNINativeMethod methods[] = {
|
|
{CC"disableElfSectionCache", CC"()V", (void*)&WB_DisableElfSectionCache },
|
|
{CC"resolvedMethodItemsCount", CC"()J", (void*)&WB_ResolvedMethodItemsCount },
|
|
{CC"protectionDomainRemovedCount", CC"()I", (void*)&WB_ProtectionDomainRemovedCount },
|
|
+ {CC"aotLibrariesCount", CC"()I", (void*)&WB_AotLibrariesCount },
|
|
{CC"getKlassMetadataSize", CC"(Ljava/lang/Class;)I",(void*)&WB_GetKlassMetadataSize},
|
|
|
|
{CC"createMetaspaceTestContext", CC"(JJ)J", (void*)&WB_CreateMetaspaceTestContext},
|
|
diff --git a/src/hotspot/share/runtime/abstract_vm_version.cpp b/src/hotspot/share/runtime/abstract_vm_version.cpp
|
|
index cd8e239f0..a7e3e22ab 100644
|
|
--- a/src/hotspot/share/runtime/abstract_vm_version.cpp
|
|
+++ b/src/hotspot/share/runtime/abstract_vm_version.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 1998, 2022, 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
|
|
@@ -128,13 +128,17 @@ const char* Abstract_VM_Version::vm_info_string() {
|
|
return UseSharedSpaces ? "interpreted mode, sharing" : "interpreted mode";
|
|
case Arguments::_mixed:
|
|
if (UseSharedSpaces) {
|
|
- if (CompilationModeFlag::quick_only()) {
|
|
+ if (UseAOT) {
|
|
+ return "mixed mode, aot, sharing";
|
|
+ } else if (CompilationModeFlag::quick_only()) {
|
|
return "mixed mode, emulated-client, sharing";
|
|
} else {
|
|
return "mixed mode, sharing";
|
|
}
|
|
} else {
|
|
- if (CompilationModeFlag::quick_only()) {
|
|
+ if (UseAOT) {
|
|
+ return "mixed mode, aot";
|
|
+ } else if (CompilationModeFlag::quick_only()) {
|
|
return "mixed mode, emulated-client";
|
|
} else {
|
|
return "mixed mode";
|
|
diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp
|
|
index a1a737915..406434ab2 100644
|
|
--- a/src/hotspot/share/runtime/arguments.cpp
|
|
+++ b/src/hotspot/share/runtime/arguments.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 1997, 2021, 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
|
|
@@ -3151,6 +3151,21 @@ jint Arguments::finalize_vm_init_args(bool patch_mod_javabase) {
|
|
}
|
|
#endif
|
|
|
|
+#if !INCLUDE_AOT
|
|
+ UNSUPPORTED_OPTION(UseAOT);
|
|
+ UNSUPPORTED_OPTION(PrintAOT);
|
|
+ UNSUPPORTED_OPTION(UseAOTStrictLoading);
|
|
+ UNSUPPORTED_OPTION_NULL(AOTLibrary);
|
|
+
|
|
+ UNSUPPORTED_OPTION_INIT(Tier3AOTInvocationThreshold, 0);
|
|
+ UNSUPPORTED_OPTION_INIT(Tier3AOTMinInvocationThreshold, 0);
|
|
+ UNSUPPORTED_OPTION_INIT(Tier3AOTCompileThreshold, 0);
|
|
+ UNSUPPORTED_OPTION_INIT(Tier3AOTBackEdgeThreshold, 0);
|
|
+#ifndef PRODUCT
|
|
+ UNSUPPORTED_OPTION(PrintAOTStatistics);
|
|
+#endif
|
|
+#endif
|
|
+
|
|
#ifndef CAN_SHOW_REGISTERS_ON_ASSERT
|
|
UNSUPPORTED_OPTION(ShowRegistersOnAssert);
|
|
#endif // CAN_SHOW_REGISTERS_ON_ASSERT
|
|
diff --git a/src/hotspot/share/runtime/deoptimization.cpp b/src/hotspot/share/runtime/deoptimization.cpp
|
|
index 46a90b678..29e9955a1 100644
|
|
--- a/src/hotspot/share/runtime/deoptimization.cpp
|
|
+++ b/src/hotspot/share/runtime/deoptimization.cpp
|
|
@@ -947,7 +947,7 @@ void Deoptimization::deoptimize_all_marked(nmethod* nmethod_only) {
|
|
Deoptimization::DeoptAction Deoptimization::_unloaded_action
|
|
= Deoptimization::Action_reinterpret;
|
|
|
|
-#if COMPILER2_OR_JVMCI
|
|
+#if COMPILER2_OR_JVMCI || INCLUDE_AOT
|
|
template<typename CacheType>
|
|
class BoxCacheBase : public CHeapObj<mtCompiler> {
|
|
protected:
|
|
@@ -1075,7 +1075,9 @@ oop Deoptimization::get_cached_box(AutoBoxObjectValue* bv, frame* fr, RegisterMa
|
|
}
|
|
return NULL;
|
|
}
|
|
+#endif // COMPILER2_OR_JVMCI || INCLUDE_AOT
|
|
|
|
+#if COMPILER2_OR_JVMCI
|
|
bool Deoptimization::realloc_objects(JavaThread* thread, frame* fr, RegisterMap* reg_map, GrowableArray<ScopeValue*>* objects, TRAPS) {
|
|
Handle pending_exception(THREAD, thread->pending_exception());
|
|
const char* exception_file = thread->exception_file();
|
|
@@ -1092,6 +1094,7 @@ bool Deoptimization::realloc_objects(JavaThread* thread, frame* fr, RegisterMap*
|
|
oop obj = NULL;
|
|
|
|
if (k->is_instance_klass()) {
|
|
+#if COMPILER2_OR_JVMCI || INCLUDE_AOT
|
|
if (sv->is_auto_box()) {
|
|
AutoBoxObjectValue* abv = (AutoBoxObjectValue*) sv;
|
|
obj = get_cached_box(abv, fr, reg_map, THREAD);
|
|
@@ -1100,7 +1103,7 @@ bool Deoptimization::realloc_objects(JavaThread* thread, frame* fr, RegisterMap*
|
|
abv->set_cached(true);
|
|
}
|
|
}
|
|
-
|
|
+#endif // COMPILER2_OR_JVMCI || INCLUDE_AOT
|
|
InstanceKlass* ik = InstanceKlass::cast(k);
|
|
if (obj == NULL) {
|
|
#ifdef COMPILER2
|
|
@@ -1442,11 +1445,12 @@ void Deoptimization::reassign_fields(frame* fr, RegisterMap* reg_map, GrowableAr
|
|
if (obj.is_null()) {
|
|
continue;
|
|
}
|
|
-
|
|
+#if COMPILER2_OR_JVMCI || INCLUDE_AOT
|
|
// Don't reassign fields of boxes that came from a cache. Caches may be in CDS.
|
|
if (sv->is_auto_box() && ((AutoBoxObjectValue*) sv)->is_cached()) {
|
|
continue;
|
|
}
|
|
+#endif // COMPILER2_OR_JVMCI || INCLUDE_AOT
|
|
#ifdef COMPILER2
|
|
if (EnableVectorSupport && VectorSupport::is_vector(k)) {
|
|
assert(sv->field_size() == 1, "%s not a vector", k->name()->as_C_string());
|
|
@@ -1997,7 +2001,7 @@ JRT_ENTRY(void, Deoptimization::uncommon_trap_inner(JavaThread* current, jint tr
|
|
int trap_bci = trap_scope->bci();
|
|
#if INCLUDE_JVMCI
|
|
jlong speculation = current->pending_failed_speculation();
|
|
- if (nm->is_compiled_by_jvmci()) {
|
|
+ if (nm->is_compiled_by_jvmci() && nm->is_nmethod()) { // Exclude AOTed methods
|
|
nm->as_nmethod()->update_speculation(current);
|
|
} else {
|
|
assert(speculation == 0, "There should not be a speculation for methods compiled by non-JVMCI compilers");
|
|
diff --git a/src/hotspot/share/runtime/frame.cpp b/src/hotspot/share/runtime/frame.cpp
|
|
index 46dde1569..4ed026879 100644
|
|
--- a/src/hotspot/share/runtime/frame.cpp
|
|
+++ b/src/hotspot/share/runtime/frame.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 1997, 2021, 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
|
|
@@ -577,6 +577,7 @@ void frame::print_C_frame(outputStream* st, char* buf, int buflen, address pc) {
|
|
//
|
|
// First letter indicates type of the frame:
|
|
// J: Java frame (compiled)
|
|
+// A: Java frame (aot compiled)
|
|
// j: Java frame (interpreted)
|
|
// V: VM frame (C/C++)
|
|
// v: Other frames running VM generated code (e.g. stubs, adapters, etc.)
|
|
@@ -618,7 +619,9 @@ void frame::print_on_error(outputStream* st, char* buf, int buflen, bool verbose
|
|
CompiledMethod* cm = (CompiledMethod*)_cb;
|
|
Method* m = cm->method();
|
|
if (m != NULL) {
|
|
- if (cm->is_nmethod()) {
|
|
+ if (cm->is_aot()) {
|
|
+ st->print("A %d ", cm->compile_id());
|
|
+ } else if (cm->is_nmethod()) {
|
|
nmethod* nm = cm->as_nmethod();
|
|
st->print("J %d%s", nm->compile_id(), (nm->is_osr_method() ? "%" : ""));
|
|
st->print(" %s", nm->compiler_name());
|
|
@@ -1219,8 +1222,9 @@ void frame::describe(FrameValues& values, int frame_no) {
|
|
// For now just label the frame
|
|
CompiledMethod* cm = (CompiledMethod*)cb();
|
|
values.describe(-1, info_address,
|
|
- FormatBuffer<1024>("#%d nmethod " INTPTR_FORMAT " for method J %s%s", frame_no,
|
|
+ FormatBuffer<1024>("#%d nmethod " INTPTR_FORMAT " for method %s%s%s", frame_no,
|
|
p2i(cm),
|
|
+ (cm->is_aot() ? "A ": "J "),
|
|
cm->method()->name_and_sig_as_C_string(),
|
|
(_deopt_state == is_deoptimized) ?
|
|
" (deoptimized)" :
|
|
diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp
|
|
index 8eae5e5cc..27695a3f5 100644
|
|
--- a/src/hotspot/share/runtime/globals.hpp
|
|
+++ b/src/hotspot/share/runtime/globals.hpp
|
|
@@ -1652,6 +1652,25 @@ const intx ObjectAlignmentInBytes = 8;
|
|
"Non-segmented code cache: X[%] of the total code cache") \
|
|
range(0, 100) \
|
|
\
|
|
+ /* AOT parameters */ \
|
|
+ product(bool, UseAOT, false, EXPERIMENTAL, \
|
|
+ "Use AOT compiled files") \
|
|
+ \
|
|
+ product(ccstrlist, AOTLibrary, NULL, EXPERIMENTAL, \
|
|
+ "AOT library") \
|
|
+ \
|
|
+ product(bool, PrintAOT, false, EXPERIMENTAL, \
|
|
+ "Print used AOT klasses and methods") \
|
|
+ \
|
|
+ notproduct(bool, PrintAOTStatistics, false, \
|
|
+ "Print AOT statistics") \
|
|
+ \
|
|
+ product(bool, UseAOTStrictLoading, false, DIAGNOSTIC, \
|
|
+ "Exit the VM if any of the AOT libraries has invalid config") \
|
|
+ \
|
|
+ product(bool, CalculateClassFingerprint, false, \
|
|
+ "Calculate class fingerprint") \
|
|
+ \
|
|
/* interpreter debugging */ \
|
|
develop(intx, BinarySwitchThreshold, 5, \
|
|
"Minimal number of lookupswitch entries for rewriting to binary " \
|
|
diff --git a/src/hotspot/share/runtime/init.cpp b/src/hotspot/share/runtime/init.cpp
|
|
index 06974b89e..09e4313cb 100644
|
|
--- a/src/hotspot/share/runtime/init.cpp
|
|
+++ b/src/hotspot/share/runtime/init.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 1997, 2021, 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
|
|
@@ -67,6 +67,9 @@ void classLoader_init1();
|
|
void compilationPolicy_init();
|
|
void codeCache_init();
|
|
void VM_Version_init();
|
|
+#if INCLUDE_AOT
|
|
+void AOTLoader_init();
|
|
+#endif
|
|
void stubRoutines_init1();
|
|
jint universe_init(); // depends on codeCache_init and stubRoutines_init
|
|
// depends on universe_init, must be before interpreter_init (currently only on SPARC)
|
|
@@ -118,6 +121,9 @@ jint init_globals() {
|
|
compilationPolicy_init();
|
|
codeCache_init();
|
|
VM_Version_init(); // depends on codeCache_init for emitting code
|
|
+#if INCLUDE_AOT
|
|
+ AOTLoader_init(); // depends on VM_Version_init to adjust vm options
|
|
+#endif
|
|
stubRoutines_init1();
|
|
jint status = universe_init(); // dependent on codeCache_init and
|
|
// stubRoutines_init1 and metaspace_init.
|
|
diff --git a/src/hotspot/share/runtime/java.cpp b/src/hotspot/share/runtime/java.cpp
|
|
index d7b1c5ed6..e27a135fc 100644
|
|
--- a/src/hotspot/share/runtime/java.cpp
|
|
+++ b/src/hotspot/share/runtime/java.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 1997, 2021, 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
|
|
@@ -96,6 +96,9 @@
|
|
#if INCLUDE_JBOOSTER
|
|
#include "jbooster/client/clientMessageHandler.hpp"
|
|
#endif // INCLUDE_JBOOSTER
|
|
+#if INCLUDE_AOT
|
|
+#include "aot/aotLoader.hpp"
|
|
+#endif
|
|
|
|
GrowableArray<Method*>* collected_profiled_methods;
|
|
|
|
@@ -270,6 +273,12 @@ void print_statistics() {
|
|
#endif // INCLUDE_JVMCI
|
|
#endif // COMPILER2
|
|
|
|
+#if INCLUDE_AOT
|
|
+ if (PrintAOTStatistics) {
|
|
+ AOTLoader::print_statistics();
|
|
+ }
|
|
+#endif
|
|
+
|
|
if (PrintNMethodStatistics) {
|
|
nmethod::print_statistics();
|
|
}
|
|
diff --git a/src/hotspot/share/runtime/sharedRuntime.cpp b/src/hotspot/share/runtime/sharedRuntime.cpp
|
|
index 9af4b513a..bb6ff23e4 100644
|
|
--- a/src/hotspot/share/runtime/sharedRuntime.cpp
|
|
+++ b/src/hotspot/share/runtime/sharedRuntime.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 1997, 2021, 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
|
|
@@ -79,6 +79,9 @@
|
|
#ifdef COMPILER1
|
|
#include "c1/c1_Runtime1.hpp"
|
|
#endif
|
|
+#if INCLUDE_AOT
|
|
+#include "aot/aotLoader.hpp"
|
|
+#endif
|
|
|
|
// Shared stub locations
|
|
RuntimeStub* SharedRuntime::_wrong_method_blob;
|
|
@@ -1327,8 +1330,8 @@ bool SharedRuntime::resolve_sub_helper_internal(methodHandle callee_method, cons
|
|
if (VM_Version::supports_fast_class_init_checks() &&
|
|
invoke_code == Bytecodes::_invokestatic &&
|
|
callee_method->needs_clinit_barrier() &&
|
|
- callee != NULL && callee->is_compiled_by_jvmci()) {
|
|
- return true; // skip patching for JVMCI
|
|
+ callee != NULL && (callee->is_compiled_by_jvmci() || callee->is_aot())) {
|
|
+ return true; // skip patching for JVMCI or AOT code
|
|
}
|
|
CompiledStaticCall* ssc = caller_nm->compiledStaticCall_before(caller_frame.pc());
|
|
if (ssc->is_clean()) ssc->set(static_call_info);
|
|
diff --git a/src/hotspot/share/runtime/thread.cpp b/src/hotspot/share/runtime/thread.cpp
|
|
index c057b1ef5..a5d5d1ec7 100644
|
|
--- a/src/hotspot/share/runtime/thread.cpp
|
|
+++ b/src/hotspot/share/runtime/thread.cpp
|
|
@@ -1,6 +1,6 @@
|
|
/*
|
|
- * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
- * Copyright (c) 2021, Azul Systems, Inc. All rights reserved.
|
|
+ * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2021, 2023, Azul Systems, Inc. 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
|
|
@@ -152,6 +152,9 @@
|
|
#if INCLUDE_JBOOSTER
|
|
#include "jbooster/jBoosterManager.hpp"
|
|
#endif // INCLUDE_JBOOSTER
|
|
+#if INCLUDE_AOT
|
|
+#include "aot/aotLoader.hpp"
|
|
+#endif
|
|
|
|
// Initialization after module runtime initialization
|
|
void universe_post_module_init(); // must happen after call_initPhase2
|
|
@@ -2744,6 +2747,10 @@ void Threads::initialize_java_lang_classes(JavaThread* main_thread, TRAPS) {
|
|
initialize_class(vmSymbols::java_lang_StackOverflowError(), CHECK);
|
|
initialize_class(vmSymbols::java_lang_IllegalMonitorStateException(), CHECK);
|
|
initialize_class(vmSymbols::java_lang_IllegalArgumentException(), CHECK);
|
|
+#if INCLUDE_AOT
|
|
+ // Eager box cache initialization only if AOT is on and any library is loaded.
|
|
+ AOTLoader::initialize_box_caches(CHECK);
|
|
+#endif
|
|
}
|
|
|
|
void Threads::initialize_jsr292_core_classes(TRAPS) {
|
|
@@ -2955,8 +2962,8 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
|
|
}
|
|
|
|
// We need this to update the java.vm.info property in case any flags used
|
|
- // to initially define it have been changed. This is needed for both CDS
|
|
- // since UseSharedSpaces may be changed after java.vm.info
|
|
+ // to initially define it have been changed. This is needed for both CDS and
|
|
+ // AOT, since UseSharedSpaces and UseAOT may be changed after java.vm.info
|
|
// is initially computed. See Abstract_VM_Version::vm_info_string().
|
|
// This update must happen before we initialize the java classes, but
|
|
// after any initialization logic that might modify the flags.
|
|
diff --git a/src/hotspot/share/runtime/vframe_hp.cpp b/src/hotspot/share/runtime/vframe_hp.cpp
|
|
index 8405bb540..b6c919a38 100644
|
|
--- a/src/hotspot/share/runtime/vframe_hp.cpp
|
|
+++ b/src/hotspot/share/runtime/vframe_hp.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 1997, 2021, 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
|
|
@@ -228,7 +228,7 @@ GrowableArray<MonitorInfo*>* compiledVFrame::monitors() const {
|
|
if (scope() == NULL) {
|
|
CompiledMethod* nm = code();
|
|
Method* method = nm->method();
|
|
- assert(method->is_native(), "Expect a native method");
|
|
+ assert(method->is_native() || nm->is_aot(), "Expect a native method or precompiled method");
|
|
if (!method->is_synchronized()) {
|
|
return new GrowableArray<MonitorInfo*>(0);
|
|
}
|
|
diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp
|
|
index 33de84a68..ef2a366f7 100644
|
|
--- a/src/hotspot/share/runtime/vmStructs.cpp
|
|
+++ b/src/hotspot/share/runtime/vmStructs.cpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2000, 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
|
|
@@ -300,6 +300,7 @@ typedef HashtableEntry<InstanceKlass*, mtClass> KlassHashtableEntry;
|
|
JVMTI_ONLY(nonstatic_field(MethodCounters, _number_of_breakpoints, u2)) \
|
|
nonstatic_field(MethodCounters, _invocation_counter, InvocationCounter) \
|
|
nonstatic_field(MethodCounters, _backedge_counter, InvocationCounter) \
|
|
+ AOT_ONLY(nonstatic_field(MethodCounters, _method, Method*)) \
|
|
nonstatic_field(Method, _constMethod, ConstMethod*) \
|
|
nonstatic_field(Method, _method_data, MethodData*) \
|
|
nonstatic_field(Method, _method_counters, MethodCounters*) \
|
|
@@ -2494,6 +2495,7 @@ typedef HashtableEntry<InstanceKlass*, mtClass> KlassHashtableEntry;
|
|
declare_constant(CompLevel_limited_profile) \
|
|
declare_constant(CompLevel_full_profile) \
|
|
declare_constant(CompLevel_full_optimization) \
|
|
+ declare_constant(CompLevel_aot) \
|
|
\
|
|
/***************/ \
|
|
/* OopMapValue */ \
|
|
diff --git a/src/hotspot/share/utilities/macros.hpp b/src/hotspot/share/utilities/macros.hpp
|
|
index fde84e048..6f8cc606f 100644
|
|
--- a/src/hotspot/share/utilities/macros.hpp
|
|
+++ b/src/hotspot/share/utilities/macros.hpp
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 1997, 2021, 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
|
|
@@ -283,6 +283,14 @@
|
|
#define INCLUDE_JVMCI 1
|
|
#endif
|
|
|
|
+#ifndef INCLUDE_AOT
|
|
+#define INCLUDE_AOT 1
|
|
+#endif
|
|
+
|
|
+#if INCLUDE_AOT && !INCLUDE_JVMCI
|
|
+# error "Must have JVMCI for AOT"
|
|
+#endif
|
|
+
|
|
#if INCLUDE_JVMCI
|
|
#define JVMCI_ONLY(code) code
|
|
#define NOT_JVMCI(code)
|
|
@@ -293,6 +301,16 @@
|
|
#define NOT_JVMCI_RETURN {}
|
|
#endif // INCLUDE_JVMCI
|
|
|
|
+#if INCLUDE_AOT
|
|
+#define AOT_ONLY(code) code
|
|
+#define NOT_AOT(code)
|
|
+#define NOT_AOT_RETURN /* next token must be ; */
|
|
+#else
|
|
+#define AOT_ONLY(code)
|
|
+#define NOT_AOT(code) code
|
|
+#define NOT_AOT_RETURN {}
|
|
+#endif // INCLUDE_AOT
|
|
+
|
|
// COMPILER1 variant
|
|
#ifdef COMPILER1
|
|
#define COMPILER1_PRESENT(code) code
|
|
diff --git a/src/hotspot/share/utilities/vmError.cpp b/src/hotspot/share/utilities/vmError.cpp
|
|
index 2f4a489e3..9f3690cdc 100644
|
|
--- a/src/hotspot/share/utilities/vmError.cpp
|
|
+++ b/src/hotspot/share/utilities/vmError.cpp
|
|
@@ -1,6 +1,6 @@
|
|
/*
|
|
- * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
- * Copyright (c) 2017, 2020 SAP SE. All rights reserved.
|
|
+ * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2017, 2023 SAP SE. All rights reserved.
|
|
* Copyright (c) 2023, Red Hat, Inc. and/or its affiliates.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
@@ -371,7 +371,7 @@ void VMError::print_native_stack(outputStream* st, frame fr, Thread* t, char* bu
|
|
|
|
// see if it's a valid frame
|
|
if (fr.pc()) {
|
|
- st->print_cr("Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)");
|
|
+ st->print_cr("Native frames: (J=compiled Java code, A=aot compiled Java code, j=interpreted, Vv=VM code, C=native code)");
|
|
|
|
int count = 0;
|
|
while (count++ < StackPrintLimit) {
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java
|
|
new file mode 100644
|
|
index 000000000..b39bc4069
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java
|
|
@@ -0,0 +1,959 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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.binformat;
|
|
+
|
|
+import static org.graalvm.compiler.hotspot.meta.HotSpotAOTProfilingPlugin.Options.TieredAOT;
|
|
+
|
|
+import java.io.ByteArrayOutputStream;
|
|
+import java.io.DataOutputStream;
|
|
+import java.io.IOException;
|
|
+import java.util.ArrayList;
|
|
+import java.util.Arrays;
|
|
+import java.util.HashMap;
|
|
+import java.util.List;
|
|
+import java.util.Map;
|
|
+
|
|
+import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
|
|
+import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
|
|
+import org.graalvm.compiler.options.OptionValues;
|
|
+import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
|
|
+
|
|
+import jdk.tools.jaotc.binformat.Symbol.Binding;
|
|
+import jdk.tools.jaotc.binformat.Symbol.Kind;
|
|
+import jdk.tools.jaotc.binformat.elf.JELFRelocObject;
|
|
+import jdk.tools.jaotc.binformat.macho.JMachORelocObject;
|
|
+import jdk.tools.jaotc.binformat.pecoff.JPECoffRelocObject;
|
|
+
|
|
+/**
|
|
+ * A format-agnostic container class that holds various components of a binary.
|
|
+ *
|
|
+ * <p>
|
|
+ * This class holds information necessary to create platform-specific binary containers such as
|
|
+ * ELFContainer for Linux or MachOContainer for Mac OS or PEContainer for MS Windows operating
|
|
+ * systems.
|
|
+ *
|
|
+ * <p>
|
|
+ * Method APIs provided by this class are used to construct and populate platform-independent
|
|
+ * contents of a binary as the first step to create a binary representation of code generated by a
|
|
+ * compiler backend such as Graal.
|
|
+ *
|
|
+ * <p>
|
|
+ * Methods to record and access code section contents, symbols and relocations are provided.
|
|
+ */
|
|
+public final class BinaryContainer implements SymbolTable {
|
|
+ private final OptionValues graalOptions;
|
|
+
|
|
+ private final int codeSegmentSize;
|
|
+
|
|
+ private final int codeEntryAlignment;
|
|
+
|
|
+ private final boolean threadLocalHandshakes;
|
|
+
|
|
+ /**
|
|
+ * Container holding code bits and any other related information.
|
|
+ */
|
|
+ private final CodeContainer codeContainer;
|
|
+
|
|
+ /**
|
|
+ * Container holding global offset data for hotspot linkage.
|
|
+ */
|
|
+ private final ByteContainer extLinkageGOTContainer;
|
|
+
|
|
+ /**
|
|
+ * Patched by HotSpot, contains Klass pointers.
|
|
+ */
|
|
+ private final ByteContainer klassesGotContainer;
|
|
+
|
|
+ /**
|
|
+ * Patched by HotSpot, contains MethodCounters pointers.
|
|
+ */
|
|
+ private final ByteContainer countersGotContainer;
|
|
+
|
|
+ /**
|
|
+ * Patched lazily by hotspot, contains klass/method pointers.
|
|
+ */
|
|
+ private final ByteContainer metadataGotContainer;
|
|
+
|
|
+ /**
|
|
+ * BSS container, contains method state array.
|
|
+ */
|
|
+ private final ByteContainer methodStateContainer;
|
|
+
|
|
+ /**
|
|
+ * Patched by hotspot, contains java object pointers.
|
|
+ */
|
|
+ private final ByteContainer oopGotContainer;
|
|
+
|
|
+ // Containers holding read-only data
|
|
+ private final ReadOnlyDataContainer configContainer;
|
|
+ private final ReadOnlyDataContainer metaspaceNamesContainer;
|
|
+ private final ReadOnlyDataContainer methodsOffsetsContainer;
|
|
+ private final ReadOnlyDataContainer klassesOffsetsContainer;
|
|
+ private final ReadOnlyDataContainer klassesDependenciesContainer;
|
|
+ private final HeaderContainer headerContainer;
|
|
+ private final ReadOnlyDataContainer stubsOffsetsContainer;
|
|
+ private final ReadOnlyDataContainer codeSegmentsContainer;
|
|
+
|
|
+ // This cannot be read only since we need to patch the metadata at runtime..
|
|
+ private final ReadOnlyDataContainer methodMetadataContainer;
|
|
+
|
|
+ /**
|
|
+ * Container containing constant data used by code.
|
|
+ */
|
|
+ private final ReadOnlyDataContainer constantDataContainer;
|
|
+
|
|
+ /**
|
|
+ * Map holding the Strings table.
|
|
+ */
|
|
+ private final Map<String, Integer> offsetStringTable = new HashMap<>();
|
|
+
|
|
+ private final Map<String, Integer> metaspaceNames = new HashMap<>();
|
|
+
|
|
+ // List of relocation table entries - (symbolName, relocationInfo)
|
|
+ private final Map<String, Symbol> symbolTable = new HashMap<>();
|
|
+ private final Map<Symbol, List<Relocation>> relocationTable = new HashMap<>();
|
|
+ private final Map<Symbol, Relocation> uniqueRelocationTable = new HashMap<>();
|
|
+
|
|
+ /**
|
|
+ * Mapping of local VM function names to known global symbols generated in the output binary.
|
|
+ */
|
|
+ private static final HashMap<String, String> functionNamesToAOTSymbols = new HashMap<>();
|
|
+
|
|
+ //@formatter:off
|
|
+ private static final String[][] map = {
|
|
+ {"CompilerToVM::Data::SharedRuntime_deopt_blob_unpack", "_aot_deopt_blob_unpack"},
|
|
+ {"CompilerToVM::Data::SharedRuntime_deopt_blob_uncommon_trap", "_aot_deopt_blob_uncommon_trap"},
|
|
+ {"CompilerToVM::Data::SharedRuntime_deopt_blob_unpack_with_exception_in_tls", "_aot_deopt_blob_unpack_with_exception_in_tls"},
|
|
+ {"CompilerToVM::Data::SharedRuntime_ic_miss_stub", "_aot_ic_miss_stub"},
|
|
+ {"CompilerToVM::Data::SharedRuntime_handle_wrong_method_stub", "_aot_handle_wrong_method_stub"},
|
|
+ {"SharedRuntime::exception_handler_for_return_address", "_aot_exception_handler_for_return_address"},
|
|
+ {"SharedRuntime::register_finalizer", "_aot_register_finalizer"},
|
|
+ {"SharedRuntime::OSR_migration_end", "_aot_OSR_migration_end"},
|
|
+ {"SharedRuntime::enable_stack_reserved_zone", "_aot_enable_stack_reserved_zone"},
|
|
+ {"CompilerRuntime::resolve_dynamic_invoke", "_aot_resolve_dynamic_invoke"},
|
|
+ {"CompilerRuntime::resolve_string_by_symbol", "_aot_resolve_string_by_symbol"},
|
|
+ {"CompilerRuntime::resolve_klass_by_symbol", "_aot_resolve_klass_by_symbol"},
|
|
+ {"CompilerRuntime::resolve_method_by_symbol_and_load_counters", "_aot_resolve_method_by_symbol_and_load_counters"},
|
|
+ {"CompilerRuntime::initialize_klass_by_symbol", "_aot_initialize_klass_by_symbol"},
|
|
+ {"CompilerRuntime::invocation_event", "_aot_invocation_event"},
|
|
+ {"CompilerRuntime::backedge_event", "_aot_backedge_event"},
|
|
+
|
|
+ {"CompilerToVM::Data::dpow", "_aot_shared_runtime_dpow"},
|
|
+ {"CompilerToVM::Data::dexp", "_aot_shared_runtime_dexp"},
|
|
+ {"CompilerToVM::Data::dcos", "_aot_shared_runtime_dcos"},
|
|
+ {"CompilerToVM::Data::dsin", "_aot_shared_runtime_dsin"},
|
|
+ {"CompilerToVM::Data::dtan", "_aot_shared_runtime_dtan"},
|
|
+ {"CompilerToVM::Data::dlog", "_aot_shared_runtime_dlog"},
|
|
+ {"CompilerToVM::Data::dlog10", "_aot_shared_runtime_dlog10"},
|
|
+
|
|
+ {"StubRoutines::_jbyte_arraycopy", "_aot_stub_routines_jbyte_arraycopy"},
|
|
+ {"StubRoutines::_jshort_arraycopy", "_aot_stub_routines_jshort_arraycopy"},
|
|
+ {"StubRoutines::_jint_arraycopy", "_aot_stub_routines_jint_arraycopy"},
|
|
+ {"StubRoutines::_jlong_arraycopy", "_aot_stub_routines_jlong_arraycopy"},
|
|
+ {"StubRoutines::_oop_arraycopy", "_aot_stub_routines_oop_arraycopy"},
|
|
+ {"StubRoutines::_oop_arraycopy_uninit", "_aot_stub_routines_oop_arraycopy_uninit"},
|
|
+
|
|
+ {"StubRoutines::_jbyte_disjoint_arraycopy", "_aot_stub_routines_jbyte_disjoint_arraycopy"},
|
|
+ {"StubRoutines::_jshort_disjoint_arraycopy", "_aot_stub_routines_jshort_disjoint_arraycopy"},
|
|
+ {"StubRoutines::_jint_disjoint_arraycopy", "_aot_stub_routines_jint_disjoint_arraycopy"},
|
|
+ {"StubRoutines::_jlong_disjoint_arraycopy", "_aot_stub_routines_jlong_disjoint_arraycopy"},
|
|
+ {"StubRoutines::_oop_disjoint_arraycopy", "_aot_stub_routines_oop_disjoint_arraycopy"},
|
|
+ {"StubRoutines::_oop_disjoint_arraycopy_uninit", "_aot_stub_routines_oop_disjoint_arraycopy_uninit"},
|
|
+
|
|
+ {"StubRoutines::_arrayof_jbyte_arraycopy", "_aot_stub_routines_arrayof_jbyte_arraycopy"},
|
|
+ {"StubRoutines::_arrayof_jshort_arraycopy", "_aot_stub_routines_arrayof_jshort_arraycopy"},
|
|
+ {"StubRoutines::_arrayof_jint_arraycopy", "_aot_stub_routines_arrayof_jint_arraycopy"},
|
|
+ {"StubRoutines::_arrayof_jlong_arraycopy", "_aot_stub_routines_arrayof_jlong_arraycopy"},
|
|
+ {"StubRoutines::_arrayof_oop_arraycopy", "_aot_stub_routines_arrayof_oop_arraycopy"},
|
|
+ {"StubRoutines::_arrayof_oop_arraycopy_uninit", "_aot_stub_routines_arrayof_oop_arraycopy_uninit"},
|
|
+
|
|
+ {"StubRoutines::_arrayof_jbyte_disjoint_arraycopy", "_aot_stub_routines_arrayof_jbyte_disjoint_arraycopy"},
|
|
+ {"StubRoutines::_arrayof_jshort_disjoint_arraycopy", "_aot_stub_routines_arrayof_jshort_disjoint_arraycopy"},
|
|
+ {"StubRoutines::_arrayof_jint_disjoint_arraycopy", "_aot_stub_routines_arrayof_jint_disjoint_arraycopy"},
|
|
+ {"StubRoutines::_arrayof_jlong_disjoint_arraycopy", "_aot_stub_routines_arrayof_jlong_disjoint_arraycopy"},
|
|
+ {"StubRoutines::_arrayof_oop_disjoint_arraycopy", "_aot_stub_routines_arrayof_oop_disjoint_arraycopy"},
|
|
+ {"StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit", "_aot_stub_routines_arrayof_oop_disjoint_arraycopy_uninit"},
|
|
+
|
|
+ {"StubRoutines::_unsafe_arraycopy", "_aot_stub_routines_unsafe_arraycopy"},
|
|
+
|
|
+ {"StubRoutines::_checkcast_arraycopy", "_aot_stub_routines_checkcast_arraycopy"},
|
|
+
|
|
+ {"StubRoutines::_generic_arraycopy", "_aot_stub_routines_generic_arraycopy"},
|
|
+
|
|
+ {"StubRoutines::_aescrypt_encryptBlock", "_aot_stub_routines_aescrypt_encryptBlock"},
|
|
+ {"StubRoutines::_aescrypt_decryptBlock", "_aot_stub_routines_aescrypt_decryptBlock"},
|
|
+ {"StubRoutines::_cipherBlockChaining_encryptAESCrypt", "_aot_stub_routines_cipherBlockChaining_encryptAESCrypt"},
|
|
+ {"StubRoutines::_cipherBlockChaining_decryptAESCrypt", "_aot_stub_routines_cipherBlockChaining_decryptAESCrypt"},
|
|
+ {"StubRoutines::_electronicCodeBook_encryptAESCrypt", "_aot_stub_routines_electronicCodeBook_encryptAESCrypt"},
|
|
+ {"StubRoutines::_electronicCodeBook_decryptAESCrypt", "_aot_stub_routines_electronicCodeBook_decryptAESCrypt"},
|
|
+ {"StubRoutines::_updateBytesCRC32", "_aot_stub_routines_update_bytes_crc32"},
|
|
+ {"StubRoutines::_crc_table_adr", "_aot_stub_routines_crc_table_adr"},
|
|
+
|
|
+ {"StubRoutines::_sha1_implCompress", "_aot_stub_routines_sha1_implCompress" },
|
|
+ {"StubRoutines::_sha1_implCompressMB", "_aot_stub_routines_sha1_implCompressMB" },
|
|
+ {"StubRoutines::_sha256_implCompress", "_aot_stub_routines_sha256_implCompress" },
|
|
+ {"StubRoutines::_sha256_implCompressMB", "_aot_stub_routines_sha256_implCompressMB" },
|
|
+ {"StubRoutines::_sha512_implCompress", "_aot_stub_routines_sha512_implCompress" },
|
|
+ {"StubRoutines::_sha512_implCompressMB", "_aot_stub_routines_sha512_implCompressMB" },
|
|
+ {"StubRoutines::_multiplyToLen", "_aot_stub_routines_multiplyToLen" },
|
|
+
|
|
+ {"StubRoutines::_counterMode_AESCrypt", "_aot_stub_routines_counterMode_AESCrypt" },
|
|
+ {"StubRoutines::_ghash_processBlocks", "_aot_stub_routines_ghash_processBlocks" },
|
|
+ {"StubRoutines::_base64_encodeBlock", "_aot_stub_routines_base64_encodeBlock" },
|
|
+ {"StubRoutines::_crc32c_table_addr", "_aot_stub_routines_crc32c_table_addr" },
|
|
+ {"StubRoutines::_updateBytesCRC32C", "_aot_stub_routines_updateBytesCRC32C" },
|
|
+ {"StubRoutines::_updateBytesAdler32", "_aot_stub_routines_updateBytesAdler32" },
|
|
+ {"StubRoutines::_squareToLen", "_aot_stub_routines_squareToLen" },
|
|
+ {"StubRoutines::_mulAdd", "_aot_stub_routines_mulAdd" },
|
|
+ {"StubRoutines::_montgomeryMultiply", "_aot_stub_routines_montgomeryMultiply" },
|
|
+ {"StubRoutines::_montgomerySquare", "_aot_stub_routines_montgomerySquare" },
|
|
+ {"StubRoutines::_vectorizedMismatch", "_aot_stub_routines_vectorizedMismatch" },
|
|
+ {"StubRoutines::_bigIntegerRightShiftWorker", "_aot_stub_routines_bigIntegerRightShiftWorker" },
|
|
+ {"StubRoutines::_bigIntegerLeftShiftWorker", "_aot_stub_routines_bigIntegerLeftShiftWorker" },
|
|
+
|
|
+ {"StubRoutines::_throw_delayed_StackOverflowError_entry", "_aot_stub_routines_throw_delayed_StackOverflowError_entry" },
|
|
+
|
|
+
|
|
+ {"os::javaTimeMillis", "_aot_os_javaTimeMillis"},
|
|
+ {"os::javaTimeNanos", "_aot_os_javaTimeNanos"},
|
|
+
|
|
+ {"JVMCIRuntime::monitorenter", "_aot_jvmci_runtime_monitorenter"},
|
|
+ {"JVMCIRuntime::monitorexit", "_aot_jvmci_runtime_monitorexit"},
|
|
+ {"JVMCIRuntime::object_notify", "_aot_object_notify"},
|
|
+ {"JVMCIRuntime::object_notifyAll", "_aot_object_notifyAll"},
|
|
+ {"JVMCIRuntime::log_object", "_aot_jvmci_runtime_log_object"},
|
|
+ {"JVMCIRuntime::log_printf", "_aot_jvmci_runtime_log_printf"},
|
|
+ {"JVMCIRuntime::vm_message", "_aot_jvmci_runtime_vm_message"},
|
|
+ {"JVMCIRuntime::new_instance", "_aot_jvmci_runtime_new_instance"},
|
|
+ {"JVMCIRuntime::new_array", "_aot_jvmci_runtime_new_array"},
|
|
+ {"JVMCIRuntime::new_multi_array", "_aot_jvmci_runtime_new_multi_array"},
|
|
+ {"JVMCIRuntime::dynamic_new_instance", "_aot_jvmci_runtime_dynamic_new_instance"},
|
|
+ {"JVMCIRuntime::dynamic_new_array", "_aot_jvmci_runtime_dynamic_new_array"},
|
|
+ {"JVMCIRuntime::new_instance_or_null", "_aot_jvmci_runtime_new_instance_or_null"},
|
|
+ {"JVMCIRuntime::new_array_or_null", "_aot_jvmci_runtime_new_array_or_null"},
|
|
+ {"JVMCIRuntime::new_multi_array_or_null", "_aot_jvmci_runtime_new_multi_array_or_null"},
|
|
+ {"JVMCIRuntime::dynamic_new_instance_or_null", "_aot_jvmci_runtime_dynamic_new_instance_or_null"},
|
|
+ {"JVMCIRuntime::dynamic_new_array_or_null", "_aot_jvmci_runtime_dynamic_new_array_or_null"},
|
|
+ {"JVMCIRuntime::log_primitive", "_aot_jvmci_runtime_log_primitive"},
|
|
+ {"JVMCIRuntime::validate_object", "_aot_jvmci_runtime_validate_object"},
|
|
+ {"JVMCIRuntime::write_barrier_pre", "_aot_jvmci_runtime_write_barrier_pre"},
|
|
+ {"JVMCIRuntime::identity_hash_code", "_aot_jvmci_runtime_identity_hash_code"},
|
|
+ {"JVMCIRuntime::write_barrier_post", "_aot_jvmci_runtime_write_barrier_post"},
|
|
+ {"JVMCIRuntime::thread_is_interrupted", "_aot_jvmci_runtime_thread_is_interrupted"},
|
|
+ {"JVMCIRuntime::exception_handler_for_pc", "_aot_jvmci_runtime_exception_handler_for_pc"},
|
|
+ {"JVMCIRuntime::test_deoptimize_call_int", "_aot_jvmci_runtime_test_deoptimize_call_int"},
|
|
+
|
|
+ {"JVMCIRuntime::throw_and_post_jvmti_exception", "_aot_jvmci_runtime_throw_and_post_jvmti_exception"},
|
|
+ {"JVMCIRuntime::throw_klass_external_name_exception", "_aot_jvmci_runtime_throw_klass_external_name_exception"},
|
|
+ {"JVMCIRuntime::throw_class_cast_exception", "_aot_jvmci_runtime_throw_class_cast_exception"},
|
|
+
|
|
+ {"JVMCIRuntime::vm_error", "_aot_jvmci_runtime_vm_error"}
|
|
+ };
|
|
+ //@formatter:on
|
|
+
|
|
+ static {
|
|
+ for (String[] entry : map) {
|
|
+ functionNamesToAOTSymbols.put(entry[0], entry[1]);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Allocates a {@code BinaryContainer} object whose content will be generated in a file with the
|
|
+ * prefix {@code prefix}. It also initializes internal code container, symbol table and
|
|
+ * relocation tables.
|
|
+ *
|
|
+ * @param graalOptions
|
|
+ */
|
|
+ public BinaryContainer(OptionValues graalOptions, GraalHotSpotVMConfig graalHotSpotVMConfig, GraphBuilderConfiguration graphBuilderConfig, int gc, String jvmVersion) {
|
|
+ this.graalOptions = graalOptions;
|
|
+
|
|
+ this.codeSegmentSize = graalHotSpotVMConfig.codeSegmentSize;
|
|
+ if (codeSegmentSize < 1 || codeSegmentSize > 1024) {
|
|
+ throw new InternalError("codeSegmentSize is not in range [1, 1024] bytes: (" + codeSegmentSize + "), update JPECoffRelocObject");
|
|
+ }
|
|
+ if ((codeSegmentSize & (codeSegmentSize - 1)) != 0) {
|
|
+ throw new InternalError("codeSegmentSize is not power of 2: (" + codeSegmentSize + "), update JPECoffRelocObject");
|
|
+ }
|
|
+
|
|
+ this.codeEntryAlignment = graalHotSpotVMConfig.codeEntryAlignment;
|
|
+
|
|
+ this.threadLocalHandshakes = graalHotSpotVMConfig.useThreadLocalPolling;
|
|
+
|
|
+ // Section unique name is limited to 8 characters due to limitation on Windows.
|
|
+ // Name could be longer but only first 8 characters are stored on Windows.
|
|
+
|
|
+ // read only, code
|
|
+ codeContainer = new CodeContainer(".text", this);
|
|
+
|
|
+ // read only, info
|
|
+ headerContainer = new HeaderContainer(jvmVersion, new ReadOnlyDataContainer(".header", this));
|
|
+ configContainer = new ReadOnlyDataContainer(".config", this);
|
|
+ metaspaceNamesContainer = new ReadOnlyDataContainer(".meta.names", this);
|
|
+ methodsOffsetsContainer = new ReadOnlyDataContainer(".meth.offsets", this);
|
|
+ klassesOffsetsContainer = new ReadOnlyDataContainer(".kls.offsets", this);
|
|
+ klassesDependenciesContainer = new ReadOnlyDataContainer(".kls.dependencies", this);
|
|
+
|
|
+ stubsOffsetsContainer = new ReadOnlyDataContainer(".stubs.offsets", this);
|
|
+ codeSegmentsContainer = new ReadOnlyDataContainer(".code.segments", this);
|
|
+ constantDataContainer = new ReadOnlyDataContainer(".meth.constdata", this);
|
|
+ methodMetadataContainer = new ReadOnlyDataContainer(".meth.metadata", this);
|
|
+
|
|
+ // writable sections
|
|
+ oopGotContainer = new ByteContainer(".oop.got", this);
|
|
+ klassesGotContainer = new ByteContainer(".kls.got", this);
|
|
+ countersGotContainer = new ByteContainer(".cnt.got", this);
|
|
+ metadataGotContainer = new ByteContainer(".meta.got", this);
|
|
+ methodStateContainer = new ByteContainer(".meth.state", this);
|
|
+ extLinkageGOTContainer = new ByteContainer(".got.linkage", this);
|
|
+
|
|
+ addGlobalSymbols();
|
|
+
|
|
+ recordConfiguration(graalHotSpotVMConfig, graphBuilderConfig, gc);
|
|
+ }
|
|
+
|
|
+ private void recordConfiguration(GraalHotSpotVMConfig graalHotSpotVMConfig, GraphBuilderConfiguration graphBuilderConfig, int gc) {
|
|
+ // @Checkstyle: stop
|
|
+ // @formatter:off
|
|
+ ArrayList<Boolean> booleanFlagsList = new ArrayList<>();
|
|
+
|
|
+ booleanFlagsList.addAll(Arrays.asList(graalHotSpotVMConfig.cAssertions, // Debug VM
|
|
+ graalHotSpotVMConfig.useCompressedOops,
|
|
+ graalHotSpotVMConfig.useCompressedClassPointers));
|
|
+ if (JavaVersionUtil.JAVA_SPEC < 15) {
|
|
+ // See JDK-8236224. FieldsAllocationStyle and CompactFields flags were removed in JDK15.
|
|
+ booleanFlagsList.add(graalHotSpotVMConfig.compactFields);
|
|
+ }
|
|
+ booleanFlagsList.addAll(Arrays.asList(graalHotSpotVMConfig.useTLAB,
|
|
+ graalHotSpotVMConfig.useBiasedLocking,
|
|
+ TieredAOT.getValue(graalOptions),
|
|
+ graalHotSpotVMConfig.enableContended,
|
|
+ graalHotSpotVMConfig.restrictContended,
|
|
+ graphBuilderConfig.omitAssertions()));
|
|
+ if (JavaVersionUtil.JAVA_SPEC < 14) {
|
|
+ // See JDK-8220049. Thread local handshakes are on by default since JDK14, the command line option has been removed.
|
|
+ booleanFlagsList.add(graalHotSpotVMConfig.useThreadLocalPolling);
|
|
+ }
|
|
+
|
|
+ ArrayList<Integer> intFlagsList = new ArrayList<>();
|
|
+ intFlagsList.addAll(Arrays.asList(graalHotSpotVMConfig.getOopEncoding().getShift(),
|
|
+ graalHotSpotVMConfig.getKlassEncoding().getShift(),
|
|
+ graalHotSpotVMConfig.contendedPaddingWidth));
|
|
+ if (JavaVersionUtil.JAVA_SPEC < 15) {
|
|
+ // See JDK-8236224. FieldsAllocationStyle and CompactFields flags were removed in JDK15.
|
|
+ intFlagsList.add(graalHotSpotVMConfig.fieldsAllocationStyle);
|
|
+ }
|
|
+ intFlagsList.addAll(Arrays.asList(1 << graalHotSpotVMConfig.logMinObjAlignment(),
|
|
+ graalHotSpotVMConfig.codeSegmentSize,
|
|
+ gc));
|
|
+
|
|
+ // @formatter:on
|
|
+ // @Checkstyle: resume
|
|
+
|
|
+ byte[] booleanFlagsAsBytes = booleanListToByteArray(booleanFlagsList);
|
|
+ int[] intFlags = intFlagsList.stream().mapToInt(i -> i).toArray();
|
|
+ int size0 = configContainer.getByteStreamSize();
|
|
+
|
|
+ // @formatter:off
|
|
+ int computedSize = booleanFlagsAsBytes.length * Byte.BYTES + // size of boolean flags
|
|
+ intFlags.length * Integer.BYTES + // size of int flags
|
|
+ Integer.BYTES; // size of the "computedSize"
|
|
+
|
|
+ configContainer.appendInt(computedSize).
|
|
+ appendInts(intFlags).
|
|
+ appendBytes(booleanFlagsAsBytes);
|
|
+ // @formatter:on
|
|
+
|
|
+ int size = configContainer.getByteStreamSize() - size0;
|
|
+ assert size == computedSize;
|
|
+ }
|
|
+
|
|
+ private static byte[] booleanListToByteArray(ArrayList<Boolean> list) {
|
|
+ byte[] byteArray = new byte[list.size()];
|
|
+ for (int i = 0; i < list.size(); ++i) {
|
|
+ byteArray[i] = boolToByte(list.get(i));
|
|
+ }
|
|
+ return byteArray;
|
|
+ }
|
|
+
|
|
+ private static byte boolToByte(boolean flag) {
|
|
+ return (byte) (flag ? 1 : 0);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Free some memory.
|
|
+ */
|
|
+ public void freeMemory() {
|
|
+ offsetStringTable.clear();
|
|
+ metaspaceNames.clear();
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Global symbol names in generated DSO corresponding to VM's symbols. VM needs to look up this
|
|
+ * symbol in DSO and link it with VM's corresponding symbol: store VM's symbol address or value
|
|
+ * in the named GOT cell.
|
|
+ */
|
|
+
|
|
+ public static String getCardTableAddressSymbolName() {
|
|
+ return "_aot_card_table_address";
|
|
+ }
|
|
+
|
|
+ public static String getHeapTopAddressSymbolName() {
|
|
+ return "_aot_heap_top_address";
|
|
+ }
|
|
+
|
|
+ public static String getHeapEndAddressSymbolName() {
|
|
+ return "_aot_heap_end_address";
|
|
+ }
|
|
+
|
|
+ public static String getCrcTableAddressSymbolName() {
|
|
+ return "_aot_stub_routines_crc_table_adr";
|
|
+ }
|
|
+
|
|
+ public static String getPollingPageSymbolName() {
|
|
+ return "_aot_polling_page";
|
|
+ }
|
|
+
|
|
+ public static String getResolveStaticEntrySymbolName() {
|
|
+ return "_resolve_static_entry";
|
|
+ }
|
|
+
|
|
+ public static String getResolveVirtualEntrySymbolName() {
|
|
+ return "_resolve_virtual_entry";
|
|
+ }
|
|
+
|
|
+ public static String getResolveOptVirtualEntrySymbolName() {
|
|
+ return "_resolve_opt_virtual_entry";
|
|
+ }
|
|
+
|
|
+ public static String getNarrowKlassBaseAddressSymbolName() {
|
|
+ return "_aot_narrow_klass_base_address";
|
|
+ }
|
|
+
|
|
+ public static String getNarrowOopBaseAddressSymbolName() {
|
|
+ return "_aot_narrow_oop_base_address";
|
|
+ }
|
|
+
|
|
+ public static String getLogOfHeapRegionGrainBytesSymbolName() {
|
|
+ return "_aot_log_of_heap_region_grain_bytes";
|
|
+ }
|
|
+
|
|
+ public static String getInlineContiguousAllocationSupportedSymbolName() {
|
|
+ return "_aot_inline_contiguous_allocation_supported";
|
|
+ }
|
|
+
|
|
+ public static String getVerifyOopsSymbolName() {
|
|
+ return "_aot_verify_oops";
|
|
+ }
|
|
+
|
|
+ public static String getVerifyOopCountAddressSymbolName() {
|
|
+ return "_aot_verify_oop_count_address";
|
|
+ }
|
|
+
|
|
+ public static String getVerifyOopBitsSymbolName() {
|
|
+ return "_aot_verify_oop_bits";
|
|
+ }
|
|
+
|
|
+ public static String getVerifyOopMaskSymbolName() {
|
|
+ return "_aot_verify_oop_mask";
|
|
+ }
|
|
+
|
|
+ public int getCodeSegmentSize() {
|
|
+ return codeSegmentSize;
|
|
+ }
|
|
+
|
|
+ public int getCodeEntryAlignment() {
|
|
+ return codeEntryAlignment;
|
|
+ }
|
|
+
|
|
+ public boolean getThreadLocalHandshakes() {
|
|
+ return threadLocalHandshakes;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Gets the global AOT symbol associated with the function name.
|
|
+ *
|
|
+ * @param functionName function name
|
|
+ * @return AOT symbol for the given function name, or null if there is no mapping.
|
|
+ */
|
|
+ public static String getAOTSymbolForVMFunctionName(String functionName) {
|
|
+ return functionNamesToAOTSymbols.get(functionName);
|
|
+ }
|
|
+
|
|
+ private void addGlobalSymbols() {
|
|
+ // Create global symbols for all containers.
|
|
+ createContainerSymbol(codeContainer);
|
|
+ createContainerSymbol(configContainer);
|
|
+ createContainerSymbol(methodsOffsetsContainer);
|
|
+ createContainerSymbol(klassesOffsetsContainer);
|
|
+ createContainerSymbol(klassesDependenciesContainer);
|
|
+ createContainerSymbol(klassesGotContainer);
|
|
+ createContainerSymbol(countersGotContainer);
|
|
+ createContainerSymbol(metadataGotContainer);
|
|
+ createContainerSymbol(methodStateContainer);
|
|
+ createContainerSymbol(oopGotContainer);
|
|
+ createContainerSymbol(metaspaceNamesContainer);
|
|
+ createContainerSymbol(methodMetadataContainer);
|
|
+ createContainerSymbol(stubsOffsetsContainer);
|
|
+ createContainerSymbol(headerContainer.getContainer());
|
|
+ createContainerSymbol(codeSegmentsContainer);
|
|
+
|
|
+ createGotSymbol(getResolveStaticEntrySymbolName());
|
|
+ createGotSymbol(getResolveVirtualEntrySymbolName());
|
|
+ createGotSymbol(getResolveOptVirtualEntrySymbolName());
|
|
+ createGotSymbol(getCardTableAddressSymbolName());
|
|
+ createGotSymbol(getHeapTopAddressSymbolName());
|
|
+ createGotSymbol(getHeapEndAddressSymbolName());
|
|
+ createGotSymbol(getNarrowKlassBaseAddressSymbolName());
|
|
+ createGotSymbol(getNarrowOopBaseAddressSymbolName());
|
|
+ createGotSymbol(getPollingPageSymbolName());
|
|
+ createGotSymbol(getLogOfHeapRegionGrainBytesSymbolName());
|
|
+ createGotSymbol(getInlineContiguousAllocationSupportedSymbolName());
|
|
+ createGotSymbol(getVerifyOopsSymbolName());
|
|
+ createGotSymbol(getVerifyOopCountAddressSymbolName());
|
|
+ createGotSymbol(getVerifyOopBitsSymbolName());
|
|
+ createGotSymbol(getVerifyOopMaskSymbolName());
|
|
+
|
|
+ for (HashMap.Entry<String, String> entry : functionNamesToAOTSymbols.entrySet()) {
|
|
+ createGotSymbol(entry.getValue());
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Creates a global symbol of the form {@code "A" + container name}. Note, linker on Windows
|
|
+ * does not allow names which start with '.'
|
|
+ *
|
|
+ * @param container container to create a symbol for
|
|
+ */
|
|
+ private static void createContainerSymbol(ByteContainer container) {
|
|
+ container.createSymbol(0, Kind.OBJECT, Binding.GLOBAL, 0, "A" + container.getContainerName());
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Creates a global GOT symbol of the form {@code "got." + name}.
|
|
+ *
|
|
+ * @param name name for the GOT symbol
|
|
+ */
|
|
+ private void createGotSymbol(String name) {
|
|
+ String s = "got." + name;
|
|
+ Symbol gotSymbol = extLinkageGOTContainer.createGotSymbol(s);
|
|
+ extLinkageGOTContainer.createSymbol(gotSymbol.getOffset(), Kind.OBJECT, Binding.GLOBAL, 8, name);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Create a platform-specific binary file representing the content of the
|
|
+ * {@code BinaryContainer} object.
|
|
+ *
|
|
+ * This method is called after creating and performing any necessary changes to the contents of
|
|
+ * code stream, symbol tables and relocation tables is completely finalized
|
|
+ *
|
|
+ * @param outputFileName name of output file
|
|
+ *
|
|
+ * @throws IOException in case of file creation failure
|
|
+ */
|
|
+ public void createBinary(String outputFileName) throws IOException {
|
|
+ String osName = System.getProperty("os.name");
|
|
+ switch (osName) {
|
|
+ case "Linux":
|
|
+ JELFRelocObject elfobj = JELFRelocObject.newInstance(this, outputFileName);
|
|
+ elfobj.createELFRelocObject(relocationTable, symbolTable.values());
|
|
+ break;
|
|
+ case "Mac OS X":
|
|
+ JMachORelocObject machobj = new JMachORelocObject(this, outputFileName);
|
|
+ machobj.createMachORelocObject(relocationTable, symbolTable.values());
|
|
+ break;
|
|
+ default:
|
|
+ if (osName.startsWith("Windows")) {
|
|
+ JPECoffRelocObject pecoffobj = new JPECoffRelocObject(this, outputFileName);
|
|
+ pecoffobj.createPECoffRelocObject(relocationTable, symbolTable.values());
|
|
+ break;
|
|
+ } else {
|
|
+ throw new InternalError("Unsupported platform: " + osName);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Add symbol to the symbol table. If the existing symbol is undefined and the specified symbol
|
|
+ * is not undefined, replace the existing symbol information with that specified.
|
|
+ *
|
|
+ * @param symInfo symbol information to be added
|
|
+ */
|
|
+ @Override
|
|
+ public void addSymbol(Symbol symInfo) {
|
|
+ if (symInfo.getName().startsWith("got.") && !(symInfo instanceof GotSymbol)) {
|
|
+ throw new InternalError("adding got. without being GotSymbol");
|
|
+ }
|
|
+ if (symbolTable.containsKey(symInfo.getName())) {
|
|
+ throw new InternalError("Symbol: " + symInfo.getName() + " already exists in SymbolTable");
|
|
+ } else {
|
|
+ // System.out.println("# Symbol [" + name + "] [" + symInfo.getValue() + "] [" +
|
|
+ // symInfo.getSection().getContainerName() + "] [" + symInfo.getSize() + "]");
|
|
+ symbolTable.put(symInfo.getName(), symInfo);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public boolean addStringOffset(String name, Integer offset) {
|
|
+ offsetStringTable.put(name, offset);
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Add relocation entry for {@code symName}. Multiple relocation entries for a given symbol may
|
|
+ * exist.
|
|
+ *
|
|
+ * @param info relocation information to be added
|
|
+ */
|
|
+ public void addRelocation(Relocation info) {
|
|
+ // System.out.println("# Relocation [" + info.getSymbol() + "] [" + info.getOffset() + "] ["
|
|
+ // +
|
|
+ // info.getSection().getContainerName() + "] [" + info.getSymbol().getName() + "] [" +
|
|
+ // info.getSymbol().getOffset() + " @ " + info.getSymbol().getSection().getContainerName() +
|
|
+ // "]");
|
|
+ if (relocationTable.containsKey(info.getSymbol())) {
|
|
+ relocationTable.get(info.getSymbol()).add(info);
|
|
+ } else if (uniqueRelocationTable.containsKey(info.getSymbol())) {
|
|
+ // promote
|
|
+ ArrayList<Relocation> list = new ArrayList<>(2);
|
|
+ list.add(uniqueRelocationTable.get(info.getSymbol()));
|
|
+ list.add(info);
|
|
+ relocationTable.put(info.getSymbol(), list);
|
|
+ uniqueRelocationTable.remove(info.getSymbol());
|
|
+ } else {
|
|
+ uniqueRelocationTable.put(info.getSymbol(), info);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Get symbol with name {@code symName}.
|
|
+ *
|
|
+ * @param symName name of symbol for which symbol table information is being queried
|
|
+ * @return success or failure of insertion operation
|
|
+ */
|
|
+ @Override
|
|
+ public Symbol getSymbol(String symName) {
|
|
+ return symbolTable.get(symName);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public Symbol createSymbol(int offset, Kind kind, Binding binding, int size, String name) {
|
|
+ if (kind != Kind.NATIVE_FUNCTION) {
|
|
+ throw new UnsupportedOperationException("Must be external functions: " + name);
|
|
+ }
|
|
+ Symbol symbol = new Symbol(offset, kind, binding, null, size, name);
|
|
+ addSymbol(symbol);
|
|
+ return symbol;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Get offset in got section with name {@code symName}.
|
|
+ *
|
|
+ * @param name for which String table information is being queried
|
|
+ * @return success or failure of insertion operation
|
|
+ */
|
|
+ public Integer getStringOffset(String name) {
|
|
+ return offsetStringTable.get(name);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Insert {@code targetCode} to code stream with {@code size} at {@code offset}.
|
|
+ *
|
|
+ * @param targetCode byte array of native code
|
|
+ * @param offset offset at which {@code targetCode} is to be inserted
|
|
+ * @param size size of {@code targetCode}
|
|
+ */
|
|
+ private static void appendBytes(ByteContainer byteContainer, byte[] targetCode, int offset, int size) {
|
|
+ byteContainer.appendBytes(targetCode, offset, size);
|
|
+ }
|
|
+
|
|
+ public void appendCodeBytes(byte[] targetCode, int offset, int size) {
|
|
+ appendBytes(codeContainer, targetCode, offset, size);
|
|
+ }
|
|
+
|
|
+ public void appendIntToCode(int value) {
|
|
+ codeContainer.appendInt(value);
|
|
+ }
|
|
+
|
|
+ public int appendExtLinkageGotBytes(byte[] bytes, int offset, int size) {
|
|
+ int startOffset = extLinkageGOTContainer.getByteStreamSize();
|
|
+ appendBytes(extLinkageGOTContainer, bytes, offset, size);
|
|
+ return startOffset;
|
|
+ }
|
|
+
|
|
+ public void addMetadataGotEntry(int offset) {
|
|
+ metadataGotContainer.appendLong(offset);
|
|
+ }
|
|
+
|
|
+ public int addMetaspaceName(String name) {
|
|
+ Integer value = metaspaceNames.get(name);
|
|
+ if (value != null) {
|
|
+ return value.intValue();
|
|
+ }
|
|
+ // Get the current length of the stubsNameContainer
|
|
+ // align on 8-byte boundary
|
|
+ int nameOffset = alignUp(metaspaceNamesContainer, 8);
|
|
+
|
|
+ try {
|
|
+ // Add the name of the symbol to the .stubs.names section
|
|
+ // Modify them to sequence of utf8 strings with length:
|
|
+ // "<u2_size>Ljava/lang/ThreadGroup;<u2_size>addUnstarted<u2_size>()V"
|
|
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
|
|
+ DataOutputStream out = new DataOutputStream(bout);
|
|
+ int len = name.length();
|
|
+ if (name.startsWith("Stub")) { // Stub
|
|
+ out.writeUTF(name);
|
|
+ } else { // Method or Klass
|
|
+ int parenthesesIndex = name.lastIndexOf('(', len - 1);
|
|
+ if (parenthesesIndex > 0) { // Method name
|
|
+ int dotIndex = name.lastIndexOf('.', parenthesesIndex - 1);
|
|
+ assert dotIndex > 0 : "method's full name should have '.' : " + name;
|
|
+ String klassName = name.substring(0, dotIndex);
|
|
+ out.writeUTF(klassName);
|
|
+ String methodName = name.substring(dotIndex + 1, parenthesesIndex);
|
|
+ out.writeUTF(methodName);
|
|
+ String signature = name.substring(parenthesesIndex, len);
|
|
+ out.writeUTF(signature);
|
|
+ } else {
|
|
+ out.writeUTF(name); // Klass
|
|
+ }
|
|
+ }
|
|
+ out.writeShort(0); // Terminate by 0.
|
|
+ byte[] b = bout.toByteArray();
|
|
+ metaspaceNamesContainer.appendBytes(b, 0, b.length);
|
|
+
|
|
+ metaspaceNames.put(name, nameOffset);
|
|
+ return nameOffset;
|
|
+ } catch (IOException e) {
|
|
+ throw new InternalError("Failed to append bytes to stubs sections", e);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Add oop symbol by as follows. Extend the oop.got section with another slot for the VM to
|
|
+ * patch.
|
|
+ *
|
|
+ * @param oopName name of the oop symbol
|
|
+ */
|
|
+ public Integer addOopSymbol(String oopName) {
|
|
+ Integer oopGotOffset = getStringOffset(oopName);
|
|
+ if (oopGotOffset != null) {
|
|
+ return oopGotOffset;
|
|
+ }
|
|
+ return newOopSymbol(oopName);
|
|
+ }
|
|
+
|
|
+ private Integer newOopSymbol(String oopName) {
|
|
+ // Reference to String resolution (ldc).
|
|
+ int offset = oopGotContainer.getByteStreamSize();
|
|
+ String gotName = "got.ldc." + offset;
|
|
+ Symbol relocationSymbol = oopGotContainer.createGotSymbol(gotName);
|
|
+
|
|
+ if (offset != relocationSymbol.getOffset()) {
|
|
+ throw new InternalError("offset must equal! (" + offset + " vs " + relocationSymbol.getOffset());
|
|
+ }
|
|
+
|
|
+ addStringOffset(oopName, relocationSymbol.getOffset());
|
|
+ return relocationSymbol.getOffset();
|
|
+ }
|
|
+
|
|
+ public int addCountersSymbol(String metaspaceName) {
|
|
+ String gotName = "got." + metaspaceName;
|
|
+ Symbol relocationSymbol = getGotSymbol(gotName);
|
|
+ int metaspaceOffset = -1;
|
|
+ if (relocationSymbol == null) {
|
|
+ // Add slots when asked in the .metaspace.got section:
|
|
+ countersGotContainer.createGotSymbol(gotName);
|
|
+ }
|
|
+ return metaspaceOffset;
|
|
+ }
|
|
+
|
|
+ public Symbol getGotSymbol(String name) {
|
|
+ assert name.startsWith("got.");
|
|
+ return symbolTable.get(name);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Add klass symbol by as follows. - Adding the symbol name to the metaspace.names section - Add
|
|
+ * the offset of the name in metaspace.names to metaspace.offsets - Extend the klasses.got
|
|
+ * section with another slot for the VM to patch
|
|
+ *
|
|
+ * @param klassName name of the metaspace symbol
|
|
+ * @return the got offset in the klasses.got of the metaspace symbol
|
|
+ */
|
|
+ public int addTwoSlotKlassSymbol(String klassName) {
|
|
+ String gotName = "got." + klassName;
|
|
+ Symbol previous = getGotSymbol(gotName);
|
|
+ assert previous == null : "should be called only once for: " + klassName;
|
|
+ // Add slots when asked in the .metaspace.got section:
|
|
+ // First slot
|
|
+ String gotInitName = "got.init." + klassName;
|
|
+ GotSymbol slot1Symbol = klassesGotContainer.createGotSymbol(gotInitName);
|
|
+ GotSymbol slot2Symbol = klassesGotContainer.createGotSymbol(gotName);
|
|
+
|
|
+ slot1Symbol.getIndex(); // check alignment and ignore result
|
|
+ // Get the index (offset/8) to the got in the .metaspace.got section
|
|
+ return slot2Symbol.getIndex();
|
|
+ }
|
|
+
|
|
+ public static int addMethodsCount(int count, ReadOnlyDataContainer container) {
|
|
+ return appendInt(count, container);
|
|
+ }
|
|
+
|
|
+ private static int appendInt(int count, ReadOnlyDataContainer container) {
|
|
+ int offset = container.getByteStreamSize();
|
|
+ container.appendInt(count);
|
|
+ return offset;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Add constant data as follows. - Adding the data to the meth.constdata section
|
|
+ *
|
|
+ * @param data
|
|
+ * @param alignment
|
|
+ * @return the offset in the meth.constdata of the data
|
|
+ */
|
|
+ public int addConstantData(byte[] data, int alignment) {
|
|
+ // Get the current length of the metaspaceNameContainer
|
|
+ int constantDataOffset = alignUp(constantDataContainer, alignment);
|
|
+ constantDataContainer.appendBytes(data, 0, data.length);
|
|
+ alignUp(constantDataContainer, alignment); // Post alignment
|
|
+ return constantDataOffset;
|
|
+ }
|
|
+
|
|
+ public static int alignUp(ByteContainer container, int alignment) {
|
|
+ if (Integer.bitCount(alignment) != 1) {
|
|
+ throw new IllegalArgumentException("Must be a power of 2");
|
|
+ }
|
|
+ int offset = container.getByteStreamSize();
|
|
+ int aligned = (offset + (alignment - 1)) & -alignment;
|
|
+ if (aligned < offset || (aligned & (alignment - 1)) != 0) {
|
|
+ throw new RuntimeException("Error aligning: " + offset + " -> " + aligned);
|
|
+ }
|
|
+ if (aligned != offset) {
|
|
+ int nullArraySz = aligned - offset;
|
|
+ byte[] nullArray = new byte[nullArraySz];
|
|
+ container.appendBytes(nullArray, 0, nullArraySz);
|
|
+ offset = aligned;
|
|
+ }
|
|
+ return offset;
|
|
+ }
|
|
+
|
|
+ public void addCodeSegments(int start, int end) {
|
|
+ assert (start % codeSegmentSize) == 0 : "not aligned code";
|
|
+ int currentOffset = codeSegmentsContainer.getByteStreamSize();
|
|
+ int offset = start / codeSegmentSize;
|
|
+ int emptySize = offset - currentOffset;
|
|
+ // add empty segments if needed
|
|
+ if (emptySize > 0) {
|
|
+ byte[] emptyArray = new byte[emptySize];
|
|
+ for (int i = 0; i < emptySize; i++) {
|
|
+ emptyArray[i] = (byte) 0xff;
|
|
+ }
|
|
+ appendBytes(codeSegmentsContainer, emptyArray, 0, emptySize);
|
|
+ }
|
|
+ int alignedEnd = (end + (codeSegmentSize - 1)) & -codeSegmentSize;
|
|
+ int segmentsCount = (alignedEnd / codeSegmentSize) - offset;
|
|
+ byte[] segments = new byte[segmentsCount];
|
|
+ int idx = 0;
|
|
+ for (int i = 0; i < segmentsCount; i++) {
|
|
+ segments[i] = (byte) idx;
|
|
+ idx = (idx == 0xfe) ? 1 : (idx + 1);
|
|
+ }
|
|
+ appendBytes(codeSegmentsContainer, segments, 0, segmentsCount);
|
|
+ }
|
|
+
|
|
+ public ByteContainer getExtLinkageGOTContainer() {
|
|
+ return extLinkageGOTContainer;
|
|
+ }
|
|
+
|
|
+ public ReadOnlyDataContainer getMethodMetadataContainer() {
|
|
+ return methodMetadataContainer;
|
|
+ }
|
|
+
|
|
+ public ReadOnlyDataContainer getMetaspaceNamesContainer() {
|
|
+ return metaspaceNamesContainer;
|
|
+ }
|
|
+
|
|
+ public ReadOnlyDataContainer getMethodsOffsetsContainer() {
|
|
+ return methodsOffsetsContainer;
|
|
+ }
|
|
+
|
|
+ public ReadOnlyDataContainer getKlassesOffsetsContainer() {
|
|
+ return klassesOffsetsContainer;
|
|
+ }
|
|
+
|
|
+ public ReadOnlyDataContainer getKlassesDependenciesContainer() {
|
|
+ return klassesDependenciesContainer;
|
|
+ }
|
|
+
|
|
+ public ReadOnlyDataContainer getStubsOffsetsContainer() {
|
|
+ return stubsOffsetsContainer;
|
|
+ }
|
|
+
|
|
+ public ReadOnlyDataContainer getCodeSegmentsContainer() {
|
|
+ return codeSegmentsContainer;
|
|
+ }
|
|
+
|
|
+ public ReadOnlyDataContainer getConstantDataContainer() {
|
|
+ return constantDataContainer;
|
|
+ }
|
|
+
|
|
+ public ByteContainer getKlassesGotContainer() {
|
|
+ return klassesGotContainer;
|
|
+ }
|
|
+
|
|
+ public ByteContainer getCountersGotContainer() {
|
|
+ return countersGotContainer;
|
|
+ }
|
|
+
|
|
+ public ByteContainer getMetadataGotContainer() {
|
|
+ return metadataGotContainer;
|
|
+ }
|
|
+
|
|
+ public ByteContainer getMethodStateContainer() {
|
|
+ return methodStateContainer;
|
|
+ }
|
|
+
|
|
+ public ByteContainer getOopGotContainer() {
|
|
+ return oopGotContainer;
|
|
+ }
|
|
+
|
|
+ public CodeContainer getCodeContainer() {
|
|
+ return codeContainer;
|
|
+ }
|
|
+
|
|
+ public ReadOnlyDataContainer getConfigContainer() {
|
|
+ return configContainer;
|
|
+ }
|
|
+
|
|
+ public Map<Symbol, Relocation> getUniqueRelocationTable() {
|
|
+ return uniqueRelocationTable;
|
|
+ }
|
|
+
|
|
+ public HeaderContainer getHeaderContainer() {
|
|
+ return headerContainer;
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/ByteContainer.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/ByteContainer.java
|
|
new file mode 100644
|
|
index 000000000..e063759c3
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/ByteContainer.java
|
|
@@ -0,0 +1,261 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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.binformat;
|
|
+
|
|
+import jdk.tools.jaotc.binformat.Symbol.Binding;
|
|
+import jdk.tools.jaotc.binformat.Symbol.Kind;
|
|
+
|
|
+import java.io.ByteArrayOutputStream;
|
|
+import java.nio.ByteBuffer;
|
|
+import java.nio.ByteOrder;
|
|
+import java.util.Arrays;
|
|
+
|
|
+/**
|
|
+ * Base class that represents content of all sections with byte-level granularity. The ByteContainer
|
|
+ * class is backed by a ByteArrayOutputStream. This class supports writing all desired byte content
|
|
+ * to the container using the method {@code appendBytes} and accessing the byte array using the
|
|
+ * method {@code getByteArray}.
|
|
+ *
|
|
+ * The method {@code putIntAt} updates the content of {@code contentBytes}. Changes are not
|
|
+ * reflected in {@code contentStream}.
|
|
+ */
|
|
+public class ByteContainer implements Container {
|
|
+ /**
|
|
+ * {@code ByteBuffer} representation of {@code BinaryContainer}.
|
|
+ */
|
|
+ private ByteBuffer contentBytes;
|
|
+
|
|
+ /**
|
|
+ * {@code ByteArrayoutputStream} to which all appends are done.
|
|
+ */
|
|
+ private ByteArrayOutputStream contentStream;
|
|
+
|
|
+ /**
|
|
+ * Boolean to indicate if contentBytes was modified.
|
|
+ */
|
|
+ private boolean bufferModified;
|
|
+
|
|
+ /**
|
|
+ * Boolean to indicate if this section contains any relocations.
|
|
+ */
|
|
+ private boolean hasRelocations;
|
|
+
|
|
+ /**
|
|
+ * Name of this container, used as section name.
|
|
+ */
|
|
+ private String containerName;
|
|
+ private final SymbolTable symbolTable;
|
|
+
|
|
+ /**
|
|
+ * Contains a unique id.
|
|
+ */
|
|
+ private int sectionId = -1;
|
|
+
|
|
+ /**
|
|
+ * Construct a {@code ByteContainer} object.
|
|
+ */
|
|
+ public ByteContainer(String containerName, SymbolTable symbolTable) {
|
|
+ this.containerName = containerName;
|
|
+ this.symbolTable = symbolTable;
|
|
+ this.contentBytes = null;
|
|
+ this.bufferModified = false;
|
|
+ this.hasRelocations = false;
|
|
+ this.contentStream = new ByteArrayOutputStream();
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Update byte buffer to reflect the current contents of byte stream.
|
|
+ *
|
|
+ * @throws InternalError throws {@code InternalError} if buffer byte array was modified
|
|
+ */
|
|
+ private void updateByteBuffer() {
|
|
+ if (!bufferModified) {
|
|
+ contentBytes = ByteBuffer.wrap(contentStream.toByteArray());
|
|
+ // Default byte order of ByteBuffer is BIG_ENDIAN.
|
|
+ // Set it appropriately
|
|
+ this.contentBytes.order(ByteOrder.nativeOrder());
|
|
+ } else {
|
|
+ throw new InternalError("Backing byte buffer no longer in sync with byte stream");
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Get the byte array of {@code ByteContainer}.
|
|
+ *
|
|
+ * @return byte array
|
|
+ * @throws InternalError throws {@code InternalError} if buffer byte array was modified
|
|
+ */
|
|
+ public byte[] getByteArray() {
|
|
+ if (!bufferModified) {
|
|
+ updateByteBuffer();
|
|
+ }
|
|
+ return contentBytes.array();
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Append to byte stream. It is an error to append to stream if the byte buffer version is
|
|
+ * changed.
|
|
+ *
|
|
+ * @param newBytes new content
|
|
+ * @param off offset start offset in {@code newBytes}
|
|
+ * @param len length of data to write
|
|
+ * @throws InternalError throws {@code InternalError} if buffer byte array was modified
|
|
+ */
|
|
+ public ByteContainer appendBytes(byte[] newBytes, int off, int len) {
|
|
+ if (bufferModified) {
|
|
+ throw new InternalError("Backing byte buffer no longer in sync with byte stream");
|
|
+ }
|
|
+ contentStream.write(newBytes, off, len);
|
|
+ return this;
|
|
+ }
|
|
+
|
|
+ public ByteContainer appendBytes(byte[] newBytes) {
|
|
+ appendBytes(newBytes, 0, newBytes.length);
|
|
+ return this;
|
|
+ }
|
|
+
|
|
+ public ByteContainer appendInt(int i) {
|
|
+ if (bufferModified) {
|
|
+ throw new InternalError("Backing byte buffer no longer in sync with byte stream");
|
|
+ }
|
|
+ ByteBuffer b = ByteBuffer.allocate(Integer.BYTES);
|
|
+ b.order(ByteOrder.nativeOrder());
|
|
+ b.putInt(i);
|
|
+ byte[] result = b.array();
|
|
+ contentStream.write(result, 0, result.length);
|
|
+ return this;
|
|
+ }
|
|
+
|
|
+ public ByteContainer appendInts(int[] newInts) {
|
|
+ if (bufferModified) {
|
|
+ throw new InternalError("Backing byte buffer no longer in sync with byte stream");
|
|
+ }
|
|
+ ByteBuffer b = ByteBuffer.allocate(Integer.BYTES * newInts.length).order(ByteOrder.nativeOrder());
|
|
+ Arrays.stream(newInts).forEach(i -> b.putInt(i));
|
|
+ byte[] result = b.array();
|
|
+ contentStream.write(result, 0, result.length);
|
|
+ return this;
|
|
+ }
|
|
+
|
|
+ public void appendLong(long l) {
|
|
+ if (bufferModified) {
|
|
+ throw new InternalError("Backing byte buffer no longer in sync with byte stream");
|
|
+ }
|
|
+ ByteBuffer b = ByteBuffer.allocate(8);
|
|
+ b.order(ByteOrder.nativeOrder());
|
|
+ b.putLong(l);
|
|
+ byte[] result = b.array();
|
|
+ contentStream.write(result, 0, result.length);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Return the current size of byte stream backing the BinaryContainer.
|
|
+ *
|
|
+ * @return size of buffer stream
|
|
+ */
|
|
+ public int getByteStreamSize() {
|
|
+ return contentStream.size();
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Return the name of this container.
|
|
+ *
|
|
+ * @return string containing name
|
|
+ */
|
|
+ @Override
|
|
+ public String getContainerName() {
|
|
+ return containerName;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Modify the byte buffer version of the byte output stream. Note that after calling this method
|
|
+ * all further updates to BinaryContainer will be out of sync with byte buffer content.
|
|
+ *
|
|
+ * @param index index of byte to be changed
|
|
+ * @param value new value
|
|
+ */
|
|
+ public void putIntAt(int index, int value) {
|
|
+ if (!bufferModified) {
|
|
+ updateByteBuffer();
|
|
+ }
|
|
+ contentBytes.putInt(index, value);
|
|
+ bufferModified = true;
|
|
+ }
|
|
+
|
|
+ public void putLongAt(int index, long value) {
|
|
+ if (!bufferModified) {
|
|
+ updateByteBuffer();
|
|
+ }
|
|
+ contentBytes.putLong(index, value);
|
|
+ bufferModified = true;
|
|
+ }
|
|
+
|
|
+ public void setSectionId(int id) {
|
|
+ if (sectionId != -1) {
|
|
+ throw new InternalError("Assigning new sectionId (old: " + sectionId + ", new: " + id + ")");
|
|
+ }
|
|
+ sectionId = id;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public int getSectionId() {
|
|
+ if (sectionId == -1) {
|
|
+ throw new InternalError("Using sectionId before assigned");
|
|
+ }
|
|
+ return sectionId;
|
|
+ }
|
|
+
|
|
+ public Symbol createSymbol(int offset, Kind kind, Binding binding, int size, String name) {
|
|
+ Symbol symbol = new Symbol(offset, kind, binding, this, size, name);
|
|
+ symbolTable.addSymbol(symbol);
|
|
+ return symbol;
|
|
+ }
|
|
+
|
|
+ public GotSymbol createGotSymbol(String name) {
|
|
+ GotSymbol symbol = new GotSymbol(Kind.OBJECT, Binding.LOCAL, this, name);
|
|
+ symbolTable.addSymbol(symbol);
|
|
+ return symbol;
|
|
+ }
|
|
+
|
|
+ public GotSymbol createGotSymbol(int offset, String name) {
|
|
+ GotSymbol symbol = new GotSymbol(offset, Kind.OBJECT, Binding.LOCAL, this, name);
|
|
+ symbolTable.addSymbol(symbol);
|
|
+ return symbol;
|
|
+ }
|
|
+
|
|
+ public void clear() {
|
|
+ this.contentBytes = null;
|
|
+ this.contentStream = null;
|
|
+ }
|
|
+
|
|
+ public void setHasRelocations() {
|
|
+ this.hasRelocations = true;
|
|
+ }
|
|
+
|
|
+ public boolean hasRelocations() {
|
|
+ return this.hasRelocations;
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/CodeContainer.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/CodeContainer.java
|
|
new file mode 100644
|
|
index 000000000..8b1f49812
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/CodeContainer.java
|
|
@@ -0,0 +1,36 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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.binformat;
|
|
+
|
|
+/**
|
|
+ * A container that holds information about code section. This is simply a ByteContainer.
|
|
+ */
|
|
+public final class CodeContainer extends ByteContainer {
|
|
+
|
|
+ public CodeContainer(String containerName, SymbolTable symbolTable) {
|
|
+ super(containerName, symbolTable);
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/Container.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/Container.java
|
|
new file mode 100644
|
|
index 000000000..c12dc155b
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/Container.java
|
|
@@ -0,0 +1,34 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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.binformat;
|
|
+
|
|
+interface Container {
|
|
+
|
|
+ String getContainerName();
|
|
+
|
|
+ int getSectionId();
|
|
+
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/GotSymbol.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/GotSymbol.java
|
|
new file mode 100644
|
|
index 000000000..6c33e65da
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/GotSymbol.java
|
|
@@ -0,0 +1,64 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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.binformat;
|
|
+
|
|
+public final class GotSymbol extends Symbol {
|
|
+
|
|
+ private static final int GOT_SIZE = 8;
|
|
+
|
|
+ public int getIndex() {
|
|
+ int offset = getOffset();
|
|
+ assert (offset % GOT_SIZE) == 0 : "got cells should be aligned: " + offset;
|
|
+ return offset / GOT_SIZE;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Create GOT symbol info.
|
|
+ *
|
|
+ * @param type type of the symbol (UNDEFINED, FUNC, etc)
|
|
+ * @param binding binding of the symbol (LOCAL, GLOBAL, ...)
|
|
+ * @param container section in which this symbol is "defined"
|
|
+ * @param name name of the symbol
|
|
+ */
|
|
+ public GotSymbol(Kind type, Binding binding, ByteContainer container, String name) {
|
|
+ this(container.getByteStreamSize(), type, binding, container, name);
|
|
+ container.appendBytes(new byte[GOT_SIZE], 0, GOT_SIZE);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Create GOT symbol info.
|
|
+ *
|
|
+ * @param offset section offset for the defined symbol
|
|
+ * @param type type of the symbol (UNDEFINED, FUNC, etc)
|
|
+ * @param binding binding of the symbol (LOCAL, GLOBAL, ...)
|
|
+ * @param sec section in which this symbol is "defined"
|
|
+ * @param name name of the symbol
|
|
+ */
|
|
+ public GotSymbol(int offset, Kind type, Binding binding, ByteContainer sec, String name) {
|
|
+ super(offset, type, binding, sec, GOT_SIZE, name);
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/HeaderContainer.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/HeaderContainer.java
|
|
new file mode 100644
|
|
index 000000000..78269a8cc
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/HeaderContainer.java
|
|
@@ -0,0 +1,94 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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.binformat;
|
|
+
|
|
+import java.io.ByteArrayOutputStream;
|
|
+import java.io.DataOutputStream;
|
|
+import java.io.IOException;
|
|
+
|
|
+public final class HeaderContainer {
|
|
+
|
|
+ private static final int CURRENT_VERSION = 1;
|
|
+ private final ReadOnlyDataContainer container;
|
|
+
|
|
+ // int _version;
|
|
+ // int _class_count;
|
|
+ // int _method_count;
|
|
+ // int _klasses_got_size;
|
|
+ // int _metadata_got_size;
|
|
+ // int _oop_got_size;
|
|
+ // int _jvm_version_offset;
|
|
+
|
|
+ public HeaderContainer(String jvmVersion, ReadOnlyDataContainer container) {
|
|
+ try {
|
|
+ byte[] filler = new byte[4 * 7];
|
|
+ container.appendBytes(filler);
|
|
+
|
|
+ // Store JVM version string at the end of header section.
|
|
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
|
|
+ DataOutputStream out = new DataOutputStream(bout);
|
|
+ out.writeUTF(jvmVersion);
|
|
+ out.writeShort(0); // Terminate by 0.
|
|
+ byte[] b = bout.toByteArray();
|
|
+ container.appendBytes(b, 0, b.length);
|
|
+ } catch (IOException e) {
|
|
+ throw new InternalError("Failed to append bytes to header section", e);
|
|
+ }
|
|
+
|
|
+ this.container = container;
|
|
+ this.container.putIntAt(0 * 4, CURRENT_VERSION);
|
|
+ this.container.putIntAt(6 * 4, 7 * 4); // JVM version string offset
|
|
+ }
|
|
+
|
|
+ public String getContainerName() {
|
|
+ return container.getContainerName();
|
|
+ }
|
|
+
|
|
+ public ReadOnlyDataContainer getContainer() {
|
|
+ return container;
|
|
+ }
|
|
+
|
|
+ public void setClassesCount(int count) {
|
|
+ this.container.putIntAt(1 * 4, count);
|
|
+ }
|
|
+
|
|
+ public void setMethodsCount(int count) {
|
|
+ this.container.putIntAt(2 * 4, count);
|
|
+ }
|
|
+
|
|
+ public void setKlassesGotSize(int size) {
|
|
+ this.container.putIntAt(3 * 4, size);
|
|
+ }
|
|
+
|
|
+ public void setMetadataGotSize(int size) {
|
|
+ this.container.putIntAt(4 * 4, size);
|
|
+ }
|
|
+
|
|
+ public void setOopGotSize(int size) {
|
|
+ this.container.putIntAt(5 * 4, size);
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/NativeSymbol.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/NativeSymbol.java
|
|
new file mode 100644
|
|
index 000000000..6deabe75f
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/NativeSymbol.java
|
|
@@ -0,0 +1,53 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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.binformat;
|
|
+
|
|
+/**
|
|
+ * This class represents a native OS specific Symbol.
|
|
+ */
|
|
+public abstract class NativeSymbol {
|
|
+
|
|
+ /** String table index. */
|
|
+ private int index;
|
|
+
|
|
+ public NativeSymbol(int index) {
|
|
+ this.index = index;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * @return the index
|
|
+ */
|
|
+ public int getIndex() {
|
|
+ return index;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * @index
|
|
+ */
|
|
+ public void setIndex(int index) {
|
|
+ this.index = index;
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/ReadOnlyDataContainer.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/ReadOnlyDataContainer.java
|
|
new file mode 100644
|
|
index 000000000..c96e27f4d
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/ReadOnlyDataContainer.java
|
|
@@ -0,0 +1,33 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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.binformat;
|
|
+
|
|
+public final class ReadOnlyDataContainer extends ByteContainer {
|
|
+
|
|
+ ReadOnlyDataContainer(String containerName, SymbolTable symbolTable) {
|
|
+ super(containerName, symbolTable);
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/Relocation.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/Relocation.java
|
|
new file mode 100644
|
|
index 000000000..5ff90bc6f
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/Relocation.java
|
|
@@ -0,0 +1,97 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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.binformat;
|
|
+
|
|
+public final class Relocation {
|
|
+
|
|
+ // @formatter:off (workaround for Eclipse formatting bug)
|
|
+ public enum RelocType {
|
|
+ UNDEFINED,
|
|
+ JAVA_CALL_INDIRECT,
|
|
+ JAVA_CALL_DIRECT,
|
|
+ FOREIGN_CALL_INDIRECT_GOT, // Call to address in GOT cell
|
|
+ STUB_CALL_DIRECT,
|
|
+ METASPACE_GOT_REFERENCE,
|
|
+ EXTERNAL_GOT_TO_PLT,
|
|
+ EXTERNAL_PLT_TO_GOT
|
|
+ }
|
|
+ // @formatter:on
|
|
+
|
|
+ private final RelocType type;
|
|
+
|
|
+ /**
|
|
+ * Byte offset from the beginning of the file affected by relocation.
|
|
+ */
|
|
+ private final int offset;
|
|
+
|
|
+ /**
|
|
+ * Size of relocation.
|
|
+ */
|
|
+ private final int size;
|
|
+
|
|
+ /**
|
|
+ * Symbol associated with this relocation.
|
|
+ */
|
|
+ private final Symbol symbol;
|
|
+
|
|
+ /**
|
|
+ * Section this relocation entry modifies.
|
|
+ */
|
|
+ private final ByteContainer section;
|
|
+
|
|
+ public Relocation(int offset, RelocType type, int size, ByteContainer section, Symbol sym) {
|
|
+ if (sym == null) {
|
|
+ throw new InternalError("must have symbol");
|
|
+ }
|
|
+ this.offset = offset;
|
|
+ this.type = type;
|
|
+ this.size = size;
|
|
+ this.symbol = sym;
|
|
+ this.section = section;
|
|
+ section.setHasRelocations();
|
|
+ }
|
|
+
|
|
+ public RelocType getType() {
|
|
+ return type;
|
|
+ }
|
|
+
|
|
+ public int getOffset() {
|
|
+ return offset;
|
|
+ }
|
|
+
|
|
+ public int getSize() {
|
|
+ return size;
|
|
+ }
|
|
+
|
|
+ public Symbol getSymbol() {
|
|
+ return symbol;
|
|
+ }
|
|
+
|
|
+ public ByteContainer getSection() {
|
|
+ return section;
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/Symbol.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/Symbol.java
|
|
new file mode 100644
|
|
index 000000000..26e458766
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/Symbol.java
|
|
@@ -0,0 +1,154 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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.binformat;
|
|
+
|
|
+import java.util.Objects;
|
|
+
|
|
+public class Symbol {
|
|
+
|
|
+ // @formatter:off (workaround for Eclipse formatting bug)
|
|
+ public enum Binding {
|
|
+ UNDEFINED,
|
|
+ LOCAL,
|
|
+ GLOBAL
|
|
+ }
|
|
+
|
|
+ public enum Kind {
|
|
+ UNDEFINED,
|
|
+ NATIVE_FUNCTION,
|
|
+ JAVA_FUNCTION,
|
|
+ OBJECT,
|
|
+ NOTYPE
|
|
+ }
|
|
+ // @formatter:on
|
|
+
|
|
+ private final String name;
|
|
+ private final int size;
|
|
+ private final int offset;
|
|
+ private final Binding binding;
|
|
+ private final Kind kind;
|
|
+
|
|
+ private ByteContainer section;
|
|
+ private NativeSymbol nativeSymbol;
|
|
+
|
|
+ /**
|
|
+ * Create symbol info.
|
|
+ *
|
|
+ * @param offset section offset for the defined symbol
|
|
+ * @param kind kind of the symbol (UNDEFINED, FUNC, etc)
|
|
+ * @param binding binding of the symbol (LOCAL, GLOBAL, ...)
|
|
+ * @param section section in which this symbol is "defined"
|
|
+ * @param size size of the symbol
|
|
+ * @param name name of the symbol
|
|
+ */
|
|
+
|
|
+ public Symbol(int offset, Kind kind, Binding binding, ByteContainer section, int size, String name) {
|
|
+ this.binding = binding;
|
|
+ this.kind = kind;
|
|
+ this.section = section;
|
|
+ this.size = size;
|
|
+ this.offset = offset;
|
|
+ this.name = name;
|
|
+ }
|
|
+
|
|
+ public String getName() {
|
|
+ return name;
|
|
+ }
|
|
+
|
|
+ public NativeSymbol getNativeSymbol() {
|
|
+ return nativeSymbol;
|
|
+ }
|
|
+
|
|
+ public void setNativeSymbol(NativeSymbol nativeSym) {
|
|
+ this.nativeSymbol = nativeSym;
|
|
+ }
|
|
+
|
|
+ public Binding getBinding() {
|
|
+ return binding;
|
|
+ }
|
|
+
|
|
+ public Kind getKind() {
|
|
+ return kind;
|
|
+ }
|
|
+
|
|
+ public int getSize() {
|
|
+ return size;
|
|
+ }
|
|
+
|
|
+ public ByteContainer getSection() {
|
|
+ return section;
|
|
+ }
|
|
+
|
|
+ public int getOffset() {
|
|
+ return offset;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean equals(Object obj) {
|
|
+ if (this == obj) {
|
|
+ return true;
|
|
+ }
|
|
+ if (!(obj instanceof Symbol)) {
|
|
+ return false;
|
|
+ }
|
|
+ if (getClass() != obj.getClass()) {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ Symbol symbol = (Symbol) obj;
|
|
+
|
|
+ if (size != symbol.size) {
|
|
+ return false;
|
|
+ }
|
|
+ if (offset != symbol.offset) {
|
|
+ return false;
|
|
+ }
|
|
+ if (!name.equals(symbol.name)) {
|
|
+ return false;
|
|
+ }
|
|
+ if (binding != symbol.binding) {
|
|
+ return false;
|
|
+ }
|
|
+ if (kind != symbol.kind) {
|
|
+ return false;
|
|
+ }
|
|
+ return !(section != null ? !section.equals(symbol.section) : symbol.section != null);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public int hashCode() {
|
|
+ int result = Objects.hash(name, binding, kind, section);
|
|
+ result = 31 * result + size;
|
|
+ result = 31 * result + offset;
|
|
+ return result;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public String toString() {
|
|
+ return "[" + name + ", " + size + ", " + offset + ", " + binding + ", " + kind + ", " + section + "]";
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/SymbolTable.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/SymbolTable.java
|
|
new file mode 100644
|
|
index 000000000..e2d4fe2cd
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/SymbolTable.java
|
|
@@ -0,0 +1,34 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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.binformat;
|
|
+
|
|
+public interface SymbolTable {
|
|
+ void addSymbol(Symbol symInfo);
|
|
+
|
|
+ Symbol getSymbol(String symName);
|
|
+
|
|
+ Symbol createSymbol(int offset, Symbol.Kind kind, Symbol.Binding binding, int size, String name);
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/AArch64JELFRelocObject.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/AArch64JELFRelocObject.java
|
|
new file mode 100644
|
|
index 000000000..7d34d1b00
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/AArch64JELFRelocObject.java
|
|
@@ -0,0 +1,118 @@
|
|
+/*
|
|
+ * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2018, 2023, Red Hat Inc. 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.binformat.elf;
|
|
+
|
|
+import jdk.tools.jaotc.binformat.BinaryContainer;
|
|
+import jdk.tools.jaotc.binformat.Relocation;
|
|
+import jdk.tools.jaotc.binformat.Relocation.RelocType;
|
|
+import jdk.tools.jaotc.binformat.Symbol;
|
|
+import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr;
|
|
+import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rela;
|
|
+
|
|
+public class AArch64JELFRelocObject extends JELFRelocObject {
|
|
+
|
|
+ AArch64JELFRelocObject(BinaryContainer binContainer, String outputFileName) {
|
|
+ super(binContainer, outputFileName);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ void createRelocation(Symbol symbol, Relocation reloc, ElfRelocTable elfRelocTable) {
|
|
+ RelocType relocType = reloc.getType();
|
|
+
|
|
+ int elfRelocType = getELFRelocationType(relocType);
|
|
+ ElfSymbol sym = (ElfSymbol) symbol.getNativeSymbol();
|
|
+ int symno = sym.getIndex();
|
|
+ int sectindex = reloc.getSection().getSectionId();
|
|
+ int offset = reloc.getOffset();
|
|
+ int addend = 0;
|
|
+
|
|
+ switch (relocType) {
|
|
+ case STUB_CALL_DIRECT:
|
|
+ case JAVA_CALL_DIRECT: {
|
|
+ break;
|
|
+ }
|
|
+ case EXTERNAL_PLT_TO_GOT:
|
|
+ offset -= 16;
|
|
+ elfRelocTable.createRelocationEntry(sectindex, offset, symno, Elf64_Rela.R_AARCH64_ADR_PREL_PG_HI21, addend);
|
|
+ elfRelocTable.createRelocationEntry(sectindex, offset + 4, symno, Elf64_Rela.R_AARCH64_ADD_ABS_LO12_NC, addend);
|
|
+ return;
|
|
+
|
|
+ case FOREIGN_CALL_INDIRECT_GOT: {
|
|
+ break;
|
|
+ }
|
|
+ case METASPACE_GOT_REFERENCE: {
|
|
+ offset -= 4;
|
|
+
|
|
+ elfRelocTable.createRelocationEntry(sectindex, offset, symno, Elf64_Rela.R_AARCH64_ADR_PREL_PG_HI21, addend);
|
|
+ elfRelocTable.createRelocationEntry(sectindex, offset + 4, symno, Elf64_Rela.R_AARCH64_ADD_ABS_LO12_NC, addend);
|
|
+ return;
|
|
+ }
|
|
+ // break;
|
|
+ case JAVA_CALL_INDIRECT: {
|
|
+ addend = -4;
|
|
+ offset = offset + addend;
|
|
+ break;
|
|
+ }
|
|
+ case EXTERNAL_GOT_TO_PLT: {
|
|
+ // this is load time relocations
|
|
+ break;
|
|
+ }
|
|
+ default:
|
|
+ throw new InternalError("Unhandled relocation type: " + relocType);
|
|
+ }
|
|
+
|
|
+ elfRelocTable.createRelocationEntry(sectindex, offset, symno, elfRelocType, addend);
|
|
+ }
|
|
+
|
|
+ int getELFRelocationType(RelocType relocType) {
|
|
+ int elfRelocType = 0; // R_<ARCH>_NONE if #define'd to 0 for all values of ARCH
|
|
+ switch (ElfTargetInfo.getElfArch()) {
|
|
+ case Elf64_Ehdr.EM_AARCH64:
|
|
+ // Return R_X86_64_* entries based on relocType
|
|
+ if (relocType == RelocType.JAVA_CALL_DIRECT ||
|
|
+ relocType == RelocType.FOREIGN_CALL_INDIRECT_GOT) {
|
|
+ elfRelocType = Elf64_Rela.R_AARCH64_CALL26;
|
|
+ } else if (relocType == RelocType.STUB_CALL_DIRECT) {
|
|
+ elfRelocType = Elf64_Rela.R_AARCH64_CALL26;
|
|
+ } else if (relocType == RelocType.JAVA_CALL_INDIRECT) {
|
|
+ elfRelocType = Elf64_Rela.R_AARCH64_CALL26;
|
|
+ } else if (relocType == RelocType.METASPACE_GOT_REFERENCE ||
|
|
+ relocType == RelocType.EXTERNAL_PLT_TO_GOT) {
|
|
+ elfRelocType = Elf64_Rela.R_AARCH64_NONE;
|
|
+ } else if (relocType == RelocType.EXTERNAL_GOT_TO_PLT) {
|
|
+ elfRelocType = Elf64_Rela.R_AARCH64_ABS64;
|
|
+ } else {
|
|
+ assert false : "Unhandled relocation type: " + relocType;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ System.out.println("Relocation Type mapping: Unhandled architecture: " + ElfTargetInfo.getElfArch());
|
|
+ }
|
|
+ return elfRelocType;
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/AMD64JELFRelocObject.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/AMD64JELFRelocObject.java
|
|
new file mode 100644
|
|
index 000000000..4f3b8d190
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/AMD64JELFRelocObject.java
|
|
@@ -0,0 +1,111 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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.binformat.elf;
|
|
+
|
|
+import jdk.tools.jaotc.binformat.BinaryContainer;
|
|
+import jdk.tools.jaotc.binformat.Relocation;
|
|
+import jdk.tools.jaotc.binformat.Relocation.RelocType;
|
|
+import jdk.tools.jaotc.binformat.Symbol;
|
|
+import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr;
|
|
+import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rela;
|
|
+
|
|
+public class AMD64JELFRelocObject extends JELFRelocObject {
|
|
+
|
|
+ AMD64JELFRelocObject(BinaryContainer binContainer, String outputFileName) {
|
|
+ super(binContainer, outputFileName);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected void createRelocation(Symbol symbol, Relocation reloc, ElfRelocTable elfRelocTable) {
|
|
+ RelocType relocType = reloc.getType();
|
|
+
|
|
+ int elfRelocType = getELFRelocationType(relocType);
|
|
+ ElfSymbol sym = (ElfSymbol) symbol.getNativeSymbol();
|
|
+ int symno = sym.getIndex();
|
|
+ int sectindex = reloc.getSection().getSectionId();
|
|
+ int offset = reloc.getOffset();
|
|
+ int addend = 0;
|
|
+
|
|
+ switch (relocType) {
|
|
+ case JAVA_CALL_DIRECT:
|
|
+ case STUB_CALL_DIRECT:
|
|
+ case FOREIGN_CALL_INDIRECT_GOT: {
|
|
+ // Create relocation entry
|
|
+ addend = -4; // Size in bytes of the patch location
|
|
+ // Relocation should be applied at the location after call operand
|
|
+ offset = offset + reloc.getSize() + addend;
|
|
+ break;
|
|
+ }
|
|
+ case JAVA_CALL_INDIRECT:
|
|
+ case METASPACE_GOT_REFERENCE:
|
|
+ case EXTERNAL_PLT_TO_GOT: {
|
|
+ addend = -4; // Size of 32-bit address of the GOT
|
|
+ /*
|
|
+ * Relocation should be applied before the test instruction to the move instruction.
|
|
+ * reloc.getOffset() points to the test instruction after the instruction that loads
|
|
+ * the address of polling page. So set the offset appropriately.
|
|
+ */
|
|
+ offset = offset + addend;
|
|
+ break;
|
|
+ }
|
|
+ case EXTERNAL_GOT_TO_PLT: {
|
|
+ // this is load time relocations
|
|
+ break;
|
|
+ }
|
|
+ default:
|
|
+ throw new InternalError("Unhandled relocation type: " + relocType);
|
|
+ }
|
|
+ elfRelocTable.createRelocationEntry(sectindex, offset, symno, elfRelocType, addend);
|
|
+ }
|
|
+
|
|
+ private static int getELFRelocationType(RelocType relocType) {
|
|
+ int elfRelocType = 0; // R_<ARCH>_NONE if #define'd to 0 for all values of ARCH
|
|
+ switch (ElfTargetInfo.getElfArch()) {
|
|
+ case Elf64_Ehdr.EM_X86_64:
|
|
+ // Return R_X86_64_* entries based on relocType
|
|
+ if (relocType == RelocType.JAVA_CALL_DIRECT ||
|
|
+ relocType == RelocType.FOREIGN_CALL_INDIRECT_GOT) {
|
|
+ elfRelocType = Elf64_Rela.R_X86_64_PLT32;
|
|
+ } else if (relocType == RelocType.STUB_CALL_DIRECT) {
|
|
+ elfRelocType = Elf64_Rela.R_X86_64_PC32;
|
|
+ } else if (relocType == RelocType.JAVA_CALL_INDIRECT) {
|
|
+ elfRelocType = Elf64_Rela.R_X86_64_NONE;
|
|
+ } else if (relocType == RelocType.METASPACE_GOT_REFERENCE ||
|
|
+ relocType == RelocType.EXTERNAL_PLT_TO_GOT) {
|
|
+ elfRelocType = Elf64_Rela.R_X86_64_PC32;
|
|
+ } else if (relocType == RelocType.EXTERNAL_GOT_TO_PLT) {
|
|
+ elfRelocType = Elf64_Rela.R_X86_64_64;
|
|
+ } else {
|
|
+ assert false : "Unhandled relocation type: " + relocType;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ System.out.println("Relocation Type mapping: Unhandled architecture: " + ElfTargetInfo.getElfArch());
|
|
+ }
|
|
+ return elfRelocType;
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/Elf.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/Elf.java
|
|
new file mode 100644
|
|
index 000000000..35deca5b1
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/Elf.java
|
|
@@ -0,0 +1,277 @@
|
|
+/*
|
|
+ * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2018, 2023, Red Hat Inc. 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.binformat.elf;
|
|
+
|
|
+//@Checkstyle: stop
|
|
+//@formatter:off
|
|
+
|
|
+/**
|
|
+ * Support for the creation of Elf Object files. Current support is limited to 64 bit x86_64.
|
|
+ */
|
|
+final class Elf {
|
|
+ /**
|
|
+ * Elf64_Ehdr structure defines.
|
|
+ */
|
|
+ enum Elf64_Ehdr {
|
|
+ e_ident( 0,16),
|
|
+ e_type(16, 2),
|
|
+ e_machine(18, 2),
|
|
+ e_version(20, 4),
|
|
+ e_entry(24, 8),
|
|
+ e_phoff(32, 8),
|
|
+ e_shoff(40, 8),
|
|
+ e_flags(48, 4),
|
|
+ e_ehsize(52, 2),
|
|
+ e_phentsize(54, 2),
|
|
+ e_phnum(56, 2),
|
|
+ e_shentsize(58, 2),
|
|
+ e_shnum(60, 2),
|
|
+ e_shstrndx(62, 2);
|
|
+
|
|
+ final int off;
|
|
+ final int sz;
|
|
+
|
|
+ Elf64_Ehdr(int offset, int size) {
|
|
+ this.off = offset;
|
|
+ this.sz = size;
|
|
+ }
|
|
+
|
|
+ static int totalsize = 64;
|
|
+
|
|
+ /**
|
|
+ * Elf64_Ehdr defines
|
|
+ */
|
|
+
|
|
+ /**
|
|
+ * e_ident
|
|
+ */
|
|
+ static final int EI_MAG0 = 0;
|
|
+ static final byte ELFMAG0 = 0x7f;
|
|
+ static final int EI_MAG1 = 1;
|
|
+ static final byte ELFMAG1 = 0x45;
|
|
+ static final int EI_MAG2 = 2;
|
|
+ static final byte ELFMAG2 = 0x4c;
|
|
+ static final int EI_MAG3 = 3;
|
|
+ static final byte ELFMAG3 = 0x46;
|
|
+ static final int EI_CLASS = 4;
|
|
+ static final byte ELFCLASS64 = 0x2;
|
|
+
|
|
+ static final int EI_DATA = 5;
|
|
+ static final byte ELFDATA2LSB = 0x1;
|
|
+
|
|
+ static final int EI_VERSION = 6;
|
|
+ static final byte EV_CURRENT = 0x1;
|
|
+
|
|
+ static final int EI_OSABI = 7;
|
|
+ static final byte ELFOSABI_NONE = 0x0;
|
|
+
|
|
+ /**
|
|
+ * e_type
|
|
+ */
|
|
+ static final char ET_REL = 0x1;
|
|
+
|
|
+ /**
|
|
+ * e_machine
|
|
+ */
|
|
+ static final char EM_NONE = 0;
|
|
+ static final char EM_X86_64 = 62;
|
|
+ static final char EM_AARCH64 = 183;
|
|
+
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Elf64_Shdr structure defines.
|
|
+ */
|
|
+ enum Elf64_Shdr {
|
|
+ sh_name( 0, 4),
|
|
+ sh_type( 4, 4),
|
|
+ sh_flags( 8, 8),
|
|
+ sh_addr(16, 8),
|
|
+ sh_offset(24, 8),
|
|
+ sh_size(32, 8),
|
|
+ sh_link(40, 4),
|
|
+ sh_info(44, 4),
|
|
+ sh_addralign(48, 8),
|
|
+ sh_entsize(56, 8);
|
|
+
|
|
+ final int off;
|
|
+ final int sz;
|
|
+
|
|
+ Elf64_Shdr(int offset, int size) {
|
|
+ this.off = offset;
|
|
+ this.sz = size;
|
|
+ }
|
|
+
|
|
+ static int totalsize = 64;
|
|
+
|
|
+ /**
|
|
+ * Elf64_Shdr defines
|
|
+ */
|
|
+
|
|
+ /**
|
|
+ * sh_type
|
|
+ */
|
|
+ static final int SHT_PROGBITS = 0x1;
|
|
+ static final int SHT_SYMTAB = 0x2;
|
|
+ static final int SHT_STRTAB = 0x3;
|
|
+ static final int SHT_RELA = 0x4;
|
|
+ static final int SHT_NOBITS = 0x8;
|
|
+ static final int SHT_REL = 0x9;
|
|
+
|
|
+ static final byte SHN_UNDEF = 0x0;
|
|
+
|
|
+ /**
|
|
+ * sh_flag
|
|
+ */
|
|
+ static final int SHF_WRITE = 0x1;
|
|
+ static final int SHF_ALLOC = 0x2;
|
|
+ static final int SHF_EXECINSTR = 0x4;
|
|
+
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Symbol table entry definitions
|
|
+ *
|
|
+ * Elf64_Sym structure defines
|
|
+ */
|
|
+ enum Elf64_Sym {
|
|
+ st_name( 0, 4),
|
|
+ st_info( 4, 1),
|
|
+ st_other( 5, 1),
|
|
+ st_shndx( 6, 2),
|
|
+ st_value( 8, 8),
|
|
+ st_size(16, 8);
|
|
+
|
|
+ final int off;
|
|
+ final int sz;
|
|
+
|
|
+ Elf64_Sym(int offset, int size) {
|
|
+ this.off = offset;
|
|
+ this.sz = size;
|
|
+ }
|
|
+
|
|
+ static int totalsize = 24;
|
|
+
|
|
+ /* ST_BIND is in bits 4-7 of st_info. ST_TYPE is in low 4 bits */
|
|
+ static final byte STB_LOCAL = 0x0;
|
|
+ static final byte STB_GLOBAL = 0x1;
|
|
+
|
|
+ static final byte STT_NOTYPE = 0x0;
|
|
+ static final byte STT_OBJECT = 0x1;
|
|
+ static final byte STT_FUNC = 0x2;
|
|
+
|
|
+ static byte ELF64_ST_INFO(byte bind, byte type) {
|
|
+ return (byte)(((bind) << 4) + ((type) & 0xf));
|
|
+ }
|
|
+
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Elf64_Rel structure defines.
|
|
+ */
|
|
+ enum Elf64_Rel {
|
|
+ r_offset( 0, 8),
|
|
+ r_info( 8, 8);
|
|
+
|
|
+ final int off;
|
|
+ final int sz;
|
|
+
|
|
+ Elf64_Rel(int offset, int size) {
|
|
+ this.off = offset;
|
|
+ this.sz = size;
|
|
+ }
|
|
+
|
|
+ static int totalsize = 16;
|
|
+
|
|
+ /**
|
|
+ * Relocation types.
|
|
+ */
|
|
+
|
|
+ static final int R_X86_64_NONE = 0x0;
|
|
+ static final int R_X86_64_64 = 0x1;
|
|
+ static final int R_X86_64_PC32 = 0x2;
|
|
+ static final int R_X86_64_PLT32 = 0x4;
|
|
+ static final int R_X86_64_GOTPCREL = 0x9;
|
|
+
|
|
+ static final int R_AARCH64_NONE = 256;
|
|
+ static final int R_AARCH64_ABS64 = 257;
|
|
+ static final int R_AARCH64_CALL26 = 283;
|
|
+ static final int R_AARCH64_ADR_GOT_PAGE = 311;
|
|
+ static final int R_AARCH64_LD64_GOT_LO12_NC = 312;
|
|
+
|
|
+ static final int R_AARCH64_MOVW_UABS_G0_NC = 264;
|
|
+ static final int R_AARCH64_MOVW_UABS_G1_NC = 266;
|
|
+ static final int R_AARCH64_MOVW_UABS_G2_NC = 268;
|
|
+
|
|
+ static final int R_AARCH64_ADR_PREL_PG_HI21 = 275;
|
|
+ static final int R_AARCH64_ADD_ABS_LO12_NC = 277;
|
|
+ static final int R_AARCH64_LDST64_ABS_LO12_NC = 286;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Elf64_Rela structure defines
|
|
+ */
|
|
+ enum Elf64_Rela {
|
|
+ r_offset( 0, 8),
|
|
+ r_info( 8, 8),
|
|
+ r_addend(16, 8);
|
|
+
|
|
+ final int off;
|
|
+ final int sz;
|
|
+
|
|
+ Elf64_Rela(int offset, int size) {
|
|
+ this.off = offset;
|
|
+ this.sz = size;
|
|
+ }
|
|
+
|
|
+ static int totalsize = 24;
|
|
+
|
|
+ static final int R_X86_64_NONE = 0x0;
|
|
+ static final int R_X86_64_64 = 0x1;
|
|
+ static final int R_X86_64_PC32 = 0x2;
|
|
+ static final int R_X86_64_PLT32 = 0x4;
|
|
+ static final int R_X86_64_GOTPCREL = 0x9;
|
|
+
|
|
+ static final int R_AARCH64_NONE = 256;
|
|
+ static final int R_AARCH64_ABS64 = 257;
|
|
+ static final int R_AARCH64_CALL26 = 283;
|
|
+ static final int R_AARCH64_ADR_GOT_PAGE = 311;
|
|
+ static final int R_AARCH64_LD64_GOT_LO12_NC = 312;
|
|
+
|
|
+ static final int R_AARCH64_MOVW_UABS_G0_NC = 264;
|
|
+ static final int R_AARCH64_MOVW_UABS_G1_NC = 266;
|
|
+ static final int R_AARCH64_MOVW_UABS_G2_NC = 268;
|
|
+
|
|
+ static final int R_AARCH64_ADR_PREL_PG_HI21 = 275;
|
|
+ static final int R_AARCH64_ADD_ABS_LO12_NC = 277;
|
|
+ static final int R_AARCH64_LDST64_ABS_LO12_NC = 286;
|
|
+
|
|
+ static long ELF64_R_INFO(int symidx, int type) {
|
|
+ return (((long) symidx << 32) + type);
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfByteBuffer.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfByteBuffer.java
|
|
new file mode 100644
|
|
index 000000000..2f9c087e8
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfByteBuffer.java
|
|
@@ -0,0 +1,45 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.binformat.elf;
|
|
+
|
|
+import java.nio.ByteBuffer;
|
|
+import java.nio.ByteOrder;
|
|
+
|
|
+import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr;
|
|
+
|
|
+final class ElfByteBuffer {
|
|
+
|
|
+ static ByteBuffer allocate(int size) {
|
|
+ ByteBuffer buf = ByteBuffer.allocate(size);
|
|
+ if (ElfTargetInfo.getElfEndian() == Elf64_Ehdr.ELFDATA2LSB) {
|
|
+ buf.order(ByteOrder.LITTLE_ENDIAN);
|
|
+ } else {
|
|
+ buf.order(ByteOrder.BIG_ENDIAN);
|
|
+ }
|
|
+ return (buf);
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfContainer.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfContainer.java
|
|
new file mode 100644
|
|
index 000000000..c3c8584bf
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfContainer.java
|
|
@@ -0,0 +1,89 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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.binformat.elf;
|
|
+
|
|
+import java.io.File;
|
|
+import java.io.FileOutputStream;
|
|
+
|
|
+final class ElfContainer {
|
|
+
|
|
+ private final File outputFile;
|
|
+ private FileOutputStream outputStream;
|
|
+ private long fileOffset;
|
|
+
|
|
+ ElfContainer(String fileName) {
|
|
+
|
|
+ outputFile = new File(fileName);
|
|
+ if (outputFile.exists()) {
|
|
+ outputFile.delete();
|
|
+ }
|
|
+
|
|
+ try {
|
|
+ outputStream = new FileOutputStream(outputFile);
|
|
+ } catch (Exception e) {
|
|
+ System.out.println("ElfContainer: Can't create file " + fileName);
|
|
+ }
|
|
+ fileOffset = 0;
|
|
+ }
|
|
+
|
|
+ void close() {
|
|
+ try {
|
|
+ outputStream.close();
|
|
+ } catch (Exception e) {
|
|
+ System.out.println("ElfContainer: close failed");
|
|
+ }
|
|
+ }
|
|
+
|
|
+ void writeBytes(byte[] bytes) {
|
|
+ if (bytes == null) {
|
|
+ return;
|
|
+ }
|
|
+ try {
|
|
+ outputStream.write(bytes);
|
|
+ } catch (Exception e) {
|
|
+ System.out.println("ElfContainer: writeBytes failed");
|
|
+ }
|
|
+ fileOffset += bytes.length;
|
|
+ }
|
|
+
|
|
+ // Write bytes to output file with up front alignment padding
|
|
+ void writeBytes(byte[] bytes, int alignment) {
|
|
+ if (bytes == null) {
|
|
+ return;
|
|
+ }
|
|
+ try {
|
|
+ // Pad to alignment
|
|
+ while ((fileOffset & (alignment - 1)) != 0) {
|
|
+ outputStream.write(0);
|
|
+ fileOffset++;
|
|
+ }
|
|
+ outputStream.write(bytes);
|
|
+ } catch (Exception e) {
|
|
+ System.out.println("ElfContainer: writeBytes failed");
|
|
+ }
|
|
+ fileOffset += bytes.length;
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfHeader.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfHeader.java
|
|
new file mode 100644
|
|
index 000000000..463a681b9
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfHeader.java
|
|
@@ -0,0 +1,75 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.binformat.elf;
|
|
+
|
|
+import java.nio.ByteBuffer;
|
|
+
|
|
+import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr;
|
|
+import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Shdr;
|
|
+
|
|
+final class ElfHeader {
|
|
+ private final ByteBuffer header;
|
|
+
|
|
+ ElfHeader() {
|
|
+ header = ElfByteBuffer.allocate(Elf64_Ehdr.totalsize);
|
|
+
|
|
+ header.put(Elf64_Ehdr.e_ident.off + Elf64_Ehdr.EI_MAG0, Elf64_Ehdr.ELFMAG0);
|
|
+ header.put(Elf64_Ehdr.e_ident.off + Elf64_Ehdr.EI_MAG1, Elf64_Ehdr.ELFMAG1);
|
|
+ header.put(Elf64_Ehdr.e_ident.off + Elf64_Ehdr.EI_MAG2, Elf64_Ehdr.ELFMAG2);
|
|
+ header.put(Elf64_Ehdr.e_ident.off + Elf64_Ehdr.EI_MAG3, Elf64_Ehdr.ELFMAG3);
|
|
+ header.put(Elf64_Ehdr.e_ident.off + Elf64_Ehdr.EI_CLASS, Elf64_Ehdr.ELFCLASS64);
|
|
+ header.put(Elf64_Ehdr.e_ident.off + Elf64_Ehdr.EI_DATA, Elf64_Ehdr.ELFDATA2LSB);
|
|
+ header.put(Elf64_Ehdr.e_ident.off + Elf64_Ehdr.EI_VERSION, Elf64_Ehdr.EV_CURRENT);
|
|
+ header.put(Elf64_Ehdr.e_ident.off + Elf64_Ehdr.EI_OSABI, Elf64_Ehdr.ELFOSABI_NONE);
|
|
+
|
|
+ header.putChar(Elf64_Ehdr.e_type.off, Elf64_Ehdr.ET_REL);
|
|
+ header.putChar(Elf64_Ehdr.e_machine.off, ElfTargetInfo.getElfArch());
|
|
+ header.putInt(Elf64_Ehdr.e_version.off, Elf64_Ehdr.EV_CURRENT);
|
|
+ header.putChar(Elf64_Ehdr.e_ehsize.off, (char) Elf64_Ehdr.totalsize);
|
|
+ header.putChar(Elf64_Ehdr.e_shentsize.off, (char) Elf64_Shdr.totalsize);
|
|
+
|
|
+ }
|
|
+
|
|
+ // Update header with file offset of first section
|
|
+ void setSectionOff(int offset) {
|
|
+ header.putLong(Elf64_Ehdr.e_shoff.off, offset);
|
|
+ }
|
|
+
|
|
+ // Update header with the number of total sections
|
|
+ void setSectionNum(int count) {
|
|
+ header.putChar(Elf64_Ehdr.e_shnum.off, (char) count);
|
|
+ }
|
|
+
|
|
+ // Update header with the section index containing the
|
|
+ // string table for section names
|
|
+ void setSectionStrNdx(int index) {
|
|
+ header.putChar(Elf64_Ehdr.e_shstrndx.off, (char) index);
|
|
+ }
|
|
+
|
|
+ byte[] getArray() {
|
|
+ return header.array();
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfRelocEntry.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfRelocEntry.java
|
|
new file mode 100644
|
|
index 000000000..e0c70170a
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfRelocEntry.java
|
|
@@ -0,0 +1,47 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.binformat.elf;
|
|
+
|
|
+import java.nio.ByteBuffer;
|
|
+
|
|
+import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rela;
|
|
+
|
|
+final class ElfRelocEntry {
|
|
+ private final ByteBuffer entry;
|
|
+
|
|
+ ElfRelocEntry(int offset, int symno, int type, int addend) {
|
|
+
|
|
+ entry = ElfByteBuffer.allocate(Elf64_Rela.totalsize);
|
|
+
|
|
+ entry.putLong(Elf64_Rela.r_offset.off, offset);
|
|
+ entry.putLong(Elf64_Rela.r_info.off, Elf64_Rela.ELF64_R_INFO(symno, type));
|
|
+ entry.putLong(Elf64_Rela.r_addend.off, addend);
|
|
+ }
|
|
+
|
|
+ byte[] getArray() {
|
|
+ return entry.array();
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfRelocTable.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfRelocTable.java
|
|
new file mode 100644
|
|
index 000000000..4a1504819
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfRelocTable.java
|
|
@@ -0,0 +1,70 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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.binformat.elf;
|
|
+
|
|
+import java.nio.ByteBuffer;
|
|
+import java.util.ArrayList;
|
|
+
|
|
+import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rela;
|
|
+
|
|
+final class ElfRelocTable {
|
|
+ private final ArrayList<ArrayList<ElfRelocEntry>> relocEntries;
|
|
+
|
|
+ ElfRelocTable(int numsects) {
|
|
+ relocEntries = new ArrayList<>(numsects);
|
|
+ for (int i = 0; i < numsects; i++) {
|
|
+ relocEntries.add(new ArrayList<ElfRelocEntry>());
|
|
+ }
|
|
+ }
|
|
+
|
|
+ void createRelocationEntry(int sectindex, int offset, int symno, int type, int addend) {
|
|
+ ElfRelocEntry entry = new ElfRelocEntry(offset, symno, type, addend);
|
|
+ relocEntries.get(sectindex).add(entry);
|
|
+ }
|
|
+
|
|
+ int getNumRelocs(int sectionIndex) {
|
|
+ return relocEntries.get(sectionIndex).size();
|
|
+ }
|
|
+
|
|
+ // Return the relocation entries for a single section
|
|
+ // or null if no entries added to section
|
|
+ byte[] getRelocData(int sectionIndex) {
|
|
+ ArrayList<ElfRelocEntry> entryList = relocEntries.get(sectionIndex);
|
|
+
|
|
+ if (entryList.size() == 0) {
|
|
+ return null;
|
|
+ }
|
|
+ ByteBuffer relocData = ElfByteBuffer.allocate(entryList.size() * Elf64_Rela.totalsize);
|
|
+
|
|
+ // Copy each entry to a single ByteBuffer
|
|
+ for (int i = 0; i < entryList.size(); i++) {
|
|
+ ElfRelocEntry entry = entryList.get(i);
|
|
+ relocData.put(entry.getArray());
|
|
+ }
|
|
+
|
|
+ return (relocData.array());
|
|
+ }
|
|
+}
|
|
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
|
|
new file mode 100644
|
|
index 000000000..7e0168a85
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSection.java
|
|
@@ -0,0 +1,157 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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.binformat.elf;
|
|
+
|
|
+import java.nio.ByteBuffer;
|
|
+
|
|
+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;
|
|
+
|
|
+final class ElfSection {
|
|
+ private final String name;
|
|
+ private final ByteBuffer section;
|
|
+ private final byte[] data;
|
|
+ private final boolean hasrelocations;
|
|
+ private final int sectionIndex;
|
|
+
|
|
+ /**
|
|
+ * String holding section name strings.
|
|
+ */
|
|
+ private static final StringBuilder sectNameTab = new StringBuilder();
|
|
+
|
|
+ /**
|
|
+ * Keeps track of bytes in section string table since strTabContent.length() is number of chars,
|
|
+ * not bytes.
|
|
+ */
|
|
+ private static int shStrTabNrOfBytes = 0;
|
|
+
|
|
+ ElfSection(String sectName, byte[] sectData, int sectFlags, int sectType,
|
|
+ boolean hasRelocations, int align, int sectIndex) {
|
|
+
|
|
+ section = ElfByteBuffer.allocate(Elf64_Shdr.totalsize);
|
|
+ name = sectName;
|
|
+ // Return all 0's for NULL section
|
|
+ if (sectIndex == 0) {
|
|
+ sectNameTab.append('\0');
|
|
+ shStrTabNrOfBytes += 1;
|
|
+ data = null;
|
|
+ hasrelocations = false;
|
|
+ sectionIndex = 0;
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ section.putInt(Elf64_Shdr.sh_name.off, shStrTabNrOfBytes);
|
|
+ sectNameTab.append(sectName).append('\0');
|
|
+ shStrTabNrOfBytes += (sectName.getBytes().length + 1);
|
|
+
|
|
+ section.putInt(Elf64_Shdr.sh_type.off, sectType);
|
|
+ section.putLong(Elf64_Shdr.sh_flags.off, sectFlags);
|
|
+ section.putLong(Elf64_Shdr.sh_addr.off, 0);
|
|
+ section.putLong(Elf64_Shdr.sh_offset.off, 0);
|
|
+
|
|
+ if (sectName.equals(".shstrtab")) {
|
|
+ section.putLong(Elf64_Shdr.sh_size.off, shStrTabNrOfBytes);
|
|
+ data = sectNameTab.toString().getBytes();
|
|
+ } else {
|
|
+ data = sectData;
|
|
+ section.putLong(Elf64_Shdr.sh_size.off, sectData.length);
|
|
+ }
|
|
+
|
|
+ section.putLong(Elf64_Shdr.sh_entsize.off, 0);
|
|
+
|
|
+ // Determine the entrysize
|
|
+ // based on type of section
|
|
+ switch (sectType) {
|
|
+ case Elf64_Shdr.SHT_SYMTAB:
|
|
+ section.putLong(Elf64_Shdr.sh_entsize.off, Elf64_Sym.totalsize);
|
|
+ break;
|
|
+ case Elf64_Shdr.SHT_RELA:
|
|
+ section.putLong(Elf64_Shdr.sh_entsize.off, Elf64_Rela.totalsize);
|
|
+ break;
|
|
+ case Elf64_Shdr.SHT_REL:
|
|
+ section.putLong(Elf64_Shdr.sh_entsize.off, Elf64_Rel.totalsize);
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ section.putLong(Elf64_Shdr.sh_addralign.off, align);
|
|
+
|
|
+ hasrelocations = hasRelocations;
|
|
+ sectionIndex = sectIndex;
|
|
+ }
|
|
+
|
|
+ String getName() {
|
|
+ return name;
|
|
+ }
|
|
+
|
|
+ long getSize() {
|
|
+ return section.getLong(Elf64_Shdr.sh_size.off);
|
|
+ }
|
|
+
|
|
+ int getDataAlign() {
|
|
+ return ((int) section.getLong(Elf64_Shdr.sh_addralign.off));
|
|
+ }
|
|
+
|
|
+ // Alignment requirements for the Elf64_Shdr structures
|
|
+ static int getShdrAlign() {
|
|
+ return (4);
|
|
+ }
|
|
+
|
|
+ byte[] getArray() {
|
|
+ return section.array();
|
|
+ }
|
|
+
|
|
+ byte[] getDataArray() {
|
|
+ return data;
|
|
+ }
|
|
+
|
|
+ void setOffset(long offset) {
|
|
+ section.putLong(Elf64_Shdr.sh_offset.off, offset);
|
|
+ }
|
|
+
|
|
+ void setLink(int link) {
|
|
+ section.putInt(Elf64_Shdr.sh_link.off, link);
|
|
+ }
|
|
+
|
|
+ void setInfo(int info) {
|
|
+ section.putInt(Elf64_Shdr.sh_info.off, info);
|
|
+ }
|
|
+
|
|
+ long getOffset() {
|
|
+ return (section.getLong(Elf64_Shdr.sh_offset.off));
|
|
+ }
|
|
+
|
|
+ boolean hasRelocations() {
|
|
+ return hasrelocations;
|
|
+ }
|
|
+
|
|
+ int getSectionId() {
|
|
+ return sectionIndex;
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSymbol.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSymbol.java
|
|
new file mode 100644
|
|
index 000000000..0f6e8d7fd
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSymbol.java
|
|
@@ -0,0 +1,53 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.binformat.elf;
|
|
+
|
|
+import java.nio.ByteBuffer;
|
|
+
|
|
+import jdk.tools.jaotc.binformat.NativeSymbol;
|
|
+import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Sym;
|
|
+
|
|
+final class ElfSymbol extends NativeSymbol {
|
|
+ private final ByteBuffer sym;
|
|
+
|
|
+ ElfSymbol(int symbolindex, int strindex, byte type, byte bind, byte sectindex, long offset, long size) {
|
|
+ super(symbolindex);
|
|
+ sym = ElfByteBuffer.allocate(Elf64_Sym.totalsize);
|
|
+
|
|
+ sym.putInt(Elf64_Sym.st_name.off, strindex);
|
|
+ sym.put(Elf64_Sym.st_info.off, Elf64_Sym.ELF64_ST_INFO(bind, type));
|
|
+ sym.put(Elf64_Sym.st_other.off, (byte) 0);
|
|
+ // Section indexes start at 1 but we manage the index internally
|
|
+ // as 0 relative
|
|
+ sym.putChar(Elf64_Sym.st_shndx.off, (char) (sectindex));
|
|
+ sym.putLong(Elf64_Sym.st_value.off, offset);
|
|
+ sym.putLong(Elf64_Sym.st_size.off, size);
|
|
+ }
|
|
+
|
|
+ byte[] getArray() {
|
|
+ return sym.array();
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSymtab.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSymtab.java
|
|
new file mode 100644
|
|
index 000000000..4cd26a5c0
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSymtab.java
|
|
@@ -0,0 +1,146 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.binformat.elf;
|
|
+
|
|
+import java.nio.ByteBuffer;
|
|
+import java.util.ArrayList;
|
|
+
|
|
+import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Sym;
|
|
+
|
|
+final class ElfSymtab {
|
|
+
|
|
+ private final ArrayList<ElfSymbol> localSymbols = new ArrayList<>();
|
|
+ private final ArrayList<ElfSymbol> globalSymbols = new ArrayList<>();
|
|
+
|
|
+ /**
|
|
+ * Number of symbols added.
|
|
+ */
|
|
+ private int symbolCount;
|
|
+
|
|
+ /**
|
|
+ * String holding symbol table strings.
|
|
+ */
|
|
+ private final StringBuilder strTabContent = new StringBuilder();
|
|
+
|
|
+ /**
|
|
+ * Keeps track of bytes in string table since strTabContent.length() is number of chars, not
|
|
+ * bytes.
|
|
+ */
|
|
+ private int strTabNrOfBytes = 0;
|
|
+
|
|
+ ElfSymtab() {
|
|
+ symbolCount = 0;
|
|
+ }
|
|
+
|
|
+ ElfSymbol addSymbolEntry(String name, byte type, byte bind, byte secHdrIndex, long offset, long size) {
|
|
+ // Get the current symbol index and append symbol name to string table.
|
|
+ int index;
|
|
+ ElfSymbol sym;
|
|
+
|
|
+ if (name.isEmpty()) {
|
|
+ index = 0;
|
|
+ strTabContent.append('\0');
|
|
+ strTabNrOfBytes += 1;
|
|
+ sym = new ElfSymbol(symbolCount, index, type, bind, secHdrIndex, offset, size);
|
|
+ localSymbols.add(sym);
|
|
+ } else {
|
|
+ // We can't trust strTabContent.length() since that is
|
|
+ // chars (UTF16), keep track of bytes on our own.
|
|
+ index = strTabNrOfBytes;
|
|
+ // strTabContent.append("_").append(name).append('\0');
|
|
+ strTabContent.append(name).append('\0');
|
|
+ // + 1 for null, + 1 for "_"
|
|
+ // strTabNrOfBytes += (name.getBytes().length + 1 + 1);
|
|
+ strTabNrOfBytes += (name.getBytes().length + 1);
|
|
+
|
|
+ sym = new ElfSymbol(symbolCount, index, type, bind, secHdrIndex, offset, size);
|
|
+ if ((bind & Elf64_Sym.STB_GLOBAL) != 0) {
|
|
+ globalSymbols.add(sym);
|
|
+ } else {
|
|
+ localSymbols.add(sym);
|
|
+ }
|
|
+ }
|
|
+ symbolCount++;
|
|
+ return (sym);
|
|
+ }
|
|
+
|
|
+ // Update the symbol indexes once all symbols have been added.
|
|
+ // This is required since we'll be reordering the symbols in the
|
|
+ // file to be in the order of Local then global.
|
|
+ void updateIndexes() {
|
|
+ int index = 0;
|
|
+
|
|
+ // Update the local symbol indexes
|
|
+ for (int i = 0; i < localSymbols.size(); i++) {
|
|
+ ElfSymbol sym = localSymbols.get(i);
|
|
+ sym.setIndex(index++);
|
|
+ }
|
|
+
|
|
+ // Update the global symbol indexes
|
|
+ for (int i = 0; i < globalSymbols.size(); i++) {
|
|
+ ElfSymbol sym = globalSymbols.get(i);
|
|
+ sym.setIndex(index++);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ int getNumLocalSyms() {
|
|
+ return localSymbols.size();
|
|
+ }
|
|
+
|
|
+ int getNumGlobalSyms() {
|
|
+ return globalSymbols.size();
|
|
+ }
|
|
+
|
|
+ // Create a single byte array that contains the symbol table entries
|
|
+ byte[] getSymtabArray() {
|
|
+ ByteBuffer symtabData = ElfByteBuffer.allocate(symbolCount * Elf64_Sym.totalsize);
|
|
+ byte[] retarray;
|
|
+
|
|
+ updateIndexes();
|
|
+
|
|
+ // Add the local symbols
|
|
+ for (int i = 0; i < localSymbols.size(); i++) {
|
|
+ ElfSymbol sym = localSymbols.get(i);
|
|
+ byte[] arr = sym.getArray();
|
|
+ symtabData.put(arr);
|
|
+ }
|
|
+ // Add the global symbols
|
|
+ for (int i = 0; i < globalSymbols.size(); i++) {
|
|
+ ElfSymbol sym = globalSymbols.get(i);
|
|
+ byte[] arr = sym.getArray();
|
|
+ symtabData.put(arr);
|
|
+ }
|
|
+ retarray = symtabData.array();
|
|
+
|
|
+ return (retarray);
|
|
+ }
|
|
+
|
|
+ // Return the string table array
|
|
+ byte[] getStrtabArray() {
|
|
+ byte[] strs = strTabContent.toString().getBytes();
|
|
+ return (strs);
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfTargetInfo.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfTargetInfo.java
|
|
new file mode 100644
|
|
index 000000000..a29e7d3b5
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfTargetInfo.java
|
|
@@ -0,0 +1,85 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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.binformat.elf;
|
|
+
|
|
+import java.nio.ByteOrder;
|
|
+import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr;
|
|
+
|
|
+/**
|
|
+ * Class that abstracts MACH-O target details.
|
|
+ *
|
|
+ */
|
|
+final class ElfTargetInfo {
|
|
+ /**
|
|
+ * Target architecture.
|
|
+ */
|
|
+ private static final char arch;
|
|
+
|
|
+ /**
|
|
+ * Architecture endian-ness.
|
|
+ */
|
|
+ private static final int endian = Elf64_Ehdr.ELFDATA2LSB;
|
|
+
|
|
+ /**
|
|
+ * Target OS string.
|
|
+ */
|
|
+ private static String osName;
|
|
+
|
|
+ static {
|
|
+ // Find the target arch details
|
|
+ String archStr = System.getProperty("os.arch").toLowerCase();
|
|
+ if (ByteOrder.nativeOrder() != ByteOrder.LITTLE_ENDIAN) {
|
|
+ System.out.println("Only Little Endian byte order supported!");
|
|
+ }
|
|
+
|
|
+ if (archStr.equals("amd64") || archStr.equals("x86_64")) {
|
|
+ arch = Elf64_Ehdr.EM_X86_64;
|
|
+ } else if (archStr.equals("aarch64")) {
|
|
+ arch = Elf64_Ehdr.EM_AARCH64;
|
|
+ } else {
|
|
+ System.out.println("Unsupported architecture " + archStr);
|
|
+ arch = Elf64_Ehdr.EM_NONE;
|
|
+ }
|
|
+
|
|
+ osName = System.getProperty("os.name").toLowerCase();
|
|
+ if (!osName.equals("linux")) {
|
|
+ System.out.println("Unsupported Operating System " + osName);
|
|
+ osName = "Unknown";
|
|
+ }
|
|
+ }
|
|
+
|
|
+ static char getElfArch() {
|
|
+ return arch;
|
|
+ }
|
|
+
|
|
+ static int getElfEndian() {
|
|
+ return endian;
|
|
+ }
|
|
+
|
|
+ static String getOsName() {
|
|
+ return osName;
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/JELFRelocObject.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/JELFRelocObject.java
|
|
new file mode 100644
|
|
index 000000000..1f3251feb
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/JELFRelocObject.java
|
|
@@ -0,0 +1,328 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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.binformat.elf;
|
|
+
|
|
+import java.io.IOException;
|
|
+import java.util.ArrayList;
|
|
+import java.util.Collection;
|
|
+import java.util.List;
|
|
+import java.util.Map;
|
|
+
|
|
+import jdk.tools.jaotc.binformat.BinaryContainer;
|
|
+import jdk.tools.jaotc.binformat.ByteContainer;
|
|
+import jdk.tools.jaotc.binformat.CodeContainer;
|
|
+import jdk.tools.jaotc.binformat.ReadOnlyDataContainer;
|
|
+import jdk.tools.jaotc.binformat.Relocation;
|
|
+import jdk.tools.jaotc.binformat.Symbol;
|
|
+import jdk.tools.jaotc.binformat.Symbol.Binding;
|
|
+import jdk.tools.jaotc.binformat.Symbol.Kind;
|
|
+import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr;
|
|
+import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Shdr;
|
|
+import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Sym;
|
|
+
|
|
+public abstract class JELFRelocObject {
|
|
+
|
|
+ private final BinaryContainer binContainer;
|
|
+
|
|
+ private final ElfContainer elfContainer;
|
|
+
|
|
+ private final int segmentSize;
|
|
+
|
|
+ protected JELFRelocObject(BinaryContainer binContainer, String outputFileName) {
|
|
+ this.binContainer = binContainer;
|
|
+ this.elfContainer = new ElfContainer(outputFileName);
|
|
+ this.segmentSize = binContainer.getCodeSegmentSize();
|
|
+ }
|
|
+
|
|
+ public static JELFRelocObject newInstance(BinaryContainer binContainer, String outputFileName) {
|
|
+ String archStr = System.getProperty("os.arch").toLowerCase();
|
|
+ if (archStr.equals("amd64") || archStr.equals("x86_64")) {
|
|
+ return new AMD64JELFRelocObject(binContainer, outputFileName);
|
|
+ } else if (archStr.equals("aarch64")) {
|
|
+ return new AArch64JELFRelocObject(binContainer, outputFileName);
|
|
+ }
|
|
+ throw new InternalError("Unsupported platform: " + archStr);
|
|
+ }
|
|
+
|
|
+ private static ElfSection createByteSection(ArrayList<ElfSection> sections,
|
|
+ String sectName,
|
|
+ byte[] scnData,
|
|
+ boolean hasRelocs,
|
|
+ int align,
|
|
+ int scnFlags,
|
|
+ int scnType) {
|
|
+
|
|
+ ElfSection sect = new ElfSection(sectName, scnData, scnFlags, scnType,
|
|
+ hasRelocs, align, sections.size());
|
|
+ // Add this section to our list
|
|
+ sections.add(sect);
|
|
+
|
|
+ return (sect);
|
|
+ }
|
|
+
|
|
+ private void createByteSection(ArrayList<ElfSection> sections,
|
|
+ ByteContainer c, int scnFlags) {
|
|
+ ElfSection sect;
|
|
+ boolean hasRelocs = c.hasRelocations();
|
|
+ byte[] scnData = c.getByteArray();
|
|
+
|
|
+ int scnType = Elf64_Shdr.SHT_PROGBITS;
|
|
+ boolean zeros = !hasRelocs;
|
|
+ if (zeros) {
|
|
+ for (byte b : scnData) {
|
|
+ if (b != 0) {
|
|
+ zeros = false;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ if (zeros) {
|
|
+ scnType = Elf64_Shdr.SHT_NOBITS;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ sect = createByteSection(sections, c.getContainerName(),
|
|
+ scnData, hasRelocs, segmentSize,
|
|
+ scnFlags, scnType);
|
|
+ c.setSectionId(sect.getSectionId());
|
|
+ }
|
|
+
|
|
+ private void createCodeSection(ArrayList<ElfSection> sections, CodeContainer c) {
|
|
+ createByteSection(sections, c, Elf64_Shdr.SHF_ALLOC | Elf64_Shdr.SHF_EXECINSTR);
|
|
+ }
|
|
+
|
|
+ private void createReadOnlySection(ArrayList<ElfSection> sections, ReadOnlyDataContainer c) {
|
|
+ createByteSection(sections, c, Elf64_Shdr.SHF_ALLOC);
|
|
+ }
|
|
+
|
|
+ private void createReadWriteSection(ArrayList<ElfSection> sections, ByteContainer c) {
|
|
+ createByteSection(sections, c, Elf64_Shdr.SHF_ALLOC | Elf64_Shdr.SHF_WRITE);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Creates an ELF relocatable object.
|
|
+ *
|
|
+ * @param relocationTable
|
|
+ * @param symbols
|
|
+ * @throws IOException throws {@code IOException} as a result of file system access failures.
|
|
+ */
|
|
+ public void createELFRelocObject(Map<Symbol, List<Relocation>> relocationTable, Collection<Symbol> symbols) throws IOException {
|
|
+ // Allocate ELF Header
|
|
+ ElfHeader eh = new ElfHeader();
|
|
+
|
|
+ ArrayList<ElfSection> sections = new ArrayList<>();
|
|
+
|
|
+ // Create the null section
|
|
+ createByteSection(sections, null, null, false, 1, 0, 0);
|
|
+
|
|
+ // Create text section
|
|
+ createCodeSection(sections, binContainer.getCodeContainer());
|
|
+ createReadOnlySection(sections, binContainer.getMetaspaceNamesContainer());
|
|
+ createReadOnlySection(sections, binContainer.getKlassesOffsetsContainer());
|
|
+ createReadOnlySection(sections, binContainer.getMethodsOffsetsContainer());
|
|
+ createReadOnlySection(sections, binContainer.getKlassesDependenciesContainer());
|
|
+ createReadOnlySection(sections, binContainer.getMethodMetadataContainer());
|
|
+ createReadOnlySection(sections, binContainer.getStubsOffsetsContainer());
|
|
+ createReadOnlySection(sections, binContainer.getHeaderContainer().getContainer());
|
|
+ createReadOnlySection(sections, binContainer.getCodeSegmentsContainer());
|
|
+ createReadOnlySection(sections, binContainer.getConstantDataContainer());
|
|
+ createReadOnlySection(sections, binContainer.getConfigContainer());
|
|
+ createReadWriteSection(sections, binContainer.getKlassesGotContainer());
|
|
+ createReadWriteSection(sections, binContainer.getCountersGotContainer());
|
|
+ createReadWriteSection(sections, binContainer.getMetadataGotContainer());
|
|
+ createReadWriteSection(sections, binContainer.getOopGotContainer());
|
|
+ createReadWriteSection(sections, binContainer.getMethodStateContainer());
|
|
+ createReadWriteSection(sections, binContainer.getExtLinkageGOTContainer());
|
|
+
|
|
+ // Get ELF symbol data from BinaryContainer object's symbol tables
|
|
+ ElfSymtab symtab = createELFSymbolTables(symbols);
|
|
+
|
|
+ // Create string table section and symbol table sections in
|
|
+ // that order since symtab section needs to set the index of
|
|
+ // strtab in sh_link field
|
|
+ ElfSection strTabSection = createByteSection(sections, ".strtab",
|
|
+ symtab.getStrtabArray(),
|
|
+ false, 1, 0,
|
|
+ Elf64_Shdr.SHT_STRTAB);
|
|
+
|
|
+ // Now create .symtab section with the symtab data constructed.
|
|
+ // On Linux, sh_link of symtab contains the index of string table
|
|
+ // its symbols reference and sh_info contains the index of first
|
|
+ // non-local symbol
|
|
+ ElfSection symTabSection = createByteSection(sections, ".symtab",
|
|
+ symtab.getSymtabArray(),
|
|
+ false, 8, 0,
|
|
+ Elf64_Shdr.SHT_SYMTAB);
|
|
+ symTabSection.setLink(strTabSection.getSectionId());
|
|
+ symTabSection.setInfo(symtab.getNumLocalSyms());
|
|
+
|
|
+ ElfRelocTable elfRelocTable = createElfRelocTable(sections, relocationTable);
|
|
+
|
|
+ createElfRelocSections(sections, elfRelocTable, symTabSection.getSectionId());
|
|
+
|
|
+ // Now, finally, after creating all sections, create shstrtab section
|
|
+ ElfSection shStrTabSection = createByteSection(sections, ".shstrtab",
|
|
+ null, false, 1, 0,
|
|
+ Elf64_Shdr.SHT_STRTAB);
|
|
+ eh.setSectionStrNdx(shStrTabSection.getSectionId());
|
|
+
|
|
+ // Update all section offsets and the Elf header section offset
|
|
+ // Write the Header followed by the contents of each section
|
|
+ // and then the section structures (section table).
|
|
+ int fileOffset = Elf64_Ehdr.totalsize;
|
|
+
|
|
+ // and round it up
|
|
+ fileOffset = (fileOffset + (sections.get(1).getDataAlign() - 1)) &
|
|
+ ~((sections.get(1).getDataAlign() - 1));
|
|
+
|
|
+ // Calc file offsets for section data skipping null section
|
|
+ for (int i = 1; i < sections.size(); i++) {
|
|
+ ElfSection sect = sections.get(i);
|
|
+ fileOffset = (fileOffset + (sect.getDataAlign() - 1)) &
|
|
+ ~((sect.getDataAlign() - 1));
|
|
+ sect.setOffset(fileOffset);
|
|
+ fileOffset += sect.getSize();
|
|
+ }
|
|
+
|
|
+ // Align the section table
|
|
+ fileOffset = (fileOffset + (ElfSection.getShdrAlign() - 1)) &
|
|
+ ~((ElfSection.getShdrAlign() - 1));
|
|
+
|
|
+ // Update the Elf Header with the offset of the first Elf64_Shdr
|
|
+ // and the number of sections.
|
|
+ eh.setSectionOff(fileOffset);
|
|
+ eh.setSectionNum(sections.size());
|
|
+
|
|
+ // Write out the Header
|
|
+ elfContainer.writeBytes(eh.getArray());
|
|
+
|
|
+ // Write out each section contents skipping null section
|
|
+ for (int i = 1; i < sections.size(); i++) {
|
|
+ ElfSection sect = sections.get(i);
|
|
+ elfContainer.writeBytes(sect.getDataArray(), sect.getDataAlign());
|
|
+ }
|
|
+
|
|
+ // Write out the section table
|
|
+ for (int i = 0; i < sections.size(); i++) {
|
|
+ ElfSection sect = sections.get(i);
|
|
+ elfContainer.writeBytes(sect.getArray(), ElfSection.getShdrAlign());
|
|
+ }
|
|
+
|
|
+ elfContainer.close();
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Construct ELF symbol data from BinaryContainer object's symbol tables. Both dynamic ELF
|
|
+ * symbol table and ELF symbol table are created from BinaryContainer's symbol info.
|
|
+ *
|
|
+ * @param symbols
|
|
+ */
|
|
+ private static ElfSymtab createELFSymbolTables(Collection<Symbol> symbols) {
|
|
+ ElfSymtab symtab = new ElfSymtab();
|
|
+
|
|
+ // First, create the initial null symbol. This is a local symbol.
|
|
+ symtab.addSymbolEntry("", (byte) 0, (byte) 0, Elf64_Shdr.SHN_UNDEF, 0, 0);
|
|
+
|
|
+ // Now create ELF symbol entries for all symbols.
|
|
+ for (Symbol symbol : symbols) {
|
|
+ // Get the index of section this symbol is defined in.
|
|
+ int secHdrIndex = symbol.getSection().getSectionId();
|
|
+ ElfSymbol elfSymbol = symtab.addSymbolEntry(symbol.getName(), getELFTypeOf(symbol), getELFBindOf(symbol), (byte) secHdrIndex, symbol.getOffset(), symbol.getSize());
|
|
+ symbol.setNativeSymbol(elfSymbol);
|
|
+ }
|
|
+ return (symtab);
|
|
+ }
|
|
+
|
|
+ private static byte getELFTypeOf(Symbol sym) {
|
|
+ Kind kind = sym.getKind();
|
|
+ if (kind == Symbol.Kind.NATIVE_FUNCTION || kind == Symbol.Kind.JAVA_FUNCTION) {
|
|
+ return Elf64_Sym.STT_FUNC;
|
|
+ } else if (kind == Symbol.Kind.OBJECT) {
|
|
+ return Elf64_Sym.STT_OBJECT;
|
|
+ }
|
|
+ return Elf64_Sym.STT_NOTYPE;
|
|
+ }
|
|
+
|
|
+ private static byte getELFBindOf(Symbol sym) {
|
|
+ Binding binding = sym.getBinding();
|
|
+ if (binding == Symbol.Binding.GLOBAL) {
|
|
+ return Elf64_Sym.STB_GLOBAL;
|
|
+ }
|
|
+ return Elf64_Sym.STB_LOCAL;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Construct a Elf relocation table from BinaryContainer object's relocation tables.
|
|
+ *
|
|
+ * @param sections
|
|
+ * @param relocationTable
|
|
+ */
|
|
+ private ElfRelocTable createElfRelocTable(ArrayList<ElfSection> sections,
|
|
+ Map<Symbol, List<Relocation>> relocationTable) {
|
|
+
|
|
+ ElfRelocTable elfRelocTable = new ElfRelocTable(sections.size());
|
|
+ /*
|
|
+ * For each of the symbols with associated relocation records, create a Elf relocation
|
|
+ * entry.
|
|
+ */
|
|
+ for (Map.Entry<Symbol, List<Relocation>> entry : relocationTable.entrySet()) {
|
|
+ List<Relocation> relocs = entry.getValue();
|
|
+ Symbol symbol = entry.getKey();
|
|
+
|
|
+ for (Relocation reloc : relocs) {
|
|
+ createRelocation(symbol, reloc, elfRelocTable);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ for (Map.Entry<Symbol, Relocation> entry : binContainer.getUniqueRelocationTable().entrySet()) {
|
|
+ createRelocation(entry.getKey(), entry.getValue(), elfRelocTable);
|
|
+ }
|
|
+
|
|
+ return (elfRelocTable);
|
|
+ }
|
|
+
|
|
+ private static void createElfRelocSections(ArrayList<ElfSection> sections,
|
|
+ ElfRelocTable elfRelocTable,
|
|
+ int symtabsectidx) {
|
|
+
|
|
+ // Grab count before we create new sections
|
|
+ int count = sections.size();
|
|
+
|
|
+ for (int i = 0; i < count; i++) {
|
|
+ if (elfRelocTable.getNumRelocs(i) > 0) {
|
|
+ ElfSection sect = sections.get(i);
|
|
+ String relname = ".rela" + sect.getName();
|
|
+ ElfSection relocSection = createByteSection(sections, relname,
|
|
+ elfRelocTable.getRelocData(i),
|
|
+ false, 8, 0, Elf64_Shdr.SHT_RELA);
|
|
+ relocSection.setLink(symtabsectidx);
|
|
+ relocSection.setInfo(sect.getSectionId());
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ abstract void createRelocation(Symbol symbol, Relocation reloc, ElfRelocTable elfRelocTable);
|
|
+
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/JMachORelocObject.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/JMachORelocObject.java
|
|
new file mode 100644
|
|
index 000000000..e6068e118
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/JMachORelocObject.java
|
|
@@ -0,0 +1,429 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.
|
|
+ */
|
|
+
|
|
+/*
|
|
+ *
|
|
+ * File Layout generated by JMachORelocObject
|
|
+ *
|
|
+ * MachO Header
|
|
+ * Load Commands
|
|
+ * LC_SEGMENT_64
|
|
+ * - Sections
|
|
+ * LC_VERSION_MIN_MAX
|
|
+ * LC_SYMTAB
|
|
+ * LC_DYSYMTAB
|
|
+ * Section Data
|
|
+ * Relocation entries
|
|
+ * Symbol table
|
|
+ *
|
|
+ */
|
|
+
|
|
+
|
|
+
|
|
+package jdk.tools.jaotc.binformat.macho;
|
|
+
|
|
+import java.io.IOException;
|
|
+import java.util.ArrayList;
|
|
+import java.util.Collection;
|
|
+import java.util.List;
|
|
+import java.util.Map;
|
|
+
|
|
+import jdk.tools.jaotc.binformat.BinaryContainer;
|
|
+import jdk.tools.jaotc.binformat.ByteContainer;
|
|
+import jdk.tools.jaotc.binformat.CodeContainer;
|
|
+import jdk.tools.jaotc.binformat.ReadOnlyDataContainer;
|
|
+import jdk.tools.jaotc.binformat.Relocation;
|
|
+import jdk.tools.jaotc.binformat.Relocation.RelocType;
|
|
+import jdk.tools.jaotc.binformat.Symbol;
|
|
+import jdk.tools.jaotc.binformat.Symbol.Kind;
|
|
+import jdk.tools.jaotc.binformat.macho.MachO.dysymtab_command;
|
|
+import jdk.tools.jaotc.binformat.macho.MachO.mach_header_64;
|
|
+import jdk.tools.jaotc.binformat.macho.MachO.nlist_64;
|
|
+import jdk.tools.jaotc.binformat.macho.MachO.reloc_info;
|
|
+import jdk.tools.jaotc.binformat.macho.MachO.section_64;
|
|
+import jdk.tools.jaotc.binformat.macho.MachO.segment_command_64;
|
|
+import jdk.tools.jaotc.binformat.macho.MachO.symtab_command;
|
|
+import jdk.tools.jaotc.binformat.macho.MachO.version_min_command;
|
|
+
|
|
+public class JMachORelocObject {
|
|
+
|
|
+ private final BinaryContainer binContainer;
|
|
+
|
|
+ private final MachOContainer machoContainer;
|
|
+
|
|
+ private final int segmentSize;
|
|
+
|
|
+ public JMachORelocObject(BinaryContainer binContainer, String outputFileName) {
|
|
+ this.binContainer = binContainer;
|
|
+ this.machoContainer = new MachOContainer(outputFileName);
|
|
+ this.segmentSize = binContainer.getCodeSegmentSize();
|
|
+ }
|
|
+
|
|
+ private void createByteSection(ArrayList<MachOSection> sections,
|
|
+ ByteContainer c, String sectName, String segName, int scnFlags) {
|
|
+
|
|
+ if (c.getByteArray().length == 0) {
|
|
+ // System.out.println("Skipping creation of " + sectName + " section, no data\n");
|
|
+ }
|
|
+
|
|
+ MachOSection sect = new MachOSection(sectName,
|
|
+ segName,
|
|
+ c.getByteArray(),
|
|
+ scnFlags,
|
|
+ c.hasRelocations(),
|
|
+ segmentSize);
|
|
+ // Add this section to our list
|
|
+ sections.add(sect);
|
|
+
|
|
+ // Record the section Id (0 relative)
|
|
+ c.setSectionId(sections.size() - 1);
|
|
+
|
|
+ // TODO: Clear out code section data to allow for GC
|
|
+ // c.clear();
|
|
+ }
|
|
+
|
|
+ private void createCodeSection(ArrayList<MachOSection> sections, CodeContainer c) {
|
|
+ createByteSection(sections, c, /* c.getContainerName() */ "__text", "__TEXT",
|
|
+ section_64.S_ATTR_PURE_INSTRUCTIONS |
|
|
+ section_64.S_ATTR_SOME_INSTRUCTIONS);
|
|
+ }
|
|
+
|
|
+ private void createReadOnlySection(ArrayList<MachOSection> sections, ReadOnlyDataContainer c) {
|
|
+ createByteSection(sections, c, c.getContainerName(), "__TEXT",
|
|
+ section_64.S_ATTR_SOME_INSTRUCTIONS);
|
|
+ }
|
|
+
|
|
+ private void createReadWriteSection(ArrayList<MachOSection> sections, ByteContainer c) {
|
|
+ createByteSection(sections, c, c.getContainerName(), "__DATA", section_64.S_REGULAR);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Creates an MachO relocatable object.
|
|
+ *
|
|
+ * @param relocationTable
|
|
+ * @param symbols
|
|
+ * @throws IOException throws {@code IOException} as a result of file system access failures.
|
|
+ */
|
|
+ public void createMachORelocObject(Map<Symbol, List<Relocation>> relocationTable, Collection<Symbol> symbols) throws IOException {
|
|
+ // Allocate MachO Header
|
|
+ // with 4 load commands
|
|
+ // LC_SEGMENT_64
|
|
+ // LC_VERSION_MIN_MACOSX
|
|
+ // LC_SYMTAB
|
|
+ // LC_DYSYMTAB
|
|
+
|
|
+ MachOHeader mh = new MachOHeader();
|
|
+
|
|
+ ArrayList<MachOSection> sections = new ArrayList<>();
|
|
+
|
|
+ // Create Sections contained in the main Segment LC_SEGMENT_64
|
|
+
|
|
+ createCodeSection(sections, binContainer.getCodeContainer());
|
|
+ createReadOnlySection(sections, binContainer.getMetaspaceNamesContainer());
|
|
+ createReadOnlySection(sections, binContainer.getKlassesOffsetsContainer());
|
|
+ createReadOnlySection(sections, binContainer.getMethodsOffsetsContainer());
|
|
+ createReadOnlySection(sections, binContainer.getKlassesDependenciesContainer());
|
|
+ createReadOnlySection(sections, binContainer.getMethodMetadataContainer());
|
|
+ createReadOnlySection(sections, binContainer.getStubsOffsetsContainer());
|
|
+ createReadOnlySection(sections, binContainer.getHeaderContainer().getContainer());
|
|
+ createReadOnlySection(sections, binContainer.getCodeSegmentsContainer());
|
|
+ createReadOnlySection(sections, binContainer.getConstantDataContainer());
|
|
+ createReadOnlySection(sections, binContainer.getConfigContainer());
|
|
+ createReadWriteSection(sections, binContainer.getKlassesGotContainer());
|
|
+ createReadWriteSection(sections, binContainer.getCountersGotContainer());
|
|
+ createReadWriteSection(sections, binContainer.getMetadataGotContainer());
|
|
+ createReadWriteSection(sections, binContainer.getMethodStateContainer());
|
|
+ createReadWriteSection(sections, binContainer.getOopGotContainer());
|
|
+ createReadWriteSection(sections, binContainer.getExtLinkageGOTContainer());
|
|
+
|
|
+ // Update the Header sizeofcmds size.
|
|
+ // This doesn't include the Header struct size
|
|
+ mh.setCmdSizes(4, segment_command_64.totalsize +
|
|
+ (section_64.totalsize * sections.size()) +
|
|
+ version_min_command.totalsize +
|
|
+ symtab_command.totalsize +
|
|
+ dysymtab_command.totalsize);
|
|
+
|
|
+ // Initialize file offset for data past commands
|
|
+ int fileOffset = mach_header_64.totalsize + mh.getCmdSize();
|
|
+ // and round it up
|
|
+ fileOffset = (fileOffset + (sections.get(0).getAlign() - 1)) & ~((sections.get(0).getAlign() - 1));
|
|
+ long address = 0;
|
|
+ int segmentOffset = fileOffset;
|
|
+
|
|
+ for (int i = 0; i < sections.size(); i++) {
|
|
+ MachOSection sect = sections.get(i);
|
|
+ fileOffset = (fileOffset + (sect.getAlign() - 1)) & ~((sect.getAlign() - 1));
|
|
+ address = (address + (sect.getAlign() - 1)) & ~((sect.getAlign() - 1));
|
|
+ sect.setOffset(fileOffset);
|
|
+ sect.setAddr(address);
|
|
+ fileOffset += sect.getSize();
|
|
+ address += sect.getSize();
|
|
+ }
|
|
+
|
|
+ // File size for Segment data
|
|
+ int segSize = fileOffset - segmentOffset;
|
|
+
|
|
+ // Create the LC_SEGMENT_64 Segment which contains the MachOSections
|
|
+ MachOSegment seg = new MachOSegment(segment_command_64.totalsize +
|
|
+ (section_64.totalsize * sections.size()),
|
|
+ segmentOffset,
|
|
+ segSize,
|
|
+ sections.size());
|
|
+
|
|
+ MachOVersion vers = new MachOVersion();
|
|
+
|
|
+ // Get symbol data from BinaryContainer object's symbol tables
|
|
+ MachOSymtab symtab = createMachOSymbolTables(sections, symbols);
|
|
+
|
|
+ // Create LC_DYSYMTAB command
|
|
+ MachODySymtab dysymtab = new MachODySymtab(symtab.getNumLocalSyms(),
|
|
+ symtab.getNumGlobalSyms(),
|
|
+ symtab.getNumUndefSyms());
|
|
+
|
|
+ // Create the Relocation Tables
|
|
+ MachORelocTable machORelocs = createMachORelocTable(sections, relocationTable, symtab);
|
|
+ // Calculate file offset for relocation data
|
|
+ fileOffset = (fileOffset + (MachORelocTable.getAlign() - 1)) & ~((MachORelocTable.getAlign() - 1));
|
|
+
|
|
+ // Update relocation sizing information in each section
|
|
+ for (int i = 0; i < sections.size(); i++) {
|
|
+ MachOSection sect = sections.get(i);
|
|
+ if (sect.hasRelocations()) {
|
|
+ int nreloc = machORelocs.getNumRelocs(i);
|
|
+ sect.setReloff(fileOffset);
|
|
+ sect.setRelcount(nreloc);
|
|
+ fileOffset += (nreloc * reloc_info.totalsize);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // Calculate and set file offset for symbol table data
|
|
+ fileOffset = (fileOffset + (MachOSymtab.getAlign() - 1)) & ~((MachOSymtab.getAlign() - 1));
|
|
+ symtab.setOffset(fileOffset);
|
|
+
|
|
+ // Write Out Header
|
|
+ machoContainer.writeBytes(mh.getArray());
|
|
+ // Write out first Segment
|
|
+ machoContainer.writeBytes(seg.getArray());
|
|
+ // Write out sections within first Segment
|
|
+ for (int i = 0; i < sections.size(); i++) {
|
|
+ MachOSection sect = sections.get(i);
|
|
+ machoContainer.writeBytes(sect.getArray());
|
|
+ }
|
|
+
|
|
+ // Write out LC_VERSION_MIN_MACOSX command
|
|
+ machoContainer.writeBytes(vers.getArray());
|
|
+
|
|
+ // Write out LC_SYMTAB command
|
|
+ symtab.calcSizes();
|
|
+ machoContainer.writeBytes(symtab.getCmdArray());
|
|
+
|
|
+ // Write out LC_DYSYMTAB command
|
|
+ machoContainer.writeBytes(dysymtab.getArray());
|
|
+
|
|
+ // Write out data associated with each Section
|
|
+ for (int i = 0; i < sections.size(); i++) {
|
|
+ MachOSection sect = sections.get(i);
|
|
+ machoContainer.writeBytes(sect.getDataArray(), sect.getAlign());
|
|
+ }
|
|
+
|
|
+ // Write out the relocation tables for all sections
|
|
+ for (int i = 0; i < sections.size(); i++) {
|
|
+ if (machORelocs.getNumRelocs(i) > 0) {
|
|
+ machoContainer.writeBytes(machORelocs.getRelocData(i), MachORelocTable.getAlign());
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // Write out data associated with LC_SYMTAB
|
|
+ machoContainer.writeBytes(symtab.getDataArray(), MachOSymtab.getAlign());
|
|
+
|
|
+ machoContainer.close();
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Construct MachO symbol data from BinaryContainer object's symbol tables. Both dynamic MachO
|
|
+ * symbol table and MachO symbol table are created from BinaryContainer's symbol info.
|
|
+ *
|
|
+ * @param sections
|
|
+ * @param symbols
|
|
+ */
|
|
+ private static MachOSymtab createMachOSymbolTables(ArrayList<MachOSection> sections,
|
|
+ Collection<Symbol> symbols) {
|
|
+ MachOSymtab symtab = new MachOSymtab();
|
|
+ // First, create the initial null symbol. This is a local symbol.
|
|
+ symtab.addSymbolEntry("", (byte) nlist_64.N_UNDF, (byte) 0, 0);
|
|
+
|
|
+ // Now create MachO symbol entries for all symbols.
|
|
+ for (Symbol symbol : symbols) {
|
|
+ int sectionId = symbol.getSection().getSectionId();
|
|
+
|
|
+ // Symbol offsets are relative to the section memory addr
|
|
+ long sectionAddr = sections.get(sectionId).getAddr();
|
|
+
|
|
+ MachOSymbol machoSymbol = symtab.addSymbolEntry(symbol.getName(),
|
|
+ getMachOTypeOf(symbol),
|
|
+ (byte) sectionId,
|
|
+ symbol.getOffset() + sectionAddr);
|
|
+ symbol.setNativeSymbol(machoSymbol);
|
|
+ }
|
|
+
|
|
+ // Now that all symbols are enterred, update the
|
|
+ // symbol indexes. This is necessary since they will
|
|
+ // be reordered based on local, global and undefined.
|
|
+ symtab.updateIndexes();
|
|
+
|
|
+ return (symtab);
|
|
+ }
|
|
+
|
|
+ private static byte getMachOTypeOf(Symbol sym) {
|
|
+ Kind kind = sym.getKind();
|
|
+ byte type = nlist_64.N_UNDF;
|
|
+
|
|
+ // Global or Local
|
|
+ if (sym.getBinding() == Symbol.Binding.GLOBAL) {
|
|
+ type = nlist_64.N_EXT;
|
|
+ }
|
|
+ // If Function or Data, add section type
|
|
+ if (kind == Symbol.Kind.NATIVE_FUNCTION ||
|
|
+ kind == Symbol.Kind.JAVA_FUNCTION ||
|
|
+ kind == Symbol.Kind.OBJECT) {
|
|
+ type |= (nlist_64.N_SECT);
|
|
+ }
|
|
+
|
|
+ return (type);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Construct a MachO relocation table from BinaryContainer object's relocation tables.
|
|
+ *
|
|
+ * @param sections
|
|
+ * @param relocationTable
|
|
+ * @param symtab
|
|
+ */
|
|
+ private MachORelocTable createMachORelocTable(ArrayList<MachOSection> sections,
|
|
+ Map<Symbol, List<Relocation>> relocationTable,
|
|
+ MachOSymtab symtab) {
|
|
+
|
|
+ MachORelocTable machORelocTable = new MachORelocTable(sections.size());
|
|
+ /*
|
|
+ * For each of the symbols with associated relocation records, create a MachO relocation
|
|
+ * entry.
|
|
+ */
|
|
+ for (Map.Entry<Symbol, List<Relocation>> entry : relocationTable.entrySet()) {
|
|
+ List<Relocation> relocs = entry.getValue();
|
|
+ Symbol symbol = entry.getKey();
|
|
+
|
|
+ for (Relocation reloc : relocs) {
|
|
+ createRelocation(symbol, reloc, machORelocTable);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ for (Map.Entry<Symbol, Relocation> entry : binContainer.getUniqueRelocationTable().entrySet()) {
|
|
+ createRelocation(entry.getKey(), entry.getValue(), machORelocTable);
|
|
+ }
|
|
+
|
|
+ return (machORelocTable);
|
|
+ }
|
|
+
|
|
+ private static void createRelocation(Symbol symbol, Relocation reloc, MachORelocTable machORelocTable) {
|
|
+ RelocType relocType = reloc.getType();
|
|
+
|
|
+ int machORelocType = getMachORelocationType(relocType);
|
|
+ MachOSymbol sym = (MachOSymbol) symbol.getNativeSymbol();
|
|
+ int symno = sym.getIndex();
|
|
+ int sectindex = reloc.getSection().getSectionId();
|
|
+ int offset = reloc.getOffset();
|
|
+ int pcrel = 0;
|
|
+ int length = 0;
|
|
+ int isextern = 1;
|
|
+
|
|
+ switch (relocType) {
|
|
+ case JAVA_CALL_DIRECT:
|
|
+ case STUB_CALL_DIRECT:
|
|
+ case FOREIGN_CALL_INDIRECT_GOT: {
|
|
+ // Create relocation entry
|
|
+ int addend = -4; // Size in bytes of the patch location
|
|
+ // Relocation should be applied at the location after call operand
|
|
+ offset = offset + reloc.getSize() + addend;
|
|
+ pcrel = 1;
|
|
+ length = 2;
|
|
+ break;
|
|
+ }
|
|
+ case JAVA_CALL_INDIRECT: {
|
|
+ // Do nothing.
|
|
+ return;
|
|
+ }
|
|
+ case METASPACE_GOT_REFERENCE:
|
|
+ case EXTERNAL_PLT_TO_GOT: {
|
|
+ int addend = -4; // Size of 32-bit address of the GOT
|
|
+ /*
|
|
+ * Relocation should be applied before the test instruction to the move instruction.
|
|
+ * reloc.getOffset() points to the test instruction after the instruction that loads
|
|
+ * the address of polling page. So set the offset appropriately.
|
|
+ */
|
|
+ offset = offset + addend;
|
|
+ pcrel = 1;
|
|
+ length = 2;
|
|
+ break;
|
|
+ }
|
|
+ case EXTERNAL_GOT_TO_PLT: {
|
|
+ // this is load time relocations
|
|
+ pcrel = 0;
|
|
+ length = 3;
|
|
+ break;
|
|
+ }
|
|
+ default:
|
|
+ throw new InternalError("Unhandled relocation type: " + relocType);
|
|
+ }
|
|
+ machORelocTable.createRelocationEntry(sectindex, offset, symno,
|
|
+ pcrel, length, isextern,
|
|
+ machORelocType);
|
|
+ }
|
|
+
|
|
+ private static int getMachORelocationType(RelocType relocType) {
|
|
+ int machORelocType = 0;
|
|
+ switch (MachOTargetInfo.getMachOArch()) {
|
|
+ case mach_header_64.CPU_TYPE_X86_64:
|
|
+ // Return X86_64_RELOC_* entries based on relocType
|
|
+ if (relocType == RelocType.JAVA_CALL_DIRECT ||
|
|
+ relocType == RelocType.FOREIGN_CALL_INDIRECT_GOT) {
|
|
+ machORelocType = reloc_info.X86_64_RELOC_BRANCH;
|
|
+ } else if (relocType == RelocType.STUB_CALL_DIRECT) {
|
|
+ machORelocType = reloc_info.X86_64_RELOC_BRANCH;
|
|
+ } else if (relocType == RelocType.JAVA_CALL_INDIRECT) {
|
|
+ machORelocType = reloc_info.X86_64_RELOC_NONE;
|
|
+ } else if (relocType == RelocType.METASPACE_GOT_REFERENCE ||
|
|
+ relocType == RelocType.EXTERNAL_PLT_TO_GOT) {
|
|
+ machORelocType = reloc_info.X86_64_RELOC_BRANCH;
|
|
+ } else if (relocType == RelocType.EXTERNAL_GOT_TO_PLT) {
|
|
+ machORelocType = reloc_info.X86_64_RELOC_UNSIGNED;
|
|
+ } else {
|
|
+ assert false : "Unhandled relocation type: " + relocType;
|
|
+ }
|
|
+ break;
|
|
+ default:
|
|
+ System.out.println("Relocation Type mapping: Unhandled architecture");
|
|
+ }
|
|
+ return machORelocType;
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachO.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachO.java
|
|
new file mode 100644
|
|
index 000000000..49d239b20
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachO.java
|
|
@@ -0,0 +1,311 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.binformat.macho;
|
|
+
|
|
+//@formatter:off
|
|
+//@Checkstyle: stop
|
|
+
|
|
+/**
|
|
+ *
|
|
+ * Support for the creation of Mach-o Object files. Current support is limited to 64 bit x86_64.
|
|
+ *
|
|
+ * File Format Overview:
|
|
+ *
|
|
+ * mach_header
|
|
+ * load_commands
|
|
+ * Typical Mac OSX 64-bit object files have these 4 load_commands
|
|
+ * (LC_SEGMENT_64, LC_SYMTAB, LC_VERSIN_MIN_MACOSX, LC_DYSYMTAB)
|
|
+ * Segments corresponding to load_commands
|
|
+ * (which each include multiple Sections)
|
|
+ */
|
|
+
|
|
+final class MachO {
|
|
+
|
|
+ /**
|
|
+ * mach_header_64 structure defines
|
|
+ */
|
|
+ enum mach_header_64 {
|
|
+ magic( 0, 4),
|
|
+ cputype( 4, 4),
|
|
+ cpusubtype( 8, 4),
|
|
+ filetype(12, 4),
|
|
+ ncmds(16, 4),
|
|
+ sizeofcmds(20, 4),
|
|
+ flags(24, 4),
|
|
+ reserved(28, 4);
|
|
+
|
|
+ final int off;
|
|
+ final int sz;
|
|
+
|
|
+ mach_header_64(int offset, int size) {
|
|
+ this.off = offset;
|
|
+ this.sz = size;
|
|
+ }
|
|
+
|
|
+ static int totalsize = 32;
|
|
+
|
|
+ /**
|
|
+ * mach_header_64 defines
|
|
+ */
|
|
+ static final int MH_MAGIC = 0xfeedface;
|
|
+ static final int MH_MAGIC_64 = 0xfeedfacf;
|
|
+ static final int MH_SUBSECTIONS_VIA_SYMBOLS = 0x2000;
|
|
+
|
|
+ /**
|
|
+ * filetype
|
|
+ */
|
|
+ static final int MH_OBJECT = 0x1;
|
|
+
|
|
+ /**
|
|
+ * cputype
|
|
+ */
|
|
+ static final int CPU_TYPE_ANY = -1;
|
|
+ static final int CPU_ARCH_ABI64 = 0x1000000;
|
|
+ static final int CPU_TYPE_X86_64 = 0x1000007;
|
|
+ static final int CPU_TYPE_ARM64 = 0x100000c;
|
|
+ /**
|
|
+ * cpusubtype
|
|
+ */
|
|
+ static final int CPU_SUBTYPE_I386_ALL = 3;
|
|
+ static final int CPU_SUBTYPE_ARM64_ALL = 0;
|
|
+ static final int CPU_SUBTYPE_LITTLE_ENDIAN = 0;
|
|
+ static final int CPU_SUBTYPE_BIG_ENDIAN = 1;
|
|
+
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * segment_command_64 structure defines
|
|
+ */
|
|
+ enum segment_command_64 {
|
|
+ cmd( 0, 4),
|
|
+ cmdsize( 4, 4),
|
|
+ segname( 8,16),
|
|
+ vmaddr(24, 8),
|
|
+ vmsize(32, 8),
|
|
+ fileoff(40, 8),
|
|
+ filesize(48, 8),
|
|
+ maxprot(56, 4),
|
|
+ initprot(60, 4),
|
|
+ nsects(64, 4),
|
|
+ flags(68, 4);
|
|
+
|
|
+ final int off;
|
|
+ final int sz;
|
|
+
|
|
+ segment_command_64(int offset, int size) {
|
|
+ this.off = offset;
|
|
+ this.sz = size;
|
|
+ }
|
|
+
|
|
+ static int totalsize = 72;
|
|
+
|
|
+ static final int LC_SEGMENT_64 = 0x19;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * section_64 structure defines
|
|
+ */
|
|
+ enum section_64 {
|
|
+ sectname( 0,16),
|
|
+ segname(16,16),
|
|
+ addr(32, 8),
|
|
+ size(40, 8),
|
|
+ offset(48, 4),
|
|
+ align(52, 4),
|
|
+ reloff(56, 4),
|
|
+ nreloc(60, 4),
|
|
+ flags(64, 4),
|
|
+ reserved1(68, 4),
|
|
+ reserved2(72, 4),
|
|
+ reserved3(76, 4);
|
|
+
|
|
+ final int off;
|
|
+ final int sz;
|
|
+
|
|
+ section_64(int offset, int size) {
|
|
+ this.off = offset;
|
|
+ this.sz = size;
|
|
+ }
|
|
+
|
|
+ static int totalsize = 80;
|
|
+
|
|
+ static int S_REGULAR = 0x0;
|
|
+ static int S_CSTRING_LITERALS = 0x2;
|
|
+ static int S_ATTR_PURE_INSTRUCTIONS = 0x80000000;
|
|
+ static int S_ATTR_SOME_INSTRUCTIONS = 0x400;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * version_min_command structure defines
|
|
+ */
|
|
+ enum version_min_command {
|
|
+ cmd( 0, 4),
|
|
+ cmdsize( 4, 4),
|
|
+ version( 8, 4),
|
|
+ sdk(12, 4);
|
|
+
|
|
+ final int off;
|
|
+ final int sz;
|
|
+
|
|
+ version_min_command(int offset, int size) {
|
|
+ this.off = offset;
|
|
+ this.sz = size;
|
|
+ }
|
|
+
|
|
+ static int totalsize = 16;
|
|
+
|
|
+ static final int LC_VERSION_MIN_MACOSX = 0x24;
|
|
+ static final int LC_VERSION_MIN_IPHONEOS = 0x25;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * symtab_command structure defines
|
|
+ */
|
|
+ enum symtab_command {
|
|
+ cmd( 0, 4),
|
|
+ cmdsize( 4, 4),
|
|
+ symoff( 8, 4),
|
|
+ nsyms(12, 4),
|
|
+ stroff(16, 4),
|
|
+ strsize(20, 4);
|
|
+
|
|
+ final int off;
|
|
+ final int sz;
|
|
+
|
|
+ symtab_command(int offset, int size) {
|
|
+ this.off = offset;
|
|
+ this.sz = size;
|
|
+ }
|
|
+
|
|
+ static int totalsize = 24;
|
|
+
|
|
+ static final int LC_SYMTAB = 0x2;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Symbol table entry definitions
|
|
+ *
|
|
+ * nlist_64 structure defines
|
|
+ */
|
|
+ enum nlist_64 {
|
|
+ n_strx( 0, 4),
|
|
+ n_type( 4, 1),
|
|
+ n_sect( 5, 1),
|
|
+ n_desc( 6, 2),
|
|
+ n_value( 8, 8);
|
|
+
|
|
+ final int off;
|
|
+ final int sz;
|
|
+
|
|
+ nlist_64(int offset, int size) {
|
|
+ this.off = offset;
|
|
+ this.sz = size;
|
|
+ }
|
|
+
|
|
+ static int totalsize = 16;
|
|
+
|
|
+ static final int N_EXT = 0x1;
|
|
+ static final int N_TYPE = 0xe;
|
|
+ static final int N_UNDF = 0x0;
|
|
+ static final int N_SECT = 0xe;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * dysymtab_command structure defines
|
|
+ */
|
|
+ enum dysymtab_command {
|
|
+ cmd( 0, 4),
|
|
+ cmdsize( 4, 4),
|
|
+ ilocalsym( 8, 4),
|
|
+ nlocalsym(12, 4),
|
|
+ iextdefsym(16, 4),
|
|
+ nextdefsym(20, 4),
|
|
+ iundefsym(24, 4),
|
|
+ nundefsym(28, 4),
|
|
+ tocoff(32, 4),
|
|
+ ntoc(36, 4),
|
|
+ modtaboff(40, 4),
|
|
+ nmodtab(44, 4),
|
|
+ extrefsymoff(48, 4),
|
|
+ nextrefsyms(52, 4),
|
|
+ indirectsymoff(56, 4),
|
|
+ nindirectsyms(60, 4),
|
|
+ extreloff(64, 4),
|
|
+ nextrel(68, 4),
|
|
+ locreloff(72, 4),
|
|
+ nlocrel(76, 4);
|
|
+
|
|
+ final int off;
|
|
+ final int sz;
|
|
+
|
|
+ dysymtab_command(int offset, int size) {
|
|
+ this.off = offset;
|
|
+ this.sz = size;
|
|
+ }
|
|
+
|
|
+ static int totalsize = 80;
|
|
+
|
|
+ static final int LC_DYSYMTAB = 0xb;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * relocation_info structure defines
|
|
+ */
|
|
+ enum reloc_info {
|
|
+ r_address( 0, 4),
|
|
+ r_relocinfo( 4, 4);
|
|
+
|
|
+ final int off;
|
|
+ final int sz;
|
|
+
|
|
+ reloc_info(int offset, int size) {
|
|
+ this.off = offset;
|
|
+ this.sz = size;
|
|
+ }
|
|
+
|
|
+ static int totalsize = 8;
|
|
+
|
|
+ static final int REL_SYMNUM_MASK = 0xffffff;
|
|
+ static final int REL_SYMNUM_SHIFT = 0x0;
|
|
+ static final int REL_PCREL_MASK = 0x1;
|
|
+ static final int REL_PCREL_SHIFT = 0x18;
|
|
+ static final int REL_LENGTH_MASK = 0x3;
|
|
+ static final int REL_LENGTH_SHIFT = 0x19;
|
|
+ static final int REL_EXTERN_MASK = 0x1;
|
|
+ static final int REL_EXTERN_SHIFT = 0x1b;
|
|
+ static final int REL_TYPE_MASK = 0xf;
|
|
+ static final int REL_TYPE_SHIFT = 0x1c;
|
|
+
|
|
+ /* reloc_type_x86_64 defines */
|
|
+
|
|
+ static final int X86_64_RELOC_NONE = 0x0;
|
|
+ static final int X86_64_RELOC_BRANCH = 0x2;
|
|
+ static final int X86_64_RELOC_GOT = 0x4;
|
|
+ static final int X86_64_RELOC_GOT_LOAD = 0x3;
|
|
+ static final int X86_64_RELOC_SIGNED = 0x1;
|
|
+ static final int X86_64_RELOC_UNSIGNED = 0x0;
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOByteBuffer.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOByteBuffer.java
|
|
new file mode 100644
|
|
index 000000000..a657b88ae
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOByteBuffer.java
|
|
@@ -0,0 +1,43 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.binformat.macho;
|
|
+
|
|
+import java.nio.ByteBuffer;
|
|
+import java.nio.ByteOrder;
|
|
+
|
|
+final class MachOByteBuffer {
|
|
+
|
|
+ static ByteBuffer allocate(int size) {
|
|
+ ByteBuffer buf = ByteBuffer.allocate(size);
|
|
+ if (MachOTargetInfo.getMachOEndian() == MachO.mach_header_64.CPU_SUBTYPE_LITTLE_ENDIAN) {
|
|
+ buf.order(ByteOrder.LITTLE_ENDIAN);
|
|
+ } else {
|
|
+ buf.order(ByteOrder.BIG_ENDIAN);
|
|
+ }
|
|
+ return (buf);
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOContainer.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOContainer.java
|
|
new file mode 100644
|
|
index 000000000..607e68ac1
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOContainer.java
|
|
@@ -0,0 +1,83 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.binformat.macho;
|
|
+
|
|
+import java.io.File;
|
|
+import java.io.FileOutputStream;
|
|
+
|
|
+final class MachOContainer {
|
|
+
|
|
+ private final File outputFile;
|
|
+ private FileOutputStream outputStream;
|
|
+ private long fileOffset;
|
|
+
|
|
+ MachOContainer(String fileName) {
|
|
+
|
|
+ outputFile = new File(fileName);
|
|
+ if (outputFile.exists()) {
|
|
+ outputFile.delete();
|
|
+ }
|
|
+
|
|
+ try {
|
|
+ outputStream = new FileOutputStream(outputFile);
|
|
+ } catch (Exception e) {
|
|
+ System.out.println("MachOContainer: Can't create file " + fileName);
|
|
+ }
|
|
+ fileOffset = 0;
|
|
+ }
|
|
+
|
|
+ void close() {
|
|
+ try {
|
|
+ outputStream.close();
|
|
+ } catch (Exception e) {
|
|
+ System.out.println("MachOContainer: close failed");
|
|
+ }
|
|
+ }
|
|
+
|
|
+ void writeBytes(byte[] bytes) {
|
|
+ try {
|
|
+ outputStream.write(bytes);
|
|
+ } catch (Exception e) {
|
|
+ System.out.println("MachOContainer: writeBytes failed");
|
|
+ }
|
|
+ fileOffset += bytes.length;
|
|
+ }
|
|
+
|
|
+ // Write bytes to output file with up front alignment padding
|
|
+ void writeBytes(byte[] bytes, int alignment) {
|
|
+ try {
|
|
+ // Pad to alignment
|
|
+ while ((fileOffset & (alignment - 1)) != 0) {
|
|
+ outputStream.write(0);
|
|
+ fileOffset++;
|
|
+ }
|
|
+ outputStream.write(bytes);
|
|
+ } catch (Exception e) {
|
|
+ System.out.println("MachOContainer: writeBytes failed");
|
|
+ }
|
|
+ fileOffset += bytes.length;
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachODySymtab.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachODySymtab.java
|
|
new file mode 100644
|
|
index 000000000..4652f9049
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachODySymtab.java
|
|
@@ -0,0 +1,51 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.binformat.macho;
|
|
+
|
|
+import java.nio.ByteBuffer;
|
|
+
|
|
+import jdk.tools.jaotc.binformat.macho.MachO.dysymtab_command;
|
|
+
|
|
+final class MachODySymtab {
|
|
+ private final ByteBuffer dysymtab;
|
|
+
|
|
+ MachODySymtab(int nlocal, int nglobal, int nundef) {
|
|
+ dysymtab = MachOByteBuffer.allocate(dysymtab_command.totalsize);
|
|
+
|
|
+ dysymtab.putInt(dysymtab_command.cmd.off, dysymtab_command.LC_DYSYMTAB);
|
|
+ dysymtab.putInt(dysymtab_command.cmdsize.off, dysymtab_command.totalsize);
|
|
+ dysymtab.putInt(dysymtab_command.ilocalsym.off, 0);
|
|
+ dysymtab.putInt(dysymtab_command.nlocalsym.off, nlocal);
|
|
+ dysymtab.putInt(dysymtab_command.iextdefsym.off, nlocal);
|
|
+ dysymtab.putInt(dysymtab_command.nextdefsym.off, nglobal);
|
|
+ dysymtab.putInt(dysymtab_command.iundefsym.off, nlocal + nglobal);
|
|
+ dysymtab.putInt(dysymtab_command.nundefsym.off, nundef);
|
|
+ }
|
|
+
|
|
+ byte[] getArray() {
|
|
+ return dysymtab.array();
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOHeader.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOHeader.java
|
|
new file mode 100644
|
|
index 000000000..707160ba6
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOHeader.java
|
|
@@ -0,0 +1,57 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.binformat.macho;
|
|
+
|
|
+import java.nio.ByteBuffer;
|
|
+
|
|
+import jdk.tools.jaotc.binformat.macho.MachO.mach_header_64;
|
|
+
|
|
+final class MachOHeader {
|
|
+ private final ByteBuffer header;
|
|
+
|
|
+ MachOHeader() {
|
|
+ header = MachOByteBuffer.allocate(mach_header_64.totalsize);
|
|
+
|
|
+ header.putInt(mach_header_64.magic.off, mach_header_64.MH_MAGIC_64);
|
|
+ header.putInt(mach_header_64.cputype.off, MachOTargetInfo.getMachOArch());
|
|
+ header.putInt(mach_header_64.cpusubtype.off, MachOTargetInfo.getMachOSubArch());
|
|
+ header.putInt(mach_header_64.flags.off, 0x2000);
|
|
+ header.putInt(mach_header_64.filetype.off, mach_header_64.MH_OBJECT);
|
|
+ }
|
|
+
|
|
+ void setCmdSizes(int ncmds, int sizeofcmds) {
|
|
+ header.putInt(mach_header_64.ncmds.off, ncmds);
|
|
+ header.putInt(mach_header_64.sizeofcmds.off, sizeofcmds);
|
|
+ }
|
|
+
|
|
+ int getCmdSize() {
|
|
+ return (header.getInt(mach_header_64.sizeofcmds.off));
|
|
+ }
|
|
+
|
|
+ byte[] getArray() {
|
|
+ return header.array();
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachORelocEntry.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachORelocEntry.java
|
|
new file mode 100644
|
|
index 000000000..1adf01af8
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachORelocEntry.java
|
|
@@ -0,0 +1,55 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.binformat.macho;
|
|
+
|
|
+import java.nio.ByteBuffer;
|
|
+
|
|
+import jdk.tools.jaotc.binformat.macho.MachO.reloc_info;
|
|
+
|
|
+final class MachORelocEntry {
|
|
+ private final ByteBuffer entry;
|
|
+
|
|
+ MachORelocEntry(int offset, int symno, int pcrel, int length, int isextern, int type) {
|
|
+
|
|
+ entry = MachOByteBuffer.allocate(reloc_info.totalsize);
|
|
+
|
|
+ entry.putInt(reloc_info.r_address.off, offset);
|
|
+
|
|
+ // Encode and store the relocation entry bitfields
|
|
+ // @formatter:off
|
|
+ entry.putInt(reloc_info.r_relocinfo.off,
|
|
+ ((symno & reloc_info.REL_SYMNUM_MASK) << reloc_info.REL_SYMNUM_SHIFT) |
|
|
+ ((pcrel & reloc_info.REL_PCREL_MASK) << reloc_info.REL_PCREL_SHIFT) |
|
|
+ ((length & reloc_info.REL_LENGTH_MASK) << reloc_info.REL_LENGTH_SHIFT) |
|
|
+ ((isextern & reloc_info.REL_EXTERN_MASK) << reloc_info.REL_EXTERN_SHIFT) |
|
|
+ ((type & reloc_info.REL_TYPE_MASK) << reloc_info.REL_TYPE_SHIFT));
|
|
+ // @formatter:on
|
|
+ }
|
|
+
|
|
+ byte[] getArray() {
|
|
+ return entry.array();
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachORelocTable.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachORelocTable.java
|
|
new file mode 100644
|
|
index 000000000..0fafb6041
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachORelocTable.java
|
|
@@ -0,0 +1,75 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.binformat.macho;
|
|
+
|
|
+import java.nio.ByteBuffer;
|
|
+import java.util.ArrayList;
|
|
+
|
|
+import jdk.tools.jaotc.binformat.macho.MachO.reloc_info;
|
|
+
|
|
+final class MachORelocTable {
|
|
+ private final ArrayList<ArrayList<MachORelocEntry>> relocEntries;
|
|
+ int fileOffset;
|
|
+
|
|
+ MachORelocTable(int numsects) {
|
|
+ relocEntries = new ArrayList<>(numsects);
|
|
+ for (int i = 0; i < numsects; i++) {
|
|
+ relocEntries.add(new ArrayList<MachORelocEntry>());
|
|
+ }
|
|
+ }
|
|
+
|
|
+ void createRelocationEntry(int sectindex, int offset, int symno, int pcrel, int length, int isextern, int type) {
|
|
+ MachORelocEntry entry = new MachORelocEntry(offset, symno, pcrel, length, isextern, type);
|
|
+ relocEntries.get(sectindex).add(entry);
|
|
+ }
|
|
+
|
|
+ static int getAlign() {
|
|
+ return (4);
|
|
+ }
|
|
+
|
|
+ int getNumRelocs(int sectionIndex) {
|
|
+ return relocEntries.get(sectionIndex).size();
|
|
+ }
|
|
+
|
|
+ // Return the relocation entries for a single section
|
|
+ // or null if no entries added to section
|
|
+ byte[] getRelocData(int sectionIndex) {
|
|
+ ArrayList<MachORelocEntry> entryList = relocEntries.get(sectionIndex);
|
|
+
|
|
+ if (entryList.size() == 0) {
|
|
+ return null;
|
|
+ }
|
|
+ ByteBuffer relocData = MachOByteBuffer.allocate(entryList.size() * reloc_info.totalsize);
|
|
+
|
|
+ // Copy each entry to a single ByteBuffer
|
|
+ for (int i = 0; i < entryList.size(); i++) {
|
|
+ MachORelocEntry entry = entryList.get(i);
|
|
+ relocData.put(entry.getArray());
|
|
+ }
|
|
+
|
|
+ return (relocData.array());
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSection.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSection.java
|
|
new file mode 100644
|
|
index 000000000..11bb2dacf
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSection.java
|
|
@@ -0,0 +1,109 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.binformat.macho;
|
|
+
|
|
+import java.nio.ByteBuffer;
|
|
+
|
|
+import jdk.tools.jaotc.binformat.macho.MachO.section_64;
|
|
+
|
|
+final class MachOSection {
|
|
+ private final ByteBuffer section;
|
|
+ private final byte[] data;
|
|
+ private final boolean hasrelocations;
|
|
+
|
|
+ MachOSection(String sectName, String segName, byte[] sectData, int sectFlags, boolean hasRelocations, int align) {
|
|
+ section = MachOByteBuffer.allocate(section_64.totalsize);
|
|
+
|
|
+ // TODO: Hotspot uses long section names.
|
|
+ // They are getting truncated.
|
|
+ // Is this a problem??
|
|
+ byte[] sectNameBytes = sectName.getBytes();
|
|
+ int sectNameMax = section_64.sectname.sz < sectNameBytes.length ? section_64.sectname.sz : sectNameBytes.length;
|
|
+
|
|
+ for (int i = 0; i < sectNameMax; i++) {
|
|
+ section.put(section_64.sectname.off + i, sectNameBytes[i]);
|
|
+ }
|
|
+ byte[] segNameBytes = segName.getBytes();
|
|
+ int segNameMax = section_64.segname.sz < segNameBytes.length ? section_64.segname.sz : segNameBytes.length;
|
|
+
|
|
+ for (int i = 0; i < segNameMax; i++) {
|
|
+ section.put(section_64.segname.off + i, segNameBytes[i]);
|
|
+ }
|
|
+ section.putLong(section_64.size.off, sectData.length);
|
|
+
|
|
+ section.putInt(section_64.align.off, 31 - Integer.numberOfLeadingZeros(align));
|
|
+
|
|
+ section.putInt(section_64.flags.off, sectFlags);
|
|
+
|
|
+ data = sectData;
|
|
+
|
|
+ hasrelocations = hasRelocations;
|
|
+ }
|
|
+
|
|
+ long getSize() {
|
|
+ return section.getLong(section_64.size.off);
|
|
+ }
|
|
+
|
|
+ int getAlign() {
|
|
+ return (1 << section.getInt(section_64.align.off));
|
|
+ }
|
|
+
|
|
+ byte[] getArray() {
|
|
+ return section.array();
|
|
+ }
|
|
+
|
|
+ byte[] getDataArray() {
|
|
+ return data;
|
|
+ }
|
|
+
|
|
+ void setAddr(long addr) {
|
|
+ section.putLong(section_64.addr.off, addr);
|
|
+ }
|
|
+
|
|
+ long getAddr() {
|
|
+ return (section.getLong(section_64.addr.off));
|
|
+ }
|
|
+
|
|
+ void setOffset(int offset) {
|
|
+ section.putInt(section_64.offset.off, offset);
|
|
+ }
|
|
+
|
|
+ int getOffset() {
|
|
+ return (section.getInt(section_64.offset.off));
|
|
+ }
|
|
+
|
|
+ void setReloff(int offset) {
|
|
+ section.putInt(section_64.reloff.off, offset);
|
|
+ }
|
|
+
|
|
+ void setRelcount(int count) {
|
|
+ section.putInt(section_64.nreloc.off, count);
|
|
+ }
|
|
+
|
|
+ boolean hasRelocations() {
|
|
+ return hasrelocations;
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSegment.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSegment.java
|
|
new file mode 100644
|
|
index 000000000..058343b05
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSegment.java
|
|
@@ -0,0 +1,53 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.binformat.macho;
|
|
+
|
|
+import java.nio.ByteBuffer;
|
|
+
|
|
+import jdk.tools.jaotc.binformat.macho.MachO.segment_command_64;
|
|
+
|
|
+public class MachOSegment {
|
|
+ ByteBuffer segment;
|
|
+
|
|
+ public MachOSegment(int size, int fileoff, int filesize, int nsects) {
|
|
+ segment = MachOByteBuffer.allocate(segment_command_64.totalsize);
|
|
+
|
|
+ segment.putInt(segment_command_64.cmd.off, segment_command_64.LC_SEGMENT_64);
|
|
+ segment.putInt(segment_command_64.cmdsize.off, size);
|
|
+ segment.putInt(segment_command_64.maxprot.off, 7);
|
|
+ segment.putInt(segment_command_64.initprot.off, 7);
|
|
+ segment.putInt(segment_command_64.nsects.off, nsects);
|
|
+ segment.putInt(segment_command_64.flags.off, 0);
|
|
+ segment.putLong(segment_command_64.vmaddr.off, 0);
|
|
+ segment.putLong(segment_command_64.vmsize.off, filesize);
|
|
+ segment.putLong(segment_command_64.fileoff.off, fileoff);
|
|
+ segment.putLong(segment_command_64.filesize.off, filesize);
|
|
+ }
|
|
+
|
|
+ public byte[] getArray() {
|
|
+ return segment.array();
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSymbol.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSymbol.java
|
|
new file mode 100644
|
|
index 000000000..d4a3f0065
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSymbol.java
|
|
@@ -0,0 +1,52 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.binformat.macho;
|
|
+
|
|
+import java.nio.ByteBuffer;
|
|
+
|
|
+import jdk.tools.jaotc.binformat.NativeSymbol;
|
|
+import jdk.tools.jaotc.binformat.macho.MachO.nlist_64;
|
|
+
|
|
+final class MachOSymbol extends NativeSymbol {
|
|
+ private final ByteBuffer sym;
|
|
+
|
|
+ MachOSymbol(int symbolindex, int strindex, byte type, byte sectindex, long offset) {
|
|
+ super(symbolindex);
|
|
+ sym = MachOByteBuffer.allocate(nlist_64.totalsize);
|
|
+
|
|
+ sym.putInt(nlist_64.n_strx.off, strindex);
|
|
+ sym.put(nlist_64.n_type.off, type);
|
|
+ // Section indexes start at 1 but we manage the index internally
|
|
+ // as 0 relative
|
|
+ sym.put(nlist_64.n_sect.off, (byte) (sectindex + 1));
|
|
+ sym.putChar(nlist_64.n_desc.off, (char) 0);
|
|
+ sym.putLong(nlist_64.n_value.off, offset);
|
|
+ }
|
|
+
|
|
+ byte[] getArray() {
|
|
+ return sym.array();
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSymtab.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSymtab.java
|
|
new file mode 100644
|
|
index 000000000..c3bcff19b
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSymtab.java
|
|
@@ -0,0 +1,209 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.binformat.macho;
|
|
+
|
|
+import java.nio.ByteBuffer;
|
|
+import java.util.ArrayList;
|
|
+
|
|
+import jdk.tools.jaotc.binformat.macho.MachO.nlist_64;
|
|
+import jdk.tools.jaotc.binformat.macho.MachO.symtab_command;
|
|
+
|
|
+final class MachOSymtab {
|
|
+
|
|
+ /**
|
|
+ * ByteBuffer holding the LC_SYMTAB command contents.
|
|
+ */
|
|
+ private final ByteBuffer symtabCmd;
|
|
+
|
|
+ private int symtabDataSize;
|
|
+
|
|
+ private final ArrayList<MachOSymbol> localSymbols = new ArrayList<>();
|
|
+ private final ArrayList<MachOSymbol> globalSymbols = new ArrayList<>();
|
|
+ private final ArrayList<MachOSymbol> undefSymbols = new ArrayList<>();
|
|
+
|
|
+ /**
|
|
+ * Number of symbols added.
|
|
+ */
|
|
+ private int symbolCount;
|
|
+
|
|
+ /**
|
|
+ * String holding symbol table strings.
|
|
+ */
|
|
+ private final StringBuilder strTabContent = new StringBuilder();
|
|
+
|
|
+ /**
|
|
+ * Keeps track of bytes in string table since strTabContent.length() is number of chars, not
|
|
+ * bytes.
|
|
+ */
|
|
+ private int strTabNrOfBytes = 0;
|
|
+
|
|
+ MachOSymtab() {
|
|
+ symtabCmd = MachOByteBuffer.allocate(symtab_command.totalsize);
|
|
+
|
|
+ symtabCmd.putInt(symtab_command.cmd.off, symtab_command.LC_SYMTAB);
|
|
+ symtabCmd.putInt(symtab_command.cmdsize.off, symtab_command.totalsize);
|
|
+
|
|
+ symbolCount = 0;
|
|
+
|
|
+ }
|
|
+
|
|
+ static int getAlign() {
|
|
+ return (4);
|
|
+ }
|
|
+
|
|
+ MachOSymbol addSymbolEntry(String name, byte type, byte secHdrIndex, long offset) {
|
|
+ // Get the current symbol index and append symbol name to string table.
|
|
+ int index;
|
|
+ MachOSymbol sym;
|
|
+
|
|
+ if (name.isEmpty()) {
|
|
+ index = 0;
|
|
+ strTabContent.append('\0');
|
|
+ strTabNrOfBytes += 1;
|
|
+ sym = new MachOSymbol(symbolCount, index, type, secHdrIndex, offset);
|
|
+ localSymbols.add(sym);
|
|
+ } else {
|
|
+ // We can't trust strTabContent.length() since that is
|
|
+ // chars (UTF16), keep track of bytes on our own.
|
|
+ index = strTabNrOfBytes;
|
|
+ strTabContent.append("_").append(name).append('\0');
|
|
+ // + 1 for null, + 1 for "_"
|
|
+ strTabNrOfBytes += (name.getBytes().length + 1 + 1);
|
|
+
|
|
+ sym = new MachOSymbol(symbolCount, index, type, secHdrIndex, offset);
|
|
+ switch (type) {
|
|
+ case nlist_64.N_EXT:
|
|
+ undefSymbols.add(sym);
|
|
+ break;
|
|
+ case nlist_64.N_SECT:
|
|
+ case nlist_64.N_UNDF: // null symbol
|
|
+ localSymbols.add(sym);
|
|
+ break;
|
|
+ case nlist_64.N_SECT | nlist_64.N_EXT:
|
|
+ globalSymbols.add(sym);
|
|
+ break;
|
|
+ default:
|
|
+ System.out.println("Unsupported Symbol type " + type);
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ symbolCount++;
|
|
+ return (sym);
|
|
+ }
|
|
+
|
|
+ void setOffset(int symoff) {
|
|
+ symtabCmd.putInt(symtab_command.symoff.off, symoff);
|
|
+ }
|
|
+
|
|
+ // Update the symbol indexes once all symbols have been added.
|
|
+ // This is required since we'll be reordering the symbols in the
|
|
+ // file to be in the order of Local, global and Undefined.
|
|
+ void updateIndexes() {
|
|
+ int index = 0;
|
|
+
|
|
+ // Update the local symbol indexes
|
|
+ for (int i = 0; i < localSymbols.size(); i++) {
|
|
+ MachOSymbol sym = localSymbols.get(i);
|
|
+ sym.setIndex(index++);
|
|
+ }
|
|
+
|
|
+ // Update the global symbol indexes
|
|
+ for (int i = 0; i < globalSymbols.size(); i++) {
|
|
+ MachOSymbol sym = globalSymbols.get(i);
|
|
+ sym.setIndex(index++);
|
|
+ }
|
|
+
|
|
+ // Update the undefined symbol indexes
|
|
+ for (int i = index; i < undefSymbols.size(); i++) {
|
|
+ MachOSymbol sym = undefSymbols.get(i);
|
|
+ sym.setIndex(index++);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // Update LC_SYMTAB command fields based on the number of symbols added
|
|
+ // return the file size taken up by symbol table entries and strings
|
|
+ int calcSizes() {
|
|
+ int stroff;
|
|
+
|
|
+ stroff = symtabCmd.getInt(symtab_command.symoff.off) + (nlist_64.totalsize * symbolCount);
|
|
+ symtabCmd.putInt(symtab_command.nsyms.off, symbolCount);
|
|
+ symtabCmd.putInt(symtab_command.stroff.off, stroff);
|
|
+ symtabCmd.putInt(symtab_command.strsize.off, strTabNrOfBytes);
|
|
+ symtabDataSize = (nlist_64.totalsize * symbolCount) + strTabNrOfBytes;
|
|
+
|
|
+ return (symtabDataSize);
|
|
+ }
|
|
+
|
|
+ int getNumLocalSyms() {
|
|
+ return localSymbols.size();
|
|
+ }
|
|
+
|
|
+ int getNumGlobalSyms() {
|
|
+ return globalSymbols.size();
|
|
+ }
|
|
+
|
|
+ int getNumUndefSyms() {
|
|
+ return undefSymbols.size();
|
|
+ }
|
|
+
|
|
+ byte[] getCmdArray() {
|
|
+ return symtabCmd.array();
|
|
+ }
|
|
+
|
|
+ // Create a single byte array that contains the symbol table entries
|
|
+ // and string table
|
|
+ byte[] getDataArray() {
|
|
+ ByteBuffer symtabData = MachOByteBuffer.allocate(symtabDataSize);
|
|
+ byte[] retarray;
|
|
+
|
|
+ // Add the local symbols
|
|
+ for (int i = 0; i < localSymbols.size(); i++) {
|
|
+ MachOSymbol sym = localSymbols.get(i);
|
|
+ byte[] arr = sym.getArray();
|
|
+ symtabData.put(arr);
|
|
+ }
|
|
+ // Add the global symbols
|
|
+ for (int i = 0; i < globalSymbols.size(); i++) {
|
|
+ MachOSymbol sym = globalSymbols.get(i);
|
|
+ byte[] arr = sym.getArray();
|
|
+ symtabData.put(arr);
|
|
+ }
|
|
+ // Add the undefined symbols
|
|
+ for (int i = 0; i < undefSymbols.size(); i++) {
|
|
+ MachOSymbol sym = undefSymbols.get(i);
|
|
+ byte[] arr = sym.getArray();
|
|
+ symtabData.put(arr);
|
|
+ }
|
|
+
|
|
+ // Add the stringtable
|
|
+ byte[] strs = strTabContent.toString().getBytes();
|
|
+ symtabData.put(strs);
|
|
+
|
|
+ retarray = symtabData.array();
|
|
+
|
|
+ return (retarray);
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOTargetInfo.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOTargetInfo.java
|
|
new file mode 100644
|
|
index 000000000..628cd574f
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOTargetInfo.java
|
|
@@ -0,0 +1,87 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.binformat.macho;
|
|
+
|
|
+import java.nio.ByteOrder;
|
|
+import jdk.tools.jaotc.binformat.macho.MachO.mach_header_64;
|
|
+
|
|
+/**
|
|
+ * Class that abstracts MACH-O target details.
|
|
+ *
|
|
+ */
|
|
+final class MachOTargetInfo {
|
|
+ /**
|
|
+ * Target architecture and subtype.
|
|
+ */
|
|
+ private static final int arch;
|
|
+ private static final int subarch;
|
|
+
|
|
+ /**
|
|
+ * Architecture endian-ness.
|
|
+ */
|
|
+ private static final int endian = mach_header_64.CPU_SUBTYPE_LITTLE_ENDIAN;
|
|
+
|
|
+ /**
|
|
+ * Target OS string.
|
|
+ */
|
|
+ private static final String osName;
|
|
+
|
|
+ static {
|
|
+ // Find the target arch details
|
|
+ String archStr = System.getProperty("os.arch").toLowerCase();
|
|
+
|
|
+ if (ByteOrder.nativeOrder() != ByteOrder.LITTLE_ENDIAN) {
|
|
+ System.out.println("Only Little Endian byte order supported!");
|
|
+ }
|
|
+
|
|
+ if (archStr.equals("amd64") || archStr.equals("x86_64")) {
|
|
+ arch = mach_header_64.CPU_TYPE_X86_64;
|
|
+ subarch = mach_header_64.CPU_SUBTYPE_I386_ALL;
|
|
+ } else {
|
|
+ System.out.println("Unsupported architecture " + archStr);
|
|
+ arch = mach_header_64.CPU_TYPE_ANY;
|
|
+ subarch = 0;
|
|
+ }
|
|
+
|
|
+ osName = System.getProperty("os.name").toLowerCase();
|
|
+ }
|
|
+
|
|
+ static int getMachOArch() {
|
|
+ return arch;
|
|
+ }
|
|
+
|
|
+ static int getMachOSubArch() {
|
|
+ return subarch;
|
|
+ }
|
|
+
|
|
+ static int getMachOEndian() {
|
|
+ return endian;
|
|
+ }
|
|
+
|
|
+ static String getOsName() {
|
|
+ return osName;
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOVersion.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOVersion.java
|
|
new file mode 100644
|
|
index 000000000..e8092fbf0
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOVersion.java
|
|
@@ -0,0 +1,47 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.binformat.macho;
|
|
+
|
|
+import java.nio.ByteBuffer;
|
|
+
|
|
+import jdk.tools.jaotc.binformat.macho.MachO.version_min_command;
|
|
+
|
|
+final class MachOVersion {
|
|
+ private final ByteBuffer version;
|
|
+
|
|
+ MachOVersion() {
|
|
+ version = MachOByteBuffer.allocate(version_min_command.totalsize);
|
|
+
|
|
+ version.putInt(version_min_command.cmd.off, version_min_command.LC_VERSION_MIN_MACOSX);
|
|
+ version.putInt(version_min_command.cmdsize.off, version_min_command.totalsize);
|
|
+ version.putInt(version_min_command.version.off, (10 << 16) | (10 << 8)); /* MacOSX 10.10 */
|
|
+ version.putInt(version_min_command.sdk.off, 0); /* N/A SDK */
|
|
+ }
|
|
+
|
|
+ byte[] getArray() {
|
|
+ return version.array();
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/JPECoffRelocObject.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/JPECoffRelocObject.java
|
|
new file mode 100644
|
|
index 000000000..01d6ad547
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/JPECoffRelocObject.java
|
|
@@ -0,0 +1,365 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.binformat.pecoff;
|
|
+
|
|
+import java.io.IOException;
|
|
+import java.util.ArrayList;
|
|
+import java.util.Collection;
|
|
+import java.util.List;
|
|
+import java.util.Map;
|
|
+
|
|
+import jdk.tools.jaotc.binformat.BinaryContainer;
|
|
+import jdk.tools.jaotc.binformat.ByteContainer;
|
|
+import jdk.tools.jaotc.binformat.CodeContainer;
|
|
+import jdk.tools.jaotc.binformat.ReadOnlyDataContainer;
|
|
+import jdk.tools.jaotc.binformat.Relocation;
|
|
+import jdk.tools.jaotc.binformat.Relocation.RelocType;
|
|
+import jdk.tools.jaotc.binformat.Symbol;
|
|
+import jdk.tools.jaotc.binformat.Symbol.Binding;
|
|
+import jdk.tools.jaotc.binformat.Symbol.Kind;
|
|
+import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_FILE_HEADER;
|
|
+import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_RELOCATION;
|
|
+import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_SECTION_HEADER;
|
|
+import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_SYMBOL;
|
|
+
|
|
+public class JPECoffRelocObject {
|
|
+
|
|
+ private final BinaryContainer binContainer;
|
|
+
|
|
+ private final PECoffContainer pecoffContainer;
|
|
+
|
|
+ private final int sectionAlignment;
|
|
+
|
|
+ public JPECoffRelocObject(BinaryContainer binContainer, String outputFileName) {
|
|
+ this.binContainer = binContainer;
|
|
+ this.pecoffContainer = new PECoffContainer(outputFileName);
|
|
+ this.sectionAlignment = binContainer.getCodeSegmentSize();
|
|
+ }
|
|
+
|
|
+ private static PECoffSection createByteSection(ArrayList<PECoffSection> sections, String sectName, byte[] scnData,
|
|
+ boolean hasRelocs, int scnFlags, int sectAlign) {
|
|
+
|
|
+ PECoffSection sect = new PECoffSection(sectName, scnData, scnFlags, sectAlign, hasRelocs, sections.size());
|
|
+ // Add this section to our list
|
|
+ sections.add(sect);
|
|
+
|
|
+ return (sect);
|
|
+ }
|
|
+
|
|
+ private static void createByteSection(ArrayList<PECoffSection> sections, ByteContainer c, int scnFlags, int sectAlign) {
|
|
+ PECoffSection sect;
|
|
+ boolean hasRelocs = c.hasRelocations();
|
|
+ byte[] scnData = c.getByteArray();
|
|
+
|
|
+ sect = createByteSection(sections, c.getContainerName(), scnData, hasRelocs, scnFlags, sectAlign);
|
|
+
|
|
+ c.setSectionId(sect.getSectionId());
|
|
+ }
|
|
+
|
|
+ private void createCodeSection(ArrayList<PECoffSection> sections, CodeContainer c) {
|
|
+ int scnFlags = IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_READ | IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_EXECUTE | IMAGE_SECTION_HEADER.IMAGE_SCN_CNT_CODE;
|
|
+ createByteSection(sections, c, scnFlags, sectionAlignment);
|
|
+ }
|
|
+
|
|
+ private void createReadOnlySection(ArrayList<PECoffSection> sections, ReadOnlyDataContainer c) {
|
|
+ int scnFlags = IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_READ | IMAGE_SECTION_HEADER.IMAGE_SCN_CNT_INITIALIZED_DATA;
|
|
+ createByteSection(sections, c, scnFlags, sectionAlignment);
|
|
+ }
|
|
+
|
|
+ private void createReadWriteSection(ArrayList<PECoffSection> sections, ByteContainer c) {
|
|
+ int scnFlags = IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_READ | IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_WRITE;
|
|
+
|
|
+ if (c.getByteArray().length > 0) {
|
|
+ scnFlags |= IMAGE_SECTION_HEADER.IMAGE_SCN_CNT_INITIALIZED_DATA;
|
|
+ } else {
|
|
+ scnFlags |= IMAGE_SECTION_HEADER.IMAGE_SCN_CNT_UNINITIALIZED_DATA;
|
|
+ }
|
|
+ createByteSection(sections, c, scnFlags, sectionAlignment);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Creates a PECoff relocatable object.
|
|
+ *
|
|
+ * @param relocationTable
|
|
+ * @param symbols
|
|
+ * @throws IOException throws {@code IOException} as a result of file system access failures.
|
|
+ */
|
|
+ public void createPECoffRelocObject(Map<Symbol, List<Relocation>> relocationTable, Collection<Symbol> symbols) throws IOException {
|
|
+ ArrayList<PECoffSection> sections = new ArrayList<>();
|
|
+
|
|
+ // Create text section
|
|
+ createCodeSection(sections, binContainer.getCodeContainer());
|
|
+ createReadOnlySection(sections, binContainer.getMetaspaceNamesContainer());
|
|
+ createReadOnlySection(sections, binContainer.getKlassesOffsetsContainer());
|
|
+ createReadOnlySection(sections, binContainer.getMethodsOffsetsContainer());
|
|
+ createReadOnlySection(sections, binContainer.getKlassesDependenciesContainer());
|
|
+ createReadOnlySection(sections, binContainer.getMethodMetadataContainer());
|
|
+ createReadOnlySection(sections, binContainer.getStubsOffsetsContainer());
|
|
+ createReadOnlySection(sections, binContainer.getHeaderContainer().getContainer());
|
|
+ createReadOnlySection(sections, binContainer.getCodeSegmentsContainer());
|
|
+ createReadOnlySection(sections, binContainer.getConstantDataContainer());
|
|
+ createReadOnlySection(sections, binContainer.getConfigContainer());
|
|
+ createReadWriteSection(sections, binContainer.getKlassesGotContainer());
|
|
+ createReadWriteSection(sections, binContainer.getCountersGotContainer());
|
|
+ createReadWriteSection(sections, binContainer.getMetadataGotContainer());
|
|
+ createReadWriteSection(sections, binContainer.getMethodStateContainer());
|
|
+ createReadWriteSection(sections, binContainer.getOopGotContainer());
|
|
+ createReadWriteSection(sections, binContainer.getExtLinkageGOTContainer());
|
|
+
|
|
+ // Allocate PECoff Header
|
|
+ PECoffHeader header = new PECoffHeader();
|
|
+
|
|
+ // Get PECoff symbol data from BinaryContainer object's symbol tables
|
|
+ PECoffSymtab symtab = createPECoffSymbolTables(symbols);
|
|
+
|
|
+ // Add Linker Directives Section
|
|
+ int scnFlags = IMAGE_SECTION_HEADER.IMAGE_SCN_LNK_INFO | IMAGE_SECTION_HEADER.IMAGE_SCN_LNK_REMOVE;
|
|
+ createByteSection(sections, ".drectve", symtab.getDirectiveArray(), false, scnFlags, 1 /*
|
|
+ * 1
|
|
+ * byte
|
|
+ * alignment
|
|
+ */);
|
|
+
|
|
+ // Create the Relocation Tables
|
|
+ PECoffRelocTable pecoffRelocs = createPECoffRelocTable(sections, relocationTable);
|
|
+
|
|
+ // File Output Order
|
|
+ //
|
|
+ // HEADER (Need address of Symbol Table + symbol count)
|
|
+ // SECTIONS (Need pointer to Section Data, Relocation Table)
|
|
+ // DIRECTIVES
|
|
+ // SYMBOL TABLE
|
|
+ // SYMBOLS
|
|
+ // SECTION DATA
|
|
+ // RELOCATION TABLE
|
|
+
|
|
+ // Calculate Offset for Symbol table
|
|
+ int fileOffset = IMAGE_FILE_HEADER.totalsize +
|
|
+ (IMAGE_SECTION_HEADER.totalsize * sections.size());
|
|
+
|
|
+ // Update Header fields
|
|
+ header.setSectionCount(sections.size());
|
|
+ header.setSymbolCount(symtab.getSymtabCount());
|
|
+ header.setSymbolOff(fileOffset);
|
|
+
|
|
+ // Calculate file offset for first section
|
|
+ fileOffset += ((symtab.getSymtabCount() * IMAGE_SYMBOL.totalsize) +
|
|
+ symtab.getStrtabSize());
|
|
+ // And round it up
|
|
+ fileOffset = (fileOffset + (sections.get(0).getDataAlign() - 1)) &
|
|
+ ~((sections.get(0).getDataAlign() - 1));
|
|
+
|
|
+ // Calc file offsets for section data
|
|
+ for (int i = 0; i < sections.size(); i++) {
|
|
+ PECoffSection sect = sections.get(i);
|
|
+ fileOffset = (fileOffset + (sect.getDataAlign() - 1)) &
|
|
+ ~((sect.getDataAlign() - 1));
|
|
+ sect.setOffset(fileOffset);
|
|
+ fileOffset += sect.getSize();
|
|
+ }
|
|
+
|
|
+ // Update relocation sizing information in each section
|
|
+ for (int i = 0; i < sections.size(); i++) {
|
|
+ PECoffSection sect = sections.get(i);
|
|
+ if (sect.hasRelocations()) {
|
|
+ int nreloc = pecoffRelocs.getNumRelocs(i);
|
|
+ sect.setReloff(fileOffset);
|
|
+ sect.setRelcount(nreloc);
|
|
+ // extended relocations add an addition entry
|
|
+ if (nreloc > 0xFFFF) {
|
|
+ nreloc++;
|
|
+ }
|
|
+ fileOffset += (nreloc * IMAGE_RELOCATION.totalsize);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // Write out the Header
|
|
+ pecoffContainer.writeBytes(header.getArray());
|
|
+
|
|
+ // Write out the section table
|
|
+ for (int i = 0; i < sections.size(); i++) {
|
|
+ PECoffSection sect = sections.get(i);
|
|
+ pecoffContainer.writeBytes(sect.getArray(), PECoffSection.getShdrAlign());
|
|
+ }
|
|
+
|
|
+ // Write out the symbol table and string table
|
|
+ pecoffContainer.writeBytes(symtab.getSymtabArray(), 4);
|
|
+ pecoffContainer.writeBytes(symtab.getStrtabArray(), 1);
|
|
+
|
|
+ // Write out each section contents
|
|
+ for (int i = 0; i < sections.size(); i++) {
|
|
+ PECoffSection sect = sections.get(i);
|
|
+ pecoffContainer.writeBytes(sect.getDataArray(), sect.getDataAlign());
|
|
+ }
|
|
+
|
|
+ // Write out Relocation Tables
|
|
+ for (int i = 0; i < sections.size(); i++) {
|
|
+ if (pecoffRelocs.getNumRelocs(i) > 0) {
|
|
+ pecoffContainer.writeBytes(pecoffRelocs.getRelocData(i));
|
|
+ }
|
|
+ }
|
|
+ pecoffContainer.close();
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Construct PECoff symbol data from BinaryContainer object's symbol tables. Both dynamic PECoff
|
|
+ * symbol table and PECoff symbol table are created from BinaryContainer's symbol info.
|
|
+ *
|
|
+ * @param symbols
|
|
+ */
|
|
+ private static PECoffSymtab createPECoffSymbolTables(Collection<Symbol> symbols) {
|
|
+ PECoffSymtab symtab = new PECoffSymtab();
|
|
+
|
|
+ // First, create the initial null symbol. This is a local symbol.
|
|
+ // symtab.addSymbolEntry("", (byte)0, (byte)0, (byte)0, 0, 0);
|
|
+
|
|
+ // Now create PECoff symbol entries for all symbols.
|
|
+ for (Symbol symbol : symbols) {
|
|
+ // Get the index of section this symbol is defined in.
|
|
+ int secHdrIndex = symbol.getSection().getSectionId();
|
|
+ PECoffSymbol pecoffSymbol = symtab.addSymbolEntry(symbol.getName(), getPECoffTypeOf(symbol), getPECoffClassOf(symbol), (byte) secHdrIndex, symbol.getOffset());
|
|
+ symbol.setNativeSymbol(pecoffSymbol);
|
|
+ }
|
|
+ return (symtab);
|
|
+ }
|
|
+
|
|
+ private static byte getPECoffTypeOf(Symbol sym) {
|
|
+ Kind kind = sym.getKind();
|
|
+ if (kind == Symbol.Kind.NATIVE_FUNCTION || kind == Symbol.Kind.JAVA_FUNCTION) {
|
|
+ return IMAGE_SYMBOL.IMAGE_SYM_DTYPE_FUNCTION;
|
|
+ }
|
|
+ return IMAGE_SYMBOL.IMAGE_SYM_DTYPE_NONE;
|
|
+ }
|
|
+
|
|
+ private static byte getPECoffClassOf(Symbol sym) {
|
|
+ Binding binding = sym.getBinding();
|
|
+ if (binding == Symbol.Binding.GLOBAL) {
|
|
+ return IMAGE_SYMBOL.IMAGE_SYM_CLASS_EXTERNAL;
|
|
+ }
|
|
+ return IMAGE_SYMBOL.IMAGE_SYM_CLASS_STATIC;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Construct a PECoff relocation table from BinaryContainer object's relocation tables.
|
|
+ *
|
|
+ * @param sections
|
|
+ * @param relocationTable
|
|
+ */
|
|
+ private PECoffRelocTable createPECoffRelocTable(ArrayList<PECoffSection> sections, Map<Symbol, List<Relocation>> relocationTable) {
|
|
+
|
|
+ PECoffRelocTable pecoffRelocTable = new PECoffRelocTable(sections.size());
|
|
+ /*
|
|
+ * For each of the symbols with associated relocation records, create a PECoff relocation
|
|
+ * entry.
|
|
+ */
|
|
+ for (Map.Entry<Symbol, List<Relocation>> entry : relocationTable.entrySet()) {
|
|
+ List<Relocation> relocs = entry.getValue();
|
|
+ Symbol symbol = entry.getKey();
|
|
+
|
|
+ for (Relocation reloc : relocs) {
|
|
+ createRelocation(symbol, reloc, pecoffRelocTable);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ for (Map.Entry<Symbol, Relocation> entry : binContainer.getUniqueRelocationTable().entrySet()) {
|
|
+ createRelocation(entry.getKey(), entry.getValue(), pecoffRelocTable);
|
|
+ }
|
|
+
|
|
+ return (pecoffRelocTable);
|
|
+ }
|
|
+
|
|
+ private static void createRelocation(Symbol symbol, Relocation reloc, PECoffRelocTable pecoffRelocTable) {
|
|
+ RelocType relocType = reloc.getType();
|
|
+
|
|
+ int pecoffRelocType = getPECoffRelocationType(relocType);
|
|
+ PECoffSymbol sym = (PECoffSymbol) symbol.getNativeSymbol();
|
|
+ int symno = sym.getIndex();
|
|
+ int sectindex = reloc.getSection().getSectionId();
|
|
+ int offset = reloc.getOffset();
|
|
+ int addend = 0;
|
|
+
|
|
+ switch (relocType) {
|
|
+ case JAVA_CALL_DIRECT:
|
|
+ case STUB_CALL_DIRECT:
|
|
+ case FOREIGN_CALL_INDIRECT_GOT: {
|
|
+ // Create relocation entry
|
|
+ addend = -4; // Size in bytes of the patch location
|
|
+ // Relocation should be applied at the location after call operand
|
|
+ offset = offset + reloc.getSize() + addend;
|
|
+ break;
|
|
+ }
|
|
+ case JAVA_CALL_INDIRECT: {
|
|
+ // Do nothing.
|
|
+ return;
|
|
+ }
|
|
+ case METASPACE_GOT_REFERENCE:
|
|
+ case EXTERNAL_PLT_TO_GOT: {
|
|
+ addend = -4; // Size of 32-bit address of the GOT
|
|
+ /*
|
|
+ * Relocation should be applied before the test instruction to the move instruction.
|
|
+ * reloc.getOffset() points to the test instruction after the instruction that loads
|
|
+ * the address of polling page. So set the offset appropriately.
|
|
+ */
|
|
+ offset = offset + addend;
|
|
+ break;
|
|
+ }
|
|
+ case EXTERNAL_GOT_TO_PLT: {
|
|
+ // this is load time relocations
|
|
+ break;
|
|
+ }
|
|
+ default:
|
|
+ throw new InternalError("Unhandled relocation type: " + relocType);
|
|
+ }
|
|
+ pecoffRelocTable.createRelocationEntry(sectindex, offset, symno, pecoffRelocType);
|
|
+ }
|
|
+
|
|
+ // Return IMAGE_RELOCATION Type based on relocType
|
|
+ private static int getPECoffRelocationType(RelocType relocType) {
|
|
+ int pecoffRelocType = 0; // R_<ARCH>_NONE if #define'd to 0 for all values of ARCH
|
|
+ switch (PECoffTargetInfo.getPECoffArch()) {
|
|
+ case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64:
|
|
+ if (relocType == RelocType.JAVA_CALL_DIRECT ||
|
|
+ relocType == RelocType.FOREIGN_CALL_INDIRECT_GOT) {
|
|
+ pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_REL32;
|
|
+ } else if (relocType == RelocType.STUB_CALL_DIRECT) {
|
|
+ pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_REL32;
|
|
+ } else if (relocType == RelocType.JAVA_CALL_INDIRECT) {
|
|
+ pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_ABSOLUTE;
|
|
+ } else if (relocType == RelocType.METASPACE_GOT_REFERENCE ||
|
|
+ relocType == RelocType.EXTERNAL_PLT_TO_GOT) {
|
|
+ pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_REL32;
|
|
+ } else if (relocType == RelocType.EXTERNAL_GOT_TO_PLT) {
|
|
+ pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_ADDR64;
|
|
+ } else {
|
|
+ assert false : "Unhandled relocation type: " + relocType;
|
|
+ }
|
|
+ break;
|
|
+ default:
|
|
+ System.out.println("Relocation Type mapping: Unhandled architecture");
|
|
+ }
|
|
+ return pecoffRelocType;
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoff.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoff.java
|
|
new file mode 100644
|
|
index 000000000..1521c2e20
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoff.java
|
|
@@ -0,0 +1,207 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.binformat.pecoff;
|
|
+
|
|
+/**
|
|
+ *
|
|
+ * Support for the creation of Coff files. Current support is limited to 64 bit x86_64.
|
|
+ *
|
|
+ */
|
|
+
|
|
+final class PECoff {
|
|
+ //@formatter:off
|
|
+ /**
|
|
+ * IMAGE_FILE_HEADER structure defines.
|
|
+ */
|
|
+ enum IMAGE_FILE_HEADER {
|
|
+ Machine(0, 2),
|
|
+ NumberOfSections(2, 2),
|
|
+ TimeDateStamp(4, 4),
|
|
+ PointerToSymbolTable(8, 4),
|
|
+ NumberOfSymbols(12, 4),
|
|
+ SizeOfOptionalHeader(16, 2),
|
|
+ Characteristics(18, 2);
|
|
+
|
|
+ final int off;
|
|
+ final int sz;
|
|
+
|
|
+ IMAGE_FILE_HEADER(int offset, int size) {
|
|
+ this.off = offset;
|
|
+ this.sz = size;
|
|
+ }
|
|
+
|
|
+ static int totalsize = 20;
|
|
+
|
|
+ /**
|
|
+ * IMAGE_FILE_HEADER defines
|
|
+ */
|
|
+
|
|
+ /**
|
|
+ * Machine.
|
|
+ */
|
|
+ static final char IMAGE_FILE_MACHINE_UNKNOWN = 0x0;
|
|
+ static final char IMAGE_FILE_MACHINE_AMD64 = 0x8664;
|
|
+
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * IMAGE_SECTION_HEADER structure defines.
|
|
+ */
|
|
+ enum IMAGE_SECTION_HEADER {
|
|
+ Name(0, 8),
|
|
+ PhysicalAddress(8, 4),
|
|
+ VirtualSize(8, 4),
|
|
+ VirtualAddress(12, 4),
|
|
+ SizeOfRawData(16, 4),
|
|
+ PointerToRawData(20, 4),
|
|
+ PointerToRelocations(24, 4),
|
|
+ PointerToLinenumbers(28, 4),
|
|
+ NumberOfRelocations(32, 2),
|
|
+ NumberOfLinenumbers(34, 2),
|
|
+ Characteristics(36, 4);
|
|
+
|
|
+ final int off;
|
|
+ final int sz;
|
|
+
|
|
+ IMAGE_SECTION_HEADER(int offset, int size) {
|
|
+ this.off = offset;
|
|
+ this.sz = size;
|
|
+ }
|
|
+
|
|
+ static int totalsize = 40;
|
|
+
|
|
+ /**
|
|
+ * IMAGE_SECTION_HEADER defines
|
|
+ */
|
|
+
|
|
+ /**
|
|
+ * Characteristics.
|
|
+ */
|
|
+ static final int IMAGE_SCN_CNT_CODE = 0x20;
|
|
+ static final int IMAGE_SCN_CNT_INITIALIZED_DATA = 0x40;
|
|
+ static final int IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x80;
|
|
+ static final int IMAGE_SCN_LNK_COMDAT = 0x1000;
|
|
+ static final int IMAGE_SCN_LNK_INFO = 0x200;
|
|
+ static final int IMAGE_SCN_LNK_REMOVE = 0x800;
|
|
+
|
|
+ static final int IMAGE_SCN_ALIGN_1BYTES = 0x100000;
|
|
+ static final int IMAGE_SCN_ALIGN_2BYTES = 0x200000;
|
|
+ static final int IMAGE_SCN_ALIGN_4BYTES = 0x300000;
|
|
+ static final int IMAGE_SCN_ALIGN_8BYTES = 0x400000;
|
|
+ static final int IMAGE_SCN_ALIGN_16BYTES = 0x500000;
|
|
+ static final int IMAGE_SCN_ALIGN_32BYTES = 0x600000;
|
|
+ static final int IMAGE_SCN_ALIGN_64BYTES = 0x700000;
|
|
+ static final int IMAGE_SCN_ALIGN_128BYTES = 0x800000;
|
|
+ static final int IMAGE_SCN_ALIGN_256BYTES = 0x900000;
|
|
+ static final int IMAGE_SCN_ALIGN_512BYTES = 0xa00000;
|
|
+ static final int IMAGE_SCN_ALIGN_1024BYTES = 0xb00000;
|
|
+ static final int IMAGE_SCN_ALIGN_MASK = 0xf00000;
|
|
+ static final int IMAGE_SCN_ALIGN_SHIFT = 20;
|
|
+
|
|
+ static final int IMAGE_SCN_LNK_NRELOC_OVFL = 0x01000000;
|
|
+
|
|
+ static final int IMAGE_SCN_MEM_SHARED = 0x10000000;
|
|
+ static final int IMAGE_SCN_MEM_EXECUTE = 0x20000000;
|
|
+ static final int IMAGE_SCN_MEM_READ = 0x40000000;
|
|
+ static final int IMAGE_SCN_MEM_WRITE = 0x80000000;
|
|
+
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Symbol table entry definitions.
|
|
+ *
|
|
+ * IMAGE_SYMBOL structure defines
|
|
+ */
|
|
+ enum IMAGE_SYMBOL {
|
|
+ ShortName(0, 8),
|
|
+ Short(0, 4),
|
|
+ Long(4, 4),
|
|
+ Value(8, 4),
|
|
+ SectionNumber(12, 2),
|
|
+ Type(14, 2),
|
|
+ StorageClass(16, 1),
|
|
+ NumberOfAuxSymbols(17, 1);
|
|
+
|
|
+ final int off;
|
|
+ final int sz;
|
|
+
|
|
+ IMAGE_SYMBOL(int offset, int size) {
|
|
+ this.off = offset;
|
|
+ this.sz = size;
|
|
+ }
|
|
+
|
|
+ static int totalsize = 18;
|
|
+
|
|
+ /**
|
|
+ * Type.
|
|
+ */
|
|
+ static final int IMAGE_SYM_DTYPE_NONE = 0x0;
|
|
+ static final int IMAGE_SYM_DTYPE_FUNCTION = 0x20;
|
|
+
|
|
+ /**
|
|
+ * StorageClass.
|
|
+ */
|
|
+ static final int IMAGE_SYM_CLASS_NULL = 0x0;
|
|
+ static final int IMAGE_SYM_CLASS_EXTERNAL = 0x2;
|
|
+ static final int IMAGE_SYM_CLASS_STATIC = 0x3;
|
|
+ static final int IMAGE_SYM_CLASS_LABEL = 0x6;
|
|
+
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * IMAGE_RELOCATION structure defines.
|
|
+ */
|
|
+ enum IMAGE_RELOCATION {
|
|
+ VirtualAddress(0, 4),
|
|
+ SymbolTableIndex(4, 4),
|
|
+ Type(8, 2);
|
|
+
|
|
+ final int off;
|
|
+ final int sz;
|
|
+
|
|
+ IMAGE_RELOCATION(int offset, int size) {
|
|
+ this.off = offset;
|
|
+ this.sz = size;
|
|
+ }
|
|
+
|
|
+ static int totalsize = 10;
|
|
+
|
|
+ /**
|
|
+ * Relocation types.
|
|
+ */
|
|
+ static final int IMAGE_REL_AMD64_ABSOLUTE = 0x0;
|
|
+ static final int IMAGE_REL_AMD64_ADDR32 = 0x2;
|
|
+ static final int IMAGE_REL_AMD64_ADDR64 = 0x1;
|
|
+ static final int IMAGE_REL_AMD64_REL32 = 0x4;
|
|
+ static final int IMAGE_REL_AMD64_REL32_1 = 0x5;
|
|
+ static final int IMAGE_REL_AMD64_REL32_2 = 0x6;
|
|
+ static final int IMAGE_REL_AMD64_REL32_3 = 0x7;
|
|
+ static final int IMAGE_REL_AMD64_REL32_4 = 0x8;
|
|
+ static final int IMAGE_REL_AMD64_REL32_5 = 0x9;
|
|
+
|
|
+ }
|
|
+ //@formatter:on
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffByteBuffer.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffByteBuffer.java
|
|
new file mode 100644
|
|
index 000000000..835642314
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffByteBuffer.java
|
|
@@ -0,0 +1,40 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.binformat.pecoff;
|
|
+
|
|
+import java.nio.ByteBuffer;
|
|
+import java.nio.ByteOrder;
|
|
+
|
|
+final class PECoffByteBuffer {
|
|
+
|
|
+ static ByteBuffer allocate(int size) {
|
|
+ ByteBuffer buf = ByteBuffer.allocate(size);
|
|
+ // Only support Little Endian on Windows
|
|
+ buf.order(ByteOrder.LITTLE_ENDIAN);
|
|
+ return (buf);
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffContainer.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffContainer.java
|
|
new file mode 100644
|
|
index 000000000..21ad80270
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffContainer.java
|
|
@@ -0,0 +1,89 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.binformat.pecoff;
|
|
+
|
|
+import java.io.File;
|
|
+import java.io.FileOutputStream;
|
|
+
|
|
+final class PECoffContainer {
|
|
+
|
|
+ private final File outputFile;
|
|
+ private FileOutputStream outputStream;
|
|
+ private long fileOffset;
|
|
+
|
|
+ PECoffContainer(String fileName) {
|
|
+
|
|
+ outputFile = new File(fileName);
|
|
+ if (outputFile.exists()) {
|
|
+ outputFile.delete();
|
|
+ }
|
|
+
|
|
+ try {
|
|
+ outputStream = new FileOutputStream(outputFile);
|
|
+ } catch (Exception e) {
|
|
+ System.out.println("PECoffContainer: Can't create file " + fileName);
|
|
+ }
|
|
+ fileOffset = 0;
|
|
+ }
|
|
+
|
|
+ void close() {
|
|
+ try {
|
|
+ outputStream.close();
|
|
+ } catch (Exception e) {
|
|
+ System.out.println("PECoffContainer: close failed");
|
|
+ }
|
|
+ }
|
|
+
|
|
+ void writeBytes(byte[] bytes) {
|
|
+ if (bytes == null) {
|
|
+ return;
|
|
+ }
|
|
+ try {
|
|
+ outputStream.write(bytes);
|
|
+ } catch (Exception e) {
|
|
+ System.out.println("PECoffContainer: writeBytes failed");
|
|
+ }
|
|
+ fileOffset += bytes.length;
|
|
+ }
|
|
+
|
|
+ // Write bytes to output file with up front alignment padding
|
|
+ void writeBytes(byte[] bytes, int alignment) {
|
|
+ if (bytes == null) {
|
|
+ return;
|
|
+ }
|
|
+ try {
|
|
+ // Pad to alignment
|
|
+ while ((fileOffset & (alignment - 1)) != 0) {
|
|
+ outputStream.write(0);
|
|
+ fileOffset++;
|
|
+ }
|
|
+ outputStream.write(bytes);
|
|
+ } catch (Exception e) {
|
|
+ System.out.println("PECoffContainer: writeBytes failed");
|
|
+ }
|
|
+ fileOffset += bytes.length;
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffHeader.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffHeader.java
|
|
new file mode 100644
|
|
index 000000000..411fcb47e
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffHeader.java
|
|
@@ -0,0 +1,65 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.binformat.pecoff;
|
|
+
|
|
+import java.nio.ByteBuffer;
|
|
+
|
|
+import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_FILE_HEADER;
|
|
+
|
|
+final class PECoffHeader {
|
|
+ private final ByteBuffer header;
|
|
+
|
|
+ PECoffHeader() {
|
|
+ header = PECoffByteBuffer.allocate(IMAGE_FILE_HEADER.totalsize);
|
|
+
|
|
+ header.putChar(IMAGE_FILE_HEADER.Machine.off, IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64);
|
|
+ header.putInt(IMAGE_FILE_HEADER.TimeDateStamp.off, (int) (System.currentTimeMillis() / 1000));
|
|
+ header.putInt(IMAGE_FILE_HEADER.PointerToSymbolTable.off, 0);
|
|
+ header.putInt(IMAGE_FILE_HEADER.NumberOfSymbols.off, 0);
|
|
+ header.putChar(IMAGE_FILE_HEADER.SizeOfOptionalHeader.off, (char) 0);
|
|
+ header.putChar(IMAGE_FILE_HEADER.Characteristics.off, (char) 0);
|
|
+
|
|
+ }
|
|
+
|
|
+ // Update header with the number of total sections
|
|
+ void setSectionCount(int count) {
|
|
+ header.putChar(IMAGE_FILE_HEADER.NumberOfSections.off, (char) count);
|
|
+ }
|
|
+
|
|
+ // Update header with the number of total symbols
|
|
+ void setSymbolCount(int count) {
|
|
+ header.putInt(IMAGE_FILE_HEADER.NumberOfSymbols.off, count);
|
|
+ }
|
|
+
|
|
+ // Update header with the offset of symbol table
|
|
+ void setSymbolOff(int offset) {
|
|
+ header.putInt(IMAGE_FILE_HEADER.PointerToSymbolTable.off, offset);
|
|
+ }
|
|
+
|
|
+ byte[] getArray() {
|
|
+ return header.array();
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffRelocEntry.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffRelocEntry.java
|
|
new file mode 100644
|
|
index 000000000..cc4236de5
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffRelocEntry.java
|
|
@@ -0,0 +1,47 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.binformat.pecoff;
|
|
+
|
|
+import java.nio.ByteBuffer;
|
|
+
|
|
+import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_RELOCATION;
|
|
+
|
|
+final class PECoffRelocEntry {
|
|
+ private final ByteBuffer entry;
|
|
+
|
|
+ PECoffRelocEntry(int offset, int symno, int type) {
|
|
+
|
|
+ entry = PECoffByteBuffer.allocate(IMAGE_RELOCATION.totalsize);
|
|
+
|
|
+ entry.putInt(IMAGE_RELOCATION.VirtualAddress.off, offset);
|
|
+ entry.putInt(IMAGE_RELOCATION.SymbolTableIndex.off, symno);
|
|
+ entry.putChar(IMAGE_RELOCATION.Type.off, (char) type);
|
|
+ }
|
|
+
|
|
+ byte[] getArray() {
|
|
+ return entry.array();
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffRelocTable.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffRelocTable.java
|
|
new file mode 100644
|
|
index 000000000..b825c70dd
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffRelocTable.java
|
|
@@ -0,0 +1,86 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.binformat.pecoff;
|
|
+
|
|
+import java.nio.ByteBuffer;
|
|
+import java.util.ArrayList;
|
|
+
|
|
+import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_RELOCATION;
|
|
+
|
|
+final class PECoffRelocTable {
|
|
+ ArrayList<ArrayList<PECoffRelocEntry>> relocEntries;
|
|
+
|
|
+ PECoffRelocTable(int numsects) {
|
|
+ relocEntries = new ArrayList<>(numsects);
|
|
+ for (int i = 0; i < numsects; i++) {
|
|
+ relocEntries.add(new ArrayList<PECoffRelocEntry>());
|
|
+ }
|
|
+ }
|
|
+
|
|
+ void createRelocationEntry(int sectindex, int offset, int symno, int type) {
|
|
+ PECoffRelocEntry entry = new PECoffRelocEntry(offset, symno, type);
|
|
+ relocEntries.get(sectindex).add(entry);
|
|
+ }
|
|
+
|
|
+ static int getAlign() {
|
|
+ return (4);
|
|
+ }
|
|
+
|
|
+ int getNumRelocs(int sectionIndex) {
|
|
+ return relocEntries.get(sectionIndex).size();
|
|
+ }
|
|
+
|
|
+ // Return the relocation entries for a single section
|
|
+ // or null if no entries added to section
|
|
+ byte[] getRelocData(int sectionIndex) {
|
|
+ ArrayList<PECoffRelocEntry> entryList = relocEntries.get(sectionIndex);
|
|
+ int entryCount = entryList.size();
|
|
+ int allocCount = entryCount;
|
|
+
|
|
+ if (entryCount == 0) {
|
|
+ return null;
|
|
+ }
|
|
+ if (entryCount > 0xFFFF) {
|
|
+ allocCount++;
|
|
+ }
|
|
+ ByteBuffer relocData = PECoffByteBuffer.allocate(allocCount * IMAGE_RELOCATION.totalsize);
|
|
+
|
|
+ // If number of relocs exceeds 65K, add the real size
|
|
+ // in a dummy first reloc entry
|
|
+ if (entryCount > 0xFFFF) {
|
|
+ PECoffRelocEntry entry = new PECoffRelocEntry(allocCount, 0, 0);
|
|
+ relocData.put(entry.getArray());
|
|
+ }
|
|
+
|
|
+ // Copy each entry to a single ByteBuffer
|
|
+ for (int i = 0; i < entryCount; i++) {
|
|
+ PECoffRelocEntry entry = entryList.get(i);
|
|
+ relocData.put(entry.getArray());
|
|
+ }
|
|
+
|
|
+ return (relocData.array());
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSection.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSection.java
|
|
new file mode 100644
|
|
index 000000000..3d3f99a26
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSection.java
|
|
@@ -0,0 +1,133 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.binformat.pecoff;
|
|
+
|
|
+import java.nio.ByteBuffer;
|
|
+
|
|
+import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_SECTION_HEADER;
|
|
+
|
|
+final class PECoffSection {
|
|
+ private final ByteBuffer section;
|
|
+ private final byte[] data;
|
|
+ private final boolean hasrelocations;
|
|
+ private final int sectionIndex;
|
|
+ private final int align;
|
|
+
|
|
+ PECoffSection(String sectName, byte[] sectData0, int sectFlags0, int sectAlign, boolean hasRelocations, int sectIndex) {
|
|
+
|
|
+ section = PECoffByteBuffer.allocate(IMAGE_SECTION_HEADER.totalsize);
|
|
+
|
|
+ // If .oop.got section is empty, VM exits since .oop.got
|
|
+ // symbol ends up as external forwarded reference.
|
|
+ byte[] sectData = sectData0;
|
|
+ if (sectData0.length == 0) {
|
|
+ sectData = new byte[8];
|
|
+ }
|
|
+
|
|
+ // Copy only Max allowed bytes to Section Entry
|
|
+ byte[] name = sectName.getBytes();
|
|
+ int max = name.length <= IMAGE_SECTION_HEADER.Name.sz ? name.length : IMAGE_SECTION_HEADER.Name.sz;
|
|
+
|
|
+ assert !(sectAlign < 1 || sectAlign > 1024 || (sectAlign & (sectAlign - 1)) != 0) : "section alignment is not valid: " + sectAlign;
|
|
+ align = sectAlign;
|
|
+
|
|
+ // Using 32 because IMAGE_SCN_ALIGN_*BYTES is value + 1
|
|
+ int sectAlignBits = (32 - Integer.numberOfLeadingZeros(align)) << IMAGE_SECTION_HEADER.IMAGE_SCN_ALIGN_SHIFT;
|
|
+ // Clear and set alignment bits
|
|
+ int sectFlags = (sectFlags0 & ~IMAGE_SECTION_HEADER.IMAGE_SCN_ALIGN_MASK) | (sectAlignBits & IMAGE_SECTION_HEADER.IMAGE_SCN_ALIGN_MASK);
|
|
+
|
|
+ section.put(name, IMAGE_SECTION_HEADER.Name.off, max);
|
|
+
|
|
+ section.putInt(IMAGE_SECTION_HEADER.VirtualSize.off, 0);
|
|
+ section.putInt(IMAGE_SECTION_HEADER.VirtualAddress.off, 0);
|
|
+ section.putInt(IMAGE_SECTION_HEADER.SizeOfRawData.off, sectData.length);
|
|
+ section.putInt(IMAGE_SECTION_HEADER.PointerToLinenumbers.off, 0);
|
|
+ section.putChar(IMAGE_SECTION_HEADER.NumberOfLinenumbers.off, (char) 0);
|
|
+
|
|
+ section.putInt(IMAGE_SECTION_HEADER.Characteristics.off, sectFlags);
|
|
+
|
|
+ data = sectData;
|
|
+ hasrelocations = hasRelocations;
|
|
+ sectionIndex = sectIndex;
|
|
+ }
|
|
+
|
|
+ long getSize() {
|
|
+ return section.getInt(IMAGE_SECTION_HEADER.SizeOfRawData.off);
|
|
+ }
|
|
+
|
|
+ int getDataAlign() {
|
|
+ return (align);
|
|
+ }
|
|
+
|
|
+ // Alignment requirements for the IMAGE_SECTION_HEADER structures
|
|
+ static int getShdrAlign() {
|
|
+ return (4);
|
|
+ }
|
|
+
|
|
+ byte[] getArray() {
|
|
+ return section.array();
|
|
+ }
|
|
+
|
|
+ byte[] getDataArray() {
|
|
+ return data;
|
|
+ }
|
|
+
|
|
+ void setOffset(long offset) {
|
|
+ section.putInt(IMAGE_SECTION_HEADER.PointerToRawData.off, (int) offset);
|
|
+ }
|
|
+
|
|
+ long getOffset() {
|
|
+ return (section.getInt(IMAGE_SECTION_HEADER.PointerToRawData.off));
|
|
+ }
|
|
+
|
|
+ void setReloff(int offset) {
|
|
+ section.putInt(IMAGE_SECTION_HEADER.PointerToRelocations.off, offset);
|
|
+ }
|
|
+
|
|
+ void setRelcount(int count) {
|
|
+ // If the number of relocs is larger than 65K, then set
|
|
+ // the overflow bit. The real count will be written to
|
|
+ // the first reloc entry for this section.
|
|
+ if (count > 0xFFFF) {
|
|
+ int flags;
|
|
+ section.putChar(IMAGE_SECTION_HEADER.NumberOfRelocations.off, (char) 0xFFFF);
|
|
+ flags = section.getInt(IMAGE_SECTION_HEADER.Characteristics.off);
|
|
+ flags |= IMAGE_SECTION_HEADER.IMAGE_SCN_LNK_NRELOC_OVFL;
|
|
+ section.putInt(IMAGE_SECTION_HEADER.Characteristics.off, flags);
|
|
+ } else {
|
|
+ section.putChar(IMAGE_SECTION_HEADER.NumberOfRelocations.off, (char) count);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ boolean hasRelocations() {
|
|
+ return hasrelocations;
|
|
+ }
|
|
+
|
|
+ int getSectionId() {
|
|
+ return sectionIndex;
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSymbol.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSymbol.java
|
|
new file mode 100644
|
|
index 000000000..105164731
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSymbol.java
|
|
@@ -0,0 +1,58 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.binformat.pecoff;
|
|
+
|
|
+import java.nio.ByteBuffer;
|
|
+
|
|
+import jdk.tools.jaotc.binformat.NativeSymbol;
|
|
+import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_SYMBOL;
|
|
+
|
|
+final class PECoffSymbol extends NativeSymbol {
|
|
+ private final ByteBuffer sym;
|
|
+
|
|
+ PECoffSymbol(int symbolindex, int strindex, byte type, byte storageclass, byte sectindex, long offset) {
|
|
+ super(symbolindex);
|
|
+ sym = PECoffByteBuffer.allocate(IMAGE_SYMBOL.totalsize);
|
|
+
|
|
+ // We don't use short names
|
|
+ sym.putInt(IMAGE_SYMBOL.Short.off, 0);
|
|
+
|
|
+ sym.putInt(IMAGE_SYMBOL.Long.off, strindex);
|
|
+ sym.putInt(IMAGE_SYMBOL.Value.off, (int) offset);
|
|
+
|
|
+ // Section indexes start at 1 but we manage the index internally
|
|
+ // as 0 relative except in this structure
|
|
+ sym.putChar(IMAGE_SYMBOL.SectionNumber.off, (char) (sectindex + 1));
|
|
+
|
|
+ sym.putChar(IMAGE_SYMBOL.Type.off, (char) type);
|
|
+ sym.put(IMAGE_SYMBOL.StorageClass.off, storageclass);
|
|
+ sym.put(IMAGE_SYMBOL.NumberOfAuxSymbols.off, (byte) 0);
|
|
+ }
|
|
+
|
|
+ byte[] getArray() {
|
|
+ return sym.array();
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSymtab.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSymtab.java
|
|
new file mode 100644
|
|
index 000000000..1e8b3ec3f
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSymtab.java
|
|
@@ -0,0 +1,150 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.binformat.pecoff;
|
|
+
|
|
+import java.nio.ByteBuffer;
|
|
+import java.nio.ByteOrder;
|
|
+import java.util.ArrayList;
|
|
+
|
|
+import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_SYMBOL;
|
|
+
|
|
+final class PECoffSymtab {
|
|
+ ArrayList<PECoffSymbol> symbols = new ArrayList<>();
|
|
+
|
|
+ /**
|
|
+ * Number of symbols added.
|
|
+ */
|
|
+ private int symbolCount;
|
|
+
|
|
+ /**
|
|
+ * String holding symbol table strings.
|
|
+ */
|
|
+ private final StringBuilder strTabContent;
|
|
+
|
|
+ /**
|
|
+ * Keeps track of bytes in string table since strTabContent.length() is number of chars, not
|
|
+ * bytes.
|
|
+ */
|
|
+ private int strTabNrOfBytes;
|
|
+
|
|
+ /**
|
|
+ * String holding Linker Directives.
|
|
+ */
|
|
+ private final StringBuilder directives;
|
|
+
|
|
+ PECoffSymtab() {
|
|
+ symbolCount = 0;
|
|
+ strTabContent = new StringBuilder();
|
|
+ directives = new StringBuilder();
|
|
+
|
|
+ // The first 4 bytes of the string table contain
|
|
+ // the length of the table (including this length field).
|
|
+ strTabNrOfBytes = 4;
|
|
+
|
|
+ // Make room for the 4 byte length field
|
|
+ strTabContent.append('\0').append('\0').append('\0').append('\0');
|
|
+
|
|
+ // Linker Directives start with 3 spaces to signify ANSI
|
|
+ directives.append(" ");
|
|
+ }
|
|
+
|
|
+ PECoffSymbol addSymbolEntry(String name, byte type, byte storageclass, byte secHdrIndex, long offset) {
|
|
+ // Get the current symbol index and append symbol name to string table.
|
|
+ int index;
|
|
+ PECoffSymbol sym;
|
|
+
|
|
+ if (name.isEmpty()) {
|
|
+ index = 0;
|
|
+ strTabContent.append('\0');
|
|
+ strTabNrOfBytes += 1;
|
|
+ sym = new PECoffSymbol(symbolCount, index, type, storageclass, secHdrIndex, offset);
|
|
+ symbols.add(sym);
|
|
+ } else {
|
|
+ int nameSize = name.getBytes().length;
|
|
+
|
|
+ // We can't trust strTabContent.length() since that is
|
|
+ // chars (UTF16), keep track of bytes on our own.
|
|
+ index = strTabNrOfBytes;
|
|
+ // strTabContent.append('_').append(name).append('\0');
|
|
+ strTabContent.append(name).append('\0');
|
|
+ strTabNrOfBytes += (nameSize + 1);
|
|
+
|
|
+ sym = new PECoffSymbol(symbolCount, index, type, storageclass, secHdrIndex, offset);
|
|
+ symbols.add(sym);
|
|
+ if (storageclass == IMAGE_SYMBOL.IMAGE_SYM_CLASS_EXTERNAL) {
|
|
+ addDirective(name, type);
|
|
+ }
|
|
+ }
|
|
+ symbolCount++;
|
|
+ return (sym);
|
|
+ }
|
|
+
|
|
+ private void addDirective(String name, byte type) {
|
|
+ directives.append("/EXPORT:" + name);
|
|
+ if (type != IMAGE_SYMBOL.IMAGE_SYM_DTYPE_FUNCTION) {
|
|
+ directives.append(",DATA");
|
|
+ }
|
|
+ directives.append(" ");
|
|
+ }
|
|
+
|
|
+ int getSymtabCount() {
|
|
+ return symbolCount;
|
|
+ }
|
|
+
|
|
+ int getStrtabSize() {
|
|
+ return strTabNrOfBytes;
|
|
+ }
|
|
+
|
|
+ // Return a byte array that contains the symbol table entries
|
|
+ byte[] getSymtabArray() {
|
|
+ ByteBuffer symtabData = PECoffByteBuffer.allocate(symbolCount * IMAGE_SYMBOL.totalsize);
|
|
+ symtabData.order(ByteOrder.LITTLE_ENDIAN);
|
|
+
|
|
+ // copy all symbols
|
|
+ for (int i = 0; i < symbolCount; i++) {
|
|
+ PECoffSymbol sym = symbols.get(i);
|
|
+ byte[] arr = sym.getArray();
|
|
+ symtabData.put(arr);
|
|
+ }
|
|
+ return (symtabData.array());
|
|
+ }
|
|
+
|
|
+ // Return the string table array
|
|
+ byte[] getStrtabArray() {
|
|
+ byte[] strs = strTabContent.toString().getBytes();
|
|
+
|
|
+ // Update the size of the string table
|
|
+ ByteBuffer buff = ByteBuffer.wrap(strs);
|
|
+ buff.order(ByteOrder.LITTLE_ENDIAN);
|
|
+ buff.putInt(0, strTabNrOfBytes);
|
|
+
|
|
+ return (strs);
|
|
+ }
|
|
+
|
|
+ byte[] getDirectiveArray() {
|
|
+ return (directives.toString().getBytes());
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffTargetInfo.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffTargetInfo.java
|
|
new file mode 100644
|
|
index 000000000..44288593c
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffTargetInfo.java
|
|
@@ -0,0 +1,74 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.binformat.pecoff;
|
|
+
|
|
+import java.nio.ByteOrder;
|
|
+import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_FILE_HEADER;
|
|
+
|
|
+/**
|
|
+ * Class that abstracts MACH-O target details.
|
|
+ *
|
|
+ */
|
|
+final class PECoffTargetInfo {
|
|
+ /**
|
|
+ * Target architecture.
|
|
+ */
|
|
+ private static final char arch;
|
|
+
|
|
+ /**
|
|
+ * Target OS string.
|
|
+ */
|
|
+ private static String osName;
|
|
+
|
|
+ static {
|
|
+ // Find the target arch details
|
|
+ String archStr = System.getProperty("os.arch").toLowerCase();
|
|
+ if (ByteOrder.nativeOrder() != ByteOrder.LITTLE_ENDIAN) {
|
|
+ System.out.println("Only Little Endian byte order supported!");
|
|
+ }
|
|
+
|
|
+ if (archStr.equals("amd64") || archStr.equals("x86_64")) {
|
|
+ arch = IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64;
|
|
+ } else {
|
|
+ System.out.println("Unsupported architecture " + archStr);
|
|
+ arch = IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_UNKNOWN;
|
|
+ }
|
|
+
|
|
+ osName = System.getProperty("os.name").toLowerCase();
|
|
+ if (!osName.contains("windows")) {
|
|
+ System.out.println("Unsupported Operating System " + osName);
|
|
+ osName = "Unknown";
|
|
+ }
|
|
+ }
|
|
+
|
|
+ static char getPECoffArch() {
|
|
+ return arch;
|
|
+ }
|
|
+
|
|
+ static String getOsName() {
|
|
+ return osName;
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/HelloWorld.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/HelloWorld.java
|
|
new file mode 100644
|
|
index 000000000..ffedd0dee
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/HelloWorld.java
|
|
@@ -0,0 +1,31 @@
|
|
+/*
|
|
+ * Copyright (c) 2018, 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
|
|
+ * 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.test;
|
|
+
|
|
+public class HelloWorld {
|
|
+ public static void main(String[] args) {
|
|
+ System.out.println("Hello, world!");
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/NativeOrderOutputStreamTest.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/NativeOrderOutputStreamTest.java
|
|
new file mode 100644
|
|
index 000000000..13ee4b1b2
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/NativeOrderOutputStreamTest.java
|
|
@@ -0,0 +1,136 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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
|
|
+ * @modules jdk.aot/jdk.tools.jaotc.utils
|
|
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.tools.jaotc.test.NativeOrderOutputStreamTest
|
|
+ */
|
|
+
|
|
+
|
|
+
|
|
+package jdk.tools.jaotc.test;
|
|
+
|
|
+import java.nio.ByteBuffer;
|
|
+import java.nio.ByteOrder;
|
|
+
|
|
+import org.junit.Assert;
|
|
+import org.junit.Test;
|
|
+
|
|
+import jdk.tools.jaotc.utils.NativeOrderOutputStream;
|
|
+
|
|
+public class NativeOrderOutputStreamTest {
|
|
+
|
|
+ @Test
|
|
+ public void shouldAdd4BytesForInt() {
|
|
+ NativeOrderOutputStream target = new NativeOrderOutputStream();
|
|
+ target.putInt(5);
|
|
+ Assert.assertEquals(4, target.position());
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void shouldAdd8BytesForLong() {
|
|
+ NativeOrderOutputStream target = new NativeOrderOutputStream();
|
|
+ target.putLong(8);
|
|
+ Assert.assertEquals(8, target.position());
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void shouldHaveCorrectSizeBeforePatch() {
|
|
+ NativeOrderOutputStream target = new NativeOrderOutputStream();
|
|
+ target.patchableInt();
|
|
+ Assert.assertEquals(4, target.position());
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void shouldHaveCorrectSizeAfterPatch() {
|
|
+ NativeOrderOutputStream target = new NativeOrderOutputStream();
|
|
+ NativeOrderOutputStream.PatchableInt patchableInt = target.patchableInt();
|
|
+ patchableInt.set(12);
|
|
+ Assert.assertEquals(4, target.position());
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void shouldSetCorrectValueInPatch() {
|
|
+ NativeOrderOutputStream target = new NativeOrderOutputStream();
|
|
+ NativeOrderOutputStream.PatchableInt patchableInt = target.patchableInt();
|
|
+ patchableInt.set(42);
|
|
+ Assert.assertEquals(42, getInt(target, 0));
|
|
+ }
|
|
+
|
|
+ private static int getInt(NativeOrderOutputStream target, int pos) {
|
|
+ ByteBuffer buffer = ByteBuffer.wrap(target.array());
|
|
+ buffer.order(ByteOrder.nativeOrder());
|
|
+ return buffer.getInt(pos);
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void shouldPutArrayCorrectly() {
|
|
+ NativeOrderOutputStream target = new NativeOrderOutputStream();
|
|
+ target.put(new byte[]{42, 5, 43, 44});
|
|
+ Assert.assertEquals(4, target.position());
|
|
+ Assert.assertEquals(42, target.array()[0]);
|
|
+ Assert.assertEquals(4, target.position());
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void shouldOnlyPatchSlot() {
|
|
+ NativeOrderOutputStream target = new NativeOrderOutputStream();
|
|
+ NativeOrderOutputStream.PatchableInt patchableInt = target.patchableInt();
|
|
+ target.putInt(7);
|
|
+ patchableInt.set(39);
|
|
+ Assert.assertEquals(39, getInt(target, 0));
|
|
+ Assert.assertEquals(7, getInt(target, 4));
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void shouldBeAbleToPatchAnywhere() {
|
|
+ NativeOrderOutputStream target = new NativeOrderOutputStream();
|
|
+ target.putInt(19);
|
|
+ NativeOrderOutputStream.PatchableInt patchableInt = target.patchableInt();
|
|
+ patchableInt.set(242);
|
|
+
|
|
+ Assert.assertEquals(19, getInt(target, 0));
|
|
+ Assert.assertEquals(242, getInt(target, 4));
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void shouldHavePatchableAtRightOffset() {
|
|
+ NativeOrderOutputStream target = new NativeOrderOutputStream();
|
|
+ target.putInt(27);
|
|
+ Assert.assertEquals(4, target.position());
|
|
+ NativeOrderOutputStream.PatchableInt patchableInt = target.patchableInt();
|
|
+ Assert.assertEquals(4, patchableInt.position());
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void shouldAlign() {
|
|
+ NativeOrderOutputStream target = new NativeOrderOutputStream();
|
|
+ target.putInt(9);
|
|
+ target.align(16);
|
|
+ target.put(new byte[]{3});
|
|
+ target.align(8);
|
|
+ Assert.assertEquals(24, target.position());
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/ClassSearchTest.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/ClassSearchTest.java
|
|
new file mode 100644
|
|
index 000000000..b2358dff2
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/ClassSearchTest.java
|
|
@@ -0,0 +1,219 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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
|
|
+ * @modules jdk.aot/jdk.tools.jaotc
|
|
+ * jdk.aot/jdk.tools.jaotc.collect
|
|
+ * @run junit/othervm jdk.tools.jaotc.test.collect.ClassSearchTest
|
|
+ */
|
|
+
|
|
+
|
|
+
|
|
+package jdk.tools.jaotc.test.collect;
|
|
+
|
|
+import java.util.ArrayList;
|
|
+import java.util.HashSet;
|
|
+import java.util.List;
|
|
+import java.util.Set;
|
|
+import java.util.function.BiConsumer;
|
|
+import java.util.function.BiFunction;
|
|
+
|
|
+import org.junit.Assert;
|
|
+import org.junit.Test;
|
|
+
|
|
+import jdk.tools.jaotc.LoadedClass;
|
|
+import jdk.tools.jaotc.collect.ClassSearch;
|
|
+import jdk.tools.jaotc.collect.ClassSource;
|
|
+import jdk.tools.jaotc.collect.SearchFor;
|
|
+import jdk.tools.jaotc.collect.SearchPath;
|
|
+import jdk.tools.jaotc.collect.SourceProvider;
|
|
+
|
|
+public class ClassSearchTest {
|
|
+ @Test(expected = InternalError.class)
|
|
+ public void itShouldThrowExceptionIfNoProvidersAvailable() {
|
|
+ ClassSearch target = new ClassSearch();
|
|
+ SearchPath searchPath = new SearchPath();
|
|
+ target.search(list(new SearchFor("foo")), searchPath);
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldFindAProviderForEachEntry() {
|
|
+ Set<String> searched = new HashSet<>();
|
|
+ ClassSearch target = new ClassSearch();
|
|
+ target.addProvider(provider("", (name, searchPath) -> {
|
|
+ searched.add(name);
|
|
+ return new NoopSource();
|
|
+ }));
|
|
+ target.search(searchForList("foo", "bar", "foobar"), null);
|
|
+ Assert.assertEquals(hashset("foo", "bar", "foobar"), searched);
|
|
+ }
|
|
+
|
|
+ private static SourceProvider provider(String supports, BiFunction<String, SearchPath, ClassSource> fn) {
|
|
+ return new SourceProvider() {
|
|
+ @Override
|
|
+ public ClassSource findSource(String name, SearchPath searchPath) {
|
|
+ return fn.apply(name, searchPath);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean supports(String type) {
|
|
+ return supports.equals(type);
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldOnlySearchSupportedProvidersForKnownType() {
|
|
+ Set<String> visited = new HashSet<>();
|
|
+ ClassSearch target = new ClassSearch();
|
|
+
|
|
+ target.addProvider(provider("jar", (name, searchPath) -> {
|
|
+ visited.add("jar");
|
|
+ return null;
|
|
+ }));
|
|
+
|
|
+ target.addProvider(provider("dir", (name, searchPath) -> {
|
|
+ visited.add("dir");
|
|
+ return null;
|
|
+ }));
|
|
+
|
|
+ try {
|
|
+ target.search(list(new SearchFor("some", "dir")), null);
|
|
+ } catch (InternalError e) {
|
|
+ // throws because no provider gives a source
|
|
+ }
|
|
+
|
|
+ Assert.assertEquals(hashset("dir"), visited);
|
|
+ }
|
|
+
|
|
+ @Test(expected = InternalError.class)
|
|
+ public void itShouldThrowErrorIfMultipleSourcesAreAvailable() {
|
|
+ ClassSearch target = new ClassSearch();
|
|
+ target.addProvider(provider("", (name, searchPath) -> consumer -> Assert.fail()));
|
|
+ target.addProvider(provider("", (name, searchPath) -> consumer -> Assert.fail()));
|
|
+
|
|
+ target.search(searchForList("somethign"), null);
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldSearchAllProvidersForUnknownType() {
|
|
+ Set<String> visited = new HashSet<>();
|
|
+ ClassSearch target = new ClassSearch();
|
|
+ target.addProvider(provider("", (name, searchPath) -> {
|
|
+ visited.add("1");
|
|
+ return null;
|
|
+ }));
|
|
+ target.addProvider(provider("", (name, searchPath) -> {
|
|
+ visited.add("2");
|
|
+ return null;
|
|
+ }));
|
|
+
|
|
+ try {
|
|
+ target.search(searchForList("foo"), null);
|
|
+ } catch (InternalError e) {
|
|
+ // throws because no provider gives a source
|
|
+ }
|
|
+
|
|
+ Assert.assertEquals(hashset("1", "2"), visited);
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldTryToLoadSaidClassFromClassLoader() {
|
|
+ Set<String> loaded = new HashSet<>();
|
|
+
|
|
+ ClassSearch target = new ClassSearch();
|
|
+ target.addProvider(new SourceProvider() {
|
|
+ @Override
|
|
+ public boolean supports(String type) {
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public ClassSource findSource(String name, SearchPath searchPath) {
|
|
+ return new ClassSource() {
|
|
+ @Override
|
|
+ public void eachClass(BiConsumer<String, ClassLoader> consumer) {
|
|
+ consumer.accept("foo.Bar", new ClassLoader() {
|
|
+ @Override
|
|
+ public Class<?> loadClass(String nm) throws ClassNotFoundException {
|
|
+ loaded.add(nm);
|
|
+ return null;
|
|
+ }
|
|
+ });
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ });
|
|
+
|
|
+ java.util.List<LoadedClass> search = target.search(searchForList("/tmp/something"), null);
|
|
+ Assert.assertEquals(list(new LoadedClass("foo.Bar", null)), search);
|
|
+ }
|
|
+
|
|
+ @Test(expected = InternalError.class)
|
|
+ public void itShouldThrowInternalErrorWhenClassLoaderFails() {
|
|
+ ClassLoader classLoader = new ClassLoader() {
|
|
+ @Override
|
|
+ public Class<?> loadClass(String name1) throws ClassNotFoundException {
|
|
+ throw new ClassNotFoundException("failed to find " + name1);
|
|
+ }
|
|
+ };
|
|
+
|
|
+ ClassSearch target = new ClassSearch();
|
|
+ target.addProvider(provider("", (name, searchPath) -> consumer -> consumer.accept("foo.Bar", classLoader)));
|
|
+ target.search(searchForList("foobar"), null);
|
|
+ }
|
|
+
|
|
+ private static List<SearchFor> searchForList(String... entries) {
|
|
+ List<SearchFor> list = new ArrayList<>();
|
|
+ for (String entry : entries) {
|
|
+ list.add(new SearchFor(entry));
|
|
+ }
|
|
+ return list;
|
|
+ }
|
|
+
|
|
+ @SafeVarargs
|
|
+ private static <T> List<T> list(T... entries) {
|
|
+ List<T> list = new ArrayList<>();
|
|
+ for (T entry : entries) {
|
|
+ list.add(entry);
|
|
+ }
|
|
+ return list;
|
|
+ }
|
|
+
|
|
+ @SafeVarargs
|
|
+ private static <T> Set<T> hashset(T... entries) {
|
|
+ Set<T> set = new HashSet<>();
|
|
+ for (T entry : entries) {
|
|
+ set.add(entry);
|
|
+ }
|
|
+ return set;
|
|
+ }
|
|
+
|
|
+ private static class NoopSource implements ClassSource {
|
|
+ @Override
|
|
+ public void eachClass(BiConsumer<String, ClassLoader> consumer) {
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/ClassSourceTest.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/ClassSourceTest.java
|
|
new file mode 100644
|
|
index 000000000..217ef28a2
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/ClassSourceTest.java
|
|
@@ -0,0 +1,66 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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
|
|
+ * @modules jdk.aot/jdk.tools.jaotc
|
|
+ * jdk.aot/jdk.tools.jaotc.collect
|
|
+ * @build jdk.tools.jaotc.test.collect.Utils
|
|
+ * @run junit/othervm jdk.tools.jaotc.test.collect.ClassSourceTest
|
|
+ */
|
|
+
|
|
+
|
|
+
|
|
+package jdk.tools.jaotc.test.collect;
|
|
+
|
|
+import org.junit.Assert;
|
|
+import org.junit.Test;
|
|
+
|
|
+import java.nio.file.Paths;
|
|
+
|
|
+import static jdk.tools.jaotc.collect.ClassSource.makeClassName;
|
|
+
|
|
+import static jdk.tools.jaotc.test.collect.Utils.getpath;
|
|
+
|
|
+public class ClassSourceTest {
|
|
+ @Test(expected = IllegalArgumentException.class)
|
|
+ public void itShouldThrowExceptionIfPathDoesntEndWithClass() {
|
|
+ makeClassName(Paths.get("Bar.clazz"));
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldReplaceSlashesWithDots() {
|
|
+ Assert.assertEquals("foo.Bar", makeClassName(getpath("foo/Bar.class")));
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldStripLeadingSlash() {
|
|
+ Assert.assertEquals("Hello", makeClassName(getpath("/Hello.class")));
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldReplaceMultipleDots() {
|
|
+ Assert.assertEquals("some.foo.bar.FooBar", makeClassName(getpath("/some/foo/bar/FooBar.class")));
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/FakeFileSupport.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/FakeFileSupport.java
|
|
new file mode 100644
|
|
index 000000000..fc7249e3f
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/FakeFileSupport.java
|
|
@@ -0,0 +1,114 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.test.collect;
|
|
+
|
|
+import java.net.MalformedURLException;
|
|
+import java.nio.file.Path;
|
|
+import java.util.HashSet;
|
|
+import java.util.Set;
|
|
+
|
|
+import jdk.tools.jaotc.collect.FileSupport;
|
|
+
|
|
+public class FakeFileSupport extends FileSupport {
|
|
+ private final Set<String> exists = new HashSet<>();
|
|
+ private final Set<String> directories = new HashSet<>();
|
|
+
|
|
+ private final Set<String> checkedExists = new HashSet<>();
|
|
+ private final Set<String> checkedDirectory = new HashSet<>();
|
|
+ private final Set<String> checkedJarFileSystemRoots = new HashSet<>();
|
|
+ private final Set<String> classloaderPaths = new HashSet<>();
|
|
+
|
|
+ private Path jarFileSystemRoot = null;
|
|
+ private final ClassLoader classLoader;
|
|
+
|
|
+ public FakeFileSupport(Set<String> existing, Set<String> directories) {
|
|
+ this.exists.addAll(existing);
|
|
+ this.directories.addAll(directories);
|
|
+
|
|
+ classLoader = new ClassLoader() {
|
|
+ @Override
|
|
+ public Class<?> loadClass(String name) throws ClassNotFoundException {
|
|
+ return null;
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+
|
|
+ public void setJarFileSystemRoot(Path path) {
|
|
+ jarFileSystemRoot = path;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean exists(Path path) {
|
|
+ checkedExists.add(path.toString());
|
|
+ return exists.contains(path.toString());
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isDirectory(Path path) {
|
|
+ checkedDirectory.add(path.toString());
|
|
+ return directories.contains(path.toString());
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public ClassLoader createClassLoader(Path path) throws MalformedURLException {
|
|
+ classloaderPaths.add(path.toString());
|
|
+ return classLoader;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public Path getJarFileSystemRoot(Path jarFile) {
|
|
+ checkedJarFileSystemRoots.add(jarFile.toString());
|
|
+ return jarFileSystemRoot;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isAbsolute(Path entry) {
|
|
+ return entry.toString().startsWith("/");
|
|
+ }
|
|
+
|
|
+ public void addExist(String name) {
|
|
+ exists.add(name);
|
|
+ }
|
|
+
|
|
+ public void addDirectory(String name) {
|
|
+ directories.add(name);
|
|
+ }
|
|
+
|
|
+ public Set<String> getCheckedExists() {
|
|
+ return checkedExists;
|
|
+ }
|
|
+
|
|
+ public Set<String> getCheckedDirectory() {
|
|
+ return checkedDirectory;
|
|
+ }
|
|
+
|
|
+ public Set<String> getCheckedJarFileSystemRoots() {
|
|
+ return checkedJarFileSystemRoots;
|
|
+ }
|
|
+
|
|
+ public Set<String> getClassloaderPaths() {
|
|
+ return classloaderPaths;
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/FakeSearchPath.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/FakeSearchPath.java
|
|
new file mode 100644
|
|
index 000000000..ee286eb44
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/FakeSearchPath.java
|
|
@@ -0,0 +1,51 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.test.collect;
|
|
+
|
|
+import jdk.tools.jaotc.collect.SearchPath;
|
|
+
|
|
+import java.nio.file.FileSystem;
|
|
+import java.nio.file.Path;
|
|
+import java.nio.file.Paths;
|
|
+import java.util.Set;
|
|
+
|
|
+import static jdk.tools.jaotc.test.collect.Utils.set;
|
|
+
|
|
+public class FakeSearchPath extends SearchPath {
|
|
+ private Path path = null;
|
|
+ public Set<String> entries = set();
|
|
+
|
|
+ public FakeSearchPath(String name) {
|
|
+ if (name != null) {
|
|
+ path = Paths.get(name);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public Path find(FileSystem fileSystem, Path entry, String... defaults) {
|
|
+ entries.add(entry.toString());
|
|
+ return path;
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/SearchPathTest.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/SearchPathTest.java
|
|
new file mode 100644
|
|
index 000000000..3705fc894
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/SearchPathTest.java
|
|
@@ -0,0 +1,122 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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
|
|
+ * @modules jdk.aot/jdk.tools.jaotc
|
|
+ * jdk.aot/jdk.tools.jaotc.collect
|
|
+ *
|
|
+ * @build jdk.tools.jaotc.test.collect.Utils
|
|
+ * @build jdk.tools.jaotc.test.collect.FakeFileSupport
|
|
+ * @run junit/othervm jdk.tools.jaotc.test.collect.SearchPathTest
|
|
+ */
|
|
+
|
|
+
|
|
+
|
|
+package jdk.tools.jaotc.test.collect;
|
|
+
|
|
+import static jdk.tools.jaotc.test.collect.Utils.mkpath;
|
|
+import static jdk.tools.jaotc.test.collect.Utils.mkpaths;
|
|
+import static jdk.tools.jaotc.test.collect.Utils.set;
|
|
+import static org.junit.Assert.assertEquals;
|
|
+import static org.junit.Assert.assertNull;
|
|
+import static org.junit.Assert.assertSame;
|
|
+
|
|
+import java.nio.file.FileSystem;
|
|
+import java.nio.file.FileSystems;
|
|
+import java.nio.file.Path;
|
|
+import java.nio.file.Paths;
|
|
+
|
|
+import org.junit.Before;
|
|
+import org.junit.Test;
|
|
+
|
|
+import jdk.tools.jaotc.collect.SearchPath;
|
|
+
|
|
+public class SearchPathTest {
|
|
+ private FakeFileSupport fileSupport;
|
|
+ private FileSystem fs;
|
|
+
|
|
+ @Before
|
|
+ public void setUp() throws Exception {
|
|
+ fs = FileSystems.getDefault();
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldUsePathIfPathIsAbsoluteAndExisting() {
|
|
+ fileSupport = new FakeFileSupport(mkpaths("/foo"), set());
|
|
+ SearchPath target = new SearchPath(fileSupport);
|
|
+ Path foo = Paths.get(mkpath("/foo"));
|
|
+ Path result = target.find(fs, foo);
|
|
+ assertSame(result, foo);
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldReturnNullIfPathIsAbsoluteAndNonExisting() {
|
|
+ fileSupport = new FakeFileSupport(set(), set());
|
|
+ SearchPath target = new SearchPath(fileSupport);
|
|
+ Path result = target.find(fs, Paths.get(mkpath("/bar")));
|
|
+ assertNull(result);
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldUseRelativeExisting() {
|
|
+ fileSupport = new FakeFileSupport(mkpaths("hello", "tmp/hello", "search/hello"), set());
|
|
+ SearchPath target = new SearchPath(fileSupport);
|
|
+ target.add("search");
|
|
+ Path hello = Paths.get("hello");
|
|
+ Path result = target.find(fs, hello, "tmp");
|
|
+ assertSame(result, hello);
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldSearchDefaultsBeforeSearchPaths() {
|
|
+ fileSupport = new FakeFileSupport(mkpaths("bar/foobar"), set());
|
|
+ SearchPath target = new SearchPath(fileSupport);
|
|
+ Path result = target.find(fs, Paths.get("foobar"), "default1", "bar");
|
|
+ assertEquals(mkpath("bar/foobar"), result.toString());
|
|
+ assertEquals(mkpaths("foobar", "default1/foobar", "bar/foobar"), fileSupport.getCheckedExists());
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldUseSearchPathsIfNotInDefaults() {
|
|
+ fileSupport = new FakeFileSupport(mkpaths("bar/tmp/foobar"), set());
|
|
+ SearchPath target = new SearchPath(fileSupport);
|
|
+ target.add("foo/tmp", "bar/tmp");
|
|
+
|
|
+ Path result = target.find(fs, Paths.get("foobar"), "foo", "bar");
|
|
+ assertEquals(mkpath("bar/tmp/foobar"), result.toString());
|
|
+ assertEquals(mkpaths("foobar", "foo/foobar", "bar/foobar", "bar/tmp/foobar", "foo/tmp/foobar"), fileSupport.getCheckedExists());
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldReturnNullIfNoExistingPathIsFound() {
|
|
+ fileSupport = new FakeFileSupport(set(), set());
|
|
+ SearchPath target = new SearchPath(fileSupport);
|
|
+ target.add("dir1", "dir2");
|
|
+
|
|
+ Path result = target.find(fs, Paths.get("entry"), "dir3", "dir4");
|
|
+ assertNull(result);
|
|
+ assertEquals(mkpaths("entry", "dir1/entry", "dir2/entry", "dir3/entry", "dir4/entry"), fileSupport.getCheckedExists());
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/Utils.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/Utils.java
|
|
new file mode 100644
|
|
index 000000000..cd1931ce9
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/Utils.java
|
|
@@ -0,0 +1,62 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.test.collect;
|
|
+
|
|
+import java.io.File;
|
|
+import java.nio.file.Path;
|
|
+import java.nio.file.Paths;
|
|
+import java.util.HashSet;
|
|
+import java.util.Set;
|
|
+
|
|
+public class Utils {
|
|
+ @SafeVarargs
|
|
+ public static <T> Set<T> set(T... entries) {
|
|
+ Set<T> set = new HashSet<>();
|
|
+ for (T entry : entries) {
|
|
+ set.add(entry);
|
|
+ }
|
|
+ return set;
|
|
+ }
|
|
+
|
|
+ public static String mkpath(String path) {
|
|
+ return getpath(path).toString();
|
|
+ }
|
|
+
|
|
+ public static Set<String> mkpaths(String... paths) {
|
|
+ Set<String> set = new HashSet<>();
|
|
+ for (String entry : paths) {
|
|
+ set.add(mkpath(entry));
|
|
+ }
|
|
+ return set;
|
|
+ }
|
|
+
|
|
+ public static Path getpath(String path) {
|
|
+ if (path.startsWith("/") && System.getProperty("os.name").startsWith("Windows")) {
|
|
+ return Paths.get(new File(path).getAbsolutePath());
|
|
+ } else {
|
|
+ return Paths.get(path);
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/directory/DirectorySourceProviderTest.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/directory/DirectorySourceProviderTest.java
|
|
new file mode 100644
|
|
index 000000000..30ee14481
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/directory/DirectorySourceProviderTest.java
|
|
@@ -0,0 +1,91 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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
|
|
+ * @modules jdk.aot/jdk.tools.jaotc
|
|
+ * jdk.aot/jdk.tools.jaotc.collect
|
|
+ * jdk.aot/jdk.tools.jaotc.collect.directory
|
|
+ * @compile ../Utils.java
|
|
+ * @compile ../FakeFileSupport.java
|
|
+ * @run junit/othervm jdk.tools.jaotc.test.collect.directory.DirectorySourceProviderTest
|
|
+ */
|
|
+
|
|
+
|
|
+
|
|
+package jdk.tools.jaotc.test.collect.directory;
|
|
+
|
|
+import jdk.tools.jaotc.collect.ClassSource;
|
|
+import jdk.tools.jaotc.collect.directory.DirectorySourceProvider;
|
|
+import jdk.tools.jaotc.test.collect.FakeFileSupport;
|
|
+import jdk.tools.jaotc.collect.FileSupport;
|
|
+import org.junit.Assert;
|
|
+import org.junit.Test;
|
|
+
|
|
+import java.net.MalformedURLException;
|
|
+import java.nio.file.Path;
|
|
+import java.util.Set;
|
|
+
|
|
+import static jdk.tools.jaotc.test.collect.Utils.set;
|
|
+
|
|
+public class DirectorySourceProviderTest {
|
|
+ @Test
|
|
+ public void itShouldReturnNullForNonExistantPath() {
|
|
+ DirectorySourceProvider target = new DirectorySourceProvider(new FakeFileSupport(set(), set()));
|
|
+ ClassSource result = target.findSource("hello", null);
|
|
+ Assert.assertNull(result);
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldReturnNullForNonDirectory() {
|
|
+ DirectorySourceProvider target = new DirectorySourceProvider(new FakeFileSupport(set("foobar"), set()));
|
|
+ ClassSource result = target.findSource("foobar", null);
|
|
+ Assert.assertNull(result);
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldReturnNullForMalformedURI() {
|
|
+ Set<String> visited = set();
|
|
+ DirectorySourceProvider target = new DirectorySourceProvider(new FakeFileSupport(set("foobar"), set("foobar")) {
|
|
+ @Override
|
|
+ public ClassLoader createClassLoader(Path path) throws MalformedURLException {
|
|
+ visited.add("1");
|
|
+ throw new MalformedURLException("...");
|
|
+ }
|
|
+ });
|
|
+ ClassSource result = target.findSource("foobar", null);
|
|
+ Assert.assertNull(result);
|
|
+ Assert.assertEquals(set("1"), visited);
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldCreateSourceIfNameExistsAndIsADirectory() {
|
|
+ FileSupport fileSupport = new FakeFileSupport(set("foo"), set("foo"));
|
|
+ DirectorySourceProvider target = new DirectorySourceProvider(fileSupport);
|
|
+ ClassSource foo = target.findSource("foo", null);
|
|
+ Assert.assertNotNull(foo);
|
|
+ Assert.assertEquals("directory:foo", foo.toString());
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/jar/JarSourceProviderTest.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/jar/JarSourceProviderTest.java
|
|
new file mode 100644
|
|
index 000000000..86624c10d
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/jar/JarSourceProviderTest.java
|
|
@@ -0,0 +1,127 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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
|
|
+ * @modules jdk.aot/jdk.tools.jaotc
|
|
+ * jdk.aot/jdk.tools.jaotc.collect
|
|
+ * jdk.aot/jdk.tools.jaotc.collect.jar
|
|
+ * @compile ../Utils.java
|
|
+ * @compile ../FakeFileSupport.java
|
|
+ * @compile ../FakeSearchPath.java
|
|
+ *
|
|
+ * @run junit/othervm jdk.tools.jaotc.test.collect.jar.JarSourceProviderTest
|
|
+ */
|
|
+
|
|
+
|
|
+
|
|
+package jdk.tools.jaotc.test.collect.jar;
|
|
+
|
|
+import static jdk.tools.jaotc.test.collect.Utils.mkpath;
|
|
+import static jdk.tools.jaotc.test.collect.Utils.set;
|
|
+
|
|
+import java.nio.file.Path;
|
|
+import java.nio.file.Paths;
|
|
+import java.nio.file.ProviderNotFoundException;
|
|
+
|
|
+import org.junit.Assert;
|
|
+import org.junit.Before;
|
|
+import org.junit.Test;
|
|
+
|
|
+import jdk.tools.jaotc.collect.ClassSource;
|
|
+import jdk.tools.jaotc.collect.jar.JarSourceProvider;
|
|
+import jdk.tools.jaotc.test.collect.FakeFileSupport;
|
|
+import jdk.tools.jaotc.test.collect.FakeSearchPath;
|
|
+
|
|
+public class JarSourceProviderTest {
|
|
+
|
|
+ private FakeFileSupport fileSupport;
|
|
+ private JarSourceProvider target;
|
|
+
|
|
+ @Before
|
|
+ public void setUp() throws Exception {
|
|
+ fileSupport = new FakeFileSupport(set(), set());
|
|
+ target = new JarSourceProvider(fileSupport);
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldUseSearchPathToFindPath() {
|
|
+ FakeSearchPath searchPath = new FakeSearchPath(null);
|
|
+ target.findSource("hello", searchPath);
|
|
+
|
|
+ Assert.assertEquals(set("hello"), searchPath.entries);
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldReturnNullIfPathIsNull() {
|
|
+ ClassSource source = target.findSource("foobar", new FakeSearchPath(null));
|
|
+ Assert.assertNull(source);
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldReturnNullIfPathIsDirectory() {
|
|
+ fileSupport.addDirectory("hello/foobar");
|
|
+ ClassSource source = target.findSource("foobar", new FakeSearchPath("hello/foobar"));
|
|
+
|
|
+ Assert.assertNull(source);
|
|
+ Assert.assertEquals(set(mkpath("hello/foobar")), fileSupport.getCheckedDirectory());
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldReturnNullIfUnableToMakeJarFileSystem() {
|
|
+ fileSupport.setJarFileSystemRoot(null);
|
|
+ ClassSource result = target.findSource("foobar", new FakeSearchPath("foo/bar"));
|
|
+
|
|
+ Assert.assertEquals(set(mkpath("foo/bar")), fileSupport.getCheckedJarFileSystemRoots());
|
|
+ Assert.assertNull(result);
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldReturnNullIfNotValidJarProvider() {
|
|
+ fileSupport = new FakeFileSupport(set(), set()) {
|
|
+
|
|
+ @Override
|
|
+ public Path getJarFileSystemRoot(Path jarFile) {
|
|
+ super.getJarFileSystemRoot(jarFile);
|
|
+ throw new ProviderNotFoundException();
|
|
+ }
|
|
+ };
|
|
+ fileSupport.setJarFileSystemRoot(null);
|
|
+ target = new JarSourceProvider(fileSupport);
|
|
+
|
|
+ ClassSource result = target.findSource("foobar", new FakeSearchPath("foo/bar"));
|
|
+
|
|
+ Assert.assertEquals(set(mkpath("foo/bar")), fileSupport.getCheckedJarFileSystemRoots());
|
|
+ Assert.assertNull(result);
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldReturnSourceWhenAllIsValid() {
|
|
+ fileSupport.setJarFileSystemRoot(Paths.get("some/bar"));
|
|
+ ClassSource result = target.findSource("foobar", new FakeSearchPath("this/bar"));
|
|
+
|
|
+ Assert.assertEquals(set(mkpath("this/bar")), fileSupport.getClassloaderPaths());
|
|
+ Assert.assertEquals("jar:" + mkpath("this/bar"), result.toString());
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/module/ModuleSourceProviderTest.java b/src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/module/ModuleSourceProviderTest.java
|
|
new file mode 100644
|
|
index 000000000..9fab0af81
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/module/ModuleSourceProviderTest.java
|
|
@@ -0,0 +1,102 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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
|
|
+ * @modules jdk.aot/jdk.tools.jaotc
|
|
+ * jdk.aot/jdk.tools.jaotc.collect
|
|
+ * jdk.aot/jdk.tools.jaotc.collect.module
|
|
+ * @compile ../Utils.java
|
|
+ * @run junit/othervm jdk.tools.jaotc.test.collect.module.ModuleSourceProviderTest
|
|
+ */
|
|
+
|
|
+
|
|
+
|
|
+package jdk.tools.jaotc.test.collect.module;
|
|
+
|
|
+import static jdk.tools.jaotc.test.collect.Utils.mkpath;
|
|
+import static org.junit.Assert.assertEquals;
|
|
+
|
|
+import java.io.IOException;
|
|
+import java.nio.file.FileSystem;
|
|
+import java.nio.file.FileSystems;
|
|
+import java.nio.file.Path;
|
|
+import java.nio.file.Paths;
|
|
+import java.util.function.BiFunction;
|
|
+
|
|
+import org.junit.Before;
|
|
+import org.junit.Test;
|
|
+
|
|
+import jdk.tools.jaotc.collect.FileSupport;
|
|
+import jdk.tools.jaotc.collect.module.ModuleSource;
|
|
+import jdk.tools.jaotc.collect.module.ModuleSourceProvider;
|
|
+
|
|
+public class ModuleSourceProviderTest {
|
|
+ private ClassLoader classLoader;
|
|
+ private ModuleSourceProvider target;
|
|
+ private FileSupport fileSupport;
|
|
+ private BiFunction<Path, Path, Path> getSubDirectory = null;
|
|
+
|
|
+ @Before
|
|
+ public void setUp() {
|
|
+ classLoader = new FakeClassLoader();
|
|
+ fileSupport = new FileSupport() {
|
|
+
|
|
+ @Override
|
|
+ public boolean isDirectory(Path path) {
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public Path getSubDirectory(FileSystem fileSystem, Path root, Path path) throws IOException {
|
|
+ if (getSubDirectory == null) {
|
|
+ throw new IOException("Nope");
|
|
+ }
|
|
+ return getSubDirectory.apply(root, path);
|
|
+ }
|
|
+ };
|
|
+ target = new ModuleSourceProvider(FileSystems.getDefault(), classLoader, fileSupport);
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldUseFileSupport() {
|
|
+ getSubDirectory = (root, path) -> {
|
|
+ if (root.toString().equals("modules") && path.toString().equals("test.module")) {
|
|
+ return Paths.get("modules/test.module");
|
|
+ }
|
|
+ return null;
|
|
+ };
|
|
+
|
|
+ ModuleSource source = (ModuleSource) target.findSource("test.module", null);
|
|
+ assertEquals(mkpath("modules/test.module"), source.getModulePath().toString());
|
|
+ assertEquals("module:" + mkpath("modules/test.module"), source.toString());
|
|
+ }
|
|
+
|
|
+ private static class FakeClassLoader extends ClassLoader {
|
|
+ @Override
|
|
+ public Class<?> loadClass(String name) throws ClassNotFoundException {
|
|
+ return null;
|
|
+ }
|
|
+ }
|
|
+}
|
|
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
|
|
new file mode 100644
|
|
index 000000000..45ad9a594
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTBackend.java
|
|
@@ -0,0 +1,176 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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;
|
|
+
|
|
+import java.util.ListIterator;
|
|
+
|
|
+import org.graalvm.compiler.code.CompilationResult;
|
|
+import org.graalvm.compiler.core.GraalCompiler;
|
|
+import org.graalvm.compiler.core.common.CompilationIdentifier;
|
|
+import org.graalvm.compiler.debug.DebugContext;
|
|
+import org.graalvm.compiler.hotspot.HotSpotBackend;
|
|
+import org.graalvm.compiler.hotspot.HotSpotCompiledCodeBuilder;
|
|
+import org.graalvm.compiler.hotspot.meta.HotSpotInvokeDynamicPlugin;
|
|
+import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
|
|
+import org.graalvm.compiler.java.GraphBuilderPhase;
|
|
+import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory;
|
|
+import org.graalvm.compiler.lir.phases.LIRSuites;
|
|
+import org.graalvm.compiler.nodes.StructuredGraph;
|
|
+import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
|
|
+import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
|
|
+import org.graalvm.compiler.options.OptionValues;
|
|
+import org.graalvm.compiler.phases.BasePhase;
|
|
+import org.graalvm.compiler.phases.OptimisticOptimizations;
|
|
+import org.graalvm.compiler.phases.PhaseSuite;
|
|
+import org.graalvm.compiler.phases.tiers.HighTierContext;
|
|
+import org.graalvm.compiler.phases.tiers.Suites;
|
|
+
|
|
+import jdk.vm.ci.code.InstalledCode;
|
|
+import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider;
|
|
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
|
|
+import jdk.vm.ci.meta.DefaultProfilingInfo;
|
|
+import jdk.vm.ci.meta.ProfilingInfo;
|
|
+import jdk.vm.ci.meta.ResolvedJavaMethod;
|
|
+import jdk.vm.ci.meta.TriState;
|
|
+
|
|
+final class AOTBackend {
|
|
+ private final Main main;
|
|
+ private final OptionValues graalOptions;
|
|
+ private final HotSpotBackend backend;
|
|
+ private final HotSpotProviders providers;
|
|
+ private final HotSpotCodeCacheProvider codeCache;
|
|
+ private final PhaseSuite<HighTierContext> graphBuilderSuite;
|
|
+ private final HighTierContext highTierContext;
|
|
+
|
|
+ AOTBackend(Main main, OptionValues graalOptions, HotSpotBackend backend, HotSpotInvokeDynamicPlugin inokeDynamicPlugin) {
|
|
+ this.main = main;
|
|
+ this.graalOptions = graalOptions;
|
|
+ this.backend = backend;
|
|
+ providers = backend.getProviders();
|
|
+ codeCache = providers.getCodeCache();
|
|
+ graphBuilderSuite = initGraphBuilderSuite(backend, main.options.compileWithAssertions, inokeDynamicPlugin);
|
|
+ highTierContext = new HighTierContext(providers, graphBuilderSuite, OptimisticOptimizations.ALL);
|
|
+ }
|
|
+
|
|
+ PhaseSuite<HighTierContext> getGraphBuilderSuite() {
|
|
+ return graphBuilderSuite;
|
|
+ }
|
|
+
|
|
+ HotSpotBackend getBackend() {
|
|
+ return backend;
|
|
+ }
|
|
+
|
|
+ HotSpotProviders getProviders() {
|
|
+ return providers;
|
|
+ }
|
|
+
|
|
+ private Suites getSuites() {
|
|
+ // create suites every time, as we modify options for the compiler
|
|
+ return backend.getSuites().getDefaultSuites(graalOptions);
|
|
+ }
|
|
+
|
|
+ private LIRSuites getLirSuites() {
|
|
+ // create suites every time, as we modify options for the compiler
|
|
+ return backend.getSuites().getDefaultLIRSuites(graalOptions);
|
|
+ }
|
|
+
|
|
+ @SuppressWarnings("try")
|
|
+ CompilationResult compileMethod(ResolvedJavaMethod resolvedMethod, DebugContext debug) {
|
|
+ StructuredGraph graph = buildStructuredGraph(resolvedMethod, debug);
|
|
+ if (graph != null) {
|
|
+ return compileGraph(resolvedMethod, graph, debug);
|
|
+ }
|
|
+ return null;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Build a structured graph for the member.
|
|
+ *
|
|
+ * @param javaMethod method for whose code the graph is to be created
|
|
+ * @param debug
|
|
+ * @return structured graph
|
|
+ */
|
|
+ @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();
|
|
+ graphBuilderSuite.apply(graph, highTierContext);
|
|
+ return graph;
|
|
+ } catch (Throwable e) {
|
|
+ main.handleError(javaMethod, e, " (building graph)");
|
|
+ }
|
|
+ return null;
|
|
+ }
|
|
+
|
|
+ @SuppressWarnings("try")
|
|
+ private CompilationResult compileGraph(ResolvedJavaMethod resolvedMethod, StructuredGraph graph, DebugContext debug) {
|
|
+ try (DebugContext.Scope s = debug.scope("AOTCompileMethod")) {
|
|
+ ProfilingInfo profilingInfo = DefaultProfilingInfo.get(TriState.FALSE);
|
|
+
|
|
+ final boolean isImmutablePIC = true;
|
|
+ CompilationIdentifier id = new CompilationIdentifier() {
|
|
+ @Override
|
|
+ public String toString(Verbosity verbosity) {
|
|
+ return resolvedMethod.getName();
|
|
+ }
|
|
+ };
|
|
+ CompilationResult compilationResult = new CompilationResult(id, isImmutablePIC);
|
|
+
|
|
+ return GraalCompiler.compileGraph(graph, resolvedMethod, providers, backend, graphBuilderSuite, OptimisticOptimizations.ALL, profilingInfo, getSuites(), getLirSuites(),
|
|
+ compilationResult, CompilationResultBuilderFactory.Default, true);
|
|
+
|
|
+ } catch (Throwable e) {
|
|
+ main.handleError(resolvedMethod, e, " (compiling graph)");
|
|
+ }
|
|
+ return null;
|
|
+ }
|
|
+
|
|
+ private static PhaseSuite<HighTierContext> initGraphBuilderSuite(HotSpotBackend backend, boolean compileWithAssertions, HotSpotInvokeDynamicPlugin inokeDynamicPlugin) {
|
|
+ PhaseSuite<HighTierContext> graphBuilderSuite = backend.getSuites().getDefaultGraphBuilderSuite().copy();
|
|
+ ListIterator<BasePhase<? super HighTierContext>> iterator = graphBuilderSuite.findPhase(GraphBuilderPhase.class);
|
|
+ GraphBuilderConfiguration baseConfig = ((GraphBuilderPhase) iterator.previous()).getGraphBuilderConfig();
|
|
+
|
|
+ // Use all default plugins.
|
|
+ Plugins plugins = baseConfig.getPlugins();
|
|
+ plugins.setInvokeDynamicPlugin(inokeDynamicPlugin);
|
|
+ GraphBuilderConfiguration aotConfig = GraphBuilderConfiguration.getDefault(plugins).withEagerResolving(true).withOmitAssertions(!compileWithAssertions);
|
|
+
|
|
+ iterator.next();
|
|
+ iterator.remove();
|
|
+ iterator.add(new GraphBuilderPhase(aotConfig));
|
|
+
|
|
+ return graphBuilderSuite;
|
|
+ }
|
|
+
|
|
+ void printCompiledMethod(HotSpotResolvedJavaMethod resolvedMethod, CompilationResult compResult) {
|
|
+ // This is really not installing the method.
|
|
+ InstalledCode installedCode = codeCache.addCode(resolvedMethod, HotSpotCompiledCodeBuilder.createCompiledCode(codeCache, resolvedMethod, null, compResult, graalOptions), null, null);
|
|
+ String disassembly = codeCache.disassemble(installedCode);
|
|
+ if (disassembly != null) {
|
|
+ main.printer.printlnDebug(disassembly);
|
|
+ }
|
|
+ }
|
|
+}
|
|
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
|
|
new file mode 100644
|
|
index 000000000..b3a72f981
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompilationTask.java
|
|
@@ -0,0 +1,211 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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;
|
|
+
|
|
+import java.util.concurrent.TimeUnit;
|
|
+import java.util.concurrent.atomic.AtomicInteger;
|
|
+
|
|
+import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
|
|
+import org.graalvm.compiler.code.CompilationResult;
|
|
+import org.graalvm.compiler.core.GraalCompilerOptions;
|
|
+import org.graalvm.compiler.debug.DebugContext;
|
|
+import org.graalvm.compiler.debug.DebugContext.Activation;
|
|
+import org.graalvm.compiler.debug.DebugContext.Builder;
|
|
+import org.graalvm.compiler.debug.TTY;
|
|
+import org.graalvm.compiler.options.OptionValues;
|
|
+import org.graalvm.compiler.printer.GraalDebugHandlersFactory;
|
|
+import org.graalvm.compiler.serviceprovider.GraalServices;
|
|
+
|
|
+import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
|
|
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
|
|
+import jdk.vm.ci.meta.ResolvedJavaMethod;
|
|
+import jdk.vm.ci.runtime.JVMCICompiler;
|
|
+
|
|
+/**
|
|
+ * Represents a task in the compile queue.
|
|
+ *
|
|
+ * This class encapsulates all Graal-specific information that is used during offline AOT
|
|
+ * compilation of classes. It also defines methods that parse compilation result of Graal to create
|
|
+ * target-independent representation {@code BinaryContainer} of the intended target binary.
|
|
+ */
|
|
+final class AOTCompilationTask implements Runnable, Comparable<Object> {
|
|
+
|
|
+ private static final AtomicInteger ids = new AtomicInteger();
|
|
+
|
|
+ private final Main main;
|
|
+
|
|
+ private OptionValues graalOptions;
|
|
+
|
|
+ /**
|
|
+ * The compilation id of this task.
|
|
+ */
|
|
+ private final int id;
|
|
+
|
|
+ private final AOTCompiledClass holder;
|
|
+
|
|
+ /**
|
|
+ * Method this task represents.
|
|
+ */
|
|
+ private final ResolvedJavaMethod method;
|
|
+
|
|
+ private final AOTBackend aotBackend;
|
|
+
|
|
+ /**
|
|
+ * The result of this compilation task.
|
|
+ */
|
|
+ private CompiledMethodInfo result;
|
|
+
|
|
+ AOTCompilationTask(Main main, OptionValues graalOptions, AOTCompiledClass holder, ResolvedJavaMethod method, AOTBackend aotBackend) {
|
|
+ this.main = main;
|
|
+ this.graalOptions = graalOptions;
|
|
+ this.id = ids.incrementAndGet();
|
|
+ this.holder = holder;
|
|
+ this.method = method;
|
|
+ this.aotBackend = aotBackend;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Compile a method or a constructor.
|
|
+ */
|
|
+ @Override
|
|
+ @SuppressWarnings("try")
|
|
+ public void run() {
|
|
+ // Ensure a JVMCI runtime is initialized prior to Debug being initialized as the former
|
|
+ // may include processing command line options used by the latter.
|
|
+ HotSpotJVMCIRuntime.runtime();
|
|
+
|
|
+ AOTCompiler.logCompilation(JavaMethodInfo.uniqueMethodName(method), "Compiling");
|
|
+
|
|
+ final long threadId = Thread.currentThread().getId();
|
|
+
|
|
+ final boolean printCompilation = GraalCompilerOptions.PrintCompilation.getValue(graalOptions) && !TTY.isSuppressed() && GraalServices.isThreadAllocatedMemorySupported();
|
|
+ if (printCompilation) {
|
|
+ TTY.println(getMethodDescription() + "...");
|
|
+ }
|
|
+
|
|
+ final long start;
|
|
+ final long allocatedBytesBefore;
|
|
+ if (printCompilation) {
|
|
+ start = System.currentTimeMillis();
|
|
+ allocatedBytesBefore = GraalServices.getThreadAllocatedBytes(threadId);
|
|
+ } else {
|
|
+ start = 0L;
|
|
+ allocatedBytesBefore = 0L;
|
|
+ }
|
|
+
|
|
+ CompilationResult compResult = null;
|
|
+ final long startTime = System.currentTimeMillis();
|
|
+ SnippetReflectionProvider snippetReflection = aotBackend.getProviders().getSnippetReflection();
|
|
+ try (DebugContext debug = new Builder(graalOptions, new GraalDebugHandlersFactory(snippetReflection)).build(); Activation a = debug.activate()) {
|
|
+ compResult = aotBackend.compileMethod(method, debug);
|
|
+ }
|
|
+ final long endTime = System.currentTimeMillis();
|
|
+
|
|
+ if (printCompilation) {
|
|
+ final long stop = System.currentTimeMillis();
|
|
+ final int targetCodeSize = compResult != null ? compResult.getTargetCodeSize() : -1;
|
|
+ final long allocatedBytesAfter = GraalServices.getThreadAllocatedBytes(threadId);
|
|
+ final long allocatedBytes = (allocatedBytesAfter - allocatedBytesBefore) / 1024;
|
|
+
|
|
+ TTY.println(getMethodDescription() + String.format(" | %4dms %5dB %5dkB", stop - start, targetCodeSize, allocatedBytes));
|
|
+ }
|
|
+
|
|
+ if (compResult == null) {
|
|
+ result = null;
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ // For now precision to the nearest second is sufficient.
|
|
+ LogPrinter.writeLog(" Compile Time: " + TimeUnit.MILLISECONDS.toSeconds(endTime - startTime) + "secs");
|
|
+ if (main.options.debug) {
|
|
+ aotBackend.printCompiledMethod((HotSpotResolvedJavaMethod) method, compResult);
|
|
+ }
|
|
+
|
|
+ result = new CompiledMethodInfo(compResult, new AOTHotSpotResolvedJavaMethod((HotSpotResolvedJavaMethod) method, aotBackend.getBackend(), graalOptions));
|
|
+ }
|
|
+
|
|
+ private String getMethodDescription() {
|
|
+ return String.format("%-6d aot %s %s", getId(), JavaMethodInfo.uniqueMethodName(method),
|
|
+ getEntryBCI() == JVMCICompiler.INVOCATION_ENTRY_BCI ? "" : "(OSR@" + getEntryBCI() + ") ");
|
|
+ }
|
|
+
|
|
+ private int getId() {
|
|
+ return id;
|
|
+ }
|
|
+
|
|
+ private static int getEntryBCI() {
|
|
+ return JVMCICompiler.INVOCATION_ENTRY_BCI;
|
|
+ }
|
|
+
|
|
+ ResolvedJavaMethod getMethod() {
|
|
+ return method;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Returns the holder of this method as a {@link AOTCompiledClass}.
|
|
+ *
|
|
+ * @return the holder of this method
|
|
+ */
|
|
+ AOTCompiledClass getHolder() {
|
|
+ return holder;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Returns the result of this compilation task.
|
|
+ *
|
|
+ * @return result of this compilation task
|
|
+ */
|
|
+ CompiledMethodInfo getResult() {
|
|
+ return result;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public int compareTo(Object obj) {
|
|
+ AOTCompilationTask other = (AOTCompilationTask) obj;
|
|
+ return this.id - other.id;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean equals(Object obj) {
|
|
+ if (this == obj) {
|
|
+ return true;
|
|
+ }
|
|
+ if (obj == null) {
|
|
+ return false;
|
|
+ }
|
|
+ if (getClass() != obj.getClass()) {
|
|
+ return false;
|
|
+ }
|
|
+ AOTCompilationTask other = (AOTCompilationTask) obj;
|
|
+ return (this.id == other.id);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public int hashCode() {
|
|
+ return 31 + id;
|
|
+ }
|
|
+
|
|
+}
|
|
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
|
|
new file mode 100644
|
|
index 000000000..416d332fc
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiledClass.java
|
|
@@ -0,0 +1,471 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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;
|
|
+
|
|
+import java.util.ArrayList;
|
|
+import java.util.HashMap;
|
|
+import java.util.Set;
|
|
+
|
|
+import jdk.tools.jaotc.AOTDynamicTypeStore.AdapterLocation;
|
|
+import jdk.tools.jaotc.AOTDynamicTypeStore.AppendixLocation;
|
|
+import jdk.tools.jaotc.AOTDynamicTypeStore.Location;
|
|
+import jdk.tools.jaotc.binformat.BinaryContainer;
|
|
+import jdk.tools.jaotc.binformat.ReadOnlyDataContainer;
|
|
+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.meta.ResolvedJavaField;
|
|
+import jdk.vm.ci.meta.ResolvedJavaMethod;
|
|
+import jdk.vm.ci.meta.ResolvedJavaType;
|
|
+
|
|
+/**
|
|
+ * Class encapsulating Graal-compiled output of a Java class. The compilation result of all methods
|
|
+ * of a class {@code className} are maintained in an array list.
|
|
+ */
|
|
+final class AOTCompiledClass {
|
|
+
|
|
+ private static AOTDynamicTypeStore dynoStore;
|
|
+
|
|
+ static void setDynamicTypeStore(AOTDynamicTypeStore s) {
|
|
+ dynoStore = s;
|
|
+ }
|
|
+
|
|
+ static class AOTKlassData {
|
|
+ private int gotIndex; // Index (offset/8) to the got in the .metaspace.got section
|
|
+ private int classId; // Unique ID
|
|
+ // Offset to compiled methods data in the .methods.offsets section.
|
|
+ private int compiledMethodsOffset;
|
|
+ // Offset to dependent methods data.
|
|
+ private int dependentMethodsOffset;
|
|
+
|
|
+ private final String metadataName;
|
|
+ HotSpotResolvedObjectType type;
|
|
+
|
|
+ /**
|
|
+ * List of dependent compiled methods which have a reference to this class.
|
|
+ */
|
|
+ private ArrayList<CompiledMethodInfo> dependentMethods;
|
|
+
|
|
+ AOTKlassData(BinaryContainer binaryContainer, HotSpotResolvedObjectType type, int classId) {
|
|
+ this.dependentMethods = new ArrayList<>();
|
|
+ this.classId = classId;
|
|
+ this.type = type;
|
|
+ this.metadataName = type.getName();
|
|
+ this.gotIndex = binaryContainer.addTwoSlotKlassSymbol(metadataName);
|
|
+ this.compiledMethodsOffset = -1; // Not compiled classes do not have compiled methods.
|
|
+ this.dependentMethodsOffset = -1;
|
|
+ }
|
|
+
|
|
+ private String[] getMetaspaceNames() {
|
|
+ String name = metadataName;
|
|
+ Set<Location> locs = dynoStore.getDynamicClassLocationsForType(type);
|
|
+ if (locs == null) {
|
|
+ return new String[]{name};
|
|
+ } else {
|
|
+ ArrayList<String> names = new ArrayList<>();
|
|
+ names.add(name);
|
|
+ for (Location l : locs) {
|
|
+ HotSpotResolvedObjectType cpType = l.getHolder();
|
|
+ AOTKlassData data = getAOTKlassData(cpType);
|
|
+ // We collect dynamic types at parse time, but late inlining
|
|
+ // may record types that don't make it into the final graph.
|
|
+ // We can safely ignore those here.
|
|
+ if (data == null) {
|
|
+ // Not a compiled or inlined method
|
|
+ continue;
|
|
+ }
|
|
+ int cpi = l.getCpi();
|
|
+ String location = "<" + data.classId + ":" + cpi + ">";
|
|
+ if (l instanceof AdapterLocation) {
|
|
+ names.add("adapter" + location);
|
|
+ AdapterLocation a = (AdapterLocation) l;
|
|
+ names.add("adapter:" + a.getMethodId() + location);
|
|
+ } else {
|
|
+ assert l instanceof AppendixLocation;
|
|
+ names.add("appendix" + location);
|
|
+ }
|
|
+ }
|
|
+ return names.toArray(new String[names.size()]);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ HotSpotResolvedObjectType getType() {
|
|
+ return type;
|
|
+ }
|
|
+
|
|
+ String getMetadataName() {
|
|
+ return metadataName;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Add a method to the list of dependent methods.
|
|
+ */
|
|
+ synchronized boolean addDependentMethod(CompiledMethodInfo cm) {
|
|
+ return dependentMethods.add(cm);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Return the array list of dependent class methods.
|
|
+ *
|
|
+ * @return array list of dependent methods
|
|
+ */
|
|
+ ArrayList<CompiledMethodInfo> getDependentMethods() {
|
|
+ return dependentMethods;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Returns if this class has dependent methods.
|
|
+ *
|
|
+ * @return true if dependent methods exist, false otherwise
|
|
+ */
|
|
+ boolean hasDependentMethods() {
|
|
+ return !dependentMethods.isEmpty();
|
|
+ }
|
|
+
|
|
+ void setCompiledMethodsOffset(int offset) {
|
|
+ compiledMethodsOffset = offset;
|
|
+ }
|
|
+
|
|
+ protected void putAOTKlassData(BinaryContainer binaryContainer, ReadOnlyDataContainer container) {
|
|
+ int cntDepMethods = dependentMethods.size();
|
|
+ // Create array of dependent methods IDs. First word is count.
|
|
+ ReadOnlyDataContainer dependenciesContainer = binaryContainer.getKlassesDependenciesContainer();
|
|
+ this.dependentMethodsOffset = BinaryContainer.addMethodsCount(cntDepMethods, dependenciesContainer);
|
|
+ for (CompiledMethodInfo methodInfo : dependentMethods) {
|
|
+ dependenciesContainer.appendInt(methodInfo.getCodeId());
|
|
+ }
|
|
+
|
|
+ verify();
|
|
+
|
|
+ // @formatter:off
|
|
+ /*
|
|
+ * The offsets layout should match AOTKlassData structure in AOT JVM runtime
|
|
+ */
|
|
+ int offset = container.getByteStreamSize();
|
|
+ for (String name : getMetaspaceNames()) {
|
|
+ container.createSymbol(offset, Kind.OBJECT, Binding.GLOBAL, 0, name);
|
|
+ }
|
|
+ // Add index (offset/8) to the got in the .metaspace.got section
|
|
+ container.appendInt(gotIndex).
|
|
+ // Add unique ID
|
|
+ appendInt(classId).
|
|
+ // Add the offset to compiled methods data in the .metaspace.offsets section.
|
|
+ appendInt(compiledMethodsOffset).
|
|
+ // Add the offset to dependent methods data in the .metaspace.offsets section.
|
|
+ appendInt(dependentMethodsOffset).
|
|
+ // Add fingerprint.
|
|
+ appendLong(type.getFingerprint());
|
|
+
|
|
+ // @formatter:on
|
|
+ }
|
|
+
|
|
+ private void verify() {
|
|
+ String name = type.getName();
|
|
+ assert gotIndex > 0 : "incorrect gotIndex: " + gotIndex + " for klass: " + name;
|
|
+ long fingerprint = type.getFingerprint();
|
|
+ assert type.isArray() || fingerprint != 0 : "incorrect fingerprint: " + fingerprint + " for klass: " + name;
|
|
+ assert compiledMethodsOffset >= -1 : "incorrect compiledMethodsOffset: " + compiledMethodsOffset + " for klass: " + name;
|
|
+ assert dependentMethodsOffset >= -1 : "incorrect dependentMethodsOffset: " + dependentMethodsOffset + " for klass: " + name;
|
|
+ assert classId >= 0 : "incorrect classId: " + classId + " for klass: " + name;
|
|
+ }
|
|
+
|
|
+ }
|
|
+
|
|
+ private final HotSpotResolvedObjectType resolvedJavaType;
|
|
+
|
|
+ /**
|
|
+ * List of all collected class data.
|
|
+ */
|
|
+ private static HashMap<String, AOTKlassData> klassData = new HashMap<>();
|
|
+
|
|
+ /**
|
|
+ * List of all methods to be compiled.
|
|
+ */
|
|
+ private ArrayList<ResolvedJavaMethod> methods = new ArrayList<>();
|
|
+
|
|
+ /**
|
|
+ * List of all compiled class methods.
|
|
+ */
|
|
+ private ArrayList<CompiledMethodInfo> compiledMethods;
|
|
+
|
|
+ /**
|
|
+ * If this class represents Graal stub code.
|
|
+ */
|
|
+ private final boolean representsStubs;
|
|
+
|
|
+ /**
|
|
+ * Classes count used to generate unique global method id.
|
|
+ */
|
|
+ private static int classesCount = 0;
|
|
+
|
|
+ /**
|
|
+ * Construct an object with compiled methods. Intended to be used for code with no corresponding
|
|
+ * Java method name in the user application.
|
|
+ *
|
|
+ * @param compiledMethods AOT compiled methods
|
|
+ */
|
|
+ AOTCompiledClass(ArrayList<CompiledMethodInfo> compiledMethods) {
|
|
+ this.resolvedJavaType = null;
|
|
+ this.compiledMethods = compiledMethods;
|
|
+ this.representsStubs = true;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Construct an object with compiled versions of the named class.
|
|
+ */
|
|
+ AOTCompiledClass(ResolvedJavaType resolvedJavaType) {
|
|
+ this.resolvedJavaType = (HotSpotResolvedObjectType) resolvedJavaType;
|
|
+ this.compiledMethods = new ArrayList<>();
|
|
+ this.representsStubs = false;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * @return the ResolvedJavaType of this class
|
|
+ */
|
|
+ ResolvedJavaType getResolvedJavaType() {
|
|
+ return resolvedJavaType;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Get the list of methods which should be compiled.
|
|
+ */
|
|
+ ArrayList<ResolvedJavaMethod> getMethods() {
|
|
+ ArrayList<ResolvedJavaMethod> m = methods;
|
|
+ methods = null; // Free - it is not used after that.
|
|
+ return m;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Get the number of all AOT classes.
|
|
+ */
|
|
+ static int getClassesCount() {
|
|
+ return classesCount;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Get the number of methods which should be compiled.
|
|
+ *
|
|
+ * @return number of methods which should be compiled
|
|
+ */
|
|
+ int getMethodCount() {
|
|
+ return methods.size();
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Add a method to the list of methods to be compiled.
|
|
+ */
|
|
+ void addMethod(ResolvedJavaMethod method) {
|
|
+ methods.add(method);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Returns if this class has methods which should be compiled.
|
|
+ *
|
|
+ * @return true if this class contains methods which should be compiled, false otherwise
|
|
+ */
|
|
+ boolean hasMethods() {
|
|
+ return !methods.isEmpty();
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Add a method to the list of compiled methods. This method needs to be thread-safe.
|
|
+ */
|
|
+ synchronized boolean addCompiledMethod(CompiledMethodInfo cm) {
|
|
+ return compiledMethods.add(cm);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Return the array list of compiled class methods.
|
|
+ *
|
|
+ * @return array list of compiled methods
|
|
+ */
|
|
+ ArrayList<CompiledMethodInfo> getCompiledMethods() {
|
|
+ return compiledMethods;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Returns if this class has successfully compiled methods.
|
|
+ *
|
|
+ * @return true if methods were compiled, false otherwise
|
|
+ */
|
|
+ boolean hasCompiledMethods() {
|
|
+ return !compiledMethods.isEmpty();
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Add a klass data.
|
|
+ */
|
|
+ static synchronized AOTKlassData addAOTKlassData(BinaryContainer binaryContainer, HotSpotResolvedObjectType type) {
|
|
+ AOTKlassData data = getAOTKlassData(type);
|
|
+ if (data == null) {
|
|
+ data = new AOTKlassData(binaryContainer, type, classesCount++);
|
|
+ klassData.put(type.getName(), data);
|
|
+ }
|
|
+ return data;
|
|
+ }
|
|
+
|
|
+ static synchronized AOTKlassData getAOTKlassData(HotSpotResolvedObjectType type) {
|
|
+ String name = type.getName();
|
|
+ AOTKlassData data = klassData.get(name);
|
|
+ if (data != null) {
|
|
+ HotSpotResolvedObjectType oldType = data.getType();
|
|
+ assert oldType.equals(type) : "duplicate classes for name " + type.getName();
|
|
+ }
|
|
+ return data;
|
|
+ }
|
|
+
|
|
+ void addAOTKlassData(BinaryContainer binaryContainer) {
|
|
+ for (CompiledMethodInfo methodInfo : compiledMethods) {
|
|
+ // Record methods holder
|
|
+ methodInfo.addDependentKlassData(binaryContainer, resolvedJavaType);
|
|
+ // Record inlinee classes
|
|
+ ResolvedJavaMethod[] inlinees = methodInfo.getCompilationResult().getMethods();
|
|
+ if (inlinees != null) {
|
|
+ for (ResolvedJavaMethod m : inlinees) {
|
|
+ methodInfo.addDependentKlassData(binaryContainer, (HotSpotResolvedObjectType) m.getDeclaringClass());
|
|
+ }
|
|
+ }
|
|
+ // Record classes of fields that were accessed
|
|
+ ResolvedJavaField[] fields = methodInfo.getCompilationResult().getFields();
|
|
+ if (fields != null) {
|
|
+ for (ResolvedJavaField f : fields) {
|
|
+ methodInfo.addDependentKlassData(binaryContainer, (HotSpotResolvedObjectType) f.getDeclaringClass());
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ static synchronized AOTKlassData addFingerprintKlassData(BinaryContainer binaryContainer, HotSpotResolvedObjectType type) {
|
|
+ if (type.isArray()) {
|
|
+ return addAOTKlassData(binaryContainer, type);
|
|
+ }
|
|
+ assert type.getFingerprint() != 0 : "no fingerprint for " + type.getName();
|
|
+ AOTKlassData old = getAOTKlassData(type);
|
|
+ if (old != null) {
|
|
+ if (areAssertionsEnabled()) {
|
|
+ HotSpotResolvedObjectType s = type.getSuperclass();
|
|
+ if (s != null) {
|
|
+ assert getAOTKlassData(s) != null : "fingerprint for super " + s.getName() + " needed for " + type.getName();
|
|
+ }
|
|
+ for (HotSpotResolvedObjectType i : type.getInterfaces()) {
|
|
+ assert getAOTKlassData(i) != null : "fingerprint for interface " + i.getName() + " needed for " + type.getName();
|
|
+ }
|
|
+ }
|
|
+ return old;
|
|
+ }
|
|
+
|
|
+ // Fingerprinting requires super classes and super interfaces
|
|
+ HotSpotResolvedObjectType s = type.getSuperclass();
|
|
+ if (s != null) {
|
|
+ addFingerprintKlassData(binaryContainer, s);
|
|
+ }
|
|
+ for (HotSpotResolvedObjectType i : type.getInterfaces()) {
|
|
+ addFingerprintKlassData(binaryContainer, i);
|
|
+ }
|
|
+
|
|
+ return addAOTKlassData(binaryContainer, type);
|
|
+ }
|
|
+
|
|
+ @SuppressWarnings("all")
|
|
+ private static boolean areAssertionsEnabled() {
|
|
+ boolean assertsEnabled = false;
|
|
+ // Next assignment will be executed when asserts are enabled.
|
|
+ assert assertsEnabled = true;
|
|
+ return assertsEnabled;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Put methods data to contained.
|
|
+ */
|
|
+ void putMethodsData(BinaryContainer binaryContainer) {
|
|
+ ReadOnlyDataContainer container = binaryContainer.getMethodsOffsetsContainer();
|
|
+ int cntMethods = compiledMethods.size();
|
|
+ int startMethods = BinaryContainer.addMethodsCount(cntMethods, container);
|
|
+ for (CompiledMethodInfo methodInfo : compiledMethods) {
|
|
+ methodInfo.addMethodOffsets(binaryContainer, container);
|
|
+ }
|
|
+ String name = resolvedJavaType.getName();
|
|
+ AOTKlassData data = getAOTKlassData(resolvedJavaType);
|
|
+ assert data != null : "missing data for klass: " + name;
|
|
+ int cntDepMethods = data.dependentMethods.size();
|
|
+ assert cntDepMethods > 0 : "no dependent methods for compiled klass: " + name;
|
|
+ data.setCompiledMethodsOffset(startMethods);
|
|
+ }
|
|
+
|
|
+ static void putAOTKlassData(BinaryContainer binaryContainer) {
|
|
+ // record dynamic types
|
|
+ Set<HotSpotResolvedObjectType> dynoTypes = dynoStore.getDynamicTypes();
|
|
+ if (dynoTypes != null) {
|
|
+ for (HotSpotResolvedObjectType dynoType : dynoTypes) {
|
|
+ addFingerprintKlassData(binaryContainer, dynoType);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ ReadOnlyDataContainer container = binaryContainer.getKlassesOffsetsContainer();
|
|
+ for (AOTKlassData data : klassData.values()) {
|
|
+ data.putAOTKlassData(binaryContainer, container);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ static HotSpotResolvedObjectType getType(Object ref) {
|
|
+ return (ref instanceof HotSpotResolvedObjectType) ? (HotSpotResolvedObjectType) ref : ((HotSpotResolvedJavaMethod) ref).getDeclaringClass();
|
|
+ }
|
|
+
|
|
+ static String metadataName(HotSpotResolvedObjectType type) {
|
|
+ AOTKlassData data = getAOTKlassData(type);
|
|
+ assert data != null : "no data for " + type;
|
|
+ return getAOTKlassData(type).getMetadataName();
|
|
+ }
|
|
+
|
|
+ private static String metadataName(HotSpotResolvedJavaMethod m) {
|
|
+ return metadataName(m.getDeclaringClass()) + "." + m.getName() + m.getSignature().toMethodDescriptor();
|
|
+ }
|
|
+
|
|
+ static String metadataName(Object ref) {
|
|
+ if (ref instanceof HotSpotResolvedJavaMethod) {
|
|
+ HotSpotResolvedJavaMethod m = (HotSpotResolvedJavaMethod) ref;
|
|
+ return metadataName(m);
|
|
+ } else {
|
|
+ assert ref instanceof HotSpotResolvedObjectType : "unexpected object type " + ref.getClass().getName();
|
|
+ HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) ref;
|
|
+ return metadataName(type);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ boolean representsStubs() {
|
|
+ return representsStubs;
|
|
+ }
|
|
+
|
|
+ void clear() {
|
|
+ for (CompiledMethodInfo c : compiledMethods) {
|
|
+ c.clear();
|
|
+ }
|
|
+ this.compiledMethods = null;
|
|
+ this.methods = null;
|
|
+ }
|
|
+
|
|
+}
|
|
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
|
|
new file mode 100644
|
|
index 000000000..4bf9047a4
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiler.java
|
|
@@ -0,0 +1,169 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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;
|
|
+
|
|
+import java.util.ArrayList;
|
|
+import java.util.List;
|
|
+import java.util.concurrent.PriorityBlockingQueue;
|
|
+import java.util.concurrent.RejectedExecutionException;
|
|
+import java.util.concurrent.ThreadPoolExecutor;
|
|
+import java.util.concurrent.TimeUnit;
|
|
+import java.util.concurrent.atomic.AtomicInteger;
|
|
+
|
|
+import org.graalvm.compiler.options.OptionValues;
|
|
+
|
|
+import jdk.vm.ci.meta.ResolvedJavaMethod;
|
|
+
|
|
+final class AOTCompiler {
|
|
+
|
|
+ private final Main main;
|
|
+
|
|
+ private final OptionValues graalOptions;
|
|
+
|
|
+ private CompileQueue compileQueue;
|
|
+
|
|
+ private final AOTBackend backend;
|
|
+
|
|
+ /**
|
|
+ * Compile queue.
|
|
+ */
|
|
+ private class CompileQueue extends ThreadPoolExecutor {
|
|
+
|
|
+ /**
|
|
+ * Time of the start of this queue.
|
|
+ */
|
|
+ private final long startTime;
|
|
+
|
|
+ /**
|
|
+ * Method counter for successful compilations.
|
|
+ */
|
|
+ private final AtomicInteger successfulMethodCount = new AtomicInteger();
|
|
+
|
|
+ /**
|
|
+ * Method counter for failed compilations.
|
|
+ */
|
|
+ private final AtomicInteger failedMethodCount = new AtomicInteger();
|
|
+
|
|
+ /**
|
|
+ * Create a compile queue with the given number of threads.
|
|
+ */
|
|
+ CompileQueue(final int threads) {
|
|
+ super(threads, threads, 0L, TimeUnit.MILLISECONDS, new PriorityBlockingQueue<>());
|
|
+ startTime = System.currentTimeMillis();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected void afterExecute(Runnable r, Throwable t) {
|
|
+ AOTCompilationTask task = (AOTCompilationTask) r;
|
|
+ if (task.getResult() != null) {
|
|
+ final int count = successfulMethodCount.incrementAndGet();
|
|
+ if (count % 100 == 0) {
|
|
+ main.printer.printInfo(".");
|
|
+ }
|
|
+ CompiledMethodInfo result = task.getResult();
|
|
+ if (result != null) {
|
|
+ task.getHolder().addCompiledMethod(result);
|
|
+ }
|
|
+ } else {
|
|
+ failedMethodCount.incrementAndGet();
|
|
+ main.printer.printlnVerbose("");
|
|
+ ResolvedJavaMethod method = task.getMethod();
|
|
+ main.printer.printlnVerbose(" failed " + method.getName() + method.getSignature().toMethodDescriptor());
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected void terminated() {
|
|
+ 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)");
|
|
+ }
|
|
+
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * @param main
|
|
+ * @param graalOptions
|
|
+ * @param aotBackend
|
|
+ * @param threads number of compilation threads
|
|
+ */
|
|
+ AOTCompiler(Main main, OptionValues graalOptions, AOTBackend aotBackend, final int threads) {
|
|
+ this.main = main;
|
|
+ this.graalOptions = graalOptions;
|
|
+ this.compileQueue = new CompileQueue(threads);
|
|
+ this.backend = aotBackend;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Compile all methods in all classes passed.
|
|
+ *
|
|
+ * @param classes a list of class to compile
|
|
+ * @throws InterruptedException
|
|
+ */
|
|
+ List<AOTCompiledClass> compileClasses(List<AOTCompiledClass> classes) throws InterruptedException {
|
|
+ main.printer.printlnInfo("Compiling with " + compileQueue.getCorePoolSize() + " threads");
|
|
+ main.printer.printInfo("."); // Compilation progress indication.
|
|
+
|
|
+ for (AOTCompiledClass c : classes) {
|
|
+ for (ResolvedJavaMethod m : c.getMethods()) {
|
|
+ enqueueMethod(c, m);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // Shutdown queue and wait for all tasks to complete.
|
|
+ compileQueue.shutdown();
|
|
+ compileQueue.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
|
|
+
|
|
+ List<AOTCompiledClass> compiledClasses = new ArrayList<>();
|
|
+ for (AOTCompiledClass compiledClass : classes) {
|
|
+ if (compiledClass.hasCompiledMethods()) {
|
|
+ compiledClasses.add(compiledClass);
|
|
+ }
|
|
+ }
|
|
+ return compiledClasses;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Enqueue a method in the {@link #compileQueue}.
|
|
+ *
|
|
+ * @param method method to be enqueued
|
|
+ */
|
|
+ private void enqueueMethod(AOTCompiledClass aotClass, ResolvedJavaMethod method) {
|
|
+ AOTCompilationTask task = new AOTCompilationTask(main, graalOptions, aotClass, method, backend);
|
|
+ try {
|
|
+ compileQueue.execute(task);
|
|
+ } catch (RejectedExecutionException e) {
|
|
+ e.printStackTrace();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ static void logCompilation(String methodName, String message) {
|
|
+ LogPrinter.writeLog(message + " " + methodName);
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTDynamicTypeStore.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTDynamicTypeStore.java
|
|
new file mode 100644
|
|
index 000000000..a8fb12048
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTDynamicTypeStore.java
|
|
@@ -0,0 +1,172 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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;
|
|
+
|
|
+import java.util.HashMap;
|
|
+import java.util.HashSet;
|
|
+import java.util.Set;
|
|
+
|
|
+import org.graalvm.compiler.hotspot.meta.HotSpotInvokeDynamicPlugin.DynamicTypeStore;
|
|
+
|
|
+import jdk.vm.ci.hotspot.HotSpotConstantPool;
|
|
+import jdk.vm.ci.hotspot.HotSpotConstantPoolObject;
|
|
+import jdk.vm.ci.hotspot.HotSpotObjectConstant;
|
|
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
|
|
+import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
|
|
+import jdk.vm.ci.meta.JavaConstant;
|
|
+
|
|
+final class AOTDynamicTypeStore implements DynamicTypeStore {
|
|
+
|
|
+ public static class Location {
|
|
+ private HotSpotResolvedObjectType holder;
|
|
+ private int cpi;
|
|
+
|
|
+ Location(HotSpotResolvedObjectType holder, int cpi) {
|
|
+ this.holder = holder;
|
|
+ this.cpi = cpi;
|
|
+ }
|
|
+
|
|
+ public HotSpotResolvedObjectType getHolder() {
|
|
+ return holder;
|
|
+ }
|
|
+
|
|
+ public int getCpi() {
|
|
+ return cpi;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public String toString() {
|
|
+ return getHolder().getName() + "@" + cpi;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public int hashCode() {
|
|
+ return holder.hashCode() + getClass().hashCode() + cpi;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean equals(Object o) {
|
|
+ if (this == o) {
|
|
+ return true;
|
|
+ }
|
|
+ if (getClass() != o.getClass()) {
|
|
+ return false;
|
|
+ }
|
|
+ Location l = (Location) o;
|
|
+ return cpi == l.cpi && holder.equals(l.holder);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public static class AdapterLocation extends Location {
|
|
+ private int methodId;
|
|
+
|
|
+ AdapterLocation(HotSpotResolvedObjectType holder, int cpi, int methodId) {
|
|
+ super(holder, cpi);
|
|
+ this.methodId = methodId;
|
|
+ }
|
|
+
|
|
+ public int getMethodId() {
|
|
+ return methodId;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public String toString() {
|
|
+ return "adapter:" + methodId + "@" + super.toString();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public static class AppendixLocation extends Location {
|
|
+ AppendixLocation(HotSpotResolvedObjectType holder, int cpi) {
|
|
+ super(holder, cpi);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public String toString() {
|
|
+ return "appendix@" + super.toString();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private HashMap<HotSpotResolvedObjectType, HashSet<Location>> typeMap = new HashMap<>();
|
|
+ private HashMap<HotSpotResolvedObjectType, HashSet<HotSpotResolvedObjectType>> holderMap = new HashMap<>();
|
|
+
|
|
+ public Set<HotSpotResolvedObjectType> getDynamicTypes() {
|
|
+ synchronized (typeMap) {
|
|
+ return typeMap.keySet();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public Set<HotSpotResolvedObjectType> getDynamicHolders() {
|
|
+ synchronized (holderMap) {
|
|
+ return holderMap.keySet();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void recordAdapter(int opcode, HotSpotResolvedObjectType holder, int index, HotSpotResolvedJavaMethod adapter) {
|
|
+ int cpi = ((HotSpotConstantPool) holder.getConstantPool()).rawIndexToConstantPoolIndex(index, opcode);
|
|
+ int methodId = adapter.methodIdnum();
|
|
+ HotSpotResolvedObjectType adapterType = adapter.getDeclaringClass();
|
|
+ recordDynamicTypeLocation(new AdapterLocation(holder, cpi, methodId), adapterType);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public JavaConstant recordAppendix(int opcode, HotSpotResolvedObjectType holder, int index, JavaConstant appendix) {
|
|
+ int cpi = ((HotSpotConstantPool) holder.getConstantPool()).rawIndexToConstantPoolIndex(index, opcode);
|
|
+ HotSpotResolvedObjectType appendixType = ((HotSpotObjectConstant) appendix).getType();
|
|
+ recordDynamicTypeLocation(new AppendixLocation(holder, cpi), appendixType);
|
|
+ // Make the constant locatable
|
|
+ return HotSpotConstantPoolObject.forObject(holder, cpi, appendix);
|
|
+ }
|
|
+
|
|
+ private static <T> void recordDynamicMapValue(HashMap<HotSpotResolvedObjectType, HashSet<T>> map, HotSpotResolvedObjectType type, T v) {
|
|
+ synchronized (map) {
|
|
+ HashSet<T> set = map.get(type);
|
|
+ if (set == null) {
|
|
+ set = new HashSet<>();
|
|
+ map.put(type, set);
|
|
+ }
|
|
+ set.add(v);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private void recordDynamicTypeLocation(Location l, HotSpotResolvedObjectType type) {
|
|
+ recordDynamicMapValue(typeMap, type, l);
|
|
+ HotSpotResolvedObjectType holder = l.getHolder();
|
|
+ recordDynamicMapValue(holderMap, holder, type);
|
|
+ }
|
|
+
|
|
+ public Set<Location> getDynamicClassLocationsForType(HotSpotResolvedObjectType type) {
|
|
+ synchronized (typeMap) {
|
|
+ return typeMap.get(type);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public Set<HotSpotResolvedObjectType> getDynamicTypesForHolder(HotSpotResolvedObjectType holder) {
|
|
+ synchronized (holderMap) {
|
|
+ return holderMap.get(holder);
|
|
+ }
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTHotSpotResolvedJavaMethod.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTHotSpotResolvedJavaMethod.java
|
|
new file mode 100644
|
|
index 000000000..0bad5d5c4
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTHotSpotResolvedJavaMethod.java
|
|
@@ -0,0 +1,64 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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;
|
|
+
|
|
+import org.graalvm.compiler.code.CompilationResult;
|
|
+import org.graalvm.compiler.core.target.Backend;
|
|
+import org.graalvm.compiler.hotspot.HotSpotCompiledCodeBuilder;
|
|
+import org.graalvm.compiler.options.OptionValues;
|
|
+
|
|
+import jdk.vm.ci.hotspot.HotSpotCompiledCode;
|
|
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
|
|
+
|
|
+final class AOTHotSpotResolvedJavaMethod implements JavaMethodInfo {
|
|
+
|
|
+ private final HotSpotResolvedJavaMethod method;
|
|
+ private final Backend backend;
|
|
+ private final OptionValues options;
|
|
+
|
|
+ AOTHotSpotResolvedJavaMethod(HotSpotResolvedJavaMethod method, Backend backend, OptionValues options) {
|
|
+ this.method = method;
|
|
+ this.backend = backend;
|
|
+ this.options = options;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public String getSymbolName() {
|
|
+ return JavaMethodInfo.uniqueMethodName(method);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public String getNameAndSignature() {
|
|
+ String className = method.getDeclaringClass().getName();
|
|
+ return className + "." + method.getName() + method.getSignature().toMethodDescriptor();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public HotSpotCompiledCode compiledCode(CompilationResult result) {
|
|
+ return HotSpotCompiledCodeBuilder.createCompiledCode(backend.getCodeCache(), method, null, result, options);
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTStub.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTStub.java
|
|
new file mode 100644
|
|
index 000000000..4848b8ef0
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTStub.java
|
|
@@ -0,0 +1,63 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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;
|
|
+
|
|
+import org.graalvm.compiler.code.CompilationResult;
|
|
+import org.graalvm.compiler.core.target.Backend;
|
|
+import org.graalvm.compiler.hotspot.HotSpotCompiledCodeBuilder;
|
|
+import org.graalvm.compiler.hotspot.stubs.Stub;
|
|
+import org.graalvm.compiler.options.OptionValues;
|
|
+
|
|
+import jdk.vm.ci.hotspot.HotSpotCompiledCode;
|
|
+
|
|
+final class AOTStub implements JavaMethodInfo {
|
|
+
|
|
+ private final Stub stub;
|
|
+ private final Backend backend;
|
|
+ private OptionValues options;
|
|
+
|
|
+ AOTStub(Stub stub, Backend backend, OptionValues options) {
|
|
+ this.stub = stub;
|
|
+ this.backend = backend;
|
|
+ this.options = options;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public String getSymbolName() {
|
|
+ return stub.toString();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public String getNameAndSignature() {
|
|
+ return stub.toString();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public HotSpotCompiledCode compiledCode(CompilationResult result) {
|
|
+ return HotSpotCompiledCodeBuilder.createCompiledCode(backend.getCodeCache(), null, null, result, options);
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CallInfo.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CallInfo.java
|
|
new file mode 100644
|
|
index 000000000..724618a3c
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CallInfo.java
|
|
@@ -0,0 +1,105 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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;
|
|
+
|
|
+import org.graalvm.compiler.bytecode.Bytecodes;
|
|
+import org.graalvm.compiler.hotspot.HotSpotMarkId;
|
|
+
|
|
+import jdk.vm.ci.code.BytecodePosition;
|
|
+import jdk.vm.ci.code.site.Call;
|
|
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
|
|
+import jdk.vm.ci.meta.ResolvedJavaMethod;
|
|
+
|
|
+final class CallInfo {
|
|
+
|
|
+ static boolean isStaticTarget(Call call) {
|
|
+ return !((HotSpotResolvedJavaMethod) call.target).hasReceiver();
|
|
+ }
|
|
+
|
|
+ private static boolean isStaticOpcode(Call call) {
|
|
+ int opcode = getByteCode(call) & 0xFF;
|
|
+ return opcode == Bytecodes.INVOKESTATIC || opcode == Bytecodes.INVOKEDYNAMIC ||
|
|
+ opcode == Bytecodes.INVOKEVIRTUAL /* invokehandle */;
|
|
+ }
|
|
+
|
|
+ static boolean isStaticCall(Call call) {
|
|
+ if (isJavaCall(call) && isStaticTarget(call)) {
|
|
+ assert isStaticOpcode(call);
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ static boolean isSpecialCall(Call call) {
|
|
+ if (isJavaCall(call)) {
|
|
+ return ((getByteCode(call) & 0xFF) == Bytecodes.INVOKESPECIAL);
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ private static boolean isInvokeVirtual(Call call) {
|
|
+ if (isJavaCall(call)) {
|
|
+ return ((getByteCode(call) & 0xFF) == Bytecodes.INVOKEVIRTUAL) || ((getByteCode(call) & 0xFF) == Bytecodes.INVOKEINTERFACE);
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ static boolean isVirtualCall(CompiledMethodInfo methodInfo, Call call) {
|
|
+ return isInvokeVirtual(call) && !methodInfo.hasMark(call, HotSpotMarkId.INVOKESPECIAL) && !isStaticTarget(call);
|
|
+ }
|
|
+
|
|
+ static boolean isOptVirtualCall(CompiledMethodInfo methodInfo, Call call) {
|
|
+ return isInvokeVirtual(call) && methodInfo.hasMark(call, HotSpotMarkId.INVOKESPECIAL);
|
|
+ }
|
|
+
|
|
+ private static boolean isJavaCall(Call call) {
|
|
+ // If there is no associated debug info return false
|
|
+ if (call.debugInfo == null) {
|
|
+ return false;
|
|
+ }
|
|
+ BytecodePosition bcpos = call.debugInfo.getBytecodePosition();
|
|
+ ResolvedJavaMethod method = bcpos.getMethod();
|
|
+ // If bytecode position indicates a special value (negative value) it is
|
|
+ // not a normal java call
|
|
+ if (bcpos.getBCI() < 0) {
|
|
+ return false;
|
|
+ }
|
|
+ // If there is no method associated with the debuginfo, return false
|
|
+ if (method == null) {
|
|
+ return false;
|
|
+ }
|
|
+ assert (method instanceof HotSpotResolvedJavaMethod) : "Not a resolved Java call";
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ private static byte getByteCode(Call call) {
|
|
+ ResolvedJavaMethod m = call.debugInfo.getBytecodePosition().getMethod();
|
|
+ int callPosition = call.debugInfo.getBytecodePosition().getBCI();
|
|
+ byte[] code = m.getCode();
|
|
+ return code[callPosition];
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CallSiteRelocationInfo.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CallSiteRelocationInfo.java
|
|
new file mode 100644
|
|
index 000000000..3adc25a98
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CallSiteRelocationInfo.java
|
|
@@ -0,0 +1,44 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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;
|
|
+
|
|
+import jdk.tools.jaotc.binformat.Relocation.RelocType;
|
|
+
|
|
+/**
|
|
+ * Describes a call site relocation. Contains a name of the callee and a relocation type, describing
|
|
+ * which relocation to use at the call site.
|
|
+ */
|
|
+abstract class CallSiteRelocationInfo {
|
|
+
|
|
+ final String targetSymbol;
|
|
+ final RelocType type;
|
|
+
|
|
+ CallSiteRelocationInfo(String targetSymbol, RelocType type) {
|
|
+ this.targetSymbol = targetSymbol;
|
|
+ this.type = type;
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CallSiteRelocationSymbol.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CallSiteRelocationSymbol.java
|
|
new file mode 100644
|
|
index 000000000..c8de636b3
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CallSiteRelocationSymbol.java
|
|
@@ -0,0 +1,84 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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;
|
|
+
|
|
+import jdk.tools.jaotc.binformat.BinaryContainer;
|
|
+import jdk.tools.jaotc.binformat.ByteContainer;
|
|
+import jdk.tools.jaotc.binformat.CodeContainer;
|
|
+import jdk.tools.jaotc.binformat.Relocation;
|
|
+import jdk.tools.jaotc.binformat.Relocation.RelocType;
|
|
+import jdk.tools.jaotc.binformat.Symbol;
|
|
+import jdk.tools.jaotc.binformat.Symbol.Binding;
|
|
+import jdk.tools.jaotc.binformat.Symbol.Kind;
|
|
+
|
|
+/**
|
|
+ * Describes a relocation symbol of a call site. That is, WHERE to do a relocation.
|
|
+ */
|
|
+abstract class CallSiteRelocationSymbol {
|
|
+
|
|
+ final Symbol symbol;
|
|
+
|
|
+ CallSiteRelocationSymbol(Symbol symbol) {
|
|
+ assert symbol != null;
|
|
+ this.symbol = symbol;
|
|
+ }
|
|
+
|
|
+ protected static Symbol createCodeContainerSymbol(BinaryContainer binaryContainer, String symbolName, int symbolOffset) {
|
|
+ return binaryContainer.getCodeContainer().createSymbol(symbolOffset, Kind.OBJECT, Binding.LOCAL, 0, symbolName);
|
|
+ }
|
|
+
|
|
+ protected static void addCodeContainerRelocation(BinaryContainer binaryContainer, String symbolName, int symbolOffset, int relocationOffset) {
|
|
+ Symbol symbol = createCodeContainerSymbol(binaryContainer, symbolName, symbolOffset);
|
|
+ addExternalGotToPltRelocation(binaryContainer, symbol, relocationOffset);
|
|
+ }
|
|
+
|
|
+ protected static void addExtLinkageGotContainerRelocation(BinaryContainer binaryContainer, String symbolName, int symbolOffset, int relocationOffset) {
|
|
+ ByteContainer container = binaryContainer.getExtLinkageGOTContainer();
|
|
+ Symbol symbol = container.createGotSymbol(symbolOffset, symbolName);
|
|
+ addExternalPltToGotRelocation(binaryContainer, symbol, relocationOffset);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Add an {@link RelocType#EXTERNAL_GOT_TO_PLT} relocation to the
|
|
+ * {@link BinaryContainer#getExtLinkageGOTContainer()}.
|
|
+ */
|
|
+ private static void addExternalGotToPltRelocation(BinaryContainer binaryContainer, Symbol symbol, int relocationOffset) {
|
|
+ ByteContainer container = binaryContainer.getExtLinkageGOTContainer();
|
|
+ Relocation relocation = new Relocation(relocationOffset, RelocType.EXTERNAL_GOT_TO_PLT, 8, container, symbol);
|
|
+ binaryContainer.addRelocation(relocation);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Add an {@link RelocType#EXTERNAL_PLT_TO_GOT} relocation to the
|
|
+ * {@link BinaryContainer#getCodeContainer()}.
|
|
+ */
|
|
+ protected static void addExternalPltToGotRelocation(BinaryContainer binaryContainer, Symbol symbol, int relocationOffset) {
|
|
+ CodeContainer container = binaryContainer.getCodeContainer();
|
|
+ Relocation relocation = new Relocation(relocationOffset, RelocType.EXTERNAL_PLT_TO_GOT, 8, container, symbol);
|
|
+ binaryContainer.addRelocation(relocation);
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CodeOffsets.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CodeOffsets.java
|
|
new file mode 100644
|
|
index 000000000..a2c9c5125
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CodeOffsets.java
|
|
@@ -0,0 +1,102 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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;
|
|
+
|
|
+import java.util.List;
|
|
+
|
|
+import org.graalvm.compiler.code.CompilationResult;
|
|
+import org.graalvm.compiler.hotspot.HotSpotMarkId;
|
|
+
|
|
+final class CodeOffsets {
|
|
+ private final int entry;
|
|
+ private final int verifiedEntry;
|
|
+ private final int exceptionHandler;
|
|
+ private final int deoptHandler;
|
|
+ private final int deoptMHHandler;
|
|
+
|
|
+ private CodeOffsets(int entry, int verifiedEntry, int exceptionHandler, int deoptHandler, int deoptMHHandler) {
|
|
+ this.entry = entry;
|
|
+ this.verifiedEntry = verifiedEntry;
|
|
+ this.exceptionHandler = exceptionHandler;
|
|
+ this.deoptHandler = deoptHandler;
|
|
+ this.deoptMHHandler = deoptMHHandler;
|
|
+ }
|
|
+
|
|
+ static CodeOffsets buildFrom(List<CompilationResult.CodeMark> marks) {
|
|
+ int entry = 0;
|
|
+ int verifiedEntry = 0;
|
|
+ int exceptionHandler = -1;
|
|
+ int deoptHandler = -1;
|
|
+ int deoptMHHandler = -1;
|
|
+
|
|
+ for (CompilationResult.CodeMark mark : marks) {
|
|
+ HotSpotMarkId markId = (HotSpotMarkId) mark.id;
|
|
+ switch (markId) {
|
|
+ case UNVERIFIED_ENTRY:
|
|
+ entry = mark.pcOffset;
|
|
+ break;
|
|
+ case VERIFIED_ENTRY:
|
|
+ verifiedEntry = mark.pcOffset;
|
|
+ break;
|
|
+ case OSR_ENTRY:
|
|
+ // Unhandled
|
|
+ break;
|
|
+ case EXCEPTION_HANDLER_ENTRY:
|
|
+ exceptionHandler = mark.pcOffset;
|
|
+ break;
|
|
+ case DEOPT_HANDLER_ENTRY:
|
|
+ deoptHandler = mark.pcOffset;
|
|
+ break;
|
|
+ case DEOPT_MH_HANDLER_ENTRY:
|
|
+ deoptMHHandler = mark.pcOffset;
|
|
+ break;
|
|
+ default:
|
|
+ break; // Ignore others
|
|
+ }
|
|
+ }
|
|
+ return new CodeOffsets(entry, verifiedEntry, exceptionHandler, deoptHandler, deoptMHHandler);
|
|
+ }
|
|
+
|
|
+ int entry() {
|
|
+ return entry;
|
|
+ }
|
|
+
|
|
+ int verifiedEntry() {
|
|
+ return verifiedEntry;
|
|
+ }
|
|
+
|
|
+ int exceptionHandler() {
|
|
+ return exceptionHandler;
|
|
+ }
|
|
+
|
|
+ int deoptHandler() {
|
|
+ return deoptHandler;
|
|
+ }
|
|
+
|
|
+ int deoptMHHandler() {
|
|
+ return deoptMHHandler;
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CodeSectionProcessor.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CodeSectionProcessor.java
|
|
new file mode 100644
|
|
index 000000000..ff5e9ca89
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CodeSectionProcessor.java
|
|
@@ -0,0 +1,149 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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;
|
|
+
|
|
+import java.util.ArrayList;
|
|
+
|
|
+import org.graalvm.compiler.code.CompilationResult;
|
|
+import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
|
|
+import org.graalvm.compiler.options.OptionValues;
|
|
+
|
|
+import jdk.tools.jaotc.binformat.BinaryContainer;
|
|
+import jdk.tools.jaotc.binformat.CodeContainer;
|
|
+import jdk.tools.jaotc.binformat.Symbol;
|
|
+import jdk.vm.ci.amd64.AMD64;
|
|
+import jdk.vm.ci.code.TargetDescription;
|
|
+import jdk.vm.ci.code.site.Call;
|
|
+import jdk.vm.ci.code.site.Infopoint;
|
|
+import jdk.vm.ci.code.site.InfopointReason;
|
|
+import jdk.vm.ci.meta.ResolvedJavaMethod;
|
|
+
|
|
+final class CodeSectionProcessor {
|
|
+
|
|
+ private final OptionValues optionValues;
|
|
+
|
|
+ private final TargetDescription target;
|
|
+
|
|
+ private final BinaryContainer binaryContainer;
|
|
+
|
|
+ CodeSectionProcessor(DataBuilder dataBuilder) {
|
|
+ this.target = dataBuilder.getBackend().getTarget();
|
|
+ this.binaryContainer = dataBuilder.getBinaryContainer();
|
|
+ this.optionValues = dataBuilder.getBackend().getRuntime().getOptions();
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Method that looks at code section of a compiled result {@code compClass} and records function
|
|
+ * entry point symbols along with the text section contents. Note that the text section contents
|
|
+ * are not yet ready to be written in the form of a binary text section since the contents may
|
|
+ * need to be patched with references to other sections.
|
|
+ *
|
|
+ * @param compClass Graal compilation result.
|
|
+ */
|
|
+ void process(AOTCompiledClass compClass) {
|
|
+ ArrayList<CompiledMethodInfo> compiledMethods = compClass.getCompiledMethods();
|
|
+
|
|
+ for (CompiledMethodInfo methodInfo : compiledMethods) {
|
|
+ CompilationResult compResult = methodInfo.getCompilationResult();
|
|
+
|
|
+ byte[] targetCode = compResult.getTargetCode();
|
|
+ int targetCodeSize = compResult.getTargetCodeSize();
|
|
+ JavaMethodInfo compMethod = methodInfo.getMethodInfo();
|
|
+
|
|
+ // Step through all foreign calls, for every call, clear destination.
|
|
+ // Otherwise libelf may not patch them correctly.
|
|
+ for (Infopoint infopoint : compResult.getInfopoints()) {
|
|
+ if (infopoint.reason == InfopointReason.CALL) {
|
|
+ final Call callInfopoint = (Call) infopoint;
|
|
+ if (callInfopoint.target instanceof HotSpotForeignCallLinkage &&
|
|
+ target.arch instanceof AMD64) {
|
|
+ // TODO 4 is x86 size of relative displacement.
|
|
+ // For SPARC need something different.
|
|
+ int destOffset = infopoint.pcOffset + callInfopoint.size - 4;
|
|
+ targetCode[destOffset + 0] = 0;
|
|
+ targetCode[destOffset + 1] = 0;
|
|
+ targetCode[destOffset + 2] = 0;
|
|
+ targetCode[destOffset + 3] = 0;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ String entry = compMethod.getSymbolName();
|
|
+ assert entry != null : "missing name for compiled method";
|
|
+
|
|
+ // Align and pad method entry
|
|
+ CodeContainer codeSection = binaryContainer.getCodeContainer();
|
|
+ int codeIdOffset = BinaryContainer.alignUp(codeSection, binaryContainer.getCodeSegmentSize());
|
|
+ // Store CodeId into code. It will be use by find_aot() using code.segments
|
|
+ methodInfo.setCodeId();
|
|
+ binaryContainer.appendIntToCode(methodInfo.getCodeId());
|
|
+ int textBaseOffset = BinaryContainer.alignUp(codeSection, binaryContainer.getCodeEntryAlignment());
|
|
+
|
|
+ codeSection.createSymbol(textBaseOffset, Symbol.Kind.JAVA_FUNCTION, Symbol.Binding.LOCAL, targetCodeSize, entry);
|
|
+
|
|
+ // Set the offset at which the text section of this method would be layed out
|
|
+ methodInfo.setTextSectionOffset(textBaseOffset);
|
|
+
|
|
+ // Write code bytes of the current method into byte stream
|
|
+ binaryContainer.appendCodeBytes(targetCode, 0, targetCodeSize);
|
|
+ int currentStubOffset = BinaryContainer.alignUp(codeSection, 8);
|
|
+ // Set the offset at which stubs of this method would be laid out
|
|
+ methodInfo.setStubsOffset(currentStubOffset - textBaseOffset);
|
|
+ // step through all calls, for every call, add a stub
|
|
+ for (Infopoint infopoint : compResult.getInfopoints()) {
|
|
+ if (infopoint.reason == InfopointReason.CALL) {
|
|
+ final Call callInfopoint = (Call) infopoint;
|
|
+ if (callInfopoint.target instanceof ResolvedJavaMethod) {
|
|
+ ResolvedJavaMethod call = (ResolvedJavaMethod) callInfopoint.target;
|
|
+ StubInformation stub = addCallStub(CallInfo.isVirtualCall(methodInfo, callInfopoint));
|
|
+ // Get the targetSymbol. A symbol for this will be created later during plt
|
|
+ // creation
|
|
+ String targetSymbol = JavaMethodInfo.uniqueMethodName(call) + ".at." + infopoint.pcOffset;
|
|
+ methodInfo.addStubCode(targetSymbol, stub);
|
|
+ currentStubOffset += stub.getSize();
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ assert currentStubOffset == codeSection.getByteStreamSize() : "wrong offset";
|
|
+ binaryContainer.addCodeSegments(codeIdOffset, currentStubOffset);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private StubInformation addCallStub(boolean isVirtualCall) {
|
|
+ final int startOffset = binaryContainer.getCodeContainer().getByteStreamSize();
|
|
+ StubInformation stub = new StubInformation(startOffset, isVirtualCall);
|
|
+ ELFMacroAssembler masm = ELFMacroAssembler.getELFMacroAssembler(target, optionValues);
|
|
+ byte[] code;
|
|
+ if (isVirtualCall) {
|
|
+ code = masm.getPLTVirtualEntryCode(stub);
|
|
+ } else {
|
|
+ code = masm.getPLTStaticEntryCode(stub);
|
|
+ }
|
|
+ binaryContainer.appendCodeBytes(code, 0, code.length);
|
|
+ return stub;
|
|
+ }
|
|
+
|
|
+}
|
|
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
|
|
new file mode 100644
|
|
index 000000000..bd127b308
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Collector.java
|
|
@@ -0,0 +1,214 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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;
|
|
+
|
|
+import java.io.BufferedReader;
|
|
+import java.io.FileNotFoundException;
|
|
+import java.io.FileReader;
|
|
+import java.io.IOException;
|
|
+import java.util.ArrayList;
|
|
+import java.util.HashSet;
|
|
+import java.util.List;
|
|
+import java.util.Set;
|
|
+
|
|
+import jdk.tools.jaotc.collect.ClassSearch;
|
|
+import jdk.tools.jaotc.collect.FileSupport;
|
|
+import jdk.tools.jaotc.collect.classname.ClassNameSourceProvider;
|
|
+import jdk.tools.jaotc.collect.directory.DirectorySourceProvider;
|
|
+import jdk.tools.jaotc.collect.jar.JarSourceProvider;
|
|
+import jdk.tools.jaotc.collect.module.ModuleSourceProvider;
|
|
+import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
|
|
+import jdk.vm.ci.meta.MetaAccessProvider;
|
|
+import jdk.vm.ci.meta.ResolvedJavaMethod;
|
|
+import jdk.vm.ci.meta.ResolvedJavaType;
|
|
+
|
|
+final class Collector {
|
|
+
|
|
+ private final Main main;
|
|
+
|
|
+ Collector(Main main) {
|
|
+ this.main = main;
|
|
+ }
|
|
+
|
|
+ Set<Class<?>> collectClassesToCompile() {
|
|
+ Set<Class<?>> classesToCompile = new HashSet<>();
|
|
+ FileSupport fileSupport = new FileSupport();
|
|
+ ClassSearch lookup = new ClassSearch();
|
|
+ lookup.addProvider(new ModuleSourceProvider());
|
|
+ lookup.addProvider(new ClassNameSourceProvider(fileSupport));
|
|
+ lookup.addProvider(new JarSourceProvider());
|
|
+ lookup.addProvider(new DirectorySourceProvider(fileSupport));
|
|
+
|
|
+ List<LoadedClass> foundClasses = null;
|
|
+ try {
|
|
+ foundClasses = lookup.search(main.options.files, main.options.searchPath, this::handleLoadingError);
|
|
+ } catch (InternalError e) {
|
|
+ main.printer.reportError(e);
|
|
+ return null;
|
|
+ }
|
|
+
|
|
+ for (LoadedClass loadedClass : foundClasses) {
|
|
+ classesToCompile.add(loadedClass.getLoadedClass());
|
|
+ }
|
|
+ return classesToCompile;
|
|
+ }
|
|
+
|
|
+ private void addMethods(AOTCompiledClass aotClass, ResolvedJavaMethod[] methods, CompilationSpec compilationRestrictions) {
|
|
+ for (ResolvedJavaMethod m : methods) {
|
|
+ addMethod(aotClass, m, compilationRestrictions);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private void addMethod(AOTCompiledClass aotClass, ResolvedJavaMethod method, CompilationSpec compilationRestrictions) {
|
|
+ // Don't compile native or abstract methods.
|
|
+ if (!method.hasBytecodes()) {
|
|
+ return;
|
|
+ }
|
|
+ if (!compilationRestrictions.shouldCompileMethod(method)) {
|
|
+ return;
|
|
+ }
|
|
+ if (!main.filters.shouldCompileMethod(method)) {
|
|
+ return;
|
|
+ }
|
|
+ assert ((HotSpotResolvedObjectType) method.getDeclaringClass()).getFingerprint() != 0 : "no fingerprint for " + method.getDeclaringClass().getName();
|
|
+
|
|
+ aotClass.addMethod(method);
|
|
+ main.printer.printlnVerbose(" added " + method.getName() + method.getSignature().toMethodDescriptor());
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Collect all method we should compile.
|
|
+ *
|
|
+ * @return array list of AOT classes which have compiled methods.
|
|
+ */
|
|
+ List<AOTCompiledClass> collectMethodsToCompile(Set<Class<?>> classesToCompile, MetaAccessProvider metaAccess) {
|
|
+ int total = 0;
|
|
+ int count = 0;
|
|
+ List<AOTCompiledClass> classes = new ArrayList<>();
|
|
+ CompilationSpec compilationRestrictions = collectSpecifiedMethods();
|
|
+
|
|
+ for (Class<?> c : classesToCompile) {
|
|
+ ResolvedJavaType resolvedJavaType = metaAccess.lookupJavaType(c);
|
|
+ if (main.filters.shouldCompileAnyMethodInClass(resolvedJavaType)) {
|
|
+ AOTCompiledClass aotClass = new AOTCompiledClass(resolvedJavaType);
|
|
+ main.printer.printlnVerbose(" Scanning " + c.getName());
|
|
+
|
|
+ // Constructors
|
|
+ try {
|
|
+ ResolvedJavaMethod[] ctors = resolvedJavaType.getDeclaredConstructors();
|
|
+ addMethods(aotClass, ctors, compilationRestrictions);
|
|
+ total += ctors.length;
|
|
+ } catch (Throwable e) {
|
|
+ handleLoadingError(c.getName(), e);
|
|
+ }
|
|
+
|
|
+ // Methods
|
|
+ try {
|
|
+ ResolvedJavaMethod[] methods = resolvedJavaType.getDeclaredMethods();
|
|
+ addMethods(aotClass, methods, compilationRestrictions);
|
|
+ total += methods.length;
|
|
+ } catch (Throwable e) {
|
|
+ handleLoadingError(c.getName(), e);
|
|
+ }
|
|
+
|
|
+ // Class initializer
|
|
+ try {
|
|
+ ResolvedJavaMethod clinit = resolvedJavaType.getClassInitializer();
|
|
+ if (clinit != null) {
|
|
+ addMethod(aotClass, clinit, compilationRestrictions);
|
|
+ total++;
|
|
+ }
|
|
+ } catch (Throwable e) {
|
|
+ handleLoadingError(c.getName(), e);
|
|
+ }
|
|
+
|
|
+ // Found any methods to compile? Add the class.
|
|
+ if (aotClass.hasMethods()) {
|
|
+ classes.add(aotClass);
|
|
+ count += aotClass.getMethodCount();
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ main.printer.printInfo(total + " methods total, " + count + " methods to compile");
|
|
+ return classes;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * 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();
|
|
+ String methodListFileName = main.options.methodList;
|
|
+
|
|
+ if (methodListFileName != null && !methodListFileName.equals("")) {
|
|
+ try {
|
|
+ FileReader methListFile = new FileReader(methodListFileName);
|
|
+ BufferedReader readBuf = new BufferedReader(methListFile);
|
|
+ String line = null;
|
|
+ while ((line = readBuf.readLine()) != null) {
|
|
+ String trimmedLine = line.trim();
|
|
+ if (!trimmedLine.startsWith("#")) {
|
|
+ String[] components = trimmedLine.split(" ");
|
|
+ if (components.length == 2) {
|
|
+ String directive = components[0];
|
|
+ String pattern = components[1];
|
|
+ switch (directive) {
|
|
+ case "compileOnly":
|
|
+ compilationRestrictions.addCompileOnlyPattern(pattern);
|
|
+ break;
|
|
+ case "exclude":
|
|
+ compilationRestrictions.addExcludePattern(pattern);
|
|
+ break;
|
|
+ default:
|
|
+ System.out.println("Unrecognized command " + directive + ". Ignoring\n\t" + line + "\n encountered in " + methodListFileName);
|
|
+ }
|
|
+ } else {
|
|
+ if (!trimmedLine.equals("")) {
|
|
+ System.out.println("Ignoring malformed line:\n\t " + line + "\n");
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ readBuf.close();
|
|
+ } catch (FileNotFoundException e) {
|
|
+ throw new InternalError("Unable to open method list file: " + methodListFileName, e);
|
|
+ } catch (IOException e) {
|
|
+ throw new InternalError("Unable to read method list file: " + methodListFileName, e);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return compilationRestrictions;
|
|
+ }
|
|
+
|
|
+ private void handleLoadingError(String name, Throwable t) {
|
|
+ if (main.options.ignoreClassLoadingErrors) {
|
|
+ main.printer.printError(name + ": " + t);
|
|
+ } else {
|
|
+ throw new InternalError(t);
|
|
+ }
|
|
+ }
|
|
+}
|
|
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
|
|
new file mode 100644
|
|
index 000000000..19662c52b
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CompilationSpec.java
|
|
@@ -0,0 +1,127 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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;
|
|
+
|
|
+import java.util.HashSet;
|
|
+import java.util.Iterator;
|
|
+import java.util.regex.Pattern;
|
|
+
|
|
+import jdk.vm.ci.meta.ResolvedJavaMethod;
|
|
+
|
|
+/**
|
|
+ * A class encapsulating any user-specified compilation restrictions.
|
|
+ */
|
|
+final class CompilationSpec {
|
|
+
|
|
+ /**
|
|
+ * Set of method names to restrict compilation to.
|
|
+ */
|
|
+ private HashSet<String> compileOnlyStrings = new HashSet<>();
|
|
+ private HashSet<Pattern> compileOnlyPatterns = new HashSet<>();
|
|
+
|
|
+ /**
|
|
+ * Set of method names that should be excluded from compilation.
|
|
+ */
|
|
+ private HashSet<String> excludeStrings = new HashSet<>();
|
|
+ private HashSet<Pattern> excludePatterns = new HashSet<>();
|
|
+
|
|
+ /**
|
|
+ * Add a {@code compileOnly} directive to the compile-only list.
|
|
+ *
|
|
+ * @param pattern regex or non-regex pattern string
|
|
+ */
|
|
+ void addCompileOnlyPattern(String pattern) {
|
|
+ if (pattern.contains("*")) {
|
|
+ compileOnlyPatterns.add(Pattern.compile(pattern));
|
|
+ } else {
|
|
+ compileOnlyStrings.add(pattern);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Add an {@code exclude} directive to the exclude list.
|
|
+ *
|
|
+ * @param pattern regex or non-regex pattern string
|
|
+ */
|
|
+ void addExcludePattern(String pattern) {
|
|
+ if (pattern.contains("*")) {
|
|
+ excludePatterns.add(Pattern.compile(pattern));
|
|
+ } else {
|
|
+ excludeStrings.add(pattern);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Check if a given method is part of a restrictive compilation.
|
|
+ *
|
|
+ * @param method method to be checked
|
|
+ * @return true or false
|
|
+ */
|
|
+ boolean shouldCompileMethod(ResolvedJavaMethod method) {
|
|
+ if (compileWithRestrictions()) {
|
|
+ // If there are user-specified compileOnly patterns, default action
|
|
+ // is not to compile the method.
|
|
+ boolean compileMethod = compileOnlyStrings.isEmpty() && compileOnlyPatterns.isEmpty();
|
|
+
|
|
+ // Check if the method matches with any of the specified compileOnly patterns.
|
|
+ String methodName = JavaMethodInfo.uniqueMethodName(method);
|
|
+
|
|
+ // compileOnly
|
|
+ if (!compileMethod) {
|
|
+ compileMethod = compileOnlyStrings.contains(methodName);
|
|
+ }
|
|
+ if (!compileMethod) {
|
|
+ Iterator<Pattern> it = compileOnlyPatterns.iterator();
|
|
+ while (!compileMethod && it.hasNext()) {
|
|
+ Pattern pattern = it.next();
|
|
+ compileMethod = pattern.matcher(methodName).matches();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // exclude
|
|
+ if (compileMethod) {
|
|
+ compileMethod = !excludeStrings.contains(methodName);
|
|
+ }
|
|
+ if (compileMethod) {
|
|
+ Iterator<Pattern> it = excludePatterns.iterator();
|
|
+ while (compileMethod && it.hasNext()) {
|
|
+ Pattern pattern = it.next();
|
|
+ compileMethod = !(pattern.matcher(methodName).matches());
|
|
+ }
|
|
+ }
|
|
+ return compileMethod;
|
|
+ }
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Return true if compilation restrictions are specified.
|
|
+ */
|
|
+ private boolean compileWithRestrictions() {
|
|
+ return !(compileOnlyStrings.isEmpty() && compileOnlyPatterns.isEmpty() && excludeStrings.isEmpty() && excludePatterns.isEmpty());
|
|
+ }
|
|
+
|
|
+}
|
|
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
|
|
new file mode 100644
|
|
index 000000000..49db6afbb
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CompiledMethodInfo.java
|
|
@@ -0,0 +1,341 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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;
|
|
+
|
|
+import java.util.HashMap;
|
|
+import java.util.HashSet;
|
|
+import java.util.concurrent.atomic.AtomicInteger;
|
|
+
|
|
+import org.graalvm.compiler.code.CompilationResult;
|
|
+import org.graalvm.compiler.hotspot.HotSpotMarkId;
|
|
+
|
|
+import jdk.tools.jaotc.AOTCompiledClass.AOTKlassData;
|
|
+import jdk.tools.jaotc.binformat.BinaryContainer;
|
|
+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;
|
|
+
|
|
+final class CompiledMethodInfo {
|
|
+
|
|
+ static final String archStr = System.getProperty("os.arch").toLowerCase();
|
|
+
|
|
+ private static final int UNINITIALIZED_OFFSET = -1;
|
|
+
|
|
+ private static class AOTMethodOffsets {
|
|
+ /**
|
|
+ * Offset in metaspace names section.
|
|
+ */
|
|
+ private int nameOffset;
|
|
+
|
|
+ /**
|
|
+ * Offset in the text section at which compiled code starts.
|
|
+ */
|
|
+ private int textSectionOffset;
|
|
+
|
|
+ /**
|
|
+ * Offset in the metadata section.
|
|
+ */
|
|
+ private int metadataOffset;
|
|
+
|
|
+ /**
|
|
+ * Offset to the metadata in the GOT table.
|
|
+ */
|
|
+ private int metadataGotOffset;
|
|
+
|
|
+ /**
|
|
+ * Size of the metadata.
|
|
+ */
|
|
+ private int metadataGotSize;
|
|
+
|
|
+ /**
|
|
+ * The sequential number corresponding to the order of methods code in code buffer.
|
|
+ */
|
|
+ private int codeId;
|
|
+
|
|
+ AOTMethodOffsets() {
|
|
+ this.nameOffset = UNINITIALIZED_OFFSET;
|
|
+ this.textSectionOffset = UNINITIALIZED_OFFSET;
|
|
+ this.metadataOffset = UNINITIALIZED_OFFSET;
|
|
+ this.metadataGotOffset = UNINITIALIZED_OFFSET;
|
|
+ this.metadataGotSize = -1;
|
|
+ this.codeId = -1;
|
|
+ }
|
|
+
|
|
+ void addMethodOffsets(ReadOnlyDataContainer container, String name) {
|
|
+ verify(name);
|
|
+ // @formatter:off
|
|
+ /*
|
|
+ * The offsets layout should match AOTMethodOffsets structure in AOT JVM runtime
|
|
+ */
|
|
+ // Add the offset to the name in the .metaspace.names section
|
|
+ container.appendInt(nameOffset).
|
|
+ // Add the offset to the code in the .text section
|
|
+ appendInt(textSectionOffset).
|
|
+ // Add the offset to the metadata in the .method.metadata section
|
|
+ appendInt(metadataOffset).
|
|
+ // Add the offset to the metadata in the .metadata.got section
|
|
+ appendInt(metadataGotOffset).
|
|
+ // Add the size of the metadata
|
|
+ appendInt(metadataGotSize).
|
|
+ // Add code ID.
|
|
+ appendInt(codeId);
|
|
+ // @formatter:on
|
|
+ }
|
|
+
|
|
+ private void verify(String name) {
|
|
+ assert nameOffset >= 0 : "incorrect nameOffset: " + nameOffset + " for method: " + name;
|
|
+ assert textSectionOffset > 0 : "incorrect textSectionOffset: " + textSectionOffset + " for method: " + name;
|
|
+ assert metadataOffset >= 0 : "incorrect metadataOffset: " + metadataOffset + " for method: " + name;
|
|
+ assert metadataGotOffset >= 0 : "incorrect metadataGotOffset: " + metadataGotOffset + " for method: " + name;
|
|
+ assert metadataGotSize >= 0 : "incorrect metadataGotSize: " + metadataGotSize + " for method: " + name;
|
|
+ assert codeId >= 0 : "incorrect codeId: " + codeId + " for method: " + name;
|
|
+ }
|
|
+
|
|
+ protected void setNameOffset(int offset) {
|
|
+ nameOffset = offset;
|
|
+ }
|
|
+
|
|
+ protected void setTextSectionOffset(int textSectionOffset) {
|
|
+ this.textSectionOffset = textSectionOffset;
|
|
+ }
|
|
+
|
|
+ protected int getTextSectionOffset() {
|
|
+ return textSectionOffset;
|
|
+ }
|
|
+
|
|
+ protected void setCodeId(int codeId) {
|
|
+ this.codeId = codeId;
|
|
+ }
|
|
+
|
|
+ protected int getCodeId() {
|
|
+ return codeId;
|
|
+ }
|
|
+
|
|
+ protected void setMetadataOffset(int offset) {
|
|
+ metadataOffset = offset;
|
|
+ }
|
|
+
|
|
+ protected void setMetadataGotOffset(int metadataGotOffset) {
|
|
+ this.metadataGotOffset = metadataGotOffset;
|
|
+ }
|
|
+
|
|
+ protected void setMetadataGotSize(int length) {
|
|
+ this.metadataGotSize = length;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Method name.
|
|
+ */
|
|
+ private String name;
|
|
+
|
|
+ /**
|
|
+ * Result of graal compilation.
|
|
+ */
|
|
+ private CompilationResult compilationResult;
|
|
+
|
|
+ /**
|
|
+ * HotSpotResolvedJavaMethod or Stub corresponding to the compilation result.
|
|
+ */
|
|
+ private JavaMethodInfo methodInfo;
|
|
+
|
|
+ /**
|
|
+ * Compiled code from installation.
|
|
+ */
|
|
+ private HotSpotCompiledCode code;
|
|
+
|
|
+ /**
|
|
+ * Offset to stubs.
|
|
+ */
|
|
+ private int stubsOffset;
|
|
+
|
|
+ /**
|
|
+ * The total size in bytes of the stub section.
|
|
+ */
|
|
+ private int totalStubSize;
|
|
+
|
|
+ /**
|
|
+ * Method's offsets.
|
|
+ */
|
|
+ private AOTMethodOffsets methodOffsets;
|
|
+
|
|
+ /**
|
|
+ * List of stubs (PLT trampoline).
|
|
+ */
|
|
+ private HashMap<String, StubInformation> stubs = new HashMap<>();
|
|
+
|
|
+ /**
|
|
+ * List of referenced classes.
|
|
+ */
|
|
+ private HashSet<AOTKlassData> dependentKlasses = new HashSet<>();
|
|
+
|
|
+ /**
|
|
+ * Methods count used to generate unique global method id.
|
|
+ */
|
|
+ private static final AtomicInteger methodsCount = new AtomicInteger();
|
|
+
|
|
+ CompiledMethodInfo(CompilationResult compilationResult, JavaMethodInfo methodInfo) {
|
|
+ this.name = methodInfo.getNameAndSignature();
|
|
+ this.compilationResult = compilationResult;
|
|
+ this.methodInfo = methodInfo;
|
|
+ this.stubsOffset = UNINITIALIZED_OFFSET;
|
|
+ this.methodOffsets = new AOTMethodOffsets();
|
|
+ }
|
|
+
|
|
+ String name() {
|
|
+ return name;
|
|
+ }
|
|
+
|
|
+ void addMethodOffsets(BinaryContainer binaryContainer, ReadOnlyDataContainer container) {
|
|
+ this.methodOffsets.setNameOffset(binaryContainer.addMetaspaceName(name));
|
|
+ this.methodOffsets.addMethodOffsets(container, name);
|
|
+ for (AOTKlassData data : dependentKlasses) {
|
|
+ data.addDependentMethod(this);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ CompilationResult getCompilationResult() {
|
|
+ return compilationResult;
|
|
+ }
|
|
+
|
|
+ JavaMethodInfo getMethodInfo() {
|
|
+ return methodInfo;
|
|
+ }
|
|
+
|
|
+ void setTextSectionOffset(int textSectionOffset) {
|
|
+ methodOffsets.setTextSectionOffset(textSectionOffset);
|
|
+ }
|
|
+
|
|
+ public int getTextSectionOffset() {
|
|
+ return methodOffsets.getTextSectionOffset();
|
|
+ }
|
|
+
|
|
+ void setCodeId() {
|
|
+ methodOffsets.setCodeId(CompiledMethodInfo.getNextCodeId());
|
|
+ }
|
|
+
|
|
+ int getCodeId() {
|
|
+ return this.methodOffsets.getCodeId();
|
|
+ }
|
|
+
|
|
+ static int getMethodsCount() {
|
|
+ return methodsCount.get();
|
|
+ }
|
|
+
|
|
+ static int getNextCodeId() {
|
|
+ return methodsCount.getAndIncrement();
|
|
+ }
|
|
+
|
|
+ int getCodeSize() {
|
|
+ return stubsOffset + getStubCodeSize();
|
|
+ }
|
|
+
|
|
+ int getStubCodeSize() {
|
|
+ return totalStubSize;
|
|
+ }
|
|
+
|
|
+ void setMetadataOffset(int offset) {
|
|
+ this.methodOffsets.setMetadataOffset(offset);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Offset into the code of this method where the stub section starts.
|
|
+ */
|
|
+ void setStubsOffset(int offset) {
|
|
+ stubsOffset = offset;
|
|
+ }
|
|
+
|
|
+ int getStubsOffset() {
|
|
+ return stubsOffset;
|
|
+ }
|
|
+
|
|
+ void setMetadataGotOffset(int metadataGotOffset) {
|
|
+ this.methodOffsets.setMetadataGotOffset(metadataGotOffset);
|
|
+ }
|
|
+
|
|
+ void setMetadataGotSize(int length) {
|
|
+ this.methodOffsets.setMetadataGotSize(length);
|
|
+ }
|
|
+
|
|
+ void addStubCode(String call, StubInformation stub) {
|
|
+ stubs.put(call, stub);
|
|
+ totalStubSize += stub.getSize();
|
|
+ }
|
|
+
|
|
+ StubInformation getStubFor(String call) {
|
|
+ StubInformation stub = stubs.get(call);
|
|
+ assert stub != null : "missing stub for call " + call;
|
|
+ stub.verify();
|
|
+ return stub;
|
|
+ }
|
|
+
|
|
+ void addDependentKlassData(BinaryContainer binaryContainer, HotSpotResolvedObjectType type) {
|
|
+ AOTKlassData klassData = AOTCompiledClass.addFingerprintKlassData(binaryContainer, type);
|
|
+ dependentKlasses.add(klassData);
|
|
+ }
|
|
+
|
|
+ AOTKlassData getDependentKlassData(HotSpotResolvedObjectType type) {
|
|
+ AOTKlassData klassData = AOTCompiledClass.getAOTKlassData(type);
|
|
+ if (dependentKlasses.contains(klassData)) {
|
|
+ return klassData;
|
|
+ }
|
|
+ return null;
|
|
+ }
|
|
+
|
|
+ boolean hasMark(Call call, HotSpotMarkId id) {
|
|
+ assert id == HotSpotMarkId.INVOKESTATIC || id == HotSpotMarkId.INVOKESPECIAL;
|
|
+ CompilationResult.CodeMark mark = compilationResult.getAssociatedMark(call);
|
|
+ if (mark != null) {
|
|
+ return mark.id == id;
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ String asTag() {
|
|
+ return "[" + methodInfo.getSymbolName() + "]";
|
|
+ }
|
|
+
|
|
+ HotSpotCompiledCode compiledCode() {
|
|
+ if (code == null) {
|
|
+ code = methodInfo.compiledCode(compilationResult);
|
|
+ }
|
|
+ return code;
|
|
+ }
|
|
+
|
|
+ // Free memory
|
|
+ void clear() {
|
|
+ this.dependentKlasses = null;
|
|
+ this.name = null;
|
|
+ }
|
|
+
|
|
+ void clearCompileData() {
|
|
+ this.code = null;
|
|
+ this.stubs = null;
|
|
+ this.compilationResult = null;
|
|
+ this.methodInfo = null;
|
|
+ }
|
|
+}
|
|
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
|
|
new file mode 100644
|
|
index 000000000..949124ffe
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataBuilder.java
|
|
@@ -0,0 +1,243 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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;
|
|
+
|
|
+import java.util.ArrayList;
|
|
+import java.util.HashMap;
|
|
+import java.util.List;
|
|
+import java.util.Map.Entry;
|
|
+
|
|
+import org.graalvm.compiler.code.CompilationResult;
|
|
+import org.graalvm.compiler.debug.DebugContext;
|
|
+import org.graalvm.compiler.hotspot.HotSpotHostBackend;
|
|
+import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProvider;
|
|
+import org.graalvm.compiler.hotspot.stubs.Stub;
|
|
+
|
|
+import jdk.tools.jaotc.binformat.BinaryContainer;
|
|
+import jdk.tools.jaotc.binformat.ByteContainer;
|
|
+import jdk.tools.jaotc.binformat.HeaderContainer;
|
|
+import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
|
|
+import jdk.vm.ci.hotspot.HotSpotVMConfigStore;
|
|
+import jdk.vm.ci.hotspot.VMField;
|
|
+
|
|
+final class DataBuilder {
|
|
+
|
|
+ private final Main main;
|
|
+
|
|
+ private final HotSpotHostBackend backend;
|
|
+
|
|
+ private final List<AOTCompiledClass> classes;
|
|
+
|
|
+ /**
|
|
+ * Target-independent container in which text symbols and code bytes are created.
|
|
+ */
|
|
+ private final BinaryContainer binaryContainer;
|
|
+
|
|
+ private static final HashMap<Long, String> vmAddresses = new HashMap<>();
|
|
+
|
|
+ DataBuilder(Main main, HotSpotHostBackend backend, List<AOTCompiledClass> classes, BinaryContainer binaryContainer) {
|
|
+ this.main = main;
|
|
+ this.backend = backend;
|
|
+ this.classes = classes;
|
|
+ this.binaryContainer = binaryContainer;
|
|
+ fillVMAddresses(HotSpotJVMCIRuntime.runtime().getConfigStore());
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Returns a value-name map of all {@link VMField} fields.
|
|
+ */
|
|
+ private static void fillVMAddresses(HotSpotVMConfigStore config) {
|
|
+ for (VMField vmField : config.getFields().values()) {
|
|
+ if (vmField.value != null && vmField.value instanceof Long) {
|
|
+ final long address = (Long) vmField.value;
|
|
+ String value = vmField.name;
|
|
+ /*
|
|
+ * Some fields don't contain addresses but integer values. At least don't add zero
|
|
+ * entries to avoid matching null addresses.
|
|
+ */
|
|
+ if (address != 0) {
|
|
+ vmAddresses.put(address, value);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ for (Entry<String, Long> vmAddress : config.getAddresses().entrySet()) {
|
|
+ final long address = vmAddress.getValue();
|
|
+ String value = vmAddress.getKey();
|
|
+ String old = vmAddresses.put(address, value);
|
|
+ if (old != null) {
|
|
+ throw new InternalError("already in map: address: " + address + ", current: " + value + ", old: " + old);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Get the C/C++ function name associated with the foreign call target {@code address}.
|
|
+ *
|
|
+ * @param address native address
|
|
+ * @return C/C++ functio name associated with the native address
|
|
+ */
|
|
+ static String getVMFunctionNameForAddress(long address) {
|
|
+ return vmAddresses.get(address);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Returns the host backend used for this compilation.
|
|
+ *
|
|
+ * @return host backend
|
|
+ */
|
|
+ HotSpotHostBackend getBackend() {
|
|
+ return backend;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Returns the binary container for this compilation.
|
|
+ *
|
|
+ * @return binary container
|
|
+ */
|
|
+ BinaryContainer getBinaryContainer() {
|
|
+ return binaryContainer;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Prepare data with all compiled classes and stubs.
|
|
+ *
|
|
+ * @param debug
|
|
+ *
|
|
+ * @throws Exception
|
|
+ */
|
|
+ @SuppressWarnings("try")
|
|
+ void prepareData(DebugContext debug) throws Exception {
|
|
+ try (Timer t = new Timer(main, "Parsing compiled code")) {
|
|
+ /*
|
|
+ * Copy compiled code into code section container and calls stubs (PLT trampoline).
|
|
+ */
|
|
+ CodeSectionProcessor codeSectionProcessor = new CodeSectionProcessor(this);
|
|
+ for (AOTCompiledClass c : classes) {
|
|
+ // For each class we need 2 GOT slots:
|
|
+ // first - for initialized klass
|
|
+ // second - only for loaded klass
|
|
+ c.addAOTKlassData(binaryContainer);
|
|
+ codeSectionProcessor.process(c);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ AOTCompiledClass stubCompiledCode = retrieveStubCode(debug);
|
|
+
|
|
+ // Free memory!
|
|
+ try (Timer t = main.options.verbose ? new Timer(main, "Freeing memory") : null) {
|
|
+ main.printer.printMemoryUsage();
|
|
+ System.gc();
|
|
+ }
|
|
+
|
|
+ MetadataBuilder metadataBuilder = null;
|
|
+ try (Timer t = new Timer(main, "Processing metadata")) {
|
|
+ /*
|
|
+ * Generate metadata for compiled code and copy it into metadata section. Create
|
|
+ * relocation information for all references (call, constants, etc) in compiled code.
|
|
+ */
|
|
+ metadataBuilder = new MetadataBuilder(this);
|
|
+ metadataBuilder.processMetadata(classes, stubCompiledCode);
|
|
+ }
|
|
+
|
|
+ // Free memory!
|
|
+ try (Timer t = main.options.verbose ? new Timer(main, "Freeing memory") : null) {
|
|
+ main.printer.printMemoryUsage();
|
|
+ System.gc();
|
|
+ }
|
|
+
|
|
+ try (Timer t = new Timer(main, "Preparing stubs binary")) {
|
|
+ prepareStubsBinary(stubCompiledCode);
|
|
+ }
|
|
+ try (Timer t = new Timer(main, "Preparing compiled binary")) {
|
|
+ // Should be called after Stubs because they can set dependent klasses.
|
|
+ prepareCompiledBinary();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Get all stubs from Graal and add them to the code section.
|
|
+ *
|
|
+ * @param debug
|
|
+ */
|
|
+ @SuppressWarnings("try")
|
|
+ private AOTCompiledClass retrieveStubCode(DebugContext debug) {
|
|
+ ArrayList<CompiledMethodInfo> stubs = new ArrayList<>();
|
|
+ HotSpotForeignCallsProvider foreignCallsProvider = backend.getProviders().getForeignCalls();
|
|
+ for (Stub stub : foreignCallsProvider.getStubs()) {
|
|
+ try (DebugContext.Scope scope = debug.scope("CompileStubs")) {
|
|
+ CompilationResult result = stub.getCompilationResult(debug, backend);
|
|
+ CompiledMethodInfo cm = new CompiledMethodInfo(result, new AOTStub(stub, backend, debug.getOptions()));
|
|
+ stubs.add(cm);
|
|
+ } catch (Throwable e) {
|
|
+ throw debug.handle(e);
|
|
+ }
|
|
+ }
|
|
+ AOTCompiledClass stubCompiledCode = new AOTCompiledClass(stubs);
|
|
+ CodeSectionProcessor codeSectionProcessor = new CodeSectionProcessor(this);
|
|
+ codeSectionProcessor.process(stubCompiledCode);
|
|
+ return stubCompiledCode;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Prepare metaspace.offsets section.
|
|
+ */
|
|
+ private void prepareCompiledBinary() {
|
|
+ for (AOTCompiledClass c : classes) {
|
|
+ // Create records for compiled AOT methods.
|
|
+ c.putMethodsData(binaryContainer);
|
|
+ }
|
|
+ // Create records for compiled AOT classes.
|
|
+ AOTCompiledClass.putAOTKlassData(binaryContainer);
|
|
+
|
|
+ // Fill in AOTHeader
|
|
+ HeaderContainer header = binaryContainer.getHeaderContainer();
|
|
+ header.setClassesCount(AOTCompiledClass.getClassesCount());
|
|
+ header.setMethodsCount(CompiledMethodInfo.getMethodsCount());
|
|
+ // Record size of got sections
|
|
+ ByteContainer bc = binaryContainer.getKlassesGotContainer();
|
|
+ header.setKlassesGotSize((bc.getByteStreamSize() / 8));
|
|
+ bc = binaryContainer.getMetadataGotContainer();
|
|
+ header.setMetadataGotSize((bc.getByteStreamSize() / 8));
|
|
+ bc = binaryContainer.getOopGotContainer();
|
|
+ header.setOopGotSize((bc.getByteStreamSize() / 8));
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Prepare stubs.offsets section.
|
|
+ */
|
|
+ private void prepareStubsBinary(AOTCompiledClass compiledClass) {
|
|
+ // For each of the compiled stubs, create records holding information about
|
|
+ // them.
|
|
+ ArrayList<CompiledMethodInfo> compiledStubs = compiledClass.getCompiledMethods();
|
|
+ int cntStubs = compiledStubs.size();
|
|
+ BinaryContainer.addMethodsCount(cntStubs, binaryContainer.getStubsOffsetsContainer());
|
|
+ for (CompiledMethodInfo methodInfo : compiledStubs) {
|
|
+ // Note, stubs have different offsets container.
|
|
+ methodInfo.addMethodOffsets(binaryContainer, binaryContainer.getStubsOffsetsContainer());
|
|
+ }
|
|
+ }
|
|
+
|
|
+}
|
|
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
|
|
new file mode 100644
|
|
index 000000000..c6b141b1f
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataPatchProcessor.java
|
|
@@ -0,0 +1,165 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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;
|
|
+
|
|
+import java.nio.ByteBuffer;
|
|
+import java.nio.ByteOrder;
|
|
+
|
|
+import org.graalvm.compiler.code.DataSection;
|
|
+import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction;
|
|
+
|
|
+import jdk.tools.jaotc.binformat.BinaryContainer;
|
|
+import jdk.tools.jaotc.binformat.Relocation;
|
|
+import jdk.tools.jaotc.binformat.Relocation.RelocType;
|
|
+import jdk.tools.jaotc.binformat.Symbol;
|
|
+import jdk.tools.jaotc.binformat.Symbol.Binding;
|
|
+import jdk.tools.jaotc.binformat.Symbol.Kind;
|
|
+import jdk.vm.ci.code.TargetDescription;
|
|
+import jdk.vm.ci.code.site.ConstantReference;
|
|
+import jdk.vm.ci.code.site.DataPatch;
|
|
+import jdk.vm.ci.code.site.DataSectionReference;
|
|
+import jdk.vm.ci.code.site.Reference;
|
|
+import jdk.vm.ci.hotspot.HotSpotConstantPoolObject;
|
|
+import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
|
|
+import jdk.vm.ci.hotspot.HotSpotObjectConstant;
|
|
+import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
|
|
+import jdk.vm.ci.hotspot.HotSpotSentinelConstant;
|
|
+import jdk.vm.ci.meta.JavaConstant;
|
|
+import jdk.vm.ci.meta.VMConstant;
|
|
+
|
|
+final class DataPatchProcessor {
|
|
+
|
|
+ private final TargetDescription target;
|
|
+
|
|
+ private final BinaryContainer binaryContainer;
|
|
+
|
|
+ DataPatchProcessor(DataBuilder dataBuilder) {
|
|
+ this.target = dataBuilder.getBackend().getTarget();
|
|
+ this.binaryContainer = dataBuilder.getBinaryContainer();
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Process a {@link DataPatch} generated by the compiler and create all needed binary section
|
|
+ * constructs.
|
|
+ */
|
|
+ void process(CompiledMethodInfo methodInfo, DataPatch dataPatch) {
|
|
+ Reference reference = dataPatch.reference;
|
|
+ if (reference instanceof ConstantReference) {
|
|
+ processConstantReference(dataPatch, methodInfo);
|
|
+ } else if (reference instanceof DataSectionReference) {
|
|
+ processDataSectionReference(dataPatch, methodInfo);
|
|
+ } else {
|
|
+ throw new InternalError("Unknown data patch reference: " + reference);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private void processConstantReference(DataPatch dataPatch, CompiledMethodInfo methodInfo) {
|
|
+ HotSpotConstantLoadAction action = (HotSpotConstantLoadAction) dataPatch.note;
|
|
+ ConstantReference constantReference = (ConstantReference) dataPatch.reference;
|
|
+ assert action != null : "action should be set";
|
|
+
|
|
+ VMConstant constant = constantReference.getConstant();
|
|
+ String targetSymbol = null;
|
|
+ String gotName = null;
|
|
+ if (constant instanceof HotSpotMetaspaceConstant) {
|
|
+ HotSpotMetaspaceConstant metaspaceConstant = (HotSpotMetaspaceConstant) constant;
|
|
+ if (metaspaceConstant.asResolvedJavaType() != null) {
|
|
+ HotSpotResolvedObjectType type = metaspaceConstant.asResolvedJavaType();
|
|
+ methodInfo.addDependentKlassData(binaryContainer, type);
|
|
+ targetSymbol = AOTCompiledClass.metadataName(type);
|
|
+ gotName = ((action == HotSpotConstantLoadAction.INITIALIZE) ? "got.init." : "got.") + targetSymbol;
|
|
+ } else if (metaspaceConstant.asResolvedJavaMethod() != null && action == HotSpotConstantLoadAction.LOAD_COUNTERS) {
|
|
+ targetSymbol = "counters." + JavaMethodInfo.uniqueMethodName(metaspaceConstant.asResolvedJavaMethod());
|
|
+ gotName = "got." + targetSymbol;
|
|
+ binaryContainer.addCountersSymbol(targetSymbol);
|
|
+ }
|
|
+ } else if (constant instanceof JavaConstant) {
|
|
+ JavaConstant jConstant = (JavaConstant) constant;
|
|
+ if (jConstant instanceof HotSpotConstantPoolObject) {
|
|
+ HotSpotConstantPoolObject cpo = (HotSpotConstantPoolObject) jConstant;
|
|
+ // Even if two locations use the same object, resolve separately
|
|
+ targetSymbol = "ldc." + cpo.toValueString();
|
|
+ Integer offset = binaryContainer.addOopSymbol(targetSymbol);
|
|
+ gotName = "got.ldc." + offset;
|
|
+ } else if (jConstant instanceof HotSpotObjectConstant) {
|
|
+ HotSpotObjectConstant oopConstant = (HotSpotObjectConstant) jConstant;
|
|
+ // String constant.
|
|
+ targetSymbol = "ldc." + oopConstant.toValueString();
|
|
+ Integer offset = binaryContainer.addOopSymbol(targetSymbol);
|
|
+ gotName = "got.ldc." + offset;
|
|
+ } else if (jConstant instanceof HotSpotSentinelConstant) {
|
|
+ targetSymbol = "state.M" + methodInfo.getCodeId();
|
|
+ gotName = "got." + targetSymbol;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ assert gotName != null : "Unknown constant type: " + constant;
|
|
+
|
|
+ InstructionDecoder decoder = InstructionDecoder.getInstructionDecoder(target);
|
|
+ decoder.decodePosition(methodInfo.getCompilationResult().getTargetCode(), dataPatch.pcOffset);
|
|
+ int instructionEndOffset = decoder.currentEndOfInstruction();
|
|
+
|
|
+ int textBaseOffset = methodInfo.getTextSectionOffset();
|
|
+ int relocOffset = textBaseOffset + instructionEndOffset;
|
|
+
|
|
+ Symbol relocationSymbol = binaryContainer.getSymbol(gotName);
|
|
+ assert relocationSymbol != null : "symbol for " + gotName + " missing";
|
|
+ Relocation reloc = new Relocation(relocOffset, RelocType.METASPACE_GOT_REFERENCE, 0, binaryContainer.getCodeContainer(), relocationSymbol);
|
|
+ binaryContainer.addRelocation(reloc);
|
|
+ }
|
|
+
|
|
+ private void processDataSectionReference(DataPatch dataPatch, CompiledMethodInfo methodInfo) {
|
|
+ DataSectionReference dataReference = (DataSectionReference) dataPatch.reference;
|
|
+
|
|
+ InstructionDecoder decoder = InstructionDecoder.getInstructionDecoder(target);
|
|
+ decoder.decodePosition(methodInfo.getCompilationResult().getTargetCode(), dataPatch.pcOffset);
|
|
+ int instructionEndOffset = decoder.currentEndOfInstruction();
|
|
+
|
|
+ int textBaseOffset = methodInfo.getTextSectionOffset();
|
|
+ int relocOffset = textBaseOffset + instructionEndOffset;
|
|
+ int dataOffset = dataReference.getOffset();
|
|
+
|
|
+ DataSection dataSection = methodInfo.getCompilationResult().getDataSection();
|
|
+ DataSection.Data data = dataSection.findData(dataReference);
|
|
+ int size = data.getSize();
|
|
+ int alignment = data.getAlignment();
|
|
+ byte[] value = new byte[size];
|
|
+ ByteBuffer buffer = ByteBuffer.wrap(value).order(ByteOrder.nativeOrder());
|
|
+ DataSection.emit(buffer, data, (p, c) -> {
|
|
+ });
|
|
+ String targetSymbol = "data.M" + methodInfo.getCodeId() + "." + dataOffset;
|
|
+ Symbol relocationSymbol = binaryContainer.getSymbol(targetSymbol);
|
|
+ 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);
|
|
+ }
|
|
+ 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/ELFMacroAssembler.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/ELFMacroAssembler.java
|
|
new file mode 100644
|
|
index 000000000..f305e5ee1
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/ELFMacroAssembler.java
|
|
@@ -0,0 +1,58 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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;
|
|
+
|
|
+import org.graalvm.compiler.options.OptionValues;
|
|
+
|
|
+import jdk.tools.jaotc.aarch64.AArch64ELFMacroAssembler;
|
|
+import jdk.tools.jaotc.amd64.AMD64ELFMacroAssembler;
|
|
+import jdk.vm.ci.aarch64.AArch64;
|
|
+import jdk.vm.ci.amd64.AMD64;
|
|
+import jdk.vm.ci.code.Architecture;
|
|
+import jdk.vm.ci.code.TargetDescription;
|
|
+
|
|
+public interface ELFMacroAssembler {
|
|
+
|
|
+ static ELFMacroAssembler getELFMacroAssembler(TargetDescription target, OptionValues optionValues) {
|
|
+ Architecture architecture = target.arch;
|
|
+ if (architecture instanceof AMD64) {
|
|
+ return new AMD64ELFMacroAssembler(target, optionValues);
|
|
+ } else if (architecture instanceof AArch64) {
|
|
+ return new AArch64ELFMacroAssembler(target);
|
|
+ } else {
|
|
+ throw new InternalError("Unsupported architecture " + architecture);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ int currentEndOfInstruction();
|
|
+
|
|
+ byte[] getPLTJumpCode();
|
|
+
|
|
+ byte[] getPLTStaticEntryCode(StubInformation stub);
|
|
+
|
|
+ byte[] getPLTVirtualEntryCode(StubInformation stub);
|
|
+
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/ForeignCallSiteRelocationInfo.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/ForeignCallSiteRelocationInfo.java
|
|
new file mode 100644
|
|
index 000000000..f7a5b7f8a
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/ForeignCallSiteRelocationInfo.java
|
|
@@ -0,0 +1,75 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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;
|
|
+
|
|
+import jdk.tools.jaotc.binformat.BinaryContainer;
|
|
+import jdk.tools.jaotc.binformat.Relocation.RelocType;
|
|
+import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
|
|
+
|
|
+import jdk.vm.ci.code.site.Call;
|
|
+
|
|
+/**
|
|
+ * This is a foreign call site. This means either a call to the VM or a call to a Graal stub. If
|
|
+ * it's a call directly to the VM, mangle the name. The call should go through regular .plt used by
|
|
+ * the system loader, at least for now. If it's a call to a Graal stub, it should always be a direct
|
|
+ * call, since the Graal stubs are contained within the .so file.
|
|
+ */
|
|
+final class ForeignCallSiteRelocationInfo extends CallSiteRelocationInfo {
|
|
+
|
|
+ ForeignCallSiteRelocationInfo(Call call, HotSpotForeignCallLinkage callTarget) {
|
|
+ super(getTargetSymbol(call, callTarget), getRelocType(callTarget));
|
|
+ }
|
|
+
|
|
+ private static String getTargetSymbol(Call call, HotSpotForeignCallLinkage callTarget) {
|
|
+ // If it specifies a foreign call linkage, find the symbol corresponding to the address in
|
|
+ // HotSpotVMConfig's fields.
|
|
+ final long foreignCallTargetAddress = callTarget.getAddress();
|
|
+
|
|
+ // Get the C/C++ function name associated with the foreign call target address.
|
|
+ String functionName = DataBuilder.getVMFunctionNameForAddress(foreignCallTargetAddress);
|
|
+ if (functionName != null) {
|
|
+ // Use the known global AOT symbol associated with function name, if one exists
|
|
+ String aotSymbol = BinaryContainer.getAOTSymbolForVMFunctionName(functionName);
|
|
+ if (aotSymbol == null) {
|
|
+ throw new InternalError("no global symbol found for: " + functionName);
|
|
+ }
|
|
+ return aotSymbol;
|
|
+ }
|
|
+
|
|
+ // Is it a Graal stub we are calling?
|
|
+ if (callTarget.isCompiledStub()) {
|
|
+ assert call.direct : "Should always be a direct call to stubs";
|
|
+ return callTarget.getSymbol();
|
|
+ }
|
|
+
|
|
+ throw new InternalError("no symbol found for: " + callTarget);
|
|
+ }
|
|
+
|
|
+ private static RelocType getRelocType(HotSpotForeignCallLinkage callTarget) {
|
|
+ return callTarget.isCompiledStub() ? RelocType.STUB_CALL_DIRECT : RelocType.FOREIGN_CALL_INDIRECT_GOT;
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/ForeignCallSiteRelocationSymbol.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/ForeignCallSiteRelocationSymbol.java
|
|
new file mode 100644
|
|
index 000000000..22ec18437
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/ForeignCallSiteRelocationSymbol.java
|
|
@@ -0,0 +1,41 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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;
|
|
+
|
|
+import jdk.tools.jaotc.binformat.BinaryContainer;
|
|
+import jdk.tools.jaotc.binformat.Symbol.Binding;
|
|
+import jdk.tools.jaotc.binformat.Symbol.Kind;
|
|
+
|
|
+/**
|
|
+ * Native function call, symbol is to a VM method.
|
|
+ */
|
|
+final class ForeignCallSiteRelocationSymbol extends CallSiteRelocationSymbol {
|
|
+
|
|
+ ForeignCallSiteRelocationSymbol(CallSiteRelocationInfo callSiteRelocation, BinaryContainer binaryContainer) {
|
|
+ super(binaryContainer.createSymbol(0, Kind.NATIVE_FUNCTION, Binding.GLOBAL, 0, callSiteRelocation.targetSymbol));
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/ForeignGotCallSiteRelocationSymbol.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/ForeignGotCallSiteRelocationSymbol.java
|
|
new file mode 100644
|
|
index 000000000..a99aacf7b
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/ForeignGotCallSiteRelocationSymbol.java
|
|
@@ -0,0 +1,72 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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;
|
|
+
|
|
+import jdk.tools.jaotc.binformat.BinaryContainer;
|
|
+import jdk.tools.jaotc.binformat.Symbol;
|
|
+
|
|
+import jdk.vm.ci.code.site.Call;
|
|
+
|
|
+final class ForeignGotCallSiteRelocationSymbol extends CallSiteRelocationSymbol {
|
|
+
|
|
+ ForeignGotCallSiteRelocationSymbol(CompiledMethodInfo mi, Call call, CallSiteRelocationInfo callSiteRelocation, DataBuilder dataBuilder) {
|
|
+ super(createPltSymbol(dataBuilder, mi, call, callSiteRelocation));
|
|
+ }
|
|
+
|
|
+ private static Symbol createPltSymbol(DataBuilder dataBuilder, CompiledMethodInfo mi, Call call, CallSiteRelocationInfo callSiteRelocation) {
|
|
+ BinaryContainer binaryContainer = dataBuilder.getBinaryContainer();
|
|
+ String vmSymbolName = callSiteRelocation.targetSymbol;
|
|
+
|
|
+ // Add relocation to GOT cell for call resolution jump.
|
|
+ String pltSymbolName = "plt." + vmSymbolName;
|
|
+ Symbol pltSymbol = binaryContainer.getSymbol(pltSymbolName);
|
|
+
|
|
+ if (pltSymbol == null) {
|
|
+ String gotSymbolName = "got." + vmSymbolName;
|
|
+ Symbol gotSymbol = binaryContainer.getGotSymbol(gotSymbolName);
|
|
+ assert gotSymbol != null : "undefined VM got symbol '" + gotSymbolName + "' for call at " + call.pcOffset + " in " + mi.getMethodInfo().getSymbolName();
|
|
+
|
|
+ // Generate PLT jump (do it only once).
|
|
+ final int pltStartOffset = binaryContainer.getCodeContainer().getByteStreamSize();
|
|
+ final int pltEndOffset = pltStartOffset + addPltJump(dataBuilder);
|
|
+
|
|
+ // Link GOT cell to PLT jump.
|
|
+ pltSymbol = createCodeContainerSymbol(binaryContainer, pltSymbolName, pltStartOffset);
|
|
+ addExternalPltToGotRelocation(binaryContainer, gotSymbol, pltEndOffset);
|
|
+ }
|
|
+
|
|
+ return pltSymbol;
|
|
+ }
|
|
+
|
|
+ private static int addPltJump(DataBuilder dataBuilder) {
|
|
+ ELFMacroAssembler masm = ELFMacroAssembler.getELFMacroAssembler(dataBuilder.getBackend().getTarget(), dataBuilder.getBackend().getRuntime().getOptions());
|
|
+ byte[] code = masm.getPLTJumpCode(); // It includes alignment nops.
|
|
+ int size = masm.currentEndOfInstruction();
|
|
+ dataBuilder.getBinaryContainer().appendCodeBytes(code, 0, code.length);
|
|
+ return size;
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/GraalFilters.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/GraalFilters.java
|
|
new file mode 100644
|
|
index 000000000..032402462
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/GraalFilters.java
|
|
@@ -0,0 +1,147 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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;
|
|
+
|
|
+import java.lang.annotation.Annotation;
|
|
+import java.util.Arrays;
|
|
+import java.util.HashSet;
|
|
+import java.util.List;
|
|
+import java.util.Set;
|
|
+import java.util.stream.Collectors;
|
|
+
|
|
+import org.graalvm.compiler.api.directives.GraalDirectives;
|
|
+import org.graalvm.compiler.api.replacements.ClassSubstitution;
|
|
+import org.graalvm.compiler.api.replacements.MethodSubstitution;
|
|
+import org.graalvm.compiler.api.replacements.Snippet;
|
|
+import org.graalvm.compiler.debug.GraalError;
|
|
+import org.graalvm.compiler.graph.Node.NodeIntrinsic;
|
|
+import org.graalvm.compiler.hotspot.replacements.HotSpotClassSubstitutions;
|
|
+import org.graalvm.compiler.hotspot.word.MetaspacePointer;
|
|
+import org.graalvm.compiler.replacements.Snippets;
|
|
+import jdk.internal.vm.compiler.word.WordBase;
|
|
+
|
|
+import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
|
|
+import jdk.vm.ci.meta.MetaAccessProvider;
|
|
+import jdk.vm.ci.meta.ResolvedJavaMethod;
|
|
+import jdk.vm.ci.meta.ResolvedJavaType;
|
|
+import jdk.vm.ci.hotspot.HotSpotConstantPool;
|
|
+
|
|
+final class GraalFilters {
|
|
+ private List<ResolvedJavaType> specialClasses;
|
|
+ private List<ResolvedJavaType> specialArgumentAndReturnTypes;
|
|
+
|
|
+ private static Set<Class<?>> skipAnnotations = new HashSet<>();
|
|
+
|
|
+ static {
|
|
+ skipAnnotations.add(NodeIntrinsic.class);
|
|
+ skipAnnotations.add(Snippet.class);
|
|
+ skipAnnotations.add(MethodSubstitution.class);
|
|
+ }
|
|
+
|
|
+ boolean shouldCompileMethod(ResolvedJavaMethod method) {
|
|
+ // NodeIntrinsics cannot be compiled.
|
|
+ if (hasExcludedAnnotation(method)) {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ ResolvedJavaType declaringClass = method.getDeclaringClass();
|
|
+ // Check for special magical types in the signature, like Word or MetaspacePointer. Those
|
|
+ // are definitely snippets.
|
|
+ List<ResolvedJavaType> signatureTypes = Arrays.asList(method.toParameterTypes()).stream().map(p -> p.resolve(declaringClass)).collect(Collectors.toList());
|
|
+ signatureTypes.add(method.getSignature().getReturnType(null).resolve(declaringClass));
|
|
+ if (signatureTypes.stream().flatMap(t -> specialArgumentAndReturnTypes.stream().filter(s -> s.isAssignableFrom(t))).findAny().isPresent()) {
|
|
+ return false;
|
|
+ }
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ private static boolean hasExcludedAnnotation(ResolvedJavaMethod method) {
|
|
+ for (Annotation annotation : method.getAnnotations()) {
|
|
+ if (skipAnnotations.contains(annotation.annotationType())) {
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ boolean shouldCompileAnyMethodInClass(ResolvedJavaType klass) {
|
|
+ if (specialClasses.stream().filter(s -> s.isAssignableFrom(klass)).findAny().isPresent()) {
|
|
+ return false;
|
|
+ }
|
|
+ // Skip klass with Condy until Graal is fixed.
|
|
+ if (((HotSpotConstantPool) ((HotSpotResolvedObjectType) klass).getConstantPool()).hasDynamicConstant()) {
|
|
+ return false;
|
|
+ }
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ // Don't compile methods in classes and their subtypes that are in the list.
|
|
+ private static List<ResolvedJavaType> getSpecialClasses(MetaAccessProvider meta) {
|
|
+ // @formatter:off
|
|
+ return Arrays.asList(meta.lookupJavaType(Snippets.class),
|
|
+ meta.lookupJavaType(HotSpotClassSubstitutions.class),
|
|
+ meta.lookupJavaType(GraalDirectives.class),
|
|
+ meta.lookupJavaType(ClassSubstitution.class));
|
|
+ // @formatter:on
|
|
+ }
|
|
+
|
|
+ // Don't compile methods that have have the listed class or their subtypes in their signature.
|
|
+ private static List<ResolvedJavaType> getSpecialArgumentAndReturnTypes(MetaAccessProvider meta) {
|
|
+ // @formatter:off
|
|
+ return Arrays.asList(meta.lookupJavaType(WordBase.class),
|
|
+ meta.lookupJavaType(MetaspacePointer.class));
|
|
+ // @formatter:on
|
|
+ }
|
|
+
|
|
+ GraalFilters(MetaAccessProvider metaAccess) {
|
|
+ specialClasses = getSpecialClasses(metaAccess);
|
|
+ specialArgumentAndReturnTypes = getSpecialArgumentAndReturnTypes(metaAccess);
|
|
+ }
|
|
+
|
|
+ static boolean shouldIgnoreException(Throwable e) {
|
|
+ if (e instanceof GraalError) {
|
|
+ String m = e.getMessage();
|
|
+ if (m.contains("ArrayKlass::_component_mirror")) {
|
|
+ // When compiling Graal, ignore errors in JDK8 snippets.
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (e instanceof org.graalvm.compiler.java.BytecodeParser.BytecodeParserError) {
|
|
+ Throwable cause = e.getCause();
|
|
+ if (cause instanceof GraalError) {
|
|
+ String m = cause.getMessage();
|
|
+ // When compiling Graal suppress attempts to compile snippet fragments that bottom
|
|
+ // out with node intrinsics. These are unfortunately not explicitly marked, so we
|
|
+ // have to try to compile them and bail out if we think it's a snippet.
|
|
+ if (m.contains("@NodeIntrinsic method") && m.contains("must only be called from within a replacement")) {
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/InfopointProcessor.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/InfopointProcessor.java
|
|
new file mode 100644
|
|
index 000000000..f6974cc34
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/InfopointProcessor.java
|
|
@@ -0,0 +1,149 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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;
|
|
+
|
|
+import jdk.tools.jaotc.binformat.BinaryContainer;
|
|
+import jdk.tools.jaotc.binformat.Relocation;
|
|
+import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
|
|
+
|
|
+import jdk.vm.ci.code.BytecodePosition;
|
|
+import jdk.vm.ci.code.VirtualObject;
|
|
+import jdk.vm.ci.code.site.Call;
|
|
+import jdk.vm.ci.code.site.Infopoint;
|
|
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
|
|
+import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
|
|
+import jdk.vm.ci.meta.InvokeTarget;
|
|
+
|
|
+final class InfopointProcessor {
|
|
+
|
|
+ private final DataBuilder dataBuilder;
|
|
+
|
|
+ private final BinaryContainer binaryContainer;
|
|
+
|
|
+ InfopointProcessor(DataBuilder dataBuilder) {
|
|
+ this.dataBuilder = dataBuilder;
|
|
+ this.binaryContainer = dataBuilder.getBinaryContainer();
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Parse an {@link Infopoint} generated by the compiler and create all needed binary section
|
|
+ * constructs.
|
|
+ *
|
|
+ * @param methodInfo compiled method info
|
|
+ * @param info info point being processed
|
|
+ */
|
|
+ void process(CompiledMethodInfo methodInfo, Infopoint info) {
|
|
+ switch (info.reason) {
|
|
+ case CALL:
|
|
+ // All calls in compiled code need a symbol and relocation entry.
|
|
+ processCallInfoPoint(methodInfo, (Call) info);
|
|
+ break;
|
|
+ case SAFEPOINT:
|
|
+ case IMPLICIT_EXCEPTION:
|
|
+ case METHOD_START:
|
|
+ case METHOD_END:
|
|
+ case BYTECODE_POSITION:
|
|
+ break;
|
|
+ default:
|
|
+ throw new InternalError("Unknown info point reason: " + info.reason);
|
|
+ }
|
|
+ if (info.debugInfo == null) {
|
|
+ return;
|
|
+ }
|
|
+ BytecodePosition bcp = info.debugInfo.getBytecodePosition();
|
|
+ if (bcp == null) {
|
|
+ return;
|
|
+ }
|
|
+ recordScopeKlasses(methodInfo, bcp, info.debugInfo.getVirtualObjectMapping());
|
|
+ }
|
|
+
|
|
+ private void recordScopeKlasses(CompiledMethodInfo methodInfo, BytecodePosition bcp, VirtualObject[] vos) {
|
|
+ BytecodePosition caller = bcp.getCaller();
|
|
+ if (caller != null) {
|
|
+ recordScopeKlasses(methodInfo, caller, vos);
|
|
+ }
|
|
+
|
|
+ HotSpotResolvedJavaMethod m = (HotSpotResolvedJavaMethod) bcp.getMethod();
|
|
+ HotSpotResolvedObjectType klass = m.getDeclaringClass();
|
|
+ methodInfo.addDependentKlassData(binaryContainer, klass);
|
|
+
|
|
+ if (vos == null) {
|
|
+ return;
|
|
+ }
|
|
+ for (VirtualObject vo : vos) {
|
|
+ HotSpotResolvedObjectType vk = (HotSpotResolvedObjectType) vo.getType();
|
|
+ methodInfo.addDependentKlassData(binaryContainer, vk);
|
|
+ }
|
|
+
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Process Call info points in Graal generated compilation result. We want to create one of the
|
|
+ * following relocations: .text -> .hotspot.plt.linkage - Java method to Java method call .text
|
|
+ * -> .text - Java method / Graal stub to Graal stub call .text -> .plt - Java method / Graal
|
|
+ * stub to VM method call.
|
|
+ *
|
|
+ * @param methodInfo compiled method info
|
|
+ * @param call call
|
|
+ */
|
|
+ private void processCallInfoPoint(CompiledMethodInfo methodInfo, Call call) {
|
|
+ CallSiteRelocationInfo callSiteRelocation = getCallSiteRelocationInfo(call);
|
|
+ CallSiteRelocationSymbol callSiteRelocationSymbol = getCallSiteRelocationSymbol(methodInfo, call, callSiteRelocation);
|
|
+
|
|
+ Relocation relocation = new Relocation(methodInfo.getTextSectionOffset() + call.pcOffset, callSiteRelocation.type, call.size, binaryContainer.getCodeContainer(),
|
|
+ callSiteRelocationSymbol.symbol);
|
|
+ binaryContainer.addRelocation(relocation);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Get information about the call site. Name of the callee and relocation call type.
|
|
+ */
|
|
+ private static CallSiteRelocationInfo getCallSiteRelocationInfo(Call call) {
|
|
+ InvokeTarget callTarget = call.target;
|
|
+ if (callTarget instanceof HotSpotResolvedJavaMethod) {
|
|
+ return new JavaCallSiteRelocationInfo(call, (HotSpotResolvedJavaMethod) callTarget);
|
|
+ } else if (callTarget instanceof HotSpotForeignCallLinkage) {
|
|
+ return new ForeignCallSiteRelocationInfo(call, (HotSpotForeignCallLinkage) callTarget);
|
|
+ } else {
|
|
+ throw new InternalError("Unhandled call type found in infopoint: " + callTarget);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Return a relocation symbol for the given call site.
|
|
+ */
|
|
+ private CallSiteRelocationSymbol getCallSiteRelocationSymbol(CompiledMethodInfo mi, Call call, CallSiteRelocationInfo callSiteRelocation) {
|
|
+ switch (callSiteRelocation.type) {
|
|
+ case STUB_CALL_DIRECT:
|
|
+ return new StubDirectCallSiteRelocationSymbol(callSiteRelocation, binaryContainer);
|
|
+ case FOREIGN_CALL_INDIRECT_GOT:
|
|
+ return new ForeignGotCallSiteRelocationSymbol(mi, call, callSiteRelocation, dataBuilder);
|
|
+ default:
|
|
+ return new JavaCallSiteRelocationSymbol(mi, call, callSiteRelocation, binaryContainer);
|
|
+ }
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/InstructionDecoder.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/InstructionDecoder.java
|
|
new file mode 100644
|
|
index 000000000..6907cf30e
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/InstructionDecoder.java
|
|
@@ -0,0 +1,53 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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;
|
|
+
|
|
+import jdk.tools.jaotc.amd64.AMD64InstructionDecoder;
|
|
+import jdk.tools.jaotc.aarch64.AArch64InstructionDecoder;
|
|
+
|
|
+import jdk.vm.ci.amd64.AMD64;
|
|
+import jdk.vm.ci.aarch64.AArch64;
|
|
+import jdk.vm.ci.code.Architecture;
|
|
+import jdk.vm.ci.code.TargetDescription;
|
|
+
|
|
+public abstract class InstructionDecoder {
|
|
+
|
|
+ public static InstructionDecoder getInstructionDecoder(TargetDescription target) {
|
|
+ Architecture architecture = target.arch;
|
|
+ if (architecture instanceof AMD64) {
|
|
+ return new AMD64InstructionDecoder(target);
|
|
+ } else if (architecture instanceof AArch64) {
|
|
+ return new AArch64InstructionDecoder();
|
|
+ } else {
|
|
+ throw new InternalError("Unsupported architecture " + architecture);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public abstract void decodePosition(byte[] code, int pcOffset);
|
|
+
|
|
+ public abstract int currentEndOfInstruction();
|
|
+
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/JavaCallSiteRelocationInfo.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/JavaCallSiteRelocationInfo.java
|
|
new file mode 100644
|
|
index 000000000..aa79e75bd
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/JavaCallSiteRelocationInfo.java
|
|
@@ -0,0 +1,43 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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;
|
|
+
|
|
+import jdk.tools.jaotc.binformat.Relocation.RelocType;
|
|
+
|
|
+import jdk.vm.ci.code.site.Call;
|
|
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
|
|
+
|
|
+/**
|
|
+ * This is a Java call site. Get the Java method name and correct call relocation type. All static
|
|
+ * Java calls should be direct. All virtual Java calls should be indirect.
|
|
+ */
|
|
+final class JavaCallSiteRelocationInfo extends CallSiteRelocationInfo {
|
|
+
|
|
+ JavaCallSiteRelocationInfo(Call call, HotSpotResolvedJavaMethod callTarget) {
|
|
+ super(JavaMethodInfo.uniqueMethodName(callTarget), call.direct ? RelocType.JAVA_CALL_DIRECT : RelocType.JAVA_CALL_INDIRECT);
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/JavaCallSiteRelocationSymbol.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/JavaCallSiteRelocationSymbol.java
|
|
new file mode 100644
|
|
index 000000000..27cfb49fb
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/JavaCallSiteRelocationSymbol.java
|
|
@@ -0,0 +1,155 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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;
|
|
+
|
|
+import org.graalvm.compiler.hotspot.HotSpotMarkId;
|
|
+
|
|
+import jdk.tools.jaotc.binformat.BinaryContainer;
|
|
+import jdk.tools.jaotc.binformat.Symbol;
|
|
+import jdk.vm.ci.code.site.Call;
|
|
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
|
|
+
|
|
+/**
|
|
+ * Symbol for a regular Java call. This method also creates additional relocations for {@code .plt}
|
|
+ * to {@code .got} and {@code .got} to {@code .plt}.
|
|
+ */
|
|
+final class JavaCallSiteRelocationSymbol extends CallSiteRelocationSymbol {
|
|
+
|
|
+ private static final byte[] zeroSlot = new byte[8];
|
|
+ // -1 represents Universe::non_oop_word() value
|
|
+ private static final byte[] minusOneSlot;
|
|
+
|
|
+ static {
|
|
+ String archStr = System.getProperty("os.arch").toLowerCase();
|
|
+ if (archStr.equals("aarch64")) {
|
|
+ // AArch64 is a special case: it uses 48-bit addresses.
|
|
+ byte[] nonOopWord = {-1, -1, -1, -1, -1, -1, 0, 0};
|
|
+ minusOneSlot = nonOopWord;
|
|
+ } else {
|
|
+ byte[] nonOopWord = {-1, -1, -1, -1, -1, -1, -1, -1};
|
|
+ minusOneSlot = nonOopWord;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ JavaCallSiteRelocationSymbol(CompiledMethodInfo mi, Call call, CallSiteRelocationInfo callSiteRelocation, BinaryContainer binaryContainer) {
|
|
+ super(createPltEntrySymbol(binaryContainer, mi, call, callSiteRelocation));
|
|
+ StubInformation stub = getStub(mi, call);
|
|
+ addRelocations(mi, stub, binaryContainer, call, callSiteRelocation);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Returns a unique symbol name with the {@code suffix} appended.
|
|
+ */
|
|
+ private static String relocationSymbolName(String suffix, CompiledMethodInfo mi, Call call, CallSiteRelocationInfo callSiteRelocation) {
|
|
+ return "M" + mi.getCodeId() + "_" + call.pcOffset + "_" + callSiteRelocation.targetSymbol + "_" + suffix;
|
|
+ }
|
|
+
|
|
+ private static Symbol createPltEntrySymbol(BinaryContainer binaryContainer, CompiledMethodInfo mi, Call call, CallSiteRelocationInfo callSiteRelocation) {
|
|
+ String symbolName = relocationSymbolName("plt.entry", mi, call, callSiteRelocation);
|
|
+ StubInformation stub = getStub(mi, call);
|
|
+ return createCodeContainerSymbol(binaryContainer, symbolName, stub.getOffset());
|
|
+ }
|
|
+
|
|
+ private static StubInformation getStub(CompiledMethodInfo mi, Call call) {
|
|
+ HotSpotResolvedJavaMethod callTarget = (HotSpotResolvedJavaMethod) call.target;
|
|
+ String callTargetSymbol = JavaMethodInfo.uniqueMethodName(callTarget) + ".at." + call.pcOffset;
|
|
+ return mi.getStubFor(callTargetSymbol);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Add all the required relocations.
|
|
+ */
|
|
+ private static void addRelocations(CompiledMethodInfo mi, StubInformation stub, BinaryContainer binaryContainer, Call call, CallSiteRelocationInfo callSiteRelocation) {
|
|
+ final boolean isVirtualCall = CallInfo.isVirtualCall(mi, call);
|
|
+
|
|
+ final int gotStartOffset = binaryContainer.appendExtLinkageGotBytes(zeroSlot, 0, zeroSlot.length);
|
|
+ if (isVirtualCall) {
|
|
+ // Nothing.
|
|
+ } else {
|
|
+ // For c2i stub we need slot with -1 value.
|
|
+ binaryContainer.appendExtLinkageGotBytes(minusOneSlot, 0, minusOneSlot.length);
|
|
+ }
|
|
+
|
|
+ // Add relocation to GOT cell for call resolution jump.
|
|
+ // This GOT cell will be initialized during JVM startup with address
|
|
+ // of JVM runtime call resolution function.
|
|
+ String gotSymbolName = "got." + getResolveSymbolName(mi, call);
|
|
+ Symbol gotSymbol = binaryContainer.getGotSymbol(gotSymbolName);
|
|
+ addExternalPltToGotRelocation(binaryContainer, gotSymbol, stub.getResolveJumpOffset());
|
|
+
|
|
+ // Add relocation to resolve call jump instruction address for GOT cell.
|
|
+ // This GOT cell will be initialized with address of resolution jump instruction and
|
|
+ // will be updated with call destination address by JVM runtime call resolution code.
|
|
+ String pltJmpSymbolName = relocationSymbolName("plt.jmp", mi, call, callSiteRelocation);
|
|
+ addCodeContainerRelocation(binaryContainer, pltJmpSymbolName, stub.getResolveJumpStart(), gotStartOffset);
|
|
+
|
|
+ // Add relocation to GOT cell for dispatch jump.
|
|
+ // The dispatch jump loads destination address from this GOT cell.
|
|
+ String gotEntrySymbolName = relocationSymbolName("got.entry", mi, call, callSiteRelocation);
|
|
+ addExtLinkageGotContainerRelocation(binaryContainer, gotEntrySymbolName, gotStartOffset, stub.getDispatchJumpOffset());
|
|
+
|
|
+ // Virtual call needs initial -1 value for Klass pointer.
|
|
+ // Non virtual call needs initial 0 value for Method pointer to call c2i adapter.
|
|
+ byte[] slot = isVirtualCall ? minusOneSlot : zeroSlot;
|
|
+ final int gotMetaOffset = binaryContainer.appendExtLinkageGotBytes(slot, 0, slot.length);
|
|
+
|
|
+ // Add relocation to GOT cell for move instruction (Klass* for virtual, Method* otherwise).
|
|
+ String gotMoveSymbolName = relocationSymbolName("got.move", mi, call, callSiteRelocation);
|
|
+ addExtLinkageGotContainerRelocation(binaryContainer, gotMoveSymbolName, gotMetaOffset, stub.getMovOffset());
|
|
+
|
|
+ if (isVirtualCall) {
|
|
+ // Nothing.
|
|
+ } else {
|
|
+ // Add relocation to GOT cell for c2i adapter jump.
|
|
+ // The c2i jump instruction loads destination address from this GOT cell.
|
|
+ // This GOT cell is initialized with -1 and will be updated
|
|
+ // by JVM runtime call resolution code.
|
|
+ String gotC2ISymbolName = relocationSymbolName("got.c2i", mi, call, callSiteRelocation);
|
|
+ addExtLinkageGotContainerRelocation(binaryContainer, gotC2ISymbolName, gotStartOffset + 8, stub.getC2IJumpOffset());
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Returns the name of the resolve method for this particular call.
|
|
+ */
|
|
+ private static String getResolveSymbolName(CompiledMethodInfo mi, Call call) {
|
|
+ String resolveSymbolName;
|
|
+ if (CallInfo.isStaticCall(call)) {
|
|
+ assert mi.hasMark(call, HotSpotMarkId.INVOKESTATIC);
|
|
+ resolveSymbolName = BinaryContainer.getResolveStaticEntrySymbolName();
|
|
+ } else if (CallInfo.isSpecialCall(call)) {
|
|
+ resolveSymbolName = BinaryContainer.getResolveOptVirtualEntrySymbolName();
|
|
+ } else if (CallInfo.isOptVirtualCall(mi, call)) {
|
|
+ resolveSymbolName = BinaryContainer.getResolveOptVirtualEntrySymbolName();
|
|
+ } else if (CallInfo.isVirtualCall(mi, call)) {
|
|
+ resolveSymbolName = BinaryContainer.getResolveVirtualEntrySymbolName();
|
|
+ } else {
|
|
+ throw new InternalError("Unknown call type in " + mi.asTag() + " @ " + call.pcOffset + " for call" + call.target);
|
|
+ }
|
|
+ return resolveSymbolName;
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/JavaMethodInfo.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/JavaMethodInfo.java
|
|
new file mode 100644
|
|
index 000000000..7bebfa3b9
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/JavaMethodInfo.java
|
|
@@ -0,0 +1,61 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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;
|
|
+
|
|
+import org.graalvm.compiler.code.CompilationResult;
|
|
+
|
|
+import jdk.vm.ci.hotspot.HotSpotCompiledCode;
|
|
+import jdk.vm.ci.meta.ResolvedJavaMethod;
|
|
+
|
|
+interface JavaMethodInfo {
|
|
+
|
|
+ /**
|
|
+ * @return unique symbol name for this method.
|
|
+ */
|
|
+ String getSymbolName();
|
|
+
|
|
+ /**
|
|
+ * Name a java method with J.L.S. class name and signature.
|
|
+ *
|
|
+ * @return unique name for this method including class and signature
|
|
+ */
|
|
+ String getNameAndSignature();
|
|
+
|
|
+ HotSpotCompiledCode compiledCode(CompilationResult result);
|
|
+
|
|
+ /**
|
|
+ * Name a java method with class and signature to make it unique.
|
|
+ *
|
|
+ * @param method to generate unique identifier for
|
|
+ * @return Unique name for this method including class and signature
|
|
+ **/
|
|
+ static String uniqueMethodName(ResolvedJavaMethod method) {
|
|
+ String className = method.getDeclaringClass().toClassName();
|
|
+ String name = className + "." + method.getName() + method.getSignature().toMethodDescriptor();
|
|
+ return name;
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Linker.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Linker.java
|
|
new file mode 100644
|
|
index 000000000..92ac33e73
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Linker.java
|
|
@@ -0,0 +1,261 @@
|
|
+/*
|
|
+ * Copyright (c) 2018, 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
|
|
+ * 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;
|
|
+
|
|
+import java.io.BufferedReader;
|
|
+import java.io.File;
|
|
+import java.io.InputStream;
|
|
+import java.io.InputStreamReader;
|
|
+import java.nio.file.Files;
|
|
+import java.nio.file.Path;
|
|
+import java.nio.file.Paths;
|
|
+import java.util.List;
|
|
+import java.util.stream.Stream;
|
|
+
|
|
+final class Linker {
|
|
+
|
|
+ private final Options options;
|
|
+ private String objectFileName;
|
|
+ private String libraryFileName;
|
|
+ private String linkerCmd;
|
|
+
|
|
+ String objFile() {
|
|
+ return objectFileName;
|
|
+ }
|
|
+
|
|
+ String libFile() {
|
|
+ return libraryFileName;
|
|
+ }
|
|
+
|
|
+ private static Stream<String> getLines(InputStream stream) {
|
|
+ return new BufferedReader(new InputStreamReader(stream)).lines();
|
|
+ }
|
|
+
|
|
+ private static String getString(InputStream stream) {
|
|
+ Stream<String> lines = getLines(stream);
|
|
+ StringBuilder sb = new StringBuilder();
|
|
+ lines.iterator().forEachRemaining(e -> sb.append(e));
|
|
+ return sb.toString();
|
|
+ }
|
|
+
|
|
+ Linker(Main main) throws Exception {
|
|
+ this.options = main.options;
|
|
+ String name = options.outputName;
|
|
+ objectFileName = name;
|
|
+ libraryFileName = name;
|
|
+
|
|
+ if (options.linkerpath != null && !(new File(options.linkerpath).exists())) {
|
|
+ throw new InternalError("Invalid linker path: " + options.linkerpath);
|
|
+ }
|
|
+ String linkerPath;
|
|
+ String linkerCheck;
|
|
+
|
|
+ switch (options.osName) {
|
|
+ case "Linux":
|
|
+ if (name.endsWith(".so")) {
|
|
+ objectFileName = name.substring(0, name.length() - ".so".length());
|
|
+ }
|
|
+ objectFileName = objectFileName + ".o";
|
|
+ linkerPath = (options.linkerpath != null) ? options.linkerpath : "ld";
|
|
+ linkerCmd = linkerPath + " -shared -z noexecstack -o " + libraryFileName + " " + objectFileName;
|
|
+ linkerCheck = linkerPath + " -v";
|
|
+ break;
|
|
+ case "Mac OS X":
|
|
+ if (name.endsWith(".dylib")) {
|
|
+ objectFileName = name.substring(0, name.length() - ".dylib".length());
|
|
+ }
|
|
+ objectFileName = objectFileName + ".o";
|
|
+ linkerPath = (options.linkerpath != null) ? options.linkerpath : "ld";
|
|
+ linkerCmd = linkerPath + " -dylib -o " + libraryFileName + " " + objectFileName;
|
|
+ linkerCheck = linkerPath + " -v";
|
|
+ break;
|
|
+ default:
|
|
+ if (options.osName.startsWith("Windows")) {
|
|
+ if (name.endsWith(".dll")) {
|
|
+ objectFileName = name.substring(0, name.length() - ".dll".length());
|
|
+ }
|
|
+ objectFileName = objectFileName + ".obj";
|
|
+ linkerPath = (options.linkerpath != null) ? options.linkerpath : getWindowsLinkPath(main);
|
|
+ if (linkerPath == null) {
|
|
+ throw new InternalError("Can't locate Microsoft Visual Studio amd64 link.exe");
|
|
+ }
|
|
+ linkerCmd = linkerPath + " /DLL /OPT:NOREF /NOLOGO /NOENTRY" + " /OUT:" + libraryFileName + " " + objectFileName;
|
|
+ linkerCheck = null; // link.exe presence is verified already
|
|
+ break;
|
|
+ } else {
|
|
+ throw new InternalError("Unsupported platform: " + options.osName);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // Check linker presence on platforms by printing its version
|
|
+ if (linkerCheck != null) {
|
|
+ Process p = Runtime.getRuntime().exec(linkerCheck);
|
|
+ final int exitCode = p.waitFor();
|
|
+ if (exitCode != 0) {
|
|
+ throw new InternalError(getString(p.getErrorStream()));
|
|
+ }
|
|
+ }
|
|
+
|
|
+ main.printer.printlnVerbose("Found linker: " + linkerPath);
|
|
+ }
|
|
+
|
|
+ void link() throws Exception {
|
|
+ Process p = Runtime.getRuntime().exec(linkerCmd);
|
|
+ final int exitCode = p.waitFor();
|
|
+ if (exitCode != 0) {
|
|
+ String errorMessage = getString(p.getErrorStream());
|
|
+ if (errorMessage.isEmpty()) {
|
|
+ errorMessage = getString(p.getInputStream());
|
|
+ }
|
|
+ throw new InternalError(errorMessage);
|
|
+ }
|
|
+ File objFile = new File(objectFileName);
|
|
+ boolean keepObjFile = Boolean.parseBoolean(System.getProperty("aot.keep.objFile", "false"));
|
|
+ if (objFile.exists() && !keepObjFile) {
|
|
+ if (!objFile.delete()) {
|
|
+ throw new InternalError("Failed to delete " + objectFileName + " file");
|
|
+ }
|
|
+ }
|
|
+ // Make non-executable for all.
|
|
+ File libFile = new File(libraryFileName);
|
|
+ if (libFile.exists() && !options.osName.startsWith("Windows")) {
|
|
+ if (!libFile.setExecutable(false, false)) {
|
|
+ throw new InternalError("Failed to change attribute for " + libraryFileName + " file");
|
|
+ }
|
|
+ }
|
|
+
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Search for Visual Studio link.exe Search Order is: VS2017+, VS2013, VS2015, VS2012.
|
|
+ */
|
|
+ private static String getWindowsLinkPath(Main main) throws Exception {
|
|
+ try {
|
|
+ Path vc141NewerLinker = getVC141AndNewerLinker();
|
|
+ if (vc141NewerLinker != null) {
|
|
+ return vc141NewerLinker.toString();
|
|
+ }
|
|
+ } catch (Exception e) {
|
|
+ main.printer.printlnVerbose("Could not find VC14 or newer version of linker: " + e.getMessage());
|
|
+ if (main.options.debug) {
|
|
+ e.printStackTrace();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ String link = "\\VC\\bin\\amd64\\link.exe";
|
|
+
|
|
+ /**
|
|
+ * First try searching the paths pointed to by the VS environment variables.
|
|
+ */
|
|
+ for (VSVERSIONS vs : VSVERSIONS.values()) {
|
|
+ String vspath = System.getenv(vs.getEnvVariable());
|
|
+ if (vspath != null) {
|
|
+ File commonTools = new File(vspath);
|
|
+ File vsRoot = commonTools.getParentFile().getParentFile();
|
|
+ File linkPath = new File(vsRoot, link);
|
|
+ if (linkPath.exists()) {
|
|
+ return linkPath.getPath();
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * If we didn't find via the VS environment variables, try the well known paths
|
|
+ */
|
|
+ for (VSVERSIONS vs : VSVERSIONS.values()) {
|
|
+ String wkp = vs.getWellKnownPath();
|
|
+ if (new File(wkp).exists()) {
|
|
+ return wkp;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return null;
|
|
+ }
|
|
+
|
|
+ private static Path getVC141AndNewerLinker() throws Exception {
|
|
+ String programFilesX86 = System.getenv("ProgramFiles(x86)");
|
|
+ if (programFilesX86 == null) {
|
|
+ throw new IllegalStateException("Could not read the ProgramFiles(x86) environment variable");
|
|
+ }
|
|
+ String vswherePath = programFilesX86 + "\\Microsoft Visual Studio\\Installer\\vswhere.exe";
|
|
+ Path vswhere = Paths.get(vswherePath);
|
|
+ if (!Files.exists(vswhere)) {
|
|
+ throw new IllegalStateException("Could not find " + vswherePath);
|
|
+ }
|
|
+
|
|
+ ProcessBuilder processBuilder = new ProcessBuilder(vswhere.toString(), "-requires",
|
|
+ "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", "-property", "installationPath", "-latest");
|
|
+ processBuilder.redirectOutput(ProcessBuilder.Redirect.PIPE);
|
|
+ processBuilder.redirectError(ProcessBuilder.Redirect.PIPE);
|
|
+ Process process = processBuilder.start();
|
|
+ final int exitCode = process.waitFor();
|
|
+ if (exitCode != 0) {
|
|
+ String errorMessage = getString(process.getErrorStream());
|
|
+ if (errorMessage.isEmpty()) {
|
|
+ errorMessage = getString(process.getInputStream());
|
|
+ }
|
|
+ throw new IllegalStateException("vswhere error: " + errorMessage);
|
|
+ }
|
|
+
|
|
+ String installationPath = getLines(process.getInputStream()).findFirst().orElseThrow(() -> new IllegalStateException("Unexpected empty output from vswhere"));
|
|
+ Path vcToolsVersionFilePath = Paths.get(installationPath, "VC\\Auxiliary\\Build\\Microsoft.VCToolsVersion.default.txt");
|
|
+ List<String> vcToolsVersionFileLines = Files.readAllLines(vcToolsVersionFilePath);
|
|
+ if (vcToolsVersionFileLines.isEmpty()) {
|
|
+ throw new IllegalStateException(vcToolsVersionFilePath.toString() + " is empty");
|
|
+ }
|
|
+ String vcToolsVersion = vcToolsVersionFileLines.get(0);
|
|
+ Path linkPath = Paths.get(installationPath, "VC\\Tools\\MSVC", vcToolsVersion, "bin\\Hostx64\\x64\\link.exe");
|
|
+ if (!Files.exists(linkPath)) {
|
|
+ throw new IllegalStateException("Linker at path " + linkPath.toString() + " does not exist");
|
|
+ }
|
|
+
|
|
+ return linkPath;
|
|
+ }
|
|
+
|
|
+ // @formatter:off (workaround for Eclipse formatting bug)
|
|
+ enum VSVERSIONS {
|
|
+ VS2013("VS120COMNTOOLS", "C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\VC\\bin\\amd64\\link.exe"),
|
|
+ VS2015("VS140COMNTOOLS", "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\bin\\amd64\\link.exe"),
|
|
+ VS2012("VS110COMNTOOLS", "C:\\Program Files (x86)\\Microsoft Visual Studio 11.0\\VC\\bin\\amd64\\link.exe");
|
|
+
|
|
+ private final String envvariable;
|
|
+ private final String wkp;
|
|
+
|
|
+ VSVERSIONS(String envvariable, String wellknownpath) {
|
|
+ this.envvariable = envvariable;
|
|
+ this.wkp = wellknownpath;
|
|
+ }
|
|
+
|
|
+ String getEnvVariable() {
|
|
+ return envvariable;
|
|
+ }
|
|
+
|
|
+ String getWellKnownPath() {
|
|
+ return wkp;
|
|
+ }
|
|
+ }
|
|
+ // @formatter:on
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/LoadedClass.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/LoadedClass.java
|
|
new file mode 100644
|
|
index 000000000..3b6d6f4d5
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/LoadedClass.java
|
|
@@ -0,0 +1,73 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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;
|
|
+
|
|
+public class LoadedClass {
|
|
+ private final String name;
|
|
+ private final Class<?> clz;
|
|
+
|
|
+ public LoadedClass(String name, Class<?> clz) {
|
|
+ this.name = name;
|
|
+ this.clz = clz;
|
|
+ }
|
|
+
|
|
+ public String getName() {
|
|
+ return name;
|
|
+ }
|
|
+
|
|
+ public Class<?> getLoadedClass() {
|
|
+ return clz;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public String toString() {
|
|
+ return name;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean equals(Object o) {
|
|
+ if (this == o) {
|
|
+ return true;
|
|
+ }
|
|
+ if (!(o instanceof LoadedClass)) {
|
|
+ return false;
|
|
+ }
|
|
+ LoadedClass that = (LoadedClass) o;
|
|
+
|
|
+ if (name != null ? !name.equals(that.name) : that.name != null) {
|
|
+ return false;
|
|
+ }
|
|
+ return clz != null ? clz.equals(that.clz) : that.clz == null;
|
|
+
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public int hashCode() {
|
|
+ int result = name != null ? name.hashCode() : 0;
|
|
+ result = 31 * result + (clz != null ? clz.hashCode() : 0);
|
|
+ return result;
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/LogPrinter.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/LogPrinter.java
|
|
new file mode 100644
|
|
index 000000000..fc1ad5e9e
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/LogPrinter.java
|
|
@@ -0,0 +1,198 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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;
|
|
+
|
|
+import java.io.FileWriter;
|
|
+import java.io.IOException;
|
|
+import java.io.PrintWriter;
|
|
+import java.lang.management.ManagementFactory;
|
|
+import java.lang.management.MemoryUsage;
|
|
+import java.nio.file.Path;
|
|
+import java.nio.file.Paths;
|
|
+import java.text.MessageFormat;
|
|
+import java.util.Date;
|
|
+
|
|
+import jdk.tools.jaotc.binformat.ByteContainer;
|
|
+import jdk.tools.jaotc.binformat.BinaryContainer;
|
|
+
|
|
+final class LogPrinter {
|
|
+
|
|
+ private static FileWriter logFile = null;
|
|
+ private final Options options;
|
|
+ private final PrintWriter log;
|
|
+
|
|
+ LogPrinter(Main main, PrintWriter log) {
|
|
+ this.options = main.options;
|
|
+ this.log = log;
|
|
+ }
|
|
+
|
|
+ void printInfo(String message) {
|
|
+ if (options.info) {
|
|
+ log.print(message);
|
|
+ log.flush();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ void printlnInfo(String message) {
|
|
+ if (options.info) {
|
|
+ log.println(message);
|
|
+ log.flush();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ void printVerbose(String message) {
|
|
+ if (options.verbose) {
|
|
+ log.print(message);
|
|
+ log.flush();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ void printlnVerbose(String message) {
|
|
+ if (options.verbose) {
|
|
+ log.println(message);
|
|
+ log.flush();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ void printDebug(String message) {
|
|
+ if (options.debug) {
|
|
+ log.print(message);
|
|
+ log.flush();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ void printlnDebug(String message) {
|
|
+ if (options.debug) {
|
|
+ log.println(message);
|
|
+ log.flush();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ void printError(String message) {
|
|
+ log.println("Error: " + message);
|
|
+ log.flush();
|
|
+ }
|
|
+
|
|
+ void reportError(Throwable e) {
|
|
+ log.println("Error: " + e.getMessage());
|
|
+ if (options.info) {
|
|
+ e.printStackTrace(log);
|
|
+ }
|
|
+ log.flush();
|
|
+ }
|
|
+
|
|
+ void reportError(String key, Object... args) {
|
|
+ printError(MessageFormat.format(key, args));
|
|
+ }
|
|
+
|
|
+ private static String humanReadableByteCount(long bytes) {
|
|
+ int unit = 1024;
|
|
+
|
|
+ if (bytes < unit) {
|
|
+ return bytes + " B";
|
|
+ }
|
|
+
|
|
+ int exp = (int) (Math.log(bytes) / Math.log(unit));
|
|
+ char pre = "KMGTPE".charAt(exp - 1);
|
|
+ return String.format("%.1f %cB", bytes / Math.pow(unit, exp), pre);
|
|
+ }
|
|
+
|
|
+ void printMemoryUsage() {
|
|
+ if (options.verbose) {
|
|
+ MemoryUsage memusage = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
|
|
+ float freeratio = 1f - (float) memusage.getUsed() / memusage.getCommitted();
|
|
+ log.format(" [used: %-7s, comm: %-7s, freeRatio ~= %.1f%%]",
|
|
+ humanReadableByteCount(memusage.getUsed()),
|
|
+ humanReadableByteCount(memusage.getCommitted()),
|
|
+ freeratio * 100);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private void printContainerInfo(ByteContainer container) {
|
|
+ printlnVerbose(container.getContainerName() + ": " + container.getByteStreamSize() + " bytes");
|
|
+ }
|
|
+
|
|
+ void containersInfo(BinaryContainer binaryContainer) {
|
|
+ printContainerInfo(binaryContainer.getHeaderContainer().getContainer());
|
|
+ printContainerInfo(binaryContainer.getConfigContainer());
|
|
+ printContainerInfo(binaryContainer.getKlassesOffsetsContainer());
|
|
+ printContainerInfo(binaryContainer.getMethodsOffsetsContainer());
|
|
+ printContainerInfo(binaryContainer.getKlassesDependenciesContainer());
|
|
+ printContainerInfo(binaryContainer.getStubsOffsetsContainer());
|
|
+ printContainerInfo(binaryContainer.getMethodMetadataContainer());
|
|
+ printContainerInfo(binaryContainer.getCodeContainer());
|
|
+ printContainerInfo(binaryContainer.getCodeSegmentsContainer());
|
|
+ printContainerInfo(binaryContainer.getConstantDataContainer());
|
|
+ printContainerInfo(binaryContainer.getKlassesGotContainer());
|
|
+ printContainerInfo(binaryContainer.getCountersGotContainer());
|
|
+ printContainerInfo(binaryContainer.getMetadataGotContainer());
|
|
+ printContainerInfo(binaryContainer.getMethodStateContainer());
|
|
+ printContainerInfo(binaryContainer.getOopGotContainer());
|
|
+ printContainerInfo(binaryContainer.getMetaspaceNamesContainer());
|
|
+ }
|
|
+
|
|
+ static void openLog() {
|
|
+ int v = Integer.getInteger("jdk.tools.jaotc.logCompilation", 0);
|
|
+ if (v == 0) {
|
|
+ logFile = null;
|
|
+ return;
|
|
+ }
|
|
+ // Create log file in current directory
|
|
+ String fileName = "aot_compilation" + new Date().getTime() + ".log";
|
|
+ Path logFilePath = Paths.get("./", fileName);
|
|
+ String logFileName = logFilePath.toString();
|
|
+ try {
|
|
+ // Create file to which we do not append
|
|
+ logFile = new FileWriter(logFileName, false);
|
|
+ } catch (IOException e) {
|
|
+ System.out.println("Unable to open logfile :" + logFileName + "\nNo logs will be created");
|
|
+ logFile = null;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ static void writeLog(String str) {
|
|
+ if (logFile != null) {
|
|
+ try {
|
|
+ logFile.write(str + "\n");
|
|
+ logFile.flush();
|
|
+ } catch (IOException e) {
|
|
+ // Print to console
|
|
+ System.out.println(str + "\n");
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ static void closeLog() {
|
|
+ if (logFile != null) {
|
|
+ try {
|
|
+ logFile.close();
|
|
+ } catch (IOException e) {
|
|
+ // Do nothing
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+}
|
|
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
|
|
new file mode 100644
|
|
index 000000000..bb9bc1667
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java
|
|
@@ -0,0 +1,356 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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;
|
|
+
|
|
+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.IOException;
|
|
+import java.io.PrintWriter;
|
|
+import java.nio.file.Files;
|
|
+import java.nio.file.Paths;
|
|
+import java.text.MessageFormat;
|
|
+import java.util.ArrayList;
|
|
+import java.util.Collections;
|
|
+import java.util.List;
|
|
+import java.util.ListIterator;
|
|
+import java.util.Set;
|
|
+import java.util.StringTokenizer;
|
|
+import java.util.stream.Stream;
|
|
+
|
|
+import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
|
|
+import org.graalvm.compiler.api.runtime.GraalJVMCICompiler;
|
|
+import org.graalvm.compiler.debug.DebugContext;
|
|
+import org.graalvm.compiler.debug.DebugContext.Activation;
|
|
+import org.graalvm.compiler.debug.DebugContext.Builder;
|
|
+import org.graalvm.compiler.hotspot.CompilerConfigurationFactory;
|
|
+import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
|
|
+import org.graalvm.compiler.hotspot.HotSpotGraalCompilerFactory;
|
|
+import org.graalvm.compiler.hotspot.HotSpotGraalOptionValues;
|
|
+import org.graalvm.compiler.hotspot.HotSpotGraalRuntime;
|
|
+import org.graalvm.compiler.hotspot.HotSpotGraalRuntime.HotSpotGC;
|
|
+import org.graalvm.compiler.hotspot.HotSpotHostBackend;
|
|
+import org.graalvm.compiler.hotspot.HotSpotMarkId;
|
|
+import org.graalvm.compiler.hotspot.meta.HotSpotInvokeDynamicPlugin;
|
|
+import org.graalvm.compiler.java.GraphBuilderPhase;
|
|
+import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
|
|
+import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
|
|
+import org.graalvm.compiler.options.OptionValues;
|
|
+import org.graalvm.compiler.phases.BasePhase;
|
|
+import org.graalvm.compiler.phases.PhaseSuite;
|
|
+import org.graalvm.compiler.phases.tiers.HighTierContext;
|
|
+import org.graalvm.compiler.printer.GraalDebugHandlersFactory;
|
|
+import org.graalvm.compiler.runtime.RuntimeProvider;
|
|
+
|
|
+import jdk.tools.jaotc.Options.Option;
|
|
+import jdk.tools.jaotc.binformat.BinaryContainer;
|
|
+import jdk.vm.ci.meta.MetaAccessProvider;
|
|
+import jdk.vm.ci.meta.ResolvedJavaMethod;
|
|
+import jdk.vm.ci.runtime.JVMCI;
|
|
+
|
|
+public final class Main {
|
|
+
|
|
+ final Options options = new Options();
|
|
+ private PrintWriter log;
|
|
+ LogPrinter printer;
|
|
+ GraalFilters filters;
|
|
+
|
|
+ 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.
|
|
+
|
|
+ private static final String PROGNAME = "jaotc";
|
|
+
|
|
+ private static final String JVM_VERSION = System.getProperty("java.runtime.version");
|
|
+
|
|
+ public static void main(String[] args) throws Exception {
|
|
+ Main t = new Main();
|
|
+ final int exitCode = t.run(parse(args));
|
|
+ System.exit(exitCode);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Expands '@file' in command line arguments by replacing '@file' with the content of 'file'
|
|
+ * parsed by StringTokenizer. '@' character can be quoted as '@@'.
|
|
+ */
|
|
+ private static String[] parse(String[] args) throws IOException {
|
|
+ List<String> result = new ArrayList<>();
|
|
+ for (String arg : args) {
|
|
+ if (arg.length() > 1 && arg.charAt(0) == '@') {
|
|
+ String v = arg.substring(1);
|
|
+ if (v.charAt(0) == '@') {
|
|
+ result.add(v);
|
|
+ } else {
|
|
+ try (Stream<String> file = Files.lines(Paths.get(v))) {
|
|
+ file.map(StringTokenizer::new).map(Collections::list).flatMap(l -> l.stream().map(o -> (String) o)).forEachOrdered(result::add);
|
|
+ }
|
|
+ }
|
|
+ } else {
|
|
+ result.add(arg);
|
|
+ }
|
|
+ }
|
|
+ return result.toArray(String[]::new);
|
|
+ }
|
|
+
|
|
+ private int run(String[] args) {
|
|
+ log = new PrintWriter(System.out);
|
|
+ printer = new LogPrinter(this, log);
|
|
+
|
|
+ try {
|
|
+ Options.handleOptions(this, args);
|
|
+ if (options.help) {
|
|
+ showHelp();
|
|
+ return EXIT_OK;
|
|
+ }
|
|
+ if (options.version) {
|
|
+ showVersion();
|
|
+ return EXIT_OK;
|
|
+ }
|
|
+
|
|
+ printer.printlnInfo("Compiling " + options.outputName + "...");
|
|
+ final long start = System.currentTimeMillis();
|
|
+ if (!run()) {
|
|
+ return EXIT_ABNORMAL;
|
|
+ }
|
|
+ final long end = System.currentTimeMillis();
|
|
+ printer.printlnInfo("Total time: " + (end - start) + " ms");
|
|
+
|
|
+ return EXIT_OK;
|
|
+ } catch (Options.BadArgs e) {
|
|
+ printer.reportError(e.key, e.args);
|
|
+ if (e.showUsage) {
|
|
+ showUsage();
|
|
+ }
|
|
+ return EXIT_CMDERR;
|
|
+ } catch (Exception e) {
|
|
+ e.printStackTrace();
|
|
+ return EXIT_ABNORMAL;
|
|
+ } finally {
|
|
+ log.flush();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @SuppressWarnings("try")
|
|
+ private boolean run() throws Exception {
|
|
+ LogPrinter.openLog();
|
|
+
|
|
+ try {
|
|
+
|
|
+ final Linker linker = new Linker(this);
|
|
+ final String objectFileName = linker.objFile();
|
|
+ final Collector collector = new Collector(this);
|
|
+ Set<Class<?>> classesToCompile;
|
|
+
|
|
+ try (Timer t = new Timer(this, "")) {
|
|
+ classesToCompile = collector.collectClassesToCompile();
|
|
+ printer.printInfo(classesToCompile.size() + " classes found");
|
|
+ }
|
|
+
|
|
+ OptionValues graalOptions = HotSpotGraalOptionValues.defaultOptions();
|
|
+ // Setting -Dgraal.TieredAOT overrides --compile-for-tiered
|
|
+ if (!TieredAOT.hasBeenSet(graalOptions)) {
|
|
+ graalOptions = new OptionValues(graalOptions, TieredAOT, options.tiered);
|
|
+ }
|
|
+ graalOptions = new OptionValues(graalOptions, GeneratePIC, true, ImmutableCode, true);
|
|
+ GraalJVMCICompiler graalCompiler = HotSpotGraalCompilerFactory.createCompiler("JAOTC", JVMCI.getRuntime(), graalOptions, CompilerConfigurationFactory.selectFactory(null, graalOptions));
|
|
+ HotSpotGraalRuntime runtime = (HotSpotGraalRuntime) graalCompiler.getGraalRuntime();
|
|
+ GraalHotSpotVMConfig graalHotSpotVMConfig = runtime.getVMConfig();
|
|
+
|
|
+ if (graalHotSpotVMConfig.verifyOops) {
|
|
+ if (!HotSpotMarkId.VERIFY_OOPS.isAvailable() || !HotSpotMarkId.VERIFY_OOP_COUNT_ADDRESS.isAvailable()) {
|
|
+ System.err.println("Running jaotc with -XX:+VerifyOops is not supported by this JDK");
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ HotSpotHostBackend backend = (HotSpotHostBackend) runtime.getCapability(RuntimeProvider.class).getHostBackend();
|
|
+ MetaAccessProvider metaAccess = backend.getProviders().getMetaAccess();
|
|
+ filters = new GraalFilters(metaAccess);
|
|
+
|
|
+ List<AOTCompiledClass> classes;
|
|
+
|
|
+ try (Timer t = new Timer(this, "")) {
|
|
+ classes = collector.collectMethodsToCompile(classesToCompile, metaAccess);
|
|
+ }
|
|
+
|
|
+ // Free memory!
|
|
+ try (Timer t = options.verbose ? new Timer(this, "Freeing memory") : null) {
|
|
+ printer.printMemoryUsage();
|
|
+ classesToCompile = null;
|
|
+ System.gc();
|
|
+ }
|
|
+
|
|
+ AOTDynamicTypeStore dynoStore = new AOTDynamicTypeStore();
|
|
+ AOTCompiledClass.setDynamicTypeStore(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;
|
|
+ }
|
|
+ };
|
|
+
|
|
+ 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);
|
|
+
|
|
+ PhaseSuite<HighTierContext> graphBuilderSuite = aotBackend.getGraphBuilderSuite();
|
|
+ ListIterator<BasePhase<? super HighTierContext>> iterator = graphBuilderSuite.findPhase(GraphBuilderPhase.class);
|
|
+ GraphBuilderConfiguration graphBuilderConfig = ((GraphBuilderPhase) iterator.previous()).getGraphBuilderConfig();
|
|
+
|
|
+ // Free memory!
|
|
+ try (Timer t = options.verbose ? new Timer(this, "Freeing memory") : null) {
|
|
+ printer.printMemoryUsage();
|
|
+ aotBackend = null;
|
|
+ compiler = null;
|
|
+ System.gc();
|
|
+ }
|
|
+
|
|
+ HotSpotGC graalGC = runtime.getGarbageCollector();
|
|
+ // Prior to JDK 14, the Graal HotSpotGC enum order matched the JDK CollectedHeap enum
|
|
+ // order, so using the ordinal value worked fine. In JDK 14, CMS was removed on the
|
|
+ // JDK side, so we need a symbolic lookup of the JDK value.
|
|
+ int def = graalGC.ordinal() + 1;
|
|
+ // The GC names are spelled the same in both enums, so no clever remapping is needed
|
|
+ // here.
|
|
+ String name = "CollectedHeap::" + graalGC.name();
|
|
+ int gc = graalHotSpotVMConfig.getConstant(name, Integer.class, def, true);
|
|
+
|
|
+ BinaryContainer binaryContainer = new BinaryContainer(graalOptions, graalHotSpotVMConfig, graphBuilderConfig, gc, JVM_VERSION);
|
|
+ DataBuilder dataBuilder = new DataBuilder(this, backend, classes, binaryContainer);
|
|
+
|
|
+ try (DebugContext debug = new Builder(graalOptions, new GraalDebugHandlersFactory(snippetReflection)).build(); Activation a = debug.activate()) {
|
|
+ dataBuilder.prepareData(debug);
|
|
+ }
|
|
+
|
|
+ // Print information about section sizes
|
|
+ printer.containersInfo(binaryContainer);
|
|
+
|
|
+ // Free memory!
|
|
+ try (Timer t = options.verbose ? new Timer(this, "Freeing memory") : null) {
|
|
+ printer.printMemoryUsage();
|
|
+ backend = null;
|
|
+ for (AOTCompiledClass aotCompClass : classes) {
|
|
+ aotCompClass.clear();
|
|
+ }
|
|
+ classes.clear();
|
|
+ classes = null;
|
|
+ dataBuilder = null;
|
|
+ binaryContainer.freeMemory();
|
|
+ System.gc();
|
|
+ }
|
|
+
|
|
+ try (Timer t = new Timer(this, "Creating binary: " + objectFileName)) {
|
|
+ binaryContainer.createBinary(objectFileName);
|
|
+ }
|
|
+
|
|
+ // Free memory!
|
|
+ try (Timer t = options.verbose ? new Timer(this, "Freeing memory") : null) {
|
|
+ printer.printMemoryUsage();
|
|
+ binaryContainer = null;
|
|
+ System.gc();
|
|
+ }
|
|
+
|
|
+ try (Timer t = new Timer(this, "Creating shared library: " + linker.libFile())) {
|
|
+ linker.link();
|
|
+ }
|
|
+
|
|
+ printer.printVerbose("Final memory ");
|
|
+ printer.printMemoryUsage();
|
|
+ printer.printlnVerbose("");
|
|
+
|
|
+ } finally {
|
|
+ LogPrinter.closeLog();
|
|
+ }
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ void handleError(ResolvedJavaMethod resolvedMethod, Throwable e, String message) {
|
|
+ String methodName = JavaMethodInfo.uniqueMethodName(resolvedMethod);
|
|
+
|
|
+ if (options.debug) {
|
|
+ printer.printError("Failed compilation: " + methodName + ": " + e);
|
|
+ }
|
|
+
|
|
+ // Ignore some exceptions when meta-compiling Graal.
|
|
+ if (GraalFilters.shouldIgnoreException(e)) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ LogPrinter.writeLog("Failed compilation of method " + methodName + message);
|
|
+
|
|
+ if (!options.debug) {
|
|
+ printer.printError("Failed compilation: " + methodName + ": " + e);
|
|
+ }
|
|
+
|
|
+ if (options.verbose) {
|
|
+ e.printStackTrace(log);
|
|
+ }
|
|
+
|
|
+ if (options.exitOnError) {
|
|
+ System.exit(1);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ void warning(String key, Object... args) {
|
|
+ log.println("Warning: " + MessageFormat.format(key, args));
|
|
+ log.flush();
|
|
+ }
|
|
+
|
|
+ private void showUsage() {
|
|
+ log.println("Usage: " + PROGNAME + " <options> list");
|
|
+ log.println("use --help for a list of possible options");
|
|
+ log.flush();
|
|
+ }
|
|
+
|
|
+ private void showHelp() {
|
|
+ log.println("Usage: " + PROGNAME + " <options> list");
|
|
+ log.println();
|
|
+ log.println(" list A : separated list of class names, modules, jar files");
|
|
+ log.println(" or directories which contain class files.");
|
|
+ log.println();
|
|
+ log.println("where options include:");
|
|
+ for (Option o : Options.recognizedOptions) {
|
|
+ String name = o.aliases[0].substring(1); // there must always be at least one name
|
|
+ name = name.charAt(0) == '-' ? name.substring(1) : name;
|
|
+ if (o.isHidden() || name.equals("h")) {
|
|
+ continue;
|
|
+ }
|
|
+ log.println(o.help);
|
|
+ }
|
|
+ log.flush();
|
|
+ }
|
|
+
|
|
+ private void showVersion() {
|
|
+ log.println(PROGNAME + " " + JVM_VERSION);
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MarkProcessor.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MarkProcessor.java
|
|
new file mode 100644
|
|
index 000000000..69c584d1c
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MarkProcessor.java
|
|
@@ -0,0 +1,137 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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;
|
|
+
|
|
+import org.graalvm.compiler.code.CompilationResult;
|
|
+import org.graalvm.compiler.hotspot.HotSpotMarkId;
|
|
+
|
|
+import jdk.tools.jaotc.binformat.BinaryContainer;
|
|
+import jdk.tools.jaotc.binformat.Relocation;
|
|
+import jdk.tools.jaotc.binformat.Relocation.RelocType;
|
|
+import jdk.tools.jaotc.binformat.Symbol;
|
|
+import jdk.vm.ci.code.site.Mark;
|
|
+
|
|
+final class MarkProcessor {
|
|
+
|
|
+ private final BinaryContainer binaryContainer;
|
|
+
|
|
+ MarkProcessor(DataBuilder dataBuilder) {
|
|
+ binaryContainer = dataBuilder.getBinaryContainer();
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Parse a {@link Mark} generated by the compiler and create all needed binary section
|
|
+ * constructs.
|
|
+ *
|
|
+ * @param methodInfo compiled method info
|
|
+ * @param mark mark being processed
|
|
+ */
|
|
+ @SuppressWarnings("fallthrough")
|
|
+ void process(CompiledMethodInfo methodInfo, CompilationResult.CodeMark mark) {
|
|
+ HotSpotMarkId markId = (HotSpotMarkId) mark.id;
|
|
+ switch (markId) {
|
|
+ case EXCEPTION_HANDLER_ENTRY:
|
|
+ case DEOPT_HANDLER_ENTRY:
|
|
+ case DEOPT_MH_HANDLER_ENTRY:
|
|
+ break;
|
|
+ case POLL_FAR:
|
|
+ case POLL_RETURN_FAR:
|
|
+ if (binaryContainer.getThreadLocalHandshakes()) {
|
|
+ // skip relocation
|
|
+ break;
|
|
+ }
|
|
+ // fallthrough
|
|
+ case CARD_TABLE_ADDRESS:
|
|
+ case NARROW_KLASS_BASE_ADDRESS:
|
|
+ case NARROW_OOP_BASE_ADDRESS:
|
|
+ case CRC_TABLE_ADDRESS:
|
|
+ case LOG_OF_HEAP_REGION_GRAIN_BYTES:
|
|
+ case VERIFY_OOPS:
|
|
+ case VERIFY_OOP_BITS:
|
|
+ case VERIFY_OOP_MASK:
|
|
+ case VERIFY_OOP_COUNT_ADDRESS:
|
|
+ String vmSymbolName;
|
|
+ switch (markId) {
|
|
+ case POLL_FAR:
|
|
+ case POLL_RETURN_FAR:
|
|
+ vmSymbolName = BinaryContainer.getPollingPageSymbolName();
|
|
+ break;
|
|
+ case CARD_TABLE_ADDRESS:
|
|
+ vmSymbolName = BinaryContainer.getCardTableAddressSymbolName();
|
|
+ break;
|
|
+ case NARROW_KLASS_BASE_ADDRESS:
|
|
+ vmSymbolName = BinaryContainer.getNarrowKlassBaseAddressSymbolName();
|
|
+ break;
|
|
+ case NARROW_OOP_BASE_ADDRESS:
|
|
+ vmSymbolName = BinaryContainer.getNarrowOopBaseAddressSymbolName();
|
|
+ break;
|
|
+ case CRC_TABLE_ADDRESS:
|
|
+ vmSymbolName = BinaryContainer.getCrcTableAddressSymbolName();
|
|
+ break;
|
|
+ case LOG_OF_HEAP_REGION_GRAIN_BYTES:
|
|
+ vmSymbolName = BinaryContainer.getLogOfHeapRegionGrainBytesSymbolName();
|
|
+ break;
|
|
+ case VERIFY_OOPS:
|
|
+ vmSymbolName = BinaryContainer.getVerifyOopsSymbolName();
|
|
+ break;
|
|
+ case VERIFY_OOP_COUNT_ADDRESS:
|
|
+ vmSymbolName = BinaryContainer.getVerifyOopCountAddressSymbolName();
|
|
+ break;
|
|
+ case VERIFY_OOP_BITS:
|
|
+ vmSymbolName = BinaryContainer.getVerifyOopBitsSymbolName();
|
|
+ break;
|
|
+ case VERIFY_OOP_MASK:
|
|
+ vmSymbolName = BinaryContainer.getVerifyOopMaskSymbolName();
|
|
+ break;
|
|
+ default:
|
|
+ throw new InternalError("Unhandled mark: " + mark);
|
|
+ }
|
|
+ String s = "got." + vmSymbolName;
|
|
+ Symbol gotSymbol = binaryContainer.getGotSymbol(s);
|
|
+ assert gotSymbol != null : " Processing Mark: Encountered undefined got symbol for " + mark;
|
|
+ final int textBaseOffset = methodInfo.getTextSectionOffset();
|
|
+ final int textOffset = textBaseOffset + mark.pcOffset;
|
|
+ Relocation reloc = new Relocation(textOffset, RelocType.EXTERNAL_PLT_TO_GOT, 8, binaryContainer.getCodeContainer(), gotSymbol);
|
|
+ binaryContainer.addRelocation(reloc);
|
|
+ break;
|
|
+ case VERIFIED_ENTRY:
|
|
+ case UNVERIFIED_ENTRY:
|
|
+ case OSR_ENTRY:
|
|
+ case FRAME_COMPLETE:
|
|
+ case INVOKEINTERFACE:
|
|
+ case INVOKEVIRTUAL:
|
|
+ case INVOKESTATIC:
|
|
+ case INVOKESPECIAL:
|
|
+ case INLINE_INVOKE:
|
|
+ case POLL_NEAR:
|
|
+ case POLL_RETURN_NEAR:
|
|
+ // Nothing to do.
|
|
+ break;
|
|
+ default:
|
|
+ throw new InternalError("Unexpected mark found: " + mark);
|
|
+ }
|
|
+ }
|
|
+}
|
|
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
|
|
new file mode 100644
|
|
index 000000000..817f6a2e2
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MetadataBuilder.java
|
|
@@ -0,0 +1,251 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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;
|
|
+
|
|
+import static jdk.tools.jaotc.AOTCompiledClass.getType;
|
|
+import static jdk.tools.jaotc.AOTCompiledClass.metadataName;
|
|
+
|
|
+import java.util.ArrayList;
|
|
+import java.util.List;
|
|
+
|
|
+import org.graalvm.compiler.code.CompilationResult;
|
|
+import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
|
|
+import org.graalvm.compiler.hotspot.HotSpotGraalServices;
|
|
+
|
|
+import jdk.tools.jaotc.binformat.BinaryContainer;
|
|
+import jdk.tools.jaotc.binformat.ByteContainer;
|
|
+import jdk.tools.jaotc.binformat.GotSymbol;
|
|
+import jdk.tools.jaotc.utils.NativeOrderOutputStream;
|
|
+import jdk.vm.ci.code.StackSlot;
|
|
+import jdk.vm.ci.code.site.DataPatch;
|
|
+import jdk.vm.ci.code.site.Infopoint;
|
|
+import jdk.vm.ci.code.site.Mark;
|
|
+import jdk.vm.ci.hotspot.HotSpotCompiledCode;
|
|
+import jdk.vm.ci.hotspot.HotSpotMetaData;
|
|
+
|
|
+final class MetadataBuilder {
|
|
+
|
|
+ private final DataBuilder dataBuilder;
|
|
+
|
|
+ private final BinaryContainer binaryContainer;
|
|
+
|
|
+ MetadataBuilder(DataBuilder dataBuilder) {
|
|
+ this.dataBuilder = dataBuilder;
|
|
+ this.binaryContainer = dataBuilder.getBinaryContainer();
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Process compiled methods and create method metadata.
|
|
+ */
|
|
+ void processMetadata(List<AOTCompiledClass> classes, AOTCompiledClass stubCompiledCode) {
|
|
+ for (AOTCompiledClass c : classes) {
|
|
+ processMetadataClass(c);
|
|
+ }
|
|
+ processMetadataClass(stubCompiledCode);
|
|
+ }
|
|
+
|
|
+ private void processMetadataClass(AOTCompiledClass c) {
|
|
+ processInfopointsAndMarks(c);
|
|
+ createMethodMetadata(c);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Add metadata for each of the compiled methods in {@code compiledClass} to read-only section
|
|
+ * of {@code binaryContainer}.
|
|
+ *
|
|
+ * @param compiledClass AOT Graal compilation result
|
|
+ */
|
|
+ private void createMethodMetadata(AOTCompiledClass compiledClass) {
|
|
+ HotSpotGraalRuntimeProvider runtime = dataBuilder.getBackend().getRuntime();
|
|
+ ByteContainer methodMetadataContainer = binaryContainer.getMethodMetadataContainer();
|
|
+
|
|
+ // For each of the compiled java methods, create records holding information about them.
|
|
+ for (CompiledMethodInfo methodInfo : compiledClass.getCompiledMethods()) {
|
|
+ // Get the current offset in the methodmetadata container.
|
|
+ final int startOffset = methodMetadataContainer.getByteStreamSize();
|
|
+ assert startOffset % 8 == 0 : "Must be aligned on 8";
|
|
+
|
|
+ methodInfo.setMetadataOffset(startOffset);
|
|
+
|
|
+ HotSpotCompiledCode compiledMethod = methodInfo.compiledCode();
|
|
+ // pc and scope description
|
|
+ HotSpotMetaData metaData = new HotSpotMetaData(runtime.getTarget(), compiledMethod);
|
|
+
|
|
+ byte[] pcDesc = metaData.pcDescBytes();
|
|
+ byte[] scopeDesc = metaData.scopesDescBytes();
|
|
+ byte[] relocationInfo = metaData.relocBytes();
|
|
+ byte[] oopMapInfo = metaData.oopMaps();
|
|
+ // this may be null as the field does not exist before JDK 13
|
|
+ byte[] implicitExceptionBytes = HotSpotGraalServices.getImplicitExceptionBytes(metaData);
|
|
+ byte[] exceptionBytes = metaData.exceptionBytes();
|
|
+
|
|
+ // create a global symbol at this position for this method
|
|
+ NativeOrderOutputStream metadataStream = new NativeOrderOutputStream();
|
|
+
|
|
+ // get the code size
|
|
+ int codeSize = methodInfo.getCodeSize();
|
|
+
|
|
+ // get code offsets
|
|
+ CodeOffsets co = CodeOffsets.buildFrom(methodInfo.getCompilationResult().getMarks());
|
|
+ int unverifiedEntry = co.entry();
|
|
+ int verifiedEntry = co.verifiedEntry();
|
|
+ int exceptionHandler = co.exceptionHandler();
|
|
+ int deoptHandler = co.deoptHandler();
|
|
+ int deoptMHHandler = co.deoptMHHandler();
|
|
+ int frameSize = methodInfo.getCompilationResult().getTotalFrameSize();
|
|
+ StackSlot deoptRescueSlot = methodInfo.getCompilationResult().getCustomStackArea();
|
|
+ int origPcOffset = deoptRescueSlot != null ? deoptRescueSlot.getOffset(frameSize) : -1;
|
|
+
|
|
+ // get stubs offset
|
|
+ int stubsOffset = methodInfo.getStubsOffset();
|
|
+
|
|
+ int offset = addMetadataEntries(binaryContainer, metaData, methodInfo);
|
|
+ methodInfo.setMetadataGotOffset(offset);
|
|
+ methodInfo.setMetadataGotSize(metaData.metadataEntries().length);
|
|
+ int unsafeAccess = methodInfo.getCompilationResult().hasUnsafeAccess() ? 1 : 0;
|
|
+ try {
|
|
+ // calculate total size of the container
|
|
+ NativeOrderOutputStream.PatchableInt totalSize = metadataStream.patchableInt();
|
|
+
|
|
+ // @formatter:off
|
|
+ metadataStream.putInt(codeSize).
|
|
+ putInt(unverifiedEntry).
|
|
+ putInt(verifiedEntry).
|
|
+ putInt(exceptionHandler).
|
|
+ putInt(deoptHandler).
|
|
+ putInt(deoptMHHandler).
|
|
+ putInt(stubsOffset).
|
|
+ putInt(frameSize).
|
|
+ putInt(origPcOffset).
|
|
+ putInt(unsafeAccess);
|
|
+ // @formatter:on
|
|
+
|
|
+ NativeOrderOutputStream.PatchableInt pcDescOffset = metadataStream.patchableInt();
|
|
+ NativeOrderOutputStream.PatchableInt scopeOffset = metadataStream.patchableInt();
|
|
+ NativeOrderOutputStream.PatchableInt relocationOffset = metadataStream.patchableInt();
|
|
+ NativeOrderOutputStream.PatchableInt exceptionOffset = metadataStream.patchableInt();
|
|
+ NativeOrderOutputStream.PatchableInt implictTableOffset = null;
|
|
+ if (implicitExceptionBytes != null) {
|
|
+ implictTableOffset = metadataStream.patchableInt();
|
|
+ }
|
|
+ NativeOrderOutputStream.PatchableInt oopMapOffset = metadataStream.patchableInt();
|
|
+ metadataStream.align(8);
|
|
+
|
|
+ pcDescOffset.set(metadataStream.position());
|
|
+ metadataStream.put(pcDesc).align(8);
|
|
+
|
|
+ scopeOffset.set(metadataStream.position());
|
|
+ metadataStream.put(scopeDesc).align(8);
|
|
+
|
|
+ relocationOffset.set(metadataStream.position());
|
|
+ metadataStream.put(relocationInfo).align(8);
|
|
+
|
|
+ exceptionOffset.set(metadataStream.position());
|
|
+ metadataStream.put(exceptionBytes).align(8);
|
|
+
|
|
+ if (implicitExceptionBytes != null) {
|
|
+ implictTableOffset.set(metadataStream.position());
|
|
+ metadataStream.put(implicitExceptionBytes).align(8);
|
|
+ }
|
|
+
|
|
+ // oopmaps should be last
|
|
+ oopMapOffset.set(metadataStream.position());
|
|
+ metadataStream.put(oopMapInfo).align(8);
|
|
+
|
|
+ totalSize.set(metadataStream.position());
|
|
+
|
|
+ byte[] data = metadataStream.array();
|
|
+
|
|
+ methodMetadataContainer.appendBytes(data, 0, data.length);
|
|
+ } catch (Exception e) {
|
|
+ throw new InternalError("Exception occurred during compilation of " + methodInfo.getMethodInfo().getSymbolName(), e);
|
|
+ }
|
|
+ methodInfo.clearCompileData(); // Clear unused anymore compilation data
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private static int addMetadataEntries(BinaryContainer binaryContainer, HotSpotMetaData metaData, CompiledMethodInfo methodInfo) {
|
|
+ Object[] metaDataEntries = metaData.metadataEntries();
|
|
+
|
|
+ if (metaDataEntries.length == 0) {
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ int metadataGotSlotsStart = binaryContainer.getMetadataGotContainer().getByteStreamSize(); // binaryContainer.reserveMetadataGOTSlots(metaDataEntries.length);
|
|
+
|
|
+ for (int index = 0; index < metaDataEntries.length; index++) {
|
|
+ Object ref = metaDataEntries[index];
|
|
+ String name = metadataName(ref);
|
|
+ // Create GOT cells for klasses referenced in metadata
|
|
+ addMetadataEntry(binaryContainer, name);
|
|
+ // We should already have added entries for this klass
|
|
+ assert AOTCompiledClass.getAOTKlassData(getType(ref)) != null;
|
|
+ assert methodInfo.getDependentKlassData(getType(ref)) != null;
|
|
+ }
|
|
+
|
|
+ return metadataGotSlotsStart;
|
|
+ }
|
|
+
|
|
+ private static void addMetadataEntry(BinaryContainer binaryContainer, String name) {
|
|
+ int stringOffset = binaryContainer.addMetaspaceName(name);
|
|
+ binaryContainer.addMetadataGotEntry(stringOffset);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Process {@link Infopoint}s, {@link Mark}s and {@link DataPatch}es generated by the compiler
|
|
+ * to create all needed binary section constructs.
|
|
+ *
|
|
+ * @param compiledClass compilation result
|
|
+ */
|
|
+ private void processInfopointsAndMarks(AOTCompiledClass compiledClass) {
|
|
+ ArrayList<CompiledMethodInfo> compiledMethods = compiledClass.getCompiledMethods();
|
|
+
|
|
+ MarkProcessor markProcessor = new MarkProcessor(dataBuilder);
|
|
+ DataPatchProcessor dataPatchProcessor = new DataPatchProcessor(dataBuilder);
|
|
+ InfopointProcessor infopointProcessor = new InfopointProcessor(dataBuilder);
|
|
+
|
|
+ for (CompiledMethodInfo methodInfo : compiledMethods) {
|
|
+ CompilationResult compilationResult = methodInfo.getCompilationResult();
|
|
+ String targetSymbol = "state.M" + methodInfo.getCodeId();
|
|
+ String gotName = "got." + targetSymbol;
|
|
+ GotSymbol symbol = binaryContainer.getMethodStateContainer().createGotSymbol(gotName);
|
|
+ assert (symbol.getIndex() == methodInfo.getCodeId()) : "wrong offset";
|
|
+
|
|
+ for (Infopoint infoPoint : compilationResult.getInfopoints()) {
|
|
+ infopointProcessor.process(methodInfo, infoPoint);
|
|
+ }
|
|
+
|
|
+ for (CompilationResult.CodeMark mark : compilationResult.getMarks()) {
|
|
+ markProcessor.process(methodInfo, mark);
|
|
+ }
|
|
+
|
|
+ for (DataPatch dataPatch : compilationResult.getDataPatches()) {
|
|
+ dataPatchProcessor.process(methodInfo, dataPatch);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+}
|
|
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
|
|
new file mode 100644
|
|
index 000000000..e5dcda118
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Options.java
|
|
@@ -0,0 +1,300 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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;
|
|
+
|
|
+import java.text.MessageFormat;
|
|
+import java.util.ArrayList;
|
|
+import java.util.LinkedList;
|
|
+import java.util.List;
|
|
+
|
|
+import jdk.tools.jaotc.collect.ClassSearch;
|
|
+import jdk.tools.jaotc.collect.ClassSource;
|
|
+import jdk.tools.jaotc.collect.SearchFor;
|
|
+import jdk.tools.jaotc.collect.SearchPath;
|
|
+import jdk.tools.jaotc.collect.classname.ClassNameSourceProvider;
|
|
+import jdk.tools.jaotc.collect.directory.DirectorySourceProvider;
|
|
+import jdk.tools.jaotc.collect.jar.JarSourceProvider;
|
|
+import jdk.tools.jaotc.collect.module.ModuleSourceProvider;
|
|
+
|
|
+final class Options {
|
|
+ List<SearchFor> files = new LinkedList<>();
|
|
+ String osName;
|
|
+ String outputName = defaultOutputName();
|
|
+ String methodList;
|
|
+ List<ClassSource> sources = new ArrayList<>();
|
|
+ String linkerpath = null;
|
|
+ SearchPath searchPath = new SearchPath();
|
|
+
|
|
+ /**
|
|
+ * We don't see scaling beyond 16 threads.
|
|
+ */
|
|
+ private static final int COMPILER_THREADS = 16;
|
|
+
|
|
+ int threads = Integer.min(COMPILER_THREADS, Runtime.getRuntime().availableProcessors());
|
|
+
|
|
+ boolean ignoreClassLoadingErrors;
|
|
+ boolean exitOnError;
|
|
+ boolean info;
|
|
+ boolean verbose;
|
|
+ boolean debug;
|
|
+ boolean help;
|
|
+ boolean version;
|
|
+ boolean compileWithAssertions;
|
|
+ boolean tiered;
|
|
+
|
|
+ private String defaultOutputName() {
|
|
+ osName = System.getProperty("os.name");
|
|
+ String name = "unnamed.";
|
|
+ String ext;
|
|
+
|
|
+ switch (osName) {
|
|
+ case "Linux":
|
|
+ ext = "so";
|
|
+ break;
|
|
+ case "Mac OS X":
|
|
+ ext = "dylib";
|
|
+ break;
|
|
+ default:
|
|
+ if (osName.startsWith("Windows")) {
|
|
+ ext = "dll";
|
|
+ } else {
|
|
+ ext = "so";
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return name + ext;
|
|
+ }
|
|
+
|
|
+ static class BadArgs extends Exception {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ final String key;
|
|
+ final Object[] args;
|
|
+ boolean showUsage;
|
|
+
|
|
+ BadArgs(String key, Object... args) {
|
|
+ super(MessageFormat.format(key, args));
|
|
+ this.key = key;
|
|
+ this.args = args;
|
|
+ }
|
|
+
|
|
+ BadArgs showUsage(boolean b) {
|
|
+ showUsage = b;
|
|
+ return this;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ abstract static class Option {
|
|
+ final String help;
|
|
+ final boolean hasArg;
|
|
+ final String[] aliases;
|
|
+
|
|
+ Option(String help, boolean hasArg, String... aliases) {
|
|
+ this.help = help;
|
|
+ this.hasArg = hasArg;
|
|
+ this.aliases = aliases;
|
|
+ }
|
|
+
|
|
+ boolean isHidden() {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ boolean matches(String opt) {
|
|
+ for (String a : aliases) {
|
|
+ if (a.equals(opt)) {
|
|
+ return true;
|
|
+ } else if (opt.startsWith("--") && hasArg && opt.startsWith(a + "=")) {
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ boolean ignoreRest() {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ abstract void process(Main task, String opt, String arg) throws BadArgs;
|
|
+ }
|
|
+
|
|
+ static Option[] recognizedOptions = {new Option(" --output <file> Output file name", true, "--output") {
|
|
+ @Override
|
|
+ void process(Main task, String opt, String arg) {
|
|
+ String name = arg;
|
|
+ task.options.outputName = name;
|
|
+ }
|
|
+ }, new Option(" --class-name <class names> List of classes to compile", true, "--class-name", "--classname") {
|
|
+ @Override
|
|
+ void process(Main task, String opt, String arg) {
|
|
+ task.options.files.addAll(ClassSearch.makeList(ClassNameSourceProvider.TYPE, arg));
|
|
+ }
|
|
+ }, new Option(" --jar <jarfiles> List of jar files to compile", true, "--jar") {
|
|
+ @Override
|
|
+ void process(Main task, String opt, String arg) {
|
|
+ task.options.files.addAll(ClassSearch.makeList(JarSourceProvider.TYPE, arg));
|
|
+ }
|
|
+ }, new Option(" --module <modules> List of modules to compile", true, "--module") {
|
|
+ @Override
|
|
+ void process(Main task, String opt, String arg) {
|
|
+ task.options.files.addAll(ClassSearch.makeList(ModuleSourceProvider.TYPE, arg));
|
|
+ }
|
|
+ }, new Option(" --directory <dirs> List of directories where to search for files to compile", true, "--directory") {
|
|
+ @Override
|
|
+ void process(Main task, String opt, String arg) {
|
|
+ task.options.files.addAll(ClassSearch.makeList(DirectorySourceProvider.TYPE, arg));
|
|
+ }
|
|
+ }, new Option(" --search-path <dirs> List of directories where to search for specified files", true, "--search-path") {
|
|
+ @Override
|
|
+ void process(Main task, String opt, String arg) {
|
|
+ String[] elements = arg.split(":");
|
|
+ task.options.searchPath.add(elements);
|
|
+ }
|
|
+ }, new Option(" --compile-commands <file> Name of file with compile commands", true, "--compile-commands") {
|
|
+ @Override
|
|
+ void process(Main task, String opt, String arg) {
|
|
+ task.options.methodList = arg;
|
|
+ }
|
|
+ }, new Option(" --compile-for-tiered Generate profiling code for tiered compilation", false, "--compile-for-tiered") {
|
|
+ @Override
|
|
+ void process(Main task, String opt, String arg) {
|
|
+ task.options.tiered = true;
|
|
+ }
|
|
+ }, new Option(" --compile-with-assertions Compile with java assertions", false, "--compile-with-assertions") {
|
|
+ @Override
|
|
+ void process(Main task, String opt, String arg) {
|
|
+ task.options.compileWithAssertions = true;
|
|
+ }
|
|
+ }, new Option(" --compile-threads <number> Number of compilation threads to be used", true, "--compile-threads", "--threads") {
|
|
+ @Override
|
|
+ void process(Main task, String opt, String arg) {
|
|
+ int threads = Integer.parseInt(arg);
|
|
+ final int available = Runtime.getRuntime().availableProcessors();
|
|
+ if (threads <= 0) {
|
|
+ task.warning("invalid number of threads specified: {0}, using: {1}", threads, available);
|
|
+ threads = available;
|
|
+ }
|
|
+ if (threads > available) {
|
|
+ task.warning("too many threads specified: {0}, limiting to: {1}", threads, available);
|
|
+ }
|
|
+ task.options.threads = Integer.min(threads, available);
|
|
+ }
|
|
+ }, new Option(" --ignore-errors Ignores all exceptions thrown during class loading", false, "--ignore-errors") {
|
|
+ @Override
|
|
+ void process(Main task, String opt, String arg) {
|
|
+ task.options.ignoreClassLoadingErrors = true;
|
|
+ }
|
|
+ }, new Option(" --exit-on-error Exit on compilation errors", false, "--exit-on-error") {
|
|
+ @Override
|
|
+ void process(Main task, String opt, String arg) {
|
|
+ task.options.exitOnError = true;
|
|
+ }
|
|
+ }, new Option(" --info Print information during compilation", false, "--info") {
|
|
+ @Override
|
|
+ void process(Main task, String opt, String arg) throws BadArgs {
|
|
+ task.options.info = true;
|
|
+ }
|
|
+ }, new Option(" --verbose Print verbose information", false, "--verbose") {
|
|
+ @Override
|
|
+ void process(Main task, String opt, String arg) throws BadArgs {
|
|
+ task.options.info = true;
|
|
+ task.options.verbose = true;
|
|
+ }
|
|
+ }, new Option(" --debug Print debug information", false, "--debug") {
|
|
+ @Override
|
|
+ void process(Main task, String opt, String arg) throws BadArgs {
|
|
+ task.options.info = true;
|
|
+ task.options.verbose = true;
|
|
+ task.options.debug = true;
|
|
+ }
|
|
+ }, new Option(" -? -h --help Print this help message", false, "--help", "-h", "-?") {
|
|
+ @Override
|
|
+ void process(Main task, String opt, String arg) {
|
|
+ task.options.help = true;
|
|
+ }
|
|
+ }, new Option(" --version Version information", false, "--version") {
|
|
+ @Override
|
|
+ void process(Main task, String opt, String arg) {
|
|
+ task.options.version = true;
|
|
+ }
|
|
+ }, new Option(" --linker-path Full path to linker executable", true, "--linker-path") {
|
|
+ @Override
|
|
+ void process(Main task, String opt, String arg) {
|
|
+ task.options.linkerpath = arg;
|
|
+ }
|
|
+ }, new Option(" -J<flag> Pass <flag> directly to the runtime system", false, "-J") {
|
|
+ @Override
|
|
+ void process(Main task, String opt, String arg) {
|
|
+ }
|
|
+ }};
|
|
+
|
|
+ static void handleOptions(Main task, String[] args) throws BadArgs {
|
|
+ if (args.length == 0) {
|
|
+ task.options.help = true;
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ // Make checkstyle happy.
|
|
+ int i = 0;
|
|
+ while (i < args.length) {
|
|
+ String arg = args[i];
|
|
+
|
|
+ if (arg.charAt(0) == '-') {
|
|
+ Option option = getOption(arg);
|
|
+ String param = null;
|
|
+
|
|
+ if (option.hasArg) {
|
|
+ if (arg.startsWith("--") && arg.indexOf('=') > 0) {
|
|
+ param = arg.substring(arg.indexOf('=') + 1, arg.length());
|
|
+ } else if (i + 1 < args.length) {
|
|
+ param = args[++i];
|
|
+ }
|
|
+
|
|
+ if (param == null || param.isEmpty() || param.charAt(0) == '-') {
|
|
+ throw new BadArgs("missing argument for option: {0}", arg).showUsage(true);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ option.process(task, arg, param);
|
|
+
|
|
+ if (option.ignoreRest()) {
|
|
+ break;
|
|
+ }
|
|
+ } else {
|
|
+ task.options.files.add(new SearchFor(arg));
|
|
+ }
|
|
+ i++;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ static Option getOption(String name) throws BadArgs {
|
|
+ for (Option o : recognizedOptions) {
|
|
+ if (o.matches(name)) {
|
|
+ return o;
|
|
+ }
|
|
+ }
|
|
+ throw new BadArgs("unknown option: {0}", name).showUsage(true);
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/StubDirectCallSiteRelocationSymbol.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/StubDirectCallSiteRelocationSymbol.java
|
|
new file mode 100644
|
|
index 000000000..e41987ab4
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/StubDirectCallSiteRelocationSymbol.java
|
|
@@ -0,0 +1,41 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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;
|
|
+
|
|
+import jdk.tools.jaotc.binformat.BinaryContainer;
|
|
+import jdk.tools.jaotc.binformat.Symbol.Binding;
|
|
+
|
|
+/**
|
|
+ * Call to a Graal stub, the symbol name should be direct.
|
|
+ */
|
|
+final class StubDirectCallSiteRelocationSymbol extends CallSiteRelocationSymbol {
|
|
+
|
|
+ StubDirectCallSiteRelocationSymbol(CallSiteRelocationInfo callSiteRelocation, BinaryContainer binaryContainer) {
|
|
+ super(binaryContainer.getSymbol(callSiteRelocation.targetSymbol));
|
|
+ assert symbol != null && symbol.getBinding() == Binding.LOCAL : "Stub symbol must exist and must be LOCAL";
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/StubInformation.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/StubInformation.java
|
|
new file mode 100644
|
|
index 000000000..53e701abf
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/StubInformation.java
|
|
@@ -0,0 +1,124 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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;
|
|
+
|
|
+public final class StubInformation {
|
|
+ private int stubOffset; // the offset inside the code (text + stubOffset)
|
|
+ private int stubSize; // the stub size
|
|
+ private int dispatchJumpOffset; // offset after main dispatch jump instruction
|
|
+ private int resolveJumpOffset; // offset after jump instruction to runtime call resolution
|
|
+ // function.
|
|
+ private int resolveJumpStart; // offset of jump instruction to VM runtime call resolution
|
|
+ // function.
|
|
+ private int c2iJumpOffset; // offset after jump instruction to c2i adapter for static
|
|
+ // calls.
|
|
+ private int movOffset; // offset after move instruction which loads from got cell:
|
|
+ // - Method* for static call
|
|
+ // - Klass* for virtual call
|
|
+
|
|
+ private boolean isVirtual; // virtual call stub
|
|
+
|
|
+ // maybe add type of stub as well, right now we only have static stubs
|
|
+
|
|
+ StubInformation(int stubOffset, boolean isVirtual) {
|
|
+ this.stubOffset = stubOffset;
|
|
+ this.isVirtual = isVirtual;
|
|
+ this.stubSize = -1;
|
|
+ this.movOffset = -1;
|
|
+ this.c2iJumpOffset = -1;
|
|
+ this.resolveJumpOffset = -1;
|
|
+ this.resolveJumpStart = -1;
|
|
+ this.dispatchJumpOffset = -1;
|
|
+ }
|
|
+
|
|
+ int getOffset() {
|
|
+ return stubOffset;
|
|
+ }
|
|
+
|
|
+ boolean isVirtual() {
|
|
+ return isVirtual;
|
|
+ }
|
|
+
|
|
+ public void setSize(int stubSize) {
|
|
+ this.stubSize = stubSize;
|
|
+ }
|
|
+
|
|
+ int getSize() {
|
|
+ return stubSize;
|
|
+ }
|
|
+
|
|
+ public void setMovOffset(int movOffset) {
|
|
+ this.movOffset = movOffset + stubOffset;
|
|
+ }
|
|
+
|
|
+ int getMovOffset() {
|
|
+ return movOffset;
|
|
+ }
|
|
+
|
|
+ public void setC2IJumpOffset(int c2iJumpOffset) {
|
|
+ this.c2iJumpOffset = c2iJumpOffset + stubOffset;
|
|
+ }
|
|
+
|
|
+ int getC2IJumpOffset() {
|
|
+ return c2iJumpOffset;
|
|
+ }
|
|
+
|
|
+ public void setResolveJumpOffset(int resolveJumpOffset) {
|
|
+ this.resolveJumpOffset = resolveJumpOffset + stubOffset;
|
|
+ }
|
|
+
|
|
+ int getResolveJumpOffset() {
|
|
+ return resolveJumpOffset;
|
|
+ }
|
|
+
|
|
+ public void setResolveJumpStart(int resolveJumpStart) {
|
|
+ this.resolveJumpStart = resolveJumpStart + stubOffset;
|
|
+ }
|
|
+
|
|
+ int getResolveJumpStart() {
|
|
+ return resolveJumpStart;
|
|
+ }
|
|
+
|
|
+ public void setDispatchJumpOffset(int dispatchJumpOffset) {
|
|
+ this.dispatchJumpOffset = dispatchJumpOffset + stubOffset;
|
|
+ }
|
|
+
|
|
+ int getDispatchJumpOffset() {
|
|
+ return dispatchJumpOffset;
|
|
+ }
|
|
+
|
|
+ void verify() {
|
|
+ assert stubOffset > 0 : "incorrect stubOffset: " + stubOffset;
|
|
+ assert stubSize > 0 : "incorrect stubSize: " + stubSize;
|
|
+ assert movOffset > 0 : "incorrect movOffset: " + movOffset;
|
|
+ assert dispatchJumpOffset > 0 : "incorrect dispatchJumpOffset: " + dispatchJumpOffset;
|
|
+ assert resolveJumpStart > 0 : "incorrect resolveJumpStart: " + resolveJumpStart;
|
|
+ assert resolveJumpOffset > 0 : "incorrect resolveJumpOffset: " + resolveJumpOffset;
|
|
+ if (!isVirtual) {
|
|
+ assert c2iJumpOffset > 0 : "incorrect c2iJumpOffset: " + c2iJumpOffset;
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Timer.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Timer.java
|
|
new file mode 100644
|
|
index 000000000..e7f81b5ef
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Timer.java
|
|
@@ -0,0 +1,45 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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;
|
|
+
|
|
+final class Timer implements AutoCloseable {
|
|
+
|
|
+ private final Main main;
|
|
+ private final long start;
|
|
+
|
|
+ Timer(Main main, String message) {
|
|
+ this.main = main;
|
|
+ start = System.currentTimeMillis();
|
|
+ main.printer.printInfo(message);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void close() {
|
|
+ final long end = System.currentTimeMillis();
|
|
+ main.printer.printlnInfo(" (" + (end - start) + " ms)");
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/aarch64/AArch64ELFMacroAssembler.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/aarch64/AArch64ELFMacroAssembler.java
|
|
new file mode 100644
|
|
index 000000000..c3d28cae2
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/aarch64/AArch64ELFMacroAssembler.java
|
|
@@ -0,0 +1,131 @@
|
|
+/*
|
|
+ * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2018, 2023, Red Hat Inc. 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.aarch64;
|
|
+
|
|
+import static jdk.vm.ci.aarch64.AArch64.r12;
|
|
+import static jdk.vm.ci.aarch64.AArch64.r16;
|
|
+import static jdk.vm.ci.aarch64.AArch64.r17;
|
|
+import static jdk.vm.ci.aarch64.AArch64.r9;
|
|
+
|
|
+import org.graalvm.compiler.asm.aarch64.AArch64Address;
|
|
+import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler;
|
|
+
|
|
+import jdk.tools.jaotc.ELFMacroAssembler;
|
|
+import jdk.tools.jaotc.StubInformation;
|
|
+import jdk.vm.ci.code.TargetDescription;
|
|
+
|
|
+public final class AArch64ELFMacroAssembler extends AArch64MacroAssembler implements ELFMacroAssembler {
|
|
+
|
|
+ private int currentEndOfInstruction;
|
|
+
|
|
+ public AArch64ELFMacroAssembler(TargetDescription target) {
|
|
+ super(target);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public int currentEndOfInstruction() {
|
|
+ return currentEndOfInstruction;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public byte[] getPLTJumpCode() {
|
|
+ // The main dispatch instruction
|
|
+ addressOf(r16);
|
|
+ ldr(64, r16, AArch64Address.createBaseRegisterOnlyAddress(r16));
|
|
+ jmp(r16);
|
|
+
|
|
+ currentEndOfInstruction = position();
|
|
+
|
|
+ align(8);
|
|
+
|
|
+ return close(true);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public byte[] getPLTStaticEntryCode(StubInformation stub) {
|
|
+ // The main dispatch instruction
|
|
+ addressOf(r16);
|
|
+ ldr(64, r16, AArch64Address.createBaseRegisterOnlyAddress(r16));
|
|
+ jmp(r16);
|
|
+ stub.setDispatchJumpOffset(position());
|
|
+
|
|
+ // C2I stub used to call interpreter. First load r12
|
|
+ // (i.e. rmethod) with a pointer to the Method structure ...
|
|
+ addressOf(r12);
|
|
+ ldr(64, r12, AArch64Address.createBaseRegisterOnlyAddress(r12));
|
|
+ nop();
|
|
+ stub.setMovOffset(position());
|
|
+
|
|
+ // ... then jump to the interpreter.
|
|
+ addressOf(r16);
|
|
+ ldr(64, r16, AArch64Address.createBaseRegisterOnlyAddress(r16));
|
|
+ jmp(r16);
|
|
+ stub.setC2IJumpOffset(position());
|
|
+
|
|
+ // Call to VM runtime to resolve the call.
|
|
+ stub.setResolveJumpStart(position());
|
|
+ addressOf(r16);
|
|
+ ldr(64, r16, AArch64Address.createBaseRegisterOnlyAddress(r16));
|
|
+ jmp(r16);
|
|
+ stub.setResolveJumpOffset(position());
|
|
+ currentEndOfInstruction = position();
|
|
+
|
|
+ align(8);
|
|
+ stub.setSize(position());
|
|
+
|
|
+ return close(true);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public byte[] getPLTVirtualEntryCode(StubInformation stub) {
|
|
+ // Fixup an inline cache.
|
|
+ // Load r9 with a pointer to the Klass.
|
|
+ addressOf(r17);
|
|
+ ldr(64, r9, AArch64Address.createBaseRegisterOnlyAddress(r17));
|
|
+ nop();
|
|
+ stub.setMovOffset(position());
|
|
+
|
|
+ // Jump to the method.
|
|
+ addressOf(r16);
|
|
+ ldr(64, r16, AArch64Address.createBaseRegisterOnlyAddress(r16));
|
|
+ jmp(r16);
|
|
+ stub.setDispatchJumpOffset(position());
|
|
+
|
|
+ // Call to VM runtime to resolve the call.
|
|
+ stub.setResolveJumpStart(position());
|
|
+ addressOf(r16);
|
|
+ ldr(64, r16, AArch64Address.createBaseRegisterOnlyAddress(r16));
|
|
+ jmp(r16);
|
|
+ stub.setResolveJumpOffset(position());
|
|
+ currentEndOfInstruction = position();
|
|
+
|
|
+ align(8);
|
|
+ stub.setSize(position());
|
|
+
|
|
+ return close(true);
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/aarch64/AArch64InstructionDecoder.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/aarch64/AArch64InstructionDecoder.java
|
|
new file mode 100644
|
|
index 000000000..a6979061a
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/aarch64/AArch64InstructionDecoder.java
|
|
@@ -0,0 +1,47 @@
|
|
+/*
|
|
+ * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2018, 2023, Red Hat Inc. 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.aarch64;
|
|
+
|
|
+import jdk.tools.jaotc.InstructionDecoder;
|
|
+
|
|
+public final class AArch64InstructionDecoder extends InstructionDecoder {
|
|
+
|
|
+ private int currentEndOfInstruction;
|
|
+
|
|
+ public AArch64InstructionDecoder() {
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public int currentEndOfInstruction() {
|
|
+ return currentEndOfInstruction;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void decodePosition(final byte[] code, int pcOffset) {
|
|
+ currentEndOfInstruction = pcOffset + 4;
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/amd64/AMD64ELFMacroAssembler.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/amd64/AMD64ELFMacroAssembler.java
|
|
new file mode 100644
|
|
index 000000000..0f28a365b
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/amd64/AMD64ELFMacroAssembler.java
|
|
@@ -0,0 +1,122 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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.amd64;
|
|
+
|
|
+import static jdk.vm.ci.amd64.AMD64.rax;
|
|
+import static jdk.vm.ci.amd64.AMD64.rbx;
|
|
+import static jdk.vm.ci.amd64.AMD64.rip;
|
|
+
|
|
+import jdk.tools.jaotc.StubInformation;
|
|
+import jdk.tools.jaotc.ELFMacroAssembler;
|
|
+import org.graalvm.compiler.asm.amd64.AMD64Address;
|
|
+import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
|
|
+
|
|
+import jdk.vm.ci.code.TargetDescription;
|
|
+import org.graalvm.compiler.options.OptionValues;
|
|
+
|
|
+public final class AMD64ELFMacroAssembler extends AMD64MacroAssembler implements ELFMacroAssembler {
|
|
+
|
|
+ private int currentEndOfInstruction;
|
|
+
|
|
+ public AMD64ELFMacroAssembler(TargetDescription target, OptionValues optionValues) {
|
|
+ super(target, optionValues);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public int currentEndOfInstruction() {
|
|
+ return currentEndOfInstruction;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public byte[] getPLTJumpCode() {
|
|
+ // The main dispatch instruction
|
|
+ // jmpq *0x00000000(%rip)
|
|
+ jmp(new AMD64Address(rip, 0));
|
|
+ currentEndOfInstruction = position();
|
|
+
|
|
+ // Align to 8 bytes
|
|
+ align(8);
|
|
+
|
|
+ return close(true);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public byte[] getPLTStaticEntryCode(StubInformation stub) {
|
|
+ // The main dispatch instruction
|
|
+ // jmpq *0x00000000(%rip)
|
|
+ jmp(new AMD64Address(rip, 0));
|
|
+ stub.setDispatchJumpOffset(position());
|
|
+
|
|
+ // C2I stub used to call interpreter.
|
|
+ // mov 0x00000000(%rip),%rbx Loading Method*
|
|
+ movq(rbx, new AMD64Address(rip, 0));
|
|
+ stub.setMovOffset(position());
|
|
+
|
|
+ // jmpq *0x00000000(%rip) [c2i addr]
|
|
+ jmp(new AMD64Address(rip, 0));
|
|
+ stub.setC2IJumpOffset(position());
|
|
+
|
|
+ // Call to VM runtime to resolve the call.
|
|
+ // jmpq *0x00000000(%rip)
|
|
+ stub.setResolveJumpStart(position());
|
|
+ jmp(new AMD64Address(rip, 0));
|
|
+ stub.setResolveJumpOffset(position());
|
|
+ currentEndOfInstruction = position();
|
|
+
|
|
+ // Align to 8 bytes
|
|
+ align(8);
|
|
+ stub.setSize(position());
|
|
+
|
|
+ return close(true);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public byte[] getPLTVirtualEntryCode(StubInformation stub) {
|
|
+ // Klass loading instruction
|
|
+ // mov 0x00000000(%rip),%rax
|
|
+ movq(rax, new AMD64Address(rip, 0));
|
|
+ stub.setMovOffset(position());
|
|
+
|
|
+ // The main dispatch instruction
|
|
+ // jmpq *0x00000000(%rip)
|
|
+ jmp(new AMD64Address(rip, 0));
|
|
+ stub.setDispatchJumpOffset(position());
|
|
+
|
|
+ // Call to VM runtime to resolve the call.
|
|
+ // jmpq *0x00000000(%rip)
|
|
+ stub.setResolveJumpStart(position());
|
|
+ jmp(new AMD64Address(rip, 0));
|
|
+ stub.setResolveJumpOffset(position());
|
|
+ currentEndOfInstruction = position();
|
|
+
|
|
+ // Align to 8 bytes
|
|
+ align(8);
|
|
+ stub.setSize(position());
|
|
+
|
|
+ return close(true);
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/amd64/AMD64InstructionDecoder.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/amd64/AMD64InstructionDecoder.java
|
|
new file mode 100644
|
|
index 000000000..8c950b83e
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/amd64/AMD64InstructionDecoder.java
|
|
@@ -0,0 +1,569 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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.amd64;
|
|
+
|
|
+import jdk.tools.jaotc.InstructionDecoder;
|
|
+
|
|
+import jdk.vm.ci.code.TargetDescription;
|
|
+
|
|
+public final class AMD64InstructionDecoder extends InstructionDecoder {
|
|
+
|
|
+ private boolean targetIs64Bit;
|
|
+ private int currentEndOfInstruction;
|
|
+
|
|
+ private static class Prefix {
|
|
+
|
|
+ // segment overrides
|
|
+ static final int CSSegment = 0x2e;
|
|
+ static final int SSSegment = 0x36;
|
|
+ static final int DSSegment = 0x3e;
|
|
+ static final int ESSegment = 0x26;
|
|
+ static final int FSSegment = 0x64;
|
|
+ static final int GSSegment = 0x65;
|
|
+ static final int REX = 0x40;
|
|
+ static final int REXB = 0x41;
|
|
+ static final int REXX = 0x42;
|
|
+ static final int REXXB = 0x43;
|
|
+ static final int REXR = 0x44;
|
|
+ static final int REXRB = 0x45;
|
|
+ static final int REXRX = 0x46;
|
|
+ static final int REXRXB = 0x47;
|
|
+ static final int REXW = 0x48;
|
|
+ static final int REXWB = 0x49;
|
|
+ static final int REXWX = 0x4A;
|
|
+ static final int REXWXB = 0x4B;
|
|
+ static final int REXWR = 0x4C;
|
|
+ static final int REXWRB = 0x4D;
|
|
+ static final int REXWRX = 0x4E;
|
|
+ static final int REXWRXB = 0x4F;
|
|
+ static final int VEX_3BYTES = 0xC4;
|
|
+ static final int VEX_2BYTES = 0xC5;
|
|
+ }
|
|
+
|
|
+ @SuppressWarnings("unused")
|
|
+ private static class VexPrefix {
|
|
+ static final int VEX_R = 0x80;
|
|
+ static final int VEX_W = 0x80;
|
|
+ }
|
|
+
|
|
+ @SuppressWarnings("unused")
|
|
+ private static class VexOpcode {
|
|
+ static final int VEX_OPCODE_NONE = 0x0;
|
|
+ static final int VEX_OPCODE_0F = 0x1;
|
|
+ static final int VEX_OPCODE_0F_38 = 0x2;
|
|
+ static final int VEX_OPCODE_0F_3A = 0x3;
|
|
+ static final int VEX_OPCODE_MASK = 0x1F;
|
|
+ }
|
|
+
|
|
+ public AMD64InstructionDecoder(TargetDescription target) {
|
|
+ this.targetIs64Bit = target.wordSize == 8;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public int currentEndOfInstruction() {
|
|
+ return currentEndOfInstruction;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ @SuppressWarnings("fallthrough")
|
|
+ public void decodePosition(final byte[] code, int pcOffset) {
|
|
+ assert pcOffset >= 0 && pcOffset < code.length;
|
|
+
|
|
+ // Decode the given instruction, and return the Pointer of
|
|
+ // an embedded 32-bit operand word.
|
|
+
|
|
+ // If "which" is WhichOperand.disp32operand, selects the displacement portion
|
|
+ // of an effective Pointer specifier.
|
|
+ // If "which" is imm64Operand, selects the trailing immediate constant.
|
|
+ // If "which" is WhichOperand.call32operand, selects the displacement of a call or jump.
|
|
+ // Caller is responsible for ensuring that there is such an operand,
|
|
+ // and that it is 32/64 bits wide.
|
|
+
|
|
+ // If "which" is endPcOperand, find the end of the instruction.
|
|
+
|
|
+ int ip = pcOffset;
|
|
+ boolean is64bit = false;
|
|
+
|
|
+ boolean hasDisp32 = false;
|
|
+ int tailSize = 0; // other random bytes (#32, #16, etc.) at end of insn
|
|
+
|
|
+ boolean againAfterPrefix = true;
|
|
+
|
|
+ while (againAfterPrefix) {
|
|
+ againAfterPrefix = false;
|
|
+ switch (0xFF & code[ip++]) {
|
|
+
|
|
+ // These convenience macros generate groups of "case" labels for the switch.
|
|
+
|
|
+ case Prefix.CSSegment:
|
|
+ case Prefix.SSSegment:
|
|
+ case Prefix.DSSegment:
|
|
+ case Prefix.ESSegment:
|
|
+ case Prefix.FSSegment:
|
|
+ case Prefix.GSSegment:
|
|
+ // Seems dubious
|
|
+ assert !targetIs64Bit : "shouldn't have that prefix";
|
|
+ assert ip == pcOffset + 1 : "only one prefix allowed";
|
|
+ againAfterPrefix = true;
|
|
+ break;
|
|
+
|
|
+ case 0x67:
|
|
+ case Prefix.REX:
|
|
+ case Prefix.REXB:
|
|
+ case Prefix.REXX:
|
|
+ case Prefix.REXXB:
|
|
+ case Prefix.REXR:
|
|
+ case Prefix.REXRB:
|
|
+ case Prefix.REXRX:
|
|
+ case Prefix.REXRXB:
|
|
+ assert targetIs64Bit : "64bit prefixes";
|
|
+ againAfterPrefix = true;
|
|
+ break;
|
|
+
|
|
+ case Prefix.REXW:
|
|
+ case Prefix.REXWB:
|
|
+ case Prefix.REXWX:
|
|
+ case Prefix.REXWXB:
|
|
+ case Prefix.REXWR:
|
|
+ case Prefix.REXWRB:
|
|
+ case Prefix.REXWRX:
|
|
+ case Prefix.REXWRXB:
|
|
+ assert targetIs64Bit : "64bit prefixes";
|
|
+ is64bit = true;
|
|
+ againAfterPrefix = true;
|
|
+ break;
|
|
+
|
|
+ case 0xFF: // pushq a; decl a; incl a; call a; jmp a
|
|
+ case 0x88: // movb a, r
|
|
+ case 0x89: // movl a, r
|
|
+ case 0x8A: // movb r, a
|
|
+ case 0x8B: // movl r, a
|
|
+ case 0x8F: // popl a
|
|
+ hasDisp32 = true;
|
|
+ break;
|
|
+
|
|
+ case 0x68: // pushq #32
|
|
+ currentEndOfInstruction = ip + 4;
|
|
+ return; // not produced by emitOperand
|
|
+
|
|
+ case 0x66: // movw ... (size prefix)
|
|
+ boolean againAfterSizePrefix2 = true;
|
|
+ while (againAfterSizePrefix2) {
|
|
+ againAfterSizePrefix2 = false;
|
|
+ switch (0xFF & code[ip++]) {
|
|
+ case Prefix.REX:
|
|
+ case Prefix.REXB:
|
|
+ case Prefix.REXX:
|
|
+ case Prefix.REXXB:
|
|
+ case Prefix.REXR:
|
|
+ case Prefix.REXRB:
|
|
+ case Prefix.REXRX:
|
|
+ case Prefix.REXRXB:
|
|
+ case Prefix.REXW:
|
|
+ case Prefix.REXWB:
|
|
+ case Prefix.REXWX:
|
|
+ case Prefix.REXWXB:
|
|
+ case Prefix.REXWR:
|
|
+ case Prefix.REXWRB:
|
|
+ case Prefix.REXWRX:
|
|
+ case Prefix.REXWRXB:
|
|
+ assert targetIs64Bit : "64bit prefix found";
|
|
+ againAfterSizePrefix2 = true;
|
|
+ break;
|
|
+ case 0x8B: // movw r, a
|
|
+ case 0x89: // movw a, r
|
|
+ hasDisp32 = true;
|
|
+ break;
|
|
+ case 0xC7: // movw a, #16
|
|
+ hasDisp32 = true;
|
|
+ tailSize = 2; // the imm16
|
|
+ break;
|
|
+ case 0x0F: // several SSE/SSE2 variants
|
|
+ ip--; // reparse the 0x0F
|
|
+ againAfterPrefix = true;
|
|
+ break;
|
|
+ default:
|
|
+ throw new InternalError("should not reach here");
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case 0xB8: // movl/q r, #32/#64(oop?)
|
|
+ case 0xB9:
|
|
+ case 0xBA:
|
|
+ case 0xBB:
|
|
+ case 0xBC:
|
|
+ case 0xBD:
|
|
+ case 0xBE:
|
|
+ case 0xBF:
|
|
+ currentEndOfInstruction = ip + (is64bit ? 8 : 4);
|
|
+ return;
|
|
+
|
|
+ case 0x69: // imul r, a, #32
|
|
+ case 0xC7: // movl a, #32(oop?)
|
|
+ tailSize = 4;
|
|
+ hasDisp32 = true; // has both kinds of operands!
|
|
+ break;
|
|
+
|
|
+ case 0x0F: // movx..., etc.
|
|
+ switch (0xFF & code[ip++]) {
|
|
+ case 0x3A: // pcmpestri
|
|
+ ip++; // skip opcode
|
|
+ tailSize = 1;
|
|
+ hasDisp32 = true; // has both kinds of operands!
|
|
+ break;
|
|
+
|
|
+ case 0x38: // ptest, pmovzxbw
|
|
+ ip++; // skip opcode
|
|
+ hasDisp32 = true; // has both kinds of operands!
|
|
+ break;
|
|
+
|
|
+ case 0x70: // pshufd r, r/a, #8
|
|
+ hasDisp32 = true; // has both kinds of operands!
|
|
+ tailSize = 1;
|
|
+ break;
|
|
+
|
|
+ case 0x73: // psrldq r, #8
|
|
+ tailSize = 1;
|
|
+ break;
|
|
+
|
|
+ case 0x12: // movlps
|
|
+ case 0x28: // movaps
|
|
+ case 0x2E: // ucomiss
|
|
+ case 0x2F: // comiss
|
|
+ case 0x54: // andps
|
|
+ case 0x55: // andnps
|
|
+ case 0x56: // orps
|
|
+ case 0x57: // xorps
|
|
+ case 0x58: // addpd
|
|
+ case 0x59: // mulpd
|
|
+ case 0x6E: // movd
|
|
+ case 0x7E: // movd
|
|
+ case 0xAE: // ldmxcsr, stmxcsr, fxrstor, fxsave, clflush
|
|
+ case 0xFE: // paddd
|
|
+ // 64bit side says it these have both operands but that doesn't
|
|
+ // appear to be true
|
|
+ hasDisp32 = true;
|
|
+ break;
|
|
+
|
|
+ case 0xAD: // shrd r, a, %cl
|
|
+ case 0xAF: // imul r, a
|
|
+ case 0xBE: // movsbl r, a (movsxb)
|
|
+ case 0xBF: // movswl r, a (movsxw)
|
|
+ case 0xB6: // movzbl r, a (movzxb)
|
|
+ case 0xB7: // movzwl r, a (movzxw)
|
|
+ case 0x40: // cmovl cc, r, a
|
|
+ case 0x41:
|
|
+ case 0x42:
|
|
+ case 0x43:
|
|
+ case 0x44:
|
|
+ case 0x45:
|
|
+ case 0x46:
|
|
+ case 0x47:
|
|
+ case 0x48:
|
|
+ case 0x49:
|
|
+ case 0x4A:
|
|
+ case 0x4B:
|
|
+ case 0x4C:
|
|
+ case 0x4D:
|
|
+ case 0x4E:
|
|
+ case 0x4F:
|
|
+ case 0xB0: // cmpxchgb
|
|
+ case 0xB1: // cmpxchg
|
|
+ case 0xC1: // xaddl
|
|
+ case 0xC7: // cmpxchg8
|
|
+ case 0x90: // setcc a
|
|
+ case 0x91:
|
|
+ case 0x92:
|
|
+ case 0x93:
|
|
+ case 0x94:
|
|
+ case 0x95:
|
|
+ case 0x96:
|
|
+ case 0x97:
|
|
+ case 0x98:
|
|
+ case 0x99:
|
|
+ case 0x9A:
|
|
+ case 0x9B:
|
|
+ case 0x9C:
|
|
+ case 0x9D:
|
|
+ case 0x9E:
|
|
+ case 0x9F:
|
|
+ hasDisp32 = true;
|
|
+ // fall out of the switch to decode the Pointer
|
|
+ break;
|
|
+
|
|
+ case 0xC4: // pinsrw r, a, #8
|
|
+ hasDisp32 = true;
|
|
+ tailSize = 1; // the imm8
|
|
+ break;
|
|
+
|
|
+ case 0xC5: // pextrw r, r, #8
|
|
+ tailSize = 1; // the imm8
|
|
+ break;
|
|
+
|
|
+ case 0xAC: // shrd r, a, #8
|
|
+ hasDisp32 = true;
|
|
+ tailSize = 1; // the imm8
|
|
+ break;
|
|
+
|
|
+ case 0x80: // jcc rdisp32
|
|
+ case 0x81:
|
|
+ case 0x82:
|
|
+ case 0x83:
|
|
+ case 0x84:
|
|
+ case 0x85:
|
|
+ case 0x86:
|
|
+ case 0x87:
|
|
+ case 0x88:
|
|
+ case 0x89:
|
|
+ case 0x8A:
|
|
+ case 0x8B:
|
|
+ case 0x8C:
|
|
+ case 0x8D:
|
|
+ case 0x8E:
|
|
+ case 0x8F:
|
|
+ currentEndOfInstruction = ip + 4;
|
|
+ return;
|
|
+ default:
|
|
+ throw new InternalError("should not reach here");
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case 0x81: // addl a, #32; addl r, #32
|
|
+ // also: orl, adcl, sbbl, andl, subl, xorl, cmpl
|
|
+ // on 32bit in the case of cmpl, the imm might be an oop
|
|
+ tailSize = 4;
|
|
+ hasDisp32 = true; // has both kinds of operands!
|
|
+ break;
|
|
+
|
|
+ case 0x83: // addl a, #8; addl r, #8
|
|
+ // also: orl, adcl, sbbl, andl, subl, xorl, cmpl
|
|
+ hasDisp32 = true; // has both kinds of operands!
|
|
+ tailSize = 1;
|
|
+ break;
|
|
+
|
|
+ case 0x9B:
|
|
+ switch (0xFF & code[ip++]) {
|
|
+ case 0xD9: // fnstcw a
|
|
+ hasDisp32 = true;
|
|
+ break;
|
|
+ default:
|
|
+ throw new InternalError("should not reach here");
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case 0x00: // addb a, r; addl a, r; addb r, a; addl r, a
|
|
+ case 0x01:
|
|
+ case 0x02:
|
|
+ case 0x03:
|
|
+ case 0x10: // adc...
|
|
+ case 0x11:
|
|
+ case 0x12:
|
|
+ case 0x13:
|
|
+ case 0x20: // and...
|
|
+ case 0x21:
|
|
+ case 0x22:
|
|
+ case 0x23:
|
|
+ case 0x30: // xor...
|
|
+ case 0x31:
|
|
+ case 0x32:
|
|
+ case 0x33:
|
|
+ case 0x08: // or...
|
|
+ case 0x09:
|
|
+ case 0x0a:
|
|
+ case 0x0b:
|
|
+ case 0x18: // sbb...
|
|
+ case 0x19:
|
|
+ case 0x1a:
|
|
+ case 0x1b:
|
|
+ case 0x28: // sub...
|
|
+ case 0x29:
|
|
+ case 0x2a:
|
|
+ case 0x2b:
|
|
+ case 0xF7: // mull a
|
|
+ case 0x8D: // lea r, a
|
|
+ case 0x87: // xchg r, a
|
|
+ case 0x38: // cmp...
|
|
+ case 0x39:
|
|
+ case 0x3a:
|
|
+ case 0x3b:
|
|
+ case 0x85: // test r, a
|
|
+ hasDisp32 = true; // has both kinds of operands!
|
|
+ break;
|
|
+
|
|
+ case 0xC1: // sal a, #8; sar a, #8; shl a, #8; shr a, #8
|
|
+ case 0xC6: // movb a, #8
|
|
+ case 0x80: // cmpb a, #8
|
|
+ case 0x6B: // imul r, a, #8
|
|
+ hasDisp32 = true; // has both kinds of operands!
|
|
+ tailSize = 1; // the imm8
|
|
+ break;
|
|
+
|
|
+ case Prefix.VEX_3BYTES:
|
|
+ case Prefix.VEX_2BYTES:
|
|
+ assert ip == pcOffset + 1 : "no prefixes allowed";
|
|
+ int vexOpcode;
|
|
+ // First byte
|
|
+ if ((code[pcOffset] & 0xFF) == Prefix.VEX_3BYTES) {
|
|
+ vexOpcode = VexOpcode.VEX_OPCODE_MASK & code[ip];
|
|
+ ip++; // third byte
|
|
+ is64bit = ((VexPrefix.VEX_W & code[ip]) == VexPrefix.VEX_W);
|
|
+ } else {
|
|
+ vexOpcode = VexOpcode.VEX_OPCODE_0F;
|
|
+ }
|
|
+ ip++; // opcode
|
|
+ // To find the end of instruction (which == end_pc_operand).
|
|
+ switch (vexOpcode) {
|
|
+ case VexOpcode.VEX_OPCODE_0F:
|
|
+ switch (0xFF & code[ip]) {
|
|
+ case 0x70: // pshufd r, r/a, #8
|
|
+ case 0x71: // ps[rl|ra|ll]w r, #8
|
|
+ case 0x72: // ps[rl|ra|ll]d r, #8
|
|
+ case 0x73: // ps[rl|ra|ll]q r, #8
|
|
+ case 0xC2: // cmp[ps|pd|ss|sd] r, r, r/a, #8
|
|
+ case 0xC4: // pinsrw r, r, r/a, #8
|
|
+ case 0xC5: // pextrw r/a, r, #8
|
|
+ case 0xC6: // shufp[s|d] r, r, r/a, #8
|
|
+ tailSize = 1; // the imm8
|
|
+ break;
|
|
+ default:
|
|
+ break; // no imm8
|
|
+ }
|
|
+ break;
|
|
+ case VexOpcode.VEX_OPCODE_0F_3A:
|
|
+ tailSize = 1;
|
|
+ break;
|
|
+ default:
|
|
+ throw new InternalError("should not reach here");
|
|
+ }
|
|
+ ip++; // skip opcode
|
|
+ hasDisp32 = true;
|
|
+ break;
|
|
+
|
|
+ case 0xE8: // call rdisp32
|
|
+ case 0xE9: // jmp rdisp32
|
|
+ currentEndOfInstruction = ip + 4;
|
|
+ return;
|
|
+
|
|
+ case 0xD1: // sal a, 1; sar a, 1; shl a, 1; shr a, 1
|
|
+ case 0xD3: // sal a, %cl; sar a, %cl; shl a, %cl; shr a, %cl
|
|
+ case 0xD9: // fldS a; fstS a; fstpS a; fldcw a
|
|
+ case 0xDD: // fldD a; fstD a; fstpD a
|
|
+ case 0xDB: // fildS a; fistpS a; fldX a; fstpX a
|
|
+ case 0xDF: // fildD a; fistpD a
|
|
+ case 0xD8: // faddS a; fsubrS a; fmulS a; fdivrS a; fcompS a
|
|
+ case 0xDC: // faddD a; fsubrD a; fmulD a; fdivrD a; fcompD a
|
|
+ case 0xDE: // faddpD a; fsubrpD a; fmulpD a; fdivrpD a; fcomppD a
|
|
+ hasDisp32 = true;
|
|
+ break;
|
|
+
|
|
+ case 0xF0: // Lock
|
|
+ againAfterPrefix = true;
|
|
+ break;
|
|
+
|
|
+ case 0xF3: // For SSE
|
|
+ case 0xF2: // For SSE2
|
|
+ switch (0xFF & code[ip++]) {
|
|
+ case Prefix.REX:
|
|
+ case Prefix.REXB:
|
|
+ case Prefix.REXX:
|
|
+ case Prefix.REXXB:
|
|
+ case Prefix.REXR:
|
|
+ case Prefix.REXRB:
|
|
+ case Prefix.REXRX:
|
|
+ case Prefix.REXRXB:
|
|
+ case Prefix.REXW:
|
|
+ case Prefix.REXWB:
|
|
+ case Prefix.REXWX:
|
|
+ case Prefix.REXWXB:
|
|
+ case Prefix.REXWR:
|
|
+ case Prefix.REXWRB:
|
|
+ case Prefix.REXWRX:
|
|
+ case Prefix.REXWRXB:
|
|
+ assert targetIs64Bit : "found 64bit prefix";
|
|
+ ip++;
|
|
+ ip++;
|
|
+ break;
|
|
+ default:
|
|
+ ip++;
|
|
+ }
|
|
+ hasDisp32 = true; // has both kinds of operands!
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ throw new InternalError("should not reach here");
|
|
+ }
|
|
+ }
|
|
+
|
|
+ assert hasDisp32 : "(tw) not sure if this holds: instruction has no disp32 field";
|
|
+
|
|
+ // parse the output of emitOperand
|
|
+ int op2 = 0xFF & code[ip++];
|
|
+ int base = op2 & 0x07;
|
|
+ int op3 = -1;
|
|
+ int b100 = 4;
|
|
+ int b101 = 5;
|
|
+ if (base == b100 && (op2 >> 6) != 3) {
|
|
+ op3 = 0xFF & code[ip++];
|
|
+ base = op3 & 0x07; // refetch the base
|
|
+ }
|
|
+ // now ip points at the disp (if any)
|
|
+
|
|
+ switch (op2 >> 6) {
|
|
+ case 0:
|
|
+ // [00 reg 100][ss index base]
|
|
+ // [00 reg 100][00 100 esp]
|
|
+ // [00 reg base]
|
|
+ // [00 reg 100][ss index 101][disp32]
|
|
+ // [00 reg 101] [disp32]
|
|
+ if (base == b101) {
|
|
+ ip += 4; // skip the disp32
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case 1:
|
|
+ // [01 reg 100][ss index base][disp8]
|
|
+ // [01 reg 100][00 100 esp][disp8]
|
|
+ // [01 reg base] [disp8]
|
|
+ ip += 1; // skip the disp8
|
|
+ break;
|
|
+
|
|
+ case 2:
|
|
+ // [10 reg 100][ss index base][disp32]
|
|
+ // [10 reg 100][00 100 esp][disp32]
|
|
+ // [10 reg base] [disp32]
|
|
+ ip += 4; // skip the disp32
|
|
+ break;
|
|
+
|
|
+ case 3:
|
|
+ // [11 reg base] (not a memory addressing mode)
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ currentEndOfInstruction = ip + tailSize;
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassSearch.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassSearch.java
|
|
new file mode 100644
|
|
index 000000000..31533ec17
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassSearch.java
|
|
@@ -0,0 +1,116 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.collect;
|
|
+
|
|
+import jdk.tools.jaotc.LoadedClass;
|
|
+
|
|
+import java.util.ArrayList;
|
|
+import java.util.List;
|
|
+import java.util.function.BiConsumer;
|
|
+import java.io.File;
|
|
+
|
|
+public final class ClassSearch {
|
|
+ private final List<SourceProvider> providers = new ArrayList<>();
|
|
+
|
|
+ public void addProvider(SourceProvider provider) {
|
|
+ providers.add(provider);
|
|
+ }
|
|
+
|
|
+ public List<LoadedClass> search(List<SearchFor> search, SearchPath searchPath) {
|
|
+ return search(search, searchPath, (s, t) -> {
|
|
+ throw new InternalError(s + " : " + t, t);
|
|
+ });
|
|
+ }
|
|
+
|
|
+ public List<LoadedClass> search(List<SearchFor> search, SearchPath searchPath, BiConsumer<String, Throwable> classLoadingErrorsHandler) {
|
|
+ List<LoadedClass> loaded = new ArrayList<>();
|
|
+
|
|
+ List<ClassSource> sources = new ArrayList<>();
|
|
+
|
|
+ for (SearchFor entry : search) {
|
|
+ sources.add(findSource(entry, searchPath, classLoadingErrorsHandler));
|
|
+ }
|
|
+
|
|
+ for (ClassSource source : sources) {
|
|
+ if (source != null) {
|
|
+ source.eachClass((name, loader) -> {
|
|
+ LoadedClass x = loadClass(name, loader, classLoadingErrorsHandler);
|
|
+ if (x != null) {
|
|
+ loaded.add(x);
|
|
+ }
|
|
+ });
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return loaded;
|
|
+ }
|
|
+
|
|
+ private static LoadedClass loadClass(String name, ClassLoader loader, BiConsumer<String, Throwable> classLoadingErrorsHandler) {
|
|
+ try {
|
|
+ Class<?> clzz = loader.loadClass(name);
|
|
+ return new LoadedClass(name, clzz);
|
|
+ } catch (Throwable e) {
|
|
+ classLoadingErrorsHandler.accept(name, e);
|
|
+ return null;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private ClassSource findSource(SearchFor searchFor, SearchPath searchPath, BiConsumer<String, Throwable> classLoadingErrorsHandler) {
|
|
+ ClassSource found = null;
|
|
+
|
|
+ for (SourceProvider provider : providers) {
|
|
+ if (!searchFor.isUnknown() && !provider.supports(searchFor.getType())) {
|
|
+ continue;
|
|
+ }
|
|
+ ClassSource source = null;
|
|
+ try {
|
|
+ source = provider.findSource(searchFor.getName(), searchPath);
|
|
+ } catch (Throwable e) {
|
|
+ classLoadingErrorsHandler.accept(searchFor.getName(), e);
|
|
+ }
|
|
+ if (source != null) {
|
|
+ if (found != null) {
|
|
+ throw new InternalError("Multiple possible sources: " + source + " and: " + found);
|
|
+ }
|
|
+ found = source;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (found == null) {
|
|
+ classLoadingErrorsHandler.accept(searchFor.getName(), new InternalError("Failed to find " + searchFor.getType() + " file: " + searchFor.getName()));
|
|
+ }
|
|
+ return found;
|
|
+ }
|
|
+
|
|
+ public static List<SearchFor> makeList(String type, String argument) {
|
|
+ List<SearchFor> list = new ArrayList<>();
|
|
+ String[] elements = argument.split(File.pathSeparator);
|
|
+ for (String element : elements) {
|
|
+ list.add(new SearchFor(element, type));
|
|
+ }
|
|
+ return list;
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassSource.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassSource.java
|
|
new file mode 100644
|
|
index 000000000..16aa62c4a
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassSource.java
|
|
@@ -0,0 +1,66 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.collect;
|
|
+
|
|
+import java.nio.file.Path;
|
|
+import java.util.function.BiConsumer;
|
|
+
|
|
+public interface ClassSource {
|
|
+ static boolean pathIsClassFile(Path entry) {
|
|
+ String fileName = entry.getFileName().toString();
|
|
+ return fileName.endsWith(".class") && !fileName.endsWith("module-info.class");
|
|
+ }
|
|
+
|
|
+ static String stripRoot(Path path) {
|
|
+ if (path.getRoot() != null) {
|
|
+ String root = path.getRoot().toString();
|
|
+ String filename = path.toString().substring(root.length());
|
|
+ String separator = path.getFileSystem().getSeparator();
|
|
+ while (filename.startsWith(separator)) {
|
|
+ filename = filename.substring(separator.length());
|
|
+ }
|
|
+ return filename;
|
|
+ }
|
|
+
|
|
+ return path.toString();
|
|
+ }
|
|
+
|
|
+ static String makeClassName(Path path) {
|
|
+ String fileName = path.toString();
|
|
+
|
|
+ if (!fileName.endsWith(".class")) {
|
|
+ throw new IllegalArgumentException("File doesn't end with .class: '" + fileName + "'");
|
|
+ }
|
|
+
|
|
+ fileName = stripRoot(path);
|
|
+
|
|
+ String className = fileName.substring(0, fileName.length() - ".class".length());
|
|
+ className = className.replace(path.getFileSystem().getSeparator(), ".");
|
|
+ return className;
|
|
+ }
|
|
+
|
|
+ void eachClass(BiConsumer<String, ClassLoader> consumer);
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/FileSupport.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/FileSupport.java
|
|
new file mode 100644
|
|
index 000000000..8b0995bff
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/FileSupport.java
|
|
@@ -0,0 +1,103 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.collect;
|
|
+
|
|
+import java.io.IOException;
|
|
+import java.net.MalformedURLException;
|
|
+import java.net.URI;
|
|
+import java.net.URISyntaxException;
|
|
+import java.net.URL;
|
|
+import java.net.URLClassLoader;
|
|
+import java.nio.file.DirectoryStream;
|
|
+import java.nio.file.FileSystem;
|
|
+import java.nio.file.FileSystems;
|
|
+import java.nio.file.Files;
|
|
+import java.nio.file.Path;
|
|
+import java.util.HashMap;
|
|
+
|
|
+public class FileSupport {
|
|
+ public boolean exists(Path path) {
|
|
+ return Files.exists(path);
|
|
+ }
|
|
+
|
|
+ public boolean isDirectory(Path path) {
|
|
+ return Files.isDirectory(path);
|
|
+ }
|
|
+
|
|
+ private static FileSystem makeJarFileSystem(Path path) {
|
|
+ try {
|
|
+ return FileSystems.newFileSystem(makeJarFileURI(path), new HashMap<>());
|
|
+ } catch (IOException e) {
|
|
+ throw new InternalError(e);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private static URI makeJarFileURI(Path path) {
|
|
+ try {
|
|
+ String name = path.toAbsolutePath().toString();
|
|
+ name = name.replace('\\', '/');
|
|
+ return new URI("jar:file", null, "///" + name + "!/", null);
|
|
+ } catch (URISyntaxException e) {
|
|
+ throw new InternalError(e);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public ClassLoader createClassLoader(Path path, ClassLoader parent) {
|
|
+ try {
|
|
+ return URLClassLoader.newInstance(buildUrls(path), parent);
|
|
+ } catch (MalformedURLException e) {
|
|
+ throw new InternalError(e);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public ClassLoader createClassLoader(Path path) throws MalformedURLException {
|
|
+ return URLClassLoader.newInstance(buildUrls(path));
|
|
+ }
|
|
+
|
|
+ private static URL[] buildUrls(Path path) throws MalformedURLException {
|
|
+ return new URL[]{path.toUri().toURL()};
|
|
+ }
|
|
+
|
|
+ public Path getJarFileSystemRoot(Path jarFile) {
|
|
+ FileSystem fileSystem = makeJarFileSystem(jarFile);
|
|
+ return fileSystem.getPath("/");
|
|
+ }
|
|
+
|
|
+ public boolean isAbsolute(Path entry) {
|
|
+ return entry.isAbsolute();
|
|
+ }
|
|
+
|
|
+ public Path getSubDirectory(FileSystem fileSystem, Path root, Path path) throws IOException {
|
|
+ DirectoryStream<Path> paths = fileSystem.provider().newDirectoryStream(root, null);
|
|
+ for (Path entry : paths) {
|
|
+ Path relative = root.relativize(entry);
|
|
+ if (relative.equals(path)) {
|
|
+ return entry;
|
|
+ }
|
|
+ }
|
|
+ return null;
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/FileSystemFinder.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/FileSystemFinder.java
|
|
new file mode 100644
|
|
index 000000000..406d27eab
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/FileSystemFinder.java
|
|
@@ -0,0 +1,83 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.collect;
|
|
+
|
|
+import static java.nio.file.FileVisitResult.CONTINUE;
|
|
+
|
|
+import java.io.IOException;
|
|
+import java.nio.file.FileVisitResult;
|
|
+import java.nio.file.FileVisitor;
|
|
+import java.nio.file.Files;
|
|
+import java.nio.file.Path;
|
|
+import java.nio.file.PathMatcher;
|
|
+import java.nio.file.SimpleFileVisitor;
|
|
+import java.nio.file.attribute.BasicFileAttributes;
|
|
+import java.util.ArrayList;
|
|
+import java.util.Iterator;
|
|
+
|
|
+/**
|
|
+ * {@link FileVisitor} implementation to find class files recursively.
|
|
+ */
|
|
+public final class FileSystemFinder extends SimpleFileVisitor<Path> implements Iterable<Path> {
|
|
+ private final ArrayList<Path> fileNames = new ArrayList<>();
|
|
+ private final PathMatcher filter;
|
|
+
|
|
+ public FileSystemFinder(Path combinedPath, PathMatcher filter) {
|
|
+ this.filter = filter;
|
|
+ try {
|
|
+ Files.walkFileTree(combinedPath, this);
|
|
+ } catch (IOException e) {
|
|
+ throw new InternalError(e);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Compares the glob pattern against the file name.
|
|
+ */
|
|
+ private void find(Path file) {
|
|
+ Path name = file.getFileName();
|
|
+ if (name != null && filter.matches(name)) {
|
|
+ fileNames.add(file);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
|
|
+ find(file);
|
|
+ return CONTINUE;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
|
|
+ find(dir);
|
|
+ return CONTINUE;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public Iterator<Path> iterator() {
|
|
+ return fileNames.iterator();
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/SearchFor.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/SearchFor.java
|
|
new file mode 100644
|
|
index 000000000..f60e4270c
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/SearchFor.java
|
|
@@ -0,0 +1,57 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.collect;
|
|
+
|
|
+public final class SearchFor {
|
|
+ private final String name;
|
|
+ private final String type;
|
|
+
|
|
+ public SearchFor(String name) {
|
|
+ this(name, "");
|
|
+ }
|
|
+
|
|
+ public SearchFor(String name, String type) {
|
|
+ this.name = name;
|
|
+ this.type = type;
|
|
+ }
|
|
+
|
|
+ boolean isUnknown() {
|
|
+ return "".equals(type);
|
|
+ }
|
|
+
|
|
+ String getType() {
|
|
+ return this.type;
|
|
+ }
|
|
+
|
|
+ String getName() {
|
|
+ return this.name;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public String toString() {
|
|
+ return type + ": " + name;
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/SearchPath.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/SearchPath.java
|
|
new file mode 100644
|
|
index 000000000..559e8f657
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/SearchPath.java
|
|
@@ -0,0 +1,89 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.collect;
|
|
+
|
|
+import java.nio.file.FileSystem;
|
|
+import java.nio.file.Path;
|
|
+import java.nio.file.Paths;
|
|
+import java.util.ArrayList;
|
|
+import java.util.List;
|
|
+
|
|
+public class SearchPath {
|
|
+ private final List<Path> searchPaths = new ArrayList<>();
|
|
+ private final FileSupport fileSupport;
|
|
+
|
|
+ public SearchPath() {
|
|
+ this(new FileSupport());
|
|
+ }
|
|
+
|
|
+ public SearchPath(FileSupport fileSupport) {
|
|
+ this.fileSupport = fileSupport;
|
|
+ }
|
|
+
|
|
+ public Path find(FileSystem fileSystem, Path entry, String... defaults) {
|
|
+ if (isAbsolute(entry)) {
|
|
+ if (exists(entry)) {
|
|
+ return entry;
|
|
+ }
|
|
+ return null;
|
|
+ }
|
|
+
|
|
+ if (exists(entry)) {
|
|
+ return entry;
|
|
+ }
|
|
+
|
|
+ for (String searchPath : defaults) {
|
|
+ Path newPath = fileSystem.getPath(searchPath, entry.toString());
|
|
+ if (exists(newPath)) {
|
|
+ return newPath;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ for (Path searchPath : searchPaths) {
|
|
+ Path newPath = fileSystem.getPath(searchPath.toString(), entry.toString());
|
|
+ if (exists(newPath)) {
|
|
+ return newPath;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return null;
|
|
+ }
|
|
+
|
|
+ private boolean isAbsolute(Path entry) {
|
|
+ return fileSupport.isAbsolute(entry);
|
|
+ }
|
|
+
|
|
+ private boolean exists(Path entry) {
|
|
+ return fileSupport.exists(entry);
|
|
+ }
|
|
+
|
|
+ public void add(String... paths) {
|
|
+ for (String name : paths) {
|
|
+ Path path = Paths.get(name);
|
|
+ searchPaths.add(path);
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/SourceProvider.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/SourceProvider.java
|
|
new file mode 100644
|
|
index 000000000..f2f6c1bb3
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/SourceProvider.java
|
|
@@ -0,0 +1,32 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.collect;
|
|
+
|
|
+public interface SourceProvider {
|
|
+ ClassSource findSource(String name, SearchPath searchPath);
|
|
+
|
|
+ boolean supports(String type);
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/classname/ClassNameSource.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/classname/ClassNameSource.java
|
|
new file mode 100644
|
|
index 000000000..bf5d34e42
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/classname/ClassNameSource.java
|
|
@@ -0,0 +1,45 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.collect.classname;
|
|
+
|
|
+import jdk.tools.jaotc.collect.ClassSource;
|
|
+
|
|
+import java.util.function.BiConsumer;
|
|
+
|
|
+public final class ClassNameSource implements ClassSource {
|
|
+ private final String name;
|
|
+ private final ClassLoader classLoader;
|
|
+
|
|
+ ClassNameSource(String name, ClassLoader classLoader) {
|
|
+ this.name = name;
|
|
+ this.classLoader = classLoader;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void eachClass(BiConsumer<String, ClassLoader> consumer) {
|
|
+ consumer.accept(name, classLoader);
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/classname/ClassNameSourceProvider.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/classname/ClassNameSourceProvider.java
|
|
new file mode 100644
|
|
index 000000000..23c731fd3
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/classname/ClassNameSourceProvider.java
|
|
@@ -0,0 +1,70 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.collect.classname;
|
|
+
|
|
+import jdk.tools.jaotc.collect.ClassSource;
|
|
+import jdk.tools.jaotc.collect.FileSupport;
|
|
+import jdk.tools.jaotc.collect.SearchPath;
|
|
+import jdk.tools.jaotc.collect.SourceProvider;
|
|
+
|
|
+import java.nio.file.Path;
|
|
+import java.nio.file.Paths;
|
|
+
|
|
+public final class ClassNameSourceProvider implements SourceProvider {
|
|
+ public static final String TYPE = "class";
|
|
+ private final ClassLoader classLoader;
|
|
+
|
|
+ public ClassNameSourceProvider(FileSupport fileSupport) {
|
|
+ String classPath = System.getProperty("java.class.path");
|
|
+ ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
|
|
+ if (classPath != null && !classPath.isEmpty()) {
|
|
+ classLoader = systemClassLoader;
|
|
+ } else {
|
|
+ Path path = Paths.get(".").toAbsolutePath();
|
|
+ classLoader = fileSupport.createClassLoader(path, systemClassLoader);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public ClassSource findSource(String name0, SearchPath searchPath) {
|
|
+ String name = name0;
|
|
+ Path path = Paths.get(name);
|
|
+ if (ClassSource.pathIsClassFile(path)) {
|
|
+ name = ClassSource.makeClassName(path);
|
|
+ }
|
|
+ try {
|
|
+ classLoader.loadClass(name);
|
|
+ return new ClassNameSource(name, classLoader);
|
|
+ } catch (ClassNotFoundException e) {
|
|
+ return null;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean supports(String type) {
|
|
+ return TYPE.equals(type);
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/directory/DirectorySource.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/directory/DirectorySource.java
|
|
new file mode 100644
|
|
index 000000000..7df6e24a2
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/directory/DirectorySource.java
|
|
@@ -0,0 +1,56 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.collect.directory;
|
|
+
|
|
+import jdk.tools.jaotc.collect.ClassSource;
|
|
+import jdk.tools.jaotc.collect.FileSystemFinder;
|
|
+
|
|
+import java.nio.file.Path;
|
|
+import java.util.function.BiConsumer;
|
|
+
|
|
+public final class DirectorySource implements ClassSource {
|
|
+ private final Path directoryPath;
|
|
+ private final ClassLoader classLoader;
|
|
+
|
|
+ DirectorySource(Path directoryPath, ClassLoader classLoader) {
|
|
+ this.directoryPath = directoryPath;
|
|
+ this.classLoader = classLoader;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void eachClass(BiConsumer<String, ClassLoader> consumer) {
|
|
+ FileSystemFinder finder = new FileSystemFinder(directoryPath, ClassSource::pathIsClassFile);
|
|
+
|
|
+ for (Path path : finder) {
|
|
+ consumer.accept(ClassSource.makeClassName(directoryPath.relativize(path).normalize()), classLoader);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public String toString() {
|
|
+ return "directory:" + directoryPath.toString();
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/directory/DirectorySourceProvider.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/directory/DirectorySourceProvider.java
|
|
new file mode 100644
|
|
index 000000000..1c7e2b2a5
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/directory/DirectorySourceProvider.java
|
|
@@ -0,0 +1,71 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.collect.directory;
|
|
+
|
|
+import jdk.tools.jaotc.collect.ClassSource;
|
|
+import jdk.tools.jaotc.collect.FileSupport;
|
|
+import jdk.tools.jaotc.collect.SearchPath;
|
|
+import jdk.tools.jaotc.collect.SourceProvider;
|
|
+
|
|
+import java.net.MalformedURLException;
|
|
+import java.nio.file.FileSystem;
|
|
+import java.nio.file.FileSystems;
|
|
+import java.nio.file.Path;
|
|
+
|
|
+public final class DirectorySourceProvider implements SourceProvider {
|
|
+ private final FileSupport fileSupport;
|
|
+ private final FileSystem fileSystem;
|
|
+ public static final String TYPE = "directory";
|
|
+
|
|
+ public DirectorySourceProvider(FileSupport fileSupport) {
|
|
+ this.fileSupport = fileSupport;
|
|
+ fileSystem = FileSystems.getDefault();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public ClassSource findSource(String name, SearchPath searchPath) {
|
|
+ Path directoryPath = fileSystem.getPath(name);
|
|
+
|
|
+ if (!fileSupport.exists(directoryPath)) {
|
|
+ return null;
|
|
+ }
|
|
+ if (!fileSupport.isDirectory(directoryPath)) {
|
|
+ return null;
|
|
+ }
|
|
+
|
|
+ try {
|
|
+ ClassLoader classLoader = fileSupport.createClassLoader(directoryPath);
|
|
+ return new DirectorySource(directoryPath, classLoader);
|
|
+ } catch (MalformedURLException e) {
|
|
+ return null;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean supports(String type) {
|
|
+ return TYPE.equals(type);
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/jar/JarFileSource.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/jar/JarFileSource.java
|
|
new file mode 100644
|
|
index 000000000..e86921191
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/jar/JarFileSource.java
|
|
@@ -0,0 +1,58 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.collect.jar;
|
|
+
|
|
+import jdk.tools.jaotc.collect.ClassSource;
|
|
+import jdk.tools.jaotc.collect.FileSystemFinder;
|
|
+
|
|
+import java.nio.file.Path;
|
|
+import java.util.function.BiConsumer;
|
|
+
|
|
+public final class JarFileSource implements ClassSource {
|
|
+ private final Path jarFile;
|
|
+ private final Path jarRootPath;
|
|
+ private final ClassLoader classLoader;
|
|
+
|
|
+ JarFileSource(Path jarFile, Path jarRootPath, ClassLoader classLoader) {
|
|
+ this.jarFile = jarFile;
|
|
+ this.jarRootPath = jarRootPath;
|
|
+ this.classLoader = classLoader;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void eachClass(BiConsumer<String, ClassLoader> consumer) {
|
|
+ FileSystemFinder finder = new FileSystemFinder(jarRootPath, ClassSource::pathIsClassFile);
|
|
+
|
|
+ for (Path path : finder) {
|
|
+ consumer.accept(ClassSource.makeClassName(jarRootPath.relativize(path).normalize()), classLoader);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public String toString() {
|
|
+ return "jar:" + jarFile.toString();
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/jar/JarSourceProvider.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/jar/JarSourceProvider.java
|
|
new file mode 100644
|
|
index 000000000..428f3b67e
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/jar/JarSourceProvider.java
|
|
@@ -0,0 +1,86 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.collect.jar;
|
|
+
|
|
+import jdk.tools.jaotc.collect.ClassSource;
|
|
+import jdk.tools.jaotc.collect.FileSupport;
|
|
+import jdk.tools.jaotc.collect.SearchPath;
|
|
+import jdk.tools.jaotc.collect.SourceProvider;
|
|
+
|
|
+import java.net.MalformedURLException;
|
|
+import java.nio.file.FileSystem;
|
|
+import java.nio.file.FileSystems;
|
|
+import java.nio.file.Path;
|
|
+import java.nio.file.ProviderNotFoundException;
|
|
+
|
|
+public final class JarSourceProvider implements SourceProvider {
|
|
+ private final FileSystem fileSystem;
|
|
+ private final FileSupport fileSupport;
|
|
+ public static final String TYPE = "jar";
|
|
+
|
|
+ public JarSourceProvider() {
|
|
+ this(new FileSupport());
|
|
+ }
|
|
+
|
|
+ public JarSourceProvider(FileSupport fileSupport) {
|
|
+ this.fileSupport = fileSupport;
|
|
+ fileSystem = FileSystems.getDefault();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public ClassSource findSource(String name, SearchPath searchPath) {
|
|
+ Path fileName = fileSystem.getPath(name);
|
|
+ Path jarFile = searchPath.find(fileSystem, fileName);
|
|
+
|
|
+ if (!validPath(jarFile)) {
|
|
+ return null;
|
|
+ }
|
|
+
|
|
+ return createSource(jarFile);
|
|
+ }
|
|
+
|
|
+ private ClassSource createSource(Path jarFile) {
|
|
+ try {
|
|
+ Path jarRootPath = fileSupport.getJarFileSystemRoot(jarFile);
|
|
+ if (jarRootPath == null) {
|
|
+ return null;
|
|
+ }
|
|
+ ClassLoader classLoader = fileSupport.createClassLoader(jarFile);
|
|
+ return new JarFileSource(jarFile, jarRootPath, classLoader);
|
|
+ } catch (ProviderNotFoundException | MalformedURLException e) {
|
|
+ }
|
|
+ return null;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean supports(String type) {
|
|
+ return TYPE.equals(type);
|
|
+ }
|
|
+
|
|
+ private boolean validPath(Path jarFile) {
|
|
+ return jarFile != null && !fileSupport.isDirectory(jarFile);
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/module/ModuleSource.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/module/ModuleSource.java
|
|
new file mode 100644
|
|
index 000000000..80975f952
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/module/ModuleSource.java
|
|
@@ -0,0 +1,60 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.collect.module;
|
|
+
|
|
+import jdk.tools.jaotc.collect.ClassSource;
|
|
+import jdk.tools.jaotc.collect.FileSystemFinder;
|
|
+
|
|
+import java.nio.file.Path;
|
|
+import java.util.function.BiConsumer;
|
|
+
|
|
+public final class ModuleSource implements ClassSource {
|
|
+ private final Path modulePath;
|
|
+ private final ClassLoader classLoader;
|
|
+
|
|
+ ModuleSource(Path modulePath, ClassLoader classLoader) {
|
|
+ this.modulePath = modulePath;
|
|
+ this.classLoader = classLoader;
|
|
+ }
|
|
+
|
|
+ public Path getModulePath() {
|
|
+ return modulePath;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void eachClass(BiConsumer<String, ClassLoader> consumer) {
|
|
+ FileSystemFinder finder = new FileSystemFinder(modulePath, ClassSource::pathIsClassFile);
|
|
+
|
|
+ for (Path path : finder) {
|
|
+ consumer.accept(ClassSource.makeClassName(modulePath.relativize(path).normalize()), classLoader);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public String toString() {
|
|
+ return "module:" + modulePath.toString();
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/module/ModuleSourceProvider.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/module/ModuleSourceProvider.java
|
|
new file mode 100644
|
|
index 000000000..cea1ba88b
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/module/ModuleSourceProvider.java
|
|
@@ -0,0 +1,85 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.collect.module;
|
|
+
|
|
+import jdk.tools.jaotc.collect.ClassSource;
|
|
+import jdk.tools.jaotc.collect.FileSupport;
|
|
+import jdk.tools.jaotc.collect.SearchPath;
|
|
+import jdk.tools.jaotc.collect.SourceProvider;
|
|
+
|
|
+import java.io.IOException;
|
|
+import java.net.URI;
|
|
+import java.nio.file.FileSystem;
|
|
+import java.nio.file.FileSystems;
|
|
+import java.nio.file.Path;
|
|
+
|
|
+public final class ModuleSourceProvider implements SourceProvider {
|
|
+ private final FileSystem fileSystem;
|
|
+ private final ClassLoader classLoader;
|
|
+ private final FileSupport fileSupport;
|
|
+ public static final String TYPE = "module";
|
|
+
|
|
+ public ModuleSourceProvider() {
|
|
+ this(FileSystems.getFileSystem(URI.create("jrt:/")), ClassLoader.getSystemClassLoader(), new FileSupport());
|
|
+ }
|
|
+
|
|
+ public ModuleSourceProvider(FileSystem fileSystem, ClassLoader classLoader, FileSupport fileSupport) {
|
|
+ this.fileSystem = fileSystem;
|
|
+ this.classLoader = classLoader;
|
|
+ this.fileSupport = fileSupport;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public ClassSource findSource(String name, SearchPath searchPath) {
|
|
+ Path path = fileSystem.getPath(name);
|
|
+ Path dir = fileSystem.getPath("modules");
|
|
+
|
|
+ if (dir == null || !fileSupport.isDirectory(dir)) {
|
|
+ return null;
|
|
+ }
|
|
+
|
|
+ Path found = findModuleDirectory(dir, path);
|
|
+
|
|
+ if (found == null) {
|
|
+ return null;
|
|
+ }
|
|
+
|
|
+ return new ModuleSource(found, classLoader);
|
|
+ }
|
|
+
|
|
+ private Path findModuleDirectory(Path root, Path path) {
|
|
+ try {
|
|
+ return fileSupport.getSubDirectory(fileSystem, root, path);
|
|
+ } catch (IOException e) {
|
|
+ throw new InternalError(e);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean supports(String type) {
|
|
+ return TYPE.equals(type);
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/utils/NativeOrderOutputStream.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/utils/NativeOrderOutputStream.java
|
|
new file mode 100644
|
|
index 000000000..e3b7b4a00
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/utils/NativeOrderOutputStream.java
|
|
@@ -0,0 +1,193 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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.utils;
|
|
+
|
|
+import java.io.ByteArrayOutputStream;
|
|
+import java.nio.ByteBuffer;
|
|
+import java.nio.ByteOrder;
|
|
+import java.util.ArrayList;
|
|
+import java.util.List;
|
|
+
|
|
+public final class NativeOrderOutputStream {
|
|
+ private final PatchableByteOutputStream os = new PatchableByteOutputStream();
|
|
+ private final byte[] backingArray = new byte[8];
|
|
+ private final ByteBuffer buffer;
|
|
+ private final List<Patchable> patches = new ArrayList<>();
|
|
+ private int size;
|
|
+
|
|
+ public NativeOrderOutputStream() {
|
|
+ buffer = ByteBuffer.wrap(backingArray);
|
|
+ buffer.order(ByteOrder.nativeOrder());
|
|
+ }
|
|
+
|
|
+ public static int alignUp(int value, int alignment) {
|
|
+ if (Integer.bitCount(alignment) != 1) {
|
|
+ throw new IllegalArgumentException("Must be a power of 2");
|
|
+ }
|
|
+
|
|
+ int aligned = (value + (alignment - 1)) & -alignment;
|
|
+
|
|
+ if (aligned < value || (aligned & (alignment - 1)) != 0) {
|
|
+ throw new RuntimeException("Error aligning: " + value + " -> " + aligned);
|
|
+ }
|
|
+ return aligned;
|
|
+ }
|
|
+
|
|
+ public NativeOrderOutputStream putLong(long value) {
|
|
+ fillLong(value);
|
|
+ os.write(backingArray, 0, 8);
|
|
+ size += 8;
|
|
+ return this;
|
|
+ }
|
|
+
|
|
+ public NativeOrderOutputStream putInt(int value) {
|
|
+ fillInt(value);
|
|
+ os.write(backingArray, 0, 4);
|
|
+ size += 4;
|
|
+ return this;
|
|
+ }
|
|
+
|
|
+ public NativeOrderOutputStream align(int alignment) {
|
|
+ int aligned = alignUp(position(), alignment);
|
|
+
|
|
+ int diff = aligned - position();
|
|
+ if (diff > 0) {
|
|
+ byte[] b = new byte[diff];
|
|
+ os.write(b, 0, b.length);
|
|
+ size += diff;
|
|
+ }
|
|
+
|
|
+ assert aligned == position();
|
|
+ return this;
|
|
+ }
|
|
+
|
|
+ public int position() {
|
|
+ return os.size();
|
|
+ }
|
|
+
|
|
+ private void fillInt(int value) {
|
|
+ buffer.putInt(0, value);
|
|
+ }
|
|
+
|
|
+ private void fillLong(long value) {
|
|
+ buffer.putLong(0, value);
|
|
+ }
|
|
+
|
|
+ private NativeOrderOutputStream putAt(byte[] data, int length, int position) {
|
|
+ os.writeAt(data, length, position);
|
|
+ return this;
|
|
+ }
|
|
+
|
|
+ public NativeOrderOutputStream put(byte[] data) {
|
|
+ os.write(data, 0, data.length);
|
|
+ size += data.length;
|
|
+ return this;
|
|
+ }
|
|
+
|
|
+ public byte[] array() {
|
|
+ checkPatches();
|
|
+ byte[] bytes = os.toByteArray();
|
|
+ assert size == bytes.length;
|
|
+ return bytes;
|
|
+ }
|
|
+
|
|
+ private void checkPatches() {
|
|
+ for (Patchable patch : patches) {
|
|
+ if (!patch.patched()) {
|
|
+ throw new RuntimeException("Not all patches patched, missing at offset: " + patch);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public PatchableInt patchableInt() {
|
|
+ int position = os.size();
|
|
+ PatchableInt patchableInt = new PatchableInt(position);
|
|
+ putInt(0);
|
|
+ patches.add(patchableInt);
|
|
+ return patchableInt;
|
|
+ }
|
|
+
|
|
+ public abstract class Patchable {
|
|
+ private final int position;
|
|
+ private boolean patched = false;
|
|
+
|
|
+ Patchable(int position) {
|
|
+ this.position = position;
|
|
+ }
|
|
+
|
|
+ protected boolean patched() {
|
|
+ return patched;
|
|
+ }
|
|
+
|
|
+ protected void patch(int length) {
|
|
+ putAt(backingArray, length, position);
|
|
+ patched = true;
|
|
+ }
|
|
+
|
|
+ public int position() {
|
|
+ return position;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public class PatchableInt extends Patchable {
|
|
+ private int value = 0;
|
|
+
|
|
+ public PatchableInt(int position) {
|
|
+ super(position);
|
|
+ }
|
|
+
|
|
+ public void set(int value) {
|
|
+ this.value = value;
|
|
+ fillInt(value);
|
|
+ patch(4);
|
|
+ }
|
|
+
|
|
+ public int value() {
|
|
+ return value;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public String toString() {
|
|
+ final StringBuilder sb = new StringBuilder("PatchableInt{");
|
|
+ sb.append("position=").append(super.position()).append(", ");
|
|
+ sb.append("patched=").append(patched()).append(", ");
|
|
+ sb.append("value=").append(value);
|
|
+ sb.append('}');
|
|
+ return sb.toString();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private static class PatchableByteOutputStream extends ByteArrayOutputStream {
|
|
+
|
|
+ public void writeAt(byte[] data, int length, int position) {
|
|
+ long end = (long) position + (long) length;
|
|
+ if (buf.length < end) {
|
|
+ throw new IllegalArgumentException("Array not properly sized");
|
|
+ }
|
|
+ System.arraycopy(data, 0, buf, position, length);
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.aot/share/classes/module-info.java b/src/jdk.aot/share/classes/module-info.java
|
|
new file mode 100644
|
|
index 000000000..f6341b8ae
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/classes/module-info.java
|
|
@@ -0,0 +1,37 @@
|
|
+/*
|
|
+ * 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
|
|
+ * under the terms of the GNU General Public License version 2 only, as
|
|
+ * published by the Free Software Foundation. Oracle designates this
|
|
+ * particular file as subject to the "Classpath" exception as provided
|
|
+ * by Oracle in the LICENSE file that accompanied this code.
|
|
+ *
|
|
+ * 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.
|
|
+ */
|
|
+
|
|
+/**
|
|
+ * Defines the Ahead-of-Time (AOT) compiler, <em>{@index jaotc jaotc tool}</em>,
|
|
+ * for compiling Java classes into AOT library.
|
|
+ *
|
|
+ * @moduleGraph
|
|
+ * @since 9
|
|
+ */
|
|
+module jdk.aot {
|
|
+ requires jdk.internal.vm.ci;
|
|
+ requires jdk.internal.vm.compiler;
|
|
+ requires jdk.management;
|
|
+}
|
|
diff --git a/src/jdk.aot/share/man/jaotc.1 b/src/jdk.aot/share/man/jaotc.1
|
|
new file mode 100644
|
|
index 000000000..2b25c005a
|
|
--- /dev/null
|
|
+++ b/src/jdk.aot/share/man/jaotc.1
|
|
@@ -0,0 +1,209 @@
|
|
+.\" Copyright (c) 2019, 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
|
|
+.\" 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.
|
|
+.\"
|
|
+.\" Automatically generated by Pandoc 2.3.1
|
|
+.\"
|
|
+.TH "JAOTC" "1" "2020" "JDK 16" "JDK Commands"
|
|
+.hy
|
|
+.SH NAME
|
|
+.PP
|
|
+jaotc \- The Java static compiler that produces native code for compiled
|
|
+Java methods
|
|
+.SH SYNOPSIS
|
|
+.PP
|
|
+\f[CB]jaotc\f[R] [\f[I]options\f[R]] [\f[I]name\f[R] | \f[I]list\f[R]]
|
|
+.TP
|
|
+.B \f[I]options\f[R]
|
|
+Command\-line options separated by spaces.
|
|
+See \f[B]jaotc Options\f[R].
|
|
+.RS
|
|
+.RE
|
|
+.TP
|
|
+.B \f[I]name\f[R]
|
|
+The Java class or jar file from which Java methods will be compiled.
|
|
+.RS
|
|
+.RE
|
|
+.TP
|
|
+.B \f[I]list\f[R]
|
|
+Colon (\f[CB]:\f[R]) separated list of class names, modules, jar files or
|
|
+directories which contain class files.
|
|
+.RS
|
|
+.RE
|
|
+.SH DESCRIPTION
|
|
+.PP
|
|
+The \f[CB]jaotc\f[R] command is a Java Ahead\-Of\-Time (AOT) static
|
|
+compiler which produces native code in the form of a shared library for
|
|
+the Java methods in specified Java class files.
|
|
+The Java Virtual Machine can load these AOT libraries and use native
|
|
+code from them when corresponding Java methods are called.
|
|
+By using \f[CB]jaotc\f[R], there is no need to wait for the JIT compiler
|
|
+to generate (by compiling bytecode) the fast native code for these Java
|
|
+methods.
|
|
+The code is already generated by \f[CB]jaotc\f[R] and ready to be
|
|
+immediately used.
|
|
+For the same reason, there is no need to execute these methods in the
|
|
+Interpreter because fast compiled native code can be executed instead.
|
|
+.PP
|
|
+\f[B]Note:\f[R]
|
|
+.PP
|
|
+The \f[CB]jaotc\f[R] command is experimental.
|
|
+See \f[B]JEP 295: Ahead\-of\-Time Compilation\f[R]
|
|
+[https://openjdk.java.net/jeps/295] for complete details.
|
|
+.SH JAOTC OPTIONS
|
|
+.TP
|
|
+.B \f[CB]\-\-output\f[R] \f[I]file\f[R]
|
|
+Output file name.
|
|
+Default name is "unnamed.so".
|
|
+.RS
|
|
+.RE
|
|
+.TP
|
|
+.B \f[CB]\-\-class\-name\f[R] \f[I]class\-names\f[R]
|
|
+List of Java classes to compile.
|
|
+.RS
|
|
+.RE
|
|
+.TP
|
|
+.B \f[CB]\-\-jar\f[R] \f[I]jar\-files\f[R]
|
|
+List of JAR files to compile.
|
|
+.RS
|
|
+.RE
|
|
+.TP
|
|
+.B \f[CB]\-\-module\f[R] \f[I]modules\f[R]
|
|
+List of Java modules to compile.
|
|
+.RS
|
|
+.RE
|
|
+.TP
|
|
+.B \f[CB]\-\-directory\f[R] \f[I]dirs\f[R]
|
|
+List of directories to search for files to compile.
|
|
+.RS
|
|
+.RE
|
|
+.TP
|
|
+.B \f[CB]\-\-search\-path\f[R] \f[I]dirs\f[R]
|
|
+List of directories to search for specified files.
|
|
+.RS
|
|
+.RE
|
|
+.TP
|
|
+.B \f[CB]\-\-compile\-commands\f[R] \f[I]file\f[R]
|
|
+Name of the file containing the compile commands:
|
|
+.RS
|
|
+.TP
|
|
+.B \f[CB]exclude\f[R]
|
|
+Excludes compilation of specified methods.
|
|
+.RS
|
|
+.RE
|
|
+.TP
|
|
+.B \f[CB]compileOnly\f[R]
|
|
+Compiles only specified methods.
|
|
+.RS
|
|
+.RE
|
|
+.PP
|
|
+Regular expressions are used to specify classes and methods.
|
|
+For example:
|
|
+.IP
|
|
+.nf
|
|
+\f[CB]
|
|
+exclude\ sun.util.resources..*.TimeZoneNames_.*.getContents\\(\\)\\[\\[Ljava/lang/Object;\
|
|
+exclude\ sun.security.ssl.*\
|
|
+compileOnly\ java.lang.String.*
|
|
+\f[R]
|
|
+.fi
|
|
+.RE
|
|
+.TP
|
|
+.B \f[CB]\-\-compile\-for\-tiered\f[R]
|
|
+Generates profiling code for tiered compilation.
|
|
+By default, profiling code is not generated (could be changed in a
|
|
+future).
|
|
+.RS
|
|
+.RE
|
|
+.TP
|
|
+.B \f[CB]\-\-compile\-with\-assertions\f[R]
|
|
+Generates code with java assertions.
|
|
+By default, assertions code is not generated.
|
|
+.RS
|
|
+.RE
|
|
+.TP
|
|
+.B \f[CB]\-\-compile\-threads\f[R] \f[I]number\f[R]
|
|
+Sets the number of compilation threads used.
|
|
+The default value is \f[CB]min(16,\ available_cpus)\f[R].
|
|
+.RS
|
|
+.RE
|
|
+.TP
|
|
+.B \f[CB]\-\-ignore\-errors\f[R]
|
|
+Ignores all exceptions thrown during class loading.
|
|
+By default, the tool will exit compilation if class loading throws an
|
|
+exception.
|
|
+.RS
|
|
+.RE
|
|
+.TP
|
|
+.B \f[CB]\-\-exit\-on\-error\f[R]
|
|
+Exits on compilation errors.
|
|
+By default, failed compilation is skipped and compilation of other
|
|
+methods continues.
|
|
+.RS
|
|
+.RE
|
|
+.TP
|
|
+.B \f[CB]\-\-info\f[R]
|
|
+Prints information about compilation phases.
|
|
+.RS
|
|
+.RE
|
|
+.TP
|
|
+.B \f[CB]\-\-verbose\f[R]
|
|
+Prints more details about compilation phases.
|
|
+.RS
|
|
+.RE
|
|
+.TP
|
|
+.B \f[CB]\-\-debug\f[R]
|
|
+Prints comprehensive details.
|
|
+.RS
|
|
+.RE
|
|
+.TP
|
|
+.B \f[CB]\-\-help\f[R] or \f[CB]\-h\f[R] or \f[CB]\-?\f[R]
|
|
+Prints a summary of standard options and exits the tool.
|
|
+.RS
|
|
+.RE
|
|
+.TP
|
|
+.B \f[CB]\-\-version\f[R]
|
|
+Prints version information.
|
|
+.RS
|
|
+.RE
|
|
+.TP
|
|
+.B \f[CB]\-J\f[R]\f[I]flag\f[R]
|
|
+Provides a flag to pass to the runtime system.
|
|
+To pass more than one flag, provide an instance of this option for each
|
|
+flag or flag argument needed.
|
|
+.RS
|
|
+.RE
|
|
+.SH JAOTC EXAMPLES
|
|
+.PP
|
|
+Use the \f[CB]jaotc\f[R] tool to execute AOT compilation.
|
|
+.IP
|
|
+.nf
|
|
+\f[CB]
|
|
+jaotc\ \-\-output\ libHelloWorld.so\ HelloWorld.class
|
|
+\f[R]
|
|
+.fi
|
|
+.PP
|
|
+Specify a generated AOT library during application execution:
|
|
+.IP
|
|
+.nf
|
|
+\f[CB]
|
|
+java\ \-XX:+UnlockExperimentalVMOptions\ \-XX:AOTLibrary=./libHelloWorld.so\ HelloWorld
|
|
+\f[R]
|
|
+.fi
|
|
diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/CodeBlob.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/CodeBlob.java
|
|
index d2f8db5ef..323c2a2d4 100644
|
|
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/CodeBlob.java
|
|
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/CodeBlob.java
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2015, 2021, 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
|
|
@@ -133,6 +133,8 @@ public class CodeBlob extends VMObject {
|
|
// Typing
|
|
public boolean isBufferBlob() { return false; }
|
|
|
|
+ public boolean isAOT() { return false; }
|
|
+
|
|
public boolean isCompiled() { return false; }
|
|
|
|
public boolean isNMethod() { return false; }
|
|
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 079f7b6c8..f2e998c56 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
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2000, 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
|
|
@@ -74,6 +74,7 @@ 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;
|
|
@@ -131,6 +132,7 @@ 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();
|
|
@@ -281,6 +283,11 @@ public class InstanceKlass extends Klass {
|
|
if (isInterface()) {
|
|
size += wordLength;
|
|
}
|
|
+
|
|
+ if (hasStoredFingerprint()) {
|
|
+ size += 8; // uint64_t
|
|
+ }
|
|
+
|
|
return alignSize(size);
|
|
}
|
|
|
|
@@ -288,6 +295,26 @@ public class InstanceKlass extends Klass {
|
|
return (int) miscFlags.getValue(this);
|
|
}
|
|
|
|
+ public static boolean shouldStoreFingerprint() {
|
|
+ VM vm = VM.getVM();
|
|
+ if (vm.getCommandLineBooleanFlag("EnableJVMCI") && !vm.getCommandLineBooleanFlag("UseJVMCICompiler")) {
|
|
+ return true;
|
|
+ }
|
|
+ if (vm.getCommandLineBooleanFlag("DumpSharedSpaces")) {
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ public boolean hasStoredFingerprint() {
|
|
+ // has_stored_fingerprint() @ instanceKlass.cpp can return true only if INCLUDE_AOT is
|
|
+ // set during compilation.
|
|
+ if (!VM.getVM().hasAOT()) {
|
|
+ return false;
|
|
+ }
|
|
+ return shouldStoreFingerprint() || isShared();
|
|
+ }
|
|
+
|
|
public static long getHeaderSize() { return headerSize; }
|
|
|
|
public short getFieldAccessFlags(int index) {
|
|
diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java
|
|
index f3cbacbbd..b42feec3f 100644
|
|
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java
|
|
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2000, 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
|
|
@@ -89,6 +89,8 @@ public class VM {
|
|
private FileMapInfo fileMapInfo;
|
|
private Bytes bytes;
|
|
|
|
+ /** Flag indicating if AOT is enabled in the build */
|
|
+ private boolean hasAOT;
|
|
/** Flag indicating if JVMTI support is included in the build */
|
|
private boolean isJvmtiSupported;
|
|
/** Flags indicating whether we are attached to a core, C1, or C2 build */
|
|
@@ -444,6 +446,16 @@ public class VM {
|
|
|
|
invocationEntryBCI = db.lookupIntConstant("InvocationEntryBci").intValue();
|
|
|
|
+ // We infer AOT if _method @ methodCounters is declared.
|
|
+ {
|
|
+ Type type = db.lookupType("MethodCounters");
|
|
+ if (type.getField("_method", false, false) == null) {
|
|
+ hasAOT = false;
|
|
+ } else {
|
|
+ hasAOT = true;
|
|
+ }
|
|
+ }
|
|
+
|
|
// We infer the presence of JVMTI from the presence of the InstanceKlass::_breakpoints field.
|
|
{
|
|
Type type = db.lookupType("InstanceKlass");
|
|
@@ -827,6 +839,11 @@ public class VM {
|
|
return isBigEndian;
|
|
}
|
|
|
|
+ /** Returns true if AOT is enabled, false otherwise */
|
|
+ public boolean hasAOT() {
|
|
+ return hasAOT;
|
|
+ }
|
|
+
|
|
/** Returns true if JVMTI is supported, false otherwise */
|
|
public boolean isJvmtiSupported() {
|
|
return isJvmtiSupported;
|
|
diff --git a/src/jdk.internal.vm.compiler/share/classes/module-info.java b/src/jdk.internal.vm.compiler/share/classes/module-info.java
|
|
index 100dde9ec..fe3bcc93d 100644
|
|
--- a/src/jdk.internal.vm.compiler/share/classes/module-info.java
|
|
+++ b/src/jdk.internal.vm.compiler/share/classes/module-info.java
|
|
@@ -43,15 +43,46 @@ module jdk.internal.vm.compiler {
|
|
uses org.graalvm.compiler.serviceprovider.JMXService;
|
|
|
|
exports jdk.internal.vm.compiler.collections to jdk.internal.vm.compiler.management;
|
|
+ exports org.graalvm.compiler.api.directives to jdk.aot;
|
|
+ exports org.graalvm.compiler.api.runtime to jdk.aot;
|
|
+ exports org.graalvm.compiler.api.replacements to jdk.aot;
|
|
+ exports org.graalvm.compiler.asm.amd64 to jdk.aot;
|
|
+ exports org.graalvm.compiler.asm.aarch64 to jdk.aot;
|
|
+ exports org.graalvm.compiler.bytecode to jdk.aot;
|
|
+ exports org.graalvm.compiler.code to jdk.aot;
|
|
+ exports org.graalvm.compiler.core to jdk.aot;
|
|
exports org.graalvm.compiler.core.common to
|
|
+ jdk.aot,
|
|
jdk.internal.vm.compiler.management;
|
|
+ exports org.graalvm.compiler.core.target to jdk.aot;
|
|
exports org.graalvm.compiler.debug to
|
|
+ jdk.aot,
|
|
jdk.internal.vm.compiler.management;
|
|
+ exports org.graalvm.compiler.graph to jdk.aot;
|
|
exports org.graalvm.compiler.hotspot to
|
|
+ jdk.aot,
|
|
jdk.internal.vm.compiler.management;
|
|
+ exports org.graalvm.compiler.hotspot.meta to jdk.aot;
|
|
+ exports org.graalvm.compiler.hotspot.replacements to jdk.aot;
|
|
+ exports org.graalvm.compiler.hotspot.stubs to jdk.aot;
|
|
+ exports org.graalvm.compiler.hotspot.word to jdk.aot;
|
|
+ exports org.graalvm.compiler.java to jdk.aot;
|
|
+ exports org.graalvm.compiler.lir.asm to jdk.aot;
|
|
+ exports org.graalvm.compiler.lir.phases to jdk.aot;
|
|
+ exports org.graalvm.compiler.nodes to jdk.aot;
|
|
+ exports org.graalvm.compiler.nodes.graphbuilderconf to jdk.aot;
|
|
exports org.graalvm.compiler.options to
|
|
+ jdk.aot,
|
|
jdk.internal.vm.compiler.management;
|
|
+ exports org.graalvm.compiler.phases to jdk.aot;
|
|
exports org.graalvm.compiler.phases.common.jmx to jdk.internal.vm.compiler.management;
|
|
+ exports org.graalvm.compiler.phases.tiers to jdk.aot;
|
|
+ exports org.graalvm.compiler.printer to jdk.aot;
|
|
+ exports org.graalvm.compiler.runtime to jdk.aot;
|
|
+ exports org.graalvm.compiler.replacements to jdk.aot;
|
|
exports org.graalvm.compiler.serviceprovider to
|
|
+ jdk.aot,
|
|
jdk.internal.vm.compiler.management;
|
|
+ exports org.graalvm.compiler.word to jdk.aot;
|
|
+ exports jdk.internal.vm.compiler.word to jdk.aot;
|
|
}
|
|
diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java
|
|
index 235104ad3..976ce455d 100644
|
|
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java
|
|
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java
|
|
@@ -112,6 +112,7 @@ import jdk.vm.ci.meta.Value;
|
|
* global invariants such as using {@link Object#equals(Object)} to compare certain types instead of
|
|
* identity comparisons.
|
|
*/
|
|
+@AddExports("jdk.internal.vm.ci/*=jdk.aot")
|
|
public class CheckGraalInvariants extends GraalCompilerTest {
|
|
|
|
/**
|
|
diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifySystemPropertyUsage.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifySystemPropertyUsage.java
|
|
index 226d5f7fa..29c12ab0d 100644
|
|
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifySystemPropertyUsage.java
|
|
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifySystemPropertyUsage.java
|
|
@@ -101,6 +101,10 @@ public class VerifySystemPropertyUsage extends VerifyPhase<CoreProviders> {
|
|
// * its JDK substitutions to mimic required JDK semantics
|
|
// * native-image for config info
|
|
return;
|
|
+ } else if (packageName.startsWith("jdk.tools.jaotc")) {
|
|
+ // Workaround since jdk.internal.vm.ci/jdk.vm.ci.services is not exported to jdk.aot.
|
|
+ // The jaotc launcher dynamically adds these exports.
|
|
+ return;
|
|
}
|
|
for (MethodCallTargetNode t : graph.getNodes(MethodCallTargetNode.TYPE)) {
|
|
ResolvedJavaMethod callee = t.targetMethod();
|
|
diff --git a/test/hotspot/jtreg/ProblemList-aot.txt b/test/hotspot/jtreg/ProblemList-aot.txt
|
|
new file mode 100644
|
|
index 000000000..a42887547
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/ProblemList-aot.txt
|
|
@@ -0,0 +1,82 @@
|
|
+#
|
|
+# Copyright (c) 2019, 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
|
|
+# 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.
|
|
+#
|
|
+
|
|
+#############################################################################
|
|
+#
|
|
+# List of quarantined tests for testing with AOT.
|
|
+#
|
|
+#############################################################################
|
|
+
|
|
+serviceability/sa/CDSJMapClstats.java 8216181 generic-all
|
|
+serviceability/sa/ClhsdbAttach.java 8216181 generic-all
|
|
+serviceability/sa/ClhsdbCDSCore.java 8216181 generic-all
|
|
+serviceability/sa/ClhsdbCDSJstackPrintAll.java 8216181 generic-all
|
|
+serviceability/sa/ClhsdbField.java 8216181 generic-all
|
|
+serviceability/sa/ClhsdbFindPC.java#id0 8216181 generic-all
|
|
+serviceability/sa/ClhsdbFindPC.java#id1 8216181 generic-all
|
|
+serviceability/sa/ClhsdbFlags.java 8216181 generic-all
|
|
+serviceability/sa/ClhsdbInspect.java 8216181 generic-all
|
|
+serviceability/sa/ClhsdbJdis.java 8216181 generic-all
|
|
+serviceability/sa/ClhsdbJhisto.java 8216181 generic-all
|
|
+serviceability/sa/ClhsdbJstack.java#id0 8216181 generic-all
|
|
+serviceability/sa/ClhsdbJstack.java#id1 8216181 generic-all
|
|
+serviceability/sa/ClhsdbJstackXcompStress.java 8216181 generic-all
|
|
+serviceability/sa/ClhsdbLongConstant.java 8216181 generic-all
|
|
+serviceability/sa/ClhsdbPmap.java 8216181 generic-all
|
|
+serviceability/sa/ClhsdbPrintAll.java 8216181 generic-all
|
|
+serviceability/sa/ClhsdbPrintAs.java 8216181 generic-all
|
|
+serviceability/sa/ClhsdbPrintStatics.java 8216181 generic-all
|
|
+serviceability/sa/ClhsdbPstack.java 8216181 generic-all
|
|
+serviceability/sa/ClhsdbRegionDetailsScanOopsForG1.java 8216181 generic-all
|
|
+serviceability/sa/ClhsdbScanOops.java#id0 8216181 generic-all
|
|
+serviceability/sa/ClhsdbScanOops.java#id1 8216181 generic-all
|
|
+serviceability/sa/ClhsdbSource.java 8216181 generic-all
|
|
+serviceability/sa/ClhsdbThread.java 8216181 generic-all
|
|
+serviceability/sa/ClhsdbVmStructsDump.java 8216181 generic-all
|
|
+serviceability/sa/ClhsdbWhere.java 8216181 generic-all
|
|
+serviceability/sa/DeadlockDetectionTest.java 8216181 generic-all
|
|
+serviceability/sa/JhsdbThreadInfoTest.java 8216181 generic-all
|
|
+serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java 8216181 generic-all
|
|
+serviceability/sa/sadebugd/DebugdConnectTest.java 8216181 generic-all
|
|
+serviceability/sa/sadebugd/SADebugDTest.java 8216181 generic-all
|
|
+serviceability/sa/TestClassDump.java 8216181 generic-all
|
|
+serviceability/sa/TestClhsdbJstackLock.java 8216181 generic-all
|
|
+serviceability/sa/TestCpoolForInvokeDynamic.java 8216181 generic-all
|
|
+serviceability/sa/TestDefaultMethods.java 8216181 generic-all
|
|
+serviceability/sa/TestG1HeapRegion.java 8216181 generic-all
|
|
+serviceability/sa/TestHeapDumpForInvokeDynamic.java 8216181 generic-all
|
|
+serviceability/sa/TestHeapDumpForLargeArray.java 8216181 generic-all
|
|
+serviceability/sa/TestInstanceKlassSizeForInterface.java 8216181 generic-all
|
|
+serviceability/sa/TestInstanceKlassSize.java 8216181 generic-all
|
|
+serviceability/sa/TestIntConstant.java 8216181 generic-all
|
|
+serviceability/sa/TestJhsdbJstackLock.java 8216181 generic-all
|
|
+serviceability/sa/TestJhsdbJstackMixed.java 8216181 generic-all
|
|
+serviceability/sa/TestJmapCore.java 8216181 generic-all
|
|
+serviceability/sa/TestJmapCoreMetaspace.java 8216181 generic-all
|
|
+serviceability/sa/TestPrintMdo.java 8216181 generic-all
|
|
+serviceability/sa/TestRevPtrsForInvokeDynamic.java 8216181 generic-all
|
|
+serviceability/sa/TestType.java 8216181 generic-all
|
|
+serviceability/sa/TestUniverse.java 8216181 generic-all
|
|
+
|
|
+vmTestbase/vm/mlvm/indy/stress/java/relinkMutableCallSiteFreq/Test.java 8226689 generic-all
|
|
+vmTestbase/vm/mlvm/indy/stress/java/relinkVolatileCallSiteFreq/Test.java 8226689 generic-all
|
|
diff --git a/test/hotspot/jtreg/TEST.ROOT b/test/hotspot/jtreg/TEST.ROOT
|
|
index f6e6209cd..e350faa40 100644
|
|
--- a/test/hotspot/jtreg/TEST.ROOT
|
|
+++ b/test/hotspot/jtreg/TEST.ROOT
|
|
@@ -67,6 +67,8 @@ requires.properties= \
|
|
vm.hasDTrace \
|
|
vm.rtm.cpu \
|
|
vm.rtm.compiler \
|
|
+ vm.aot \
|
|
+ vm.aot.enabled \
|
|
vm.cds \
|
|
vm.cds.custom.loaders \
|
|
vm.cds.write.archived.java.heap \
|
|
diff --git a/test/hotspot/jtreg/TEST.groups b/test/hotspot/jtreg/TEST.groups
|
|
index 915dac962..5a3765365 100644
|
|
--- a/test/hotspot/jtreg/TEST.groups
|
|
+++ b/test/hotspot/jtreg/TEST.groups
|
|
@@ -45,7 +45,7 @@ hotspot_compiler_xcomp = \
|
|
|
|
hotspot_compiler_all_gcs = \
|
|
:hotspot_compiler \
|
|
- -compiler/jvmci \
|
|
+ -:tier1_compiler_aot_jvmci \
|
|
-compiler/graalunit
|
|
|
|
hotspot_gc = \
|
|
@@ -242,8 +242,13 @@ tier3_compiler = \
|
|
-:tier2_compiler
|
|
|
|
tier1_compiler_not_xcomp = \
|
|
+ compiler/aot \
|
|
compiler/profiling
|
|
|
|
+tier1_compiler_aot_jvmci = \
|
|
+ compiler/aot \
|
|
+ compiler/jvmci
|
|
+
|
|
tier1_compiler_graal = \
|
|
compiler/graalunit/HotspotTest.java
|
|
|
|
diff --git a/test/hotspot/jtreg/applications/ctw/modules/jdk_aot.java b/test/hotspot/jtreg/applications/ctw/modules/jdk_aot.java
|
|
new file mode 100644
|
|
index 000000000..b2d6d77b6
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_aot.java
|
|
@@ -0,0 +1,38 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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
|
|
+ * @summary run CTW for all classes from jdk.aot module
|
|
+ *
|
|
+ * @library /test/lib / /testlibrary/ctw/src
|
|
+ * @modules java.base/jdk.internal.access
|
|
+ * java.base/jdk.internal.jimage
|
|
+ * java.base/jdk.internal.misc
|
|
+ * java.base/jdk.internal.reflect
|
|
+ * @modules jdk.aot
|
|
+ *
|
|
+ * @build jdk.test.whitebox.WhiteBox
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
|
+ * @run driver/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.aot
|
|
+ */
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/AotCompiler.java b/test/hotspot/jtreg/compiler/aot/AotCompiler.java
|
|
new file mode 100644
|
|
index 000000000..8ad1da403
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/AotCompiler.java
|
|
@@ -0,0 +1,280 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 compiler.aot;
|
|
+
|
|
+import jdk.test.lib.Platform;
|
|
+import jdk.test.lib.artifacts.Artifact;
|
|
+import jdk.test.lib.artifacts.ArtifactResolver;
|
|
+import jdk.test.lib.artifacts.ArtifactResolverException;
|
|
+import jdk.test.lib.process.OutputAnalyzer;
|
|
+import java.io.File;
|
|
+import java.io.IOException;
|
|
+import java.lang.annotation.Annotation;
|
|
+import java.nio.file.Files;
|
|
+import java.nio.file.Path;
|
|
+import java.nio.file.Paths;
|
|
+import java.nio.file.StandardOpenOption;
|
|
+import java.util.ArrayList;
|
|
+import java.util.Arrays;
|
|
+import java.util.List;
|
|
+import jdk.test.lib.JDKToolLauncher;
|
|
+import jdk.test.lib.Utils;
|
|
+import jdk.test.lib.process.ProcessTools;
|
|
+
|
|
+/**
|
|
+ * A simple class calling AOT compiler over requested items
|
|
+ */
|
|
+public class AotCompiler {
|
|
+
|
|
+ private final static String METHODS_LIST_FILENAME = "methodsList.txt";
|
|
+
|
|
+ public static void main(String args[]) {
|
|
+ String className = null;
|
|
+ List<String> compileList = new ArrayList<>();
|
|
+ String libName = null;
|
|
+ List<String> extraopts = new ArrayList<>();
|
|
+ for (int i = 0; i < args.length; i++) {
|
|
+ switch (args[i]) {
|
|
+ case "-class":
|
|
+ className = args[++i];
|
|
+ break;
|
|
+ case "-compile":
|
|
+ compileList.add("compileOnly " + args[++i]);
|
|
+ break;
|
|
+ case "-libname":
|
|
+ libName = args[++i];
|
|
+ break;
|
|
+ case "-extraopt":
|
|
+ extraopts.add(args[++i]);
|
|
+ break;
|
|
+ default:
|
|
+ throw new Error("Unknown option: " + args[i]);
|
|
+ }
|
|
+ }
|
|
+ extraopts.add("-classpath");
|
|
+ extraopts.add(Utils.TEST_CLASS_PATH + File.pathSeparator + Utils.TEST_SRC);
|
|
+ if (className != null && libName != null) {
|
|
+ OutputAnalyzer oa = launchCompiler(libName, className, extraopts, compileList);
|
|
+ oa.shouldHaveExitValue(0);
|
|
+ } else {
|
|
+ printUsage();
|
|
+ throw new Error("Mandatory arguments aren't passed");
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public static OutputAnalyzer launchCompilerSimple(String... args) {
|
|
+ return launchJaotc(Arrays.asList(args), null);
|
|
+ }
|
|
+
|
|
+ public static OutputAnalyzer launchCompiler(String libName, String item, List<String> extraopts,
|
|
+ List<String> compList) {
|
|
+ Path file = null;
|
|
+ if (compList != null && !compList.isEmpty()) {
|
|
+ file = Paths.get(METHODS_LIST_FILENAME);
|
|
+ try {
|
|
+ Files.write(file, compList, StandardOpenOption.CREATE);
|
|
+ } catch (IOException e) {
|
|
+ throw new Error("Couldn't write " + METHODS_LIST_FILENAME + " " + e, e);
|
|
+ }
|
|
+ }
|
|
+ List<String> args = new ArrayList<>();
|
|
+ args.add("--compile-with-assertions");
|
|
+ args.add("--info");
|
|
+ args.add("--output");
|
|
+ args.add(libName);
|
|
+ if (file != null) {
|
|
+ args.add("--compile-commands");
|
|
+ args.add(file.toString());
|
|
+ }
|
|
+ args.add("--class-name");
|
|
+ args.add(item);
|
|
+ String linker = resolveLinker();
|
|
+ if (linker != null) {
|
|
+ args.add("--linker-path");
|
|
+ args.add(linker);
|
|
+ }
|
|
+ // Execute with asserts
|
|
+ args.add("-J-ea");
|
|
+ args.add("-J-esa");
|
|
+ // we don't want to run jaotc w/ Xcomp even if it's in extraopts
|
|
+ args.add("-J-Xmixed");
|
|
+ return launchJaotc(args, extraopts);
|
|
+ }
|
|
+
|
|
+ private static OutputAnalyzer launchJaotc(List<String> args, List<String> extraVmOpts) {
|
|
+ JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jaotc");
|
|
+ for (String vmOpt : Utils.getTestJavaOpts()) {
|
|
+ launcher.addVMArg(vmOpt);
|
|
+ }
|
|
+ if (extraVmOpts != null) {
|
|
+ for (String vmOpt : extraVmOpts) {
|
|
+ launcher.addVMArg(vmOpt);
|
|
+ }
|
|
+ }
|
|
+ for (String arg : args) {
|
|
+ launcher.addToolArg(arg);
|
|
+ }
|
|
+ try {
|
|
+ return ProcessTools.executeCommand(new ProcessBuilder(launcher.getCommand()).redirectErrorStream(true));
|
|
+ } catch (Throwable e) {
|
|
+ throw new Error("Can't start test process: " + e, e);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public static void printUsage() {
|
|
+ System.err.println("Usage: " + AotCompiler.class.getName()
|
|
+ + " -class <class> -libname <.so name>"
|
|
+ + " [-compile <compileItems>]* [-extraopt <java option>]*");
|
|
+ }
|
|
+
|
|
+ // runs ld -v and check its exit code
|
|
+ private static boolean checkLd(Path bin) {
|
|
+ try {
|
|
+ return 0 == ProcessTools.executeCommand(bin.toString(), "-v")
|
|
+ .getExitValue();
|
|
+ } catch (Throwable t) {
|
|
+ // any errors mean ld doesn't work
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public static String resolveLinker() {
|
|
+ Path linker = null;
|
|
+ // if non windows, 1st, check if PATH has ld
|
|
+ if (!Platform.isWindows()) {
|
|
+ String bin = "ld";
|
|
+ for (String path : System.getenv("PATH").split(File.pathSeparator)) {
|
|
+ Path ld = Paths.get(path).resolve("ld");
|
|
+ if (Files.exists(ld)) {
|
|
+ // there is ld in PATH
|
|
+ if (checkLd(ld)) {
|
|
+ System.out.println("found working linker: " + ld);
|
|
+ // ld works, jaotc is supposed to find and use it
|
|
+ return null;
|
|
+ } else {
|
|
+ System.out.println("found broken linker: " + ld);
|
|
+ // ld exists in PATH, but doesn't work, have to use devkit
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ // there is no ld in PATH, will use ld from devkit
|
|
+ // artifacts are got from common/conf/jib-profiles.js
|
|
+ try {
|
|
+ if (Platform.isWindows()) {
|
|
+ if (Platform.isX64()) {
|
|
+ @Artifact(organization = "jpg.infra.builddeps",
|
|
+ name = "devkit-windows_x64",
|
|
+ revision = "VS2017-15.5.5+1.0",
|
|
+ extension = "tar.gz")
|
|
+ class DevkitWindowsX64 { }
|
|
+ String artifactName = "jpg.infra.builddeps."
|
|
+ + "devkit-windows_x64-"
|
|
+ + "VS2017-15.5.5+1.0";
|
|
+ Path devkit = ArtifactResolver.resolve(DevkitWindowsX64.class)
|
|
+ .get(artifactName);
|
|
+ linker = devkit.resolve("VC")
|
|
+ .resolve("bin")
|
|
+ .resolve("x64")
|
|
+ .resolve("link.exe");
|
|
+ }
|
|
+ } else if (Platform.isOSX()) {
|
|
+ @Artifact(organization = "jpg.infra.builddeps",
|
|
+ name = "devkit-macosx_x64",
|
|
+ revision = "Xcode6.3-MacOSX10.9+1.0",
|
|
+ extension = "tar.gz")
|
|
+ class DevkitMacosx { }
|
|
+ String artifactName = "jpg.infra.builddeps."
|
|
+ + "devkit-macosx_x64-"
|
|
+ + "Xcode6.3-MacOSX10.9+1.0";
|
|
+ Path devkit = ArtifactResolver.resolve(DevkitMacosx.class)
|
|
+ .get(artifactName);
|
|
+ linker = devkit.resolve("Xcode.app")
|
|
+ .resolve("Contents")
|
|
+ .resolve("Developer")
|
|
+ .resolve("Toolchains")
|
|
+ .resolve("XcodeDefault.xctoolchain")
|
|
+ .resolve("usr")
|
|
+ .resolve("bin")
|
|
+ .resolve("ld");
|
|
+ } else if (Platform.isLinux()) {
|
|
+ if (Platform.isAArch64()) {
|
|
+ @Artifact(organization = "jpg.infra.builddeps",
|
|
+ name = "devkit-linux_aarch64",
|
|
+ revision = "gcc-linaro-aarch64-linux-gnu-4.8-2013.11_linux+1.0",
|
|
+ extension = "tar.gz")
|
|
+ class DevkitLinuxAArch64 { }
|
|
+
|
|
+ String artifactName = "jpg.infra.builddeps."
|
|
+ + "devkit-linux_aarch64-"
|
|
+ + "gcc-linaro-aarch64-linux-gnu-4.8-2013.11_linux+1.0";
|
|
+ Path devkit = ArtifactResolver.resolve(DevkitLinuxAArch64.class)
|
|
+ .get(artifactName);
|
|
+ linker = devkit.resolve("aarch64-linux-gnu")
|
|
+ .resolve("bin")
|
|
+ .resolve("ld");
|
|
+ } else if (Platform.isARM()) {
|
|
+ @Artifact(organization = "jpg.infra.builddeps",
|
|
+ name = "devkit-linux_arm",
|
|
+ revision = "gcc-linaro-arm-linux-gnueabihf-raspbian-2012.09-20120921_linux+1.0",
|
|
+ extension = "tar.gz")
|
|
+ class DevkitLinuxARM { }
|
|
+
|
|
+ String artifactName = "jpg.infra.builddeps."
|
|
+ + "devkit-linux_arm-"
|
|
+ + "gcc-linaro-arm-linux-gnueabihf-raspbian-2012.09-20120921_linux+1.0";
|
|
+ Path devkit = ArtifactResolver.resolve(DevkitLinuxARM.class)
|
|
+ .get(artifactName);
|
|
+ linker = devkit.resolve("arm-linux-gnueabihf")
|
|
+ .resolve("bin")
|
|
+ .resolve("ld");
|
|
+ } else if (Platform.isX64()) {
|
|
+ @Artifact(organization = "jpg.infra.builddeps",
|
|
+ name = "devkit-linux_x64",
|
|
+ revision = "gcc7.3.0-OEL6.4+1.0",
|
|
+ extension = "tar.gz")
|
|
+ class DevkitLinuxX64 { }
|
|
+
|
|
+ String artifactName = "jpg.infra.builddeps."
|
|
+ + "devkit-linux_x64-"
|
|
+ + "gcc7.3.0-OEL6.4+1.0";
|
|
+ Path devkit = ArtifactResolver.resolve(DevkitLinuxX64.class)
|
|
+ .get(artifactName);
|
|
+ linker = devkit.resolve("bin")
|
|
+ .resolve("ld");
|
|
+ }
|
|
+ }
|
|
+ } catch (ArtifactResolverException e) {
|
|
+ System.err.println("artifact resolution error: " + e);
|
|
+ e.printStackTrace(System.err);
|
|
+ // let jaotc try to find linker
|
|
+ return null;
|
|
+ }
|
|
+ if (linker != null) {
|
|
+ return linker.toAbsolutePath().toString();
|
|
+ }
|
|
+ return null;
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/DeoptimizationTest.java b/test/hotspot/jtreg/compiler/aot/DeoptimizationTest.java
|
|
new file mode 100644
|
|
index 000000000..e4752e5cd
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/DeoptimizationTest.java
|
|
@@ -0,0 +1,86 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 /
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.aot.DeoptimizationTest
|
|
+ * jdk.test.whitebox.WhiteBox
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
|
+ * @run driver compiler.aot.AotCompiler -libname libDeoptimizationTest.so
|
|
+ * -class compiler.aot.DeoptimizationTest
|
|
+ * -compile compiler.aot.DeoptimizationTest.testMethod()D
|
|
+ * -extraopt -XX:-UseCompressedOops
|
|
+ * @run main/othervm -Xmixed -XX:+UnlockExperimentalVMOptions -XX:+UseAOT -XX:+TieredCompilation
|
|
+ * -XX:-UseCompressedOops
|
|
+ * -XX:CompileCommand=dontinline,compiler.aot.DeoptimizationTest::*
|
|
+ * -XX:AOTLibrary=./libDeoptimizationTest.so -Xbootclasspath/a:.
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
|
+ * compiler.aot.DeoptimizationTest
|
|
+ * @summary check if aot code can be deoptimized
|
|
+ */
|
|
+
|
|
+package compiler.aot;
|
|
+
|
|
+import java.lang.reflect.Method;
|
|
+import jdk.test.lib.Asserts;
|
|
+import jdk.test.lib.Utils;
|
|
+import jdk.test.whitebox.WhiteBox;
|
|
+import compiler.whitebox.CompilerWhiteBoxTest;
|
|
+
|
|
+public final class DeoptimizationTest {
|
|
+ private static final String TEST_METHOD = "testMethod";
|
|
+ private static final WhiteBox WB = WhiteBox.getWhiteBox();
|
|
+ private final Method testMethod;
|
|
+
|
|
+ private DeoptimizationTest() {
|
|
+ try {
|
|
+ testMethod = getClass().getDeclaredMethod(TEST_METHOD);
|
|
+ } catch (NoSuchMethodException e) {
|
|
+ throw new Error("TEST BUG: no test method found", e);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public static void main(String args[]) {
|
|
+ new DeoptimizationTest().test();
|
|
+ }
|
|
+
|
|
+ private double testMethod() {
|
|
+ return 42 / 0;
|
|
+ }
|
|
+
|
|
+ private void test() {
|
|
+ Asserts.assertTrue(WB.isMethodCompiled(testMethod),
|
|
+ "Method expected to be compiled");
|
|
+ Asserts.assertEQ(WB.getMethodCompilationLevel(testMethod),
|
|
+ CompilerWhiteBoxTest.COMP_LEVEL_AOT,
|
|
+ "Unexpected compilation level at start");
|
|
+ Utils.runAndCheckException(() -> testMethod(), ArithmeticException.class);
|
|
+ Asserts.assertFalse(WB.isMethodCompiled(testMethod),
|
|
+ "Method is unexpectedly compiled after deoptimization");
|
|
+ Asserts.assertEQ(WB.getMethodCompilationLevel(testMethod), 0,
|
|
+ "Unexpected compilation level after deoptimization");
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/HelloWorldPrinter.java b/test/hotspot/jtreg/compiler/aot/HelloWorldPrinter.java
|
|
new file mode 100644
|
|
index 000000000..e91a53e2f
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/HelloWorldPrinter.java
|
|
@@ -0,0 +1,41 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 compiler.aot;
|
|
+
|
|
+public class HelloWorldPrinter {
|
|
+ public static final String MESSAGE = "Hello world";
|
|
+ public static final String CLINIT_MESSAGE = "Hello <clinit> world";
|
|
+
|
|
+ static {
|
|
+ System.out.println(CLINIT_MESSAGE);
|
|
+ }
|
|
+
|
|
+ public static void main(String args[]) {
|
|
+ print();
|
|
+ }
|
|
+
|
|
+ public static void print() {
|
|
+ System.out.println(MESSAGE);
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/RecompilationTest.java b/test/hotspot/jtreg/compiler/aot/RecompilationTest.java
|
|
new file mode 100644
|
|
index 000000000..6ab10c681
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/RecompilationTest.java
|
|
@@ -0,0 +1,110 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 /
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.aot.RecompilationTest
|
|
+ * jdk.test.whitebox.WhiteBox
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
|
+ * @run driver compiler.aot.AotCompiler -libname libRecompilationTest1.so
|
|
+ * -class compiler.whitebox.SimpleTestCaseHelper
|
|
+ * -extraopt -Dgraal.TieredAOT=true -extraopt -Dgraal.ProfileSimpleMethods=true
|
|
+ * -extraopt -Dgraal.ProbabilisticProfiling=false
|
|
+ * -extraopt -XX:+UnlockDiagnosticVMOptions -extraopt -XX:+WhiteBoxAPI -extraopt -Xbootclasspath/a:.
|
|
+ * -extraopt -XX:-UseCompressedOops
|
|
+ * -extraopt -XX:CompileCommand=dontinline,compiler.whitebox.SimpleTestCaseHelper::*
|
|
+ * @run driver compiler.aot.AotCompiler -libname libRecompilationTest2.so
|
|
+ * -class compiler.whitebox.SimpleTestCaseHelper
|
|
+ * -extraopt -Dgraal.TieredAOT=false
|
|
+ * -extraopt -XX:+UnlockDiagnosticVMOptions -extraopt -XX:+WhiteBoxAPI -extraopt -Xbootclasspath/a:.
|
|
+ * -extraopt -XX:-UseCompressedOops
|
|
+ * -extraopt -XX:CompileCommand=dontinline,compiler.whitebox.SimpleTestCaseHelper::*
|
|
+ * @run main/othervm -Xmixed -Xbatch -XX:+UnlockExperimentalVMOptions -XX:+UseAOT -XX:-TieredCompilation
|
|
+ * -XX:-UseCounterDecay -XX:-UseCompressedOops
|
|
+ * -XX:-Inline
|
|
+ * -XX:AOTLibrary=./libRecompilationTest2.so -Xbootclasspath/a:.
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
|
+ * -Dcompiler.aot.RecompilationTest.check_level=-2
|
|
+ * compiler.aot.RecompilationTest
|
|
+ * @summary check if recompilation after aot goes fine
|
|
+ */
|
|
+
|
|
+ /* having whitebox-related options for aot compiler is a temporary solution,
|
|
+ because of JDK-8146201
|
|
+ */
|
|
+
|
|
+package compiler.aot;
|
|
+
|
|
+import compiler.whitebox.CompilerWhiteBoxTest;
|
|
+import java.lang.reflect.Executable;
|
|
+import jdk.test.lib.Asserts;
|
|
+
|
|
+public final class RecompilationTest extends CompilerWhiteBoxTest {
|
|
+ private static final int CHECK_LEVEL = Integer.getInteger(
|
|
+ "compiler.aot.RecompilationTest.check_level");
|
|
+
|
|
+ public static void main(String args[]) {
|
|
+ CompilerWhiteBoxTest.main(RecompilationTest::new, args);
|
|
+ }
|
|
+
|
|
+ private RecompilationTest(TestCase testCase) {
|
|
+ super(testCase);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected void test() throws Exception {
|
|
+ if (testCase.isOsr()) {
|
|
+ /* aot compiler is not using osr compilation */
|
|
+ System.out.println("Skipping OSR case");
|
|
+ return;
|
|
+ }
|
|
+ Executable e = testCase.getExecutable();
|
|
+ Asserts.assertTrue(WHITE_BOX.isMethodCompiled(e),
|
|
+ testCase.name() + ": an executable expected to be compiled");
|
|
+ Asserts.assertEQ(WHITE_BOX.getMethodCompilationLevel(e),
|
|
+ COMP_LEVEL_AOT,
|
|
+ String.format("%s: unexpected compilation level at start",
|
|
+ testCase.name()));
|
|
+ compile();
|
|
+ Asserts.assertTrue(WHITE_BOX.isMethodCompiled(e), testCase.name()
|
|
+ + ": method expected to be compiled");
|
|
+ /* a case with AOT'ed code checks exact compilation level equality
|
|
+ while another case checks minimum level and if method compiled
|
|
+ because there might be different compilation level transitions */
|
|
+ if (CHECK_LEVEL != COMP_LEVEL_AOT) {
|
|
+ Asserts.assertGTE(WHITE_BOX.getMethodCompilationLevel(e),
|
|
+ CHECK_LEVEL,
|
|
+ String.format("%s: expected compilation level"
|
|
+ + " after compilation to be no less than %d for %s",
|
|
+ testCase.name(), CHECK_LEVEL, testCase.name()));
|
|
+ } else {
|
|
+ Asserts.assertEQ(WHITE_BOX.getMethodCompilationLevel(e),
|
|
+ COMP_LEVEL_AOT, String.format("%s: expected compilation"
|
|
+ + " level after compilation to be equal to %d for %s",
|
|
+ testCase.name(), COMP_LEVEL_AOT, testCase.name()));
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/SharedUsageTest.java b/test/hotspot/jtreg/compiler/aot/SharedUsageTest.java
|
|
new file mode 100644
|
|
index 000000000..ee0a4aac6
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/SharedUsageTest.java
|
|
@@ -0,0 +1,79 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 /
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.aot.SharedUsageTest
|
|
+ * compiler.aot.AotCompiler
|
|
+ * @run driver compiler.aot.AotCompiler -libname libSharedUsageTest.so
|
|
+ * -class compiler.aot.SharedUsageTest
|
|
+ * -extraopt -XX:-UseCompressedOops
|
|
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * -XX:AOTLibrary=./libSharedUsageTest.so
|
|
+ * -XX:-UseCompressedOops
|
|
+ * -Dcompiler.aot.SharedUsageTest.parent=true
|
|
+ * compiler.aot.SharedUsageTest
|
|
+ * @summary check if .so can be successfully shared with 2 java processes
|
|
+ */
|
|
+
|
|
+package compiler.aot;
|
|
+
|
|
+import jdk.test.lib.Asserts;
|
|
+import jdk.test.lib.process.ExitCode;
|
|
+import jdk.test.lib.Utils;
|
|
+import jdk.test.lib.cli.CommandLineOptionTest;
|
|
+
|
|
+public class SharedUsageTest {
|
|
+ private static final String HELLO_MSG = "HelloWorld";
|
|
+ private static final boolean ADD_TEST_VM_OPTION = false;
|
|
+ private static boolean shouldBeFalseInParent = false;
|
|
+ private static final boolean IS_PARENT = Boolean.getBoolean(
|
|
+ "compiler.aot.SharedUsageTest.parent");
|
|
+
|
|
+ public static void main(String args[]) throws Throwable {
|
|
+ Asserts.assertFalse(shouldBeFalseInParent,
|
|
+ "A test invariant is broken");
|
|
+ if (IS_PARENT) {
|
|
+ /* An output of .so being used is verified after launch.
|
|
+ A respective message is triggered by PrintAOT option. */
|
|
+ CommandLineOptionTest.verifyJVMStartup(
|
|
+ new String[]{"libSharedUsageTest.so aot library",
|
|
+ HELLO_MSG}, null, "Unexpected exit code",
|
|
+ "Unexpected output", ExitCode.OK, ADD_TEST_VM_OPTION,
|
|
+ "-XX:+UnlockExperimentalVMOptions", "-XX:+UseAOT", "-XX:+PrintAOT",
|
|
+ "-Dtest.jdk=" + Utils.TEST_JDK,
|
|
+ "-XX:AOTLibrary=./libSharedUsageTest.so",
|
|
+ SharedUsageTest.class.getName());
|
|
+ Asserts.assertFalse(shouldBeFalseInParent, "A static member got "
|
|
+ + "unexpectedly changed");
|
|
+ } else {
|
|
+ shouldBeFalseInParent = true;
|
|
+ Asserts.assertTrue(shouldBeFalseInParent, "A static member wasn't"
|
|
+ + "changed as expected");
|
|
+ System.out.println(HELLO_MSG);
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/TestHeapBase.java b/test/hotspot/jtreg/compiler/aot/TestHeapBase.java
|
|
new file mode 100644
|
|
index 000000000..7662e1dd7
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/TestHeapBase.java
|
|
@@ -0,0 +1,81 @@
|
|
+/*
|
|
+ * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2020, 2023, Arm Limited. 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
|
|
+ * @bug 8244164
|
|
+ * @requires vm.aot & vm.bits == 64
|
|
+ * @library /test/lib /testlibrary /
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.aot.TestHeapBase
|
|
+ * jdk.test.whitebox.WhiteBox
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
|
+ * @run driver compiler.aot.AotCompiler -libname libTestHeapBase.so
|
|
+ * -class compiler.aot.TestHeapBase
|
|
+ * -compile compiler.aot.TestHeapBase.test()V
|
|
+ * -extraopt -XX:+UseCompressedOops -extraopt -Xmx1g
|
|
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * -XX:+UseCompressedOops -XX:HeapBaseMinAddress=32g
|
|
+ * -XX:AOTLibrary=./libTestHeapBase.so -Xbootclasspath/a:.
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xlog:aot+class+load=trace
|
|
+ * compiler.aot.TestHeapBase
|
|
+ * @summary check for crash when jaotc is run with zero-based compressed oops then
|
|
+ * generated code is loaded in vm with non-zero-based compressed oops.
|
|
+ */
|
|
+
|
|
+package compiler.aot;
|
|
+
|
|
+import java.lang.reflect.Method;
|
|
+import jdk.test.lib.Asserts;
|
|
+import jdk.test.lib.Utils;
|
|
+import jdk.test.whitebox.WhiteBox;
|
|
+import compiler.whitebox.CompilerWhiteBoxTest;
|
|
+
|
|
+public final class TestHeapBase {
|
|
+ private static final String TEST_METHOD = "test";
|
|
+ private static final WhiteBox WB = WhiteBox.getWhiteBox();
|
|
+ private final Method testMethod;
|
|
+
|
|
+ private TestHeapBase() {
|
|
+ try {
|
|
+ testMethod = getClass().getDeclaredMethod(TEST_METHOD);
|
|
+ } catch (NoSuchMethodException e) {
|
|
+ throw new Error("TEST BUG: no test method found", e);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public static void main(String args[]) {
|
|
+ new TestHeapBase().test();
|
|
+ }
|
|
+
|
|
+ private void test() {
|
|
+ System.out.println("Hello, World!");
|
|
+
|
|
+ Asserts.assertTrue(WB.isMethodCompiled(testMethod),
|
|
+ "Method expected to be compiled");
|
|
+ Asserts.assertEQ(WB.getMethodCompilationLevel(testMethod),
|
|
+ CompilerWhiteBoxTest.COMP_LEVEL_AOT,
|
|
+ "Expected method to be AOT compiled");
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeDynamic2AotTest.java b/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeDynamic2AotTest.java
|
|
new file mode 100644
|
|
index 000000000..a99063674
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeDynamic2AotTest.java
|
|
@@ -0,0 +1,43 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 /
|
|
+ * @modules java.base/jdk.internal.org.objectweb.asm
|
|
+ * java.base/jdk.internal.misc
|
|
+ * @build compiler.calls.common.InvokeDynamic
|
|
+ * jdk.test.whitebox.WhiteBox
|
|
+ * @run driver compiler.calls.common.InvokeDynamicPatcher
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
|
+ * @run driver compiler.aot.AotCompiler -libname AotInvokeDynamic2AotTest.so
|
|
+ * -class compiler.calls.common.InvokeDynamic
|
|
+ * -extraopt -XX:+UnlockDiagnosticVMOptions -extraopt -XX:+WhiteBoxAPI -extraopt -Xbootclasspath/a:.
|
|
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * -XX:AOTLibrary=./AotInvokeDynamic2AotTest.so
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
|
+ * compiler.calls.common.InvokeDynamic
|
|
+ * -checkCallerCompileLevel -2 -checkCalleeCompileLevel -2
|
|
+ * @summary check calls from aot to aot code using invokedynamic
|
|
+ */
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeDynamic2CompiledTest.java b/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeDynamic2CompiledTest.java
|
|
new file mode 100644
|
|
index 000000000..440afc469
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeDynamic2CompiledTest.java
|
|
@@ -0,0 +1,48 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 /
|
|
+ * @modules java.base/jdk.internal.org.objectweb.asm
|
|
+ * java.base/jdk.internal.misc
|
|
+ * @build compiler.calls.common.InvokeDynamic
|
|
+ * jdk.test.whitebox.WhiteBox
|
|
+ * @run driver compiler.calls.common.InvokeDynamicPatcher
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
|
+ * @run driver compiler.aot.AotCompiler -libname AotInvokeDynamic2CompiledTest.so
|
|
+ * -class compiler.calls.common.InvokeDynamic
|
|
+ * -compile compiler.calls.common.InvokeDynamic.caller()V
|
|
+ * @run main/othervm -Xbatch -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * -XX:AOTLibrary=./AotInvokeDynamic2CompiledTest.so
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
|
+ * compiler.calls.common.InvokeDynamic -compileCallee 1
|
|
+ * -checkCalleeCompileLevel 1
|
|
+ * @run main/othervm -Xbatch -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * -XX:AOTLibrary=./AotInvokeDynamic2CompiledTest.so
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
|
+ * compiler.calls.common.InvokeDynamic -compileCallee 4
|
|
+ * -checkCalleeCompileLevel 4
|
|
+ * @summary check calls from aot to jit-compiled code using invokedynamic
|
|
+ */
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeDynamic2InterpretedTest.java b/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeDynamic2InterpretedTest.java
|
|
new file mode 100644
|
|
index 000000000..d0fedf37a
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeDynamic2InterpretedTest.java
|
|
@@ -0,0 +1,44 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 /
|
|
+ * @modules java.base/jdk.internal.org.objectweb.asm
|
|
+ * java.base/jdk.internal.misc
|
|
+ * @build compiler.calls.common.InvokeDynamic
|
|
+ * jdk.test.whitebox.WhiteBox
|
|
+ * @run driver compiler.calls.common.InvokeDynamicPatcher
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
|
+ * @run driver compiler.aot.AotCompiler
|
|
+ * -libname AotInvokeDynamic2InterpretedTest.so
|
|
+ * -class compiler.calls.common.InvokeDynamic
|
|
+ * -compile compiler.calls.common.InvokeDynamic.caller()V
|
|
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions
|
|
+ * -XX:AOTLibrary=./AotInvokeDynamic2InterpretedTest.so
|
|
+ * -XX:CompileCommand=exclude,compiler.calls.common.InvokeDynamic::callee
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
|
+ * -XX:+UseAOT compiler.calls.common.InvokeDynamic -checkCallerCompileLevel -2
|
|
+ * @summary check calls from aot to interpreted code using invokedynamic
|
|
+ */
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeDynamic2NativeTest.java b/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeDynamic2NativeTest.java
|
|
new file mode 100644
|
|
index 000000000..3f137af95
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeDynamic2NativeTest.java
|
|
@@ -0,0 +1,42 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 /
|
|
+ * @modules java.base/jdk.internal.org.objectweb.asm
|
|
+ * java.base/jdk.internal.misc
|
|
+ * @build compiler.calls.common.InvokeDynamic
|
|
+ * jdk.test.whitebox.WhiteBox
|
|
+ * @run driver compiler.calls.common.InvokeDynamicPatcher
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
|
+ * @run driver compiler.aot.AotCompiler -libname AotInvokeDynamic2NativeTest.so
|
|
+ * -class compiler.calls.common.InvokeDynamic
|
|
+ * -compile compiler.calls.common.InvokeDynamic.caller()V
|
|
+ * @run main/othervm/native -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * -XX:AOTLibrary=./AotInvokeDynamic2NativeTest.so
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
|
+ * compiler.calls.common.InvokeDynamic -nativeCallee -checkCallerCompileLevel -2
|
|
+ * @summary check calls from aot to native code using invokedynamic
|
|
+ */
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeInterface2AotTest.java b/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeInterface2AotTest.java
|
|
new file mode 100644
|
|
index 000000000..647f056bf
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeInterface2AotTest.java
|
|
@@ -0,0 +1,41 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 /
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.calls.common.InvokeInterface
|
|
+ * jdk.test.whitebox.WhiteBox
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
|
+ * @run driver compiler.aot.AotCompiler -libname AotInvokeInterface2AotTest.so
|
|
+ * -class compiler.calls.common.InvokeInterface
|
|
+ * -extraopt -XX:+UnlockDiagnosticVMOptions -extraopt -XX:+WhiteBoxAPI -extraopt -Xbootclasspath/a:.
|
|
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * -XX:AOTLibrary=./AotInvokeInterface2AotTest.so
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
|
+ * compiler.calls.common.InvokeInterface
|
|
+ * -checkCallerCompileLevel -2 -checkCalleeCompileLevel -2
|
|
+ * @summary check calls from aot to aot code using invokeinterface
|
|
+ */
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeInterface2CompiledTest.java b/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeInterface2CompiledTest.java
|
|
new file mode 100644
|
|
index 000000000..e980fb1bc
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeInterface2CompiledTest.java
|
|
@@ -0,0 +1,47 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 /
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.calls.common.InvokeInterface
|
|
+ * jdk.test.whitebox.WhiteBox
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
|
+ * @run driver compiler.aot.AotCompiler
|
|
+ * -libname AotInvokeInterface2CompiledTest.so
|
|
+ * -class compiler.calls.common.InvokeInterface
|
|
+ * -compile compiler.calls.common.InvokeInterface.caller()V
|
|
+ * @run main/othervm -Xbatch -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * -XX:AOTLibrary=./AotInvokeInterface2CompiledTest.so
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
|
+ * compiler.calls.common.InvokeInterface -compileCallee 1
|
|
+ * -checkCalleeCompileLevel 1
|
|
+ * @run main/othervm -Xbatch -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * -XX:AOTLibrary=./AotInvokeInterface2CompiledTest.so
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
|
+ * compiler.calls.common.InvokeInterface -compileCallee 4
|
|
+ * -checkCalleeCompileLevel 4
|
|
+ * @summary check calls from aot to jit-compiled code using invokeinterface
|
|
+ */
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeInterface2InterpretedTest.java b/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeInterface2InterpretedTest.java
|
|
new file mode 100644
|
|
index 000000000..66ab8ab9a
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeInterface2InterpretedTest.java
|
|
@@ -0,0 +1,42 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 /
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.calls.common.InvokeInterface
|
|
+ * jdk.test.whitebox.WhiteBox
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
|
+ * @run driver compiler.aot.AotCompiler
|
|
+ * -libname AotInvokeInterface2InterpretedTest.so
|
|
+ * -class compiler.calls.common.InvokeInterface
|
|
+ * -compile compiler.calls.common.InvokeInterface.caller()V
|
|
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * -XX:AOTLibrary=./AotInvokeInterface2InterpretedTest.so
|
|
+ * -XX:CompileCommand=exclude,compiler.calls.common.InvokeInterface::callee
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
|
+ * compiler.calls.common.InvokeInterface -checkCallerCompileLevel -2
|
|
+ * @summary check calls from aot to interpreted code using invokeinterface
|
|
+ */
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeInterface2NativeTest.java b/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeInterface2NativeTest.java
|
|
new file mode 100644
|
|
index 000000000..47fe30fd8
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeInterface2NativeTest.java
|
|
@@ -0,0 +1,40 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 /
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.calls.common.InvokeInterface
|
|
+ * jdk.test.whitebox.WhiteBox
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
|
+ * @run driver compiler.aot.AotCompiler -libname AotInvokeInterface2NativeTest.so
|
|
+ * -class compiler.calls.common.InvokeInterface
|
|
+ * -compile compiler.calls.common.InvokeInterface.caller()V
|
|
+ * @run main/othervm/native -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * -XX:AOTLibrary=./AotInvokeInterface2NativeTest.so
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
|
+ * compiler.calls.common.InvokeInterface -nativeCallee -checkCallerCompileLevel -2
|
|
+ * @summary check calls from aot to native code using invokeinterface
|
|
+ */
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeSpecial2AotTest.java b/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeSpecial2AotTest.java
|
|
new file mode 100644
|
|
index 000000000..de91a28db
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeSpecial2AotTest.java
|
|
@@ -0,0 +1,41 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 /
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.calls.common.InvokeSpecial
|
|
+ * jdk.test.whitebox.WhiteBox
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
|
+ * @run driver compiler.aot.AotCompiler -libname AotInvokeSpecial2AotTest.so
|
|
+ * -class compiler.calls.common.InvokeSpecial
|
|
+ * -extraopt -XX:+UnlockDiagnosticVMOptions -extraopt -XX:+WhiteBoxAPI -extraopt -Xbootclasspath/a:.
|
|
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * -XX:AOTLibrary=./AotInvokeSpecial2AotTest.so
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
|
+ * compiler.calls.common.InvokeSpecial
|
|
+ * -checkCallerCompileLevel -2 -checkCalleeCompileLevel -2
|
|
+ * @summary check calls from aot to aot code using invokespecial
|
|
+ */
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeSpecial2CompiledTest.java b/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeSpecial2CompiledTest.java
|
|
new file mode 100644
|
|
index 000000000..b2b846f3d
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeSpecial2CompiledTest.java
|
|
@@ -0,0 +1,46 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 /
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.calls.common.InvokeSpecial
|
|
+ * jdk.test.whitebox.WhiteBox
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
|
+ * @run driver compiler.aot.AotCompiler -libname AotInvokeSpecial2CompiledTest.so
|
|
+ * -class compiler.calls.common.InvokeSpecial
|
|
+ * -compile compiler.calls.common.InvokeSpecial.caller()V
|
|
+ * @run main/othervm -Xbatch -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * -XX:AOTLibrary=./AotInvokeSpecial2CompiledTest.so
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
|
+ * compiler.calls.common.InvokeSpecial -compileCallee 1
|
|
+ * -checkCalleeCompileLevel 1
|
|
+ * @run main/othervm -Xbatch -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * -XX:AOTLibrary=./AotInvokeSpecial2CompiledTest.so
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
|
+ * compiler.calls.common.InvokeSpecial -compileCallee 4
|
|
+ * -checkCalleeCompileLevel 4
|
|
+ * @summary check calls from aot to jit-compiled code using invokespecial
|
|
+ */
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeSpecial2InterpretedTest.java b/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeSpecial2InterpretedTest.java
|
|
new file mode 100644
|
|
index 000000000..7c401741e
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeSpecial2InterpretedTest.java
|
|
@@ -0,0 +1,42 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 /
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.calls.common.InvokeSpecial
|
|
+ * jdk.test.whitebox.WhiteBox
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
|
+ * @run driver compiler.aot.AotCompiler
|
|
+ * -libname AotInvokeSpecial2InterpretedTest.so
|
|
+ * -class compiler.calls.common.InvokeSpecial
|
|
+ * -compile compiler.calls.common.InvokeSpecial.caller()V
|
|
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * -XX:AOTLibrary=./AotInvokeSpecial2InterpretedTest.so
|
|
+ * -XX:CompileCommand=exclude,compiler.calls.common.InvokeSpecial::callee
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
|
+ * compiler.calls.common.InvokeSpecial -checkCallerCompileLevel -2
|
|
+ * @summary check calls from aot to interpreted code using invokespecial
|
|
+ */
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeSpecial2NativeTest.java b/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeSpecial2NativeTest.java
|
|
new file mode 100644
|
|
index 000000000..abaf49288
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeSpecial2NativeTest.java
|
|
@@ -0,0 +1,40 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 /
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.calls.common.InvokeSpecial
|
|
+ * jdk.test.whitebox.WhiteBox
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
|
+ * @run driver compiler.aot.AotCompiler -libname AotInvokeSpecial2NativeTest.so
|
|
+ * -class compiler.calls.common.InvokeSpecial
|
|
+ * -compile compiler.calls.common.InvokeSpecial.caller()V
|
|
+ * @run main/othervm/native -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * -XX:AOTLibrary=./AotInvokeSpecial2NativeTest.so
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
|
+ * compiler.calls.common.InvokeSpecial -nativeCallee -checkCallerCompileLevel -2
|
|
+ * @summary check calls from aot to interpreted code using invokespecial
|
|
+ */
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeStatic2AotTest.java b/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeStatic2AotTest.java
|
|
new file mode 100644
|
|
index 000000000..3f9ab84eb
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeStatic2AotTest.java
|
|
@@ -0,0 +1,41 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 /
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.calls.common.InvokeStatic
|
|
+ * jdk.test.whitebox.WhiteBox
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
|
+ * @run driver compiler.aot.AotCompiler -libname AotInvokeStatic2AotTest.so
|
|
+ * -class compiler.calls.common.InvokeStatic
|
|
+ * -extraopt -XX:+UnlockDiagnosticVMOptions -extraopt -XX:+WhiteBoxAPI -extraopt -Xbootclasspath/a:.
|
|
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * -XX:AOTLibrary=./AotInvokeStatic2AotTest.so
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
|
+ * compiler.calls.common.InvokeStatic
|
|
+ * -checkCallerCompileLevel -2 -checkCalleeCompileLevel -2
|
|
+ * @summary check calls from aot to aot code using invokestatic
|
|
+ */
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeStatic2CompiledTest.java b/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeStatic2CompiledTest.java
|
|
new file mode 100644
|
|
index 000000000..a69b5c31d
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeStatic2CompiledTest.java
|
|
@@ -0,0 +1,46 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 /
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.calls.common.InvokeStatic
|
|
+ * jdk.test.whitebox.WhiteBox
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
|
+ * @run driver compiler.aot.AotCompiler -libname AotInvokeStatic2CompiledTest.so
|
|
+ * -class compiler.calls.common.InvokeStatic
|
|
+ * -compile compiler.calls.common.InvokeStatic.caller()V
|
|
+ * @run main/othervm -Xbatch -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * -XX:AOTLibrary=./AotInvokeStatic2CompiledTest.so
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
|
+ * compiler.calls.common.InvokeStatic -compileCallee 1
|
|
+ * -checkCalleeCompileLevel 1
|
|
+ * @run main/othervm -Xbatch -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * -XX:AOTLibrary=./AotInvokeStatic2CompiledTest.so
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
|
+ * compiler.calls.common.InvokeStatic -compileCallee 4
|
|
+ * -checkCalleeCompileLevel 4
|
|
+ * @summary check calls from aot to jit-compiled code using invokestatic
|
|
+ */
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeStatic2InterpretedTest.java b/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeStatic2InterpretedTest.java
|
|
new file mode 100644
|
|
index 000000000..12ad2e786
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeStatic2InterpretedTest.java
|
|
@@ -0,0 +1,42 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 /
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.calls.common.InvokeStatic
|
|
+ * jdk.test.whitebox.WhiteBox
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
|
+ * @run driver compiler.aot.AotCompiler
|
|
+ * -libname AotInvokeStatic2InterpretedTest.so
|
|
+ * -class compiler.calls.common.InvokeStatic
|
|
+ * -compile compiler.calls.common.InvokeStatic.caller()V
|
|
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * -XX:AOTLibrary=./AotInvokeStatic2InterpretedTest.so
|
|
+ * -XX:CompileCommand=exclude,compiler.calls.common.InvokeStatic::callee
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
|
+ * compiler.calls.common.InvokeStatic -checkCallerCompileLevel -2
|
|
+ * @summary check calls from aot to interpreted code using invokestatic
|
|
+ */
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeStatic2NativeTest.java b/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeStatic2NativeTest.java
|
|
new file mode 100644
|
|
index 000000000..3ccc920e4
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeStatic2NativeTest.java
|
|
@@ -0,0 +1,40 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 /
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.calls.common.InvokeStatic
|
|
+ * jdk.test.whitebox.WhiteBox
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
|
+ * @run driver compiler.aot.AotCompiler -libname AotInvokeStatic2NativeTest.so
|
|
+ * -class compiler.calls.common.InvokeStatic
|
|
+ * -compile compiler.calls.common.InvokeStatic.caller()V
|
|
+ * @run main/othervm/native -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * -XX:AOTLibrary=./AotInvokeStatic2NativeTest.so
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
|
+ * compiler.calls.common.InvokeStatic -nativeCallee -checkCallerCompileLevel -2
|
|
+ * @summary check calls from aot to native code using invokestatic
|
|
+ */
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeVirtual2AotTest.java b/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeVirtual2AotTest.java
|
|
new file mode 100644
|
|
index 000000000..8fc2c9ae0
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeVirtual2AotTest.java
|
|
@@ -0,0 +1,41 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 /
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.calls.common.InvokeVirtual
|
|
+ * jdk.test.whitebox.WhiteBox
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
|
+ * @run driver compiler.aot.AotCompiler -libname AotInvokeVirtual2AotTest.so
|
|
+ * -class compiler.calls.common.InvokeVirtual
|
|
+ * -extraopt -XX:+UnlockDiagnosticVMOptions -extraopt -XX:+WhiteBoxAPI -extraopt -Xbootclasspath/a:.
|
|
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * -XX:AOTLibrary=./AotInvokeVirtual2AotTest.so
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
|
+ * compiler.calls.common.InvokeVirtual
|
|
+ * -checkCallerCompileLevel -2 -checkCalleeCompileLevel -2
|
|
+ * @summary check calls from aot to aot code, using invokevirtual
|
|
+ */
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeVirtual2CompiledTest.java b/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeVirtual2CompiledTest.java
|
|
new file mode 100644
|
|
index 000000000..10251b9b0
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeVirtual2CompiledTest.java
|
|
@@ -0,0 +1,46 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 /
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.calls.common.InvokeVirtual
|
|
+ * jdk.test.whitebox.WhiteBox
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
|
+ * @run driver compiler.aot.AotCompiler -libname AotInvokeVirtual2CompiledTest.so
|
|
+ * -class compiler.calls.common.InvokeVirtual
|
|
+ * -compile compiler.calls.common.InvokeVirtual.caller()V
|
|
+ * @run main/othervm -Xbatch -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * -XX:AOTLibrary=./AotInvokeVirtual2CompiledTest.so
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
|
+ * compiler.calls.common.InvokeVirtual -compileCallee 1
|
|
+ * -checkCalleeCompileLevel 1
|
|
+ * @run main/othervm -Xbatch -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * -XX:AOTLibrary=./AotInvokeVirtual2CompiledTest.so
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
|
+ * compiler.calls.common.InvokeVirtual -compileCallee 4
|
|
+ * -checkCalleeCompileLevel 4
|
|
+ * @summary check calls from aot to jit-compiled code, using invokevirtual
|
|
+ */
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeVirtual2InterpretedTest.java b/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeVirtual2InterpretedTest.java
|
|
new file mode 100644
|
|
index 000000000..754d5fef7
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeVirtual2InterpretedTest.java
|
|
@@ -0,0 +1,42 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 /
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.calls.common.InvokeVirtual
|
|
+ * jdk.test.whitebox.WhiteBox
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
|
+ * @run driver compiler.aot.AotCompiler
|
|
+ * -libname AotInvokeVirtual2InterpretedTest.so
|
|
+ * -class compiler.calls.common.InvokeVirtual
|
|
+ * -compile compiler.calls.common.InvokeVirtual.caller()V
|
|
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * -XX:AOTLibrary=./AotInvokeVirtual2InterpretedTest.so
|
|
+ * -XX:CompileCommand=exclude,compiler.calls.common.InvokeVirtual::callee
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
|
+ * compiler.calls.common.InvokeVirtual -checkCallerCompileLevel -2
|
|
+ * @summary check calls from aot to interpreted code, using invokevirtual
|
|
+ */
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeVirtual2NativeTest.java b/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeVirtual2NativeTest.java
|
|
new file mode 100644
|
|
index 000000000..6761e19d1
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/calls/fromAot/AotInvokeVirtual2NativeTest.java
|
|
@@ -0,0 +1,40 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 /
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.calls.common.InvokeVirtual
|
|
+ * jdk.test.whitebox.WhiteBox
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
|
+ * @run driver compiler.aot.AotCompiler -libname AotInvokeVirtual2NativeTest.so
|
|
+ * -class compiler.calls.common.InvokeVirtual
|
|
+ * -compile compiler.calls.common.InvokeVirtual.caller()V
|
|
+ * @run main/othervm/native -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * -XX:AOTLibrary=./AotInvokeVirtual2NativeTest.so
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
|
+ * compiler.calls.common.InvokeVirtual -nativeCallee -checkCallerCompileLevel -2
|
|
+ * @summary check calls from aot to native code, using invokevirtual
|
|
+ */
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/calls/fromCompiled/CompiledInvokeDynamic2AotTest.java b/test/hotspot/jtreg/compiler/aot/calls/fromCompiled/CompiledInvokeDynamic2AotTest.java
|
|
new file mode 100644
|
|
index 000000000..20e24378b
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/calls/fromCompiled/CompiledInvokeDynamic2AotTest.java
|
|
@@ -0,0 +1,48 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 /
|
|
+ * @modules java.base/jdk.internal.org.objectweb.asm
|
|
+ * java.base/jdk.internal.misc
|
|
+ * @build compiler.calls.common.InvokeDynamic
|
|
+ * jdk.test.whitebox.WhiteBox
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
|
+ * @run driver compiler.calls.common.InvokeDynamicPatcher
|
|
+ * @run driver compiler.aot.AotCompiler -libname CompiledInvokeDynamic2AotTest.so
|
|
+ * -class compiler.calls.common.InvokeDynamic
|
|
+ * -compile compiler.calls.common.InvokeDynamic.callee.*
|
|
+ * @run main/othervm -Xbatch -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * -XX:AOTLibrary=./CompiledInvokeDynamic2AotTest.so
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
|
+ * compiler.calls.common.InvokeDynamic -compileCaller 1
|
|
+ * -checkCalleeCompileLevel -2 -checkCallerCompileLevel 1
|
|
+ * @run main/othervm -Xbatch -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * -XX:AOTLibrary=./CompiledInvokeDynamic2AotTest.so
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
|
+ * compiler.calls.common.InvokeDynamic -compileCaller 4
|
|
+ * -checkCallerCompileLevel 4 -checkCalleeCompileLevel -2
|
|
+ * @summary check calls from jit-compiled to aot code using invokedynamic
|
|
+ */
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/calls/fromCompiled/CompiledInvokeInterface2AotTest.java b/test/hotspot/jtreg/compiler/aot/calls/fromCompiled/CompiledInvokeInterface2AotTest.java
|
|
new file mode 100644
|
|
index 000000000..78cb53589
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/calls/fromCompiled/CompiledInvokeInterface2AotTest.java
|
|
@@ -0,0 +1,47 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 /
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.calls.common.InvokeInterface
|
|
+ * jdk.test.whitebox.WhiteBox
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
|
+ * @run driver compiler.aot.AotCompiler
|
|
+ * -libname CompiledInvokeInterface2AotTest.so
|
|
+ * -class compiler.calls.common.InvokeInterface
|
|
+ * -compile compiler.calls.common.InvokeInterface.callee.*
|
|
+ * @run main/othervm -Xbatch -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * -XX:AOTLibrary=./CompiledInvokeInterface2AotTest.so
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
|
+ * compiler.calls.common.InvokeInterface -compileCaller 1
|
|
+ * -checkCalleeCompileLevel -2 -checkCallerCompileLevel 1
|
|
+ * @run main/othervm -Xbatch -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * -XX:AOTLibrary=./CompiledInvokeInterface2AotTest.so
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
|
+ * compiler.calls.common.InvokeInterface -compileCaller 4
|
|
+ * -checkCallerCompileLevel 4 -checkCalleeCompileLevel -2
|
|
+ * @summary check calls from jit-compiled to aot code using invokeinterface
|
|
+ */
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/calls/fromCompiled/CompiledInvokeSpecial2AotTest.java b/test/hotspot/jtreg/compiler/aot/calls/fromCompiled/CompiledInvokeSpecial2AotTest.java
|
|
new file mode 100644
|
|
index 000000000..04ae4ecac
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/calls/fromCompiled/CompiledInvokeSpecial2AotTest.java
|
|
@@ -0,0 +1,46 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 /
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.calls.common.InvokeSpecial
|
|
+ * jdk.test.whitebox.WhiteBox
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
|
+ * @run driver compiler.aot.AotCompiler -libname CompiledInvokeSpecial2AotTest.so
|
|
+ * -class compiler.calls.common.InvokeSpecial
|
|
+ * -compile compiler.calls.common.InvokeSpecial.callee.*
|
|
+ * @run main/othervm -Xbatch -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * -XX:AOTLibrary=./CompiledInvokeSpecial2AotTest.so
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
|
+ * compiler.calls.common.InvokeSpecial -compileCaller 1
|
|
+ * -checkCalleeCompileLevel -2 -checkCallerCompileLevel 1
|
|
+ * @run main/othervm -Xbatch -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * -XX:AOTLibrary=./CompiledInvokeSpecial2AotTest.so
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
|
+ * compiler.calls.common.InvokeSpecial -compileCaller 4
|
|
+ * -checkCallerCompileLevel 4 -checkCalleeCompileLevel -2
|
|
+ * @summary check calls from jit-compiled to aot code using invokespecial
|
|
+ */
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/calls/fromCompiled/CompiledInvokeStatic2AotTest.java b/test/hotspot/jtreg/compiler/aot/calls/fromCompiled/CompiledInvokeStatic2AotTest.java
|
|
new file mode 100644
|
|
index 000000000..d07f7d5e0
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/calls/fromCompiled/CompiledInvokeStatic2AotTest.java
|
|
@@ -0,0 +1,46 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 /
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.calls.common.InvokeStatic
|
|
+ * jdk.test.whitebox.WhiteBox
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
|
+ * @run driver compiler.aot.AotCompiler -libname CompiledInvokeStatic2AotTest.so
|
|
+ * -class compiler.calls.common.InvokeStatic
|
|
+ * -compile compiler.calls.common.InvokeStatic.callee.*
|
|
+ * @run main/othervm -Xbatch -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * -XX:AOTLibrary=./CompiledInvokeStatic2AotTest.so
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
|
+ * compiler.calls.common.InvokeStatic -compileCaller 1
|
|
+ * -checkCalleeCompileLevel -2 -checkCallerCompileLevel 1
|
|
+ * @run main/othervm -Xbatch -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * -XX:AOTLibrary=./CompiledInvokeStatic2AotTest.so
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
|
+ * compiler.calls.common.InvokeStatic -compileCaller 4
|
|
+ * -checkCallerCompileLevel 4 -checkCalleeCompileLevel -2
|
|
+ * @summary check calls from jit-compiled to aot code using invokestatic
|
|
+ */
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/calls/fromCompiled/CompiledInvokeVirtual2AotTest.java b/test/hotspot/jtreg/compiler/aot/calls/fromCompiled/CompiledInvokeVirtual2AotTest.java
|
|
new file mode 100644
|
|
index 000000000..807526e30
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/calls/fromCompiled/CompiledInvokeVirtual2AotTest.java
|
|
@@ -0,0 +1,46 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 /
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.calls.common.InvokeVirtual
|
|
+ * jdk.test.whitebox.WhiteBox
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
|
+ * @run driver compiler.aot.AotCompiler -libname CompiledInvokeVirtual2AotTest.so
|
|
+ * -class compiler.calls.common.InvokeVirtual
|
|
+ * -compile compiler.calls.common.InvokeVirtual.callee.*
|
|
+ * @run main/othervm -Xbatch -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * -XX:AOTLibrary=./CompiledInvokeVirtual2AotTest.so
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
|
+ * compiler.calls.common.InvokeVirtual -compileCaller 1
|
|
+ * -checkCalleeCompileLevel -2 -checkCallerCompileLevel 1
|
|
+ * @run main/othervm -Xbatch -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * -XX:AOTLibrary=./CompiledInvokeVirtual2AotTest.so
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
|
+ * compiler.calls.common.InvokeVirtual -compileCaller 4
|
|
+ * -checkCallerCompileLevel 4 -checkCalleeCompileLevel -2
|
|
+ * @summary check calls from jit-compiled to aot code using invokevirtual
|
|
+ */
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/calls/fromInterpreted/InterpretedInvokeDynamic2AotTest.java b/test/hotspot/jtreg/compiler/aot/calls/fromInterpreted/InterpretedInvokeDynamic2AotTest.java
|
|
new file mode 100644
|
|
index 000000000..c08bb7382
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/calls/fromInterpreted/InterpretedInvokeDynamic2AotTest.java
|
|
@@ -0,0 +1,44 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 /
|
|
+ * @modules java.base/jdk.internal.org.objectweb.asm
|
|
+ * java.base/jdk.internal.misc
|
|
+ * @build compiler.calls.common.InvokeDynamic
|
|
+ * jdk.test.whitebox.WhiteBox
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
|
+ * @run driver compiler.calls.common.InvokeDynamicPatcher
|
|
+ * @run driver compiler.aot.AotCompiler
|
|
+ * -libname InterpretedInvokeDynamic2AotTest.so
|
|
+ * -class compiler.calls.common.InvokeDynamic
|
|
+ * -compile compiler.calls.common.InvokeDynamic.callee.*
|
|
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * -XX:AOTLibrary=./InterpretedInvokeDynamic2AotTest.so
|
|
+ * -XX:CompileCommand=exclude,compiler.calls.common.InvokeDynamic::caller
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
|
+ * compiler.calls.common.InvokeDynamic -checkCalleeCompileLevel -2
|
|
+ * @summary check calls from interpreted to aot code using invokedynamic
|
|
+ */
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/calls/fromInterpreted/InterpretedInvokeInterface2AotTest.java b/test/hotspot/jtreg/compiler/aot/calls/fromInterpreted/InterpretedInvokeInterface2AotTest.java
|
|
new file mode 100644
|
|
index 000000000..320c1072e
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/calls/fromInterpreted/InterpretedInvokeInterface2AotTest.java
|
|
@@ -0,0 +1,42 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 /
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.calls.common.InvokeInterface
|
|
+ * jdk.test.whitebox.WhiteBox
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
|
+ * @run driver compiler.aot.AotCompiler
|
|
+ * -libname InterpretedInvokeInterface2AotTest.so
|
|
+ * -class compiler.calls.common.InvokeInterface
|
|
+ * -compile compiler.calls.common.InvokeInterface.callee.*
|
|
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * -XX:AOTLibrary=./InterpretedInvokeInterface2AotTest.so
|
|
+ * -XX:CompileCommand=exclude,compiler.calls.common.InvokeInterface::caller
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
|
+ * compiler.calls.common.InvokeInterface -checkCalleeCompileLevel -2
|
|
+ * @summary check calls from interpreted to aot code using invokeinterface
|
|
+ */
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/calls/fromInterpreted/InterpretedInvokeSpecial2AotTest.java b/test/hotspot/jtreg/compiler/aot/calls/fromInterpreted/InterpretedInvokeSpecial2AotTest.java
|
|
new file mode 100644
|
|
index 000000000..bd591c2fc
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/calls/fromInterpreted/InterpretedInvokeSpecial2AotTest.java
|
|
@@ -0,0 +1,42 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 /
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.calls.common.InvokeSpecial
|
|
+ * jdk.test.whitebox.WhiteBox
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
|
+ * @run driver compiler.aot.AotCompiler
|
|
+ * -libname InterpretedInvokeSpecial2AotTest.so
|
|
+ * -class compiler.calls.common.InvokeSpecial
|
|
+ * -compile compiler.calls.common.InvokeSpecial.callee.*
|
|
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * -XX:AOTLibrary=./InterpretedInvokeSpecial2AotTest.so
|
|
+ * -XX:CompileCommand=exclude,compiler.calls.common.InvokeSpecial::caller
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
|
+ * compiler.calls.common.InvokeSpecial -checkCalleeCompileLevel -2
|
|
+ * @summary check calls from interpreted to aot code using invokespecial
|
|
+ */
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/calls/fromInterpreted/InterpretedInvokeStatic2AotTest.java b/test/hotspot/jtreg/compiler/aot/calls/fromInterpreted/InterpretedInvokeStatic2AotTest.java
|
|
new file mode 100644
|
|
index 000000000..090ee2af4
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/calls/fromInterpreted/InterpretedInvokeStatic2AotTest.java
|
|
@@ -0,0 +1,42 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 /
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.calls.common.InvokeStatic
|
|
+ * jdk.test.whitebox.WhiteBox
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
|
+ * @run driver compiler.aot.AotCompiler
|
|
+ * -libname InterpretedInvokeStatic2AotTest.so
|
|
+ * -class compiler.calls.common.InvokeStatic
|
|
+ * -compile compiler.calls.common.InvokeStatic.callee.*
|
|
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * -XX:AOTLibrary=./InterpretedInvokeStatic2AotTest.so
|
|
+ * -XX:CompileCommand=exclude,compiler.calls.common.InvokeStatic::caller
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
|
+ * compiler.calls.common.InvokeStatic -checkCalleeCompileLevel -2
|
|
+ * @summary check calls from interpreted to aot code using invokestatic
|
|
+ */
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/calls/fromInterpreted/InterpretedInvokeVirtual2AotTest.java b/test/hotspot/jtreg/compiler/aot/calls/fromInterpreted/InterpretedInvokeVirtual2AotTest.java
|
|
new file mode 100644
|
|
index 000000000..31cb0d8c5
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/calls/fromInterpreted/InterpretedInvokeVirtual2AotTest.java
|
|
@@ -0,0 +1,42 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 /
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.calls.common.InvokeVirtual
|
|
+ * jdk.test.whitebox.WhiteBox
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
|
+ * @run driver compiler.aot.AotCompiler
|
|
+ * -libname InterpretedInvokeVirtual2AotTest.so
|
|
+ * -class compiler.calls.common.InvokeVirtual
|
|
+ * -compile compiler.calls.common.InvokeVirtual.callee.*
|
|
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * -XX:AOTLibrary=./InterpretedInvokeVirtual2AotTest.so
|
|
+ * -XX:CompileCommand=exclude,compiler.calls.common.InvokeVirtual::caller
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
|
+ * compiler.calls.common.InvokeVirtual -checkCalleeCompileLevel -2
|
|
+ * @summary check calls from interpreted to aot code using invokevirtual
|
|
+ */
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/calls/fromNative/NativeInvokeSpecial2AotTest.java b/test/hotspot/jtreg/compiler/aot/calls/fromNative/NativeInvokeSpecial2AotTest.java
|
|
new file mode 100644
|
|
index 000000000..705e3c818
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/calls/fromNative/NativeInvokeSpecial2AotTest.java
|
|
@@ -0,0 +1,40 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 /
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.calls.common.InvokeSpecial
|
|
+ * jdk.test.whitebox.WhiteBox
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
|
+ * @run driver compiler.aot.AotCompiler -libname NativeInvokeSpecial2AotTest.so
|
|
+ * -class compiler.calls.common.InvokeSpecial
|
|
+ * -compile compiler.calls.common.InvokeSpecial.callee.*
|
|
+ * @run main/othervm/native -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * -XX:AOTLibrary=./NativeInvokeSpecial2AotTest.so
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
|
+ * compiler.calls.common.InvokeSpecial -nativeCaller -checkCalleeCompileLevel -2
|
|
+ * @summary check calls from native to aot code using invokespecial
|
|
+ */
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/calls/fromNative/NativeInvokeStatic2AotTest.java b/test/hotspot/jtreg/compiler/aot/calls/fromNative/NativeInvokeStatic2AotTest.java
|
|
new file mode 100644
|
|
index 000000000..ac810313b
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/calls/fromNative/NativeInvokeStatic2AotTest.java
|
|
@@ -0,0 +1,40 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 /
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.calls.common.InvokeStatic
|
|
+ * jdk.test.whitebox.WhiteBox
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
|
+ * @run driver compiler.aot.AotCompiler -libname NativeInvokeStatic2AotTest.so
|
|
+ * -class compiler.calls.common.InvokeStatic
|
|
+ * -compile compiler.calls.common.InvokeStatic.callee.*
|
|
+ * @run main/othervm/native -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * -XX:AOTLibrary=./NativeInvokeStatic2AotTest.so
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
|
+ * compiler.calls.common.InvokeStatic -nativeCaller -checkCalleeCompileLevel -2
|
|
+ * @summary check calls from native to aot code using invokestatic
|
|
+ */
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/calls/fromNative/NativeInvokeVirtual2AotTest.java b/test/hotspot/jtreg/compiler/aot/calls/fromNative/NativeInvokeVirtual2AotTest.java
|
|
new file mode 100644
|
|
index 000000000..8d8ab9f18
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/calls/fromNative/NativeInvokeVirtual2AotTest.java
|
|
@@ -0,0 +1,40 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 /
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.calls.common.InvokeVirtual
|
|
+ * jdk.test.whitebox.WhiteBox
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
|
+ * @run driver compiler.aot.AotCompiler -libname NativeInvokeVirtual2AotTest.so
|
|
+ * -class compiler.calls.common.InvokeVirtual
|
|
+ * -compile compiler.calls.common.InvokeVirtual.callee.*
|
|
+ * @run main/othervm/native -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * -XX:AOTLibrary=./NativeInvokeVirtual2AotTest.so
|
|
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
|
+ * compiler.calls.common.InvokeVirtual -nativeCaller -checkCalleeCompileLevel -2
|
|
+ * @summary check calls from native to aot code using invokevirtual
|
|
+ */
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/cli/AotLibraryNegativeBase.java b/test/hotspot/jtreg/compiler/aot/cli/AotLibraryNegativeBase.java
|
|
new file mode 100644
|
|
index 000000000..56a6ecda6
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/cli/AotLibraryNegativeBase.java
|
|
@@ -0,0 +1,49 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 compiler.aot.cli;
|
|
+
|
|
+import compiler.aot.HelloWorldPrinter;
|
|
+import jdk.test.lib.process.ExitCode;
|
|
+import jdk.test.lib.cli.CommandLineOptionTest;
|
|
+
|
|
+public class AotLibraryNegativeBase {
|
|
+ private static final String[] UNEXPECTED_MESSAGES = new String[] {
|
|
+ HelloWorldPrinter.MESSAGE
|
|
+ };
|
|
+
|
|
+ public static void launchTest(String option, String expectedMessages[]) {
|
|
+ try {
|
|
+ boolean addTestVMOptions = true;
|
|
+ CommandLineOptionTest.verifyJVMStartup(expectedMessages,
|
|
+ UNEXPECTED_MESSAGES,
|
|
+ "Unexpected exit code using " + option,
|
|
+ "Unexpected output using " + option, ExitCode.FAIL,
|
|
+ addTestVMOptions, "-XX:+UnlockExperimentalVMOptions", "-XX:+UseAOT",
|
|
+ "-XX:+PrintAOT", option, HelloWorldPrinter.class.getName());
|
|
+ } catch (Throwable t) {
|
|
+ throw new Error("Problems executing test using " + option
|
|
+ + ": " + t, t);
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/cli/DisabledAOTWithLibraryTest.java b/test/hotspot/jtreg/compiler/aot/cli/DisabledAOTWithLibraryTest.java
|
|
new file mode 100644
|
|
index 000000000..433231de3
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/cli/DisabledAOTWithLibraryTest.java
|
|
@@ -0,0 +1,66 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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.cli.DisabledAOTWithLibraryTest
|
|
+ * compiler.aot.AotCompiler
|
|
+ * @run driver compiler.aot.AotCompiler -libname libDisabledAOTWithLibraryTest.so
|
|
+ * -class compiler.aot.HelloWorldPrinter
|
|
+ * -compile compiler.aot.HelloWorldPrinter.print()V
|
|
+ * @run driver compiler.aot.cli.DisabledAOTWithLibraryTest
|
|
+ * @summary check if providing aot library with aot disabled is handled properly
|
|
+ */
|
|
+
|
|
+package compiler.aot.cli;
|
|
+
|
|
+import compiler.aot.HelloWorldPrinter;
|
|
+import jdk.test.lib.process.ExitCode;
|
|
+import jdk.test.lib.cli.CommandLineOptionTest;
|
|
+
|
|
+public class DisabledAOTWithLibraryTest {
|
|
+ private final static String LIB_NAME = "libDisabledAOTWithLibraryTest.so";
|
|
+ private final static String[] UNEXPECTED_MESSAGES = new String[] {
|
|
+ LIB_NAME + " aot library"
|
|
+ };
|
|
+
|
|
+ private final static String[] EXPECTED_MESSAGES = new String[] {
|
|
+ HelloWorldPrinter.MESSAGE
|
|
+ };
|
|
+
|
|
+ public static void main(String args[]) {
|
|
+ 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,
|
|
+ HelloWorldPrinter.class.getName());
|
|
+ } catch (Throwable t) {
|
|
+ throw new Error("Problems executing test " + t, t);
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/cli/IncorrectAOTLibraryTest.java b/test/hotspot/jtreg/compiler/aot/cli/IncorrectAOTLibraryTest.java
|
|
new file mode 100644
|
|
index 000000000..a5b7ea9ca
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/cli/IncorrectAOTLibraryTest.java
|
|
@@ -0,0 +1,48 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 /
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.lib.helpers.ClassFileInstaller
|
|
+ * @run driver compiler.aot.cli.IncorrectAOTLibraryTest
|
|
+ * @summary check if incorrect aot library is handled properly
|
|
+ */
|
|
+
|
|
+package compiler.aot.cli;
|
|
+
|
|
+import java.nio.file.Paths;
|
|
+
|
|
+public class IncorrectAOTLibraryTest {
|
|
+ private static final String OPTION
|
|
+ = "-XX:AOTLibrary=./" + Paths.get("jdk", "test", "lib", "helpers", "ClassFileInstaller.class").toString();
|
|
+ private static final String[] EXPECTED_MESSAGES = new String[] {
|
|
+ "error opening file:"
|
|
+ };
|
|
+
|
|
+ public static void main(String args[]) {
|
|
+ AotLibraryNegativeBase.launchTest(OPTION, EXPECTED_MESSAGES);
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/cli/MultipleAOTLibraryTest.java b/test/hotspot/jtreg/compiler/aot/cli/MultipleAOTLibraryTest.java
|
|
new file mode 100644
|
|
index 000000000..1423c55dc
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/cli/MultipleAOTLibraryTest.java
|
|
@@ -0,0 +1,96 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 /
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.aot.cli.MultipleAOTLibraryTest
|
|
+ * compiler.aot.AotCompiler
|
|
+ * @run driver compiler.aot.AotCompiler
|
|
+ * -libname libMultipleAOTLibraryTest1.so
|
|
+ * -class compiler.aot.HelloWorldPrinter
|
|
+ * -compile compiler.aot.HelloWorldPrinter.*
|
|
+ * -extraopt -XX:+UseCompressedOops
|
|
+ * @run driver compiler.aot.AotCompiler
|
|
+ * -libname libMultipleAOTLibraryTest2.so
|
|
+ * -class compiler.aot.HelloWorldPrinter
|
|
+ * -compile compiler.aot.HelloWorldPrinter.print()V
|
|
+ * -extraopt -XX:+UseCompressedOops
|
|
+ * @run driver compiler.aot.cli.MultipleAOTLibraryTest -XX:+UseCompressedOops
|
|
+ * @run driver compiler.aot.AotCompiler -libname libMultipleAOTLibraryTest1.so
|
|
+ * -class compiler.aot.HelloWorldPrinter
|
|
+ * -compile compiler.aot.HelloWorldPrinter.*
|
|
+ * -extraopt -XX:-UseCompressedOops
|
|
+ * @run driver compiler.aot.AotCompiler -libname libMultipleAOTLibraryTest2.so
|
|
+ * -class compiler.aot.HelloWorldPrinter
|
|
+ * -compile compiler.aot.HelloWorldPrinter.print()V
|
|
+ * -extraopt -XX:-UseCompressedOops
|
|
+ * @run driver compiler.aot.cli.MultipleAOTLibraryTest -XX:-UseCompressedOops
|
|
+ * @summary check if multiple aot libraries are loaded successfully
|
|
+ */
|
|
+
|
|
+package compiler.aot.cli;
|
|
+
|
|
+import compiler.aot.HelloWorldPrinter;
|
|
+import java.io.File;
|
|
+import java.util.Arrays;
|
|
+import jdk.test.lib.process.ExitCode;
|
|
+import jdk.test.lib.cli.CommandLineOptionTest;
|
|
+
|
|
+public final class MultipleAOTLibraryTest {
|
|
+ private final static String EXPECTED_OUTPUT[] = new String[] {
|
|
+ "libMultipleAOTLibraryTest1.so aot library",
|
|
+ "libMultipleAOTLibraryTest2.so aot library",
|
|
+ HelloWorldPrinter.MESSAGE
|
|
+ };
|
|
+ private final static String UNEXPECTED_OUTPUT[] = null;
|
|
+
|
|
+ public static void main(String args[]) {
|
|
+ new MultipleAOTLibraryTest().runTest(args);
|
|
+ }
|
|
+
|
|
+ private void runTest(String args[]) {
|
|
+ try {
|
|
+ boolean addTestVMOptions = true;
|
|
+ String[] allArgs = Arrays.copyOf(args, args.length + 5);
|
|
+ allArgs[args.length] = "-XX:+UnlockExperimentalVMOptions";
|
|
+ allArgs[args.length + 1] = "-XX:AOTLibrary="
|
|
+ + "." + File.separator
|
|
+ + "libMultipleAOTLibraryTest1.so"
|
|
+ + File.pathSeparator
|
|
+ + "." + File.separator
|
|
+ + "libMultipleAOTLibraryTest2.so";
|
|
+ allArgs[args.length + 2] = "-XX:+PrintAOT";
|
|
+ allArgs[args.length + 3] = "-XX:+UseAOT";
|
|
+ allArgs[args.length + 4] = HelloWorldPrinter.class.getName();
|
|
+ CommandLineOptionTest.verifyJVMStartup(EXPECTED_OUTPUT,
|
|
+ UNEXPECTED_OUTPUT, "Unexpected exit code",
|
|
+ "Unexpected output", ExitCode.OK, addTestVMOptions,
|
|
+ allArgs);
|
|
+ } catch (Throwable t) {
|
|
+ throw new Error("Problems executing test: " + t, t);
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/cli/NonExistingAOTLibraryTest.java b/test/hotspot/jtreg/compiler/aot/cli/NonExistingAOTLibraryTest.java
|
|
new file mode 100644
|
|
index 000000000..1d317643b
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/cli/NonExistingAOTLibraryTest.java
|
|
@@ -0,0 +1,50 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 /
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @run driver compiler.aot.cli.NonExistingAOTLibraryTest
|
|
+ * @summary check if non-existing aot library is handled properly
|
|
+ */
|
|
+
|
|
+package compiler.aot.cli;
|
|
+
|
|
+import java.io.File;
|
|
+
|
|
+public class NonExistingAOTLibraryTest {
|
|
+ private static final String PATH = "./NonExisting.so";
|
|
+ private static final String OPTION = "-XX:AOTLibrary=" + PATH;
|
|
+ private static final String[] EXPECTED_MESSAGES = new String[] {
|
|
+ "error opening file"
|
|
+ };
|
|
+
|
|
+ public static void main(String args[]) {
|
|
+ if (new File(PATH).exists()) {
|
|
+ throw new Error("TESTBUG: " + PATH + " unexpectedly exists");
|
|
+ }
|
|
+ AotLibraryNegativeBase.launchTest(OPTION, EXPECTED_MESSAGES);
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/cli/SingleAOTLibraryTest.java b/test/hotspot/jtreg/compiler/aot/cli/SingleAOTLibraryTest.java
|
|
new file mode 100644
|
|
index 000000000..79403d199
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/cli/SingleAOTLibraryTest.java
|
|
@@ -0,0 +1,77 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.aot.cli.SingleAOTLibraryTest
|
|
+ * compiler.aot.AotCompiler
|
|
+ * @run driver compiler.aot.AotCompiler -libname libSingleAOTLibraryTest.so
|
|
+ * -class compiler.aot.HelloWorldPrinter
|
|
+ * -compile compiler.aot.HelloWorldPrinter.print()V
|
|
+ * -extraopt -XX:+UseCompressedOops
|
|
+ * @run driver compiler.aot.cli.SingleAOTLibraryTest -XX:+UseCompressedOops
|
|
+ * @run driver compiler.aot.AotCompiler -libname libSingleAOTLibraryTest.so
|
|
+ * -class compiler.aot.HelloWorldPrinter
|
|
+ * -compile compiler.aot.HelloWorldPrinter.print()V
|
|
+ * -extraopt -XX:-UseCompressedOops
|
|
+ * @run driver compiler.aot.cli.SingleAOTLibraryTest -XX:-UseCompressedOops
|
|
+ * @summary check if single aot library is loaded successfully
|
|
+ */
|
|
+
|
|
+package compiler.aot.cli;
|
|
+
|
|
+import compiler.aot.HelloWorldPrinter;
|
|
+import jdk.test.lib.process.ExitCode;
|
|
+import jdk.test.lib.cli.CommandLineOptionTest;
|
|
+
|
|
+public final class SingleAOTLibraryTest {
|
|
+ private static final String[] EXPECTED_MESSAGES = new String[] {
|
|
+ "libSingleAOTLibraryTest.so aot library",
|
|
+ HelloWorldPrinter.MESSAGE
|
|
+ };
|
|
+ private static final String[] UNEXPECTED_MESSAGES = null;
|
|
+ public static void main(String args[]) {
|
|
+ if (args.length == 1) {
|
|
+ new SingleAOTLibraryTest().runTest(args[0]);
|
|
+ } else {
|
|
+ throw new Error("Test expects 1 parameter");
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private void runTest(String arg) {
|
|
+ try {
|
|
+ boolean addTestVMOptions = true;
|
|
+ CommandLineOptionTest.verifyJVMStartup(EXPECTED_MESSAGES,
|
|
+ UNEXPECTED_MESSAGES, "Unexpected exit code using " + arg,
|
|
+ "Unexpected output using " + arg, ExitCode.OK,
|
|
+ addTestVMOptions, "-XX:+UnlockExperimentalVMOptions", "-XX:+UseAOT",
|
|
+ "-XX:+PrintAOT", arg, "-XX:AOTLibrary=./libSingleAOTLibraryTest.so",
|
|
+ HelloWorldPrinter.class.getName());
|
|
+ } catch (Throwable t) {
|
|
+ throw new Error("Problems executing test: " + t, t);
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/cli/SingleAOTOptionTest.java b/test/hotspot/jtreg/compiler/aot/cli/SingleAOTOptionTest.java
|
|
new file mode 100644
|
|
index 000000000..cbc065cbf
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/cli/SingleAOTOptionTest.java
|
|
@@ -0,0 +1,86 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 /
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.aot.cli.SingleAOTOptionTest
|
|
+ * compiler.aot.AotCompiler
|
|
+ * @run driver compiler.aot.AotCompiler -libname libSingleAOTOptionTest.so
|
|
+ * -class compiler.aot.HelloWorldPrinter
|
|
+ * -compile compiler.aot.HelloWorldPrinter.print()V
|
|
+ * -extraopt -XX:+UseCompressedOops
|
|
+ * @run driver compiler.aot.cli.SingleAOTOptionTest -XX:+UseCompressedOops
|
|
+ * -XX:+UnlockExperimentalVMOptions -XX:AOTLibrary=./libSingleAOTOptionTest.so
|
|
+ * @run main compiler.aot.cli.SingleAOTOptionTest
|
|
+ * -XX:+UseCompressedOops -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * @run driver compiler.aot.AotCompiler -libname libSingleAOTOptionTest.so
|
|
+ * -class compiler.aot.HelloWorldPrinter
|
|
+ * -compile compiler.aot.HelloWorldPrinter.print()V
|
|
+ * -extraopt -XX:-UseCompressedOops
|
|
+ * @run driver compiler.aot.cli.SingleAOTOptionTest -XX:-UseCompressedOops
|
|
+ * -XX:+UnlockExperimentalVMOptions -XX:AOTLibrary=./libSingleAOTOptionTest.so
|
|
+ * @run driver compiler.aot.cli.SingleAOTOptionTest
|
|
+ * -XX:-UseCompressedOops -XX:+UnlockExperimentalVMOptions -XX:+UseAOT
|
|
+ * @summary check if specifying only one aot option handled properly
|
|
+ */
|
|
+
|
|
+package compiler.aot.cli;
|
|
+
|
|
+import compiler.aot.HelloWorldPrinter;
|
|
+import jdk.test.lib.process.ExitCode;
|
|
+import jdk.test.lib.cli.CommandLineOptionTest;
|
|
+
|
|
+public class SingleAOTOptionTest {
|
|
+ private static final String[] EXPECTED_MESSAGES = new String[] {
|
|
+ HelloWorldPrinter.MESSAGE
|
|
+ };
|
|
+ private static final String[] UNEXPECTED_MESSAGES = null;
|
|
+
|
|
+ public static void main(String args[]) {
|
|
+ if (args.length == 3) {
|
|
+ new SingleAOTOptionTest().runTest(args[0], args[1], args[2]);
|
|
+ } else {
|
|
+ throw new Error("Test expects 2 parameters");
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private void runTest(String arg1, String arg2, String arg3) {
|
|
+ try {
|
|
+ String exitCodeErrorMessage = String.format("Unexpected exit code "
|
|
+ + "using %s %s %s", arg1, arg2, arg3);
|
|
+ String outputErrorMessage = String.format("Unexpected output using"
|
|
+ + " %s %s", arg1, arg2, arg3);
|
|
+ boolean addTestVMOptions = true;
|
|
+ CommandLineOptionTest.verifyJVMStartup(EXPECTED_MESSAGES,
|
|
+ UNEXPECTED_MESSAGES, exitCodeErrorMessage,
|
|
+ outputErrorMessage, ExitCode.OK, addTestVMOptions, arg1,
|
|
+ arg2, arg3, HelloWorldPrinter.class.getName());
|
|
+ } catch (Throwable t) {
|
|
+ throw new Error("Problems executing test: " + t, t);
|
|
+ }
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/cli/jaotc/AtFileTest.java b/test/hotspot/jtreg/compiler/aot/cli/jaotc/AtFileTest.java
|
|
new file mode 100644
|
|
index 000000000..0f14f1053
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/cli/jaotc/AtFileTest.java
|
|
@@ -0,0 +1,60 @@
|
|
+/*
|
|
+ * Copyright (c) 2018, 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
|
|
+ * 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
|
|
+ * @summary check at-file jaotc support
|
|
+ * @comment based on CompileClassTest with arguments wrote in 'jaotc.cmd' file
|
|
+ * @requires vm.aot
|
|
+ * @bug 8215322
|
|
+ * @library / /test/lib /testlibrary
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.aot.cli.jaotc.AtFileTest
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller compiler.aot.cli.jaotc.data.HelloWorldOne
|
|
+ * @run driver compiler.aot.cli.jaotc.AtFileTest
|
|
+ */
|
|
+
|
|
+package compiler.aot.cli.jaotc;
|
|
+
|
|
+import compiler.aot.cli.jaotc.data.HelloWorldOne;
|
|
+import java.io.File;
|
|
+import java.nio.file.Path;
|
|
+import java.nio.file.Paths;
|
|
+import java.nio.file.Files;
|
|
+import java.util.List;
|
|
+import jdk.test.lib.Asserts;
|
|
+import jdk.test.lib.process.OutputAnalyzer;
|
|
+
|
|
+public class AtFileTest {
|
|
+ public static void main(String[] args) throws Exception {
|
|
+ Path file = Paths.get("jaotc.cmd");
|
|
+ Files.write(file, List.of("--class-name",
|
|
+ JaotcTestHelper.getClassAotCompilationName(HelloWorldOne.class)));
|
|
+ OutputAnalyzer oa = JaotcTestHelper.compileLibrary("@" + file.toString());
|
|
+ oa.shouldHaveExitValue(0);
|
|
+ File compiledLibrary = new File(JaotcTestHelper.DEFAULT_LIB_PATH);
|
|
+ Asserts.assertTrue(compiledLibrary.exists(), "Compiled library file missing");
|
|
+ Asserts.assertGT(compiledLibrary.length(), 0L, "Unexpected compiled library size");
|
|
+ JaotcTestHelper.checkLibraryUsage(HelloWorldOne.class.getName());
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/cli/jaotc/ClasspathOptionUnknownClassTest.java b/test/hotspot/jtreg/compiler/aot/cli/jaotc/ClasspathOptionUnknownClassTest.java
|
|
new file mode 100644
|
|
index 000000000..fe03c108d
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/cli/jaotc/ClasspathOptionUnknownClassTest.java
|
|
@@ -0,0 +1,47 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 / /testlibrary/ /test/lib
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @compile data/HelloWorldOne.java
|
|
+ * @run driver compiler.aot.cli.jaotc.ClasspathOptionUnknownClassTest
|
|
+ * @summary check jaotc can't compile class not from classpath
|
|
+ */
|
|
+
|
|
+package compiler.aot.cli.jaotc;
|
|
+
|
|
+import java.io.File;
|
|
+import jdk.test.lib.Asserts;
|
|
+import jdk.test.lib.process.OutputAnalyzer;
|
|
+
|
|
+public class ClasspathOptionUnknownClassTest {
|
|
+ public static void main(String[] args) {
|
|
+ OutputAnalyzer oa = JaotcTestHelper.compileLibrary("--class-name", "HelloWorldOne");
|
|
+ Asserts.assertNE(oa.getExitValue(), 0, "Unexpected compilation exit code");
|
|
+ File compiledLibrary = new File(JaotcTestHelper.DEFAULT_LIB_PATH);
|
|
+ Asserts.assertFalse(compiledLibrary.exists(), "Compiler library unexpectedly exists");
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/cli/jaotc/CompileAbsoluteDirectoryTest.java b/test/hotspot/jtreg/compiler/aot/cli/jaotc/CompileAbsoluteDirectoryTest.java
|
|
new file mode 100644
|
|
index 000000000..6e1cf3081
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/cli/jaotc/CompileAbsoluteDirectoryTest.java
|
|
@@ -0,0 +1,60 @@
|
|
+/*
|
|
+ * Copyright (c) 2019, 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
|
|
+ * 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
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.aot.cli.jaotc.CompileAbsoluteDirectoryTest
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller compiler.aot.cli.jaotc.data.HelloWorldOne
|
|
+ * compiler.aot.cli.jaotc.data.HelloWorldTwo
|
|
+ * @run driver compiler.aot.cli.jaotc.CompileAbsoluteDirectoryTest
|
|
+ * @summary check jaotc can compile directory with classes where directory is specified by absolute path
|
|
+ * @bug 8218859
|
|
+ */
|
|
+package compiler.aot.cli.jaotc;
|
|
+
|
|
+import compiler.aot.cli.jaotc.data.HelloWorldOne;
|
|
+import compiler.aot.cli.jaotc.data.HelloWorldTwo;
|
|
+import java.io.File;
|
|
+import jdk.test.lib.Asserts;
|
|
+import jdk.test.lib.process.OutputAnalyzer;
|
|
+
|
|
+public class CompileAbsoluteDirectoryTest {
|
|
+ public static void main(String[] args) {
|
|
+ try {
|
|
+ String dir = new java.io.File(".").getAbsolutePath();
|
|
+ System.out.println("Do test --directory " + dir);
|
|
+ OutputAnalyzer oa = JaotcTestHelper.compileLibrary("--directory", dir);
|
|
+ oa.shouldHaveExitValue(0);
|
|
+ File compiledLibrary = new File(JaotcTestHelper.DEFAULT_LIB_PATH);
|
|
+ Asserts.assertTrue(compiledLibrary.exists(), "Compiled library file missing");
|
|
+ Asserts.assertGT(compiledLibrary.length(), 0L, "Unexpected compiled library size");
|
|
+ JaotcTestHelper.checkLibraryUsage(HelloWorldOne.class.getName());
|
|
+ JaotcTestHelper.checkLibraryUsage(HelloWorldTwo.class.getName());
|
|
+ } catch (Exception e) {
|
|
+ throw new Error("Can't get full path name for '.', got exception " + e, e);
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/cli/jaotc/CompileClassTest.java b/test/hotspot/jtreg/compiler/aot/cli/jaotc/CompileClassTest.java
|
|
new file mode 100644
|
|
index 000000000..efc7cc523
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/cli/jaotc/CompileClassTest.java
|
|
@@ -0,0 +1,52 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.aot.cli.jaotc.CompileClassTest
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller compiler.aot.cli.jaotc.data.HelloWorldOne
|
|
+ * @run driver compiler.aot.cli.jaotc.CompileClassTest
|
|
+ * @summary check jaotc can compile class
|
|
+ */
|
|
+
|
|
+package compiler.aot.cli.jaotc;
|
|
+
|
|
+import compiler.aot.cli.jaotc.data.HelloWorldOne;
|
|
+import java.io.File;
|
|
+import jdk.test.lib.Asserts;
|
|
+import jdk.test.lib.process.OutputAnalyzer;
|
|
+
|
|
+public class CompileClassTest {
|
|
+ public static void main(String[] args) {
|
|
+ OutputAnalyzer oa = JaotcTestHelper.compileLibrary("--class-name", JaotcTestHelper
|
|
+ .getClassAotCompilationName(HelloWorldOne.class));
|
|
+ oa.shouldHaveExitValue(0);
|
|
+ File compiledLibrary = new File(JaotcTestHelper.DEFAULT_LIB_PATH);
|
|
+ Asserts.assertTrue(compiledLibrary.exists(), "Compiled library file missing");
|
|
+ Asserts.assertGT(compiledLibrary.length(), 0L, "Unexpected compiled library size");
|
|
+ JaotcTestHelper.checkLibraryUsage(HelloWorldOne.class.getName());
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/cli/jaotc/CompileClassWithDebugTest.java b/test/hotspot/jtreg/compiler/aot/cli/jaotc/CompileClassWithDebugTest.java
|
|
new file mode 100644
|
|
index 000000000..7681a9dfe
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/cli/jaotc/CompileClassWithDebugTest.java
|
|
@@ -0,0 +1,52 @@
|
|
+/*
|
|
+ * Copyright (c) 2018, 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
|
|
+ * 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
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.aot.cli.jaotc.CompileClassWithDebugTest
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller compiler.aot.cli.jaotc.data.HelloWorldOne
|
|
+ * @run driver compiler.aot.cli.jaotc.CompileClassWithDebugTest
|
|
+ * @summary check that jaotc can compile a class with a --debug flag
|
|
+ */
|
|
+
|
|
+package compiler.aot.cli.jaotc;
|
|
+
|
|
+import compiler.aot.cli.jaotc.data.HelloWorldOne;
|
|
+import java.io.File;
|
|
+import jdk.test.lib.Asserts;
|
|
+import jdk.test.lib.process.OutputAnalyzer;
|
|
+
|
|
+public class CompileClassWithDebugTest {
|
|
+ public static void main(String[] args) {
|
|
+ OutputAnalyzer oa = JaotcTestHelper.compileLibrary("--debug", "--class-name", JaotcTestHelper
|
|
+ .getClassAotCompilationName(HelloWorldOne.class));
|
|
+ oa.shouldHaveExitValue(0);
|
|
+ File compiledLibrary = new File(JaotcTestHelper.DEFAULT_LIB_PATH);
|
|
+ Asserts.assertTrue(compiledLibrary.exists(), "Compiled library file missing");
|
|
+ Asserts.assertGT(compiledLibrary.length(), 0L, "Unexpected compiled library size");
|
|
+ JaotcTestHelper.checkLibraryUsage(HelloWorldOne.class.getName());
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/cli/jaotc/CompileDirectoryTest.java b/test/hotspot/jtreg/compiler/aot/cli/jaotc/CompileDirectoryTest.java
|
|
new file mode 100644
|
|
index 000000000..cb02909a8
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/cli/jaotc/CompileDirectoryTest.java
|
|
@@ -0,0 +1,53 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.aot.cli.jaotc.CompileDirectoryTest
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller compiler.aot.cli.jaotc.data.HelloWorldOne
|
|
+ * compiler.aot.cli.jaotc.data.HelloWorldTwo
|
|
+ * @run driver compiler.aot.cli.jaotc.CompileDirectoryTest
|
|
+ * @summary check jaotc can compile directory with classes where directory is specified by relative path
|
|
+ */
|
|
+package compiler.aot.cli.jaotc;
|
|
+
|
|
+import compiler.aot.cli.jaotc.data.HelloWorldOne;
|
|
+import compiler.aot.cli.jaotc.data.HelloWorldTwo;
|
|
+import java.io.File;
|
|
+import jdk.test.lib.Asserts;
|
|
+import jdk.test.lib.process.OutputAnalyzer;
|
|
+
|
|
+public class CompileDirectoryTest {
|
|
+ public static void main(String[] args) {
|
|
+ OutputAnalyzer oa =JaotcTestHelper.compileLibrary("--directory", ".");
|
|
+ oa.shouldHaveExitValue(0);
|
|
+ File compiledLibrary = new File(JaotcTestHelper.DEFAULT_LIB_PATH);
|
|
+ Asserts.assertTrue(compiledLibrary.exists(), "Compiled library file missing");
|
|
+ Asserts.assertGT(compiledLibrary.length(), 0L, "Unexpected compiled library size");
|
|
+ JaotcTestHelper.checkLibraryUsage(HelloWorldOne.class.getName());
|
|
+ JaotcTestHelper.checkLibraryUsage(HelloWorldTwo.class.getName());
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/cli/jaotc/CompileJarTest.java b/test/hotspot/jtreg/compiler/aot/cli/jaotc/CompileJarTest.java
|
|
new file mode 100644
|
|
index 000000000..2868bf463
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/cli/jaotc/CompileJarTest.java
|
|
@@ -0,0 +1,75 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.aot.cli.jaotc.CompileJarTest
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller compiler.aot.cli.jaotc.data.HelloWorldOne
|
|
+ * compiler.aot.cli.jaotc.data.HelloWorldTwo
|
|
+ * @run driver compiler.aot.cli.jaotc.CompileJarTest
|
|
+ * @summary check jaotc can compile jar
|
|
+ */
|
|
+
|
|
+package compiler.aot.cli.jaotc;
|
|
+
|
|
+import compiler.aot.cli.jaotc.data.HelloWorldOne;
|
|
+import compiler.aot.cli.jaotc.data.HelloWorldTwo;
|
|
+import java.io.File;
|
|
+import java.io.IOException;
|
|
+import jdk.test.lib.Asserts;
|
|
+import jdk.test.lib.JDKToolLauncher;
|
|
+import jdk.test.lib.process.OutputAnalyzer;
|
|
+
|
|
+public class CompileJarTest {
|
|
+ private static final String JAR_NAME = "test.jar";
|
|
+
|
|
+ public static void main(String[] args) {
|
|
+ createJar();
|
|
+ OutputAnalyzer oa = JaotcTestHelper.compileLibrary("--jar", JAR_NAME);
|
|
+ oa.shouldHaveExitValue(0);
|
|
+ File compiledLibrary = new File(JaotcTestHelper.DEFAULT_LIB_PATH);
|
|
+ Asserts.assertTrue(compiledLibrary.exists(), "Compiled library file missing");
|
|
+ Asserts.assertGT(compiledLibrary.length(), 0L, "Unexpected compiled library size");
|
|
+ JaotcTestHelper.checkLibraryUsage(HelloWorldOne.class.getName());
|
|
+ JaotcTestHelper.checkLibraryUsage(HelloWorldTwo.class.getName());
|
|
+ }
|
|
+
|
|
+ private static void createJar() {
|
|
+ JDKToolLauncher jar = JDKToolLauncher.create("jar")
|
|
+ .addToolArg("-cf")
|
|
+ .addToolArg(JAR_NAME)
|
|
+ .addToolArg("-C")
|
|
+ .addToolArg(".")
|
|
+ .addToolArg(".");
|
|
+ OutputAnalyzer oa;
|
|
+ try {
|
|
+ oa = new OutputAnalyzer(new ProcessBuilder(jar.getCommand()).start());
|
|
+ } catch (IOException e) {
|
|
+ throw new Error("Problems launching jar: " + e, e);
|
|
+ }
|
|
+ oa.shouldHaveExitValue(0);
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/cli/jaotc/CompileModuleTest.java b/test/hotspot/jtreg/compiler/aot/cli/jaotc/CompileModuleTest.java
|
|
new file mode 100644
|
|
index 000000000..c33b8d7c7
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/cli/jaotc/CompileModuleTest.java
|
|
@@ -0,0 +1,75 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @run driver compiler.aot.cli.jaotc.CompileModuleTest
|
|
+ * @summary check jaotc can compile module
|
|
+ */
|
|
+
|
|
+package compiler.aot.cli.jaotc;
|
|
+
|
|
+import compiler.aot.cli.jaotc.data.HelloWorldTwo;
|
|
+import java.io.File;
|
|
+import java.io.IOException;
|
|
+import java.nio.file.Files;
|
|
+import java.nio.file.Path;
|
|
+import java.nio.file.Paths;
|
|
+import java.nio.file.StandardOpenOption;
|
|
+import java.util.Arrays;
|
|
+import jdk.test.lib.Asserts;
|
|
+import jdk.test.lib.process.OutputAnalyzer;
|
|
+
|
|
+public class CompileModuleTest {
|
|
+ private static final String TESTED_CLASS_NAME = HelloWorldTwo.class.getName();
|
|
+ private static final String STRING_LENGTH = String.class.getName() + ".length";
|
|
+ private static final String COMPILE_COMMAND = "compileOnly " + STRING_LENGTH + ".*";
|
|
+ private static final Path COMPILE_COMMAND_FILE = Paths.get("stringLengthOnly.list");
|
|
+ private static final String[] EXPECTED = new String[]{
|
|
+ JaotcTestHelper.DEFAULT_LIBRARY_LOAD_MESSAGE,
|
|
+ STRING_LENGTH
|
|
+ };
|
|
+ private static final String[] UNEXPECTED = new String[]{
|
|
+ TESTED_CLASS_NAME
|
|
+ };
|
|
+
|
|
+ public static void main(String[] args) {
|
|
+ // compile only java.lang.String::length from java.base module to have reasonable compilation time
|
|
+ try {
|
|
+ Files.write(COMPILE_COMMAND_FILE, Arrays.asList(COMPILE_COMMAND),
|
|
+ StandardOpenOption.WRITE, StandardOpenOption.CREATE_NEW);
|
|
+ } catch (IOException e) {
|
|
+ throw new Error("TESTBUG: can't write list file " + e, e);
|
|
+ }
|
|
+ OutputAnalyzer oa = JaotcTestHelper.compileLibrary("--compile-commands",
|
|
+ COMPILE_COMMAND_FILE.toString(), "--module", "java.base");
|
|
+ oa.shouldHaveExitValue(0);
|
|
+ File compiledLibrary = new File(JaotcTestHelper.DEFAULT_LIB_PATH);
|
|
+ Asserts.assertTrue(compiledLibrary.exists(), "Compiled library file missing");
|
|
+ Asserts.assertGT(compiledLibrary.length(), 0L, "Unexpected compiled library size");
|
|
+ JaotcTestHelper.checkLibraryUsage(TESTED_CLASS_NAME, EXPECTED, UNEXPECTED);
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/cli/jaotc/IgnoreErrorsTest.java b/test/hotspot/jtreg/compiler/aot/cli/jaotc/IgnoreErrorsTest.java
|
|
new file mode 100644
|
|
index 000000000..ac0eb233d
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/cli/jaotc/IgnoreErrorsTest.java
|
|
@@ -0,0 +1,88 @@
|
|
+/*
|
|
+ * Copyright (c) 2018, 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
|
|
+ * 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
|
|
+ * @compile IllegalClass.jasm
|
|
+ * @run driver/timeout=360 compiler.aot.cli.jaotc.IgnoreErrorsTest
|
|
+ */
|
|
+
|
|
+package compiler.aot.cli.jaotc;
|
|
+
|
|
+import java.io.File;
|
|
+import java.io.IOException;
|
|
+import java.nio.file.Files;
|
|
+import java.nio.file.Path;
|
|
+import java.nio.file.Paths;
|
|
+import java.nio.file.StandardOpenOption;
|
|
+
|
|
+import jdk.test.lib.Asserts;
|
|
+import jdk.test.lib.process.OutputAnalyzer;
|
|
+
|
|
+public class IgnoreErrorsTest {
|
|
+ public static void main(String[] args) {
|
|
+ try {
|
|
+ Files.write(Paths.get("Empty.class"), new byte[] { }, StandardOpenOption.CREATE_NEW);
|
|
+ } catch (IOException e) {
|
|
+ throw new Error("can't create empty class file", e);
|
|
+ }
|
|
+ File compiledLibrary = new File(JaotcTestHelper.DEFAULT_LIB_PATH);
|
|
+ OutputAnalyzer oa;
|
|
+
|
|
+ System.out.println("Compiling empty class file w/o --ignore-errors");
|
|
+ oa = JaotcTestHelper.compileLibrary(
|
|
+ "--class-name", "Empty",
|
|
+ "--class-name", "java.lang.Object");
|
|
+ oa.shouldNotHaveExitValue(0);
|
|
+ Asserts.assertTrue(!compiledLibrary.exists(), "Compiled library file exists");
|
|
+
|
|
+ System.out.println("Compiling empty class file w/ --ignore-errors");
|
|
+ oa = JaotcTestHelper.compileLibrary(
|
|
+ "--ignore-errors",
|
|
+ "--class-name", "Empty",
|
|
+ "--class-name", "java.lang.Object");
|
|
+ oa.shouldHaveExitValue(0);
|
|
+ Asserts.assertTrue(compiledLibrary.exists(), "Compiled library file is missed");
|
|
+ JaotcTestHelper.checkLibraryUsage("-version");
|
|
+ compiledLibrary.delete();
|
|
+
|
|
+ System.out.println("Compiling illegal class file w/o --ignore-errors");
|
|
+ oa = JaotcTestHelper.compileLibrary(
|
|
+ "--class-name", "IllegalClass",
|
|
+ "--class-name", "java.lang.Object");
|
|
+ oa.shouldNotHaveExitValue(0);
|
|
+ Asserts.assertTrue(!compiledLibrary.exists(), "Compiled library file exists");
|
|
+
|
|
+ System.out.println("Compiling illegal class file w/ --ignore-errors");
|
|
+ oa = JaotcTestHelper.compileLibrary(
|
|
+ "--ignore-errors",
|
|
+ "--class-name", "IllegalClass",
|
|
+ "--class-name", "java.lang.Object");
|
|
+ oa.shouldHaveExitValue(0);
|
|
+ Asserts.assertTrue(compiledLibrary.exists(), "Compiled library file is missed");
|
|
+ JaotcTestHelper.checkLibraryUsage("-version");
|
|
+ compiledLibrary.delete();
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/cli/jaotc/IllegalClass.jasm b/test/hotspot/jtreg/compiler/aot/cli/jaotc/IllegalClass.jasm
|
|
new file mode 100644
|
|
index 000000000..1aa0057df
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/cli/jaotc/IllegalClass.jasm
|
|
@@ -0,0 +1,27 @@
|
|
+/*
|
|
+ * Copyright (c) 2018, 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
|
|
+ * 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.
|
|
+ */
|
|
+
|
|
+super public class IllegalClass
|
|
+ extends java/lang/String
|
|
+ version 46:0
|
|
+{ }
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/cli/jaotc/JaotcTestHelper.java b/test/hotspot/jtreg/compiler/aot/cli/jaotc/JaotcTestHelper.java
|
|
new file mode 100644
|
|
index 000000000..ee85d3278
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/cli/jaotc/JaotcTestHelper.java
|
|
@@ -0,0 +1,93 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 compiler.aot.cli.jaotc;
|
|
+
|
|
+import compiler.aot.AotCompiler;
|
|
+
|
|
+import java.io.File;
|
|
+import java.io.IOException;
|
|
+
|
|
+import jdk.test.lib.process.ExitCode;
|
|
+import jdk.test.lib.Platform;
|
|
+import jdk.test.lib.JDKToolLauncher;
|
|
+import jdk.test.lib.Utils;
|
|
+import jdk.test.lib.cli.CommandLineOptionTest;
|
|
+import jdk.test.lib.process.OutputAnalyzer;
|
|
+import jdk.test.lib.process.ProcessTools;
|
|
+
|
|
+public class JaotcTestHelper {
|
|
+ public static final String DEFAULT_LIB_PATH = "./unnamed." + Platform.sharedLibraryExt();
|
|
+ public static final String DEFAULT_LIBRARY_LOAD_MESSAGE = "loaded " + DEFAULT_LIB_PATH
|
|
+ + " aot library";
|
|
+ private static final String UNLOCK_EXPERIMENTAL_VM_OPTIONS = "-XX:+UnlockExperimentalVMOptions";
|
|
+ private static final String ENABLE_AOT = "-XX:+UseAOT";
|
|
+ private static final String AOT_LIBRARY = "-XX:AOTLibrary=" + DEFAULT_LIB_PATH;
|
|
+ private static final String PRINT_AOT = "-XX:+PrintAOT";
|
|
+
|
|
+ public static OutputAnalyzer compileLibrary(String... args) {
|
|
+ JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jaotc");
|
|
+ for (String vmOpt : Utils.getTestJavaOpts()) {
|
|
+ launcher.addVMArg(vmOpt);
|
|
+ }
|
|
+ launcher.addToolArg("--compile-with-assertions");
|
|
+ for (String arg : args) {
|
|
+ launcher.addToolArg(arg);
|
|
+ }
|
|
+ String linker = AotCompiler.resolveLinker();
|
|
+ if (linker != null) {
|
|
+ launcher.addToolArg("--linker-path");
|
|
+ launcher.addToolArg(linker);
|
|
+ }
|
|
+ String[] cmd = launcher.getCommand();
|
|
+ try {
|
|
+ return ProcessTools.executeCommand(cmd);
|
|
+ } catch (Throwable e) {
|
|
+ throw new Error("Can't start test process: " + e, e);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public static void checkLibraryUsage(String classToRun) {
|
|
+ checkLibraryUsage(classToRun, new String[]{DEFAULT_LIBRARY_LOAD_MESSAGE}, null);
|
|
+ }
|
|
+
|
|
+ public static void checkLibraryUsage(String classToRun, String[] expectedOutput,
|
|
+ String[] unexpectedOutput) {
|
|
+ try {
|
|
+ CommandLineOptionTest.verifyJVMStartup(expectedOutput, unexpectedOutput,
|
|
+ "Unexpected exit code", "Unexpected output", ExitCode.OK,
|
|
+ /* addTestVMOpts */ true, UNLOCK_EXPERIMENTAL_VM_OPTIONS,
|
|
+ ENABLE_AOT, AOT_LIBRARY, PRINT_AOT, classToRun);
|
|
+ } catch (Throwable t) {
|
|
+ throw new Error("Library usage verification failed: " + t, t);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public static String getClassAotCompilationFilename(Class<?> classToCompile) {
|
|
+ return classToCompile.getName().replaceAll("\\.","/") + ".class";
|
|
+ }
|
|
+
|
|
+ public static String getClassAotCompilationName(Class<?> classToCompile) {
|
|
+ return classToCompile.getName();
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/cli/jaotc/ListOptionNotExistingTest.java b/test/hotspot/jtreg/compiler/aot/cli/jaotc/ListOptionNotExistingTest.java
|
|
new file mode 100644
|
|
index 000000000..0eb3e1916
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/cli/jaotc/ListOptionNotExistingTest.java
|
|
@@ -0,0 +1,54 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.aot.cli.jaotc.ListOptionNotExistingTest
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller compiler.aot.cli.jaotc.data.HelloWorldOne
|
|
+ * @run driver compiler.aot.cli.jaotc.ListOptionNotExistingTest
|
|
+ * @summary check jaotc can handle situation with missing --compile-commands file
|
|
+ */
|
|
+
|
|
+package compiler.aot.cli.jaotc;
|
|
+
|
|
+import compiler.aot.cli.jaotc.data.HelloWorldOne;
|
|
+import java.io.File;
|
|
+import jdk.test.lib.Asserts;
|
|
+import jdk.test.lib.process.OutputAnalyzer;
|
|
+
|
|
+public class ListOptionNotExistingTest {
|
|
+ private static final String COMPILE_ITEM
|
|
+ = JaotcTestHelper.getClassAotCompilationName(HelloWorldOne.class);
|
|
+
|
|
+ public static void main(String[] args) {
|
|
+ OutputAnalyzer oa = JaotcTestHelper.compileLibrary("--compile-commands", "./notExisting.list",
|
|
+ "--class-name", COMPILE_ITEM);
|
|
+ int exitCode = oa.getExitValue();
|
|
+ Asserts.assertNE(exitCode, 0, "Unexpected compilation exit code");
|
|
+ File compiledLibrary = new File(JaotcTestHelper.DEFAULT_LIB_PATH);
|
|
+ Asserts.assertFalse(compiledLibrary.exists(), "Compiler library unexpectedly exists");
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/cli/jaotc/ListOptionTest.java b/test/hotspot/jtreg/compiler/aot/cli/jaotc/ListOptionTest.java
|
|
new file mode 100644
|
|
index 000000000..8bf2fcf98
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/cli/jaotc/ListOptionTest.java
|
|
@@ -0,0 +1,76 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.aot.cli.jaotc.ListOptionTest
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller compiler.aot.cli.jaotc.data.HelloWorldOne
|
|
+ * @run driver compiler.aot.cli.jaotc.ListOptionTest
|
|
+ * @summary check jaotc can use --compile-commands option successfully and respective compileCommand is applied
|
|
+ */
|
|
+
|
|
+package compiler.aot.cli.jaotc;
|
|
+
|
|
+import compiler.aot.cli.jaotc.data.HelloWorldOne;
|
|
+import java.io.File;
|
|
+import java.io.IOException;
|
|
+import java.nio.file.Files;
|
|
+import java.nio.file.Path;
|
|
+import java.nio.file.Paths;
|
|
+import java.nio.file.StandardOpenOption;
|
|
+import java.util.Arrays;
|
|
+import jdk.test.lib.Asserts;
|
|
+import jdk.test.lib.process.OutputAnalyzer;
|
|
+
|
|
+public class ListOptionTest {
|
|
+ private static final String TESTED_CLASS_NAME = HelloWorldOne.class.getName();
|
|
+ private static final String HELLOWORLDONE_MAIN = TESTED_CLASS_NAME + ".main";
|
|
+ private static final String COMPILE_COMMAND = "compileOnly " + HELLOWORLDONE_MAIN + ".*";
|
|
+ private static final Path COMPILE_COMMAND_FILE = Paths.get("helloWorldMainMethodOnly.list");
|
|
+ private static final String[] EXPECTED = new String[]{
|
|
+ JaotcTestHelper.DEFAULT_LIBRARY_LOAD_MESSAGE,
|
|
+ TESTED_CLASS_NAME + ".main"
|
|
+ };
|
|
+ private static final String[] UNEXPECTED = new String[]{
|
|
+ TESTED_CLASS_NAME + ".<init>"
|
|
+ };
|
|
+
|
|
+ public static void main(String[] args) {
|
|
+ try {
|
|
+ Files.write(COMPILE_COMMAND_FILE, Arrays.asList(COMPILE_COMMAND),
|
|
+ StandardOpenOption.WRITE, StandardOpenOption.CREATE_NEW);
|
|
+ } catch (IOException e) {
|
|
+ throw new Error("TESTBUG: can't write list file " + e, e);
|
|
+ }
|
|
+ OutputAnalyzer oa = JaotcTestHelper.compileLibrary("--compile-commands", COMPILE_COMMAND_FILE.toString(),
|
|
+ "--class-name", JaotcTestHelper.getClassAotCompilationName(HelloWorldOne.class));
|
|
+ oa.shouldHaveExitValue(0);
|
|
+ File compiledLibrary = new File(JaotcTestHelper.DEFAULT_LIB_PATH);
|
|
+ Asserts.assertTrue(compiledLibrary.exists(), "Compiled library file missing");
|
|
+ Asserts.assertGT(compiledLibrary.length(), 0L, "Unexpected compiled library size");
|
|
+ JaotcTestHelper.checkLibraryUsage(TESTED_CLASS_NAME, EXPECTED, UNEXPECTED);
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/cli/jaotc/ListOptionWrongFileTest.java b/test/hotspot/jtreg/compiler/aot/cli/jaotc/ListOptionWrongFileTest.java
|
|
new file mode 100644
|
|
index 000000000..0f1df8e12
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/cli/jaotc/ListOptionWrongFileTest.java
|
|
@@ -0,0 +1,63 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.aot.cli.jaotc.ListOptionWrongFileTest
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller compiler.aot.cli.jaotc.data.HelloWorldOne
|
|
+ * @run driver compiler.aot.cli.jaotc.ListOptionWrongFileTest
|
|
+ * @summary check jaotc can handle incorrect --compile-commands file
|
|
+ */
|
|
+
|
|
+package compiler.aot.cli.jaotc;
|
|
+
|
|
+import compiler.aot.cli.jaotc.data.HelloWorldOne;
|
|
+import java.io.File;
|
|
+import jdk.test.lib.Asserts;
|
|
+import jdk.test.lib.process.OutputAnalyzer;
|
|
+
|
|
+public class ListOptionWrongFileTest {
|
|
+ private static final String TESTED_CLASS_NAME = HelloWorldOne.class.getName();
|
|
+ private static final String[] EXPECTED = new String[]{
|
|
+ JaotcTestHelper.DEFAULT_LIBRARY_LOAD_MESSAGE,
|
|
+ TESTED_CLASS_NAME
|
|
+ };
|
|
+
|
|
+ private static final String COMPILE_ITEM
|
|
+ = JaotcTestHelper.getClassAotCompilationName(HelloWorldOne.class);
|
|
+
|
|
+ private static final String COMPILE_FILE
|
|
+ = JaotcTestHelper.getClassAotCompilationFilename(HelloWorldOne.class);
|
|
+
|
|
+ public static void main(String[] args) {
|
|
+ // expecting wrong file to be read but no compilation directive recognized, so, all compiled
|
|
+ OutputAnalyzer oa = JaotcTestHelper.compileLibrary("--compile-commands", COMPILE_FILE, "--class-name", COMPILE_ITEM);
|
|
+ oa.shouldHaveExitValue(0);
|
|
+ File compiledLibrary = new File(JaotcTestHelper.DEFAULT_LIB_PATH);
|
|
+ Asserts.assertTrue(compiledLibrary.exists(), "Expected compiler library to exist");
|
|
+ JaotcTestHelper.checkLibraryUsage(HelloWorldOne.class.getName(), EXPECTED, null);
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/cli/jaotc/data/HelloWorldOne.java b/test/hotspot/jtreg/compiler/aot/cli/jaotc/data/HelloWorldOne.java
|
|
new file mode 100644
|
|
index 000000000..8a1d727b1
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/cli/jaotc/data/HelloWorldOne.java
|
|
@@ -0,0 +1,32 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 compiler.aot.cli.jaotc.data;
|
|
+
|
|
+public class HelloWorldOne {
|
|
+ public static final String MESSAGE = "HelloWorld1";
|
|
+
|
|
+ public static void main(String args[]) {
|
|
+ System.out.println(MESSAGE);
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/cli/jaotc/data/HelloWorldTwo.java b/test/hotspot/jtreg/compiler/aot/cli/jaotc/data/HelloWorldTwo.java
|
|
new file mode 100644
|
|
index 000000000..dce2b2902
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/cli/jaotc/data/HelloWorldTwo.java
|
|
@@ -0,0 +1,33 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 compiler.aot.cli.jaotc.data;
|
|
+
|
|
+public class HelloWorldTwo {
|
|
+ public static final String MESSAGE = "HelloWorld2";
|
|
+
|
|
+ public static void main(String args[]) {
|
|
+ System.out.println(MESSAGE);
|
|
+ System.out.println("Message length = " + MESSAGE.length());
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/fingerprint/CDSDumper.java b/test/hotspot/jtreg/compiler/aot/fingerprint/CDSDumper.java
|
|
new file mode 100644
|
|
index 000000000..af1700419
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/fingerprint/CDSDumper.java
|
|
@@ -0,0 +1,69 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 compiler.aot.fingerprint;
|
|
+
|
|
+import java.io.File;
|
|
+import java.io.FileOutputStream;
|
|
+import java.io.PrintStream;
|
|
+
|
|
+import jdk.test.lib.process.OutputAnalyzer;
|
|
+import jdk.test.lib.process.ProcessTools;
|
|
+
|
|
+// Usage:
|
|
+// java CDSDumper <classpath> <classlist> <archive> <heapsize> <class1> <class2> ...
|
|
+public class CDSDumper {
|
|
+ public static void main(String[] args) throws Exception {
|
|
+ String classpath = args[0];
|
|
+ String classlist = args[1];
|
|
+ String archive = args[2];
|
|
+ String heapsize = args[3];
|
|
+
|
|
+ // Prepare the classlist
|
|
+ FileOutputStream fos = new FileOutputStream(classlist);
|
|
+ PrintStream ps = new PrintStream(fos);
|
|
+
|
|
+ for (int i=4; i<args.length; i++) {
|
|
+ ps.println(args[i].replace('.', '/'));
|
|
+ }
|
|
+ ps.close();
|
|
+ fos.close();
|
|
+
|
|
+ // Dump the archive
|
|
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
|
|
+ heapsize,
|
|
+ "-XX:+IgnoreUnrecognizedVMOptions",
|
|
+ "-cp", classpath,
|
|
+ "-XX:ExtraSharedClassListFile=" + classlist,
|
|
+ "-XX:SharedArchiveFile=" + archive,
|
|
+ "-Xshare:dump",
|
|
+ "-Xlog:gc+heap+coops",
|
|
+ "-Xlog:cds");
|
|
+
|
|
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
|
+ System.out.println("[stdout = " + output.getStdout() + "]");
|
|
+ System.out.println("[stderr = " + output.getStderr() + "]");
|
|
+ output.shouldContain("Loading classes to share");
|
|
+ output.shouldHaveExitValue(0);
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/fingerprint/CDSRunner.java b/test/hotspot/jtreg/compiler/aot/fingerprint/CDSRunner.java
|
|
new file mode 100644
|
|
index 000000000..3b45cff8d
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/fingerprint/CDSRunner.java
|
|
@@ -0,0 +1,42 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 compiler.aot.fingerprint;
|
|
+
|
|
+import jdk.test.lib.process.OutputAnalyzer;
|
|
+import jdk.test.lib.process.ProcessTools;
|
|
+
|
|
+// Usage:
|
|
+// java CDSRunner <vmargs> <class> <args> ...
|
|
+public class CDSRunner {
|
|
+ public static void main(String[] args) throws Exception {
|
|
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(args);
|
|
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
|
+
|
|
+ System.out.println("[stdout = " + output.getStdout() + "]");
|
|
+ System.out.println("[stderr = " + output.getStderr() + "]");
|
|
+
|
|
+ output.shouldContain("PASSED");
|
|
+ output.shouldHaveExitValue(0);
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/fingerprint/SelfChanged.java b/test/hotspot/jtreg/compiler/aot/fingerprint/SelfChanged.java
|
|
new file mode 100644
|
|
index 000000000..bde477836
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/fingerprint/SelfChanged.java
|
|
@@ -0,0 +1,132 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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
|
|
+ * @summary AOT methods should be swept if a super class has changed.
|
|
+ * @library /test/lib /
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * java.management
|
|
+ * @requires vm.aot
|
|
+ * @build compiler.aot.fingerprint.SelfChanged
|
|
+ * compiler.aot.AotCompiler
|
|
+ *
|
|
+ * @run main
|
|
+ * compiler.aot.fingerprint.SelfChanged WRITE-UNMODIFIED-CLASS
|
|
+ * @run driver compiler.aot.AotCompiler -libname libSelfChanged.so
|
|
+ * -class compiler.aot.fingerprint.Blah
|
|
+ *
|
|
+ * @run main/othervm
|
|
+ * compiler.aot.fingerprint.SelfChanged TEST-UNMODIFIED
|
|
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseAOT -XX:+PrintAOT
|
|
+ * -XX:AOTLibrary=./libSelfChanged.so
|
|
+ * -Xlog:aot+class+fingerprint=trace -Xlog:aot+class+load=trace
|
|
+ * compiler.aot.fingerprint.SelfChanged TEST-UNMODIFIED
|
|
+ *
|
|
+ * @run main
|
|
+ * compiler.aot.fingerprint.SelfChanged WRITE-MODIFIED-CLASS
|
|
+ * @run main
|
|
+ * compiler.aot.fingerprint.SelfChanged TEST-MODIFIED
|
|
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseAOT -XX:+PrintAOT
|
|
+ * -XX:AOTLibrary=./libSelfChanged.so
|
|
+ * -Xlog:aot+class+fingerprint=trace -Xlog:aot+class+load=trace
|
|
+ * compiler.aot.fingerprint.SelfChanged TEST-MODIFIED
|
|
+ */
|
|
+
|
|
+package compiler.aot.fingerprint;
|
|
+
|
|
+import jdk.test.lib.Asserts;
|
|
+import jdk.test.lib.compiler.InMemoryJavaCompiler;
|
|
+
|
|
+import java.io.*;
|
|
+
|
|
+class Blah {
|
|
+ volatile int z;
|
|
+ int getX() {
|
|
+ for (z = 0; z < 10000; z++) {
|
|
+ if (z % 7 == 1) {
|
|
+ z += 2;
|
|
+ }
|
|
+ }
|
|
+ return 0;
|
|
+ }
|
|
+}
|
|
+
|
|
+public class SelfChanged {
|
|
+ public static void main(String args[]) throws Throwable {
|
|
+ Blah f = new Blah();
|
|
+ System.out.println("f.getX = " + f.getX());
|
|
+ switch (args[0]) {
|
|
+ case "WRITE-UNMODIFIED-CLASS":
|
|
+ compileClass(false);
|
|
+ break;
|
|
+ case "WRITE-MODIFIED-CLASS":
|
|
+ compileClass(true);
|
|
+ break;
|
|
+ case "TEST-UNMODIFIED":
|
|
+ Asserts.assertTrue(f.getX() == 0, "getX from unmodified Blah class should return 0");
|
|
+ break;
|
|
+ case "TEST-MODIFIED":
|
|
+ Asserts.assertTrue(f.getX() == 1, "getX from modified Blah class should return 1");
|
|
+ break;
|
|
+ default:
|
|
+ throw new RuntimeException("unexpected option: " + args[0]);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ static void compileClass(boolean isModified) throws Throwable {
|
|
+ String src =
|
|
+ "package compiler.aot.fingerprint;"
|
|
+ + "public class Blah {"
|
|
+ + " volatile int z;"
|
|
+ + " int getX() {"
|
|
+ + " for (z = 0; z < 10000; z++) {"
|
|
+ + " if (z % 7 == 1) {"
|
|
+ + " z += 2;"
|
|
+ + " }"
|
|
+ + " }"
|
|
+ + " return " + ((isModified) ? "1" : "0") + ";"
|
|
+ + " }"
|
|
+ + " int getY() {return 255;}"
|
|
+
|
|
+ // The following is for the SelfChangedCDS.java test case. We always load an unmodified
|
|
+ // version of Blah from the CDS archive. However, we would load an AOT library that
|
|
+ // was compiled using a modified version of Blah. The getX method in this AOT library should
|
|
+ // not be used.
|
|
+
|
|
+ + " public static void main(String args[]) {"
|
|
+ + " Blah b = new Blah();"
|
|
+ + " int n = b.getX();"
|
|
+ + " if (n != 0) {"
|
|
+ + " throw new RuntimeException(args[0] + \" : \" + n);"
|
|
+ + " }"
|
|
+ + " System.out.println(\"PASSED\");"
|
|
+ + " }"
|
|
+ + "}";
|
|
+
|
|
+ String filename = System.getProperty("test.classes") + "/compiler/aot/fingerprint/Blah.class";
|
|
+ FileOutputStream fos = new FileOutputStream(filename);
|
|
+ fos.write(InMemoryJavaCompiler.compile("compiler.aot.fingerprint.Blah", src));
|
|
+ fos.close();
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/fingerprint/SelfChangedCDS.java b/test/hotspot/jtreg/compiler/aot/fingerprint/SelfChangedCDS.java
|
|
new file mode 100644
|
|
index 000000000..7463ab0c9
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/fingerprint/SelfChangedCDS.java
|
|
@@ -0,0 +1,90 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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
|
|
+ * @summary AOT methods should be swept if a super class has changed (with CDS).
|
|
+ * @library /test/lib /
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * java.management
|
|
+ * @requires vm.aot & vm.cds
|
|
+ * @build compiler.aot.fingerprint.SelfChanged
|
|
+ * jdk.test.whitebox.WhiteBox
|
|
+ *
|
|
+ * @run driver compiler.aot.fingerprint.SelfChanged WRITE-UNMODIFIED-CLASS
|
|
+ * @run driver compiler.aot.AotCompiler -libname libSelfChanged.so
|
|
+ * -class compiler.aot.fingerprint.Blah
|
|
+ *
|
|
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar SelfChangedCDS.jar compiler.aot.fingerprint.Blah
|
|
+ * @run driver compiler.aot.fingerprint.CDSDumper SelfChangedCDS.jar SelfChangedCDS.classlist SelfChangedCDS.jsa -showversion
|
|
+ * compiler.aot.fingerprint.Blah
|
|
+ *
|
|
+ * @run driver compiler.aot.fingerprint.CDSRunner -cp SelfChangedCDS.jar
|
|
+ * compiler.aot.fingerprint.Blah TEST-UNMODIFIED
|
|
+ * @run driver compiler.aot.fingerprint.CDSRunner -cp SelfChangedCDS.jar
|
|
+ * -XX:+UnlockExperimentalVMOptions -XX:+UseAOT -XX:+PrintAOT
|
|
+ * -XX:AOTLibrary=./libSelfChanged.so
|
|
+ * -XX:SharedArchiveFile=SelfChangedCDS.jsa
|
|
+ * -XX:+IgnoreUnrecognizedVMOptions
|
|
+ * -Xshare:auto -showversion
|
|
+ * -Xlog:cds -Xlog:gc+heap+coops
|
|
+ * -Xlog:aot+class+fingerprint=trace -Xlog:aot+class+load=trace
|
|
+ * compiler.aot.fingerprint.Blah TEST-UNMODIFIED
|
|
+ *
|
|
+ * @run driver
|
|
+ * compiler.aot.fingerprint.SelfChanged WRITE-MODIFIED-CLASS
|
|
+ * @run driver compiler.aot.AotCompiler -libname libSelfChanged.so
|
|
+ * -class compiler.aot.fingerprint.Blah
|
|
+ *
|
|
+ * @run driver compiler.aot.fingerprint.CDSRunner -cp SelfChangedCDS.jar
|
|
+ * compiler.aot.fingerprint.Blah TEST-MODIFIED
|
|
+ * @run driver compiler.aot.fingerprint.CDSRunner -cp SelfChangedCDS.jar
|
|
+ * -XX:+UnlockExperimentalVMOptions -XX:+UseAOT -XX:+PrintAOT
|
|
+ * -XX:AOTLibrary=./libSelfChanged.so
|
|
+ * -XX:SharedArchiveFile=SelfChangedCDS.jsa
|
|
+ * -XX:+IgnoreUnrecognizedVMOptions
|
|
+ * -Xshare:auto -showversion
|
|
+ * -Xlog:cds -Xlog:gc+heap+coops
|
|
+ * -Xlog:aot+class+fingerprint=trace -Xlog:aot+class+load=trace
|
|
+ * compiler.aot.fingerprint.Blah TEST-MODIFIED
|
|
+ *
|
|
+ *
|
|
+ * @run driver compiler.aot.AotCompiler -libname libSelfChanged.so
|
|
+ * -class compiler.aot.fingerprint.Blah
|
|
+ * -extraopt -Xmx512m
|
|
+ *
|
|
+ * @run driver compiler.aot.fingerprint.CDSDumper SelfChangedCDS.jar SelfChangedCDS.classlist SelfChangedCDS.jsa -Xmx512m
|
|
+ * compiler.aot.fingerprint.Blah
|
|
+ *
|
|
+ * @run driver compiler.aot.fingerprint.CDSRunner -Xmx512m -cp SelfChangedCDS.jar
|
|
+ * compiler.aot.fingerprint.Blah TEST-UNMODIFIED
|
|
+ * @run driver compiler.aot.fingerprint.CDSRunner -Xmx512m -cp SelfChangedCDS.jar
|
|
+ * -XX:+UnlockExperimentalVMOptions -XX:+UseAOT -XX:+PrintAOT
|
|
+ * -XX:AOTLibrary=./libSelfChanged.so
|
|
+ * -XX:SharedArchiveFile=SelfChangedCDS.jsa
|
|
+ * -XX:+IgnoreUnrecognizedVMOptions
|
|
+ * -Xshare:auto -showversion
|
|
+ * -Xlog:cds -Xlog:gc+heap+coops
|
|
+ * -Xlog:aot+class+fingerprint=trace -Xlog:aot+class+load=trace
|
|
+ * compiler.aot.fingerprint.Blah TEST-UNMODIFIED
|
|
+ */
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/fingerprint/SuperChanged.java b/test/hotspot/jtreg/compiler/aot/fingerprint/SuperChanged.java
|
|
new file mode 100644
|
|
index 000000000..fa4bd84e7
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/fingerprint/SuperChanged.java
|
|
@@ -0,0 +1,113 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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
|
|
+ * @summary AOT methods should be swept if a super class has changed.
|
|
+ * @library /test/lib /
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * java.management
|
|
+ * @requires vm.aot
|
|
+ * @build compiler.aot.fingerprint.SuperChanged
|
|
+ * compiler.aot.AotCompiler
|
|
+ *
|
|
+ * @run main
|
|
+ * compiler.aot.fingerprint.SuperChanged WRITE-UNMODIFIED-CLASS
|
|
+ * @run driver compiler.aot.AotCompiler -libname libSuperChanged.so
|
|
+ * -class compiler.aot.fingerprint.Foo
|
|
+ *
|
|
+ * @run main
|
|
+ * compiler.aot.fingerprint.SuperChanged TEST-UNMODIFIED
|
|
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseAOT -XX:+PrintAOT
|
|
+ * -XX:AOTLibrary=./libSuperChanged.so
|
|
+ * -Xlog:aot+class+fingerprint=trace -Xlog:aot+class+load=trace
|
|
+ * compiler.aot.fingerprint.SuperChanged TEST-UNMODIFIED
|
|
+ *
|
|
+ * @run main
|
|
+ * compiler.aot.fingerprint.SuperChanged WRITE-MODIFIED-CLASS
|
|
+ * @run main
|
|
+ * compiler.aot.fingerprint.SuperChanged TEST-MODIFIED
|
|
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseAOT -XX:+PrintAOT
|
|
+ * -XX:AOTLibrary=./libSuperChanged.so
|
|
+ * -Xlog:aot+class+fingerprint=trace -Xlog:aot+class+load=trace
|
|
+ * compiler.aot.fingerprint.SuperChanged TEST-MODIFIED
|
|
+ */
|
|
+
|
|
+package compiler.aot.fingerprint;
|
|
+
|
|
+import jdk.test.lib.Asserts;
|
|
+import jdk.test.lib.compiler.InMemoryJavaCompiler;
|
|
+
|
|
+import java.io.*;
|
|
+
|
|
+class Bar {
|
|
+ volatile int x = 0;
|
|
+ volatile int y = 1;
|
|
+}
|
|
+
|
|
+class Foo extends Bar {
|
|
+
|
|
+ volatile int z;
|
|
+ int getX() {
|
|
+ for (z = 0; z < 10000; z++) {
|
|
+ if (z % 7 == 1) {
|
|
+ z += 2;
|
|
+ }
|
|
+ }
|
|
+ return x;
|
|
+ }
|
|
+}
|
|
+
|
|
+public class SuperChanged {
|
|
+ public static void main(String args[]) throws Throwable {
|
|
+ Foo f = new Foo();
|
|
+ System.out.println("f.getX = " + f.getX());
|
|
+ switch (args[0]) {
|
|
+ case "WRITE-UNMODIFIED-CLASS":
|
|
+ compileClass(false);
|
|
+ break;
|
|
+ case "WRITE-MODIFIED-CLASS":
|
|
+ compileClass(true);
|
|
+ break;
|
|
+ case "TEST-UNMODIFIED":
|
|
+ Asserts.assertTrue(f.getX() == 0, "getX from unmodified Foo class should return 0");
|
|
+ break;
|
|
+ case "TEST-MODIFIED":
|
|
+ Asserts.assertTrue(f.getX() == 1, "getX from modified Foo class should return 1");
|
|
+ break;
|
|
+ default:
|
|
+ throw new RuntimeException("unexpected option: " + args[0]);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ static void compileClass(boolean isModified) throws Throwable {
|
|
+ String class_src_0 = "package compiler.aot.fingerprint; class Bar {volatile int x = 0; volatile int y = 1;}";
|
|
+ String class_src_1 = "package compiler.aot.fingerprint; class Bar {volatile int y = 0; volatile int x = 1;}";
|
|
+ String src = (isModified) ? class_src_1 : class_src_0;
|
|
+
|
|
+ String filename = System.getProperty("test.classes") + "/compiler/aot/fingerprint/Bar.class";
|
|
+ FileOutputStream fos = new FileOutputStream(filename);
|
|
+ fos.write(InMemoryJavaCompiler.compile("compiler.aot.fingerprint.Bar", src));
|
|
+ fos.close();
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/NativeOrderOutputStreamTest.java b/test/hotspot/jtreg/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/NativeOrderOutputStreamTest.java
|
|
new file mode 100644
|
|
index 000000000..9304a8e42
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/NativeOrderOutputStreamTest.java
|
|
@@ -0,0 +1,131 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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
|
|
+ * @modules jdk.aot/jdk.tools.jaotc.utils
|
|
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.tools.jaotc.test.NativeOrderOutputStreamTest
|
|
+ */
|
|
+
|
|
+package jdk.tools.jaotc.test;
|
|
+
|
|
+import jdk.tools.jaotc.utils.NativeOrderOutputStream;
|
|
+import org.junit.Assert;
|
|
+import org.junit.Before;
|
|
+import org.junit.Test;
|
|
+
|
|
+import java.nio.ByteBuffer;
|
|
+import java.nio.ByteOrder;
|
|
+
|
|
+public class NativeOrderOutputStreamTest {
|
|
+
|
|
+ private NativeOrderOutputStream target;
|
|
+
|
|
+ @Before
|
|
+ public void setup() {
|
|
+ target = new NativeOrderOutputStream();
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void shouldAdd4BytesForInt() {
|
|
+ target.putInt(5);
|
|
+ Assert.assertEquals(4, target.position());
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void shouldAdd8BytesForLong() {
|
|
+ target.putLong(8);
|
|
+ Assert.assertEquals(8, target.position());
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void shouldHaveCorrectSizeBeforePatch() {
|
|
+ target.patchableInt();
|
|
+ Assert.assertEquals(4, target.position());
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void shouldHaveCorrectSizeAfterPatch() {
|
|
+ NativeOrderOutputStream.PatchableInt patchableInt = target.patchableInt();
|
|
+ patchableInt.set(12);
|
|
+ Assert.assertEquals(4, target.position());
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void shouldSetCorrectValueInPatch() {
|
|
+ NativeOrderOutputStream.PatchableInt patchableInt = target.patchableInt();
|
|
+ patchableInt.set(42);
|
|
+ Assert.assertEquals(42, getInt(0));
|
|
+ }
|
|
+
|
|
+ private int getInt(int pos) {
|
|
+ ByteBuffer buffer = ByteBuffer.wrap(target.array());
|
|
+ buffer.order(ByteOrder.nativeOrder());
|
|
+ return buffer.getInt(pos);
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void shouldPutArrayCorrectly() {
|
|
+ target.put(new byte[]{42, 5, 43, 44});
|
|
+ Assert.assertEquals(4, target.position());
|
|
+ Assert.assertEquals(42, target.array()[0]);
|
|
+ Assert.assertEquals(4, target.position());
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void shouldOnlyPatchSlot() {
|
|
+ NativeOrderOutputStream.PatchableInt patchableInt = target.patchableInt();
|
|
+ target.putInt(7);
|
|
+ patchableInt.set(39);
|
|
+ Assert.assertEquals(39, getInt(0));
|
|
+ Assert.assertEquals(7, getInt(4));
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void shouldBeAbleToPatchAnywhere() {
|
|
+ target.putInt(19);
|
|
+ NativeOrderOutputStream.PatchableInt patchableInt = target.patchableInt();
|
|
+ patchableInt.set(242);
|
|
+
|
|
+ Assert.assertEquals(19, getInt(0));
|
|
+ Assert.assertEquals(242, getInt(4));
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void shouldHavePatchableAtRightOffset() {
|
|
+ target.putInt(27);
|
|
+ Assert.assertEquals(4, target.position());
|
|
+ NativeOrderOutputStream.PatchableInt patchableInt = target.patchableInt();
|
|
+ Assert.assertEquals(4, patchableInt.position());
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void shouldAlign() {
|
|
+ target.putInt(9);
|
|
+ target.align(16);
|
|
+ target.put(new byte[]{3});
|
|
+ target.align(8);
|
|
+ Assert.assertEquals(24, target.position());
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/ClassSearchTest.java b/test/hotspot/jtreg/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/ClassSearchTest.java
|
|
new file mode 100644
|
|
index 000000000..9a6de1a19
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/ClassSearchTest.java
|
|
@@ -0,0 +1,211 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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
|
|
+ * @modules jdk.aot/jdk.tools.jaotc
|
|
+ * jdk.aot/jdk.tools.jaotc.collect
|
|
+ * @run junit/othervm jdk.tools.jaotc.test.collect.ClassSearchTest
|
|
+ */
|
|
+
|
|
+package jdk.tools.jaotc.test.collect;
|
|
+
|
|
+
|
|
+import jdk.tools.jaotc.LoadedClass;
|
|
+import jdk.tools.jaotc.collect.*;
|
|
+import org.junit.Assert;
|
|
+import org.junit.Test;
|
|
+
|
|
+import java.util.ArrayList;
|
|
+import java.util.HashSet;
|
|
+import java.util.List;
|
|
+import java.util.Set;
|
|
+import java.util.function.BiConsumer;
|
|
+import java.util.function.BiFunction;
|
|
+
|
|
+public class ClassSearchTest {
|
|
+ @Test(expected = InternalError.class)
|
|
+ public void itShouldThrowExceptionIfNoProvidersAvailable() {
|
|
+ ClassSearch target = new ClassSearch();
|
|
+ SearchPath searchPath = new SearchPath();
|
|
+ target.search(list(new SearchFor("foo")), searchPath);
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldFindAProviderForEachEntry() {
|
|
+ Set<String> searched = new HashSet<>();
|
|
+ ClassSearch target = new ClassSearch();
|
|
+ target.addProvider(provider("", (name, searchPath) -> {
|
|
+ searched.add(name);
|
|
+ return new NoopSource();
|
|
+ }));
|
|
+ target.search(searchForList("foo", "bar", "foobar"), null);
|
|
+ Assert.assertEquals(hashset("foo", "bar", "foobar"), searched);
|
|
+ }
|
|
+
|
|
+ private SourceProvider provider(String supports, BiFunction<String, SearchPath, ClassSource> fn) {
|
|
+ return new SourceProvider() {
|
|
+ @Override
|
|
+ public ClassSource findSource(String name, SearchPath searchPath) {
|
|
+ return fn.apply(name, searchPath);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean supports(String type) {
|
|
+ return supports.equals(type);
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldOnlySearchSupportedProvidersForKnownType() {
|
|
+ Set<String> visited = new HashSet<>();
|
|
+ ClassSearch target = new ClassSearch();
|
|
+
|
|
+ target.addProvider(provider("jar", (name, searchPath) -> {
|
|
+ visited.add("jar");
|
|
+ return null;
|
|
+ }));
|
|
+
|
|
+ target.addProvider(provider("dir", (name, searchPath) -> {
|
|
+ visited.add("dir");
|
|
+ return null;
|
|
+ }));
|
|
+
|
|
+ try {
|
|
+ target.search(list(new SearchFor("some", "dir")), null);
|
|
+ } catch (InternalError e) {
|
|
+ // throws because no provider gives a source
|
|
+ }
|
|
+
|
|
+ Assert.assertEquals(hashset("dir"), visited);
|
|
+ }
|
|
+
|
|
+ @Test(expected = InternalError.class)
|
|
+ public void itShouldThrowErrorIfMultipleSourcesAreAvailable() {
|
|
+ ClassSearch target = new ClassSearch();
|
|
+ target.addProvider(provider("", (name, searchPath) -> consumer -> Assert.fail()));
|
|
+ target.addProvider(provider("", (name, searchPath) -> consumer -> Assert.fail()));
|
|
+
|
|
+ target.search(searchForList("somethign"), null);
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldSearchAllProvidersForUnknownType() {
|
|
+ Set<String> visited = new HashSet<>();
|
|
+ ClassSearch target = new ClassSearch();
|
|
+ target.addProvider(provider("", (name, searchPath) -> {
|
|
+ visited.add("1");
|
|
+ return null;
|
|
+ }));
|
|
+ target.addProvider(provider("", (name, searchPath) -> {
|
|
+ visited.add("2");
|
|
+ return null;
|
|
+ }));
|
|
+
|
|
+ try {
|
|
+ target.search(searchForList("foo"), null);
|
|
+ } catch (InternalError e) {
|
|
+ // throws because no provider gives a source
|
|
+ }
|
|
+
|
|
+ Assert.assertEquals(hashset("1", "2"), visited);
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldTryToLoadSaidClassFromClassLoader() {
|
|
+ Set<String> loaded = new HashSet<>();
|
|
+
|
|
+ ClassSearch target = new ClassSearch();
|
|
+ target.addProvider(new SourceProvider() {
|
|
+ @Override
|
|
+ public boolean supports(String type) {
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public ClassSource findSource(String name, SearchPath searchPath) {
|
|
+ return new ClassSource() {
|
|
+ @Override
|
|
+ public void eachClass(BiConsumer<String, ClassLoader> consumer) {
|
|
+ consumer.accept("foo.Bar", new ClassLoader() {
|
|
+ @Override
|
|
+ public Class<?> loadClass(String name) throws ClassNotFoundException {
|
|
+ loaded.add(name);
|
|
+ return null;
|
|
+ }
|
|
+ });
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ });
|
|
+
|
|
+ java.util.List<LoadedClass> search = target.search(searchForList("/tmp/something"), null);
|
|
+ Assert.assertEquals(list(new LoadedClass("foo.Bar", null)), search);
|
|
+ }
|
|
+
|
|
+ @Test(expected = InternalError.class)
|
|
+ public void itShouldThrowInternalErrorWhenClassLoaderFails() {
|
|
+ ClassLoader classLoader = new ClassLoader() {
|
|
+ @Override
|
|
+ public Class<?> loadClass(String name1) throws ClassNotFoundException {
|
|
+ throw new ClassNotFoundException("failed to find " + name1);
|
|
+ }
|
|
+ };
|
|
+
|
|
+ ClassSearch target = new ClassSearch();
|
|
+ target.addProvider(provider("", (name, searchPath) -> consumer -> consumer.accept("foo.Bar", classLoader)));
|
|
+ target.search(searchForList("foobar"), null);
|
|
+ }
|
|
+
|
|
+ private List<SearchFor> searchForList(String... entries) {
|
|
+ List<SearchFor> list = new ArrayList<>();
|
|
+ for (String entry : entries) {
|
|
+ list.add(new SearchFor(entry));
|
|
+ }
|
|
+ return list;
|
|
+ }
|
|
+
|
|
+ private <T> List<T> list(T... entries) {
|
|
+ List<T> list = new ArrayList<T>();
|
|
+ for (T entry : entries) {
|
|
+ list.add(entry);
|
|
+ }
|
|
+ return list;
|
|
+ }
|
|
+
|
|
+ private <T> Set<T> hashset(T... entries) {
|
|
+ Set<T> set = new HashSet<T>();
|
|
+ for (T entry : entries) {
|
|
+ set.add(entry);
|
|
+ }
|
|
+ return set;
|
|
+ }
|
|
+
|
|
+ private static class NoopSource implements ClassSource {
|
|
+ @Override
|
|
+ public void eachClass(BiConsumer<String, ClassLoader> consumer) {
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/ClassSourceTest.java b/test/hotspot/jtreg/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/ClassSourceTest.java
|
|
new file mode 100644
|
|
index 000000000..a2cf4f542
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/ClassSourceTest.java
|
|
@@ -0,0 +1,64 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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
|
|
+ * @modules jdk.aot/jdk.tools.jaotc
|
|
+ * jdk.aot/jdk.tools.jaotc.collect
|
|
+ * @build jdk.tools.jaotc.test.collect.Utils
|
|
+ * @run junit/othervm jdk.tools.jaotc.test.collect.ClassSourceTest
|
|
+ */
|
|
+
|
|
+package jdk.tools.jaotc.test.collect;
|
|
+
|
|
+import org.junit.Assert;
|
|
+import org.junit.Test;
|
|
+
|
|
+import java.nio.file.Paths;
|
|
+
|
|
+import static jdk.tools.jaotc.collect.ClassSource.makeClassName;
|
|
+
|
|
+import static jdk.tools.jaotc.test.collect.Utils.getpath;
|
|
+
|
|
+public class ClassSourceTest {
|
|
+ @Test(expected=IllegalArgumentException.class)
|
|
+ public void itShouldThrowExceptionIfPathDoesntEndWithClass() {
|
|
+ makeClassName(Paths.get("Bar.clazz"));
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldReplaceSlashesWithDots() {
|
|
+ Assert.assertEquals("foo.Bar", makeClassName(getpath("foo/Bar.class")));
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldStripLeadingSlash() {
|
|
+ Assert.assertEquals("Hello", makeClassName(getpath("/Hello.class")));
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldReplaceMultipleDots() {
|
|
+ Assert.assertEquals("some.foo.bar.FooBar", makeClassName(getpath("/some/foo/bar/FooBar.class")));
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/FakeFileSupport.java b/test/hotspot/jtreg/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/FakeFileSupport.java
|
|
new file mode 100644
|
|
index 000000000..7784d0b46
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/FakeFileSupport.java
|
|
@@ -0,0 +1,112 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.test.collect;
|
|
+
|
|
+import java.net.MalformedURLException;
|
|
+import java.nio.file.Path;
|
|
+import java.util.HashSet;
|
|
+import java.util.Set;
|
|
+
|
|
+import jdk.tools.jaotc.collect.FileSupport;
|
|
+
|
|
+public class FakeFileSupport extends FileSupport {
|
|
+ private final Set<String> exists = new HashSet<>();
|
|
+ private final Set<String> directories = new HashSet<>();
|
|
+
|
|
+ private final Set<String> checkedExists = new HashSet<>();
|
|
+ private final Set<String> checkedDirectory = new HashSet<>();
|
|
+ private final Set<String> checkedJarFileSystemRoots = new HashSet<>();
|
|
+ private final Set<String> classloaderPaths = new HashSet<>();
|
|
+
|
|
+ private Path jarFileSystemRoot = null;
|
|
+ private final ClassLoader classLoader;
|
|
+
|
|
+ public FakeFileSupport(Set<String> existing, Set<String> directories) {
|
|
+ this.exists.addAll(existing);
|
|
+ this.directories.addAll(directories);
|
|
+
|
|
+ classLoader = new ClassLoader() {
|
|
+ @Override
|
|
+ public Class<?> loadClass(String name) throws ClassNotFoundException {
|
|
+ return null;
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+
|
|
+ public void setJarFileSystemRoot(Path path) {
|
|
+ jarFileSystemRoot = path;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean exists(Path path) {
|
|
+ checkedExists.add(path.toString());
|
|
+ return exists.contains(path.toString());
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isDirectory(Path path) {
|
|
+ checkedDirectory.add(path.toString());
|
|
+ return directories.contains(path.toString());
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public ClassLoader createClassLoader(Path path) throws MalformedURLException {
|
|
+ classloaderPaths.add(path.toString());
|
|
+ return classLoader;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public Path getJarFileSystemRoot(Path jarFile) {
|
|
+ checkedJarFileSystemRoots.add(jarFile.toString());
|
|
+ return jarFileSystemRoot;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isAbsolute(Path entry) {
|
|
+ return entry.toString().startsWith("/");
|
|
+ }
|
|
+
|
|
+ public void addExist(String name) {
|
|
+ exists.add(name);
|
|
+ }
|
|
+
|
|
+ public void addDirectory(String name) {
|
|
+ directories.add(name);
|
|
+ }
|
|
+
|
|
+ public Set<String> getCheckedExists() {
|
|
+ return checkedExists;
|
|
+ }
|
|
+
|
|
+ public Set<String> getCheckedDirectory() {
|
|
+ return checkedDirectory;
|
|
+ }
|
|
+
|
|
+ public Set<String> getCheckedJarFileSystemRoots() {
|
|
+ return checkedJarFileSystemRoots;
|
|
+ }
|
|
+
|
|
+ public Set<String> getClassloaderPaths() {
|
|
+ return classloaderPaths;
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/FakeSearchPath.java b/test/hotspot/jtreg/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/FakeSearchPath.java
|
|
new file mode 100644
|
|
index 000000000..93d50bc90
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/FakeSearchPath.java
|
|
@@ -0,0 +1,49 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.test.collect;
|
|
+
|
|
+import jdk.tools.jaotc.collect.SearchPath;
|
|
+
|
|
+import java.nio.file.FileSystem;
|
|
+import java.nio.file.Path;
|
|
+import java.nio.file.Paths;
|
|
+import java.util.Set;
|
|
+
|
|
+import static jdk.tools.jaotc.test.collect.Utils.set;
|
|
+
|
|
+public class FakeSearchPath extends SearchPath {
|
|
+ private Path path = null;
|
|
+ public Set<String> entries = set();
|
|
+
|
|
+ public FakeSearchPath(String name) {
|
|
+ if (name != null) {
|
|
+ path = Paths.get(name);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public Path find(FileSystem fileSystem, Path entry, String... defaults) {
|
|
+ entries.add(entry.toString());
|
|
+ return path;
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/SearchPathTest.java b/test/hotspot/jtreg/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/SearchPathTest.java
|
|
new file mode 100644
|
|
index 000000000..172b731ce
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/SearchPathTest.java
|
|
@@ -0,0 +1,118 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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
|
|
+ * @modules jdk.aot/jdk.tools.jaotc
|
|
+ * jdk.aot/jdk.tools.jaotc.collect
|
|
+ *
|
|
+ * @build jdk.tools.jaotc.test.collect.Utils
|
|
+ * @build jdk.tools.jaotc.test.collect.FakeFileSupport
|
|
+ * @run junit/othervm jdk.tools.jaotc.test.collect.SearchPathTest
|
|
+ */
|
|
+
|
|
+package jdk.tools.jaotc.test.collect;
|
|
+
|
|
+import org.junit.Before;
|
|
+import org.junit.Test;
|
|
+
|
|
+import java.nio.file.FileSystem;
|
|
+import java.nio.file.FileSystems;
|
|
+import java.nio.file.Path;
|
|
+import java.nio.file.Paths;
|
|
+
|
|
+import jdk.tools.jaotc.collect.*;
|
|
+
|
|
+import static jdk.tools.jaotc.test.collect.Utils.set;
|
|
+import static jdk.tools.jaotc.test.collect.Utils.mkpath;
|
|
+import static jdk.tools.jaotc.test.collect.Utils.mkpaths;
|
|
+import static org.junit.Assert.*;
|
|
+
|
|
+public class SearchPathTest {
|
|
+ private FakeFileSupport fileSupport;
|
|
+ private FileSystem fs;
|
|
+
|
|
+ @Before
|
|
+ public void setUp() throws Exception {
|
|
+ fs = FileSystems.getDefault();
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldUsePathIfPathIsAbsoluteAndExisting() {
|
|
+ fileSupport = new FakeFileSupport(mkpaths("/foo"), set());
|
|
+ SearchPath target = new SearchPath(fileSupport);
|
|
+ Path foo = Paths.get(mkpath("/foo"));
|
|
+ Path result = target.find(fs, foo);
|
|
+ assertSame(result, foo);
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldReturnNullIfPathIsAbsoluteAndNonExisting() {
|
|
+ fileSupport = new FakeFileSupport(set(), set());
|
|
+ SearchPath target = new SearchPath(fileSupport);
|
|
+ Path result = target.find(fs, Paths.get(mkpath("/bar")));
|
|
+ assertNull(result);
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldUseRelativeExisting() {
|
|
+ fileSupport = new FakeFileSupport(mkpaths("hello", "tmp/hello", "search/hello"), set());
|
|
+ SearchPath target = new SearchPath(fileSupport);
|
|
+ target.add("search");
|
|
+ Path hello = Paths.get("hello");
|
|
+ Path result = target.find(fs, hello, "tmp");
|
|
+ assertSame(result, hello);
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldSearchDefaultsBeforeSearchPaths() {
|
|
+ fileSupport = new FakeFileSupport(mkpaths("bar/foobar"), set());
|
|
+ SearchPath target = new SearchPath(fileSupport);
|
|
+ Path result = target.find(fs, Paths.get("foobar"), "default1", "bar");
|
|
+ assertEquals(mkpath("bar/foobar"), result.toString());
|
|
+ assertEquals(mkpaths("foobar", "default1/foobar", "bar/foobar"), fileSupport.getCheckedExists());
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldUseSearchPathsIfNotInDefaults() {
|
|
+ fileSupport = new FakeFileSupport(mkpaths("bar/tmp/foobar"), set());
|
|
+ SearchPath target = new SearchPath(fileSupport);
|
|
+ target.add("foo/tmp", "bar/tmp");
|
|
+
|
|
+ Path result = target.find(fs, Paths.get("foobar"), "foo", "bar");
|
|
+ assertEquals(mkpath("bar/tmp/foobar"), result.toString());
|
|
+ assertEquals(mkpaths("foobar", "foo/foobar", "bar/foobar", "bar/tmp/foobar", "foo/tmp/foobar"), fileSupport.getCheckedExists());
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldReturnNullIfNoExistingPathIsFound() {
|
|
+ fileSupport = new FakeFileSupport(set(), set());
|
|
+ SearchPath target = new SearchPath(fileSupport);
|
|
+ target.add("dir1", "dir2");
|
|
+
|
|
+ Path result = target.find(fs, Paths.get("entry"), "dir3", "dir4");
|
|
+ assertNull(result);
|
|
+ assertEquals(mkpaths("entry", "dir1/entry", "dir2/entry", "dir3/entry", "dir4/entry"), fileSupport.getCheckedExists());
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/Utils.java b/test/hotspot/jtreg/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/Utils.java
|
|
new file mode 100644
|
|
index 000000000..1ac63782e
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/Utils.java
|
|
@@ -0,0 +1,58 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.test.collect;
|
|
+
|
|
+import java.io.File;
|
|
+import java.nio.file.Path;
|
|
+import java.nio.file.Paths;
|
|
+import java.util.HashSet;
|
|
+import java.util.Set;
|
|
+
|
|
+public class Utils {
|
|
+ public static <T> Set<T> set(T... entries) {
|
|
+ Set<T> set = new HashSet<T>();
|
|
+ for (T entry : entries) {
|
|
+ set.add(entry);
|
|
+ }
|
|
+ return set;
|
|
+ }
|
|
+
|
|
+ public static String mkpath(String path) {
|
|
+ return getpath(path).toString();
|
|
+ }
|
|
+
|
|
+ public static Set<String> mkpaths(String... paths) {
|
|
+ Set<String> set = new HashSet<String>();
|
|
+ for (String entry : paths) {
|
|
+ set.add(mkpath(entry));
|
|
+ }
|
|
+ return set;
|
|
+ }
|
|
+
|
|
+ public static Path getpath(String path) {
|
|
+ if (path.startsWith("/") && System.getProperty("os.name").startsWith("Windows")) {
|
|
+ path = new File(path).getAbsolutePath();
|
|
+ }
|
|
+ return Paths.get(path);
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/directory/DirectorySourceProviderTest.java b/test/hotspot/jtreg/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/directory/DirectorySourceProviderTest.java
|
|
new file mode 100644
|
|
index 000000000..ed148be5e
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/directory/DirectorySourceProviderTest.java
|
|
@@ -0,0 +1,89 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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
|
|
+ * @modules jdk.aot/jdk.tools.jaotc
|
|
+ * jdk.aot/jdk.tools.jaotc.collect
|
|
+ * jdk.aot/jdk.tools.jaotc.collect.directory
|
|
+ * @compile ../Utils.java
|
|
+ * @compile ../FakeFileSupport.java
|
|
+ * @run junit/othervm jdk.tools.jaotc.test.collect.directory.DirectorySourceProviderTest
|
|
+ */
|
|
+
|
|
+package jdk.tools.jaotc.test.collect.directory;
|
|
+
|
|
+import jdk.tools.jaotc.collect.ClassSource;
|
|
+import jdk.tools.jaotc.collect.directory.DirectorySourceProvider;
|
|
+import jdk.tools.jaotc.test.collect.FakeFileSupport;
|
|
+import jdk.tools.jaotc.collect.FileSupport;
|
|
+import org.junit.Assert;
|
|
+import org.junit.Test;
|
|
+
|
|
+import java.net.MalformedURLException;
|
|
+import java.nio.file.Path;
|
|
+import java.util.Set;
|
|
+
|
|
+import static jdk.tools.jaotc.test.collect.Utils.set;
|
|
+
|
|
+public class DirectorySourceProviderTest {
|
|
+ @Test
|
|
+ public void itShouldReturnNullForNonExistantPath() {
|
|
+ DirectorySourceProvider target = new DirectorySourceProvider(new FakeFileSupport(set(), set()));
|
|
+ ClassSource result = target.findSource("hello", null);
|
|
+ Assert.assertNull(result);
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldReturnNullForNonDirectory() {
|
|
+ DirectorySourceProvider target = new DirectorySourceProvider(new FakeFileSupport(set("foobar"), set()));
|
|
+ ClassSource result = target.findSource("foobar", null);
|
|
+ Assert.assertNull(result);
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldReturnNullForMalformedURI() {
|
|
+ Set<String> visited = set();
|
|
+ DirectorySourceProvider target = new DirectorySourceProvider(new FakeFileSupport(set("foobar"), set("foobar")) {
|
|
+ @Override
|
|
+ public ClassLoader createClassLoader(Path path) throws MalformedURLException {
|
|
+ visited.add("1");
|
|
+ throw new MalformedURLException("...");
|
|
+ }
|
|
+ });
|
|
+ ClassSource result = target.findSource("foobar", null);
|
|
+ Assert.assertNull(result);
|
|
+ Assert.assertEquals(set("1"), visited);
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldCreateSourceIfNameExistsAndIsADirectory() {
|
|
+ FileSupport fileSupport = new FakeFileSupport(set("foo"), set("foo"));
|
|
+ DirectorySourceProvider target = new DirectorySourceProvider(fileSupport);
|
|
+ ClassSource foo = target.findSource("foo", null);
|
|
+ Assert.assertNotNull(foo);
|
|
+ Assert.assertEquals("directory:foo", foo.toString());
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/jar/JarSourceProviderTest.java b/test/hotspot/jtreg/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/jar/JarSourceProviderTest.java
|
|
new file mode 100644
|
|
index 000000000..a1eb78d04
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/jar/JarSourceProviderTest.java
|
|
@@ -0,0 +1,128 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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
|
|
+ * @modules jdk.aot/jdk.tools.jaotc
|
|
+ * jdk.aot/jdk.tools.jaotc.collect
|
|
+ * jdk.aot/jdk.tools.jaotc.collect.jar
|
|
+ * @compile ../Utils.java
|
|
+ * @compile ../FakeFileSupport.java
|
|
+ * @compile ../FakeSearchPath.java
|
|
+ *
|
|
+ * @run junit/othervm jdk.tools.jaotc.test.collect.jar.JarSourceProviderTest
|
|
+ */
|
|
+
|
|
+package jdk.tools.jaotc.test.collect.jar;
|
|
+
|
|
+import jdk.tools.jaotc.collect.ClassSource;
|
|
+import jdk.tools.jaotc.collect.jar.JarSourceProvider;
|
|
+import jdk.tools.jaotc.test.collect.FakeFileSupport;
|
|
+import jdk.tools.jaotc.test.collect.FakeSearchPath;
|
|
+import org.junit.Assert;
|
|
+import org.junit.Before;
|
|
+import org.junit.Test;
|
|
+
|
|
+import java.nio.file.Path;
|
|
+import java.nio.file.Paths;
|
|
+import java.nio.file.ProviderNotFoundException;
|
|
+import java.util.Set;
|
|
+
|
|
+import static jdk.tools.jaotc.test.collect.Utils.mkpath;
|
|
+import static jdk.tools.jaotc.test.collect.Utils.set;
|
|
+
|
|
+public class JarSourceProviderTest {
|
|
+
|
|
+ private FakeFileSupport fileSupport;
|
|
+ private JarSourceProvider target;
|
|
+
|
|
+ @Before
|
|
+ public void setUp() throws Exception {
|
|
+ fileSupport = new FakeFileSupport(set(), set());
|
|
+ target = new JarSourceProvider(fileSupport);
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldUseSearchPathToFindPath() {
|
|
+ Set<String> visited = set();
|
|
+ JarSourceProvider target = new JarSourceProvider(fileSupport);
|
|
+ FakeSearchPath searchPath = new FakeSearchPath(null);
|
|
+ ClassSource source = target.findSource("hello", searchPath);
|
|
+
|
|
+ Assert.assertEquals(set("hello"), searchPath.entries);
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldReturnNullIfPathIsNull() {
|
|
+ JarSourceProvider target = new JarSourceProvider(fileSupport);
|
|
+ ClassSource source = target.findSource("foobar", new FakeSearchPath(null));
|
|
+ Assert.assertNull(source);
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldReturnNullIfPathIsDirectory() {
|
|
+ fileSupport.addDirectory("hello/foobar");
|
|
+ ClassSource source = target.findSource("foobar", new FakeSearchPath("hello/foobar"));
|
|
+
|
|
+ Assert.assertNull(source);
|
|
+ Assert.assertEquals(set(mkpath("hello/foobar")), fileSupport.getCheckedDirectory());
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldReturnNullIfUnableToMakeJarFileSystem() {
|
|
+ fileSupport.setJarFileSystemRoot(null);
|
|
+ ClassSource result = target.findSource("foobar", new FakeSearchPath("foo/bar"));
|
|
+
|
|
+ Assert.assertEquals(set(mkpath("foo/bar")), fileSupport.getCheckedJarFileSystemRoots());
|
|
+ Assert.assertNull(result);
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldReturnNullIfNotValidJarProvider() {
|
|
+ fileSupport = new FakeFileSupport(set(), set()) {
|
|
+
|
|
+ @Override
|
|
+ public Path getJarFileSystemRoot(Path jarFile) {
|
|
+ super.getJarFileSystemRoot(jarFile);
|
|
+ throw new ProviderNotFoundException();
|
|
+ }
|
|
+ };
|
|
+ fileSupport.setJarFileSystemRoot(null);
|
|
+ target = new JarSourceProvider(fileSupport);
|
|
+
|
|
+ ClassSource result = target.findSource("foobar", new FakeSearchPath("foo/bar"));
|
|
+
|
|
+ Assert.assertEquals(set(mkpath("foo/bar")), fileSupport.getCheckedJarFileSystemRoots());
|
|
+ Assert.assertNull(result);
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldReturnSourceWhenAllIsValid() {
|
|
+ fileSupport.setJarFileSystemRoot(Paths.get("some/bar"));
|
|
+ ClassSource result = target.findSource("foobar", new FakeSearchPath("this/bar"));
|
|
+
|
|
+ Assert.assertEquals(set(mkpath("this/bar")), fileSupport.getClassloaderPaths());
|
|
+ Assert.assertEquals("jar:" + mkpath("this/bar"), result.toString());
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/module/ModuleSourceProviderTest.java b/test/hotspot/jtreg/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/module/ModuleSourceProviderTest.java
|
|
new file mode 100644
|
|
index 000000000..4bf2b9ca1
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/module/ModuleSourceProviderTest.java
|
|
@@ -0,0 +1,103 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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
|
|
+ * @modules jdk.aot/jdk.tools.jaotc
|
|
+ * jdk.aot/jdk.tools.jaotc.collect
|
|
+ * jdk.aot/jdk.tools.jaotc.collect.module
|
|
+ * @compile ../Utils.java
|
|
+ * @run junit/othervm jdk.tools.jaotc.test.collect.module.ModuleSourceProviderTest
|
|
+ */
|
|
+
|
|
+package jdk.tools.jaotc.test.collect.module;
|
|
+
|
|
+import jdk.tools.jaotc.collect.FileSupport;
|
|
+import jdk.tools.jaotc.collect.module.ModuleSource;
|
|
+import jdk.tools.jaotc.collect.module.ModuleSourceProvider;
|
|
+import jdk.tools.jaotc.test.collect.Utils;
|
|
+import org.junit.Before;
|
|
+import org.junit.Test;
|
|
+
|
|
+import java.io.IOException;
|
|
+import java.nio.file.FileSystem;
|
|
+import java.nio.file.FileSystems;
|
|
+import java.nio.file.Path;
|
|
+import java.nio.file.Paths;
|
|
+import java.util.function.BiFunction;
|
|
+
|
|
+import static jdk.tools.jaotc.test.collect.Utils.mkpath;
|
|
+
|
|
+import static org.junit.Assert.assertEquals;
|
|
+import static org.junit.Assert.assertNull;
|
|
+
|
|
+
|
|
+public class ModuleSourceProviderTest {
|
|
+ private ClassLoader classLoader;
|
|
+ private ModuleSourceProvider target;
|
|
+ private FileSupport fileSupport;
|
|
+ private BiFunction<Path, Path, Path> getSubDirectory = null;
|
|
+
|
|
+ @Before
|
|
+ public void setUp() {
|
|
+ classLoader = new FakeClassLoader();
|
|
+ fileSupport = new FileSupport() {
|
|
+
|
|
+ @Override
|
|
+ public boolean isDirectory(Path path) {
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public Path getSubDirectory(FileSystem fileSystem, Path root, Path path) throws IOException {
|
|
+ if (getSubDirectory == null) {
|
|
+ throw new IOException("Nope");
|
|
+ }
|
|
+ return getSubDirectory.apply(root, path);
|
|
+ }
|
|
+ };
|
|
+ target = new ModuleSourceProvider(FileSystems.getDefault(), classLoader, fileSupport);
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void itShouldUseFileSupport() {
|
|
+ getSubDirectory = (root, path) -> {
|
|
+ if (root.toString().equals("modules") && path.toString().equals("test.module")) {
|
|
+ return Paths.get("modules/test.module");
|
|
+ }
|
|
+ return null;
|
|
+ };
|
|
+
|
|
+ ModuleSource source = (ModuleSource) target.findSource("test.module", null);
|
|
+ assertEquals(mkpath("modules/test.module"), source.getModulePath().toString());
|
|
+ assertEquals("module:" + mkpath("modules/test.module"), source.toString());
|
|
+ }
|
|
+
|
|
+ private static class FakeClassLoader extends ClassLoader {
|
|
+ @Override
|
|
+ public Class<?> loadClass(String name) throws ClassNotFoundException {
|
|
+ return null;
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/scripts/HelloWorld.java b/test/hotspot/jtreg/compiler/aot/scripts/HelloWorld.java
|
|
new file mode 100644
|
|
index 000000000..663161b63
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/scripts/HelloWorld.java
|
|
@@ -0,0 +1,5 @@
|
|
+public class HelloWorld {
|
|
+ public static void main(String[] args) {
|
|
+ System.out.println("Hello, world!");
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/scripts/InitGraal.java b/test/hotspot/jtreg/compiler/aot/scripts/InitGraal.java
|
|
new file mode 100644
|
|
index 000000000..ed1bffd8a
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/scripts/InitGraal.java
|
|
@@ -0,0 +1,30 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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
|
|
+ * 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.
|
|
+ */
|
|
+
|
|
+import jdk.vm.ci.hotspot.*;
|
|
+
|
|
+public class InitGraal {
|
|
+ public static void main(String[] args) throws Throwable {
|
|
+ HotSpotJVMCIRuntime.runtime().getCompiler();
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/scripts/README b/test/hotspot/jtreg/compiler/aot/scripts/README
|
|
new file mode 100644
|
|
index 000000000..c1fb204d6
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/scripts/README
|
|
@@ -0,0 +1,32 @@
|
|
+Copyright (c) 2017, 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
|
|
+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.
|
|
+
|
|
+--------------------------------------------
|
|
+This directory contains scripts to test AOT.
|
|
+
|
|
+JAVA_HOME should point to local JDK (scripts will install AOT libraries into it) which supports AOT.
|
|
+
|
|
+Use 'bash' shell to run scripts.
|
|
+
|
|
+Execute build-bootmodules.sh first before running test* scripts.
|
|
+
|
|
+Download dacapo-9.12-bach.jar and execute build-jdk.vm-modules.sh before running test-graal.sh
|
|
+
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/scripts/build-bootmodules.sh b/test/hotspot/jtreg/compiler/aot/scripts/build-bootmodules.sh
|
|
new file mode 100644
|
|
index 000000000..5400700ee
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/scripts/build-bootmodules.sh
|
|
@@ -0,0 +1,106 @@
|
|
+# Copyright (c) 2017, 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
|
|
+# 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.
|
|
+
|
|
+pushd `dirname $0` > /dev/null
|
|
+DIR=`pwd`
|
|
+popd > /dev/null
|
|
+
|
|
+# set env variables
|
|
+. $DIR/test-env.sh
|
|
+
|
|
+MODULES="java.base"
|
|
+
|
|
+TEST=HelloWorld
|
|
+
|
|
+for m in $MODULES; do
|
|
+ rm -f $JAVA_HOME/lib/lib$m*.$SO_TYPE
|
|
+done
|
|
+
|
|
+$JAVA_HOME/bin/javac -d . $DIR/$TEST.java
|
|
+
|
|
+JAOTC_OPTS="-J-ea -J-Xmx4g --compile-for-tiered --info"
|
|
+JAVA_OPTS="-Xmx4g -XX:+UnlockExperimentalVMOptions -XX:+UseAOT -XX:+UnlockDiagnosticVMOptions -XX:+UseAOTStrictLoading"
|
|
+
|
|
+# Compile with: +UseCompressedOops +UseG1GC
|
|
+LIBRARIES=""
|
|
+for m in $MODULES; do
|
|
+ if [ -f $DIR/$m-list.txt ]; then
|
|
+ LIST="--compile-commands $DIR/$m-list.txt"
|
|
+ else
|
|
+ LIST=""
|
|
+ fi
|
|
+ $JAVA_HOME/bin/jaotc -J-XX:+UseCompressedOops -J-XX:+UseG1GC $JAOTC_OPTS $LIST --output lib$m-coop.$SO_TYPE --module $m || exit 1
|
|
+ LIBRARIES="$LIBRARIES$PWD/lib$m-coop.$SO_TYPE:"
|
|
+done
|
|
+$JAVA_HOME/bin/java $JAVA_OPTS -XX:+UseCompressedOops -XX:+UseG1GC -XX:AOTLibrary=$LIBRARIES $TEST || exit 1
|
|
+
|
|
+# Compile with: +UseCompressedOops +UseParallelGC
|
|
+LIBRARIES=""
|
|
+for m in $MODULES; do
|
|
+ if [ -f $DIR/$m-list.txt ]; then
|
|
+ LIST="--compile-commands $DIR/$m-list.txt"
|
|
+ else
|
|
+ LIST=""
|
|
+ fi
|
|
+ $JAVA_HOME/bin/jaotc -J-XX:+UseCompressedOops -J-XX:+UseParallelGC $JAOTC_OPTS $LIST --output lib$m-coop-nong1.$SO_TYPE --module $m || exit 1
|
|
+ LIBRARIES="$LIBRARIES$PWD/lib$m-coop-nong1.$SO_TYPE:"
|
|
+done
|
|
+$JAVA_HOME/bin/java $JAVA_OPTS -XX:+UseCompressedOops -XX:+UseParallelGC -XX:AOTLibrary=$LIBRARIES $TEST || exit 1
|
|
+
|
|
+# Compile with: -UseCompressedOops +UseG1GC
|
|
+LIBRARIES=""
|
|
+for m in $MODULES; do
|
|
+ if [ -f $DIR/$m-list.txt ]; then
|
|
+ LIST="--compile-commands $DIR/$m-list.txt"
|
|
+ else
|
|
+ LIST=""
|
|
+ fi
|
|
+ $JAVA_HOME/bin/jaotc -J-XX:-UseCompressedOops -J-XX:+UseG1GC $JAOTC_OPTS $LIST --output lib$m.$SO_TYPE --module $m || exit 1
|
|
+ LIBRARIES="$LIBRARIES$PWD/lib$m.$SO_TYPE:"
|
|
+done
|
|
+$JAVA_HOME/bin/java $JAVA_OPTS -XX:-UseCompressedOops -XX:+UseG1GC -XX:AOTLibrary=$LIBRARIES $TEST || exit 1
|
|
+
|
|
+# Compile with: -UseCompressedOops +UseParallelGC
|
|
+LIBRARIES=""
|
|
+for m in $MODULES; do
|
|
+ if [ -f $DIR/$m-list.txt ]; then
|
|
+ LIST="--compile-commands $DIR/$m-list.txt"
|
|
+ else
|
|
+ LIST=""
|
|
+ fi
|
|
+ $JAVA_HOME/bin/jaotc -J-XX:-UseCompressedOops -J-XX:+UseParallelGC $JAOTC_OPTS $LIST --output lib$m-nong1.$SO_TYPE --module $m || exit 1
|
|
+ LIBRARIES="$LIBRARIES$PWD/lib$m-nong1.$SO_TYPE:"
|
|
+done
|
|
+$JAVA_HOME/bin/java $JAVA_OPTS -XX:-UseCompressedOops -XX:+UseParallelGC -XX:AOTLibrary=$LIBRARIES $TEST || exit 1
|
|
+
|
|
+echo "Installing shared libraries in: $JAVA_HOME/lib/"
|
|
+for m in $MODULES; do
|
|
+ mv -f lib$m*.$SO_TYPE $JAVA_HOME/lib/
|
|
+done
|
|
+
|
|
+# Test installed libraries.
|
|
+$JAVA_HOME/bin/java $JAVA_OPTS -XX:-UseCompressedOops -XX:+UseG1GC -XX:+PrintAOT $TEST | grep "aot library" || exit 1
|
|
+$JAVA_HOME/bin/java $JAVA_OPTS -XX:-UseCompressedOops -XX:+UseParallelGC -XX:+PrintAOT $TEST | grep "aot library" || exit 1
|
|
+$JAVA_HOME/bin/java $JAVA_OPTS -XX:+UseCompressedOops -XX:+UseG1GC -XX:+PrintAOT $TEST | grep "aot library" || exit 1
|
|
+$JAVA_HOME/bin/java $JAVA_OPTS -XX:+UseCompressedOops -XX:+UseParallelGC -XX:+PrintAOT $TEST | grep "aot library" || exit 1
|
|
+
|
|
+rm -f $TEST.class
|
|
+
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/scripts/build-jdk.vm-modules.sh b/test/hotspot/jtreg/compiler/aot/scripts/build-jdk.vm-modules.sh
|
|
new file mode 100644
|
|
index 000000000..473d4717a
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/scripts/build-jdk.vm-modules.sh
|
|
@@ -0,0 +1,110 @@
|
|
+# Copyright (c) 2017, 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
|
|
+# 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.
|
|
+
|
|
+pushd `dirname $0` > /dev/null
|
|
+DIR=`pwd`
|
|
+popd > /dev/null
|
|
+
|
|
+# set env variables
|
|
+. $DIR/test-env.sh
|
|
+
|
|
+MODULES="jdk.internal.vm.ci jdk.internal.vm.compiler"
|
|
+
|
|
+TEST=InitGraal
|
|
+
|
|
+for m in $MODULES; do
|
|
+ rm -f $JAVA_HOME/lib/lib$m*.$SO_TYPE
|
|
+done
|
|
+
|
|
+$JAVA_HOME/bin/javac --add-modules jdk.internal.vm.ci --add-exports jdk.internal.vm.ci/jdk.vm.ci.hotspot=ALL-UNNAMED $DIR/$TEST.java
|
|
+
|
|
+# AOT compile non-tiered code version.
|
|
+JAOTC_OPTS="-J-Xmx4g --info"
|
|
+JAVA_OPTS="-Xmx4g -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -XX:+UseAOT -XX:+UnlockDiagnosticVMOptions -XX:+UseAOTStrictLoading --add-modules jdk.internal.vm.ci --add-exports jdk.internal.vm.ci/jdk.vm.ci.hotspot=ALL-UNNAMED"
|
|
+
|
|
+# Compile with: +UseCompressedOops +UseG1GC
|
|
+RT_OPTS="-J-XX:+UseCompressedOops -J-XX:+UseG1GC"
|
|
+LIBRARIES=""
|
|
+for m in $MODULES; do
|
|
+ if [ -f $DIR/$m-list.txt ]; then
|
|
+ LIST="--compile-commands $DIR/$m-list.txt"
|
|
+ else
|
|
+ LIST=""
|
|
+ fi
|
|
+ $JAVA_HOME/bin/jaotc $RT_OPTS $JAOTC_OPTS $LIST --output lib$m-coop.$SO_TYPE --module $m -J-XX:AOTLibrary=$LIBRARIES || exit 1
|
|
+ LIBRARIES="$LIBRARIES$PWD/lib$m-coop.$SO_TYPE:"
|
|
+done
|
|
+$JAVA_HOME/bin/java $JAVA_OPTS -XX:+UseCompressedOops -XX:+UseG1GC -XX:+PrintAOT -XX:AOTLibrary=$LIBRARIES $TEST | grep "aot library" || exit 1
|
|
+
|
|
+# Compile with: +UseCompressedOops +UseParallelGC
|
|
+RT_OPTS="-J-XX:+UseCompressedOops -J-XX:+UseParallelGC"
|
|
+LIBRARIES=""
|
|
+for m in $MODULES; do
|
|
+ if [ -f $DIR/$m-list.txt ]; then
|
|
+ LIST="--compile-commands $DIR/$m-list.txt"
|
|
+ else
|
|
+ LIST=""
|
|
+ fi
|
|
+ $JAVA_HOME/bin/jaotc $RT_OPTS $JAOTC_OPTS $LIST --output lib$m-coop-nong1.$SO_TYPE --module $m -J-XX:AOTLibrary=$LIBRARIES || exit 1
|
|
+ LIBRARIES="$LIBRARIES$PWD/lib$m-coop-nong1.$SO_TYPE:"
|
|
+done
|
|
+$JAVA_HOME/bin/java $JAVA_OPTS -XX:+UseCompressedOops -XX:+UseParallelGC -XX:+PrintAOT -XX:AOTLibrary=$LIBRARIES $TEST | grep "aot library" || exit 1
|
|
+
|
|
+# Compile with: -UseCompressedOops +UseG1GC
|
|
+RT_OPTS="-J-XX:-UseCompressedOops -J-XX:+UseG1GC"
|
|
+LIBRARIES=""
|
|
+for m in $MODULES; do
|
|
+ if [ -f $DIR/$m-list.txt ]; then
|
|
+ LIST="--compile-commands $DIR/$m-list.txt"
|
|
+ else
|
|
+ LIST=""
|
|
+ fi
|
|
+ $JAVA_HOME/bin/jaotc $RT_OPTS $JAOTC_OPTS $LIST --output lib$m.$SO_TYPE --module $m -J-XX:AOTLibrary=$LIBRARIES || exit 1
|
|
+ LIBRARIES="$LIBRARIES$PWD/lib$m.$SO_TYPE:"
|
|
+done
|
|
+$JAVA_HOME/bin/java $JAVA_OPTS -XX:-UseCompressedOops -XX:+UseG1GC -XX:+PrintAOT -XX:AOTLibrary=$LIBRARIES $TEST | grep "aot library" || exit 1
|
|
+
|
|
+# Compile with: -UseCompressedOops +UseParallelGC
|
|
+RT_OPTS="-J-XX:-UseCompressedOops -J-XX:+UseParallelGC"
|
|
+LIBRARIES=""
|
|
+for m in $MODULES; do
|
|
+ if [ -f $DIR/$m-list.txt ]; then
|
|
+ LIST="--compile-commands $DIR/$m-list.txt"
|
|
+ else
|
|
+ LIST=""
|
|
+ fi
|
|
+ $JAVA_HOME/bin/jaotc $RT_OPTS $JAOTC_OPTS $LIST --output lib$m-nong1.$SO_TYPE --module $m -J-XX:AOTLibrary=$LIBRARIES || exit 1
|
|
+ LIBRARIES="$LIBRARIES$PWD/lib$m-nong1.$SO_TYPE:"
|
|
+done
|
|
+$JAVA_HOME/bin/java $JAVA_OPTS -XX:-UseCompressedOops -XX:+UseParallelGC -XX:+PrintAOT -XX:AOTLibrary=$LIBRARIES $TEST | grep "aot library" || exit 1
|
|
+
|
|
+echo "Installing shared libraries in: $JAVA_HOME/lib/"
|
|
+for m in $MODULES; do
|
|
+ mv -f lib$m*.$SO_TYPE $JAVA_HOME/lib/
|
|
+done
|
|
+
|
|
+# Test installed libraries.
|
|
+$JAVA_HOME/bin/java $JAVA_OPTS -XX:-UseCompressedOops -XX:+UseG1GC -XX:+PrintAOT $TEST | grep "aot library" || exit 1
|
|
+$JAVA_HOME/bin/java $JAVA_OPTS -XX:-UseCompressedOops -XX:+UseParallelGC -XX:+PrintAOT $TEST | grep "aot library" || exit 1
|
|
+$JAVA_HOME/bin/java $JAVA_OPTS -XX:+UseCompressedOops -XX:+UseG1GC -XX:+PrintAOT $TEST | grep "aot library" || exit 1
|
|
+$JAVA_HOME/bin/java $JAVA_OPTS -XX:+UseCompressedOops -XX:+UseParallelGC -XX:+PrintAOT $TEST | grep "aot library" || exit 1
|
|
+
|
|
+rm -f $TEST.class
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/scripts/empty.js b/test/hotspot/jtreg/compiler/aot/scripts/empty.js
|
|
new file mode 100644
|
|
index 000000000..226697f87
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/scripts/empty.js
|
|
@@ -0,0 +1 @@
|
|
+i = 0;
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/scripts/java.base-list.txt b/test/hotspot/jtreg/compiler/aot/scripts/java.base-list.txt
|
|
new file mode 100644
|
|
index 000000000..380a4586c
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/scripts/java.base-list.txt
|
|
@@ -0,0 +1,20 @@
|
|
+# Copyright (c) 2017, 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
|
|
+# 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.
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/scripts/jdk.internal.vm.compiler-list.txt b/test/hotspot/jtreg/compiler/aot/scripts/jdk.internal.vm.compiler-list.txt
|
|
new file mode 100644
|
|
index 000000000..59b4eba7d
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/scripts/jdk.internal.vm.compiler-list.txt
|
|
@@ -0,0 +1,45 @@
|
|
+# Copyright (c) 2017, 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
|
|
+# 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.
|
|
+
|
|
+#
|
|
+exclude org.graalvm.compiler.hotspot.replacements.arraycopy.ArrayCopyCallNode.*
|
|
+exclude org.graalvm.compiler.hotspot.replacements.AESCryptSubstitutions.*
|
|
+exclude org.graalvm.compiler.hotspot.replacements.CipherBlockChainingSubstitutions.crypt(Ljava/lang/Object;[BII[BILjava/lang/Object;ZZ)V
|
|
+exclude org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.arrayAllocationSize(III)I
|
|
+exclude org.graalvm.compiler.hotspot.replacements.PluginFactory_HotSpotReplacementsUtil\$config.execute(.*).*
|
|
+exclude org.graalvm.compiler.hotspot.replacements.PluginFactory_HotSpotReplacementsUtil\$getWordKind.execute(.*).*
|
|
+exclude org.graalvm.compiler.hotspot.replacements.PluginFactory_HotSpotReplacementsUtil\$getConfig.execute(.*).
|
|
+#
|
|
+exclude org.graalvm.compiler.hotspot.stubs.StubUtil.printf(.*).*
|
|
+exclude org.graalvm.compiler.hotspot.stubs.StubUtil.decipher(J)V
|
|
+exclude org.graalvm.compiler.hotspot.stubs.StubUtil.fatal(.*).*
|
|
+#
|
|
+exclude org.graalvm.compiler.nodes.java.NewArrayNode.newUninitializedArray(Ljava/lang/Class;I)Ljava/lang/Object;
|
|
+exclude org.graalvm.compiler.nodes.java.DynamicNewArrayNode.newArray(Ljava/lang/Class;ILjdk/vm/ci/meta/JavaKind;)Ljava/lang/Object;
|
|
+exclude org.graalvm.compiler.nodes.java.DynamicNewArrayNode.newUninitializedArray(Ljava/lang/Class;ILjdk/vm/ci/meta/JavaKind;)Ljava/lang/Object;
|
|
+exclude org.graalvm.compiler.nodes.PiNode.piCastNonNull(Ljava/lang/Object;Ljava/lang/Class;)Ljava/lang/Object;
|
|
+#
|
|
+exclude org.graalvm.compiler.replacements.nodes.ArrayEqualsNode.equals(.*).*
|
|
+exclude org.graalvm.compiler.replacements.Log.print.*
|
|
+exclude org.graalvm.compiler.replacements.ReplacementsUtil.*
|
|
+exclude org.graalvm.compiler.replacements.SnippetCounter.*
|
|
+exclude org.graalvm.compiler.replacements.SnippetCounterNode.*
|
|
+exclude org.graalvm.compiler.replacements.SnippetIntegerHistogram.inc(J)V
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/scripts/test-env.sh b/test/hotspot/jtreg/compiler/aot/scripts/test-env.sh
|
|
new file mode 100644
|
|
index 000000000..ac660724b
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/scripts/test-env.sh
|
|
@@ -0,0 +1,42 @@
|
|
+# Copyright (c) 2017, 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
|
|
+# 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.
|
|
+
|
|
+# set platform-dependent variables
|
|
+OS=`uname -s`
|
|
+case "$OS" in
|
|
+ Linux )
|
|
+ SO_TYPE=so
|
|
+ ;;
|
|
+ Darwin )
|
|
+ SO_TYPE=dylib
|
|
+ ;;
|
|
+ Windows_* )
|
|
+ SO_TYPE=dll
|
|
+ ;;
|
|
+ CYGWIN_* )
|
|
+ SO_TYPE=dll
|
|
+ ;;
|
|
+ * )
|
|
+ echo "Unrecognized system!"
|
|
+ exit 1;
|
|
+ ;;
|
|
+esac
|
|
+
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/scripts/test-graal.sh b/test/hotspot/jtreg/compiler/aot/scripts/test-graal.sh
|
|
new file mode 100644
|
|
index 000000000..d2f77d22c
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/scripts/test-graal.sh
|
|
@@ -0,0 +1,62 @@
|
|
+# Copyright (c) 2017, 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
|
|
+# 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.
|
|
+
|
|
+JAR="dacapo-9.12-bach.jar"
|
|
+
|
|
+if [ ! -f $JAR ]; then
|
|
+ echo "$JAR not found."
|
|
+ exit 1
|
|
+fi
|
|
+
|
|
+pushd `dirname $0` > /dev/null
|
|
+DIR=`pwd`
|
|
+popd > /dev/null
|
|
+
|
|
+APP="-jar $JAR -s small -n 5"
|
|
+
|
|
+JAVA_OPTS="-XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -XX:+UseJVMCICompiler -XX:-BootstrapJVMCI -XX:-TieredCompilation -Xmx4g -XX:+UseCompressedOops -XX:+UseG1GC"
|
|
+
|
|
+MODULE_OPTS="--add-modules jdk.internal.vm.ci --add-exports jdk.internal.vm.ci/jdk.vm.ci.hotspot=ALL-UNNAMED"
|
|
+
|
|
+$JAVA_HOME/bin/java $JAVA_OPTS -version || exit 1
|
|
+
|
|
+$JAVA_HOME/bin/javac $MODULE_OPTS InitGraal.java || exit 1
|
|
+
|
|
+PATTERN="(aot library|DONE:.*HotSpotVMConfig|DONE:.*HotSpotJVMCIRuntime|DONE:.*HotSpotGraalRuntime)"
|
|
+echo "----------"
|
|
+$JAVA_HOME/bin/java $JAVA_OPTS $MODULE_OPTS -XX:+TieredCompilation -XX:-UseAOT -XX:+PrintAOT -Djvmci.InitTimer=true InitGraal | grep -E "$PATTERN" || exit 1
|
|
+echo "----------"
|
|
+$JAVA_HOME/bin/java $JAVA_OPTS $MODULE_OPTS -XX:+TieredCompilation -XX:+PrintAOT -Djvmci.InitTimer=true InitGraal | grep -E "$PATTERN" || exit 1
|
|
+echo "----------"
|
|
+$JAVA_HOME/bin/java $JAVA_OPTS $MODULE_OPTS -XX:+PrintAOT -Djvmci.InitTimer=true InitGraal | grep -E "$PATTERN" || exit 1
|
|
+echo "----------"
|
|
+
|
|
+rm -f InitGraal.class
|
|
+
|
|
+# eclipse started to fail again with JDK 9.
|
|
+#BENCHMARKS="avrora batik eclipse fop jython h2 luindex lusearch pmd sunflow tradebeans tradesoap xalan"
|
|
+BENCHMARKS="avrora batik fop jython h2 luindex lusearch pmd sunflow xalan"
|
|
+
|
|
+for i in $BENCHMARKS; do
|
|
+ $JAVA_HOME/bin/java $JAVA_OPTS $APP $i || exit 1
|
|
+ rm -rf ./scratch
|
|
+done
|
|
+
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/scripts/test-helloworld.sh b/test/hotspot/jtreg/compiler/aot/scripts/test-helloworld.sh
|
|
new file mode 100644
|
|
index 000000000..860b0ee21
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/scripts/test-helloworld.sh
|
|
@@ -0,0 +1,97 @@
|
|
+# Copyright (c) 2017, 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
|
|
+# 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.
|
|
+
|
|
+pushd `dirname $0` > /dev/null
|
|
+DIR=`pwd`
|
|
+popd > /dev/null
|
|
+
|
|
+# set env variables
|
|
+. $DIR/test-env.sh
|
|
+
|
|
+rm -f libHelloWorld*.$SO_TYPE HelloWorld.class
|
|
+
|
|
+$JAVA_HOME/bin/javac -d . $DIR/HelloWorld.java
|
|
+
|
|
+# Run once with non-compressed oops.
|
|
+OPTS="-J-Xmx4g -J-XX:-UseCompressedOops --info --verbose"
|
|
+$JAVA_HOME/bin/jaotc $OPTS --output libHelloWorld.$SO_TYPE HelloWorld.class || exit 1
|
|
+
|
|
+JAVA_OPTS="-Xmx4g -XX:-UseCompressedOops -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseAOTStrictLoading -XX:AOTLibrary=./libHelloWorld.$SO_TYPE"
|
|
+
|
|
+$JAVA_HOME/bin/java $JAVA_OPTS -XX:+PrintAOT -version | grep "aot library" || exit 1
|
|
+$JAVA_HOME/bin/java $JAVA_OPTS HelloWorld || exit 1
|
|
+
|
|
+TIMEFORMAT="%3R"
|
|
+N=5
|
|
+
|
|
+LIBRARY=libHelloWorld-coop.$SO_TYPE
|
|
+
|
|
+for gc in UseG1GC UseParallelGC; do
|
|
+ # Now with compressed oops.
|
|
+ OPTS="-J-XX:+UseCompressedOops -J-XX:+$gc --info --verbose"
|
|
+ $JAVA_HOME/bin/jaotc $OPTS --output $LIBRARY HelloWorld.class
|
|
+
|
|
+ # Dump CDS archive.
|
|
+ $JAVA_HOME/bin/java -Xshare:dump -XX:+UnlockExperimentalVMOptions -XX:-UseAOT -XX:+$gc || exit 1
|
|
+
|
|
+ JAVA_OPTS="-Xmx256m"
|
|
+
|
|
+ echo "Tiered C1 $gc:"
|
|
+ for i in `seq 1 $N`; do
|
|
+ OUT=`time $JAVA_HOME/bin/java -XX:+$gc -XX:-UseCompressedOops -XX:+UnlockExperimentalVMOptions -XX:-UseAOT -XX:TieredStopAtLevel=1 $JAVA_OPTS HelloWorld`
|
|
+ if [ "$OUT" != "Hello, world!" ]; then
|
|
+ echo $OUT
|
|
+ exit 1
|
|
+ fi
|
|
+ done
|
|
+
|
|
+ echo "Tiered C1/C2 $gc:"
|
|
+ for i in `seq 1 $N`; do
|
|
+ OUT=`time $JAVA_HOME/bin/java -XX:+$gc -XX:-UseCompressedOops -XX:+UnlockExperimentalVMOptions -XX:-UseAOT $JAVA_OPTS HelloWorld`
|
|
+ if [ "$OUT" != "Hello, world!" ]; then
|
|
+ echo $OUT
|
|
+ exit 1
|
|
+ fi
|
|
+ done
|
|
+
|
|
+ JAVA_OPTS="-Xmx256m -XX:+UseCompressedOops -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseAOTStrictLoading -XX:AOTLibrary=./$LIBRARY"
|
|
+
|
|
+
|
|
+ echo "AOT $gc:"
|
|
+ for i in `seq 1 $N`; do
|
|
+ OUT=`time $JAVA_HOME/bin/java -XX:+$gc $JAVA_OPTS HelloWorld`
|
|
+ if [ "$OUT" != "Hello, world!" ]; then
|
|
+ echo $OUT
|
|
+ exit 1
|
|
+ fi
|
|
+ done
|
|
+
|
|
+ echo "AOT -Xshare:on $gc:"
|
|
+ for i in `seq 1 $N`; do
|
|
+ OUT=`time $JAVA_HOME/bin/java -Xshare:on -XX:+$gc $JAVA_OPTS HelloWorld`
|
|
+ if [ "$OUT" != "Hello, world!" ]; then
|
|
+ echo $OUT
|
|
+ exit 1
|
|
+ fi
|
|
+ done
|
|
+done
|
|
+
|
|
+rm -f libHelloWorld*.$SO_TYPE HelloWorld.class
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/scripts/test-jaotc.sh b/test/hotspot/jtreg/compiler/aot/scripts/test-jaotc.sh
|
|
new file mode 100644
|
|
index 000000000..ca8ec53a1
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/scripts/test-jaotc.sh
|
|
@@ -0,0 +1,43 @@
|
|
+# Copyright (c) 2017, 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
|
|
+# 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.
|
|
+
|
|
+pushd `dirname $0` > /dev/null
|
|
+DIR=`pwd`
|
|
+popd > /dev/null
|
|
+
|
|
+# set env variables
|
|
+. $DIR/test-env.sh
|
|
+
|
|
+JAOTC_OPTS="-J-Xmx4g -J-XX:-UseCompressedOops"
|
|
+
|
|
+rm -f libjdk.aot.$SO_TYPE
|
|
+
|
|
+$JAVA_HOME/bin/jaotc $JAOTC_OPTS --info --module jdk.aot --output libjdk.aot.$SO_TYPE || exit 1
|
|
+
|
|
+rm -f libjava.base-aot.$SO_TYPE
|
|
+
|
|
+$JAVA_HOME/bin/jaotc $JAOTC_OPTS -J-XX:AOTLibrary=./libjdk.aot.$SO_TYPE --info --compile-commands $DIR/java.base-list.txt --output libjava.base-aot.$SO_TYPE --module java.base || exit 1
|
|
+
|
|
+$JAVA_HOME/bin/javac -d . $DIR/HelloWorld.java
|
|
+
|
|
+$JAVA_HOME/bin/java -XX:-UseCompressedOops -XX:+UnlockExperimentalVMOptions -XX:AOTLibrary=./libjava.base-aot.$SO_TYPE HelloWorld
|
|
+
|
|
+rm -f HelloWorld.class libjdk.aot.$SO_TYPE libjava.base-aot.$SO_TYPE
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/scripts/test-javac.sh b/test/hotspot/jtreg/compiler/aot/scripts/test-javac.sh
|
|
new file mode 100644
|
|
index 000000000..006c96a63
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/scripts/test-javac.sh
|
|
@@ -0,0 +1,157 @@
|
|
+# Copyright (c) 2017, 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
|
|
+# 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.
|
|
+
|
|
+pushd `dirname $0` > /dev/null
|
|
+DIR=`pwd`
|
|
+popd > /dev/null
|
|
+
|
|
+AOT_OPTS="-XX:+UnlockExperimentalVMOptions -XX:+UseAOT"
|
|
+
|
|
+$JAVA_HOME/bin/java $AOT_OPTS -XX:+PrintAOT -version | grep "aot library" || exit 1
|
|
+
|
|
+# Dump CDS archive.
|
|
+$JAVA_HOME/bin/java $AOT_OPTS -Xshare:dump || exit 1
|
|
+
|
|
+FILE="HelloWorld"
|
|
+
|
|
+APP="com.sun.tools.javac.Main"
|
|
+
|
|
+JAVA_OPTS="-XX:-UseCompressedOops"
|
|
+
|
|
+rm -f $FILE.class
|
|
+
|
|
+$JAVA_HOME/bin/java $JAVA_OPTS $AOT_OPTS $APP -verbose $FILE.java || exit 1
|
|
+$JAVA_HOME/bin/java $AOT_OPTS $FILE || exit 1
|
|
+
|
|
+JAVA_OPTS="-XX:+UseCompressedOops"
|
|
+
|
|
+rm -f $FILE.class
|
|
+
|
|
+$JAVA_HOME/bin/java $JAVA_OPTS $AOT_OPTS $APP -verbose $FILE.java || exit 1
|
|
+$JAVA_HOME/bin/java $AOT_OPTS $FILE || exit 1
|
|
+
|
|
+rm -f $FILE.class
|
|
+
|
|
+TIMEFORMAT="%3R"
|
|
+N=5
|
|
+
|
|
+#echo "-Xint:"
|
|
+#for i in `seq 1 10`; do
|
|
+# time $JAVA_HOME/bin/java -Xint $JAVA_OPTS $APP $FILE.java
|
|
+# if [ $? -ne 0 ]; then
|
|
+# exit 1
|
|
+# fi
|
|
+# rm -f $FILE.class
|
|
+#done
|
|
+
|
|
+echo "Tiered C1:"
|
|
+for i in `seq 1 $N`; do
|
|
+ time $JAVA_HOME/bin/java $JAVA_OPTS -XX:+UnlockExperimentalVMOptions -XX:-UseAOT -XX:TieredStopAtLevel=1 $APP $FILE.java
|
|
+ if [ $? -ne 0 ]; then
|
|
+ exit 1
|
|
+ fi
|
|
+ rm -f $FILE.class
|
|
+done
|
|
+
|
|
+echo "Tiered C1/C2:"
|
|
+for i in `seq 1 $N`; do
|
|
+ time $JAVA_HOME/bin/java $JAVA_OPTS -XX:+UnlockExperimentalVMOptions -XX:-UseAOT $APP $FILE.java
|
|
+ if [ $? -ne 0 ]; then
|
|
+ exit 1
|
|
+ fi
|
|
+ rm -f $FILE.class
|
|
+done
|
|
+
|
|
+echo "Tiered C1/C2 -Xshare:on:"
|
|
+for i in `seq 1 $N`; do
|
|
+ time $JAVA_HOME/bin/java $JAVA_OPTS -XX:+UnlockExperimentalVMOptions -XX:-UseAOT -Xshare:on $APP $FILE.java
|
|
+ if [ $? -ne 0 ]; then
|
|
+ exit 1
|
|
+ fi
|
|
+ rm -f $FILE.class
|
|
+done
|
|
+
|
|
+echo "Tiered AOT:"
|
|
+for i in `seq 1 $N`; do
|
|
+ time $JAVA_HOME/bin/java $JAVA_OPTS $AOT_OPTS $APP $FILE.java
|
|
+ if [ $? -ne 0 ]; then
|
|
+ exit 1
|
|
+ fi
|
|
+ rm -f $FILE.class
|
|
+done
|
|
+
|
|
+echo "Tiered AOT -Xshare:on:"
|
|
+for i in `seq 1 $N`; do
|
|
+ time $JAVA_HOME/bin/java $JAVA_OPTS $AOT_OPTS -Xshare:on $APP $FILE.java
|
|
+ if [ $? -ne 0 ]; then
|
|
+ exit 1
|
|
+ fi
|
|
+ rm -f $FILE.class
|
|
+done
|
|
+
|
|
+NAME="jvmci"
|
|
+DIR="$DIR/../../../../../../src/jdk.internal.vm.ci"
|
|
+FILES=`find $DIR -type f -name '*.java'`
|
|
+COUNT=`find $DIR -type f -name '*.java' | wc -l`
|
|
+
|
|
+rm -rf tmp
|
|
+
|
|
+echo "Tiered C1 (compiling $NAME: $COUNT classes):"
|
|
+for i in `seq 1 $N`; do
|
|
+ mkdir tmp
|
|
+ time $JAVA_HOME/bin/javac -J-XX:+UnlockExperimentalVMOptions -J-XX:-UseAOT -J-XX:TieredStopAtLevel=1 -XDignore.symbol.file -d tmp $FILES
|
|
+ if [ $? -ne 0 ]; then
|
|
+ exit 1
|
|
+ fi
|
|
+ rm -rf tmp
|
|
+done
|
|
+
|
|
+echo "Tiered C1/C2 (compiling $NAME: $COUNT classes):"
|
|
+for i in `seq 1 $N`; do
|
|
+ mkdir tmp
|
|
+ time $JAVA_HOME/bin/javac -J-XX:+UnlockExperimentalVMOptions -J-XX:-UseAOT -XDignore.symbol.file -cp /java/devtools/share/junit/latest/junit.jar -d tmp $FILES
|
|
+ if [ $? -ne 0 ]; then
|
|
+ exit 1
|
|
+ fi
|
|
+ rm -rf tmp
|
|
+done
|
|
+
|
|
+echo "Tiered AOT (compiling $NAME: $COUNT classes):"
|
|
+for i in `seq 1 $N`; do
|
|
+ mkdir tmp
|
|
+ time $JAVA_HOME/bin/javac -J-XX:+UnlockExperimentalVMOptions -J-XX:+UseAOT -XDignore.symbol.file -cp /java/devtools/share/junit/latest/junit.jar -d tmp $FILES
|
|
+ if [ $? -ne 0 ]; then
|
|
+ exit 1
|
|
+ fi
|
|
+ rm -rf tmp
|
|
+done
|
|
+
|
|
+echo "Tiered AOT -Xshare:on (compiling $NAME: $COUNT classes):"
|
|
+for i in `seq 1 $N`; do
|
|
+ mkdir tmp
|
|
+ time $JAVA_HOME/bin/javac -J-Xshare:on -J-XX:+UnlockExperimentalVMOptions -J-XX:+UseAOT -XDignore.symbol.file -cp /java/devtools/share/junit/latest/junit.jar -d tmp $FILES
|
|
+ if [ $? -ne 0 ]; then
|
|
+ exit 1
|
|
+ fi
|
|
+ rm -rf tmp
|
|
+done
|
|
+
|
|
+
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/verification/ClassAndLibraryNotMatchTest.java b/test/hotspot/jtreg/compiler/aot/verification/ClassAndLibraryNotMatchTest.java
|
|
new file mode 100644
|
|
index 000000000..ecb2f52fb
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/verification/ClassAndLibraryNotMatchTest.java
|
|
@@ -0,0 +1,124 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 /
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.aot.verification.ClassAndLibraryNotMatchTest
|
|
+ * @run driver compiler.aot.verification.ClassAndLibraryNotMatchTest
|
|
+ * @summary check if class and aot library are properly bound to each other
|
|
+ */
|
|
+
|
|
+package compiler.aot.verification;
|
|
+
|
|
+import compiler.aot.AotCompiler;
|
|
+import java.io.File;
|
|
+import java.io.IOException;
|
|
+import java.nio.file.Files;
|
|
+import java.nio.file.Paths;
|
|
+import java.nio.file.StandardOpenOption;
|
|
+import java.util.Arrays;
|
|
+import jdk.test.lib.JDKToolFinder;
|
|
+import jdk.test.lib.Utils;
|
|
+import jdk.test.lib.process.OutputAnalyzer;
|
|
+import jdk.test.lib.process.ProcessTools;
|
|
+
|
|
+public class ClassAndLibraryNotMatchTest {
|
|
+ private static final String HELLO_WORLD_CLASS_NAME = "HelloWorld";
|
|
+ private static final String LIB_NAME = "lib" + HELLO_WORLD_CLASS_NAME + ".so";
|
|
+ private static final String HELLO_WORLD_MSG1 = "HelloWorld1";
|
|
+ private static final String HELLO_WORLD_MSG2 = "HelloWorld2";
|
|
+ private static final String HELLO_WORLD_FILE = "./" + HELLO_WORLD_CLASS_NAME + ".java";
|
|
+ private static final String HELLO_WORLD_PRE = "public class "
|
|
+ + HELLO_WORLD_CLASS_NAME + " {\n"
|
|
+ + " public static void main(String args[]) {\n"
|
|
+ + " System.out.println(\"";
|
|
+ private static final String HELLO_WORLD_POST = "\");\n"
|
|
+ + " }\n"
|
|
+ + "}\n";
|
|
+
|
|
+ public static void main(String args[]) {
|
|
+ new ClassAndLibraryNotMatchTest().runTest();
|
|
+ }
|
|
+
|
|
+ private void writeHelloWorld(String message) {
|
|
+ String src = HELLO_WORLD_PRE + message + HELLO_WORLD_POST;
|
|
+ try{
|
|
+ Files.write(Paths.get(HELLO_WORLD_FILE), src.getBytes(), StandardOpenOption.CREATE);
|
|
+ } catch (IOException e) {
|
|
+ throw new Error("Can't write HelloWorld " + e, e);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private void compileHelloWorld() {
|
|
+ String javac = JDKToolFinder.getCompileJDKTool("javac");
|
|
+ ProcessBuilder pb = new ProcessBuilder(javac, HELLO_WORLD_FILE);
|
|
+ OutputAnalyzer oa;
|
|
+ try {
|
|
+ oa = ProcessTools.executeProcess(pb);
|
|
+ } catch (Exception e) {
|
|
+ throw new Error("Can't compile class " + e, e);
|
|
+ }
|
|
+ oa.shouldHaveExitValue(0);
|
|
+ }
|
|
+
|
|
+ private void compileAotLibrary() {
|
|
+ AotCompiler.launchCompiler(LIB_NAME, HELLO_WORLD_CLASS_NAME,
|
|
+ Arrays.asList("-classpath", Utils.TEST_CLASS_PATH + File.pathSeparator + "."), null);
|
|
+ }
|
|
+
|
|
+ private void runAndCheckHelloWorld(String checkString) {
|
|
+ ProcessBuilder pb;
|
|
+ try {
|
|
+ pb = ProcessTools.createTestJvm("-cp", ".",
|
|
+ "-XX:+UnlockExperimentalVMOptions", "-XX:+UseAOT",
|
|
+ "-XX:AOTLibrary=./" + LIB_NAME, HELLO_WORLD_CLASS_NAME);
|
|
+ } catch (Exception e) {
|
|
+ throw new Error("Can't create ProcessBuilder to run "
|
|
+ + HELLO_WORLD_CLASS_NAME + " " + e, e);
|
|
+ }
|
|
+ OutputAnalyzer oa;
|
|
+ try {
|
|
+ oa = ProcessTools.executeProcess(pb);
|
|
+ } catch (Exception e) {
|
|
+ throw new Error("Can't execute " + HELLO_WORLD_CLASS_NAME + " " + e, e);
|
|
+ }
|
|
+ oa.shouldHaveExitValue(0);
|
|
+ oa.shouldContain(checkString);
|
|
+ }
|
|
+
|
|
+ private void createHelloWorld(String msg) {
|
|
+ writeHelloWorld(msg);
|
|
+ compileHelloWorld();
|
|
+ }
|
|
+
|
|
+ private void runTest() {
|
|
+ createHelloWorld(HELLO_WORLD_MSG1);
|
|
+ compileAotLibrary();
|
|
+ runAndCheckHelloWorld(HELLO_WORLD_MSG1);
|
|
+ createHelloWorld(HELLO_WORLD_MSG2);
|
|
+ runAndCheckHelloWorld(HELLO_WORLD_MSG2);
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/verification/vmflags/BasicFlagsChange.java b/test/hotspot/jtreg/compiler/aot/verification/vmflags/BasicFlagsChange.java
|
|
new file mode 100644
|
|
index 000000000..c0eefb5f9
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/verification/vmflags/BasicFlagsChange.java
|
|
@@ -0,0 +1,112 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 compiler.aot.verification.vmflags;
|
|
+
|
|
+import jdk.test.lib.process.OutputAnalyzer;
|
|
+import jdk.test.lib.process.ProcessTools;
|
|
+import jdk.test.lib.Utils;
|
|
+import compiler.aot.HelloWorldPrinter;
|
|
+import compiler.aot.AotCompiler;
|
|
+import java.io.File;
|
|
+import java.util.ArrayList;
|
|
+import java.util.List;
|
|
+
|
|
+/**
|
|
+ * A class with common launch and check logic for testing vm flags change
|
|
+ */
|
|
+public class BasicFlagsChange {
|
|
+ private static final boolean CAN_LOAD = true;
|
|
+ /**
|
|
+ * A main method which parse arguments, expecting vm option name to
|
|
+ * be present, launch java process with combinations of provided flag
|
|
+ * enabled/disable in aot library and vm flag expecting different flag
|
|
+ * values in library and vm to be negative cases
|
|
+ * @param args should have true/false treated as "loadAlways" for
|
|
+ * tracked/non-tracked options and vm option name
|
|
+ */
|
|
+ public static void main(String args[]) {
|
|
+ if (args.length != 2) {
|
|
+ throw new Error("TESTBUG: Unexpected number of arguments: "
|
|
+ + args.length);
|
|
+ }
|
|
+ if (!"false".equals(args[0]) && !"true".equals(args[0])) {
|
|
+ throw new Error("TESTBUG: unexpected value of 1st parameter: "
|
|
+ + args[0]);
|
|
+ }
|
|
+ boolean loadAlways = Boolean.parseBoolean(args[0]);
|
|
+ String optName = args[1];
|
|
+ String optEnabled = "-XX:+" + optName;
|
|
+ String optDisabled = "-XX:-" + optName;
|
|
+ String enabledLibName = "libEnabled.so";
|
|
+ String disabledLibName = "libDisabled.so";
|
|
+ // compile libraries
|
|
+ compileLibrary(optEnabled, enabledLibName);
|
|
+ compileLibrary(optDisabled, disabledLibName);
|
|
+ // run 4 combinations
|
|
+ runAndCheck(optEnabled, enabledLibName, CAN_LOAD || loadAlways);
|
|
+ runAndCheck(optDisabled, enabledLibName, !CAN_LOAD || loadAlways);
|
|
+ runAndCheck(optEnabled, disabledLibName, !CAN_LOAD || loadAlways);
|
|
+ runAndCheck(optDisabled, disabledLibName, CAN_LOAD || loadAlways);
|
|
+ }
|
|
+
|
|
+ private static void compileLibrary(String option, String libName) {
|
|
+ String className = BasicFlagsChange.class.getName();
|
|
+ List<String> extraOpts = new ArrayList<>();
|
|
+ extraOpts.add(option);
|
|
+ extraOpts.add("-classpath");
|
|
+ extraOpts.add(Utils.TEST_CLASS_PATH + File.pathSeparator + Utils.TEST_SRC);
|
|
+ AotCompiler.launchCompiler(libName, className, extraOpts, null);
|
|
+ }
|
|
+
|
|
+ private static void runAndCheck(String option, String libName,
|
|
+ boolean positiveCase) {
|
|
+ ProcessBuilder pb;
|
|
+ try {
|
|
+ /* using +PrintAOT to check if library has been loaded or skipped,
|
|
+ so, a message like "skipped $pathTolibrary aot library" or
|
|
+ "loaded $pathToLibrary aot library" is present for cases of
|
|
+ incompatible or compatible flags respectively */
|
|
+ pb = ProcessTools.createTestJvm("-XX:+UnlockExperimentalVMOptions",
|
|
+ "-XX:+UseAOT", "-XX:+PrintAOT", "-XX:AOTLibrary=./" + libName, option,
|
|
+ HelloWorldPrinter.class.getName());
|
|
+ } catch (Exception ex) {
|
|
+ throw new Error("Problems creating ProcessBuilder using " + option
|
|
+ + " Caused by: " + ex, ex);
|
|
+ }
|
|
+ OutputAnalyzer oa;
|
|
+ try {
|
|
+ oa = ProcessTools.executeProcess(pb);
|
|
+ } catch (Exception ex) {
|
|
+ throw new Error("Problems execution child process using case "
|
|
+ + option + " Caused by: " + ex, ex);
|
|
+ }
|
|
+ oa.shouldHaveExitValue(0);
|
|
+ oa.shouldContain(HelloWorldPrinter.MESSAGE);
|
|
+ if (positiveCase) {
|
|
+ oa.shouldContain("loaded ./" + libName + " aot library");
|
|
+ } else {
|
|
+ oa.shouldContain("skipped ./" + libName + " aot library");
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/verification/vmflags/NotTrackedFlagTest.java b/test/hotspot/jtreg/compiler/aot/verification/vmflags/NotTrackedFlagTest.java
|
|
new file mode 100644
|
|
index 000000000..306e7d9e6
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/verification/vmflags/NotTrackedFlagTest.java
|
|
@@ -0,0 +1,33 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 /
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.aot.verification.vmflags.BasicFlagsChange
|
|
+ * @run driver compiler.aot.verification.vmflags.BasicFlagsChange
|
|
+ * true PrintCommandLineFlags
|
|
+ * @summary check if some not aot-related vm flag change doesn't affect aot library loading
|
|
+ */
|
|
diff --git a/test/hotspot/jtreg/compiler/aot/verification/vmflags/TrackedFlagTest.java b/test/hotspot/jtreg/compiler/aot/verification/vmflags/TrackedFlagTest.java
|
|
new file mode 100644
|
|
index 000000000..382399a05
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/compiler/aot/verification/vmflags/TrackedFlagTest.java
|
|
@@ -0,0 +1,34 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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 /
|
|
+ * @modules java.base/jdk.internal.misc
|
|
+ * @build compiler.aot.verification.vmflags.BasicFlagsChange
|
|
+ * @run driver compiler.aot.verification.vmflags.BasicFlagsChange
|
|
+ * false UseCompressedOops
|
|
+ * @summary check if tracked flag UseCompressedOops is controlled properly
|
|
+ */
|
|
+
|
|
diff --git a/test/hotspot/jtreg/compiler/intrinsics/bigInteger/TestMulAdd.java b/test/hotspot/jtreg/compiler/intrinsics/bigInteger/TestMulAdd.java
|
|
index f72cc8cb5..14942dfa5 100644
|
|
--- a/test/hotspot/jtreg/compiler/intrinsics/bigInteger/TestMulAdd.java
|
|
+++ b/test/hotspot/jtreg/compiler/intrinsics/bigInteger/TestMulAdd.java
|
|
@@ -26,6 +26,8 @@
|
|
* @key randomness
|
|
* @bug 8081778
|
|
* @summary Add C2 x86 intrinsic for BigInteger::mulAdd() method
|
|
+ * @comment the test disables intrinsics, so it can't be run w/ AOT'ed java.base
|
|
+ * @requires !vm.aot.enabled
|
|
*
|
|
* @library /test/lib
|
|
* @run main/othervm/timeout=600 -XX:-TieredCompilation -Xbatch
|
|
diff --git a/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestMD5Intrinsics.java b/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestMD5Intrinsics.java
|
|
index 16f2b6cc5..db165cc56 100644
|
|
--- a/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestMD5Intrinsics.java
|
|
+++ b/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestMD5Intrinsics.java
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2020, 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
|
|
@@ -25,6 +25,8 @@
|
|
* @test
|
|
* @bug 8035968
|
|
* @summary Verify that MD5 intrinsic is actually used.
|
|
+ * @comment the test verifies compilation of java.base methods, so it can't be run w/ AOT'ed java.base
|
|
+ * @requires !vm.aot.enabled
|
|
*
|
|
* @library /test/lib /
|
|
* @modules java.base/jdk.internal.misc
|
|
diff --git a/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestMD5MultiBlockIntrinsics.java b/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestMD5MultiBlockIntrinsics.java
|
|
index d6c9006ee..b9473ea91 100644
|
|
--- a/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestMD5MultiBlockIntrinsics.java
|
|
+++ b/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestMD5MultiBlockIntrinsics.java
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2020, 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
|
|
@@ -25,6 +25,8 @@
|
|
* @test
|
|
* @bug 8035968
|
|
* @summary Verify that MD5 multi block intrinsic is actually used.
|
|
+ * @comment the test verifies compilation of java.base methods, so it can't be run w/ AOT'ed java.base
|
|
+ * @requires !vm.aot.enabled
|
|
*
|
|
* @library /test/lib /
|
|
* @modules java.base/jdk.internal.misc
|
|
diff --git a/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestSHA1Intrinsics.java b/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestSHA1Intrinsics.java
|
|
index 5a756a6ec..ca3d5751f 100644
|
|
--- a/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestSHA1Intrinsics.java
|
|
+++ b/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestSHA1Intrinsics.java
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2014, 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
|
|
@@ -25,6 +25,8 @@
|
|
* @test
|
|
* @bug 8035968
|
|
* @summary Verify that SHA-1 intrinsic is actually used.
|
|
+ * @comment the test verifies compilation of java.base methods, so it can't be run w/ AOT'ed java.base
|
|
+ * @requires !vm.aot.enabled
|
|
*
|
|
* @library /test/lib /
|
|
* @modules java.base/jdk.internal.misc
|
|
diff --git a/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestSHA1MultiBlockIntrinsics.java b/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestSHA1MultiBlockIntrinsics.java
|
|
index 415bbe6ec..753dcdb48 100644
|
|
--- a/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestSHA1MultiBlockIntrinsics.java
|
|
+++ b/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestSHA1MultiBlockIntrinsics.java
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2014, 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
|
|
@@ -25,6 +25,8 @@
|
|
* @test
|
|
* @bug 8035968
|
|
* @summary Verify that SHA-1 multi block intrinsic is actually used.
|
|
+ * @comment the test verifies compilation of java.base methods, so it can't be run w/ AOT'ed java.base
|
|
+ * @requires !vm.aot.enabled
|
|
*
|
|
* @library /test/lib /
|
|
* @modules java.base/jdk.internal.misc
|
|
diff --git a/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestSHA256Intrinsics.java b/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestSHA256Intrinsics.java
|
|
index 607a48a45..7567aadac 100644
|
|
--- a/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestSHA256Intrinsics.java
|
|
+++ b/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestSHA256Intrinsics.java
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2014, 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
|
|
@@ -25,6 +25,8 @@
|
|
* @test
|
|
* @bug 8035968
|
|
* @summary Verify that SHA-256 intrinsic is actually used.
|
|
+ * @comment the test verifies compilation of java.base methods, so it can't be run w/ AOT'ed java.base
|
|
+ * @requires !vm.aot.enabled
|
|
*
|
|
* @library /test/lib /
|
|
* @modules java.base/jdk.internal.misc
|
|
diff --git a/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestSHA256MultiBlockIntrinsics.java b/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestSHA256MultiBlockIntrinsics.java
|
|
index a1200d183..c3d01e8f2 100644
|
|
--- a/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestSHA256MultiBlockIntrinsics.java
|
|
+++ b/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestSHA256MultiBlockIntrinsics.java
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2014, 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
|
|
@@ -25,6 +25,8 @@
|
|
* @test
|
|
* @bug 8035968
|
|
* @summary Verify that SHA-256 multi block intrinsic is actually used.
|
|
+ * @comment the test verifies compilation of java.base methods, so it can't be run w/ AOT'ed java.base
|
|
+ * @requires !vm.aot.enabled
|
|
*
|
|
* @library /test/lib /
|
|
* @modules java.base/jdk.internal.misc
|
|
diff --git a/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestSHA3Intrinsics.java b/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestSHA3Intrinsics.java
|
|
index df90a545d..892d1a8a4 100644
|
|
--- a/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestSHA3Intrinsics.java
|
|
+++ b/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestSHA3Intrinsics.java
|
|
@@ -1,6 +1,6 @@
|
|
/*
|
|
- * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
|
- * Copyright (c) 2020, Huawei Technologies Co., Ltd. All rights reserved.
|
|
+ * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2020, 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
|
|
@@ -26,6 +26,8 @@
|
|
* @test
|
|
* @bug 8252204
|
|
* @summary Verify that SHA3-224, SHA3-256, SHA3-384, SHA3-512 intrinsic is actually used.
|
|
+ * @comment the test verifies compilation of java.base methods, so it can't be run w/ AOT'ed java.base
|
|
+ * @requires !vm.aot.enabled
|
|
*
|
|
* @library /test/lib /
|
|
* @modules java.base/jdk.internal.misc
|
|
diff --git a/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestSHA3MultiBlockIntrinsics.java b/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestSHA3MultiBlockIntrinsics.java
|
|
index 1e01b543f..53eafe3ce 100644
|
|
--- a/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestSHA3MultiBlockIntrinsics.java
|
|
+++ b/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestSHA3MultiBlockIntrinsics.java
|
|
@@ -1,6 +1,6 @@
|
|
/*
|
|
- * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
|
- * Copyright (c) 2020, Huawei Technologies Co., Ltd. All rights reserved.
|
|
+ * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2020, 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
|
|
@@ -26,6 +26,8 @@
|
|
* @test
|
|
* @bug 8252204
|
|
* @summary Verify that SHA3-224, SHA3-256, SHA3-384, SHA3-512 multi block intrinsic is actually used.
|
|
+ * @comment the test verifies compilation of java.base methods, so it can't be run w/ AOT'ed java.base
|
|
+ * @requires !vm.aot.enabled
|
|
*
|
|
* @library /test/lib /
|
|
* @modules java.base/jdk.internal.misc
|
|
diff --git a/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestSHA512Intrinsics.java b/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestSHA512Intrinsics.java
|
|
index 2a5f9bf09..259d6cf99 100644
|
|
--- a/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestSHA512Intrinsics.java
|
|
+++ b/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestSHA512Intrinsics.java
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2014, 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
|
|
@@ -25,6 +25,8 @@
|
|
* @test
|
|
* @bug 8035968
|
|
* @summary Verify that SHA-512 intrinsic is actually used.
|
|
+ * @comment the test verifies compilation of java.base methods, so it can't be run w/ AOT'ed java.base
|
|
+ * @requires !vm.aot.enabled
|
|
*
|
|
* @library /test/lib /
|
|
* @modules java.base/jdk.internal.misc
|
|
diff --git a/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestSHA512MultiBlockIntrinsics.java b/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestSHA512MultiBlockIntrinsics.java
|
|
index 5caf35f23..12583507f 100644
|
|
--- a/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestSHA512MultiBlockIntrinsics.java
|
|
+++ b/test/hotspot/jtreg/compiler/intrinsics/sha/sanity/TestSHA512MultiBlockIntrinsics.java
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2014, 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
|
|
@@ -25,6 +25,8 @@
|
|
* @test
|
|
* @bug 8035968
|
|
* @summary Verify that SHA-512 multi block intrinsic is actually used.
|
|
+ * @comment the test verifies compilation of java.base methods, so it can't be run w/ AOT'ed java.base
|
|
+ * @requires !vm.aot.enabled
|
|
*
|
|
* @library /test/lib /
|
|
* @modules java.base/jdk.internal.misc
|
|
diff --git a/test/hotspot/jtreg/compiler/whitebox/CompilerWhiteBoxTest.java b/test/hotspot/jtreg/compiler/whitebox/CompilerWhiteBoxTest.java
|
|
index 407aac786..30bb71236 100644
|
|
--- a/test/hotspot/jtreg/compiler/whitebox/CompilerWhiteBoxTest.java
|
|
+++ b/test/hotspot/jtreg/compiler/whitebox/CompilerWhiteBoxTest.java
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2013, 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
|
|
@@ -41,6 +41,8 @@ import java.util.function.Function;
|
|
public abstract class CompilerWhiteBoxTest {
|
|
/** {@code CompLevel::CompLevel_none} -- Interpreter */
|
|
public static final int COMP_LEVEL_NONE = 0;
|
|
+ /** {@code CompLevel::CompLevel_aot} -- AOT */
|
|
+ public static final int COMP_LEVEL_AOT = -2;
|
|
/** {@code CompLevel::CompLevel_any}, {@code CompLevel::CompLevel_all} */
|
|
public static final int COMP_LEVEL_ANY = -1;
|
|
/** {@code CompLevel::CompLevel_simple} -- C1 */
|
|
diff --git a/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointers.java b/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointers.java
|
|
index 8e2033e73..ccbaddeb5 100644
|
|
--- a/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointers.java
|
|
+++ b/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointers.java
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2013, 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
|
|
@@ -94,6 +94,7 @@ public class CompressedClassPointers {
|
|
"-XX:+UnlockDiagnosticVMOptions",
|
|
"-XX:+UnlockExperimentalVMOptions",
|
|
"-Xmx30g",
|
|
+ "-XX:-UseAOT", // AOT explicitly set klass shift to 3.
|
|
logging_option,
|
|
"-Xshare:off",
|
|
"-XX:+VerifyBeforeGC", "-version");
|
|
@@ -119,6 +120,7 @@ public class CompressedClassPointers {
|
|
"-XX:+UnlockDiagnosticVMOptions",
|
|
"-XX:+UnlockExperimentalVMOptions",
|
|
"-Xmx31g",
|
|
+ "-XX:-UseAOT", // AOT explicitly set klass shift to 3.
|
|
logging_option,
|
|
"-Xshare:off",
|
|
"-XX:+VerifyBeforeGC", "-version");
|
|
@@ -238,6 +240,7 @@ public class CompressedClassPointers {
|
|
"-XX:+UnlockDiagnosticVMOptions",
|
|
"-XX:+UnlockExperimentalVMOptions",
|
|
"-Xmx30g",
|
|
+ "-XX:-UseAOT", // AOT explicitly set klass shift to 3.
|
|
"-Xlog:gc+metaspace=trace",
|
|
"-Xshare:off",
|
|
"-Xlog:cds=trace",
|
|
diff --git a/test/hotspot/jtreg/runtime/cds/TestInterpreterMethodEntries.java b/test/hotspot/jtreg/runtime/cds/TestInterpreterMethodEntries.java
|
|
index a29432f36..e258ee8c3 100644
|
|
--- a/test/hotspot/jtreg/runtime/cds/TestInterpreterMethodEntries.java
|
|
+++ b/test/hotspot/jtreg/runtime/cds/TestInterpreterMethodEntries.java
|
|
@@ -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
|
|
@@ -27,6 +27,8 @@
|
|
* @summary Test interpreter method entries for intrinsics with CDS (class data sharing)
|
|
* and the intrinsic flag enabled during dump and disabled during use of the archive.
|
|
* @requires vm.cds
|
|
+ * @comment the test disables intrinsics, so it can't be run w/ AOT'ed java module
|
|
+ * @requires !vm.aot.enabled
|
|
* @library /test/lib
|
|
* @run driver TestInterpreterMethodEntries true false
|
|
*/
|
|
diff --git a/test/hotspot/jtreg/serviceability/dcmd/compiler/CodelistTest.java b/test/hotspot/jtreg/serviceability/dcmd/compiler/CodelistTest.java
|
|
index 260de5c1e..c93d943f4 100644
|
|
--- a/test/hotspot/jtreg/serviceability/dcmd/compiler/CodelistTest.java
|
|
+++ b/test/hotspot/jtreg/serviceability/dcmd/compiler/CodelistTest.java
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2014, 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
|
|
@@ -120,7 +120,7 @@ public class CodelistTest {
|
|
Assert.assertTrue(compileID > 0, "CompileID must be positive");
|
|
|
|
int compileLevel = Integer.parseInt(parts[1]);
|
|
- Assert.assertTrue(compileLevel >= -1, "CompileLevel must be at least -1 (Any)");
|
|
+ Assert.assertTrue(compileLevel >= -1, "CompileLevel must be at least -1 (AOT)");
|
|
Assert.assertTrue(compileLevel <= 4, "CompileLevel must be at most 4 (C2)");
|
|
|
|
int codeState = Integer.parseInt(parts[2]);
|
|
diff --git a/test/hotspot/jtreg/testlibrary/jittester/Makefile b/test/hotspot/jtreg/testlibrary/jittester/Makefile
|
|
index 32548e6cd..fdc34fe69 100644
|
|
--- a/test/hotspot/jtreg/testlibrary/jittester/Makefile
|
|
+++ b/test/hotspot/jtreg/testlibrary/jittester/Makefile
|
|
@@ -1,5 +1,5 @@
|
|
#
|
|
-# Copyright (c) 2015, 2021, 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
|
|
@@ -108,7 +108,7 @@ filelist: $(SRC_FILES)
|
|
INIT: $(DIST_DIR)
|
|
$(shell if [ ! -d $(CLASSES_DIR) ]; then mkdir -p $(CLASSES_DIR); fi)
|
|
|
|
-install: clean_testbase testgroup testroot copytestlibrary $(DIST_JAR) cleantmp
|
|
+install: clean_testbase testgroup testroot copytestlibrary copyaot $(DIST_JAR) cleantmp
|
|
$(JAVA) --add-exports=java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED -ea -jar $(DIST_JAR) $(APPLICATION_ARGS)
|
|
|
|
clean_testbase:
|
|
@@ -122,6 +122,9 @@ copytestlibrary: $(TESTBASE_DIR)/jdk/test/lib/jittester/jtreg
|
|
@cp -r src/jdk/test/lib/jittester/jtreg/*.java $(TESTBASE_DIR)/jdk/test/lib/jittester/jtreg
|
|
@cp -r $(TESTLIBRARY_SRC_DIR) $(TESTBASE_DIR)/jdk/test/
|
|
|
|
+copyaot: $(TESTBASE_DIR)/compiler/aot
|
|
+ @cp ../../compiler/aot/AotCompiler.java $(TESTBASE_DIR)/compiler/aot
|
|
+
|
|
testgroup: $(TESTBASE_DIR)
|
|
@echo 'jittester_all = \' > $(TESTGROUP_FILE)
|
|
@echo ' /' >> $(TESTGROUP_FILE)
|
|
@@ -130,9 +133,13 @@ testgroup: $(TESTBASE_DIR)
|
|
@echo ' java_tests \' >> $(TESTGROUP_FILE)
|
|
@echo ' bytecode_tests' >> $(TESTGROUP_FILE)
|
|
@echo '' >> $(TESTGROUP_FILE)
|
|
+ @echo 'aot_tests = \' >> $(TESTGROUP_FILE)
|
|
+ @echo ' aot_bytecode_tests \' >> $(TESTGROUP_FILE)
|
|
+ @echo ' aot_java_tests' >> $(TESTGROUP_FILE)
|
|
+ @echo '' >> $(TESTGROUP_FILE)
|
|
|
|
testroot: $(TESTBASE_DIR)
|
|
@echo 'groups=TEST.groups' > $(TESTROOT_FILE)
|
|
|
|
-$(TESTBASE_DIR) $(DIST_DIR) $(TESTBASE_DIR)/jdk/test/lib/jittester/jtreg:
|
|
+$(TESTBASE_DIR) $(DIST_DIR) $(TESTBASE_DIR)/jdk/test/lib/jittester/jtreg $(TESTBASE_DIR)/compiler/aot:
|
|
$(shell if [ ! -d $@ ]; then mkdir -p $@; fi)
|
|
diff --git a/test/hotspot/jtreg/testlibrary/jittester/conf/default.properties b/test/hotspot/jtreg/testlibrary/jittester/conf/default.properties
|
|
index cd559e591..0573cc1d4 100644
|
|
--- a/test/hotspot/jtreg/testlibrary/jittester/conf/default.properties
|
|
+++ b/test/hotspot/jtreg/testlibrary/jittester/conf/default.properties
|
|
@@ -9,5 +9,5 @@ exclude-methods-file=conf/exclude.methods.lst
|
|
print-complexity=true
|
|
print-hierarchy=true
|
|
disable-static=true
|
|
-generatorsFactories=jdk.test.lib.jittester.TestGeneratorsFactory
|
|
+generatorsFactories=jdk.test.lib.jittester.TestGeneratorsFactory,jdk.test.lib.jittester.AotTestGeneratorsFactory
|
|
generators=JavaCode,ByteCode
|
|
diff --git a/test/hotspot/jtreg/testlibrary/jittester/src/jdk/test/lib/jittester/AotTestGeneratorsFactory.java b/test/hotspot/jtreg/testlibrary/jittester/src/jdk/test/lib/jittester/AotTestGeneratorsFactory.java
|
|
new file mode 100644
|
|
index 000000000..2f0db9a7e
|
|
--- /dev/null
|
|
+++ b/test/hotspot/jtreg/testlibrary/jittester/src/jdk/test/lib/jittester/AotTestGeneratorsFactory.java
|
|
@@ -0,0 +1,72 @@
|
|
+/*
|
|
+ * 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
|
|
+ * 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.test.lib.jittester;
|
|
+
|
|
+import java.util.ArrayList;
|
|
+import java.util.List;
|
|
+import java.util.function.Function;
|
|
+
|
|
+public class AotTestGeneratorsFactory implements Function<String[], List<TestsGenerator>> {
|
|
+ private static final String AOT_OPTIONS
|
|
+ = "-XX:+UnlockExperimentalVMOptions -XX:+UseAOT -XX:AOTLibrary=./aottest.so";
|
|
+ private static final String AOT_COMPILER_BUILD_ACTION
|
|
+ = "@build compiler.aot.AotCompiler";
|
|
+ private static final String AOT_COMPILER_RUN_ACTION_PREFIX
|
|
+ = "@run driver compiler.aot.AotCompiler -extraopt -Xmixed -libname aottest.so -class ";
|
|
+
|
|
+ @Override
|
|
+ public List<TestsGenerator> apply(String[] input) {
|
|
+ List<TestsGenerator> result = new ArrayList<>();
|
|
+ for (String generatorName : input) {
|
|
+ switch (generatorName) {
|
|
+ case "ByteCode":
|
|
+ result.add(new ByteCodeGenerator("aot_bytecode_tests",
|
|
+ AotTestGeneratorsFactory::generateBytecodeHeader, AOT_OPTIONS));
|
|
+ break;
|
|
+ case "JavaCode":
|
|
+ result.add(new JavaCodeGenerator("aot_java_tests",
|
|
+ AotTestGeneratorsFactory::generateJavaHeader, AOT_OPTIONS));
|
|
+ break;
|
|
+ default:
|
|
+ throw new IllegalArgumentException("Unknown generator: " + generatorName);
|
|
+ }
|
|
+ }
|
|
+ return result;
|
|
+ }
|
|
+
|
|
+ private static String[] generateBytecodeHeader(String mainClassName) {
|
|
+ return new String[]{
|
|
+ AOT_COMPILER_BUILD_ACTION,
|
|
+ AOT_COMPILER_RUN_ACTION_PREFIX + mainClassName
|
|
+ };
|
|
+ }
|
|
+
|
|
+ private static String[] generateJavaHeader(String mainClassName) {
|
|
+ return new String[]{
|
|
+ "@compile " + mainClassName + ".java",
|
|
+ AOT_COMPILER_BUILD_ACTION,
|
|
+ AOT_COMPILER_RUN_ACTION_PREFIX + mainClassName
|
|
+ };
|
|
+ }
|
|
+}
|
|
diff --git a/test/hotspot/jtreg/vmTestbase/vm/compiler/CodeCacheInfo/Test.java b/test/hotspot/jtreg/vmTestbase/vm/compiler/CodeCacheInfo/Test.java
|
|
index 118d6c8f8..a3cc54cfd 100644
|
|
--- a/test/hotspot/jtreg/vmTestbase/vm/compiler/CodeCacheInfo/Test.java
|
|
+++ b/test/hotspot/jtreg/vmTestbase/vm/compiler/CodeCacheInfo/Test.java
|
|
@@ -62,6 +62,15 @@ public class Test {
|
|
String segPrefix = "^(CodeHeap '[^']+':" + p1 + p2 + ")+";
|
|
String nosegPrefix = "^CodeCache:" + p1 + p2;
|
|
|
|
+ // check if AOT is enabled
|
|
+ if (WhiteBox.getWhiteBox().aotLibrariesCount() > 0) {
|
|
+ System.out.println("AOT is enabled");
|
|
+ String aotSegment = "CodeHeap 'AOT':" + p1 + p2;
|
|
+ segPrefix += aotSegment;
|
|
+ nosegPrefix += aotSegment;
|
|
+ } else {
|
|
+ System.out.println("AOT is not enabled");
|
|
+ }
|
|
SEG_REGEXP = segPrefix + p3 + p4;
|
|
NOSEG_REGEXP = nosegPrefix + p3 + p4;
|
|
}
|
|
diff --git a/test/jdk/ProblemList-aot.txt b/test/jdk/ProblemList-aot.txt
|
|
new file mode 100644
|
|
index 000000000..722f4c9e3
|
|
--- /dev/null
|
|
+++ b/test/jdk/ProblemList-aot.txt
|
|
@@ -0,0 +1,34 @@
|
|
+#
|
|
+# Copyright (c) 2019, 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
|
|
+# 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.
|
|
+#
|
|
+
|
|
+#############################################################################
|
|
+#
|
|
+# List of quarantined tests for testing AOT.
|
|
+#
|
|
+#############################################################################
|
|
+
|
|
+java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java 8222445 windows-x64
|
|
+java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java 8222445 windows-x64
|
|
+java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java 8222445 windows-x64
|
|
+java/lang/reflect/PublicMethods/PublicMethodsTest.java 8226309 generic-all
|
|
+java/lang/constant/MethodTypeDescTest.java 8225349 windows-x64
|
|
diff --git a/test/jdk/java/lang/Class/getDeclaredField/FieldSetAccessibleTest.java b/test/jdk/java/lang/Class/getDeclaredField/FieldSetAccessibleTest.java
|
|
index 12cab1f5d..7c647d6d4 100644
|
|
--- a/test/jdk/java/lang/Class/getDeclaredField/FieldSetAccessibleTest.java
|
|
+++ b/test/jdk/java/lang/Class/getDeclaredField/FieldSetAccessibleTest.java
|
|
@@ -312,8 +312,8 @@ public class FieldSetAccessibleTest {
|
|
|
|
Set<String> mods = Set.of(
|
|
// All JVMCI packages other than jdk.vm.ci.services are dynamically
|
|
- // exported to jdk.internal.vm.compiler
|
|
- "jdk.internal.vm.compiler", "jdk.internal.vm.compiler.management"
|
|
+ // exported to jdk.internal.vm.compiler and jdk.aot
|
|
+ "jdk.internal.vm.compiler", "jdk.internal.vm.compiler.management", "jdk.aot"
|
|
);
|
|
// Filters all modules that directly or indirectly require jdk.internal.vm.compiler
|
|
// and jdk.internal.vm.compiler.management, as these are upgradeable and
|
|
diff --git a/test/jdk/jdk/modules/etc/UpgradeableModules.java b/test/jdk/jdk/modules/etc/UpgradeableModules.java
|
|
index 59ff5aa6b..a7e467b50 100644
|
|
--- a/test/jdk/jdk/modules/etc/UpgradeableModules.java
|
|
+++ b/test/jdk/jdk/modules/etc/UpgradeableModules.java
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2017, 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
|
|
@@ -44,6 +44,7 @@ import java.util.stream.Collectors;
|
|
public class UpgradeableModules {
|
|
private static final List<String> UPGRADEABLE_MODULES =
|
|
List.of("java.compiler",
|
|
+ "jdk.aot",
|
|
"jdk.internal.vm.compiler",
|
|
"jdk.internal.vm.compiler.management");
|
|
|
|
diff --git a/test/jdk/tools/jimage/VerifyJimage.java b/test/jdk/tools/jimage/VerifyJimage.java
|
|
index 59d0a5cec..e1012d6ad 100644
|
|
--- a/test/jdk/tools/jimage/VerifyJimage.java
|
|
+++ b/test/jdk/tools/jimage/VerifyJimage.java
|
|
@@ -197,7 +197,7 @@ public class VerifyJimage {
|
|
|
|
// All JVMCI packages other than jdk.vm.ci.services are dynamically
|
|
// exported to jdk.internal.vm.compiler
|
|
- private static Set<String> EXCLUDED_MODULES = Set.of("jdk.internal.vm.compiler");
|
|
+ private static Set<String> EXCLUDED_MODULES = Set.of("jdk.internal.vm.compiler", "jdk.aot");
|
|
|
|
private boolean accept(String entry) {
|
|
int index = entry.indexOf('/', 1);
|
|
diff --git a/test/jdk/tools/launcher/HelpFlagsTest.java b/test/jdk/tools/launcher/HelpFlagsTest.java
|
|
index 62405855d..f7a4acd0c 100644
|
|
--- a/test/jdk/tools/launcher/HelpFlagsTest.java
|
|
+++ b/test/jdk/tools/launcher/HelpFlagsTest.java
|
|
@@ -1,6 +1,6 @@
|
|
/*
|
|
- * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
- * Copyright (c) 2018, 2020 SAP SE. All rights reserved.
|
|
+ * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2018, 2023 SAP SE. 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
|
|
@@ -122,6 +122,7 @@ public class HelpFlagsTest extends TestHelper {
|
|
// of help docu of wrong
|
|
// mented flag
|
|
new ToolHelpSpec("jabswitch", 0, 0, 0, 0, 0, 0, 0), // /?, prints help message anyways, win only
|
|
+ new ToolHelpSpec("jaotc", 1, 1, 1, 0, 0, 0, 2), // -?, -h, --help
|
|
new ToolHelpSpec("jar", 1, 1, 1, 0, 0, 0, 1), // -?, -h, --help
|
|
new ToolHelpSpec("jarsigner", 1, 1, 1, 0, 1, 0, 1), // -?, -h, --help, -help accepted but not documented.
|
|
new ToolHelpSpec("java", 1, 1, 1, 0, 1, 1, 1), // -?, -h, --help -help, Documents -help
|
|
diff --git a/test/jdk/tools/launcher/VersionCheck.java b/test/jdk/tools/launcher/VersionCheck.java
|
|
index c5b488d76..1fd5dd99a 100644
|
|
--- a/test/jdk/tools/launcher/VersionCheck.java
|
|
+++ b/test/jdk/tools/launcher/VersionCheck.java
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2007, 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
|
|
@@ -54,6 +54,7 @@ public class VersionCheck extends TestHelper {
|
|
"jaccessinspector-32",
|
|
"jaccesswalker",
|
|
"jaccesswalker-32",
|
|
+ "jaotc",
|
|
"javaw",
|
|
"javaws",
|
|
"jbooster",
|
|
@@ -73,6 +74,7 @@ public class VersionCheck extends TestHelper {
|
|
"jaccessinspector-32",
|
|
"jaccesswalker",
|
|
"jaccesswalker-32",
|
|
+ "jaotc",
|
|
"jar",
|
|
"jarsigner",
|
|
"java-rmi",
|
|
diff --git a/test/jtreg-ext/requires/VMProps.java b/test/jtreg-ext/requires/VMProps.java
|
|
index 452f3c9dc..e696966b5 100644
|
|
--- a/test/jtreg-ext/requires/VMProps.java
|
|
+++ b/test/jtreg-ext/requires/VMProps.java
|
|
@@ -112,6 +112,8 @@ public class VMProps implements Callable<Map<String, String>> {
|
|
map.put("vm.pageSize", this::vmPageSize);
|
|
map.put("vm.rtm.cpu", this::vmRTMCPU);
|
|
map.put("vm.rtm.compiler", this::vmRTMCompiler);
|
|
+ map.put("vm.aot", this::vmAOT);
|
|
+ map.put("vm.aot.enabled", this::vmAotEnabled);
|
|
// vm.cds is true if the VM is compiled with cds support.
|
|
map.put("vm.cds", this::vmCDS);
|
|
map.put("vm.cds.custom.loaders", this::vmCDSForCustomLoaders);
|
|
@@ -372,6 +374,46 @@ public class VMProps implements Callable<Map<String, String>> {
|
|
return "" + CPUInfo.hasFeature("rtm");
|
|
}
|
|
|
|
+ /**
|
|
+ * @return true if VM supports AOT and false otherwise
|
|
+ */
|
|
+ protected String vmAOT() {
|
|
+ // builds with aot have jaotc in <JDK>/bin
|
|
+ Path bin = Paths.get(System.getProperty("java.home"))
|
|
+ .resolve("bin");
|
|
+ Path jaotc;
|
|
+ if (Platform.isWindows()) {
|
|
+ jaotc = bin.resolve("jaotc.exe");
|
|
+ } else {
|
|
+ jaotc = bin.resolve("jaotc");
|
|
+ }
|
|
+
|
|
+ if (!Files.exists(jaotc)) {
|
|
+ // No jaotc => no AOT
|
|
+ return "false";
|
|
+ }
|
|
+
|
|
+ switch (GC.selected()) {
|
|
+ case Serial:
|
|
+ case Parallel:
|
|
+ case G1:
|
|
+ // These GCs are supported with AOT
|
|
+ return "true";
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ // Every other GC is not supported
|
|
+ return "false";
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * @return true if there is at least one loaded AOT'ed library.
|
|
+ */
|
|
+ protected String vmAotEnabled() {
|
|
+ return "" + (WB.aotLibrariesCount() > 0);
|
|
+ }
|
|
+
|
|
/**
|
|
* Check for CDS support.
|
|
*
|
|
diff --git a/test/lib/jdk/test/whitebox/WhiteBox.java b/test/lib/jdk/test/whitebox/WhiteBox.java
|
|
index 5a0ab744a..55972aa1b 100644
|
|
--- a/test/lib/jdk/test/whitebox/WhiteBox.java
|
|
+++ b/test/lib/jdk/test/whitebox/WhiteBox.java
|
|
@@ -638,6 +638,9 @@ public class WhiteBox {
|
|
// Protection Domain Table
|
|
public native int protectionDomainRemovedCount();
|
|
|
|
+ // Number of loaded AOT libraries
|
|
+ public native int aotLibrariesCount();
|
|
+
|
|
public native int getKlassMetadataSize(Class<?> c);
|
|
|
|
// ThreadSMR GC safety check for threadObj
|
|
diff --git a/test/lib/jdk/test/whitebox/code/CodeBlob.java b/test/lib/jdk/test/whitebox/code/CodeBlob.java
|
|
index c6c23fdff..2b99a9a2f 100644
|
|
--- a/test/lib/jdk/test/whitebox/code/CodeBlob.java
|
|
+++ b/test/lib/jdk/test/whitebox/code/CodeBlob.java
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2014, 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
|
|
@@ -50,8 +50,12 @@ public class CodeBlob {
|
|
name = (String) obj[0];
|
|
size = (Integer) obj[1];
|
|
int blob_type_index = (Integer) obj[2];
|
|
- code_blob_type = BlobType.values()[blob_type_index];
|
|
- assert code_blob_type.id == (Integer) obj[2];
|
|
+ if (blob_type_index == -1) { // AOT
|
|
+ code_blob_type = null;
|
|
+ } else {
|
|
+ code_blob_type = BlobType.values()[blob_type_index];
|
|
+ assert code_blob_type.id == (Integer) obj[2];
|
|
+ }
|
|
address = (Long) obj[3];
|
|
}
|
|
public final String name;
|
|
--
|
|
2.19.1
|
|
|