changeset 42650:1f304d0c888b

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>
author kvn
date Sun, 11 Dec 2016 19:07:04 -0800
parents 28238583a459
children 8883ad66f6a9
files 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
diffstat 262 files changed, 19625 insertions(+), 676 deletions(-) [+]
line wrap: on
line diff
--- 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;
+