8171008: Integrate AOT compiler into JDK
authorkvn
Sun, 11 Dec 2016 19:07:04 -0800
changeset 42650 1f304d0c888b
parent 42649 28238583a459
child 42651 8883ad66f6a9
8171008: Integrate AOT compiler into JDK Reviewed-by: erikj, mchung, psandoz, coleenp, iklam, stefank, simonis Contributed-by: Bharadwaj Yadavalli <bharadwaj.yadavalli@oracle.com>, Christian Thalinger <cthalinger@twitter.com>, Dean Long <dean.long@oracle.com>, Dmitrij Pochepko <dmitrij.pochepko@oracle.com>, Dmitry Chuyko <dmitry.chuyko@oracle.com>, Doug Simon <doug.simon@oracle.com>, Eric Caspole <eric.caspole@oracle.com>, Igor Ignatyev <igor.ignatyev@oracle.com>, Igor Veresov <igor.veresov@oracle.com>, John Rose <john.r.rose@oracle.com>, Morris Meyer <morris.meyer@oracle.com>, Niclas Adlertz <niclas.adlertz@oracle.com>, Rickard Backman <rickard.backman@oracle.com>
hotspot/.hgignore
hotspot/make/lib/JvmFeatures.gmk
hotspot/make/lib/Lib-jdk.aot.gmk
hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp
hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.hpp
hotspot/src/cpu/aarch64/vm/compiledIC_aarch64.cpp
hotspot/src/cpu/ppc/vm/c1_LIRAssembler_ppc.cpp
hotspot/src/cpu/ppc/vm/c1_LIRAssembler_ppc.hpp
hotspot/src/cpu/ppc/vm/compiledIC_ppc.cpp
hotspot/src/cpu/s390/vm/c1_LIRAssembler_s390.cpp
hotspot/src/cpu/s390/vm/c1_LIRAssembler_s390.hpp
hotspot/src/cpu/s390/vm/compiledIC_s390.cpp
hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp
hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.hpp
hotspot/src/cpu/sparc/vm/compiledIC_sparc.cpp
hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp
hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.hpp
hotspot/src/cpu/x86/vm/compiledIC_aot_x86_64.cpp
hotspot/src/cpu/x86/vm/compiledIC_x86.cpp
hotspot/src/cpu/x86/vm/icBuffer_x86.cpp
hotspot/src/cpu/x86/vm/nativeInst_x86.cpp
hotspot/src/cpu/x86/vm/nativeInst_x86.hpp
hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp
hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp
hotspot/src/cpu/x86/vm/x86_64.ad
hotspot/src/cpu/zero/vm/compiledIC_zero.cpp
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/ByteContainer.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/CodeContainer.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/GotSymbol.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/HeaderContainer.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/ReadOnlyDataContainer.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/Relocation.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/Symbol.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/SymbolTable.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/JELFRelocObject.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/ELFContainer.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/ELFSymbol.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNIELFContainer.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNIELFRelocation.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNIELFTargetInfo.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNILibELFAPI.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/Pointer.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/UnsafeAccess.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/linux/Elf_Cmd.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/sunos/Elf_Cmd.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTBackend.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompilationTask.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiledClass.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiler.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTHotSpotResolvedJavaMethod.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTStub.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CallSiteRelocationInfo.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CallSiteRelocationSymbol.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CodeOffsets.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CodeSectionProcessor.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CompilationSpec.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CompiledMethodInfo.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataBuilder.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataPatchProcessor.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/ELFMacroAssembler.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/ForeignCallSiteRelocationInfo.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/ForeignCallSiteRelocationSymbol.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/ForeignGotCallSiteRelocationSymbol.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/GraalFilters.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/InfopointProcessor.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/InstructionDecoder.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/JavaCallSiteRelocationInfo.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/JavaCallSiteRelocationSymbol.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/JavaMethodInfo.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/LogPrinter.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MarkId.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MarkProcessor.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MetadataBuilder.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MiscUtils.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/StubDirectCallSiteRelocationSymbol.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/amd64/AMD64ELFMacroAssembler.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/amd64/AMD64InstructionDecoder.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassCollector.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/utils/NativeOrderOutputStream.java
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/utils/Timer.java
hotspot/src/jdk.aot/share/classes/module-info.java
hotspot/src/jdk.aot/unix/native/libjelfshim/jdk_tools_jaotc_jnilibelf_JNILibELFAPI.c
hotspot/src/jdk.aot/unix/native/libjelfshim/shim_functions.c
hotspot/src/jdk.hotspot.agent/linux/native/libsaproc/symtab.c
hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/Dictionary.java
hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java
hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/DebugInfo.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaData.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java
hotspot/src/jdk.vm.ci/share/classes/module-info.java
hotspot/src/jdk.vm.compiler/share/classes/module-info.java
hotspot/src/share/vm/aot/aotCodeHeap.cpp
hotspot/src/share/vm/aot/aotCodeHeap.hpp
hotspot/src/share/vm/aot/aotCompiledMethod.cpp
hotspot/src/share/vm/aot/aotCompiledMethod.hpp
hotspot/src/share/vm/aot/aotLoader.cpp
hotspot/src/share/vm/aot/aotLoader.hpp
hotspot/src/share/vm/aot/aotLoader.inline.hpp
hotspot/src/share/vm/aot/compiledIC_aot.cpp
hotspot/src/share/vm/aot/compiledIC_aot.hpp
hotspot/src/share/vm/c1/c1_Compilation.cpp
hotspot/src/share/vm/c1/c1_LIRAssembler.hpp
hotspot/src/share/vm/classfile/classFileParser.cpp
hotspot/src/share/vm/classfile/classFileStream.cpp
hotspot/src/share/vm/classfile/classFileStream.hpp
hotspot/src/share/vm/classfile/klassFactory.cpp
hotspot/src/share/vm/classfile/systemDictionary.cpp
hotspot/src/share/vm/code/codeBlob.hpp
hotspot/src/share/vm/code/codeCache.cpp
hotspot/src/share/vm/code/codeCache.hpp
hotspot/src/share/vm/code/compiledIC.cpp
hotspot/src/share/vm/code/compiledIC.hpp
hotspot/src/share/vm/code/compiledMethod.cpp
hotspot/src/share/vm/code/compiledMethod.hpp
hotspot/src/share/vm/code/nmethod.cpp
hotspot/src/share/vm/code/nmethod.hpp
hotspot/src/share/vm/code/relocInfo.cpp
hotspot/src/share/vm/code/relocInfo.hpp
hotspot/src/share/vm/compiler/compileTask.cpp
hotspot/src/share/vm/compiler/compileTask.hpp
hotspot/src/share/vm/compiler/compilerDefinitions.hpp
hotspot/src/share/vm/compiler/disassembler.cpp
hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp
hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp
hotspot/src/share/vm/gc/g1/g1RootProcessor.cpp
hotspot/src/share/vm/gc/g1/g1RootProcessor.hpp
hotspot/src/share/vm/gc/g1/heapRegion.cpp
hotspot/src/share/vm/gc/parallel/pcTasks.cpp
hotspot/src/share/vm/gc/parallel/psMarkSweep.cpp
hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp
hotspot/src/share/vm/gc/parallel/psTasks.cpp
hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp
hotspot/src/share/vm/jvmci/compilerRuntime.cpp
hotspot/src/share/vm/jvmci/compilerRuntime.hpp
hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp
hotspot/src/share/vm/jvmci/jvmciCodeInstaller.hpp
hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp
hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp
hotspot/src/share/vm/jvmci/jvmciJavaClasses.cpp
hotspot/src/share/vm/jvmci/vmStructs_compiler_runtime.hpp
hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp
hotspot/src/share/vm/logging/logTag.hpp
hotspot/src/share/vm/memory/heap.cpp
hotspot/src/share/vm/memory/heap.hpp
hotspot/src/share/vm/memory/metaspace.cpp
hotspot/src/share/vm/memory/universe.cpp
hotspot/src/share/vm/memory/virtualspace.hpp
hotspot/src/share/vm/oops/instanceKlass.cpp
hotspot/src/share/vm/oops/instanceKlass.hpp
hotspot/src/share/vm/oops/metadata.cpp
hotspot/src/share/vm/oops/method.hpp
hotspot/src/share/vm/oops/methodCounters.hpp
hotspot/src/share/vm/opto/output.cpp
hotspot/src/share/vm/prims/jvmtiExport.cpp
hotspot/src/share/vm/prims/jvmtiExport.hpp
hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp
hotspot/src/share/vm/prims/whitebox.cpp
hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp
hotspot/src/share/vm/runtime/advancedThresholdPolicy.hpp
hotspot/src/share/vm/runtime/frame.cpp
hotspot/src/share/vm/runtime/globals.hpp
hotspot/src/share/vm/runtime/java.cpp
hotspot/src/share/vm/runtime/sharedRuntime.cpp
hotspot/src/share/vm/runtime/sharedRuntime.hpp
hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp
hotspot/src/share/vm/runtime/simpleThresholdPolicy.hpp
hotspot/src/share/vm/runtime/simpleThresholdPolicy.inline.hpp
hotspot/src/share/vm/runtime/sweeper.cpp
hotspot/src/share/vm/runtime/vframe_hp.cpp
hotspot/src/share/vm/runtime/vmStructs.cpp
hotspot/src/share/vm/runtime/vm_version.cpp
hotspot/src/share/vm/utilities/debug.cpp
hotspot/src/share/vm/utilities/growableArray.hpp
hotspot/src/share/vm/utilities/macros.hpp
hotspot/test/TEST.groups
hotspot/test/compiler/aot/AotCompiler.java
hotspot/test/compiler/aot/DeoptimizationTest.java
hotspot/test/compiler/aot/HelloWorldPrinter.java
hotspot/test/compiler/aot/RecompilationTest.java
hotspot/test/compiler/aot/SharedUsageTest.java
hotspot/test/compiler/aot/calls/fromAot/AotInvokeDynamic2AotTest.java
hotspot/test/compiler/aot/calls/fromAot/AotInvokeDynamic2CompiledTest.java
hotspot/test/compiler/aot/calls/fromAot/AotInvokeDynamic2InterpretedTest.java
hotspot/test/compiler/aot/calls/fromAot/AotInvokeDynamic2NativeTest.java
hotspot/test/compiler/aot/calls/fromAot/AotInvokeInterface2AotTest.java
hotspot/test/compiler/aot/calls/fromAot/AotInvokeInterface2CompiledTest.java
hotspot/test/compiler/aot/calls/fromAot/AotInvokeInterface2InterpretedTest.java
hotspot/test/compiler/aot/calls/fromAot/AotInvokeInterface2NativeTest.java
hotspot/test/compiler/aot/calls/fromAot/AotInvokeSpecial2AotTest.java
hotspot/test/compiler/aot/calls/fromAot/AotInvokeSpecial2CompiledTest.java
hotspot/test/compiler/aot/calls/fromAot/AotInvokeSpecial2InterpretedTest.java
hotspot/test/compiler/aot/calls/fromAot/AotInvokeSpecial2NativeTest.java
hotspot/test/compiler/aot/calls/fromAot/AotInvokeStatic2AotTest.java
hotspot/test/compiler/aot/calls/fromAot/AotInvokeStatic2CompiledTest.java
hotspot/test/compiler/aot/calls/fromAot/AotInvokeStatic2InterpretedTest.java
hotspot/test/compiler/aot/calls/fromAot/AotInvokeStatic2NativeTest.java
hotspot/test/compiler/aot/calls/fromAot/AotInvokeVirtual2AotTest.java
hotspot/test/compiler/aot/calls/fromAot/AotInvokeVirtual2CompiledTest.java
hotspot/test/compiler/aot/calls/fromAot/AotInvokeVirtual2InterpretedTest.java
hotspot/test/compiler/aot/calls/fromAot/AotInvokeVirtual2NativeTest.java
hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeDynamic2AotTest.java
hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeInterface2AotTest.java
hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeSpecial2AotTest.java
hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeStatic2AotTest.java
hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeVirtual2AotTest.java
hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeDynamic2AotTest.java
hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeInterface2AotTest.java
hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeSpecial2AotTest.java
hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeStatic2AotTest.java
hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeVirtual2AotTest.java
hotspot/test/compiler/aot/calls/fromNative/NativeInvokeSpecial2AotTest.java
hotspot/test/compiler/aot/calls/fromNative/NativeInvokeStatic2AotTest.java
hotspot/test/compiler/aot/calls/fromNative/NativeInvokeVirtual2AotTest.java
hotspot/test/compiler/aot/cli/AotLibraryNegativeBase.java
hotspot/test/compiler/aot/cli/DisabledAOTWithLibraryTest.java
hotspot/test/compiler/aot/cli/IncorrectAOTLibraryTest.java
hotspot/test/compiler/aot/cli/MultipleAOTLibraryTest.java
hotspot/test/compiler/aot/cli/NonExistingAOTLibraryTest.java
hotspot/test/compiler/aot/cli/SingleAOTLibraryTest.java
hotspot/test/compiler/aot/cli/SingleAOTOptionTest.java
hotspot/test/compiler/aot/cli/jaotc/ClasspathOptionTest.java
hotspot/test/compiler/aot/cli/jaotc/ClasspathOptionUnknownClassTest.java
hotspot/test/compiler/aot/cli/jaotc/CompileClassTest.java
hotspot/test/compiler/aot/cli/jaotc/CompileDirectoryTest.java
hotspot/test/compiler/aot/cli/jaotc/CompileJarTest.java
hotspot/test/compiler/aot/cli/jaotc/CompileModuleTest.java
hotspot/test/compiler/aot/cli/jaotc/JaotcTestHelper.java
hotspot/test/compiler/aot/cli/jaotc/ListOptionNotExistingTest.java
hotspot/test/compiler/aot/cli/jaotc/ListOptionTest.java
hotspot/test/compiler/aot/cli/jaotc/ListOptionWrongFileTest.java
hotspot/test/compiler/aot/cli/jaotc/data/HelloWorldOne.java
hotspot/test/compiler/aot/cli/jaotc/data/HelloWorldTwo.java
hotspot/test/compiler/aot/fingerprint/CDSDumper.java
hotspot/test/compiler/aot/fingerprint/CDSRunner.java
hotspot/test/compiler/aot/fingerprint/SelfChanged.java
hotspot/test/compiler/aot/fingerprint/SelfChangedCDS.java
hotspot/test/compiler/aot/fingerprint/SuperChanged.java
hotspot/test/compiler/aot/jdk.tools.jaotc.jnilibelf.test/src/jdk/tools/jaotc/jnilibelf/test/JNILibELFTest.java
hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/NativeOrderOutputStreamTest.java
hotspot/test/compiler/aot/verification/ClassAndLibraryNotMatchTest.java
hotspot/test/compiler/aot/verification/vmflags/BasicFlagsChange.java
hotspot/test/compiler/aot/verification/vmflags/NotTrackedFlagTest.java
hotspot/test/compiler/aot/verification/vmflags/TrackedFlagTest.java
hotspot/test/compiler/classUnloading/anonymousClass/TestAnonymousClassUnloading.java
hotspot/test/compiler/classUnloading/methodUnloading/TestMethodUnloading.java
hotspot/test/compiler/intrinsics/IntrinsicDisabledTest.java
hotspot/test/compiler/intrinsics/bigInteger/MontgomeryMultiplyTest.java
hotspot/test/compiler/intrinsics/mathexact/sanity/IntrinsicBase.java
hotspot/test/compiler/uncommontrap/Test8009761.java
hotspot/test/compiler/whitebox/CompilerWhiteBoxTest.java
hotspot/test/runtime/CompressedOops/CompressedClassPointers.java
hotspot/test/serviceability/dcmd/compiler/CodeCacheTest.java
hotspot/test/testlibrary/jittester/Makefile
hotspot/test/testlibrary/jittester/conf/default.properties
hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/AotTestGeneratorsFactory.java
--- a/hotspot/.hgignore	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/.hgignore	Sun Dec 11 19:07:04 2016 -0800
@@ -23,3 +23,19 @@
 ^test/compiler/jvmci/\w[\w\.]*/.*\.iml
 ^test/compiler/jvmci/\w[\w\.]*/nbproject
 ^test/compiler/jvmci/\w[\w\.]*/\..*
+^test/compiler/aot/\w[\w\.]*/.*\.xml
+^test/compiler/aot/\w[\w\.]*/.*\.iml
+^test/compiler/aot/\w[\w\.]*/nbproject
+^test/compiler/aot/\w[\w\.]*/\..*
+^src/jdk.vm.compiler/\.mx.graal/env
+^src/jdk.vm.compiler/\.mx.graal/.*\.pyc
+^src/jdk.vm.compiler/\.mx.graal/eclipse-launches/.*
+^src/jdk.aot/share/classes/\w[\w\.]*/.*\.xml
+^src/jdk.aot/share/classes/\w[\w\.]*/.*\.iml
+^src/jdk.aot/share/classes/\w[\w\.]*/nbproject
+^src/jdk.aot/share/classes/\w[\w\.]*/\..*
+^src/jdk.vm.compiler/share/classes/\w[\w\.]*/.*\.xml
+^src/jdk.vm.compiler/share/classes/\w[\w\.]*/.*\.iml
+^src/jdk.vm.compiler/share/classes/\w[\w\.]*/nbproject
+^src/jdk.vm.compiler/share/classes/\w[\w\.]*/\..*
+
--- a/hotspot/make/lib/JvmFeatures.gmk	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/make/lib/JvmFeatures.gmk	Sun Dec 11 19:07:04 2016 -0800
@@ -146,3 +146,11 @@
       memBaseline.cpp memReporter.cpp mallocTracker.cpp virtualMemoryTracker.cpp nmtCommon.cpp \
       memTracker.cpp nmtDCmd.cpp mallocSiteTable.cpp
 endif
+
+ifeq ($(call check-jvm-feature, aot), true)
+  JVM_CFLAGS_FEATURES += -DINCLUDE_AOT
+else
+  JVM_EXCLUDE_FILES += \
+      compiledIC_aot_x86_64.cpp compilerRuntime.cpp \
+      aotCodeHeap.cpp aotCompiledMethod.cpp aotLoader.cpp compiledIC_aot.cpp
+endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/make/lib/Lib-jdk.aot.gmk	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,53 @@
+#
+# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+# 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 $(SPEC)
+include NativeCompilation.gmk
+
+$(eval $(call IncludeCustomExtension, hotspot, lib/Lib-jdk.aot.gmk))
+
+##############################################################################
+# Build libjelfshim only when AOT is enabled.
+ifeq ($(ENABLE_AOT), true)
+  JELFSHIM_NAME := jelfshim
+
+  $(eval $(call SetupNativeCompilation, BUILD_LIBJELFSHIM, \
+      TOOLCHAIN := TOOLCHAIN_DEFAULT, \
+      OPTIMIZATION := LOW, \
+      LIBRARY := $(JELFSHIM_NAME), \
+      OUTPUT_DIR := $(call FindLibDirForModule, $(MODULE)), \
+      SRC := $(HOTSPOT_TOPDIR)/src/jdk.aot/unix/native/libjelfshim, \
+      CFLAGS := $(CFLAGS_JDKLIB) $(ELF_CFLAGS) \
+          -DAOT_VERSION_STRING='"$(VERSION_STRING)"' \
+          -I$(SUPPORT_OUTPUTDIR)/headers/$(MODULE), \
+      LDFLAGS := $(LDFLAGS_JDKLIB), \
+      OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/lib$(JELFSHIM_NAME), \
+      LIBS := $(ELF_LIBS) $(LIBS_JDKLIB), \
+  ))
+
+  TARGETS += $(BUILD_LIBJELFSHIM)
+endif
+
+##############################################################################
--- a/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -375,7 +375,7 @@
   __ nop();
 
   // generate code for exception handler
-  address handler_base = __ start_a_stub(exception_handler_size);
+  address handler_base = __ start_a_stub(exception_handler_size());
   if (handler_base == NULL) {
     // not enough space left for the handler
     bailout("exception handler overflow");
@@ -393,7 +393,7 @@
 
   // search an exception handler (r0: exception oop, r3: throwing pc)
   __ far_call(RuntimeAddress(Runtime1::entry_for(Runtime1::handle_exception_from_callee_id)));  __ should_not_reach_here();
-  guarantee(code_offset() - offset <= exception_handler_size, "overflow");
+  guarantee(code_offset() - offset <= exception_handler_size(), "overflow");
   __ end_a_stub();
 
   return offset;
@@ -467,7 +467,7 @@
   __ nop();
 
   // generate code for exception handler
-  address handler_base = __ start_a_stub(deopt_handler_size);
+  address handler_base = __ start_a_stub(deopt_handler_size());
   if (handler_base == NULL) {
     // not enough space left for the handler
     bailout("deopt handler overflow");
@@ -478,7 +478,7 @@
 
   __ adr(lr, pc());
   __ far_jump(RuntimeAddress(SharedRuntime::deopt_blob()->unpack()));
-  guarantee(code_offset() - offset <= deopt_handler_size, "overflow");
+  guarantee(code_offset() - offset <= deopt_handler_size(), "overflow");
   __ end_a_stub();
 
   return offset;
@@ -2001,7 +2001,7 @@
 
 void LIR_Assembler::emit_static_call_stub() {
   address call_pc = __ pc();
-  address stub = __ start_a_stub(call_stub_size);
+  address stub = __ start_a_stub(call_stub_size());
   if (stub == NULL) {
     bailout("static call stub overflow");
     return;
@@ -2014,7 +2014,7 @@
   __ movptr(rscratch1, 0);
   __ br(rscratch1);
 
-  assert(__ offset() - start <= call_stub_size, "stub too big");
+  assert(__ offset() - start <= call_stub_size(), "stub too big");
   __ end_a_stub();
 }
 
--- a/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.hpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.hpp	Sun Dec 11 19:07:04 2016 -0800
@@ -68,14 +68,17 @@
 
   void deoptimize_trap(CodeEmitInfo *info);
 
+  enum {
+    _call_stub_size = 12 * NativeInstruction::instruction_size,
+    _call_aot_stub_size = 0,
+    _exception_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(175),
+    _deopt_handler_size = 7 * NativeInstruction::instruction_size
+  };
+
 public:
 
   void store_parameter(Register r, int offset_from_esp_in_words);
   void store_parameter(jint c,     int offset_from_esp_in_words);
   void store_parameter(jobject c,  int offset_from_esp_in_words);
 
-enum { call_stub_size = 12 * NativeInstruction::instruction_size,
-       exception_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(175),
-       deopt_handler_size = 7 * NativeInstruction::instruction_size };
-
 #endif // CPU_AARCH64_VM_C1_LIRASSEMBLER_AARCH64_HPP
--- a/hotspot/src/cpu/aarch64/vm/compiledIC_aarch64.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/cpu/aarch64/vm/compiledIC_aarch64.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -76,13 +76,13 @@
   return 4; // 3 in emit_to_interp_stub + 1 in emit_call
 }
 
-void CompiledStaticCall::set_to_interpreted(methodHandle callee, address entry) {
-  address stub = find_stub();
+void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, address entry) {
+  address stub = find_stub(false /* is_aot */);
   guarantee(stub != NULL, "stub not found");
 
   if (TraceICs) {
     ResourceMark rm;
-    tty->print_cr("CompiledStaticCall@" INTPTR_FORMAT ": set_to_interpreted %s",
+    tty->print_cr("CompiledDirectStaticCall@" INTPTR_FORMAT ": set_to_interpreted %s",
                   p2i(instruction_address()),
                   callee->name_and_sig_as_C_string());
   }
@@ -107,7 +107,7 @@
   set_destination_mt_safe(stub);
 }
 
-void CompiledStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
+void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
   assert (CompiledIC_lock->is_locked() || SafepointSynchronize::is_at_safepoint(), "mt unsafe call");
   // Reset stub.
   address stub = static_stub->addr();
@@ -121,15 +121,15 @@
 // Non-product mode code
 #ifndef PRODUCT
 
-void CompiledStaticCall::verify() {
+void CompiledDirectStaticCall::verify() {
   // Verify call.
-  NativeCall::verify();
+  _call->verify();
   if (os::is_MP()) {
-    verify_alignment();
+    _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 = nativeMovConstReg_at(stub);
--- a/hotspot/src/cpu/ppc/vm/c1_LIRAssembler_ppc.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/cpu/ppc/vm/c1_LIRAssembler_ppc.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -153,7 +153,7 @@
   __ nop();
 
   // Generate code for the exception handler.
-  address handler_base = __ start_a_stub(exception_handler_size);
+  address handler_base = __ start_a_stub(exception_handler_size());
 
   if (handler_base == NULL) {
     // Not enough space left for the handler.
@@ -168,7 +168,7 @@
   __ mtctr(R0);
   __ bctr();
 
-  guarantee(code_offset() - offset <= exception_handler_size, "overflow");
+  guarantee(code_offset() - offset <= exception_handler_size(), "overflow");
   __ end_a_stub();
 
   return offset;
@@ -233,7 +233,7 @@
   __ nop();
 
   // Generate code for deopt handler.
-  address handler_base = __ start_a_stub(deopt_handler_size);
+  address handler_base = __ start_a_stub(deopt_handler_size());
 
   if (handler_base == NULL) {
     // Not enough space left for the handler.
@@ -244,7 +244,7 @@
   int offset = code_offset();
   __ bl64_patchable(SharedRuntime::deopt_blob()->unpack(), relocInfo::runtime_call_type);
 
-  guarantee(code_offset() - offset <= deopt_handler_size, "overflow");
+  guarantee(code_offset() - offset <= deopt_handler_size(), "overflow");
   __ end_a_stub();
 
   return offset;
@@ -1307,7 +1307,7 @@
 
 void LIR_Assembler::emit_static_call_stub() {
   address call_pc = __ pc();
-  address stub = __ start_a_stub(max_static_call_stub_size);
+  address stub = __ start_a_stub(static_call_stub_size());
   if (stub == NULL) {
     bailout("static call stub overflow");
     return;
@@ -1346,7 +1346,7 @@
     return;
   }
 
-  assert(__ offset() - start <= max_static_call_stub_size, "stub too big");
+  assert(__ offset() - start <= static_call_stub_size(), "stub too big");
   __ end_a_stub();
 }
 
--- a/hotspot/src/cpu/ppc/vm/c1_LIRAssembler_ppc.hpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/cpu/ppc/vm/c1_LIRAssembler_ppc.hpp	Sun Dec 11 19:07:04 2016 -0800
@@ -60,10 +60,21 @@
   bool emit_trampoline_stub_for_call(address target, Register Rtoc = noreg);
 
 enum {
-  max_static_call_stub_size = 4 * BytesPerInstWord + MacroAssembler::b64_patchable_size,
-  call_stub_size = max_static_call_stub_size + MacroAssembler::trampoline_stub_size, // or smaller
-  exception_handler_size = MacroAssembler::b64_patchable_size, // or smaller
-  deopt_handler_size = MacroAssembler::bl64_patchable_size
+  _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
 };
 
+  // '_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() {
+    if (UseAOT) {
+      return _static_call_stub_size + _call_aot_stub_size;
+    } else {
+      return _static_call_stub_size;
+    }
+  }
+
 #endif // CPU_PPC_VM_C1_LIRASSEMBLER_PPC_HPP
--- a/hotspot/src/cpu/ppc/vm/compiledIC_ppc.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/cpu/ppc/vm/compiledIC_ppc.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -37,7 +37,7 @@
 
 // ----------------------------------------------------------------------------
 
-// A PPC CompiledStaticCall looks like this:
+// A PPC CompiledDirectStaticCall looks like this:
 //
 // >>>> consts
 //
@@ -163,13 +163,13 @@
   return 5;
 }
 
-void CompiledStaticCall::set_to_interpreted(methodHandle callee, address entry) {
-  address stub = find_stub();
+void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, address entry) {
+  address stub = find_stub(/*is_aot*/ false);
   guarantee(stub != NULL, "stub not found");
 
   if (TraceICs) {
     ResourceMark rm;
-    tty->print_cr("CompiledStaticCall@" INTPTR_FORMAT ": set_to_interpreted %s",
+    tty->print_cr("CompiledDirectStaticCall@" INTPTR_FORMAT ": set_to_interpreted %s",
                   p2i(instruction_address()),
                   callee->name_and_sig_as_C_string());
   }
@@ -196,7 +196,7 @@
   set_destination_mt_safe(stub);
 }
 
-void CompiledStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
+void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
   assert (CompiledIC_lock->is_locked() || SafepointSynchronize::is_at_safepoint(), "mt unsafe call");
   // Reset stub.
   address stub = static_stub->addr();
@@ -212,15 +212,15 @@
 // Non-product mode code
 #ifndef PRODUCT
 
-void CompiledStaticCall::verify() {
+void CompiledDirectStaticCall::verify() {
   // Verify call.
-  NativeCall::verify();
+  _call->verify();
   if (os::is_MP()) {
-    verify_alignment();
+    _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);
--- a/hotspot/src/cpu/s390/vm/c1_LIRAssembler_s390.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/cpu/s390/vm/c1_LIRAssembler_s390.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -153,7 +153,7 @@
   __ nop();
 
   // Generate code for exception handler.
-  address handler_base = __ start_a_stub(exception_handler_size);
+  address handler_base = __ start_a_stub(exception_handler_size());
   if (handler_base == NULL) {
     // Not enough space left for the handler.
     bailout("exception handler overflow");
@@ -166,7 +166,7 @@
   address call_addr = emit_call_c(a);
   CHECK_BAILOUT_(-1);
   __ should_not_reach_here();
-  guarantee(code_offset() - offset <= exception_handler_size, "overflow");
+  guarantee(code_offset() - offset <= exception_handler_size(), "overflow");
   __ end_a_stub();
 
   return offset;
@@ -251,7 +251,7 @@
   __ nop();
 
   // Generate code for exception handler.
-  address handler_base = __ start_a_stub(deopt_handler_size);
+  address handler_base = __ start_a_stub(deopt_handler_size());
   if (handler_base == NULL) {
     // Not enough space left for the handler.
     bailout("deopt handler overflow");
@@ -260,7 +260,7 @@
   // Size must be constant (see HandlerImpl::emit_deopt_handler).
   __ load_const(Z_R1_scratch, SharedRuntime::deopt_blob()->unpack());
   __ call(Z_R1_scratch);
-  guarantee(code_offset() - offset <= deopt_handler_size, "overflow");
+  guarantee(code_offset() - offset <= deopt_handler_size(), "overflow");
   __ end_a_stub();
 
   return offset;
@@ -1157,7 +1157,7 @@
   // compiled code to calling interpreted code.
 
   address call_pc = __ pc();
-  address stub = __ start_a_stub(call_stub_size);
+  address stub = __ start_a_stub(call_stub_size());
   if (stub == NULL) {
     bailout("static call stub overflow");
     return;
@@ -1180,7 +1180,7 @@
   }
 
   __ z_br(Z_R1);
-  assert(__ offset() - start <= call_stub_size, "stub too big");
+  assert(__ offset() - start <= call_stub_size(), "stub too big");
   __ end_a_stub(); // Update current stubs pointer and restore insts_end.
 }
 
--- a/hotspot/src/cpu/s390/vm/c1_LIRAssembler_s390.hpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/cpu/s390/vm/c1_LIRAssembler_s390.hpp	Sun Dec 11 19:07:04 2016 -0800
@@ -46,9 +46,10 @@
   }
 
   enum {
-    call_stub_size = 512, // See Compile::MAX_stubs_size and CompiledStaticCall::emit_to_interp_stub.
-    exception_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(128),
-    deopt_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(64)
+    _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)
   };
 
 #endif // CPU_S390_VM_C1_LIRASSEMBLER_S390_HPP
--- a/hotspot/src/cpu/s390/vm/compiledIC_s390.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/cpu/s390/vm/compiledIC_s390.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -90,19 +90,19 @@
   return 5; // 4 in emit_java_to_interp + 1 in Java_Static_Call
 }
 
-void CompiledStaticCall::set_to_interpreted(methodHandle callee, address entry) {
-  address stub = find_stub();
+void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, address entry) {
+  address stub = find_stub(/*is_aot*/ false);
   guarantee(stub != NULL, "stub not found");
 
   if (TraceICs) {
     ResourceMark rm;
-    tty->print_cr("CompiledStaticCall@" INTPTR_FORMAT ": set_to_interpreted %s",
+    tty->print_cr("CompiledDirectStaticCall@" INTPTR_FORMAT ": set_to_interpreted %s",
                   p2i(instruction_address()),
                   callee->name_and_sig_as_C_string());
   }
 
   // Creation also verifies the object.
-  NativeMovConstReg* method_holder = nativeMovConstReg_at(stub + get_IC_pos_in_java_to_interp_stub());
+  NativeMovConstReg* method_holder = nativeMovConstReg_at(stub + NativeCall::get_IC_pos_in_java_to_interp_stub());
   NativeJump*        jump          = nativeJump_at(method_holder->next_instruction_address());
 
   // A generated lambda form might be deleted from the Lambdaform
@@ -123,13 +123,13 @@
   set_destination_mt_safe(stub);
 }
 
-void CompiledStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
+void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
   assert (CompiledIC_lock->is_locked() || SafepointSynchronize::is_at_safepoint(), "mt unsafe call");
   // Reset stub.
   address stub = static_stub->addr();
   assert(stub != NULL, "stub not found");
   // Creation also verifies the object.
-  NativeMovConstReg* method_holder = nativeMovConstReg_at(stub + get_IC_pos_in_java_to_interp_stub());
+  NativeMovConstReg* method_holder = nativeMovConstReg_at(stub + NativeCall::get_IC_pos_in_java_to_interp_stub());
   NativeJump*        jump          = nativeJump_at(method_holder->next_instruction_address());
   method_holder->set_data(0);
   jump->set_jump_destination((address)-1);
@@ -139,18 +139,18 @@
 
 #ifndef PRODUCT
 
-void CompiledStaticCall::verify() {
+void CompiledDirectStaticCall::verify() {
   // Verify call.
-  NativeCall::verify();
+  _call->verify();
   if (os::is_MP()) {
-    verify_alignment();
+    _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 + get_IC_pos_in_java_to_interp_stub());
+  NativeMovConstReg* method_holder = nativeMovConstReg_at(stub + NativeCall::get_IC_pos_in_java_to_interp_stub());
   NativeJump*        jump          = nativeJump_at(method_holder->next_instruction_address());
 
   // Verify state.
--- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -287,7 +287,7 @@
   // generate code for exception handler
   ciMethod* method = compilation()->method();
 
-  address handler_base = __ start_a_stub(exception_handler_size);
+  address handler_base = __ start_a_stub(exception_handler_size());
 
   if (handler_base == NULL) {
     // not enough space left for the handler
@@ -300,7 +300,7 @@
   __ call(Runtime1::entry_for(Runtime1::handle_exception_from_callee_id), relocInfo::runtime_call_type);
   __ delayed()->nop();
   __ should_not_reach_here();
-  guarantee(code_offset() - offset <= exception_handler_size, "overflow");
+  guarantee(code_offset() - offset <= exception_handler_size(), "overflow");
   __ end_a_stub();
 
   return offset;
@@ -375,7 +375,7 @@
 
   // generate code for deopt handler
   ciMethod* method = compilation()->method();
-  address handler_base = __ start_a_stub(deopt_handler_size);
+  address handler_base = __ start_a_stub(deopt_handler_size());
   if (handler_base == NULL) {
     // not enough space left for the handler
     bailout("deopt handler overflow");
@@ -386,7 +386,7 @@
   AddressLiteral deopt_blob(SharedRuntime::deopt_blob()->unpack());
   __ JUMP(deopt_blob, G3_scratch, 0); // sethi;jmp
   __ delayed()->nop();
-  guarantee(code_offset() - offset <= deopt_handler_size, "overflow");
+  guarantee(code_offset() - offset <= deopt_handler_size(), "overflow");
   __ end_a_stub();
 
   return offset;
@@ -1493,7 +1493,7 @@
 
 void LIR_Assembler::emit_static_call_stub() {
   address call_pc = __ pc();
-  address stub = __ start_a_stub(call_stub_size);
+  address stub = __ start_a_stub(call_stub_size());
   if (stub == NULL) {
     bailout("static call stub overflow");
     return;
@@ -1508,7 +1508,7 @@
   __ jump_to(addrlit, G3);
   __ delayed()->nop();
 
-  assert(__ offset() - start <= call_stub_size, "stub too big");
+  assert(__ offset() - start <= call_stub_size(), "stub too big");
   __ end_a_stub();
 }
 
--- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.hpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.hpp	Sun Dec 11 19:07:04 2016 -0800
@@ -59,17 +59,20 @@
   // Setup pointers to MDO, MDO slot, also compute offset bias to access the slot.
   void setup_md_access(ciMethod* method, int bci,
                        ciMethodData*& md, ciProfileData*& data, int& mdo_offset_bias);
+
+  enum {
+#ifdef _LP64
+    _call_stub_size = 68,
+#else
+    _call_stub_size = 20,
+#endif // _LP64
+    _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)
+  };
+
  public:
   void   pack64(LIR_Opr src, LIR_Opr dst);
   void unpack64(LIR_Opr src, LIR_Opr dst);
 
-enum {
-#ifdef _LP64
-         call_stub_size = 68,
-#else
-         call_stub_size = 20,
-#endif // _LP64
-         exception_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(128),
-         deopt_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(64)  };
-
 #endif // CPU_SPARC_VM_C1_LIRASSEMBLER_SPARC_HPP
--- a/hotspot/src/cpu/sparc/vm/compiledIC_sparc.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/cpu/sparc/vm/compiledIC_sparc.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -85,13 +85,13 @@
   return 10;  // 4 in emit_java_to_interp + 1 in Java_Static_Call
 }
 
-void CompiledStaticCall::set_to_interpreted(methodHandle callee, address entry) {
-  address stub = find_stub();
+void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, address entry) {
+  address stub = find_stub(/*is_aot*/ false);
   guarantee(stub != NULL, "stub not found");
 
   if (TraceICs) {
     ResourceMark rm;
-    tty->print_cr("CompiledStaticCall@" INTPTR_FORMAT ": set_to_interpreted %s",
+    tty->print_cr("CompiledDirectStaticCall@" INTPTR_FORMAT ": set_to_interpreted %s",
                   p2i(instruction_address()),
                   callee->name_and_sig_as_C_string());
   }
@@ -118,7 +118,7 @@
   set_destination_mt_safe(stub);
 }
 
-void CompiledStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
+void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
   assert (CompiledIC_lock->is_locked() || SafepointSynchronize::is_at_safepoint(), "mt unsafe call");
   // Reset stub.
   address stub = static_stub->addr();
@@ -134,15 +134,15 @@
 // Non-product mode code
 #ifndef PRODUCT
 
-void CompiledStaticCall::verify() {
+void CompiledDirectStaticCall::verify() {
   // Verify call.
-  NativeCall::verify();
+  _call->verify();
   if (os::is_MP()) {
-    verify_alignment();
+    _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);
--- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -393,7 +393,7 @@
   __ nop();
 
   // generate code for exception handler
-  address handler_base = __ start_a_stub(exception_handler_size);
+  address handler_base = __ start_a_stub(exception_handler_size());
   if (handler_base == NULL) {
     // not enough space left for the handler
     bailout("exception handler overflow");
@@ -412,7 +412,7 @@
   // search an exception handler (rax: exception oop, rdx: throwing pc)
   __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::handle_exception_from_callee_id)));
   __ should_not_reach_here();
-  guarantee(code_offset() - offset <= exception_handler_size, "overflow");
+  guarantee(code_offset() - offset <= exception_handler_size(), "overflow");
   __ end_a_stub();
 
   return offset;
@@ -490,7 +490,7 @@
   __ nop();
 
   // generate code for exception handler
-  address handler_base = __ start_a_stub(deopt_handler_size);
+  address handler_base = __ start_a_stub(deopt_handler_size());
   if (handler_base == NULL) {
     // not enough space left for the handler
     bailout("deopt handler overflow");
@@ -502,7 +502,7 @@
 
   __ pushptr(here.addr());
   __ jump(RuntimeAddress(SharedRuntime::deopt_blob()->unpack()));
-  guarantee(code_offset() - offset <= deopt_handler_size, "overflow");
+  guarantee(code_offset() - offset <= deopt_handler_size(), "overflow");
   __ end_a_stub();
 
   return offset;
@@ -2805,7 +2805,7 @@
 
 void LIR_Assembler::emit_static_call_stub() {
   address call_pc = __ pc();
-  address stub = __ start_a_stub(call_stub_size);
+  address stub = __ start_a_stub(call_stub_size());
   if (stub == NULL) {
     bailout("static call stub overflow");
     return;
@@ -2816,14 +2816,24 @@
     // 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(!os::is_MP() || ((__ offset() + 1) % BytesPerWord) == 0, "must be aligned on MP");
   // On 64bit this will die since it will take a movq & jmp, must be only a jmp
   __ jump(RuntimeAddress(__ pc()));
 
-  assert(__ offset() - start <= call_stub_size, "stub too big");
+  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();
 }
 
--- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.hpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.hpp	Sun Dec 11 19:07:04 2016 -0800
@@ -47,6 +47,14 @@
   void type_profile_helper(Register mdo,
                            ciMethodData *md, ciProfileData *data,
                            Register recv, Label* update_done);
+
+  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)
+  };
+
 public:
 
   void store_parameter(Register r,  int offset_from_esp_in_words);
@@ -54,9 +62,4 @@
   void store_parameter(jobject c,   int offset_from_esp_in_words);
   void store_parameter(Metadata* c, int offset_from_esp_in_words);
 
-  enum { call_stub_size = NOT_LP64(15) LP64_ONLY(28),
-         exception_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(175),
-         deopt_handler_size = NOT_LP64(10) LP64_ONLY(17)
-       };
-
 #endif // CPU_X86_VM_C1_LIRASSEMBLER_X86_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/cpu/x86/vm/compiledIC_aot_x86_64.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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"
+
+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) {
+  assert (CompiledIC_lock->is_locked() || SafepointSynchronize::is_at_safepoint(), "mt unsafe call");
+  // Reset stub.
+  address stub = static_stub->addr();
+  assert(stub != NULL, "stub not found");
+  // 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
--- a/hotspot/src/cpu/x86/vm/compiledIC_x86.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/cpu/x86/vm/compiledIC_x86.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "asm/macroAssembler.inline.hpp"
+#include "code/codeCache.hpp"
 #include "code/compiledIC.hpp"
 #include "code/icBuffer.hpp"
 #include "code/nmethod.hpp"
@@ -53,7 +54,7 @@
     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.
@@ -77,13 +78,73 @@
   return 4; // 3 in emit_to_interp_stub + 1 in emit_call
 }
 
-void CompiledStaticCall::set_to_interpreted(methodHandle callee, address entry) {
-  address stub = find_stub();
+#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(false /* is_aot */);
   guarantee(stub != NULL, "stub not found");
 
   if (TraceICs) {
     ResourceMark rm;
-    tty->print_cr("CompiledStaticCall@" INTPTR_FORMAT ": set_to_interpreted %s",
+    tty->print_cr("CompiledDirectStaticCall@" INTPTR_FORMAT ": set_to_interpreted %s",
                   p2i(instruction_address()),
                   callee->name_and_sig_as_C_string());
   }
@@ -110,7 +171,7 @@
   set_destination_mt_safe(stub);
 }
 
-void CompiledStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
+void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
   assert (CompiledIC_lock->is_locked() || SafepointSynchronize::is_at_safepoint(), "mt unsafe call");
   // Reset stub.
   address stub = static_stub->addr();
@@ -118,8 +179,10 @@
   // 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);
+  }
 }
 
 
@@ -127,15 +190,20 @@
 // Non-product mode code
 #ifndef PRODUCT
 
-void CompiledStaticCall::verify() {
+void CompiledDirectStaticCall::verify() {
   // Verify call.
-  NativeCall::verify();
+  _call->verify();
   if (os::is_MP()) {
-    verify_alignment();
+    _call->verify_alignment();
   }
 
+#ifdef ASSERT
+  CodeBlob *cb = CodeCache::find_blob_unsafe((address) _call);
+  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);
--- a/hotspot/src/cpu/x86/vm/icBuffer_x86.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/cpu/x86/vm/icBuffer_x86.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -33,12 +33,18 @@
 #include "oops/oop.inline.hpp"
 
 int InlineCacheBuffer::ic_stub_code_size() {
-  return NativeMovConstReg::instruction_size +
-         NativeJump::instruction_size +
-         1;
-  // so that code_end can be set in CodeBuffer
-  // 64bit 16 = 5 + 10 bytes + 1 byte
-  // 32bit 11 = 10 bytes + 1 byte
+  // Worst case, if destination is not a near call:
+  // lea rax, lit1
+  // lea scratch, lit2
+  // jmp scratch
+
+  // Best case
+  // lea rax, lit1
+  // jmp lit2
+
+  int best = NativeMovConstReg::instruction_size + NativeJump::instruction_size;
+  int worst = 2 * NativeMovConstReg::instruction_size + 3;
+  return MAX2(best, worst);
 }
 
 
@@ -59,8 +65,16 @@
 
 address InlineCacheBuffer::ic_buffer_entry_point(address code_begin) {
   NativeMovConstReg* move = nativeMovConstReg_at(code_begin);   // creation also verifies the object
-  NativeJump*        jump = nativeJump_at(move->next_instruction_address());
-  return jump->jump_destination();
+  address jmp = move->next_instruction_address();
+  NativeInstruction* ni = nativeInstruction_at(jmp);
+  if (ni->is_jump()) {
+    NativeJump*        jump = nativeJump_at(jmp);
+    return jump->jump_destination();
+  } else {
+    assert(ni->is_far_jump(), "unexpected instruction");
+    NativeFarJump*     jump = nativeFarJump_at(jmp);
+    return jump->jump_destination();
+  }
 }
 
 
@@ -68,7 +82,14 @@
   // creation also verifies the object
   NativeMovConstReg* move = nativeMovConstReg_at(code_begin);
   // Verifies the jump
-  NativeJump*        jump = nativeJump_at(move->next_instruction_address());
+  address jmp = move->next_instruction_address();
+  NativeInstruction* ni = nativeInstruction_at(jmp);
+  if (ni->is_jump()) {
+    NativeJump*        jump = nativeJump_at(jmp);
+  } else {
+    assert(ni->is_far_jump(), "unexpected instruction");
+    NativeFarJump*     jump = nativeFarJump_at(jmp);
+  }
   void* o = (void*)move->data();
   return o;
 }
--- a/hotspot/src/cpu/x86/vm/nativeInst_x86.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/cpu/x86/vm/nativeInst_x86.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -39,6 +39,124 @@
   ICache::invalidate_word(addr_at(offset));
 }
 
+void NativeLoadGot::report_and_fail() const {
+  tty->print_cr("Addr: " INTPTR_FORMAT, p2i(instruction_address()));
+  fatal("not a indirect rip mov to rbx");
+}
+
+void NativeLoadGot::verify() const {
+  if (has_rex) {
+    int rex = ubyte_at(0);
+    if (rex != rex_prefix) {
+      report_and_fail();
+    }
+  }
+
+  int inst = ubyte_at(rex_size);
+  if (inst != instruction_code) {
+    report_and_fail();
+  }
+  int modrm = ubyte_at(rex_size + 1);
+  if (modrm != modrm_rbx_code && modrm != modrm_rax_code) {
+    report_and_fail();
+  }
+}
+
+intptr_t NativeLoadGot::data() const {
+  return *(intptr_t *) got_address();
+}
+
+address NativePltCall::destination() const {
+  NativeGotJump* jump = nativeGotJump_at(plt_jump());
+  return jump->destination();
+}
+
+address NativePltCall::plt_entry() const {
+  return return_address() + displacement();
+}
+
+address NativePltCall::plt_jump() const {
+  address entry = plt_entry();
+  // Virtual PLT code has move instruction first
+  if (((NativeGotJump*)entry)->is_GotJump()) {
+    return entry;
+  } else {
+    return nativeLoadGot_at(entry)->next_instruction_address();
+  }
+}
+
+address NativePltCall::plt_load_got() const {
+  address entry = plt_entry();
+  if (!((NativeGotJump*)entry)->is_GotJump()) {
+    // Virtual PLT code has move instruction first
+    return entry;
+  } else {
+    // Static PLT code has move instruction second (from c2i stub)
+    return nativeGotJump_at(entry)->next_instruction_address();
+  }
+}
+
+address NativePltCall::plt_c2i_stub() const {
+  address entry = plt_load_got();
+  // This method should be called only for static calls which has C2I stub.
+  NativeLoadGot* load = nativeLoadGot_at(entry);
+  return entry;
+}
+
+address NativePltCall::plt_resolve_call() const {
+  NativeGotJump* jump = nativeGotJump_at(plt_jump());
+  address entry = jump->next_instruction_address();
+  if (((NativeGotJump*)entry)->is_GotJump()) {
+    return entry;
+  } else {
+    // c2i stub 2 instructions
+    entry = nativeLoadGot_at(entry)->next_instruction_address();
+    return nativeGotJump_at(entry)->next_instruction_address();
+  }
+}
+
+void NativePltCall::reset_to_plt_resolve_call() {
+  set_destination_mt_safe(plt_resolve_call());
+}
+
+void NativePltCall::set_destination_mt_safe(address dest) {
+  // rewriting the value in the GOT, it should always be aligned
+  NativeGotJump* jump = nativeGotJump_at(plt_jump());
+  address* got = (address *) jump->got_address();
+  *got = dest;
+}
+
+void NativePltCall::set_stub_to_clean() {
+  NativeLoadGot* method_loader = nativeLoadGot_at(plt_c2i_stub());
+  NativeGotJump* jump          = nativeGotJump_at(method_loader->next_instruction_address());
+  method_loader->set_data(0);
+  jump->set_jump_destination((address)-1);
+}
+
+void NativePltCall::verify() const {
+  // Make sure code pattern is actually a call rip+off32 instruction.
+  int inst = ubyte_at(0);
+  if (inst != instruction_code) {
+    tty->print_cr("Addr: " INTPTR_FORMAT " Code: 0x%x", p2i(instruction_address()),
+                                                        inst);
+    fatal("not a call rip+off32");
+  }
+}
+
+address NativeGotJump::destination() const {
+  address *got_entry = (address *) got_address();
+  return *got_entry;
+}
+
+void NativeGotJump::verify() const {
+  int inst = ubyte_at(0);
+  if (inst != instruction_code) {
+    tty->print_cr("Addr: " INTPTR_FORMAT " Code: 0x%x", p2i(instruction_address()),
+                                                        inst);
+    fatal("not a indirect rip jump");
+  }
+}
+
 void NativeCall::verify() {
   // Make sure code pattern is actually a call imm32 instruction.
   int inst = ubyte_at(0);
@@ -422,7 +540,12 @@
 
 void NativeJump::verify() {
   if (*(u_char*)instruction_address() != instruction_code) {
-    fatal("not a jump instruction");
+    // far jump
+    NativeMovConstReg* mov = nativeMovConstReg_at(instruction_address());
+    NativeInstruction* jmp = nativeInstruction_at(mov->next_instruction_address());
+    if (!jmp->is_jump_reg()) {
+      fatal("not a jump instruction");
+    }
   }
 }
 
@@ -514,6 +637,20 @@
 
 }
 
+address NativeFarJump::jump_destination() const          {
+  NativeMovConstReg* mov = nativeMovConstReg_at(addr_at(0));
+  return (address)mov->data();
+}
+
+void NativeFarJump::verify() {
+  if (is_far_jump()) {
+    NativeMovConstReg* mov = nativeMovConstReg_at(addr_at(0));
+    NativeInstruction* jmp = nativeInstruction_at(mov->next_instruction_address());
+    if (jmp->is_jump_reg()) return;
+  }
+  fatal("not a jump instruction");
+}
+
 void NativePopReg::insert(address code_pos, Register reg) {
   assert(reg->encoding() < 8, "no space for REX");
   assert(NativePopReg::instruction_size == sizeof(char), "right address unit for update");
--- a/hotspot/src/cpu/x86/vm/nativeInst_x86.hpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/cpu/x86/vm/nativeInst_x86.hpp	Sun Dec 11 19:07:04 2016 -0800
@@ -38,6 +38,7 @@
 // - - NativeMovRegMem
 // - - NativeMovRegMemPatching
 // - - NativeJump
+// - - NativeFarJump
 // - - NativeIllegalOpCode
 // - - NativeGeneralJump
 // - - NativeReturn
@@ -63,6 +64,8 @@
   inline bool is_illegal();
   inline bool is_return();
   inline bool is_jump();
+  inline bool is_jump_reg();
+  inline bool is_far_jump();
   inline bool is_cond_jump();
   inline bool is_safepoint_poll();
   inline bool is_mov_literal64();
@@ -105,6 +108,47 @@
   return inst;
 }
 
+class NativePltCall: public NativeInstruction {
+public:
+  enum Intel_specific_constants {
+    instruction_code           = 0xE8,
+    instruction_size           =    5,
+    instruction_offset         =    0,
+    displacement_offset        =    1,
+    return_address_offset      =    5
+  };
+  address instruction_address() const { return addr_at(instruction_offset); }
+  address next_instruction_address() const { return addr_at(return_address_offset); }
+  address displacement_address() const { return addr_at(displacement_offset); }
+  int displacement() const { return (jint) int_at(displacement_offset); }
+  address return_address() const { return addr_at(return_address_offset); }
+  address destination() const;
+  address plt_entry() const;
+  address plt_jump() const;
+  address plt_load_got() const;
+  address plt_resolve_call() const;
+  address plt_c2i_stub() const;
+  void set_stub_to_clean();
+
+  void  reset_to_plt_resolve_call();
+  void  set_destination_mt_safe(address dest);
+
+  void verify() const;
+};
+
+inline NativePltCall* nativePltCall_at(address address) {
+  NativePltCall* call = (NativePltCall*) address;
+#ifdef ASSERT
+  call->verify();
+#endif
+  return call;
+}
+
+inline NativePltCall* nativePltCall_before(address addr) {
+  address at = addr - NativePltCall::instruction_size;
+  return nativePltCall_at(at);
+}
+
 inline NativeCall* nativeCall_at(address address);
 // The NativeCall is an abstraction for accessing/manipulating native call imm32/rel32off
 // instructions (used to manipulate inline caches, primitive & dll calls, etc.).
@@ -129,9 +173,8 @@
   address destination() const;
   void  set_destination(address dest)       {
 #ifdef AMD64
-    assert((labs((intptr_t) dest - (intptr_t) return_address())  &
-            0xFFFFFFFF00000000) == 0,
-           "must be 32bit offset");
+    intptr_t disp = dest - return_address();
+    guarantee(disp == (intptr_t)(jint)disp, "must be 32-bit offset");
 #endif // AMD64
     set_int_at(displacement_offset, dest - return_address());
   }
@@ -158,6 +201,13 @@
       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);
 
@@ -380,6 +430,51 @@
   }
 };
 
+// destination is rbx or rax
+// mov rbx, [rip + offset]
+class NativeLoadGot: public NativeInstruction {
+#ifdef AMD64
+  static const bool has_rex = true;
+  static const int rex_size = 1;
+#else
+  static const bool has_rex = false;
+  static const int rex_size = 0;
+#endif
+public:
+  enum Intel_specific_constants {
+    rex_prefix = 0x48,
+    instruction_code = 0x8b,
+    modrm_rbx_code = 0x1d,
+    modrm_rax_code = 0x05,
+    instruction_length = 6 + rex_size,
+    offset_offset = 2 + rex_size
+  };
+
+  address instruction_address() const { return addr_at(0); }
+  address rip_offset_address() const { return addr_at(offset_offset); }
+  int rip_offset() const { return int_at(offset_offset); }
+  address return_address() const { return addr_at(instruction_length); }
+  address got_address() const { return return_address() + rip_offset(); }
+  address next_instruction_address() const { return return_address(); }
+  intptr_t data() const;
+  void set_data(intptr_t data) {
+    intptr_t *addr = (intptr_t *) got_address();
+    *addr = data;
+  }
+
+  void verify() const;
+private:
+  void report_and_fail() const;
+};
+
+inline NativeLoadGot* nativeLoadGot_at(address addr) {
+  NativeLoadGot* load = (NativeLoadGot*) addr;
+#ifdef ASSERT
+  load->verify();
+#endif
+  return load;
+}
+
 // jump rel32off
 
 class NativeJump: public NativeInstruction {
@@ -440,6 +535,29 @@
   return jump;
 }
 
+// far jump reg
+class NativeFarJump: public NativeInstruction {
+ public:
+  address jump_destination() const;
+
+  // Creation
+  inline friend NativeFarJump* nativeFarJump_at(address address);
+
+  void verify();
+
+  // Unit testing stuff
+  static void test() {}
+
+};
+
+inline NativeFarJump* nativeFarJump_at(address address) {
+  NativeFarJump* jump = (NativeFarJump*)(address);
+#ifdef ASSERT
+  jump->verify();
+#endif
+  return jump;
+}
+
 // Handles all kinds of jump on Intel. Long/far, conditional/unconditional
 class NativeGeneralJump: public NativeInstruction {
  public:
@@ -473,6 +591,36 @@
   return jump;
 }
 
+class NativeGotJump: public NativeInstruction {
+public:
+  enum Intel_specific_constants {
+    instruction_code = 0xff,
+    instruction_offset = 0,
+    instruction_size = 6,
+    rip_offset = 2
+  };
+
+  void verify() const;
+  address instruction_address() const { return addr_at(instruction_offset); }
+  address destination() const;
+  address return_address() const { return addr_at(instruction_size); }
+  int got_offset() const { return (jint) int_at(rip_offset); }
+  address got_address() const { return return_address() + got_offset(); }
+  address next_instruction_address() const { return addr_at(instruction_size); }
+  bool is_GotJump() const { return ubyte_at(0) == instruction_code; }
+
+  void set_jump_destination(address dest)  {
+    address *got_entry = (address *) got_address();
+    *got_entry = dest;
+  }
+};
+
+inline NativeGotJump* nativeGotJump_at(address addr) {
+  NativeGotJump* jump = (NativeGotJump*)(addr);
+  debug_only(jump->verify());
+  return jump;
+}
+
 class NativePopReg : public NativeInstruction {
  public:
   enum Intel_specific_constants {
@@ -544,6 +692,12 @@
                                                           ubyte_at(0) == NativeReturnX::instruction_code; }
 inline bool NativeInstruction::is_jump()         { return ubyte_at(0) == NativeJump::instruction_code ||
                                                           ubyte_at(0) == 0xEB; /* short jump */ }
+inline bool NativeInstruction::is_jump_reg()     {
+  int pos = 0;
+  if (ubyte_at(0) == Assembler::REX_B) pos = 1;
+  return ubyte_at(pos) == 0xFF && (ubyte_at(pos + 1) & 0xF0) == 0xE0;
+}
+inline bool NativeInstruction::is_far_jump()     { return is_mov_literal64(); }
 inline bool NativeInstruction::is_cond_jump()    { return (int_at(0) & 0xF0FF) == 0x800F /* long jump */ ||
                                                           (ubyte_at(0) & 0xF0) == 0x70;  /* short jump */ }
 inline bool NativeInstruction::is_safepoint_poll() {
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -800,7 +800,7 @@
   __ 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;
@@ -2758,7 +2758,7 @@
   // 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
@@ -2832,7 +2832,7 @@
   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())));
@@ -2947,7 +2947,7 @@
   __ reset_last_Java_frame(false);
 
 #if INCLUDE_JVMCI
-  if (EnableJVMCI) {
+  if (EnableJVMCI || UseAOT) {
     __ bind(after_fetch_unroll_info_call);
   }
 #endif
@@ -3112,7 +3112,7 @@
   _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);
   }
--- a/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -256,7 +256,7 @@
 #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 (UseJVMCICompiler && state == vtos && step == 0) {
+  if ((UseJVMCICompiler || UseAOT) && state == vtos && step == 0) {
     Label L;
     __ cmpb(Address(thread, JavaThread::pending_monitorenter_offset()), 0);
     __ jcc(Assembler::zero, L);
--- a/hotspot/src/cpu/x86/vm/x86_64.ad	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/cpu/x86/vm/x86_64.ad	Sun Dec 11 19:07:04 2016 -0800
@@ -2147,6 +2147,9 @@
         ciEnv::current()->record_failure("CodeCache is full");
         return;
       }
+#if INCLUDE_AOT
+      CompiledStaticCall::emit_to_aot_stub(cbuf, mark);
+#endif
     }
   %}
 
--- a/hotspot/src/cpu/zero/vm/compiledIC_zero.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/cpu/zero/vm/compiledIC_zero.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -60,11 +60,11 @@
   return 0;
 }
 
-void CompiledStaticCall::set_to_interpreted(methodHandle callee, address entry) {
+void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, address entry) {
   ShouldNotReachHere(); // Only needed for COMPILER2.
 }
 
-void CompiledStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
+void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
   ShouldNotReachHere(); // Only needed for COMPILER2.
 }
 
@@ -72,7 +72,7 @@
 // Non-product mode code.
 #ifndef PRODUCT
 
-void CompiledStaticCall::verify() {
+void CompiledDirectStaticCall::verify() {
   ShouldNotReachHere(); // Only needed for COMPILER2.
 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,866 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import jdk.tools.jaotc.binformat.Symbol.Binding;
+import jdk.tools.jaotc.binformat.Symbol.Kind;
+import jdk.tools.jaotc.binformat.elf.JELFRelocObject;
+import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
+
+/**
+ * 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 and Solaris operating systems or yet-to be created 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 class BinaryContainer implements SymbolTable {
+
+    private final int codeSegmentSize;
+
+    private final int codeEntryAlignment;
+
+    /**
+     * Container holding code bits and any other related information.
+     */
+    private final CodeContainer codeContainer;
+
+    /**
+     * Container holding external hotspot linkage bits (PLT entries).
+     */
+    private final CodeContainer extLinkageContainer;
+
+    /**
+     * Container holding global offset data for hotspot linkage.
+     */
+    private final ByteContainer extLinkageGOTContainer;
+
+    /**
+     * Patched by HotSpot, contains metaspace pointers.
+     */
+    private final ByteContainer metaspaceGotContainer;
+
+    /**
+     * 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<>();
+
+    private static final String[][] map = {
+//@formatter:off
+        {"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_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"},
+        {"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::_checkcast_arraycopy", "_aot_stub_routines_checkcast_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::_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::_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::_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::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::log_primitive", "_aot_jvmci_runtime_log_primitive"},
+        {"JVMCIRuntime::new_multi_array", "_aot_jvmci_runtime_new_multi_array"},
+        {"JVMCIRuntime::validate_object", "_aot_jvmci_runtime_validate_object"},
+        {"JVMCIRuntime::dynamic_new_array", "_aot_jvmci_runtime_dynamic_new_array"},
+        {"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::dynamic_new_instance", "_aot_jvmci_runtime_dynamic_new_instance"},
+        {"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"},
+        {"JVMCIRuntime::new_array", "_aot_jvmci_runtime_new_array"}
+        //@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.
+     */
+    public BinaryContainer(GraalHotSpotVMConfig config, String jvmVersion) {
+        this.codeSegmentSize = config.codeSegmentSize;
+        this.codeEntryAlignment = config.codeEntryAlignment;
+
+        // read only, code
+        codeContainer = new CodeContainer(".text", this);
+        extLinkageContainer = new CodeContainer(".hotspot.linkage.plt", this);
+
+        // read only, info
+        configContainer = new ReadOnlyDataContainer(".config", this);
+        metaspaceNamesContainer = new ReadOnlyDataContainer(".metaspace.names", this);
+        methodsOffsetsContainer = new ReadOnlyDataContainer(".methods.offsets", this);
+        klassesOffsetsContainer = new ReadOnlyDataContainer(".klasses.offsets", this);
+        klassesDependenciesContainer = new ReadOnlyDataContainer(".klasses.dependencies", this);
+
+        headerContainer = new HeaderContainer(jvmVersion, new ReadOnlyDataContainer(".header", this));
+        stubsOffsetsContainer = new ReadOnlyDataContainer(".stubs.offsets", this);
+        codeSegmentsContainer = new ReadOnlyDataContainer(".code.segments", this);
+        constantDataContainer = new ReadOnlyDataContainer(".method.constdata", this);
+
+        // needs relocation patching at load time by the loader
+        methodMetadataContainer = new ReadOnlyDataContainer(".method.metadata", this);
+
+        // writable sections
+        metaspaceGotContainer = new ByteContainer(".metaspace.got", this);
+        metadataGotContainer = new ByteContainer(".metadata.got", this);
+        methodStateContainer = new ByteContainer(".method.state", this);
+        oopGotContainer = new ByteContainer(".oop.got", this);
+        extLinkageGOTContainer = new ByteContainer(".hotspot.linkage.got", this);
+
+        addGlobalSymbols();
+
+        recordConfiguration(config);
+    }
+
+    private void recordConfiguration(GraalHotSpotVMConfig config) {
+        // @formatter:off
+        boolean[] booleanFlags = { config.cAssertions, // Debug VM
+                                   config.useCompressedOops,
+                                   config.useCompressedClassPointers,
+                                   config.compactFields,
+                                   config.useG1GC,
+                                   config.useCMSGC,
+                                   config.useTLAB,
+                                   config.useBiasedLocking,
+                                   TieredAOT.getValue(),
+                                   config.enableContended,
+                                   config.restrictContended,
+        };
+
+        int[] intFlags         = { config.narrowOopShift,
+                                   config.narrowKlassShift,
+                                   config.contendedPaddingWidth,
+                                   config.fieldsAllocationStyle,
+                                   config.objectAlignment,
+                                   config.codeSegmentSize,
+        };
+        // @formatter:on
+
+        byte[] booleanFlagsAsBytes = flagsToByteArray(booleanFlags);
+        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[] flagsToByteArray(boolean[] flags) {
+        byte[] byteArray = new byte[flags.length];
+        for (int i = 0; i < flags.length; ++i) {
+            byteArray[i] = boolToByte(flags[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 String getCardTableAddressSymbolName() {
+        return "_aot_card_table_address";
+    }
+
+    public String getHeapTopAddressSymbolName() {
+        return "_aot_heap_top_address";
+    }
+
+    public String getHeapEndAddressSymbolName() {
+        return "_aot_heap_end_address";
+    }
+
+    public String getCrcTableAddressSymbolName() {
+        return "_aot_stub_routines_crc_table_adr";
+    }
+
+    public String getPollingPageSymbolName() {
+        return "_aot_polling_page";
+    }
+
+    public String getResolveStaticEntrySymbolName() {
+        return "_resolve_static_entry";
+    }
+
+    public String getResolveVirtualEntrySymbolName() {
+        return "_resolve_virtual_entry";
+    }
+
+    public String getResolveOptVirtualEntrySymbolName() {
+        return "_resolve_opt_virtual_entry";
+    }
+
+    public String getNarrowKlassBaseAddressSymbolName() {
+        return "_aot_narrow_klass_base_address";
+    }
+
+    public String getLogOfHeapRegionGrainBytesSymbolName() {
+        return "_aot_log_of_heap_region_grain_bytes";
+    }
+
+    public String getInlineContiguousAllocationSupportedSymbolName() {
+        return "_aot_inline_contiguous_allocation_supported";
+    }
+
+    public int getCodeSegmentSize() {
+        return codeSegmentSize;
+    }
+
+    public int getCodeEntryAlignment() {
+        return codeEntryAlignment;
+    }
+
+    /**
+     * 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 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(metaspaceGotContainer);
+        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(getPollingPageSymbolName());
+        createGotSymbol(getLogOfHeapRegionGrainBytesSymbolName());
+        createGotSymbol(getInlineContiguousAllocationSupportedSymbolName());
+
+        for (HashMap.Entry<String, String> entry : functionNamesToAOTSymbols.entrySet()) {
+            createGotSymbol(entry.getValue());
+        }
+    }
+
+    /**
+     * Creates a global symbol of the form {@code "JVM" + container name}.
+     *
+     * @param container container to create a symbol for
+     */
+    private static void createContainerSymbol(ByteContainer container) {
+        container.createSymbol(0, Kind.OBJECT, Binding.GLOBAL, 0, "JVM" + 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, String aotVersion) throws IOException {
+        String osName = System.getProperty("os.name");
+        switch (osName) {
+            case "Linux":
+            case "SunOS":
+                JELFRelocObject elfso = new JELFRelocObject(this, outputFileName, aotVersion);
+                elfso.createELFRelocObject(relocationTable, symbolTable.values());
+                break;
+            default:
+                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
+     */
+    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 [" + symName + "] [" + 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 int appendMetaspaceGotBytes(byte[] bytes, int offset, int size) {
+        int startOffset = metaspaceGotContainer.getByteStreamSize();
+        appendBytes(metaspaceGotContainer, 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 addMetaspaceSymbol(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:
+            metaspaceGotContainer.createGotSymbol(gotName);
+        }
+        return metaspaceOffset;
+    }
+
+    public Symbol getGotSymbol(String name) {
+        assert name.startsWith("got.");
+        return symbolTable.get(name);
+    }
+
+    /**
+     * Add metaspace 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 metaspace.got
+     * section with another slot for the VM to patch
+     *
+     * @param metaspaceName name of the metaspace symbol
+     * @return the got offset in the metaspace.got of the metaspace symbol
+     */
+    public int addTwoSlotMetaspaceSymbol(String metaspaceName) {
+        String gotName = "got." + metaspaceName;
+        Symbol previous = getGotSymbol(gotName);
+        assert previous == null : "should be called only once for: " + metaspaceName;
+        // Add slots when asked in the .metaspace.got section:
+        // First slot
+        String gotInitName = "got.init." + metaspaceName;
+        GotSymbol slot1Symbol = metaspaceGotContainer.createGotSymbol(gotInitName);
+        GotSymbol slot2Symbol = metaspaceGotContainer.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 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 method.constdata section
+     *
+     * @param data
+     * @param alignment
+     * @return the offset in the method.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 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 CodeContainer getExtLinkageContainer() {
+        return extLinkageContainer;
+    }
+
+    public ByteContainer getExtLinkageGOTContainer() {
+        return extLinkageGOTContainer;
+    }
+
+    public ByteContainer 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 getMetaspaceGotContainer() {
+        return metaspaceGotContainer;
+    }
+
+    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;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/ByteContainer.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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 jdk.tools.jaotc.jnilibelf.ELFContainer;
+
+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 ELFContainer {
+    /**
+     * {@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
+     */
+    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;
+    }
+
+    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;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/CodeContainer.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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 class CodeContainer extends ByteContainer {
+
+    public CodeContainer(String containerName, SymbolTable symbolTable) {
+        super(containerName, symbolTable);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/GotSymbol.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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 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;
+    }
+
+    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 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"
+     */
+    public GotSymbol(int offset, Kind type, Binding binding, ByteContainer sec, String name) {
+        super(offset, type, binding, sec, GOT_SIZE, name);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/HeaderContainer.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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 class HeaderContainer {
+
+    private static final int CURRENT_VERSION = 1;
+    private final ReadOnlyDataContainer container;
+    // int _version;
+    // int _class_count;
+    // int _method_count;
+    // int _metaspace_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 setMetaspaceGotSize(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);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/ReadOnlyDataContainer.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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 class ReadOnlyDataContainer extends ByteContainer {
+
+    public ReadOnlyDataContainer(String containerName, SymbolTable symbolTable) {
+        super(containerName, symbolTable);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/Relocation.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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 class Relocation {
+
+    public enum RelocType {
+        UNDEFINED,
+        JAVA_CALL_INDIRECT,
+        JAVA_CALL_DIRECT,
+        FOREIGN_CALL_INDIRECT,
+        FOREIGN_CALL_INDIRECT_GOT, // Call to address in GOT cell
+        FOREIGN_CALL_DIRECT,
+        FOREIGN_CALL_DIRECT_FAR,
+        STUB_CALL_DIRECT,
+        STUB_CALL_INDIRECT,
+        EXTERNAL_DATA_REFERENCE_FAR,
+        METASPACE_GOT_REFERENCE,
+        EXTERNAL_GOT_TO_PLT,
+        EXTERNAL_PLT_TO_GOT,
+        STATIC_STUB_TO_STATIC_METHOD,
+        STATIC_STUB_TO_HOTSPOT_LINKAGE_GOT,
+        LOADTIME_ADDRESS
+    }
+
+    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;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/Symbol.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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;
+
+import jdk.tools.jaotc.jnilibelf.ELFSymbol;
+
+public class Symbol {
+
+    public enum Binding {
+        UNDEFINED,
+        LOCAL,
+        GLOBAL
+    }
+
+    public enum Kind {
+        UNDEFINED,
+        NATIVE_FUNCTION,
+        JAVA_FUNCTION,
+        STATIC_STUB_CALL, // static call stub inside the text section
+        OBJECT,
+        NOTYPE
+    }
+
+    private final String name;
+    private final int size;
+    private final int offset;
+    private final Binding binding;
+    private final Kind kind;
+
+    private ByteContainer section;
+    private ELFSymbol elfSymbol;
+
+    /**
+     * 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 ELFSymbol getElfSymbol() {
+        return elfSymbol;
+    }
+
+    public void setElfSymbol(ELFSymbol elfSymbol) {
+        this.elfSymbol = elfSymbol;
+    }
+
+    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 + "]";
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/SymbolTable.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/JELFRelocObject.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,420 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.nio.charset.StandardCharsets;
+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.jnilibelf.ELFContainer;
+import jdk.tools.jaotc.jnilibelf.ELFSymbol;
+import jdk.tools.jaotc.jnilibelf.JNIELFContainer;
+import jdk.tools.jaotc.jnilibelf.JNIELFRelocation;
+import jdk.tools.jaotc.jnilibelf.JNIELFTargetInfo;
+import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.ELF;
+import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.LibELF.Elf_Cmd;
+import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.LibELF.Elf_Type;
+import jdk.tools.jaotc.jnilibelf.Pointer;
+
+public class JELFRelocObject {
+
+    private final BinaryContainer binContainer;
+
+    private final JNIELFContainer elfContainer;
+
+    private final int segmentSize;
+
+    public JELFRelocObject(BinaryContainer binContainer, String outputFileName, String aotVersion) {
+        this.binContainer = binContainer;
+        this.elfContainer = new JNIELFContainer(outputFileName, aotVersion);
+        this.segmentSize = binContainer.getCodeSegmentSize();
+    }
+
+    private void createByteSection(ByteContainer c, int scnFlags) {
+        byte[] scnData = c.getByteArray();
+        int scnType = ELF.SHT_PROGBITS;
+        boolean zeros = !c.hasRelocations();
+        if (zeros) {
+            for (byte b : scnData) {
+                if (b != 0) {
+                    zeros = false;
+                    break;
+                }
+            }
+            if (zeros) {
+                scnType = ELF.SHT_NOBITS;
+            }
+        }
+
+        int sectionId = elfContainer.createSection(c.getContainerName(), scnData, Elf_Type.ELF_T_BYTE, segmentSize, scnType, scnFlags, ELF.SHN_UNDEF, 0);
+        c.setSectionId(sectionId);
+        // Clear out code section data to allow for GC
+        c.clear();
+    }
+
+    private void createCodeSection(CodeContainer c) {
+        createByteSection(c, ELF.SHF_ALLOC | ELF.SHF_EXECINSTR);
+    }
+
+    private void createReadOnlySection(ReadOnlyDataContainer c) {
+        createByteSection(c, ELF.SHF_ALLOC);
+    }
+
+    private void createReadWriteSection(ByteContainer c) {
+        createByteSection(c, ELF.SHF_ALLOC | ELF.SHF_WRITE);
+    }
+
+    /**
+     * Create an ELF relocatable object using jdk.tools.jaotc.jnilibelf API.
+     *
+     * @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
+        elfContainer.createELFHeader(ELF.ET_REL);
+
+        // Create text section
+        createCodeSection(binContainer.getCodeContainer());
+        createReadOnlySection(binContainer.getMetaspaceNamesContainer());
+        createReadOnlySection(binContainer.getKlassesOffsetsContainer());
+        createReadOnlySection(binContainer.getMethodsOffsetsContainer());
+        createReadOnlySection(binContainer.getKlassesDependenciesContainer());
+        createReadWriteSection(binContainer.getMetaspaceGotContainer());
+        createReadWriteSection(binContainer.getMetadataGotContainer());
+        createReadWriteSection(binContainer.getMethodStateContainer());
+        createReadWriteSection(binContainer.getOopGotContainer());
+        createReadWriteSection(binContainer.getMethodMetadataContainer());
+        createReadOnlySection(binContainer.getStubsOffsetsContainer());
+        createReadOnlySection(binContainer.getHeaderContainer().getContainer());
+        createReadOnlySection(binContainer.getCodeSegmentsContainer());
+        createReadOnlySection(binContainer.getConstantDataContainer());
+        createReadOnlySection(binContainer.getConfigContainer());
+
+        // createExternalLinkage();
+
+        createCodeSection(binContainer.getExtLinkageContainer());
+        createReadWriteSection(binContainer.getExtLinkageGOTContainer());
+
+        // Get ELF symbol data from BinaryContainer object's symbol tables
+        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
+        int strTabSectionIndex = elfContainer.createSection(".strtab", elfContainer.getStrTabContent().getBytes(StandardCharsets.UTF_8), Elf_Type.ELF_T_BYTE, 1, ELF.SHT_STRTAB, 0, ELF.SHN_UNDEF, 0);
+
+        // 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
+        int scnInfo = elfContainer.getFirstNonLocalSymbolIndex();
+        int symTabSectionIndex = elfContainer.createSection(".symtab", getELFSymbolTableData(), Elf_Type.ELF_T_SYM, 8, ELF.SHT_SYMTAB, ELF.SHF_ALLOC, strTabSectionIndex, scnInfo);
+
+        buildRelocations(relocationTable, symTabSectionIndex);
+
+        // Now, finally, after creating all sections, create shstrtab section
+        elfContainer.createSection(".shstrtab", elfContainer.getShStrTabContent().getBytes(StandardCharsets.UTF_8), Elf_Type.ELF_T_BYTE, 1, ELF.SHT_STRTAB, 0, ELF.SHN_UNDEF, 0);
+
+        // Run elf_update
+        elfContainer.elfUpdate(Elf_Cmd.ELF_C_NULL);
+
+        // Run elfUpdate again to write it out.
+        elfContainer.elfUpdate(Elf_Cmd.ELF_C_WRITE);
+        // Finish ELF processing
+        elfContainer.elfEnd();
+    }
+
+    private void buildRelocations(Map<Symbol, List<Relocation>> relocationTable, final int symTabSectionIndex) {
+        /*
+         * Create relocation sections. This needs to be done after symbol table sections were
+         * created since relocation entries will need indices of sections to which they apply.
+         */
+        createELFRelocationTables(relocationTable);
+        createAllRelocationSections(new SymTabELFContainer(symTabSectionIndex));
+    }
+
+    /**
+     * 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 void createELFSymbolTables(Collection<Symbol> symbols) {
+        // First, create the initial null symbol. This is a local symbol.
+        elfContainer.createELFSymbolEntry("", 0, 0, ELF.SHN_UNDEF, 0, 0, true);
+
+        // 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();
+            boolean isLocal = (symbol.getBinding() == Binding.LOCAL);
+            ELFSymbol elfSymbol = elfContainer.createELFSymbolEntry(symbol.getName(), getELFTypeOf(symbol), getELFBindOf(symbol), secHdrIndex, symbol.getSize(), symbol.getOffset(), isLocal);
+            symbol.setElfSymbol(elfSymbol);
+        }
+    }
+
+    /**
+     * Construct ELF symbol data from BinaryContainer object's symbol tables.
+     *
+     * @return a byte array containing the symbol table
+     */
+    private byte[] getELFSymbolTableData() {
+        final int entrySize = JNIELFTargetInfo.sizeOfSymtabEntry();
+
+        // First, add all local symbols.
+        List<ELFSymbol> localSymbols = elfContainer.getLocalSymbols();
+        List<ELFSymbol> globalSymbols = elfContainer.getGlobalSymbols();
+
+        int localSymCount = localSymbols.size();
+        int globalSymCount = globalSymbols.size();
+        byte[] sectionDataArray = new byte[(localSymCount + globalSymCount) * entrySize];
+
+        for (int i = 0; i < localSymCount; i++) {
+            ELFSymbol symbol = localSymbols.get(i);
+            Pointer address = symbol.getAddress();
+            address.copyBytesTo(sectionDataArray, entrySize, i * entrySize);
+        }
+
+        // Next, add all global symbols.
+
+        for (int i = 0; i < globalSymCount; i++) {
+            ELFSymbol symbol = globalSymbols.get(i);
+            Pointer address = symbol.getAddress();
+            address.copyBytesTo(sectionDataArray, entrySize, (localSymCount + i) * entrySize);
+        }
+
+        return sectionDataArray;
+    }
+
+    private static int getELFTypeOf(Symbol sym) {
+        Kind kind = sym.getKind();
+        if (kind == Symbol.Kind.NATIVE_FUNCTION || kind == Symbol.Kind.JAVA_FUNCTION) {
+            return ELF.STT_FUNC;
+        } else if (kind == Symbol.Kind.OBJECT) {
+            return ELF.STT_OBJECT;
+        }
+        return ELF.STT_NOTYPE;
+    }
+
+    private static int getELFBindOf(Symbol sym) {
+        Binding binding = sym.getBinding();
+        if (binding == Symbol.Binding.GLOBAL) {
+            return ELF.STB_GLOBAL;
+        }
+        return ELF.STB_LOCAL;
+    }
+
+    /**
+     * Construct ELF relocation section data from BinaryContainer object's relocation tables.
+     *
+     * @param relocationTable
+     */
+    private void createELFRelocationTables(Map<Symbol, List<Relocation>> relocationTable) {
+        /*
+         * For each of the symbols with associated relocation records, create an 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);
+            }
+        }
+
+        for (Map.Entry<Symbol, Relocation> entry : binContainer.getUniqueRelocationTable().entrySet()) {
+            createRelocation(entry.getKey(), entry.getValue());
+        }
+    }
+
+    private void createRelocation(Symbol symbol, Relocation reloc) {
+        RelocType relocType = reloc.getType();
+        int elfRelocType = getELFRelocationType(relocType);
+
+        switch (relocType) {
+            case FOREIGN_CALL_DIRECT:
+            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
+                int offset = reloc.getOffset() + reloc.getSize() + addend;
+                elfContainer.createELFRelocationEntry(reloc.getSection(), offset, elfRelocType, addend, symbol.getElfSymbol());
+                break;
+            }
+            case FOREIGN_CALL_DIRECT_FAR: {
+                // Create relocation entry
+                int addend = -8; // Size in bytes of the patch location
+                // Relocation should be applied at the location after call operand
+                // 10 = 2 (jmp [r]) + 8 (imm64)
+                int offset = reloc.getOffset() + reloc.getSize() + addend - 2;
+                elfContainer.createELFRelocationEntry(reloc.getSection(), offset, elfRelocType, addend, symbol.getElfSymbol());
+                break;
+            }
+            case FOREIGN_CALL_INDIRECT:
+            case JAVA_CALL_INDIRECT:
+            case STUB_CALL_INDIRECT: {
+                // Do nothing.
+                break;
+            }
+            case EXTERNAL_DATA_REFERENCE_FAR: {
+                // Create relocation entry
+                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.
+                 */
+                int offset = reloc.getOffset() + addend;
+                elfContainer.createELFRelocationEntry(reloc.getSection(), offset, elfRelocType, addend, symbol.getElfSymbol());
+                break;
+            }
+            case METASPACE_GOT_REFERENCE:
+            case EXTERNAL_PLT_TO_GOT:
+            case STATIC_STUB_TO_STATIC_METHOD:
+            case STATIC_STUB_TO_HOTSPOT_LINKAGE_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.
+                 */
+                int offset = reloc.getOffset() + addend;
+                elfContainer.createELFRelocationEntry(reloc.getSection(), offset, elfRelocType, addend, symbol.getElfSymbol());
+                break;
+            }
+            case EXTERNAL_GOT_TO_PLT:
+            case LOADTIME_ADDRESS: {
+                // this is load time relocations
+                elfContainer.createELFRelocationEntry(reloc.getSection(), reloc.getOffset(), elfRelocType, 0, symbol.getElfSymbol());
+                break;
+            }
+            default:
+                throw new InternalError("Unhandled relocation type: " + relocType);
+        }
+    }
+
+    // TODO: Populate the mapping of RelocType to ELF relocation types
+    private static int getELFRelocationType(RelocType relocType) {
+        int elfRelocType = 0; // R_<ARCH>_NONE if #define'd to 0 for all values of ARCH
+        switch (JNIELFTargetInfo.getELFArch()) {
+            case ELF.EM_X64_64:
+                // Return R_X86_64_* entries based on relocType
+                if (relocType == RelocType.FOREIGN_CALL_DIRECT || relocType == RelocType.JAVA_CALL_DIRECT || relocType == RelocType.FOREIGN_CALL_INDIRECT_GOT) {
+                    elfRelocType = JNIELFRelocation.X86_64.R_X86_64_PLT32;
+                } else if (relocType == RelocType.STUB_CALL_DIRECT) {
+                    elfRelocType = JNIELFRelocation.X86_64.R_X86_64_PC32;
+                } else if (relocType == RelocType.FOREIGN_CALL_DIRECT_FAR) {
+                    elfRelocType = JNIELFRelocation.X86_64.R_X86_64_64;
+                } else if (relocType == RelocType.FOREIGN_CALL_INDIRECT || relocType == RelocType.JAVA_CALL_INDIRECT || relocType == RelocType.STUB_CALL_INDIRECT) {
+                    elfRelocType = JNIELFRelocation.X86_64.R_X86_64_NONE;
+                } else if ((relocType == RelocType.EXTERNAL_DATA_REFERENCE_FAR)) {
+                    elfRelocType = JNIELFRelocation.X86_64.R_X86_64_GOTPCREL;
+                } else if (relocType == RelocType.METASPACE_GOT_REFERENCE || relocType == RelocType.EXTERNAL_PLT_TO_GOT || relocType == RelocType.STATIC_STUB_TO_STATIC_METHOD ||
+                                relocType == RelocType.STATIC_STUB_TO_HOTSPOT_LINKAGE_GOT) {
+                    elfRelocType = JNIELFRelocation.X86_64.R_X86_64_PC32;
+                } else if (relocType == RelocType.EXTERNAL_GOT_TO_PLT || relocType == RelocType.LOADTIME_ADDRESS) {
+                    elfRelocType = JNIELFRelocation.X86_64.R_X86_64_64;
+                } else {
+                    assert false : "Unhandled relocation type: " + relocType;
+                }
+                break;
+            default:
+                System.out.println("Relocation Type mapping: Unhandled architecture");
+        }
+        return elfRelocType;
+    }
+
+    private void createAllRelocationSections(ELFContainer symtab) {
+        for (Map.Entry<ELFContainer, ArrayList<Pointer>> entry : elfContainer.getRelocTables().entrySet()) {
+            createRelocationSection(entry.getKey(), entry.getValue(), symtab);
+        }
+    }
+
+    private void createRelocationSection(ELFContainer container, ArrayList<Pointer> relocations, ELFContainer symtab) {
+        String secName = container.getContainerName();
+        int entrySize = JNIELFTargetInfo.sizeOfRelocEntry();
+        int numEntries = relocations.size();
+        byte[] sectionDataBytes = new byte[numEntries * entrySize];
+
+        for (int index = 0; index < relocations.size(); index++) {
+            Pointer entry = relocations.get(index);
+            entry.copyBytesTo(sectionDataBytes, entrySize, index * entrySize);
+        }
+        String fullSecName;
+        // If relocDat is non-null create section
+        if (sectionDataBytes.length > 0) {
+            int scnType;
+            Elf_Type dataType;
+            if (JNIELFTargetInfo.createReloca() == 0) {
+                scnType = ELF.SHT_REL;
+                dataType = Elf_Type.ELF_T_REL;
+                fullSecName = ".rel" + secName;
+            } else {
+                scnType = ELF.SHT_RELA;
+                dataType = Elf_Type.ELF_T_RELA;
+                fullSecName = ".rela" + secName;
+            }
+            // assert compareBytes(relocData.toByteArray(), sectionDataBytes) : "******* Bad array
+            // copy";
+            // sh_link holds the index of section header of symbol table associated with this
+            // relocation table.
+            // sh_info holds the index of section header to which this relocation table applies
+            // to.
+            elfContainer.createSection(fullSecName, sectionDataBytes, dataType, 8, scnType, ELF.SHF_ALLOC, symtab.getSectionId(), container.getSectionId());
+        }
+    }
+
+    private static class SymTabELFContainer implements ELFContainer {
+        private final int symTabSectionIndex;
+
+        public SymTabELFContainer(int symTabSectionIndex) {
+            this.symTabSectionIndex = symTabSectionIndex;
+        }
+
+        @Override
+        public String getContainerName() {
+            return ".symtab";
+        }
+
+        @Override
+        public int getSectionId() {
+            return symTabSectionIndex;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/ELFContainer.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.jnilibelf;
+
+public interface ELFContainer {
+
+    String getContainerName();
+
+    int getSectionId();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/ELFSymbol.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.jnilibelf;
+
+/**
+ * This class represents a {@code Elf32_Sym} or {@code Elf64_Sym} as defined in {@code elf.h}.
+ */
+public class ELFSymbol {
+    /** Symbol name. */
+    private final String name;
+
+    /** String table index. */
+    private final int index;
+
+    /** Native memory address of ELF sym entry. */
+    private final Pointer address;
+    private final boolean isLocal;
+
+    public ELFSymbol(String name, int index, Pointer address, boolean isLocal) {
+        this.name = name;
+        this.index = index;
+        this.address = address;
+        this.isLocal = isLocal;
+    }
+
+    /**
+     * @return the name
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * @return the index
+     */
+    public int getIndex() {
+        return index;
+    }
+
+    /**
+     * @return the address
+     */
+    public Pointer getAddress() {
+        return address;
+    }
+
+    @Override
+    public String toString() {
+        return "name=" + name + ", index=" + index + ", address=" + address;
+    }
+
+    public boolean isLocal() {
+        return isLocal;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNIELFContainer.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,476 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.jnilibelf;
+
+import static jdk.tools.jaotc.jnilibelf.UnsafeAccess.UNSAFE;
+
+import java.io.File;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.ELF;
+import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.LibELF;
+import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.LibELF.Elf_Type;
+
+/**
+ * A class abstraction of an ELF file.
+ *
+ */
+public class JNIELFContainer {
+
+    private String outputFileName;
+    private File outFile;
+    private int outFileDesc;
+
+    /**
+     * Pointer to Elf file. This is the same as struct Elf found in libelf.h
+     */
+    private Pointer elfPtr;
+
+    /**
+     * Class of the ELF container - one of ELFCLASS32 or ELFCLASS64.
+     */
+    private final int elfClass;
+
+    /**
+     * Pointer to ELF Header.
+     */
+    private Pointer ehdrPtr;
+
+    /**
+     * Pointer to Program Header.
+     */
+    private Pointer phdrPtr;
+
+    /**
+     * String holding .shstrtab contents.
+     */
+    private String shStrTabContent = "";
+
+    /**
+     * Map of local symbol indexes to ELF symbol entries.
+     */
+    private List<ELFSymbol> localSymbolIndex = new ArrayList<>();
+
+    /**
+     * Map of global symbol indexes to ELF symbol entries.
+     */
+    private List<ELFSymbol> globalSymbolIndex = new ArrayList<>();
+
+    /**
+     * String holding .strtab contents.
+     */
+    private StringBuilder strTabContent = new StringBuilder();
+
+    /**
+     * Keeps track of nr of bytes in .strtab since strTabContent.length() is number of chars, not
+     * bytes.
+     */
+    private int strTabNrOfBytes = 0;
+
+    /**
+     * A hashtable that holds (section-name, relocation-table) pairs. For example, [(".rela.text",
+     * rela-text-reloc-entries), (".rela.plt", rela-plt-reloc-entries), ...].
+     */
+    private Map<ELFContainer, ArrayList<Pointer>> relocTables = new HashMap<>();
+
+    /**
+     * Create reloca; 0 => false and non-zero => true.
+     */
+    private final int createReloca;
+
+    /**
+     * Construct an ELFContainer in preparation for a disk image with file {@code prefix}.
+     *
+     * @param fileName name of ELF file to be created
+     */
+    public JNIELFContainer(String fileName, String aotVersion) {
+        // Check for version compatibility
+        if (!JNILibELFAPI.elfshim_version().equals(aotVersion)) {
+            throw new InternalError("libelfshim version mismatch: " + JNILibELFAPI.elfshim_version() + " vs " + aotVersion);
+        }
+
+        elfClass = JNIELFTargetInfo.getELFClass();
+        createReloca = JNIELFTargetInfo.createReloca();
+        outputFileName = fileName;
+    }
+
+    /**
+     * Get the local ELF symbol table.
+     *
+     * @return local symbol table
+     */
+    public List<ELFSymbol> getLocalSymbols() {
+        return localSymbolIndex;
+    }
+
+    /**
+     * Get the global ELF symbol table.
+     *
+     * @return list of global ELF symbol table entries
+     */
+    public List<ELFSymbol> getGlobalSymbols() {
+        return globalSymbolIndex;
+    }
+
+    /**
+     * Get string table content (.strtab).
+     *
+     * @return string table content
+     */
+    public String getStrTabContent() {
+        return strTabContent.toString();
+    }
+
+    /**
+     * Get section header string table content (.shstrtab).
+     *
+     * @return section header string table content
+     */
+    public String getShStrTabContent() {
+        return shStrTabContent;
+    }
+
+    /**
+     * Get relocation tables.
+     *
+     * @return relocation tables
+     */
+    public Map<ELFContainer, ArrayList<Pointer>> getRelocTables() {
+        return relocTables;
+    }
+
+    /**
+     * Get the index of first non-local symbol in symbol table.
+     *
+     * @return symbol table index
+     */
+    public int getFirstNonLocalSymbolIndex() {
+        return localSymbolIndex.size();
+    }
+
+    /**
+     * Create ELF header of type {@code ececType}.
+     *
+     * @param type type of ELF executable
+     */
+    public void createELFHeader(int type) {
+        // Check for version compatibility
+        if (JNILibELFAPI.elf_version(ELF.EV_CURRENT) == ELF.EV_NONE) {
+            throw new InternalError("ELF version mismatch");
+        }
+
+        outFile = constructRelocFile(outputFileName);
+        // Open a temporary file for the shared library to be created
+        // TODO: Revisit file permissions; need to add execute permission
+        outFileDesc = JNILibELFAPI.open_rw(outFile.getPath());
+
+        if (outFileDesc == -1) {
+            System.out.println("Failed to open file " + outFile.getPath() + " to write relocatable object.");
+        }
+
+        elfPtr = JNILibELFAPI.elf_begin(outFileDesc, LibELF.Elf_Cmd.ELF_C_WRITE.intValue(), new Pointer(0L));
+        if (elfPtr == null) {
+            throw new InternalError("elf_begin failed");
+        }
+
+        // Allocate new Ehdr of current architecture class
+
+        ehdrPtr = JNILibELFAPI.gelf_newehdr(elfPtr, elfClass);
+
+        JNILibELFAPI.ehdr_set_data_encoding(ehdrPtr, JNIELFTargetInfo.getELFEndian());
+        JNILibELFAPI.set_Ehdr_e_machine(elfClass, ehdrPtr, JNIELFTargetInfo.getELFArch());
+        JNILibELFAPI.set_Ehdr_e_type(elfClass, ehdrPtr, type);
+        JNILibELFAPI.set_Ehdr_e_version(elfClass, ehdrPtr, ELF.EV_CURRENT);
+    }
+
+    /**
+     * If the file name has a .so extension, replace it with .o extension. Else just add .o
+     * extension
+     *
+     * @param fileName
+     * @return File object
+     */
+    private static File constructRelocFile(String fileName) {
+        File relocFile = new File(fileName);
+        if (relocFile.exists()) {
+            if (!relocFile.delete()) {
+                throw new InternalError("Failed to delete existing " + fileName + " file");
+            }
+        }
+        return relocFile;
+    }
+
+    /**
+     * Create {@code count} number of Program headers.
+     *
+     * @param count number of program headers to create
+     * @return true upon success; false upon failure
+     */
+    public boolean createProgramHeader(int count) {
+        phdrPtr = JNILibELFAPI.gelf_newphdr(elfPtr, count);
+        if (phdrPtr == null) {
+            System.out.println("gelf_newphdr error");
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Set program header to be of type self.
+     *
+     * @return true
+     */
+    public boolean setProgHdrTypeToSelf() {
+        // Set program header to be of type self
+        JNILibELFAPI.phdr_set_type_self(elfClass, ehdrPtr, phdrPtr);
+        // And thus mark it as dirty so that elfUpdate can recompute the structures
+        JNILibELFAPI.elf_flagphdr(elfPtr, LibELF.Elf_Cmd.ELF_C_SET.intValue(), LibELF.ELF_F_DIRTY);
+        // TODO: Error checking; look at the return value of elf_update
+        // and call elf_errmsg appropriately.
+        return true;
+    }
+
+    /**
+     * Create a section. The corresponding section header and section data are created by calling
+     * the necessary libelf APIs. The section that is created is inserted into the ELF container.
+     *
+     * @param secName name of the section
+     * @param scnData section data
+     * @param dataType data type
+     * @param align section alignment
+     * @param scnType section type
+     * @param scnFlags section flags
+     * @param scnLink sh_link field of Elf{32,64}_Shdr
+     * @param scnInfo sh_info field of Elf{32,64}_Shdr
+     * @return section index
+     */
+    public int createSection(String secName, byte[] scnData, Elf_Type dataType, int align, int scnType, int scnFlags, int scnLink, int scnInfo) {
+        // Create a new section
+        Pointer scnPtr = JNILibELFAPI.elf_newscn(elfPtr);
+        if (scnPtr == null) {
+            throw new InternalError("elf_newscn error");
+        }
+
+        // Allocate section data for the section
+        Pointer scnDataPtr = JNILibELFAPI.elf_newdata(scnPtr);
+        if (scnDataPtr == null) {
+            String errMsg = JNILibELFAPI.elf_errmsg(-1);
+            throw new InternalError("elf_newdata error: " + errMsg);
+        }
+
+        // Get the pointer to section header associated with the new section
+        Pointer scnHdrPtr = JNILibELFAPI.elf64_getshdr(scnPtr);
+
+        // Add name of the section to section name string
+        // If secName is null, point the name to the 0th index
+        // that holds `\0'
+        byte[] modScnData;
+        if (secName.isEmpty()) {
+            JNILibELFAPI.set_Shdr_sh_name(elfClass, scnHdrPtr, 0);
+            modScnData = scnData;
+        } else {
+            if (secName.equals(".shstrtab")) {
+                // Modify .shstrtab data by inserting '\0' at index 0
+                String shstrtabSecName = ".shstrtab" + '\0';
+                // Additional byte for the '\0' at position 0
+                ByteBuffer nbuf = ByteBuffer.allocate(scnData.length + 1 + shstrtabSecName.length());
+                nbuf.put(0, (byte) 0);
+                nbuf.position(1);
+                nbuf.put(scnData);
+                nbuf.position(scnData.length + 1);
+                // Add the section name ".shstrtab" to its own data
+                nbuf.put(shstrtabSecName.getBytes(StandardCharsets.UTF_8));
+                modScnData = nbuf.array();
+                JNILibELFAPI.set_Shdr_sh_name(elfClass, scnHdrPtr, scnData.length + 1);
+                // Set strtab section index
+                JNILibELFAPI.set_Ehdr_e_shstrndx(elfClass, ehdrPtr, JNILibELFAPI.elf_ndxscn(scnPtr));
+            } else if (secName.equals(".strtab")) {
+                // Modify strtab section data to insert '\0' at position 0.
+                // Additional byte for the '\0' at position 0
+                ByteBuffer nbuf = ByteBuffer.allocate(scnData.length + 1);
+                nbuf.put(0, (byte) 0);
+                nbuf.position(1);
+                nbuf.put(scnData);
+                modScnData = nbuf.array();
+                // Set the sh_name
+                JNILibELFAPI.set_Shdr_sh_name(elfClass, scnHdrPtr, shStrTabContent.length() + 1);
+                // Add scnName to stringList
+                shStrTabContent += secName + '\0';
+            } else {
+                // Set the sh_name
+                JNILibELFAPI.set_Shdr_sh_name(elfClass, scnHdrPtr, shStrTabContent.length() + 1);
+                // Add scnName to stringList
+                shStrTabContent += secName + '\0';
+                modScnData = scnData;
+            }
+        }
+
+        final int scnDataBufSize = modScnData.length;
+
+        Pointer scnDataBufPtr = null;
+        if (scnType != ELF.SHT_NOBITS) {
+        // Allocate native memory for section data
+          final long address = UNSAFE.allocateMemory(scnDataBufSize + 1);
+          scnDataBufPtr = new Pointer(address);
+          scnDataBufPtr.put(modScnData);
+        } else {
+          scnDataBufPtr = new Pointer(0L);
+        }
+
+        // Set data descriptor fields
+        JNILibELFAPI.set_Data_d_align(scnDataPtr, align);
+        JNILibELFAPI.set_Data_d_buf(scnDataPtr, scnDataBufPtr);
+        JNILibELFAPI.set_Data_d_size(scnDataPtr, scnDataBufSize);
+        JNILibELFAPI.set_Data_d_off(scnDataPtr, 0);
+        JNILibELFAPI.set_Data_d_type(scnDataPtr, dataType.intValue());
+        JNILibELFAPI.set_Data_d_version(scnDataPtr, ELF.EV_CURRENT);
+
+        JNILibELFAPI.set_Shdr_sh_type(elfClass, scnHdrPtr, scnType);
+        JNILibELFAPI.set_Shdr_sh_flags(elfClass, scnHdrPtr, scnFlags);
+        JNILibELFAPI.set_Shdr_sh_entsize(elfClass, scnHdrPtr, 0); // TODO: Is this right??
+        JNILibELFAPI.set_Shdr_sh_link(elfClass, scnHdrPtr, scnLink);
+        JNILibELFAPI.set_Shdr_sh_info(elfClass, scnHdrPtr, scnInfo);
+
+        // Add hash section to section pointer list
+        int index = JNILibELFAPI.elf_ndxscn(scnPtr);
+        return index;
+    }
+
+    /**
+     * Create an ELF symbol entry for a symbol with the given properties.
+     *
+     * @param name name of the section in which symName is referenced
+     * @param type type of symName
+     * @param bind binding of symName
+     * @param secHdrIndex section header index of the section in which symName is referenced
+     *            (st_shndx of ELF symbol entry)
+     * @param size symName size (st_size of ELF symbol entry)
+     * @param value symName value (st_value of ELF symbol entry)
+     * @param isLocal true if symbol is local.
+     */
+    public ELFSymbol createELFSymbolEntry(String name, int type, int bind, int secHdrIndex, int size, int value, boolean isLocal) {
+        // Get the current symbol index and append symbol name to string table.
+        int index;
+        if (name.isEmpty()) {
+            index = 0;
+        } else {
+            // NOTE: The +1 comes from the null symbol!
+            // We can't trust strTabContent.length() since that is chars (UTF16), keep track of
+            // bytes on our own.
+            index = strTabNrOfBytes + 1;
+            strTabContent.append(name).append('\0');
+            strTabNrOfBytes += name.getBytes(StandardCharsets.UTF_8).length + 1;
+        }
+
+        // Create ELF symbol entry
+        long address = JNILibELFAPI.create_sym_entry(elfClass, index, type, bind, secHdrIndex, size, value);
+        if (address == 0) {
+            throw new InternalError("create_sym_entry failed");
+        }
+        Pointer ptr = new Pointer(address);
+
+        if (isLocal) {
+            final int localIndex = localSymbolIndex.size();
+            ELFSymbol symbol = new ELFSymbol(name, localIndex, ptr, isLocal);
+            localSymbolIndex.add(symbol);
+            return symbol;
+        } else {
+            final int globalIndex = globalSymbolIndex.size();
+            ELFSymbol symbol = new ELFSymbol(name, globalIndex, ptr, isLocal);
+            globalSymbolIndex.add(symbol);
+            return symbol;
+        }
+    }
+
+    /**
+     * Create an ELF relocation entry for given symbol {@code name} to section {@code secname}.
+     *
+     * @param container the section
+     * @param offset offset into the section contents at which the relocation needs to be applied
+     * @param type ELF type of the relocation entry
+     * @param addend Addend for for relocation of type reloca
+     */
+    public void createELFRelocationEntry(ELFContainer container, int offset, int type, int addend, ELFSymbol elfSymbol) {
+        // Get the index of the symbol.
+        int index;
+        if (elfSymbol.isLocal()) {
+            index = elfSymbol.getIndex();
+        } else {
+            /*
+             * For global symbol entries the index will be offset by the number of local symbols
+             * which will be listed first in the symbol table.
+             */
+            index = elfSymbol.getIndex() + localSymbolIndex.size();
+        }
+
+        long address = JNILibELFAPI.create_reloc_entry(elfClass, offset, index, type, addend, createReloca);
+        if (address == 0) {
+            throw new InternalError("create_reloc_entry failed");
+        }
+        Pointer ptr = new Pointer(address);
+        /*
+         * If section name associated with this symbol is set to undefined i.e., secname is null,
+         * symIndex is undef i.e., 0.
+         */
+        if (relocTables.get(container) == null) {
+            // Allocate a new table and add it to the hash table of reloc tables
+            relocTables.put(container, new ArrayList<>());
+        }
+
+        // Add the entry
+        relocTables.get(container).add(ptr);
+    }
+
+    /**
+     * Invokes native libelf function loff_t elf_update (Elf *elfPtr, Elf_Cmd cmd).
+     *
+     * @param cmd command
+     * @return return value of the native function called
+     */
+    public boolean elfUpdate(LibELF.Elf_Cmd cmd) {
+        JNILibELFAPI.elf_update(elfPtr, cmd.intValue());
+        // TODO: Error checking; look at the return value of elf_update
+        // and call elf_errmsg appropriately.
+        return true;
+    }
+
+    /**
+     * Wrapper function that invokes int elf_end (Elf *elfPtr). and closes ELF output file
+     * descriptor
+     *
+     * @return true
+     */
+    public boolean elfEnd() {
+        // Finish ELF processing
+        JNILibELFAPI.elf_end(elfPtr);
+        // Close file descriptor
+        JNILibELFAPI.close(outFileDesc);
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNIELFRelocation.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.jnilibelf;
+
+/**
+ * Class that abstracts ELF relocations.
+ *
+ */
+public interface JNIELFRelocation {
+    int R_UNDEF = -1;
+
+    /**
+     * x86-specific relocation types.
+     *
+     */
+    public interface I386 {
+        /* i386 relocs. */
+
+        int R_386_NONE = 0; /* No reloc */
+        int R_386_32 = 1; /* Direct 32 bit */
+        int R_386_PC32 = 2; /* PC relative 32 bit */
+        int R_386_GOT32 = 3; /* 32 bit GOT entry */
+        int R_386_PLT32 = 4; /* 32 bit PLT address */
+        int R_386_COPY = 5; /* Copy symbol at runtime */
+        int R_386_GLOB_DAT = 6; /* Create GOT entry */
+        int R_386_JMP_SLOT = 7; /* Create PLT entry */
+        int R_386_RELATIVE = 8; /* Adjust by program base */
+        int R_386_GOTOFF = 9; /* 32 bit offset to GOT */
+        int R_386_GOTPC = 10; /* 32 bit PC relative offset to GOT */
+        int R_386_32PLT = 11;
+        int R_386_TLS_TPOFF = 14; /* Offset in static TLS block */
+        int R_386_TLS_IE = 15; /* Address of GOT entry for static TLS block offset */
+        int R_386_TLS_GOTIE = 16; /* GOT entry for static TLS block offset */
+        int R_386_TLS_LE = 17; /* Offset relative to static TLS block */
+        int R_386_TLS_GD = 18; /* Direct 32 bit for GNU version of general dynamic thread local data */
+        int R_386_TLS_LDM = 19; /*
+                                 * Direct 32 bit for GNU version of local dynamic thread local data
+                                 * in LE code
+                                 */
+        int R_386_16 = 20;
+        int R_386_PC16 = 21;
+        int R_386_8 = 22;
+        int R_386_PC8 = 23;
+        int R_386_TLS_GD_32 = 24; /* Direct 32 bit for general dynamic thread local data */
+        int R_386_TLS_GD_PUSH = 25; /* Tag for pushl in GD TLS code */
+        int R_386_TLS_GD_CALL = 26; /* Relocation for call to __tls_get_addr() */
+        int R_386_TLS_GD_POP = 27; /* Tag for popl in GD TLS code */
+        int R_386_TLS_LDM_32 = 28; /* Direct 32 bit for local dynamic thread local data in LE code */
+        int R_386_TLS_LDM_PUSH = 29; /* Tag for pushl in LDM TLS code */
+        int R_386_TLS_LDM_CALL = 30; /* Relocation for call to __tls_get_addr() in LDM code */
+        int R_386_TLS_LDM_POP = 31; /* Tag for popl in LDM TLS code */
+        int R_386_TLS_LDO_32 = 32; /* Offset relative to TLS block */
+        int R_386_TLS_IE_32 = 33; /* GOT entry for negated static TLS block offset */
+        int R_386_TLS_LE_32 = 34; /* Negated offset relative to static TLS block */
+        int R_386_TLS_DTPMOD32 = 35; /* ID of module containing symbol */
+        int R_386_TLS_DTPOFF32 = 36; /* Offset in TLS block */
+        int R_386_TLS_TPOFF32 = 37; /* Negated offset in static TLS block */
+        int R_386_SIZE32 = 38; /* 32-bit symbol size */
+        int R_386_TLS_GOTDESC = 39; /* GOT offset for TLS descriptor. */
+        int R_386_TLS_DESC_CALL = 40; /* Marker of call through TLS descriptor for relaxation. */
+        int R_386_TLS_DESC = 41; /*
+                                  * TLS descriptor containing pointer to code and to argument,
+                                  * returning the TLS offset for the symbol.
+                                  */
+        int R_386_IRELATIVE = 42; /* Adjust indirectly by program base */
+        /* Keep this the last entry. */
+        int R_386_NUM = 43;
+    }
+
+    /**
+     * x86_64-specific relocation types.
+     */
+    public interface X86_64 {
+        /* AMD x86-64 relocations. */
+        int R_X86_64_NONE = 0; /* No reloc */
+        int R_X86_64_64 = 1; /* Direct 64 bit */
+        int R_X86_64_PC32 = 2; /* PC relative 32 bit signed */
+        int R_X86_64_GOT32 = 3; /* 32 bit GOT entry */
+        int R_X86_64_PLT32 = 4; /* 32 bit PLT address */
+        int R_X86_64_COPY = 5; /* Copy symbol at runtime */
+        int R_X86_64_GLOB_DAT = 6; /* Create GOT entry */
+        int R_X86_64_JUMP_SLOT = 7; /* Create PLT entry */
+        int R_X86_64_RELATIVE = 8; /* Adjust by program base */
+        int R_X86_64_GOTPCREL = 9; /* 32 bit signed PC relative offset to GOT */
+        int R_X86_64_32 = 10; /* Direct 32 bit zero extended */
+        int R_X86_64_32S = 11; /* Direct 32 bit sign extended */
+        int R_X86_64_16 = 12; /* Direct 16 bit zero extended */
+        int R_X86_64_PC16 = 13; /* 16 bit sign extended pc relative */
+        int R_X86_64_8 = 14; /* Direct 8 bit sign extended */
+        int R_X86_64_PC8 = 15; /* 8 bit sign extended pc relative */
+        int R_X86_64_DTPMOD64 = 16; /* ID of module containing symbol */
+        int R_X86_64_DTPOFF64 = 17; /* Offset in module's TLS block */
+        int R_X86_64_TPOFF64 = 18; /* Offset in initial TLS block */
+        int R_X86_64_TLSGD = 19; /*
+                                  * 32 bit signed PC relative offset to two GOT entries for GD
+                                  * symbol
+                                  */
+        int R_X86_64_TLSLD = 20; /*
+                                  * 32 bit signed PC relative offset to two GOT entries for LD
+                                  * symbol
+                                  */
+        int R_X86_64_DTPOFF32 = 21; /* Offset in TLS block */
+        int R_X86_64_GOTTPOFF = 22; /*
+                                     * 32 bit signed PC relative offset to GOT entry for IE symbol
+                                     */
+        int R_X86_64_TPOFF32 = 23; /* Offset in initial TLS block */
+        int R_X86_64_PC64 = 24; /* PC relative 64 bit */
+        int R_X86_64_GOTOFF64 = 25; /* 64 bit offset to GOT */
+        int R_X86_64_GOTPC32 = 26; /* 32 bit signed pc relative offset to GOT */
+        int R_X86_64_GOT64 = 27; /* 64-bit GOT entry offset */
+        int R_X86_64_GOTPCREL64 = 28; /* 64-bit PC relative offset to GOT entry */
+        int R_X86_64_GOTPC64 = 29; /* 64-bit PC relative offset to GOT */
+        int R_X86_64_GOTPLT64 = 30; /* like GOT64, says PLT entry needed */
+        int R_X86_64_PLTOFF64 = 31; /* 64-bit GOT relative offset to PLT entry */
+        int R_X86_64_SIZE32 = 32; /* Size of symbol plus 32-bit addend */
+        int R_X86_64_SIZE64 = 33; /* Size of symbol plus 64-bit addend */
+        int R_X86_64_GOTPC32_TLSDESC = 34; /* GOT offset for TLS descriptor. */
+        int R_X86_64_TLSDESC_CALL = 35; /*
+                                         * Marker for call through TLS descriptor.
+                                         */
+        int R_X86_64_TLSDESC = 36; /* TLS descriptor. */
+        int R_X86_64_IRELATIVE = 37; /* Adjust indirectly by program base */
+        int R_X86_64_RELATIVE64 = 38; /* 64-bit adjust by program base */
+
+        int R_X86_64_NUM = 39;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNIELFTargetInfo.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.jnilibelf;
+
+import java.nio.ByteOrder;
+
+import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.ELF;
+
+/**
+ * Class that abstracts ELF target details.
+ *
+ */
+public class JNIELFTargetInfo {
+    /**
+     * ELF Class of the target.
+     */
+    private static final int elfClass;
+    /**
+     * Target architecture.
+     */
+    private static final int arch;
+    /**
+     * Architecture endian-ness.
+     */
+    private static final int endian;
+
+    /**
+     * Target OS string.
+     */
+    private static final String osName;
+
+    static {
+        // Find the target arch details
+        String archStr = System.getProperty("os.arch").toLowerCase();
+        String datamodelStr = System.getProperty("sun.arch.data.model");
+
+        if (datamodelStr.equals("32")) {
+            elfClass = ELF.ELFCLASS32;
+        } else if (datamodelStr.equals("64")) {
+            elfClass = ELF.ELFCLASS64;
+        } else {
+            System.out.println("Failed to discover ELF class!");
+            elfClass = ELF.ELFCLASSNONE;
+        }
+
+        ByteOrder bo = ByteOrder.nativeOrder();
+        if (bo == ByteOrder.LITTLE_ENDIAN) {
+            endian = ELF.ELFDATA2LSB;
+        } else if (bo == ByteOrder.BIG_ENDIAN) {
+            endian = ELF.ELFDATA2MSB;
+        } else {
+            System.out.println("Failed to discover endian-ness!");
+            endian = ELF.ELFDATANONE;
+        }
+
+        if (archStr.equals("x86")) {
+            arch = ELF.EM_386;
+        } else if (archStr.equals("amd64") || archStr.equals("x86_64")) {
+            arch = ELF.EM_X64_64;
+        } else if (archStr.equals("sparcv9")) {
+            arch = ELF.EM_SPARCV9;
+        } else {
+            System.out.println("Unsupported architecture " + archStr);
+            arch = ELF.EM_NONE;
+        }
+
+        osName = System.getProperty("os.name").toLowerCase();
+    }
+
+    public static int getELFArch() {
+        return arch;
+    }
+
+    public static int getELFClass() {
+        return elfClass;
+    }
+
+    public static int getELFEndian() {
+        return endian;
+    }
+
+    public static String getOsName() {
+        return osName;
+    }
+
+    public static int createReloca() {
+        switch (arch) {
+            case ELF.EM_X64_64:
+                return 1;
+            default:
+                return 0;
+        }
+    }
+
+    public static int sizeOfSymtabEntry() {
+        return JNILibELFAPI.size_of_Sym(elfClass);
+    }
+
+    public static int sizeOfRelocEntry() {
+        if (createReloca() == 1) {
+            return JNILibELFAPI.size_of_Rela(elfClass);
+        } else {
+            return JNILibELFAPI.size_of_Rel(elfClass);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNILibELFAPI.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,677 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.jnilibelf;
+
+public class JNILibELFAPI {
+
+    static {
+        System.loadLibrary("jelfshim");
+    }
+
+    /**
+     * Definitions for file open.
+     */
+    public static enum OpenFlags {
+        O_RDONLY(0x0),
+        O_WRONLY(0x1),
+        O_RDWR(0x2),
+        O_CREAT(0x40);
+
+        private final int intVal;
+
+        private OpenFlags(int v) {
+            intVal = v;
+        }
+
+        public int intValue() {
+            return intVal;
+        }
+    }
+
+    /**
+     * Definitions reflecting those in elf.h.
+     *
+     */
+    public interface ELF {
+        int EI_NIDENT = 16;
+
+        int EI_CLASS = 4; /* File class byte index */
+        int ELFCLASSNONE = 0; /* Invalid class */
+        int ELFCLASS32 = 1; /* 32-bit objects */
+        int ELFCLASS64 = 2; /* 64-bit objects */
+        int ELFCLASSNUM = 3;
+
+        int EI_DATA = 5; /* Data encoding byte index */
+        int ELFDATANONE = 0; /* Invalid data encoding */
+        int ELFDATA2LSB = 1; /* 2's complement, little endian */
+        int ELFDATA2MSB = 2; /* 2's complement, big endian */
+        int ELFDATANUM = 3;
+
+        // Legal architecture values for e_machine (add others as needed)
+        int EM_NONE = 0; /* No machine */
+        int EM_SPARC = 2; /* SUN SPARC */
+        int EM_386 = 3; /* Intel 80386 */
+        int EM_SPARCV9 = 43; /* SPARC v9 64-bit */
+        int EM_X64_64 = 62; /* AMD x86-64 architecture */
+
+        /* Legal values for e_type (object file type). */
+
+        int ET_NONE = 0; /* No file type */
+        int ET_REL = 1; /* Relocatable file */
+        int ET_EXEC = 2; /* Executable file */
+        int ET_DYN = 3; /* Shared object file */
+        int ET_CORE = 4; /* Core file */
+        int ET_NUM = 5; /* Number of defined types */
+        int ET_LOOS = 0xfe00; /* OS-specific range start */
+        int ET_HIOS = 0xfeff; /* OS-specific range end */
+        int ET_LOPROC = 0xff00; /* Processor-specific range start */
+        int ET_HIPROC = 0xffff; /* Processor-specific range end */
+
+        /* Legal values for e_version (version). */
+
+        int EV_NONE = 0; /* Invalid ELF version */
+        int EV_CURRENT = 1; /* Current version */
+        int EV_NUM = 2;
+
+        /* Legal values for p_type (segment type). */
+
+        int PT_NULL = 0; /* Program header table entry unused */
+        int PT_LOAD = 1; /* Loadable program segment */
+        int PT_DYNAMIC = 2; /* Dynamic linking information */
+        int PT_INTERP = 3; /* Program interpreter */
+        int PT_NOTE = 4; /* Auxiliary information */
+        int PT_SHLIB = 5; /* Reserved */
+        int PT_PHDR = 6; /* Entry for header table itself */
+        int PT_TLS = 7; /* Thread-local storage segment */
+        int PT_NUM = 8; /* Number of defined types */
+        int PT_LOOS = 0x60000000; /* Start of OS-specific */
+        int PT_GNU_EH_FRAME = 0x6474e550; /* GCC .eh_frame_hdr segment */
+        int PT_GNU_STACK = 0x6474e551; /* Indicates stack executability */
+        int PT_GNU_RELRO = 0x6474e552; /* Read-only after relocation */
+        int PT_LOSUNW = 0x6ffffffa;
+        int PT_SUNWBSS = 0x6ffffffa; /* Sun Specific segment */
+        int PT_SUNWSTACK = 0x6ffffffb; /* Stack segment */
+        int PT_HISUNW = 0x6fffffff;
+        int PT_HIOS = 0x6fffffff; /* End of OS-specific */
+        int PT_LOPROC = 0x70000000; /* Start of processor-specific */
+        int PT_HIPROC = 0x7fffffff; /* End of processor-specific */
+
+        /* Special section indices. */
+
+        int SHN_UNDEF = 0; /* Undefined section */
+        int SHN_LORESERVE = 0xff00; /* Start of reserved indices */
+        int SHN_LOPROC = 0xff00; /* Start of processor-specific */
+        int SHN_BEFORE = 0xff00; /* Order section before all others (Solaris). */
+        int SHN_AFTER = 0xff01; /* Order section after all others (Solaris). */
+        int SHN_HIPROC = 0xff1f; /* End of processor-specific */
+        int SHN_LOOS = 0xff20; /* Start of OS-specific */
+        int SHN_HIOS = 0xff3f; /* End of OS-specific */
+        int SHN_ABS = 0xfff1; /* Associated symbol is absolute */
+        int SHN_COMMON = 0xfff2; /* Associated symbol is common */
+        int SHN_XINDEX = 0xffff; /* Index is in extra table. */
+        int SHN_HIRESERVE = 0xffff; /* End of reserved indices */
+
+        /* Legal values for sh_type (section type). */
+
+        int SHT_NULL = 0; /* Section header table entry unused */
+        int SHT_PROGBITS = 1; /* Program data */
+        int SHT_SYMTAB = 2; /* Symbol table */
+        int SHT_STRTAB = 3; /* String table */
+        int SHT_RELA = 4; /* Relocation entries with addends */
+        int SHT_HASH = 5; /* Symbol hash table */
+        int SHT_DYNAMIC = 6; /* Dynamic linking information */
+        int SHT_NOTE = 7; /* Notes */
+        int SHT_NOBITS = 8; /* Program space with no data (bss) */
+        int SHT_REL = 9; /* Relocation entries, no addends */
+        int SHT_SHLIB = 10; /* Reserved */
+        int SHT_DYNSYM = 11; /* Dynamic linker symbol table */
+        int SHT_INIT_ARRAY = 14; /* Array of constructors */
+        int SHT_FINI_ARRAY = 15; /* Array of destructors */
+        int SHT_PREINIT_ARRAY = 16; /* Array of pre-constructors */
+        int SHT_GROUP = 17; /* Section group */
+        int SHT_SYMTAB_SHNDX = 18; /* Extended section indeces */
+        int SHT_NUM = 19; /* Number of defined types. */
+        int SHT_LOOS = 0x60000000; /* Start OS-specific. */
+        int SHT_GNU_ATTRIBUTES = 0x6ffffff5; /* Object attributes. */
+        int SHT_GNU_HASH = 0x6ffffff6; /* GNU-style hash table. */
+        int SHT_GNU_LIBLIST = 0x6ffffff7; /* Prelink library list */
+        int SHT_CHECKSUM = 0x6ffffff8; /* Checksum for DSO content. */
+        int SHT_LOSUNW = 0x6ffffffa; /* Sun-specific low bound. */
+        int SHT_SUNW_move = 0x6ffffffa;
+        int SHT_SUNW_COMDAT = 0x6ffffffb;
+        int SHT_SUNW_syminfo = 0x6ffffffc;
+        int SHT_GNU_verdef = 0x6ffffffd; /* Version definition section. */
+        int SHT_GNU_verneed = 0x6ffffffe; /* Version needs section. */
+        int SHT_GNU_versym = 0x6fffffff; /* Version symbol table. */
+        int SHT_HISUNW = 0x6fffffff; /* Sun-specific high bound. */
+        int SHT_HIOS = 0x6fffffff; /* End OS-specific type */
+        int SHT_LOPROC = 0x70000000; /* Start of processor-specific */
+        int SHT_HIPROC = 0x7fffffff; /* End of processor-specific */
+        int SHT_LOUSER = 0x80000000; /* Start of application-specific */
+        int SHT_HIUSER = 0x8fffffff; /* End of application-specific */
+
+        /* Legal values for sh_flags (section flags). */
+
+        int SHF_WRITE = (1 << 0); /* Writable */
+        int SHF_ALLOC = (1 << 1); /* Occupies memory during execution */
+        int SHF_EXECINSTR = (1 << 2); /* Executable */
+        int SHF_MERGE = (1 << 4); /* Might be merged */
+        int SHF_STRINGS = (1 << 5); /* Contains nul-terminated strings */
+        int SHF_INFO_LINK = (1 << 6); /* `sh_info' contains SHT index */
+        int SHF_LINK_ORDER = (1 << 7); /* Preserve order after combining */
+        int SHF_OS_NONCONFORMING = (1 << 8); /* Non-standard OS specific handling required */
+        int SHF_GROUP = (1 << 9); /* Section is member of a group. */
+        int SHF_TLS = (1 << 10); /* Section hold thread-local data. */
+        int SHF_MASKOS = 0x0ff00000; /* OS-specific. */
+        int SHF_MASKPROC = 0xf0000000; /* Processor-specific */
+        int SHF_ORDERED = (1 << 30); /* Special ordering requirement (Solaris). */
+        int SHF_EXCLUDE = (1 << 31); /*
+                                      * Section is excluded unless referenced or allocated
+                                      * (Solaris).
+                                      */
+
+        /* Legal values for ST_BIND subfield of st_info (symbol binding). */
+
+        int STB_LOCAL = 0; /* Local symbol */
+        int STB_GLOBAL = 1; /* Global symbol */
+        int STB_WEAK = 2; /* Weak symbol */
+        int STB_NUM = 3; /* Number of defined types. */
+        int STB_LOOS = 10; /* Start of OS-specific */
+        int STB_GNU_UNIQUE = 10; /* Unique symbol. */
+        int STB_HIOS = 12; /* End of OS-specific */
+        int STB_LOPROC = 13; /* Start of processor-specific */
+        int STB_HIPROC = 15; /* End of processor-specific */
+
+        /* Legal values for ST_TYPE subfield of st_info (symbol type). */
+
+        int STT_NOTYPE = 0; /* Symbol type is unspecified */
+        int STT_OBJECT = 1; /* Symbol is a data object */
+        int STT_FUNC = 2; /* Symbol is a code object */
+        int STT_SECTION = 3; /* Symbol associated with a section */
+        int STT_FILE = 4; /* Symbol's name is file name */
+        int STT_COMMON = 5; /* Symbol is a common data object */
+        int STT_TLS = 6; /* Symbol is thread-local data object */
+        int STT_NUM = 7; /* Number of defined types. */
+        int STT_LOOS = 10; /* Start of OS-specific */
+        int STT_GNU_IFUNC = 10; /* Symbol is indirect code object */
+        int STT_HIOS = 12; /* End of OS-specific */
+        int STT_LOPROC = 13; /* Start of processor-specific */
+        int STT_HIPROC = 15; /* End of processor-specific */
+    }
+
+    /**
+     * Definitions reflecting those in libelf.h.
+     *
+     */
+    public interface LibELF {
+
+        public static enum Elf_Cmd {
+            ELF_C_NULL("NULL"), /* Nothing, terminate, or compute only. */
+            ELF_C_READ("READ"), /* Read .. */
+            ELF_C_RDWR("RDWR"), /* Read and write .. */
+            ELF_C_WRITE("WRITE"), /* Write .. */
+            ELF_C_CLR("CLR"), /* Clear flag. */
+            ELF_C_SET("SET"), /* Set flag. */
+            ELF_C_FDDONE("FDDONE"), /*
+                                     * Signal that file descriptor will not be used anymore.
+                                     */
+            ELF_C_FDREAD("FDREAD"), /*
+                                     * Read rest of data so that file descriptor is not used
+                                     * anymore.
+                                     */
+            /* The following are Linux-only extensions. */
+            ELF_C_READ_MMAP("READ_MMAP"), /* Read, but mmap the file if possible. */
+            ELF_C_RDWR_MMAP("RDWR_MMAP"), /* Read and write, with mmap. */
+            ELF_C_WRITE_MMAP("WRITE_MMAP"), /* Write, with mmap. */
+            ELF_C_READ_MMAP_PRIVATE("READ_MMAP_PRIVATE"), /*
+                                                           * Read, but memory is writable, results
+                                                           * are not written to the file.
+                                                           */
+            ELF_C_EMPTY("EMPTY"), /* Copy basic file data but not the content. */
+            /* The following are SunOS-only enums */
+            ELF_C_WRIMAGE("WRIMAGE"),
+            ELF_C_IMAGE("IMAGE"),
+            /* Common last entry. */
+            ELF_C_NUM("NUM");
+            private final int intVal;
+            private final String name;
+
+            private Elf_Cmd(String cmd) {
+                name = "ELF_C_" + cmd;
+                switch (cmd) {
+                    case "NULL":
+                        // ELF_C_NULL has the same enum ordinal on both Linux and SunOS
+                        intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_NULL.ordinal();
+                        break;
+
+                    case "READ":
+                        // ELF_C_READ has the same enum ordinal on both Linux and SunOS
+                        intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_READ.ordinal();
+                        break;
+
+                    // Enums defined in libelf.h of both Linux and SunOS
+                    // but with different ordinals
+                    case "RDWR":
+                        if (JNIELFTargetInfo.getOsName().equals("linux")) {
+                            intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_RDWR.ordinal();
+                        } else if (JNIELFTargetInfo.getOsName().equals("sunos")) {
+                            intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_RDWR.ordinal();
+                        } else {
+                            // Unsupported platform
+                            intVal = -1;
+                        }
+                        break;
+
+                    case "WRITE":
+                        if (JNIELFTargetInfo.getOsName().equals("linux")) {
+                            intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_WRITE.ordinal();
+                        } else if (JNIELFTargetInfo.getOsName().equals("sunos")) {
+                            intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_WRITE.ordinal();
+                        } else {
+                            // Unsupported platform
+                            intVal = -1;
+                        }
+                        break;
+
+                    case "CLR":
+                        if (JNIELFTargetInfo.getOsName().equals("linux")) {
+                            intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_CLR.ordinal();
+                        } else if (JNIELFTargetInfo.getOsName().equals("sunos")) {
+                            intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_CLR.ordinal();
+                        } else {
+                            // Unsupported platform
+                            intVal = -1;
+                        }
+                        break;
+
+                    case "SET":
+                        if (JNIELFTargetInfo.getOsName().equals("linux")) {
+                            intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_SET.ordinal();
+                        } else if (JNIELFTargetInfo.getOsName().equals("sunos")) {
+                            intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_SET.ordinal();
+                        } else {
+                            // Unsupported platform
+                            intVal = -1;
+                        }
+                        break;
+
+                    case "FDDONE":
+                        if (JNIELFTargetInfo.getOsName().equals("linux")) {
+                            intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_FDDONE.ordinal();
+                        } else if (JNIELFTargetInfo.getOsName().equals("sunos")) {
+                            intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_FDDONE.ordinal();
+                        } else {
+                            // Unsupported platform
+                            intVal = -1;
+                        }
+                        break;
+
+                    case "FDREAD":
+                        if (JNIELFTargetInfo.getOsName().equals("linux")) {
+                            intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_FDREAD.ordinal();
+                        } else if (JNIELFTargetInfo.getOsName().equals("sunos")) {
+                            intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_FDREAD.ordinal();
+                        } else {
+                            // Unsupported platform
+                            intVal = -1;
+                        }
+                        break;
+
+                    case "NUM":
+                        if (JNIELFTargetInfo.getOsName().equals("linux")) {
+                            intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_NUM.ordinal();
+                        } else if (JNIELFTargetInfo.getOsName().equals("sunos")) {
+                            intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_NUM.ordinal();
+                        } else {
+                            // Unsupported platform
+                            intVal = -1;
+                        }
+                        break;
+
+                    // Linux-only Elf_Cmd enums
+                    case "READ_MMAP":
+                        if (JNIELFTargetInfo.getOsName().equals("linux")) {
+                            intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_READ_MMAP.ordinal();
+                        } else {
+                            // Unsupported platform
+                            intVal = -1;
+                        }
+                        break;
+
+                    case "RDWR_MMAP":
+                        if (JNIELFTargetInfo.getOsName().equals("linux")) {
+                            intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_RDWR_MMAP.ordinal();
+                        } else {
+                            // Unsupported platform
+                            intVal = -1;
+                        }
+                        break;
+
+                    case "WRITE_MMAP":
+                        if (JNIELFTargetInfo.getOsName().equals("linux")) {
+                            intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_WRITE_MMAP.ordinal();
+                        } else {
+                            // Unsupported platform
+                            intVal = -1;
+                        }
+                        break;
+
+                    case "READ_MMAP_PRIVATE":
+                        if (JNIELFTargetInfo.getOsName().equals("linux")) {
+                            intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_READ_MMAP_PRIVATE.ordinal();
+                        } else {
+                            // Unsupported platform
+                            intVal = -1;
+                        }
+                        break;
+
+                    case "EMPTY":
+                        if (JNIELFTargetInfo.getOsName().equals("linux")) {
+                            intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_EMPTY.ordinal();
+                        } else {
+                            // Unsupported platform
+                            intVal = -1;
+                        }
+                        break;
+                    // SunOS-only Elf_Cmd enums
+                    case "WRIMAGE":
+                        if (JNIELFTargetInfo.getOsName().equals("linux")) {
+                            intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_WRIMAGE.ordinal();
+                        } else {
+                            // Unsupported platform
+                            intVal = -1;
+                        }
+                        break;
+                    case "IMAGE":
+                        if (JNIELFTargetInfo.getOsName().equals("linux")) {
+                            intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_IMAGE.ordinal();
+                        } else {
+                            // Unsupported platform
+                            intVal = -1;
+                        }
+                        break;
+                    default:
+                        intVal = -1;
+                }
+            }
+
+            public int intValue() {
+                assert intVal != -1 : "enum " + name + "not supported on " + JNIELFTargetInfo.getOsName();
+                return intVal;
+            }
+
+            public String getName() {
+                return name;
+            }
+        }
+
+        public static enum Elf_Type {
+            ELF_T_BYTE(0), /* unsigned char */
+            ELF_T_ADDR(1), /* Elf32_Addr, Elf64_Addr, ... */
+            ELF_T_DYN(2), /* Dynamic section record. */
+            ELF_T_EHDR(3), /* ELF header. */
+            ELF_T_HALF(4), /* Elf32_Half, Elf64_Half, ... */
+            ELF_T_OFF(5), /* Elf32_Off, Elf64_Off, ... */
+            ELF_T_PHDR(6), /* Program header. */
+            ELF_T_RELA(7), /* Relocation entry with addend. */
+            ELF_T_REL(8), /* Relocation entry. */
+            ELF_T_SHDR(9), /* Section header. */
+            ELF_T_SWORD(10), /* Elf32_Sword, Elf64_Sword, ... */
+            ELF_T_SYM(11), /* Symbol record. */
+            ELF_T_WORD(12), /* Elf32_Word, Elf64_Word, ... */
+            ELF_T_XWORD(13), /* Elf32_Xword, Elf64_Xword, ... */
+            ELF_T_SXWORD(14), /* Elf32_Sxword, Elf64_Sxword, ... */
+            ELF_T_VDEF(15), /* Elf32_Verdef, Elf64_Verdef, ... */
+            ELF_T_VDAUX(16), /* Elf32_Verdaux, Elf64_Verdaux, ... */
+            ELF_T_VNEED(17), /* Elf32_Verneed, Elf64_Verneed, ... */
+            ELF_T_VNAUX(18), /* Elf32_Vernaux, Elf64_Vernaux, ... */
+            ELF_T_NHDR(19), /* Elf32_Nhdr, Elf64_Nhdr, ... */
+            ELF_T_SYMINFO(20), /* Elf32_Syminfo, Elf64_Syminfo, ... */
+            ELF_T_MOVE(21), /* Elf32_Move, Elf64_Move, ... */
+            ELF_T_LIB(22), /* Elf32_Lib, Elf64_Lib, ... */
+            ELF_T_GNUHASH(23), /* GNU-style hash section. */
+            ELF_T_AUXV(24), /* Elf32_auxv_t, Elf64_auxv_t, ... */
+            /* Keep this the last entry. */
+            ELF_T_NUM(25);
+
+            private final int intVal;
+
+            private Elf_Type(int v) {
+                intVal = v;
+            }
+
+            public int intValue() {
+                return intVal;
+            }
+        }
+
+        /* Flags for the ELF structures. */
+        int ELF_F_DIRTY = 0x1;
+        int ELF_F_LAYOUT = 0x4;
+        int ELF_F_PERMISSIVE = 0x8;
+
+        public static enum Elf_Kind {
+            ELF_K_NONE(0), /* Unknown. */
+            ELF_K_AR(1), /* Archive. */
+            ELF_K_COFF(2), /* Stupid old COFF. */
+            ELF_K_ELF(3), /* ELF file. */
+            /* Keep this the last entry. */
+            ELF_K_NUM(4);
+            private final int intVal;
+
+            private Elf_Kind(int v) {
+                intVal = v;
+            }
+
+            public int intValue() {
+                return intVal;
+            }
+        }
+    }
+
+    /**
+     * Invoke native libelf function unsigned int elf_version (unsigned int v).
+     *
+     * @param v version
+     * @return return value of native call
+     */
+    // Checkstyle: stop method name check
+    static native int elf_version(int v);
+
+    /**
+     * Return version recorded in libelfshim.
+     *
+     * @return return version string
+     */
+    // Checkstyle: stop method name check
+    static native String elfshim_version();
+
+    /**
+     * Invoke native libelf function Elf *elf_begin (int fildes, Elf_Cmd cmd, Elf *elfPtr).
+     *
+     * @param fildes open file descriptor
+     * @param elfCRead command
+     * @param elfHdrPtr pointer to ELF header
+     * @return return value of native call
+     */
+    static native Pointer elf_begin(int fildes, int elfCRead, Pointer elfHdrPtr);
+
+    /**
+     * Invoke native libelf function elf_end (Elf *elfPtr).
+     *
+     * @param elfPtr pointer to ELF header
+     * @return return value of native call
+     */
+    static native int elf_end(Pointer elfPtr);
+
+    /**
+     * Invoke native libelf function elf_end (Elf *elfPtr).
+     *
+     * @param elfPtr pointer to ELF header
+     * @return return value of native call
+     */
+    static native int elf_kind(Pointer elfPtr);
+
+    /**
+     * Invoke native libelf function unsigned int elf_flagphdr (Elf *elf, Elf_Cmd cmd, unsigned int
+     * flags).
+     *
+     * @param elfPtr Pointer to ELF descriptor
+     * @param cmd command
+     * @param flags flags
+     * @return return value of native call
+     */
+    static native int elf_flagphdr(Pointer elfPtr, int cmd, int flags);
+
+    /**
+     * Invoke native libelf function Elf_Scn *elf_newscn (Elf *elfPtr).
+     *
+     * @param elfPtr Elf header pointer
+     * @return return value of native call
+     */
+    static native Pointer elf_newscn(Pointer elfPtr);
+
+    /**
+     * Invoke native libelf function Elf_Data *elf_newdata (Elf_Scn *scn).
+     *
+     * @param scnPtr pointer to section for which the new data descriptor is to be created
+     * @return return value of native call
+     */
+    static native Pointer elf_newdata(Pointer scnPtr);
+
+    /**
+     * Invoke native libelf function Elf64_Shdr *elf64_getshdr (Elf_Scn *scnPtr).
+     *
+     * @param scnPtr pointer to section whose header information is to be retrieved
+     * @return return value of native call
+     */
+    static native Pointer elf64_getshdr(Pointer scnPtr);
+
+    /**
+     * Invoke native libelf function loff_t elf_update (Elf *elfPtr, Elf_Cmd cmd).
+     *
+     * @param elfPtr Pointer to ELF descriptor
+     * @param cmd command
+     * @return return value of native call
+     */
+    static native long elf_update(Pointer elfPtr, int cmd);
+
+    /**
+     * Invoke native libelf function char *elf_errmsg (int error).
+     *
+     * @param error error
+     * @return return value of native call
+     */
+    static native String elf_errmsg(int error);
+
+    /**
+     * Invoke native libelf function size_t elf_ndxscn (Elf_Scn *scn).
+     *
+     * @param scn section pointer
+     * @return return value of native call
+     */
+    static native int elf_ndxscn(Pointer scn);
+
+    /**
+     * GELF interfaces
+     */
+    /**
+     * Invoke native libelf function unsigned long int gelf_newehdr (Elf *elf, int elfClass).
+     *
+     * @param elf ELF Header pointer
+     * @param elfclass ELF class
+     * @return return value of native call boxed as a pointer
+     */
+    static native Pointer gelf_newehdr(Pointer elf, int elfclass);
+
+    /**
+     * Invoke native libelf function unsigned long int gelf_newphdr (Elf *elf, size_t phnum).
+     *
+     * @param elf ELF header pointer
+     * @param phnum number of program headers
+     * @return return value of native call boxed as a pointer
+     */
+    static native Pointer gelf_newphdr(Pointer elf, int phnum);
+
+    /**
+     * Miscellaneous convenience native methods that help peek and poke ELF data structures.
+     */
+    static native int size_of_Sym(int elfClass);
+
+    static native int size_of_Rela(int elfClass);
+
+    static native int size_of_Rel(int elfClass);
+
+    static native void ehdr_set_data_encoding(Pointer ehdr, int val);
+
+    static native void set_Ehdr_e_machine(int elfclass, Pointer structPtr, int val);
+
+    static native void set_Ehdr_e_type(int elfclass, Pointer structPtr, int val);
+
+    static native void set_Ehdr_e_version(int elfclass, Pointer structPtr, int val);
+
+    static native void set_Ehdr_e_shstrndx(int elfclass, Pointer structPtr, int val);
+
+    static native void phdr_set_type_self(int elfclass, Pointer ehdr, Pointer phdr);
+
+    static native void set_Shdr_sh_name(int elfclass, Pointer structPtr, int val);
+
+    static native void set_Shdr_sh_type(int elfclass, Pointer structPtr, int val);
+
+    static native void set_Shdr_sh_flags(int elfclass, Pointer structPtr, int val);
+
+    static native void set_Shdr_sh_entsize(int elfclass, Pointer structPtr, int val);
+
+    static native void set_Shdr_sh_link(int elfclass, Pointer structPtr, int val);
+
+    static native void set_Shdr_sh_info(int elfclass, Pointer structPtr, int val);
+
+    static native void set_Data_d_align(Pointer structPtr, int val);
+
+    static native void set_Data_d_off(Pointer structPtr, int val);
+
+    static native void set_Data_d_buf(Pointer structPtr, Pointer val);
+
+    static native void set_Data_d_type(Pointer structPtr, int val);
+
+    static native void set_Data_d_size(Pointer structPtr, int val);
+
+    static native void set_Data_d_version(Pointer structPtr, int val);
+
+    static native long create_sym_entry(int elfclass, int index, int type, int bind, int shndx, int size, int value);
+
+    static native long create_reloc_entry(int elfclass, int roffset, int symtabIdx, int relocType, int raddend, int reloca);
+
+    /**
+     * File Operations.
+     */
+    static native int open_rw(String fileName);
+
+    static native int open(String fileName, int flags);
+
+    static native int open(String fileName, int flags, int mode);
+
+    static native int close(int fd);
+    // Checkstyle: resume method name check
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/Pointer.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.jnilibelf;
+
+import jdk.internal.misc.Unsafe;
+
+import static jdk.tools.jaotc.jnilibelf.UnsafeAccess.UNSAFE;
+
+public class Pointer {
+
+    private final long address;
+
+    public Pointer(long val) {
+        address = val;
+    }
+
+    /**
+     * Put (i.e., copy) content of byte array at consecutive addresses beginning at this Pointer.
+     *
+     * @param src source byte array
+     */
+    public void put(byte[] src) {
+        UNSAFE.copyMemory(src, Unsafe.ARRAY_BYTE_BASE_OFFSET, null, address, src.length);
+    }
+
+    /**
+     * Get (i.e., copy) content at this Pointer to the given byte array.
+     *
+     * @param dst destination byte array
+     */
+    public void get(byte[] dst) {
+        UNSAFE.copyMemory(null, address, dst, Unsafe.ARRAY_BYTE_BASE_OFFSET, dst.length);
+    }
+
+    /**
+     * Read {@code readSize} number of bytes to copy them starting at {@code startIndex} of
+     * {@code byteArray}
+     *
+     * @param byteArray target array to copy bytes
+     * @param readSize number of bytes to copy
+     * @param startIndex index of the array to start copy at
+     */
+    public void copyBytesTo(byte[] byteArray, int readSize, int startIndex) {
+        long end = (long)startIndex + (long)readSize;
+        if (end > byteArray.length) {
+            throw new IllegalArgumentException("writing beyond array bounds");
+        }
+        UNSAFE.copyMemory(null, address, byteArray, Unsafe.ARRAY_BYTE_BASE_OFFSET+startIndex, readSize);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/UnsafeAccess.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.jnilibelf;
+
+import jdk.internal.misc.Unsafe;
+
+/**
+ * Package private access to the {@link Unsafe} capability.
+ */
+class UnsafeAccess {
+
+    static final Unsafe UNSAFE = Unsafe.getUnsafe();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/linux/Elf_Cmd.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.jnilibelf.linux;
+
+/**
+ * Represent Elf_Cmd enums defined in libelf.h on Linux as they slightly different from libelf.h on
+ * SunOS.
+ */
+public enum Elf_Cmd {
+    /** Nothing, terminate, or compute only. */
+    ELF_C_NULL,
+
+    /** Read. */
+    ELF_C_READ,
+
+    /** Read and write. */
+    ELF_C_RDWR,
+
+    /** Write. */
+    ELF_C_WRITE,
+
+    /** Clear flag. */
+    ELF_C_CLR,
+
+    /** Set flag. */
+    ELF_C_SET,
+
+    /**
+     * Signal that file descriptor will not be used anymore.
+     */
+    ELF_C_FDDONE,
+
+    /**
+     * Read rest of data so that file descriptor is not used anymore.
+     */
+    ELF_C_FDREAD,
+
+    /* The following are extensions. */
+
+    /** Read, but mmap the file if possible. */
+    ELF_C_READ_MMAP,
+
+    /** Read and write, with mmap. */
+    ELF_C_RDWR_MMAP,
+
+    /** Write, with mmap. */
+    ELF_C_WRITE_MMAP,
+
+    /**
+     * Read, but memory is writable, results are not written to the file.
+     */
+    ELF_C_READ_MMAP_PRIVATE,
+
+    /** Copy basic file data but not the content. */
+    ELF_C_EMPTY,
+
+    /** Keep this the last entry. */
+    ELF_C_NUM;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/sunos/Elf_Cmd.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.jnilibelf.sunos;
+
+/**
+ * Represent Elf_Cmd enums defined in libelf.h on SunOS as they slightly different from libelf.h on
+ * Linux.
+ */
+public enum Elf_Cmd {
+    /** Must be first, 0. */
+    ELF_C_NULL,
+
+    ELF_C_READ,
+    ELF_C_WRITE,
+    ELF_C_CLR,
+    ELF_C_SET,
+    ELF_C_FDDONE,
+    ELF_C_FDREAD,
+    ELF_C_RDWR,
+    ELF_C_WRIMAGE,
+    ELF_C_IMAGE,
+
+    /** Must be last. */
+    ELF_C_NUM
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTBackend.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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 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.Debug;
+import org.graalvm.compiler.debug.Debug.Scope;
+import org.graalvm.compiler.debug.GraalError;
+import org.graalvm.compiler.hotspot.HotSpotBackend;
+import org.graalvm.compiler.hotspot.HotSpotCompiledCodeBuilder;
+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.OptionValue;
+import org.graalvm.compiler.options.OptionValue.OverrideScope;
+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;
+
+public class AOTBackend {
+
+    private final Main main;
+
+    private final HotSpotBackend backend;
+
+    private final HotSpotProviders providers;
+    private final HotSpotCodeCacheProvider codeCache;
+    private final PhaseSuite<HighTierContext> graphBuilderSuite;
+    private final HighTierContext highTierContext;
+    private final GraalFilters filters;
+
+    public AOTBackend(Main main, HotSpotBackend backend, GraalFilters filters) {
+        this.main = main;
+        this.backend = backend;
+        this.filters = filters;
+        providers = backend.getProviders();
+        codeCache = providers.getCodeCache();
+        graphBuilderSuite = initGraphBuilderSuite(backend);
+        highTierContext = new HighTierContext(providers, graphBuilderSuite, OptimisticOptimizations.ALL);
+    }
+
+    private Suites getSuites() {
+        // create suites every time, as we modify options for the compiler
+        return backend.getSuites().getDefaultSuites();
+    }
+
+    private LIRSuites getLirSuites() {
+        // create suites every time, as we modify options for the compiler
+        return backend.getSuites().getDefaultLIRSuites();
+    }
+
+    @SuppressWarnings("try")
+    public CompilationResult compileMethod(ResolvedJavaMethod resolvedMethod) {
+        try (OverrideScope s = OptionValue.override(ImmutableCode, true, GeneratePIC, true)) {
+            StructuredGraph graph = buildStructuredGraph(resolvedMethod);
+            if (graph != null) {
+                return compileGraph(resolvedMethod, graph);
+            }
+            return null;
+        }
+    }
+
+    /**
+     * Build a structured graph for the member.
+     *
+     * @param javaMethod method for whose code the graph is to be created
+     * @return structured graph
+     */
+    @SuppressWarnings("try")
+    private StructuredGraph buildStructuredGraph(ResolvedJavaMethod javaMethod) {
+        try (Scope s = Debug.scope("AOTParseMethod")) {
+            StructuredGraph graph = new StructuredGraph(javaMethod, StructuredGraph.AllowAssumptions.NO, false, CompilationIdentifier.INVALID_COMPILATION_ID);
+            graphBuilderSuite.apply(graph, highTierContext);
+            return graph;
+        } catch (Throwable e) {
+            handleError(javaMethod, e, " (building graph)");
+        }
+        return null;
+    }
+
+    @SuppressWarnings("try")
+    private CompilationResult compileGraph(ResolvedJavaMethod resolvedMethod, StructuredGraph graph) {
+        try (Scope s = Debug.scope("AOTCompileMethod")) {
+            ProfilingInfo profilingInfo = DefaultProfilingInfo.get(TriState.FALSE);
+
+            final boolean isImmutablePIC = true;
+            CompilationResult compilationResult = new CompilationResult(resolvedMethod.getName(), isImmutablePIC);
+
+            return GraalCompiler.compileGraph(graph, resolvedMethod, providers, backend, graphBuilderSuite, OptimisticOptimizations.ALL, profilingInfo, getSuites(), getLirSuites(),
+                            compilationResult, CompilationResultBuilderFactory.Default);
+
+        } catch (Throwable e) {
+            handleError(resolvedMethod, e, " (compiling graph)");
+        }
+        return null;
+    }
+
+    /**
+     * Returns whether the VM is a debug build.
+     *
+     * @return true is debug VM, false otherwise
+     */
+    public boolean isDebugVM() {
+        return backend.getRuntime().getVMConfig().cAssertions;
+    }
+
+    private static PhaseSuite<HighTierContext> initGraphBuilderSuite(HotSpotBackend backend) {
+        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();
+        GraphBuilderConfiguration aotConfig = GraphBuilderConfiguration.getDefault(plugins).withEagerResolving(true);
+
+        iterator.next();
+        iterator.remove();
+        iterator.add(new GraphBuilderPhase(aotConfig));
+
+        return graphBuilderSuite;
+    }
+
+    private void handleError(ResolvedJavaMethod resolvedMethod, Throwable e, String message) {
+        String methodName = MiscUtils.uniqueMethodName(resolvedMethod);
+
+        if (main.options.debug) {
+            main.printError("Failed compilation: " + methodName + ": " + e);
+        }
+
+        // Ignore some exceptions when meta-compiling Graal.
+        if (filters.shouldIgnoreException(e)) {
+            return;
+        }
+
+        Main.writeLog("Failed compilation of method " + methodName + message);
+
+        if (!main.options.debug) {
+            main.printError("Failed compilation: " + methodName + ": " + e);
+        }
+
+        if (main.options.verbose) {
+            e.printStackTrace(main.log);
+        }
+
+        if (main.options.exitOnError) {
+            System.exit(1);
+        }
+    }
+
+    public void printCompiledMethod(HotSpotResolvedJavaMethod resolvedMethod, CompilationResult compResult) {
+        // This is really not installing the method.
+        InstalledCode installedCode = codeCache.addCode(resolvedMethod, HotSpotCompiledCodeBuilder.createCompiledCode(null, null, compResult), null, null);
+        String disassembly = codeCache.disassemble(installedCode);
+        if (disassembly != null) {
+            main.printlnDebug(disassembly);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompilationTask.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.code.CompilationResult;
+import org.graalvm.compiler.core.GraalCompilerOptions;
+import org.graalvm.compiler.debug.Debug;
+import org.graalvm.compiler.debug.DebugEnvironment;
+import org.graalvm.compiler.debug.Management;
+import org.graalvm.compiler.debug.TTY;
+import org.graalvm.compiler.debug.internal.DebugScope;
+
+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.
+ */
+public class AOTCompilationTask implements Runnable, Comparable<Object> {
+
+    private static final AtomicInteger ids = new AtomicInteger();
+
+    private static final com.sun.management.ThreadMXBean threadMXBean = (com.sun.management.ThreadMXBean) Management.getThreadMXBean();
+
+    private final Main main;
+
+    /**
+     * 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;
+
+    public AOTCompilationTask(Main main, AOTCompiledClass holder, ResolvedJavaMethod method, AOTBackend aotBackend) {
+        this.main = main;
+        this.id = ids.getAndIncrement();
+        this.holder = holder;
+        this.method = method;
+        this.aotBackend = aotBackend;
+    }
+
+    /**
+     * Compile a method or a constructor.
+     */
+    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();
+
+        // Ensure a debug configuration for this thread is initialized
+        if (Debug.isEnabled() && DebugScope.getConfig() == null) {
+            DebugEnvironment.initialize(TTY.out);
+        }
+        AOTCompiler.logCompilation(MiscUtils.uniqueMethodName(method), "Compiling");
+
+        final long threadId = Thread.currentThread().getId();
+
+        final boolean printCompilation = GraalCompilerOptions.PrintCompilation.getValue() && !TTY.isSuppressed();
+        final boolean printAfterCompilation = GraalCompilerOptions.PrintAfterCompilation.getValue() && !TTY.isSuppressed();
+        if (printCompilation) {
+            TTY.println(getMethodDescription() + "...");
+        }
+
+        final long start;
+        final long allocatedBytesBefore;
+        if (printAfterCompilation || printCompilation) {
+            start = System.currentTimeMillis();
+            allocatedBytesBefore = printAfterCompilation || printCompilation ? threadMXBean.getThreadAllocatedBytes(threadId) : 0L;
+        } else {
+            start = 0L;
+            allocatedBytesBefore = 0L;
+        }
+
+        final long startTime = System.currentTimeMillis();
+        CompilationResult compResult = aotBackend.compileMethod(method);
+        final long endTime = System.currentTimeMillis();
+
+        if (printAfterCompilation || printCompilation) {
+            final long stop = System.currentTimeMillis();
+            final int targetCodeSize = compResult != null ? compResult.getTargetCodeSize() : -1;
+            final long allocatedBytesAfter = threadMXBean.getThreadAllocatedBytes(threadId);
+            final long allocatedBytes = (allocatedBytesAfter - allocatedBytesBefore) / 1024;
+
+            if (printAfterCompilation) {
+                TTY.println(getMethodDescription() + String.format(" | %4dms %5dB %5dkB", stop - start, targetCodeSize, allocatedBytes));
+            } else if (printCompilation) {
+                TTY.println(String.format("%-6d JVMCI %-70s %-45s %-50s | %4dms %5dB %5dkB", getId(), "", "", "", stop - start, targetCodeSize, allocatedBytes));
+            }
+        }
+
+        if (compResult == null) {
+            result = null;
+            return;
+        }
+
+        // For now precision to the nearest second is sufficient.
+        Main.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));
+    }
+
+    private String getMethodDescription() {
+        return String.format("%-6d JVMCI %-70s %-45s %-50s %s", getId(), method.getDeclaringClass().getName(), method.getName(), method.getSignature().toMethodDescriptor(),
+                        getEntryBCI() == JVMCICompiler.INVOCATION_ENTRY_BCI ? "" : "(OSR@" + getEntryBCI() + ") ");
+    }
+
+    private int getId() {
+        return id;
+    }
+
+    public int getEntryBCI() {
+        return JVMCICompiler.INVOCATION_ENTRY_BCI;
+    }
+
+    public ResolvedJavaMethod getMethod() {
+        return method;
+    }
+
+    /**
+     * Returns the holder of this method as a {@link AOTCompiledClass}.
+     *
+     * @return the holder of this method
+     */
+    public AOTCompiledClass getHolder() {
+        return holder;
+    }
+
+    /**
+     * Returns the result of this compilation task.
+     *
+     * @return result of this compilation task
+     */
+    public 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;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiledClass.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,377 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.Map;
+
+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.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.
+ */
+public class AOTCompiledClass {
+
+    public static class AOTKlassData {
+        int gotIndex; // Index (offset/8) to the got in the .metaspace.got section
+        int classId;  // Unique ID
+        // Offset to compiled methods data in the .methods.offsets section.
+        int compiledMethodsOffset;
+        // Offset to dependent methods data.
+        int dependentMethodsOffset;
+        long fingerprint;           // Class fingerprint
+
+        private final String name;
+        private boolean isArray;
+
+        /**
+         * List of dependent compiled methods which have a reference to this class.
+         */
+        private ArrayList<CompiledMethodInfo> dependentMethods;
+
+        public AOTKlassData(BinaryContainer binaryContainer, String name, long fingerprint, int classId) {
+            this.dependentMethods = new ArrayList<>();
+            this.classId = classId;
+            this.fingerprint = fingerprint;
+            this.gotIndex = binaryContainer.addTwoSlotMetaspaceSymbol(name);
+            this.compiledMethodsOffset = -1; // Not compiled classes do not have compiled methods.
+            this.dependentMethodsOffset = -1;
+            this.name = name;
+            this.isArray = name.length() > 0 && name.charAt(0) == '[';
+        }
+
+        public long getFingerprint() {
+            return fingerprint;
+        }
+
+        /**
+         * Add a method to the list of dependent methods.
+         */
+        public synchronized boolean addDependentMethod(CompiledMethodInfo cm) {
+            return dependentMethods.add(cm);
+        }
+
+        /**
+         * Return the array list of dependent class methods.
+         *
+         * @return array list of dependent methods
+         */
+        public ArrayList<CompiledMethodInfo> getDependentMethods() {
+            return dependentMethods;
+        }
+
+        /**
+         * Returns if this class has dependent methods.
+         *
+         * @return true if dependent methods exist, false otherwise
+         */
+        public boolean hasDependentMethods() {
+            return !dependentMethods.isEmpty();
+        }
+
+        public 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();
+            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(fingerprint);
+            // @formatter:on
+        }
+
+        private void verify() {
+            assert gotIndex > 0 : "incorrect gotIndex: " + gotIndex + " for klass: " + name;
+            assert 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 Map<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
+     */
+    public AOTCompiledClass(ArrayList<CompiledMethodInfo> compiledMethods) {
+        this.resolvedJavaType = null;
+        this.compiledMethods = compiledMethods;
+        this.representsStubs = true;
+    }
+
+    /**
+     * Construct an object with compiled versions of the named class.
+     */
+    public AOTCompiledClass(ResolvedJavaType resolvedJavaType) {
+        this.resolvedJavaType = (HotSpotResolvedObjectType) resolvedJavaType;
+        this.compiledMethods = new ArrayList<>();
+        this.representsStubs = false;
+    }
+
+    /**
+     * @return the ResolvedJavaType of this class
+     */
+    public ResolvedJavaType getResolvedJavaType() {
+        return resolvedJavaType;
+    }
+
+    /**
+     * Get the list of methods which should be compiled.
+     */
+    public 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.
+     */
+    public static int getClassesCount() {
+        return classesCount;
+    }
+
+    /**
+     * Get the number of methods which should be compiled.
+     *
+     * @return number of methods which should be compiled
+     */
+    public int getMethodCount() {
+        return methods.size();
+    }
+
+    /**
+     * Add a method to the list of methods to be compiled.
+     */
+    public 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
+     */
+    public boolean hasMethods() {
+        return !methods.isEmpty();
+    }
+
+    /**
+     * Add a method to the list of compiled methods. This method needs to be thread-safe.
+     */
+    public synchronized boolean addCompiledMethod(CompiledMethodInfo cm) {
+        return compiledMethods.add(cm);
+    }
+
+    /**
+     * Return the array list of compiled class methods.
+     *
+     * @return array list of compiled methods
+     */
+    public ArrayList<CompiledMethodInfo> getCompiledMethods() {
+        return compiledMethods;
+    }
+
+    /**
+     * Returns if this class has successfully compiled methods.
+     *
+     * @return true if methods were compiled, false otherwise
+     */
+    public boolean hasCompiledMethods() {
+        return !compiledMethods.isEmpty();
+    }
+
+    /**
+     * Add a klass data.
+     */
+    public synchronized static AOTKlassData addAOTKlassData(BinaryContainer binaryContainer, HotSpotResolvedObjectType type) {
+        String name = type.getName();
+        long fingerprint = type.getFingerprint();
+        AOTKlassData data = klassData.get(name);
+        if (data != null) {
+            assert data.getFingerprint() == fingerprint : "incorrect fingerprint data for klass: " + name;
+        } else {
+            data = new AOTKlassData(binaryContainer, name, fingerprint, classesCount++);
+            klassData.put(name, data);
+        }
+        return data;
+    }
+
+    public synchronized static AOTKlassData getAOTKlassData(String name) {
+        return klassData.get(name);
+    }
+
+    public synchronized static AOTKlassData getAOTKlassData(HotSpotResolvedObjectType type) {
+        return getAOTKlassData(type.getName());
+    }
+
+    public void addAOTKlassData(BinaryContainer binaryContainer) {
+        for (CompiledMethodInfo methodInfo : compiledMethods) {
+            // Record methods holder
+            methodInfo.addDependentKlassData(binaryContainer, resolvedJavaType);
+            // Record inlinee classes
+            for (ResolvedJavaMethod m : methodInfo.getCompilationResult().getMethods()) {
+                methodInfo.addDependentKlassData(binaryContainer, (HotSpotResolvedObjectType) m.getDeclaringClass());
+            }
+            // Record classes of fields that were accessed
+            for (ResolvedJavaField f : methodInfo.getCompilationResult().getFields()) {
+                methodInfo.addDependentKlassData(binaryContainer, (HotSpotResolvedObjectType) f.getDeclaringClass());
+            }
+        }
+    }
+
+    public synchronized static 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) {
+            boolean assertsEnabled = false;
+            assert assertsEnabled = true;
+            if (assertsEnabled) {
+                HotSpotResolvedObjectType s = type.getSuperclass();
+                if (s != null) {
+                    assert getAOTKlassData(s) != null : "fingerprint super " + s.getName() + " needed for " + type.getName();
+                }
+                for (HotSpotResolvedObjectType i : type.getInterfaces()) {
+                    assert getAOTKlassData(i) != null : "fingerprint super " + 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);
+    }
+
+    /*
+     * Put methods data to contained.
+     */
+    public 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 = klassData.get(name);
+        assert data != null : "missing data for klass: " + name;
+        assert data.getFingerprint() == resolvedJavaType.getFingerprint() : "incorrect fingerprint for klass: " + name;
+        int cntDepMethods = data.dependentMethods.size();
+        assert cntDepMethods > 0 : "no dependent methods for compiled klass: " + name;
+        data.setCompiledMethodsOffset(startMethods);
+    }
+
+    public static void putAOTKlassData(BinaryContainer binaryContainer) {
+        ReadOnlyDataContainer container = binaryContainer.getKlassesOffsetsContainer();
+        for (AOTKlassData data : klassData.values()) {
+            data.putAOTKlassData(binaryContainer, container);
+        }
+    }
+
+    public boolean representsStubs() {
+        return representsStubs;
+    }
+
+    public void clear() {
+        for (CompiledMethodInfo c : compiledMethods) {
+            c.clear();
+        }
+        this.compiledMethods = null;
+        this.methods = null;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiler.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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 jdk.vm.ci.meta.ResolvedJavaMethod;
+
+public class AOTCompiler {
+
+    private final Main main;
+
+    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.
+         */
+        public 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.printInfo(".");
+                }
+                CompiledMethodInfo result = task.getResult();
+                if (result != null) {
+                    task.getHolder().addCompiledMethod(result);
+                }
+            } else {
+                failedMethodCount.incrementAndGet();
+                main.printlnVerbose("");
+                ResolvedJavaMethod method = task.getMethod();
+                main.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.printlnInfo("");
+            main.printlnInfo(success + " methods compiled, " + failed + " methods failed (" + (endTime - startTime) + " ms)");
+        }
+
+    }
+
+    /**
+     * @param main
+     * @param aotBackend
+     * @param threads number of compilation threads
+     */
+    public AOTCompiler(Main main, AOTBackend aotBackend, final int threads) {
+        this.main = main;
+        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
+     */
+    public List<AOTCompiledClass> compileClasses(List<AOTCompiledClass> classes) throws InterruptedException {
+        main.printlnInfo("Compiling with " + compileQueue.getCorePoolSize() + " threads");
+        main.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, aotClass, method, backend);
+        try {
+            compileQueue.execute(task);
+        } catch (RejectedExecutionException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public static void logCompilation(String methodName, String message) {
+        Main.writeLog(message + " " + methodName);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTHotSpotResolvedJavaMethod.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.HotSpotCompiledCodeBuilder;
+import jdk.vm.ci.hotspot.HotSpotCompiledCode;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
+
+public class AOTHotSpotResolvedJavaMethod implements JavaMethodInfo {
+
+    private final HotSpotResolvedJavaMethod method;
+
+    public AOTHotSpotResolvedJavaMethod(HotSpotResolvedJavaMethod method) {
+        this.method = method;
+    }
+
+    public String getSymbolName() {
+        return MiscUtils.uniqueMethodName(method);
+    }
+
+    public String getNameAndSignature() {
+        String className = method.getDeclaringClass().getName();
+        return className + "." + method.getName() + method.getSignature().toMethodDescriptor();
+    }
+
+    public HotSpotCompiledCode compiledCode(CompilationResult result) {
+        return HotSpotCompiledCodeBuilder.createCompiledCode(method, null, result);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTStub.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.stubs.Stub;
+
+import jdk.vm.ci.hotspot.HotSpotCompiledCode;
+
+public class AOTStub implements JavaMethodInfo {
+
+    private final Stub stub;
+    private final Backend backend;
+
+    public AOTStub(Stub stub, Backend backend) {
+        this.stub = stub;
+        this.backend = backend;
+    }
+
+    public String getSymbolName() {
+        return stub.toString();
+    }
+
+    public String getNameAndSignature() {
+        return stub.toString();
+    }
+
+    public HotSpotCompiledCode compiledCode(CompilationResult result) {
+        return stub.getCompiledCode(backend);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CallSiteRelocationInfo.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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 {
+
+    public final String targetSymbol;
+    public final RelocType type;
+
+    public CallSiteRelocationInfo(String targetSymbol, RelocType type) {
+        this.targetSymbol = targetSymbol;
+        this.type = type;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CallSiteRelocationSymbol.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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 {
+
+    public final Symbol symbol;
+
+    public 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);
+    }
+
+    protected static void addMetaspaceGotRelocation(BinaryContainer binaryContainer, String symbolName, int symbolOffset, int relocationOffset) {
+        ByteContainer container = binaryContainer.getMetaspaceGotContainer();
+        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);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CodeOffsets.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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 jdk.vm.ci.code.site.Mark;
+
+public final class CodeOffsets {
+    private final int entry;
+    private final int verifiedEntry;
+    private final int exceptionHandler;
+    private final int deoptHandler;
+
+    private CodeOffsets(int entry, int verifiedEntry, int exceptionHandler, int deoptHandler) {
+        this.entry = entry;
+        this.verifiedEntry = verifiedEntry;
+        this.exceptionHandler = exceptionHandler;
+        this.deoptHandler = deoptHandler;
+    }
+
+    public static CodeOffsets buildFrom(List<Mark> marks) {
+        int entry = 0;
+        int verifiedEntry = 0;
+        int exceptionHandler = -1;
+        int deoptHandler = -1;
+
+        for (Mark mark : marks) {
+            if (mark.id instanceof Integer) {
+                MarkId markId = MarkId.getEnum((int) 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;
+                    default:
+                        break; // Ignore others
+                }
+            }
+        }
+        return new CodeOffsets(entry, verifiedEntry, exceptionHandler, deoptHandler);
+    }
+
+    public int entry() {
+        return entry;
+    }
+
+    public int verifiedEntry() {
+        return verifiedEntry;
+    }
+
+    public int exceptionHandler() {
+        return exceptionHandler;
+    }
+
+    public int deoptHandler() {
+        return deoptHandler;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CodeSectionProcessor.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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 jdk.tools.jaotc.binformat.BinaryContainer;
+import jdk.tools.jaotc.binformat.CodeContainer;
+import jdk.tools.jaotc.binformat.Symbol;
+import jdk.tools.jaotc.CompiledMethodInfo.StubInformation;
+import org.graalvm.compiler.code.CompilationResult;
+import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
+
+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;
+
+class CodeSectionProcessor {
+
+    private final TargetDescription target;
+
+    private final BinaryContainer binaryContainer;
+
+    CodeSectionProcessor(DataBuilder dataBuilder) {
+        this.target = dataBuilder.getBackend().getTarget();
+        this.binaryContainer = dataBuilder.getBinaryContainer();
+    }
+
+    /**
+     * 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) {
+                        // 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(MiscUtils.isVirtualCall(methodInfo, callInfopoint));
+                        // Get the targetSymbol. A symbol for this will be created later during plt
+                        // creation
+                        String targetSymbol = MiscUtils.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);
+        byte[] code;
+        if (isVirtualCall) {
+            code = masm.getPLTVirtualEntryCode(stub);
+        } else {
+            code = masm.getPLTStaticEntryCode(stub);
+        }
+        binaryContainer.appendCodeBytes(code, 0, code.length);
+        return stub;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CompilationSpec.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.
+ */
+public 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
+     */
+    public 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
+     */
+    public 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
+     */
+    public 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 = MiscUtils.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());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CompiledMethodInfo.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,441 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.atomic.AtomicInteger;
+import java.util.HashMap;
+import java.util.Map;
+
+import jdk.tools.jaotc.binformat.BinaryContainer;
+import jdk.tools.jaotc.binformat.ReadOnlyDataContainer;
+import jdk.tools.jaotc.AOTCompiledClass.AOTKlassData;
+import org.graalvm.compiler.code.CompilationResult;
+
+import jdk.vm.ci.code.site.Mark;
+import jdk.vm.ci.code.site.Site;
+import jdk.vm.ci.hotspot.HotSpotCompiledCode;
+import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
+
+public class CompiledMethodInfo {
+
+    public static class StubInformation {
+        int stubOffset;         // the offset inside the code (text + stubOffset)
+        int stubSize;           // the stub size
+        int dispatchJumpOffset; // offset after main dispatch jump instruction
+        int resolveJumpOffset;  // offset after jump instruction to runtime call resolution
+                               // function.
+        int resolveJumpStart;   // offset of jump instruction to VM runtime call resolution
+                              // function.
+        int c2iJumpOffset;      // offset after jump instruction to c2i adapter for static calls.
+        int movOffset; // offset after move instruction which loads from got cell:
+                       // - Method* for static call
+                       // - Klass* for virtual call
+
+        boolean isVirtual;  // virtual call stub
+
+        // maybe add type of stub as well, right now we only have static stubs
+
+        public 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;
+        }
+
+        public int getOffset() {
+            return stubOffset;
+        }
+
+        public boolean isVirtual() {
+            return isVirtual;
+        }
+
+        public void setSize(int stubSize) {
+            this.stubSize = stubSize;
+        }
+
+        public int getSize() {
+            return stubSize;
+        }
+
+        public void setMovOffset(int movOffset) {
+            this.movOffset = movOffset + stubOffset;
+        }
+
+        public int getMovOffset() {
+            return movOffset;
+        }
+
+        public void setC2IJumpOffset(int c2iJumpOffset) {
+            this.c2iJumpOffset = c2iJumpOffset + stubOffset;
+        }
+
+        public int getC2IJumpOffset() {
+            return c2iJumpOffset;
+        }
+
+        public void setResolveJumpOffset(int resolveJumpOffset) {
+            this.resolveJumpOffset = resolveJumpOffset + stubOffset;
+        }
+
+        public int getResolveJumpOffset() {
+            return resolveJumpOffset;
+        }
+
+        public void setResolveJumpStart(int resolveJumpStart) {
+            this.resolveJumpStart = resolveJumpStart + stubOffset;
+        }
+
+        public int getResolveJumpStart() {
+            return resolveJumpStart;
+        }
+
+        public void setDispatchJumpOffset(int dispatchJumpOffset) {
+            this.dispatchJumpOffset = dispatchJumpOffset + stubOffset;
+        }
+
+        public int getDispatchJumpOffset() {
+            return dispatchJumpOffset;
+        }
+
+        public 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;
+            }
+        }
+    }
+
+    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;
+
+        public AOTMethodOffsets() {
+            this.nameOffset = UNINITIALIZED_OFFSET;
+            this.textSectionOffset = UNINITIALIZED_OFFSET;
+            this.metadataOffset = UNINITIALIZED_OFFSET;
+            this.metadataGotOffset = UNINITIALIZED_OFFSET;
+            this.metadataGotSize = -1;
+            this.codeId = -1;
+        }
+
+        protected 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 Map<String, StubInformation> stubs = new HashMap<>();
+
+    /**
+     * List of referenced classes.
+     */
+    private Map<String, AOTKlassData> dependentKlasses = new HashMap<>();
+
+    /**
+     * Methods count used to generate unique global method id.
+     */
+    private static final AtomicInteger methodsCount = new AtomicInteger();
+
+    public CompiledMethodInfo(CompilationResult compilationResult, JavaMethodInfo methodInfo) {
+        this.name = methodInfo.getNameAndSignature();
+        this.compilationResult = compilationResult;
+        this.methodInfo = methodInfo;
+        this.stubsOffset = UNINITIALIZED_OFFSET;
+        this.methodOffsets = new AOTMethodOffsets();
+    }
+
+    public String name() {
+        return name;
+    }
+
+    public void addMethodOffsets(BinaryContainer binaryContainer, ReadOnlyDataContainer container) {
+        this.methodOffsets.setNameOffset(binaryContainer.addMetaspaceName(name));
+        this.methodOffsets.addMethodOffsets(container, name);
+        for (AOTKlassData data : dependentKlasses.values()) {
+            data.addDependentMethod(this);
+        }
+    }
+
+    public CompilationResult getCompilationResult() {
+        return compilationResult;
+    }
+
+    public JavaMethodInfo getMethodInfo() {
+        return methodInfo;
+    }
+
+    public void setTextSectionOffset(int textSectionOffset) {
+        methodOffsets.setTextSectionOffset(textSectionOffset);
+    }
+
+    public int getTextSectionOffset() {
+        return methodOffsets.getTextSectionOffset();
+    }
+
+    public void setCodeId() {
+        methodOffsets.setCodeId(CompiledMethodInfo.getNextCodeId());
+    }
+
+    public int getCodeId() {
+        return this.methodOffsets.getCodeId();
+    }
+
+    public static int getMethodsCount() {
+        return methodsCount.get();
+    }
+
+    public static int getNextCodeId() {
+        return methodsCount.getAndIncrement();
+    }
+
+    public int getCodeSize() {
+        return stubsOffset + getStubCodeSize();
+    }
+
+    public int getStubCodeSize() {
+        return totalStubSize;
+    }
+
+    public void setMetadataOffset(int offset) {
+        this.methodOffsets.setMetadataOffset(offset);
+    }
+
+    /**
+     * Offset into the code of this method where the stub section starts.
+     */
+    public void setStubsOffset(int offset) {
+        stubsOffset = offset;
+    }
+
+    public int getStubsOffset() {
+        return stubsOffset;
+    }
+
+    public void setMetadataGotOffset(int metadataGotOffset) {
+        this.methodOffsets.setMetadataGotOffset(metadataGotOffset);
+    }
+
+    public void setMetadataGotSize(int length) {
+        this.methodOffsets.setMetadataGotSize(length);
+    }
+
+    public void addStubCode(String call, StubInformation stub) {
+        stubs.put(call, stub);
+        totalStubSize += stub.getSize();
+    }
+
+    public StubInformation getStubFor(String call) {
+        StubInformation stub = stubs.get(call);
+        assert stub != null : "missing stub for call " + call;
+        stub.verify();
+        return stub;
+    }
+
+    public void addDependentKlassData(BinaryContainer binaryContainer, HotSpotResolvedObjectType type) {
+        AOTKlassData klassData = AOTCompiledClass.addFingerprintKlassData(binaryContainer, type);
+        String klassName = type.getName();
+
+        if (dependentKlasses.containsKey(klassName)) {
+            assert dependentKlasses.get(klassName) == klassData : "duplicated data for klass: " + klassName;
+        } else {
+            dependentKlasses.put(klassName, klassData);
+        }
+    }
+
+    public AOTKlassData getDependentKlassData(String klassName) {
+        return dependentKlasses.get(klassName);
+    }
+
+    public boolean hasMark(Site call, MarkId id) {
+        for (Mark m : compilationResult.getMarks()) {
+            // TODO: X64-specific code.
+            // Call instructions are aligned to 8
+            // bytes - 1 on x86 to patch address atomically,
+            int adjOffset = (m.pcOffset & (-8)) + 7;
+            // Mark points before aligning nops.
+            if ((call.pcOffset == adjOffset) && MarkId.getEnum((int) m.id) == id) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public String asTag() {
+        return "[" + methodInfo.getSymbolName() + "]";
+    }
+
+    public HotSpotCompiledCode compiledCode() {
+        if (code == null) {
+            code = methodInfo.compiledCode(compilationResult);
+        }
+        return code;
+    }
+
+    // Free memory
+    public void clear() {
+        this.dependentKlasses = null;
+        this.name = null;
+    }
+
+    public void clearCompileData() {
+        this.code = null;
+        this.stubs = null;
+        this.compilationResult = null;
+        this.methodInfo = null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataBuilder.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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 jdk.tools.jaotc.binformat.BinaryContainer;
+import jdk.tools.jaotc.binformat.ByteContainer;
+import jdk.tools.jaotc.binformat.HeaderContainer;
+import jdk.tools.jaotc.utils.Timer;
+import org.graalvm.compiler.code.CompilationResult;
+import org.graalvm.compiler.debug.Debug;
+import org.graalvm.compiler.debug.Debug.Scope;
+import org.graalvm.compiler.hotspot.HotSpotHostBackend;
+import org.graalvm.compiler.hotspot.stubs.Stub;
+
+import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
+import jdk.vm.ci.hotspot.HotSpotVMConfigStore;
+import jdk.vm.ci.hotspot.VMField;
+
+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 final HashMap<Long, String> vmAddresses = new HashMap<>();
+
+    public 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 void fillVMAddresses(HotSpotVMConfigStore config) {
+        for (VMField vmField : config.getFields().values()) {
+            if (vmField.value != null) {
+                final long address = 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
+     */
+    public String getVMFunctionNameForAddress(long address) {
+        return vmAddresses.get(address);
+    }
+
+    /**
+     * Returns the host backend used for this compilation.
+     *
+     * @return host backend
+     */
+    public HotSpotHostBackend getBackend() {
+        return backend;
+    }
+
+    /**
+     * Returns the binary container for this compilation.
+     *
+     * @return binary container
+     */
+    public BinaryContainer getBinaryContainer() {
+        return binaryContainer;
+    }
+
+    /**
+     * Prepare data with all compiled classes and stubs.
+     *
+     * @throws Exception
+     */
+    @SuppressWarnings("try")
+    public void prepareData() 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();
+
+        // Free memory!
+        try (Timer t = main.options.verbose ? new Timer(main, "Freeing memory") : null) {
+            main.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.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(metadataBuilder);
+        }
+    }
+
+    /**
+     * Get all stubs from Graal and add them to the code section.
+     */
+    @SuppressWarnings("try")
+    private AOTCompiledClass retrieveStubCode() {
+        ArrayList<CompiledMethodInfo> stubs = new ArrayList<>();
+        for (Stub stub : Stub.getStubs()) {
+            try (Scope scope = Debug.scope("CompileStubs")) {
+                CompilationResult result = stub.getCompilationResult(backend);
+                CompiledMethodInfo cm = new CompiledMethodInfo(result, new AOTStub(stub, backend));
+                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(MetadataBuilder metadataBuilder) {
+        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.getMetaspaceGotContainer();
+        header.setMetaspaceGotSize((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());
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataPatchProcessor.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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 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.tools.jaotc.AOTCompiledClass.AOTKlassData;
+import org.graalvm.compiler.code.DataSection;
+import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction;
+
+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.HotSpotMetaspaceConstant;
+import jdk.vm.ci.hotspot.HotSpotObjectConstant;
+import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
+import jdk.vm.ci.hotspot.HotSpotSentinelConstant;
+import jdk.vm.ci.meta.VMConstant;
+
+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();
+                targetSymbol = type.getName();
+                gotName = ((action == HotSpotConstantLoadAction.INITIALIZE) ? "got.init." : "got.") + targetSymbol;
+                methodInfo.addDependentKlassData(binaryContainer, type);
+            } else if (metaspaceConstant.asResolvedJavaMethod() != null && action == HotSpotConstantLoadAction.LOAD_COUNTERS) {
+                targetSymbol = "counters." + MiscUtils.uniqueMethodName(metaspaceConstant.asResolvedJavaMethod());
+                gotName = "got." + targetSymbol;
+                binaryContainer.addMetaspaceSymbol(targetSymbol);
+            }
+        } else if (constant instanceof HotSpotObjectConstant) {
+            // String constant.
+            HotSpotObjectConstant oopConstant = (HotSpotObjectConstant) constant;
+            targetSymbol = "ldc." + oopConstant.toValueString();
+            Integer offset = binaryContainer.addOopSymbol(targetSymbol);
+            gotName = "got.ldc." + offset;
+        } else if (constant 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 -> {
+        });
+        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);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/ELFMacroAssembler.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.CompiledMethodInfo.StubInformation;
+import jdk.tools.jaotc.amd64.AMD64ELFMacroAssembler;
+
+import jdk.vm.ci.amd64.AMD64;
+import jdk.vm.ci.code.Architecture;
+import jdk.vm.ci.code.TargetDescription;
+
+public interface ELFMacroAssembler {
+
+    public static ELFMacroAssembler getELFMacroAssembler(TargetDescription target) {
+        Architecture architecture = target.arch;
+        if (architecture instanceof AMD64) {
+            return new AMD64ELFMacroAssembler(target);
+        } else {
+            throw new InternalError("Unsupported architecture " + architecture);
+        }
+    }
+
+    public int currentEndOfInstruction();
+
+    public byte[] getPLTJumpCode();
+
+    public byte[] getPLTStaticEntryCode(StubInformation stub);
+
+    public byte[] getPLTVirtualEntryCode(StubInformation stub);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/ForeignCallSiteRelocationInfo.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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, DataBuilder dataBuilder) {
+        super(getTargetSymbol(call, callTarget, dataBuilder), getRelocType(callTarget));
+    }
+
+    private static String getTargetSymbol(Call call, HotSpotForeignCallLinkage callTarget, DataBuilder dataBuilder) {
+        // 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
+            BinaryContainer binaryContainer = dataBuilder.getBinaryContainer();
+            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;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/ForeignCallSiteRelocationSymbol.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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 {
+
+    public ForeignCallSiteRelocationSymbol(CallSiteRelocationInfo callSiteRelocation, BinaryContainer binaryContainer) {
+        super(binaryContainer.createSymbol(0, Kind.NATIVE_FUNCTION, Binding.GLOBAL, 0, callSiteRelocation.targetSymbol));
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/ForeignGotCallSiteRelocationSymbol.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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 {
+
+    public 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());
+        byte[] code = masm.getPLTJumpCode(); // It includes alignment nops.
+        int size = masm.currentEndOfInstruction();
+        dataBuilder.getBinaryContainer().appendCodeBytes(code, 0, code.length);
+        return size;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/GraalFilters.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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 jdk.vm.ci.meta.MetaAccessProvider;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+
+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 org.graalvm.compiler.word.WordBase;
+
+public 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);
+    }
+
+    public 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;
+    }
+
+    public boolean shouldCompileAnyMethodInClass(ResolvedJavaType klass) {
+        if (specialClasses.stream().filter(s -> s.isAssignableFrom(klass)).findAny().isPresent()) {
+            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);
+    }
+
+    public 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;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/InfopointProcessor.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.DebugInfo;
+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.HotSpotResolvedJavaType;
+import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
+import jdk.vm.ci.meta.InvokeTarget;
+
+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 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, dataBuilder);
+        } 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);
+            case FOREIGN_CALL_DIRECT:
+            case FOREIGN_CALL_DIRECT_FAR:
+            case FOREIGN_CALL_INDIRECT:
+                return new ForeignCallSiteRelocationSymbol(callSiteRelocation, binaryContainer);
+            default:
+                return new JavaCallSiteRelocationSymbol(mi, call, callSiteRelocation, binaryContainer);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/InstructionDecoder.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.vm.ci.amd64.AMD64;
+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 {
+            throw new InternalError("Unsupported architecture " + architecture);
+        }
+    }
+
+    public abstract void decodePosition(final byte[] code, int pcOffset);
+
+    public abstract int currentEndOfInstruction();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/JavaCallSiteRelocationInfo.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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 {
+
+    public JavaCallSiteRelocationInfo(Call call, HotSpotResolvedJavaMethod callTarget) {
+        super(MiscUtils.uniqueMethodName(callTarget), call.direct ? RelocType.JAVA_CALL_DIRECT : RelocType.JAVA_CALL_INDIRECT);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/JavaCallSiteRelocationSymbol.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.tools.jaotc.CompiledMethodInfo.StubInformation;
+
+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];
+    private static final byte[] minusOneSlot = {-1, -1, -1, -1, -1, -1, -1, -1};
+
+    public 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 = MiscUtils.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 = MiscUtils.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.
+        String gotSymbolName = "got." + getResolveSymbolName(binaryContainer, mi, call);
+        Symbol gotSymbol = binaryContainer.getGotSymbol(gotSymbolName);
+        addExternalPltToGotRelocation(binaryContainer, gotSymbol, stub.getResolveJumpOffset());
+
+        // Add relocation to resolve call jump instruction address for GOT cell.
+        String pltJmpSymbolName = relocationSymbolName("plt.jmp", mi, call, callSiteRelocation);
+        addCodeContainerRelocation(binaryContainer, pltJmpSymbolName, stub.getResolveJumpStart(), gotStartOffset);
+
+        // Add relocation to GOT cell for dispatch jump.
+        String gotEntrySymbolName = relocationSymbolName("got.entry", mi, call, callSiteRelocation);
+        addExtLinkageGotContainerRelocation(binaryContainer, gotEntrySymbolName, gotStartOffset, stub.getDispatchJumpOffset());
+
+        // Virtual call needs initial -1 value.
+        byte[] slot = isVirtualCall ? minusOneSlot : zeroSlot;
+        final int gotMetaOffset = binaryContainer.appendMetaspaceGotBytes(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);
+        addMetaspaceGotRelocation(binaryContainer, gotMoveSymbolName, gotMetaOffset, stub.getMovOffset());
+
+        if (isVirtualCall) {
+            // Nothing.
+        } else {
+            // Add relocation to GOT cell for c2i adapter jump.
+            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(BinaryContainer binaryContainer, CompiledMethodInfo mi, Call call) {
+        String resolveSymbolName;
+        if (MiscUtils.isStaticCall(call)) {
+            resolveSymbolName = binaryContainer.getResolveStaticEntrySymbolName();
+        } else if (MiscUtils.isSpecialCall(call)) {
+            resolveSymbolName = binaryContainer.getResolveOptVirtualEntrySymbolName();
+        } else if (MiscUtils.isOptVirtualCall(mi, call)) {
+            resolveSymbolName = binaryContainer.getResolveOptVirtualEntrySymbolName();
+        } else if (MiscUtils.isVirtualCall(mi, call)) {
+            resolveSymbolName = binaryContainer.getResolveVirtualEntrySymbolName();
+        } else {
+            throw new InternalError("Unknown call type in " + mi.asTag() + " @ " + call.pcOffset + " for call" + call.target);
+        }
+        return resolveSymbolName;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/JavaMethodInfo.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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;
+
+public 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);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/LogPrinter.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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 interface LogPrinter {
+    void printInfo(String s);
+
+    void printlnVerbose(String s);
+
+    void printlnInfo(String s);
+
+    void printError(String s);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,767 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+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.ArrayList;
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Stream;
+
+import jdk.tools.jaotc.binformat.BinaryContainer;
+import jdk.tools.jaotc.binformat.ByteContainer;
+import jdk.tools.jaotc.collect.ClassCollector;
+import jdk.tools.jaotc.utils.Timer;
+
+import org.graalvm.compiler.api.runtime.GraalJVMCICompiler;
+import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
+import org.graalvm.compiler.hotspot.HotSpotHostBackend;
+import org.graalvm.compiler.runtime.RuntimeProvider;
+
+import jdk.vm.ci.meta.MetaAccessProvider;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.runtime.JVMCI;
+
+public class Main implements LogPrinter {
+    static {
+        GeneratePIC.setValue(true);
+        ImmutableCode.setValue(true);
+    }
+
+    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("  --module <name>            Module to compile", true, "--module") {
+        @Override
+        void process(Main task, String opt, String arg) {
+            task.options.module = arg;
+        }
+    }, new Option("  --module-path <path>       Specify where to find module to compile", true, "--module-path") {
+        @Override
+        void process(Main task, String opt, String arg) {
+            task.options.modulepath = arg;
+        }
+    }, new Option("  --output <file>            Output file name", true, "--output") {
+        @Override
+        void process(Main task, String opt, String arg) {
+            String name = arg;
+            if (name.endsWith(".so")) {
+                name = name.substring(0, name.length() - ".so".length());
+            }
+            task.options.outputName = name;
+        }
+    }, 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       Generated profiling code for tiered compilation", false, "--compile-for-tiered") {
+        @Override
+        void process(Main task, String opt, String arg) {
+            TieredAOT.setValue(true);
+        }
+    }, new Option("  --classpath <path>         Specify where to find user class files", true, "--classpath", "--class-path") {
+        @Override
+        void process(Main task, String opt, String arg) {
+            task.options.classpath = arg;
+        }
+    }, new Option("  --threads <number>         Number of compilation threads to be used", true, "--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("  --help                     Print this usage message", false, "--help") {
+        @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("  -J<flag>                   Pass <flag> directly to the runtime system", false, "-J") {
+        @Override
+        void process(Main task, String opt, String arg) {
+        }
+    }};
+
+    public static class Options {
+        public List<String> files = new LinkedList<>();
+        public String module = null;
+        public String modulepath = "modules";
+        public String outputName = "unnamed";
+        public String methodList;
+        public String classpath = ".";
+
+        /**
+         * We don't see scaling beyond 16 threads.
+         */
+        private static final int COMPILER_THREADS = 16;
+
+        int threads = Integer.min(COMPILER_THREADS, Runtime.getRuntime().availableProcessors());
+
+        public boolean ignoreClassLoadingErrors;
+        public boolean exitOnError;
+        boolean info;
+        boolean verbose;
+        boolean debug;
+        boolean help;
+        boolean version;
+    }
+
+    /* package */final Options options = new Options();
+
+    /**
+     * Logfile.
+     */
+    private static FileWriter logFile = null;
+
+    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(args);
+        System.exit(exitCode);
+    }
+
+    private int run(String[] args) {
+        if (log == null) {
+            log = new PrintWriter(System.out);
+        }
+
+        try {
+            handleOptions(args);
+            if (options.help) {
+                showHelp();
+                return EXIT_OK;
+            }
+            if (options.version) {
+                showVersion();
+                return EXIT_OK;
+            }
+
+            printlnInfo("Compiling " + options.outputName + "...");
+            final long start = System.currentTimeMillis();
+            run();
+            final long end = System.currentTimeMillis();
+            printlnInfo("Total time: " + (end - start) + " ms");
+
+            return EXIT_OK;
+        } catch (BadArgs e) {
+            reportError(e.key, e.args);
+            if (e.showUsage) {
+                showUsage();
+            }
+            return EXIT_CMDERR;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return EXIT_ABNORMAL;
+        } finally {
+            log.flush();
+        }
+    }
+
+    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);
+        }
+    }
+
+    @SuppressWarnings("try")
+    private void run() throws Exception {
+        openLog();
+
+        try {
+            CompilationSpec compilationRestrictions = collectSpecifiedMethods();
+
+            Set<Class<?>> classesToCompile;
+
+            try (Timer t = new Timer(this, "")) {
+                ClassCollector collector = new ClassCollector(this.options, this);
+                classesToCompile = collector.collectClassesToCompile();
+                printInfo(classesToCompile.size() + " classes found");
+            }
+
+            GraalJVMCICompiler graalCompiler = (GraalJVMCICompiler) JVMCI.getRuntime().getCompiler();
+            HotSpotGraalRuntimeProvider runtime = (HotSpotGraalRuntimeProvider) graalCompiler.getGraalRuntime();
+            HotSpotHostBackend backend = (HotSpotHostBackend) runtime.getCapability(RuntimeProvider.class).getHostBackend();
+            MetaAccessProvider metaAccess = backend.getProviders().getMetaAccess();
+            GraalFilters filters = new GraalFilters(metaAccess);
+
+            List<AOTCompiledClass> classes;
+
+            try (Timer t = new Timer(this, "")) {
+                classes = collectMethodsToCompile(classesToCompile, compilationRestrictions, filters, metaAccess);
+            }
+
+            // Free memory!
+            try (Timer t = options.verbose ? new Timer(this, "Freeing memory") : null) {
+                printMemoryUsage();
+                compilationRestrictions = null;
+                classesToCompile = null;
+                System.gc();
+            }
+
+            AOTBackend aotBackend = new AOTBackend(this, backend, filters);
+            AOTCompiler compiler = new AOTCompiler(this, aotBackend, options.threads);
+            classes = compiler.compileClasses(classes);
+
+            // Free memory!
+            try (Timer t = options.verbose ? new Timer(this, "Freeing memory") : null) {
+                printMemoryUsage();
+                aotBackend = null;
+                compiler = null;
+                System.gc();
+            }
+
+            BinaryContainer binaryContainer = new BinaryContainer(runtime.getVMConfig(), JVM_VERSION);
+            DataBuilder dataBuilder = new DataBuilder(this, backend, classes, binaryContainer);
+            dataBuilder.prepareData();
+
+            // Print information about section sizes
+            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.getMetaspaceGotContainer());
+            printContainerInfo(binaryContainer.getMetadataGotContainer());
+            printContainerInfo(binaryContainer.getMethodStateContainer());
+            printContainerInfo(binaryContainer.getOopGotContainer());
+            printContainerInfo(binaryContainer.getMetaspaceNamesContainer());
+
+            // Free memory!
+            try (Timer t = options.verbose ? new Timer(this, "Freeing memory") : null) {
+                printMemoryUsage();
+                backend = null;
+                for (AOTCompiledClass aotCompClass : classes) {
+                    aotCompClass.clear();
+                }
+                classes.clear();
+                classes = null;
+                dataBuilder = null;
+                binaryContainer.freeMemory();
+                System.gc();
+            }
+
+            String objectFileName = options.outputName + ".o";
+            String libraryFileName = options.outputName + ".so";
+
+            try (Timer t = new Timer(this, "Creating binary: " + objectFileName)) {
+                binaryContainer.createBinary(objectFileName, JVM_VERSION);
+            }
+
+            // Free memory!
+            try (Timer t = options.verbose ? new Timer(this, "Freeing memory") : null) {
+                printMemoryUsage();
+                binaryContainer = null;
+                System.gc();
+            }
+
+            try (Timer t = new Timer(this, "Creating shared library: " + libraryFileName)) {
+                Process p = Runtime.getRuntime().exec("ld -shared -z noexecstack -o " + libraryFileName + " " + objectFileName);
+                final int exitCode = p.waitFor();
+                if (exitCode != 0) {
+                    InputStream stderr = p.getErrorStream();
+                    BufferedReader br = new BufferedReader(new InputStreamReader(stderr));
+                    Stream<String> lines = br.lines();
+                    StringBuilder sb = new StringBuilder();
+                    lines.iterator().forEachRemaining(e -> sb.append(e));
+                    throw new InternalError(sb.toString());
+                }
+                File objFile = new File(objectFileName);
+                if (objFile.exists()) {
+                    if (!objFile.delete()) {
+                        throw new InternalError("Failed to delete " + objectFileName + " file");
+                    }
+                }
+                // Make non-executable for all.
+                File libFile = new File(libraryFileName);
+                if (libFile.exists()) {
+                    if (!libFile.setExecutable(false, false)) {
+                        throw new InternalError("Failed to change attribute for " + libraryFileName + " file");
+                    }
+                }
+            }
+
+            printVerbose("Final memory  ");
+            printMemoryUsage();
+            printlnVerbose("");
+
+        } finally {
+            closeLog();
+        }
+    }
+
+    private void addMethods(AOTCompiledClass aotClass, ResolvedJavaMethod[] methods, CompilationSpec compilationRestrictions, GraalFilters filters) {
+        for (ResolvedJavaMethod m : methods) {
+            addMethod(aotClass, m, compilationRestrictions, filters);
+        }
+    }
+
+    private void addMethod(AOTCompiledClass aotClass, ResolvedJavaMethod method, CompilationSpec compilationRestrictions, GraalFilters filters) {
+        // Don't compile native or abstract methods.
+        if (!method.hasBytecodes()) {
+            return;
+        }
+        if (!compilationRestrictions.shouldCompileMethod(method)) {
+            return;
+        }
+        if (!filters.shouldCompileMethod(method)) {
+            return;
+        }
+
+        aotClass.addMethod(method);
+        printlnVerbose("  added " + method.getName() + method.getSignature().toMethodDescriptor());
+    }
+
+    private void printContainerInfo(ByteContainer container) {
+        printlnVerbose(container.getContainerName() + ": " + container.getByteStreamSize() + " bytes");
+    }
+
+    PrintWriter log;
+
+    private void handleOptions(String[] args) throws BadArgs {
+        if (args.length == 0) {
+            options.help = true;
+            return;
+        }
+
+        // Make checkstyle happy.
+        int i = 0;
+        for (; i < args.length; i++) {
+            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(this, arg, param);
+
+                if (option.ignoreRest()) {
+                    break;
+                }
+            } else {
+                options.files.add(arg);
+            }
+        }
+    }
+
+    private 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);
+    }
+
+    public void printInfo(String message) {
+        if (options.info) {
+            log.print(message);
+            log.flush();
+        }
+    }
+
+    public void printlnInfo(String message) {
+        if (options.info) {
+            log.println(message);
+            log.flush();
+        }
+    }
+
+    public void printVerbose(String message) {
+        if (options.verbose) {
+            log.print(message);
+            log.flush();
+        }
+    }
+
+    public void printlnVerbose(String message) {
+        if (options.verbose) {
+            log.println(message);
+            log.flush();
+        }
+    }
+
+    public void printDebug(String message) {
+        if (options.debug) {
+            log.print(message);
+            log.flush();
+        }
+    }
+
+    public void printlnDebug(String message) {
+        if (options.debug) {
+            log.println(message);
+            log.flush();
+        }
+    }
+
+    public void printError(String message) {
+        log.println("Error: " + message);
+        log.flush();
+    }
+
+    private void reportError(String key, Object... args) {
+        printError(MessageFormat.format(key, args));
+    }
+
+    private 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");
+    }
+
+    private void showHelp() {
+        log.println("Usage: " + PROGNAME + " <options> <--module name> | <list...>");
+        log.println();
+        log.println("  list       A list of class files, jar files or directories which");
+        log.println("             contains class files.");
+        log.println();
+        log.println("where possible options include:");
+        for (Option o : 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);
+        }
+    }
+
+    private void showVersion() {
+        log.println(PROGNAME + " " + JVM_VERSION);
+    }
+
+    /**
+     * Collect all method we should compile.
+     *
+     * @return array list of AOT classes which have compiled methods.
+     */
+    private List<AOTCompiledClass> collectMethodsToCompile(Set<Class<?>> classesToCompile, CompilationSpec compilationRestrictions, GraalFilters filters, MetaAccessProvider metaAccess) {
+        int total = 0;
+        int count = 0;
+        List<AOTCompiledClass> classes = new ArrayList<>();
+
+        for (Class<?> c : classesToCompile) {
+            ResolvedJavaType resolvedJavaType = metaAccess.lookupJavaType(c);
+            if (filters.shouldCompileAnyMethodInClass(resolvedJavaType)) {
+                AOTCompiledClass aotClass = new AOTCompiledClass(resolvedJavaType);
+                printlnVerbose(" Scanning " + c.getName());
+
+                // Constructors
+                try {
+                    ResolvedJavaMethod[] ctors = resolvedJavaType.getDeclaredConstructors();
+                    addMethods(aotClass, ctors, compilationRestrictions, filters);
+                    total += ctors.length;
+                } catch (Throwable e) {
+                    // If we are running in JCK mode we ignore all exceptions.
+                    if (options.ignoreClassLoadingErrors) {
+                        printError(c.getName() + ": " + e);
+                    } else {
+                        throw new InternalError(e);
+                    }
+                }
+
+                // Methods
+                try {
+                    ResolvedJavaMethod[] methods = resolvedJavaType.getDeclaredMethods();
+                    addMethods(aotClass, methods, compilationRestrictions, filters);
+                    total += methods.length;
+                } catch (Throwable e) {
+                    // If we are running in JCK mode we ignore all exceptions.
+                    if (options.ignoreClassLoadingErrors) {
+                        printError(c.getName() + ": " + e);
+                    } else {
+                        throw new InternalError(e);
+                    }
+                }
+
+                // Class initializer
+                try {
+                    ResolvedJavaMethod clinit = resolvedJavaType.getClassInitializer();
+                    if (clinit != null) {
+                        addMethod(aotClass, clinit, compilationRestrictions, filters);
+                        total++;
+                    }
+                } catch (Throwable e) {
+                    // If we are running in JCK mode we ignore all exceptions.
+                    if (options.ignoreClassLoadingErrors) {
+                        printError(c.getName() + ": " + e);
+                    } else {
+                        throw new InternalError(e);
+                    }
+                }
+
+                // Found any methods to compile? Add the class.
+                if (aotClass.hasMethods()) {
+                    classes.add(aotClass);
+                    count += aotClass.getMethodCount();
+                }
+            }
+        }
+        printInfo(total + " methods total, " + count + " methods to compile");
+        return classes;
+    }
+
+    /**
+     * If a file with compilation limitations is specified using the java property
+     * jdk.tools.jaotc.compile.method.list, read the file's contents and collect the restrictions.
+     */
+    private CompilationSpec collectSpecifiedMethods() {
+        CompilationSpec compilationRestrictions = new CompilationSpec();
+        String methodListFileName = 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 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;
+        }
+    }
+
+    public 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");
+            }
+        }
+    }
+
+    public static void closeLog() {
+        if (logFile != null) {
+            try {
+                logFile.close();
+            } catch (IOException e) {
+                // Do nothing
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MarkId.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.vm.ci.hotspot.HotSpotJVMCIRuntime;
+
+/**
+ * Constants used to mark special positions in code being installed into the code cache by Graal C++
+ * code.
+ */
+enum MarkId {
+    VERIFIED_ENTRY("CodeInstaller::VERIFIED_ENTRY"),
+    UNVERIFIED_ENTRY("CodeInstaller::UNVERIFIED_ENTRY"),
+    OSR_ENTRY("CodeInstaller::OSR_ENTRY"),
+    EXCEPTION_HANDLER_ENTRY("CodeInstaller::EXCEPTION_HANDLER_ENTRY"),
+    DEOPT_HANDLER_ENTRY("CodeInstaller::DEOPT_HANDLER_ENTRY"),
+    INVOKEINTERFACE("CodeInstaller::INVOKEINTERFACE"),
+    INVOKEVIRTUAL("CodeInstaller::INVOKEVIRTUAL"),
+    INVOKESTATIC("CodeInstaller::INVOKESTATIC"),
+    INVOKESPECIAL("CodeInstaller::INVOKESPECIAL"),
+    INLINE_INVOKE("CodeInstaller::INLINE_INVOKE"),
+    POLL_NEAR("CodeInstaller::POLL_NEAR"),
+    POLL_RETURN_NEAR("CodeInstaller::POLL_RETURN_NEAR"),
+    POLL_FAR("CodeInstaller::POLL_FAR"),
+    POLL_RETURN_FAR("CodeInstaller::POLL_RETURN_FAR"),
+    CARD_TABLE_ADDRESS("CodeInstaller::CARD_TABLE_ADDRESS"),
+    HEAP_TOP_ADDRESS("CodeInstaller::HEAP_TOP_ADDRESS"),
+    HEAP_END_ADDRESS("CodeInstaller::HEAP_END_ADDRESS"),
+    NARROW_KLASS_BASE_ADDRESS("CodeInstaller::NARROW_KLASS_BASE_ADDRESS"),
+    CRC_TABLE_ADDRESS("CodeInstaller::CRC_TABLE_ADDRESS"),
+    LOG_OF_HEAP_REGION_GRAIN_BYTES("CodeInstaller::LOG_OF_HEAP_REGION_GRAIN_BYTES"),
+    INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED("CodeInstaller::INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED");
+
+    private final int value;
+
+    private MarkId(String name) {
+        this.value = (int) (long) HotSpotJVMCIRuntime.runtime().getConfigStore().getConstants().get(name);
+    }
+
+    public static MarkId getEnum(int value) {
+        for (MarkId e : values()) {
+            if (e.value == value) {
+                return e;
+            }
+        }
+        throw new InternalError("Unknown enum value: " + value);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MarkProcessor.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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 jdk.tools.jaotc.binformat.Relocation.RelocType;
+import jdk.tools.jaotc.binformat.Symbol;
+
+import jdk.vm.ci.code.site.Mark;
+
+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
+     */
+    void process(CompiledMethodInfo methodInfo, Mark mark) {
+        MarkId markId = MarkId.getEnum((int) mark.id);
+        switch (markId) {
+            case EXCEPTION_HANDLER_ENTRY:
+            case DEOPT_HANDLER_ENTRY:
+                break;
+            case POLL_FAR:
+            case POLL_RETURN_FAR:
+            case CARD_TABLE_ADDRESS:
+            case HEAP_TOP_ADDRESS:
+            case HEAP_END_ADDRESS:
+            case NARROW_KLASS_BASE_ADDRESS:
+            case CRC_TABLE_ADDRESS:
+            case LOG_OF_HEAP_REGION_GRAIN_BYTES:
+            case INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED:
+                String vmSymbolName;
+                switch (markId) {
+                    case POLL_FAR:
+                    case POLL_RETURN_FAR:
+                        vmSymbolName = binaryContainer.getPollingPageSymbolName();
+                        break;
+                    case CARD_TABLE_ADDRESS:
+                        vmSymbolName = binaryContainer.getCardTableAddressSymbolName();
+                        break;
+                    case HEAP_TOP_ADDRESS:
+                        vmSymbolName = binaryContainer.getHeapTopAddressSymbolName();
+                        break;
+                    case HEAP_END_ADDRESS:
+                        vmSymbolName = binaryContainer.getHeapEndAddressSymbolName();
+                        break;
+                    case NARROW_KLASS_BASE_ADDRESS:
+                        vmSymbolName = binaryContainer.getNarrowKlassBaseAddressSymbolName();
+                        break;
+                    case CRC_TABLE_ADDRESS:
+                        vmSymbolName = binaryContainer.getCrcTableAddressSymbolName();
+                        break;
+                    case LOG_OF_HEAP_REGION_GRAIN_BYTES:
+                        vmSymbolName = binaryContainer.getLogOfHeapRegionGrainBytesSymbolName();
+                        break;
+                    case INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED:
+                        vmSymbolName = binaryContainer.getInlineContiguousAllocationSupportedSymbolName();
+                        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 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);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MetadataBuilder.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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 jdk.tools.jaotc.binformat.BinaryContainer;
+import jdk.tools.jaotc.binformat.ByteContainer;
+import jdk.tools.jaotc.binformat.Symbol.Binding;
+import jdk.tools.jaotc.binformat.Symbol.Kind;
+import jdk.tools.jaotc.binformat.GotSymbol;
+import jdk.tools.jaotc.AOTCompiledClass.AOTKlassData;
+import jdk.tools.jaotc.utils.NativeOrderOutputStream;
+import org.graalvm.compiler.code.CompilationResult;
+import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
+
+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;
+
+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) {
+        binaryContainer.getMethodMetadataContainer().createSymbol(0, Kind.OBJECT, Binding.LOCAL, 0, "metaStart");
+
+        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();
+
+            // 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 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(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 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(metaData.exceptionBytes()).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) {
+        String[] 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++) {
+            String name = metaDataEntries[index];
+            addMetadataEntry(binaryContainer, name);
+            // Create GOT cells for klasses referenced in metadata
+            String klassName = name;
+            int len = name.length();
+            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;
+                klassName = name.substring(0, dotIndex);
+            }
+            // We should already have added entries for this klass
+            assert AOTCompiledClass.getAOTKlassData(klassName) != null;
+            assert methodInfo.getDependentKlassData(klassName) != 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 (Mark mark : compilationResult.getMarks()) {
+                markProcessor.process(methodInfo, mark);
+            }
+
+            for (DataPatch dataPatch : compilationResult.getDataPatches()) {
+                dataPatchProcessor.process(methodInfo, dataPatch);
+            }
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MiscUtils.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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 jdk.vm.ci.code.BytecodePosition;
+import jdk.vm.ci.code.site.Call;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
+public class MiscUtils {
+
+    /**
+     * 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
+     **/
+    public static String uniqueMethodName(ResolvedJavaMethod method) {
+        String className = method.getDeclaringClass().toClassName();
+        String name = className + "." + method.getName() + method.getSignature().toMethodDescriptor();
+        return name;
+    }
+
+    public static boolean isStaticCall(Call call) {
+        if (isJavaCall(call)) {
+            return ((getByteCode(call) & 0xFF) == Bytecodes.INVOKESTATIC);
+        }
+        return false;
+    }
+
+    public 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;
+    }
+
+    public static boolean isVirtualCall(CompiledMethodInfo methodInfo, Call call) {
+        return isInvokeVirtual(call) && !methodInfo.hasMark(call, MarkId.INVOKESPECIAL);
+    }
+
+    public static boolean isOptVirtualCall(CompiledMethodInfo methodInfo, Call call) {
+        return isInvokeVirtual(call) && methodInfo.hasMark(call, MarkId.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];
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/StubDirectCallSiteRelocationSymbol.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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 {
+
+    public 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";
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/amd64/AMD64ELFMacroAssembler.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.CompiledMethodInfo.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;
+
+public final class AMD64ELFMacroAssembler extends AMD64MacroAssembler implements ELFMacroAssembler {
+
+    private int currentEndOfInstruction;
+
+    public AMD64ELFMacroAssembler(TargetDescription target) {
+        super(target);
+    }
+
+    @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);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/amd64/AMD64InstructionDecoder.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,565 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+        public static final int CSSegment = 0x2e;
+        public static final int SSSegment = 0x36;
+        public static final int DSSegment = 0x3e;
+        public static final int ESSegment = 0x26;
+        public static final int FSSegment = 0x64;
+        public static final int GSSegment = 0x65;
+        public static final int REX = 0x40;
+        public static final int REXB = 0x41;
+        public static final int REXX = 0x42;
+        public static final int REXXB = 0x43;
+        public static final int REXR = 0x44;
+        public static final int REXRB = 0x45;
+        public static final int REXRX = 0x46;
+        public static final int REXRXB = 0x47;
+        public static final int REXW = 0x48;
+        public static final int REXWB = 0x49;
+        public static final int REXWX = 0x4A;
+        public static final int REXWXB = 0x4B;
+        public static final int REXWR = 0x4C;
+        public static final int REXWRB = 0x4D;
+        public static final int REXWRX = 0x4E;
+        public static final int REXWRXB = 0x4F;
+        public static final int VEX_3BYTES = 0xC4;
+        public static final int VEX_2BYTES = 0xC5;
+    }
+
+    public static class VexPrefix {
+        public static final int VEX_R = 0x80;
+        public static final int VEX_W = 0x80;
+    }
+
+    public static class VexOpcode {
+        public static final int VEX_OPCODE_NONE = 0x0;
+        public static final int VEX_OPCODE_0F = 0x1;
+        public static final int VEX_OPCODE_0F_38 = 0x2;
+        public static final int VEX_OPCODE_0F_3A = 0x3;
+        public 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 vex_opcode;
+                    // First byte
+                    if ((code[pcOffset] & 0xFF) == Prefix.VEX_3BYTES) {
+                        vex_opcode = VexOpcode.VEX_OPCODE_MASK & code[ip];
+                        ip++; // third byte
+                        is64bit = ((VexPrefix.VEX_W & code[ip]) == VexPrefix.VEX_W);
+                    } else {
+                        vex_opcode = VexOpcode.VEX_OPCODE_0F;
+                    }
+                    ip++; // opcode
+                    // To find the end of instruction (which == end_pc_operand).
+                    switch (vex_opcode) {
+                        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:
+                                    ; // 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;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassCollector.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,332 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.LogPrinter;
+import jdk.tools.jaotc.Main;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.*;
+import java.nio.file.*;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.*;
+
+import static java.nio.file.FileVisitResult.CONTINUE;
+
+public class ClassCollector {
+    private final Main.Options options;
+    private final LogPrinter log;
+
+    public ClassCollector(Main.Options options, LogPrinter log) {
+        this.options = options;
+        this.log = log;
+    }
+
+    /**
+     * Collect all class names passed by the user.
+     *
+     * @return array list of classes
+     */
+    public Set<Class<?>> collectClassesToCompile() {
+        Set<Class<?>> classes = new HashSet<>();
+        List<String> filesToScan = new LinkedList<>(options.files);
+
+        if (options.module != null) {
+            classes.addAll(scanModule(filesToScan));
+        }
+
+        classes.addAll(scanFiles(filesToScan));
+        return classes;
+    }
+
+    private Set<Class<?>> scanModule(List<String> filesToScan) {
+        String module = options.module;
+        // Search module in standard JDK installation.
+        Path dir = getModuleDirectory(options.modulepath, module);
+
+        if (Files.isDirectory(dir)) {
+            return loadFromModuleDirectory(dir);
+        } else {
+            findFilesToScan(filesToScan, module);
+            return new HashSet<>();
+        }
+    }
+
+    private Set<Class<?>> loadFromModuleDirectory(Path dir) {
+        log.printInfo("Scanning module: " + dir + " ...");
+        log.printlnVerbose(" "); // Break line
+
+        FileSystemFinder finder = new FileSystemFinder(dir, pathname -> entryIsClassFile(pathname.toString()));
+        Set<Class<?>> cls = loadWithClassLoader(() -> ClassLoader.getSystemClassLoader(), dir, finder);
+        log.printlnInfo(" " + cls.size() + " classes loaded.");
+        return cls;
+    }
+
+    private void findFilesToScan(List<String> filesToScan, String module) {
+        // Try to search regular directory, .jar or .class files
+        Path path = Paths.get(options.modulepath, module);
+
+        if (Files.isDirectory(path)) {
+            filesToScan.add(".");
+            options.classpath = path.toString();
+        } else if (path.endsWith(".jar") || path.endsWith(".class")) {
+            filesToScan.add(path.toString());
+        } else {
+            path = Paths.get(options.modulepath, module + ".jar");
+            if (Files.exists(path)) {
+                filesToScan.add(path.toString());
+            } else {
+                path = Paths.get(options.modulepath, module + ".class");
+                if (Files.exists(path)) {
+                    filesToScan.add(path.toString());
+                } else {
+                    throw new InternalError("Expecting a .class, .jar or directory: " + path);
+                }
+            }
+        }
+    }
+
+    private boolean entryIsClassFile(String entry) {
+        return entry.endsWith(".class") && !entry.endsWith("module-info.class");
+    }
+
+    private Set<Class<?>> scanFiles(List<String> filesToScan) {
+        Set<Class<?>> classes = new HashSet<>();
+        for (String fileName : filesToScan) {
+            Set<Class<?>> loaded = scanFile(fileName);
+            log.printlnInfo(" " + loaded.size() + " classes loaded.");
+            classes.addAll(loaded);
+        }
+        return classes;
+    }
+
+    interface ClassLoaderFactory {
+        ClassLoader create() throws IOException;
+    }
+
+    private Set<Class<?>> loadWithClassLoader(ClassLoaderFactory factory, Path root, FileSystemFinder finder) {
+        ClassLoader loader = null;
+        try {
+            loader = factory.create();
+            return loadClassFiles(root, finder, loader);
+        } catch (IOException e) {
+            throw new InternalError(e);
+        } finally {
+            if (loader instanceof AutoCloseable) {
+                try {
+                    ((AutoCloseable) loader).close();
+                } catch (Exception e) {
+                    throw new InternalError(e);
+                }
+            }
+        }
+    }
+
+    private Set<Class<?>> scanFile(String fileName) {
+        log.printInfo("Scanning: " + fileName + " ...");
+        log.printlnVerbose(" "); // Break line
+
+        if (fileName.endsWith(".jar")) {
+            return loadFromJarFile(fileName);
+        } else if (fileName.endsWith(".class")) {
+            Set<Class<?>> classes = new HashSet<>();
+            loadFromClassFile(fileName, classes);
+            return classes;
+        } else {
+            return scanClassPath(fileName);
+        }
+    }
+
+    private Set<Class<?>> loadFromJarFile(String fileName) {
+        FileSystem fs = makeFileSystem(fileName);
+        FileSystemFinder finder = new FileSystemFinder(fs.getPath("/"), pathname -> entryIsClassFile(pathname.toString()));
+        return loadWithClassLoader(() -> URLClassLoader.newInstance(buildUrls(fileName)), fs.getPath("/"), finder);
+    }
+
+    private void loadFromClassFile(String fileName, Set<Class<?>> classes) {
+        Class<?> result;
+        File file = new File(options.classpath);
+        try (URLClassLoader loader = URLClassLoader.newInstance(buildUrls(file))) {
+            result = loadClassFile(loader, fileName);
+        } catch (IOException e) {
+            throw new InternalError(e);
+        }
+        Class<?> c = result;
+        addClass(classes, fileName, c);
+    }
+
+    private Set<Class<?>> scanClassPath(String fileName) {
+        Path classPath = Paths.get(options.classpath);
+        if (!Files.exists(classPath)) {
+            throw new InternalError("Path does not exist: " + classPath);
+        }
+        if (!Files.isDirectory(classPath)) {
+            throw new InternalError("Path must be a directory: " + classPath);
+        }
+
+        // Combine class path and file name and see what it is.
+        Path combinedPath = Paths.get(options.classpath + File.separator + fileName);
+        if (combinedPath.endsWith(".class")) {
+            throw new InternalError("unimplemented");
+        } else if (Files.isDirectory(combinedPath)) {
+            return scanDirectory(classPath, combinedPath);
+        } else {
+            throw new InternalError("Expecting a .class, .jar or directory: " + fileName);
+        }
+    }
+
+    private FileSystem makeFileSystem(String fileName) {
+        try {
+            return FileSystems.newFileSystem(makeJarFileURI(fileName), new HashMap<>());
+        } catch (IOException e) {
+            throw new InternalError(e);
+        }
+    }
+
+    private URI makeJarFileURI(String fileName) {
+        try {
+            return new URI("jar:file:" + Paths.get(fileName).toAbsolutePath() + "!/");
+        } catch (URISyntaxException e) {
+            throw new InternalError(e);
+        }
+    }
+
+    private PathMatcher combine(PathMatcher m1, PathMatcher m2) {
+        return path -> m1.matches(path) && m2.matches(path);
+    }
+
+    private Set<Class<?>> scanDirectory(Path classPath, Path combinedPath) {
+        String dir = options.classpath;
+
+        FileSystem fileSystem = FileSystems.getDefault();
+        PathMatcher matcher = fileSystem.getPathMatcher("glob:" + "*.class");
+        FileSystemFinder finder = new FileSystemFinder(combinedPath,
+            combine(matcher, pathname -> entryIsClassFile(pathname.toString())));
+
+        File file = new File(dir);
+        try (URLClassLoader loader = URLClassLoader.newInstance(buildUrls(file))) {
+            return loadClassFiles(classPath, finder, loader);
+        } catch (IOException e) {
+            throw new InternalError(e);
+        }
+    }
+
+    private Set<Class<?>> loadClassFiles(Path root, FileSystemFinder finder, ClassLoader loader) {
+        Set<Class<?>> classes = new HashSet<>();
+        for (Path name : finder.done()) {
+            // Now relativize to the class path so we get the actual class names.
+            String entry = root.relativize(name).normalize().toString();
+            Class<?> c = loadClassFile(loader, entry);
+            addClass(classes, entry, c);
+        }
+        return classes;
+    }
+
+    private void addClass(Set<Class<?>> classes, String name, Class<?> c) {
+        if (c != null) {
+            classes.add(c);
+            log.printlnVerbose(" loaded " + name);
+        }
+    }
+
+    private URL[] buildUrls(String fileName) throws MalformedURLException {
+        return new URL[]{ new URL("jar:file:" + Paths.get(fileName).toAbsolutePath() + "!/") };
+    }
+
+    private URL[] buildUrls(File file) throws MalformedURLException {
+        return new URL[] {file.toURI().toURL() };
+    }
+
+    private Path getModuleDirectory(String modulepath, String module) {
+        FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
+        return fs.getPath(modulepath, module);
+    }
+
+    /**
+     * Loads a class with the given file name from the specified {@link URLClassLoader}.
+     */
+    private Class<?> loadClassFile(final ClassLoader loader, final String fileName) {
+        int start = 0;
+        if (fileName.startsWith("/")) {
+            start = 1;
+        }
+        String className = fileName.substring(start, fileName.length() - ".class".length());
+        className = className.replace('/', '.');
+        try {
+            return loader.loadClass(className);
+        } catch (Throwable e) {
+            // If we are running in JCK mode we ignore all exceptions.
+            if (options.ignoreClassLoadingErrors) {
+                log.printError(className + ": " + e);
+                return null;
+            }
+            throw new InternalError(e);
+        }
+    }
+
+    /**
+     * {@link FileVisitor} implementation to find class files recursively.
+     */
+    private static class FileSystemFinder extends SimpleFileVisitor<Path> {
+        private final ArrayList<Path> fileNames = new ArrayList<>();
+        private final PathMatcher filter;
+
+        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.
+         */
+        void find(Path file) {
+            Path name = file.getFileName();
+            if (name != null && filter.matches(name)) {
+                fileNames.add(file);
+            }
+        }
+
+        List<Path> done() {
+            return fileNames;
+        }
+
+        @Override
+        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
+            find(file);
+            return CONTINUE;
+        }
+
+        @Override
+        public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
+            find(dir);
+            return CONTINUE;
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/utils/NativeOrderOutputStream.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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 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);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/utils/Timer.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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 jdk.tools.jaotc.Main;
+
+public class Timer implements AutoCloseable {
+
+    private final Main main;
+    private final long start;
+
+    public Timer(Main main, String message) {
+        this.main = main;
+        start = System.currentTimeMillis();
+        main.printInfo(message);
+    }
+
+    public void close() {
+        final long end = System.currentTimeMillis();
+        main.printlnInfo(" (" + (end - start) + " ms)");
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/module-info.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.
+ */
+
+module jdk.aot {
+    requires jdk.management;
+    requires jdk.vm.ci;
+    requires jdk.vm.compiler;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/unix/native/libjelfshim/jdk_tools_jaotc_jnilibelf_JNILibELFAPI.c	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,522 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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 "jdk_tools_jaotc_jnilibelf_JNILibELFAPI.h"
+
+// For file open and close
+#include <fcntl.h>
+#include <unistd.h>
+#include <err.h>
+#include <sysexits.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <assert.h>
+
+// For libelf interfaces
+#include <libelf.h>
+#include <gelf.h>
+
+// Convenience macro to shut the compiler warnings
+#ifdef UNUSED
+#elif defined(__GNUC__)
+# define UNUSED(x) UNUSED_ ## x __attribute__((unused))
+#elif defined(__LCLINT__)
+# define UNUSED(x) /*@unused@*/ x
+#else
+# define UNUSED(x) x
+#endif
+
+/**
+ * libelfshim version
+ */
+#ifndef AOT_VERSION_STRING
+  #error AOT_VERSION_STRING must be defined
+#endif
+
+JNIEXPORT jstring JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elfshim_1version
+(JNIEnv* env, jclass UNUSED(c))  {
+   const char* ver = AOT_VERSION_STRING;
+   return (*env)->NewStringUTF(env, ver);
+}
+
+JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1version
+(JNIEnv* UNUSED(env), jclass UNUSED(c), jint v)  {
+    return elf_version(v);
+}
+
+/**
+ * Unbox the Pointer object the encapsulated native address.
+ */
+
+static jlong getNativeAddress(JNIEnv* env, jobject ptrObj) {
+   jclass ptrClass;
+   jfieldID fidNumber;
+   jlong nativeAddress = -1;
+    assert (ptrObj != NULL);
+   // Get a reference to ptr object's class
+   ptrClass = (*env)->GetObjectClass(env, ptrObj);
+
+   // Get the Field ID of the instance variables "address"
+   fidNumber = (*env)->GetFieldID(env, ptrClass, "address", "J");
+   if (fidNumber != NULL) {
+       // Get the long given the Field ID
+       nativeAddress = (*env)->GetLongField(env, ptrObj, fidNumber);
+   }
+   // fprintf(stderr, "Native address : %lx\n", nativeAddress);
+   return nativeAddress;
+}
+
+/**
+ * Box the nativeAddress as a Pointer object.
+ */
+static jobject makePointerObject(JNIEnv* env, jlong nativeAddr) {
+   jclass ptrClass = (*env)->FindClass(env, "jdk/tools/jaotc/jnilibelf/Pointer");
+   // Call back constructor to allocate a Pointer object, with an int argument
+   jmethodID constructorId = (*env)->GetMethodID(env, ptrClass, "<init>", "(J)V");
+   jobject retObj = (*env)->NewObject(env, ptrClass, constructorId, nativeAddr);
+   return retObj;
+}
+
+JNIEXPORT jobject JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1begin
+(JNIEnv* env, jclass UNUSED(class), jint filedes, jint cmd, jobject ptrObj) {
+
+   Elf* elfPtr = NULL;
+   jlong addr = getNativeAddress(env, ptrObj);
+
+   if (addr != -1) {
+       // Call libelf function
+       if ((elfPtr = elf_begin(filedes, cmd, (Elf *) addr)) == NULL) {
+           errx(EX_SOFTWARE, "elf_begin() failed: %s.", elf_errmsg(-1));
+       }
+   } else {
+       fprintf(stderr, "Failed to get native address to call elf_begin()\n");
+   }
+
+   return makePointerObject(env, (jlong) elfPtr);
+}
+
+JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1end
+(JNIEnv* env, jclass UNUSED(class), jobject ptrObj) {
+
+   jlong addr = getNativeAddress(env, ptrObj);
+
+   if (addr != -1) {
+       // Call libelf function
+       return elf_end((Elf *) addr);
+   } else {
+       fprintf(stderr, "Failed to get native address to call elf_end()\n");
+       return -1;
+   }
+}
+
+JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1kind
+(JNIEnv* env, jclass UNUSED(c), jobject ptrObj) {
+   jlong addr = getNativeAddress(env, ptrObj);
+
+   if (addr != -1) {
+       // Call libelf function
+       return elf_kind((Elf *) addr);
+   } else {
+       fprintf(stderr, "Failed to get native address to call elf_kind()\n");
+       return -1;
+   }
+}
+JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1flagphdr
+(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint cmd, jint flags) {
+
+   jlong addr = getNativeAddress(env, ptrObj);
+   unsigned int retVal = 0;
+
+   if (addr != -1) {
+       // Call libelf function
+       if ((retVal = elf_flagphdr((Elf *) addr, cmd, flags)) == 0) {
+           errx(EX_SOFTWARE, "elf_flagphdr() failed: %s.", elf_errmsg(-1));
+       }
+   } else {
+       fprintf(stderr, "Failed to get native address to call elf_flagphdr()\n");
+   }
+   return retVal;
+}
+
+JNIEXPORT jobject JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1newscn
+(JNIEnv* env, jclass UNUSED(c), jobject ptrObj) {
+
+   Elf_Scn* elfSecPtr = NULL;
+   jlong addr = getNativeAddress(env, ptrObj);
+
+   if (addr != -1) {
+       // Call libelf function
+       if ((elfSecPtr = elf_newscn((Elf *) addr)) == NULL) {
+           errx(EX_SOFTWARE, "elf_newscn() failed: %s.", elf_errmsg(-1));
+       }
+   } else {
+       fprintf(stderr, "Failed to get native address to call elf_newscn()\n");
+   }
+
+   return makePointerObject(env, (jlong) elfSecPtr);
+}
+
+JNIEXPORT jobject JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1newdata
+(JNIEnv* env, jclass UNUSED(c), jobject ptrObj) {
+
+   Elf_Data* elfDataPtr = NULL;
+   jlong addr = getNativeAddress(env, ptrObj);
+
+   if (addr != -1) {
+       // Call libelf function
+       if ((elfDataPtr = elf_newdata((Elf_Scn *) addr)) == NULL) {
+           errx(EX_SOFTWARE, "elf_newdata() failed: %s.", elf_errmsg(-1));
+       }
+   } else {
+       fprintf(stderr, "Failed to get native address to call elf_newdata()\n");
+   }
+   return makePointerObject(env, (jlong) elfDataPtr);
+}
+
+JNIEXPORT jobject JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf64_1getshdr
+(JNIEnv* env, jclass UNUSED(c), jobject ptrObj) {
+
+   Elf64_Shdr* elf64ShdrPtr = NULL;
+   jlong addr = getNativeAddress(env, ptrObj);
+
+   if (addr != -1) {
+       // Call libelf function
+       if ((elf64ShdrPtr = elf64_getshdr((Elf_Scn *) addr)) == NULL) {
+           errx(EX_SOFTWARE, "elf64_getshdr() failed: %s.", elf_errmsg(-1));
+       }
+   } else {
+       fprintf(stderr, "Failed to get native address to call elf_getshdr()\n");
+   }
+   return makePointerObject(env, (jlong) elf64ShdrPtr);
+}
+
+JNIEXPORT jlong JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1update
+(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint cmd) {
+
+   off_t size = -1;
+   jlong addr = getNativeAddress(env, ptrObj);
+
+   if (addr != -1) {
+       // Call libelf function
+       if ((size = elf_update((Elf*) addr, cmd)) == -1) {
+           errx(EX_SOFTWARE, "elf_update() failed: %s size (%d) cmd (%d).", elf_errmsg(-1), (int)size, cmd);
+       }
+   } else {
+       fprintf(stderr, "Failed to get native address to call elf_update()\n");
+   }
+   return size;
+}
+
+JNIEXPORT jstring JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1errmsg
+(JNIEnv* env, jclass UNUSED(c), jint errno) {
+
+   const char * retPtr = NULL;
+   // Call libelf function
+   if ((retPtr = elf_errmsg(errno)) == NULL) {
+       errx(EX_SOFTWARE, "elf_errmsg() failed: %s.", elf_errmsg(-1));
+   }
+   return (*env)->NewStringUTF(env, retPtr);
+}
+
+JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1ndxscn
+(JNIEnv* env, jclass UNUSED(c), jobject ptrObj) {
+   jint secnum = SHN_UNDEF;
+   jlong addr = getNativeAddress(env, ptrObj);
+   if (addr != -1) {
+       // Call libelf function
+       secnum = elf_ndxscn((Elf_Scn*) addr);
+   } else {
+       fprintf(stderr, "Failed to get native address to call elf_ndxscn()\n");
+   }
+   return secnum;
+}
+
+JNIEXPORT jobject JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_gelf_1newehdr
+(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint elfClass) {
+   unsigned long int retPtr = 0;
+   jlong addr = getNativeAddress(env, ptrObj);
+   if (addr != -1) {
+       // Call libelf function
+       if ((retPtr = gelf_newehdr((Elf*) addr, elfClass)) == 0) {
+           errx(EX_SOFTWARE, "gelf_newehdr() failed: %s.", elf_errmsg(-1));
+       }
+   } else {
+       fprintf(stderr, "Failed to get native address to call elf_newehdr()\n");
+   }
+   return makePointerObject(env, (jlong) retPtr);
+}
+
+JNIEXPORT jobject JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_gelf_1newphdr
+(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint phnum) {
+   unsigned long int retPtr = 0;
+   jlong addr = getNativeAddress(env, ptrObj);
+   if (addr != -1) {
+       // Call libelf function
+       if ((retPtr = gelf_newphdr((Elf*) addr, phnum)) == 0) {
+           errx(EX_SOFTWARE, "gelf_newphdr() failed: %s.", elf_errmsg(-1));
+       }
+   } else {
+       fprintf(stderr, "Failed to get native address to call elf_newphdr()\n");
+   }
+   return makePointerObject(env, (jlong) retPtr);
+}
+
+
+/* File operations */
+
+JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_open_1rw
+(JNIEnv * env, jclass UNUSED(class), jstring jfileName)  {
+    int flags = O_RDWR | O_CREAT | O_TRUNC;
+    int mode  = 0666;
+    int retVal;
+    const char* cfileName = (*env)->GetStringUTFChars(env, jfileName, NULL);
+    if (cfileName == NULL) {
+        return -1;
+    }
+    retVal = open(cfileName, flags, mode);
+    if (retVal < 0) {
+       err(EX_NOINPUT, "open %s failed", cfileName);
+    }
+    (*env)->ReleaseStringUTFChars(env, jfileName, cfileName);
+
+    return retVal;
+}
+
+JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_open__Ljava_lang_String_2I
+(JNIEnv * env, jclass UNUSED(class), jstring jfileName, jint flags)  {
+    int retVal;
+    const char* cfileName = (*env)->GetStringUTFChars(env, jfileName, NULL);
+    if (cfileName == NULL) {
+        return -1;
+    }
+    retVal = open(cfileName, flags);
+    if (retVal < 0) {
+       err(EX_NOINPUT, "open %s failed", cfileName);
+    }
+    (*env)->ReleaseStringUTFChars(env, jfileName, cfileName);
+
+    return retVal;
+}
+
+JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_open__Ljava_lang_String_2II
+(JNIEnv * env, jclass UNUSED(class), jstring jfileName, jint flags, jint mode)  {
+    int retVal;
+    const char* cfileName = (*env)->GetStringUTFChars(env, jfileName, NULL);
+    if (cfileName == NULL) {
+        return -1;
+    }
+    retVal = open(cfileName, flags, mode);
+    if (retVal < 0) {
+       err(EX_NOINPUT, "open %s failed", cfileName);
+    }
+    (*env)->ReleaseStringUTFChars(env, jfileName, cfileName);
+
+    return retVal;
+}
+
+
+JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_close
+(JNIEnv* UNUSED(env), jclass UNUSED(class), jint fd) {
+    return close(fd);
+}
+
+/**
+ * Miscellaneous ELF data structure peek-poke functions in
+ * shim_functions.c. No corresponding .h file exists yet.
+ * So each function needs to be declared as extern
+ */
+
+extern int size_of_Sym(int elfclass);
+extern int size_of_Rel(int elfclass);
+extern int size_of_Rela(int elfclass);
+
+extern void ehdr_set_data_encoding(void * ehdr, int val);
+extern void set_Ehdr_e_machine(int elfclass, void * structPtr, int val);
+extern void set_Ehdr_e_type(int elfclass, void * structPtr, int val);
+extern void set_Ehdr_e_version(int elfclass, void * structPtr, int val);
+extern void set_Ehdr_e_shstrndx(int elfclass, void * structPtr, int val);
+
+extern void phdr_set_type_self(int elfclass, void * ehdr, void * phdr);
+extern void phdr_set_type_self(int elfclass, void * ehdr, void * phdr);
+
+extern void set_Shdr_sh_name(int elfclass, void* structPtr, int val);
+extern void set_Shdr_sh_type(int elfclass, void* structPtr, int val);
+extern void set_Shdr_sh_flags(int elfclass, void* structPtr, int val);
+extern void set_Shdr_sh_entsize(int elfclass, void* structPtr, int val);
+extern void set_Shdr_sh_link(int elfclass, void* structPtr, int val);
+extern void set_Shdr_sh_info(int elfclass, void* structPtr, int val);
+
+extern void set_Data_d_align(void* structPtr, int val);
+extern void set_Data_d_off(void* structPtr, int val);
+extern void set_Data_d_buf(void* structPtr, void* val);
+extern void set_Data_d_type(void* structPtr, int val);
+extern void set_Data_d_size(void* structPtr, int val);
+extern void set_Data_d_version(void* structPtr, int val);
+
+extern void* create_sym_entry(int elfclass, int index, int type, int bind,
+                               int shndx, int size, int value);
+extern void * create_reloc_entry(int elfclass, int roffset, int symtabIdx,
+                                 int relocType, int raddend, int reloca);
+
+JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_size_1of_1Sym
+(JNIEnv* UNUSED(env), jclass UNUSED(c), jint elfClass) {
+    return size_of_Sym(elfClass);
+}
+
+JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_size_1of_1Rela
+(JNIEnv* UNUSED(env), jclass UNUSED(c), jint elfClass) {
+    return size_of_Rela(elfClass);
+}
+
+JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_size_1of_1Rel
+(JNIEnv* UNUSED(env), jclass UNUSED(c), jint elfClass) {
+    return size_of_Rel(elfClass);
+}
+
+JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_ehdr_1set_1data_1encoding
+(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint val) {
+    void* ehdr = (void*) getNativeAddress(env, ptrObj);
+    ehdr_set_data_encoding(ehdr, val);
+}
+
+JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Ehdr_1e_1machine
+(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) {
+    void* ehdr = (void*) getNativeAddress(env, ptrObj);
+    set_Ehdr_e_machine(elfClass, ehdr, val);
+}
+
+JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Ehdr_1e_1type
+(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) {
+    void* ehdr = (void*) getNativeAddress(env, ptrObj);
+    set_Ehdr_e_type(elfClass, ehdr, val);
+}
+
+JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Ehdr_1e_1version
+(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) {
+    void* ehdr = (void*) getNativeAddress(env, ptrObj);
+    set_Ehdr_e_version(elfClass, ehdr, val);
+}
+JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Ehdr_1e_1shstrndx
+(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) {
+    void* shdr = (void*) getNativeAddress(env, ptrObj);
+    set_Ehdr_e_shstrndx(elfClass, shdr, val);
+}
+
+JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_phdr_1set_1type_1self
+(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ehdrPtr, jobject phdrPtr) {
+    void* ehdr = (void*) getNativeAddress(env, ehdrPtr);
+    void* phdr = (void*) getNativeAddress(env, phdrPtr);
+    phdr_set_type_self(elfClass, ehdr, phdr);
+}
+
+JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Shdr_1sh_1name
+(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) {
+    void* shdr = (void*) getNativeAddress(env, ptrObj);
+    set_Shdr_sh_name(elfClass, shdr, val);
+}
+
+JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Shdr_1sh_1type
+(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) {
+    void* shdr = (void*) getNativeAddress(env, ptrObj);
+    set_Shdr_sh_type(elfClass, shdr, val);
+}
+
+JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Shdr_1sh_1flags
+(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) {
+    void* shdr = (void*) getNativeAddress(env, ptrObj);
+    set_Shdr_sh_flags(elfClass, shdr, val);
+}
+
+JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Shdr_1sh_1entsize
+(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) {
+    void* shdr = (void*) getNativeAddress(env, ptrObj);
+    set_Shdr_sh_entsize(elfClass, shdr, val);
+}
+
+JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Shdr_1sh_1info
+(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) {
+    void* shdr = (void*) getNativeAddress(env, ptrObj);
+    set_Shdr_sh_info(elfClass, shdr, val);
+}
+
+JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Shdr_1sh_1link
+(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) {
+    void* shdr = (void*) getNativeAddress(env, ptrObj);
+    set_Shdr_sh_link(elfClass, shdr, val);
+}
+
+JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Data_1d_1align
+(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint val) {
+    void* dptr = (void*) getNativeAddress(env, ptrObj);
+    set_Data_d_align(dptr, val);
+}
+
+
+JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Data_1d_1off
+(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint val) {
+    void* dptr = (void*) getNativeAddress(env, ptrObj);
+    set_Data_d_off(dptr, val);
+}
+
+JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Data_1d_1buf
+(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jobject bufPtr) {
+    void* dptr = (void*) getNativeAddress(env, ptrObj);
+    void* bptr = (void*) getNativeAddress(env, bufPtr);
+    set_Data_d_buf(dptr, bptr);
+}
+
+JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Data_1d_1type
+(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint val) {
+    void* dptr = (void*) getNativeAddress(env, ptrObj);
+    set_Data_d_type(dptr, val);
+}
+
+JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Data_1d_1size
+(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint val) {
+    void* dptr = (void*) getNativeAddress(env, ptrObj);
+    set_Data_d_size(dptr, val);
+}
+
+JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Data_1d_1version
+(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint val) {
+    void* dptr = (void*) getNativeAddress(env, ptrObj);
+    set_Data_d_version(dptr, val);
+}
+
+JNIEXPORT jlong JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_create_1sym_1entry
+(JNIEnv* UNUSED(env), jclass UNUSED(c), jint elfClass, jint index, jint type,
+ jint bind, jint shndx, jint size, jint value) {
+   void * retVal = create_sym_entry(elfClass, index, type, bind,
+                                    shndx, size, value);
+   return (jlong)retVal;
+}
+
+JNIEXPORT jlong JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_create_1reloc_1entry
+(JNIEnv* UNUSED(env), jclass UNUSED(c), jint elfClass, jint roffset,
+ jint symTabIdx, jint relocType, jint raddend, jint reloca) {
+   void * retVal = create_reloc_entry(elfClass, roffset, symTabIdx,
+                                      relocType, raddend, reloca);
+   return (jlong)retVal;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/unix/native/libjelfshim/shim_functions.c	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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 <libelf.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/**
+ * TODO: This is an intial and crude attempt to access structure
+ * fields of some ELF structrures. Need to figure out a way to access the
+ * given field of a given structure instead of writing one shim function
+ * per access of each of the structure field.
+ **/
+
+#define STRINGIFYHELPER(x) #x
+#define STRINGIFY(x) STRINGIFYHELPER(x)
+#define FUNC_NAME(S, F) set_ ## S ## _ ## F
+#define CAST_STRUCT(S, F) ((Elf_ ## S *) structPtr)
+#define CAST_STRUCT32(S, F) ((Elf32_ ## S *) structPtr)
+#define CAST_STRUCT64(S, F) ((Elf64_ ## S *) structPtr)
+#define ACCESS_FIELD(S, F) CAST_STRUCT(S, F)-> F
+#define ACCESS_FIELD32(S, F) CAST_STRUCT32(S, F)-> F
+#define ACCESS_FIELD64(S, F) CAST_STRUCT64(S, F)-> F
+
+/*
+   Example:
+   SET_TYPE_BASED_FIELD(Ehdr, e_machine, int)
+   expands to
+   set_Ehdr_e_machine(int elfclass, void * strPtr, int val) {
+}
+*/
+
+#define SET_TYPE_BASED_FIELD(S, F, T)                               \
+    void FUNC_NAME(S, F)(int elfclass, void * structPtr, T val) {   \
+       if (elfclass == ELFCLASS32)  {                               \
+           ACCESS_FIELD32(S, F) = val;                    \
+       } else if (elfclass == ELFCLASS64) {               \
+           ACCESS_FIELD64(S, F) = val;                    \
+       } else {                                           \
+           printf("%s: Unknown ELF Class %d provided\n", STRINGIFY(FUNC_NAME(S, F)), elfclass); \
+    }  \
+    return; \
+}
+
+/*
+   Example:
+   SET_FIELD(Ehdr, e_machine, int)
+   expands to
+   set_Ehdr_e_machine(void * strPtr, int val) {
+}
+*/
+
+#define SET_FIELD(S, F, T)                               \
+    void FUNC_NAME(S, F)(void * structPtr, T val) {      \
+       ACCESS_FIELD(S, F) = val;                         \
+       return; \
+}
+
+int size_of_Sym(int elfclass) {
+    if (elfclass == ELFCLASS32)  {
+        return sizeof(Elf32_Sym);
+    } else if (elfclass == ELFCLASS64) {
+        return sizeof(Elf64_Sym);
+    } else {
+        printf("Unknown ELF Class %d provided\n", elfclass);
+    }
+    return -1;
+}
+
+int size_of_Rela(int elfclass) {
+    if (elfclass == ELFCLASS32)  {
+        return sizeof(Elf32_Rela);
+    } else if (elfclass == ELFCLASS64) {
+        return sizeof(Elf64_Rela);
+    } else {
+        printf("Unknown ELF Class %d provided\n", elfclass);
+    }
+    return -1;
+}
+
+int size_of_Rel(int elfclass) {
+    if (elfclass == ELFCLASS32)  {
+        return sizeof(Elf32_Rel);
+    } else if (elfclass == ELFCLASS64) {
+        return sizeof(Elf64_Rel);
+    } else {
+        printf("Unknown ELF Class %d provided\n", elfclass);
+    }
+    return -1;
+}
+
+/* ELF Header field access */
+
+void ehdr_set_data_encoding(void * ehdr, int val)  {
+    ((Elf32_Ehdr *) ehdr)->e_ident[EI_DATA] = val;
+    return;
+}
+
+SET_TYPE_BASED_FIELD(Ehdr, e_machine, int)
+SET_TYPE_BASED_FIELD(Ehdr, e_type, int)
+SET_TYPE_BASED_FIELD(Ehdr, e_version, int)
+SET_TYPE_BASED_FIELD(Ehdr, e_shstrndx, int)
+
+/* Data descriptor field access */
+SET_FIELD(Data, d_align, int)
+SET_FIELD(Data, d_off, int)
+SET_FIELD(Data, d_buf, void*)
+SET_FIELD(Data, d_type, int)
+SET_FIELD(Data, d_size, int)
+SET_FIELD(Data, d_version, int)
+
+/* Section Header Access functions */
+SET_TYPE_BASED_FIELD(Shdr, sh_name, int)
+SET_TYPE_BASED_FIELD(Shdr, sh_type, int)
+SET_TYPE_BASED_FIELD(Shdr, sh_flags, int)
+SET_TYPE_BASED_FIELD(Shdr, sh_entsize, int)
+SET_TYPE_BASED_FIELD(Shdr, sh_link, int)
+SET_TYPE_BASED_FIELD(Shdr, sh_info, int)
+
+/* Set the Program Header to be of PH_PHDR type and initialize other
+   related fields of the program header.
+*/
+void phdr_set_type_self(int elfclass, void * ehdr, void * phdr)  {
+    if (elfclass == ELFCLASS32) {
+        Elf32_Ehdr * ehdr32 = (Elf32_Ehdr *) ehdr;
+        Elf32_Phdr * phdr32 = (Elf32_Phdr *) phdr;
+        phdr32->p_type = PT_PHDR;
+        phdr32->p_offset = ehdr32->e_phoff;
+        phdr32->p_filesz = elf32_fsize(ELF_T_PHDR, 1, EV_CURRENT);
+    } else if (elfclass == ELFCLASS64) {
+        Elf64_Ehdr * ehdr64 = (Elf64_Ehdr *) ehdr;
+        Elf64_Phdr * phdr64 = (Elf64_Phdr *) phdr;
+        phdr64->p_type = PT_PHDR;
+        phdr64->p_offset = ehdr64->e_phoff;
+        phdr64->p_filesz = elf64_fsize(ELF_T_PHDR, 1, EV_CURRENT);
+    } else {
+        printf("phdr_set_type_self: Unknown ELF Class %d provided\n", elfclass);
+    }
+    return;
+}
+
+/*
+  Create symbol table entry with given type and binding
+*/
+void * create_sym_entry(int elfclass, int index, int type, int bind,
+                        int shndx, int size, int value) {
+  void * symentry = NULL;
+    if (elfclass == ELFCLASS32) {
+      Elf32_Sym * sym32 = (Elf32_Sym *) malloc(sizeof(Elf32_Sym));
+      sym32->st_name = index;
+      sym32->st_value = value;
+      sym32->st_size = size;
+      sym32->st_info = ELF32_ST_INFO(bind, type);
+      sym32->st_other = 0;  // TODO: Add an argument to get this value ??
+      sym32->st_shndx = shndx;
+      symentry = sym32;
+    } else if (elfclass == ELFCLASS64) {
+      Elf64_Sym * sym64 = (Elf64_Sym *) malloc(sizeof(Elf64_Sym));
+      sym64->st_name = index;
+      sym64->st_value = value;
+      sym64->st_size = size;
+      sym64->st_info = ELF64_ST_INFO(bind, type);
+      sym64->st_other = 0;  // TODO: Add an argument to get this value ??
+      sym64->st_shndx = shndx;
+      symentry = sym64;
+    } else {
+        printf("create_sym_entry: Unknown ELF Class %d provided\n", elfclass);
+    }
+    return (void *) symentry;
+}
+
+// Create a reloc (or reloca entry if argument reloca is non-zero)
+void * create_reloc_entry(int elfclass, int roffset, int symtabIdx,
+                          int relocType, int raddend, int reloca) {
+  void * relocentry = NULL;
+  if (elfclass == ELFCLASS32) {
+    if (reloca) {
+      Elf32_Rela * rela32 = (Elf32_Rela *) malloc(sizeof(Elf32_Rela));
+      rela32->r_offset = roffset;
+      rela32->r_info = ELF32_R_INFO(symtabIdx, relocType);
+      rela32->r_addend = raddend;
+      relocentry = rela32;
+    } else {
+      Elf32_Rel * rel32 = (Elf32_Rel *) malloc(sizeof(Elf32_Rel));
+      rel32->r_offset = roffset;
+      rel32->r_info = ELF32_R_INFO(symtabIdx, relocType);
+      relocentry = rel32;
+    }
+  } else if (elfclass == ELFCLASS64) {
+    if (reloca) {
+      Elf64_Rela * rela64 = (Elf64_Rela *) malloc(sizeof(Elf64_Rela));
+      rela64->r_offset = roffset;
+      rela64->r_info = ELF64_R_INFO(symtabIdx, relocType);
+      rela64->r_addend = raddend;
+      relocentry = rela64;
+    } else {
+      Elf64_Rel * rel64 = (Elf64_Rel *) malloc(sizeof(Elf64_Rel));
+      rel64->r_offset = roffset;
+      rel64->r_info = ELF64_R_INFO(symtabIdx, relocType);
+      relocentry = rel64;
+    }
+  } else {
+    printf("create_reloc_entry: Unknown ELF Class %d provided\n", elfclass);
+  }
+  return (void *) relocentry;
+}
--- a/hotspot/src/jdk.hotspot.agent/linux/native/libsaproc/symtab.c	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/jdk.hotspot.agent/linux/native/libsaproc/symtab.c	Sun Dec 11 19:07:04 2016 -0800
@@ -387,8 +387,8 @@
 
     if (shdr->sh_type == sym_section) {
       ELF_SYM  *syms;
-      int j, n, rslt;
-      size_t size;
+      int rslt;
+      size_t size, n, j, htab_sz;
 
       // FIXME: there could be multiple data buffers associated with the
       // same ELF section. Here we can handle only one buffer. See man page
@@ -407,6 +407,15 @@
 
       // create hash table, we use hcreate_r, hsearch_r and hdestroy_r to
       // manipulate the hash table.
+
+      // NOTES section in the man page of hcreate_r says
+      // "Hash table implementations are usually more efficient when
+      // the table contains enough free space to minimize collisions.
+      // Typically, this means that nel should be at least 25% larger
+      // than the maximum number of elements that the caller expects
+      // to store in the table."
+      htab_sz = n*1.25;
+
       symtab->hash_table = (struct hsearch_data*) calloc(1, sizeof(struct hsearch_data));
       rslt = hcreate_r(n, symtab->hash_table);
       // guarantee(rslt, "unexpected failure: hcreate_r");
@@ -452,7 +461,6 @@
         symtab->symbols[j].offset = sym_value - baseaddr;
         item.key = sym_name;
         item.data = (void *)&(symtab->symbols[j]);
-
         hsearch_r(item, ENTER, &ret, symtab->hash_table);
       }
     }
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/Dictionary.java	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/Dictionary.java	Sun Dec 11 19:07:04 2016 -0800
@@ -102,4 +102,17 @@
     }
     return null;
   }
+
+  public boolean contains(Klass c, Oop classLoader) {
+    long hash = computeHash(c.getName(), classLoader);
+    int index = hashToIndex(hash);
+
+    for (DictionaryEntry entry = (DictionaryEntry) bucket(index); entry != null;
+                                    entry = (DictionaryEntry) entry.next()) {
+      if (entry.literalValue().equals(c.getAddress())) {
+        return true;
+      }
+    }
+    return false;
+  }
 }
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java	Sun Dec 11 19:07:04 2016 -0800
@@ -29,6 +29,7 @@
 import sun.jvm.hotspot.classfile.ClassLoaderData;
 import sun.jvm.hotspot.debugger.*;
 import sun.jvm.hotspot.memory.*;
+import sun.jvm.hotspot.memory.Dictionary;
 import sun.jvm.hotspot.runtime.*;
 import sun.jvm.hotspot.types.*;
 import sun.jvm.hotspot.utilities.*;
@@ -64,6 +65,21 @@
   private static int CLASS_STATE_FULLY_INITIALIZED;
   private static int CLASS_STATE_INITIALIZATION_ERROR;
 
+  // _misc_flags constants
+  private static int MISC_REWRITTEN;
+  private static int MISC_HAS_NONSTATIC_FIELDS;
+  private static int MISC_SHOULD_VERIFY_CLASS;
+  private static int MISC_IS_ANONYMOUS;
+  private static int MISC_IS_CONTENDED;
+  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;
+  private static int MISC_IS_SHARED_APP_CLASS;
+
   private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
     Type type            = db.lookupType("InstanceKlass");
     arrayKlasses         = new MetadataField(type.getAddressField("_array_klasses"), 0);
@@ -90,6 +106,7 @@
       breakpoints        = type.getAddressField("_breakpoints");
     }
     genericSignatureIndex = new CIntField(type.getCIntegerField("_generic_signature_index"), 0);
+    miscFlags            = new CIntField(type.getCIntegerField("_misc_flags"), 0);
     majorVersion         = new CIntField(type.getCIntegerField("_major_version"), 0);
     minorVersion         = new CIntField(type.getCIntegerField("_minor_version"), 0);
     headerSize           = type.getSize();
@@ -114,6 +131,19 @@
     CLASS_STATE_FULLY_INITIALIZED = db.lookupIntConstant("InstanceKlass::fully_initialized").intValue();
     CLASS_STATE_INITIALIZATION_ERROR = db.lookupIntConstant("InstanceKlass::initialization_error").intValue();
 
+    MISC_REWRITTEN                    = db.lookupIntConstant("InstanceKlass::_misc_rewritten").intValue();
+    MISC_HAS_NONSTATIC_FIELDS         = db.lookupIntConstant("InstanceKlass::_misc_has_nonstatic_fields").intValue();
+    MISC_SHOULD_VERIFY_CLASS          = db.lookupIntConstant("InstanceKlass::_misc_should_verify_class").intValue();
+    MISC_IS_ANONYMOUS                 = db.lookupIntConstant("InstanceKlass::_misc_is_anonymous").intValue();
+    MISC_IS_CONTENDED                 = db.lookupIntConstant("InstanceKlass::_misc_is_contended").intValue();
+    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();
+    MISC_IS_SHARED_APP_CLASS          = db.lookupIntConstant("InstanceKlass::_misc_is_shared_app_class").intValue();
   }
 
   public InstanceKlass(Address addr) {
@@ -149,6 +179,7 @@
   private static CIntField itableLen;
   private static AddressField breakpoints;
   private static CIntField genericSignatureIndex;
+  private static CIntField miscFlags;
   private static CIntField majorVersion;
   private static CIntField minorVersion;
 
@@ -243,7 +274,7 @@
     return getSizeHelper() * VM.getVM().getAddressSize();
   }
 
-  public long getSize() {
+  public long getSize() { // in number of bytes
     long wordLength = VM.getVM().getBytesPerWord();
     long size = getHeaderSize() +
                 (getVtableLen() +
@@ -252,9 +283,59 @@
     if (isInterface()) {
       size += wordLength;
     }
+    if (isAnonymous()) {
+      size += wordLength;
+    }
+    if (hasStoredFingerprint()) {
+      size += 8; // uint64_t
+    }
     return alignSize(size);
   }
 
+  private int getMiscFlags() {
+    return (int) miscFlags.getValue(this);
+  }
+
+  public boolean isAnonymous() {
+    return (getMiscFlags() & MISC_IS_ANONYMOUS) != 0;
+  }
+
+  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() {
+    return shouldStoreFingerprint() || isShared();
+  }
+
+  public boolean isShared() {
+    VM vm = VM.getVM();
+    if (vm.isSharingEnabled()) {
+      // This is not the same implementation as the C++ function MetaspaceObj::is_shared()
+      //     bool MetaspaceObj::is_shared() const {
+      //       return MetaspaceShared::is_in_shared_space(this);
+      //     }
+      // However, MetaspaceShared::is_in_shared_space is complicated and hard to emulate in
+      // Java code, so let's do this by looking up from the shared dictionary. Of course,
+      // this works for shared InstanceKlass only and does not work for other types of
+      // MetaspaceObj in the CDS shared archive.
+      Dictionary sharedDictionary = vm.getSystemDictionary().sharedDictionary();
+      if (sharedDictionary != null) {
+        if (sharedDictionary.contains(this, null)) {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
   public static long getHeaderSize() { return headerSize; }
 
   public short getFieldAccessFlags(int index) {
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java	Sun Dec 11 19:07:04 2016 -0800
@@ -861,6 +861,12 @@
       return (flag == null) ? false: flag.getBool();
   }
 
+  public boolean getCommandLineBooleanFlag(String name) {
+    Flag flag = getCommandLineFlag(name);
+    return (flag == null) ? Boolean.FALSE:
+      (flag.getBool()? Boolean.TRUE: Boolean.FALSE);
+  }
+
   // returns null, if not available.
   public Flag[] getCommandLineFlags() {
     if (commandLineFlags == null) {
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/DebugInfo.java	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/DebugInfo.java	Sun Dec 11 19:07:04 2016 -0800
@@ -40,7 +40,7 @@
 
     private final BytecodePosition bytecodePosition;
     private ReferenceMap referenceMap;
-    @SuppressWarnings("unused") private final VirtualObject[] virtualObjectMapping;
+    private final VirtualObject[] virtualObjectMapping;
     private RegisterSaveLayout calleeSaveInfo;
 
     /**
@@ -102,6 +102,10 @@
         return referenceMap;
     }
 
+    public VirtualObject[] getVirtualObjectMapping() {
+        return virtualObjectMapping;
+    }
+
     /**
      * Sets the map from the registers (in the caller's frame) to the slots where they are saved in
      * the current frame.
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java	Sun Dec 11 19:07:04 2016 -0800
@@ -333,7 +333,7 @@
      *         {@link HotSpotVMConfig#codeInstallResultDependenciesInvalid}.
      * @throws JVMCIError if there is something wrong with the compiled code or the metadata
      */
-    public native int getMetadata(TargetDescription target, HotSpotCompiledCode compiledCode, HotSpotMetaData metaData);
+    native int getMetadata(TargetDescription target, HotSpotCompiledCode compiledCode, HotSpotMetaData metaData);
 
     /**
      * Resets all compilation statistics.
@@ -605,6 +605,14 @@
     native int methodDataProfileDataSize(long metaspaceMethodData, int position);
 
     /**
+     * Gets the fingerprint for a given Klass*
+     *
+     * @param metaspaceKlass
+     * @return the value of the fingerprint (zero for arrays and synthetic classes).
+     */
+    native long getFingerprint(long metaspaceKlass);
+
+    /**
      * Return the amount of native stack required for the interpreter frames represented by
      * {@code frame}. This is used when emitting the stack banging code to ensure that there is
      * enough space for the frames during deoptimization.
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java	Sun Dec 11 19:07:04 2016 -0800
@@ -96,7 +96,8 @@
         TraceMethodDataFilter(String.class, null,
                         "Enables tracing of profiling info when read by JVMCI.",
                         "Empty value: trace all methods",
-                        "Non-empty value: trace methods whose fully qualified name contains the value.");
+                        "Non-empty value: trace methods whose fully qualified name contains the value."),
+        UseProfilingInformation(Boolean.class, true, "");
         // @formatter:on
 
         /**
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaData.java	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaData.java	Sun Dec 11 19:07:04 2016 -0800
@@ -22,38 +22,51 @@
  */
 package jdk.vm.ci.hotspot;
 
-/**
- * Encapsulates the VM metadata generated by {@link CompilerToVM#getMetadata}.
- */
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
+
+import jdk.vm.ci.code.TargetDescription;
+
 public class HotSpotMetaData {
-    @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "field is set by the native part") private byte[] pcDescBytes;
-    @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "field is set by the native part") private byte[] scopesDescBytes;
-    @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "field is set by the native part") private byte[] relocBytes;
-    @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "field is set by the native part") private byte[] exceptionBytes;
-    @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "field is set by the native part") private byte[] oopMaps;
-    @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "field is set by the native part") private String[] metadata;
+    private byte[] pcDescBytes;
+    private byte[] scopesDescBytes;
+    private byte[] relocBytes;
+    private byte[] exceptionBytes;
+    private byte[] oopMaps;
+    private String[] metadata;
+
+    public HotSpotMetaData(TargetDescription target, HotSpotCompiledCode compiledMethod) {
+        // Assign the fields default values...
+        pcDescBytes = new byte[0];
+        scopesDescBytes = new byte[0];
+        relocBytes = new byte[0];
+        exceptionBytes = new byte[0];
+        oopMaps = new byte[0];
+        metadata = new String[0];
+        // ...some of them will be overwritten by the VM:
+        runtime().getCompilerToVM().getMetadata(target, compiledMethod, this);
+    }
 
     public byte[] pcDescBytes() {
-        return pcDescBytes != null ? pcDescBytes : new byte[0];
+        return pcDescBytes;
     }
 
     public byte[] scopesDescBytes() {
-        return scopesDescBytes != null ? scopesDescBytes : new byte[0];
+        return scopesDescBytes;
     }
 
     public byte[] relocBytes() {
-        return relocBytes != null ? relocBytes : new byte[0];
+        return relocBytes;
     }
 
     public byte[] exceptionBytes() {
-        return exceptionBytes != null ? exceptionBytes : new byte[0];
+        return exceptionBytes;
     }
 
     public byte[] oopMaps() {
-        return oopMaps != null ? oopMaps : new byte[0];
+        return oopMaps;
     }
 
     public String[] metadataEntries() {
-        return metadata != null ? metadata : new String[0];
+        return metadata;
     }
 }
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java	Sun Dec 11 19:07:04 2016 -0800
@@ -430,7 +430,7 @@
     public ProfilingInfo getProfilingInfo(boolean includeNormal, boolean includeOSR) {
         ProfilingInfo info;
 
-        if (methodData == null) {
+        if (Option.UseProfilingInformation.getBoolean() && methodData == null) {
             long metaspaceMethodData = UNSAFE.getAddress(metaspaceMethod + config().methodDataOffset);
             if (metaspaceMethodData != 0) {
                 methodData = new HotSpotMethodData(metaspaceMethodData, this);
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java	Sun Dec 11 19:07:04 2016 -0800
@@ -103,6 +103,8 @@
 
     int layoutHelper();
 
+    long getFingerprint();
+
     HotSpotResolvedObjectType getEnclosingType();
 
     ResolvedJavaMethod getClassInitializer();
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java	Sun Dec 11 19:07:04 2016 -0800
@@ -478,6 +478,11 @@
         return UNSAFE.getInt(getMetaspaceKlass() + config.klassLayoutHelperOffset);
     }
 
+    @Override
+    public long getFingerprint() {
+        return compilerToVM().getFingerprint(getMetaspaceKlass());
+    }
+
     synchronized HotSpotResolvedJavaMethod createMethod(long metaspaceMethod) {
         HotSpotResolvedJavaMethodImpl method = null;
         if (methodCache == null) {
--- a/hotspot/src/jdk.vm.ci/share/classes/module-info.java	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/module-info.java	Sun Dec 11 19:07:04 2016 -0800
@@ -37,16 +37,20 @@
     exports jdk.vm.ci.aarch64 to
         jdk.vm.compiler;
     exports jdk.vm.ci.amd64 to
+        jdk.aot,
         jdk.vm.compiler;
     exports jdk.vm.ci.code to
+        jdk.aot,
         jdk.vm.compiler;
     exports jdk.vm.ci.code.site to
+        jdk.aot,
         jdk.vm.compiler;
     exports jdk.vm.ci.code.stack to
         jdk.vm.compiler;
     exports jdk.vm.ci.common to
         jdk.vm.compiler;
     exports jdk.vm.ci.hotspot to
+        jdk.aot,
         jdk.vm.compiler;
     exports jdk.vm.ci.hotspot.aarch64 to
         jdk.vm.compiler;
@@ -55,8 +59,10 @@
     exports jdk.vm.ci.hotspot.sparc to
         jdk.vm.compiler;
     exports jdk.vm.ci.meta to
+        jdk.aot,
         jdk.vm.compiler;
     exports jdk.vm.ci.runtime to
+        jdk.aot,
         jdk.vm.compiler;
     exports jdk.vm.ci.sparc to
         jdk.vm.compiler;
--- a/hotspot/src/jdk.vm.compiler/share/classes/module-info.java	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/jdk.vm.compiler/share/classes/module-info.java	Sun Dec 11 19:07:04 2016 -0800
@@ -41,4 +41,32 @@
     uses org.graalvm.compiler.hotspot.HotSpotBackendFactory;
     uses org.graalvm.compiler.nodes.graphbuilderconf.NodeIntrinsicPluginFactory;
 
+    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.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;
+    exports org.graalvm.compiler.core.target            to jdk.aot;
+    exports org.graalvm.compiler.debug                  to jdk.aot;
+    exports org.graalvm.compiler.debug.internal         to jdk.aot;
+    exports org.graalvm.compiler.graph                  to jdk.aot;
+    exports org.graalvm.compiler.hotspot                to jdk.aot;
+    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;
+    exports org.graalvm.compiler.phases                 to jdk.aot;
+    exports org.graalvm.compiler.phases.tiers           to jdk.aot;
+    exports org.graalvm.compiler.runtime                to jdk.aot;
+    exports org.graalvm.compiler.replacements           to jdk.aot;
+    exports org.graalvm.compiler.word                   to jdk.aot;
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/aot/aotCodeHeap.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,907 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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 "gc/g1/heapRegion.hpp"
+#include "gc/shared/gcLocker.hpp"
+#include "interpreter/abstractInterpreter.hpp"
+#include "jvmci/compilerRuntime.hpp"
+#include "jvmci/jvmciRuntime.hpp"
+#include "oops/method.hpp"
+#include "runtime/os.hpp"
+#include "runtime/sharedRuntime.hpp"
+#include "runtime/vm_operations.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) dlsym(_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*)_metaspace_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);
+    }
+    _metaspace_got[klass_data->_got_index] = k;
+  }
+  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] == 'L') {
+    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, thread);
+  assert(!thread->has_pending_exception(), "should not throw");
+
+  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 flags
+  verify_flag(_config->_useCompressedOops, UseCompressedOops, "UseCompressedOops");
+  verify_flag(_config->_useCompressedClassPointers, UseCompressedClassPointers, "UseCompressedClassPointers");
+  verify_flag(_config->_useG1GC, UseG1GC, "UseG1GC");
+  verify_flag(_config->_useCMSGC, UseConcMarkSweepGC, "UseConcMarkSweepGC");
+  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->_fieldsAllocationStyle, FieldsAllocationStyle, "FieldsAllocationStyle");
+  verify_flag(_config->_compactFields, CompactFields, "CompactFields");
+  verify_flag(_config->_enableContended, EnableContended, "EnableContended");
+  verify_flag(_config->_restrictContended, RestrictContended, "RestrictContended");
+
+  if (!TieredCompilation && _config->_tieredAOT) {
+    handle_config_error("Shared file %s error: Expected to run with tiered compilation on", _name);
+  }
+
+  // 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() {
+  free((void*) _name);
+}
+
+AOTCodeHeap::~AOTCodeHeap() {
+  if (_classes != NULL) {
+    FREE_C_HEAP_ARRAY(AOTClass, _classes);
+  }
+  if (_code_to_aot != NULL) {
+    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*) strdup(name);
+
+  // Verify that VM runs with the same parameters as AOT tool.
+  _config = (AOTConfiguration*) load_symbol("JVM.config");
+  _header = (AOTHeader*) load_symbol("JVM.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("JVM.metaspace.names");
+  _method_metadata =     (address) _lib->load_symbol("JVM.method.metadata");
+  _methods_offsets =     (address) _lib->load_symbol("JVM.methods.offsets");
+  _klasses_offsets =     (address) _lib->load_symbol("JVM.klasses.offsets");
+  _dependencies    =     (address) _lib->load_symbol("JVM.klasses.dependencies");
+  _code_space      =     (address) _lib->load_symbol("JVM.text");
+
+  // First cell is number of elements.
+  jlong* got_sect;
+  _metaspace_got      = (Metadata**) _lib->load_symbol("JVM.metaspace.got");
+  _metaspace_got_size = _lib->header()->_metaspace_got_size;
+
+  _metadata_got      = (Metadata**) _lib->load_symbol("JVM.metadata.got");
+  _metadata_got_size = _lib->header()->_metadata_got_size;
+
+  _oop_got      = (oop*) _lib->load_symbol("JVM.oop.got");
+  _oop_got_size = _lib->header()->_oop_got_size;
+
+  // Collect stubs info
+  _stubs_offsets = (int*) _lib->load_symbol("JVM.stubs.offsets");
+
+  // code segments table
+  _code_segments = (address) _lib->load_symbol("JVM.code.segments");
+
+  // method state
+  _method_state = (jlong*) _lib->load_symbol("JVM.method.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));
+
+  _low_boundary = _code_space;
+  _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.
+  if (CompilerOracle::should_exclude(mh) || !AbstractInterpreter::can_be_compiled(mh)) {
+    return;
+  }
+
+  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()) {
+    // 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.
+    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(in_use, (jint*)&_code_to_aot[code_id]._state, not_set) != not_set) {
+    _code_to_aot[code_id]._aot = NULL; // Clean
+  } else { // success
+    // Publish method
+#ifdef TIERED
+    mh->set_aot_code(aot);
+#endif
+    Method::set_code(mh, aot);
+    if (PrintAOT || (PrintCompilation && PrintAOT)) {
+      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_primitive_array_klasses() {
+  ResourceMark rm;
+  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);
+      AOTKlassData* klass_data = (AOTKlassData*) dlsym(_lib->dl_handle(), arr_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.
+        _metaspace_got[klass_data->_got_index-1] = (Metadata*)arr_klass; // Initialized
+        _metaspace_got[klass_data->_got_index  ] = (Metadata*)arr_klass; // Resolved
+        if (PrintAOT) {
+          tty->print_cr("[Found  %s  in  %s]", arr_klass->internal_name(), _lib->name());
+        }
+      }
+    }
+  }
+}
+
+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 = build_u2_from((address)stub_name);
+    stub_name += 2;
+    char* full_name = NEW_C_HEAP_ARRAY(char, len+5, mtCode);
+    if (full_name == NULL) { // No memory?
+      break;
+    }
+    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(in_use, (jint*)&_code_to_aot[code_id]._state, not_set) != 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) \
+  {                                                                   \
+    char* error;                                                      \
+    /* Clear any existing error */                                    \
+    dlerror();                                                        \
+    AOTSYMTYPE * adr = (AOTSYMTYPE *) dlsym(_lib->dl_handle(), AOTSYMNAME);  \
+    /* Check for any dlsym lookup error */                            \
+    error = dlerror();                                                \
+    guarantee(error == NULL, "%s", error);                            \
+    *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_array", address, JVMCIRuntime::dynamic_new_array);
+    SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_validate_object", address, JVMCIRuntime::validate_object);
+    SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_write_barrier_pre", address, JVMCIRuntime::write_barrier_pre);
+    SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_identity_hash_code", address, JVMCIRuntime::identity_hash_code);
+    SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_write_barrier_post", address, JVMCIRuntime::write_barrier_post);
+    SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_dynamic_new_instance", address, JVMCIRuntime::dynamic_new_instance);
+    SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_jvmci_runtime_thread_is_interrupted", address, JVMCIRuntime::thread_is_interrupted);
+    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_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_OSR_migration_end", address, SharedRuntime::OSR_migration_end);
+    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_checkcast_arraycopy", address, StubRoutines::_checkcast_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_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_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_throw_delayed_StackOverflowError_entry", address, StubRoutines::_throw_delayed_StackOverflowError_entry);
+
+}
+
+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();
+    CardTableModRefBS* ct = (CardTableModRefBS*)(heap->barrier_set());
+    SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_card_table_address", address, ct->byte_map_base);
+    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_polling_page", address, os::get_polling_page());
+    SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_narrow_klass_base_address", address, Universe::narrow_klass_base());
+    SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_log_of_heap_region_grain_bytes", int, HeapRegion::LogOfHRGrainBytes);
+    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 primitive array klasses.
+    link_primitive_array_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(KlassHandle klass, Thread* thread, const char* method_name) {
+  int method_name_len = build_u2_from((address)method_name);
+  method_name += 2;
+  const char* signature_name = method_name + method_name_len;
+  int signature_name_len = build_u2_from((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(InstanceKlass* ik) {
+  ResourceMark rm;
+  AOTKlassData* klass_data = (AOTKlassData*) dlsym(_lib->dl_handle(), 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::sweep_dependent_methods(AOTKlassData* klass_data) {
+  // Make dependent methods non_entrant forever.
+  int methods_offset = klass_data->_dependent_methods_offset;
+  if (methods_offset >= 0) {
+    int marked = 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];
+      // Invalidate aot code.
+      if (Atomic::cmpxchg(invalid, (jint*)&_code_to_aot[code_id]._state, not_set) != 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) {
+      VM_Deoptimize op;
+      VMThread::execute(&op);
+    }
+  }
+}
+
+bool AOTCodeHeap::load_klass_data(instanceKlassHandle kh, Thread* thread) {
+  ResourceMark rm;
+
+  NOT_PRODUCT( klasses_seen++; )
+
+  AOTKlassData* klass_data = find_klass(kh());
+  if (klass_data == NULL) {
+    return false;
+  }
+
+  if (!kh->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,
+                                   kh->internal_name(), kh->is_shared() ? " (shared)" : "",
+                                   _lib->name(), p2i(thread));
+    sweep_dependent_methods(klass_data);
+    return false;
+  }
+
+  if (kh->has_been_redefined()) {
+    log_trace(aot, class, load)("class  %s%s in %s  has been redefined tid=" INTPTR_FORMAT,
+                                   kh->internal_name(), kh->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];
+  if (aot_class->_classloader != NULL && aot_class->_classloader != kh->class_loader_data()) {
+    log_trace(aot, class, load)("class  %s  in  %s already loaded for classloader %p vs %p tid=" INTPTR_FORMAT,
+                             kh->internal_name(), _lib->name(), aot_class->_classloader, kh->class_loader_data(), p2i(thread));
+    NOT_PRODUCT( aot_klasses_cl_miss++; )
+    return false;
+  }
+
+  NOT_PRODUCT( aot_klasses_found++; )
+
+  log_trace(aot, class, load)("found  %s  in  %s for classloader %p tid=" INTPTR_FORMAT, kh->internal_name(), _lib->name(), kh->class_loader_data(), p2i(thread));
+
+  aot_class->_classloader = kh->class_loader_data();
+  // Set klass's Resolve (second) got cell.
+  _metaspace_got[klass_data->_got_index] = kh();
+
+  // Initialize global symbols of the DSO to the correspondingVM 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 = build_u2_from((address)aot_name);
+      const char* method_name = aot_name + 2 + klass_len;
+      Method* m = AOTCodeHeap::find_method(kh, 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);
+  }
+}
+
+// Yes, this is faster than going through the relocations,
+// but there are two problems:
+// 1) GOT slots are sometimes patched with non-Metadata values
+// 2) We don't want to scan metadata for dead methods
+// Unfortunately we don't know if the metadata belongs to
+// live aot methods or not, so process them all.  If this
+// is for mark_on_stack, some old methods may stick around
+// forever instead of getting cleaned up.
+void AOTCodeHeap::got_metadata_do(void f(Metadata*)) {
+  for (int i = 1; i < _metaspace_got_size; i++) {
+    Metadata** p = &_metaspace_got[i];
+    Metadata* md = *p;
+    if (md == NULL)  continue;  // skip non-oops
+    intptr_t meta = (intptr_t)md;
+    if (meta == -1)  continue;  // skip non-oops
+    if (Metaspace::contains(md)) {
+      f(md);
+    }
+  }
+  for (int i = 1; i < _metadata_got_size; i++) {
+    Metadata** p = &_metadata_got[i];
+    Metadata* md = *p;
+    intptr_t meta = (intptr_t)md;
+    if ((meta & 1) == 1) {
+      // already resolved
+      md = (Metadata*)(meta & ~1);
+    } else {
+      continue;
+    }
+    if (md == NULL)  continue;  // skip non-oops
+    if (Metaspace::contains(md)) {
+      f(md);
+    }
+  }
+}
+
+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();
+  }
+}
+
+#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::flush_evol_dependents_on(instanceKlassHandle dependee) {
+  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->flush_evol_dependents_on(dependee);
+  }
+}
+
+void AOTCodeHeap::metadata_do(void f(Metadata*)) {
+  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);
+    }
+  }
+#if 0
+  // With the marking above, this call doesn't seem to be needed
+  got_metadata_do(f);
+#endif
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/aot/aotCodeHeap.hpp	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,307 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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_VM_AOT_AOTCODEHEAP_HPP
+#define SHARE_VM_AOT_AOTCODEHEAP_HPP
+
+#include "aot/aotCompiledMethod.hpp"
+#include "classfile/symbolTable.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 _metaspace_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 = 11 + 7 * 4 };
+  int _config_size;
+  int _narrowOopShift;
+  int _narrowKlassShift;
+  int _contendedPaddingWidth;
+  int _fieldsAllocationStyle;
+  int _objectAlignment;
+  int _codeSegmentSize;
+  // byte[11] array map to boolean values here
+  bool _debug_VM;
+  bool _useCompressedOops;
+  bool _useCompressedClassPointers;
+  bool _compactFields;
+  bool _useG1GC;
+  bool _useCMSGC;
+  bool _useTLAB;
+  bool _useBiasedLocking;
+  bool _tieredAOT;
+  bool _enableContended;
+  bool _restrictContended;
+} 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** _metaspace_got;
+  Metadata** _metadata_got;
+  oop*    _oop_got;
+
+  int _metaspace_got_size;
+  int _metadata_got_size;
+  int _oop_got_size;
+
+  // Collect stubs info
+  int* _stubs_offsets;
+
+  address _low_boundary;
+
+  bool _lib_symbols_initialized;
+
+  void adjust_boundaries(AOTCompiledMethod* method) {
+    address low = _low_boundary;
+    if (method->code_begin() < low) {
+      low = method->code_begin();
+    }
+    address high = high_boundary();
+    if (method->code_end() > high) {
+      high = method->code_end();
+    }
+    assert(_method_count > 0, "methods count should be set already");
+
+    _low_boundary = low;
+    _memory.set_high_boundary((char *)high);
+    _memory.set_high((char *)high);
+  }
+
+  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_primitive_array_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();
+
+  address low_boundary()  const { return _low_boundary; }
+  address high_boundary() const { return (address)CodeHeap::high(); }
+
+  bool contains(const void* p) const {
+    bool result = (low_boundary() <= p) && (p < high_boundary());
+    assert(!result || (_method_count > 0), "");
+    assert(result == CodeHeap::contains(p), "");
+    return result;
+  }
+  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(instanceKlassHandle kh, Thread* thread);
+  Klass* get_klass_from_got(const char* klass_name, int klass_len, const Method* method);
+  void sweep_dependent_methods(AOTKlassData* klass_data);
+  bool is_dependent_method(Klass* dependee, AOTCompiledMethod* aot);
+
+  const char* get_name_at(int offset) {
+    return _metaspace_names + offset;
+  }
+
+  void oops_do(OopClosure* f);
+  void metadata_do(void f(Metadata*));
+  void got_metadata_do(void f(Metadata*));
+
+#ifdef ASSERT
+  bool got_contains(Metadata **p) {
+    return (p >= &_metadata_got[0] && p < &_metadata_got[_metadata_got_size]) ||
+           (p >= &_metaspace_got[0] && p < &_metaspace_got[_metaspace_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(KlassHandle klass, Thread* thread, const char* method_name);
+
+  void cleanup_inline_caches();
+
+  DEBUG_ONLY( int verify_icholder_relocations(); )
+
+  void flush_evol_dependents_on(instanceKlassHandle dependee);
+
+  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
+};
+
+#endif // SHARE_VM_AOT_AOTCODEHEAP_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/aot/aotCompiledMethod.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,453 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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/cardTableModRefBS.hpp"
+#include "gc/shared/collectedHeap.hpp"
+#include "gc/shared/gcLocker.hpp"
+#include "jvmci/compilerRuntime.hpp"
+#include "jvmci/jvmciRuntime.hpp"
+#include "oops/method.hpp"
+#include "runtime/java.hpp"
+#include "runtime/os.hpp"
+#include "runtime/sharedRuntime.hpp"
+#include "utilities/array.hpp"
+#include "utilities/xmlstream.hpp"
+
+#include <dlfcn.h>
+#include <stdio.h>
+
+#if 0
+static void metadata_oops_do(Metadata** metadata_begin, Metadata **metadata_end, OopClosure* f) {
+  // Visit the metadata/oops 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), "");
+    if (m->is_method()) {
+      m = ((Method*)m)->method_holder();
+    }
+    assert(m->is_klass(), "must be");
+    oop o = ((Klass*)m)->klass_holder();
+    if (o != NULL) {
+      f->do_oop(&o);
+    }
+  }
+}
+#endif
+
+void AOTCompiledMethod::oops_do(OopClosure* f) {
+  if (_oop != NULL) {
+    f->do_oop(&_oop);
+  }
+#if 0
+  metadata_oops_do(metadata_begin(), metadata_end(), f);
+#endif
+}
+
+bool AOTCompiledMethod::do_unloading_oops(address low_boundary, BoolObjectClosure* is_alive, bool unloading_occurred) {
+  return false;
+}
+
+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 = build_u2_from((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 = build_u2_from((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 = build_u2_from((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 = build_u2_from((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 = build_u2_from((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?
+        Thread* thread = Thread::current();
+        KlassHandle klass = KlassHandle(thread, k);
+        const char* method_name = klass_name + klass_len;
+        m = AOTCodeHeap::find_method(klass, thread, method_name);
+      }
+      meta = ((intptr_t)m) | 1;
+      *entry = (Metadata*)meta; // Should be atomic on x64
+      return (Metadata*)m;
+    }
+    // need to resolve it here..., patching of GOT need to be CAS or atomic operation.
+    // FIXIT: need methods for debuginfo.
+    // return _method;
+  }
+  ShouldNotReachHere(); return NULL;
+}
+
+bool AOTCompiledMethod::make_not_entrant_helper(int new_state) {
+  // Make sure the method is not flushed in case of a safepoint in code below.
+  methodHandle the_method(method());
+  NoSafepointVerifier nsv;
+
+  {
+    // Enter critical section.  Does not block for safepoint.
+    MutexLockerEx pl(Patching_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();
+
+#ifdef TIERED
+    // Remain non-entrant forever
+    if (new_state == not_entrant && method() != NULL) {
+        method()->set_aot_code(NULL);
+    }
+#endif
+
+    // Remove AOTCompiledMethod from method.
+    if (method() != NULL && (method()->code() == this ||
+                             method()->from_compiled_entry() == verified_entry_point())) {
+      HandleMark hm;
+      method()->clear_code(false /* already owns Patching_lock */);
+    }
+  } // leave critical region under Patching_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() {
+  assert(!method()->is_old(), "reviving evolved method!");
+  assert(*_state_adr != not_entrant, "%s", method()->has_aot_code() ? "has_aot_code() not cleared" : "caller didn't check has_aot_code()");
+
+  // Make sure the method is not flushed in case of a safepoint in code below.
+  methodHandle the_method(method());
+  NoSafepointVerifier nsv;
+
+  {
+    // Enter critical section.  Does not block for safepoint.
+    MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag);
+
+    if (*_state_adr == in_use) {
+      // 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 Patching_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;
+}
+
+// We don't have full dependencies for AOT methods, so flushing is
+// more conservative than for nmethods.
+void AOTCompiledMethod::flush_evol_dependents_on(instanceKlassHandle dependee) {
+  if (is_java_method()) {
+    cleanup_inline_caches();
+    mark_for_deoptimization();
+    make_not_entrant();
+  }
+}
+
+// Iterate over metadata calling this function.   Used by RedefineClasses
+// Copied from nmethod::metadata_do
+void AOTCompiledMethod::metadata_do(void f(Metadata*)) {
+  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(md);
+        }
+      } else if (iter.type() == relocInfo::virtual_call_type) {
+        // Check compiledIC holders associated with this nmethod
+        CompiledIC *ic = CompiledIC_at(&iter);
+        if (ic->is_icholder_call()) {
+          CompiledICHolder* cichk = ic->cached_icholder();
+          f(cichk->holder_method());
+          f(cichk->holder_klass());
+        } else {
+          Metadata* ic_oop = ic->cached_metadata();
+          if (ic_oop != NULL) {
+            f(ic_oop);
+          }
+        }
+      }
+    }
+  }
+
+  // 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(m);
+  }
+
+  // Visit metadata not embedded in the other places.
+  if (_method != NULL) f(_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) st->time_stamp().milliseconds());
+    st->print("%4d ", _aot_id);    // print compilation number
+    st->print("    aot[%2d]", _heap->dso_id());
+    // Stubs have _method == NULL
+    st->print("   %s", (_method == NULL ? _name : _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();
+}
+
+bool AOTCompiledMethod::is_evol_dependent_on(Klass* dependee) {
+  return !is_aot_runtime_stub() && _heap->is_dependent_method(dependee, this);
+}
+
+void AOTCompiledMethod::clear_inline_caches() {
+  assert(SafepointSynchronize::is_at_safepoint(), "cleaning of IC's only allowed at safepoint");
+  if (is_zombie()) {
+    return;
+  }
+
+  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();
+    }
+  }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/aot/aotCompiledMethod.hpp	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,326 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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_VM_AOT_AOTCOMPILEDMETHOD_HPP
+#define SHARE_VM_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 _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 _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(_oopmap_begin); }
+
+  address nul_chk_table_begin() const { return at_offset(_oopmap_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 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) { return (address*) ((address)fr->unextended_sp() + _meta->orig_pc_offset()); }
+  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),
+    _method_index(method_index),
+    _aot_id(aot_id) {
+
+    _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();
+    _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() < zombie; }
+
+  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; }
+
+  address exception_begin() { 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_evol_dependent_on(Klass* dependee);
+  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; }
+
+#ifdef HOTSWAP
+  // Flushing and deoptimization in case of evolution
+  void flush_evol_dependents_on(instanceKlassHandle dependee);
+#endif // HOTSWAP
+
+  virtual void metadata_do(void f(Metadata*));
+
+  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);
+  }
+
+  virtual void oops_do(OopClosure* f);
+
+  // inlined and non-virtual for AOTCodeHeap::oops_do
+  void do_oops(OopClosure* f) {
+    assert(_is_alive(), "");
+    if (_oop != NULL) {
+      f->do_oop(&_oop);
+    }
+#if 0
+    metadata_oops_do(metadata_begin(), metadata_end(), f);
+#endif
+  }
+
+
+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; }
+
+protected:
+  virtual bool do_unloading_oops(address low_boundary, BoolObjectClosure* is_alive, bool unloading_occurred);
+  virtual bool do_unloading_jvmci(BoolObjectClosure* is_alive, bool unloading_occurred) { return false; }
+
+};
+
+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_VM_AOT_AOTCOMPILEDMETHOD_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/aot/aotLoader.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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 "jvmci/jvmciRuntime.hpp"
+#include "oops/method.hpp"
+
+GrowableArray<AOTCodeHeap*>* AOTLoader::_heaps = new(ResourceObj::C_HEAP, mtCode) GrowableArray<AOTCodeHeap*> (2, true);
+GrowableArray<AOTLib*>* AOTLoader::_libraries = new(ResourceObj::C_HEAP, mtCode) GrowableArray<AOTLib*> (2, true);
+
+// 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(instanceKlassHandle kh, Thread* thread) {
+  if (UseAOT) {
+    FOR_ALL_AOT_HEAPS(heap) {
+      (*heap)->load_klass_data(kh, thread);
+    }
+  }
+}
+
+uint64_t AOTLoader::get_saved_fingerprint(InstanceKlass* ik) {
+  FOR_ALL_AOT_HEAPS(heap) {
+    AOTKlassData* klass_data = (*heap)->find_klass(ik);
+    if (klass_data != NULL) {
+      return klass_data->_fingerprint;
+    }
+  }
+  return 0;
+}
+
+bool AOTLoader::find_klass(InstanceKlass* ik) {
+  FOR_ALL_AOT_HEAPS(heap) {
+    if ((*heap)->find_klass(ik) != NULL) {
+      return true;
+    }
+  }
+  return false;
+}
+
+bool AOTLoader::contains(address p) {
+  FOR_ALL_AOT_HEAPS(heap) {
+    if ((*heap)->contains(p)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+void AOTLoader::oops_do(OopClosure* f) {
+  if (UseAOT) {
+    FOR_ALL_AOT_HEAPS(heap) {
+      (*heap)->oops_do(f);
+    }
+  }
+}
+
+void AOTLoader::metadata_do(void f(Metadata*)) {
+  if (UseAOT) {
+    FOR_ALL_AOT_HEAPS(heap) {
+      (*heap)->metadata_do(f);
+    }
+  }
+}
+
+address AOTLoader::exception_begin(JavaThread* thread, CodeBlob* blob, address return_address) {
+  assert(blob->is_aot(), "sanity");
+  AOTCompiledMethod* aotm = (AOTCompiledMethod*)blob;
+  // Set flag if return address is a method handle call site.
+  thread->set_is_method_handle_return(aotm->is_method_handle_return(return_address));
+  return aotm->exception_begin();
+}
+
+// Flushing and deoptimization in case of evolution
+void AOTLoader::flush_evol_dependents_on(instanceKlassHandle dependee) {
+  // make non entrant and mark for deoptimization
+  FOR_ALL_AOT_HEAPS(heap) {
+    (*heap)->flush_evol_dependents_on(dependee);
+  }
+  Deoptimization::deoptimize_dependents();
+}
+
+/**
+ * List of core modules for which we search for shared libraries.
+ */
+static const char* modules[] = {
+  "java.base",
+  "java.logging",
+  "jdk.compiler",
+  "jdk.scripting.nashorn",
+  "jdk.vm.ci",
+  "jdk.vm.compiler"
+};
+
+void AOTLoader::initialize() {
+  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) {
+      warning("EagerInitialization 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()) {
+      warning("-Xint is not compatible with AOT (switching AOT off)");
+      FLAG_SET_DEFAULT(UseAOT, false);
+      return;
+    }
+
+    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.so", home, file_separator, file_separator, modules[i], UseCompressedOops ? "-coop" : "", UseG1GC ? "" : "-nong1");
+      load_library(library, false);
+    }
+
+    // Scan the AOTLibrary option.
+    if (AOTLibrary != NULL) {
+      const int len = strlen(AOTLibrary);
+      char* cp  = NEW_C_HEAP_ARRAY(char, len+1, mtCode);
+      if (cp != NULL) { // No memory?
+        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) != ':' && (*cp) != ';')  cp++;
+          cp[0] = '\0';  // Terminate name
+          cp++;
+          load_library(name, true);
+        }
+      }
+    }
+  }
+}
+
+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.
+    // Set shifts value based on first AOT library config.
+    if (UseCompressedOops && AOTLib::narrow_oop_shift_initialized()) {
+      int oop_shift = Universe::narrow_oop_shift();
+      if (oop_shift == 0) {
+        Universe::set_narrow_oop_shift(AOTLib::narrow_oop_shift());
+      } else {
+        FOR_ALL_AOT_LIBRARIES(lib) {
+          (*lib)->verify_flag(AOTLib::narrow_oop_shift(), oop_shift, "Universe::narrow_oop_shift");
+        }
+      }
+      if (UseCompressedClassPointers) { // It is set only if UseCompressedOops is set
+        int klass_shift = Universe::narrow_klass_shift();
+        if (klass_shift == 0) {
+          Universe::set_narrow_klass_shift(AOTLib::narrow_klass_shift());
+        } else {
+          FOR_ALL_AOT_LIBRARIES(lib) {
+            (*lib)->verify_flag(AOTLib::narrow_klass_shift(), klass_shift, "Universe::narrow_klass_shift");
+          }
+        }
+      }
+    }
+    // Create heaps for all the libraries
+    FOR_ALL_AOT_LIBRARIES(lib) {
+      if ((*lib)->is_valid()) {
+        AOTCodeHeap* heap = new AOTCodeHeap(*lib);
+        {
+          MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+          add_heap(heap);
+          CodeCache::add_heap(heap);
+        }
+      }
+    }
+  }
+  if (heaps_count() == 0) {
+    if (FLAG_IS_DEFAULT(UseAOT)) {
+      FLAG_SET_DEFAULT(UseAOT, false);
+    }
+  }
+}
+
+void AOTLoader::set_narrow_klass_shift() {
+  // This method could be called from Metaspace::set_narrow_klass_base_and_shift().
+  // In case it is not called (during dump CDS, for example) the corresponding code in
+  // AOTLoader::universe_init(), which is called later, will set the shift value.
+  if (UseAOT && libraries_count() > 0 &&
+      UseCompressedOops && AOTLib::narrow_oop_shift_initialized() &&
+      UseCompressedClassPointers) {
+    int klass_shift = Universe::narrow_klass_shift();
+    if (klass_shift == 0) {
+      Universe::set_narrow_klass_shift(AOTLib::narrow_klass_shift());
+    } else {
+      FOR_ALL_AOT_LIBRARIES(lib) {
+        (*lib)->verify_flag(AOTLib::narrow_klass_shift(), klass_shift, "Universe::narrow_klass_shift");
+      }
+    }
+  }
+}
+
+void AOTLoader::load_library(const char* name, bool exit_on_error) {
+  void* handle = dlopen(name, RTLD_LAZY);
+  if (handle == NULL) {
+    if (exit_on_error) {
+      tty->print_cr("error opening file: %s", dlerror());
+      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;
+    dlclose(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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/aot/aotLoader.hpp	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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_VM_AOT_AOTLOADER_HPP
+#define SHARE_VM_AOT_AOTLOADER_HPP
+
+#include "runtime/globals_extension.hpp"
+#include "runtime/handles.hpp"
+
+class AOTCodeHeap;
+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(bool, UseAOT, false); });
+
+  static void universe_init() NOT_AOT_RETURN;
+  static void set_narrow_klass_shift() NOT_AOT_RETURN;
+  static bool contains(address p) NOT_AOT({ return false; });
+  static void load_for_klass(instanceKlassHandle, Thread* thread) NOT_AOT_RETURN;
+  static bool find_klass(InstanceKlass* ik) NOT_AOT({ return false; });
+  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(void f(Metadata*)) NOT_AOT_RETURN;
+  static address exception_begin(JavaThread* thread, CodeBlob* blob, address return_address) NOT_AOT({ return NULL; });
+
+  NOT_PRODUCT( static void print_statistics() NOT_AOT_RETURN; )
+
+#ifdef HOTSWAP
+  // Flushing and deoptimization in case of evolution
+  static void flush_evol_dependents_on(instanceKlassHandle dependee) NOT_AOT_RETURN;
+#endif // HOTSWAP
+
+};
+
+#endif // SHARE_VM_AOT_AOTLOADER_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/aot/aotLoader.inline.hpp	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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_VM_AOT_AOTLOADER_INLLINE_HPP
+#define SHARE_VM_AOT_AOTLOADER_INLLINE_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_VM_AOT_AOTLOADER_INLLINE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/aot/compiledIC_aot.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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"
+
+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();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/aot/compiledIC_aot.hpp	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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_VM_AOT_COMPILEDIC_AOT_HPP
+#define SHARE_VM_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_VM_AOT_COMPILEDIC_AOT_HPP
--- a/hotspot/src/share/vm/c1/c1_Compilation.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/c1/c1_Compilation.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -328,10 +328,9 @@
                                         locs_buffer_size / sizeof(relocInfo));
   code->initialize_consts_size(Compilation::desired_max_constant_size());
   // Call stubs + two deopt handlers (regular and MH) + exception handler
-  int call_stub_size = LIR_Assembler::call_stub_size;
-  int stub_size = (call_stub_estimate * call_stub_size) +
-                   LIR_Assembler::exception_handler_size +
-                   (2 * LIR_Assembler::deopt_handler_size);
+  int stub_size = (call_stub_estimate * LIR_Assembler::call_stub_size()) +
+                   LIR_Assembler::exception_handler_size() +
+                   (2 * LIR_Assembler::deopt_handler_size());
   if (stub_size >= code->insts_capacity()) return false;
   code->initialize_stubs_size(stub_size);
   return true;
--- a/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp	Sun Dec 11 19:07:04 2016 -0800
@@ -260,6 +260,21 @@
 
 #include CPU_HEADER(c1_LIRAssembler)
 
+  static int call_stub_size() {
+    if (UseAOT) {
+      return _call_stub_size + _call_aot_stub_size;
+    } else {
+      return _call_stub_size;
+    }
+  }
+
+  static int exception_handler_size() {
+    return _exception_handler_size;
+  }
+
+  static int deopt_handler_size() {
+    return _deopt_handler_size;
+  }
 };
 
 #endif // SHARE_VM_C1_C1_LIRASSEMBLER_HPP
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -22,11 +22,13 @@
  *
  */
 #include "precompiled.hpp"
+#include "aot/aotLoader.hpp"
 #include "classfile/classFileParser.hpp"
 #include "classfile/classFileStream.hpp"
 #include "classfile/classLoader.hpp"
 #include "classfile/classLoaderData.inline.hpp"
 #include "classfile/defaultMethods.hpp"
+#include "classfile/dictionary.hpp"
 #include "classfile/javaClasses.inline.hpp"
 #include "classfile/moduleEntry.hpp"
 #include "classfile/symbolTable.hpp"
@@ -5211,6 +5213,19 @@
 
   assert(_klass == ik, "invariant");
 
+  ik->set_has_passed_fingerprint_check(false);
+  if (UseAOT && ik->supers_have_passed_fingerprint_checks()) {
+    uint64_t aot_fp = AOTLoader::get_saved_fingerprint(ik);
+    if (aot_fp != 0 && aot_fp == _stream->compute_fingerprint()) {
+      // 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());
+    }
+  }
+
   return ik;
 }
 
--- a/hotspot/src/share/vm/classfile/classFileStream.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/classfile/classFileStream.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -24,6 +24,8 @@
 
 #include "precompiled.hpp"
 #include "classfile/classFileStream.hpp"
+#include "classfile/classLoader.hpp"
+#include "classfile/dictionary.hpp"
 #include "classfile/vmSymbols.hpp"
 #include "memory/resourceArea.hpp"
 
@@ -133,3 +135,12 @@
   }
   _current += length * 4;
 }
+
+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;
+}
--- a/hotspot/src/share/vm/classfile/classFileStream.hpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/classfile/classFileStream.hpp	Sun Dec 11 19:07:04 2016 -0800
@@ -150,6 +150,8 @@
 
   // Tells whether eos is reached
   bool at_eos() const { return _current == _buffer_end; }
+
+  uint64_t compute_fingerprint() const;
 };
 
 #endif // SHARE_VM_CLASSFILE_CLASSFILESTREAM_HPP
--- a/hotspot/src/share/vm/classfile/klassFactory.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/classfile/klassFactory.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -212,6 +212,10 @@
     result->set_cached_class_file(cached_class_file);
   }
 
+  if (InstanceKlass::should_store_fingerprint()) {
+    result->store_fingerprint(!result->is_anonymous() ? stream->compute_fingerprint() : 0);
+  }
+
   TRACE_KLASS_CREATION(result, parser, THREAD);
 
 #if INCLUDE_CDS && INCLUDE_JVMTI
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -23,6 +23,7 @@
  */
 
 #include "precompiled.hpp"
+#include "aot/aotLoader.hpp"
 #include "classfile/classFileParser.hpp"
 #include "classfile/classFileStream.hpp"
 #include "classfile/classLoader.hpp"
@@ -1151,13 +1152,21 @@
   Symbol* h_name = k->name();
   assert(class_name == NULL || class_name == h_name, "name mismatch");
 
+  bool define_succeeded = false;
   // Add class just loaded
   // If a class loader supports parallel classloading handle parallel define requests
   // find_or_define_instance_class may return a different InstanceKlass
   if (is_parallelCapable(class_loader)) {
-    k = find_or_define_instance_class(h_name, class_loader, k, CHECK_NULL);
+    instanceKlassHandle defined_k = find_or_define_instance_class(h_name, class_loader, k, CHECK_NULL);
+    if (k() == defined_k()) {
+      // we have won over other concurrent threads (if any) that are
+      // competing to define the same class.
+      define_succeeded = true;
+    }
+    k = defined_k;
   } else {
     define_instance_class(k, CHECK_NULL);
+    define_succeeded = true;
   }
 
   // Make sure we have an entry in the SystemDictionary on success
@@ -1401,6 +1410,19 @@
     // notify a class loaded from shared object
     ClassLoadingService::notify_class_loaded(ik(), true /* shared class */);
   }
+
+  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 {
+      ResourceMark rm;
+      log_info(class, fingerprint)("%s :  expected = " PTR64_FORMAT " actual = " PTR64_FORMAT, ik->external_name(), aot_fp, cds_fp);
+    }
+  }
   return ik;
 }
 #endif // INCLUDE_CDS
@@ -1487,7 +1509,9 @@
 
     // find_or_define_instance_class may return a different InstanceKlass
     if (!k.is_null()) {
-      k = find_or_define_instance_class(class_name, class_loader, k, CHECK_(nh));
+      instanceKlassHandle defined_k =
+        find_or_define_instance_class(class_name, class_loader, k, CHECK_(nh));
+      k = defined_k;
     }
     return k;
   } else {
--- a/hotspot/src/share/vm/code/codeBlob.hpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/code/codeBlob.hpp	Sun Dec 11 19:07:04 2016 -0800
@@ -41,7 +41,8 @@
     NonNMethod          = 2,    // Non-nmethods like Buffers, Adapters and Runtime Stubs
     All                 = 3,    // All types (No code cache segmentation)
     Pregenerated        = 4,    // Special blobs, managed by CodeCacheExtensions
-    NumTypes            = 5     // Number of CodeBlobTypes
+    AOT                 = 5,    // AOT methods
+    NumTypes            = 6     // Number of CodeBlobTypes
   };
 };
 
@@ -118,6 +119,7 @@
   virtual bool is_safepoint_stub() const              { return false; }
   virtual bool is_adapter_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; }
 
   inline bool is_compiled_by_c1() const    { return _type == compiler_c1; };
@@ -131,6 +133,7 @@
   nmethod* as_nmethod()                        { assert(is_nmethod(), "must be nmethod"); return (nmethod*) this; }
   CompiledMethod* as_compiled_method_or_null() { return is_compiled() ? (CompiledMethod*) this : NULL; }
   CompiledMethod* as_compiled_method()         { assert(is_compiled(), "must be compiled"); return (CompiledMethod*) this; }
+  CodeBlob* as_codeblob_or_null() const        { return (CodeBlob*) this; }
 
   // Boundaries
   address header_begin() const        { return (address) this; }
@@ -206,6 +209,7 @@
 
   // Transfer ownership of comments to this CodeBlob
   void set_strings(CodeStrings& strings) {
+    assert(!is_aot(), "invalid on aot");
     _strings.assign(strings);
   }
 
--- a/hotspot/src/share/vm/code/codeCache.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/code/codeCache.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -23,6 +23,7 @@
  */
 
 #include "precompiled.hpp"
+#include "aot/aotLoader.hpp"
 #include "code/codeBlob.hpp"
 #include "code/codeCache.hpp"
 #include "code/compiledIC.hpp"
@@ -128,6 +129,8 @@
 
 // Iterate over all CodeHeaps
 #define FOR_ALL_HEAPS(heap) for (GrowableArrayIterator<CodeHeap*> heap = _heaps->begin(); heap != _heaps->end(); ++heap)
+#define FOR_ALL_NMETHOD_HEAPS(heap) for (GrowableArrayIterator<CodeHeap*> heap = _nmethod_heaps->begin(); heap != _nmethod_heaps->end(); ++heap)
+
 // Iterate over all CodeBlobs (cb) on the given CodeHeap
 #define FOR_ALL_BLOBS(cb, heap) for (CodeBlob* cb = first_blob(heap); cb != NULL; cb = next_blob(heap, cb))
 
@@ -139,6 +142,8 @@
 
 // Initialize array of CodeHeaps
 GrowableArray<CodeHeap*>* CodeCache::_heaps = new(ResourceObj::C_HEAP, mtCode) GrowableArray<CodeHeap*> (CodeBlobType::All, true);
+GrowableArray<CodeHeap*>* CodeCache::_compiled_heaps = new(ResourceObj::C_HEAP, mtCode) GrowableArray<CodeHeap*> (CodeBlobType::All, true);
+GrowableArray<CodeHeap*>* CodeCache::_nmethod_heaps = new(ResourceObj::C_HEAP, mtCode) GrowableArray<CodeHeap*> (CodeBlobType::All, true);
 
 void CodeCache::check_heap_sizes(size_t non_nmethod_size, size_t profiled_size, size_t non_profiled_size, size_t cache_size, bool all_set) {
   size_t total_size = non_nmethod_size + profiled_size + non_profiled_size;
@@ -365,6 +370,28 @@
   return NULL;
 }
 
+int CodeCache::code_heap_compare(CodeHeap* const &lhs, CodeHeap* const &rhs) {
+  if (lhs->code_blob_type() == rhs->code_blob_type()) {
+    return (lhs > rhs) ? 1 : ((lhs < rhs) ? -1 : 0);
+  } else {
+    return lhs->code_blob_type() - rhs->code_blob_type();
+  }
+}
+
+void CodeCache::add_heap(CodeHeap* heap) {
+  assert(!Universe::is_fully_initialized(), "late heap addition?");
+
+  _heaps->insert_sorted<code_heap_compare>(heap);
+
+  int type = heap->code_blob_type();
+  if (code_blob_type_accepts_compiled(type)) {
+    _compiled_heaps->insert_sorted<code_heap_compare>(heap);
+  }
+  if (code_blob_type_accepts_nmethod(type)) {
+    _nmethod_heaps->insert_sorted<code_heap_compare>(heap);
+  }
+}
+
 void CodeCache::add_heap(ReservedSpace rs, const char* name, int code_blob_type) {
   // Check if heap is needed
   if (!heap_available(code_blob_type)) {
@@ -373,7 +400,7 @@
 
   // Create CodeHeap
   CodeHeap* heap = new CodeHeap(name, code_blob_type);
-  _heaps->append(heap);
+  add_heap(heap);
 
   // Reserve Space
   size_t size_initial = MIN2(InitialCodeCacheSize, rs.size());
@@ -389,7 +416,7 @@
 CodeHeap* CodeCache::get_code_heap(const CodeBlob* cb) {
   assert(cb != NULL, "CodeBlob is null");
   FOR_ALL_HEAPS(heap) {
-    if ((*heap)->contains(cb)) {
+    if ((*heap)->contains(cb->code_begin())) {
       return *heap;
     }
   }
@@ -426,10 +453,6 @@
   return (CodeBlob*)heap->next(cb);
 }
 
-CodeBlob* CodeCache::next_blob(CodeBlob* cb) {
-  return next_blob(get_code_heap(cb), cb);
-}
-
 /**
  * Do not seize the CodeCache lock here--if the caller has not
  * already done so, we are going to lose bigtime, since the code
@@ -494,7 +517,7 @@
     }
     if (PrintCodeCacheExtension) {
       ResourceMark rm;
-      if (_heaps->length() >= 1) {
+      if (_nmethod_heaps->length() >= 1) {
         tty->print("%s", heap->name());
       } else {
         tty->print("CodeCache");
@@ -559,6 +582,10 @@
   return false;
 }
 
+bool CodeCache::contains(nmethod *nm) {
+  return contains((void *)nm);
+}
+
 // This method is safe to call without holding the CodeCache_lock, as long as a dead CodeBlob is not
 // looked up (i.e., one that has been marked for deletion). It only depends on the _segmap to contain
 // valid indices, which it will always do, as long as the CodeBlob is not in the process of being recycled.
@@ -575,8 +602,8 @@
   // NMT can walk the stack before code cache is created
   if (_heaps != NULL && !_heaps->is_empty()) {
     FOR_ALL_HEAPS(heap) {
-      CodeBlob* result = (CodeBlob*) (*heap)->find_start(start);
-      if (result != NULL && result->blob_contains((address)start)) {
+      CodeBlob* result = (*heap)->find_blob_unsafe(start);
+      if (result != NULL) {
         return result;
       }
     }
@@ -592,7 +619,7 @@
 
 void CodeCache::blobs_do(void f(CodeBlob* nm)) {
   assert_locked_or_safepoint(CodeCache_lock);
-  FOR_ALL_HEAPS(heap) {
+  FOR_ALL_NMETHOD_HEAPS(heap) {
     FOR_ALL_BLOBS(cb, *heap) {
       f(cb);
     }
@@ -613,6 +640,7 @@
   while(iter.next_alive()) {
     iter.method()->metadata_do(f);
   }
+  AOTLoader::metadata_do(f);
 }
 
 int CodeCache::alignment_unit() {
@@ -634,11 +662,10 @@
 
 void CodeCache::blobs_do(CodeBlobClosure* f) {
   assert_locked_or_safepoint(CodeCache_lock);
-  FOR_ALL_HEAPS(heap) {
+  FOR_ALL_NMETHOD_HEAPS(heap) {
     FOR_ALL_BLOBS(cb, *heap) {
       if (cb->is_alive()) {
         f->do_code_blob(cb);
-
 #ifdef ASSERT
         if (cb->is_nmethod())
         ((nmethod*)cb)->verify_scavenge_root_oops();
@@ -835,13 +862,12 @@
   int count = 0;
   FOR_ALL_HEAPS(heap) {
     FOR_ALL_BLOBS(cb, *heap) {
-      if (cb->is_nmethod()) {
-        nmethod* nm = (nmethod*)cb;
+      CompiledMethod *nm = cb->as_compiled_method_or_null();
+      if (nm != NULL) {
         count += nm->verify_icholder_relocations();
       }
     }
   }
-
   assert(count + InlineCacheBuffer::pending_icholder_count() + CompiledICHolder::live_not_claimed_count() ==
          CompiledICHolder::live_count(), "must agree");
 #endif
@@ -902,7 +928,7 @@
 
 int CodeCache::nmethod_count() {
   int count = 0;
-  FOR_ALL_HEAPS(heap) {
+  FOR_ALL_NMETHOD_HEAPS(heap) {
     count += (*heap)->nmethod_count();
   }
   return count;
@@ -933,7 +959,7 @@
 
 size_t CodeCache::capacity() {
   size_t cap = 0;
-  FOR_ALL_HEAPS(heap) {
+  FOR_ALL_NMETHOD_HEAPS(heap) {
     cap += (*heap)->capacity();
   }
   return cap;
@@ -946,7 +972,7 @@
 
 size_t CodeCache::unallocated_capacity() {
   size_t unallocated_cap = 0;
-  FOR_ALL_HEAPS(heap) {
+  FOR_ALL_NMETHOD_HEAPS(heap) {
     unallocated_cap += (*heap)->unallocated_capacity();
   }
   return unallocated_cap;
@@ -954,7 +980,7 @@
 
 size_t CodeCache::max_capacity() {
   size_t max_cap = 0;
-  FOR_ALL_HEAPS(heap) {
+  FOR_ALL_NMETHOD_HEAPS(heap) {
     max_cap += (*heap)->max_capacity();
   }
   return max_cap;
@@ -980,7 +1006,7 @@
 
 size_t CodeCache::bytes_allocated_in_freelists() {
   size_t allocated_bytes = 0;
-  FOR_ALL_HEAPS(heap) {
+  FOR_ALL_NMETHOD_HEAPS(heap) {
     allocated_bytes += (*heap)->allocated_in_freelist();
   }
   return allocated_bytes;
@@ -988,7 +1014,7 @@
 
 int CodeCache::allocated_segments() {
   int number_of_segments = 0;
-  FOR_ALL_HEAPS(heap) {
+  FOR_ALL_NMETHOD_HEAPS(heap) {
     number_of_segments += (*heap)->allocated_segments();
   }
   return number_of_segments;
@@ -996,7 +1022,7 @@
 
 size_t CodeCache::freelists_length() {
   size_t length = 0;
-  FOR_ALL_HEAPS(heap) {
+  FOR_ALL_NMETHOD_HEAPS(heap) {
     length += (*heap)->freelist_length();
   }
   return length;
@@ -1039,6 +1065,8 @@
 
 void codeCache_init() {
   CodeCache::initialize();
+  // Load AOT libraries and add AOT code heaps.
+  AOTLoader::initialize();
 }
 
 //------------------------------------------------------------------------------------------------
@@ -1102,6 +1130,15 @@
   return (CompiledMethod*)cb;
 }
 
+bool CodeCache::is_far_target(address target) {
+#if INCLUDE_AOT
+  return NativeCall::is_far_call(_low_bound,  target) ||
+         NativeCall::is_far_call(_high_bound, target);
+#else
+  return false;
+#endif
+}
+
 #ifdef HOTSWAP
 int CodeCache::mark_for_evol_deoptimization(instanceKlassHandle dependee) {
   MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
@@ -1204,7 +1241,7 @@
 void CodeCache::flush_evol_dependents_on(instanceKlassHandle ev_k_h) {
   // --- Compile_lock is not held. However we are at a safepoint.
   assert_locked_or_safepoint(Compile_lock);
-  if (number_of_nmethods_with_dependencies() == 0) return;
+  if (number_of_nmethods_with_dependencies() == 0 && !UseAOT) return;
 
   // CodeCache can only be updated by a thread_in_VM and they will all be
   // stopped during the safepoint so CodeCache will be safe to update without
@@ -1316,7 +1353,7 @@
 
 void CodeCache::print_memory_overhead() {
   size_t wasted_bytes = 0;
-  FOR_ALL_HEAPS(heap) {
+  FOR_ALL_NMETHOD_HEAPS(heap) {
       CodeHeap* curr_heap = *heap;
       for (CodeBlob* cb = (CodeBlob*)curr_heap->first(); cb != NULL; cb = (CodeBlob*)curr_heap->next(cb)) {
         HeapBlock* heap_block = ((HeapBlock*)cb) - 1;
@@ -1362,8 +1399,8 @@
   ResourceMark rm;
 
   int i = 0;
-  FOR_ALL_HEAPS(heap) {
-    if ((_heaps->length() >= 1) && Verbose) {
+  FOR_ALL_NMETHOD_HEAPS(heap) {
+    if ((_nmethod_heaps->length() >= 1) && Verbose) {
       tty->print_cr("-- %s --", (*heap)->name());
     }
     FOR_ALL_BLOBS(cb, *heap) {
@@ -1459,7 +1496,7 @@
   CodeBlob_sizes live;
   CodeBlob_sizes dead;
 
-  FOR_ALL_HEAPS(heap) {
+  FOR_ALL_NMETHOD_HEAPS(heap) {
     FOR_ALL_BLOBS(cb, *heap) {
       if (!cb->is_alive()) {
         dead.add(cb);
@@ -1485,7 +1522,7 @@
     int number_of_blobs = 0;
     int number_of_oop_maps = 0;
     int map_size = 0;
-    FOR_ALL_HEAPS(heap) {
+    FOR_ALL_NMETHOD_HEAPS(heap) {
       FOR_ALL_BLOBS(cb, *heap) {
         if (cb->is_alive()) {
           number_of_blobs++;
@@ -1568,35 +1605,3 @@
             unallocated_capacity());
 }
 
-// Initialize iterator to given compiled method
-void CompiledMethodIterator::initialize(CompiledMethod* cm) {
-  _code_blob = (CodeBlob*)cm;
-  if (!SegmentedCodeCache) {
-    // Iterate over all CodeBlobs
-    _code_blob_type = CodeBlobType::All;
-  } else if (cm != NULL) {
-    _code_blob_type = CodeCache::get_code_blob_type(cm);
-  } else {
-    // Only iterate over method code heaps, starting with non-profiled
-    _code_blob_type = CodeBlobType::MethodNonProfiled;
-  }
-}
-
-// Advance iterator to the next compiled method in the current code heap
-bool CompiledMethodIterator::next_compiled_method() {
-  // Get first method CodeBlob
-  if (_code_blob == NULL) {
-    _code_blob = CodeCache::first_blob(_code_blob_type);
-    if (_code_blob == NULL) {
-      return false;
-    } else if (_code_blob->is_nmethod()) {
-      return true;
-    }
-  }
-  // Search for next method CodeBlob
-  _code_blob = CodeCache::next_blob(_code_blob);
-  while (_code_blob != NULL && !_code_blob->is_compiled()) {
-    _code_blob = CodeCache::next_blob(_code_blob);
-  }
-  return _code_blob != NULL;
-}
--- a/hotspot/src/share/vm/code/codeCache.hpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/code/codeCache.hpp	Sun Dec 11 19:07:04 2016 -0800
@@ -26,6 +26,7 @@
 #define SHARE_VM_CODE_CODECACHE_HPP
 
 #include "code/codeBlob.hpp"
+#include "code/codeCacheExtensions.hpp"
 #include "code/nmethod.hpp"
 #include "memory/allocation.hpp"
 #include "memory/heap.hpp"
@@ -77,13 +78,14 @@
 class CodeCache : AllStatic {
   friend class VMStructs;
   friend class JVMCIVMStructs;
-  friend class NMethodIterator;
-  friend class CompiledMethodIterator;
+  template <class T, class Filter> friend class CodeBlobIterator;
   friend class WhiteBox;
   friend class CodeCacheLoader;
  private:
   // CodeHeaps of the cache
   static GrowableArray<CodeHeap*>* _heaps;
+  static GrowableArray<CodeHeap*>* _compiled_heaps;
+  static GrowableArray<CodeHeap*>* _nmethod_heaps;
 
   static address _low_bound;                            // Lower bound of CodeHeap addresses
   static address _high_bound;                           // Upper bound of CodeHeap addresses
@@ -110,8 +112,7 @@
   // Iteration
   static CodeBlob* first_blob(CodeHeap* heap);                // Returns the first CodeBlob on the given CodeHeap
   static CodeBlob* first_blob(int code_blob_type);            // Returns the first CodeBlob of the given type
-  static CodeBlob* next_blob(CodeHeap* heap, CodeBlob* cb);   // Returns the first alive CodeBlob on the given CodeHeap
-  static CodeBlob* next_blob(CodeBlob* cb);                   // Returns the next CodeBlob of the given type succeeding the given CodeBlob
+  static CodeBlob* next_blob(CodeHeap* heap, CodeBlob* cb);   // Returns the next CodeBlob on the given CodeHeap
 
   static size_t bytes_allocated_in_freelists();
   static int    allocated_segments();
@@ -121,10 +122,20 @@
   static void prune_scavenge_root_nmethods();
   static void unlink_scavenge_root_nmethod(nmethod* nm, nmethod* prev);
 
+  // Make private to prevent unsafe calls.  Not all CodeBlob*'s are embedded in a CodeHeap.
+  static bool contains(CodeBlob *p) { fatal("don't call me!"); return false; }
+
  public:
   // Initialization
   static void initialize();
 
+  static int code_heap_compare(CodeHeap* const &lhs, CodeHeap* const &rhs);
+
+  static void add_heap(CodeHeap* heap);
+  static const GrowableArray<CodeHeap*>* heaps() { return _heaps; }
+  static const GrowableArray<CodeHeap*>* compiled_heaps() { return _compiled_heaps; }
+  static const GrowableArray<CodeHeap*>* nmethod_heaps() { return _nmethod_heaps; }
+
   // Allocation/administration
   static CodeBlob* allocate(int size, int code_blob_type, int orig_code_blob_type = CodeBlobType::All); // allocates a new CodeBlob
   static void commit(CodeBlob* cb);                        // called when the allocated CodeBlob has been filled
@@ -132,6 +143,7 @@
   static int  alignment_offset();                          // guaranteed offset of first CodeBlob byte within alignment unit (i.e., allocation header)
   static void free(CodeBlob* cb);                          // frees a CodeBlob
   static bool contains(void *p);                           // returns whether p is included
+  static bool contains(nmethod* nm);                       // returns whether nm is included
   static void blobs_do(void f(CodeBlob* cb));              // iterates over all CodeBlobs
   static void blobs_do(CodeBlobClosure* f);                // iterates over all CodeBlobs
   static void nmethods_do(void f(nmethod* nm));            // iterates over all nmethods
@@ -192,6 +204,9 @@
   static address high_bound()                         { return _high_bound; }
   static address high_bound(int code_blob_type);
 
+  // Have to use far call instructions to call this pc.
+  static bool is_far_target(address pc);
+
   // Profiling
   static size_t capacity();
   static size_t unallocated_capacity(int code_blob_type);
@@ -208,11 +223,21 @@
   // Returns true if an own CodeHeap for the given CodeBlobType is available
   static bool heap_available(int code_blob_type);
 
-  // Returns the CodeBlobType for the given nmethod
+  // Returns the CodeBlobType for the given CompiledMethod
   static int get_code_blob_type(CompiledMethod* cm) {
     return get_code_heap(cm)->code_blob_type();
   }
 
+  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;
+  }
+
+  static bool code_blob_type_accepts_nmethod(int type) {
+    return type == CodeBlobType::All || type <= CodeBlobType::MethodProfiled;
+  }
+
   // Returns the CodeBlobType for the given compilation level
   static int get_code_blob_type(int comp_level) {
     if (comp_level == CompLevel_none ||
@@ -264,35 +289,47 @@
 
 
 // Iterator to iterate over nmethods in the CodeCache.
-class NMethodIterator : public StackObj {
+template <class T, class Filter> class CodeBlobIterator : public StackObj {
  private:
   CodeBlob* _code_blob;   // Current CodeBlob
-  int _code_blob_type;    // Refers to current CodeHeap
+  GrowableArrayIterator<CodeHeap*> _heap;
+  GrowableArrayIterator<CodeHeap*> _end;
 
  public:
-  NMethodIterator() {
-    initialize(NULL); // Set to NULL, initialized by first call to next()
+  CodeBlobIterator(T* nm = NULL) {
+    if (Filter::heaps() == NULL) {
+      return;
+    }
+    _heap = Filter::heaps()->begin();
+    _end = Filter::heaps()->end();
+    // If set to NULL, initialized by first call to next()
+    _code_blob = (CodeBlob*)nm;
+    if (nm != NULL) {
+      address start = nm->code_begin();
+      while(!(*_heap)->contains(start)) {
+        ++_heap;
+      }
+      assert((*_heap)->contains(start), "match not found");
+    }
   }
 
-  NMethodIterator(nmethod* nm) {
-    initialize(nm);
-  }
-
-  // Advance iterator to next nmethod
+  // Advance iterator to next blob
   bool next() {
     assert_locked_or_safepoint(CodeCache_lock);
-    assert(_code_blob_type < CodeBlobType::NumTypes, "end reached");
 
-    bool result = next_nmethod();
-    while (!result && (_code_blob_type < CodeBlobType::MethodProfiled)) {
-      // Advance to next code heap if segmented code cache
-      _code_blob_type++;
-      result = next_nmethod();
+    bool result = next_blob();
+    while (!result && _heap != _end) {
+      // Advance to next code heap of segmented code cache
+      if (++_heap == _end) {
+        break;
+      }
+      result = next_blob();
     }
+
     return result;
   }
 
-  // Advance iterator to next alive nmethod
+  // Advance iterator to next alive blob
   bool next_alive() {
     bool result = next();
     while(result && !_code_blob->is_alive()) {
@@ -302,90 +339,48 @@
   }
 
   bool end()        const   { return _code_blob == NULL; }
-  nmethod* method() const   { return (nmethod*)_code_blob; }
+  T* method() const   { return (T*)_code_blob; }
 
 private:
-  // Initialize iterator to given nmethod
-  void initialize(nmethod* nm) {
-    _code_blob = (CodeBlob*)nm;
-    if (!SegmentedCodeCache) {
-      // Iterate over all CodeBlobs
-      _code_blob_type = CodeBlobType::All;
-    } else if (nm != NULL) {
-      _code_blob_type = CodeCache::get_code_blob_type(nm);
-    } else {
-      // Only iterate over method code heaps, starting with non-profiled
-      _code_blob_type = CodeBlobType::MethodNonProfiled;
+
+  // Advance iterator to the next blob in the current code heap
+  bool next_blob() {
+    if (_heap == _end) {
+      return false;
     }
-  }
-
-  // Advance iterator to the next nmethod in the current code heap
-  bool next_nmethod() {
+    CodeHeap *heap = *_heap;
     // Get first method CodeBlob
     if (_code_blob == NULL) {
-      _code_blob = CodeCache::first_blob(_code_blob_type);
+      _code_blob = CodeCache::first_blob(heap);
       if (_code_blob == NULL) {
         return false;
-      } else if (_code_blob->is_nmethod()) {
+      } else if (Filter::apply(_code_blob)) {
         return true;
       }
     }
     // Search for next method CodeBlob
-    _code_blob = CodeCache::next_blob(_code_blob);
-    while (_code_blob != NULL && !_code_blob->is_nmethod()) {
-      _code_blob = CodeCache::next_blob(_code_blob);
+    _code_blob = CodeCache::next_blob(heap, _code_blob);
+    while (_code_blob != NULL && !Filter::apply(_code_blob)) {
+      _code_blob = CodeCache::next_blob(heap, _code_blob);
     }
     return _code_blob != NULL;
   }
 };
 
-// Iterator to iterate over compiled methods in the CodeCache.
-class CompiledMethodIterator : public StackObj {
- private:
-  CodeBlob* _code_blob;   // Current CodeBlob
-  int _code_blob_type;    // Refers to current CodeHeap
 
- public:
-  CompiledMethodIterator() {
-    initialize(NULL); // Set to NULL, initialized by first call to next()
-  }
-
-  CompiledMethodIterator(CompiledMethod* cm) {
-    initialize(cm);
-  }
-
-  // Advance iterator to next compiled method
-  bool next() {
-    assert_locked_or_safepoint(CodeCache_lock);
-    assert(_code_blob_type < CodeBlobType::NumTypes, "end reached");
-
-    bool result = next_compiled_method();
-    while (!result && (_code_blob_type < CodeBlobType::MethodProfiled)) {
-      // Advance to next code heap if segmented code cache
-      _code_blob_type++;
-      result = next_compiled_method();
-    }
-    return result;
-  }
-
-  // Advance iterator to next alive compiled method
-  bool next_alive() {
-    bool result = next();
-    while(result && !_code_blob->is_alive()) {
-      result = next();
-    }
-    return result;
-  }
-
-  bool end()        const   { return _code_blob == NULL; }
-  CompiledMethod* method() const   { return (_code_blob != NULL) ? _code_blob->as_compiled_method() : NULL; }
-
-private:
-  // Initialize iterator to given compiled method
-  void initialize(CompiledMethod* cm);
-
-  // Advance iterator to the next compiled method in the current code heap
-  bool next_compiled_method();
+struct CompiledMethodFilter {
+  static bool apply(CodeBlob* cb) { return cb->is_compiled(); }
+  static const GrowableArray<CodeHeap*>* heaps() { return CodeCache::compiled_heaps(); }
 };
 
+
+struct NMethodFilter {
+  static bool apply(CodeBlob* cb) { return cb->is_nmethod(); }
+  static const GrowableArray<CodeHeap*>* heaps() { return CodeCache::nmethod_heaps(); }
+};
+
+
+typedef CodeBlobIterator<CompiledMethod, CompiledMethodFilter> CompiledMethodIterator;
+typedef CodeBlobIterator<nmethod, NMethodFilter> NMethodIterator;
+
 #endif // SHARE_VM_CODE_CODECACHE_HPP
--- a/hotspot/src/share/vm/code/compiledIC.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/code/compiledIC.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -55,7 +55,7 @@
   assert (!is_optimized(), "an optimized virtual call does not have a cached metadata");
 
   if (!is_in_transition_state()) {
-    void* data = (void*)_value->data();
+    void* data = get_data();
     // If we let the metadata value here be initialized to zero...
     assert(data != NULL || Universe::non_oop_word() == NULL,
            "no raw nulls in CompiledIC metadatas, because of patching races");
@@ -77,13 +77,13 @@
   // Don't use ic_destination for this test since that forwards
   // through ICBuffer instead of returning the actual current state of
   // the CompiledIC.
-  if (is_icholder_entry(_ic_call->destination())) {
+  if (is_icholder_entry(_call->destination())) {
     // When patching for the ICStub case the cached value isn't
     // overwritten until the ICStub copied into the CompiledIC during
     // the next safepoint.  Make sure that the CompiledICHolder* is
     // marked for release at this point since it won't be identifiable
     // once the entry point is overwritten.
-    InlineCacheBuffer::queue_for_release((CompiledICHolder*)_value->data());
+    InlineCacheBuffer::queue_for_release((CompiledICHolder*)get_data());
   }
 
   if (TraceCompiledIC) {
@@ -102,10 +102,10 @@
   {
     MutexLockerEx pl(SafepointSynchronize::is_at_safepoint() ? NULL : Patching_lock, Mutex::_no_safepoint_check_flag);
 #ifdef ASSERT
-    CodeBlob* cb = CodeCache::find_blob_unsafe(_ic_call);
+    CodeBlob* cb = CodeCache::find_blob_unsafe(_call->instruction_address());
     assert(cb != NULL && cb->is_compiled(), "must be compiled");
 #endif
-     _ic_call->set_destination_mt_safe(entry_point);
+    _call->set_destination_mt_safe(entry_point);
   }
 
   if (is_optimized() || is_icstub) {
@@ -118,7 +118,7 @@
 
   if (cache == NULL)  cache = (void*)Universe::non_oop_word();
 
-  _value->set_data((intptr_t)cache);
+  set_data((intptr_t)cache);
 }
 
 
@@ -131,7 +131,7 @@
 address CompiledIC::ic_destination() const {
  assert (CompiledIC_lock->is_locked() || SafepointSynchronize::is_at_safepoint(), "");
  if (!is_in_transition_state()) {
-   return _ic_call->destination();
+   return _call->destination();
  } else {
    return InlineCacheBuffer::ic_destination_for((CompiledIC *)this);
  }
@@ -140,7 +140,7 @@
 
 bool CompiledIC::is_in_transition_state() const {
   assert (CompiledIC_lock->is_locked() || SafepointSynchronize::is_at_safepoint(), "");
-  return InlineCacheBuffer::contains(_ic_call->destination());
+  return InlineCacheBuffer::contains(_call->destination());;
 }
 
 
@@ -153,7 +153,7 @@
 // the InlineCacheBuffer when it needs to find the stub.
 address CompiledIC::stub_address() const {
   assert(is_in_transition_state(), "should only be called when we are in a transition state");
-  return _ic_call->destination();
+  return _call->destination();
 }
 
 // Clears the IC stub if the compiled IC is in transition state
@@ -164,17 +164,16 @@
   }
 }
 
-
 //-----------------------------------------------------------------------------
 // High-level access to an inline cache. Guaranteed to be MT-safe.
 
 void CompiledIC::initialize_from_iter(RelocIterator* iter) {
-  assert(iter->addr() == _ic_call->instruction_address(), "must find ic_call");
+  assert(iter->addr() == _call->instruction_address(), "must find ic_call");
 
   if (iter->type() == relocInfo::virtual_call_type) {
     virtual_call_Relocation* r = iter->virtual_call_reloc();
     _is_optimized = false;
-    _value = nativeMovConstReg_at(r->cached_value());
+    _value = _call->get_load_instruction(r);
   } else {
     assert(iter->type() == relocInfo::opt_virtual_call_type, "must be a virtual call");
     _is_optimized = true;
@@ -183,9 +182,10 @@
 }
 
 CompiledIC::CompiledIC(CompiledMethod* cm, NativeCall* call)
-  : _ic_call(call)
+  : _method(cm)
 {
-  address ic_call = _ic_call->instruction_address();
+  _call = _method->call_wrapper_at((address) call);
+  address ic_call = _call->instruction_address();
 
   assert(ic_call != NULL, "ic_call address must be set");
   assert(cm != NULL, "must pass compiled method");
@@ -201,9 +201,10 @@
 }
 
 CompiledIC::CompiledIC(RelocIterator* iter)
-  : _ic_call(nativeCall_at(iter->addr()))
+  : _method(iter->code())
 {
-  address ic_call = _ic_call->instruction_address();
+  _call = _method->call_wrapper_at(iter->addr());
+  address ic_call = _call->instruction_address();
 
   CompiledMethod* nm = iter->code();
   assert(ic_call != NULL, "ic_call address must be set");
@@ -311,20 +312,17 @@
     assert(!is_call_to_interpreted || (is_icholder_call() && cached_icholder() != NULL), "sanity check");
   } else {
     // Check if we are calling into our own codeblob (i.e., to a stub)
-    CodeBlob* cb = CodeCache::find_blob(_ic_call->instruction_address());
     address dest = ic_destination();
 #ifdef ASSERT
     {
-      CodeBlob* db = CodeCache::find_blob_unsafe(dest);
-      assert(!db->is_adapter_blob(), "must use stub!");
+      _call->verify_resolve_call(dest);
     }
 #endif /* ASSERT */
-    is_call_to_interpreted = cb->contains(dest);
+    is_call_to_interpreted = _call->is_call_to_interpreted(dest);
   }
   return is_call_to_interpreted;
 }
 
-
 void CompiledIC::set_to_clean(bool in_use) {
   assert(SafepointSynchronize::is_at_safepoint() || CompiledIC_lock->is_locked() , "MT-unsafe call");
   if (TraceInlineCacheClearing || TraceICs) {
@@ -332,16 +330,11 @@
     print();
   }
 
-  address entry;
-  if (is_optimized()) {
-    entry = SharedRuntime::get_resolve_opt_virtual_call_stub();
-  } else {
-    entry = SharedRuntime::get_resolve_virtual_call_stub();
-  }
+  address entry = _call->get_resolve_call_stub(is_optimized());
 
   // A zombie transition will always be safe, since the metadata has already been set to NULL, so
   // we only need to patch the destination
-  bool safe_transition = !in_use || is_optimized() || SafepointSynchronize::is_at_safepoint();
+  bool safe_transition = _call->is_safe_for_patching() || !in_use || is_optimized() || SafepointSynchronize::is_at_safepoint();
 
   if (safe_transition) {
     // Kill any leftover stub we might have too
@@ -364,18 +357,15 @@
   // assert(is_clean(), "sanity check");
 }
 
-
 bool CompiledIC::is_clean() const {
   assert (CompiledIC_lock->is_locked() || SafepointSynchronize::is_at_safepoint(), "");
   bool is_clean = false;
   address dest = ic_destination();
-  is_clean = dest == SharedRuntime::get_resolve_opt_virtual_call_stub() ||
-             dest == SharedRuntime::get_resolve_virtual_call_stub();
+  is_clean = dest == _call->get_resolve_call_stub(is_optimized());
   assert(!is_clean || is_optimized() || cached_value() == NULL, "sanity check");
   return is_clean;
 }
 
-
 void CompiledIC::set_to_monomorphic(CompiledICInfo& info) {
   assert (CompiledIC_lock->is_locked() || SafepointSynchronize::is_at_safepoint(), "");
   // Updating a cache to the wrong entry can cause bugs that are very hard
@@ -391,7 +381,7 @@
   // 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");
@@ -401,13 +391,14 @@
       // At code generation time, this call has been emitted as static call
       // Call via stub
       assert(info.cached_metadata() != NULL && info.cached_metadata()->is_method(), "sanity check");
-      CompiledStaticCall* csc = compiledStaticCall_at(instruction_address());
       methodHandle method (thread, (Method*)info.cached_metadata());
-      csc->set_to_interpreted(method, info.entry());
+      _call->set_to_interpreted(method, 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 {
@@ -469,6 +460,7 @@
                                            KlassHandle receiver_klass,
                                            bool is_optimized,
                                            bool static_bound,
+                                           bool caller_is_nmethod,
                                            CompiledICInfo& info,
                                            TRAPS) {
   CompiledMethod* method_code = method->code();
@@ -499,13 +491,19 @@
       entry      = method_code->entry_point();
     }
   }
-  if (entry != NULL) {
-    // Call to 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, (static_bound || 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");
@@ -522,8 +520,15 @@
   return (cb != NULL && cb->is_adapter_blob());
 }
 
+bool CompiledIC::is_icholder_call_site(virtual_call_Relocation* call_site, const CompiledMethod* cm) {
+  // This call site might have become stale so inspect it carefully.
+  address dest = cm->call_wrapper_at(call_site->addr())->destination();
+  return is_icholder_entry(dest);
+}
+
 // Release the CompiledICHolder* associated with this call site is there is one.
-void CompiledIC::cleanup_call_site(virtual_call_Relocation* call_site) {
+void CompiledIC::cleanup_call_site(virtual_call_Relocation* call_site, const CompiledMethod* cm) {
+  assert(cm->is_nmethod(), "must be nmethod");
   // This call site might have become stale so inspect it carefully.
   NativeCall* call = nativeCall_at(call_site->addr());
   if (is_icholder_entry(call->destination())) {
@@ -532,12 +537,6 @@
   }
 }
 
-bool CompiledIC::is_icholder_call_site(virtual_call_Relocation* call_site) {
-  // This call site might have become stale so inspect it carefully.
-  NativeCall* call = nativeCall_at(call_site->addr());
-  return is_icholder_entry(call->destination());
-}
-
 // ----------------------------------------------------------------------------
 
 void CompiledStaticCall::set_to_clean() {
@@ -545,33 +544,52 @@
   // Reset call site
   MutexLockerEx pl(SafepointSynchronize::is_at_safepoint() ? NULL : Patching_lock, Mutex::_no_safepoint_check_flag);
 #ifdef ASSERT
-  CodeBlob* cb = CodeCache::find_blob_unsafe(this);
+  CodeBlob* cb = CodeCache::find_blob_unsafe(instruction_address());
   assert(cb != NULL && cb->is_compiled(), "must be compiled");
 #endif
-  set_destination_mt_safe(SharedRuntime::get_resolve_static_call_stub());
+
+  set_destination_mt_safe(resolve_call_stub());
 
   // Do not reset stub here:  It is too expensive to call find_stub.
   // Instead, rely on caller (nmethod::clear_inline_caches) to clear
   // both the call and its stub.
 }
 
-
 bool CompiledStaticCall::is_clean() const {
-  return destination() == SharedRuntime::get_resolve_static_call_stub();
+  return destination() == resolve_call_stub();
 }
 
 bool CompiledStaticCall::is_call_to_compiled() const {
   return CodeCache::contains(destination());
 }
 
-
-bool CompiledStaticCall::is_call_to_interpreted() const {
+bool CompiledDirectStaticCall::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
   CompiledMethod* cm = CodeCache::find_compiled(instruction_address());
   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;
+    tty->print_cr("%s@" INTPTR_FORMAT ": set_to_compiled " INTPTR_FORMAT,
+        name(),
+        p2i(instruction_address()),
+        p2i(entry));
+  }
+  // Call to compiled code
+  assert(CodeCache::contains(entry), "wrong entry point");
+  set_destination_mt_safe(entry);
+}
+
 void CompiledStaticCall::set(const StaticCallInfo& info) {
   assert (CompiledIC_lock->is_locked() || SafepointSynchronize::is_at_safepoint(), "mt unsafe call");
   MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag);
@@ -584,26 +602,28 @@
   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 {
-    if (TraceICs) {
-      ResourceMark rm;
-      tty->print_cr("CompiledStaticCall@" INTPTR_FORMAT ": set_to_compiled " INTPTR_FORMAT,
-                    p2i(instruction_address()),
-                    p2i(info.entry()));
-    }
-    // Call to compiled code
-    assert (CodeCache::contains(info.entry()), "wrong entry point");
-    set_destination_mt_safe(info.entry());
+    set_to_compiled(info.entry());
   }
 }
 
-
 // Compute settings for a CompiledStaticCall. Since we might have to set
 // the stub when calling to the interpreter, we need to return arguments.
-void CompiledStaticCall::compute_entry(const methodHandle& m, StaticCallInfo& info) {
+void CompiledStaticCall::compute_entry(const methodHandle& m, bool caller_is_nmethod, StaticCallInfo& info) {
   CompiledMethod* m_code = m->code();
   info._callee = m;
   if (m_code != NULL && m_code->is_in_use()) {
+    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 {
@@ -615,18 +635,18 @@
   }
 }
 
-address CompiledStaticCall::find_stub() {
+address CompiledDirectStaticCall::find_stub_for(address instruction, bool is_aot) {
   // Find reloc. information containing this call-site
-  RelocIterator iter((nmethod*)NULL, instruction_address());
+  RelocIterator iter((nmethod*)NULL, instruction);
   while (iter.next()) {
-    if (iter.addr() == instruction_address()) {
+    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:
@@ -637,17 +657,20 @@
   return NULL;
 }
 
+address CompiledDirectStaticCall::find_stub(bool is_aot) {
+  return CompiledDirectStaticCall::find_stub_for(instruction_address(), is_aot);
+}
+
+address CompiledDirectStaticCall::resolve_call_stub() const {
+  return SharedRuntime::get_resolve_static_call_stub();
+}
 
 //-----------------------------------------------------------------------------
 // Non-product mode code
 #ifndef PRODUCT
 
 void CompiledIC::verify() {
-  // make sure code pattern is actually a call imm32 instruction
-  _ic_call->verify();
-  if (os::is_MP()) {
-    _ic_call->verify_alignment();
-  }
+  _call->verify();
   assert(is_clean() || is_call_to_compiled() || is_call_to_interpreted()
           || is_optimized() || is_megamorphic(), "sanity check");
 }
@@ -662,12 +685,14 @@
              p2i(instruction_address()), is_call_to_interpreted() ? "interpreted " : "", p2i(ic_destination()), p2i(is_optimized() ? NULL : cached_value()));
 }
 
-void CompiledStaticCall::print() {
+void CompiledDirectStaticCall::print() {
   tty->print("static call at " INTPTR_FORMAT " -> ", p2i(instruction_address()));
   if (is_clean()) {
     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");
   }
--- a/hotspot/src/share/vm/code/compiledIC.hpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/code/compiledIC.hpp	Sun Dec 11 19:07:04 2016 -0800
@@ -68,6 +68,7 @@
   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; }
@@ -81,12 +82,14 @@
     return icholder;
   }
   bool    is_optimized() const { return _is_optimized; }
-  bool         to_interpreter() const  { return _to_interpreter; }
+  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;
@@ -96,6 +99,17 @@
     _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;
@@ -105,13 +119,14 @@
     _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),
-                    _to_interpreter(false), _is_optimized(false), _release_icholder(false) {
+                    _to_interpreter(false), _to_aot(false), _is_optimized(false), _release_icholder(false) {
   }
   ~CompiledICInfo() {
     // In rare cases the info is computed but not used, so release any
@@ -125,15 +140,36 @@
   }
 };
 
+class NativeCallWrapper: public ResourceObj {
+public:
+  virtual address destination() const = 0;
+  virtual address instruction_address() const = 0;
+  virtual address next_instruction_address() const = 0;
+  virtual address return_address() const = 0;
+  virtual address get_resolve_call_stub(bool is_optimized) const = 0;
+  virtual void set_destination_mt_safe(address dest) = 0;
+  virtual void set_to_interpreted(const methodHandle& method, CompiledICInfo& info) = 0;
+  virtual void verify() const = 0;
+  virtual void verify_resolve_call(address dest) const = 0;
+
+  virtual bool is_call_to_interpreted(address dest) const = 0;
+  virtual bool is_safe_for_patching() const = 0;
+
+  virtual NativeInstruction* get_load_instruction(virtual_call_Relocation* r) const = 0;
+
+  virtual void *get_data(NativeInstruction* instruction) const = 0;
+  virtual void set_data(NativeInstruction* instruction, intptr_t data) = 0;
+};
+
 class CompiledIC: public ResourceObj {
   friend class InlineCacheBuffer;
   friend class ICStub;
 
-
  private:
-  NativeCall*   _ic_call;       // the call instruction
-  NativeMovConstReg* _value;    // patchable value cell for this IC
+  NativeCallWrapper* _call;
+  NativeInstruction* _value;    // patchable value cell for this IC
   bool          _is_optimized;  // an optimized virtual call (i.e., no compiled IC)
+  CompiledMethod* _method;
 
   CompiledIC(CompiledMethod* cm, NativeCall* ic_call);
   CompiledIC(RelocIterator* iter);
@@ -177,8 +213,8 @@
   // This is used to release CompiledICHolder*s from nmethods that
   // are about to be freed.  The callsite might contain other stale
   // values of other kinds so it must be careful.
-  static void cleanup_call_site(virtual_call_Relocation* call_site);
-  static bool is_icholder_call_site(virtual_call_Relocation* call_site);
+  static void cleanup_call_site(virtual_call_Relocation* call_site, const CompiledMethod* cm);
+  static bool is_icholder_call_site(virtual_call_Relocation* call_site, const CompiledMethod* cm);
 
   // Return the cached_metadata/destination associated with this inline cache. If the cache currently points
   // to a transition stub, it will read the values from the transition stub.
@@ -192,6 +228,14 @@
     return (Metadata*) cached_value();
   }
 
+  void* get_data() const {
+    return _call->get_data(_value);
+  }
+
+  void set_data(intptr_t data) {
+    _call->set_data(_value, data);
+  }
+
   address ic_destination() const;
 
   bool is_optimized() const   { return _is_optimized; }
@@ -204,7 +248,7 @@
 
   bool is_icholder_call() const;
 
-  address end_of_call() { return  _ic_call->return_address(); }
+  address end_of_call() { return  _call->return_address(); }
 
   // MT-safe patching of inline caches. Note: Only safe to call is_xxx when holding the CompiledIC_ock
   // so you are guaranteed that no patching takes place. The same goes for verify.
@@ -223,10 +267,11 @@
   bool set_to_megamorphic(CallInfo* call_info, Bytecodes::Code bytecode, TRAPS);
 
   static void compute_monomorphic_entry(const methodHandle& method, KlassHandle receiver_klass,
-                                        bool is_optimized, bool static_bound, CompiledICInfo& info, TRAPS);
+                                        bool is_optimized, bool static_bound, bool caller_is_nmethod,
+                                        CompiledICInfo& info, TRAPS);
 
   // Location
-  address instruction_address() const { return _ic_call->instruction_address(); }
+  address instruction_address() const { return _call->instruction_address(); }
 
   // Misc
   void print()             PRODUCT_RETURN;
@@ -278,42 +323,38 @@
 //  Interpreted code: Calls to stub that set Method* reference
 //
 //
-class CompiledStaticCall;
 
 class StaticCallInfo {
  private:
   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;
+  friend class CompiledPltStaticCall;
  public:
   address      entry() const    { return _entry;  }
   methodHandle callee() const   { return _callee; }
 };
 
-
-class CompiledStaticCall: public NativeCall {
-  friend class CompiledIC;
-
-  // Also used by CompiledIC
-  void set_to_interpreted(methodHandle callee, address entry);
-  bool is_optimized_virtual();
-
+class CompiledStaticCall : public ResourceObj {
  public:
-  friend CompiledStaticCall* compiledStaticCall_before(address return_addr);
-  friend CompiledStaticCall* compiledStaticCall_at(address native_call);
-  friend CompiledStaticCall* compiledStaticCall_at(Relocation* call_site);
-
   // Code
   static address emit_to_interp_stub(CodeBuffer &cbuf, address mark = NULL);
   static int to_interp_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();
 
-  // State
-  bool is_clean() const;
-  bool is_call_to_compiled() const;
-  bool is_call_to_interpreted() const;
+  // Compute entry point given a method
+  static void compute_entry(const methodHandle& m, bool caller_is_nmethod, StaticCallInfo& info);
+
+public:
+  // Clean static call (will force resolving on next use)
+  virtual address destination() const = 0;
 
   // Clean static call (will force resolving on next use)
   void set_to_clean();
@@ -323,33 +364,77 @@
   // a OptoRuntime::resolve_xxx.
   void set(const StaticCallInfo& info);
 
-  // Compute entry point given a method
-  static void compute_entry(const methodHandle& m, StaticCallInfo& info);
+  // State
+  bool is_clean() const;
+  bool is_call_to_compiled() const;
+  virtual bool is_call_to_interpreted() const = 0;
+
+  virtual address instruction_address() const = 0;
+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;
+
+  void set_to_compiled(address entry);
+};
+
+class CompiledDirectStaticCall : public CompiledStaticCall {
+private:
+  friend class CompiledIC;
+  friend class DirectNativeCallWrapper;
+
+  // Also used by CompiledIC
+  void set_to_interpreted(const methodHandle& callee, address entry);
+#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); }
+
+  NativeCall* _call;
+
+  CompiledDirectStaticCall(NativeCall* call) : _call(call) {}
+
+ public:
+  static inline CompiledDirectStaticCall* before(address return_addr) {
+    CompiledDirectStaticCall* st = new CompiledDirectStaticCall(nativeCall_before(return_addr));
+    st->verify();
+    return st;
+  }
+
+  static inline CompiledDirectStaticCall* at(address native_call) {
+    CompiledDirectStaticCall* st = new CompiledDirectStaticCall(nativeCall_at(native_call));
+    st->verify();
+    return st;
+  }
+
+  static inline CompiledDirectStaticCall* at(Relocation* call_site) {
+    return at(call_site->addr());
+  }
+
+  // Delegation
+  address destination() const { return _call->destination(); }
+
+  // State
+  virtual bool is_call_to_interpreted() const;
+  bool is_call_to_far() const;
 
   // Stub support
-  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.
   void print()  PRODUCT_RETURN;
   void verify() PRODUCT_RETURN;
+
+ protected:
+  virtual address resolve_call_stub() const;
+  virtual const char* name() const { return "CompiledDirectStaticCall"; }
 };
 
-
-inline CompiledStaticCall* compiledStaticCall_before(address return_addr) {
-  CompiledStaticCall* st = (CompiledStaticCall*)nativeCall_before(return_addr);
-  st->verify();
-  return st;
-}
-
-inline CompiledStaticCall* compiledStaticCall_at(address native_call) {
-  CompiledStaticCall* st = (CompiledStaticCall*)native_call;
-  st->verify();
-  return st;
-}
-
-inline CompiledStaticCall* compiledStaticCall_at(Relocation* call_site) {
-  return compiledStaticCall_at(call_site->addr());
-}
-
 #endif // SHARE_VM_CODE_COMPILEDIC_HPP
--- a/hotspot/src/share/vm/code/compiledMethod.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/code/compiledMethod.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -274,7 +274,7 @@
   RelocIterator iter(this);
   while(iter.next()) {
     if (iter.type() == relocInfo::virtual_call_type) {
-      if (CompiledIC::is_icholder_call_site(iter.virtual_call_reloc())) {
+      if (CompiledIC::is_icholder_call_site(iter.virtual_call_reloc(), this)) {
         CompiledIC *ic = CompiledIC_at(&iter);
         if (TraceCompiledIC) {
           tty->print("noticed icholder " INTPTR_FORMAT " ", p2i(ic->cached_icholder()));
@@ -410,6 +410,7 @@
 BoolObjectClosure* CheckClass::_is_alive = NULL;
 #endif // ASSERT
 
+
 void CompiledMethod::clean_ic_if_metadata_is_dead(CompiledIC *ic, BoolObjectClosure *is_alive) {
   if (ic->is_icholder_call()) {
     // The only exception is compiledICHolder oops which may
--- a/hotspot/src/share/vm/code/compiledMethod.hpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/code/compiledMethod.hpp	Sun Dec 11 19:07:04 2016 -0800
@@ -35,6 +35,7 @@
 class AbstractCompiler;
 class xmlStream;
 class CompiledStaticCall;
+class NativeCallWrapper;
 
 // This class is used internally by nmethods, to cache
 // exception/pc/handler information.
@@ -334,6 +335,14 @@
   // corresponds to the given method as well.
   virtual bool is_dependent_on_method(Method* dependee) = 0;
 
+  virtual NativeCallWrapper* call_wrapper_at(address call) const = 0;
+  virtual NativeCallWrapper* call_wrapper_before(address return_pc) const = 0;
+  virtual address call_instruction_address(address pc) const = 0;
+
+  virtual CompiledStaticCall* compiledStaticCall_at(Relocation* call_site) const = 0;
+  virtual CompiledStaticCall* compiledStaticCall_at(address addr) const = 0;
+  virtual CompiledStaticCall* compiledStaticCall_before(address addr) const = 0;
+
   Method* attached_method(address call_pc);
   Method* attached_method_before_pc(address pc);
 
--- a/hotspot/src/share/vm/code/nmethod.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/code/nmethod.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -400,6 +400,7 @@
   _lock_count                 = 0;
   _stack_traversal_mark       = 0;
   _unload_reported            = false; // jvmti state
+  _is_far_code                = false; // nmethods are located in CodeCache
 
 #ifdef ASSERT
   _oops_are_stale             = false;
@@ -2054,6 +2055,7 @@
 // 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");
@@ -2061,6 +2063,7 @@
 
 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");
@@ -2170,11 +2173,11 @@
         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:
@@ -2724,6 +2727,114 @@
 
 }
 
+class DirectNativeCallWrapper: public NativeCallWrapper {
+private:
+  NativeCall* _call;
+
+public:
+  DirectNativeCallWrapper(NativeCall* 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 {
+    if (is_optimized) {
+      return SharedRuntime::get_resolve_opt_virtual_call_stub();
+    }
+    return SharedRuntime::get_resolve_virtual_call_stub();
+  }
+
+  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(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());
+    }
+  }
+
+  virtual void verify() const {
+    // make sure code pattern is actually a call imm32 instruction
+    _call->verify();
+    if (os::is_MP()) {
+      _call->verify_alignment();
+    }
+  }
+
+  virtual void verify_resolve_call(address dest) const {
+    CodeBlob* db = CodeCache::find_blob_unsafe(dest);
+    assert(!db->is_adapter_blob(), "must use stub!");
+  }
+
+  virtual bool is_call_to_interpreted(address dest) const {
+    CodeBlob* cb = CodeCache::find_blob(_call->instruction_address());
+    return cb->contains(dest);
+  }
+
+  virtual bool is_safe_for_patching() const { return false; }
+
+  virtual NativeInstruction* get_load_instruction(virtual_call_Relocation* r) const {
+    return nativeMovConstReg_at(r->cached_value());
+  }
+
+  virtual void *get_data(NativeInstruction* instruction) const {
+    return (void*)((NativeMovConstReg*) instruction)->data();
+  }
+
+  virtual void set_data(NativeInstruction* instruction, intptr_t data) {
+    ((NativeMovConstReg*) instruction)->set_data(data);
+  }
+};
+
+NativeCallWrapper* nmethod::call_wrapper_at(address call) const {
+  return new DirectNativeCallWrapper((NativeCall*) call);
+}
+
+NativeCallWrapper* nmethod::call_wrapper_before(address return_pc) const {
+  return new DirectNativeCallWrapper(nativeCall_before(return_pc));
+}
+
+address nmethod::call_instruction_address(address pc) const {
+  if (NativeCall::is_call_before(pc)) {
+    NativeCall *ncall = nativeCall_before(pc);
+    return ncall->instruction_address();
+  }
+  return NULL;
+}
+
+CompiledStaticCall* nmethod::compiledStaticCall_at(Relocation* call_site) const {
+  return CompiledDirectStaticCall::at(call_site);
+}
+
+CompiledStaticCall* nmethod::compiledStaticCall_at(address call_site) const {
+  return CompiledDirectStaticCall::at(call_site);
+}
+
+CompiledStaticCall* nmethod::compiledStaticCall_before(address return_addr) const {
+  return CompiledDirectStaticCall::before(return_addr);
+}
+
 #ifndef PRODUCT
 
 void nmethod::print_value_on(outputStream* st) const {
@@ -2743,7 +2854,7 @@
     }
     case relocInfo::static_call_type:
       st->print_cr("Static call at " INTPTR_FORMAT, p2i(iter.reloc()->addr()));
-      compiledStaticCall_at(iter.reloc())->print();
+      CompiledDirectStaticCall::at(iter.reloc())->print();
       break;
     }
   }
--- a/hotspot/src/share/vm/code/nmethod.hpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/code/nmethod.hpp	Sun Dec 11 19:07:04 2016 -0800
@@ -302,13 +302,6 @@
   address entry_point() const                     { return _entry_point;             } // normal entry point
   address verified_entry_point() const            { return _verified_entry_point;    } // if klass is correct
 
-  enum { in_use       = 0,   // executable nmethod
-         not_entrant  = 1,   // marked for deoptimization but activations may still exist,
-                             // will be transformed to zombie when all activations are gone
-         zombie       = 2,   // no activations exist, nmethod is ready for purge
-         unloaded     = 3 }; // there should be no activations, should not be called,
-                             // will be transformed to zombie immediately
-
   // flag accessing and manipulation
   bool  is_in_use() const                         { return _state == in_use; }
   bool  is_alive() const                          { unsigned char s = _state; return s < zombie; }
@@ -583,6 +576,14 @@
   static int state_offset()                       { return offset_of(nmethod, _state); }
 
   virtual void metadata_do(void f(Metadata*));
+
+  NativeCallWrapper* call_wrapper_at(address call) const;
+  NativeCallWrapper* call_wrapper_before(address return_pc) const;
+  address call_instruction_address(address pc) const;
+
+  virtual CompiledStaticCall* compiledStaticCall_at(Relocation* call_site) const;
+  virtual CompiledStaticCall* compiledStaticCall_at(address addr) const;
+  virtual CompiledStaticCall* compiledStaticCall_before(address addr) const;
 };
 
 // Locks an nmethod so its code will not get removed and it will not
--- a/hotspot/src/share/vm/code/relocInfo.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/code/relocInfo.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -565,14 +565,18 @@
   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 ) {
@@ -796,14 +800,14 @@
 }
 
 
-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();
       }
     }
@@ -832,19 +836,19 @@
 
 void static_call_Relocation::clear_inline_cache() {
   // Safe call site info
-  CompiledStaticCall* handler = compiledStaticCall_at(this);
+  CompiledStaticCall* handler = this->code()->compiledStaticCall_at(this);
   handler->set_to_clean();
 }
 
 
-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();
       }
     }
@@ -875,7 +879,7 @@
 void static_stub_Relocation::clear_inline_cache() {
   // Call stub is only used when calling the interpreted code.
   // It does not really need to be cleared, except that we want to clean out the methodoop.
-  CompiledStaticCall::set_stub_to_clean(this);
+  CompiledDirectStaticCall::set_stub_to_clean(this);
 }
 
 
--- a/hotspot/src/share/vm/code/relocInfo.hpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/code/relocInfo.hpp	Sun Dec 11 19:07:04 2016 -0800
@@ -1090,7 +1090,7 @@
   void clear_inline_cache();
 
   // find the matching static_stub
-  address static_stub();
+  address static_stub(bool is_aot);
 };
 
 
@@ -1124,24 +1124,26 @@
   void clear_inline_cache();
 
   // find the matching static_stub
-  address static_stub();
+  address static_stub(bool is_aot);
 };
 
 class static_stub_Relocation : public Relocation {
   relocInfo::relocType type() { return relocInfo::static_stub_type; }
 
  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) {
     _static_call = static_call;
+    _is_aot = is_aot;
   }
 
   friend class RelocIterator;
@@ -1151,6 +1153,7 @@
   void 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);
--- a/hotspot/src/share/vm/compiler/compileTask.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/compiler/compileTask.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -292,8 +292,7 @@
   if (_osr_bci != CompileBroker::standard_entry_bci) {
     log->print(" osr_bci='%d'", _osr_bci);
   }
-  // Always print the level in tiered.
-  if (_comp_level != CompLevel_highest_tier || TieredCompilation) {
+  if (_comp_level != CompLevel_highest_tier) {
     log->print(" level='%d'", _comp_level);
   }
   if (_is_blocking) {
@@ -329,24 +328,6 @@
 
 
 // ------------------------------------------------------------------
-// CompileTask::log_task_dequeued
-void CompileTask::log_task_dequeued(const char* comment) {
-  if (LogCompilation && xtty != NULL) {
-    Thread* thread = Thread::current();
-    ttyLocker ttyl;
-    ResourceMark rm(thread);
-
-    xtty->begin_elem("task_dequeued");
-    log_task(xtty);
-    if (comment != NULL) {
-      xtty->print(" comment='%s'", comment);
-    }
-    xtty->end_elem();
-  }
-}
-
-
-// ------------------------------------------------------------------
 // CompileTask::log_task_start
 void CompileTask::log_task_start(CompileLog* log)   {
   log->begin_head("task");
--- a/hotspot/src/share/vm/compiler/compileTask.hpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/compiler/compileTask.hpp	Sun Dec 11 19:07:04 2016 -0800
@@ -193,7 +193,6 @@
 
   void         log_task(xmlStream* log);
   void         log_task_queued();
-  void         log_task_dequeued(const char* comment);
   void         log_task_start(CompileLog* log);
   void         log_task_done(CompileLog* log);
 
--- a/hotspot/src/share/vm/compiler/compilerDefinitions.hpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/compiler/compilerDefinitions.hpp	Sun Dec 11 19:07:04 2016 -0800
@@ -47,8 +47,9 @@
 
 // Enumeration to distinguish tiers of compilation
 enum CompLevel {
-  CompLevel_any               = -1,
-  CompLevel_all               = -1,
+  CompLevel_any               = -2,
+  CompLevel_all               = -2,
+  CompLevel_aot               = -1,
   CompLevel_none              = 0,         // Interpreter
   CompLevel_simple            = 1,         // C1
   CompLevel_limited_profile   = 2,         // C1, invocation & backedge counters
--- a/hotspot/src/share/vm/compiler/disassembler.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/compiler/disassembler.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -505,7 +505,21 @@
   }
   decode_env env(cb, st);
   env.output()->print_cr("----------------------------------------------------------------------");
-  env.output()->print_cr("%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_cr("%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())) * sizeof(unsigned char*));
   env.decode_instructions(cb->code_begin(), cb->code_end());
 }
--- a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -69,6 +69,9 @@
   }
   _gc_par_phases[ScanRS] = new WorkerDataArray<double>(max_gc_threads, "Scan RS (ms):");
   _gc_par_phases[CodeRoots] = new WorkerDataArray<double>(max_gc_threads, "Code Root Scanning (ms):");
+#if INCLUDE_AOT
+  _gc_par_phases[AOTCodeRoots] = new WorkerDataArray<double>(max_gc_threads, "AOT Root Scanning (ms):");
+#endif
   _gc_par_phases[ObjCopy] = new WorkerDataArray<double>(max_gc_threads, "Object Copy (ms):");
   _gc_par_phases[Termination] = new WorkerDataArray<double>(max_gc_threads, "Termination (ms):");
   _gc_par_phases[GCWorkerTotal] = new WorkerDataArray<double>(max_gc_threads, "GC Worker Total (ms):");
@@ -311,6 +314,9 @@
   }
   debug_phase(_gc_par_phases[ScanRS]);
   debug_phase(_gc_par_phases[CodeRoots]);
+#if INCLUDE_AOT
+  debug_phase(_gc_par_phases[AOTCodeRoots]);
+#endif
   debug_phase(_gc_par_phases[ObjCopy]);
   debug_phase(_gc_par_phases[Termination]);
   debug_phase(_gc_par_phases[Other]);
--- a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp	Sun Dec 11 19:07:04 2016 -0800
@@ -59,6 +59,9 @@
     ScanHCC,
     ScanRS,
     CodeRoots,
+#if INCLUDE_AOT
+    AOTCodeRoots,
+#endif
     ObjCopy,
     Termination,
     Other,
--- a/hotspot/src/share/vm/gc/g1/g1RootProcessor.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/gc/g1/g1RootProcessor.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 
+#include "aot/aotLoader.hpp"
 #include "classfile/stringTable.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "code/codeCache.hpp"
@@ -290,6 +291,15 @@
     }
   }
 
+#if INCLUDE_AOT
+  if (UseAOT) {
+    G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::AOTCodeRoots, worker_i);
+    if (!_process_strong_tasks.is_task_claimed(G1RP_PS_aot_oops_do)) {
+        AOTLoader::oops_do(strong_roots);
+    }
+  }
+#endif
+
   {
     G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::SystemDictionaryRoots, worker_i);
     if (!_process_strong_tasks.is_task_claimed(G1RP_PS_SystemDictionary_oops_do)) {
--- a/hotspot/src/share/vm/gc/g1/g1RootProcessor.hpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/gc/g1/g1RootProcessor.hpp	Sun Dec 11 19:07:04 2016 -0800
@@ -64,6 +64,7 @@
     G1RP_PS_ClassLoaderDataGraph_oops_do,
     G1RP_PS_jvmti_oops_do,
     G1RP_PS_CodeCache_oops_do,
+    G1RP_PS_aot_oops_do,
     G1RP_PS_filter_satb_buffers,
     G1RP_PS_refProcessor_oops_do,
     // Leave this one last.
--- a/hotspot/src/share/vm/gc/g1/heapRegion.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/gc/g1/heapRegion.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -528,7 +528,7 @@
     _hr(hr), _failures(false) {}
 
   void do_code_blob(CodeBlob* cb) {
-    nmethod* nm = (cb == NULL) ? NULL : cb->as_nmethod_or_null();
+    nmethod* nm = (cb == NULL) ? NULL : cb->as_compiled_method()->as_nmethod_or_null();
     if (nm != NULL) {
       // Verify that the nemthod is live
       if (!nm->is_alive()) {
--- a/hotspot/src/share/vm/gc/parallel/pcTasks.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/gc/parallel/pcTasks.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -23,6 +23,7 @@
  */
 
 #include "precompiled.hpp"
+#include "aot/aotLoader.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "code/codeCache.hpp"
 #include "gc/parallel/parallelScavengeHeap.hpp"
@@ -127,6 +128,7 @@
     case code_cache:
       // Do not treat nmethods as strong roots for mark/sweep, since we can unload them.
       //CodeCache::scavenge_root_nmethods_do(CodeBlobToOopClosure(&mark_and_push_closure));
+      AOTLoader::oops_do(&mark_and_push_closure);
       break;
 
     default:
--- a/hotspot/src/share/vm/gc/parallel/psMarkSweep.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/gc/parallel/psMarkSweep.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -23,6 +23,7 @@
  */
 
 #include "precompiled.hpp"
+#include "aot/aotLoader.hpp"
 #include "classfile/stringTable.hpp"
 #include "classfile/symbolTable.hpp"
 #include "classfile/systemDictionary.hpp"
@@ -515,6 +516,7 @@
     ClassLoaderDataGraph::always_strong_cld_do(follow_cld_closure());
     // Do not treat nmethods as strong roots for mark/sweep, since we can unload them.
     //CodeCache::scavenge_root_nmethods_do(CodeBlobToOopClosure(mark_and_push_closure()));
+    AOTLoader::oops_do(mark_and_push_closure());
   }
 
   // Flush marking stack.
@@ -611,6 +613,7 @@
 
   CodeBlobToOopClosure adjust_from_blobs(adjust_pointer_closure(), CodeBlobToOopClosure::FixRelocations);
   CodeCache::blobs_do(&adjust_from_blobs);
+  AOTLoader::oops_do(adjust_pointer_closure());
   StringTable::oops_do(adjust_pointer_closure());
   ref_processor()->weak_oops_do(adjust_pointer_closure());
   PSScavenge::reference_processor()->weak_oops_do(adjust_pointer_closure());
--- a/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -23,6 +23,7 @@
  */
 
 #include "precompiled.hpp"
+#include "aot/aotLoader.hpp"
 #include "classfile/stringTable.hpp"
 #include "classfile/symbolTable.hpp"
 #include "classfile/systemDictionary.hpp"
@@ -2170,6 +2171,7 @@
 
   CodeBlobToOopClosure adjust_from_blobs(&oop_closure, CodeBlobToOopClosure::FixRelocations);
   CodeCache::blobs_do(&adjust_from_blobs);
+  AOTLoader::oops_do(&oop_closure);
   StringTable::oops_do(&oop_closure);
   ref_processor()->weak_oops_do(&oop_closure);
   // Roots were visited so references into the young gen in roots
--- a/hotspot/src/share/vm/gc/parallel/psTasks.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/gc/parallel/psTasks.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -23,6 +23,7 @@
  */
 
 #include "precompiled.hpp"
+#include "aot/aotLoader.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "code/codeCache.hpp"
 #include "gc/parallel/cardTableExtension.hpp"
@@ -101,6 +102,7 @@
       {
         MarkingCodeBlobClosure each_scavengable_code_blob(&roots_to_old_closure, CodeBlobToOopClosure::FixRelocations);
         CodeCache::scavenge_root_nmethods_do(&each_scavengable_code_blob);
+        AOTLoader::oops_do(&roots_closure);
       }
       break;
 
--- a/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -23,6 +23,7 @@
  */
 
 #include "precompiled.hpp"
+#include "aot/aotLoader.hpp"
 #include "classfile/symbolTable.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "classfile/vmSymbols.hpp"
@@ -73,6 +74,7 @@
   GCH_PS_ClassLoaderDataGraph_oops_do,
   GCH_PS_jvmti_oops_do,
   GCH_PS_CodeCache_oops_do,
+  GCH_PS_aot_oops_do,
   GCH_PS_younger_gens,
   // Leave this one last.
   GCH_PS_NumElements
@@ -608,6 +610,9 @@
   if (!_process_strong_tasks->is_task_claimed(GCH_PS_jvmti_oops_do)) {
     JvmtiExport::oops_do(strong_roots);
   }
+  if (UseAOT && !_process_strong_tasks->is_task_claimed(GCH_PS_aot_oops_do)) {
+    AOTLoader::oops_do(strong_roots);
+  }
 
   if (!_process_strong_tasks->is_task_claimed(GCH_PS_SystemDictionary_oops_do)) {
     SystemDictionary::roots_oops_do(strong_roots, weak_roots);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/jvmci/compilerRuntime.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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 "jvmci/compilerRuntime.hpp"
+#include "runtime/compilationPolicy.hpp"
+#include "runtime/deoptimization.hpp"
+#include "runtime/interfaceSupport.hpp"
+
+// Resolve and allocate String
+JRT_BLOCK_ENTRY(void, CompilerRuntime::resolve_string_by_symbol(JavaThread *thread, 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 = build_u2_from((address)name);
+      name += 2;
+      TempNewSymbol sym = SymbolTable::new_symbol(name, len, CHECK);
+      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!");
+    thread->set_vm_result(str);
+  JRT_BLOCK_END
+JRT_END
+
+
+
+Klass* CompilerRuntime::resolve_klass_helper(JavaThread *thread, const char* name, int len, TRAPS) {
+  ResourceMark rm(THREAD);
+  // last java frame on stack (which includes native call frames)
+  RegisterMap cbl_map(thread, false);
+  // Skip stub
+  frame caller_frame = thread->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(THREAD, caller_nm->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] == 'L') {
+    assert(len > 2, "small name %s", name);
+    name++;
+    len -= 2;
+  }
+  TempNewSymbol sym = SymbolTable::new_symbol(name, len, CHECK_NULL);
+  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 *thread, 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 = build_u2_from((address)name);
+      name += 2;
+      k = CompilerRuntime::resolve_klass_helper(thread, 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(MethodCounters*, CompilerRuntime::resolve_method_by_symbol_and_load_counters(JavaThread *thread, 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 = build_u2_from((address)data);
+       data += sizeof(u2);
+       const char* method_name = data;
+       data += method_name_len;
+
+       // Get signature and its length
+       int signature_name_len = build_u2_from((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(thread);
+       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 *thread, 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 = build_u2_from((address)name);
+        const char *cname = name + 2;
+        k = CompilerRuntime::resolve_klass_helper(thread,  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 *thread, MethodCounters* counters))
+  if (!TieredCompilation) {
+    // Ignore the event if tiered is off
+    return;
+  }
+  JRT_BLOCK
+    methodHandle mh(THREAD, counters->method());
+    RegisterMap map(thread, false);
+
+    // Compute the enclosing method
+    frame fr = thread->last_frame().sender(&map);
+    CompiledMethod* cm = fr.cb()->as_compiled_method_or_null();
+    assert(cm != NULL && cm->is_compiled(), "Sanity check");
+    methodHandle emh(THREAD, cm->method());
+
+    assert(!HAS_PENDING_EXCEPTION, "Should not have any exceptions pending");
+    CompilationPolicy::policy()->event(emh, mh, InvocationEntryBci, InvocationEntryBci, CompLevel_aot, cm, thread);
+    assert(!HAS_PENDING_EXCEPTION, "Event handler should not throw any exceptions");
+  JRT_BLOCK_END
+JRT_END
+
+JRT_BLOCK_ENTRY(void, CompilerRuntime::backedge_event(JavaThread *thread, MethodCounters* counters, int branch_bci, int target_bci))
+  if (!TieredCompilation) {
+    // Ignore the event if tiered is off
+    return;
+  }
+  assert(branch_bci != InvocationEntryBci && target_bci != InvocationEntryBci, "Wrong bci");
+  assert(target_bci <= branch_bci, "Expected a back edge");
+  JRT_BLOCK
+    methodHandle mh(THREAD, counters->method());
+    RegisterMap map(thread, false);
+
+    // Compute the enclosing method
+    frame fr = thread->last_frame().sender(&map);
+    CompiledMethod* cm = fr.cb()->as_compiled_method_or_null();
+    assert(cm != NULL && cm->is_compiled(), "Sanity check");
+    methodHandle emh(THREAD, cm->method());
+    assert(!HAS_PENDING_EXCEPTION, "Should not have any exceptions pending");
+    nmethod* osr_nm = CompilationPolicy::policy()->event(emh, mh, branch_bci, target_bci, CompLevel_aot, cm, thread);
+    assert(!HAS_PENDING_EXCEPTION, "Event handler should not throw any exceptions");
+    if (osr_nm != NULL) {
+      Deoptimization::deoptimize_frame(thread, fr.id());
+    }
+  JRT_BLOCK_END
+JRT_END
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/jvmci/compilerRuntime.hpp	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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_VM_RUNTIME_COMPILERRUNTIME_HPP
+#define SHARE_VM_RUNTIME_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(JavaThread *thread, 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 *thread, void* string_result, const char* name);
+  static Klass* resolve_klass_by_symbol(JavaThread *thread, Klass** klass_result, const char* name);
+  static Klass* initialize_klass_by_symbol(JavaThread *thread, Klass** klass_result, const char* name);
+  static MethodCounters* resolve_method_by_symbol_and_load_counters(JavaThread *thread, MethodCounters** counters_result, Klass* klass_hint, const char* data);
+  static void invocation_event(JavaThread *thread, MethodCounters* counters);
+  static void backedge_event(JavaThread *thread, MethodCounters* counters, int branch_bci, int target_bci);
+};
+
+#endif // SHARE_VM_RUNTIME_COMPILERRUNTIME_HPP
--- a/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -172,6 +172,69 @@
   return map;
 }
 
+AOTOopRecorder::AOTOopRecorder(Arena* arena, bool deduplicate) : OopRecorder(arena, deduplicate) {
+  _meta_strings = new GrowableArray<const char*>();
+}
+
+int AOTOopRecorder::nr_meta_strings() const {
+  return _meta_strings->length();
+}
+
+const char* AOTOopRecorder::meta_element(int pos) const {
+  return _meta_strings->at(pos);
+}
+
+int AOTOopRecorder::find_index(Metadata* h) {
+  int index =  this->OopRecorder::find_index(h);
+
+  Klass* klass = NULL;
+  if (h->is_klass()) {
+    klass = (Klass*) h;
+    record_meta_string(klass->signature_name(), index);
+  } else if (h->is_method()) {
+    Method* method = (Method*) h;
+    // Need klass->signature_name() in method name
+    klass = method->method_holder();
+    const char* klass_name = klass->signature_name();
+    int klass_name_len  = (int)strlen(klass_name);
+    Symbol* method_name = method->name();
+    Symbol* signature   = method->signature();
+    int method_name_len = method_name->utf8_length();
+    int method_sign_len = signature->utf8_length();
+    int len             = klass_name_len + 1 + method_name_len + method_sign_len;
+    char* dest          = NEW_RESOURCE_ARRAY(char, len + 1);
+    strcpy(dest, klass_name);
+    dest[klass_name_len] = '.';
+    strcpy(&dest[klass_name_len + 1], method_name->as_C_string());
+    strcpy(&dest[klass_name_len + 1 + method_name_len], signature->as_C_string());
+    dest[len] = 0;
+    record_meta_string(dest, 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_string(const char* name, int index) {
+  assert(index > 0, "must be 1..n");
+  index -= 1; // reduce by one to convert to array index
+
+  if (index < _meta_strings->length()) {
+    assert(strcmp(name, _meta_strings->at(index)) == 0, "must match");
+  } else {
+    assert(index == _meta_strings->length(), "must be last");
+    _meta_strings->append(name);
+  }
+}
+
 void* CodeInstaller::record_metadata_reference(CodeSection* section, address dest, Handle constant, TRAPS) {
   /*
    * This method needs to return a raw (untyped) pointer, since the value of a pointer to the base
@@ -481,7 +544,10 @@
 JVMCIEnv::CodeInstallResult CodeInstaller::gather_metadata(Handle target, Handle compiled_code, CodeMetadata& metadata, TRAPS) {
   CodeBuffer buffer("JVMCI Compiler CodeBuffer for Metadata");
   jobject compiled_code_obj = JNIHandles::make_local(compiled_code());
-  initialize_dependencies(JNIHandles::resolve(compiled_code_obj), NULL, CHECK_OK);
+  AOTOopRecorder* recorder = new AOTOopRecorder(&_arena, true);
+  initialize_dependencies(JNIHandles::resolve(compiled_code_obj), recorder, CHECK_OK);
+
+  metadata.set_oop_recorder(recorder);
 
   // Get instructions and constants CodeSections early because we need it.
   _instructions = buffer.insts();
@@ -553,7 +619,7 @@
                                        stack_slots, _debug_recorder->_oopmaps, &_exception_handler_table,
                                        compiler, _debug_recorder, _dependencies, env, id,
                                        has_unsafe_access, _has_wide_vector, installed_code, compiled_code, speculation_log);
-    cb = nm;
+    cb = nm->as_codeblob_or_null();
     if (nm != NULL && env == NULL) {
       DirectiveSet* directive = DirectivesStack::getMatchingDirective(method, compiler);
       bool printnmethods = directive->PrintAssemblyOption || directive->PrintNMethodsOption;
@@ -623,25 +689,40 @@
 }
 
 int CodeInstaller::estimate_stubs_size(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;
   objArrayOop sites = this->sites();
   for (int i = 0; i < sites->length(); i++) {
     oop site = sites->obj_at(i);
-    if (site != NULL && site->is_a(site_Mark::klass())) {
-      oop id_obj = site_Mark::id(site);
-      if (id_obj != NULL) {
-        if (!java_lang_boxing_object::is_instance(id_obj, T_INT)) {
-          JVMCI_ERROR_0("expected Integer id, got %s", id_obj->klass()->signature_name());
+    if (site != NULL) {
+      if (site->is_a(site_Mark::klass())) {
+        oop id_obj = site_Mark::id(site);
+        if (id_obj != NULL) {
+          if (!java_lang_boxing_object::is_instance(id_obj, T_INT)) {
+            JVMCI_ERROR_0("expected Integer id, got %s", id_obj->klass()->signature_name());
+          }
+          jint id = id_obj->int_field(java_lang_boxing_object::value_offset_in_bytes(T_INT));
+          if (id == INVOKESTATIC || id == INVOKESPECIAL) {
+            static_call_stubs++;
+          }
         }
-        jint id = id_obj->int_field(java_lang_boxing_object::value_offset_in_bytes(T_INT));
-        if (id == INVOKESTATIC || id == INVOKESPECIAL) {
-          static_call_stubs++;
+      }
+      if (UseAOT && site->is_a(site_Call::klass())) {
+        oop target = site_Call::target(site);
+        InstanceKlass* target_klass = InstanceKlass::cast(target->klass());
+        if (!target_klass->is_subclass_of(SystemDictionary::HotSpotForeignCallTarget_klass())) {
+          // Add far aot trampolines.
+          aot_call_stubs++;
         }
       }
     }
   }
-  return static_call_stubs * CompiledStaticCall::to_interp_stub_size();
+  int size = static_call_stubs * CompiledStaticCall::to_interp_stub_size();
+#if INCLUDE_AOT
+  size += aot_call_stubs * CompiledStaticCall::to_aot_stub_size();
+#endif
+  return size;
 }
 
 // perform data and call relocation on the CodeBuffer
@@ -1063,6 +1144,10 @@
 
   if (foreign_call.not_null()) {
     jlong foreign_call_destination = 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, CHECK);
   } else { // method != NULL
     if (debug_info.is_null()) {
@@ -1075,6 +1160,10 @@
       // Need a static call stub for transitions from compiled to interpreted.
       CompiledStaticCall::emit_to_interp_stub(buffer, _instructions->start() + pc_offset);
     }
+#if INCLUDE_AOT
+    // Trampoline to far aot code.
+    CompiledStaticCall::emit_to_aot_stub(buffer, _instructions->start() + pc_offset);
+#endif
   }
 
   _next_call_type = INVOKE_INVALID;
@@ -1093,9 +1182,18 @@
     if (constant.is_null()) {
       THROW(vmSymbols::java_lang_NullPointerException());
     } else if (constant->is_a(HotSpotObjectConstantImpl::klass())) {
-      pd_patch_OopConstant(pc_offset, constant, CHECK);
+      if (!_immutable_pic_compilation) {
+        // Do not patch during PIC compilation.
+        pd_patch_OopConstant(pc_offset, constant, CHECK);
+      }
     } else if (constant->is_a(HotSpotMetaspaceConstantImpl::klass())) {
-      pd_patch_MetaspaceConstant(pc_offset, constant, CHECK);
+      if (!_immutable_pic_compilation) {
+        pd_patch_MetaspaceConstant(pc_offset, constant, CHECK);
+      }
+    } else if (constant->is_a(HotSpotSentinelConstant::klass())) {
+      if (!_immutable_pic_compilation) {
+        JVMCI_ERROR("sentinel constant not supported for normal compiles: %s", constant->klass()->signature_name());
+      }
     } else {
       JVMCI_ERROR("unknown constant type in data patch: %s", constant->klass()->signature_name());
     }
@@ -1158,6 +1256,8 @@
       case HEAP_END_ADDRESS:
       case NARROW_KLASS_BASE_ADDRESS:
       case CRC_TABLE_ADDRESS:
+      case LOG_OF_HEAP_REGION_GRAIN_BYTES:
+      case INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED:
         break;
       default:
         JVMCI_ERROR("invalid mark id: %d", id);
--- a/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.hpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.hpp	Sun Dec 11 19:07:04 2016 -0800
@@ -43,6 +43,21 @@
   char *_buffer;
 };
 
+class AOTOopRecorder : public OopRecorder {
+public:
+  AOTOopRecorder(Arena* arena = NULL, bool deduplicate = false);
+
+  virtual int find_index(Metadata* h);
+  virtual int find_index(jobject h);
+  int nr_meta_strings() const;
+  const char* meta_element(int pos) const;
+
+private:
+  void record_meta_string(const char* name, int index);
+
+  GrowableArray<const char*>* _meta_strings;
+};
+
 class CodeMetadata {
 public:
   CodeMetadata() {}
@@ -57,6 +72,8 @@
 
   RelocBuffer* get_reloc_buffer() { return &_reloc_buffer; }
 
+  AOTOopRecorder* get_oop_recorder() { return _oop_recorder; }
+
   ExceptionHandlerTable* get_exception_table() { return _exception_table; }
 
   void set_pc_desc(PcDesc* desc, int count) {
@@ -69,6 +86,10 @@
     _nr_scopes_desc = size;
   }
 
+  void set_oop_recorder(AOTOopRecorder* recorder) {
+    _oop_recorder = recorder;
+  }
+
   void set_exception_table(ExceptionHandlerTable* table) {
     _exception_table = table;
   }
@@ -82,6 +103,7 @@
   int _nr_scopes_desc;
 
   RelocBuffer _reloc_buffer;
+  AOTOopRecorder* _oop_recorder;
   ExceptionHandlerTable* _exception_table;
 };
 
@@ -92,27 +114,29 @@
   friend class JVMCIVMStructs;
 private:
   enum MarkId {
-    VERIFIED_ENTRY             = 1,
-    UNVERIFIED_ENTRY           = 2,
-    OSR_ENTRY                  = 3,
-    EXCEPTION_HANDLER_ENTRY    = 4,
-    DEOPT_HANDLER_ENTRY        = 5,
-    INVOKEINTERFACE            = 6,
-    INVOKEVIRTUAL              = 7,
-    INVOKESTATIC               = 8,
-    INVOKESPECIAL              = 9,
-    INLINE_INVOKE              = 10,
-    POLL_NEAR                  = 11,
-    POLL_RETURN_NEAR           = 12,
-    POLL_FAR                   = 13,
-    POLL_RETURN_FAR            = 14,
-    CARD_TABLE_ADDRESS         = 15,
-    CARD_TABLE_SHIFT           = 16,
-    HEAP_TOP_ADDRESS           = 17,
-    HEAP_END_ADDRESS           = 18,
-    NARROW_KLASS_BASE_ADDRESS  = 19,
-    CRC_TABLE_ADDRESS          = 20,
-    INVOKE_INVALID             = -1
+    VERIFIED_ENTRY                         = 1,
+    UNVERIFIED_ENTRY                       = 2,
+    OSR_ENTRY                              = 3,
+    EXCEPTION_HANDLER_ENTRY                = 4,
+    DEOPT_HANDLER_ENTRY                    = 5,
+    INVOKEINTERFACE                        = 6,
+    INVOKEVIRTUAL                          = 7,
+    INVOKESTATIC                           = 8,
+    INVOKESPECIAL                          = 9,
+    INLINE_INVOKE                          = 10,
+    POLL_NEAR                              = 11,
+    POLL_RETURN_NEAR                       = 12,
+    POLL_FAR                               = 13,
+    POLL_RETURN_FAR                        = 14,
+    CARD_TABLE_ADDRESS                     = 15,
+    CARD_TABLE_SHIFT                       = 16,
+    HEAP_TOP_ADDRESS                       = 17,
+    HEAP_END_ADDRESS                       = 18,
+    NARROW_KLASS_BASE_ADDRESS              = 19,
+    CRC_TABLE_ADDRESS                      = 20,
+    LOG_OF_HEAP_REGION_GRAIN_BYTES         = 21,
+    INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED = 22,
+    INVOKE_INVALID                         = -1
   };
 
   Arena         _arena;
@@ -146,6 +170,8 @@
   Dependencies*             _dependencies;
   ExceptionHandlerTable     _exception_handler_table;
 
+  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;
@@ -173,7 +199,7 @@
 
 public:
 
-  CodeInstaller() : _arena(mtCompiler) {}
+  CodeInstaller(bool immutable_pic_compilation) : _arena(mtCompiler), _immutable_pic_compilation(immutable_pic_compilation) {}
 
   JVMCIEnv::CodeInstallResult gather_metadata(Handle target, Handle compiled_code, CodeMetadata& metadata, TRAPS);
   JVMCIEnv::CodeInstallResult install(JVMCICompiler* compiler, Handle target, Handle compiled_code, CodeBlob*& cb, Handle installed_code, Handle speculation_log, TRAPS);
--- a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -847,7 +847,8 @@
   JVMCICompiler* compiler = JVMCICompiler::instance(CHECK_JNI_ERR);
 
   TraceTime install_time("installCode", JVMCICompiler::codeInstallTimer());
-  CodeInstaller installer;
+  bool is_immutable_PIC = HotSpotCompiledCode::isImmutablePIC(compiled_code_handle) > 0;
+  CodeInstaller installer(is_immutable_PIC);
   JVMCIEnv::CodeInstallResult result = installer.install(compiler, target_handle, compiled_code_handle, cb, installed_code_handle, speculation_log_handle, CHECK_0);
 
   if (PrintCodeCacheOnCompilation) {
@@ -905,7 +906,7 @@
 
   CodeMetadata code_metadata;
   CodeBlob *cb = NULL;
-  CodeInstaller installer;
+  CodeInstaller installer(true /* immutable PIC compilation */);
 
   JVMCIEnv::CodeInstallResult result = installer.gather_metadata(target_handle, compiled_code_handle, code_metadata, CHECK_0);
   if (result != JVMCIEnv::ok) {
@@ -941,7 +942,16 @@
     HotSpotMetaData::set_oopMaps(metadata_handle, oopMapArrayHandle());
   }
 
-  HotSpotMetaData::set_metadata(metadata_handle, NULL);
+  AOTOopRecorder* recorder = code_metadata.get_oop_recorder();
+
+  int nr_meta_strings = recorder->nr_meta_strings();
+  objArrayHandle metadataArrayHandle = oopFactory::new_objectArray(nr_meta_strings, CHECK_(JVMCIEnv::cache_full));
+  for (int i = 0; i < nr_meta_strings; ++i) {
+    const char* element = recorder->meta_element(i);
+    Handle java_string = java_lang_String::create_from_str(element, CHECK_(JVMCIEnv::cache_full));
+    metadataArrayHandle->obj_at_put(i, java_string());
+  }
+  HotSpotMetaData::set_metadata(metadata_handle, metadataArrayHandle());
 
   ExceptionHandlerTable* handler = code_metadata.get_exception_table();
   int table_size = handler->size_in_bytes();
@@ -1493,6 +1503,15 @@
   THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), err_msg("Invalid profile data position %d", position));
 C2V_END
 
+C2V_VMENTRY(jlong, getFingerprint, (JNIEnv*, jobject, jlong metaspace_klass))
+  Klass *k = CompilerToVM::asKlass(metaspace_klass);
+  if (k->is_instance_klass()) {
+    return InstanceKlass::cast(k)->get_stored_fingerprint();
+  } else {
+    return 0;
+  }
+C2V_END
+
 C2V_VMENTRY(int, interpreterFrameSize, (JNIEnv*, jobject, jobject bytecode_frame_handle))
   if (bytecode_frame_handle == NULL) {
     THROW_0(vmSymbols::java_lang_NullPointerException());
@@ -1621,6 +1640,7 @@
   {CC "writeDebugOutput",                             CC "([BII)V",                                                                         FN_PTR(writeDebugOutput)},
   {CC "flushDebugOutput",                             CC "()V",                                                                             FN_PTR(flushDebugOutput)},
   {CC "methodDataProfileDataSize",                    CC "(JI)I",                                                                           FN_PTR(methodDataProfileDataSize)},
+  {CC "getFingerprint",                               CC "(J)J",                                                                            FN_PTR(getFingerprint)},
   {CC "interpreterFrameSize",                         CC "(" BYTECODE_FRAME ")I",                                                           FN_PTR(interpreterFrameSize)},
   {CC "compileToBytecode",                            CC "(" OBJECT ")V",                                                                   FN_PTR(compileToBytecode)},
 };
--- a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp	Sun Dec 11 19:07:04 2016 -0800
@@ -125,6 +125,10 @@
     return java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(jvmci_type));
   }
 
+  static inline Klass* asKlass(jlong metaspaceKlass) {
+    return (Klass*) (address) metaspaceKlass;
+  }
+
   static inline MethodData* asMethodData(jlong metaspaceMethodData) {
     return (MethodData*) (address) metaspaceMethodData;
   }
--- a/hotspot/src/share/vm/jvmci/jvmciJavaClasses.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/jvmci/jvmciJavaClasses.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -44,7 +44,7 @@
   fieldDescriptor fd;
   if (!ik->find_field(name_symbol, signature_symbol, &fd)) {
     ResourceMark rm;
-    fatal("Invalid layout of %s at %s", name_symbol->as_C_string(), ik->external_name());
+    fatal("Invalid layout of %s %s at %s", name_symbol->as_C_string(), signature_symbol->as_C_string(), ik->external_name());
   }
   guarantee(fd.is_static() == static_field, "static/instance mismatch");
   dest_offset = fd.offset();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/jvmci/vmStructs_compiler_runtime.hpp	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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_VM_JVMCI_VMSTRUCTS_COMPILER_RUNTIME_HPP
+#define SHARE_VM_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_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_VM_AOT_VMSTRUCTS_COMPILER_RUNTIME_HPP
--- a/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -30,6 +30,7 @@
 #include "jvmci/jvmciCompilerToVM.hpp"
 #include "jvmci/jvmciEnv.hpp"
 #include "jvmci/jvmciRuntime.hpp"
+#include "jvmci/vmStructs_compiler_runtime.hpp"
 #include "jvmci/vmStructs_jvmci.hpp"
 #include "oops/oop.hpp"
 #include "oops/objArrayKlass.hpp"
@@ -43,7 +44,6 @@
 #include "gc/g1/heapRegion.hpp"
 #endif
 
-
 #define VM_STRUCTS(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field) \
   static_field(CompilerToVM::Data,             Klass_vtable_start_offset,              int)                                          \
   static_field(CompilerToVM::Data,             Klass_vtable_length_offset,             int)                                          \
@@ -430,6 +430,8 @@
   declare_constant(CodeInstaller::HEAP_END_ADDRESS)                       \
   declare_constant(CodeInstaller::NARROW_KLASS_BASE_ADDRESS)              \
   declare_constant(CodeInstaller::CRC_TABLE_ADDRESS)                      \
+  declare_constant(CodeInstaller::LOG_OF_HEAP_REGION_GRAIN_BYTES)         \
+  declare_constant(CodeInstaller::INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED) \
   declare_constant(CodeInstaller::INVOKE_INVALID)                         \
                                                                           \
   declare_constant(ConstantPool::CPCACHE_INDEX_TAG)                       \
@@ -896,7 +898,9 @@
   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)
--- a/hotspot/src/share/vm/logging/logTag.hpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/logging/logTag.hpp	Sun Dec 11 19:07:04 2016 -0800
@@ -35,6 +35,7 @@
   LOG_TAG(add) \
   LOG_TAG(age) \
   LOG_TAG(alloc) \
+  LOG_TAG(aot) \
   LOG_TAG(annotation) \
   LOG_TAG(arguments) \
   LOG_TAG(attach) \
@@ -59,6 +60,7 @@
   LOG_TAG(ergo) \
   LOG_TAG(exceptions) \
   LOG_TAG(exit) \
+  LOG_TAG(fingerprint) \
   LOG_TAG(freelist) \
   LOG_TAG(gc) \
   LOG_TAG(hashtables) \
--- a/hotspot/src/share/vm/memory/heap.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/memory/heap.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -275,6 +275,13 @@
   return h->allocated_space();
 }
 
+CodeBlob* CodeHeap::find_blob_unsafe(void* start) const {
+  CodeBlob* result = (CodeBlob*)CodeHeap::find_start(start);
+  if (result != NULL && result->blob_contains((address)start)) {
+    return result;
+  }
+  return NULL;
+}
 
 size_t CodeHeap::alignment_unit() const {
   // this will be a power of two
--- a/hotspot/src/share/vm/memory/heap.hpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/memory/heap.hpp	Sun Dec 11 19:07:04 2016 -0800
@@ -82,7 +82,7 @@
 class CodeHeap : public CHeapObj<mtCode> {
   friend class VMStructs;
   friend class PregeneratedCodeHeap;
- private:
+ protected:
   VirtualSpace _memory;                          // the memory holding the blocks
   VirtualSpace _segmap;                          // the memory holding the segment map
 
@@ -156,6 +156,7 @@
 
   virtual bool  contains(const void* p) const    { return low_boundary() <= p && p < high(); }
   virtual void* find_start(void* p)     const;   // returns the block containing p or NULL
+  virtual CodeBlob* find_blob_unsafe(void* start) const;
   size_t alignment_unit()       const;           // alignment of any block
   size_t alignment_offset()     const;           // offset of first byte of any block, within the enclosing alignment unit
   static size_t header_size();                   // returns the header size for each heap block
--- a/hotspot/src/share/vm/memory/metaspace.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/memory/metaspace.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -22,6 +22,7 @@
  *
  */
 #include "precompiled.hpp"
+#include "aot/aotLoader.hpp"
 #include "gc/shared/collectedHeap.hpp"
 #include "gc/shared/collectorPolicy.hpp"
 #include "gc/shared/gcLocker.hpp"
@@ -3043,6 +3044,7 @@
     assert(!UseSharedSpaces, "Cannot shift with UseSharedSpaces");
     Universe::set_narrow_klass_shift(LogKlassAlignmentInBytes);
   }
+  AOTLoader::set_narrow_klass_shift();
 }
 
 #if INCLUDE_CDS
--- a/hotspot/src/share/vm/memory/universe.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/memory/universe.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -23,6 +23,7 @@
  */
 
 #include "precompiled.hpp"
+#include "aot/aotLoader.hpp"
 #include "classfile/classLoader.hpp"
 #include "classfile/classLoaderData.hpp"
 #include "classfile/javaClasses.hpp"
@@ -671,6 +672,8 @@
 
   Metaspace::global_initialize();
 
+  AOTLoader::universe_init();
+
   // Checks 'AfterMemoryInit' constraints.
   if (!CommandLineFlagConstraintList::check_constraints(CommandLineFlagConstraint::AfterMemoryInit)) {
     return JNI_EINVAL;
--- a/hotspot/src/share/vm/memory/virtualspace.hpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/memory/virtualspace.hpp	Sun Dec 11 19:07:04 2016 -0800
@@ -184,6 +184,14 @@
   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:
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -23,8 +23,10 @@
  */
 
 #include "precompiled.hpp"
+#include "aot/aotLoader.hpp"
 #include "classfile/classFileParser.hpp"
 #include "classfile/classFileStream.hpp"
+#include "classfile/classLoader.hpp"
 #include "classfile/javaClasses.hpp"
 #include "classfile/moduleEntry.hpp"
 #include "classfile/systemDictionary.hpp"
@@ -145,7 +147,8 @@
                                        parser.itable_size(),
                                        nonstatic_oop_map_size(parser.total_oop_map_count()),
                                        parser.is_interface(),
-                                       parser.is_anonymous());
+                                       parser.is_anonymous(),
+                                       should_store_fingerprint());
 
   const Symbol* const class_name = parser.class_name();
   assert(class_name != NULL, "invariant");
@@ -788,6 +791,9 @@
   }
 
 
+  // Look for aot compiled methods for this klass, including class initializer.
+  AOTLoader::load_for_klass(this_k, THREAD);
+
   // Step 8
   {
     assert(THREAD->is_Java_thread(), "non-JavaThread in initialize_impl");
@@ -1951,6 +1957,72 @@
   }
 }
 
+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<Klass*>* local_interfaces = this->local_interfaces();
+  if (local_interfaces != NULL) {
+    int length = local_interfaces->length();
+    for (int i = 0; i < length; i++) {
+      InstanceKlass* intf = InstanceKlass::cast(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;
+}
+
+bool InstanceKlass::should_store_fingerprint() {
+#if INCLUDE_AOT
+  // We store the fingerprint into the InstanceKlass only in the following 2 cases:
+  if (EnableJVMCI && !UseJVMCICompiler) {
+    // (1) We are running AOT to generate a shared library.
+    return true;
+  }
+  if (DumpSharedSpaces) {
+    // (2) We are running -Xshare:dump to create a shared archive
+    return true;
+  }
+#endif
+
+  // In all other cases we might set the _misc_has_passed_fingerprint_check bit,
+  // but do not store the 64-bit fingerprint to save space.
+  return false;
+}
+
+bool InstanceKlass::has_stored_fingerprint() const {
+#if INCLUDE_AOT
+  return should_store_fingerprint() || is_shared();
+#else
+  return false;
+#endif
+}
+
+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());
+  }
+}
 
 static void remove_unshareable_in_class(Klass* k) {
   // remove klass's unshareable info
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp	Sun Dec 11 19:07:04 2016 -0800
@@ -54,6 +54,7 @@
 //      indicating where oops are located in instances of this klass.
 //    [EMBEDDED implementor of the interface] only exist for interface
 //    [EMBEDDED host klass        ] only exist for an anonymous class (JSR 292 enabled)
+//    [EMBEDDED fingerprint       ] only if should_store_fingerprint()==true
 
 
 // forward declaration for class -- see below for definition
@@ -215,10 +216,12 @@
     _misc_has_nonstatic_concrete_methods      = 1 << 7,  // class/superclass/implemented interfaces has non-static, concrete methods
     _misc_declares_nonstatic_concrete_methods = 1 << 8,  // directly declares non-static, concrete methods
     _misc_has_been_redefined                  = 1 << 9,  // class has been redefined
-    _misc_is_scratch_class                    = 1 << 10, // class is the redefined scratch class
-    _misc_is_shared_boot_class                = 1 << 11, // defining class loader is boot class loader
-    _misc_is_shared_platform_class            = 1 << 12, // defining class loader is platform class loader
-    _misc_is_shared_app_class                 = 1 << 13  // defining class loader is app class loader
+    _misc_has_passed_fingerprint_check        = 1 << 10, // when this class was loaded, the fingerprint computed from its
+                                                         // code source was found to be matching the value recorded by AOT.
+    _misc_is_scratch_class                    = 1 << 11, // class is the redefined scratch class
+    _misc_is_shared_boot_class                = 1 << 12, // defining class loader is boot class loader
+    _misc_is_shared_platform_class            = 1 << 13, // defining class loader is platform class loader
+    _misc_is_shared_app_class                 = 1 << 14  // defining class loader is app class loader
   };
   u2 loader_type_bits() {
     return _misc_is_shared_boot_class|_misc_is_shared_platform_class|_misc_is_shared_app_class;
@@ -732,6 +735,23 @@
     _misc_flags |= _misc_has_been_redefined;
   }
 
+  bool has_passed_fingerprint_check() const {
+    return (_misc_flags & _misc_has_passed_fingerprint_check) != 0;
+  }
+  void set_has_passed_fingerprint_check(bool b) {
+    if (b) {
+      _misc_flags |= _misc_has_passed_fingerprint_check;
+    } else {
+      _misc_flags &= ~_misc_has_passed_fingerprint_check;
+    }
+  }
+  bool supers_have_passed_fingerprint_checks();
+
+  static bool should_store_fingerprint();
+  bool has_stored_fingerprint() const;
+  uint64_t get_stored_fingerprint() const;
+  void store_fingerprint(uint64_t fingerprint);
+
   bool is_scratch_class() const {
     return (_misc_flags & _misc_is_scratch_class) != 0;
   }
@@ -1028,19 +1048,21 @@
 
   static int size(int vtable_length, int itable_length,
                   int nonstatic_oop_map_size,
-                  bool is_interface, bool is_anonymous) {
+                  bool is_interface, bool is_anonymous, 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_anonymous ? (int)sizeof(Klass*)/wordSize : 0));
+           (is_anonymous ? (int)sizeof(Klass*)/wordSize : 0) +
+           (has_stored_fingerprint ? (int)sizeof(uint64_t*)/wordSize : 0));
   }
   int size() const                    { return size(vtable_length(),
                                                itable_length(),
                                                nonstatic_oop_map_size(),
                                                is_interface(),
-                                               is_anonymous());
+                                               is_anonymous(),
+                                               has_stored_fingerprint());
   }
 #if INCLUDE_SERVICES
   virtual void collect_statistics(KlassSizeStats *sz) const;
@@ -1083,6 +1105,24 @@
     }
   }
 
+  address adr_fingerprint() const {
+    if (has_stored_fingerprint()) {
+      InstanceKlass** adr_host = adr_host_klass();
+      if (adr_host != NULL) {
+        return (address)(adr_host + 1);
+      }
+
+      Klass** adr_impl = adr_implementor();
+      if (adr_impl != NULL) {
+        return (address)(adr_impl + 1);
+      }
+
+      return (address)end_of_nonstatic_oop_maps();
+    } else {
+      return NULL;
+    }
+  }
+
   // Use this to return the size of an instance in heap words:
   int size_helper() const {
     return layout_helper_to_size_helper(layout_helper());
--- a/hotspot/src/share/vm/oops/metadata.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/oops/metadata.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -42,7 +42,7 @@
 }
 
 char* Metadata::print_value_string() const {
-  char buf[100];
+  char buf[256];
   stringStream st(buf, sizeof(buf));
   if (this == NULL) {
     st.print("NULL");
--- a/hotspot/src/share/vm/oops/method.hpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/oops/method.hpp	Sun Dec 11 19:07:04 2016 -0800
@@ -103,6 +103,10 @@
   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 && defined(TIERED)
+  CompiledMethod* _aot_code;
+#endif
+
   // Constructor
   Method(ConstMethod* xconst, AccessFlags access_flags);
  public:
@@ -386,7 +390,20 @@
       mcs->set_rate(rate);
     }
   }
-#endif
+
+#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
+#endif // TIERED
+
   int nmethod_age() const {
     if (method_counters() == NULL) {
       return INT_MAX;
@@ -648,6 +665,10 @@
   // simultaneously. Use with caution.
   bool has_compiled_code() const                 { return code() != NULL; }
 
+#ifdef TIERED
+  bool has_aot_code() const                      { return aot_code() != NULL; }
+#endif
+
   // sizing
   static int header_size()                       { return sizeof(Method)/wordSize; }
   static int size(bool is_native);
--- a/hotspot/src/share/vm/oops/methodCounters.hpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/oops/methodCounters.hpp	Sun Dec 11 19:07:04 2016 -0800
@@ -34,6 +34,9 @@
  friend class VMStructs;
  friend class JVMCIVMStructs;
  private:
+#if INCLUDE_AOT
+  Method*           _method;                     // Back link to Method
+#endif
 #if defined(COMPILER2) || INCLUDE_JVMCI
   int               _interpreter_invocation_count; // Count of times invoked (reused as prev_event_count in tiered)
   u2                _interpreter_throwout_count; // Count of times method was exited via exception while interpreting
@@ -64,7 +67,11 @@
   u1                _highest_osr_comp_level;      // Same for OSR level
 #endif
 
-  MethodCounters(methodHandle mh) : _nmethod_age(INT_MAX)
+  MethodCounters(methodHandle mh) :
+#if INCLUDE_AOT
+                                    _method(mh()),
+#endif
+                                    _nmethod_age(INT_MAX)
 #ifdef TIERED
                                  , _rate(0),
                                    _prev_time(0),
@@ -107,6 +114,8 @@
   void deallocate_contents(ClassLoaderData* loader_data) {}
   DEBUG_ONLY(bool on_stack() { return false; })  // for template
 
+  AOT_ONLY(Method* method() const { return _method; })
+
   static int size() { return sizeof(MethodCounters) / wordSize; }
 
   bool is_klass() const { return false; }
--- a/hotspot/src/share/vm/opto/output.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/opto/output.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -292,6 +292,10 @@
           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
--- a/hotspot/src/share/vm/prims/jvmtiExport.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/prims/jvmtiExport.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -746,6 +746,7 @@
   JvmtiThreadState *   _state;
   KlassHandle *        _h_class_being_redefined;
   JvmtiClassLoadKind   _load_kind;
+  bool                 _has_been_modified;
 
  public:
   inline JvmtiClassFileLoadHookPoster(Symbol* h_name, Handle class_loader,
@@ -762,6 +763,7 @@
     _curr_data = *data_ptr;
     _curr_env = NULL;
     _cached_class_file_ptr = cache_ptr;
+    _has_been_modified = false;
 
     _state = _thread->jvmti_thread_state();
     if (_state != NULL) {
@@ -800,6 +802,8 @@
     copy_modified_data();
   }
 
+  bool has_been_modified() { return _has_been_modified; }
+
  private:
   void post_all_envs() {
     if (_load_kind != jvmti_class_load_kind_retransform) {
@@ -846,6 +850,7 @@
     }
     if (new_data != NULL) {
       // this agent has modified class data.
+      _has_been_modified = true;
       if (caching_needed && *_cached_class_file_ptr == NULL) {
         // data has been changed by the new retransformable agent
         // and it hasn't already been cached, cache it
@@ -893,14 +898,14 @@
 bool JvmtiExport::_should_post_class_file_load_hook = false;
 
 // this entry is for class file load hook on class load, redefine and retransform
-void JvmtiExport::post_class_file_load_hook(Symbol* h_name,
+bool JvmtiExport::post_class_file_load_hook(Symbol* h_name,
                                             Handle class_loader,
                                             Handle h_protection_domain,
                                             unsigned char **data_ptr,
                                             unsigned char **end_ptr,
                                             JvmtiCachedClassFileData **cache_ptr) {
   if (JvmtiEnv::get_phase() < JVMTI_PHASE_PRIMORDIAL) {
-    return;
+    return false;
   }
 
   JvmtiClassFileLoadHookPoster poster(h_name, class_loader,
@@ -908,6 +913,7 @@
                                       data_ptr, end_ptr,
                                       cache_ptr);
   poster.post();
+  return poster.has_been_modified();
 }
 
 void JvmtiExport::report_unsupported(bool on) {
--- a/hotspot/src/share/vm/prims/jvmtiExport.hpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/prims/jvmtiExport.hpp	Sun Dec 11 19:07:04 2016 -0800
@@ -341,10 +341,11 @@
     JVMTI_ONLY(return _should_post_class_file_load_hook);
     NOT_JVMTI(return false;)
   }
-  static void post_class_file_load_hook(Symbol* h_name, Handle class_loader,
+  // Return true if the class was modified by the hook.
+  static bool post_class_file_load_hook(Symbol* h_name, Handle class_loader,
                                         Handle h_protection_domain,
                                         unsigned char **data_ptr, unsigned char **end_ptr,
-                                        JvmtiCachedClassFileData **cache_ptr) NOT_JVMTI_RETURN;
+                                        JvmtiCachedClassFileData **cache_ptr) NOT_JVMTI_RETURN_(false);
   static void post_native_method_bind(Method* method, address* function_ptr) NOT_JVMTI_RETURN;
   static void post_compiled_method_load(nmethod *nm) NOT_JVMTI_RETURN;
   static void post_dynamic_code_generated(const char *name, const void *code_begin, const void *code_end) NOT_JVMTI_RETURN;
--- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -23,6 +23,7 @@
  */
 
 #include "precompiled.hpp"
+#include "aot/aotLoader.hpp"
 #include "classfile/classFileStream.hpp"
 #include "classfile/metadataOnStackMark.hpp"
 #include "classfile/systemDictionary.hpp"
@@ -4011,8 +4012,18 @@
     scratch_class->enclosing_method_method_index());
   scratch_class->set_enclosing_method_indices(old_class_idx, old_method_idx);
 
+  // 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());
+
   the_class->set_has_been_redefined();
 
+  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, THREAD);
+  }
+
   // keep track of previous versions of this class
   the_class->add_previous_version(scratch_class, emcp_method_count);
 
--- a/hotspot/src/share/vm/prims/whitebox.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/prims/whitebox.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -1172,6 +1172,9 @@
 
 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();
 }
 
@@ -1227,7 +1230,8 @@
   if (code == NULL) {
     return result;
   }
-  int insts_size = code->insts_size();
+  int comp_level = code->comp_level();
+  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());
@@ -1242,7 +1246,7 @@
   CHECK_JNI_EXCEPTION_(env, NULL);
   env->SetObjectArrayElement(result, 0, codeBlob);
 
-  jobject level = integerBox(thread, env, code->comp_level());
+  jobject level = integerBox(thread, env, comp_level);
   CHECK_JNI_EXCEPTION_(env, NULL);
   env->SetObjectArrayElement(result, 1, level);
 
--- a/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -24,7 +24,6 @@
 
 #include "precompiled.hpp"
 #include "code/codeCache.hpp"
-#include "compiler/compileTask.hpp"
 #include "runtime/advancedThresholdPolicy.hpp"
 #include "runtime/simpleThresholdPolicy.inline.hpp"
 #if INCLUDE_JVMCI
@@ -206,7 +205,6 @@
         if (PrintTieredEvents) {
           print_event(REMOVE_FROM_QUEUE, method, method, task->osr_bci(), (CompLevel)task->comp_level());
         }
-        task->log_task_dequeued("stale");
         compile_queue->remove_and_mark_stale(task);
         method->clear_queued_for_compilation();
         task = next_task;
@@ -276,6 +274,10 @@
 // the threshold values double.
 bool AdvancedThresholdPolicy::loop_predicate(int i, int b, CompLevel cur_level, Method* method) {
   switch(cur_level) {
+  case CompLevel_aot: {
+    double k = threshold_scale(CompLevel_full_profile, Tier3LoadFeedback);
+    return loop_predicate_helper<CompLevel_aot>(i, b, k, method);
+  }
   case CompLevel_none:
   case CompLevel_limited_profile: {
     double k = threshold_scale(CompLevel_full_profile, Tier3LoadFeedback);
@@ -292,6 +294,10 @@
 
 bool AdvancedThresholdPolicy::call_predicate(int i, int b, CompLevel cur_level, Method* method) {
   switch(cur_level) {
+  case CompLevel_aot: {
+    double k = threshold_scale(CompLevel_full_profile, Tier3LoadFeedback);
+    return call_predicate_helper<CompLevel_aot>(i, b, k, method);
+  }
   case CompLevel_none:
   case CompLevel_limited_profile: {
     double k = threshold_scale(CompLevel_full_profile, Tier3LoadFeedback);
@@ -394,31 +400,49 @@
     next_level = CompLevel_simple;
   } else {
     switch(cur_level) {
+    case CompLevel_aot: {
+      // If we were at full profile level, would we switch to full opt?
+      if (common(p, 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) &&
+                               (this->*p)(i, b, cur_level, method))) {
+        next_level = CompLevel_full_profile;
+      }
+    }
+    break;
     case CompLevel_none:
       // If we were at full profile level, would we switch to full opt?
       if (common(p, method, CompLevel_full_profile, disable_feedback) == CompLevel_full_optimization) {
         next_level = CompLevel_full_optimization;
       } else if ((this->*p)(i, b, cur_level, method)) {
 #if INCLUDE_JVMCI
-        if (UseJVMCICompiler) {
+        if (EnableJVMCI && UseJVMCICompiler) {
           // Since JVMCI takes a while to warm up, its queue inevitably backs up during
-          // early VM execution.
+          // early VM execution. As of 2014-06-13, JVMCI's inliner assumes that the root
+          // compilation method and all potential inlinees have mature profiles (which
+          // includes type profiling). If it sees immature profiles, JVMCI's inliner
+          // can perform pathologically bad (e.g., causing OutOfMemoryErrors due to
+          // exploring/inlining too many graphs). Since a rewrite of the inliner is
+          // in progress, we simply disable the dialing back heuristic for now and will
+          // revisit this decision once the new inliner is completed.
           next_level = CompLevel_full_profile;
-          break;
-        }
+        } else
 #endif
-        // C1-generated fully profiled code is about 30% slower than the limited profile
-        // code that has only invocation and backedge counters. The observation is that
-        // if C2 queue is large enough we can spend too much time in the fully profiled code
-        // while waiting for C2 to pick the method from the queue. To alleviate this problem
-        // we introduce a feedback on the C2 queue size. If the C2 queue is sufficiently long
-        // we choose to compile a limited profiled version and then recompile with full profiling
-        // when the load on C2 goes down.
-        if (!disable_feedback && CompileBroker::queue_size(CompLevel_full_optimization) >
-            Tier3DelayOn * compiler_count(CompLevel_full_optimization)) {
-          next_level = CompLevel_limited_profile;
-        } else {
-          next_level = CompLevel_full_profile;
+        {
+          // C1-generated fully profiled code is about 30% slower than the limited profile
+          // code that has only invocation and backedge counters. The observation is that
+          // if C2 queue is large enough we can spend too much time in the fully profiled code
+          // while waiting for C2 to pick the method from the queue. To alleviate this problem
+          // we introduce a feedback on the C2 queue size. If the C2 queue is sufficiently long
+          // we choose to compile a limited profiled version and then recompile with full profiling
+          // when the load on C2 goes down.
+          if (!disable_feedback && CompileBroker::queue_size(CompLevel_full_optimization) >
+              Tier3DelayOn * compiler_count(CompLevel_full_optimization)) {
+            next_level = CompLevel_limited_profile;
+          } else {
+            next_level = CompLevel_full_profile;
+          }
         }
       }
       break;
@@ -438,6 +462,13 @@
           } else {
             next_level = CompLevel_full_optimization;
           }
+        } else {
+          // If there is no MDO we need to profile
+          if (disable_feedback || (CompileBroker::queue_size(CompLevel_full_optimization) <=
+                                   Tier3DelayOff * compiler_count(CompLevel_full_optimization) &&
+                                   (this->*p)(i, b, cur_level, method))) {
+            next_level = CompLevel_full_profile;
+          }
         }
       }
       break;
@@ -514,15 +545,39 @@
   CompileBroker::compile_method(mh, bci, level, mh, hot_count, CompileTask::Reason_Tiered, thread);
 }
 
+bool AdvancedThresholdPolicy::maybe_switch_to_aot(methodHandle mh, CompLevel cur_level, CompLevel next_level, JavaThread* thread) {
+  if (UseAOT && !delay_compilation_during_startup()) {
+    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 AdvancedThresholdPolicy::method_invocation_event(const methodHandle& mh, const methodHandle& imh,
                                                       CompLevel level, CompiledMethod* nm, JavaThread* thread) {
   if (should_create_mdo(mh(), level)) {
     create_mdo(mh, thread);
   }
-  if (is_compilation_enabled() && !CompileBroker::compilation_is_in_queue(mh)) {
-    CompLevel next_level = call_event(mh(), level, thread);
-    if (next_level != level) {
+  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);
     }
   }
@@ -552,46 +607,56 @@
     // enough calls.
     CompLevel cur_level, next_level;
     if (mh() != imh()) { // If there is an enclosing method
-      guarantee(nm != NULL, "Should have nmethod here");
-      cur_level = comp_level(mh());
-      next_level = call_event(mh(), cur_level, thread);
+      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)) {
+          compile(mh, InvocationEntryBci, MIN2((CompLevel)TieredStopAtLevel, CompLevel_full_profile), 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);
 
-      if (max_osr_level == CompLevel_full_optimization) {
-        // The inlinee OSRed to full opt, we need to modify the enclosing method to avoid deopts
-        bool make_not_entrant = false;
-        if (nm->is_osr_method()) {
-          // This is an osr method, just make it not entrant and recompile later if needed
-          make_not_entrant = true;
-        } else {
-          if (next_level != CompLevel_full_optimization) {
-            // next_level is not full opt, so we need to recompile the
-            // enclosing method without the inlinee
-            cur_level = CompLevel_none;
+        if (max_osr_level == CompLevel_full_optimization) {
+          // The inlinee OSRed to full opt, we need to modify the enclosing method to avoid deopts
+          bool make_not_entrant = false;
+          if (nm->is_osr_method()) {
+            // This is an osr method, just make it not entrant and recompile later if needed
             make_not_entrant = true;
+          } else {
+            if (next_level != CompLevel_full_optimization) {
+              // next_level is not full opt, so we need to recompile the
+              // enclosing method without the inlinee
+              cur_level = CompLevel_none;
+              make_not_entrant = true;
+            }
+          }
+          if (make_not_entrant) {
+            if (PrintTieredEvents) {
+              int osr_bci = nm->is_osr_method() ? nm->osr_entry_bci() : InvocationEntryBci;
+              print_event(MAKE_NOT_ENTRANT, mh(), mh(), osr_bci, level);
+            }
+            nm->make_not_entrant();
           }
         }
-        if (make_not_entrant) {
-          if (PrintTieredEvents) {
-            int osr_bci = nm->is_osr_method() ? nm->osr_entry_bci() : InvocationEntryBci;
-            print_event(MAKE_NOT_ENTRANT, mh(), mh(), osr_bci, level);
-          }
-          nm->make_not_entrant();
-        }
-      }
-      if (!CompileBroker::compilation_is_in_queue(mh)) {
         // Fix up next_level if necessary to avoid deopts
         if (next_level == CompLevel_limited_profile && max_osr_level == CompLevel_full_profile) {
           next_level = CompLevel_full_profile;
         }
         if (cur_level != next_level) {
-          compile(mh, InvocationEntryBci, next_level, thread);
+          if (!maybe_switch_to_aot(mh, cur_level, next_level, thread) && !CompileBroker::compilation_is_in_queue(mh)) {
+            compile(mh, InvocationEntryBci, next_level, thread);
+          }
         }
       }
     } else {
-      cur_level = comp_level(imh());
-      next_level = call_event(imh(), cur_level, thread);
-      if (!CompileBroker::compilation_is_in_queue(imh) && (next_level != cur_level)) {
-        compile(imh, InvocationEntryBci, next_level, thread);
+      cur_level = comp_level(mh());
+      next_level = call_event(mh(), cur_level, thread);
+      if (next_level != cur_level) {
+        if (!maybe_switch_to_aot(mh, cur_level, next_level, thread) && !CompileBroker::compilation_is_in_queue(mh)) {
+          compile(mh, InvocationEntryBci, next_level, thread);
+        }
       }
     }
   }
--- a/hotspot/src/share/vm/runtime/advancedThresholdPolicy.hpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/runtime/advancedThresholdPolicy.hpp	Sun Dec 11 19:07:04 2016 -0800
@@ -205,6 +205,8 @@
 
   double _increase_threshold_at_ratio;
 
+  bool maybe_switch_to_aot(methodHandle mh, CompLevel cur_level, CompLevel next_level, JavaThread* thread);
+
 protected:
   void print_specific(EventType type, methodHandle mh, methodHandle imh, int bci, CompLevel level);
 
--- a/hotspot/src/share/vm/runtime/frame.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/runtime/frame.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -644,6 +644,7 @@
 //
 // 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.)
@@ -685,7 +686,9 @@
       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());
@@ -1266,8 +1269,10 @@
     // For now just label the frame
     CompiledMethod* cm = (CompiledMethod*)cb();
     values.describe(-1, info_address,
-                    FormatBuffer<1024>("#%d nmethod " INTPTR_FORMAT " for method %s%s", frame_no,
-                                       p2i(cm), cm->method()->name_and_sig_as_C_string(),
+                    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)" :
                                        ((_deopt_state == unknown) ? " (state unknown)" : "")),
--- a/hotspot/src/share/vm/runtime/globals.hpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/runtime/globals.hpp	Sun Dec 11 19:07:04 2016 -0800
@@ -3387,6 +3387,22 @@
           "Non-segmented code cache: X[%] of the total code cache")         \
           range(0, 100)                                                     \
                                                                             \
+  /* AOT parameters */                                                      \
+  product(bool, UseAOT, AOT_ONLY(true) NOT_AOT(false),                      \
+          "Use AOT compiled files")                                         \
+                                                                            \
+  product(ccstrlist, AOTLibrary, NULL,                                      \
+          "AOT library")                                                    \
+                                                                            \
+  product(bool, PrintAOT, false,                                            \
+          "Print used AOT klasses and methods")                             \
+                                                                            \
+  notproduct(bool, PrintAOTStatistics, false,                               \
+          "Print AOT statistics")                                           \
+                                                                            \
+  diagnostic(bool, UseAOTStrictLoading, false,                              \
+          "Exit the VM if any of the AOT libraries has invalid config")     \
+                                                                            \
   /* interpreter debugging */                                               \
   develop(intx, BinarySwitchThreshold, 5,                                   \
           "Minimal number of lookupswitch entries for rewriting to binary " \
@@ -3659,6 +3675,25 @@
           "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")                                   \
+          range(0, max_jint)                                                \
+                                                                            \
+  product(intx, Tier3AOTMinInvocationThreshold, 1000,                       \
+          "Minimum invocation to compile at tier 3 if coming from AOT")     \
+          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")                  \
+          range(0, max_jint)                                                \
+                                                                            \
+  product(intx, Tier3AOTBackEdgeThreshold,  120000,                         \
+          "Back edge threshold at which tier 3 OSR compilation is invoked " \
+          "if coming from AOT")                                             \
+          range(0, max_jint)                                                \
+                                                                            \
   product(intx, Tier4InvocationThreshold, 5000,                             \
           "Compile if number of method invocations crosses this "           \
           "threshold")                                                      \
--- a/hotspot/src/share/vm/runtime/java.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/runtime/java.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -23,6 +23,7 @@
  */
 
 #include "precompiled.hpp"
+#include "aot/aotLoader.hpp"
 #include "classfile/classLoader.hpp"
 #include "classfile/stringTable.hpp"
 #include "classfile/systemDictionary.hpp"
@@ -280,6 +281,10 @@
 #endif
 #endif
 
+  if (PrintAOTStatistics) {
+    AOTLoader::print_statistics();
+  }
+
   if (PrintNMethodStatistics) {
     nmethod::print_statistics();
   }
--- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -23,6 +23,7 @@
  */
 
 #include "precompiled.hpp"
+#include "aot/aotLoader.hpp"
 #include "classfile/stringTable.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "classfile/vmSymbols.hpp"
@@ -79,6 +80,7 @@
 RuntimeStub*        SharedRuntime::_resolve_opt_virtual_call_blob;
 RuntimeStub*        SharedRuntime::_resolve_virtual_call_blob;
 RuntimeStub*        SharedRuntime::_resolve_static_call_blob;
+address             SharedRuntime::_resolve_static_call_entry;
 
 DeoptimizationBlob* SharedRuntime::_deopt_blob;
 SafepointBlob*      SharedRuntime::_polling_page_vectors_safepoint_handler_blob;
@@ -98,6 +100,7 @@
   _resolve_opt_virtual_call_blob       = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::resolve_opt_virtual_call_C),   "resolve_opt_virtual_call");
   _resolve_virtual_call_blob           = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::resolve_virtual_call_C),       "resolve_virtual_call");
   _resolve_static_call_blob            = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::resolve_static_call_C),        "resolve_static_call");
+  _resolve_static_call_entry           = _resolve_static_call_blob->entry_point();
 
 #if defined(COMPILER2) || INCLUDE_JVMCI
   // Vectors are generated only by C2 and JVMCI.
@@ -476,7 +479,7 @@
   // JVMCI's ExceptionHandlerStub expects the thread local exception PC to be clear
   // and other exception handler continuations do not read it
   thread->set_exception_pc(NULL);
-#endif
+#endif // INCLUDE_JVMCI
 
   // The fastest case first
   CodeBlob* blob = CodeCache::find_blob(return_address);
@@ -504,6 +507,13 @@
     }
   }
 
+#if INCLUDE_AOT
+  if (UseAOT && blob->is_aot()) {
+    // AOT Compiled code
+    return AOTLoader::exception_begin(thread, blob, return_address);
+  }
+#endif
+
   // Entry code
   if (StubRoutines::returns_to_call_stub(return_address)) {
     return StubRoutines::catch_exception_entry();
@@ -989,17 +999,12 @@
 }
 
 JRT_ENTRY_NO_ASYNC(void, SharedRuntime::register_finalizer(JavaThread* thread, oopDesc* obj))
-  assert(obj->is_oop(), "must be a valid oop");
 #if INCLUDE_JVMCI
-  // This removes the requirement for JVMCI compilers to emit code
-  // performing a dynamic check that obj has a finalizer before
-  // calling this routine. There should be no performance impact
-  // for C1 since it emits a dynamic check. C2 and the interpreter
-  // uses other runtime routines for registering finalizers.
   if (!obj->klass()->has_finalizer()) {
     return;
   }
 #endif // INCLUDE_JVMCI
+  assert(obj->is_oop(), "must be a valid oop");
   assert(obj->klass()->has_finalizer(), "shouldn't be here otherwise");
   InstanceKlass::register_finalizer(instanceOop(obj), CHECK);
 JRT_END
@@ -1226,7 +1231,6 @@
     assert(fr.is_entry_frame(), "must be");
     // fr is now pointing to the entry frame.
     callee_method = methodHandle(THREAD, fr.entry_frame_call_wrapper()->callee_method());
-    assert(fr.entry_frame_call_wrapper()->receiver() == NULL || !callee_method->is_static(), "non-null receiver for static call??");
   } else {
     Bytecodes::Code bc;
     CallInfo callinfo;
@@ -1355,16 +1359,18 @@
   address dest_entry_point = callee == NULL ? 0 : callee->entry_point(); // used below
 #endif
 
+  bool is_nmethod = caller_nm->is_nmethod();
+
   if (is_virtual) {
     assert(receiver.not_null() || invoke_code == Bytecodes::_invokehandle, "sanity check");
     bool static_bound = call_info.resolved_method()->can_be_statically_bound();
     KlassHandle h_klass(THREAD, invoke_code == Bytecodes::_invokehandle ? NULL : receiver->klass());
     CompiledIC::compute_monomorphic_entry(callee_method, h_klass,
-                     is_optimized, static_bound, virtual_call_info,
+                     is_optimized, static_bound, is_nmethod, virtual_call_info,
                      CHECK_(methodHandle()));
   } else {
     // static call
-    CompiledStaticCall::compute_entry(callee_method, static_call_info);
+    CompiledStaticCall::compute_entry(callee_method, is_nmethod, static_call_info);
   }
 
   // grab lock, check for deoptimization and potentially patch caller
@@ -1395,7 +1401,7 @@
           inline_cache->set_to_monomorphic(virtual_call_info);
         }
       } else {
-        CompiledStaticCall* ssc = compiledStaticCall_before(caller_frame.pc());
+        CompiledStaticCall* ssc = caller_nm->compiledStaticCall_before(caller_frame.pc());
         if (ssc->is_clean()) ssc->set(static_call_info);
       }
     }
@@ -1511,6 +1517,7 @@
 JRT_END
 
 
+
 methodHandle SharedRuntime::handle_ic_miss_helper(JavaThread *thread, TRAPS) {
   ResourceMark rm(thread);
   CallInfo call_info;
@@ -1623,7 +1630,7 @@
         inline_cache->compute_monomorphic_entry(callee_method,
                                                 receiver_klass,
                                                 inline_cache->is_optimized(),
-                                                false,
+                                                false, caller_nm->is_nmethod(),
                                                 info, CHECK_(methodHandle()));
         inline_cache->set_to_monomorphic(info);
       } else if (!inline_cache->is_megamorphic() && !inline_cache->is_clean()) {
@@ -1692,10 +1699,7 @@
       // busy patching it.
       MutexLockerEx ml_patch(Patching_lock, Mutex::_no_safepoint_check_flag);
       // Location of call instruction
-      if (NativeCall::is_call_before(pc)) {
-        NativeCall *ncall = nativeCall_before(pc);
-        call_addr = ncall->instruction_address();
-      }
+      call_addr = caller_nm->call_instruction_address(pc);
     }
     // Make sure nmethod doesn't get deoptimized and removed until
     // this is done with it.
@@ -1725,9 +1729,10 @@
       // to a wrong method). It should not be performance critical, since the
       // resolve is only done once.
 
+      bool is_nmethod = caller_nm->is_nmethod();
       MutexLocker ml(CompiledIC_lock);
       if (is_static_call) {
-        CompiledStaticCall* ssc= compiledStaticCall_at(call_addr);
+        CompiledStaticCall* ssc = caller_nm->compiledStaticCall_at(call_addr);
         ssc->set_to_clean();
       } else {
         // compiled, dispatched call (which used to call an interpreted method)
@@ -1794,6 +1799,37 @@
 }
 #endif
 
+bool SharedRuntime::should_fixup_call_destination(address destination, address entry_point, address caller_pc, Method* moop, CodeBlob* cb) {
+  if (destination != entry_point) {
+    CodeBlob* callee = CodeCache::find_blob(destination);
+    // callee == cb seems weird. It means calling interpreter thru stub.
+    if (callee == cb || callee->is_adapter_blob()) {
+      // static call or optimized virtual
+      if (TraceCallFixup) {
+        tty->print("fixup callsite           at " INTPTR_FORMAT " to compiled code for", p2i(caller_pc));
+        moop->print_short_name(tty);
+        tty->print_cr(" to " INTPTR_FORMAT, p2i(entry_point));
+      }
+      return true;
+    } else {
+      if (TraceCallFixup) {
+        tty->print("failed to fixup callsite at " INTPTR_FORMAT " to compiled code for", p2i(caller_pc));
+        moop->print_short_name(tty);
+        tty->print_cr(" to " INTPTR_FORMAT, p2i(entry_point));
+      }
+      // assert is too strong could also be resolve destinations.
+      // assert(InlineCacheBuffer::contains(destination) || VtableStubs::contains(destination), "must be");
+    }
+  } else {
+    if (TraceCallFixup) {
+      tty->print("already patched callsite at " INTPTR_FORMAT " to compiled code for", p2i(caller_pc));
+      moop->print_short_name(tty);
+      tty->print_cr(" to " INTPTR_FORMAT, p2i(entry_point));
+    }
+  }
+  return false;
+}
+
 // ---------------------------------------------------------------------------
 // We are calling the interpreter via a c2i. Normally this would mean that
 // we were called by a compiled method. However we could have lost a race
@@ -1843,7 +1879,8 @@
     // Expect to find a native call there (unless it was no-inline cache vtable dispatch)
     MutexLockerEx ml_patch(Patching_lock, Mutex::_no_safepoint_check_flag);
     if (NativeCall::is_call_before(return_pc)) {
-      NativeCall *call = nativeCall_before(return_pc);
+      ResourceMark mark;
+      NativeCallWrapper* call = nm->call_wrapper_before(return_pc);
       //
       // bug 6281185. We might get here after resolving a call site to a vanilla
       // virtual call. Because the resolvee uses the verified entry it may then
@@ -1864,32 +1901,8 @@
         return;
       }
       address destination = call->destination();
-      if (destination != entry_point) {
-        CodeBlob* callee = CodeCache::find_blob(destination);
-        // callee == cb seems weird. It means calling interpreter thru stub.
-        if (callee == cb || callee->is_adapter_blob()) {
-          // static call or optimized virtual
-          if (TraceCallFixup) {
-            tty->print("fixup callsite           at " INTPTR_FORMAT " to compiled code for", p2i(caller_pc));
-            moop->print_short_name(tty);
-            tty->print_cr(" to " INTPTR_FORMAT, p2i(entry_point));
-          }
-          call->set_destination_mt_safe(entry_point);
-        } else {
-          if (TraceCallFixup) {
-            tty->print("failed to fixup callsite at " INTPTR_FORMAT " to compiled code for", p2i(caller_pc));
-            moop->print_short_name(tty);
-            tty->print_cr(" to " INTPTR_FORMAT, p2i(entry_point));
-          }
-          // assert is too strong could also be resolve destinations.
-          // assert(InlineCacheBuffer::contains(destination) || VtableStubs::contains(destination), "must be");
-        }
-      } else {
-          if (TraceCallFixup) {
-            tty->print("already patched callsite at " INTPTR_FORMAT " to compiled code for", p2i(caller_pc));
-            moop->print_short_name(tty);
-            tty->print_cr(" to " INTPTR_FORMAT, p2i(entry_point));
-          }
+      if (should_fixup_call_destination(destination, entry_point, caller_pc, moop, cb)) {
+        call->set_destination_mt_safe(entry_point);
       }
     }
   }
--- a/hotspot/src/share/vm/runtime/sharedRuntime.hpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp	Sun Dec 11 19:07:04 2016 -0800
@@ -60,6 +60,7 @@
   static RuntimeStub*        _resolve_opt_virtual_call_blob;
   static RuntimeStub*        _resolve_virtual_call_blob;
   static RuntimeStub*        _resolve_static_call_blob;
+  static address             _resolve_static_call_entry;
 
   static DeoptimizationBlob* _deopt_blob;
 
--- a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -33,6 +33,7 @@
 #include "jvmci/jvmciRuntime.hpp"
 #endif
 
+#ifdef TIERED
 
 void SimpleThresholdPolicy::print_counters(const char* prefix, methodHandle mh) {
   int invocation_count = mh->invocation_count();
@@ -242,6 +243,23 @@
   if (level == CompLevel_none) {
     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();
+        }
+        Method::set_code(mh, mh->aot_code());
+      }
+    }
+    return;
+  }
 
   // Check if the method can be compiled. If it cannot be compiled with C1, continue profiling
   // in the interpreter and then compile with C2 (the transition function will request that,
@@ -275,6 +293,9 @@
 // are passed to common() transition function).
 bool SimpleThresholdPolicy::loop_predicate(int i, int b, CompLevel cur_level, Method* method) {
   switch(cur_level) {
+  case CompLevel_aot: {
+    return loop_predicate_helper<CompLevel_aot>(i, b, 1.0, method);
+  }
   case CompLevel_none:
   case CompLevel_limited_profile: {
     return loop_predicate_helper<CompLevel_none>(i, b, 1.0, method);
@@ -289,6 +310,9 @@
 
 bool SimpleThresholdPolicy::call_predicate(int i, int b, CompLevel cur_level, Method* method) {
   switch(cur_level) {
+  case CompLevel_aot: {
+    return call_predicate_helper<CompLevel_aot>(i, b, 1.0, method);
+  }
   case CompLevel_none:
   case CompLevel_limited_profile: {
     return call_predicate_helper<CompLevel_none>(i, b, 1.0, method);
@@ -321,10 +345,16 @@
   int i = method->invocation_count();
   int b = method->backedge_count();
 
-  if (is_trivial(method)) {
+  if (is_trivial(method) && cur_level != CompLevel_aot) {
     next_level = CompLevel_simple;
   } else {
     switch(cur_level) {
+    case CompLevel_aot: {
+      if ((this->*p)(i, b, cur_level, method)) {
+        next_level = CompLevel_full_profile;
+      }
+    }
+    break;
     case CompLevel_none:
       // If we were at full profile level, would we switch to full opt?
       if (common(p, method, CompLevel_full_profile) == CompLevel_full_optimization) {
@@ -438,3 +468,5 @@
     }
   }
 }
+
+#endif
--- a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.hpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.hpp	Sun Dec 11 19:07:04 2016 -0800
@@ -30,6 +30,8 @@
 #include "runtime/compilationPolicy.hpp"
 #include "utilities/globalDefinitions.hpp"
 
+#ifdef TIERED
+
 class CompileTask;
 class CompileQueue;
 
@@ -118,4 +120,6 @@
   }
 };
 
+#endif // TIERED
+
 #endif // SHARE_VM_RUNTIME_SIMPLETHRESHOLDPOLICY_HPP
--- a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.inline.hpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.inline.hpp	Sun Dec 11 19:07:04 2016 -0800
@@ -27,6 +27,8 @@
 
 #include "compiler/compilerOracle.hpp"
 
+#ifdef TIERED
+
 template<CompLevel level>
 bool SimpleThresholdPolicy::call_predicate_helper(int i, int b, double scale, Method* method) {
   double threshold_scaling;
@@ -34,6 +36,9 @@
     scale *= threshold_scaling;
   }
   switch(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) ||
@@ -52,6 +57,8 @@
     scale *= threshold_scaling;
   }
   switch(level) {
+  case CompLevel_aot:
+    return b >= Tier3AOTBackEdgeThreshold * scale;
   case CompLevel_none:
   case CompLevel_limited_profile:
     return b >= Tier3BackEdgeThreshold * scale;
@@ -87,4 +94,6 @@
   return false;
 }
 
+#endif // TIERED
+
 #endif // SHARE_VM_RUNTIME_SIMPLETHRESHOLDPOLICY_INLINE_HPP
--- a/hotspot/src/share/vm/runtime/sweeper.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/runtime/sweeper.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -213,6 +213,8 @@
   if (_current.method() != NULL) {
     if (_current.method()->is_nmethod()) {
       assert(CodeCache::find_blob_unsafe(_current.method()) == _current.method(), "Sweeper nmethod cached state invalid");
+    } else if (_current.method()->is_aot()) {
+      assert(CodeCache::find_blob_unsafe(_current.method()->code_begin()) == _current.method(), "Sweeper AOT method cached state invalid");
     } else {
       ShouldNotReachHere();
     }
@@ -570,7 +572,7 @@
     RelocIterator iter(nm);
     while (iter.next()) {
       if (iter.type() == relocInfo::virtual_call_type) {
-        CompiledIC::cleanup_call_site(iter.virtual_call_reloc());
+        CompiledIC::cleanup_call_site(iter.virtual_call_reloc(), nm);
       }
     }
   }
--- a/hotspot/src/share/vm/runtime/vframe_hp.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/runtime/vframe_hp.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -198,7 +198,7 @@
   if (scope() == NULL) {
     CompiledMethod* nm = code();
     Method* method = nm->method();
-    assert(method->is_native(), "");
+    assert(method->is_native() || nm->is_aot(), "Expect a native method or precompiled method");
     if (!method->is_synchronized()) {
       return new GrowableArray<MonitorInfo*>(0);
     }
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -2537,6 +2537,24 @@
   declare_constant(InstanceKlass::fully_initialized)                      \
   declare_constant(InstanceKlass::initialization_error)                   \
                                                                           \
+  /***************************************/                               \
+  /* InstanceKlass enums for _misc_flags */                               \
+  /***************************************/                               \
+                                                                          \
+  declare_constant(InstanceKlass::_misc_rewritten)                        \
+  declare_constant(InstanceKlass::_misc_has_nonstatic_fields)             \
+  declare_constant(InstanceKlass::_misc_should_verify_class)              \
+  declare_constant(InstanceKlass::_misc_is_anonymous)                     \
+  declare_constant(InstanceKlass::_misc_is_contended)                     \
+  declare_constant(InstanceKlass::_misc_has_nonstatic_concrete_methods)   \
+  declare_constant(InstanceKlass::_misc_declares_nonstatic_concrete_methods)\
+  declare_constant(InstanceKlass::_misc_has_been_redefined)               \
+  declare_constant(InstanceKlass::_misc_has_passed_fingerprint_check)     \
+  declare_constant(InstanceKlass::_misc_is_scratch_class)                 \
+  declare_constant(InstanceKlass::_misc_is_shared_boot_class)             \
+  declare_constant(InstanceKlass::_misc_is_shared_platform_class)         \
+  declare_constant(InstanceKlass::_misc_is_shared_app_class)              \
+                                                                          \
   /*********************************/                                     \
   /* Symbol* - symbol max length */                                       \
   /*********************************/                                     \
@@ -2685,6 +2703,7 @@
   declare_constant(CompLevel_limited_profile)                             \
   declare_constant(CompLevel_full_profile)                                \
   declare_constant(CompLevel_full_optimization)                           \
+  declare_constant(CompLevel_aot)                                         \
                                                                           \
   /***************/                                                       \
   /* OopMapValue */                                                       \
--- a/hotspot/src/share/vm/runtime/vm_version.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/runtime/vm_version.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -134,7 +134,19 @@
     case Arguments::_int:
       return UseSharedSpaces ? "interpreted mode, sharing" : "interpreted mode";
     case Arguments::_mixed:
-      return UseSharedSpaces ? "mixed mode, sharing"       :  "mixed mode";
+      if (UseSharedSpaces) {
+          if (UseAOT) {
+            return "mixed mode, aot, sharing";
+          } else {
+            return "mixed mode, sharing";
+          }
+      } else {
+        if (UseAOT) {
+          return "mixed mode, aot";
+        } else {
+          return "mixed mode";
+        }
+      }
     case Arguments::_comp:
       return UseSharedSpaces ? "compiled mode, sharing"    : "compiled mode";
   };
--- a/hotspot/src/share/vm/utilities/debug.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/utilities/debug.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -771,7 +771,7 @@
 
   // 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) {
--- a/hotspot/src/share/vm/utilities/growableArray.hpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/utilities/growableArray.hpp	Sun Dec 11 19:07:04 2016 -0800
@@ -503,6 +503,7 @@
   }
 
  public:
+  GrowableArrayIterator() : _array(NULL), _position(0) { }
   GrowableArrayIterator<E>& operator++()  { ++_position; return *this; }
   E operator*()                           { return _array->at(_position); }
 
--- a/hotspot/src/share/vm/utilities/macros.hpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/utilities/macros.hpp	Sun Dec 11 19:07:04 2016 -0800
@@ -180,6 +180,14 @@
 #define INCLUDE_JVMCI 1
 #endif
 
+#ifdef INCLUDE_AOT
+# if INCLUDE_AOT && !(INCLUDE_JVMCI)
+#   error "Must have JVMCI for AOT"
+# endif
+#else
+# define INCLUDE_AOT 0
+#endif
+
 #if INCLUDE_JVMCI
 #define JVMCI_ONLY(code) code
 #define NOT_JVMCI(code)
@@ -190,6 +198,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
 #ifdef COMPILER2
--- a/hotspot/test/TEST.groups	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/test/TEST.groups	Sun Dec 11 19:07:04 2016 -0800
@@ -83,6 +83,7 @@
 # can be resolved in some cases by using tools from the compile-jdk.
 #
 needs_jdk = \
+  compiler/aot \
   gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java \
   gc/metaspace/TestMetaspacePerfCounters.java \
   gc/metaspace/TestPerfCountersAndMemoryPools.java \
@@ -273,6 +274,7 @@
   native_sanity
 
 hotspot_fast_compiler_1 = \
+  compiler/aot/ \
   compiler/arraycopy/ \
   compiler/c1/ \
   compiler/c2/ \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/AotCompiler.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.process.OutputAnalyzer;
+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.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import jdk.test.lib.JDKToolLauncher;
+import jdk.test.lib.Utils;
+
+/**
+ * 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 + ".class", 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("--output");
+        args.add(libName);
+        if (file != null) {
+            args.add("--compile-commands");
+            args.add(file.toString());
+        }
+        args.add(item);
+        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 new OutputAnalyzer(new ProcessBuilder(launcher.getCommand()).inheritIO().start());
+        } catch (IOException 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>]*");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/DeoptimizationTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib /testlibrary /
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @modules java.base/jdk.internal.misc
+ * @build compiler.aot.DeoptimizationTest
+ *        compiler.aot.AotCompiler
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *     sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main compiler.aot.AotCompiler -libname libDeoptimizationTest.so
+ *     -class compiler.aot.DeoptimizationTest
+ *     -compile compiler.aot.DeoptimizationTest.testMethod()D
+ * @run main/othervm -Xmixed -XX:+UseAOT -XX:+TieredCompilation
+ *     -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 sun.hotspot.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");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/HelloWorldPrinter.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/RecompilationTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib /testlibrary /
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @modules java.base/jdk.internal.misc
+ * @build compiler.aot.RecompilationTest
+ *        compiler.aot.AotCompiler
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *     sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main compiler.aot.AotCompiler -libname libRecompilationTest.so
+ *     -class compiler.whitebox.SimpleTestCaseHelper
+ *     -extraopt -Dgraal.TieredAOT=true -extraopt -Dgraal.ProfileSimpleMethods=true
+ *     -extraopt -XX:+UnlockDiagnosticVMOptions -extraopt -XX:+WhiteBoxAPI -extraopt -Xbootclasspath/a:.
+ * @run main/othervm -Xmixed -Xbatch -XX:+UseAOT -XX:+TieredCompilation -XX:-UseCounterDecay
+ *     -XX:CompileCommand=dontinline,*.*
+ *     -XX:AOTLibrary=./libRecompilationTest.so -Xbootclasspath/a:.
+ *     -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ *     -Dcompiler.aot.RecompilationTest.check_level=1
+ *     compiler.aot.RecompilationTest
+ * @run main compiler.aot.AotCompiler -libname libRecompilationTest.so
+ *     -class compiler.whitebox.SimpleTestCaseHelper
+ *     -extraopt -Dgraal.TieredAOT=false
+ *     -extraopt -XX:+UnlockDiagnosticVMOptions -extraopt -XX:+WhiteBoxAPI -extraopt -Xbootclasspath/a:.
+ * @run main/othervm -Xmixed -Xbatch -XX:+UseAOT -XX:+TieredCompilation -XX:-UseCounterDecay
+ *     -XX:CompileCommand=dontinline,*.*
+ *     -XX:AOTLibrary=./libRecompilationTest.so -Xbootclasspath/a:.
+ *     -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ *     -Dcompiler.aot.RecompilationTest.check_level=-1
+ *     compiler.aot.RecompilationTest
+ * @run main/othervm -Xmixed -Xbatch -XX:+UseAOT -XX:-TieredCompilation -XX:-UseCounterDecay
+ *     -XX:CompileCommand=dontinline,*.*
+ *     -XX:AOTLibrary=./libRecompilationTest.so -Xbootclasspath/a:.
+ *     -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ *     -Dcompiler.aot.RecompilationTest.check_level=-1
+ *     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()));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/SharedUsageTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib /testlibrary /
+ * @modules java.base/jdk.internal.misc
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @build compiler.aot.SharedUsageTest
+ *        compiler.aot.AotCompiler
+ * @run main compiler.aot.AotCompiler -libname libSharedUsageTest.so
+ *      -class compiler.aot.SharedUsageTest
+ * @run main/othervm -XX:+UseAOT -XX:AOTLibrary=./libSharedUsageTest.so
+ *      -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:+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);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeDynamic2AotTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib /testlibrary /
+ * @ignore 8132547
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ *          java.base/jdk.internal.misc
+ * @build compiler.calls.common.InvokeDynamic
+ *        compiler.calls.common.InvokeDynamicPatcher
+ *        compiler.aot.AotCompiler
+ * @run main compiler.calls.common.InvokeDynamicPatcher
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *      sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main compiler.aot.AotCompiler -libname AotInvokeDynamic2AotTest.so
+ *      -class compiler.calls.common.InvokeDynamic
+ * @run main/othervm -XX:+UseAOT -XX:AOTLibrary=./AotInvokeDynamic2AotTest.so
+ *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ *      compiler.calls.common.InvokeDynamic
+ *      -checkCallerCompileLevel -1 -checkCalleeCompileLevel -1
+ * @summary check calls from aot to aot code using invokedynamic
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeDynamic2CompiledTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib /testlibrary /
+ * @ignore 8132547
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ *          java.base/jdk.internal.misc
+ * @build compiler.calls.common.InvokeDynamic
+ *        compiler.calls.common.InvokeDynamicPatcher
+ *        compiler.aot.AotCompiler
+ * @run main compiler.calls.common.InvokeDynamicPatcher
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *      sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main compiler.aot.AotCompiler -libname AotInvokeDynamic2CompiledTest.so
+ *      -class compiler.calls.common.InvokeDynamic
+ *      -compile compiler.calls.common.InvokeDynamic.caller()V
+ * @run main/othervm -XX:+UseAOT
+ *      -XX:AOTLibrary=./AotInvokeDynamic2CompiledTest.so
+ *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ *      compiler.calls.common.InvokeDynamic -compileCallee 1
+ *      -checkCalleeCompileLevel 1 -checkCallerCompileLevel -1
+ * @run main/othervm -XX:+UseAOT
+ *      -XX:AOTLibrary=./AotInvokeDynamic2CompiledTest.so
+ *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ *      compiler.calls.common.InvokeDynamic -compileCallee 4
+ *      -checkCallerCompileLevel -1 -checkCalleeCompileLevel 4
+ * @summary check calls from aot to jit-compiled code using invokedynamic
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeDynamic2InterpretedTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib /testlibrary /
+ * @ignore 8132547
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ *          java.base/jdk.internal.misc
+ * @build compiler.calls.common.InvokeDynamic
+ *        compiler.calls.common.InvokeDynamicPatcher
+ *        compiler.aot.AotCompiler
+ * @run main compiler.calls.common.InvokeDynamicPatcher
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *      sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main compiler.aot.AotCompiler
+ *      -libname AotInvokeDynamic2InterpretedTest.so
+ *      -class compiler.calls.common.InvokeDynamic
+ *      -compile compiler.calls.common.InvokeDynamic.caller()V
+ * @run main/othervm -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 -1
+ * @summary check calls from aot to interpreted code using invokedynamic
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeDynamic2NativeTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib /testlibrary /
+ * @ignore 8132547
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ *          java.base/jdk.internal.misc
+ * @build compiler.calls.common.InvokeDynamic
+ *        compiler.calls.common.InvokeDynamicPatcher
+ *        compiler.aot.AotCompiler
+ * @run main compiler.calls.common.InvokeDynamicPatcher
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *      sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main compiler.aot.AotCompiler -libname AotInvokeDynamic2NativeTest.so
+ *      -class compiler.calls.common.InvokeDynamic
+ *      -compile compiler.calls.common.InvokeDynamic.caller()V
+ * @run main/othervm/native -XX:+UseAOT
+ *       -XX:AOTLibrary=./AotInvokeDynamic2NativeTest.so
+ *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ *       compiler.calls.common.InvokeDynamic -nativeCallee -checkCallerCompileLevel -1
+ * @summary check calls from aot to native code using invokedynamic
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeInterface2AotTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib /testlibrary /
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @modules java.base/jdk.internal.misc
+ * @build compiler.calls.common.InvokeInterface
+ *        compiler.aot.AotCompiler
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *      sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main compiler.aot.AotCompiler -libname AotInvokeInterface2AotTest.so
+ *      -class compiler.calls.common.InvokeInterface
+ * @run main/othervm -XX:+UseAOT -XX:AOTLibrary=./AotInvokeInterface2AotTest.so
+ *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ *      compiler.calls.common.InvokeInterface
+ *      -checkCallerCompileLevel -1 -checkCalleeCompileLevel -1
+ * @summary check calls from aot to aot code using invokeinterface
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeInterface2CompiledTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib /testlibrary /
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @modules java.base/jdk.internal.misc
+ * @build compiler.calls.common.InvokeInterface
+ *        compiler.aot.AotCompiler
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *      sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main compiler.aot.AotCompiler
+ *      -libname AotInvokeInterface2CompiledTest.so
+ *      -class compiler.calls.common.InvokeInterface
+ *      -compile compiler.calls.common.InvokeInterface.caller()V
+ * @run main/othervm -XX:+UseAOT
+ *      -XX:AOTLibrary=./AotInvokeInterface2CompiledTest.so
+ *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ *      compiler.calls.common.InvokeInterface -compileCallee 1
+ *      -checkCallerCompileLevel -1 -checkCalleeCompileLevel 1
+ * @run main/othervm -XX:+UseAOT
+ *      -XX:AOTLibrary=./AotInvokeInterface2CompiledTest.so
+ *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ *      compiler.calls.common.InvokeInterface -compileCallee 4
+ *      -checkCallerCompileLevel -1 -checkCalleeCompileLevel 4
+ * @summary check calls from aot to jit-compiled code using invokeinterface
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeInterface2InterpretedTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib /testlibrary /
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @modules java.base/jdk.internal.misc
+ * @build compiler.calls.common.InvokeInterface
+ *        compiler.aot.AotCompiler
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *      sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main compiler.aot.AotCompiler
+ *      -libname AotInvokeInterface2InterpretedTest.so
+ *      -class compiler.calls.common.InvokeInterface
+ *      -compile compiler.calls.common.InvokeInterface.caller()V
+ * @run main/othervm -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 -1
+ * @summary check calls from aot to interpreted code using invokeinterface
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeInterface2NativeTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib /testlibrary /
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @modules java.base/jdk.internal.misc
+ * @build compiler.calls.common.InvokeInterface
+ *        compiler.aot.AotCompiler
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *      sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main compiler.aot.AotCompiler -libname AotInvokeInterface2NativeTest.so
+ *      -class compiler.calls.common.InvokeInterface
+ *      -compile compiler.calls.common.InvokeInterface.caller()V
+ * @run main/othervm/native -XX:+UseAOT
+ *      -XX:AOTLibrary=./AotInvokeInterface2NativeTest.so
+ *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ *      compiler.calls.common.InvokeInterface -nativeCallee -checkCallerCompileLevel -1
+ * @summary check calls from aot to native code using invokeinterface
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeSpecial2AotTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib /testlibrary /
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @modules java.base/jdk.internal.misc
+ * @build compiler.calls.common.InvokeSpecial
+ *        compiler.aot.AotCompiler
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *      sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main compiler.aot.AotCompiler -libname AotInvokeSpecial2AotTest.so
+ *      -class compiler.calls.common.InvokeSpecial
+ * @run main/othervm -XX:+UseAOT -XX:AOTLibrary=./AotInvokeSpecial2AotTest.so
+ *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ *      compiler.calls.common.InvokeSpecial
+ *      -checkCallerCompileLevel -1 -checkCalleeCompileLevel -1
+ * @summary check calls from aot to aot code using invokespecial
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeSpecial2CompiledTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib /testlibrary /
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @modules java.base/jdk.internal.misc
+ * @build compiler.calls.common.InvokeSpecial
+ *        compiler.aot.AotCompiler
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *      sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main compiler.aot.AotCompiler -libname AotInvokeSpecial2CompiledTest.so
+ *      -class compiler.calls.common.InvokeSpecial
+ *      -compile compiler.calls.common.InvokeSpecial.caller()V
+ * @run main/othervm -XX:+UseAOT
+ *      -XX:AOTLibrary=./AotInvokeSpecial2CompiledTest.so
+ *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ *      compiler.calls.common.InvokeSpecial -compileCallee 1
+ *      -checkCallerCompileLevel -1 -checkCalleeCompileLevel 1
+ * @run main/othervm -XX:+UseAOT
+ *      -XX:AOTLibrary=./AotInvokeSpecial2CompiledTest.so
+ *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ *      compiler.calls.common.InvokeSpecial -compileCallee 4
+ *      -checkCallerCompileLevel -1 -checkCalleeCompileLevel 4
+ * @summary check calls from aot to jit-compiled code using invokespecial
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeSpecial2InterpretedTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib /testlibrary /
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @modules java.base/jdk.internal.misc
+ * @build compiler.calls.common.InvokeSpecial
+ *        compiler.aot.AotCompiler
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *      sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main compiler.aot.AotCompiler
+ *      -libname AotInvokeSpecial2InterpretedTest.so
+ *      -class compiler.calls.common.InvokeSpecial
+ *      -compile compiler.calls.common.InvokeSpecial.caller()V
+ * @run main/othervm -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 -1
+ * @summary check calls from aot to interpreted code using invokespecial
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeSpecial2NativeTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib /testlibrary /
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @modules java.base/jdk.internal.misc
+ * @build compiler.calls.common.InvokeSpecial
+ *        compiler.aot.AotCompiler
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *      sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main compiler.aot.AotCompiler -libname AotInvokeSpecial2NativeTest.so
+ *      -class compiler.calls.common.InvokeSpecial
+ *      -compile compiler.calls.common.InvokeSpecial.caller()V
+ * @run main/othervm/native -XX:+UseAOT
+ *      -XX:AOTLibrary=./AotInvokeSpecial2NativeTest.so
+ *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ *      compiler.calls.common.InvokeSpecial -nativeCallee -checkCallerCompileLevel -1
+ * @summary check calls from aot to interpreted code using invokespecial
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeStatic2AotTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib /testlibrary /
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @modules java.base/jdk.internal.misc
+ * @build compiler.calls.common.InvokeStatic
+ *        compiler.aot.AotCompiler
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *      sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main compiler.aot.AotCompiler -libname AotInvokeStatic2AotTest.so
+ *      -class compiler.calls.common.InvokeStatic
+ * @run main/othervm -XX:+UseAOT -XX:AOTLibrary=./AotInvokeStatic2AotTest.so
+ *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ *      compiler.calls.common.InvokeStatic
+ *      -checkCallerCompileLevel -1 -checkCalleeCompileLevel -1
+ * @summary check calls from aot to aot code using invokestatic
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeStatic2CompiledTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib /testlibrary /
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @modules java.base/jdk.internal.misc
+ * @build compiler.calls.common.InvokeStatic
+ *        compiler.aot.AotCompiler
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *      sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main compiler.aot.AotCompiler -libname AotInvokeStatic2CompiledTest.so
+ *      -class compiler.calls.common.InvokeStatic
+ *      -compile compiler.calls.common.InvokeStatic.caller()V
+ * @run main/othervm -XX:+UseAOT
+ *      -XX:AOTLibrary=./AotInvokeStatic2CompiledTest.so
+ *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ *      compiler.calls.common.InvokeStatic -compileCallee 1
+ *      -checkCallerCompileLevel -1 -checkCalleeCompileLevel 1
+ * @run main/othervm -XX:+UseAOT
+ *      -XX:AOTLibrary=./AotInvokeStatic2CompiledTest.so
+ *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ *      compiler.calls.common.InvokeStatic -compileCallee 4
+ *      -checkCallerCompileLevel -1 -checkCalleeCompileLevel 4
+ * @summary check calls from aot to jit-compiled code using invokestatic
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeStatic2InterpretedTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib /testlibrary /
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @modules java.base/jdk.internal.misc
+ * @build compiler.calls.common.InvokeStatic
+ *        compiler.aot.AotCompiler
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *      sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main compiler.aot.AotCompiler
+ *      -libname AotInvokeStatic2InterpretedTest.so
+ *      -class compiler.calls.common.InvokeStatic
+ *      -compile compiler.calls.common.InvokeStatic.caller()V
+ * @run main/othervm -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 -1
+ * @summary check calls from aot to interpreted code using invokestatic
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeStatic2NativeTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib /testlibrary /
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @modules java.base/jdk.internal.misc
+ * @build compiler.calls.common.InvokeStatic
+ *        compiler.aot.AotCompiler
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *      sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main compiler.aot.AotCompiler -libname AotInvokeStatic2NativeTest.so
+ *      -class compiler.calls.common.InvokeStatic
+ *      -compile compiler.calls.common.InvokeStatic.caller()V
+ * @run main/othervm/native -XX:+UseAOT
+ *      -XX:AOTLibrary=./AotInvokeStatic2NativeTest.so
+ *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ *      compiler.calls.common.InvokeStatic -nativeCallee -checkCallerCompileLevel -1
+ * @summary check calls from aot to native code using invokestatic
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeVirtual2AotTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib /testlibrary /
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @modules java.base/jdk.internal.misc
+ * @build compiler.calls.common.InvokeVirtual
+ *        compiler.aot.AotCompiler
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *      sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main compiler.aot.AotCompiler -libname AotInvokeVirtual2AotTest.so
+ *      -class compiler.calls.common.InvokeVirtual
+ * @run main/othervm -XX:+UseAOT -XX:AOTLibrary=./AotInvokeVirtual2AotTest.so
+ *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ *      compiler.calls.common.InvokeVirtual
+ *      -checkCallerCompileLevel -1 -checkCalleeCompileLevel -1
+ * @summary check calls from aot to aot code, using invokevirtual
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeVirtual2CompiledTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib /testlibrary /
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @modules java.base/jdk.internal.misc
+ * @build compiler.calls.common.InvokeVirtual
+ *        compiler.aot.AotCompiler
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *      sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main compiler.aot.AotCompiler -libname AotInvokeVirtual2CompiledTest.so
+ *      -class compiler.calls.common.InvokeVirtual
+ *      -compile compiler.calls.common.InvokeVirtual.caller()V
+ * @run main/othervm -XX:+UseAOT
+ *      -XX:AOTLibrary=./AotInvokeVirtual2CompiledTest.so
+ *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ *      compiler.calls.common.InvokeVirtual -compileCallee 1
+ *      -checkCallerCompileLevel -1 -checkCalleeCompileLevel 1
+ * @run main/othervm -XX:+UseAOT
+ *      -XX:AOTLibrary=./AotInvokeVirtual2CompiledTest.so
+ *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ *      compiler.calls.common.InvokeVirtual -compileCallee 4
+ *      -checkCallerCompileLevel -1 -checkCalleeCompileLevel 4
+ * @summary check calls from aot to jit-compiled code, using invokevirtual
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeVirtual2InterpretedTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib /testlibrary /
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @modules java.base/jdk.internal.misc
+ * @build compiler.calls.common.InvokeVirtual
+ *        compiler.aot.AotCompiler
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *      sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main compiler.aot.AotCompiler
+ *      -libname AotInvokeVirtual2InterpretedTest.so
+ *      -class compiler.calls.common.InvokeVirtual
+ *      -compile compiler.calls.common.InvokeVirtual.caller()V
+ * @run main/othervm -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 -1
+ * @summary check calls from aot to interpreted code, using invokevirtual
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/calls/fromAot/AotInvokeVirtual2NativeTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib /testlibrary /
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @modules java.base/jdk.internal.misc
+ * @build compiler.calls.common.InvokeVirtual
+ *        compiler.aot.AotCompiler
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *      sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main compiler.aot.AotCompiler -libname AotInvokeVirtual2NativeTest.so
+ *      -class compiler.calls.common.InvokeVirtual
+ *      -compile compiler.calls.common.InvokeVirtual.caller()V
+ * @run main/othervm/native -XX:+UseAOT
+ *      -XX:AOTLibrary=./AotInvokeVirtual2NativeTest.so
+ *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ *      compiler.calls.common.InvokeVirtual -nativeCallee -checkCallerCompileLevel -1
+ * @summary check calls from aot to native code, using invokevirtual
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeDynamic2AotTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib /testlibrary /
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ *          java.base/jdk.internal.misc
+ * @build compiler.calls.common.InvokeDynamic
+ *        compiler.calls.common.InvokeDynamicPatcher
+ *        compiler.aot.AotCompiler
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *      sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main compiler.calls.common.InvokeDynamicPatcher
+ * @run main compiler.aot.AotCompiler -libname CompiledInvokeDynamic2AotTest.so
+ *      -class compiler.calls.common.InvokeDynamic
+ *      -compile compiler.calls.common.InvokeDynamic.callee.*
+ * @run main/othervm -XX:+UseAOT
+ *      -XX:AOTLibrary=./CompiledInvokeDynamic2AotTest.so
+ *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ *      compiler.calls.common.InvokeDynamic -compileCaller 1
+ *      -checkCalleeCompileLevel -1 -checkCallerCompileLevel 1
+ * @run main/othervm -XX:+UseAOT
+ *      -XX:AOTLibrary=./CompiledInvokeDynamic2AotTest.so
+ *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ *      compiler.calls.common.InvokeDynamic -compileCaller 4
+ *      -checkCallerCompileLevel 4 -checkCalleeCompileLevel -1
+ * @summary check calls from jit-compiled to aot code using invokedynamic
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeInterface2AotTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib /testlibrary /
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @modules java.base/jdk.internal.misc
+ * @build compiler.calls.common.InvokeInterface
+ *      compiler.aot.AotCompiler
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *      sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main compiler.aot.AotCompiler
+ *      -libname CompiledInvokeInterface2AotTest.so
+ *      -class compiler.calls.common.InvokeInterface
+ *      -compile compiler.calls.common.InvokeInterface.callee.*
+ * @run main/othervm -XX:+UseAOT
+ *      -XX:AOTLibrary=./CompiledInvokeInterface2AotTest.so
+ *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ *      compiler.calls.common.InvokeInterface -compileCaller 1
+ *      -checkCalleeCompileLevel -1 -checkCallerCompileLevel 1
+ * @run main/othervm -XX:+UseAOT
+ *      -XX:AOTLibrary=./CompiledInvokeInterface2AotTest.so
+ *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ *      compiler.calls.common.InvokeInterface -compileCaller 4
+ *      -checkCallerCompileLevel 4 -checkCalleeCompileLevel -1
+ * @summary check calls from jit-compiled to aot code using invokeinterface
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeSpecial2AotTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib /testlibrary /
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @modules java.base/jdk.internal.misc
+ * @build compiler.calls.common.InvokeSpecial
+ *        compiler.aot.AotCompiler
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *      sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main compiler.aot.AotCompiler -libname CompiledInvokeSpecial2AotTest.so
+ *      -class compiler.calls.common.InvokeSpecial
+ *      -compile compiler.calls.common.InvokeSpecial.callee.*
+ * @run main/othervm -XX:+UseAOT
+ *      -XX:AOTLibrary=./CompiledInvokeSpecial2AotTest.so
+ *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ *      compiler.calls.common.InvokeSpecial -compileCaller 1
+ *      -checkCalleeCompileLevel -1 -checkCallerCompileLevel 1
+ * @run main/othervm -XX:+UseAOT
+ *      -XX:AOTLibrary=./CompiledInvokeSpecial2AotTest.so
+ *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ *      compiler.calls.common.InvokeSpecial -compileCaller 4
+ *      -checkCallerCompileLevel 4 -checkCalleeCompileLevel -1
+ * @summary check calls from jit-compiled to aot code using invokespecial
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeStatic2AotTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib /testlibrary /
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @modules java.base/jdk.internal.misc
+ * @build compiler.calls.common.InvokeStatic
+ *        compiler.aot.AotCompiler
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *      sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main compiler.aot.AotCompiler -libname CompiledInvokeStatic2AotTest.so
+ *      -class compiler.calls.common.InvokeStatic
+ *      -compile compiler.calls.common.InvokeStatic.callee.*
+ * @run main/othervm -XX:+UseAOT
+ *      -XX:AOTLibrary=./CompiledInvokeStatic2AotTest.so
+ *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ *      compiler.calls.common.InvokeStatic -compileCaller 1
+ *      -checkCalleeCompileLevel -1 -checkCallerCompileLevel 1
+ * @run main/othervm -XX:+UseAOT
+ *      -XX:AOTLibrary=./CompiledInvokeStatic2AotTest.so
+ *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ *      compiler.calls.common.InvokeStatic -compileCaller 4
+ *      -checkCallerCompileLevel 4 -checkCalleeCompileLevel -1
+ * @summary check calls from jit-compiled to aot code using invokestatic
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/calls/fromCompiled/CompiledInvokeVirtual2AotTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib /testlibrary /
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @modules java.base/jdk.internal.misc
+ * @build compiler.calls.common.InvokeVirtual
+ *        compiler.aot.AotCompiler
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *      sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main compiler.aot.AotCompiler -libname CompiledInvokeVirtual2AotTest.so
+ *      -class compiler.calls.common.InvokeVirtual
+ *      -compile compiler.calls.common.InvokeVirtual.callee.*
+ * @run main/othervm -XX:+UseAOT
+ *      -XX:AOTLibrary=./CompiledInvokeVirtual2AotTest.so
+ *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ *      compiler.calls.common.InvokeVirtual -compileCaller 1
+ *      -checkCalleeCompileLevel -1 -checkCallerCompileLevel 1
+ * @run main/othervm -XX:+UseAOT
+ *      -XX:AOTLibrary=./CompiledInvokeVirtual2AotTest.so
+ *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ *      compiler.calls.common.InvokeVirtual -compileCaller 4
+ *      -checkCallerCompileLevel 4 -checkCalleeCompileLevel -1
+ * @summary check calls from jit-compiled to aot code using invokevirtual
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeDynamic2AotTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib /testlibrary /
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ *          java.base/jdk.internal.misc
+ * @build compiler.calls.common.InvokeDynamic
+ *        compiler.calls.common.InvokeDynamicPatcher
+ *        compiler.aot.AotCompiler
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *      sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main compiler.calls.common.InvokeDynamicPatcher
+ * @run main compiler.aot.AotCompiler
+ *      -libname InterpretedInvokeDynamic2AotTest.so
+ *      -class compiler.calls.common.InvokeDynamic
+ *      -compile compiler.calls.common.InvokeDynamic.callee.*
+ * @run main/othervm -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 -1
+ * @summary check calls from interpreted to aot code using invokedynamic
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeInterface2AotTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib /testlibrary /
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @modules java.base/jdk.internal.misc
+ * @build compiler.calls.common.InvokeInterface
+ *        compiler.aot.AotCompiler
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *      sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main compiler.aot.AotCompiler
+ *      -libname InterpretedInvokeInterface2AotTest.so
+ *      -class compiler.calls.common.InvokeInterface
+ *      -compile compiler.calls.common.InvokeInterface.callee.*
+ * @run main/othervm -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 -1
+ * @summary check calls from interpreted to aot code using invokeinterface
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeSpecial2AotTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib /testlibrary /
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @modules java.base/jdk.internal.misc
+ * @build compiler.calls.common.InvokeSpecial
+ *        compiler.aot.AotCompiler
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *      sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main compiler.aot.AotCompiler
+ *      -libname InterpretedInvokeSpecial2AotTest.so
+ *      -class compiler.calls.common.InvokeSpecial
+ *      -compile compiler.calls.common.InvokeSpecial.callee.*
+ * @run main/othervm -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 -1
+ * @summary check calls from interpreted to aot code using invokespecial
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeStatic2AotTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib /testlibrary /
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @modules java.base/jdk.internal.misc
+ * @build compiler.calls.common.InvokeStatic
+ *        compiler.aot.AotCompiler
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *      sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main compiler.aot.AotCompiler
+ *      -libname InterpretedInvokeStatic2AotTest.so
+ *      -class compiler.calls.common.InvokeStatic
+ *      -compile compiler.calls.common.InvokeStatic.callee.*
+ * @run main/othervm -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 -1
+ * @summary check calls from interpreted to aot code using invokestatic
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/calls/fromInterpreted/InterpretedInvokeVirtual2AotTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib /testlibrary /
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @modules java.base/jdk.internal.misc
+ * @build compiler.calls.common.InvokeVirtual
+ *        compiler.aot.AotCompiler
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *      sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main compiler.aot.AotCompiler
+ *      -libname InterpretedInvokeVirtual2AotTest.so
+ *      -class compiler.calls.common.InvokeVirtual
+ *      -compile compiler.calls.common.InvokeVirtual.callee.*
+ * @run main/othervm -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 -1
+ * @summary check calls from interpreted to aot code using invokevirtual
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/calls/fromNative/NativeInvokeSpecial2AotTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib /testlibrary /
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @modules java.base/jdk.internal.misc
+ * @build compiler.calls.common.InvokeSpecial
+ *        compiler.aot.AotCompiler
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *      sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main compiler.aot.AotCompiler -libname NativeInvokeSpecial2AotTest.so
+ *      -class compiler.calls.common.InvokeSpecial
+ *      -compile compiler.calls.common.InvokeSpecial.callee.*
+ * @run main/othervm/native -XX:+UseAOT
+ *      -XX:AOTLibrary=./NativeInvokeSpecial2AotTest.so
+ *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ *      compiler.calls.common.InvokeSpecial -nativeCaller -checkCalleeCompileLevel -1
+ * @summary check calls from native to aot code using invokespecial
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/calls/fromNative/NativeInvokeStatic2AotTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib /testlibrary /
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @modules java.base/jdk.internal.misc
+ * @build compiler.calls.common.InvokeStatic
+ *        compiler.aot.AotCompiler
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *      sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main compiler.aot.AotCompiler -libname NativeInvokeStatic2AotTest.so
+ *      -class compiler.calls.common.InvokeStatic
+ *      -compile compiler.calls.common.InvokeStatic.callee.*
+ * @run main/othervm/native -XX:+UseAOT
+ *      -XX:AOTLibrary=./NativeInvokeStatic2AotTest.so
+ *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ *      compiler.calls.common.InvokeStatic -nativeCaller -checkCalleeCompileLevel -1
+ * @summary check calls from native to aot code using invokestatic
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/calls/fromNative/NativeInvokeVirtual2AotTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib /testlibrary /
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @modules java.base/jdk.internal.misc
+ * @build compiler.calls.common.InvokeVirtual
+ *        compiler.aot.AotCompiler
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *      sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main compiler.aot.AotCompiler -libname NativeInvokeVirtual2AotTest.so
+ *      -class compiler.calls.common.InvokeVirtual
+ *      -compile compiler.calls.common.InvokeVirtual.callee.*
+ * @run main/othervm/native -XX:+UseAOT
+ *      -XX:AOTLibrary=./NativeInvokeVirtual2AotTest.so
+ *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ *      compiler.calls.common.InvokeVirtual -nativeCaller -checkCalleeCompileLevel -1
+ * @summary check calls from native to aot code using invokevirtual
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/cli/AotLibraryNegativeBase.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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:+UseAOT", "-XX:+PrintAOT",
+                    option, HelloWorldPrinter.class.getName());
+        } catch (Throwable t) {
+            throw new Error("Problems executing test using " + option
+                    + ": " + t, t);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/cli/DisabledAOTWithLibraryTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib /testlibrary /
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @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:-UseAOT", "-XX:+PrintAOT",
+                    "-XX:AOTLibrary=./" + LIB_NAME,
+                    HelloWorldPrinter.class.getName());
+        } catch (Throwable t) {
+            throw new Error("Problems executing test " + t, t);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/cli/IncorrectAOTLibraryTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib /testlibrary /
+ * @modules java.base/jdk.internal.misc
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @run driver ClassFileInstaller ClassFileInstaller
+ * @run driver compiler.aot.cli.IncorrectAOTLibraryTest
+ * @summary check if incorrect aot library is handled properly
+ */
+
+package compiler.aot.cli;
+
+public class IncorrectAOTLibraryTest {
+    private static final String OPTION
+            = "-XX:AOTLibrary=./ClassFileInstaller.class";
+    private static final String[] EXPECTED_MESSAGES = new String[] {
+        "error opening file:"
+    };
+
+    public static void main(String args[]) {
+        AotLibraryNegativeBase.launchTest(OPTION, EXPECTED_MESSAGES);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/cli/MultipleAOTLibraryTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib /testlibrary /
+ * @modules java.base/jdk.internal.misc
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @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.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 + 4);
+            allArgs[args.length] = "-XX:AOTLibrary="
+                    + "./libMultipleAOTLibraryTest1.so:"
+                    + "./libMultipleAOTLibraryTest2.so";
+            allArgs[args.length + 1] = "-XX:+PrintAOT";
+            allArgs[args.length + 2] = "-XX:+UseAOT";
+            allArgs[args.length + 3] = 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);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/cli/NonExistingAOTLibraryTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib /testlibrary /
+ * @modules java.base/jdk.internal.misc
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @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[] {
+        "cannot open shared object file"
+    };
+
+    public static void main(String args[]) {
+        if (new File(PATH).exists()) {
+            throw new Error("TESTBUG: " + PATH + " unexpectedly exists");
+        }
+        AotLibraryNegativeBase.launchTest(OPTION, EXPECTED_MESSAGES);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/cli/SingleAOTLibraryTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib / /testlibrary
+ * @modules java.base/jdk.internal.misc
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @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:+UseAOT", "-XX:+PrintAOT", arg,
+                    "-XX:AOTLibrary=./libSingleAOTLibraryTest.so",
+                    HelloWorldPrinter.class.getName());
+        } catch (Throwable t) {
+            throw new Error("Problems executing test: " + t, t);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/cli/SingleAOTOptionTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib /testlibrary /
+ * @modules java.base/jdk.internal.misc
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @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:AOTLibrary=./libSingleAOTOptionTest.so
+ * @run main compiler.aot.cli.SingleAOTOptionTest
+ *      -XX:+UseCompressedOops -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:AOTLibrary=./libSingleAOTOptionTest.so
+ * @run driver compiler.aot.cli.SingleAOTOptionTest
+ *      -XX:-UseCompressedOops -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 == 2) {
+            new SingleAOTOptionTest().runTest(args[0], args[1]);
+        } else {
+            throw new Error("Test expects 2 parameters");
+        }
+    }
+
+    private void runTest(String arg1, String arg2) {
+        try {
+            String exitCodeErrorMessage = String.format("Unexpected exit code "
+                    + "using %s and %s", arg1, arg2);
+            String outputErrorMessage = String.format("Unexpected output using"
+                    + " %s and %s", arg1, arg2);
+            boolean addTestVMOptions = true;
+            CommandLineOptionTest.verifyJVMStartup(EXPECTED_MESSAGES,
+                    UNEXPECTED_MESSAGES, exitCodeErrorMessage,
+                    outputErrorMessage, ExitCode.OK, addTestVMOptions, arg1,
+                    arg2, HelloWorldPrinter.class.getName());
+        } catch (Throwable t) {
+            throw new Error("Problems executing test: " + t, t);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/cli/jaotc/ClasspathOptionTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library / /test/lib /testlibrary
+ * @modules java.base/jdk.internal.misc
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @build compiler.aot.cli.jaotc.ClasspathOptionTest
+ * @run driver ClassFileInstaller compiler.aot.cli.jaotc.data.HelloWorldOne
+ * @run driver compiler.aot.cli.jaotc.ClasspathOptionTest
+ * @summary check jaotc can compile class from classpath
+ */
+
+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 jdk.test.lib.Asserts;
+import jdk.test.lib.process.OutputAnalyzer;
+
+public class ClasspathOptionTest {
+    public static void main(String[] args) {
+        Path cp = Paths.get("testClasspath");
+        try {
+            Files.createDirectory(cp);
+            Files.move(Paths.get("compiler"), cp.resolve("compiler"));
+        } catch (IOException e) {
+            throw new Error("TESTBUG: can't create test data " + e, e);
+        }
+        OutputAnalyzer oa = JaotcTestHelper.compileLibrary("--classpath", cp.toString(),
+                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());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/cli/jaotc/ClasspathOptionUnknownClassTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library / /testlibrary/ /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @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("HelloWorldOne.class");
+        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");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/cli/jaotc/CompileClassTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library / /test/lib /testlibrary
+ * @modules java.base/jdk.internal.misc
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @build compiler.aot.cli.jaotc.CompileClassTest
+ * @run driver 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(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());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/cli/jaotc/CompileDirectoryTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library / /test/lib /testlibrary
+ * @modules java.base/jdk.internal.misc
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @build compiler.aot.cli.jaotc.CompileDirectoryTest
+ * @run driver 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
+ */
+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(".");
+        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());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/cli/jaotc/CompileJarTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library / /test/lib /testlibrary
+ * @modules java.base/jdk.internal.misc
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @build compiler.aot.cli.jaotc.CompileJarTest
+ * @run driver 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_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);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/cli/jaotc/CompileModuleTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library / /test/lib /testlibrary
+ * @modules java.base/jdk.internal.misc
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @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);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/cli/jaotc/JaotcTestHelper.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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 java.io.File;
+import java.io.IOException;
+import jdk.test.lib.process.ExitCode;
+import jdk.test.lib.JDKToolLauncher;
+import jdk.test.lib.Utils;
+import jdk.test.lib.cli.CommandLineOptionTest;
+import jdk.test.lib.process.OutputAnalyzer;
+
+public class JaotcTestHelper {
+    public static final String DEFAULT_LIB_PATH = "./unnamed.so";
+    public static final String DEFAULT_LIBRARY_LOAD_MESSAGE = "loaded    " + DEFAULT_LIB_PATH
+            + "  aot library";
+    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);
+        }
+        for (String arg : args) {
+            launcher.addToolArg(arg);
+        }
+        String[] cmd = launcher.getCommand();
+        try {
+            return new OutputAnalyzer(new ProcessBuilder(cmd).start());
+        } catch (IOException 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, ENABLE_AOT, AOT_LIBRARY, PRINT_AOT, classToRun);
+        } catch (Throwable t) {
+            throw new Error("Library usage verification failed: " + t, t);
+        }
+    }
+
+    public static String getClassAotCompilationName(Class<?> classToCompile) {
+        return classToCompile.getName().replaceAll("\\.", File.separator) + ".class";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/cli/jaotc/ListOptionNotExistingTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library / /test/lib /testlibrary
+ * @modules java.base/jdk.internal.misc
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @build compiler.aot.cli.jaotc.ListOptionNotExistingTest
+ * @run driver 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",
+                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");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/cli/jaotc/ListOptionTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library / /test/lib /testlibrary
+ * @modules java.base/jdk.internal.misc
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @build compiler.aot.cli.jaotc.ListOptionTest
+ * @run driver 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(),
+                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);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/cli/jaotc/ListOptionWrongFileTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library / /test/lib /testlibrary
+ * @modules java.base/jdk.internal.misc
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @build compiler.aot.cli.jaotc.ListOptionWrongFileTest
+ * @run driver 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);
+
+    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_ITEM, COMPILE_ITEM);
+        oa.shouldHaveExitValue(0);
+        File compiledLibrary = new File(JaotcTestHelper.DEFAULT_LIB_PATH);
+        Asserts.assertTrue(compiledLibrary.exists(), "Expecte compiler library to exist");
+        JaotcTestHelper.checkLibraryUsage(HelloWorldOne.class.getName(), EXPECTED, null);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/cli/jaotc/data/HelloWorldOne.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/cli/jaotc/data/HelloWorldTwo.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/fingerprint/CDSDumper.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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> <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];
+
+        // Prepare the classlist
+        FileOutputStream fos = new FileOutputStream(classlist);
+        PrintStream ps = new PrintStream(fos);
+
+        for (int i=3; i<args.length; i++) {
+            ps.println(args[i].replace('.', '/'));
+        }
+        ps.close();
+        fos.close();
+
+        // Dump the archive
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+            "-XX:+UnlockCommercialFeatures",
+            "-XX:+UseAppCDS",
+            "-XX:+UnlockDiagnosticVMOptions",
+            "-cp", classpath,
+            "-XX:ExtraSharedClassListFile=" + classlist,
+            "-XX:SharedArchiveFile=" + archive,
+            "-Xshare:dump",
+            "-XX:+PrintSharedSpaces");
+
+        OutputAnalyzer output = new OutputAnalyzer(pb.start());
+        output.shouldContain("Loading classes to share");
+        output.shouldHaveExitValue(0);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/fingerprint/CDSRunner.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/fingerprint/SelfChanged.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @build compiler.aot.fingerprint.SelfChanged
+ *        compiler.aot.AotCompiler
+ *
+ * @run main
+ *      compiler.aot.fingerprint.SelfChanged WRITE-UNMODIFIED-CLASS
+ * @run main/othervm compiler.aot.AotCompiler -libname libSelfChanged.so
+ *      -class compiler.aot.fingerprint.Blah
+ *
+ * @run main/othervm
+ *      compiler.aot.fingerprint.SelfChanged TEST-UNMODIFIED
+ * @run main/othervm -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:+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.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();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/fingerprint/SelfChangedCDS.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @build compiler.aot.fingerprint.SelfChanged
+ *        compiler.aot.AotCompiler
+ *
+ * @run main compiler.aot.fingerprint.SelfChanged WRITE-UNMODIFIED-CLASS
+ * @run main/othervm compiler.aot.AotCompiler -libname libSelfChanged.so
+ *      -class compiler.aot.fingerprint.Blah
+ *
+ * @run main ClassFileInstaller -jar SelfChangedCDS.jar compiler.aot.fingerprint.Blah
+ * @run main compiler.aot.fingerprint.CDSDumper SelfChangedCDS.jar SelfChangedCDS.classlist SelfChangedCDS.jsa
+ *      compiler.aot.fingerprint.Blah
+ *
+ * @run main compiler.aot.fingerprint.CDSRunner -cp SelfChangedCDS.jar
+ *      compiler.aot.fingerprint.Blah TEST-UNMODIFIED
+ * @run main compiler.aot.fingerprint.CDSRunner -cp SelfChangedCDS.jar
+ *      -XX:+UseAOT -XX:+PrintAOT -XX:AOTLibrary=./libSelfChanged.so
+ *      -XX:+UnlockDiagnosticVMOptions -XX:SharedArchiveFile=SelfChangedCDS.jsa
+ *      -Xshare:auto -XX:+UnlockCommercialFeatures -XX:+UseAppCDS -showversion
+ *      -Xlog:aot+class+fingerprint=trace -Xlog:aot+class+load=trace
+ *      compiler.aot.fingerprint.Blah TEST-UNMODIFIED
+ *
+ * @run main
+ *      compiler.aot.fingerprint.SelfChanged WRITE-MODIFIED-CLASS
+ * @run main/othervm compiler.aot.AotCompiler -libname libSelfChanged.so
+ *      -class compiler.aot.fingerprint.Blah
+ *
+ * @run main compiler.aot.fingerprint.CDSRunner -cp SelfChangedCDS.jar
+ *      compiler.aot.fingerprint.Blah TEST-MODIFIED
+ * @run main compiler.aot.fingerprint.CDSRunner -cp SelfChangedCDS.jar
+ *      -XX:+UseAOT -XX:+PrintAOT -XX:AOTLibrary=./libSelfChanged.so
+ *      -XX:+UnlockDiagnosticVMOptions -XX:SharedArchiveFile=SelfChangedCDS.jsa
+ *      -Xshare:auto -XX:+UnlockCommercialFeatures -XX:+UseAppCDS -showversion
+ *      -Xlog:aot+class+fingerprint=trace -Xlog:aot+class+load=trace
+ *      compiler.aot.fingerprint.Blah TEST-MODIFIED
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/fingerprint/SuperChanged.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @build compiler.aot.fingerprint.SuperChanged
+ *        compiler.aot.AotCompiler
+ *
+ * @run main
+ *      compiler.aot.fingerprint.SuperChanged WRITE-UNMODIFIED-CLASS
+ * @run main/othervm compiler.aot.AotCompiler -libname libSuperChanged.so
+ *      -class compiler.aot.fingerprint.Foo
+ *
+ * @run main
+ *      compiler.aot.fingerprint.SuperChanged TEST-UNMODIFIED
+ * @run main/othervm -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:+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.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();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/jdk.tools.jaotc.jnilibelf.test/src/jdk/tools/jaotc/jnilibelf/test/JNILibELFTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.jnilibelf.test;
+
+import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
+
+import jdk.tools.jaotc.jnilibelf.JNIELFContainer;
+import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.ELF;
+import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.LibELF.Elf_Cmd;
+import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.LibELF.Elf_Type;
+
+public class JNILibELFTest {
+
+    public static void main(String[] args) {
+        // if (args.length != 2) {
+        // System.out.println("Please provide file-name as argument");
+        // return;
+        // }
+        createSharedLib();
+    }
+
+    private static boolean createSharedLib() {
+
+        int numProgHdrs = 1;
+        JNIELFContainer elfContainer = new JNIELFContainer("ELF");
+
+        // Allocate ELF Header
+        elfContainer.createELFHeader(ELF.ET_DYN);
+
+        // Allocate 'numProgHdrs' program headers
+
+        if (!elfContainer.createProgramHeader(numProgHdrs)) {
+            System.out.println("Failed to create Program Headers");
+            return false;
+        }
+
+        // Hash table content
+        int[] bhashWords = {0x01234567, 0x89abcdef, 0xdeadc0de};
+        // int[] data = { 100, 200, 300, 400 };
+
+        ByteBuffer byteBuffer = ByteBuffer.allocate(bhashWords.length * 4);
+        IntBuffer intBuffer = byteBuffer.asIntBuffer();
+        intBuffer.put(bhashWords);
+
+        // byte[] int_hash_array = byteBuffer.array();
+
+        // Hash Table content
+        // ByteBuffer hash_words = ByteBuffer.allocate(14).putInt(0x01234567);
+        // hash_words.putInt(0x89abcdef);
+        // hash_words.putInt(0xdeadc0de);
+
+        // Create a hash section
+        // Setting sh_link as 0 since this is just a demo - the value should actually be the section
+        // header index
+        // of the symbol table to which the hash table applies.
+        int index = elfContainer.createSection(".hash", byteBuffer.array(), Elf_Type.ELF_T_WORD, 4, ELF.SHT_HASH, ELF.SHF_ALLOC, 0, 0);
+        if (index == 0) {
+            System.out.println("Failed to create hash section");
+            return false;
+        }
+
+        elfContainer.createSection(".strtab", elfContainer.getStrTabContent().getBytes(), Elf_Type.ELF_T_BYTE, 1, ELF.SHT_STRTAB, (ELF.SHF_STRINGS | ELF.SHF_ALLOC), ELF.SHN_UNDEF, 0);
+        // Now, finally, after creating all sections, create shstrtab section
+        elfContainer.createSection(".shstrtab", elfContainer.getShStrTabContent().getBytes(), Elf_Type.ELF_T_BYTE, 1, ELF.SHT_STRTAB, 0, ELF.SHN_UNDEF, 0);
+        // Run elf_update
+        elfContainer.elfUpdate(Elf_Cmd.ELF_C_NULL);
+
+        // Set program header type to self
+        elfContainer.setProgHdrTypeToSelf();
+        // Setting pheader to self type also sets it to be dirty. So run elfUpdate again
+        // to write it out.
+        elfContainer.elfUpdate(Elf_Cmd.ELF_C_WRITE);
+        // Finish ELF processing
+        elfContainer.elfEnd();
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/NativeOrderOutputStreamTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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 os.family == "linux" & vm.bits == "64" & os.arch == "amd64"
+ * @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());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/verification/ClassAndLibraryNotMatchTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib /
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @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 + ".class",
+                Arrays.asList("-classpath", Utils.TEST_CLASS_PATH + File.pathSeparator
+                        + Utils.TEST_SRC), null);
+    }
+
+    private void runAndCheckHelloWorld(String checkString) {
+        ProcessBuilder pb;
+        try {
+            pb = ProcessTools.createJavaProcessBuilder(true, "-cp", ".",
+                    "-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);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/verification/vmflags/BasicFlagsChange.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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 + ".class", 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.createJavaProcessBuilder(true, "-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");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/verification/vmflags/NotTrackedFlagTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib /
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @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
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/verification/vmflags/TrackedFlagTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @library /test/lib /
+ * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
+ * @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
+ */
+
--- a/hotspot/test/compiler/classUnloading/anonymousClass/TestAnonymousClassUnloading.java	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/test/compiler/classUnloading/anonymousClass/TestAnonymousClassUnloading.java	Sun Dec 11 19:07:04 2016 -0800
@@ -42,12 +42,11 @@
 import java.lang.reflect.Method;
 import java.net.URL;
 import java.net.URLConnection;
+import compiler.whitebox.CompilerWhiteBoxTest;
 
 public class TestAnonymousClassUnloading {
     private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
     private static final Unsafe UNSAFE = Unsafe.getUnsafe();
-    private static int COMP_LEVEL_SIMPLE = 1;
-    private static int COMP_LEVEL_FULL_OPTIMIZATION = 4;
 
     /**
      * We override hashCode here to be able to access this implementation
@@ -87,9 +86,9 @@
         // Check if already compiled
         if (!WHITE_BOX.isMethodCompiled(m)) {
             // If not, try to compile it with C2
-            if(!WHITE_BOX.enqueueMethodForCompilation(m, COMP_LEVEL_FULL_OPTIMIZATION)) {
+            if(!WHITE_BOX.enqueueMethodForCompilation(m, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION)) {
                 // C2 compiler not available, try to compile with C1
-                WHITE_BOX.enqueueMethodForCompilation(m, COMP_LEVEL_SIMPLE);
+                WHITE_BOX.enqueueMethodForCompilation(m, CompilerWhiteBoxTest.COMP_LEVEL_SIMPLE);
             }
             // Because background compilation is disabled, method should now be compiled
             if(!WHITE_BOX.isMethodCompiled(m)) {
--- a/hotspot/test/compiler/classUnloading/methodUnloading/TestMethodUnloading.java	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/test/compiler/classUnloading/methodUnloading/TestMethodUnloading.java	Sun Dec 11 19:07:04 2016 -0800
@@ -46,14 +46,13 @@
 import java.lang.reflect.Method;
 import java.net.URL;
 import java.net.URLClassLoader;
+import compiler.whitebox.CompilerWhiteBoxTest;
 
 public class TestMethodUnloading {
     private static final String workerClassName = "compiler.classUnloading.methodUnloading.WorkerClass";
     private static int work = -1;
 
     private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
-    private static int COMP_LEVEL_SIMPLE = 1;
-    private static int COMP_LEVEL_FULL_OPTIMIZATION = 4;
 
     /**
      * Does some work by either using the workerClass or locally producing values.
@@ -93,9 +92,9 @@
         // Check if already compiled
         if (!WHITE_BOX.isMethodCompiled(m)) {
             // If not, try to compile it with C2
-            if(!WHITE_BOX.enqueueMethodForCompilation(m, COMP_LEVEL_FULL_OPTIMIZATION)) {
+            if(!WHITE_BOX.enqueueMethodForCompilation(m, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION)) {
                 // C2 compiler not available, try to compile with C1
-                WHITE_BOX.enqueueMethodForCompilation(m, COMP_LEVEL_SIMPLE);
+                WHITE_BOX.enqueueMethodForCompilation(m, CompilerWhiteBoxTest.COMP_LEVEL_SIMPLE);
             }
             // Because background compilation is disabled, method should now be compiled
             if(!WHITE_BOX.isMethodCompiled(m)) {
--- a/hotspot/test/compiler/intrinsics/IntrinsicDisabledTest.java	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/test/compiler/intrinsics/IntrinsicDisabledTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -25,7 +25,7 @@
  * @test
  * @bug 8138651
  * @modules java.base/jdk.internal.misc
- * @library /test/lib
+ * @library /test/lib /
  *
  * @build sun.hotspot.WhiteBox
  * @run driver ClassFileInstaller sun.hotspot.WhiteBox
@@ -44,6 +44,7 @@
 
 import jdk.test.lib.Platform;
 import sun.hotspot.WhiteBox;
+import compiler.whitebox.CompilerWhiteBoxTest;
 
 import java.lang.reflect.Executable;
 import java.util.Objects;
@@ -52,12 +53,6 @@
 
     private static final WhiteBox wb = WhiteBox.getWhiteBox();
 
-    /* Compilation level corresponding to C1. */
-    private static final int COMP_LEVEL_SIMPLE = 1;
-
-    /* Compilation level corresponding to C2. */
-    private static final int COMP_LEVEL_FULL_OPTIMIZATION = 4;
-
     /* Determine if tiered compilation is enabled. */
     private static final boolean TIERED_COMPILATION = wb.getBooleanVMFlag("TieredCompilation");
 
@@ -202,13 +197,13 @@
     }
 
     public static void main(String args[]) {
-        if (Platform.isServer() && (TIERED_STOP_AT_LEVEL == COMP_LEVEL_FULL_OPTIMIZATION)) {
+        if (Platform.isServer() && (TIERED_STOP_AT_LEVEL == CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION)) {
             if (TIERED_COMPILATION) {
-                test(COMP_LEVEL_SIMPLE);
+                test(CompilerWhiteBoxTest.COMP_LEVEL_SIMPLE);
             }
-            test(COMP_LEVEL_FULL_OPTIMIZATION);
+            test(CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
         } else {
-            test(COMP_LEVEL_SIMPLE);
+            test(CompilerWhiteBoxTest.COMP_LEVEL_SIMPLE);
         }
     }
 }
--- a/hotspot/test/compiler/intrinsics/bigInteger/MontgomeryMultiplyTest.java	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/test/compiler/intrinsics/bigInteger/MontgomeryMultiplyTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -29,7 +29,7 @@
  * @requires vm.flavor == "server"
  * @modules java.base/jdk.internal.misc:open
  * @modules java.base/java.math:open
- * @library /test/lib
+ * @library /test/lib /
  *
  * @build sun.hotspot.WhiteBox
  * @run driver ClassFileInstaller sun.hotspot.WhiteBox
@@ -42,6 +42,7 @@
 
 import jdk.test.lib.Platform;
 import sun.hotspot.WhiteBox;
+import compiler.whitebox.CompilerWhiteBoxTest;
 
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
@@ -57,9 +58,6 @@
 
     private static final WhiteBox wb = WhiteBox.getWhiteBox();
 
-    /* Compilation level corresponding to C2. */
-    private static final int COMP_LEVEL_FULL_OPTIMIZATION = 4;
-
     static final MethodHandles.Lookup lookup = MethodHandles.lookup();
 
     static final MethodHandle montgomeryMultiplyHandle, montgomerySquareHandle;
@@ -319,8 +317,8 @@
         if (!Platform.isServer()) {
             throw new Error("TESTBUG: Not server VM");
         }
-        if (wb.isIntrinsicAvailable(getExecutable(true), COMP_LEVEL_FULL_OPTIMIZATION) &&
-                wb.isIntrinsicAvailable(getExecutable(false), COMP_LEVEL_FULL_OPTIMIZATION)) {
+        if (wb.isIntrinsicAvailable(getExecutable(true), CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION) &&
+                wb.isIntrinsicAvailable(getExecutable(false), CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION)) {
             try {
                 new MontgomeryMultiplyTest().testMontgomeryMultiplyChecks();
                 new MontgomeryMultiplyTest().testResultValues();
--- a/hotspot/test/compiler/intrinsics/mathexact/sanity/IntrinsicBase.java	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/IntrinsicBase.java	Sun Dec 11 19:07:04 2016 -0800
@@ -54,18 +54,18 @@
             if (TIERED_COMPILATION) {
                 int max_level = TIERED_STOP_AT_LEVEL;
                 expectedIntrinsicCount = (max_level == COMP_LEVEL_MAX) ? 1 : 0;
-                for (int i = CompilerWhiteBoxTest.COMP_LEVEL_SIMPLE; i <= max_level; ++i) {
+                for (int i = COMP_LEVEL_SIMPLE; i <= max_level; ++i) {
                     deoptimize();
                     compileAtLevel(i);
                 }
             } else {
                 expectedIntrinsicCount = 1;
                 deoptimize();
-                compileAtLevel(CompilerWhiteBoxTest.COMP_LEVEL_MAX);
+                compileAtLevel(COMP_LEVEL_MAX);
             }
         } else {
             deoptimize();
-            compileAtLevel(CompilerWhiteBoxTest.COMP_LEVEL_SIMPLE);
+            compileAtLevel(COMP_LEVEL_SIMPLE);
         }
 
         if (!isIntrinsicAvailable()) {
--- a/hotspot/test/compiler/uncommontrap/Test8009761.java	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/test/compiler/uncommontrap/Test8009761.java	Sun Dec 11 19:07:04 2016 -0800
@@ -40,14 +40,12 @@
 package compiler.uncommontrap;
 
 import sun.hotspot.WhiteBox;
-
 import java.lang.reflect.Method;
+import compiler.whitebox.CompilerWhiteBoxTest;
 
 public class Test8009761 {
 
     private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
-    private static int COMP_LEVEL_SIMPLE = 1;
-    private static int COMP_LEVEL_FULL_OPTIMIZATION = 4;
     private static Method m3 = null;
 
     static Object m1(boolean deopt) {
@@ -263,9 +261,9 @@
         c1 = count;
 
         // Force the compilation of m3() that will inline m1()
-        if(!WHITE_BOX.enqueueMethodForCompilation(m3, COMP_LEVEL_FULL_OPTIMIZATION)) {
+        if(!WHITE_BOX.enqueueMethodForCompilation(m3, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION)) {
             // C2 compiler not available, compile with C1
-            WHITE_BOX.enqueueMethodForCompilation(m3, COMP_LEVEL_SIMPLE);
+            WHITE_BOX.enqueueMethodForCompilation(m3, CompilerWhiteBoxTest.COMP_LEVEL_SIMPLE);
         }
 
         // Because background compilation is disabled, method should now be compiled
--- a/hotspot/test/compiler/whitebox/CompilerWhiteBoxTest.java	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/test/compiler/whitebox/CompilerWhiteBoxTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,7 +42,9 @@
     /** {@code CompLevel::CompLevel_none} -- Interpreter */
     public static final int COMP_LEVEL_NONE = 0;
     /** {@code CompLevel::CompLevel_any}, {@code CompLevel::CompLevel_all} */
-    public static final int COMP_LEVEL_ANY = -1;
+    public static final int COMP_LEVEL_ANY = -2;
+    /** {@code CompLevel::CompLevel_aot} -- AOT */
+    public static final int COMP_LEVEL_AOT = -1;
     /** {@code CompLevel::CompLevel_simple} -- C1 */
     public static final int COMP_LEVEL_SIMPLE = 1;
     /** {@code CompLevel::CompLevel_limited_profile} -- C1, invocation &amp; backedge counters */
--- a/hotspot/test/runtime/CompressedOops/CompressedClassPointers.java	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/test/runtime/CompressedOops/CompressedClassPointers.java	Sun Dec 11 19:07:04 2016 -0800
@@ -64,6 +64,7 @@
         ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
             "-XX:+UnlockDiagnosticVMOptions",
             "-Xmx30g",
+            "-XX:-UseAOT", // AOT explicitly set klass shift to 3.
             "-Xlog:gc+metaspace=trace",
             "-XX:+VerifyBeforeGC", "-version");
         OutputAnalyzer output = new OutputAnalyzer(pb.start());
--- a/hotspot/test/serviceability/dcmd/compiler/CodeCacheTest.java	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/test/serviceability/dcmd/compiler/CodeCacheTest.java	Sun Dec 11 19:07:04 2016 -0800
@@ -116,7 +116,8 @@
         // Validate code cache segments
         String line;
         Matcher m;
-        for (int s = 0; s < segmentsCount; ++s) {
+        int matchedCount = 0;
+        while (true) {
           // Validate first line
           line = lines.next();
           m = line1.matcher(line);
@@ -128,7 +129,7 @@
                   }
               }
           } else {
-              Assert.fail("Regexp 1 failed to match line: " + line);
+              break;
           }
 
           // Validate second line
@@ -149,10 +150,14 @@
           } else {
               Assert.fail("Regexp 2 failed to match line: " + line);
           }
+          ++matchedCount;
+        }
+        // Because of CodeCacheExtensions, we could match more than expected
+        if (matchedCount < segmentsCount) {
+            Assert.fail("Fewer segments matched (" + matchedCount + ") than expected (" + segmentsCount + ")");
         }
 
         // Validate third line
-        line = lines.next();
         m = line3.matcher(line);
         if (m.matches()) {
             int blobs = Integer.parseInt(m.group(1));
--- a/hotspot/test/testlibrary/jittester/Makefile	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/test/testlibrary/jittester/Makefile	Sun Dec 11 19:07:04 2016 -0800
@@ -107,7 +107,7 @@
 INIT: $(DIST_DIR)
 	$(shell if [ ! -d $(CLASSES_DIR) ]; then mkdir -p $(CLASSES_DIR); fi)
 
-install: clean_testbase testgroup testroot copytestlibrary JAR cleantmp
+install: clean_testbase testgroup testroot copytestlibrary copyaot JAR cleantmp
 	$(JAVA) --add-exports=java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED -ea -jar $(DIST_JAR) $(APPLICATION_ARGS)
 
 clean_testbase:
@@ -121,6 +121,9 @@
 	@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)
@@ -129,6 +132,6 @@
 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)
 
--- a/hotspot/test/testlibrary/jittester/conf/default.properties	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/test/testlibrary/jittester/conf/default.properties	Sun Dec 11 19:07:04 2016 -0800
@@ -9,5 +9,5 @@
 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/AotTestGeneratorsFactory.java	Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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:+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 -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
+        };
+    }
+}